"use client"; import { useState, useMemo } from "react"; import { useRouter } from "next/navigation"; import { Loader2, AlertCircle } from "lucide-react"; type AssetOption = { id: string; code: string; name: string; category: string }; // Books one invoice line to a plant item from the register. // // Saves immediately on change — there is no separate "save" button to miss on a phone. // On success it refreshes the router so the server-rendered header, banner and totals // re-read from PocketBase rather than showing stale booking state. export function BookingSelect({ lineId, value, assets, }: { lineId: string; value: string; assets: AssetOption[]; }) { const router = useRouter(); const [current, setCurrent] = useState(value); const [saving, setSaving] = useState(false); const [error, setError] = useState(null); // 44 plant items flat in one dropdown is unusable — group them by category. const groups = useMemo(() => { const byCategory = new Map(); for (const a of assets) { const key = a.category || "Other"; if (!byCategory.has(key)) byCategory.set(key, []); byCategory.get(key)!.push(a); } return Array.from(byCategory.entries()) .map(([category, items]) => ({ category, items: items.sort((x, y) => x.code.localeCompare(y.code)) })) .sort((a, b) => a.category.localeCompare(b.category)); }, [assets]); async function book(assetId: string) { const previous = current; setSaving(true); setError(null); setCurrent(assetId); // optimistic try { const res = await fetch(`/api/invoice-lines/${lineId}/book`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ assetId }), }); const data = await res.json().catch(() => ({ ok: false, error: "Unexpected response" })); if (!data.ok) { setCurrent(previous); // roll back so the UI never claims a booking that failed setError(data.error || "Booking failed"); } else { router.refresh(); // re-read server-rendered banner/totals } } catch { setCurrent(previous); setError("Could not reach the server"); } finally { setSaving(false); } } return (
{saving && }
{error && (

{error}

)}
); }