From 4d36beeaf47977d1c8f1cd0f4b1984ba5d9d8052 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Mon, 8 Sep 2025 16:09:11 +0000 Subject: [PATCH 1/2] Update invoice list to show supplier first and add edit/delete functionality Adds modals for editing and deleting invoices, reorders the invoice list to display supplier information first, and includes a placeholder for status changes. 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/5h3gCuD --- client/src/pages/Avoirs.tsx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/client/src/pages/Avoirs.tsx b/client/src/pages/Avoirs.tsx index 22e21e8..625661a 100644 --- a/client/src/pages/Avoirs.tsx +++ b/client/src/pages/Avoirs.tsx @@ -6,6 +6,7 @@ import { Input } from "@/components/ui/input"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; +import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Checkbox } from "@/components/ui/checkbox"; @@ -80,6 +81,9 @@ type AvoirFormData = z.infer; export default function Avoirs() { const [searchTerm, setSearchTerm] = useState(""); const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false); + const [isEditDialogOpen, setIsEditDialogOpen] = useState(false); + const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false); + const [selectedAvoir, setSelectedAvoir] = useState(null); const [selectedStoreId, setSelectedStoreId] = useState("all"); const { toast } = useToast(); const queryClient = useQueryClient(); @@ -447,15 +451,15 @@ export default function Avoirs() { + - @@ -476,6 +480,9 @@ export default function Avoirs() { return ( + -
+ Fournisseur + Statut Référence - Fournisseur - Magasin
+ {avoir.supplier.name} +
{getStatusIcon(avoir.status)} @@ -484,11 +491,8 @@ export default function Avoirs() {
- #{avoir.invoiceReference || 'Sans référence'} - - {avoir.supplier.name} + #{avoir.invoiceReference || 'Sans référence'}
From a433026820de34ba91d56432b88c04832390e890 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Mon, 8 Sep 2025 16:10:45 +0000 Subject: [PATCH 2/2] Add editing and deletion capabilities for avoirs with improved status management Integrates useMutation for edit and delete operations on avoirs, introduces edit form handling, and refactors table display to prioritize supplier names. 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/5h3gCuD --- client/src/pages/Avoirs.tsx | 297 +++++++++++++++++++++++++++++++++++- 1 file changed, 296 insertions(+), 1 deletion(-) diff --git a/client/src/pages/Avoirs.tsx b/client/src/pages/Avoirs.tsx index 625661a..11eceac 100644 --- a/client/src/pages/Avoirs.tsx +++ b/client/src/pages/Avoirs.tsx @@ -145,7 +145,71 @@ export default function Avoirs() { } }); - // Initialize form + // Edit avoir mutation + const editAvoirMutation = useMutation({ + mutationFn: async ({ id, data }: { id: number, data: AvoirFormData }) => { + const response = await fetch(`/api/avoirs/${id}`, { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(data), + credentials: 'include', + }); + if (!response.ok) { + throw new Error('Failed to edit avoir'); + } + return response.json(); + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['/api/avoirs'] }); + setIsEditDialogOpen(false); + setSelectedAvoir(null); + toast({ + title: "Avoir modifié", + description: "L'avoir a été modifié avec succès.", + }); + }, + onError: (error: any) => { + toast({ + title: "Erreur", + description: error.message || "Erreur lors de la modification", + variant: "destructive", + }); + } + }); + + // Delete avoir mutation + const deleteAvoirMutation = useMutation({ + mutationFn: async (id: number) => { + const response = await fetch(`/api/avoirs/${id}`, { + method: 'DELETE', + credentials: 'include', + }); + if (!response.ok) { + throw new Error('Failed to delete avoir'); + } + return response.json(); + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['/api/avoirs'] }); + setIsDeleteDialogOpen(false); + setSelectedAvoir(null); + toast({ + title: "Avoir supprimé", + description: "L'avoir a été supprimé avec succès.", + }); + }, + onError: (error: any) => { + toast({ + title: "Erreur", + description: error.message || "Erreur lors de la suppression", + variant: "destructive", + }); + } + }); + + // Initialize create form const form = useForm({ resolver: zodResolver(avoirSchema), defaultValues: { @@ -158,11 +222,59 @@ export default function Avoirs() { }, }); + // Initialize edit form + const editForm = useForm({ + resolver: zodResolver(avoirSchema), + defaultValues: { + supplierId: 0, + groupId: 0, + invoiceReference: "", + amount: undefined, + comment: "", + commercialProcessed: false, + }, + }); + // Handle form submission const onSubmit = (data: AvoirFormData) => { createAvoirMutation.mutate(data); }; + // Handle edit form submission + const onEditSubmit = (data: AvoirFormData) => { + if (selectedAvoir) { + editAvoirMutation.mutate({ id: selectedAvoir.id, data }); + } + }; + + // Handle edit action + const handleEdit = (avoir: Avoir) => { + setSelectedAvoir(avoir); + editForm.reset({ + supplierId: avoir.supplierId, + groupId: avoir.groupId, + invoiceReference: avoir.invoiceReference || "", + amount: avoir.amount, + comment: avoir.comment || "", + commercialProcessed: avoir.commercialProcessed, + status: avoir.status, + }); + setIsEditDialogOpen(true); + }; + + // Handle delete action + const handleDelete = (avoir: Avoir) => { + setSelectedAvoir(avoir); + setIsDeleteDialogOpen(true); + }; + + // Confirm delete + const confirmDelete = () => { + if (selectedAvoir) { + deleteAvoirMutation.mutate(selectedAvoir.id); + } + }; + // Filter avoirs based on search term const filteredAvoirs = avoirs.filter(avoir => avoir.invoiceReference?.toLowerCase().includes(searchTerm.toLowerCase()) || @@ -525,6 +637,7 @@ export default function Avoirs() { size="sm" className="h-8 w-8 p-0" title="Modifier" + onClick={() => handleEdit(avoir)} > @@ -533,6 +646,7 @@ export default function Avoirs() { size="sm" className="h-8 w-8 p-0 text-red-600 hover:text-red-700 hover:bg-red-50" title="Supprimer" + onClick={() => handleDelete(avoir)} > @@ -549,6 +663,187 @@ export default function Avoirs() { )}
+ + {/* Edit Modal */} + + + + Modifier l'avoir + + Modifiez les informations de l'avoir. + + + +
+ + ( + + Fournisseur * + + + + )} + /> + + ( + + Référence facture + + + + + + )} + /> + + ( + + Montant + + + + + + )} + /> + + ( + + Statut + + + + )} + /> + + ( + + Commentaire + +