mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-21 12:11:11 -05:00
135 lines
4.3 KiB
TypeScript
135 lines
4.3 KiB
TypeScript
import { useEffect, useState } from 'react';
|
||
import { supabase } from '@/lib/supabaseClient';
|
||
import { authStorage } from '@/lib/authStorage';
|
||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
||
import { Badge } from '@/components/ui/badge';
|
||
import { Button } from '@/components/ui/button';
|
||
import { logger } from '@/lib/logger';
|
||
|
||
interface AuthDiagnosticsData {
|
||
timestamp: string;
|
||
storage: {
|
||
type: string;
|
||
persistent: boolean;
|
||
};
|
||
session: {
|
||
exists: boolean;
|
||
user: string | null;
|
||
expiresAt: number | null;
|
||
error: string | null;
|
||
};
|
||
network: {
|
||
online: boolean;
|
||
};
|
||
environment: {
|
||
url: string;
|
||
isIframe: boolean;
|
||
cookiesEnabled: boolean;
|
||
};
|
||
}
|
||
|
||
export function AuthDiagnostics() {
|
||
const [diagnostics, setDiagnostics] = useState<AuthDiagnosticsData | null>(null);
|
||
const [isOpen, setIsOpen] = useState(false);
|
||
const [isRefreshing, setIsRefreshing] = useState(false);
|
||
|
||
const runDiagnostics = async () => {
|
||
setIsRefreshing(true);
|
||
try {
|
||
const storageStatus = authStorage.getStorageStatus();
|
||
const { data: { session }, error: sessionError } = await supabase.auth.getSession();
|
||
|
||
const results = {
|
||
timestamp: new Date().toISOString(),
|
||
storage: storageStatus,
|
||
session: {
|
||
exists: !!session,
|
||
user: session?.user?.email || null,
|
||
expiresAt: session?.expires_at || null,
|
||
error: sessionError?.message || null,
|
||
},
|
||
network: {
|
||
online: navigator.onLine,
|
||
},
|
||
environment: {
|
||
url: window.location.href,
|
||
isIframe: window.self !== window.top,
|
||
cookiesEnabled: navigator.cookieEnabled,
|
||
}
|
||
};
|
||
|
||
setDiagnostics(results);
|
||
logger.debug('Auth diagnostics', { results });
|
||
} finally {
|
||
setIsRefreshing(false);
|
||
}
|
||
};
|
||
|
||
useEffect(() => {
|
||
// Run diagnostics on mount if there's a session issue
|
||
const checkSession = async () => {
|
||
const { data: { session } } = await supabase.auth.getSession();
|
||
if (!session) {
|
||
await runDiagnostics();
|
||
setIsOpen(true);
|
||
}
|
||
};
|
||
|
||
// Only run if not already authenticated
|
||
const timer = setTimeout(checkSession, 3000);
|
||
return () => clearTimeout(timer);
|
||
}, []);
|
||
|
||
if (!isOpen || !diagnostics) return null;
|
||
|
||
return (
|
||
<Card className="fixed bottom-4 right-4 w-96 z-50 shadow-lg">
|
||
<CardHeader>
|
||
<CardTitle className="flex items-center justify-between">
|
||
<span>Authentication Diagnostics</span>
|
||
<Button variant="ghost" size="sm" onClick={() => setIsOpen(false)}>✕</Button>
|
||
</CardTitle>
|
||
<CardDescription>Debug information for session issues</CardDescription>
|
||
</CardHeader>
|
||
<CardContent className="space-y-2 text-sm">
|
||
<div>
|
||
<strong>Storage Type:</strong>{' '}
|
||
<Badge variant={diagnostics.storage.persistent ? 'default' : 'destructive'}>
|
||
{diagnostics.storage.type}
|
||
</Badge>
|
||
</div>
|
||
<div>
|
||
<strong>Session Status:</strong>{' '}
|
||
<Badge variant={diagnostics.session.exists ? 'default' : 'destructive'}>
|
||
{diagnostics.session.exists ? 'Active' : 'None'}
|
||
</Badge>
|
||
</div>
|
||
{diagnostics.session.user && (
|
||
<div className="text-xs text-muted-foreground">
|
||
User: {diagnostics.session.user}
|
||
</div>
|
||
)}
|
||
{diagnostics.session.error && (
|
||
<div className="text-xs text-destructive">
|
||
Error: {diagnostics.session.error}
|
||
</div>
|
||
)}
|
||
<div>
|
||
<strong>Cookies Enabled:</strong>{' '}
|
||
<Badge variant={diagnostics.environment.cookiesEnabled ? 'default' : 'destructive'}>
|
||
{diagnostics.environment.cookiesEnabled ? 'Yes' : 'No'}
|
||
</Badge>
|
||
</div>
|
||
{diagnostics.environment.isIframe && (
|
||
<div className="text-xs text-yellow-600 dark:text-yellow-400">
|
||
⚠️ Running in iframe - storage may be restricted
|
||
</div>
|
||
)}
|
||
<Button onClick={runDiagnostics} loading={isRefreshing} loadingText="Refreshing..." variant="outline" size="sm" className="w-full mt-2">
|
||
Refresh Diagnostics
|
||
</Button>
|
||
</CardContent>
|
||
</Card>
|
||
);
|
||
}
|