diff --git a/src/components/moderation/ModerationQueue.tsx b/src/components/moderation/ModerationQueue.tsx index bb308199..2340a517 100644 --- a/src/components/moderation/ModerationQueue.tsx +++ b/src/components/moderation/ModerationQueue.tsx @@ -1,5 +1,6 @@ import { useState, useImperativeHandle, forwardRef, useMemo } from 'react'; import { Card, CardContent } from '@/components/ui/card'; +import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; import { useToast } from '@/hooks/use-toast'; import { useUserRole } from '@/hooks/useUserRole'; import { useAuth } from '@/hooks/useAuth'; @@ -19,7 +20,8 @@ import { AutoRefreshIndicator } from './AutoRefreshIndicator'; import { NewItemsAlert } from './NewItemsAlert'; import { EmptyQueueState } from './EmptyQueueState'; import { QueuePagination } from './QueuePagination'; -import type { ModerationQueueRef } from '@/types/moderation'; +import type { ModerationQueueRef, QueueTab } from '@/types/moderation'; +import { AlertTriangle, Clock, Archive } from 'lucide-react'; export const ModerationQueue = forwardRef((props, ref) => { const isMobile = useIsMobile(); @@ -87,6 +89,28 @@ export const ModerationQueue = forwardRef((props, ref) => { return (
+ {/* Queue Tabs */} + queueManager.filters.setActiveTab(value as QueueTab)} + className="w-full" + > + + + + Main Queue + + + + Escalated + + + + Archive + + + + {/* Queue Statistics & Lock Status */} {queueManager.queue.queueStats && ( diff --git a/src/hooks/moderation/useModerationQueueManager.ts b/src/hooks/moderation/useModerationQueueManager.ts index dc4fed1d..4b4d6d66 100644 --- a/src/hooks/moderation/useModerationQueueManager.ts +++ b/src/hooks/moderation/useModerationQueueManager.ts @@ -238,9 +238,8 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): ascending: sort.config.direction === 'asc' }); - // Apply sorting: escalated first (desc), then user's chosen field + // Apply sorting by user's chosen field only submissionsQuery = submissionsQuery - .order("escalated", { ascending: false }) .order(sortField, { ascending: sort.config.direction === 'asc' }); // Apply tab-based status filtering @@ -249,6 +248,20 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): const entityFilter = filters.debouncedEntityFilter; if (tab === "mainQueue") { + // Main queue: non-escalated pending items + submissionsQuery = submissionsQuery.eq("escalated", false); + + if (statusFilter === "all") { + submissionsQuery = submissionsQuery.in("status", ["pending", "flagged", "partially_approved"]); + } else if (statusFilter === "pending") { + submissionsQuery = submissionsQuery.in("status", ["pending", "partially_approved"]); + } else { + submissionsQuery = submissionsQuery.eq("status", statusFilter); + } + } else if (tab === "escalated") { + // Escalated queue: only escalated items + submissionsQuery = submissionsQuery.eq("escalated", true); + if (statusFilter === "all") { submissionsQuery = submissionsQuery.in("status", ["pending", "flagged", "partially_approved"]); } else if (statusFilter === "pending") { @@ -257,6 +270,7 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): submissionsQuery = submissionsQuery.eq("status", statusFilter); } } else { + // Archive: completed items (non-escalated and escalated) if (statusFilter === "all") { submissionsQuery = submissionsQuery.in("status", ["approved", "rejected"]); } else { @@ -286,6 +300,18 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig): // Apply the exact same filters as the main query if (tab === "mainQueue") { + countQuery = countQuery.eq("escalated", false); + + 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 (tab === "escalated") { + countQuery = countQuery.eq("escalated", true); + if (statusFilter === "all") { countQuery = countQuery.in("status", ["pending", "flagged", "partially_approved"]); } else if (statusFilter === "pending") { diff --git a/src/types/moderation.ts b/src/types/moderation.ts index ae93bd55..17edbf32 100644 --- a/src/types/moderation.ts +++ b/src/types/moderation.ts @@ -97,7 +97,7 @@ export type StatusFilter = 'all' | 'pending' | 'partially_approved' | 'flagged' /** * Available tabs in the moderation interface */ -export type QueueTab = 'mainQueue' | 'archive'; +export type QueueTab = 'mainQueue' | 'escalated' | 'archive'; /** * Fields that can be used for sorting the moderation queue