From b73f9f25d1050fb99adc859c44008ae20ab61aa5 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Tue, 30 Sep 2025 09:19:41 +0000 Subject: [PATCH] Add functionality to mark delivery controls as validated Introduces a new API endpoint and UI elements to allow users to mark delivery controls as validated, including associated badges and mutation logic. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 1e4433b5-47ab-464c-b663-fea2e53367dd Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/1e4433b5-47ab-464c-b663-fea2e53367dd/Q8UjAXl --- .replit | 4 ++ client/src/pages/Deliveries.tsx | 71 ++++++++++++++++++++++++++++++++- server/storage.ts | 1 + 3 files changed, 74 insertions(+), 2 deletions(-) diff --git a/.replit b/.replit index c7abdf5..bf3ee09 100644 --- a/.replit +++ b/.replit @@ -47,6 +47,10 @@ externalPort = 6000 localPort = 44549 externalPort = 5173 +[[ports]] +localPort = 44701 +externalPort = 8000 + [[ports]] localPort = 44965 externalPort = 6800 diff --git a/client/src/pages/Deliveries.tsx b/client/src/pages/Deliveries.tsx index accf271..9003aa6 100644 --- a/client/src/pages/Deliveries.tsx +++ b/client/src/pages/Deliveries.tsx @@ -23,7 +23,9 @@ import { Building, User, Check, - Package + Package, + AlertTriangle, + CheckCircle } from "lucide-react"; import { safeFormat } from "@/lib/dateUtils"; import CreateDeliveryModal from "@/components/modals/CreateDeliveryModal"; @@ -111,6 +113,30 @@ export default function Deliveries() { const groups = Array.isArray(groupsData) ? groupsData : []; + const markControlValidatedMutation = useMutation({ + mutationFn: async (id: number) => { + await apiRequest(`/api/deliveries/${id}/control`, "PUT"); + }, + onSuccess: () => { + toast({ + title: "Succès", + description: "Contrôle validé avec succès", + }); + queryClient.invalidateQueries({ queryKey: ['/api/deliveries'] }); + queryClient.invalidateQueries({ queryKey: [deliveriesUrl] }); + }, + onError: (error: any) => { + if (isUnauthorizedError(error)) { + return; + } + toast({ + title: "Erreur", + description: "Impossible de valider le contrôle", + variant: "destructive", + }); + }, + }); + const deleteMutation = useMutation({ mutationFn: async (id: number) => { await apiRequest(`/api/deliveries/${id}`, "DELETE"); @@ -180,6 +206,28 @@ export default function Deliveries() { } }; + const getControlBadge = (delivery: DeliveryWithRelations) => { + if (!delivery.supplier?.requiresControl) { + return null; + } + + if (delivery.controlValidated) { + return ( + + + Contrôle validé + + ); + } + + return ( + + + Contrôle à faire + + ); + }; + const formatQuantity = (quantity: number, unit: string) => { return `${quantity} ${unit === 'palettes' ? 'P' : 'C'}`; }; @@ -209,6 +257,10 @@ export default function Deliveries() { setShowDeleteModal(true); }; + const handleMarkControlValidated = (deliveryId: number) => { + markControlValidatedMutation.mutate(deliveryId); + }; + const confirmDeleteDelivery = () => { if (deliveryToDelete) { deleteMutation.mutate(deliveryToDelete.id); @@ -375,7 +427,10 @@ export default function Deliveries() { - {getStatusBadge(delivery.status)} +
+ {getStatusBadge(delivery.status)} + {getControlBadge(delivery)} +
{delivery.order ? ( @@ -422,6 +477,18 @@ export default function Deliveries() { )} + {delivery.supplier?.requiresControl && !delivery.controlValidated && delivery.status === 'delivered' && ( + + )} {canDelete && (