elmeg-demo/frontend/components/admin/nickname-queue.tsx

84 lines
3.2 KiB
TypeScript

"use client"
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"
interface Nickname {
id: number
nickname: string
description: string
performance_id: number
status: string
}
export function NicknameQueue() {
const [nicknames, setNicknames] = useState<Nickname[]>([])
const [loading, setLoading] = useState(true)
const fetchQueue = () => {
const token = localStorage.getItem("token")
if (!token) return
fetch(`${getApiUrl()}/moderation/queue/nicknames`, {
headers: { Authorization: `Bearer ${token}` }
})
.then(res => res.json())
.then(setNicknames)
.catch(console.error)
.finally(() => setLoading(false))
}
useEffect(() => {
fetchQueue()
}, [])
const moderate = (id: number, action: "approve" | "reject") => {
const token = localStorage.getItem("token")
if (!token) return
fetch(`${getApiUrl()}/moderation/nicknames/${id}/${action}`, {
method: "PUT",
headers: { Authorization: `Bearer ${token}` }
}).then(() => {
setNicknames(prev => prev.filter(n => n.id !== id))
})
}
if (loading) return <div>Loading queue...</div>
return (
<div className="space-y-4">
<h2 className="text-xl font-semibold">Pending Nicknames</h2>
{nicknames.length === 0 ? (
<p className="text-muted-foreground">No pending nicknames.</p>
) : (
<div className="grid gap-4">
{nicknames.map((nick) => (
<Card key={nick.id}>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-base font-medium">
"{nick.nickname}"
</CardTitle>
<div className="flex gap-2">
<Button size="sm" variant="outline" className="text-green-600 hover:text-green-700 hover:bg-green-50" onClick={() => moderate(nick.id, "approve")}>
<Check className="h-4 w-4" />
</Button>
<Button size="sm" variant="outline" className="text-red-600 hover:text-red-700 hover:bg-red-50" onClick={() => moderate(nick.id, "reject")}>
<X className="h-4 w-4" />
</Button>
</div>
</CardHeader>
<CardContent>
<p className="text-sm text-muted-foreground">{nick.description}</p>
<p className="text-xs text-muted-foreground mt-2">Performance ID: {nick.performance_id}</p>
</CardContent>
</Card>
))}
</div>
)}
</div>
)
}