import { useState } from "react"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Pagination, usePagination } from "@/components/ui/pagination"; import { useAuthUnified } from "@/hooks/useAuthUnified"; import { useStore } from "@/components/Layout"; import { useToast } from "@/hooks/use-toast"; import { apiRequest } from "@/lib/queryClient"; import { isUnauthorizedError } from "@/lib/authUtils"; import { Plus, Search, Filter, Truck, Calendar, Eye, Edit, Trash2, Building, User, Check, Package } from "lucide-react"; import { safeFormat } from "@/lib/dateUtils"; import CreateDeliveryModal from "@/components/modals/CreateDeliveryModal"; import EditDeliveryModal from "@/components/modals/EditDeliveryModal"; import OrderDetailModal from "@/components/modals/OrderDetailModal"; import ConfirmDeleteModal from "@/components/modals/ConfirmDeleteModal"; import type { DeliveryWithRelations } from "@shared/schema"; export default function Deliveries() { const { user } = useAuthUnified(); const { selectedStoreId } = useStore(); const { toast } = useToast(); const queryClient = useQueryClient(); // Redirection pour les employés if (user?.role === 'employee') { return (

Accès restreint
Seuls les managers et administrateurs peuvent accéder à la page des livraisons.

); } const [searchTerm, setSearchTerm] = useState(""); const [statusFilter, setStatusFilter] = useState("all"); const [showCreateModal, setShowCreateModal] = useState(false); const [showEditModal, setShowEditModal] = useState(false); const [showDetailModal, setShowDetailModal] = useState(false); const [showDeleteModal, setShowDeleteModal] = useState(false); const [selectedDelivery, setSelectedDelivery] = useState(null); const [deliveryToDelete, setDeliveryToDelete] = useState(null); // Construire l'URL pour l'historique complet sans filtrage par date const deliveriesUrl = `/api/deliveries${selectedStoreId && user?.role === 'admin' ? `?storeId=${selectedStoreId}` : ''}`; const { data: deliveriesData = [], isLoading } = useQuery({ queryKey: ['/api/deliveries', selectedStoreId, user?.role], queryFn: async () => { const url = deliveriesUrl; console.log('🚚 Fetching deliveries from:', url); const response = await fetch(url, { credentials: 'include' }); if (!response.ok) { throw new Error('Failed to fetch deliveries'); } const data = await response.json(); console.log('🚚 Deliveries received:', Array.isArray(data) ? data.length : 'NOT_ARRAY', 'items', data.slice(0, 2)); console.log('🚚 Sample delivery data:', data[0]); return Array.isArray(data) ? data : []; }, }); // Production Bug Fix: Ensure array safety for all data operations const deliveries = Array.isArray(deliveriesData) ? deliveriesData : []; console.log('🚚 Deliveries Debug:', { isLoading, deliveriesCount: deliveries?.length, deliveries: deliveries?.slice(0, 2), selectedStoreId, deliveriesUrl }); const { data: groupsData = [] } = useQuery({ queryKey: ['/api/groups'], }); const groups = Array.isArray(groupsData) ? groupsData : []; const validateMutation = useMutation({ mutationFn: async (id: number) => { await apiRequest(`/api/deliveries/${id}/validate`, "POST"); }, onSuccess: () => { toast({ title: "Succès", description: "Livraison validée avec succès", }); // Invalider tous les caches liés aux livraisons queryClient.invalidateQueries({ queryKey: ['/api/deliveries'] }); queryClient.invalidateQueries({ queryKey: [deliveriesUrl] }); // Invalider tous les caches BL/Rapprochement queryClient.invalidateQueries({ predicate: (query) => query.queryKey[0] === '/api/deliveries/bl' || query.queryKey[0] === '/api/deliveries' }); queryClient.invalidateQueries({ queryKey: ['/api/orders'] }); queryClient.invalidateQueries({ queryKey: ['/api/stats/monthly'] }); }, onError: (error) => { if (isUnauthorizedError(error)) { toast({ title: "Non autorisé", description: "Vous êtes déconnecté. Reconnexion...", variant: "destructive", }); setTimeout(() => { window.location.href = "/api/login"; }, 500); return; } toast({ title: "Erreur", description: "Impossible de valider la livraison", variant: "destructive", }); }, }); const deleteMutation = useMutation({ mutationFn: async (id: number) => { await apiRequest(`/api/deliveries/${id}`, "DELETE"); }, onSuccess: () => { toast({ title: "Succès", description: "Livraison supprimée avec succès", }); // Invalider tous les caches liés aux livraisons queryClient.invalidateQueries({ queryKey: ['/api/deliveries'] }); queryClient.invalidateQueries({ queryKey: [deliveriesUrl] }); queryClient.invalidateQueries({ queryKey: ['/api/stats/monthly'] }); }, onError: (error) => { if (isUnauthorizedError(error)) { toast({ title: "Non autorisé", description: "Vous êtes déconnecté. Reconnexion...", variant: "destructive", }); setTimeout(() => { window.location.href = "/api/login"; }, 500); return; } toast({ title: "Erreur", description: "Impossible de supprimer la livraison", variant: "destructive", }); }, }); const filteredDeliveries = Array.isArray(deliveries) ? deliveries.filter(delivery => { console.log('🔍 Filtering delivery:', delivery.id, { searchTerm, statusFilter }); const matchesSearch = delivery.supplier?.name.toLowerCase().includes(searchTerm.toLowerCase()) || delivery.group?.name.toLowerCase().includes(searchTerm.toLowerCase()) || delivery.notes?.toLowerCase().includes(searchTerm.toLowerCase()); const matchesStatus = statusFilter === "all" || delivery.status === statusFilter; return matchesSearch && matchesStatus; }) : []; // Pagination const { currentPage, setCurrentPage, itemsPerPage, setItemsPerPage, totalPages, paginatedData: paginatedDeliveries, totalItems } = usePagination(filteredDeliveries, 20); const getStatusBadge = (status: string) => { switch (status) { case 'pending': return En attente; case 'planned': return Planifié; case 'delivered': return Livré; default: return {status}; } }; const formatQuantity = (quantity: number, unit: string) => { return `${quantity} ${unit === 'palettes' ? 'P' : 'C'}`; }; const handleViewDelivery = (delivery: DeliveryWithRelations) => { setSelectedDelivery({ ...delivery, type: 'delivery' }); setShowDetailModal(true); }; const handleEditDelivery = (delivery: DeliveryWithRelations) => { setSelectedDelivery(delivery); setShowEditModal(true); }; const handleValidateDelivery = (id: number) => { if (window.confirm("Êtes-vous sûr de vouloir valider cette livraison ?")) { validateMutation.mutate(id); } }; const handleDeleteDelivery = (delivery: DeliveryWithRelations) => { setDeliveryToDelete(delivery); setShowDeleteModal(true); }; const confirmDeleteDelivery = () => { if (deliveryToDelete) { deleteMutation.mutate(deliveryToDelete.id); setShowDeleteModal(false); setDeliveryToDelete(null); } }; const canCreate = true; // All users can create deliveries const canEdit = user?.role === 'admin' || user?.role === 'manager'; const canDelete = user?.role === 'admin' || user?.role === 'manager'; const canValidate = user?.role === 'admin' || user?.role === 'manager'; return (
{/* Header */}

