From 785509fed9a9a2c1406b6e219fcb44ba4df1a5c5 Mon Sep 17 00:00:00 2001 From: g Date: Fri, 28 Nov 2025 20:14:17 +0000 Subject: [PATCH] Refactor admin ban page to use API and improve UX Replaced mock data in the admin ban page with real API calls for fetching, banning, and unbanning users. Improved form validation, loading states, and search functionality. Updated banned users table to show live data and added confirmation dialogs for ban/unban actions. Enhanced user status display in the admin users page with tooltips for blocked reasons. --- app/dashboard/admin/ban/page.tsx | 453 +++++++++++++++++------------ app/dashboard/admin/users/page.tsx | 37 ++- public/git-info.json | 4 +- 3 files changed, 294 insertions(+), 200 deletions(-) diff --git a/app/dashboard/admin/ban/page.tsx b/app/dashboard/admin/ban/page.tsx index a370064..370fc93 100644 --- a/app/dashboard/admin/ban/page.tsx +++ b/app/dashboard/admin/ban/page.tsx @@ -1,6 +1,6 @@ "use client"; -import React from "react"; +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"; @@ -10,133 +10,200 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@ 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 } from "lucide-react"; -import { useState } from "react"; -import Link from "next/link"; +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 [banData, setBanData] = useState({ - username: "", + telegramUserId: "", reason: "", - duration: "", - description: "" + additionalDetails: "", }); - // Mock data for banned users - const bannedUsers = [ - { - id: "1", - username: "spam_user", - email: "spam@example.com", - reason: "Spam", - bannedBy: "admin1", - banDate: "2024-01-15", - duration: "Permanent", - status: "active" - }, - { - id: "2", - username: "fraud_vendor", - email: "fraud@example.com", - reason: "Fraud", - bannedBy: "admin1", - banDate: "2024-01-20", - duration: "30 days", - status: "active" - }, - { - id: "3", - username: "policy_violator", - email: "violator@example.com", - reason: "Policy Violation", - bannedBy: "admin1", - banDate: "2024-01-25", - duration: "7 days", - status: "expired" - } - ]; + useEffect(() => { + fetchBlockedUsers(); + }, []); - const handleBanUser = () => { - // Handle ban user logic - console.log("Banning user:", banData); + const fetchBlockedUsers = async () => { + try { + setLoading(true); + const data = await fetchClient("/admin/blocked-users"); + setBlockedUsers(data); + } 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 () => { + if (!banData.telegramUserId) { + toast({ + title: "Error", + description: "Telegram User ID is required", + variant: "destructive", + }); + return; + } + + try { + setBanning(true); + await fetchClient("/admin/ban", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + telegramUserId: parseInt(banData.telegramUserId), + reason: banData.additionalDetails || banData.reason || undefined, + }), + }); + + toast({ + title: "Success", + description: "User has been banned", + }); + + setBanData({ telegramUserId: "", reason: "", additionalDetails: "" }); + 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) => { + try { + setUnbanning(telegramUserId.toString()); + await fetchClient(`/admin/ban/${telegramUserId}`, { + method: "DELETE", + }); + + toast({ + title: "Success", + description: "User has been unbanned", + }); + + 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

-
- +
+

Ban Users

+

Manage user bans and suspensions

{/* Stats Cards */} -
+
Active Bans -
12
+
{activeBans}

Currently banned

- Permanent Bans + Total Bans -
3
-

Permanent suspensions

+
{activeBans}
+

All time bans

- Temporary Bans + Recent Bans -
9
-

Time-limited bans

-
-
- - - Appeals Pending - - - -
2
-

Awaiting review

+
+ {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 user details and reason for banning - - - + {/* Ban User Form */} + + + + + Ban User + + + Enter Telegram User ID and reason for banning + + + +
- + setBanData({...banData, username: e.target.value})} + id="telegramUserId" + type="number" + placeholder="Enter Telegram User ID" + value={banData.telegramUserId} + onChange={(e) => setBanData({...banData, telegramUserId: e.target.value})} />
@@ -144,7 +211,7 @@ export default function AdminBanPage() { setBanData({...banData, duration: value})}> - - - - - 1 Day - 7 Days - 30 Days - 90 Days - Permanent - - -
- -
- -