From 50a8807019422d506a5162d4d81d4abed4ea5ffd Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Mon, 18 Aug 2025 07:32:44 +0000 Subject: [PATCH] Improve SAV ticket management by fixing status updates and adding new comment indicators Implement ticket status update mutation, show new comment badges, and refactor SAV modal layout for better client and product information separation. Replit-Commit-Author: Agent Replit-Commit-Session-Id: f9197b9b-a5b3-4469-a27d-930a9e9ee736 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/f9197b9b-a5b3-4469-a27d-930a9e9ee736/GCVoWnM --- client/src/pages/SavTickets.tsx | 514 +++++++++++++++++++------------- 1 file changed, 314 insertions(+), 200 deletions(-) diff --git a/client/src/pages/SavTickets.tsx b/client/src/pages/SavTickets.tsx index b74b162..e631de6 100644 --- a/client/src/pages/SavTickets.tsx +++ b/client/src/pages/SavTickets.tsx @@ -190,6 +190,38 @@ export default function SavTickets() { }, }); + // Update ticket status/priority mutation + const updateTicketMutation = useMutation({ + mutationFn: async (data: { ticketId: number; status?: string; priority?: string; resolutionDescription?: string }) => { + const response = await apiRequest(`/api/sav/tickets/${data.ticketId}`, "PATCH", { + status: data.status, + priority: data.priority, + resolutionDescription: data.resolutionDescription, + }); + return response; + }, + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: ['/api/sav/tickets'] }); + queryClient.invalidateQueries({ queryKey: ['/api/sav/stats'] }); + if (selectedTicket) { + queryClient.invalidateQueries({ queryKey: [`/api/sav/tickets/${selectedTicket.id}`] }); + } + setTempStatus(""); + setTempPriority(""); + toast({ + title: "Ticket mis à jour", + description: "Le statut du ticket a été modifié avec succès.", + }); + }, + onError: (error: any) => { + toast({ + title: "Erreur", + description: error?.message || "Impossible de modifier le ticket.", + variant: "destructive", + }); + }, + }); + // Delete ticket mutation const deleteTicketMutation = useMutation({ mutationFn: async (ticketId: number) => { @@ -263,7 +295,7 @@ export default function SavTickets() { problemDescription: formData.problemDescription, priority: formData.priority as "faible" | "normale" | "haute" | "critique", status: "nouveau" as const, - createdBy: 1, // Will be set by the backend from session + createdBy: "1", // Will be set by the backend from session clientName: formData.clientName || undefined, clientPhone: formData.clientPhone || undefined, }; @@ -285,6 +317,20 @@ export default function SavTickets() { staleTime: 0, // Toujours récupérer les derniers commentaires }); + // Function to check if ticket has recent comments (last 24h) + const hasRecentComments = (ticket: SavTicketWithRelations) => { + if (!ticket.history || ticket.history.length === 0) return false; + + const oneDayAgo = new Date(); + oneDayAgo.setDate(oneDayAgo.getDate() - 1); + + return ticket.history.some(entry => + entry.action === 'comment' && + entry.createdAt && + new Date(entry.createdAt) > oneDayAgo + ); + }; + // Handle editing ticket const handleEditTicket = (ticket: SavTicketWithRelations) => { setSelectedTicket(ticket); @@ -370,160 +416,200 @@ export default function SavTickets() { -
- {/* Informations produit */} -
-

Informations produit

- -
- - setFormData({...formData, productGencode: e.target.value})} - placeholder="Code-barres du produit" - /> -
- -
- - setFormData({...formData, productReference: e.target.value})} - placeholder="Référence du produit" - /> -
- -
- - setFormData({...formData, productDesignation: e.target.value})} - placeholder="Nom/désignation du produit" - /> -
- -
- - -
- - {availableGroups.length > 1 && ( -
- - -
- )} - - {availableGroups.length === 1 && ( -
- -
- - {availableGroups[0].name} +
+ {/* Section Informations Produit */} + + + + + Informations Produit + + + Détails du produit concerné par le SAV + + + +
+
+ + setFormData({...formData, productGencode: e.target.value})} + placeholder="Code-barres du produit" + /> +
+ +
+ + setFormData({...formData, productReference: e.target.value})} + placeholder="Référence du produit" + />
- )} - - {availableGroups.length === 0 && ( +
- -
- Aucun magasin assigné. Contactez un administrateur. -
+ + setFormData({...formData, productDesignation: e.target.value})} + placeholder="Nom/désignation du produit" + />
- )} -
+ +
+
+ + +
+ + {availableGroups.length > 1 && ( +
+ + +
+ )} +
+ + {availableGroups.length === 1 && ( +
+ +
+ + {availableGroups[0].name} +
+
+ )} + + {availableGroups.length === 0 && ( +
+ +
+ Aucun magasin assigné. Contactez un administrateur. +
+
+ )} + + - {/* Informations problème et client */} -
-

Problème et client

- -
- - -
- -
- - -
- -
- -