"use client"; import { useMemo, useState } from "react"; import { inBounds, presetBounds, saDay, type LogPreset } from "@/lib/oil-log"; import { formatMinutes, JOB_TYPES, jobTypeLabel } from "@/lib/job-cards"; export type JobRow = { id: string; startedAt: string; endedAt: string; open: boolean; asset: string; assetName: string; mechanic: string; type: string; minutes: number; odometer: number | null; note: string; }; const PRESETS: { id: LogPreset; label: string }[] = [ { id: "today", label: "Today" }, { id: "week", label: "This week" }, { id: "month", label: "This month" }, { id: "all", label: "Everything" }, { id: "range", label: "Date range" }, ]; const fmt = (n: number) => n.toLocaleString("en-ZA", { maximumFractionDigits: 1 }); const when = (s: string) => (s ? new Date(s.replace(" ", "T")).toLocaleString("en-ZA", { timeZone: "Africa/Johannesburg", day: "numeric", month: "short", hour: "2-digit", minute: "2-digit", hourCycle: "h23" }) : "—"); export function JobCardsTable({ rows }: { rows: JobRow[] }) { const [preset, setPreset] = useState("month"); const [from, setFrom] = useState(""); const [to, setTo] = useState(""); const [type, setType] = useState(""); const [asset, setAsset] = useState(""); const [mechanic, setMechanic] = useState(""); const assets = useMemo(() => [...new Set(rows.map((r) => r.asset))].filter(Boolean).sort(), [rows]); const mechanics = useMemo(() => [...new Set(rows.map((r) => r.mechanic))].filter(Boolean).sort(), [rows]); const shown = useMemo(() => { const bounds = presetBounds(preset, saDay(new Date().toISOString()), from, to); return rows.filter((r) => inBounds(saDay(r.startedAt), bounds) && (!type || r.type === type) && (!asset || r.asset === asset) && (!mechanic || r.mechanic === mechanic)); }, [rows, preset, from, to, type, asset, mechanic]); const done = shown.filter((r) => !r.open); const totalMinutes = done.reduce((s, r) => s + r.minutes, 0); const field = "min-h-[44px] rounded-lg border border-gray-200 dark:border-border bg-white dark:bg-surface px-3 text-sm"; return (
{PRESETS.map((p) => ( ))}
{preset === "range" && (
setFrom(e.target.value)} aria-label="From" /> to setTo(e.target.value)} aria-label="To" />
)}
{shown.length} job{shown.length !== 1 && "s"} {formatMinutes(totalMinutes)} on finished jobs {shown.some((r) => r.open) && {shown.filter((r) => r.open).length} in progress}
{shown.length === 0 ? (

{rows.length === 0 ? "No job cards yet. Mechanics start one by scanning a vehicle's QR in the Plant Clock app." : "No jobs match these filters."}

) : (
{shown.map((r) => ( ))}
Vehicle Mechanic Started Finished Time Work Odometer Note
{r.asset || "—"}{r.assetName} {r.mechanic || "—"} {when(r.startedAt)} {r.open ? In progress : when(r.endedAt)} {r.open ? "—" : formatMinutes(r.minutes)} {jobTypeLabel(r.type) || "—"} {r.odometer != null ? fmt(r.odometer) : "—"} {r.note || "—"}
)}
); }