import { useEffect, useState, type FormEvent } from 'react' import { useNavigate } from 'react-router-dom' import { catalog, partners, salesOrders } from '@/api/client' import type { Item, Partner } from '@/types/api' import { PageHeader } from '@/components/PageHeader' import { ErrorBox } from '@/components/ErrorBox' interface LineInput { itemCode: string quantity: string unitPrice: string } export function CreateSalesOrderPage() { const navigate = useNavigate() const [code, setCode] = useState('') const [partnerCode, setPartnerCode] = useState('') const [currencyCode] = useState('USD') const [lines, setLines] = useState([ { itemCode: '', quantity: '', unitPrice: '' }, ]) const [items, setItems] = useState([]) const [partnerList, setPartnerList] = useState([]) const [submitting, setSubmitting] = useState(false) const [error, setError] = useState(null) useEffect(() => { Promise.all([catalog.listItems(), partners.list()]).then(([i, p]) => { setItems(i) const customers = p.filter((x) => x.type === 'CUSTOMER' || x.type === 'BOTH') setPartnerList(customers) if (customers.length > 0 && !partnerCode) setPartnerCode(customers[0].code) }) }, []) // eslint-disable-line react-hooks/exhaustive-deps const addLine = () => setLines([...lines, { itemCode: items[0]?.code ?? '', quantity: '1', unitPrice: '1.00' }]) const removeLine = (idx: number) => { if (lines.length <= 1) return setLines(lines.filter((_, i) => i !== idx)) } const updateLine = (idx: number, field: keyof LineInput, value: string) => { const next = [...lines] next[idx] = { ...next[idx], [field]: value } setLines(next) } const onSubmit = async (e: FormEvent) => { e.preventDefault() setError(null) setSubmitting(true) try { const created = await salesOrders.create({ code, partnerCode, orderDate: new Date().toISOString().slice(0, 10), currencyCode, lines: lines.map((l, i) => ({ lineNo: i + 1, itemCode: l.itemCode, quantity: Number(l.quantity), unitPrice: Number(l.unitPrice), currencyCode, })), }) navigate(`/sales-orders/${created.id}`) } catch (err: unknown) { setError(err instanceof Error ? err : new Error(String(err))) } finally { setSubmitting(false) } } return (
navigate('/sales-orders')}> Cancel } />
setCode(e.target.value)} placeholder="SO-2026-0003" className="mt-1 w-full rounded-md border border-slate-300 px-3 py-2 text-sm shadow-sm focus:border-brand-500 focus:ring-brand-500" />
{lines.map((line, idx) => (
{idx + 1} updateLine(idx, 'quantity', e.target.value)} className="w-20 rounded-md border border-slate-300 px-2 py-1.5 text-sm text-right" /> updateLine(idx, 'unitPrice', e.target.value)} className="w-24 rounded-md border border-slate-300 px-2 py-1.5 text-sm text-right" />
))}
{error && }
After creation, confirm the order to auto-generate work orders.
) }