"use client"; import { useState, useTransition } from "react"; import { Plus, Trash2 } from "lucide-react"; import { toast } from "sonner"; import { logBatchUsage } from "@/app/(app)/usage/actions"; import type { PickerItem } from "@/data/usage.queries"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; const ITEM_TYPES = ["FILAMENT", "RESIN", "PAINT", "SUPPLY"] as const; type ItemType = (typeof ITEM_TYPES)[number]; interface UsageRow { id: string; itemType: ItemType | ""; itemId: string; amount: string; notes: string; } function createEmptyRow(): UsageRow { return { id: crypto.randomUUID(), itemType: "", itemId: "", amount: "", notes: "", }; } interface QuickUsageDialogProps { open: boolean; onOpenChange: (open: boolean) => void; items: PickerItem[]; } export function QuickUsageDialog({ open, onOpenChange, items }: QuickUsageDialogProps) { const [rows, setRows] = useState([createEmptyRow()]); const [isPending, startTransition] = useTransition(); function updateRow(id: string, updates: Partial) { setRows((prev) => prev.map((row) => { if (row.id !== id) return row; const updated = { ...row, ...updates }; // Reset itemId when type changes if (updates.itemType !== undefined && updates.itemType !== row.itemType) { updated.itemId = ""; } return updated; }) ); } function removeRow(id: string) { setRows((prev) => { if (prev.length <= 1) return prev; return prev.filter((row) => row.id !== id); }); } function addRow() { setRows((prev) => [...prev, createEmptyRow()]); } function resetAndClose() { setRows([createEmptyRow()]); onOpenChange(false); } function getItemsForType(type: ItemType | "") { if (!type) return []; return items.filter((item) => item.type === type); } function getUnit(row: UsageRow): string { if (!row.itemId) { if (row.itemType === "FILAMENT") return "g"; if (row.itemType === "RESIN" || row.itemType === "PAINT") return "ml"; return ""; } const item = items.find((i) => i.id === row.itemId); return item?.unit ?? ""; } function isValid(): boolean { return rows.every( (row) => row.itemType !== "" && row.itemId !== "" && row.amount !== "" && Number(row.amount) > 0 ); } function handleSubmit() { if (!isValid()) return; startTransition(async () => { const entries = rows.map((row) => ({ itemType: row.itemType as ItemType, itemId: row.itemId, amount: Number(row.amount), notes: row.notes || undefined, })); const result = await logBatchUsage({ entries }); if (!result.success) { toast.error(result.error || "Failed to log usage"); return; } toast.success( entries.length === 1 ? "Usage logged successfully" : `${entries.length} usage entries logged` ); resetAndClose(); }); } return ( (o ? onOpenChange(true) : resetAndClose())}> Log Usage Record material consumption for one or more items.
{rows.map((row, index) => { const availableItems = getItemsForType(row.itemType); const unit = getUnit(row); return (
Item {index + 1} {rows.length > 1 && ( )}
{/* Item Type */}
{/* Item */}
{/* Amount */}
updateRow(row.id, { amount: e.target.value })} className="h-9" />
{/* Notes */}
updateRow(row.id, { notes: e.target.value })} className="h-9" maxLength={512} />
); })} {/* Add Row */} {/* Actions */}
); }