import { useNavigate } from "react-router"; import { NavBar } from "../components/NavBar"; import { useAuth } from "../contexts/AuthContext"; import SessionExpiredPopup from "../components/SessionExpiredPopup"; import { useState } from "react"; const Admin = () => { const { user, isLoading, logout } = useAuth(); const [showAddGame, setShowAddGame] = useState(false); const [showCreateInvite, setShowCreateInvite] = useState(false); const [formData, setFormData] = useState({ gameInternalName: '', gameFormattedName: '', gameDescription: '' }); const [inviteFormData, setInviteFormData] = useState({ uses: '', code: '' }); const [isSubmitting, setIsSubmitting] = useState(false); const [isCreatingInvite, setIsCreatingInvite] = useState(false); const [createdInviteCode, setCreatedInviteCode] = useState(null); const navigate = useNavigate(); const handleLogout = async () => { try { await logout(); navigate("/"); } catch (error) { console.error("Logout failed:", error); alert("Network error during logout. Please try again."); } }; const handleInputChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setFormData(prev => ({ ...prev, [name]: value })); }; const handleInviteInputChange = (e: React.ChangeEvent) => { const { name, value } = e.target; setInviteFormData(prev => ({ ...prev, [name]: value })); }; const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!formData.gameInternalName || !formData.gameFormattedName || !formData.gameDescription) { alert('Please fill in all fields'); return; } setIsSubmitting(true); try { const response = await fetch(import.meta.env.VITE_API_URL + '/admin/createGame', { method: 'POST', headers: { 'Content-Type': 'application/json', }, credentials: 'include', body: JSON.stringify(formData), }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || 'Failed to create game'); } alert('Game created successfully!'); setFormData({ gameInternalName: '', gameFormattedName: '', gameDescription: '' }); setShowAddGame(false); } catch (error) { console.error('Failed to create game:', error); alert(error instanceof Error ? error.message : 'Failed to create game'); } finally { setIsSubmitting(false); } }; const handleInviteSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!inviteFormData.uses) { alert('Please specify the number of uses for the invite code'); return; } const uses = parseInt(inviteFormData.uses); if (isNaN(uses) || uses <= 0) { alert('Please enter a valid number of uses'); return; } setIsCreatingInvite(true); try { const requestBody: { uses: number; code?: string } = { uses }; if (inviteFormData.code.trim()) { requestBody.code = inviteFormData.code.trim(); } const response = await fetch(import.meta.env.VITE_API_URL + '/admin/createInvite', { method: 'POST', headers: { 'Content-Type': 'application/json', }, credentials: 'include', body: JSON.stringify(requestBody), }); if (!response.ok) { const error = await response.json(); throw new Error(error.error || 'Failed to create invite code'); } const result = await response.json(); setCreatedInviteCode(result.inviteCode.code); setInviteFormData({ uses: '', code: '' }); } catch (error) { console.error('Failed to create invite code:', error); alert(error instanceof Error ? error.message : 'Failed to create invite code'); } finally { setIsCreatingInvite(false); } }; const copyToClipboard = (text: string) => { navigator.clipboard.writeText(text).then(() => { alert('Invite code copied to clipboard!'); }).catch(() => { alert('Failed to copy to clipboard'); }); }; if (isLoading) { return (

Loading Admin dashboard...

); } if (!user) { return ; } if(!user.isAdmin && user.id != 1){ console.log(user.id == 1) return

You are not authorized to access this page.

; } return (
{/* Main Content */}
{/* Header */}

Admin Page

Welcome Mirage Webmaster! Here are a variety of settings and tools you can use to customize the experience

{/* Create Invite Code Section */}
{showCreateInvite && (

Generate invite codes to allow new users to register. You can specify how many times the code can be used and optionally set a custom code (otherwise one will be generated automatically).

{createdInviteCode && (

Invite Code Created Successfully!

{createdInviteCode}
)}
)}
{/* Add New Game Section */}
{showAddGame && (

This form allows you to add a new game to Mirage. By default, Mirage will attempt to derive a method of showing the game's score on its own. You may override this behavior by writing your own custom score display logic.

)}
); }; export default Admin;