import { useState, useMemo } from "react"; import { motion } from "framer-motion"; import { Link, useLocation } from "wouter"; import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; import { useAuth } from "@/lib/auth"; import { Users, FileCode, Shield, Activity, LogOut, Home, BarChart3, Settings, User, Search, CheckCircle, XCircle, Eye, Edit, ChevronRight, Download, Trash2, Square, CheckSquare } from "lucide-react"; export default function AdminArchitects() { const { user, logout } = useAuth(); const [, setLocation] = useLocation(); const [searchQuery, setSearchQuery] = useState(""); const [selectedProfile, setSelectedProfile] = useState(null); const [selectedIds, setSelectedIds] = useState>(new Set()); const [roleFilter, setRoleFilter] = useState("all"); const [verifiedFilter, setVerifiedFilter] = useState("all"); const queryClient = useQueryClient(); const { data: profiles, isLoading } = useQuery({ queryKey: ["profiles"], queryFn: async () => { const res = await fetch("/api/profiles"); return res.json(); }, }); const updateProfileMutation = useMutation({ mutationFn: async ({ id, updates }: { id: string; updates: any }) => { const res = await fetch(`/api/profiles/${id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(updates), }); if (!res.ok) throw new Error("Failed to update"); return res.json(); }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["profiles"] }); setSelectedProfile(null); }, }); const filteredProfiles = useMemo(() => { if (!profiles) return []; return profiles.filter((p: any) => { const matchesSearch = p.username?.toLowerCase().includes(searchQuery.toLowerCase()) || p.email?.toLowerCase().includes(searchQuery.toLowerCase()); const matchesRole = roleFilter === "all" || p.role === roleFilter; const matchesVerified = verifiedFilter === "all" || (verifiedFilter === "verified" && p.is_verified) || (verifiedFilter === "unverified" && !p.is_verified); return matchesSearch && matchesRole && matchesVerified; }); }, [profiles, searchQuery, roleFilter, verifiedFilter]); const toggleSelectAll = () => { if (selectedIds.size === filteredProfiles.length) { setSelectedIds(new Set()); } else { setSelectedIds(new Set(filteredProfiles.map((p: any) => p.id))); } }; const toggleSelect = (id: string) => { const newSet = new Set(selectedIds); if (newSet.has(id)) { newSet.delete(id); } else { newSet.add(id); } setSelectedIds(newSet); }; const exportToCSV = () => { const dataToExport = selectedIds.size > 0 ? filteredProfiles.filter((p: any) => selectedIds.has(p.id)) : filteredProfiles; const headers = ["Username", "Email", "Role", "Level", "XP", "Status", "Verified"]; const csvContent = [ headers.join(","), ...dataToExport.map((p: any) => [ p.username || "", p.email || "", p.role || "", p.level || 0, p.total_xp || 0, p.status || "", p.is_verified ? "Yes" : "No" ].join(",")) ].join("\n"); const blob = new Blob([csvContent], { type: "text/csv;charset=utf-8;" }); const link = document.createElement("a"); link.href = URL.createObjectURL(blob); link.download = `architects_${new Date().toISOString().split("T")[0]}.csv`; link.click(); }; const bulkVerify = async (verify: boolean) => { const ids = Array.from(selectedIds); for (const id of ids) { await updateProfileMutation.mutateAsync({ id, updates: { is_verified: verify } }); } setSelectedIds(new Set()); }; const handleLogout = async () => { await logout(); setLocation("/"); }; const toggleVerified = (profile: any) => { updateProfileMutation.mutate({ id: profile.id, updates: { is_verified: !profile.is_verified } }); }; return (
{/* Sidebar */}

AeThex

Command Center

{user?.username}
{user?.isAdmin ? "Administrator" : "Member"}
{/* Main Content */}

Architects

{filteredProfiles.length} of {profiles?.length || 0} architects

setSearchQuery(e.target.value)} className="bg-card border border-white/10 pl-10 pr-4 py-2 text-sm text-white placeholder-muted-foreground focus:border-primary/50 focus:outline-none w-64" data-testid="input-search" />
{selectedIds.size > 0 && (
{selectedIds.size} selected
)} {selectedIds.size === 0 && (
)} {/* Table */}
{isLoading ? ( ) : filteredProfiles.length === 0 ? ( ) : ( filteredProfiles.map((profile: any) => ( )) )}
User Role Level XP Status Verified Actions
Loading...
No architects found
{profile.username}
{profile.username}
{profile.email}
{profile.role} {profile.level} {profile.total_xp} {profile.status}
{/* Profile Detail Modal */} {selectedProfile && (
{selectedProfile.username}

{selectedProfile.username}

{selectedProfile.email}

{selectedProfile.role}
{selectedProfile.level}
{selectedProfile.total_xp}
{selectedProfile.status}
{selectedProfile.aethex_passport_id}
{selectedProfile.is_verified ? 'Yes' : 'No'}
{selectedProfile.bio || 'No bio'}
{selectedProfile.skills?.map((skill: string, i: number) => ( {skill} )) || No skills listed}
)}
); } function NavItem({ icon, label, href, active = false }: { icon: React.ReactNode; label: string; href: string; active?: boolean; }) { return (
{icon} {label}
); }