diff --git a/frontend/src/pages/Batch.tsx b/frontend/src/pages/Batch.tsx
index 6620597..d0c271b 100644
--- a/frontend/src/pages/Batch.tsx
+++ b/frontend/src/pages/Batch.tsx
@@ -1,7 +1,7 @@
import { useState } from 'react';
-import { useMutation } from '@tanstack/react-query';
+import { useMutation, useQuery } from '@tanstack/react-query';
import { analysisApi } from '../api/client';
-import { Rocket, CheckCircle, AlertCircle, ChevronDown, ChevronUp } from 'lucide-react';
+import { Rocket, CheckCircle, AlertCircle, ChevronDown, ChevronUp, RefreshCw, Inbox } from 'lucide-react';
import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer, Cell } from 'recharts';
import type { BatchAnalysisResult } from '../types';
@@ -11,10 +11,18 @@ export function Batch() {
const [result, setResult] = useState(null);
const [expandedItems, setExpandedItems] = useState>(new Set());
+ const jobsQuery = useQuery({
+ queryKey: ['jobs'],
+ queryFn: () => analysisApi.listJobs(undefined, 20),
+ });
+
const mutation = useMutation({
mutationFn: ({ companies, workers }: { companies: string[]; workers: number }) =>
analysisApi.analyzeBatch(companies, workers),
- onSuccess: (data) => setResult(data),
+ onSuccess: (data) => {
+ setResult(data);
+ jobsQuery.refetch();
+ },
});
const handleSubmit = (e: React.FormEvent) => {
@@ -123,12 +131,29 @@ export function Batch() {
{mutation.error instanceof Error ? mutation.error.message : 'An unexpected error occurred.'}
{' '}Check your connection and try again.
-
+
+
+
+
)}
@@ -230,6 +255,123 @@ export function Batch() {
)}
+
+ {/* Job History */}
+
+
+ Job History
+
+
+ {/* Loading skeleton */}
+ {jobsQuery.isLoading && (
+
+ {[...Array(3)].map((_, i) => (
+
+ ))}
+
+ )}
+
+ {/* Job history error */}
+ {jobsQuery.isError && (
+
+
+
+
Failed to load job history
+
+
+ {jobsQuery.error instanceof Error ? jobsQuery.error.message : 'Could not retrieve past jobs.'}
+
+
+
+ )}
+
+ {/* Empty state */}
+ {jobsQuery.isSuccess && jobsQuery.data.length === 0 && !result && (
+
+
+
No batch jobs yet
+
+ Submit a batch analysis above to get started. Your job history will appear here.
+
+
+ )}
+
+ {/* Job list */}
+ {jobsQuery.isSuccess && jobsQuery.data.length > 0 && (
+
+ {jobsQuery.data.map((job) => (
+
+
+
+ {job.status === 'completed' &&
}
+ {job.status === 'failed' &&
}
+ {(job.status === 'pending' || job.status === 'running') && (
+
+ )}
+
{job.job_id.slice(0, 8)}
+
+ {job.total_companies} {job.total_companies === 1 ? 'company' : 'companies'}
+
+
+
+ {job.status}
+
+
+ {(job.status === 'running' || job.status === 'pending') && job.total_companies > 0 && (
+
+
+ Progress
+ {job.completed_companies}/{job.total_companies}
+
+
+
+ )}
+ {job.status === 'failed' && job.error && (
+
{job.error}
+ )}
+
+ ))}
+
+ )}
+
);
}