84 lines
3.0 KiB
TypeScript
84 lines
3.0 KiB
TypeScript
/**
|
|
* @ai-summary Auth0 callback handler page - routes users based on their status
|
|
* @ai-context Fetches user status after Auth0 callback and redirects appropriately
|
|
*/
|
|
|
|
import React, { useEffect } from 'react';
|
|
import { useNavigate, useLocation } from 'react-router-dom';
|
|
import { useUserStatus } from '../../../core/auth/useUserStatus';
|
|
|
|
export const CallbackPage: React.FC = () => {
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
const { data: userStatus, isLoading, error } = useUserStatus();
|
|
|
|
// Get returnTo from location state (passed from Auth0Provider onRedirectCallback)
|
|
const returnTo = (location.state as { returnTo?: string })?.returnTo || '/garage';
|
|
|
|
useEffect(() => {
|
|
if (isLoading) return;
|
|
|
|
if (error) {
|
|
console.error('[CallbackPage] Error fetching user status:', error);
|
|
// On error, redirect to garage and let normal auth flow handle it
|
|
navigate('/garage', { replace: true });
|
|
return;
|
|
}
|
|
|
|
if (userStatus) {
|
|
// Note: Unverified users should never reach this page if Auth0 action is configured
|
|
// But as a safety check, redirect to verify-email if not verified
|
|
if (!userStatus.emailVerified) {
|
|
console.log('[CallbackPage] User not verified, redirecting to verify-email');
|
|
navigate('/verify-email', { replace: true });
|
|
return;
|
|
}
|
|
|
|
// Check if onboarding is completed
|
|
if (!userStatus.onboardingCompleted) {
|
|
console.log('[CallbackPage] User not onboarded, redirecting to onboarding');
|
|
navigate('/onboarding', { replace: true });
|
|
return;
|
|
}
|
|
|
|
// User is verified and onboarded - go to requested destination
|
|
console.log('[CallbackPage] User verified and onboarded, redirecting to:', returnTo);
|
|
navigate(returnTo, { replace: true });
|
|
}
|
|
}, [userStatus, isLoading, error, navigate, returnTo]);
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-white to-rose-50 flex items-center justify-center p-4">
|
|
<div className="text-center">
|
|
<div className="inline-flex items-center justify-center w-16 h-16 rounded-full bg-primary-100 mb-4">
|
|
<svg
|
|
className="w-8 h-8 text-primary-600 animate-spin"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<circle
|
|
className="opacity-25"
|
|
cx="12"
|
|
cy="12"
|
|
r="10"
|
|
stroke="currentColor"
|
|
strokeWidth="4"
|
|
/>
|
|
<path
|
|
className="opacity-75"
|
|
fill="currentColor"
|
|
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
<h2 className="text-xl font-semibold text-slate-800 mb-2">
|
|
Setting up your session...
|
|
</h2>
|
|
<p className="text-slate-600">Please wait while we prepare your garage.</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default CallbackPage;
|