import React, { useState, useEffect } from 'react' import { Button } from '@/components/ui/button' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Badge } from '@/components/ui/badge' import { ChevronDown, ChevronUp, Clock, CheckCircle, XCircle, Trash2, Filter, ArrowRight } from 'lucide-react' interface EnhancementLog { id: string timestamp: string memoryId: string status: 'success' | 'failed' | 'skipped' model: string processingTime: number before: { title: string | null summary: string | null content: string } after: { title: string summary: string } | null error?: string } interface EnhancementLogsProps { websocket?: WebSocket } export function EnhancementLogs({ websocket }: EnhancementLogsProps) { const [logs, setLogs] = useState([]) const [isExpanded, setIsExpanded] = useState(false) const [isLoading, setIsLoading] = useState(false) const [statusFilter, setStatusFilter] = useState<'all' | 'success' | 'failed'>('all') const [expandedLogs, setExpandedLogs] = useState>(new Set()) // Load logs from API const loadLogs = async () => { setIsLoading(true) try { const response = await fetch('/api/enhancement-logs?limit=100') const data = await response.json() setLogs(data.logs || []) } catch (error) { console.error('Failed to load enhancement logs:', error) } finally { setIsLoading(false) } } // Clear all logs const clearLogs = async () => { try { await fetch('/api/enhancement-logs', { method: 'DELETE' }) setLogs([]) } catch (error) { console.error('Failed to clear logs:', error) } } // WebSocket listener for real-time updates useEffect(() => { if (websocket) { const handleMessage = (event: MessageEvent) => { const message = JSON.parse(event.data) if (message.type === 'enhancementLog') { setLogs(prevLogs => [message.data, ...prevLogs.slice(0, 99)]) } else if (message.type === 'enhancementLogsCleared') { setLogs([]) } } websocket.addEventListener('message', handleMessage) return () => websocket.removeEventListener('message', handleMessage) } }, [websocket]) // Load logs on mount useEffect(() => { if (isExpanded) { loadLogs() } }, [isExpanded]) // Toggle log expansion const toggleLogExpansion = (logId: string) => { setExpandedLogs(prev => { const newSet = new Set(prev) if (newSet.has(logId)) { newSet.delete(logId) } else { newSet.add(logId) } return newSet }) } // Filter logs by status const filteredLogs = logs.filter(log => statusFilter === 'all' || log.status === statusFilter ) // Status badge colors const getStatusBadge = (status: string) => { switch (status) { case 'success': return Success case 'failed': return Failed default: return {status} } } // Format timestamp const formatTimestamp = (timestamp: string) => { return new Date(timestamp).toLocaleString() } return ( setIsExpanded(!isExpanded)}>
Enhancement Logs {logs.length}
{isExpanded ? : }
{isExpanded && ( {/* Controls */}
{/* Log entries */}
{isLoading ? (
Loading logs...
) : filteredLogs.length === 0 ? (
{logs.length === 0 ? 'No enhancement logs yet' : 'No logs match the current filter'}
) : ( filteredLogs.map(log => (
{/* Header */}
{getStatusBadge(log.status)} {formatTimestamp(log.timestamp)} {log.model} {log.processingTime.toFixed(1)}s
{/* Compact view */} {!expandedLogs.has(log.id) && (
{log.memoryId} {log.status === 'success' && log.after && (
{log.before.title ? `"${log.before.title}"` : 'No title'} "{log.after.title}"
)} {log.status === 'failed' && (
Error: {log.error || 'Unknown error'}
)}
)} {/* Expanded view */} {expandedLogs.has(log.id) && (
Memory ID: {log.memoryId}
{/* Before/After comparison */}
{/* Before */}

Before

Title:
{log.before.title || No title}
Summary:
{log.before.summary || No summary}
Content:
{log.before.content}
{/* After */}

After

{log.status === 'success' && log.after ? (
Title:
{log.after.title}
Summary:
{log.after.summary}
) : (
Error:
{log.error || 'Enhancement failed'}
)}
)}
)) )}
)}
) }