diff --git a/src/App.test.tsx b/src/App.test.tsx index 91e3a83..02809ef 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -226,7 +226,7 @@ describe("homepage", () => { test("historical check-ins use the selected date's tracking method and preserve today", async () => { const f = connectAccount(); - f.setTime("2026-09-03T12:00:00Z"); + f.setTime("2026-01-03T12:00:00Z"); const habit = await f.json("/habits", "POST", { name: "Reading", method: "manual" }, 201); f.setTime("2026-09-04T12:00:00Z"); await f.json(`/habits/${habit.id}`, "PATCH", { method: "count", target: 10, unit: "pages" }); @@ -243,6 +243,14 @@ describe("homepage", () => { expect((await f.json(`/habits/${habit.id}/days/2026-09-03`)).complete).toBe(true); expect((await f.json(`/habits/${habit.id}/days/2026-09-04`)).value).toBe(0); expect(container.textContent).toContain("Saved check-in for 2026-09-03"); + fetchMock.mockClear(); + await act(async () => { + const input = container.querySelector('input[type="date"]')!; + Object.getOwnPropertyDescriptor(dom.HTMLInputElement.prototype, "value")!.set!.call(input, "2026-01-03"); + input.dispatchEvent(new dom.Event("change", { bubbles: true }) as unknown as Event); + }); + expect(container.querySelector('[aria-label^="2026-01-03:"]')).not.toBeNull(); + expect(fetchMock.mock.calls.some(([url]) => String(url).includes("from=2025-11-01") && String(url).includes("compact=true"))).toBe(true); }); test("signed-out visitors can try progress without calling private habit APIs", async () => { diff --git a/src/components/HabitHistory.tsx b/src/components/HabitHistory.tsx index c6a8345..fde0552 100644 --- a/src/components/HabitHistory.tsx +++ b/src/components/HabitHistory.tsx @@ -47,6 +47,14 @@ export function HabitHistory({ const [historyLoading, setHistoryLoading] = useState(false); useEffect(() => { setRange(monthWindow(date, 3)); }, [date]); const [selectedDate, setSelectedDate] = useState(); + function selectDate(selected: string) { + setSelectedDate(selected); + const available = monthWindow(date, 12); + if (selected >= available.from && selected <= available.to && (selected < range.from || selected > range.to)) { + const requested = monthWindow(selected, 3); + setRange({ from: requested.from < available.from ? available.from : requested.from, to: requested.to }); + } + } const [editingDay, setEditingDay] = useState(false); const [savingDay, setSavingDay] = useState(false); const [calendar, setCalendar] = useState(null); @@ -119,7 +127,7 @@ export function HabitHistory({ ) : ( <> } + selectedDayAction={selected => } legend={ {editingDay && setEditingDay(false)} busy={savingDay}>
-
{id => { if (event.target.value) setSelectedDate(event.target.value); }} />}
+
{id => { if (event.target.value) selectDate(event.target.value); }} />}
{ setAttempt(value => value + 1); onHistorySaved?.(); }} />
}