website refactor
This commit is contained in:
@@ -1,10 +1,18 @@
|
||||
'use client';
|
||||
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { X, RefreshCw, Copy, Terminal, Activity, AlertTriangle } from 'lucide-react';
|
||||
import { ApiError } from '@/lib/api/base/ApiError';
|
||||
import { connectionMonitor } from '@/lib/api/base/ApiConnectionMonitor';
|
||||
import { CircuitBreakerRegistry } from '@/lib/api/base/RetryHandler';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { X, RefreshCw, Copy, Terminal, Activity, AlertTriangle } from 'lucide-react';
|
||||
import { Box } from '@/ui/Box';
|
||||
import { Text } from '@/ui/Text';
|
||||
import { Stack } from '@/ui/Stack';
|
||||
import { Icon } from '@/ui/Icon';
|
||||
import { Badge } from '@/ui/Badge';
|
||||
import { Button } from '@/ui/Button';
|
||||
import { Heading } from '@/ui/Heading';
|
||||
import { Surface } from '@/ui/Surface';
|
||||
|
||||
interface DevErrorPanelProps {
|
||||
error: ApiError;
|
||||
@@ -80,268 +88,295 @@ export function DevErrorPanel({ error, onReset }: DevErrorPanelProps) {
|
||||
setCircuitBreakers(CircuitBreakerRegistry.getInstance().getStatus());
|
||||
};
|
||||
|
||||
const getSeverityColor = (type: string) => {
|
||||
const getSeverityVariant = (): 'danger' | 'warning' | 'info' | 'default' => {
|
||||
switch (error.getSeverity()) {
|
||||
case 'error': return 'bg-red-500/20 text-red-400 border-red-500/40';
|
||||
case 'warn': return 'bg-yellow-500/20 text-yellow-400 border-yellow-500/40';
|
||||
case 'info': return 'bg-blue-500/20 text-blue-400 border-blue-500/40';
|
||||
default: return 'bg-gray-500/20 text-gray-400 border-gray-500/40';
|
||||
case 'error': return 'danger';
|
||||
case 'warn': return 'warning';
|
||||
case 'info': return 'info';
|
||||
default: return 'default';
|
||||
}
|
||||
};
|
||||
|
||||
const reliability = connectionMonitor.getReliability();
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 overflow-auto bg-deep-graphite p-4 font-mono text-sm">
|
||||
<div className="max-w-6xl mx-auto space-y-4">
|
||||
{/* Header */}
|
||||
<div className="bg-iron-gray border border-charcoal-outline rounded-lg p-4 flex items-center justify-between">
|
||||
<div className="flex items-center gap-3">
|
||||
<Terminal className="w-5 h-5 text-primary-blue" />
|
||||
<h2 className="text-lg font-bold text-white">API Error Debug Panel</h2>
|
||||
<span className={`px-2 py-1 rounded border text-xs ${getSeverityColor(error.type)}`}>
|
||||
{error.type}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
onClick={copyToClipboard}
|
||||
className="px-3 py-1 bg-iron-gray hover:bg-charcoal-outline border border-charcoal-outline rounded text-gray-300 flex items-center gap-2"
|
||||
title="Copy debug info"
|
||||
>
|
||||
<Copy className="w-4 h-4" />
|
||||
{copied ? 'Copied!' : 'Copy'}
|
||||
</button>
|
||||
<button
|
||||
onClick={onReset}
|
||||
className="px-3 py-1 bg-primary-blue hover:bg-primary-blue/80 text-white rounded flex items-center gap-2"
|
||||
>
|
||||
<X className="w-4 h-4" />
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<Box
|
||||
position="fixed"
|
||||
inset="0"
|
||||
zIndex={50}
|
||||
overflow="auto"
|
||||
bg="bg-deep-graphite"
|
||||
p={4}
|
||||
>
|
||||
<Box maxWidth="6xl" mx="auto">
|
||||
<Stack gap={4}>
|
||||
{/* Header */}
|
||||
<Box bg="bg-iron-gray" border borderColor="border-charcoal-outline" rounded="lg" p={4} display="flex" alignItems="center" justifyContent="between">
|
||||
<Box display="flex" alignItems="center" gap={3}>
|
||||
<Icon icon={Terminal} size={5} color="rgb(59, 130, 246)" />
|
||||
<Heading level={2}>API Error Debug Panel</Heading>
|
||||
<Badge variant={getSeverityVariant()}>
|
||||
{error.type}
|
||||
</Badge>
|
||||
</Box>
|
||||
<Box display="flex" gap={2}>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={copyToClipboard}
|
||||
icon={<Icon icon={Copy} size={4} />}
|
||||
>
|
||||
{copied ? 'Copied!' : 'Copy'}
|
||||
</Button>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={onReset}
|
||||
icon={<Icon icon={X} size={4} />}
|
||||
>
|
||||
Close
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Error Details */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
<div className="space-y-4">
|
||||
<div className="bg-iron-gray border border-charcoal-outline rounded-lg overflow-hidden">
|
||||
<div className="bg-charcoal-outline px-4 py-2 font-semibold text-white flex items-center gap-2">
|
||||
<AlertTriangle className="w-4 h-4" />
|
||||
Error Details
|
||||
</div>
|
||||
<div className="p-4 space-y-2 text-xs">
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Type:</span>
|
||||
<span className="col-span-2 text-red-400 font-bold">{error.type}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Message:</span>
|
||||
<span className="col-span-2 text-gray-300">{error.message}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Endpoint:</span>
|
||||
<span className="col-span-2 text-blue-400">{error.context.endpoint || 'N/A'}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Method:</span>
|
||||
<span className="col-span-2 text-yellow-400">{error.context.method || 'N/A'}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Status:</span>
|
||||
<span className="col-span-2">{error.context.statusCode || 'N/A'}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Retry Count:</span>
|
||||
<span className="col-span-2">{error.context.retryCount || 0}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Timestamp:</span>
|
||||
<span className="col-span-2 text-gray-500">{error.context.timestamp}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Retryable:</span>
|
||||
<span className={`col-span-2 ${error.isRetryable() ? 'text-green-400' : 'text-red-400'}`}>
|
||||
{error.isRetryable() ? 'Yes' : 'No'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Connectivity:</span>
|
||||
<span className={`col-span-2 ${error.isConnectivityIssue() ? 'text-red-400' : 'text-green-400'}`}>
|
||||
{error.isConnectivityIssue() ? 'Yes' : 'No'}
|
||||
</span>
|
||||
</div>
|
||||
{error.context.troubleshooting && (
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Troubleshoot:</span>
|
||||
<span className="col-span-2 text-yellow-400">{error.context.troubleshooting}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* Error Details */}
|
||||
<Box display="grid" gridCols={{ base: 1, lg: 2 }} gap={4}>
|
||||
<Stack gap={4}>
|
||||
<Surface variant="muted" rounded="lg" overflow="hidden" border borderColor="border-charcoal-outline">
|
||||
<Box bg="bg-charcoal-outline" px={4} py={2} display="flex" alignItems="center" gap={2}>
|
||||
<Icon icon={AlertTriangle} size={4} color="text-white" />
|
||||
<Text weight="semibold" color="text-white">Error Details</Text>
|
||||
</Box>
|
||||
<Box p={4}>
|
||||
<Stack gap={2} fontSize="0.75rem">
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Type:</Text>
|
||||
<Text colSpan={2} color="text-red-400" weight="bold">{error.type}</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Message:</Text>
|
||||
<Text colSpan={2} color="text-gray-300">{error.message}</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Endpoint:</Text>
|
||||
<Text colSpan={2} color="text-primary-blue">{error.context.endpoint || 'N/A'}</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Method:</Text>
|
||||
<Text colSpan={2} color="text-warning-amber">{error.context.method || 'N/A'}</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Status:</Text>
|
||||
<Text colSpan={2}>{error.context.statusCode || 'N/A'}</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Retry Count:</Text>
|
||||
<Text colSpan={2}>{error.context.retryCount || 0}</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Timestamp:</Text>
|
||||
<Text colSpan={2} color="text-gray-500">{error.context.timestamp}</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Retryable:</Text>
|
||||
<Text colSpan={2} color={error.isRetryable() ? 'text-performance-green' : 'text-red-400'}>
|
||||
{error.isRetryable() ? 'Yes' : 'No'}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Connectivity:</Text>
|
||||
<Text colSpan={2} color={error.isConnectivityIssue() ? 'text-red-400' : 'text-performance-green'}>
|
||||
{error.isConnectivityIssue() ? 'Yes' : 'No'}
|
||||
</Text>
|
||||
</Box>
|
||||
{error.context.troubleshooting && (
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Troubleshoot:</Text>
|
||||
<Text colSpan={2} color="text-warning-amber">{error.context.troubleshooting}</Text>
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
</Box>
|
||||
</Surface>
|
||||
|
||||
{/* Connection Status */}
|
||||
<div className="bg-iron-gray border border-charcoal-outline rounded-lg overflow-hidden">
|
||||
<div className="bg-charcoal-outline px-4 py-2 font-semibold text-white flex items-center gap-2">
|
||||
<Activity className="w-4 h-4" />
|
||||
Connection Health
|
||||
</div>
|
||||
<div className="p-4 space-y-2 text-xs">
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Status:</span>
|
||||
<span className={`col-span-2 font-bold ${
|
||||
connectionStatus.status === 'connected' ? 'text-green-400' :
|
||||
connectionStatus.status === 'degraded' ? 'text-yellow-400' :
|
||||
'text-red-400'
|
||||
}`}>
|
||||
{connectionStatus.status.toUpperCase()}
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Reliability:</span>
|
||||
<span className="col-span-2">{reliability.toFixed(2)}%</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Total Requests:</span>
|
||||
<span className="col-span-2">{connectionStatus.totalRequests}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Successful:</span>
|
||||
<span className="col-span-2 text-green-400">{connectionStatus.successfulRequests}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Failed:</span>
|
||||
<span className="col-span-2 text-red-400">{connectionStatus.failedRequests}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Consecutive Failures:</span>
|
||||
<span className="col-span-2">{connectionStatus.consecutiveFailures}</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Avg Response:</span>
|
||||
<span className="col-span-2">{connectionStatus.averageResponseTime.toFixed(2)}ms</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-2">
|
||||
<span className="text-gray-500">Last Check:</span>
|
||||
<span className="col-span-2 text-gray-500">
|
||||
{connectionStatus.lastCheck?.toLocaleTimeString() || 'Never'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Connection Status */}
|
||||
<Surface variant="muted" rounded="lg" overflow="hidden" border borderColor="border-charcoal-outline">
|
||||
<Box bg="bg-charcoal-outline" px={4} py={2} display="flex" alignItems="center" gap={2}>
|
||||
<Icon icon={Activity} size={4} color="text-white" />
|
||||
<Text weight="semibold" color="text-white">Connection Health</Text>
|
||||
</Box>
|
||||
<Box p={4}>
|
||||
<Stack gap={2} fontSize="0.75rem">
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Status:</Text>
|
||||
<Text colSpan={2} weight="bold" color={
|
||||
connectionStatus.status === 'connected' ? 'text-performance-green' :
|
||||
connectionStatus.status === 'degraded' ? 'text-warning-amber' :
|
||||
'text-red-400'
|
||||
}>
|
||||
{connectionStatus.status.toUpperCase()}
|
||||
</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Reliability:</Text>
|
||||
<Text colSpan={2}>{reliability.toFixed(2)}%</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Total Requests:</Text>
|
||||
<Text colSpan={2}>{connectionStatus.totalRequests}</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Successful:</Text>
|
||||
<Text colSpan={2} color="text-performance-green">{connectionStatus.successfulRequests}</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Failed:</Text>
|
||||
<Text colSpan={2} color="text-red-400">{connectionStatus.failedRequests}</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Consecutive Failures:</Text>
|
||||
<Text colSpan={2}>{connectionStatus.consecutiveFailures}</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Avg Response:</Text>
|
||||
<Text colSpan={2}>{connectionStatus.averageResponseTime.toFixed(2)}ms</Text>
|
||||
</Box>
|
||||
<Box display="grid" gridCols={3} gap={2}>
|
||||
<Text color="text-gray-500">Last Check:</Text>
|
||||
<Text colSpan={2} color="text-gray-500">
|
||||
{connectionStatus.lastCheck?.toLocaleTimeString() || 'Never'}
|
||||
</Text>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Surface>
|
||||
</Stack>
|
||||
|
||||
{/* Right Column */}
|
||||
<div className="space-y-4">
|
||||
{/* Circuit Breakers */}
|
||||
<div className="bg-iron-gray border border-charcoal-outline rounded-lg overflow-hidden">
|
||||
<div className="bg-charcoal-outline px-4 py-2 font-semibold text-white flex items-center gap-2">
|
||||
<span className="text-lg">⚡</span>
|
||||
Circuit Breakers
|
||||
</div>
|
||||
<div className="p-4">
|
||||
{Object.keys(circuitBreakers).length === 0 ? (
|
||||
<div className="text-gray-500 text-center py-4">No circuit breakers active</div>
|
||||
) : (
|
||||
<div className="space-y-2 text-xs max-h-48 overflow-auto">
|
||||
{Object.entries(circuitBreakers).map(([endpoint, status]) => (
|
||||
<div key={endpoint} className="flex items-center justify-between p-2 bg-deep-graphite rounded border border-charcoal-outline">
|
||||
<span className="text-blue-400 truncate flex-1">{endpoint}</span>
|
||||
<span className={`px-2 py-1 rounded ${
|
||||
status.state === 'CLOSED' ? 'bg-green-500/20 text-green-400' :
|
||||
status.state === 'OPEN' ? 'bg-red-500/20 text-red-400' :
|
||||
'bg-yellow-500/20 text-yellow-400'
|
||||
}`}>
|
||||
{status.state}
|
||||
</span>
|
||||
<span className="text-gray-500 ml-2">{status.failures} failures</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{/* Right Column */}
|
||||
<Stack gap={4}>
|
||||
{/* Circuit Breakers */}
|
||||
<Surface variant="muted" rounded="lg" overflow="hidden" border borderColor="border-charcoal-outline">
|
||||
<Box bg="bg-charcoal-outline" px={4} py={2} display="flex" alignItems="center" gap={2}>
|
||||
<Text size="lg">⚡</Text>
|
||||
<Text weight="semibold" color="text-white">Circuit Breakers</Text>
|
||||
</Box>
|
||||
<Box p={4}>
|
||||
{Object.keys(circuitBreakers).length === 0 ? (
|
||||
<Box textAlign="center" py={4}>
|
||||
<Text color="text-gray-500">No circuit breakers active</Text>
|
||||
</Box>
|
||||
) : (
|
||||
<Stack gap={2} maxHeight="12rem" overflow="auto" fontSize="0.75rem">
|
||||
{Object.entries(circuitBreakers).map(([endpoint, status]) => (
|
||||
<Box key={endpoint} display="flex" alignItems="center" justifyContent="between" p={2} bg="bg-deep-graphite" rounded="md" border borderColor="border-charcoal-outline">
|
||||
<Text color="text-primary-blue" truncate flexGrow={1}>{endpoint}</Text>
|
||||
<Box px={2} py={1} rounded="sm" bg={
|
||||
status.state === 'CLOSED' ? 'bg-green-500/20' :
|
||||
status.state === 'OPEN' ? 'bg-red-500/20' :
|
||||
'bg-yellow-500/20'
|
||||
}>
|
||||
<Text color={
|
||||
status.state === 'CLOSED' ? 'text-performance-green' :
|
||||
status.state === 'OPEN' ? 'text-red-400' :
|
||||
'text-warning-amber'
|
||||
}>
|
||||
{status.state}
|
||||
</Text>
|
||||
</Box>
|
||||
<Text color="text-gray-500" ml={2}>{status.failures} failures</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Stack>
|
||||
)}
|
||||
</Box>
|
||||
</Surface>
|
||||
|
||||
{/* Actions */}
|
||||
<div className="bg-iron-gray border border-charcoal-outline rounded-lg overflow-hidden">
|
||||
<div className="bg-charcoal-outline px-4 py-2 font-semibold text-white">
|
||||
Actions
|
||||
</div>
|
||||
<div className="p-4 space-y-2">
|
||||
<button
|
||||
onClick={triggerHealthCheck}
|
||||
className="w-full px-3 py-2 bg-primary-blue hover:bg-primary-blue/80 text-white rounded flex items-center justify-center gap-2"
|
||||
>
|
||||
<RefreshCw className="w-4 h-4" />
|
||||
Run Health Check
|
||||
</button>
|
||||
<button
|
||||
onClick={resetCircuitBreakers}
|
||||
className="w-full px-3 py-2 bg-yellow-600 hover:bg-yellow-700 text-white rounded flex items-center justify-center gap-2"
|
||||
>
|
||||
<span className="text-lg">🔄</span>
|
||||
Reset Circuit Breakers
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
connectionMonitor.reset();
|
||||
setConnectionStatus(connectionMonitor.getHealth());
|
||||
}}
|
||||
className="w-full px-3 py-2 bg-red-600 hover:bg-red-700 text-white rounded flex items-center justify-center gap-2"
|
||||
>
|
||||
<span className="text-lg">🗑️</span>
|
||||
Reset Connection Stats
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/* Actions */}
|
||||
<Surface variant="muted" rounded="lg" overflow="hidden" border borderColor="border-charcoal-outline">
|
||||
<Box bg="bg-charcoal-outline" px={4} py={2}>
|
||||
<Text weight="semibold" color="text-white">Actions</Text>
|
||||
</Box>
|
||||
<Box p={4}>
|
||||
<Stack gap={2}>
|
||||
<Button
|
||||
variant="primary"
|
||||
onClick={triggerHealthCheck}
|
||||
fullWidth
|
||||
icon={<Icon icon={RefreshCw} size={4} />}
|
||||
>
|
||||
Run Health Check
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={resetCircuitBreakers}
|
||||
fullWidth
|
||||
icon={<Text size="lg">🔄</Text>}
|
||||
>
|
||||
Reset Circuit Breakers
|
||||
</Button>
|
||||
<Button
|
||||
variant="danger"
|
||||
onClick={() => {
|
||||
connectionMonitor.reset();
|
||||
setConnectionStatus(connectionMonitor.getHealth());
|
||||
}}
|
||||
fullWidth
|
||||
icon={<Text size="lg">🗑️</Text>}
|
||||
>
|
||||
Reset Connection Stats
|
||||
</Button>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Surface>
|
||||
|
||||
{/* Quick Fixes */}
|
||||
<div className="bg-iron-gray border border-charcoal-outline rounded-lg overflow-hidden">
|
||||
<div className="bg-charcoal-outline px-4 py-2 font-semibold text-white">
|
||||
Quick Fixes
|
||||
</div>
|
||||
<div className="p-4 space-y-2 text-xs">
|
||||
<div className="text-gray-400">Common solutions:</div>
|
||||
<ul className="list-disc list-inside space-y-1 text-gray-300">
|
||||
<li>Check API server is running</li>
|
||||
<li>Verify CORS configuration</li>
|
||||
<li>Check environment variables</li>
|
||||
<li>Review network connectivity</li>
|
||||
<li>Check API rate limits</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{/* Quick Fixes */}
|
||||
<Surface variant="muted" rounded="lg" overflow="hidden" border borderColor="border-charcoal-outline">
|
||||
<Box bg="bg-charcoal-outline" px={4} py={2}>
|
||||
<Text weight="semibold" color="text-white">Quick Fixes</Text>
|
||||
</Box>
|
||||
<Box p={4}>
|
||||
<Stack gap={2} fontSize="0.75rem">
|
||||
<Text color="text-gray-400">Common solutions:</Text>
|
||||
<Stack as="ul" gap={1} pl={4}>
|
||||
<Box as="li"><Text color="text-gray-300">Check API server is running</Text></Box>
|
||||
<Box as="li"><Text color="text-gray-300">Verify CORS configuration</Text></Box>
|
||||
<Box as="li"><Text color="text-gray-300">Check environment variables</Text></Box>
|
||||
<Box as="li"><Text color="text-gray-300">Review network connectivity</Text></Box>
|
||||
<Box as="li"><Text color="text-gray-300">Check API rate limits</Text></Box>
|
||||
</Stack>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Surface>
|
||||
|
||||
{/* Raw Error */}
|
||||
<div className="bg-iron-gray border border-charcoal-outline rounded-lg overflow-hidden">
|
||||
<div className="bg-charcoal-outline px-4 py-2 font-semibold text-white">
|
||||
Raw Error
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<pre className="text-xs text-gray-400 overflow-auto max-h-32 bg-deep-graphite p-2 rounded">
|
||||
{JSON.stringify({
|
||||
type: error.type,
|
||||
message: error.message,
|
||||
context: error.context,
|
||||
}, null, 2)}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Raw Error */}
|
||||
<Surface variant="muted" rounded="lg" overflow="hidden" border borderColor="border-charcoal-outline">
|
||||
<Box bg="bg-charcoal-outline" px={4} py={2}>
|
||||
<Text weight="semibold" color="text-white">Raw Error</Text>
|
||||
</Box>
|
||||
<Box p={4}>
|
||||
<Box as="pre" p={2} bg="bg-deep-graphite" rounded="md" overflow="auto" maxHeight="8rem" fontSize="0.75rem" color="text-gray-400">
|
||||
{JSON.stringify({
|
||||
type: error.type,
|
||||
message: error.message,
|
||||
context: error.context,
|
||||
}, null, 2)}
|
||||
</Box>
|
||||
</Box>
|
||||
</Surface>
|
||||
</Stack>
|
||||
</Box>
|
||||
|
||||
{/* Console Output */}
|
||||
<div className="bg-iron-gray border border-charcoal-outline rounded-lg overflow-hidden">
|
||||
<div className="bg-charcoal-outline px-4 py-2 font-semibold text-white flex items-center gap-2">
|
||||
<Terminal className="w-4 h-4" />
|
||||
Console Output
|
||||
</div>
|
||||
<div className="p-4 bg-deep-graphite font-mono text-xs">
|
||||
<div className="text-gray-500 mb-2">{'>'} {error.getDeveloperMessage()}</div>
|
||||
<div className="text-gray-600">Check browser console for full stack trace and additional debug info.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* Console Output */}
|
||||
<Surface variant="muted" rounded="lg" overflow="hidden" border borderColor="border-charcoal-outline">
|
||||
<Box bg="bg-charcoal-outline" px={4} py={2} display="flex" alignItems="center" gap={2}>
|
||||
<Icon icon={Terminal} size={4} color="text-white" />
|
||||
<Text weight="semibold" color="text-white">Console Output</Text>
|
||||
</Box>
|
||||
<Box p={4} bg="bg-deep-graphite" fontSize="0.75rem">
|
||||
<Text color="text-gray-500" block mb={2}>{'>'} {error.getDeveloperMessage()}</Text>
|
||||
<Text color="text-gray-600" block>Check browser console for full stack trace and additional debug info.</Text>
|
||||
</Box>
|
||||
</Surface>
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user