import { useState, useEffect, useCallback } from 'react' import { X, Trash2, MapPin } from 'lucide-react' import toast from 'react-hot-toast' import { useStore } from '../store' import { createContact, updateContact, deleteContact, fetchContacts, fetchReverse } from '../api' const CATEGORIES = ['family', 'friend', 'business', 'emergency', 'ham', 'bug-out', 'favorite'] export default function ContactModal() { const editingContact = useStore((s) => s.editingContact) const clearEditingContact = useStore((s) => s.clearEditingContact) const setContacts = useStore((s) => s.setContacts) const [form, setForm] = useState({}) const [saving, setSaving] = useState(false) useEffect(() => { if (editingContact) { setForm({ label: editingContact.label || '', name: editingContact.name || '', call_sign: editingContact.call_sign || '', phone: editingContact.phone || '', email: editingContact.email || '', category: editingContact.category || '', notes: editingContact.notes || '', show_proximity: editingContact.show_proximity || false, lat: editingContact.lat ?? null, lon: editingContact.lon ?? null, osm_type: editingContact.osm_type || null, osm_id: editingContact.osm_id || null, address: editingContact.address || '', }) } }, [editingContact]) // Auto-populate address from reverse geocode when lat/lon exist but address is empty useEffect(() => { if (!editingContact) return const hasGeo = form.lat != null && form.lon != null const addressEmpty = !form.address || form.address.trim() === '' if (hasGeo && addressEmpty) { let cancelled = false fetchReverse(form.lat, form.lon).then((place) => { if (!cancelled && place) { const addr = place.address || place.name || '' if (addr) { setForm((f) => ({ ...f, address: addr })) } } }) return () => { cancelled = true } } }, [editingContact, form.lat, form.lon]) const close = useCallback(() => clearEditingContact(), [clearEditingContact]) useEffect(() => { if (!editingContact) return const onKey = (e) => { if (e.key === 'Escape') close() } document.addEventListener('keydown', onKey) return () => document.removeEventListener('keydown', onKey) }, [editingContact, close]) if (!editingContact) return null const isEdit = editingContact.id != null const hasGeo = form.lat != null && form.lon != null const setField = (key, val) => setForm((f) => ({ ...f, [key]: val })) const refreshContacts = async () => { const data = await fetchContacts() if (!data?.auth && Array.isArray(data)) setContacts(data) else if (Array.isArray(data)) setContacts(data) } const handleSave = async () => { if (!form.label?.trim()) { toast.error('Label is required') return } setSaving(true) try { const payload = { ...form, label: form.label.trim() } if (payload.show_proximity === false) payload.show_proximity = false const result = isEdit ? await updateContact(editingContact.id, payload) : await createContact(payload) if (result?.auth === false) { toast.error('Sign in to save contacts') setSaving(false) return } if (result?._status === 409 || result?.error?.includes('Home/Work')) { toast.error('You already have a Home/Work contact') setSaving(false) return } toast.success(isEdit ? 'Contact updated' : 'Contact saved') await refreshContacts() close() } catch (e) { toast.error(e.message) } finally { setSaving(false) } } const handleDelete = async () => { if (!confirm('Delete this contact? You can restore it from the dashboard.')) return setSaving(true) try { await deleteContact(editingContact.id) toast('Contact deleted') await refreshContacts() close() } catch (e) { toast.error(e.message) } finally { setSaving(false) } } return (
{ if (e.target === e.currentTarget) close() }}>
{/* Header */}

{isEdit ? 'Edit Contact' : 'Save Contact'}

{/* Label with quick-fill */}
{['Home', 'Work'].map((l) => ( ))}
setField('label', e.target.value)} placeholder="e.g. Home, Work, Mom, Bug Out" />
{/* Address */}
setField('address', e.target.value)} placeholder="Street address, city, state..." />
{/* Location */}
{hasGeo ? (
{form.lat.toFixed(6)}, {form.lon.toFixed(6)}
) : (
No location — save from a place card to attach coordinates
)}
{/* Category */}
setField('category', e.target.value)} placeholder="family, friend, emergency..." /> {CATEGORIES.map((c) =>
{/* Name + Call Sign */}
setField('name', e.target.value)} />
setField('call_sign', e.target.value)} />
{/* Phone + Email */}
setField('phone', e.target.value)} type="tel" />
setField('email', e.target.value)} type="email" />
{/* Notes */}