'use client'; import React, { useState, useEffect, useCallback, Suspense } from 'react'; import Link from 'next/link'; import { useAuth } from '@/contexts/AuthContext'; import { useRouter, useSearchParams } from 'next/navigation'; const SITES = ['broadcastbeat','avbeat','backlotbeat','broadcastengineering']; const STATUSES = ['active','completed','cancelled']; const SCHEDULES = ['single','monthly','quarterly']; function fmt(cents: number) { return '$' + (cents / 100).toLocaleString('en-US', { minimumFractionDigits: 2 }); } function OrdersContent() { const { user, loading } = useAuth(); const router = useRouter(); const sp = useSearchParams(); const [orders, setOrders] = useState([]); const [clients, setClients] = useState([]); const [staff, setStaff] = useState([]); const [products, setProducts] = useState([]); const [loadingData, setLoadingData] = useState(true); const [showForm, setShowForm] = useState(false); const [saving, setSaving] = useState(false); const [filterSite, setFilterSite] = useState(sp.get('site') ?? ''); const [filterStatus, setFilterStatus] = useState(sp.get('status') ?? ''); const [filterClient, setFilterClient] = useState(''); const [errors, setErrors] = useState>({}); const [successMsg, setSuccessMsg] = useState(''); const [form, setForm] = useState({ client_id: '', site: '', product_id: '', ad_unit: '', description: '', start_date: '', end_date: '', total_amount_cents: '', currency: 'USD', invoicing_schedule: 'single', next_invoice_date: '', staff_id: '', po_number: '', notes: '', }); useEffect(() => { if (!loading && !user) router.push('/login'); }, [user, loading, router]); const load = useCallback(async () => { setLoadingData(true); const params = new URLSearchParams(); if (filterSite) params.set('site', filterSite); if (filterStatus) params.set('status', filterStatus); if (filterClient) params.set('client', filterClient); const [ordersRes, clientsRes, staffRes] = await Promise.all([ fetch(`/api/accounting/orders?${params}`), fetch('/api/accounting/clients?status=all'), fetch('/api/accounting/staff'), ]); const [od, cd, sd] = await Promise.all([ordersRes.json(), clientsRes.json(), staffRes.json()]); setOrders(od.orders ?? []); setClients(cd.clients ?? []); setStaff(sd.staff ?? []); setLoadingData(false); }, [filterSite, filterStatus, filterClient]); useEffect(() => { if (user) load(); }, [user, load]); useEffect(() => { if (!form.site) return; fetch(`/api/accounting/products?site=${form.site}`) .then(r => r.json()).then(d => setProducts(d.products ?? [])); }, [form.site]); function handleChange(key: string, value: string) { setForm(p => ({ ...p, [key]: value })); if (errors[key]) setErrors(p => { const n = { ...p }; delete n[key]; return n; }); } function validate() { const errs: Record = {}; if (!form.client_id) errs.client_id = 'Client is required.'; if (!form.site) errs.site = 'Site is required.'; if (form.total_amount_cents && isNaN(parseFloat(form.total_amount_cents))) errs.total_amount_cents = 'Enter a valid amount.'; if (form.total_amount_cents && parseFloat(form.total_amount_cents) < 0) errs.total_amount_cents = 'Amount must be positive.'; if (form.start_date && form.end_date && form.end_date < form.start_date) errs.end_date = 'End date must be after start date.'; return errs; } async function handleCreate(e: React.FormEvent) { e.preventDefault(); const errs = validate(); if (Object.keys(errs).length > 0) { setErrors(errs); return; } setSaving(true); try { const body = { ...form, total_amount_cents: form.total_amount_cents ? Math.round(parseFloat(form.total_amount_cents) * 100) : null }; const res = await fetch('/api/accounting/orders', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }); if (!res.ok) throw new Error('Failed to create order'); const clientName = clients.find((c: any) => c.id === form.client_id)?.company_name ?? 'Order'; setShowForm(false); setErrors({}); setForm({ client_id: '', site: '', product_id: '', ad_unit: '', description: '', start_date: '', end_date: '', total_amount_cents: '', currency: 'USD', invoicing_schedule: 'single', next_invoice_date: '', staff_id: '', po_number: '', notes: '' }); setSuccessMsg(`Order for "${clientName}" created successfully.`); setTimeout(() => setSuccessMsg(''), 4000); load(); } catch { setErrors({ _form: 'Something went wrong. Please try again.' }); } finally { setSaving(false); } } function handleCancel() { setShowForm(false); setErrors({}); setForm({ client_id: '', site: '', product_id: '', ad_unit: '', description: '', start_date: '', end_date: '', total_amount_cents: '', currency: 'USD', invoicing_schedule: 'single', next_invoice_date: '', staff_id: '', po_number: '', notes: '' }); } if (loading) return
; if (!user) return null; return (

Orders

← Accounting
{/* Success Toast */} {successMsg && (
{successMsg}
)} {/* Filters */}
setFilterClient(e.target.value)} placeholder="Filter by client…" className="px-2 py-1 bg-[#111] border border-[#252525] rounded text-xs text-white placeholder-[#555] focus:outline-none focus:border-[#3b82f6]" />
{/* New Order Form */} {showForm && (

New Order

{errors._form && (
{errors._form}
)}
{errors.client_id &&

{errors.client_id}

}
{errors.site &&

{errors.site}

}
handleChange('ad_unit', e.target.value)} className="w-full px-2 py-1.5 bg-[#0a0a0a] border border-[#252525] rounded text-xs text-white focus:outline-none focus:border-[#3b82f6]" />
handleChange('start_date', e.target.value)} className="w-full px-2 py-1.5 bg-[#0a0a0a] border border-[#252525] rounded text-xs text-white focus:outline-none focus:border-[#3b82f6]" />
handleChange('end_date', e.target.value)} className={`w-full px-2 py-1.5 bg-[#0a0a0a] border rounded text-xs text-white focus:outline-none focus:border-[#3b82f6] ${errors.end_date ? 'border-red-500/60' : 'border-[#252525]'}`} /> {errors.end_date &&

{errors.end_date}

}
handleChange('total_amount_cents', e.target.value)} className={`w-full px-2 py-1.5 bg-[#0a0a0a] border rounded text-xs text-white focus:outline-none focus:border-[#3b82f6] ${errors.total_amount_cents ? 'border-red-500/60' : 'border-[#252525]'}`} /> {errors.total_amount_cents &&

{errors.total_amount_cents}

}
handleChange('next_invoice_date', e.target.value)} className="w-full px-2 py-1.5 bg-[#0a0a0a] border border-[#252525] rounded text-xs text-white focus:outline-none focus:border-[#3b82f6]" />
handleChange('po_number', e.target.value)} className="w-full px-2 py-1.5 bg-[#0a0a0a] border border-[#252525] rounded text-xs text-white focus:outline-none focus:border-[#3b82f6]" />