import type { ProjectCustomerOptionDto, ProjectDocumentOptionDto, ProjectInput, ProjectOwnerOptionDto, ProjectShipmentOptionDto, } from "@mrp/shared/dist/projects/types.js"; import { useEffect, useState } from "react"; import { Link, useNavigate, useParams } from "react-router-dom"; import { useAuth } from "../../auth/AuthProvider"; import { api, ApiError } from "../../lib/api"; import { emptyProjectInput, projectPriorityOptions, projectStatusOptions } from "./config"; export function ProjectFormPage({ mode }: { mode: "create" | "edit" }) { const { token, user } = useAuth(); const navigate = useNavigate(); const { projectId } = useParams(); const [form, setForm] = useState(() => ({ ...emptyProjectInput, ownerId: user?.id ?? null })); const [customerOptions, setCustomerOptions] = useState([]); const [ownerOptions, setOwnerOptions] = useState([]); const [quoteOptions, setQuoteOptions] = useState([]); const [orderOptions, setOrderOptions] = useState([]); const [shipmentOptions, setShipmentOptions] = useState([]); const [status, setStatus] = useState(mode === "create" ? "Create a new project." : "Loading project..."); const [isSaving, setIsSaving] = useState(false); useEffect(() => { if (!token) { return; } api.getProjectCustomerOptions(token).then(setCustomerOptions).catch(() => setCustomerOptions([])); api.getProjectOwnerOptions(token).then(setOwnerOptions).catch(() => setOwnerOptions([])); }, [token]); useEffect(() => { if (!token || !form.customerId) { setQuoteOptions([]); setOrderOptions([]); setShipmentOptions([]); return; } api.getProjectQuoteOptions(token, form.customerId).then(setQuoteOptions).catch(() => setQuoteOptions([])); api.getProjectOrderOptions(token, form.customerId).then(setOrderOptions).catch(() => setOrderOptions([])); api.getProjectShipmentOptions(token, form.customerId).then(setShipmentOptions).catch(() => setShipmentOptions([])); }, [form.customerId, token]); useEffect(() => { if (!token || mode !== "edit" || !projectId) { return; } api.getProject(token, projectId) .then((project) => { setForm({ name: project.name, status: project.status, priority: project.priority, customerId: project.customerId, salesQuoteId: project.salesQuoteId, salesOrderId: project.salesOrderId, shipmentId: project.shipmentId, ownerId: project.ownerId, dueDate: project.dueDate, notes: project.notes, }); setStatus("Project loaded."); }) .catch((error: unknown) => { const message = error instanceof ApiError ? error.message : "Unable to load project."; setStatus(message); }); }, [mode, projectId, token]); function updateField(key: Key, value: ProjectInput[Key]) { setForm((current: ProjectInput) => ({ ...current, [key]: value, ...(key === "customerId" ? { salesQuoteId: null, salesOrderId: null, shipmentId: null, } : {}), })); } async function handleSubmit(event: React.FormEvent) { event.preventDefault(); if (!token) { return; } setIsSaving(true); setStatus("Saving project..."); try { const saved = mode === "create" ? await api.createProject(token, form) : await api.updateProject(token, projectId ?? "", form); navigate(`/projects/${saved.id}`); } catch (error: unknown) { const message = error instanceof ApiError ? error.message : "Unable to save project."; setStatus(message); setIsSaving(false); } } return (

Projects Editor

{mode === "create" ? "New Project" : "Edit Project"}

Create a customer-linked program record that can anchor commercial documents, delivery work, and project files.

Cancel