import React, { useEffect } from 'react' import { useAuth } from '../lib/authContext' // ── AuthGate ────────────────────────────────────────────────────────────────── // // Single source of truth for the "not authenticated" UI (IV6, IV7). // // - authenticated → renders children normally. // - unauthenticated (cold, hasBeenAuthenticated === false) // → shows a manual "Sign in with OIDC" card (IV7). // - unauthenticated (mid-session, hasBeenAuthenticated === true) // → auto-redirects via useEffect, shows a placeholder (IV7). // - auth_error → shows the distinct error card with a manual "Try again" // button (IV6). Never auto-retries. export function AuthGate({ children }: { children: React.ReactNode }): React.JSX.Element { const { state, signIn } = useAuth() const { status, hasBeenAuthenticated, error } = state // Mid-session expiry: auto-redirect on mount only (IV7). useEffect(() => { if (status === 'unauthenticated' && hasBeenAuthenticated) { signIn(window.location.pathname) } // eslint-disable-next-line react-hooks/exhaustive-deps }, [status, hasBeenAuthenticated]) // intentionally omits signIn (stable callback) if (status === 'authenticated') { return <>{children} } if (status === 'auth_error') { return (
couldn't sign you in
{error ?? 'An unknown error occurred.'}
) } // status === 'unauthenticated' if (hasBeenAuthenticated) { // Mid-session expiry — auto-redirect is in progress (useEffect above). return (
session expired
Redirecting to sign in…
) } // Cold first render — show manual sign-in button (IV7). return (
not authenticated
Sign in to continue.
) }