"use client"; import { useEffect, useState } from "react"; import { usePathname, useRouter } from "next/navigation"; import { SuperAdminSessionProvider } from "@/components/auth/session-context"; import { getSuperAdminSession } from "@/lib/api/superadmin"; import { refreshSuperAdmin } from "@/lib/auth/client"; import type { SuperAdminSessionResponse } from "@/types/api"; const RETRY_DELAY_MS = 5000; function isRecoverableSessionError(error: unknown) { const message = String(error).toLowerCase(); return [ "502", "503", "504", "fetch failed", "failed to fetch", "econnrefused", "timeout", "network", "upstream", ].some((token) => message.includes(token)); } export function AuthGuard({ children }: { children: React.ReactNode }) { const [ready, setReady] = useState(false); const [sessionError, setSessionError] = useState(null); const [session, setSession] = useState(null); const [retryNonce, setRetryNonce] = useState(0); const [retryCountdown, setRetryCountdown] = useState(null); const router = useRouter(); const pathname = usePathname(); useEffect(() => { let active = true; let retryTimeout: number | null = null; let countdownInterval: number | null = null; const clearRetryTimers = () => { if (retryTimeout) { window.clearTimeout(retryTimeout); retryTimeout = null; } if (countdownInterval) { window.clearInterval(countdownInterval); countdownInterval = null; } }; const scheduleRetry = () => { clearRetryTimers(); setRetryCountdown(RETRY_DELAY_MS / 1000); countdownInterval = window.setInterval(() => { setRetryCountdown((value) => (value && value > 1 ? value - 1 : 1)); }, 1000); retryTimeout = window.setTimeout(() => { clearRetryTimers(); setRetryCountdown(null); if (active) { setRetryNonce((value) => value + 1); } }, RETRY_DELAY_MS); }; const ensureSession = async () => { try { const nextSession = await getSuperAdminSession(); if (!active) { return; } clearRetryTimers(); setSession(nextSession); setSessionError(null); setRetryCountdown(null); setReady(true); } catch (initialError) { try { const refreshed = await refreshSuperAdmin(); if (!refreshed) { router.replace("/login"); return; } const nextSession = await getSuperAdminSession(); if (!active) { return; } clearRetryTimers(); setSession(nextSession); setSessionError(null); setRetryCountdown(null); setReady(true); } catch (error) { if (String(initialError).includes("401") || String(error).includes("401")) { router.replace("/login"); return; } if (!active) { return; } setSession(null); setSessionError(String(error)); setReady(true); if (isRecoverableSessionError(initialError) || isRecoverableSessionError(error)) { scheduleRetry(); } else { clearRetryTimers(); setRetryCountdown(null); } } } }; void ensureSession(); return () => { active = false; clearRetryTimers(); }; }, [router, pathname, retryNonce]); if (!ready) { return (
Checking the current SuperAdmin session...
); } if (sessionError && !session) { return (
The dashboard could not verify the current session, so permissions were not loaded. Reload the page after the backend connection is available again.
{sessionError}
{retryCountdown !== null ? (
Retrying automatically in {retryCountdown}s...
) : null}
); } return ( {children} ); }