Remove every automatic timezone-setting mechanism (task 7f685179) (#282)

Co-authored-by: Joshua <joshua@cnjmail.com>
Co-committed-by: Joshua <joshua@cnjmail.com>
This commit was merged in pull request #282.
This commit is contained in:
2026-09-30 07:22:57 -04:00
committed by approver_agent
parent 6e25c9e42c
commit 2db780e3ee
16 changed files with 282 additions and 546 deletions
+4 -44
View File
@@ -5,9 +5,8 @@
* household's child profiles. Every write refetches the list.
*
* Preferences: the household settings (planning horizon, day rollover,
* timezone, notifications). Save patches only the changed fields. A timezone
* the admin never chose is set once, on load, to the browser's own zone;
* saving the timezone (even clearing it) marks it chosen, so it sticks.
* timezone, notifications). Save patches only the changed fields. The
* timezone is only ever set by the admin saving it here.
*
* One write at a time across both sections.
*/
@@ -291,19 +290,6 @@ export const COMMON_TIMEZONES = [
"Pacific/Auckland",
];
/**
* The browser's own IANA zone — the location-derived default for an unset
* household timezone — or "" when it is missing or not a usable zone name.
*/
export function detectTimezone(): string {
try {
const zone = Intl.DateTimeFormat().resolvedOptions().timeZone;
return typeof zone === "string" && zone !== "Etc/Unknown" && IANA_ZONE.test(zone) ? zone : "";
} catch {
return "";
}
}
/** The form's working copy: the number is text so it can be mid-edit. */
type PreferencesDraft = Omit<HouseholdSettings, "horizon_days"> & { horizon_days: string };
@@ -342,9 +328,6 @@ function buildChanges(draft: PreferencesDraft, loaded: HouseholdSettings): Setti
for (const key of Object.keys(loaded) as (keyof HouseholdSettings)[]) {
if (next[key] !== loaded[key]) (changes as Record<string, unknown>)[key] = next[key];
}
// An explicit choice — including "" (the API host's local time) — must
// persist, or the next load would auto-set the browser's zone over it.
if ("timezone" in changes) changes.timezone_configured = true;
if (Object.keys(changes).length === 0) return "No changes to save.";
return changes;
}
@@ -574,8 +557,6 @@ export default function SettingsScreen({ onClose }: { onClose: () => void }) {
} | null>(null);
// A ref, not state: two taps in one frame must not both see `busy === null`.
const inFlight = useRef(false);
// The never-chosen-timezone auto-set fires at most once per screen.
const timezoneAutoSet = useRef(false);
const screenRef = useRef<HTMLDivElement>(null);
const titleRef = useRef<HTMLHeadingElement>(null);
const addRef = useRef<HTMLButtonElement>(null);
@@ -620,29 +601,8 @@ export default function SettingsScreen({ onClose }: { onClose: () => void }) {
let cancelled = false;
setPreferences({ kind: "loading" });
fetchSettings()
.then(async (settings) => {
if (cancelled) return;
// Never chosen: adopt the browser's zone before the form shows, so
// nothing the admin enters can be overwritten by it. An empty zone the
// admin chose (timezone_configured) is left alone.
const unchosen = settings.timezone === "" && !settings.timezone_configured;
const detected = unchosen ? detectTimezone() : "";
if (!detected || timezoneAutoSet.current) {
setPreferences({ kind: "ready", settings });
return;
}
timezoneAutoSet.current = true;
try {
const saved = await updateSettings({ timezone: detected, timezone_configured: true });
if (!cancelled) setPreferences({ kind: "ready", settings: saved });
} catch (error) {
if (cancelled) return;
setPreferences({ kind: "ready", settings });
setPreferencesMessage({
kind: "error",
text: errorMessage(error, `The timezone could not be set to ${detected}`),
});
}
.then((settings) => {
if (!cancelled) setPreferences({ kind: "ready", settings });
})
.catch((error: unknown) => {
if (cancelled) return;