import Layout from "@/components/Layout"; import SEO from "@/components/SEO"; import LoadingScreen from "@/components/LoadingScreen"; import { useAuth } from "@/contexts/AuthContext"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useNavigate } from "react-router-dom"; import { aethexToast } from "@/lib/aethex-toast"; import { aethexUserService, type AethexUserProfile, } from "@/lib/aethex-database-adapter"; import { Card, CardContent, CardHeader, CardTitle, CardDescription, } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import AdminStatCard from "@/components/admin/AdminStatCard"; import AdminMemberManager from "@/components/admin/AdminMemberManager"; import AdminAchievementManager from "@/components/admin/AdminAchievementManager"; import AdminSpotlightManager from "@/components/admin/AdminSpotlightManager"; import AdminStatusOverview from "@/components/admin/AdminStatusOverview"; import AdminChangelogDigest from "@/components/admin/AdminChangelogDigest"; import AdminSystemMap from "@/components/admin/AdminSystemMap"; import AdminMentorshipManager from "@/components/admin/AdminMentorshipManager"; import AdminRoadmap from "@/components/admin/AdminRoadmap"; import { AdminDiscordManagement } from "@/components/admin/AdminDiscordManagement"; import AdminDiscordDiagnostic from "@/components/admin/AdminDiscordDiagnostic"; import BannerSettings from "@/components/admin/BannerSettings"; import { changelogEntries } from "@/pages/Changelog"; import { blogSeedPosts } from "@/data/blogSeed"; import { Shield, Users, Rocket, PenTool, Command, Activity, Settings, ClipboardList, Loader2, BarChart3, Grid3x3, MessageSquare, Gauge, Award, FileText, } from "lucide-react"; type Studio = { name: string; tagline?: string; metrics?: string; specialties?: string[]; }; type ProjectApplication = { id: string; status?: string | null; applicant_email?: string | null; applicant_name?: string | null; created_at?: string | null; notes?: string | null; projects?: { id?: string | null; title?: string | null; user_id?: string | null; } | null; }; type OpportunityApplication = { id: string; type?: string | null; full_name?: string | null; email?: string | null; status?: string | null; availability?: string | null; role_interest?: string | null; primary_skill?: string | null; experience_level?: string | null; submitted_at?: string | null; message?: string | null; }; export default function Admin() { const { user, roles, loading } = useAuth(); const navigate = useNavigate(); // Role-based access: allow "admin" and "staff" roles const hasAdminAccess = roles.includes("admin") || roles.includes("staff"); useEffect(() => { if (!loading && !user) { navigate("/login", { replace: true }); } }, [user, loading, navigate]); const [managedProfiles, setManagedProfiles] = useState( [], ); const [studios, setStudios] = useState([ { name: "Lone Star Studio", tagline: "Indie craftsmanship with AAA polish", metrics: "Top-rated indie hits", specialties: ["Unity", "Unreal", "Pixel Art"], }, { name: "AeThex | GameForge", tagline: "High-performance cross-platform experiences", metrics: "Billions of player sessions", specialties: ["Roblox", "Backend", "LiveOps"], }, { name: "Gaming Control", tagline: "Strategy, simulation, and systems-first design", metrics: "Award-winning franchises", specialties: ["Simulation", "AI/ML", "Economy"], }, ]); const [projectApplications, setProjectApplications] = useState< ProjectApplication[] >([]); const [projectApplicationsLoading, setProjectApplicationsLoading] = useState(false); const [opportunityApplications, setOpportunityApplications] = useState< OpportunityApplication[] >([]); const [opportunityApplicationsLoading, setOpportunityApplicationsLoading] = useState(false); const [selectedMemberId, setSelectedMemberId] = useState(null); const [blogPosts, setBlogPosts] = useState([]); const [loadingPosts, setLoadingPosts] = useState(false); const [activeTab, setActiveTab] = useState("overview"); const loadProfiles = useCallback(async () => { try { const list = await aethexUserService.listProfiles(200); setManagedProfiles(list); } catch (error) { console.warn("Failed to load managed profiles:", error); setManagedProfiles([]); } }, []); useEffect(() => { loadProfiles().catch(() => undefined); }, [loadProfiles]); useEffect(() => { fetch("/api/featured-studios") .then((r) => (r.ok ? r.json() : [])) .then((data) => { if (Array.isArray(data) && data.length) setStudios(data); }) .catch(() => void 0); }, []); const loadProjectApplications = useCallback(async () => { if (!user?.id) return; setProjectApplicationsLoading(true); try { const response = await fetch( `/api/applications?user_id=${encodeURIComponent(user.id)}`, ); if (response.ok) { const data = await response.json(); setProjectApplications(Array.isArray(data) ? data : []); } else { setProjectApplications([]); } } catch (error) { console.warn("Failed to load project applications:", error); setProjectApplications([]); } finally { setProjectApplicationsLoading(false); } }, [user?.id]); useEffect(() => { loadProjectApplications().catch(() => undefined); }, [loadProjectApplications]); const loadOpportunityApplications = useCallback(async () => { const email = user?.email?.toLowerCase(); if (!email) return; setOpportunityApplicationsLoading(true); try { const response = await fetch( `/api/opportunities/applications?email=${encodeURIComponent(email)}`, ); if (response.ok) { const data = await response.json(); setOpportunityApplications(Array.isArray(data) ? data : []); } else { const message = await response.text().catch(() => ""); if (response.status === 403) { aethexToast.error({ title: "Access denied", description: "You must be signed in as an admin or staff member to view opportunity applications.", }); } else { console.warn("Opportunity applications request failed:", message); } setOpportunityApplications([]); } } catch (error) { console.warn("Failed to load opportunity applications:", error); setOpportunityApplications([]); } finally { setOpportunityApplicationsLoading(false); } }, [user?.email]); useEffect(() => { loadOpportunityApplications().catch(() => undefined); }, [loadOpportunityApplications]); useEffect(() => { if (!selectedMemberId && managedProfiles.length) { setSelectedMemberId(managedProfiles[0].id); } }, [managedProfiles, selectedMemberId]); useEffect(() => { (async () => { try { setLoadingPosts(true); const res = await fetch("/api/blog?limit=100"); const data = res.ok ? await res.json() : []; if (Array.isArray(data)) setBlogPosts(data); } catch (e) { console.warn("Failed to load blog posts:", e); } finally { setLoadingPosts(false); } })(); }, []); const resolvedBlogPosts = blogPosts.length ? blogPosts : blogSeedPosts; const selectedMember = useMemo( () => managedProfiles.find((profile) => profile.id === selectedMemberId) ?? null, [managedProfiles, selectedMemberId], ); const totalMembers = managedProfiles.length; const publishedPosts = resolvedBlogPosts.length; const featuredStudios = studios.length; const pendingProjectApplications = projectApplications.filter((app) => { const status = (app.status ?? "").toLowerCase(); return ( status !== "approved" && status !== "completed" && status !== "closed" ); }).length; if (loading) { return ( ); } if (!user || !hasAdminAccess) { return ( <>
Access denied This panel requires admin or staff access. Your current roles: {roles.length ? roles.join(", ") : "none"}.
); } return ( <>

Control Center

Manage platform, users, content, and integrations · Roles:{" "} {roles.join(", ") || "none"}

Overview System Map Roadmap Staff Content Community Mentorship Arm Metrics Discord Operations
Total Members
{totalMembers || "—"}

Active profiles synced

Published Posts
{publishedPosts || "0"}

Blog entries available

Featured Studios
{featuredStudios}

Highlighted partners

Pending Applications
{pendingProjectApplications}

Awaiting review

Quick Actions
Staff Management
Manage AeThex staff, employees, and contractors

Staff management and team collaboration tools are consolidated within the Admin Control Center. Use the tabs above to access team metrics, member management, and community features.

Blog Management
{publishedPosts} published{" "} {publishedPosts === 1 ? "post" : "posts"} ·{" "} {loadingPosts ? "refreshing content…" : "latest Supabase sync"}

Drafts and announcements appear instantly on the public blog after saving.

setSelectedMemberId(id)} onRefresh={loadProfiles} ownerEmail="admin@aethex.tech" />
Labs

Research

12 projects

Team

24 members

GameForge

Games

45 shipped

Players

2.8M MAU

Corp

Clients

34 active

ARR

$4.2M

Foundation

Learners

342 active

Completion

87.5%

Nexus

Creators

1,240 active

Success Rate

68%

Home Banner
Controls the notice shown at the top of the home page
Featured Studios
Control studios highlighted across AeThex
{studios.map((s, i) => (

{s.name}

{s.tagline}

))}
); }