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
+
+
+
+
- )}
-
- {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
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- setFormData({...formData, clientName: e.target.value})}
- placeholder="Nom du client"
- />
-
-
-
-
- setFormData({...formData, clientPhone: e.target.value})}
- placeholder="Numéro de téléphone"
- />
-
-
+ {/* Section Informations Client */}
+
+
+
+
+ Informations Client
+
+
+ Informations de contact du client (optionnel)
+
+
+
+
+
+
+
+ {/* Section Problème et Priorité */}
+
+
+
+
+ Problème et Priorité
+
+
+ Description du problème rencontré
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -719,9 +805,15 @@ export default function SavTickets() {
-
+
{ticket.ticketNumber}
+ {hasRecentComments(ticket) && (
+
+
+ Nouveau
+
+ )}
|
@@ -822,10 +914,15 @@ export default function SavTickets() {
{/* Colonne de gauche - Détails et Actions */}
- {/* Product Info */}
-
- Informations produit
-
+ {/* Section Informations Produit */}
+
+
+
+
+ Informations Produit
+
+
+
Code-barres:
{selectedTicket.productGencode}
@@ -838,35 +935,19 @@ export default function SavTickets() {
Désignation:
{selectedTicket.productDesignation}
-
-
+
+
- {/* Problem Info */}
-
- Problème
-
-
- Type:
- {selectedTicket.problemType}
-
-
- Priorité:
-
- {priorityConfig[selectedTicket.priority as keyof typeof priorityConfig]?.label}
-
-
-
- Description:
- {selectedTicket.problemDescription}
-
-
-
-
- {/* Client Info */}
+ {/* Section Informations Client */}
{(selectedTicket.clientName || selectedTicket.clientPhone) && (
-
- Client
-
+
+
+
+
+ Informations Client
+
+
+
Nom:
{selectedTicket.clientName || "Non renseigné"}
@@ -875,14 +956,47 @@ export default function SavTickets() {
Téléphone:
{selectedTicket.clientPhone || "Non renseigné"}
-
-
+
+
)}
- {/* Ticket Info */}
-
- Informations ticket
-
+ {/* Section Problème */}
+
+
+
+
+ Problème
+
+
+
+
+
+ Type:
+ {selectedTicket.problemType}
+
+
+ Priorité:
+
+ {priorityConfig[selectedTicket.priority as keyof typeof priorityConfig]?.label}
+
+
+
+
+ Description:
+ {selectedTicket.problemDescription}
+
+
+
+
+ {/* Section Informations Ticket */}
+
+
+
+
+ Informations Ticket
+
+
+
Statut:
@@ -901,8 +1015,8 @@ export default function SavTickets() {
Créé le:
{safeFormat(selectedTicket.createdAt, 'dd/MM/yyyy HH:mm')}
-
-
+
+
{/* Actions rapides */}
{canModify && (
@@ -911,11 +1025,11 @@ export default function SavTickets() {
- |