import { useState } from 'react'; import { useParams, Link } from 'react-router-dom'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { ArrowLeft, Phone, Mail, Car, Edit2, Plus } from 'lucide-react'; import { api } from '../api/client'; import { Card, Button, Badge, Input, Modal } from '../components/ui'; import type { Owner, Vehicle, Job } from '../types'; const statusLabel: Record = { received: 'Received', in_progress: 'In Progress', completed: 'Completed', invoiced: 'Invoiced', closed: 'Closed', }; export default function OwnerDetail() { const { id } = useParams(); const queryClient = useQueryClient(); const [showEditModal, setShowEditModal] = useState(false); const { data: owner, isLoading } = useQuery({ queryKey: ['owners', id], queryFn: () => api.getOwner(Number(id)), }); // Get all jobs for this owner const { data: jobs = [] } = useQuery({ queryKey: ['jobs', { ownerId: id }], queryFn: async () => { const allJobs = await api.getJobs({}); return allJobs.filter((j: Job) => j.owner_id === Number(id)); }, enabled: !!id, }); // Get invoices for this owner const { data: invoices = [] } = useQuery({ queryKey: ['invoices', { ownerId: id }], queryFn: () => api.getInvoices({ ownerId: Number(id) }), enabled: !!id, }); const updateMutation = useMutation({ mutationFn: (data: any) => api.updateOwner(Number(id), data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['owners', id] }); setShowEditModal(false); }, }); if (isLoading || !owner) return

Loading...

; const vehicles = owner.vehicles || []; return (
Back to Owners

{owner.first_name} {owner.last_name}

{owner.phone && {owner.phone}} {owner.email && {owner.email}}
{owner.notes && (

Notes

{owner.notes}

)} {/* Vehicles */}

Vehicles ({vehicles.length})

{vehicles.length === 0 ? (

No vehicles registered.

) : (
{vehicles.map((v: Vehicle) => (

{[v.year, v.make, v.model].filter(Boolean).join(' ')}

{[v.color, v.vin && `VIN: ${v.vin}`, v.license_plate && `Plate: ${v.license_plate}`].filter(Boolean).join(' — ')}

))}
)}
{/* Job History */}

Job History ({jobs.length})

{jobs.length === 0 ? (

No jobs yet.

) : (
{jobs.map((job: Job) => (
{job.job_number}

{[job.year, job.make, job.model].filter(Boolean).join(' ')} {job.description && ` — ${job.description.slice(0, 50)}${job.description.length > 50 ? '...' : ''}`}

{statusLabel[job.status]}
))}
)}
{/* Invoices */} {invoices.length > 0 && (

Invoices ({invoices.length})

{invoices.map((inv: any) => (
{inv.invoice_number}

{new Date(inv.invoice_date).toLocaleDateString()} — ${inv.total.toFixed(2)}

{inv.status}
))}
)} {showEditModal && ( setShowEditModal(false)} onSave={(data) => updateMutation.mutate(data)} saving={updateMutation.isPending} /> )}
); } function EditOwnerModal({ owner, open, onClose, onSave, saving }: { owner: Owner; open: boolean; onClose: () => void; onSave: (data: any) => void; saving: boolean; }) { const [form, setForm] = useState({ firstName: owner.first_name, lastName: owner.last_name, phone: owner.phone || '', email: owner.email || '', notes: owner.notes || '', }); return (
{ e.preventDefault(); onSave(form); }} className="space-y-3">
setForm({ ...form, firstName: e.target.value })} required /> setForm({ ...form, lastName: e.target.value })} required />
setForm({ ...form, phone: e.target.value })} /> setForm({ ...form, email: e.target.value })} />