diff --git a/src/components/cycle/log-day-sheet.tsx b/src/components/cycle/log-day-sheet.tsx index ebb633514..815b77df7 100644 --- a/src/components/cycle/log-day-sheet.tsx +++ b/src/components/cycle/log-day-sheet.tsx @@ -479,10 +479,19 @@ function CervixRow({ * deliberately: it is how people recognise a date they are recalling. */ export function formatSheetDate(date: string, locale: Locale): string { - const [year, month, day] = date.split("-").map(Number); - return new Date(year, month - 1, day).toLocaleDateString( + // A cycle day key is a calendar day, not an instant, so it is anchored at + // noon UTC and rendered in UTC — the same anchor the domain's day arithmetic + // uses. Formatting it in the browser's zone would let a reader east or west + // of it see the sheet name a different day than the one it writes to. + return new Date(`${date}T12:00:00Z`).toLocaleDateString( resolveIntlLocale(locale), - { weekday: "long", day: "numeric", month: "long", year: "numeric" }, + { + weekday: "long", + day: "numeric", + month: "long", + year: "numeric", + timeZone: "UTC", + }, ); } diff --git a/src/components/cycle/use-cycle.ts b/src/components/cycle/use-cycle.ts index d21060e30..0e8b4fd22 100644 --- a/src/components/cycle/use-cycle.ts +++ b/src/components/cycle/use-cycle.ts @@ -20,6 +20,7 @@ import { apiPost, } from "@/lib/api/api-fetch"; import { useTranslations } from "@/lib/i18n/context"; +import { toastWrittenOutcome } from "@/components/outcome/outcome-toast"; import { cycleDependentKeys, @@ -247,7 +248,7 @@ export function useLogDay() { }, onSuccess: () => { void invalidateKeys(qc, cycleDependentKeys); - toast.success(t("cycle.saveSuccess")); + toastWrittenOutcome("success", t("cycle.saveSuccess")); }, }); } @@ -293,7 +294,7 @@ export function usePatchDayLog() { }, onSuccess: () => { void invalidateKeys(qc, cycleDependentKeys); - toast.success(t("cycle.saveSuccess")); + toastWrittenOutcome("success", t("cycle.saveSuccess")); }, }); } @@ -311,7 +312,7 @@ export function useStartPeriod() { }, onSuccess: () => { void invalidateKeys(qc, cycleDependentKeys); - toast.success(t("cycle.periodStartSaved")); + toastWrittenOutcome("success", t("cycle.periodStartSaved")); }, // v1.16.4 — period boundaries had no failure signal at all (the sheet // simply stayed open); a toast names the rejection. @@ -333,7 +334,7 @@ export function useEndPeriod() { }, onSuccess: () => { void invalidateKeys(qc, cycleDependentKeys); - toast.success(t("cycle.periodEndSaved")); + toastWrittenOutcome("success", t("cycle.periodEndSaved")); }, onError: () => toast.error(t("cycle.saveError")), }); @@ -349,7 +350,7 @@ export function useDeleteDayLog() { }, onSuccess: () => { void invalidateKeys(qc, cycleDependentKeys); - toast.success(t("cycle.deleteSuccess")); + toastWrittenOutcome("success", t("cycle.deleteSuccess")); }, onError: () => toast.error(t("cycle.deleteError")), });