Introduces new admin dashboard pages for alerts, bans, invites, orders, settings, status, and vendors under app/dashboard/admin/. Moves the main admin page to the new dashboard structure and adds a shared admin layout. Updates sidebar configuration and adds supporting components and hooks for admin features.
281 lines
11 KiB
TypeScript
281 lines
11 KiB
TypeScript
import React 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 } from "lucide-react";
|
|
import { useState } from "react";
|
|
|
|
export default function AdminBanPage() {
|
|
const [banData, setBanData] = useState({
|
|
username: "",
|
|
reason: "",
|
|
duration: "",
|
|
description: ""
|
|
});
|
|
|
|
// 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"
|
|
}
|
|
];
|
|
|
|
const handleBanUser = () => {
|
|
// Handle ban user logic
|
|
console.log("Banning user:", banData);
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div>
|
|
<h1 className="text-2xl font-semibold tracking-tight">Ban Users</h1>
|
|
<p className="text-sm text-muted-foreground mt-1">Manage user bans and suspensions</p>
|
|
</div>
|
|
|
|
{/* Stats Cards */}
|
|
<div className="grid gap-4 md:grid-cols-4">
|
|
<Card>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">Active Bans</CardTitle>
|
|
<Shield className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">12</div>
|
|
<p className="text-xs text-muted-foreground">Currently banned</p>
|
|
</CardContent>
|
|
</Card>
|
|
<Card>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">Permanent Bans</CardTitle>
|
|
<UserX className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">3</div>
|
|
<p className="text-xs text-muted-foreground">Permanent suspensions</p>
|
|
</CardContent>
|
|
</Card>
|
|
<Card>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">Temporary Bans</CardTitle>
|
|
<Ban className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">9</div>
|
|
<p className="text-xs text-muted-foreground">Time-limited bans</p>
|
|
</CardContent>
|
|
</Card>
|
|
<Card>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">Appeals Pending</CardTitle>
|
|
<Unlock className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">2</div>
|
|
<p className="text-xs text-muted-foreground">Awaiting review</p>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
<div className="grid gap-6 lg:grid-cols-2">
|
|
{/* Ban User Form */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle className="flex items-center">
|
|
<UserX className="h-5 w-5 mr-2" />
|
|
Ban User
|
|
</CardTitle>
|
|
<CardDescription>
|
|
Enter user details and reason for banning
|
|
</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div className="space-y-2">
|
|
<Label htmlFor="username">Username</Label>
|
|
<Input
|
|
id="username"
|
|
placeholder="Enter username to ban"
|
|
value={banData.username}
|
|
onChange={(e) => setBanData({...banData, username: e.target.value})}
|
|
/>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label htmlFor="reason">Reason</Label>
|
|
<Select value={banData.reason} onValueChange={(value) => setBanData({...banData, reason: value})}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Select ban reason" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="spam">Spam</SelectItem>
|
|
<SelectItem value="fraud">Fraud</SelectItem>
|
|
<SelectItem value="harassment">Harassment</SelectItem>
|
|
<SelectItem value="policy_violation">Policy Violation</SelectItem>
|
|
<SelectItem value="suspicious_activity">Suspicious Activity</SelectItem>
|
|
<SelectItem value="other">Other</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label htmlFor="duration">Duration</Label>
|
|
<Select value={banData.duration} onValueChange={(value) => setBanData({...banData, duration: value})}>
|
|
<SelectTrigger>
|
|
<SelectValue placeholder="Select ban duration" />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
<SelectItem value="1_day">1 Day</SelectItem>
|
|
<SelectItem value="7_days">7 Days</SelectItem>
|
|
<SelectItem value="30_days">30 Days</SelectItem>
|
|
<SelectItem value="90_days">90 Days</SelectItem>
|
|
<SelectItem value="permanent">Permanent</SelectItem>
|
|
</SelectContent>
|
|
</Select>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<Label htmlFor="description">Additional Details</Label>
|
|
<Textarea
|
|
id="description"
|
|
placeholder="Provide additional context for the ban..."
|
|
value={banData.description}
|
|
onChange={(e) => setBanData({...banData, description: e.target.value})}
|
|
/>
|
|
</div>
|
|
|
|
<AlertDialog>
|
|
<AlertDialogTrigger asChild>
|
|
<Button variant="destructive" className="w-full">
|
|
<Ban className="h-4 w-4 mr-2" />
|
|
Ban User
|
|
</Button>
|
|
</AlertDialogTrigger>
|
|
<AlertDialogContent>
|
|
<AlertDialogHeader>
|
|
<AlertDialogTitle>Confirm Ban</AlertDialogTitle>
|
|
<AlertDialogDescription>
|
|
Are you sure you want to ban user "{banData.username}"? This action cannot be undone.
|
|
</AlertDialogDescription>
|
|
</AlertDialogHeader>
|
|
<AlertDialogFooter>
|
|
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
|
<AlertDialogAction onClick={handleBanUser}>
|
|
Confirm Ban
|
|
</AlertDialogAction>
|
|
</AlertDialogFooter>
|
|
</AlertDialogContent>
|
|
</AlertDialog>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
{/* Search Banned Users */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Search Banned Users</CardTitle>
|
|
<CardDescription>Look up existing bans and their status</CardDescription>
|
|
</CardHeader>
|
|
<CardContent className="space-y-4">
|
|
<div className="relative">
|
|
<Search className="absolute left-2 top-2.5 h-4 w-4 text-muted-foreground" />
|
|
<Input placeholder="Search by username or email..." className="pl-8" />
|
|
</div>
|
|
<Button variant="outline" className="w-full">
|
|
Search Bans
|
|
</Button>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
|
|
{/* Banned Users Table */}
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Recent Bans</CardTitle>
|
|
<CardDescription>View and manage current and past bans</CardDescription>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<Table>
|
|
<TableHeader>
|
|
<TableRow>
|
|
<TableHead>User</TableHead>
|
|
<TableHead>Reason</TableHead>
|
|
<TableHead>Duration</TableHead>
|
|
<TableHead>Banned By</TableHead>
|
|
<TableHead>Date</TableHead>
|
|
<TableHead>Status</TableHead>
|
|
<TableHead className="text-right">Actions</TableHead>
|
|
</TableRow>
|
|
</TableHeader>
|
|
<TableBody>
|
|
{bannedUsers.map((user) => (
|
|
<TableRow key={user.id}>
|
|
<TableCell>
|
|
<div>
|
|
<div className="font-medium">{user.username}</div>
|
|
<div className="text-sm text-muted-foreground">{user.email}</div>
|
|
</div>
|
|
</TableCell>
|
|
<TableCell>{user.reason}</TableCell>
|
|
<TableCell>{user.duration}</TableCell>
|
|
<TableCell>{user.bannedBy}</TableCell>
|
|
<TableCell>{user.banDate}</TableCell>
|
|
<TableCell>
|
|
<Badge
|
|
variant={user.status === "active" ? "destructive" : "secondary"}
|
|
>
|
|
{user.status}
|
|
</Badge>
|
|
</TableCell>
|
|
<TableCell className="text-right">
|
|
<div className="flex items-center justify-end space-x-2">
|
|
{user.status === "active" && (
|
|
<Button variant="outline" size="sm">
|
|
<Unlock className="h-4 w-4" />
|
|
</Button>
|
|
)}
|
|
<Button variant="outline" size="sm">
|
|
View Details
|
|
</Button>
|
|
</div>
|
|
</TableCell>
|
|
</TableRow>
|
|
))}
|
|
</TableBody>
|
|
</Table>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|