import type { ManufacturingItemOptionDto, ManufacturingProjectOptionDto, WorkOrderInput, } from "@mrp/shared"; import type { WarehouseLocationOptionDto } from "@mrp/shared/dist/inventory/types.js"; import { useEffect, useMemo, useState } from "react"; import { useNavigate, useParams, useSearchParams } from "react-router-dom"; import { useAuth } from "../../auth/AuthProvider"; import { api, ApiError } from "../../lib/api"; import { emptyWorkOrderInput, workOrderStatusOptions } from "./config"; export function WorkOrderFormPage({ mode }: { mode: "create" | "edit" }) { const { token } = useAuth(); const navigate = useNavigate(); const { workOrderId } = useParams(); const [searchParams] = useSearchParams(); const seededProjectId = searchParams.get("projectId"); const seededItemId = searchParams.get("itemId"); const seededSalesOrderId = searchParams.get("salesOrderId"); const seededSalesOrderLineId = searchParams.get("salesOrderLineId"); const seededQuantity = searchParams.get("quantity"); const seededStatus = searchParams.get("status"); const seededDueDate = searchParams.get("dueDate"); const seededNotes = searchParams.get("notes"); const [form, setForm] = useState(emptyWorkOrderInput); const [itemOptions, setItemOptions] = useState([]); const [projectOptions, setProjectOptions] = useState([]); const [locationOptions, setLocationOptions] = useState([]); const [itemSearchTerm, setItemSearchTerm] = useState(""); const [projectSearchTerm, setProjectSearchTerm] = useState(""); const [itemPickerOpen, setItemPickerOpen] = useState(false); const [projectPickerOpen, setProjectPickerOpen] = useState(false); const [status, setStatus] = useState(mode === "create" ? "Create a new work order." : "Loading work order..."); const [isSaving, setIsSaving] = useState(false); useEffect(() => { if (!token) { return; } api.getManufacturingItemOptions(token).then((options) => { setItemOptions(options); if (mode === "create" && seededItemId) { const seededItem = options.find((option) => option.id === seededItemId); if (seededItem) { setForm((current) => ({ ...current, itemId: seededItem.id, salesOrderId: seededSalesOrderId || current.salesOrderId, salesOrderLineId: seededSalesOrderLineId || current.salesOrderLineId, quantity: seededQuantity ? Number.parseInt(seededQuantity, 10) || current.quantity : current.quantity, status: seededStatus && workOrderStatusOptions.some((option) => option.value === seededStatus) ? (seededStatus as WorkOrderInput["status"]) : current.status, dueDate: seededDueDate || current.dueDate, notes: seededNotes || current.notes, })); setItemSearchTerm(`${seededItem.sku} - ${seededItem.name}`); } } }).catch(() => setItemOptions([])); api.getManufacturingProjectOptions(token).then((options) => { setProjectOptions(options); if (mode === "create" && seededProjectId) { const seededProject = options.find((option) => option.id === seededProjectId); if (seededProject) { setForm((current) => ({ ...current, projectId: seededProject.id })); setProjectSearchTerm(`${seededProject.projectNumber} - ${seededProject.name}`); } } }).catch(() => setProjectOptions([])); api.getWarehouseLocationOptions(token).then(setLocationOptions).catch(() => setLocationOptions([])); }, [mode, seededDueDate, seededItemId, seededNotes, seededProjectId, seededQuantity, seededSalesOrderId, seededSalesOrderLineId, seededStatus, token]); useEffect(() => { if (!token || mode !== "edit" || !workOrderId) { return; } api.getWorkOrder(token, workOrderId) .then((workOrder) => { setForm({ itemId: workOrder.itemId, projectId: workOrder.projectId, salesOrderId: workOrder.salesOrderId, salesOrderLineId: workOrder.salesOrderLineId, status: workOrder.status, quantity: workOrder.quantity, warehouseId: workOrder.warehouseId, locationId: workOrder.locationId, dueDate: workOrder.dueDate, notes: workOrder.notes, }); setItemSearchTerm(`${workOrder.itemSku} - ${workOrder.itemName}`); setProjectSearchTerm(workOrder.projectNumber ? `${workOrder.projectNumber} - ${workOrder.projectName}` : ""); setStatus("Work order loaded."); }) .catch((error: unknown) => { const message = error instanceof ApiError ? error.message : "Unable to load work order."; setStatus(message); }); }, [mode, token, workOrderId]); const warehouseOptions = useMemo( () => [...new Map(locationOptions.map((option) => [option.warehouseId, option])).values()], [locationOptions] ); const filteredLocationOptions = useMemo( () => locationOptions.filter((option) => option.warehouseId === form.warehouseId), [form.warehouseId, locationOptions] ); function updateField(key: Key, value: WorkOrderInput[Key]) { setForm((current) => ({ ...current, [key]: value, ...(key === "warehouseId" ? { locationId: "" } : {}), })); } async function handleSubmit(event: React.FormEvent) { event.preventDefault(); if (!token) { return; } setIsSaving(true); setStatus("Saving work order..."); try { const saved = mode === "create" ? await api.createWorkOrder(token, form) : await api.updateWorkOrder(token, workOrderId ?? "", form); navigate(`/manufacturing/work-orders/${saved.id}`); } catch (error: unknown) { const message = error instanceof ApiError ? error.message : "Unable to save work order."; setStatus(message); setIsSaving(false); } } function closeEditor() { navigate(mode === "create" ? "/manufacturing/work-orders" : `/manufacturing/work-orders/${workOrderId}`); } return (

MANUFACTURING EDITOR

{mode === "create" ? "NEW WORK ORDER" : "EDIT WORK ORDER"}