From 6378fa5a7cb858c0bff70a1b9726bc4dedaa5b1f Mon Sep 17 00:00:00 2001 From: R0m1k3 Date: Wed, 10 Dec 2025 14:24:18 +0100 Subject: [PATCH] feat: add mobile calendar page to display orders and deliveries as events. --- client/src/pages/mobile/CalendarPage.tsx | 175 ++++++++++++++++------- 1 file changed, 127 insertions(+), 48 deletions(-) diff --git a/client/src/pages/mobile/CalendarPage.tsx b/client/src/pages/mobile/CalendarPage.tsx index 3c4c708..1757152 100644 --- a/client/src/pages/mobile/CalendarPage.tsx +++ b/client/src/pages/mobile/CalendarPage.tsx @@ -1,5 +1,6 @@ /** * CalendarPage Mobile - Calendrier simplifié pour mobile + * Affiche les commandes et livraisons comme événements */ import { useState } from "react"; import { useQuery } from "@tanstack/react-query"; @@ -13,8 +14,8 @@ import { Calendar as CalendarIcon, ChevronLeft, ChevronRight, - Clock, - MapPin + Package, + Truck } from "lucide-react"; import { format, @@ -31,15 +32,14 @@ import { } from "date-fns"; import { fr } from "date-fns/locale"; -// Type pour les événements +// Type pour les événements (combinaison de commandes et livraisons) type CalendarEvent = { id: number; title: string; - startDate: string; - endDate?: string; - description?: string; - location?: string; - type?: string; + date: string; + type: 'order' | 'delivery'; + status?: string; + supplier?: { name: string }; }; export default function MobileCalendarPage() { @@ -48,15 +48,20 @@ export default function MobileCalendarPage() { const [currentMonth, setCurrentMonth] = useState(new Date()); const [selectedDate, setSelectedDate] = useState(new Date()); - // Fetch calendar events - const { data: events = [], isLoading } = useQuery({ - queryKey: ["/api/calendar/events", selectedStoreId, format(currentMonth, 'yyyy-MM')], - queryFn: async () => { - const params = new URLSearchParams(); - if (selectedStoreId) params.append('storeId', selectedStoreId.toString()); - params.append('month', format(currentMonth, 'yyyy-MM')); + const monthStart = startOfMonth(currentMonth); + const monthEnd = endOfMonth(currentMonth); - const response = await fetch(`/api/calendar/events?${params}`, { + // Fetch orders for current month + const { data: orders = [] } = useQuery({ + queryKey: ["/api/orders", selectedStoreId, format(currentMonth, 'yyyy-MM')], + queryFn: async () => { + const params = new URLSearchParams({ + startDate: format(monthStart, 'yyyy-MM-dd'), + endDate: format(monthEnd, 'yyyy-MM-dd') + }); + if (selectedStoreId) params.append('storeId', selectedStoreId.toString()); + + const response = await fetch(`/api/orders?${params}`, { credentials: 'include' }); if (!response.ok) return []; @@ -66,25 +71,67 @@ export default function MobileCalendarPage() { enabled: !!user, }); + // Fetch deliveries for current month + const { data: deliveries = [] } = useQuery({ + queryKey: ["/api/deliveries", selectedStoreId, format(currentMonth, 'yyyy-MM')], + queryFn: async () => { + const params = new URLSearchParams({ + startDate: format(monthStart, 'yyyy-MM-dd'), + endDate: format(monthEnd, 'yyyy-MM-dd') + }); + if (selectedStoreId) params.append('storeId', selectedStoreId.toString()); + + const response = await fetch(`/api/deliveries?${params}`, { + credentials: 'include' + }); + if (!response.ok) return []; + const data = await response.json(); + return Array.isArray(data) ? data : []; + }, + enabled: !!user, + }); + + // Combine orders and deliveries into events + const events: CalendarEvent[] = [ + ...orders.map((order: any) => ({ + id: order.id, + title: `Cmd #${order.orderNumber || order.id}`, + date: order.orderDate, + type: 'order' as const, + status: order.status, + supplier: order.supplier + })), + ...deliveries.map((delivery: any) => ({ + id: delivery.id, + title: `Liv #${delivery.deliveryNumber || delivery.id}`, + date: delivery.expectedDate, + type: 'delivery' as const, + status: delivery.status, + supplier: delivery.supplier + })) + ]; + // Get days for the calendar grid - const monthStart = startOfMonth(currentMonth); - const monthEnd = endOfMonth(currentMonth); const calendarStart = startOfWeek(monthStart, { locale: fr }); const calendarEnd = endOfWeek(monthEnd, { locale: fr }); const calendarDays = eachDayOfInterval({ start: calendarStart, end: calendarEnd }); // Get events for selected date const selectedDateEvents = selectedDate - ? events.filter((event: CalendarEvent) => - isSameDay(new Date(event.startDate), selectedDate) - ) + ? events.filter((event) => { + if (!event.date) return false; + const eventDate = new Date(event.date); + return !isNaN(eventDate.getTime()) && isSameDay(eventDate, selectedDate); + }) : []; // Check if a day has events - const hasEvents = (day: Date) => { - return events.some((event: CalendarEvent) => - isSameDay(new Date(event.startDate), day) - ); + const getEventsForDay = (day: Date) => { + return events.filter((event) => { + if (!event.date) return false; + const eventDate = new Date(event.date); + return !isNaN(eventDate.getTime()) && isSameDay(eventDate, day); + }); }; const navigateMonth = (direction: 'prev' | 'next') => { @@ -103,6 +150,7 @@ export default function MobileCalendarPage() {

Calendrier

+ {events.length} événements {/* Month navigation */} @@ -130,6 +178,18 @@ export default function MobileCalendarPage() { + {/* Legend */} +
+
+
+ Commandes +
+
+
+ Livraisons +
+
+ {/* Calendar grid */} @@ -151,14 +211,16 @@ export default function MobileCalendarPage() { const isCurrentMonth = isSameMonth(day, currentMonth); const isTodayDate = isToday(day); const isSelected = selectedDate && isSameDay(day, selectedDate); - const dayHasEvents = hasEvents(day); + const dayEvents = getEventsForDay(day); + const hasOrders = dayEvents.some(e => e.type === 'order'); + const hasDeliveries = dayEvents.some(e => e.type === 'delivery'); return ( ); @@ -180,32 +245,46 @@ export default function MobileCalendarPage() { {selectedDate && (

- {format(selectedDate, 'd MMMM', { locale: fr })} + {format(selectedDate, 'EEEE d MMMM', { locale: fr })}

{selectedDateEvents.length === 0 ? (

- Aucun événement + Aucun événement ce jour

) : ( - selectedDateEvents.map((event: CalendarEvent) => ( - + selectedDateEvents.map((event) => ( + -

- {event.title} -

- {event.startDate && ( -

- - {format(new Date(event.startDate), 'HH:mm')} -

- )} - {event.location && ( -

- - {event.location} -

- )} +
+
+ {event.type === 'order' + ? + : + } +
+
+

+ {event.title} +

+ {event.supplier && ( +

+ {event.supplier.name} +

+ )} + {event.status && ( + + {event.status} + + )} +
+
))