import { useState } from "react";
/* ββ Platform Data ββ */
const PLATFORM = { name: "DanceChamp", version: "1.0 MVP", totalRevenue: "12,450 BYN" };
const ORGS_DATA = [
{ id: "o1", name: "Zero Gravity Team", instagram: "@zerogravity_pole", logo: "π", status: "active", joined: "Jan 15, 2026", champsCount: 2, membersCount: 24, city: "Minsk", email: "team@zerogravity.by", verified: true },
{ id: "o2", name: "Pole Universe", instagram: "@pole_universe", logo: "π", status: "active", joined: "Feb 2, 2026", champsCount: 1, membersCount: 12, city: "Moscow", email: "info@poleuniverse.ru", verified: true },
{ id: "o3", name: "Sky Pole Studio", instagram: "@sky_pole", logo: "βοΈ", status: "pending", joined: "Feb 20, 2026", champsCount: 0, membersCount: 0, city: "St. Petersburg", email: "hello@skypole.ru", verified: false },
{ id: "o4", name: "Dance Flames", instagram: "@dance_flames", logo: "π₯", status: "blocked", joined: "Dec 10, 2025", champsCount: 1, membersCount: 5, city: "Kyiv", email: "admin@danceflames.ua", verified: false, blockReason: "Fake organization β no real events" },
];
const CHAMPS_DATA = [
{ id: "c1", orgId: "o1", orgName: "Zero Gravity Team", name: "Zero Gravity", dates: "May 30, 2026", location: "Minsk", status: "live", members: 24, passed: 8, pending: 8, revenue: "4,200 BYN", orgVerified: true },
{ id: "c2", orgId: "o1", orgName: "Zero Gravity Team", name: "Pole Star", dates: "Jul 12, 2026", location: "Moscow", status: "draft", members: 1, passed: 0, pending: 0, revenue: "0", orgVerified: true },
{ id: "c3", orgId: "o2", orgName: "Pole Universe", name: "Galactic Pole", dates: "Sep 15, 2026", location: "Moscow", status: "live", members: 12, passed: 0, pending: 12, revenue: "1,800 BYN", orgVerified: true },
{ id: "c4", orgId: "o3", orgName: "Sky Pole Studio", name: "Sky Open", dates: "Oct 5, 2026", location: "St. Petersburg", status: "pending_approval", members: 0, passed: 0, pending: 0, revenue: "0", orgVerified: false },
{ id: "c5", orgId: "o4", orgName: "Dance Flames", name: "Fire Cup", dates: "Mar 1, 2026", location: "Kyiv", status: "blocked", members: 5, passed: 0, pending: 0, revenue: "250 BYN", orgVerified: false },
];
const USERS_DATA = [
{ id: "u1", name: "Alex Petrova", instagram: "@alex_pole", email: "alex@mail.ru", city: "Moscow", joined: "Jan 20, 2026", champsJoined: 2, status: "active", role: "member" },
{ id: "u2", name: "Maria Ivanova", instagram: "@maria_exotic", email: "maria@gmail.com", city: "Minsk", joined: "Jan 22, 2026", champsJoined: 1, status: "active", role: "member" },
{ id: "u3", name: "Elena Kozlova", instagram: "@elena.pole", email: "elena@ya.ru", city: "St. Petersburg", joined: "Feb 1, 2026", champsJoined: 1, status: "active", role: "member" },
{ id: "u4", name: "Daria Sokolova", instagram: "@daria_art", email: "daria@mail.ru", city: "Kyiv", joined: "Feb 5, 2026", champsJoined: 1, status: "active", role: "member" },
{ id: "u5", name: "Anna Belova", instagram: "@anna.b_pole", email: "anna@gmail.com", city: "Minsk", joined: "Feb 10, 2026", champsJoined: 1, status: "active", role: "member" },
{ id: "u6", name: "Olga Morozova", instagram: "@olga_exotic", email: "olga@mail.ru", city: "Moscow", joined: "Feb 12, 2026", champsJoined: 3, status: "warned", role: "member", warnReason: "Disputed payment β under review" },
{ id: "u7", name: "Ivan Petrov", instagram: "@ivan_admin", email: "ivan@zerogravity.by", city: "Minsk", joined: "Jan 10, 2026", champsJoined: 0, status: "active", role: "org_admin", org: "Zero Gravity Team" },
{ id: "u8", name: "Spam Bot", instagram: "@totally_real", email: "spam@fake.com", city: "Unknown", joined: "Feb 22, 2026", champsJoined: 0, status: "blocked", role: "member", blockReason: "Spam account" },
];
const LOGS_DATA = [
{ id: "l1", action: "Org approved & verified", target: "Pole Universe", by: "Admin", date: "Feb 2, 2026", type: "org" },
{ id: "l2", action: "User blocked", target: "Spam Bot", by: "Admin", date: "Feb 22, 2026", type: "user" },
{ id: "l3", action: "Org blocked", target: "Dance Flames", by: "Admin", date: "Feb 23, 2026", type: "org" },
{ id: "l4", action: "Champ auto-approved (verified org)", target: "Zero Gravity", by: "System", date: "Feb 1, 2026", type: "champ" },
{ id: "l5", action: "User warned", target: "Olga Morozova", by: "Admin", date: "Feb 20, 2026", type: "user" },
{ id: "l6", action: "New org registered (pending)", target: "Sky Pole Studio", by: "System", date: "Feb 20, 2026", type: "org" },
{ id: "l7", action: "Champ submitted for review", target: "Sky Open", by: "Sky Pole Studio", date: "Feb 21, 2026", type: "champ" },
];
/* ββ Theme (admin = darker, more neutral accent) ββ */
const c = { bg: "#07060C", card: "#111019", cardH: "#18172290", brd: "#1D1C2B", text: "#F2F0FA", dim: "#5E5C72", mid: "#8F8DA6", accent: "#6366F1", accentS: "rgba(99,102,241,0.10)", green: "#10B981", greenS: "rgba(16,185,129,0.10)", yellow: "#F59E0B", yellowS: "rgba(245,158,11,0.10)", purple: "#8B5CF6", purpleS: "rgba(139,92,246,0.10)", blue: "#60A5FA", blueS: "rgba(96,165,250,0.10)", red: "#EF4444", redS: "rgba(239,68,68,0.10)", orange: "#F97316", orangeS: "rgba(249,115,22,0.10)" };
const f = { d: "'Playfair Display',Georgia,serif", b: "'DM Sans','Segoe UI',sans-serif", m: "'JetBrains Mono',monospace" };
/* ββ Shared UI ββ */
const Cd = ({ children, style: s }) =>
{children}
;
const ST = ({ children, right }) => {children}
{right};
const Bg = ({ label, color, bg }) => {label};
const statusConfig = {
active: { l: "ACTIVE", c: c.green, b: c.greenS }, live: { l: "LIVE", c: c.green, b: c.greenS },
pending: { l: "PENDING", c: c.yellow, b: c.yellowS }, pending_approval: { l: "AWAITING REVIEW", c: c.orange, b: c.orangeS },
draft: { l: "DRAFT", c: c.dim, b: `${c.dim}15` },
blocked: { l: "BLOCKED", c: c.red, b: c.redS }, warned: { l: "WARNED", c: c.orange, b: c.orangeS },
};
function Hdr({ title, subtitle, onBack, right }) {
return
{onBack &&
β
}
{title}
{subtitle &&
{subtitle}
}
{right}
;
}
function Nav({ active, onChange }) {
return
{[{ id: "dash", i: "π", l: "Overview" }, { id: "orgs", i: "π’", l: "Orgs" }, { id: "champs", i: "π", l: "Champs" }, { id: "users", i: "π₯", l: "Users" }].map(x =>
onChange(x.id)} style={{ display: "flex", flexDirection: "column", alignItems: "center", gap: 2, cursor: "pointer", opacity: active === x.id ? 1 : 0.35 }}>{x.i}{x.l}
)}
;
}
function SearchBar({ value, onChange, placeholder }) {
return
π
onChange(e.target.value)} style={{ background: "transparent", border: "none", outline: "none", color: c.text, fontFamily: f.b, fontSize: 13, width: "100%" }} />
;
}
function FilterChips({ filters, active, onChange, accent }) {
return
{filters.map(fi =>
onChange(fi.id)} style={{ fontFamily: f.m, fontSize: 9, fontWeight: 600, whiteSpace: "nowrap", color: active === fi.id ? accent || c.accent : c.dim, background: active === fi.id ? `${accent || c.accent}15` : "transparent", border: `1px solid ${active === fi.id ? `${accent || c.accent}30` : "transparent"}`, padding: "5px 10px", borderRadius: 16, cursor: "pointer" }}>{fi.l}{fi.n !== undefined ? ` (${fi.n})` : ""}
)}
;
}
function ActionBtn({ label, color, onClick, icon, filled }) {
return
{icon && {icon}}
{label}
;
}
/* ββ Dashboard ββ */
function Dashboard({ orgs, champs, users, onNav }) {
const pendingOrgs = orgs.filter(o => o.status === "pending").length;
const pendingChamps = champs.filter(c2 => c2.status === "pending_approval").length;
const blockedUsers = users.filter(u => u.status === "blocked").length;
return
β‘
} />
{/* Platform stats */}
{[{ n: orgs.filter(o => o.status === "active").length, l: "Orgs", co: c.accent, go: "orgs" },
{ n: champs.filter(c2 => c2.status === "live").length, l: "Live Champs", co: c.green, go: "champs" },
{ n: users.length, l: "Users", co: c.blue, go: "users" },
].map(s =>
onNav(s.go)} style={{ flex: 1, background: c.card, border: `1px solid ${c.brd}`, borderRadius: 12, padding: "10px 6px", textAlign: "center", cursor: "pointer" }}>
{s.n}
{s.l}
)}
{/* Needs attention */}
{(pendingOrgs > 0 || pendingChamps > 0) &&
}>β‘ Needs Attention
{pendingOrgs > 0 && onNav("orgs")} style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 0", borderBottom: `1px solid ${c.brd}`, cursor: "pointer" }}>
π’
Organizations awaiting approval
{pendingOrgs}
βΊ
}
{pendingChamps > 0 && onNav("champs")} style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 0", cursor: "pointer" }}>
π
Champs awaiting approval (unverified orgs)
{pendingChamps}
βΊ
}
}
{/* Quick stats */}
Platform Health
{[{ l: "Total revenue", v: PLATFORM.totalRevenue, co: c.green },
{ l: "Active orgs", v: `${orgs.filter(o => o.status === "active").length}/${orgs.length}`, co: c.accent },
{ l: "Blocked users", v: `${blockedUsers}`, co: blockedUsers > 0 ? c.red : c.green },
{ l: "Avg members/champ", v: Math.round(users.filter(u => u.role === "member").length / Math.max(champs.filter(c2 => c2.status === "live").length, 1)), co: c.blue },
].map(s =>
{s.l}
{s.v}
)}
{/* Recent activity */}
{LOGS_DATA.length} entries}>Recent Activity
{LOGS_DATA.slice(0, 5).map(log => {
const tc = { org: c.accent, user: c.blue, champ: c.green }[log.type] || c.dim;
return
{log.action}: {log.target}
{log.date} Β· {log.by}
;
})}
;
}
/* ββ Organizations ββ */
function OrgsList({ orgs, onOrgTap }) {
const [search, setSearch] = useState("");
const [filter, setFilter] = useState("all");
const filters = [
{ id: "all", l: "All", n: orgs.length },
{ id: "active", l: "β
Active", n: orgs.filter(o => o.status === "active").length },
{ id: "pending", l: "β³ Pending", n: orgs.filter(o => o.status === "pending").length },
{ id: "blocked", l: "π« Blocked", n: orgs.filter(o => o.status === "blocked").length },
];
const filtered = orgs.filter(o => {
const q = !search || o.name.toLowerCase().includes(search.toLowerCase()) || o.instagram.toLowerCase().includes(search.toLowerCase());
if (!q) return false;
if (filter === "active") return o.status === "active";
if (filter === "pending") return o.status === "pending";
if (filter === "blocked") return o.status === "blocked";
return true;
});
return
{filtered.map(o => {
const st = statusConfig[o.status] || statusConfig.active;
return
onOrgTap(o)} style={{ background: c.card, border: `1px solid ${c.brd}`, borderRadius: 14, padding: 14, cursor: "pointer" }}>
π {o.city}
π {o.champsCount} champs
π₯ {o.membersCount} members
;
})}
;
}
/* ββ Org Detail ββ */
function OrgDetail({ org: initial, onBack, champs }) {
const [o, setO] = useState(initial);
const st = statusConfig[o.status] || statusConfig.active;
const orgChamps = champs.filter(c2 => c2.orgId === o.id);
return
{/* Profile */}
{o.logo}
{o.name}
{o.instagram}
π {o.city} Β· π§ {o.email}
{/* Info */}
Details
{[{ l: "Joined", v: o.joined }, { l: "Championships", v: o.champsCount }, { l: "Total members", v: o.membersCount }, { l: "Verified", v: o.verified ? "β
Yes" : "β No" }].map(r =>
{r.l}
{r.v}
)}
{/* Approval policy */}
{o.verified ? "π‘οΈ" : "β³"}
{o.verified ? "Verified β Auto-approve events" : "Unverified β Events need manual approval"}
{o.verified ? "Championships go live instantly when org clicks 'Go Live'" : "Admin must review & approve each championship before it becomes visible"}
{/* Championships */}
{orgChamps.length > 0 &&
{orgChamps.length}}>Championships
{orgChamps.map(ch => {
const cs = statusConfig[ch.status] || statusConfig.draft;
return
{ch.name}
{ch.dates} Β· {ch.location}
;
})}
}
{/* Block reason */}
{o.blockReason &&
Block Reason
{o.blockReason}
}
{/* Actions */}
{o.status === "pending" &&
setO(p => ({ ...p, status: "active", verified: true }))} icon="β
" filled />
setO(p => ({ ...p, status: "blocked", blockReason: "Rejected by admin" }))} icon="β" filled />
}
{o.status === "active" &&
setO(p => ({ ...p, status: "blocked", blockReason: "Blocked by admin" }))} icon="π«" />}
{o.status === "blocked" && setO(p => ({ ...p, status: "active", blockReason: null }))} icon="β
" />}
{!o.verified && o.status !== "blocked" && setO(p => ({ ...p, verified: true }))} icon="π‘οΈ" />}
{}} icon="ποΈ" />
;
}
/* ββ Championships ββ */
function ChampsList({ champs, onChampTap }) {
const [search, setSearch] = useState("");
const [filter, setFilter] = useState("all");
const filters = [
{ id: "all", l: "All", n: champs.length },
{ id: "live", l: "π’ Live", n: champs.filter(c2 => c2.status === "live").length },
{ id: "pending_approval", l: "β³ Awaiting", n: champs.filter(c2 => c2.status === "pending_approval").length },
{ id: "draft", l: "π Draft", n: champs.filter(c2 => c2.status === "draft").length },
{ id: "blocked", l: "π« Blocked", n: champs.filter(c2 => c2.status === "blocked").length },
];
const filtered = champs.filter(ch => {
const q = !search || ch.name.toLowerCase().includes(search.toLowerCase()) || ch.orgName.toLowerCase().includes(search.toLowerCase());
if (!q) return false;
if (filter !== "all") return ch.status === filter;
return true;
});
return
{filtered.map(ch => {
const st = statusConfig[ch.status] || statusConfig.draft;
return
onChampTap(ch)} style={{ background: c.card, border: `1px solid ${c.brd}`, borderRadius: 14, padding: 14, cursor: "pointer" }}>
{ch.name}
by {ch.orgName} {ch.orgVerified ? "π‘οΈ" : ""}
π
{ch.dates}
π {ch.location}
π₯ {ch.members}
;
})}
;
}
/* ββ Championship Detail ββ */
function ChampDetail({ ch: initial, onBack }) {
const [ch, setCh] = useState(initial);
const st = statusConfig[ch.status] || statusConfig.draft;
return
π
{ch.name}
{ch.orgName}
π
{ch.dates} Β· π {ch.location}
Stats
{[{ l: "Members", v: ch.members }, { l: "Passed", v: ch.passed }, { l: "Pending", v: ch.pending }, { l: "Revenue", v: ch.revenue }].map(r =>
{r.l}
{r.v}
)}
{/* Approval info */}
{ch.orgVerified !== undefined &&
Approval Policy
{ch.orgVerified ? "π‘οΈ" : "β³"}
{ch.orgVerified ? "Verified org β auto-approved" : "Unverified org β manual review required"}
{ch.orgVerified ? "This org can go live without admin approval" : "Admin must approve before members can see this event"}
}
{ch.status === "pending_approval" &&
setCh(p => ({ ...p, status: "live" }))} icon="β
" filled />
setCh(p => ({ ...p, status: "blocked" }))} icon="β" filled />
}
{ch.status === "live" &&
setCh(p => ({ ...p, status: "blocked" }))} icon="βΈοΈ" />}
{ch.status === "blocked" && setCh(p => ({ ...p, status: "live" }))} icon="β
" />}
{}} icon="ποΈ" />
;
}
/* ββ Users ββ */
function UsersList({ users, onUserTap }) {
const [search, setSearch] = useState("");
const [filter, setFilter] = useState("all");
const filters = [
{ id: "all", l: "All", n: users.length },
{ id: "active", l: "β
Active", n: users.filter(u => u.status === "active").length },
{ id: "warned", l: "β οΈ Warned", n: users.filter(u => u.status === "warned").length },
{ id: "blocked", l: "π« Blocked", n: users.filter(u => u.status === "blocked").length },
{ id: "org_admin", l: "π’ Org Admins", n: users.filter(u => u.role === "org_admin").length },
];
const filtered = users.filter(u => {
const q = !search || u.name.toLowerCase().includes(search.toLowerCase()) || u.instagram.toLowerCase().includes(search.toLowerCase()) || u.email.toLowerCase().includes(search.toLowerCase());
if (!q) return false;
if (filter === "active") return u.status === "active";
if (filter === "warned") return u.status === "warned";
if (filter === "blocked") return u.status === "blocked";
if (filter === "org_admin") return u.role === "org_admin";
return true;
});
return
{filtered.map(u => {
const st = statusConfig[u.status] || statusConfig.active;
return
onUserTap(u)} style={{ background: c.card, border: `1px solid ${c.brd}`, borderRadius: 14, padding: 12, cursor: "pointer" }}>
{u.role === "org_admin" ? "π’" : "π€"}
;
})}
;
}
/* ββ User Detail ββ */
function UserDetail({ user: initial, onBack }) {
const [u, setU] = useState(initial);
const st = statusConfig[u.status] || statusConfig.active;
return
π€
{u.name}
{u.instagram}
π§ {u.email}
Info
{[{ l: "City", v: u.city }, { l: "Joined", v: u.joined }, { l: "Championships", v: u.champsJoined },
{ l: "Role", v: u.role === "org_admin" ? `Org Admin (${u.org})` : "Member" },
].map(r =>
{r.l}
{r.v}
)}
{(u.blockReason || u.warnReason) &&
{u.status === "blocked" ? "Block" : "Warning"} Reason
{u.blockReason || u.warnReason}
}
{u.status === "active" && <>
setU(p => ({ ...p, status: "warned", warnReason: "Warning issued by admin" }))} icon="β οΈ" />
setU(p => ({ ...p, status: "blocked", blockReason: "Blocked by admin" }))} icon="π«" />
>}
{u.status === "warned" && <>
setU(p => ({ ...p, status: "active", warnReason: null }))} icon="β
" />
setU(p => ({ ...p, status: "blocked", blockReason: "Blocked after warning" }))} icon="π«" />
>}
{u.status === "blocked" && setU(p => ({ ...p, status: "active", blockReason: null }))} icon="β
" />}
{}} icon="ποΈ" />
;
}
/* ββ App Shell ββ */
export default function AdminApp() {
const [scr, setScr] = useState("dash");
const [sel, setSel] = useState(null);
const go = (screen, data) => { setScr(screen); setSel(data || null); };
const render = () => {
if (scr === "orgDetail" && sel) return go("orgs")} champs={CHAMPS_DATA} />;
if (scr === "champDetail" && sel) return go("champs")} />;
if (scr === "userDetail" && sel) return go("users")} />;
if (scr === "orgs") return go("orgDetail", o)} />;
if (scr === "champs") return go("champDetail", ch)} />;
if (scr === "users") return go("userDetail", u)} />;
return ;
};
const showNav = ["dash", "orgs", "champs", "users"].includes(scr);
return ;
}