"use client"; import React, { useState, useEffect } from "react"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; import { Textarea } from "@/components/ui/textarea"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { Badge } from "@/components/ui/badge"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog"; import { UserX, Shield, Search, Ban, Unlock, Loader2 } from "lucide-react"; import { fetchClient } from "@/lib/api-client"; import { useToast } from "@/hooks/use-toast"; interface BlockedUser { _id: string; telegramUserId: number; reason?: string; blockedBy?: { _id: string; username: string; }; blockedAt: string; } export default function AdminBanPage() { const { toast } = useToast(); const [loading, setLoading] = useState(true); const [banning, setBanning] = useState(false); const [unbanning, setUnbanning] = useState(null); const [blockedUsers, setBlockedUsers] = useState([]); const [searchQuery, setSearchQuery] = useState(""); const [banDialogOpen, setBanDialogOpen] = useState(false); const [page, setPage] = useState(1); const [pagination, setPagination] = useState<{ page: number; limit: number; total: number; totalPages: number; hasNextPage: boolean; hasPrevPage: boolean; } | null>(null); const [banData, setBanData] = useState({ telegramUserId: "", reason: "", additionalDetails: "", }); useEffect(() => { fetchBlockedUsers(); }, [page]); const fetchBlockedUsers = async () => { try { setLoading(true); const data = await fetchClient<{ success: boolean; blockedUsers: BlockedUser[]; pagination: { page: number; limit: number; total: number; totalPages: number; hasNextPage: boolean; hasPrevPage: boolean; }; }>(`/admin/blocked-users?page=${page}&limit=25`); setBlockedUsers(data.blockedUsers); setPagination(data.pagination); } catch (error) { console.error("Failed to fetch blocked users:", error); toast({ title: "Error", description: "Failed to load blocked users", variant: "destructive", }); } finally { setLoading(false); } }; const handleBanUser = async (e?: React.MouseEvent) => { e?.preventDefault(); e?.stopPropagation(); if (!banData.telegramUserId) { toast({ title: "Error", description: "Telegram User ID is required", variant: "destructive", }); return; } try { setBanning(true); const response = await fetchClient("/admin/ban", { method: "POST", body: { telegramUserId: parseInt(banData.telegramUserId), reason: banData.additionalDetails || banData.reason || undefined, }, }); toast({ title: "Success", description: "User has been banned", }); setBanData({ telegramUserId: "", reason: "", additionalDetails: "" }); setBanDialogOpen(false); await fetchBlockedUsers(); } catch (error: any) { console.error("Failed to ban user:", error); toast({ title: "Error", description: error.message || "Failed to ban user", variant: "destructive", }); } finally { setBanning(false); } }; const handleUnbanUser = async (telegramUserId: number, e?: React.MouseEvent) => { e?.preventDefault(); e?.stopPropagation(); try { setUnbanning(telegramUserId.toString()); await fetchClient(`/admin/ban/${telegramUserId}`, { method: "DELETE", }); toast({ title: "Success", description: "User has been unbanned", }); await fetchBlockedUsers(); } catch (error: any) { console.error("Failed to unban user:", error); toast({ title: "Error", description: error.message || "Failed to unban user", variant: "destructive", }); } finally { setUnbanning(null); } }; const filteredUsers = blockedUsers.filter((user) => { if (!searchQuery) return true; const query = searchQuery.toLowerCase(); return ( user.telegramUserId.toString().includes(query) || user.reason?.toLowerCase().includes(query) || user.blockedBy?.username?.toLowerCase().includes(query) ); }); const activeBans = blockedUsers.length; return (

Ban Users

Manage user bans and suspensions

{/* Stats Cards */}
Active Bans
{activeBans}

Currently banned

Total Bans
{activeBans}

All time bans

Recent Bans
{blockedUsers.filter( (u) => new Date(u.blockedAt) > new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) ).length}

Last 7 days

{/* Ban User Form */} Ban User Enter Telegram User ID and reason for banning
setBanData({...banData, telegramUserId: e.target.value})} />
setBanData({...banData, additionalDetails: e.target.value})} />
{ if (!banning) { setBanDialogOpen(open); } }} > Confirm Ban Are you sure you want to ban Telegram User ID "{banData.telegramUserId}"? This action can be reversed later. Cancel { e.preventDefault(); handleBanUser(e); }} disabled={banning} className="bg-destructive text-destructive-foreground hover:bg-destructive/90" > {banning ? ( <> Banning... ) : ( "Confirm Ban" )}
{/* Banned Users Table */}
Banned Users View and manage current bans
setSearchQuery(e.target.value)} />
{loading ? (
) : ( Telegram User ID Reason Banned By Date Actions {filteredUsers.length === 0 ? ( {searchQuery ? "No users found matching your search" : "No banned users"} ) : ( filteredUsers.map((user) => (
{user.telegramUserId}
{user.reason ? ( {user.reason} ) : ( No reason provided )} {user.blockedBy?.username || "Unknown"} {new Date(user.blockedAt).toLocaleDateString()} Confirm Unban Are you sure you want to unban Telegram User ID "{user.telegramUserId}"? They will be able to use the platform again. Cancel handleUnbanUser(user.telegramUserId, e)} disabled={unbanning === user.telegramUserId.toString()} > {unbanning === user.telegramUserId.toString() ? ( <> Unbanning... ) : ( "Confirm Unban" )}
)) )}
)} {pagination && pagination.totalPages > 1 && (
Showing page {pagination.page} of {pagination.totalPages} ({pagination.total} total)
)}
); }