import React, { useRef, useState, useCallback } from 'react'; import { cn } from '../lib/utils'; import type { LogEntry } from '../types'; import { levelColorMap } from '../constants'; import { Button } from './ui/button'; import { Copy, Check } from 'lucide-react'; import type { LogLevel } from 'scn-ts-core'; const LOG_LEVELS: Exclude[] = ['error', 'warn', 'info', 'debug']; const LogViewer: React.FC<{ logs: readonly LogEntry[] }> = ({ logs }) => { const scrollContainerRef = useRef(null); const [isCopied, setIsCopied] = useState(false); const [visibleLevels, setVisibleLevels] = useState>>( new Set(LOG_LEVELS), ); const handleCopy = useCallback(() => { const logsToCopy = logs.filter(log => visibleLevels.has(log.level)); if (logsToCopy.length > 0) { const logText = logsToCopy .map( log => `${new Date(log.timestamp).toLocaleTimeString()} [${log.level.toUpperCase()}] ${log.message}`, ) .join('\n'); navigator.clipboard.writeText(logText).then(() => { setIsCopied(true); setTimeout(() => setIsCopied(false), 2000); }); } }, [logs, visibleLevels]); const toggleLevel = (level: Exclude) => { setVisibleLevels(prev => { const newSet = new Set(prev); if (newSet.has(level)) { newSet.delete(level); } else { newSet.add(level); } return newSet; }); }; const filteredLogs = logs.filter(log => visibleLevels.has(log.level)); return (
Show levels: {LOG_LEVELS.map(level => ( ))}
{filteredLogs.length === 0 && (

{logs.length === 0 ? 'No logs yet. Click "Analyze" to start.' : 'No logs match the current filter.'}

)} {filteredLogs.map((log, index) => (
{new Date(log.timestamp).toLocaleTimeString()} [{log.level.toUpperCase()}] {log.message}
))}
{logs.length > 0 && ( )}
); }; export default LogViewer;