import Layout from "@/components/Layout"; import LoadingScreen from "@/components/LoadingScreen"; import { useAuth } from "@/contexts/AuthContext"; import { useEffect, useState } from "react"; import { ensureDemoSeed } from "@/lib/demo-feed"; import { isSupabaseConfigured } from "@/lib/supabase"; import { useNavigate } from "react-router-dom"; import { aethexToast } from "@/lib/aethex-toast"; import { Card, CardContent, CardHeader, CardTitle, CardDescription, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Shield, UserCog, Rocket, Settings, Users, Activity, } from "lucide-react"; export default function Admin() { const { user, loading, roles } = useAuth(); const navigate = useNavigate(); const isOwner = Array.isArray(roles) && roles.includes("owner"); const [demoProfiles, setDemoProfiles] = useState([]); type Studio = { name: string; tagline?: string; metrics?: string; specialties?: string[]; }; 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"], }, ]); useEffect(() => { try { if (!isSupabaseConfigured) { ensureDemoSeed(); const list = JSON.parse(localStorage.getItem("demo_profiles") || "[]"); setDemoProfiles(Array.isArray(list) ? list : []); } else { setDemoProfiles([]); } } catch { setDemoProfiles([]); } fetch("/api/featured-studios") .then((r) => (r.ok ? r.json() : [])) .then((data) => { if (Array.isArray(data) && data.length) setStudios(data); }) .catch(() => void 0); }, []); useEffect(() => { if (!loading) { if (!user) { navigate("/login", { replace: true }); } } }, [user, loading, navigate]); if (loading || !user) { return ( ); } if (!isOwner) { return (
Access Denied You dont have permission to access the admin panel.
); } const [blogPosts, setBlogPosts] = useState([]); const [loadingPosts, setLoadingPosts] = useState(false); 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 savePost = async (idx: number) => { const p = blogPosts[idx]; const payload = { ...p, slug: (p.slug || p.title || "") .toLowerCase() .trim() .replace(/[^a-z0-9\s-]/g, "") .replace(/\s+/g, "-"), }; const res = await fetch("/api/blog", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload), }); if (!res.ok) return aethexToast.error({ title: "Save failed", description: await res.text().catch(() => ""), }); const saved = await res.json(); const next = blogPosts.slice(); next[idx] = saved; setBlogPosts(next); aethexToast.success({ title: "Saved", description: saved.title }); }; const deletePost = async (idx: number) => { const p = blogPosts[idx]; const res = await fetch(`/api/blog/${encodeURIComponent(p.slug)}`, { method: "DELETE", }); if (!res.ok) return aethexToast.error({ title: "Delete failed", description: await res.text().catch(() => ""), }); setBlogPosts(blogPosts.filter((_, i) => i !== idx)); aethexToast.info({ title: "Deleted", description: p.title }); }; return (

Admin Panel

Site Owner • Admin • Founder

Site Owner Admin Founder
Access Control
Owner-only access is enforced by email
  • Owner:{" "} mrpiglr@gmail.com
  • All other users are denied access
Users & Roles
Future: manage roles, invitations, and status

Coming soon

{/* Blog Posts Management */}
Blog Posts
Manage blog content stored in Supabase
{blogPosts.map((p, i) => (
{ const next = blogPosts.slice(); next[i] = { ...next[i], title: e.target.value }; setBlogPosts(next); }} /> { const next = blogPosts.slice(); next[i] = { ...next[i], slug: e.target.value }; setBlogPosts(next); }} />
{ const n = blogPosts.slice(); n[i] = { ...n[i], author: e.target.value }; setBlogPosts(n); }} /> { const n = blogPosts.slice(); n[i] = { ...n[i], date: e.target.value }; setBlogPosts(n); }} />
{ const n = blogPosts.slice(); n[i] = { ...n[i], read_time: e.target.value }; setBlogPosts(n); }} /> { const n = blogPosts.slice(); n[i] = { ...n[i], category: e.target.value }; setBlogPosts(n); }} /> { const n = blogPosts.slice(); n[i] = { ...n[i], image: e.target.value }; setBlogPosts(n); }} />