diff --git a/src/hooks/moderation/useModerationQueueManager.ts b/src/hooks/moderation/useModerationQueueManager.ts index f6f33403..7776f527 100644 --- a/src/hooks/moderation/useModerationQueueManager.ts +++ b/src/hooks/moderation/useModerationQueueManager.ts @@ -145,7 +145,7 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): const isMountingRef = useRef(true); const fetchItemsRef = useRef<((silent?: boolean) => Promise) | null>(null); - const FETCH_COOLDOWN_MS = 1000; + const FETCH_COOLDOWN_MS = 300; // Match filter debounce delay for responsive sort changes // Store settings in refs to avoid re-creating fetchItems const settingsRef = useRef(settings); @@ -162,10 +162,11 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): * Fetch queue items from database */ const fetchItems = useCallback( - async (silent = false) => { + async (silent = false, bypassCooldown = false) => { console.log('πŸ”„ [fetchItems RECREATED]', { sortField: sort.field, sortDirection: sort.direction, + bypassCooldown, timestamp: new Date().toISOString() }); @@ -195,10 +196,10 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): return; } - // Cooldown check + // Cooldown check (can be bypassed for critical operations like sort changes) const now = Date.now(); const timeSinceLastFetch = now - lastFetchTimeRef.current; - if (timeSinceLastFetch < FETCH_COOLDOWN_MS && lastFetchTimeRef.current > 0) { + if (!bypassCooldown && timeSinceLastFetch < FETCH_COOLDOWN_MS && lastFetchTimeRef.current > 0) { console.log(`⏸️ Fetch cooldown active (${timeSinceLastFetch}ms)`); return; } @@ -321,12 +322,42 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): ); } - // Get total count - const { count } = await supabase + // Get total count for pagination (rebuild query with same filters) + let countQuery = supabase .from("content_submissions") - .select("*", { count: "exact", head: true }) - .match(submissionsQuery as any); + .select("*", { count: "exact", head: true }); + // Apply same filters as main query + if (tab === "mainQueue") { + if (statusFilter === "all") { + countQuery = countQuery.in("status", ["pending", "flagged", "partially_approved"]); + } else if (statusFilter === "pending") { + countQuery = countQuery.in("status", ["pending", "partially_approved"]); + } else { + countQuery = countQuery.eq("status", statusFilter); + } + } else { + if (statusFilter === "all") { + countQuery = countQuery.in("status", ["approved", "rejected"]); + } else { + countQuery = countQuery.eq("status", statusFilter); + } + } + + if (entityFilter === "photos") { + countQuery = countQuery.eq("submission_type", "photo"); + } else if (entityFilter === "submissions") { + countQuery = countQuery.neq("submission_type", "photo"); + } + + if (!isAdmin && !isSuperuser) { + const now = new Date().toISOString(); + countQuery = countQuery.or( + `assigned_to.is.null,locked_until.lt.${now},assigned_to.eq.${user.id}`, + ); + } + + const { count } = await countQuery; pagination.setTotalCount(count || 0); // Apply pagination @@ -353,6 +384,22 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): if (submissionsError) throw submissionsError; + // VALIDATE: Log first few items to verify sort is working + if (submissions && submissions.length > 0) { + console.log('[Query] Results returned (first 3 items):', { + sortColumn, + sortDirection: sortAscending ? 'ASC' : 'DESC', + items: submissions.slice(0, 3).map(s => ({ + id: s.id.substring(0, 8), + type: s.submission_type, + status: s.status, + created: s.created_at, + escalated: s.escalated, + sortValue: s[sortColumn as keyof typeof s] + })) + }); + } + // Fetch related profiles and entities const userIds = [ ...new Set([ @@ -955,9 +1002,6 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): console.log('πŸ”„ [Sort Changed]', { field: sort.field, direction: sort.direction, - configField: sort.config.field, - configDirection: sort.config.direction, - match: sort.field === sort.config.field && sort.direction === sort.config.direction, timestamp: new Date().toISOString() }); @@ -973,19 +1017,15 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): return; } - // CRITICAL: Ensure we're using the latest fetchItems - if (fetchItemsRef.current) { - console.log('βœ… Triggering refetch due to sort change', { - willUseField: sort.field, - willUseDirection: sort.direction - }); - - // Force immediate refetch - fetchItemsRef.current(false); - } else { - console.error('❌ fetchItemsRef.current is null - cannot refetch!'); - } - }, [sort.field, sort.direction]); + console.log('βœ… Triggering refetch due to sort change', { + willUseField: sort.field, + willUseDirection: sort.direction + }); + + // Call fetchItems directly (guaranteed to have latest sort values in closure) + // Use bypass to skip cooldown for immediate sort response + fetchItems(false, true); + }, [sort.field, sort.direction, fetchItems]); // Initialize realtime subscriptions useRealtimeSubscriptions({