From 037d2aa46343723f773748961c6fc8b28b596b9d Mon Sep 17 00:00:00 2001 From: fullsizemalt <106900403+fullsizemalt@users.noreply.github.com> Date: Wed, 24 Dec 2025 13:04:35 -0800 Subject: [PATCH] feat: enhance Nickname Queue with status filtering --- backend/routers/moderation.py | 12 +- frontend/components/admin/nickname-queue.tsx | 145 ++++++++++++++----- 2 files changed, 116 insertions(+), 41 deletions(-) diff --git a/backend/routers/moderation.py b/backend/routers/moderation.py index 79a4c09..c0d352c 100644 --- a/backend/routers/moderation.py +++ b/backend/routers/moderation.py @@ -267,10 +267,14 @@ def create_report( return db_report @router.get("/queue/nicknames", response_model=List[PerformanceNicknameRead], dependencies=[Depends(allow_moderator)]) -def get_pending_nicknames(session: Session = Depends(get_session)): - nicknames = session.exec( - select(PerformanceNickname).where(PerformanceNickname.status == "pending") - ).all() +def get_pending_nicknames( + status: str = "pending", + session: Session = Depends(get_session) +): + query = select(PerformanceNickname) + if status in ("pending", "approved", "rejected"): + query = query.where(PerformanceNickname.status == status) + nicknames = session.exec(query.limit(100)).all() return nicknames @router.put("/nicknames/{nickname_id}/{action}", response_model=PerformanceNicknameRead, dependencies=[Depends(allow_moderator)]) diff --git a/frontend/components/admin/nickname-queue.tsx b/frontend/components/admin/nickname-queue.tsx index 702cd9a..3c2f3f8 100644 --- a/frontend/components/admin/nickname-queue.tsx +++ b/frontend/components/admin/nickname-queue.tsx @@ -4,7 +4,10 @@ import { useEffect, useState } from "react" import { getApiUrl } from "@/lib/api-config" import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" -import { Check, X } from "lucide-react" +import { Badge } from "@/components/ui/badge" +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" +import { Check, X, Clock, ExternalLink } from "lucide-react" +import Link from "next/link" interface Nickname { id: number @@ -12,28 +15,34 @@ interface Nickname { description: string performance_id: number status: string + song_title?: string + song_slug?: string + show_date?: string + suggested_by_username?: string } export function NicknameQueue() { const [nicknames, setNicknames] = useState([]) const [loading, setLoading] = useState(true) + const [activeTab, setActiveTab] = useState("pending") - const fetchQueue = () => { + const fetchQueue = (status: string = "pending") => { const token = localStorage.getItem("token") if (!token) return - fetch(`${getApiUrl()}/moderation/queue/nicknames`, { + setLoading(true) + fetch(`${getApiUrl()}/moderation/queue/nicknames?status=${status}`, { headers: { Authorization: `Bearer ${token}` } }) .then(res => res.json()) - .then(setNicknames) + .then(data => setNicknames(Array.isArray(data) ? data : [])) .catch(console.error) .finally(() => setLoading(false)) } useEffect(() => { - fetchQueue() - }, []) + fetchQueue(activeTab) + }, [activeTab]) const moderate = (id: number, action: "approve" | "reject") => { const token = localStorage.getItem("token") @@ -47,38 +56,100 @@ export function NicknameQueue() { }) } - if (loading) return
Loading queue...
+ const getStatusBadge = (status: string) => { + switch (status) { + case "approved": + return Approved + case "rejected": + return Rejected + default: + return Pending + } + } + + const renderNicknameCard = (nick: Nickname) => ( + + +
+ + "{nick.nickname}" + + {nick.song_title && ( + + {nick.song_title} + + + )} +
+
+ {getStatusBadge(nick.status)} + {nick.status === "pending" && ( +
+ + +
+ )} +
+
+ + {nick.description && ( +

{nick.description}

+ )} +
+ {nick.show_date && {nick.show_date}} + {nick.suggested_by_username && ( + Suggested by: {nick.suggested_by_username} + )} +
+
+
+ ) return ( -
-

Pending Nicknames

- {nicknames.length === 0 ? ( -

No pending nicknames.

- ) : ( -
- {nicknames.map((nick) => ( - - - - "{nick.nickname}" - -
- - -
-
- -

{nick.description}

-

Performance ID: {nick.performance_id}

-
-
- ))} -
- )} -
+ + + + + Pending + + + + Approved + + + + Rejected + + + + + {loading ? ( +
Loading...
+ ) : nicknames.length === 0 ? ( +

No {activeTab} nicknames.

+ ) : ( +
+ {nicknames.map(renderNicknameCard)} +
+ )} +
+
) }