"use client"; import { useEffect, useMemo, useState } from "react"; const STORAGE_KEY = "fpsms_server_wait_until_ms"; const WAIT_SECONDS = 30; const RELOAD_INTERVAL_SECONDS = 5; function formatSeconds(s: number) { const v = Math.max(0, Math.floor(s)); return `${v} 秒`; } /** * Catches root-level errors (e.g. backend down during deploy). * Shows a reconnect countdown and retries, then forwards to login if still failing. * Must define and
because this replaces the root layout. */ export default function GlobalError({ error, reset, }: { error: Error & { digest?: string }; reset: () => void; }) { const [remaining, setRemaining] = useState(WAIT_SECONDS); const waitUntilMs = useMemo(() => { const existing = Number(window.localStorage.getItem(STORAGE_KEY) || "0"); const now = Date.now(); if (existing && existing > now) return existing; const next = now + WAIT_SECONDS * 1000; window.localStorage.setItem(STORAGE_KEY, String(next)); return next; }, []); useEffect(() => { const start = Date.now(); const tick = () => { const now = Date.now(); const msLeft = Math.max(0, waitUntilMs - now); setRemaining(msLeft / 1000); if (msLeft <= 0) { window.localStorage.removeItem(STORAGE_KEY); window.location.href = "/login"; } }; tick(); const interval = window.setInterval(tick, 250); const reloadTimer = window.setInterval(() => { const elapsedSec = (Date.now() - start) / 1000; if (elapsedSec >= WAIT_SECONDS) return; window.location.reload(); }, RELOAD_INTERVAL_SECONDS * 1000); return () => { window.clearInterval(interval); window.clearInterval(reloadTimer); }; }, [waitUntilMs]); return (連線異常,伺服器暫停中
系統會在後台恢復後自動重試。倒數中:{formatSeconds(remaining)}