import { useRef, useEffect, useState } from 'react'; interface LogEntry { id: string; timestamp: Date; level: string; component: string; message: string; metadata?: unknown; } interface LogPanelProps { logs: LogEntry[]; expanded: boolean; onToggleExpand: () => void; } const levelColors: Record = { debug: 'text-gray-500', info: 'text-green-400', warn: 'text-yellow-400', alert: 'text-red-400', error: 'bg-red-800 text-white', crit: 'bg-red-800 text-yellow-300', fatal: 'bg-red-800 text-gray-400', }; function formatTimestamp(date: Date): string { const y = date.getFullYear(); const m = String(date.getMonth() + 1).padStart(2, '0'); const d = String(date.getDate()).padStart(2, '0'); const hh = String(date.getHours()).padStart(2, '0'); const mm = String(date.getMinutes()).padStart(2, '0'); const ss = String(date.getSeconds()).padStart(2, '0'); const ms = String(date.getMilliseconds()).padStart(3, '0'); return `${y}-${m}-${d} ${hh}:${mm}:${ss}.${ms}`; } export default function LogPanel({ logs, expanded, onToggleExpand }: LogPanelProps) { const scrollRef = useRef(null); const [expandedMetadata, setExpandedMetadata] = useState>(new Set()); useEffect(() => { if (scrollRef.current) { scrollRef.current.scrollTop = scrollRef.current.scrollHeight; } }, [logs]); const toggleMetadata = (id: string) => { setExpandedMetadata(prev => { const next = new Set(prev); if (next.has(id)) { next.delete(id); } else { next.add(id); } return next; }); }; return (

Log

{logs.length === 0 ? (
No log entries
) : ( logs.map((entry) => { const levelClass = levelColors[entry.level] || 'text-text-secondary'; return (
{formatTimestamp(entry.timestamp)} {entry.level.toUpperCase().padEnd(5)} {entry.component} {entry.message} {entry.metadata != null && ( )} {entry.metadata != null && expandedMetadata.has(entry.id) && (
                      {JSON.stringify(entry.metadata, null, 2)}
                    
)}
); }) )}
); }