File size: 5,959 Bytes
ceb943f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7bb5991
ceb943f
 
 
 
7bb5991
 
 
ceb943f
 
7bb5991
 
 
 
 
 
ceb943f
7bb5991
 
 
ceb943f
 
 
7bb5991
 
ceb943f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7bb5991
ceb943f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7bb5991
 
 
 
 
 
 
 
 
 
 
 
 
 
ceb943f
 
 
 
7bb5991
 
ceb943f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
"use client";

import React, { useState } from "react";
import { Card } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { ShieldAlert, Filter, Search, RotateCcw } from "lucide-react";
import { AdminDetectionCard } from "./admin-detection-card";
import { AdminCorrectionModal } from "./admin-correction-modal";
import { AdminMarkIncorrectModal } from "./admin-mark-incorrect-modal";

interface AdminDetection {
    detection: {
        id: string;
        objectName: string;
        category: string;
        confidenceScore: number;
        status: string;
        frameTimestamp: number;
        createdAt: Date;
    };
    video: {
        id: string;
        title: string;
        thumbnailUrl: string;
    };
    channel: {
        creatorId: string;
        channelName: string;
    };
    marketplaceMatches: any[];
    pledgeCount?: number;
}

interface AdminModerationQueueProps {
    initialDetections: AdminDetection[];
    initialMinPledges?: number;
    initialCategory?: string;
    initialMinConfidence?: number;
}

export function AdminModerationQueue({
    initialDetections,
    initialMinPledges = 0,
    initialCategory = "all",
    initialMinConfidence = 0
}: AdminModerationQueueProps) {
    const [detections, setDetections] = useState(initialDetections);
    const [filterCategory, setFilterCategory] = useState<string>(initialCategory);
    const [minConfidence, setMinConfidence] = useState(initialMinConfidence);
    const [minPledges, setMinPledges] = useState(initialMinPledges);

    const filteredDetections = detections.filter(d =>
        (filterCategory === "all" || d.detection.category === filterCategory) &&
        d.detection.confidenceScore >= minConfidence &&
        (d.pledgeCount || 0) >= minPledges
    );

    const categories = Array.from(new Set(initialDetections.map(d => d.detection.category)));

    const removeDetection = (id: string) => {
        setDetections(prev => prev.filter(d => d.detection.id !== id));
    };

    return (
        <div className="space-y-6">
            {/* Filters Bar */}
            <div className="flex flex-col md:flex-row gap-4 items-end justify-between bg-card/50 p-4 rounded-lg border border-border/50 backdrop-blur-sm">
                <div className="flex flex-wrap gap-4 items-center">
                    <div className="space-y-1">
                        <Label>Category</Label>
                        <Select value={filterCategory} onValueChange={setFilterCategory}>
                            <SelectTrigger className="w-[160px]">
                                <SelectValue placeholder="All Categories" />
                            </SelectTrigger>
                            <SelectContent>
                                <SelectItem value="all">All Categories</SelectItem>
                                {categories.map(cat => (
                                    <SelectItem key={cat} value={cat}>{cat}</SelectItem>
                                ))}
                            </SelectContent>
                        </Select>
                    </div>

                    <div className="space-y-1">
                        <Label>Min Confidence ({Math.round(minConfidence * 100)}%)</Label>
                        <Input
                            type="range"
                            min="0"
                            max="1"
                            step="0.05"
                            value={minConfidence}
                            onChange={(e) => setMinConfidence(parseFloat(e.target.value))}
                            className="w-[150px]"
                        />
                    </div>

                    <div className="space-y-1">
                        <Label>Min Pledges ({minPledges})</Label>
                        <Input
                            type="range"
                            min="0"
                            max="20"
                            step="1"
                            value={minPledges}
                            onChange={(e) => setMinPledges(parseInt(e.target.value))}
                            className="w-[150px] accent-emerald-500"
                        />
                    </div>
                </div>

                <Button variant="outline" size="sm" onClick={() => { setFilterCategory("all"); setMinConfidence(0); setMinPledges(0); }}>
                    <RotateCcw className="w-4 h-4 mr-2" /> Reset
                </Button>
            </div>

            {/* Grid */}
            {filteredDetections.length > 0 ? (
                <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
                    {filteredDetections.map((d) => (
                        <AdminDetectionCard
                            key={d.detection.id}
                            detection={d}
                            onActionSuccess={() => removeDetection(d.detection.id)}
                        />
                    ))}
                </div>
            ) : (
                <div className="col-span-full py-20 text-center space-y-4 bg-muted/10 rounded-xl border-2 border-dashed border-border/40">
                    <div className="flex justify-center">
                        <ShieldAlert className="w-12 h-12 text-muted-foreground opacity-20" />
                    </div>
                    <div className="space-y-2">
                        <h3 className="text-xl font-semibold text-muted-foreground">Admin Queue Clear</h3>
                        <p className="text-muted-foreground max-w-xs mx-auto">No flagged items found with current filters. Good job on the quality control!</p>
                    </div>
                </div>
            )}
        </div>
    );
}