import React, { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { Link, useNavigate } from 'react-router-dom'; import { __ } from '@/lib/i18n'; import { CustomersApi, type Customer } from '@/lib/api/customers'; import { showErrorToast, showSuccessToast, getPageLoadErrorMessage } from '@/lib/errorHandling'; import { useFABConfig } from '@/hooks/useFABConfig'; import { Checkbox } from '@/components/ui/checkbox'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { Card } from '@/components/ui/card'; import { ErrorCard } from '@/components/ErrorCard'; import { Skeleton } from '@/components/ui/skeleton'; import { RefreshCw, Trash2, Search, User, ChevronRight } from 'lucide-react'; import { formatMoney } from '@/lib/currency'; export default function CustomersIndex() { const navigate = useNavigate(); const queryClient = useQueryClient(); // State const [page, setPage] = useState(1); const [search, setSearch] = useState(''); const [selectedIds, setSelectedIds] = useState([]); // FAB config - 'none' because submenu has 'New' tab (per SOP) useFABConfig('none'); // Fetch customers const customersQuery = useQuery({ queryKey: ['customers', page, search], queryFn: () => CustomersApi.list({ page, per_page: 20, search }), }); // Delete mutation const deleteMutation = useMutation({ mutationFn: async (ids: number[]) => { await Promise.all(ids.map(id => CustomersApi.delete(id))); }, onSuccess: () => { showSuccessToast(__('Customers deleted successfully')); setSelectedIds([]); queryClient.invalidateQueries({ queryKey: ['customers'] }); }, onError: (error: any) => { showErrorToast(error); }, }); // Handlers const toggleSelection = (id: number) => { setSelectedIds(prev => prev.includes(id) ? prev.filter(i => i !== id) : [...prev, id] ); }; const toggleAll = () => { if (selectedIds.length === customers.length) { setSelectedIds([]); } else { setSelectedIds(customers.map(c => c.id)); } }; const handleDelete = () => { if (selectedIds.length === 0) return; if (!confirm(__('Are you sure you want to delete the selected customers? This action cannot be undone.'))) return; deleteMutation.mutate(selectedIds); }; const handleRefresh = () => { queryClient.invalidateQueries({ queryKey: ['customers'] }); }; // Data const customers = customersQuery.data?.data || []; const pagination = customersQuery.data?.pagination; // Loading state if (customersQuery.isLoading) { return (
); } // Error state if (customersQuery.isError) { return ( customersQuery.refetch()} /> ); } return (
{/* Mobile: Search */}
{ setSearch(e.target.value); setPage(1); }} className="pl-9" />
{/* Desktop: Toolbar */}
{/* Left: Bulk Actions */}
{selectedIds.length > 0 && ( )}
{/* Right: Search */}
{ setSearch(e.target.value); setPage(1); }} className="pl-9 w-64" />
{/* Desktop: Table */}
{customers.length === 0 ? ( ) : ( customers.map((customer) => ( )) )}
0} onCheckedChange={toggleAll} aria-label={__('Select all')} /> {__('Customer')} {__('Email')} {__('Orders')} {__('Total Spent')} {__('Registered')}
{search ? __('No customers found matching your search') : __('No customers yet')} {!search && (

{__('Create your first customer')}

)}
toggleSelection(customer.id)} aria-label={__('Select customer')} /> {customer.display_name || `${customer.first_name} ${customer.last_name}`} {customer.email} {customer.stats?.total_orders || 0} {customer.stats?.total_spent ? formatMoney(customer.stats.total_spent) : '—'} {new Date(customer.registered).toLocaleDateString()}
{/* Mobile: Cards */}
{customers.length === 0 ? ( {search ? __('No customers found') : __('No customers yet')} ) : ( customers.map((customer) => (
{/* Checkbox */}
{ e.preventDefault(); e.stopPropagation(); toggleSelection(customer.id); }} >
{/* Content */}
{/* Line 1: Name */}

{customer.display_name || `${customer.first_name} ${customer.last_name}`}

{/* Line 2: Email */}
{customer.email}
{/* Line 3: Stats */}
{customer.stats?.total_orders || 0} {__('orders')} {new Date(customer.registered).toLocaleDateString()}
{/* Line 4: Total Spent */}
{customer.stats?.total_spent ? formatMoney(customer.stats.total_spent) : '—'}
{/* Chevron */}
)) )}
{/* Pagination */} {pagination && pagination.total_pages > 1 && (
{__('Page')} {page} {__('of')} {pagination.total_pages}
)}
); }