Add ability for users to add and edit notes for delivery items

Integrates a new feature allowing users to add, view, and edit notes for delivery items. This includes a mutation for updating notes via `PUT /api/deliveries/:deliveryId/notes`, associated modal components for user interaction, and toast notifications for success/error feedback. The `BLReconciliation` page is updated to include a button to trigger the comment modal and `queryClient.invalidateQueries` calls to refresh data upon successful note updates.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 9fcf4b21-eb0c-4e53-a567-e2ce4a6ad869
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/9fcf4b21-eb0c-4e53-a567-e2ce4a6ad869/yiEpJFx
This commit is contained in:
michaelschal committed 2025-09-09 13:24:19 +00:00
1 parent 0f431676f5
commit 9e5855d496
1 file changed
+69
+69
View File
@@ -142,6 +142,42 @@ export default function BLReconciliation() {
}
});
// Mutation pour mettre à jour les notes
const updateNoteMutation = useMutation({
mutationFn: async ({ deliveryId, notes }: { deliveryId: number; notes: string }) => {
const response = await apiRequest(`/api/deliveries/${deliveryId}/notes`, 'PUT', { notes });
return response;
},
onSuccess: () => {
toast({
title: "Commentaire sauvegardé",
description: "Le commentaire a été mis à jour avec succès",
});
// Rafraîchir les données
queryClient.invalidateQueries({ queryKey: ['/api/deliveries/bl'] });
queryClient.invalidateQueries({ queryKey: ['/api/deliveries'] });
handleCloseCommentModal();
},
onError: (error) => {
console.error('Erreur sauvegarde commentaire:', error);
toast({
title: "Erreur",
description: "Impossible de sauvegarder le commentaire",
variant: "destructive",
});
}
});
// Fonction pour sauvegarder le commentaire
const handleSaveComment = () => {
if (!selectedDeliveryForComment) return;
updateNoteMutation.mutate({
deliveryId: selectedDeliveryForComment.id,
notes: commentText
});
};
// Fonction pour déclencher la vérification
const handleVerifyInvoice = (delivery: any, forceRefresh: boolean = false) => {
// Accepter soit une référence de facture soit un numéro BL
@@ -352,6 +388,19 @@ export default function BLReconciliation() {
setShowInvoiceModal(true);
};
// Fonctions pour le modal de commentaire
const handleOpenCommentModal = (delivery: any) => {
setSelectedDeliveryForComment(delivery);
setCommentText(delivery.notes || "");
setShowCommentModal(true);
};
const handleCloseCommentModal = () => {
setShowCommentModal(false);
setSelectedDeliveryForComment(null);
setCommentText("");
};
const handleCloseInvoiceModal = () => {
setShowInvoiceModal(false);
setSelectedDeliveryForInvoice(null);
@@ -931,6 +980,15 @@ export default function BLReconciliation() {
<Upload className="h-4 w-4" />
</Button>
)}
<Button
variant="outline"
size="sm"
onClick={() => handleOpenCommentModal(delivery)}
className={`h-8 w-8 p-0 ${delivery.notes ? 'text-blue-600 hover:text-blue-700' : 'text-gray-400 hover:text-gray-600'}`}
title={delivery.notes ? "Voir/Modifier commentaire" : "Ajouter commentaire"}
>
<MessageSquare className="h-4 w-4" />
</Button>
{!delivery.reconciled ? (
<>
{permissions.canValidate('reconciliation') && (
@@ -1134,6 +1192,17 @@ export default function BLReconciliation() {
<Upload className="h-4 w-4" />
</button>
)}
<button
onClick={() => handleOpenCommentModal(delivery)}
className={`transition-colors duration-200 p-1 rounded ${
delivery.notes
? 'text-blue-600 hover:text-blue-700 hover:bg-blue-50'
: 'text-gray-400 hover:text-gray-600 hover:bg-gray-50'
}`}
title={delivery.notes ? "Voir/Modifier commentaire" : "Ajouter commentaire"}
>
<MessageSquare className="h-4 w-4" />
</button>
{(permissions.canEdit('reconciliation') || permissions.canValidate('reconciliation')) && (
<button
onClick={() => handleDevalidateReconciliation(delivery.id)}