From 745ddc68054885689122acdb36c7171c6c82dc59 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Mon, 11 Aug 2025 21:50:26 +0000 Subject: [PATCH] Display promotional content alongside orders and deliveries on the calendar Fetch and display publicity information on the calendar view, filtering based on selected store and user groups. 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/ByygiiM --- client/src/components/CalendarGrid.tsx | 79 +++++++++++++++++++++++++- client/src/pages/Calendar.tsx | 37 +++++++++++- 2 files changed, 114 insertions(+), 2 deletions(-) diff --git a/client/src/components/CalendarGrid.tsx b/client/src/components/CalendarGrid.tsx index bdbf99d..d705b8c 100644 --- a/client/src/components/CalendarGrid.tsx +++ b/client/src/components/CalendarGrid.tsx @@ -11,6 +11,9 @@ 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; } @@ -162,12 +165,49 @@ export default function CalendarGrid({ currentDate, orders, deliveries, + publicities, + selectedStoreId, + userGroups, onDateClick, onItemClick, }: CalendarGridProps) { const monthStart = startOfMonth(currentDate); const monthEnd = endOfMonth(currentDate); + // Helper function to filter publicities based on user's assigned stores + const getPublicitiesForDate = (date: Date) => { + const dateStr = format(date, 'yyyy-MM-dd'); + + return publicities.filter(pub => { + // Check if the date is within the publicity period + const pubStart = pub.startDate; + const pubEnd = pub.endDate; + + if (dateStr < pubStart || dateStr > pubEnd) { + return false; + } + + // If no store is selected and user has no assigned groups, show all publicities + if (!selectedStoreId && (!userGroups || userGroups.length === 0)) { + return true; + } + + // If a specific store is selected, check if that store participates + if (selectedStoreId) { + return pub.participatingGroups?.some((pg: any) => pg.groupId === selectedStoreId); + } + + // 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); + return pub.participatingGroups?.some((pg: any) => userGroupIds.includes(pg.groupId)); + } + + return true; + }); + }; + // Get all days in the month const monthDays = eachDayOfInterval({ start: monthStart, @@ -280,6 +320,7 @@ export default function CalendarGrid({ const isCurrentMonth = isSameMonth(date, currentDate); const isTodayDate = isToday(date); const { orders: dayOrders, deliveries: dayDeliveries } = getItemsForDate(date); + const dayPublicities = getPublicitiesForDate(date); return (
+ {/* Publicities in top-right corner */} + {dayPublicities.length > 0 && ( +
+ {dayPublicities.slice(0, 3).map((pub, idx) => ( +
pg.group?.name).join(', ')}` : ''}`} + > + {pub.pubNumber} +
+ ))} + {dayPublicities.length > 3 && ( +
+ +{dayPublicities.length - 3} +
+ )} +
+ )} + {/* Quick Create Button */} - {isCurrentMonth && ( + {isCurrentMonth && dayPublicities.length === 0 && (
)} + + {/* Quick Create Button when publicities are present */} + {isCurrentMonth && dayPublicities.length > 0 && ( +
+ +
+ )} ); })} diff --git a/client/src/pages/Calendar.tsx b/client/src/pages/Calendar.tsx index 2935aaa..840253f 100644 --- a/client/src/pages/Calendar.tsx +++ b/client/src/pages/Calendar.tsx @@ -105,6 +105,38 @@ export default function Calendar() { }, }); + // Fetch publicities for the current year + const { data: publicities = [], isLoading: loadingPublicities } = useQuery({ + queryKey: ['/api/publicities', currentDate.getFullYear(), selectedStoreId], + queryFn: async () => { + const params = new URLSearchParams(); + params.append('year', currentDate.getFullYear().toString()); + if (selectedStoreId && user?.role === 'admin') { + params.append('storeId', selectedStoreId.toString()); + } + + const url = `/api/publicities?${params.toString()}`; + console.log('📅 Calendar fetching publicities:', { + url, + selectedStoreId, + userRole: user?.role, + year: currentDate.getFullYear() + }); + + const response = await fetch(url, { + credentials: 'include' + }); + + if (!response.ok) { + throw new Error('Failed to fetch publicities'); + } + + const data = await response.json(); + console.log('📅 Calendar publicities received:', Array.isArray(data) ? data.length : 'NOT_ARRAY', 'items'); + return Array.isArray(data) ? data : []; + }, + }); + const navigateMonth = (direction: 'prev' | 'next') => { const newDate = new Date(currentDate); if (direction === 'prev') { @@ -143,7 +175,7 @@ export default function Calendar() { - const isLoading = loadingOrders || loadingDeliveries; + const isLoading = loadingOrders || loadingDeliveries || loadingPublicities; return (
@@ -226,6 +258,9 @@ export default function Calendar() { currentDate={currentDate} orders={orders} deliveries={deliveries} + publicities={publicities} + selectedStoreId={selectedStoreId} + userGroups={user?.userGroups || []} onDateClick={handleDateClick} onItemClick={handleItemClick} />