import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { MapPin, Search, Plus, Pencil, Trash2, Check, X, ChevronLeft, ChevronRight, } from 'lucide-react'; import { Input } from '@/components/ui/input'; import { Button } from '@/components/ui/button'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { cn } from '@/lib/utils'; import { api } from '@/services/api'; import { toast } from 'sonner'; interface BranchData { id: number; email: string; branch: string; active: boolean; updatedAt: string; } const BRANCH_COLORS = [ 'bg-blue-100 text-blue-600', 'bg-indigo-100 text-indigo-600', 'bg-purple-100 text-purple-600', 'bg-teal-100 text-teal-600', 'bg-amber-100 text-amber-600', 'bg-pink-100 text-pink-600', 'bg-emerald-100 text-emerald-600', 'bg-cyan-100 text-cyan-600', ]; function getBranchColor(name: string): string { let hash = 0; for (let i = 0; i < name.length; i++) { hash = name.charCodeAt(i) + ((hash << 5) - hash); } return BRANCH_COLORS[Math.abs(hash) % BRANCH_COLORS.length]; } const PER_PAGE = 100; export default function BranchTable() { const { t } = useTranslation(); const queryClient = useQueryClient(); const [search, setSearch] = useState(''); const [statusFilter, setStatusFilter] = useState('all'); const [currentPage, setCurrentPage] = useState(1); // Add form state const [showAddForm, setShowAddForm] = useState(false); const [addEmail, setAddEmail] = useState(''); const [addBranch, setAddBranch] = useState(''); // Edit state const [editingId, setEditingId] = useState(null); const [editEmail, setEditEmail] = useState(''); const [editBranch, setEditBranch] = useState(''); // Delete confirmation state const [deletingId, setDeletingId] = useState(null); // Fetch branches const { data, isLoading, isError } = useQuery({ queryKey: ['branches'], queryFn: () => api.get<{ branches: BranchData[] }>('/settings/branches'), retry: false, }); const allBranches = data?.branches ?? []; // Filter branches const filtered = allBranches.filter((b) => { const matchesSearch = !search || b.email.toLowerCase().includes(search.toLowerCase()) || b.branch.toLowerCase().includes(search.toLowerCase()); const matchesStatus = statusFilter === 'all' || (statusFilter === 'active' && b.active) || (statusFilter === 'inactive' && !b.active); return matchesSearch && matchesStatus; }); const totalPages = Math.ceil(filtered.length / PER_PAGE); const paginated = filtered.slice( (currentPage - 1) * PER_PAGE, currentPage * PER_PAGE ); const startItem = filtered.length > 0 ? (currentPage - 1) * PER_PAGE + 1 : 0; const endItem = Math.min(currentPage * PER_PAGE, filtered.length); // Mutations const addMutation = useMutation({ mutationFn: (data: { email: string; branch: string }) => api.post('/settings/branches', data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['branches'] }); setShowAddForm(false); setAddEmail(''); setAddBranch(''); toast.success('Succursale ajoutée'); }, onError: (err: Error) => { toast.error(err.message); }, }); const updateMutation = useMutation({ mutationFn: ({ id, ...data }: { id: number; email?: string; branch?: string; active?: boolean }) => api.put(`/settings/branches/${id}`, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['branches'] }); setEditingId(null); toast.success('Succursale mise à jour'); }, onError: (err: Error) => { toast.error(err.message); }, }); const deleteMutation = useMutation({ mutationFn: (id: number) => api.delete(`/settings/branches/${id}`), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['branches'] }); setDeletingId(null); toast.success('Succursale supprimée'); }, onError: (err: Error) => { toast.error(err.message); }, }); const handleAdd = () => { if (!addEmail || !addBranch) return; addMutation.mutate({ email: addEmail, branch: addBranch }); }; const startEdit = (b: BranchData) => { setEditingId(b.id); setEditEmail(b.email); setEditBranch(b.branch); }; const handleEdit = () => { if (editingId === null || !editEmail || !editBranch) return; updateMutation.mutate({ id: editingId, email: editEmail, branch: editBranch }); }; const toggleActive = (b: BranchData) => { updateMutation.mutate({ id: b.id, active: !b.active }); }; return (
{/* Search & Filters */}
{ setSearch(e.target.value); setCurrentPage(1); }} />
{/* Add form */} {showAddForm && (
setAddEmail(e.target.value)} className="bg-white" />
setAddBranch(e.target.value)} className="bg-white" />
)} {/* Table */}
{t('branches.colEmail')} {t('branches.colBranch')} {t('branches.colStatus')} {t('branches.colActions')} {isLoading ? ( Array.from({ length: 5 }).map((_, i) => ( {Array.from({ length: 4 }).map((_, j) => (
))} )) ) : isError ? ( Veuillez vous connecter pour voir les succursales. ) : paginated.length === 0 ? (

{search ? t('transactions.noResults') : t('branches.emptyTitle', 'No branches configured yet')}

{search ? '' : t('branches.emptyDesc', 'Add a branch to map recipient emails to branch names')}

{!search && !showAddForm && ( )}
) : ( paginated.map((branch) => ( {editingId === branch.id ? ( <> setEditEmail(e.target.value)} className="h-8 text-sm" /> setEditBranch(e.target.value)} className="h-8 text-sm" /> ) : ( <> {branch.email}
{branch.branch}
{deletingId === branch.id ? ( <> ) : ( <> )} )}
)) )}
{/* Pagination */} {filtered.length > 0 && (

{t('transactions.showing')}{' '} {startItem}{' '} {t('transactions.to')}{' '} {endItem}{' '} {t('transactions.of')}{' '} {filtered.length}{' '} {t('transactions.results')}

{totalPages > 1 && ( )}
)}
); }