diff --git a/attached_assets/{66B42A7D-EB4F-45AC-A9CA-1EA3033AD4E3}_1755173214117.png b/attached_assets/{66B42A7D-EB4F-45AC-A9CA-1EA3033AD4E3}_1755173214117.png new file mode 100644 index 0000000..93838a3 Binary files /dev/null and b/attached_assets/{66B42A7D-EB4F-45AC-A9CA-1EA3033AD4E3}_1755173214117.png differ diff --git a/client/src/pages/SavTickets.tsx b/client/src/pages/SavTickets.tsx index 6de9732..3acd203 100644 --- a/client/src/pages/SavTickets.tsx +++ b/client/src/pages/SavTickets.tsx @@ -59,7 +59,10 @@ export default function SavTickets() { const [showCreateModal, setShowCreateModal] = useState(false); const [showDetailModal, setShowDetailModal] = useState(false); const [showEditModal, setShowEditModal] = useState(false); + const [showCommentModal, setShowCommentModal] = useState(false); + const [showDeleteModal, setShowDeleteModal] = useState(false); const [selectedTicket, setSelectedTicket] = useState(null); + const [newComment, setNewComment] = useState(""); const [formData, setFormData] = useState({ supplierId: "", groupId: "", @@ -156,6 +159,56 @@ export default function SavTickets() { }, }); + // Add comment mutation + const addCommentMutation = useMutation({ + mutationFn: async (data: { ticketId: number; comment: string }) => { + const response = await apiRequest(`/api/sav-tickets/${data.ticketId}/comments`, "POST", { + comment: data.comment + }); + return response; + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['/api/sav/tickets'] }); + setShowCommentModal(false); + setNewComment(""); + toast({ + title: "Commentaire ajouté", + description: "Le commentaire a été ajouté avec succès.", + }); + }, + onError: (error: any) => { + toast({ + title: "Erreur", + description: error?.message || "Impossible d'ajouter le commentaire.", + variant: "destructive", + }); + }, + }); + + // Delete ticket mutation + const deleteTicketMutation = useMutation({ + mutationFn: async (ticketId: number) => { + const response = await apiRequest(`/api/sav-tickets/${ticketId}`, "DELETE"); + return response; + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['/api/sav/tickets'] }); + queryClient.invalidateQueries({ queryKey: ['/api/sav/stats'] }); + setShowDeleteModal(false); + toast({ + title: "Ticket supprimé", + description: "Le ticket a été supprimé avec succès.", + }); + }, + onError: (error: any) => { + toast({ + title: "Erreur", + description: error?.message || "Impossible de supprimer le ticket.", + variant: "destructive", + }); + }, + }); + // Check permissions AFTER all hooks are called const canView = ['admin', 'directeur', 'manager', 'employee'].includes(user?.role || ''); const canModify = ['admin', 'directeur', 'manager'].includes(user?.role || ''); @@ -237,6 +290,19 @@ export default function SavTickets() { setShowEditModal(true); }; + // Handle commenting on ticket + const handleCommentTicket = (ticket: SavTicketWithRelations) => { + setSelectedTicket(ticket); + setNewComment(""); + setShowCommentModal(true); + }; + + // Handle deleting ticket + const handleDeleteTicket = (ticket: SavTicketWithRelations) => { + setSelectedTicket(ticket); + setShowDeleteModal(true); + }; + // Handle permission check without early return if (!canView) { return ( @@ -717,13 +783,13 @@ export default function SavTickets() { - )} {canDelete && ( - )} @@ -971,6 +1037,94 @@ export default function SavTickets() { )} + + {/* Comment Modal */} + {selectedTicket && ( + + + + Ajouter un commentaire + + Ajouter un commentaire au ticket {selectedTicket.ticketNumber} + + +
+
+ +