diff --git a/CalendarGrid.PRODUCTION.tsx b/CalendarGrid.PRODUCTION.tsx deleted file mode 100644 index 7337eec..0000000 --- a/CalendarGrid.PRODUCTION.tsx +++ /dev/null @@ -1,355 +0,0 @@ -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, Package } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"; -import { useState } from "react"; -import type { OrderWithRelations, DeliveryWithRelations } from "@shared/schema"; - -interface CalendarGridProps { - currentDate: Date; - orders: OrderWithRelations[]; - deliveries: DeliveryWithRelations[]; - publicities: any[]; - selectedStoreId: number | null; - userGroups: any[]; - onDateClick: (date: Date) => void; - onItemClick: (item: any, type: 'order' | 'delivery') => void; -} - -// Composant pour afficher un élément (commande ou livraison) - VERSION PRODUCTION -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 getOrderStyle = () => { - switch (item.status) { - case 'delivered': - return 'bg-gray-400 text-white shadow-sm border-l-4 border-gray-500'; - case 'planned': - return 'bg-yellow-300 text-gray-800 shadow-sm border-l-4 border-yellow-500 font-medium'; - default: - return 'bg-blue-300 text-gray-800 shadow-sm border-l-4 border-blue-500'; - } - }; - - return ( -
{ - e.stopPropagation(); - onItemClick(item, 'order'); - }} - style={{marginBottom: '2px', display: 'block', width: '100%'}} - > -
- - {item.supplier?.name || 'Commande'} - -
- {item.status === 'planned' && ( -
- )} - {item.status === 'delivered' && ( - - )} -
-
-
- ); - } - - // Livraison - const getDeliveryStyle = () => { - switch (item.status) { - case 'delivered': - return 'bg-gray-400 text-white shadow-sm border-l-4 border-gray-500'; - case 'pending': - return 'bg-green-300 text-gray-800 shadow-sm border-l-4 border-green-500'; - default: - return 'bg-green-300 text-gray-800 shadow-sm border-l-4 border-green-500'; - } - }; - - return ( -
{ - e.stopPropagation(); - onItemClick(item, 'delivery'); - }} - style={{marginBottom: '2px', display: 'block', width: '100%'}} - > -
- - {item.supplier?.name || 'Livraison'} - {formatQuantity(item.quantity, item.unit)} - -
- {item.status === 'pending' && ( -
- )} - {item.status === 'delivered' && ( - - )} -
-
-
- ); -} - -// Composant pour gérer l'overflow avec modal - VERSION PRODUCTION -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 = 4; // PRODUCTION : TOUJOURS 4 ÉLÉMENTS - 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 modal - PRODUCTION */} - {hiddenCount > 0 && ( - - - - - - - - - Éléments du jour ({totalItems}) - - -
-
- {allItems.map((item, index) => ( -
- { - onItemClick(clickedItem, type); - setIsOpen(false); - }} - /> -
- ))} -
-
-
-
- )} -
- ); -} - -export default function CalendarGrid({ - currentDate, - orders, - deliveries, - publicities, - selectedStoreId, - userGroups, - onDateClick, - onItemClick -}: CalendarGridProps) { - const weekDays = ['LUN', 'MAR', 'MER', 'JEU', 'VEN', 'SAM', 'DIM']; - - // Generate calendar days - const monthStart = startOfMonth(currentDate); - const monthEnd = endOfMonth(currentDate); - const calendarDays = eachDayOfInterval({ start: monthStart, end: monthEnd }); - - // Calculate the number of days to show before the month starts (to align with Monday) - const startPadding = (monthStart.getDay() + 6) % 7; // Convert Sunday=0 to Monday=0 format - const paddingDays = Array.from({ length: startPadding }, (_, i) => { - const date = new Date(monthStart); - date.setDate(date.getDate() - startPadding + i); - return date; - }); - - const paddedDays = [...paddingDays, ...calendarDays]; - - // Filter data based on selected store - const filteredOrders = selectedStoreId - ? orders.filter(order => order.groupId === selectedStoreId) - : orders; - - const filteredDeliveries = selectedStoreId - ? deliveries.filter(delivery => delivery.groupId === selectedStoreId) - : deliveries; - - const getItemsForDate = (date: Date) => { - const dayOrders = filteredOrders.filter(order => { - const orderDate = safeDate(order.scheduledDate || order.deliveredDate || order.createdAt); - return orderDate && isSameDay(orderDate, date); - }); - - const dayDeliveries = filteredDeliveries.filter(delivery => { - const deliveryDate = safeDate(delivery.scheduledDate || delivery.deliveredDate || delivery.createdAt); - return deliveryDate && isSameDay(deliveryDate, date); - }); - - return { orders: dayOrders, deliveries: dayDeliveries }; - }; - - const getPublicitiesForDate = (date: Date) => { - return publicities.filter(pub => { - if (!pub.validFrom || !pub.validTo) return false; - - const pubStart = safeDate(pub.validFrom); - const pubEnd = safeDate(pub.validTo); - - if (!pubStart || !pubEnd) return false; - - return date >= pubStart && date <= pubEnd; - }); - }; - - return ( -
- {/* Calendar Header */} -
- {weekDays.map((day, index) => ( -
= 5 ? 'text-slate-700' : 'text-slate-800' - } uppercase border-r border-gray-300 last:border-r-0`} - > - {day} -
- ))} -
- - {/* Calendar Days */} -
- {paddedDays.map((date, index) => { - const isCurrentMonth = isSameMonth(date, currentDate); - const isTodayDate = isToday(date); - const isWeekend = date.getDay() === 0 || date.getDay() === 6; - const { orders: dayOrders, deliveries: dayDeliveries } = getItemsForDate(date); - const dayPublicities = getPublicitiesForDate(date); - - return ( -
onDateClick(date)} - > -
- {/* Numéro du jour */} -
- - {format(date, 'd')} - - - {/* Indicateur weekend */} - {isWeekend && isCurrentMonth && ( -
- )} -
- - {/* Orders and Deliveries - PRODUCTION OPTIMISÉ */} -
- -
-
- - {/* Publicities */} - {dayPublicities.length > 0 && ( -
- {dayPublicities.slice(0, 2).map((pub, idx) => ( -
pg.group?.name).join(', ')}` : ''}`} - > - {pub.pubNumber} -
- ))} - {dayPublicities.length > 2 && ( -
- +{dayPublicities.length - 2} -
- )} -
- )} - - {/* Quick Create Button */} - {isCurrentMonth && ( -
- -
- )} -
- ); - })} -
-
- ); -} \ No newline at end of file diff --git a/SYNC_DEV_PRODUCTION.md b/SYNC_DEV_PRODUCTION.md new file mode 100644 index 0000000..f904c76 --- /dev/null +++ b/SYNC_DEV_PRODUCTION.md @@ -0,0 +1,42 @@ +# SYNCHRONISATION DEV ↔ PRODUCTION + +## PROBLÈME RÉSOLU +Le fichier `client/src/components/CalendarGrid.tsx` est maintenant unifié pour développement ET production. + +## CHANGEMENTS APPLIQUÉS + +### ✅ Paramètres uniformisés +- `MAX_VISIBLE_ITEMS = 4` (identique dev/prod) +- Bouton "+X autres" blanc/gris (fini l'orange) +- Hauteur cellules `h-36` (plus d'espace) +- Styles forcés pour compatibilité production + +### ✅ Commentaires clarifiés +- "DEV = PRODUCTION" dans le code +- "IDENTIQUE DEV/PROD" sur les composants +- "BLANC/GRIS UNIFORME" sur le bouton + +## POUR VOTRE PRODUCTION + +1. **Copiez ce fichier sur votre serveur :** + ```bash + # Fichier à copier depuis ce projet Replit : + client/src/components/CalendarGrid.tsx + ``` + +2. **Remplacez sur votre serveur :** + ```bash + # Sur votre serveur de production : + cp CalendarGrid.tsx client/src/components/CalendarGrid.tsx + ``` + +3. **Redémarrez votre application** + +## RÉSULTAT ATTENDU +- ✅ 4 éléments max visibles par jour +- ✅ Bouton "+X autres" blanc/gris +- ✅ Modal qui s'ouvre correctement +- ✅ Interface identique dev/production + +--- +**Le fichier est maintenant unifié - plus de différences entre dev et prod !** \ No newline at end of file diff --git a/client/src/components/CalendarGrid.tsx b/client/src/components/CalendarGrid.tsx index ce9f26f..71f0603 100644 --- a/client/src/components/CalendarGrid.tsx +++ b/client/src/components/CalendarGrid.tsx @@ -100,10 +100,10 @@ function CalendarItem({ item, type, onItemClick }: { item: any, type: 'order' | ); } -// Composant pour gérer l'overflow avec modal +// Composant pour gérer l'overflow avec modal - DEV = PRODUCTION 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 = 4; // Production : 4 éléments visibles + const MAX_VISIBLE_ITEMS = 4; // FORCÉ : 4 éléments en dev ET production const totalItems = dayOrders.length + dayDeliveries.length; if (totalItems === 0) return null; @@ -118,8 +118,8 @@ function DayItemsContainer({ dayOrders, dayDeliveries, onItemClick }: { dayOrder const hiddenCount = Math.max(0, totalItems - MAX_VISIBLE_ITEMS); return ( -
- {/* Éléments visibles */} +
+ {/* Éléments visibles - IDENTIQUE DEV/PROD */} {visibleItems.map((item, index) => ( ))} - {/* Badge "+X autres" avec modal moderne */} + {/* Badge "+X autres" - BLANC/GRIS UNIFORME */} {hiddenCount > 0 && (
- {/* Orders and Deliveries - Production optimisé */} + {/* Orders and Deliveries - DEV = PRODUCTION */}