From e46922bd569e2d27d7dd19bd3d02e6be2a801a26 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Mon, 11 Aug 2025 22:11:04 +0000 Subject: [PATCH] Improve calendar display stability and data handling Add robust error handling and data validation to the calendar component and API routes to prevent production crashes, specifically addressing issues with invalid publicity data and ensuring array types for fetched data. Replit-Commit-Author: Agent Replit-Commit-Session-Id: b163d4c0-de5e-4f4e-a9c0-aed4c7049718 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/b163d4c0-de5e-4f4e-a9c0-aed4c7049718/FL119j1 --- client/src/components/CalendarGrid.tsx | 53 ++++++++++++---- client/src/pages/Calendar.tsx | 22 +++++-- server/routes.ts | 87 +++++++++++--------------- 3 files changed, 94 insertions(+), 68 deletions(-) diff --git a/client/src/components/CalendarGrid.tsx b/client/src/components/CalendarGrid.tsx index 5c9e21b..aa908bf 100644 --- a/client/src/components/CalendarGrid.tsx +++ b/client/src/components/CalendarGrid.tsx @@ -171,6 +171,14 @@ export default function CalendarGrid({ onDateClick, onItemClick, }: CalendarGridProps) { + console.log('🗓️ CalendarGrid rendered with:', { + currentDate: currentDate?.toISOString(), + ordersCount: orders?.length || 0, + deliveriesCount: deliveries?.length || 0, + publicitiesCount: publicities?.length || 0, + selectedStoreId, + userGroupsCount: userGroups?.length || 0 + }); const monthStart = startOfMonth(currentDate); const monthEnd = endOfMonth(currentDate); @@ -178,29 +186,42 @@ export default function CalendarGrid({ const getPublicitiesForDate = (date: Date) => { const dateStr = format(date, 'yyyy-MM-dd'); + // Protection contre les données invalides qui causent des plantages en production + if (!publicities || !Array.isArray(publicities)) { + console.warn('⚠️ Invalid publicities data:', publicities); + return []; + } + console.log('🔍 CalendarGrid getPublicitiesForDate:', { date: dateStr, totalPublicities: publicities.length, selectedStoreId, - userGroups: userGroups.length + userGroups: userGroups?.length || 0 }); - if (publicities.length > 0) { - console.log('📄 Sample publicity structure:', publicities[0]); - } - - return publicities.filter(pub => { + try { + return publicities.filter(pub => { + // Vérifications de sécurité pour éviter les plantages + if (!pub || typeof pub !== 'object') { + console.warn('⚠️ Invalid publicity object:', pub); + return false; + } // Check if the date is within the publicity period const pubStart = pub.startDate; const pubEnd = pub.endDate; + if (!pubStart || !pubEnd) { + console.warn('⚠️ Publicity missing dates:', { pubNumber: pub.pubNumber, startDate: pubStart, endDate: pubEnd }); + return false; + } + if (dateStr < pubStart || dateStr > pubEnd) { return false; } // If no store is selected and user has no assigned groups, show only publicities with participations if (!selectedStoreId && (!userGroups || userGroups.length === 0)) { - const hasParticipations = pub.participations && pub.participations.length > 0; + const hasParticipations = pub.participations && Array.isArray(pub.participations) && pub.participations.length > 0; if (hasParticipations) { console.log('📋 Publicity has participations (no store selected):', { pubNumber: pub.pubNumber, participationCount: pub.participations.length }); } @@ -209,7 +230,8 @@ export default function CalendarGrid({ // If a specific store is selected, check if that store participates if (selectedStoreId) { - const matches = pub.participations?.some((pg: any) => pg.groupId === selectedStoreId); + const matches = pub.participations && Array.isArray(pub.participations) && + pub.participations.some((pg: any) => pg?.groupId === selectedStoreId); if (matches) { console.log('🎯 Publicity matches selected store:', { pubNumber: pub.pubNumber, selectedStoreId }); } @@ -218,9 +240,10 @@ export default function CalendarGrid({ // If no specific store selected but user has assigned stores, // show publicities where any of user's stores participate - if (userGroups && userGroups.length > 0) { - const userGroupIds = userGroups.map((ug: any) => ug.groupId); - const matches = pub.participations?.some((pg: any) => userGroupIds.includes(pg.groupId)); + if (userGroups && Array.isArray(userGroups) && userGroups.length > 0) { + const userGroupIds = userGroups.map((ug: any) => ug?.groupId).filter(id => id !== undefined); + const matches = pub.participations && Array.isArray(pub.participations) && + pub.participations.some((pg: any) => pg?.groupId && userGroupIds.includes(pg.groupId)); if (matches) { console.log('👥 Publicity matches user groups:', { pubNumber: pub.pubNumber, userGroupIds }); } @@ -228,12 +251,16 @@ export default function CalendarGrid({ } // Default case: only show publicities with participations - const hasParticipations = pub.participations && pub.participations.length > 0; + const hasParticipations = pub.participations && Array.isArray(pub.participations) && pub.participations.length > 0; if (hasParticipations) { console.log('📋 Publicity has participations (default case):', { pubNumber: pub.pubNumber, participationCount: pub.participations.length }); } return hasParticipations; - }); + }); + } catch (error) { + console.error('❌ Error filtering publicities:', error); + return []; + } }; // Get all days in the month diff --git a/client/src/pages/Calendar.tsx b/client/src/pages/Calendar.tsx index a8fdc8d..b94b329 100644 --- a/client/src/pages/Calendar.tsx +++ b/client/src/pages/Calendar.tsx @@ -1,6 +1,6 @@ import { useState } from "react"; import { useQuery, useQueryClient } from "@tanstack/react-query"; -import { ChevronLeft, ChevronRight, Plus, RefreshCw } from "lucide-react"; +import { ChevronLeft, ChevronRight, Plus, RefreshCw, Calendar as CalendarIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import CalendarGrid from "@/components/CalendarGrid"; import QuickCreateMenu from "@/components/modals/QuickCreateMenu"; @@ -65,6 +65,12 @@ export default function Calendar() { const data = await response.json(); console.log('📅 Calendar orders received:', Array.isArray(data) ? data.length : 'NOT_ARRAY', 'items'); + + // Protection contre les données invalides en production + if (!Array.isArray(data)) { + console.warn('⚠️ Orders data is not an array, returning empty array'); + return []; + } return data; }, }); @@ -101,6 +107,12 @@ export default function Calendar() { const data = await response.json(); console.log('📅 Calendar deliveries received:', Array.isArray(data) ? data.length : 'NOT_ARRAY', 'items'); + + // Protection contre les données invalides en production + if (!Array.isArray(data)) { + console.warn('⚠️ Deliveries data is not an array, returning empty array'); + return []; + } return data; }, }); @@ -183,7 +195,7 @@ export default function Calendar() {