mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-11 17:27:31 +02:00
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
This commit is contained in:
1 parent
4d36beeaf4
commit
a433026820
1 file changed
+296
-1
+296
-1
@@ -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<AvoirFormData>({
|
||||
resolver: zodResolver(avoirSchema),
|
||||
defaultValues: {
|
||||
@@ -158,11 +222,59 @@ export default function Avoirs() {
|
||||
},
|
||||
});
|
||||
|
||||
// Initialize edit form
|
||||
const editForm = useForm<AvoirFormData>({
|
||||
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)}
|
||||
>
|
||||
<Edit className="h-4 w-4" />
|
||||
</Button>
|
||||
@@ -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)}
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
@@ -549,6 +663,187 @@ export default function Avoirs() {
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Edit Modal */}
|
||||
<Dialog open={isEditDialogOpen} onOpenChange={setIsEditDialogOpen}>
|
||||
<DialogContent className="sm:max-w-[425px]">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Modifier l'avoir</DialogTitle>
|
||||
<DialogDescription>
|
||||
Modifiez les informations de l'avoir.
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<Form {...editForm}>
|
||||
<form onSubmit={editForm.handleSubmit(onEditSubmit)} className="space-y-4">
|
||||
<FormField
|
||||
control={editForm.control}
|
||||
name="supplierId"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Fournisseur *</FormLabel>
|
||||
<Select
|
||||
value={field.value.toString()}
|
||||
onValueChange={(value) => field.onChange(parseInt(value))}
|
||||
>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Sélectionnez un fournisseur" />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
{suppliers.map((supplier) => (
|
||||
<SelectItem key={supplier.id} value={supplier.id.toString()}>
|
||||
{supplier.name}
|
||||
</SelectItem>
|
||||
))}
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={editForm.control}
|
||||
name="invoiceReference"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Référence facture</FormLabel>
|
||||
<FormControl>
|
||||
<Input placeholder="Référence de la facture (optionnel)" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={editForm.control}
|
||||
name="amount"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Montant</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
type="number"
|
||||
step="0.01"
|
||||
placeholder="Montant en euros (optionnel)"
|
||||
{...field}
|
||||
value={field.value || ""}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={editForm.control}
|
||||
name="status"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Statut</FormLabel>
|
||||
<Select value={field.value} onValueChange={field.onChange}>
|
||||
<FormControl>
|
||||
<SelectTrigger>
|
||||
<SelectValue />
|
||||
</SelectTrigger>
|
||||
</FormControl>
|
||||
<SelectContent>
|
||||
<SelectItem value="En attente de demande">En attente de demande</SelectItem>
|
||||
<SelectItem value="Demandé">Demandé</SelectItem>
|
||||
<SelectItem value="Reçu">Reçu</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={editForm.control}
|
||||
name="comment"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Commentaire</FormLabel>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
placeholder="Commentaire ou description (optionnel)"
|
||||
{...field}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={editForm.control}
|
||||
name="commercialProcessed"
|
||||
render={({ field }) => (
|
||||
<FormItem className="flex flex-row items-start space-x-3 space-y-0">
|
||||
<FormControl>
|
||||
<Checkbox
|
||||
checked={field.value}
|
||||
onCheckedChange={field.onChange}
|
||||
/>
|
||||
</FormControl>
|
||||
<div className="space-y-1 leading-none">
|
||||
<FormLabel>
|
||||
Avoir fait par commercial
|
||||
</FormLabel>
|
||||
</div>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<div className="flex justify-end space-x-2 pt-4">
|
||||
<Button type="button" variant="outline" onClick={() => setIsEditDialogOpen(false)}>
|
||||
Annuler
|
||||
</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={editAvoirMutation.isPending}
|
||||
>
|
||||
{editAvoirMutation.isPending ? "Modification..." : "Modifier"}
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Form>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
{/* Delete Modal */}
|
||||
<AlertDialog open={isDeleteDialogOpen} onOpenChange={setIsDeleteDialogOpen}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Confirmer la suppression</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
Êtes-vous sûr de vouloir supprimer cet avoir ? Cette action ne peut pas être annulée.
|
||||
{selectedAvoir && (
|
||||
<div className="mt-4 p-3 bg-gray-50 rounded-lg">
|
||||
<div className="text-sm">
|
||||
<div><strong>Fournisseur:</strong> {selectedAvoir.supplier.name}</div>
|
||||
<div><strong>Référence:</strong> {selectedAvoir.invoiceReference || 'Sans référence'}</div>
|
||||
<div><strong>Montant:</strong> {selectedAvoir.amount ? `${selectedAvoir.amount.toFixed(2)} €` : 'Non spécifié'}</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Annuler</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={confirmDelete}
|
||||
disabled={deleteAvoirMutation.isPending}
|
||||
className="bg-red-600 hover:bg-red-700"
|
||||
>
|
||||
{deleteAvoirMutation.isPending ? "Suppression..." : "Supprimer"}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user