'use client'; import { connectionMonitor } from '@/lib/api/base/ApiConnectionMonitor'; import { ApiError } from '@/lib/api/base/ApiError'; import { CircuitBreakerRegistry } from '@/lib/api/base/RetryHandler'; import { Badge } from '@/ui/Badge'; import { Button } from '@/ui/Button'; import { Card } from '@/ui/Card'; import { Heading } from '@/ui/Heading'; import { Icon } from '@/ui/Icon'; import { Grid } from '@/ui/primitives/Grid'; import { Stack } from '@/ui/primitives/Stack'; import { Text } from '@/ui/Text'; import { Activity, AlertTriangle, Copy, RefreshCw, Terminal, X } from 'lucide-react'; import { useEffect, useState } from 'react'; interface DevErrorPanelProps { error: ApiError; onReset: () => void; } /** * Developer-focused error panel with detailed debugging information */ export function DevErrorPanel({ error, onReset }: DevErrorPanelProps) { const [connectionStatus, setConnectionStatus] = useState(connectionMonitor.getHealth()); const [circuitBreakers, setCircuitBreakers] = useState(CircuitBreakerRegistry.getInstance().getStatus()); const [copied, setCopied] = useState(false); useEffect(() => { // Update status on mount const health = connectionMonitor.getHealth(); setConnectionStatus(health); setCircuitBreakers(CircuitBreakerRegistry.getInstance().getStatus()); // Listen for status changes const handleStatusChange = () => { setConnectionStatus(connectionMonitor.getHealth()); setCircuitBreakers(CircuitBreakerRegistry.getInstance().getStatus()); }; connectionMonitor.on('success', handleStatusChange); connectionMonitor.on('failure', handleStatusChange); connectionMonitor.on('connected', handleStatusChange); connectionMonitor.on('disconnected', handleStatusChange); connectionMonitor.on('degraded', handleStatusChange); return () => { connectionMonitor.off('success', handleStatusChange); connectionMonitor.off('failure', handleStatusChange); connectionMonitor.off('connected', handleStatusChange); connectionMonitor.off('disconnected', handleStatusChange); connectionMonitor.off('degraded', handleStatusChange); }; }, []); const copyToClipboard = async () => { const debugInfo = { error: { type: error.type, message: error.message, context: error.context, stack: error.stack, }, connection: connectionStatus, circuitBreakers, timestamp: new Date().toISOString(), userAgent: navigator.userAgent, url: window.location.href, }; try { await navigator.clipboard.writeText(JSON.stringify(debugInfo, null, 2)); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch (err) { // Silent failure for clipboard operations } }; const triggerHealthCheck = async () => { await connectionMonitor.performHealthCheck(); setConnectionStatus(connectionMonitor.getHealth()); }; const resetCircuitBreakers = () => { CircuitBreakerRegistry.getInstance().resetAll(); setCircuitBreakers(CircuitBreakerRegistry.getInstance().getStatus()); }; const getSeverityVariant = (): 'danger' | 'warning' | 'info' | 'default' => { switch (error.getSeverity()) { case 'error': return 'danger'; case 'warn': return 'warning'; case 'info': return 'info'; default: return 'default'; } }; const reliability = connectionMonitor.getReliability(); return ( {/* Header */} API Error Debug Panel {error.type} {/* Error Details */} Error Details Type: {error.type} Message: {error.message} Endpoint: {error.context.endpoint || 'N/A'} Method: {error.context.method || 'N/A'} Status: {error.context.statusCode || 'N/A'} Retry Count: {error.context.retryCount || 0} Timestamp: {error.context.timestamp} Retryable: {error.isRetryable() ? 'Yes' : 'No'} Connectivity: {error.isConnectivityIssue() ? 'Yes' : 'No'} {error.context.troubleshooting && ( Troubleshoot: {error.context.troubleshooting} )} {/* Connection Status */} Connection Health Status: {connectionStatus.status.toUpperCase()} Reliability: {reliability.toFixed(2)}% Total Requests: {connectionStatus.totalRequests} Successful: {connectionStatus.successfulRequests} Failed: {connectionStatus.failedRequests} Consecutive Failures: {connectionStatus.consecutiveFailures} Avg Response: {connectionStatus.averageResponseTime.toFixed(2)}ms Last Check: {connectionStatus.lastCheck?.toLocaleTimeString() || 'Never'} {/* Right Column */} {/* Circuit Breakers */} Circuit Breakers {Object.keys(circuitBreakers).length === 0 ? ( No circuit breakers active ) : ( {Object.entries(circuitBreakers).map(([endpoint, status]) => ( {endpoint} {status.state} {status.failures} failures ))} )} {/* Actions */} Actions {/* Quick Fixes */} Quick Fixes Common solutions: Check API server is running Verify CORS configuration Check environment variables Review network connectivity Check API rate limits {/* Raw Error */} Raw Error {JSON.stringify({ type: error.type, message: error.message, context: error.context, }, null, 2)} {/* Console Output */} Console Output {'>'} {error.getDeveloperMessage()} Check browser console for full stack trace and additional debug info. ); }