import { useState } from 'react' import { api, message } from '../bridge.js' import CustomerPhoto, { useCustomerPhoto } from './CustomerPhoto.jsx' import VisitHistory from './VisitHistory.jsx' import EraseCustomer from './EraseCustomer.jsx' // The in-store form. Two jobs in one sheet: capture who this person is, and // record what they bought — because staff have the customer in front of them // once, and asking them to open a second screen means the sale never gets // recorded. export default function CustomerForm({ customer, session, onClose, onSaved }) { const [f, setF] = useState({ full_name: customer.full_name ?? '', phone: customer.phone ?? '', email: customer.email ?? '', gender: '', date_of_birth: '', notes: '', consent: customer.has_consent ?? false, }) const [purchase, setPurchase] = useState({ amount: '', items: '', notes: '' }) const [busy, setBusy] = useState(false) const [error, setError] = useState(null) const [erasing, setErasing] = useState(false) const [photo, setPhoto] = useState(null) const fetched = useCustomerPhoto(customer.id) const shown = photo ?? fetched // Erasure destroys a record permanently, so it is a manager's decision. The // server enforces this too — this only avoids offering a button that would // come back 403. const role = session?.user?.role const canErase = ['admin', 'owner', 'manager'].includes(role) const set = k => e => setF({ ...f, [k]: e.target.value }) async function save(e) { e.preventDefault() setBusy(true); setError(null) try { await api.saveProfile({ visitor_id: customer.id, ...f }) const amount = parseFloat(purchase.amount) if (!isNaN(amount) && amount > 0) { const items = purchase.items.split(',').map(s => s.trim()).filter(Boolean) await api.recordPurchase(customer.id, amount, items, purchase.notes) } onSaved() } catch (err) { setError(message(err)) } finally { setBusy(false) } } return (
e.target === e.currentTarget && onClose()}>
setPhoto({ available: false, reason: 'The photo could not be loaded.' })} />

{customer.full_name || customer.label}

{customer.visit_count} visit{customer.visit_count === 1 ? '' : 's'} {customer.last_seen_at && ` · last seen ${new Date(customer.last_seen_at).toLocaleDateString()}`}

{shown && !shown.available && shown.reason &&

{shown.reason}

}
{error &&
{error}
}

Customer details