import { useEffect, useState } from "react"; import { api } from "../api/client"; import type { Profile as ProfileType } from "../types/api"; function NumberField({ label, value, onChange, step = 1, }: { label: string; value: number; onChange: (v: number) => void; step?: number; }) { return ( ); } function NullableNumberField({ label, value, onChange, }: { label: string; value: number | null; onChange: (v: number | null) => void; }) { return ( ); } export function Profile() { const [profile, setProfile] = useState(null); const [error, setError] = useState(null); const [saved, setSaved] = useState(false); useEffect(() => { api.getProfile().then(setProfile).catch((e) => setError(String(e))); }, []); function set(key: K, value: ProfileType[K]) { setProfile((p) => (p ? { ...p, [key]: value } : p)); setSaved(false); } async function save() { if (!profile) return; setError(null); try { const updated = await api.updateProfile(profile); setProfile(updated); setSaved(true); } catch (e) { setError(String(e)); setSaved(false); } } if (!profile) { return (

Profile

{error ?

{error}

:

Loading...

}
); } return (

Profile

{error &&

{error}

} {saved &&

Saved.

}
Garmin account
Classification set("RollingWindowDays", v)} />
Heart rate set("MaxHeartRate", v)} /> set("RestingHeartRate", v)} /> {([1, 2, 3, 4, 5] as const).map((zone) => (
set(`HRZone${zone}MinPct` as keyof ProfileType, v as never)} /> set(`HRZone${zone}MaxPct` as keyof ProfileType, v as never)} />
))}
); }