'use client'; import React, { useState, useEffect, useCallback } from 'react'; import Link from 'next/link'; import { useAuth } from '@/contexts/AuthContext'; import { useRouter } from 'next/navigation'; interface Client { id: string; company_name: string; contact_name: string; contact_email: string; contact_phone: string; billing_address: string; notes: string; status: string; created_at: string; active_orders?: number; total_revenue?: number; } function fmt(cents: number) { return '$' + (cents / 100).toLocaleString('en-US', { minimumFractionDigits: 2 }); } function validateEmail(email: string) { return !email || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); } export default function ClientsPage() { const { user, loading } = useAuth(); const router = useRouter(); const [clients, setClients] = useState([]); const [filter, setFilter] = useState('active'); const [search, setSearch] = useState(''); const [loadingData, setLoadingData] = useState(true); const [showForm, setShowForm] = useState(false); const [form, setForm] = useState({ company_name: '', contact_name: '', contact_email: '', contact_phone: '', billing_address: '', notes: '' }); const [saving, setSaving] = useState(false); const [errors, setErrors] = useState>({}); const [successMsg, setSuccessMsg] = useState(''); useEffect(() => { if (!loading && !user) router.push('/login?next=' + encodeURIComponent(window.location.pathname)); }, [user, loading, router]); const load = useCallback(async () => { setLoadingData(true); const params = new URLSearchParams({ status: filter, search }); const r = await fetch(`/api/accounting/clients?${params}`); const d = await r.json(); setClients(d.clients ?? []); setLoadingData(false); }, [filter, search]); useEffect(() => { if (user) load(); }, [user, load]); function validate() { const errs: Record = {}; if (!form.company_name.trim()) errs.company_name = 'Company name is required.'; if (!validateEmail(form.contact_email)) errs.contact_email = 'Enter a valid email address.'; return errs; } function handleChange(key: string, value: string) { setForm(p => ({ ...p, [key]: value })); if (errors[key]) setErrors(p => { const n = { ...p }; delete n[key]; return n; }); } async function handleCreate(e: React.FormEvent) { e.preventDefault(); const errs = validate(); if (Object.keys(errs).length > 0) { setErrors(errs); return; } setSaving(true); try { const res = await fetch('/api/accounting/clients', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(form) }); if (!res.ok) throw new Error('Failed to create client'); setShowForm(false); setForm({ company_name: '', contact_name: '', contact_email: '', contact_phone: '', billing_address: '', notes: '' }); setErrors({}); setSuccessMsg(`Client "${form.company_name}" created successfully.`); setTimeout(() => setSuccessMsg(''), 4000); load(); } catch { setErrors({ _form: 'Something went wrong. Please try again.' }); } finally { setSaving(false); } } function handleCancel() { setShowForm(false); setErrors({}); setForm({ company_name: '', contact_name: '', contact_email: '', contact_phone: '', billing_address: '', notes: '' }); } if (loading) return
; if (!user) return null; return (

Clients

← Accounting
{/* Success Toast */} {successMsg && (
{successMsg}
)} {/* Filters */}
{['active','inactive','all'].map(s => ( ))} setSearch(e.target.value)} placeholder="Search clients…" className="ml-auto px-3 py-1 bg-[#111] border border-[#DCE6F2] rounded text-xs text-white placeholder-[#555] focus:outline-none focus:border-[#1D4ED8]" />
{/* New Client Form */} {showForm && (

New Client

{errors._form && (
{errors._form}
)}
{[ { key: 'company_name', label: 'Company Name', required: true }, { key: 'contact_name', label: 'Contact Name' }, { key: 'contact_email', label: 'Email' }, { key: 'contact_phone', label: 'Phone' }, ].map(f => (
handleChange(f.key, e.target.value)} className={`w-full px-2 py-1.5 bg-[#0a0a0a] border rounded text-xs text-white focus:outline-none focus:border-[#1D4ED8] ${errors[f.key] ? 'border-red-500/60' : 'border-[#DCE6F2]'}`} /> {errors[f.key] &&

{errors[f.key]}

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