mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-22 03:31:13 -05:00
Refactor: Separate escalated items queue
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { useState, useImperativeHandle, forwardRef, useMemo } from 'react';
|
import { useState, useImperativeHandle, forwardRef, useMemo } from 'react';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
|
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
import { useUserRole } from '@/hooks/useUserRole';
|
import { useUserRole } from '@/hooks/useUserRole';
|
||||||
import { useAuth } from '@/hooks/useAuth';
|
import { useAuth } from '@/hooks/useAuth';
|
||||||
@@ -19,7 +20,8 @@ import { AutoRefreshIndicator } from './AutoRefreshIndicator';
|
|||||||
import { NewItemsAlert } from './NewItemsAlert';
|
import { NewItemsAlert } from './NewItemsAlert';
|
||||||
import { EmptyQueueState } from './EmptyQueueState';
|
import { EmptyQueueState } from './EmptyQueueState';
|
||||||
import { QueuePagination } from './QueuePagination';
|
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<ModerationQueueRef>((props, ref) => {
|
export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
@@ -87,6 +89,28 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
{/* Queue Tabs */}
|
||||||
|
<Tabs
|
||||||
|
value={queueManager.filters.activeTab}
|
||||||
|
onValueChange={(value) => queueManager.filters.setActiveTab(value as QueueTab)}
|
||||||
|
className="w-full"
|
||||||
|
>
|
||||||
|
<TabsList className="grid w-full grid-cols-3">
|
||||||
|
<TabsTrigger value="mainQueue" className="flex items-center gap-2">
|
||||||
|
<Clock className="w-4 h-4" />
|
||||||
|
Main Queue
|
||||||
|
</TabsTrigger>
|
||||||
|
<TabsTrigger value="escalated" className="flex items-center gap-2">
|
||||||
|
<AlertTriangle className="w-4 h-4" />
|
||||||
|
Escalated
|
||||||
|
</TabsTrigger>
|
||||||
|
<TabsTrigger value="archive" className="flex items-center gap-2">
|
||||||
|
<Archive className="w-4 h-4" />
|
||||||
|
Archive
|
||||||
|
</TabsTrigger>
|
||||||
|
</TabsList>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
{/* Queue Statistics & Lock Status */}
|
{/* Queue Statistics & Lock Status */}
|
||||||
{queueManager.queue.queueStats && (
|
{queueManager.queue.queueStats && (
|
||||||
<Card className="bg-gradient-to-r from-primary/5 to-primary/10 border-primary/20">
|
<Card className="bg-gradient-to-r from-primary/5 to-primary/10 border-primary/20">
|
||||||
|
|||||||
@@ -238,9 +238,8 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
|||||||
ascending: sort.config.direction === 'asc'
|
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
|
submissionsQuery = submissionsQuery
|
||||||
.order("escalated", { ascending: false })
|
|
||||||
.order(sortField, { ascending: sort.config.direction === 'asc' });
|
.order(sortField, { ascending: sort.config.direction === 'asc' });
|
||||||
|
|
||||||
// Apply tab-based status filtering
|
// Apply tab-based status filtering
|
||||||
@@ -249,6 +248,20 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
|||||||
const entityFilter = filters.debouncedEntityFilter;
|
const entityFilter = filters.debouncedEntityFilter;
|
||||||
|
|
||||||
if (tab === "mainQueue") {
|
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") {
|
if (statusFilter === "all") {
|
||||||
submissionsQuery = submissionsQuery.in("status", ["pending", "flagged", "partially_approved"]);
|
submissionsQuery = submissionsQuery.in("status", ["pending", "flagged", "partially_approved"]);
|
||||||
} else if (statusFilter === "pending") {
|
} else if (statusFilter === "pending") {
|
||||||
@@ -257,6 +270,7 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
|||||||
submissionsQuery = submissionsQuery.eq("status", statusFilter);
|
submissionsQuery = submissionsQuery.eq("status", statusFilter);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// Archive: completed items (non-escalated and escalated)
|
||||||
if (statusFilter === "all") {
|
if (statusFilter === "all") {
|
||||||
submissionsQuery = submissionsQuery.in("status", ["approved", "rejected"]);
|
submissionsQuery = submissionsQuery.in("status", ["approved", "rejected"]);
|
||||||
} else {
|
} else {
|
||||||
@@ -286,6 +300,18 @@ export function useModerationQueueManager(config: ModerationQueueManagerConfig):
|
|||||||
|
|
||||||
// Apply the exact same filters as the main query
|
// Apply the exact same filters as the main query
|
||||||
if (tab === "mainQueue") {
|
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") {
|
if (statusFilter === "all") {
|
||||||
countQuery = countQuery.in("status", ["pending", "flagged", "partially_approved"]);
|
countQuery = countQuery.in("status", ["pending", "flagged", "partially_approved"]);
|
||||||
} else if (statusFilter === "pending") {
|
} else if (statusFilter === "pending") {
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ export type StatusFilter = 'all' | 'pending' | 'partially_approved' | 'flagged'
|
|||||||
/**
|
/**
|
||||||
* Available tabs in the moderation interface
|
* 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
|
* Fields that can be used for sorting the moderation queue
|
||||||
|
|||||||
Reference in New Issue
Block a user