'use client'; import { useState } from 'react'; import { AuthGuard } from '@/components/AuthGuard'; import { DashboardLayout } from '@/components/DashboardLayout'; import { useQuery } from '@tanstack/react-query'; import { processingRunsApi, ProcessingRun, ProcessingLog } from '@/lib/api'; import { FileText, ChevronLeft, ChevronRight, CheckCircle, XCircle, Clock, RefreshCw, ChevronDown, ChevronUp, } from 'lucide-react'; const STATUS_STYLES: Record = { completed: 'bg-green-100 text-green-800', failed: 'bg-red-100 text-red-800', partial_failure: 'bg-yellow-100 text-yellow-800', running: 'bg-blue-100 text-blue-800', }; function formatDuration(seconds?: number | null): string { if (seconds == null) return '—'; if (seconds < 60) return `${seconds.toFixed(1)}s`; const totalSecs = Math.floor(seconds); return `${Math.floor(totalSecs / 60)}m ${totalSecs % 60}s`; } function formatDate(iso: string): string { return new Date(iso).toLocaleString(undefined, { dateStyle: 'short', timeStyle: 'medium', }); } function RunRow({ run }: { run: ProcessingRun }) { const [expanded, setExpanded] = useState(false); const [logsPage, setLogsPage] = useState(1); const { data: logsData, isLoading: logsLoading } = useQuery({ queryKey: ['run-logs', run.id, logsPage], queryFn: () => processingRunsApi.getLogs(run.id, { page: logsPage, page_size: 20 }), enabled: expanded, }); const statusClass = STATUS_STYLES[run.status] ?? 'bg-gray-100 text-gray-800'; return ( <> setExpanded((v) => !v)} > {formatDate(run.started_at)}
{run.account_name ?? '—'}
{run.account_email ?? ''}
{run.status} {run.emails_fetched} {run.emails_forwarded} {run.emails_failed > 0 ? run.emails_failed : 0} {formatDuration(run.duration_seconds)} {expanded ? ( ) : ( )} {expanded && ( {run.error_message && (
{run.error_message}
)} {logsLoading ? (
Loading logs…
) : logsData && logsData.items.length > 0 ? ( <> {logsData.items.map((log: ProcessingLog) => ( ))}
Time Level Subject From Status
{formatDate(log.timestamp)} {log.level} {log.email_subject ?? '—'} {log.email_from ?? '—'} {log.success ? ( ) : ( )}
{logsData.pages > 1 && (
Page {logsPage} of {logsData.pages}
)} ) : (

No per-email logs recorded for this run.

)} )} ); } export default function LogsPage() { const [page, setPage] = useState(1); const { data, isLoading, isError, refetch } = useQuery({ queryKey: ['processing-runs', page], queryFn: () => processingRunsApi.list({ page, page_size: 20 }), }); return (
{/* Header */}

Processing Logs

History of email processing runs for all your mail accounts.

{/* Table */} {isLoading ? (
) : isError ? (
Failed to load processing logs. Please try again.
) : data && data.items.length > 0 ? (
{data.items.map((run) => ( ))}
Started Account Status Fetched Forwarded Failed Duration
{/* Pagination */} {data.pages > 1 && (
Page {data.page} of {data.pages} ({data.total} runs)
)}
) : (

No processing runs yet

Logs will appear here once your mail accounts start processing emails.

)}
); }