import React, { useEffect, useMemo, useState } from "react"; import Layout from "@/components/Layout"; import { useAuth } from "@/contexts/AuthContext"; import { useNavigate } from "react-router-dom"; import { aethexToast } from "@/lib/aethex-toast"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Separator } from "@/components/ui/separator"; function useHasStaffAccess(roles: string[]) { return useMemo( () => roles.some((r) => ["owner", "admin", "founder", "staff", "employee"].includes( r.toLowerCase(), ), ), [roles], ); } export default function Staff() { const { user, roles, loading } = useAuth(); const navigate = useNavigate(); const hasAccess = useHasStaffAccess(roles); useEffect(() => { if (loading) return; if (!user) { aethexToast.info({ title: "Sign in required", description: "Staff area requires authentication", }); navigate("/onboarding"); return; } if (!hasAccess) { aethexToast.error({ title: "Access denied", description: "You don't have staff permissions", }); navigate("/dashboard"); } }, [user, roles, hasAccess, loading, navigate]); const [activeTab, setActiveTab] = useState("overview"); const [openReports, setOpenReports] = useState([]); const [mentorshipAll, setMentorshipAll] = useState([]); const [loadingData, setLoadingData] = useState(false); const [searchQ, setSearchQ] = useState(""); const [users, setUsers] = useState([]); const refresh = async () => { setLoadingData(true); try { const [r1, r2] = await Promise.all([ fetch("/api/moderation/reports?status=open&limit=100"), fetch("/api/mentorship/requests/all?limit=50&status=pending"), ]); const reports = r1.ok ? await r1.json() : []; const m = r2.ok ? await r2.json() : []; setOpenReports(Array.isArray(reports) ? reports : []); setMentorshipAll(Array.isArray(m) ? m : []); } catch (e) { /* ignore */ } finally { setLoadingData(false); } }; useEffect(() => { if (user && hasAccess) refresh(); }, [user, hasAccess]); const loadUsers = async () => { try { const params = new URLSearchParams(); if (searchQ.trim()) params.set("q", searchQ.trim()); params.set("limit", "25"); const resp = await fetch(`/api/staff/users?${params.toString()}`); const data = resp.ok ? await resp.json() : []; setUsers(Array.isArray(data) ? data : []); } catch { setUsers([]); } }; const updateReportStatus = async ( id: string, status: "resolved" | "ignored" | "open", ) => { try { const resp = await fetch( `/api/moderation/reports/${encodeURIComponent(id)}/status`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ status }), }, ); if (resp.ok) { aethexToast.success({ title: "Updated", description: `Report marked ${status}`, }); refresh(); } } catch {} }; return (
Internal

Operations Command

Staff dashboards, moderation, and internal tools.

Overview Moderation Mentorship Users
Community Health Quick pulse across posts and reports
Open reports
{openReports.length}
Mentorship requests
{mentorshipAll.length}
Service Status APIs and queues
Admin API
OK
Notifications
OK
Shortcuts Common operational links
Moderation Queue Flagged content and actions {loadingData && (

Loading…

)} {!loadingData && openReports.length === 0 && (

No items in queue.

)}
{openReports.map((r) => (
{r.reason}
{r.details}
))}
Mentorship Requests Review recent mentor/mentee activity {loadingData && (

Loading…

)} {!loadingData && mentorshipAll.length === 0 && (

No requests to review.

)}
{mentorshipAll.map((req) => (
{req.mentee?.full_name || req.mentee?.username} →{" "} {req.mentor?.full_name || req.mentor?.username}
{req.message || "No message"}
{req.status}
))}
Users Search, roles, and quick actions
setSearchQ(e.target.value)} />
{users.length === 0 ? (

No users found.

) : (
{users.map((u) => (
{u.full_name || u.username || u.id}
{u.username}
{u.user_type || "unknown"}
))}
)}
); }