import React, { useState, useMemo } from 'react'; import { useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { ColumnDef } from '@tanstack/react-table'; import { useContacts, useDeleteContact, Contact } from '@/api/hooks'; import { DataGrid } from '@/components/shared/DataGrid'; import { Button } from '@/components/ui/Button'; import { Input } from '@/components/ui/Input'; import { EmptyState } from '@/components/ui/EmptyState'; import { ConfirmDialog } from '@/components/ui/ConfirmDialog'; import { useToast } from '@/components/ui/Toast'; import { Avatar } from '@/components/ui/Avatar'; export function ContactsListPage() { const { t } = useTranslation(); const navigate = useNavigate(); const toast = useToast(); const [page, setPage] = useState(1); const [pageSize] = useState(25); const [search, setSearch] = useState(''); const [debouncedSearch, setDebouncedSearch] = useState(''); const [deleteTarget, setDeleteTarget] = useState(null); const { data, isLoading } = useContacts(page, pageSize, debouncedSearch); const deleteMutation = useDeleteContact(); React.useEffect(() => { const timer = setTimeout(() => setDebouncedSearch(search), 300); return () => clearTimeout(timer); }, [search]); const columns = useMemo[]>( () => [ { id: 'name', header: t('contacts.fullName'), cell: ({ row }) => (
{row.original.first_name} {row.original.last_name}
), }, { accessorKey: 'email', header: t('contacts.email'), cell: (info) => info.getValue() ? ( {info.getValue()} ) : ( '—' ), }, { accessorKey: 'phone', header: t('contacts.phone'), cell: (info) => info.getValue() || '—', }, { accessorKey: 'position', header: t('contacts.position'), cell: (info) => info.getValue() || '—', }, ], [t] ); const handleDelete = async () => { if (!deleteTarget) return; try { await deleteMutation.mutateAsync(deleteTarget.id); toast.success(t('contacts.deleted')); setDeleteTarget(null); } catch (err: any) { toast.error(err.message || t('common.error')); } }; const contacts = data?.items ?? []; const total = data?.total ?? 0; const isEmpty = !isLoading && contacts.length === 0 && !debouncedSearch; if (isEmpty) { return (

{t('contacts.title')}

navigate('/contacts/new')}> {t('contacts.create')} } />
); } return (

{t('contacts.title')}

setSearch(e.target.value)} placeholder={t('common.search')} aria-label={t('common.search')} />
navigate(`/contacts/${row.id}`)} loading={isLoading} emptyMessage={t('common.noResults')} testId="contacts-grid" /> setDeleteTarget(null)} />
); }