contents(admin): tidy the review queue + add gallery screenshots
- Review queue: past verdicts (e.g. the 13 hidden labels from an Aug/Sep cleanup
sweep) are correct but noisy — they buried the items that still need a
decision. They are now COLLAPSED behind a 'Show actioned (N)' toggle, with the
verdicts untouched (still hidden) and 'Undo all N' still available. Verified:
the Spots tab renders 0 hidden cards by default with the toggle + Undo all.
- public/images/screenshots/{map,spot,marketplace}.png (1280x800, quantised) for
the app-listing gallery.
This commit is contained in:
parent
48a27d552d
commit
3051858de7
4 changed files with 32 additions and 3 deletions
BIN
public/images/screenshots/map.png
Normal file
BIN
public/images/screenshots/map.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
BIN
public/images/screenshots/marketplace.png
Normal file
BIN
public/images/screenshots/marketplace.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
BIN
public/images/screenshots/spot.png
Normal file
BIN
public/images/screenshots/spot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 319 KiB |
|
|
@ -125,6 +125,9 @@ function QueueList({
|
|||
const { toast } = useToast();
|
||||
|
||||
const [bulkBusy, setBulkBusy] = useState(false);
|
||||
// Old verdicts (e.g. a cleanup sweep from weeks ago) are correct but noisy —
|
||||
// they must not bury the items that still need a decision.
|
||||
const [showActioned, setShowActioned] = useState(false);
|
||||
const mappers = useMemo(() => [...new Set(rows.map((r) => r.pubkey))], [rows]);
|
||||
const { data: trustScores } = useBatchTrustScores(mappers);
|
||||
const { getCounts } = useSpotReports(rows);
|
||||
|
|
@ -214,6 +217,8 @@ function QueueList({
|
|||
}
|
||||
|
||||
const actioned = prepared.filter((r) => r.actioned);
|
||||
const open = prepared.filter((r) => !r.actioned);
|
||||
const visible = showActioned ? prepared : open;
|
||||
|
||||
const undoAll = async () => {
|
||||
setBulkBusy(true);
|
||||
|
|
@ -235,11 +240,22 @@ function QueueList({
|
|||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
{actioned.length > 1 && (
|
||||
{actioned.length > 0 && (
|
||||
<div className="flex flex-wrap items-center justify-between gap-2 rounded-2xl border border-white/10 bg-white/[0.02] px-4 py-3">
|
||||
<p className="text-xs text-gray-400">
|
||||
{actioned.length} item{actioned.length === 1 ? '' : 's'} hidden or confirmed in this tab.
|
||||
{actioned.length} already actioned in this tab (hidden or confirmed).
|
||||
</p>
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Button
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
className="gap-1.5 text-gray-400 hover:text-white"
|
||||
onClick={() => setShowActioned((v) => !v)}
|
||||
>
|
||||
<EyeOff className="h-3.5 w-3.5" />
|
||||
{showActioned ? 'Hide actioned' : `Show actioned (${actioned.length})`}
|
||||
</Button>
|
||||
{actioned.length > 1 && (
|
||||
<AlertDialog>
|
||||
<AlertDialogTrigger asChild>
|
||||
<Button size="sm" variant="outline" className="gap-1.5 border-white/20" disabled={bulkBusy}>
|
||||
|
|
@ -263,9 +279,22 @@ function QueueList({
|
|||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{prepared.map(({ row, coord, hidden, verified, trust, reports, flags }) => (
|
||||
{visible.length === 0 && (
|
||||
<Card className="border-dashed border-white/10">
|
||||
<CardContent className="space-y-3 py-12 text-center">
|
||||
<CheckCircle2 className="mx-auto h-8 w-8 text-emerald-500" />
|
||||
<p className="text-sm text-gray-400">
|
||||
Nothing waiting on you. {actioned.length} earlier verdict
|
||||
{actioned.length === 1 ? '' : 's'} {actioned.length === 1 ? 'is' : 'are'} hidden above.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
{visible.map(({ row, coord, hidden, verified, trust, reports, flags }) => (
|
||||
<Card
|
||||
key={row.id}
|
||||
className={
|
||||
|
|
|
|||
Loading…
Reference in a new issue