import { useState, useCallback, useMemo } from 'react' import { Trash2, ScanLine, BarChart3, Sparkles, Send, Clock, CheckCircle, AlertTriangle, XCircle, Filter, } from 'lucide-react' import { Header } from '../components/layout/Header' import { Card, CardContent, Badge, Button, EmptyState, PageLoader } from '../components/common' import { useLogs } from '../hooks' import { endpoints, getErrorMessage } from '../api/client' import { formatTimeAgo, formatNumber } from '../utils' import { t } from '../lib/i18n' import type { LogActionType, LogStatus } from '../types' function getActionConfig(): Record { return { scan: { label: t('Scanning'), icon: ScanLine, color: 'text-blue-600 bg-blue-50' }, analyze: { label: t('Analysis'), icon: BarChart3, color: 'text-purple-600 bg-purple-50' }, generate: { label: t('Generation'), icon: Sparkles, color: 'text-bc-primary bg-bc-primary-light' }, publish: { label: t('Publishing'), icon: Send, color: 'text-green-600 bg-green-50' }, } } function getStatusBadge(): Record { return { success: { label: t('Succeeded'), variant: 'success' }, warning: { label: t('Warning'), variant: 'warning' }, error: { label: t('Error'), variant: 'error' }, } } type FilterAction = 'all' | LogActionType export default function LogsPage() { const [filterAction, setFilterAction] = useState('all') const [isClearing, setIsClearing] = useState(false) const [clearError, setClearError] = useState(null) const [isRefreshing, setIsRefreshing] = useState(false) const { logs, loading, refetch } = useLogs({ limit: 100 }) const handleRefresh = useCallback(async () => { setIsRefreshing(true) await refetch() setIsRefreshing(false) }, [refetch]) const handleClearLogs = async () => { if (!confirm(t('Delete all logs?'))) return setIsClearing(true) setClearError(null) try { await endpoints.deleteLogs() await refetch() } catch (err) { setClearError(getErrorMessage(err, t('Failed to clear logs'))) } finally { setIsClearing(false) } } const filteredLogs = useMemo(() => filterAction === 'all' ? logs : logs.filter(l => l.action_type === filterAction), [logs, filterAction] ) const actionCounts = useMemo(() => ({ all: logs.length, scan: logs.filter(l => l.action_type === 'scan').length, analyze: logs.filter(l => l.action_type === 'analyze').length, generate: logs.filter(l => l.action_type === 'generate').length, publish: logs.filter(l => l.action_type === 'publish').length, }), [logs]) const totalTokens = useMemo( () => logs.reduce((sum, l) => sum + (l.tokens_used || 0), 0), [logs] ) if (loading) return const actionConfig = getActionConfig() const statusBadge = getStatusBadge() return (
{/* Summary stats */}
{logs.length}
{t('Total records')}
{logs.filter(l => l.status === 'success').length}
{t('Succeeded count')}
{logs.filter(l => l.status === 'error').length}
{t('Errors count')}
{formatNumber(totalTokens)}
{t('Tokens used')}
{/* Filter tabs */}
{([ { key: 'all' as FilterAction, label: t('All (filter)') }, { key: 'scan' as FilterAction, label: t('Scans') }, { key: 'analyze' as FilterAction, label: t('Analyses') }, { key: 'generate' as FilterAction, label: t('Generations') }, { key: 'publish' as FilterAction, label: t('Publications') }, ]).map(tab => ( ))}
{logs.length > 0 && ( )}
{clearError && (
{clearError}
)} {/* Logs list */} {filteredLogs.length === 0 ? ( ) : (
{filteredLogs.map(log => { const action = actionConfig[log.action_type] || actionConfig.scan const status = statusBadge[log.status] || statusBadge.success const ActionIcon = action.icon const StatusIcon = log.status === 'success' ? CheckCircle : log.status === 'warning' ? AlertTriangle : XCircle return (
{action.label} {log.post_type && ( {log.post_type} )} {status.label}
{formatTimeAgo(log.created_at)} {log.duration_ms > 0 && ( {(log.duration_ms / 1000).toFixed(1)} {t('seconds')} )} {log.tokens_used > 0 && ( {formatNumber(log.tokens_used)} {t('tokens')} )}
{log.error_message && (

{log.error_message}

)} {log.details && Object.keys(log.details).length > 0 && (
{Object.entries(log.details).map(([key, value]) => ( {formatDetailKey(key)}: {String(value)} ))}
)}
) })}
)}
) } function formatDetailKey(key: string): string { const map: Record = { found_meta_fields: t('meta fields'), found_taxonomies: t('taxonomies'), samples_analyzed: t('samples'), category: t('category'), count: t('count'), post_type: t('content type'), } return map[key] || key.replace(/_/g, ' ') }