import { Stack } from 'expo-router'; import React from 'react'; import { Alert, Pressable, Text, View } from 'react-native'; import { NavCard, PriorityCard, Screen, Sec } from '../components/ui'; import { useAuth } from '../lib/api'; import { agoTxt, fmtD, fmtDY, hm, num, cap } from '../lib/format'; import { shapeBiomarkers, shapeSleep, weekStart, workoutVolume } from '../lib/shape'; import { C } from '../lib/theme'; import type { BiomarkersResponse, DexaResponse, HealthMeta, MeditationStats, SleepApiResponse, SleepCycleExport, WorkoutsResponse, } from '../lib/types'; import { loadAll, useLoad } from '../lib/use-load'; export default function Today() { const { logout } = useAuth(); const { data, loading, refresh } = useLoad(() => loadAll({ meta: 'meta', bio: 'biomarkers', wo: 'workouts', sApi: 'sleepApi', sc: 'sleepCycle', dexa: 'dexa', med: 'medStats', } as const), ); const r = data as | { meta: HealthMeta | null; bio: BiomarkersResponse | null; wo: WorkoutsResponse | null; sApi: SleepApiResponse | null; sc: SleepCycleExport | null; dexa: DexaResponse | null; med: MeditationStats | null; } | undefined; const cards: React.ReactNode[] = []; if (r) { if (r.sApi && r.sc) { const nights = shapeSleep(r.sApi, r.sc); const last = nights[nights.length - 1]; cards.push( , ); } else cards.push(); if (r.wo) { const ws = [...r.wo.workouts].sort((a, b) => (a.start_time < b.start_time ? -1 : 1)); const last = ws[ws.length - 1]; const { vol } = workoutVolume(last); const wkCount = ws.filter( (w) => weekStart(w.start_time) === weekStart(new Date().toISOString()), ).length; cards.push( , ); } else cards.push(); if (r.bio) { const marks = shapeBiomarkers(r.bio); const latestDraw = r.bio.biomarkers.reduce((m, b) => (b.collected > m ? b.collected : m), ''); const flagged = marks.filter((m) => m.latest.flagged && m.latest.collected === latestDraw); cards.push( cap(f.name)).join(', ')}${flagged.length > 3 ? '…' : ''}` : undefined } okline={flagged.length ? undefined : 'All markers in range'} note={`Latest draw ${fmtDY(latestDraw)}`} />, ); } else cards.push(); if (r.dexa) { const scan = r.dexa.scans[r.dexa.scans.length - 1]; cards.push( , ); } else cards.push(); if (r.med) { cards.push( , ); } else cards.push(); cards.push( , ); } return ( <> ( Alert.alert('Lock the dashboard?', 'You will need the password to get back in.', [ { text: 'Cancel', style: 'cancel' }, { text: 'Lock', style: 'destructive', onPress: logout }, ]) }> 🔒 ), }} /> {loading && !r ? ( Loading… ) : ( {cards} )} {r?.meta?.current_priorities?.length ? ( <> {r.meta.current_priorities.map((p, i) => ( ))} ) : null} Personal health data · served from rehbock.xyz over HTTPS · nothing cached on device ); }