website refactor

This commit is contained in:
2026-01-15 17:12:24 +01:00
parent c3b308e960
commit f035cfe7ce
468 changed files with 24378 additions and 17324 deletions

View File

@@ -1,27 +1,32 @@
'use client';
import { useEffectiveDriverId } from "@/lib/hooks/useEffectiveDriverId";
import { useNotifications } from '@/components/notifications/NotificationProvider';
import type { NotificationVariant } from '@/components/notifications/notificationTypes';
import React, { useEffect, useState } from 'react';
import { Wrench, ChevronDown, ChevronUp, X, MessageSquare, Activity, 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 { useEffectiveDriverId } from "@/hooks/useEffectiveDriverId";
import { useNotifications } from '@/components/notifications/NotificationProvider';
import type { NotificationVariant } from '@/components/notifications/notificationTypes';
// Import our new components
import { Accordion } from './Accordion';
import { Accordion } from '@/ui/Accordion';
import { NotificationTypeSection } from './sections/NotificationTypeSection';
import { UrgencySection } from './sections/UrgencySection';
import { NotificationSendSection } from './sections/NotificationSendSection';
import { APIStatusSection } from './sections/APIStatusSection';
import { Box } from '@/ui/Box';
import { Text } from '@/ui/Text';
import { Stack } from '@/ui/Stack';
import { Icon } from '@/ui/Icon';
import { IconButton } from '@/ui/IconButton';
import { Badge } from '@/ui/Badge';
import { Button } from '@/ui/Button';
// Import types
import type { DemoNotificationType, DemoUrgency } from './types';
export default function DevToolbar() {
const router = useRouter();
export function DevToolbar() {
const { addNotification } = useNotifications();
const [isExpanded, setIsExpanded] = useState(false);
const [isMinimized, setIsMinimized] = useState(false);
@@ -225,140 +230,155 @@ export default function DevToolbar() {
if (isMinimized) {
return (
<button
onClick={() => setIsMinimized(false)}
className="fixed bottom-4 right-4 z-50 p-3 bg-iron-gray border border-charcoal-outline rounded-full shadow-lg hover:bg-charcoal-outline transition-colors"
title="Open Dev Toolbar"
>
<Wrench className="w-5 h-5 text-primary-blue" />
</button>
<Box position="fixed" bottom="4" right="4" zIndex={50}>
<IconButton
icon={Wrench}
onClick={() => setIsMinimized(false)}
variant="secondary"
title="Open Dev Toolbar"
size="lg"
/>
</Box>
);
}
return (
<div className="fixed bottom-4 right-4 z-50 w-80 bg-deep-graphite border border-charcoal-outline rounded-xl shadow-2xl overflow-hidden">
<Box
position="fixed"
bottom="4"
right="4"
zIndex={50}
w="80"
bg="bg-deep-graphite"
border
borderColor="border-charcoal-outline"
rounded="xl"
shadow="2xl"
overflow="hidden"
>
{/* Header */}
<div className="flex items-center justify-between px-4 py-3 bg-iron-gray/50 border-b border-charcoal-outline">
<div className="flex items-center gap-2">
<Wrench className="w-4 h-4 text-primary-blue" />
<span className="text-sm font-semibold text-white">Dev Toolbar</span>
<span className="px-1.5 py-0.5 text-[10px] font-medium bg-primary-blue/20 text-primary-blue rounded">
<Box display="flex" alignItems="center" justifyContent="between" px={4} py={3} bg="bg-iron-gray/50" borderBottom borderColor="border-charcoal-outline">
<Box display="flex" alignItems="center" gap={2}>
<Icon icon={Wrench} size={4} color="rgb(59, 130, 246)" />
<Text size="sm" weight="semibold" color="text-white">Dev Toolbar</Text>
<Badge variant="primary" size="xs">
DEMO
</span>
</div>
<div className="flex items-center gap-1">
<button
</Badge>
</Box>
<Box display="flex" alignItems="center" gap={1}>
<IconButton
icon={isExpanded ? ChevronDown : ChevronUp}
onClick={() => setIsExpanded(!isExpanded)}
className="p-1.5 hover:bg-charcoal-outline rounded transition-colors"
>
{isExpanded ? (
<ChevronDown className="w-4 h-4 text-gray-400" />
) : (
<ChevronUp className="w-4 h-4 text-gray-400" />
)}
</button>
<button
variant="ghost"
size="sm"
/>
<IconButton
icon={X}
onClick={() => setIsMinimized(true)}
className="p-1.5 hover:bg-charcoal-outline rounded transition-colors"
>
<X className="w-4 h-4 text-gray-400" />
</button>
</div>
</div>
variant="ghost"
size="sm"
/>
</Box>
</Box>
{/* Content */}
{isExpanded && (
<div className="p-4 space-y-3">
{/* Notification Section - Accordion */}
<Accordion
title="Notifications"
icon={<MessageSquare className="w-4 h-4 text-gray-400" />}
isOpen={openAccordion === 'notifications'}
onToggle={() => setOpenAccordion(openAccordion === 'notifications' ? null : 'notifications')}
>
<div className="space-y-3">
<NotificationTypeSection
selectedType={selectedType}
onSelectType={setSelectedType}
/>
<UrgencySection
selectedUrgency={selectedUrgency}
onSelectUrgency={setSelectedUrgency}
/>
<NotificationSendSection
selectedType={selectedType}
selectedUrgency={selectedUrgency}
sending={sending}
lastSent={lastSent}
onSend={handleSendNotification}
/>
</div>
</Accordion>
<Box p={4}>
<Stack gap={3}>
{/* Notification Section - Accordion */}
<Accordion
title="Notifications"
icon={<Icon icon={MessageSquare} size={4} color="rgb(156, 163, 175)" />}
isOpen={openAccordion === 'notifications'}
onToggle={() => setOpenAccordion(openAccordion === 'notifications' ? null : 'notifications')}
>
<Stack gap={3}>
<NotificationTypeSection
selectedType={selectedType}
onSelectType={setSelectedType}
/>
<UrgencySection
selectedUrgency={selectedUrgency}
onSelectUrgency={setSelectedUrgency}
/>
<NotificationSendSection
selectedType={selectedType}
selectedUrgency={selectedUrgency}
sending={sending}
lastSent={lastSent}
onSend={handleSendNotification}
/>
</Stack>
</Accordion>
{/* API Status Section - Accordion */}
<Accordion
title="API Status"
icon={<Activity className="w-4 h-4 text-gray-400" />}
isOpen={openAccordion === 'apiStatus'}
onToggle={() => setOpenAccordion(openAccordion === 'apiStatus' ? null : 'apiStatus')}
>
<APIStatusSection
apiStatus={apiStatus}
apiHealth={apiHealth}
circuitBreakers={circuitBreakers}
checkingHealth={checkingHealth}
onHealthCheck={handleApiHealthCheck}
onResetStats={handleResetApiStats}
onTestError={handleTestApiError}
/>
</Accordion>
{/* API Status Section - Accordion */}
<Accordion
title="API Status"
icon={<Icon icon={Activity} size={4} color="rgb(156, 163, 175)" />}
isOpen={openAccordion === 'apiStatus'}
onToggle={() => setOpenAccordion(openAccordion === 'apiStatus' ? null : 'apiStatus')}
>
<APIStatusSection
apiStatus={apiStatus}
apiHealth={apiHealth}
circuitBreakers={circuitBreakers}
checkingHealth={checkingHealth}
onHealthCheck={handleApiHealthCheck}
onResetStats={handleResetApiStats}
onTestError={handleTestApiError}
/>
</Accordion>
{/* Error Stats Section - Accordion */}
<Accordion
title="Error Stats"
icon={<AlertTriangle className="w-4 h-4 text-gray-400" />}
isOpen={openAccordion === 'errors'}
onToggle={() => setOpenAccordion(openAccordion === 'errors' ? null : 'errors')}
>
<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>
{/* Error Stats Section - Accordion */}
<Accordion
title="Error Stats"
icon={<Icon icon={AlertTriangle} size={4} color="rgb(156, 163, 175)" />}
isOpen={openAccordion === 'errors'}
onToggle={() => setOpenAccordion(openAccordion === 'errors' ? null : 'errors')}
>
<Stack gap={2}>
<Box display="flex" justifyContent="between" alignItems="center" p={2} bg="bg-iron-gray/30" rounded="md">
<Text size="xs" color="text-gray-400">Total Errors</Text>
<Text size="xs" font="mono" weight="bold" color="text-red-400">{errorStats.total}</Text>
</Box>
{Object.keys(errorStats.byType).length > 0 ? (
<Stack gap={1}>
{Object.entries(errorStats.byType).map(([type, count]) => (
<Box key={type} display="flex" justifyContent="between" alignItems="center" p={1.5} bg="bg-deep-graphite" rounded="md">
<Text size="xs" color="text-gray-300">{type}</Text>
<Text size="xs" font="mono" color="text-warning-amber">{count}</Text>
</Box>
))}
</Stack>
) : (
<Box textAlign="center" py={2}>
<Text size="xs" color="text-gray-500">No errors yet</Text>
</Box>
)}
<Button
variant="secondary"
onClick={() => {
const handler = getGlobalErrorHandler();
handler.clearHistory();
setErrorStats({ total: 0, byType: {} });
}}
fullWidth
size="sm"
>
Clear Error History
</Button>
</Stack>
</Accordion>
</Stack>
</Box>
)}
{/* Collapsed state hint */}
{!isExpanded && (
<div className="px-4 py-2 text-xs text-gray-500">
Click to expand dev tools
</div>
<Box px={4} py={2}>
<Text size="xs" color="text-gray-500">Click to expand dev tools</Text>
</Box>
)}
</div>
</Box>
);
}
}