import { View, Text, Modal, ScrollView, TouchableOpacity, KeyboardAvoidingView, Platform } from 'react-native'; import { useState } from 'react'; import { X } from 'lucide-react-native'; import * as Location from 'expo-location'; import { Input } from '@/components/ui/Input'; import { Button } from '@/components/ui/Button'; import { useUserStore } from '@/store/useUserStore'; import { getDatabase } from '@/lib/database'; import { newContactId } from '@/lib/contactHelpers'; const STATUS_OPTIONS = ['Active', 'Return Visit', 'Bible Study', 'Not Interested', 'Do Not Call']; const CATEGORY_OPTIONS = ['Adult', 'Teenager', 'Kid']; interface Props { visible: boolean; onClose: () => void; onSaved: () => void; } export function AddContactSheet({ visible, onClose, onSaved }: Props) { const user = useUserStore((s) => s.user); const [fullName, setFullName] = useState(''); const [address, setAddress] = useState(''); const [status, setStatus] = useState('Active'); const [category, setCategory] = useState('Adult'); const [notes, setNotes] = useState(''); const [territoryCode, setTerritoryCode] = useState(''); const [coords, setCoords] = useState<{ lat: number; lng: number } | null>(null); const [loading, setLoading] = useState(false); const [errors, setErrors] = useState>({}); function reset() { setFullName(''); setAddress(''); setStatus('Active'); setCategory('Adult'); setNotes(''); setErrors({}); setTerritoryCode(''); setCoords(null); } async function handleSave() { const errs: Record = {}; if (!fullName.trim()) errs.fullName = 'Name is required'; if (Object.keys(errs).length) { setErrors(errs); return; } setLoading(true); try { const db = await getDatabase(); const now = Math.floor(Date.now() / 1000); const id = newContactId(); await db.runAsync( `INSERT INTO contacts (id, owner_id, full_name, address, category, status, tags, notes, territory_code, latitude, longitude, household_count, created_at, updated_at) VALUES (?, ?, ?, ?, ?, ?, '[]', ?, ?, ?, ?, 1, ?, ?)`, [id, user?.id ?? 'unknown', fullName.trim(), address.trim() || null, category, status, notes.trim() || null, territoryCode.trim().toUpperCase() || null, coords?.lat ?? null, coords?.lng ?? null, now, now] ); reset(); onSaved(); } catch (e) { console.error('Save contact error:', e); } finally { setLoading(false); } } return ( {/* Header */} { reset(); onClose(); }} accessibilityRole="button" accessibilityLabel="Close" style={{ minWidth: 44, minHeight: 44, alignItems: 'center', justifyContent: 'center' }} > New Contact { setFullName(t); setErrors((e) => ({ ...e, fullName: '' })); }} error={errors.fullName} /> {/* Status */} Status {STATUS_OPTIONS.map((s) => ( setStatus(s)} className={`px-3 py-1.5 rounded-full border ${status === s ? 'bg-primary border-primary' : 'bg-white border-gray-200'}`} accessibilityRole="button" accessibilityLabel={`Status: ${s}`} accessibilityState={{ selected: status === s }} style={{ minHeight: 36 }} > {s} ))} {/* Category */} Category {CATEGORY_OPTIONS.map((c) => ( setCategory(c)} className={`px-3 py-1.5 rounded-full border ${category === c ? 'bg-primary border-primary' : 'bg-white border-gray-200'}`} accessibilityRole="button" accessibilityLabel={`Category: ${c}`} accessibilityState={{ selected: category === c }} style={{ minHeight: 36 }} > {c} ))} {/* Territory Code */} {/* GPS Tag */} { const { status } = await Location.requestForegroundPermissionsAsync(); if (status !== 'granted') { alert('Location permission denied'); return; } const loc = await Location.getCurrentPositionAsync({}); setCoords({ lat: loc.coords.latitude, lng: loc.coords.longitude }); }} className={`flex-row items-center border rounded-xl px-4 py-3 mb-4 ${coords ? 'border-primary bg-primary/5' : 'border-gray-200 bg-white'}`} > 📍 {coords ? `GPS: ${coords.lat.toFixed(5)}, ${coords.lng.toFixed(5)}` : 'Tag GPS Location (optional)'}