"use client"; import { useState, useEffect } from "react"; import useSWR from "swr"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { toast } from "sonner"; import { formatCurrency } from "@/lib/format"; import type { Component } from "@/lib/types"; const fetcher = (url: string) => fetch(url).then((r) => r.json()); interface AddStockDialogProps { open: boolean; onOpenChange: (open: boolean) => void; component: Component | null; onSaved: () => void; onPrintLabel?: (partNumber: string, quantity: number) => void; } const transactionTypes = [ { value: "purchase", label: "Purchase (New Stock)" }, { value: "adjustment", label: "Adjustment (Correction)" }, { value: "return", label: "Return (Supplier Return)" }, { value: "consumption", label: "Consumption (Used/Removed)" }, ]; export function AddStockDialog({ open, onOpenChange, component, onSaved, onPrintLabel, }: AddStockDialogProps) { const [loading, setLoading] = useState(false); const [form, setForm] = useState({ transaction_type: "purchase", quantity: "", unit_cost: "", supplier: "", supplier_code: "", supplier_order_ref: "", notes: "", }); // Fetch available supplier POs for dropdown const { data: supplierPos = [] } = useSWR>( open ? "/api/supplier-pos" : null, fetcher ); useEffect(() => { if (open && component) { setForm({ transaction_type: "purchase", quantity: "", unit_cost: String(component.unit_price || ""), supplier: component.supplier || "", supplier_code: component.supplier_code || "", supplier_order_ref: "", notes: "", }); } }, [open, component]); async function handleSubmit(e: React.FormEvent) { e.preventDefault(); if (!component) return; if (!form.quantity || Number(form.quantity) <= 0) { toast.error("Quantity must be greater than 0"); return; } setLoading(true); try { const res = await fetch("/api/stock", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ component_id: component.id, transaction_type: form.transaction_type, quantity: Number(form.quantity), unit_cost: form.unit_cost ? Number(form.unit_cost) : null, supplier: form.supplier || null, supplier_order_ref: form.supplier_order_ref || null, notes: form.notes || null, }), }); if (!res.ok) { const err = await res.json(); throw new Error(err.error || "Failed to save"); } const typeLabel = transactionTypes.find( (t) => t.value === form.transaction_type )?.label; toast.success( `Stock ${form.transaction_type === "consumption" ? "reduced" : "added"}: ${form.quantity} units (${typeLabel})` ); const qty = Number(form.quantity); const partNum = component.part_number; onSaved(); onOpenChange(false); // Prompt label printing for non-consumption transactions if (form.transaction_type !== "consumption" && onPrintLabel) { onPrintLabel(partNum, qty); } } catch (err) { toast.error( err instanceof Error ? err.message : "Failed to update stock" ); } finally { setLoading(false); } } const totalCost = form.unit_cost && form.quantity ? (Number(form.unit_cost) * Number(form.quantity)).toFixed(2) : null; return ( {form.transaction_type === "consumption" ? "Remove Stock" : "Add Stock"} {component?.name} ({component?.part_number}) - Current stock:{" "} {component?.stock_quantity}
setForm({ ...form, quantity: e.target.value }) } placeholder="e.g. 100" required />
setForm({ ...form, unit_cost: e.target.value }) } placeholder="0.0000" />
{totalCost && (
Total cost:{" "} {formatCurrency(Number(totalCost))}
)} {form.transaction_type !== "consumption" && ( <>
setForm({ ...form, supplier: e.target.value }) } placeholder="e.g. Digi-Key" />
setForm({ ...form, supplier_code: e.target.value }) } placeholder="e.g. C245215" className="font-mono" />
{form.transaction_type === "purchase" && (

Only open POs (pending, ordered, partial) are shown

)} )}