Gestion des Livraisons

{filteredDeliveries.length} livraison{filteredDeliveries.length !== 1 ? 's' : ''}

{canCreate && ( )}
{/* Filters */}
setSearchTerm(e.target.value)} className="pl-10 border border-gray-300 shadow-sm" />
{/* Deliveries List */}
{isLoading ? (
) : (console.log('🚚 Filtered deliveries length:', filteredDeliveries.length) || filteredDeliveries.length === 0) ? (

Aucune livraison trouvée

{searchTerm || statusFilter !== "all" ? "Aucune livraison ne correspond à vos critères de recherche." : "Vous n'avez pas encore de livraisons. Créez votre première livraison pour commencer."}

{canCreate && !searchTerm && statusFilter === "all" && ( )}
) : (
{paginatedDeliveries.map((delivery) => ( ))}
Fournisseur Groupe Date prévue Quantité Statut Commande liée Créé par Actions
{delivery.supplier?.name}
#{delivery.id}
{delivery.group?.name}
{safeFormat(delivery.scheduledDate, 'dd MMM yyyy')}
{formatQuantity(delivery.quantity, delivery.unit)} {getStatusBadge(delivery.status)} {delivery.order ? (
#{delivery.order.id}
) : ( Aucune )}
{delivery.creator?.firstName} {delivery.creator?.lastName}
{canEdit && ( )} {canValidate && delivery.status !== 'delivered' && ( )} {canDelete && ( )}
{/* Pagination */}
)}
{/* Modals */} {showCreateModal && ( setShowCreateModal(false)} selectedDate={null} /> )} {showEditModal && selectedDelivery && ( setShowEditModal(false)} delivery={selectedDelivery} /> )} {showDetailModal && selectedDelivery && ( setShowDetailModal(false)} item={selectedDelivery} /> )} {/* Modal de confirmation de suppression */} { setShowDeleteModal(false); setDeliveryToDelete(null); }} onConfirm={confirmDeleteDelivery} title="Supprimer la livraison" description="Êtes-vous sûr de vouloir supprimer cette livraison ?" itemName={deliveryToDelete ? `${deliveryToDelete.supplier?.name} - ${safeFormat(deliveryToDelete.scheduledDate, 'dd/MM/yyyy')}` : undefined} isLoading={deleteMutation.isPending} />
); }