From 367e09c2342cdadb7186558b09173c434f345197 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Thu, 11 Sep 2025 11:13:28 +0000 Subject: [PATCH 1/4] Display notifications for pending client calls and improve data caching Add an alert component to display pending client calls and adjust query invalidation logic for pending calls. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 95e8aab4-f39f-4b48-aa57-a759ec15ba3d Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/95e8aab4-f39f-4b48-aa57-a759ec15ba3d/IFoerZ5 --- .replit | 8 ++-- .../components/modals/ClientCallsModal.tsx | 8 +++- client/src/pages/CustomerOrders.tsx | 45 ++++++++++++++++++- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/.replit b/.replit index 233e6b9..19a7af5 100644 --- a/.replit +++ b/.replit @@ -15,10 +15,6 @@ run = ["npm", "run", "start"] localPort = 5000 externalPort = 80 -[[ports]] -localPort = 38145 -externalPort = 3003 - [[ports]] localPort = 38451 externalPort = 3002 @@ -27,6 +23,10 @@ externalPort = 3002 localPort = 41343 externalPort = 3001 +[[ports]] +localPort = 45663 +externalPort = 3000 + [workflows] runButton = "Project" diff --git a/client/src/components/modals/ClientCallsModal.tsx b/client/src/components/modals/ClientCallsModal.tsx index ef931ec..43090e5 100644 --- a/client/src/components/modals/ClientCallsModal.tsx +++ b/client/src/components/modals/ClientCallsModal.tsx @@ -33,8 +33,12 @@ export default function ClientCallsModal({ isOpen, onClose, pendingCalls }: Clie description: "L'appel a été enregistré avec succès", }); - // Invalider les caches - queryClient.invalidateQueries({ queryKey: ['/api/customer-orders/pending-calls'] }); + // Invalider les caches avec la bonne stratégie + queryClient.invalidateQueries({ + predicate: (query) => { + return query.queryKey[0] === '/api/customer-orders/pending-calls'; + } + }); queryClient.invalidateQueries({ queryKey: ['/api/customer-orders'] }); }, onError: (error, customerOrderId) => { diff --git a/client/src/pages/CustomerOrders.tsx b/client/src/pages/CustomerOrders.tsx index 60a2f0e..bdd9512 100644 --- a/client/src/pages/CustomerOrders.tsx +++ b/client/src/pages/CustomerOrders.tsx @@ -5,6 +5,7 @@ import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; +import { Alert, AlertDescription } from "@/components/ui/alert"; import { Dialog, DialogContent, @@ -28,7 +29,7 @@ import { SelectValue, } from "@/components/ui/select"; import { Pagination, usePagination } from "@/components/ui/pagination"; -import { Plus, Edit, Trash2, Phone, PhoneCall, Printer, Eye, Package } from "lucide-react"; +import { Plus, Edit, Trash2, Phone, PhoneCall, Printer, Eye, Package, AlertCircle } from "lucide-react"; import JsBarcode from 'jsbarcode'; import { safeFormat, safeDate } from "@/lib/dateUtils"; import { format } from "date-fns"; @@ -39,6 +40,7 @@ import type { CustomerOrderWithRelations, Group } from "@shared/schema"; import { CustomerOrderForm } from "@/components/CustomerOrderForm"; import { CustomerOrderDetails } from "@/components/CustomerOrderDetails"; import { ConfirmationModal } from "@/components/ConfirmationModal"; +import ClientCallsModal from "@/components/modals/ClientCallsModal"; import { useStore } from "@/contexts/StoreContext"; import { usePermissions } from "@shared/permissions"; @@ -52,6 +54,7 @@ export default function CustomerOrders() { const [showDetailsModal, setShowDetailsModal] = useState(false); const [showDeleteModal, setShowDeleteModal] = useState(false); const [showStatusModal, setShowStatusModal] = useState(false); + const [showClientCallsModal, setShowClientCallsModal] = useState(false); const [selectedOrder, setSelectedOrder] = useState(null); const [searchTerm, setSearchTerm] = useState(""); const [sortBy, setSortBy] = useState<"date" | "status" | "supplier">("date"); @@ -64,6 +67,22 @@ export default function CustomerOrders() { queryKey: ['/api/groups'], }); + // Query pour les appels clients en attente + const { data: pendingCalls = [], isLoading: isPendingCallsLoading } = useQuery({ + queryKey: ['/api/customer-orders/pending-calls', selectedStoreId], + queryFn: async () => { + const pendingCallsUrl = `/api/customer-orders/pending-calls${selectedStoreId ? `?storeId=${selectedStoreId}` : ''}`; + const response = await fetch(pendingCallsUrl, { credentials: 'include' }); + if (!response.ok) { + throw new Error('Failed to fetch pending calls'); + } + const data = await response.json(); + console.log('📞 Customer Orders - Pending calls received:', Array.isArray(data) ? data.length : 'NOT_ARRAY', 'items'); + return data; + }, + refetchInterval: 30000, // Refetch every 30 seconds + }); + // Fetch suppliers for filter const { data: suppliers = [] } = useQuery({ queryKey: ['/api/suppliers'], @@ -688,6 +707,23 @@ export default function CustomerOrders() { return (
+ {/* Alerte pour les appels clients en attente */} + {!isPendingCallsLoading && pendingCalls.length > 0 && ( + setShowClientCallsModal(true)} + data-testid="alert-client-calls" + > + + + 📞 {pendingCalls.length} client{pendingCalls.length > 1 ? 's' : ''} à appeler + + Produits disponibles - Cliquez pour voir la liste des clients à contacter + + + + )} + {/* Header */}
@@ -996,6 +1032,13 @@ export default function CustomerOrders() { confirmText="Supprimer" isLoading={deleteMutation.isPending} /> + + {/* Modal pour les appels clients */} + setShowClientCallsModal(false)} + pendingCalls={pendingCalls} + />
); } \ No newline at end of file From 7ae93cc4b8c17df8e6e0148f4a2cfc799ebc6519 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Thu, 11 Sep 2025 11:13:51 +0000 Subject: [PATCH 2/4] Fix error in production that prevents alerts from appearing No changes were made to the codebase. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 95e8aab4-f39f-4b48-aa57-a759ec15ba3d Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/95e8aab4-f39f-4b48-aa57-a759ec15ba3d/IFoerZ5 From 967fe14a335e031d6a796557decdf5e7d218934b Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Thu, 11 Sep 2025 11:18:37 +0000 Subject: [PATCH 3/4] Add alert for clients not contacted when their order status is available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update `getPendingClientCalls` to filter customer orders where the client has not been notified and the order status is one of 'Disponible', 'disponible', 'Arrivé', 'arrivé', 'Prêt', or 'prêt' in both database and in-memory storage. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 95e8aab4-f39f-4b48-aa57-a759ec15ba3d Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/95e8aab4-f39f-4b48-aa57-a759ec15ba3d/TckvSqR --- .replit | 4 ++++ server/storage.ts | 18 +++++++----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.replit b/.replit index 19a7af5..b84ad63 100644 --- a/.replit +++ b/.replit @@ -15,6 +15,10 @@ run = ["npm", "run", "start"] localPort = 5000 externalPort = 80 +[[ports]] +localPort = 35077 +externalPort = 3003 + [[ports]] localPort = 38451 externalPort = 3002 diff --git a/server/storage.ts b/server/storage.ts index 651d9c7..307f307 100644 --- a/server/storage.ts +++ b/server/storage.ts @@ -1682,8 +1682,8 @@ export class DatabaseStorage implements IStorage { async getPendingClientCalls(groupIds?: number[]): Promise { const conditions = [ - eq(dlcProducts.status, 'valides'), - eq(customerOrders.customerNotified, false) + eq(customerOrders.customerNotified, false), + inArray(customerOrders.status, ['Disponible', 'disponible', 'Arrivé', 'arrivé', 'Prêt', 'prêt']) ]; if (groupIds && groupIds.length > 0) { @@ -1697,7 +1697,6 @@ export class DatabaseStorage implements IStorage { group: groups }) .from(customerOrders) - .innerJoin(dlcProducts, eq(customerOrders.gencode, dlcProducts.gencode)) .leftJoin(suppliers, eq(customerOrders.supplierId, suppliers.id)) .leftJoin(groups, eq(customerOrders.groupId, groups.id)) .where(and(...conditions)) @@ -3477,15 +3476,12 @@ export class MemStorage implements IStorage { orders = orders.filter(order => groupIds.includes(order.groupId)); } - // Find orders where client not notified and product is available + // Find orders where client not notified and status is 'Disponible' const pendingOrders = orders.filter(order => { - if (order.customerNotified) return false; - - // Check if there's a DLC product with status 'valides' matching this gencode - const matchingDlcProduct = Array.from(this.dlcProducts.values()) - .find(dlc => dlc.gencode === order.gencode && dlc.status === 'valides'); - - return !!matchingDlcProduct; + return !order.customerNotified && + (order.status === 'Disponible' || order.status === 'disponible' || + order.status === 'Arrivé' || order.status === 'arrivé' || + order.status === 'Prêt' || order.status === 'prêt'); }); return pendingOrders.map(order => ({ From 428eb74f554c9796f9db5fd5de191903c3551007 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Thu, 11 Sep 2025 11:19:47 +0000 Subject: [PATCH 4/4] Add logic to alert when a client's order status is available but they haven't been contacted Implement alert generation for uncontacted clients with available order statuses. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 95e8aab4-f39f-4b48-aa57-a759ec15ba3d Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/95e8aab4-f39f-4b48-aa57-a759ec15ba3d/TckvSqR --- .replit | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.replit b/.replit index b84ad63..2122ba9 100644 --- a/.replit +++ b/.replit @@ -27,10 +27,6 @@ externalPort = 3002 localPort = 41343 externalPort = 3001 -[[ports]] -localPort = 45663 -externalPort = 3000 - [workflows] runButton = "Project"