import React from 'react'; import clsx from 'clsx'; import { useTranslation } from 'react-i18next'; import { Badge } from '@/components/ui/Badge'; import { Pagination } from '@/components/ui/Pagination'; import { EmptyState } from '@/components/ui/EmptyState'; import type { UnifiedContact } from '@/api/hooks'; export type ContactViewMode = 'list' | 'table' | 'cards'; export interface ContactListProps { contacts: UnifiedContact[]; selectedContactId: string | null; onSelectContact: (contact: UnifiedContact) => void; loading?: boolean; currentPage: number; total: number; pageSize: number; onPageChange: (page: number) => void; viewMode: ContactViewMode; sortBy: string; sortOrder: 'asc' | 'desc'; onSortChange: (sortBy: string, sortOrder: 'asc' | 'desc') => void; } function TypeBadge({ type }: { type: string }) { const { t } = useTranslation(); return ( {type === 'company' ? t('contacts.companies') : t('contacts.persons')} ); } function getDisplayName(c: UnifiedContact): string { return c.displayname || c.name || [c.firstname, c.surname].filter(Boolean).join(' ') || c.email_1 || c.id; } function getInitials(c: UnifiedContact): string { const name = getDisplayName(c); return name.charAt(0).toUpperCase(); } function getCity(c: UnifiedContact): string { return c.mailing_city || c.visit_city || c.invoice_city || '—'; } function getEmail(c: UnifiedContact): string { return c.email_1 || c.email_2 || '—'; } function getPhone(c: UnifiedContact): string { return c.phone_1 || c.phone_2 || '—'; } function getTags(c: UnifiedContact): string[] { if (!c.tags) return []; return c.tags.split(',').map((t) => t.trim()).filter(Boolean); } export function ContactList({ contacts, selectedContactId, onSelectContact, loading, currentPage, total, pageSize, onPageChange, viewMode, sortBy, sortOrder, onSortChange, }: ContactListProps) { const { t } = useTranslation(); if (loading) { return (
{t('common.loading')}
); } if (contacts.length === 0) { return (
); } const totalPages = Math.ceil(total / pageSize); const handleSort = (field: string) => { if (sortBy === field) { onSortChange(field, sortOrder === 'asc' ? 'desc' : 'asc'); } else { onSortChange(field, 'asc'); } }; // ── List View ── if (viewMode === 'list') { return (
); } // ── Table View ── if (viewMode === 'table') { const sortIcon = (field: string) => { if (sortBy !== field) return null; return sortOrder === 'asc' ? ' ▲' : ' ▼'; }; return (
{contacts.map((contact) => ( { e.dataTransfer.setData('text/plain', contact.id); e.dataTransfer.effectAllowed = 'move'; }} onClick={() => onSelectContact(contact)} className={clsx( 'cursor-pointer transition-colors', selectedContactId === contact.id ? 'bg-primary-50' : 'hover:bg-secondary-50', )} aria-current={selectedContactId === contact.id ? 'true' : undefined} > ))}
handleSort('type')} aria-sort={sortBy === 'type' ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none'} > {t('contacts.type')}{sortIcon('type')} handleSort('displayname')} aria-sort={sortBy === 'displayname' ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none'} > {t('contacts.fullName')}{sortIcon('displayname')} handleSort('email_1')} aria-sort={sortBy === 'email_1' ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none'} > {t('contacts.email')}{sortIcon('email_1')} {t('contacts.phone')} handleSort('mailing_city')} aria-sort={sortBy === 'mailing_city' ? (sortOrder === 'asc' ? 'ascending' : 'descending') : 'none'} > {t('address.city')}{sortIcon('mailing_city')} {t('tags.title')}
e.stopPropagation()}> {getDisplayName(contact)} {getEmail(contact)} {getPhone(contact)} {getCity(contact)}
{getTags(contact).slice(0, 3).map((tag) => ( {tag} ))}
); } // ── Cards View ── return (
{contacts.map((contact) => (
{ e.dataTransfer.setData('text/plain', contact.id); e.dataTransfer.effectAllowed = 'move'; }} onClick={() => onSelectContact(contact)} className={clsx( 'p-3 rounded-lg border cursor-pointer transition-colors min-h-touch', selectedContactId === contact.id ? 'border-primary-300 bg-primary-50' : 'border-secondary-200 bg-white hover:bg-secondary-50', )} role="button" tabIndex={0} aria-current={selectedContactId === contact.id ? 'true' : undefined} >
{getInitials(contact)}
{getDisplayName(contact)}
{getEmail(contact)}
{getPhone(contact)}
{getCity(contact)}
))}
); }