import { useEffect, useMemo, useState } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; import { useAuth, OAUTH_POST_LOGIN_REDIRECT_KEY } from '../contexts/AuthContext'; import { useLanguage } from '../contexts/LanguageContext'; function toInternalPath(urlOrPath: string): string { try { const parsed = new URL(urlOrPath, window.location.origin); if (parsed.origin !== window.location.origin) { return '/'; } return `${parsed.pathname}${parsed.search}${parsed.hash}`; } catch { return '/'; } } export default function AuthCallbackPage() { const navigate = useNavigate(); const [searchParams] = useSearchParams(); const { completeGoogleOAuth } = useAuth(); const { t } = useLanguage(); const [error, setError] = useState(null); const code = useMemo(() => searchParams.get('code') ?? '', [searchParams]); const state = useMemo(() => searchParams.get('state') ?? '', [searchParams]); useEffect(() => { let mounted = true; const run = async () => { if (!code || !state) { if (mounted) { setError(t.auth.oauthFailed); } return; } const redirectUri = `${window.location.origin}/auth/google/callback`; const result = await completeGoogleOAuth({ code, state, redirect_uri: redirectUri }); if (result.error) { if (mounted) { setError(result.error.message || t.auth.oauthFailed); } return; } const redirectTarget = sessionStorage.getItem(OAUTH_POST_LOGIN_REDIRECT_KEY) || '/'; navigate(toInternalPath(redirectTarget), { replace: true }); }; run(); return () => { mounted = false; }; }, [code, completeGoogleOAuth, navigate, state, t.auth.oauthFailed]); return (

Google OAuth

{!error &&

{t.auth.oauthExchanging}

} {error && ( <>

{error}

)}
); }