From 02809d64634a404df1bad735baf9d684c1a3d708 Mon Sep 17 00:00:00 2001 From: michaelschal <35957947-michaelschal@users.noreply.replit.com> Date: Mon, 18 Aug 2025 10:24:01 +0000 Subject: [PATCH] Filter ticket views and stats by selected store for administrators Refactors the SAV tickets page to allow administrators to filter tickets and statistics based on a selected store (groupId). Updates backend routes to conditionally filter by groupId when provided in the query parameters for both ticket listings and statistics retrieval. Enables query fetching only when user and store are initialized for administrators. Replit-Commit-Author: Agent Replit-Commit-Session-Id: f9197b9b-a5b3-4469-a27d-930a9e9ee736 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/f9197b9b-a5b3-4469-a27d-930a9e9ee736/icib2nb --- client/src/pages/SavTickets.tsx | 31 ++++++++++++++++++++++++++++--- server/routes.ts | 26 ++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/client/src/pages/SavTickets.tsx b/client/src/pages/SavTickets.tsx index d1799b2..bff0072 100644 --- a/client/src/pages/SavTickets.tsx +++ b/client/src/pages/SavTickets.tsx @@ -11,6 +11,7 @@ import { Textarea } from "@/components/ui/textarea"; import { useAuthUnified } from "@/hooks/useAuthUnified"; import { useToast } from "@/hooks/use-toast"; import { apiRequest } from "@/lib/queryClient"; +import { useStore } from "@/components/Layout"; import { Plus, Search, @@ -52,6 +53,7 @@ export default function SavTickets() { const { user } = useAuthUnified(); const { toast } = useToast(); const queryClient = useQueryClient(); + const { selectedStoreId, storeInitialized } = useStore(); const [searchTerm, setSearchTerm] = useState(""); const [statusFilter, setStatusFilter] = useState("all"); @@ -79,16 +81,22 @@ export default function SavTickets() { clientPhone: "" }); - // Build query parameters + // Build query parameters with store filtering const queryParams = new URLSearchParams(); if (statusFilter !== 'all') queryParams.append('status', statusFilter); if (priorityFilter !== 'all') queryParams.append('priority', priorityFilter); if (supplierFilter !== 'all') queryParams.append('supplierId', supplierFilter); + // Add store filtering for admin users + if (selectedStoreId && user?.role === 'admin') { + queryParams.append('groupId', selectedStoreId.toString()); + } + const ticketsUrl = `/api/sav/tickets${queryParams.toString() ? '?' + queryParams.toString() : ''}`; const { data: ticketsData = [], isLoading } = useQuery({ - queryKey: [ticketsUrl], + queryKey: [ticketsUrl, selectedStoreId], + enabled: !!user && (user.role !== 'admin' || storeInitialized), staleTime: 1000 * 60 * 5, // 5 minutes }); @@ -109,7 +117,24 @@ export default function SavTickets() { resolvedTickets: number; criticalTickets: number; }>({ - queryKey: ['/api/sav/stats'], + queryKey: ['/api/sav/stats', selectedStoreId], + queryFn: async () => { + const params = new URLSearchParams(); + if (selectedStoreId && user?.role === 'admin') { + params.append('groupId', selectedStoreId.toString()); + } + + const response = await fetch(`/api/sav/stats?${params.toString()}`, { + credentials: 'include' + }); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + + return response.json(); + }, + enabled: !!user && (user.role !== 'admin' || storeInitialized), staleTime: 1000 * 60 * 2, // 2 minutes }); diff --git a/server/routes.ts b/server/routes.ts index 85c2289..1307a23 100644 --- a/server/routes.ts +++ b/server/routes.ts @@ -2623,12 +2623,21 @@ RÉSUMÉ DU SCAN // Get user's group IDs for filtering let groupIds: number[] = []; if (user.role === 'admin') { - // Admin can see all tickets - groupIds = []; + // Admin can see all tickets if no specific store is selected + // But if a store is selected in the UI, filter by that store + const selectedGroupId = req.query.groupId ? parseInt(req.query.groupId) : null; + if (selectedGroupId) { + groupIds = [selectedGroupId]; + console.log(`🎫 [SAV] Admin filtering by selected store: ${selectedGroupId}`); + } else { + groupIds = []; // See all tickets + console.log(`🎫 [SAV] Admin viewing all tickets`); + } } else { // Other roles see only their assigned groups const userGroups = (user as any).userGroups; groupIds = userGroups ? userGroups.map((ug: any) => ug.groupId) : []; + console.log(`🎫 [SAV] User ${user.username} (${user.role}) can see stores:`, groupIds); } // Parse query filters @@ -2891,12 +2900,21 @@ RÉSUMÉ DU SCAN // Get user's group IDs for filtering let groupIds: number[] = []; if (user.role === 'admin') { - // Admin can see all stats - groupIds = []; + // Admin can see all stats if no specific store is selected + // But if a store is selected in the UI, filter by that store + const selectedGroupId = req.query.groupId ? parseInt(req.query.groupId) : null; + if (selectedGroupId) { + groupIds = [selectedGroupId]; + console.log(`📊 [SAV STATS] Admin filtering by selected store: ${selectedGroupId}`); + } else { + groupIds = []; // See all stats + console.log(`📊 [SAV STATS] Admin viewing all stats`); + } } else { // Other roles see only their assigned groups const userGroups = (user as any).userGroups; groupIds = userGroups ? userGroups.map((ug: any) => ug.groupId) : []; + console.log(`📊 [SAV STATS] User ${user.username} (${user.role}) can see stores:`, groupIds); } const stats = await storage.getSavTicketStats(groupIds.length > 0 ? groupIds : undefined);