diff --git a/components/mission-control.tsx b/components/mission-control.tsx index d45cfba..03e874e 100644 --- a/components/mission-control.tsx +++ b/components/mission-control.tsx @@ -63,6 +63,9 @@ export function MissionControl() { const [activeTab, setActiveTab] = useState(null) // #38 — admin DB CRUD overlay, opened from the header. const [adminOpen, setAdminOpen] = useState(false) + // #44 (v0.10.1) — true only after hydration: the banner clock must render '' in both SSR and the + // first client render, otherwise the prerendered (build-time) string desyncs at hydration. + const [hydrated, setHydrated] = useState(false) // #44 — the four mount fetches, extracted into a callback so the NEXT TURN button (5b) can // re-run them after /api/turn: a tick can change all four snapshots (the turn always; inventory @@ -120,6 +123,9 @@ export function MissionControl() { return () => clearInterval(id) }, []) + // #44 (v0.10.1) — flip after hydration so the banner clock can start (SSR/first render both ''). + useEffect(() => setHydrated(true), []) + // #27 — restore the persisted tab once on mount (validated against TAB_IDS). useEffect(() => { const stored = window.localStorage.getItem(ACTIVE_TAB_KEY) @@ -139,7 +145,9 @@ export function MissionControl() { .catch(() => {}) }, []) - const timeStr = new Date().toLocaleTimeString('en-GB', { hour12: false }) + // #44 (v0.10.1) — hydration-safe: '' until hydrated (SSR and first client render agree), then the + // live time on the 1s tick — no more build-time clock baked into the prerendered HTML. + const timeStr = hydrated ? new Date().toLocaleTimeString('en-GB', { hour12: false }) : '' // Slugs of the researched techs — drives the effective caps + build gates in the SHIP SYSTEMS // tab via the same pure helpers the API enforces (lib/game/tech.ts).