import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import toast from 'react-hot-toast'; import { Play, CheckCircle2, AlertCircle, Clock } from 'lucide-react'; import { api } from '../../lib/api-client'; import { AppShell, PageHeader, PageBody } from '../../layout/AppShell'; import { Badge, Button, Card } from '../../components/ui/primitives'; interface CronDef { name: string; schedule: string; description: string; last_run: { started_at: string; finished_at: string | null; status: string; output_summary: string | null; error_message: string | null; duration_secs: number | null; } | null; } const STATUS_ICON: Record = { completed: , running: , triggered: , failed: , }; const STATUS_VARIANTS: Record = { completed: 'success', running: 'info', triggered: 'warn', failed: 'danger', }; export function CronMonitor() { const qc = useQueryClient(); const { data } = useQuery({ queryKey: ['crons'], queryFn: () => api.get<{ crons: CronDef[] }>('/crons'), refetchInterval: 15000, }); const triggerMut = useMutation({ mutationFn: (name: string) => api.post('/crons', { name }), onSuccess: (_r, name) => { toast.success(`Cron "${name}" getriggerd`); qc.invalidateQueries({ queryKey: ['crons'] }); }, onError: (e: Error) => toast.error(e.message), }); const crons = data?.crons ?? []; return (
{crons.map((c) => { const last = c.last_run; return (

{c.name}

{last && {last.status}}

{c.description}

{c.schedule}

{last ? ( <>
{STATUS_ICON[last.status] ?? null} Laatst: {new Date(last.started_at).toLocaleString('nl-NL')} {last.duration_secs !== null && ( ({last.duration_secs}s) )}
{last.output_summary && (

{last.output_summary}

)} {last.error_message && (

{last.error_message}

)} ) : (

Nog nooit gedraaid.

)}
); })}
{crons.length === 0 && (
Geen crons geconfigureerd.
)}
); }