import { format, startOfMonth, endOfMonth, eachDayOfInterval, isSameDay, isSameMonth, isToday } from "date-fns"; import { fr } from "date-fns/locale"; import { safeDate } from "@/lib/dateUtils"; import { Plus, Check, MoreHorizontal } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"; import { useState } from "react"; import type { OrderWithRelations, DeliveryWithRelations } from "@shared/schema"; interface CalendarGridProps { currentDate: Date; orders: OrderWithRelations[]; deliveries: DeliveryWithRelations[]; onDateClick: (date: Date) => void; onItemClick: (item: any, type: 'order' | 'delivery') => void; } // Composant pour afficher un élément (commande ou livraison) function CalendarItem({ item, type, onItemClick }: { item: any, type: 'order' | 'delivery', onItemClick: (item: any, type: 'order' | 'delivery') => void }) { const formatQuantity = (quantity: number, unit: string) => { return `${quantity}${unit === 'palettes' ? 'P' : 'C'}`; }; if (type === 'order') { const colorClass = item.status === 'delivered' ? 'bg-delivered text-white' : item.status === 'planned' ? 'bg-orange-500 text-white border-2 border-orange-300' : 'bg-primary text-white'; return (
{ e.stopPropagation(); onItemClick(item, 'order'); }} > {item.supplier.name}
{item.status === 'planned' && ( )} {item.status === 'delivered' && ( )}
); } // Livraison return (
{ e.stopPropagation(); onItemClick(item, 'delivery'); }} > {item.supplier.name} - {formatQuantity(item.quantity, item.unit)}
{item.status === 'pending' && ( )} {item.status === 'delivered' && ( )}
); } // Composant pour gérer l'overflow avec popover function DayItemsContainer({ dayOrders, dayDeliveries, onItemClick }: { dayOrders: any[], dayDeliveries: any[], onItemClick: (item: any, type: 'order' | 'delivery') => void }) { const [isOpen, setIsOpen] = useState(false); const MAX_VISIBLE_ITEMS = 2; const totalItems = dayOrders.length + dayDeliveries.length; if (totalItems === 0) return null; // Combiner tous les éléments avec leur type const allItems = [ ...dayOrders.map(order => ({ ...order, itemType: 'order' as const })), ...dayDeliveries.map(delivery => ({ ...delivery, itemType: 'delivery' as const })) ]; const visibleItems = allItems.slice(0, MAX_VISIBLE_ITEMS); const hiddenCount = Math.max(0, totalItems - MAX_VISIBLE_ITEMS); return (
{/* Éléments visibles */} {visibleItems.map((item, index) => ( ))} {/* Badge "+X autres" avec popover */} {hiddenCount > 0 && ( e.stopPropagation()} >

Tous les éléments ({totalItems})

{allItems.map((item) => ( { onItemClick(clickedItem, type); setIsOpen(false); }} /> ))}
)}
); } export default function CalendarGrid({ currentDate, orders, deliveries, onDateClick, onItemClick, }: CalendarGridProps) { const monthStart = startOfMonth(currentDate); const monthEnd = endOfMonth(currentDate); // Get all days in the month const monthDays = eachDayOfInterval({ start: monthStart, end: monthEnd, }); // Pad the calendar to start on Monday const firstDayOfWeek = monthStart.getDay(); const startPadding = firstDayOfWeek === 0 ? 6 : firstDayOfWeek - 1; const paddedDays = []; // Add padding days from previous month for (let i = startPadding; i > 0; i--) { const paddingDate = new Date(monthStart); paddingDate.setDate(paddingDate.getDate() - i); paddedDays.push(paddingDate); } // Add current month days paddedDays.push(...monthDays); // Add padding days from next month to complete the grid const remainingCells = 42 - paddedDays.length; // 6 weeks * 7 days for (let i = 1; i <= remainingCells; i++) { const paddingDate = new Date(monthEnd); paddingDate.setDate(paddingDate.getDate() + i); paddedDays.push(paddingDate); } const weekDays = ["Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"]; const getItemsForDate = (date: Date) => { // Debug: Log des commandes reçues (seulement une fois) if (orders.length > 0 && date.getDate() === 1) { console.log('📅 CalendarGrid Debug - Orders received:', orders.length); console.log('📅 First order structure:', orders[0]); console.log('📅 All orders dates:', orders.map(o => ({ id: o.id, plannedDate: o.plannedDate, supplier: o.supplier?.name }))); } // Debug: Log des livraisons reçues (seulement une fois) if (deliveries.length > 0 && date.getDate() === 1) { console.log('🚛 CalendarGrid Debug - Deliveries received:', deliveries.length); console.log('🚛 First delivery structure:', deliveries[0]); console.log('🚛 All deliveries dates:', deliveries.map(d => ({ id: d.id, scheduledDate: d.scheduledDate, supplier: d.supplier?.name }))); } const dayOrders = orders.filter(order => { // Protection contre undefined/null if (!order || !order.supplier) { console.warn('📅 Invalid order found:', order); return false; } // Essayer plusieurs champs de date possibles const orderDate = safeDate(order.plannedDate || order.createdAt); const matches = orderDate && isSameDay(orderDate, date); if (matches) { console.log('📅 Order matches date:', { orderId: order.id, supplier: order.supplier?.name, plannedDate: order.plannedDate, matchingDate: format(date, 'yyyy-MM-dd') }); } return matches; }); const dayDeliveries = deliveries.filter(delivery => { // Protection contre undefined/null if (!delivery || !delivery.supplier) { console.warn('🚛 Invalid delivery found:', delivery); return false; } // Essayer plusieurs champs de date possibles const deliveryDate = safeDate(delivery.scheduledDate || delivery.deliveredDate || delivery.createdAt); const matches = deliveryDate && isSameDay(deliveryDate, date); if (matches) { console.log('🚛 Delivery matches date:', { deliveryId: delivery.id, supplier: delivery.supplier?.name, scheduledDate: delivery.scheduledDate, matchingDate: format(date, 'yyyy-MM-dd') }); } return matches; }); return { orders: dayOrders, deliveries: dayDeliveries }; }; return (
{/* Calendar Header */}
{weekDays.map(day => (
{day}
))}
{/* Calendar Days */}
{paddedDays.map((date, index) => { const isCurrentMonth = isSameMonth(date, currentDate); const isTodayDate = isToday(date); const { orders: dayOrders, deliveries: dayDeliveries } = getItemsForDate(date); return (
onDateClick(date)} >
{format(date, 'd')} {/* Orders and Deliveries avec système d'overflow */}
{/* Quick Create Button */} {isCurrentMonth && (
)}
); })}
); }