dev experience
This commit is contained in:
@@ -3,11 +3,12 @@
|
||||
import { useEffectiveDriverId } from '@/hooks/useEffectiveDriverId';
|
||||
import { useNotifications } from '@/components/notifications/NotificationProvider';
|
||||
import type { NotificationVariant } from '@/components/notifications/notificationTypes';
|
||||
import { Wrench, ChevronDown, ChevronUp, X, MessageSquare, Activity, LogIn, Play } from 'lucide-react';
|
||||
import { Wrench, ChevronDown, ChevronUp, X, MessageSquare, Activity, LogIn, AlertTriangle } from 'lucide-react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { ApiConnectionMonitor } from '@/lib/api/base/ApiConnectionMonitor';
|
||||
import { CircuitBreakerRegistry } from '@/lib/api/base/RetryHandler';
|
||||
import { getGlobalErrorHandler } from '@/lib/infrastructure/GlobalErrorHandler';
|
||||
|
||||
// Import our new components
|
||||
import { Accordion } from './Accordion';
|
||||
@@ -16,7 +17,6 @@ import { UrgencySection } from './sections/UrgencySection';
|
||||
import { NotificationSendSection } from './sections/NotificationSendSection';
|
||||
import { APIStatusSection } from './sections/APIStatusSection';
|
||||
import { LoginSection } from './sections/LoginSection';
|
||||
import { ReplaySection } from './sections/ReplaySection';
|
||||
|
||||
// Import types
|
||||
import type { DemoNotificationType, DemoUrgency, LoginMode } from './types';
|
||||
@@ -39,6 +39,9 @@ export default function DevToolbar() {
|
||||
const [circuitBreakers, setCircuitBreakers] = useState(() => CircuitBreakerRegistry.getInstance().getStatus());
|
||||
const [checkingHealth, setCheckingHealth] = useState(false);
|
||||
|
||||
// Error Stats State
|
||||
const [errorStats, setErrorStats] = useState({ total: 0, byType: {} as Record<string, number> });
|
||||
|
||||
// Accordion state - only one open at a time
|
||||
const [openAccordion, setOpenAccordion] = useState<string | null>('notifications');
|
||||
|
||||
@@ -136,6 +139,28 @@ export default function DevToolbar() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Error Stats Effect
|
||||
useEffect(() => {
|
||||
const updateErrorStats = () => {
|
||||
try {
|
||||
const handler = getGlobalErrorHandler();
|
||||
const stats = handler.getStats();
|
||||
setErrorStats(stats);
|
||||
} catch {
|
||||
// Handler might not be initialized yet
|
||||
setErrorStats({ total: 0, byType: {} });
|
||||
}
|
||||
};
|
||||
|
||||
// Initial update
|
||||
updateErrorStats();
|
||||
|
||||
// Poll for updates every 3 seconds
|
||||
const interval = setInterval(updateErrorStats, 3000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
// API Health Check Handler
|
||||
const handleApiHealthCheck = async () => {
|
||||
setCheckingHealth(true);
|
||||
@@ -412,15 +437,43 @@ export default function DevToolbar() {
|
||||
/>
|
||||
</Accordion>
|
||||
|
||||
{/* Replay Section - Accordion */}
|
||||
{/* Error Stats Section - Accordion */}
|
||||
<Accordion
|
||||
title="Error Replay"
|
||||
icon={<Play className="w-4 h-4 text-gray-400" />}
|
||||
isOpen={openAccordion === 'replay'}
|
||||
onToggle={() => setOpenAccordion(openAccordion === 'replay' ? null : 'replay')}
|
||||
title="Error Stats"
|
||||
icon={<AlertTriangle className="w-4 h-4 text-gray-400" />}
|
||||
isOpen={openAccordion === 'errors'}
|
||||
onToggle={() => setOpenAccordion(openAccordion === 'errors' ? null : 'errors')}
|
||||
>
|
||||
<ReplaySection />
|
||||
<div className="space-y-2 text-xs">
|
||||
<div className="flex justify-between items-center p-2 bg-iron-gray/30 rounded">
|
||||
<span className="text-gray-400">Total Errors</span>
|
||||
<span className="font-mono font-bold text-red-400">{errorStats.total}</span>
|
||||
</div>
|
||||
{Object.keys(errorStats.byType).length > 0 ? (
|
||||
<div className="space-y-1">
|
||||
{Object.entries(errorStats.byType).map(([type, count]) => (
|
||||
<div key={type} className="flex justify-between items-center p-1.5 bg-deep-graphite rounded">
|
||||
<span className="text-gray-300">{type}</span>
|
||||
<span className="font-mono text-yellow-400">{count}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-center text-gray-500 py-2">No errors yet</div>
|
||||
)}
|
||||
<button
|
||||
onClick={() => {
|
||||
const handler = getGlobalErrorHandler();
|
||||
handler.clearHistory();
|
||||
setErrorStats({ total: 0, byType: {} });
|
||||
}}
|
||||
className="w-full p-2 bg-iron-gray hover:bg-charcoal-outline text-gray-300 rounded border border-charcoal-outline text-xs"
|
||||
>
|
||||
Clear Error History
|
||||
</button>
|
||||
</div>
|
||||
</Accordion>
|
||||
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user