import type { CrmCustomerHierarchyOptionDto, CrmRecordInput } from "@mrp/shared/dist/crm/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 { CrmRecordForm } from "./CrmRecordForm"; import { type CrmEntity, crmConfigs, emptyCrmRecordInput } from "./config"; interface CrmFormPageProps { entity: CrmEntity; mode: "create" | "edit"; } export function CrmFormPage({ entity, mode }: CrmFormPageProps) { const navigate = useNavigate(); const { token } = useAuth(); const { customerId, vendorId } = useParams(); const recordId = entity === "customer" ? customerId : vendorId; const config = crmConfigs[entity]; const [form, setForm] = useState(emptyCrmRecordInput); const [hierarchyOptions, setHierarchyOptions] = useState([]); const [status, setStatus] = useState( mode === "create" ? `Create a new ${config.singularLabel.toLowerCase()} record.` : `Loading ${config.singularLabel.toLowerCase()}...` ); const [isSaving, setIsSaving] = useState(false); useEffect(() => { if (entity !== "customer" || !token) { return; } api .getCustomerHierarchyOptions(token, mode === "edit" ? recordId : undefined) .then(setHierarchyOptions) .catch(() => setHierarchyOptions([])); }, [entity, mode, recordId, token]); useEffect(() => { if (mode !== "edit" || !token || !recordId) { return; } const loadRecord = entity === "customer" ? api.getCustomer(token, recordId) : api.getVendor(token, recordId); loadRecord .then((record) => { setForm({ name: record.name, email: record.email, phone: record.phone, addressLine1: record.addressLine1, addressLine2: record.addressLine2, city: record.city, state: record.state, postalCode: record.postalCode, country: record.country, status: record.status, isReseller: record.isReseller ?? false, resellerDiscountPercent: record.resellerDiscountPercent ?? 0, parentCustomerId: record.parentCustomerId ?? null, paymentTerms: record.paymentTerms ?? "Net 30", currencyCode: record.currencyCode ?? "USD", taxExempt: record.taxExempt ?? false, creditHold: record.creditHold ?? false, notes: record.notes, }); setStatus(`${config.singularLabel} record loaded.`); }) .catch((error: unknown) => { const message = error instanceof ApiError ? error.message : `Unable to load ${config.singularLabel.toLowerCase()}.`; setStatus(message); }); }, [config.singularLabel, entity, mode, recordId, token]); function updateField(key: Key, value: CrmRecordInput[Key]) { setForm((current: CrmRecordInput) => ({ ...current, [key]: value })); } async function handleSubmit(event: React.FormEvent) { event.preventDefault(); if (!token) { return; } setIsSaving(true); setStatus(`Saving ${config.singularLabel.toLowerCase()}...`); try { const savedRecord = entity === "customer" ? mode === "create" ? await api.createCustomer(token, form) : await api.updateCustomer(token, recordId ?? "", form) : mode === "create" ? await api.createVendor(token, form) : await api.updateVendor(token, recordId ?? "", form); navigate(`${config.routeBase}/${savedRecord.id}`); } catch (error: unknown) { const message = error instanceof ApiError ? error.message : `Unable to save ${config.singularLabel.toLowerCase()}.`; setStatus(message); setIsSaving(false); } } return (

CRM Editor

{mode === "create" ? `New ${config.singularLabel}` : `Edit ${config.singularLabel}`}

Capture the operational contact and address details needed for quoting, purchasing, and shipping workflows.

Cancel
{status}
); }