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 { Link, useNavigate, useParams } 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 [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(setItemOptions).catch(() => setItemOptions([])); api.getManufacturingProjectOptions(token).then(setProjectOptions).catch(() => setProjectOptions([])); api.getWarehouseLocationOptions(token).then(setLocationOptions).catch(() => setLocationOptions([])); }, [token]); useEffect(() => { if (!token || mode !== "edit" || !workOrderId) { return; } api.getWorkOrder(token, workOrderId) .then((workOrder) => { setForm({ itemId: workOrder.itemId, projectId: workOrder.projectId, 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); } } return (

Manufacturing Editor

{mode === "create" ? "New Work Order" : "Edit Work Order"}

Create a build record for a manufactured item, assign it to a project when needed, and define where completed output should post.

Cancel