/** * User Management Panel * Complete user administration with roles, tiers, bans */ import { useState } from 'react'; import { useQuery, useMutation } from '@tanstack/react-query'; import { db, supabase } from '../../services/supabase'; import { Users, Search, Shield, Crown, User, Ban, CheckCircle, AlertTriangle, Lock, Unlock, Edit3, Download, RefreshCw, Star, } from 'lucide-react'; const TIERS = ['FREE', 'BASIC', 'PRO', 'ELITE', 'ENTERPRISE']; const ROLES = ['USER', 'ANALYST', 'MODERATOR', 'ADMIN']; export default function UserManagement() { const [searchQuery, setSearchQuery] = useState(''); const [roleFilter, setRoleFilter] = useState('all'); const [tierFilter, setTierFilter] = useState('all'); const [selectedUser, setSelectedUser] = useState(null); const [showEditModal, setShowEditModal] = useState(false); const [showBanModal, setShowBanModal] = useState(false); const [banReason, setBanReason] = useState(''); // Fetch users const { data: users, isLoading, refetch } = useQuery({ queryKey: ['admin-users'], queryFn: async () => { const { data, error } = await db.users.getAll(); if (error) throw error; return data || []; }, }); // Update user mutation const updateUser = useMutation({ mutationFn: async ({ id, updates }: { id: string; updates: any }) => { const { data, error } = await db.users.update(id, updates); if (error) throw error; return data; }, onSuccess: () => { refetch(); setShowEditModal(false); }, }); // Ban user mutation const banUser = useMutation({ mutationFn: async ({ id, reason, duration }: { id: string; reason: string; duration?: number }) => { const { data, error } = await db.users.ban(id, reason, duration); if (error) throw error; return data; }, onSuccess: () => { refetch(); setShowBanModal(false); setBanReason(''); }, }); // Unban user helper const unbanUser = useMutation({ mutationFn: async (id: string) => { const { data, error } = await db.users.unban(id); if (error) throw error; return data; }, onSuccess: () => { refetch(); setShowBanModal(false); }, }); // Reset password mutation - triggers email via Supabase Auth const resetPassword = useMutation({ mutationFn: async (userId: string) => { // Get user email first const { data: user, error: userError } = await db.users.getById(userId); if (userError || !user?.email) throw new Error('User not found'); // Trigger password reset email via Supabase Auth const { error } = await supabase.auth.resetPasswordForEmail(user.email, { redirectTo: `${window.location.origin}/reset-password`, }); if (error) throw error; return { success: true }; }, }); const filteredUsers = users?.filter((u: any) => { const matchesSearch = u.email?.toLowerCase().includes(searchQuery.toLowerCase()) || u.id?.toLowerCase().includes(searchQuery.toLowerCase()); const matchesRole = roleFilter === 'all' || u.role === roleFilter; const matchesTier = tierFilter === 'all' || u.tier === tierFilter; return matchesSearch && matchesRole && matchesTier; }); const stats = { total: users?.length || 0, admins: users?.filter((u: any) => u.role === 'ADMIN').length || 0, analysts: users?.filter((u: any) => u.role === 'ANALYST').length || 0, proUsers: users?.filter((u: any) => ['PRO', 'ELITE', 'ENTERPRISE'].includes(u.tier)).length || 0, banned: users?.filter((u: any) => u.banned).length || 0, }; const getRoleIcon = (role: string) => { switch (role) { case 'ADMIN': return ; case 'MODERATOR': return ; case 'ANALYST': return ; default: return ; } }; const getTierColor = (tier: string) => { switch (tier) { case 'ENTERPRISE': return 'text-purple-400 bg-purple-500/20'; case 'ELITE': return 'text-yellow-400 bg-yellow-500/20'; case 'PRO': return 'text-blue-400 bg-blue-500/20'; case 'BASIC': return 'text-green-400 bg-green-500/20'; default: return 'text-gray-400 bg-gray-500/20'; } }; return (
{/* Header Stats */}
{/* Filters */}
setSearchQuery(e.target.value)} className="w-full bg-crypto-dark border border-crypto-border rounded-lg pl-10 pr-4 py-2 text-white" />
{/* Users Table */}
{isLoading ? (
Loading users...
) : (
{filteredUsers?.map((user: any) => ( ))}
User Role Tier Reputation Joined Last Active Status Actions
{user.email?.charAt(0).toUpperCase()}

{user.email}

{user.id?.slice(0, 8)}...

{getRoleIcon(user.role)} {user.role}
{user.tier}
{user.reputation_score || 0}
{new Date(user.created_at).toLocaleDateString()} {user.last_active ? new Date(user.last_active).toLocaleDateString() : 'Never'} {user.banned ? ( Banned ) : user.email_confirmed ? ( Active ) : ( Unconfirmed )}
)}
{/* Edit User Modal */} {showEditModal && selectedUser && (

Edit User

{selectedUser.email}

{selectedUser.id}

{ e.preventDefault(); const formData = new FormData(e.currentTarget); updateUser.mutate({ id: selectedUser.id, updates: { role: formData.get('role'), tier: formData.get('tier'), reputation_score: parseInt(formData.get('reputation') as string), }, }); }} className="space-y-4" >
)} {/* Ban User Modal */} {showBanModal && selectedUser && (

{selectedUser.banned ? 'Unban User' : 'Ban User'}

{selectedUser.email}

ID: {selectedUser.id}

{!selectedUser.banned && (