import { useState } from 'react'; import { Title, Table, Group, Button, Stack, TextInput, Modal, NumberInput, Select, Badge, ActionIcon, Text, Loader, Center, Tooltip, Alert, } from '@mantine/core'; import { useForm } from '@mantine/form'; import { useDisclosure } from '@mantine/hooks'; import { notifications } from '@mantine/notifications'; import { IconPlus, IconEdit, IconSearch, IconTrash, IconInfoCircle } from '@tabler/icons-react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import api from '../../services/api'; interface Unit { id: string; unit_number: string; address_line1: string; owner_name: string; owner_email: string; monthly_assessment: string; status: string; balance_due?: string; assessment_group_id?: string; assessment_group_name?: string; group_regular_assessment?: string; group_frequency?: string; } interface AssessmentGroup { id: string; name: string; regular_assessment: string; frequency: string; is_default: boolean; } export function UnitsPage() { const [opened, { open, close }] = useDisclosure(false); const [editing, setEditing] = useState(null); const [search, setSearch] = useState(''); const [deleteConfirm, setDeleteConfirm] = useState(null); const queryClient = useQueryClient(); const { data: units = [], isLoading } = useQuery({ queryKey: ['units'], queryFn: async () => { const { data } = await api.get('/units'); return data; }, }); const { data: assessmentGroups = [] } = useQuery({ queryKey: ['assessment-groups'], queryFn: async () => { const { data } = await api.get('/assessment-groups'); return data; }, }); const defaultGroup = assessmentGroups.find(g => g.is_default); const hasGroups = assessmentGroups.length > 0; const form = useForm({ initialValues: { unit_number: '', address_line1: '', city: '', state: '', zip_code: '', owner_name: '', owner_email: '', owner_phone: '', monthly_assessment: 0, assessment_group_id: '' as string | null, }, validate: { unit_number: (v) => (v.length > 0 ? null : 'Required'), assessment_group_id: (v) => (v && v.length > 0 ? null : 'Assessment group is required'), }, }); const saveMutation = useMutation({ mutationFn: (values: any) => { const payload = { ...values, assessment_group_id: values.assessment_group_id || null }; return editing ? api.put(`/units/${editing.id}`, payload) : api.post('/units', payload); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['units'] }); notifications.show({ message: editing ? 'Unit updated' : 'Unit created', color: 'green' }); close(); setEditing(null); form.reset(); }, onError: (err: any) => { notifications.show({ message: err.response?.data?.message || 'Error', color: 'red' }); }, }); const deleteMutation = useMutation({ mutationFn: (id: string) => api.delete(`/units/${id}`), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['units'] }); notifications.show({ message: 'Unit deleted', color: 'green' }); setDeleteConfirm(null); }, onError: (err: any) => { notifications.show({ message: err.response?.data?.message || 'Cannot delete unit', color: 'red' }); setDeleteConfirm(null); }, }); const handleEdit = (u: Unit) => { setEditing(u); form.setValues({ unit_number: u.unit_number, address_line1: u.address_line1 || '', city: '', state: '', zip_code: '', owner_name: u.owner_name || '', owner_email: u.owner_email || '', owner_phone: '', monthly_assessment: parseFloat(u.monthly_assessment || '0'), assessment_group_id: u.assessment_group_id || '', }); open(); }; const handleNew = () => { setEditing(null); form.reset(); // Pre-populate with default group if (defaultGroup) { form.setFieldValue('assessment_group_id', defaultGroup.id); form.setFieldValue('monthly_assessment', parseFloat(defaultGroup.regular_assessment || '0')); } open(); }; const handleGroupChange = (groupId: string | null) => { form.setFieldValue('assessment_group_id', groupId); if (groupId) { const group = assessmentGroups.find(g => g.id === groupId); if (group) { form.setFieldValue('monthly_assessment', parseFloat(group.regular_assessment || '0')); } } }; const filtered = units.filter((u) => !search || u.unit_number.toLowerCase().includes(search.toLowerCase()) || (u.owner_name || '').toLowerCase().includes(search.toLowerCase()) ); if (isLoading) return
; return ( Units / Homeowners {hasGroups ? ( ) : ( )} {!hasGroups && ( } color="yellow" variant="light"> You must create at least one assessment group before adding units. Go to Assessment Groups to create one. )} } value={search} onChange={(e) => setSearch(e.currentTarget.value)} /> Unit # Address Owner Email Group Assessment Status {filtered.map((u) => ( {u.unit_number} {u.address_line1} {u.owner_name} {u.owner_email} {u.assessment_group_name ? ( {u.assessment_group_name} ) : ( - )} ${parseFloat(u.monthly_assessment || '0').toFixed(2)} {u.status} handleEdit(u)}> setDeleteConfirm(u)}> ))} {filtered.length === 0 && No units yet}
{/* Create/Edit Modal */}
saveMutation.mutate(v))}>