diff --git a/frontend/src/pages/Profile.tsx b/frontend/src/pages/Profile.tsx
index 406c1f1..a576e35 100644
--- a/frontend/src/pages/Profile.tsx
+++ b/frontend/src/pages/Profile.tsx
@@ -31,6 +31,54 @@ function NumberField({
);
}
+// Renders/edits BackfillHorizonDays as a calendar date (the day sync should
+// backfill through) rather than a raw day count, which is easier to reason
+// about than counting days back -- the stored value is still a day count
+// (what the backend actually consumes), just presented as its equivalent
+// date, recomputed against "today" on every render/change.
+function daysAgoToISODate(days: number): string {
+ const d = new Date();
+ d.setHours(0, 0, 0, 0);
+ d.setDate(d.getDate() - days);
+ // Deliberately not toISOString(): that formats in UTC, which in any
+ // timezone ahead of UTC shifts local midnight back to the previous day.
+ const y = d.getFullYear();
+ const m = String(d.getMonth() + 1).padStart(2, "0");
+ const day = String(d.getDate()).padStart(2, "0");
+ return `${y}-${m}-${day}`;
+}
+
+function isoDateToDaysAgo(iso: string): number {
+ const picked = new Date(iso + "T00:00:00");
+ const today = new Date();
+ today.setHours(0, 0, 0, 0);
+ const diffMs = today.getTime() - picked.getTime();
+ return Math.max(0, Math.round(diffMs / (24 * 60 * 60 * 1000)));
+}
+
+function BackfillHorizonField({
+ value,
+ onChange,
+}: {
+ value: number;
+ onChange: (v: number) => void;
+}) {
+ return (
+
+ );
+}
+
// How long to wait after the last edit before actually saving, so typing a
// name or a multi-digit number doesn't fire one request per keystroke --
// only the last edit in a burst triggers a save, covering every field
@@ -162,8 +210,7 @@ export function Profile({ onSaved }: { onSaved?: (p: ProfileType) => void }) {
onChange={(e) => set("GarminPassword", e.target.value)}
/>
- set("BackfillHorizonDays", v)}
/>