'use client' import { useState } from 'react' import { Plus, X, Pencil, Contact as ContactIcon } from 'lucide-react' import { createContact, updateContact, deleteContact } from '@/lib/actions' import { useConfirm } from '@/components/ui/confirm' import type { Tables } from '@/types/database' import { PageTitle } from '@/components/ui/page-title' import { Empty, EmptyHeader, EmptyMedia, EmptyTitle, EmptyContent } from '@/components/ui/empty' type Contact = Tables<'contacts'> const CATEGORY_COLORS: Record = { vendor: 'text-primary border-primary/30 bg-primary/5', supplier: 'text-muted-foreground border-border bg-muted', landlord: 'text-orange-600 border-orange-300 bg-orange-50', city: 'text-red-600 border-red-300 bg-red-50', partner: 'text-blue-600 border-blue-300 bg-blue-50', } const GROUPS: Record = { 'Vendors & Suppliers': ['vendor', 'supplier'], 'Landlord & City': ['landlord', 'city'], 'Community & Partners': ['partner'], } export function ContactsClient({ contacts: initialContacts }: { contacts: Contact[] }) { const confirm = useConfirm() const [contacts, setContacts] = useState(initialContacts) const [search, setSearch] = useState('') const [showCreate, setShowCreate] = useState(false) const [editContact, setEditContact] = useState(null) const [form, setForm] = useState({ name: '', contact_type: 'vendor', email: '', phone: '', details: '', group_label: '', tags: '' }) const [loading, setLoading] = useState(false) const [error, setError] = useState('') const filtered = search ? contacts.filter(c => c.name.toLowerCase().includes(search.toLowerCase()) || c.email?.toLowerCase().includes(search.toLowerCase()) || c.phone?.includes(search) ) : contacts // Group by type const grouped: Record = {} for (const [groupName, types] of Object.entries(GROUPS)) { const items = filtered.filter(c => types.includes(c.contact_type)) if (items.length > 0) grouped[groupName] = items } // Catch any ungrouped const knownTypes = Object.values(GROUPS).flat() const other = filtered.filter(c => !knownTypes.includes(c.contact_type)) if (other.length > 0) grouped['Other'] = other async function handleCreate(e: React.FormEvent) { e.preventDefault() setLoading(true) setError('') const result = await createContact({ ...form, tags: form.tags ? form.tags.split(',').map(t => t.trim()).filter(Boolean) : [], }) if (result.error) { setError(result.error); setLoading(false); return } if (result.data) setContacts(prev => [...prev, result.data as Contact]) setShowCreate(false) resetForm() setLoading(false) } async function handleEdit(e: React.FormEvent) { e.preventDefault() if (!editContact) return setLoading(true) setError('') const result = await updateContact(editContact.id, { ...form, tags: form.tags ? form.tags.split(',').map(t => t.trim()).filter(Boolean) : [], }) if (result.error) { setError(result.error); setLoading(false); return } setContacts(prev => prev.map(c => c.id === editContact.id ? { ...c, ...form } : c)) setEditContact(null) setLoading(false) } async function handleDelete(id: string) { if (!(await confirm({ title: 'Delete contact', description: 'This contact will be permanently removed.', confirmText: 'Delete', destructive: true }))) return const result = await deleteContact(id) if (!result.error) setContacts(prev => prev.filter(c => c.id !== id)) } function openEdit(c: Contact) { setEditContact(c) setForm({ name: c.name, contact_type: c.contact_type, email: c.email ?? '', phone: c.phone ?? '', details: c.details ?? '', group_label: c.group_label ?? '', tags: c.tags?.join(', ') ?? '', }) setError('') } function resetForm() { setForm({ name: '', contact_type: 'vendor', email: '', phone: '', details: '', group_label: '', tags: '' }) setError('') } const ContactForm = ({ onSubmit, submitLabel }: { onSubmit: (e: React.FormEvent) => void, submitLabel: string }) => (
setForm(f => ({ ...f, name: e.target.value }))} className="w-full bg-background border border-border rounded px-3 py-2 font-sans text-sm text-foreground focus:outline-none focus:border-primary transition" />
setForm(f => ({ ...f, email: e.target.value }))} className="w-full bg-background border border-border rounded px-3 py-2 font-sans text-sm text-foreground focus:outline-none focus:border-primary transition" />
setForm(f => ({ ...f, phone: e.target.value }))} className="w-full bg-background border border-border rounded px-3 py-2 font-sans text-sm text-foreground focus:outline-none focus:border-primary transition" />