import React, { useState, useEffect, useRef } from 'react'; import { HashRouter, Routes, Route, Link, Navigate, useLocation } from 'react-router-dom'; import { Terminal, Flag, Trophy, Newspaper, Settings, LogOut, X, History, User, ChevronDown } from 'lucide-react'; import { CTFProvider, useCTF } from './CTFContext'; import { ProtectedRoute, Button, Countdown } from './UIComponents'; import { Home } from './Home'; import { ChallengeList } from './Challenges'; import { Blog } from './Blog'; import { Scoreboard, ScoreMatrix } from './Scoreboard'; import { Admin } from './Admin'; import { Login, Register } from './Auth'; import { calculateTeamTotalScore } from './services/scoring'; const ProfileSettingsModal: React.FC<{ onClose: () => void }> = ({ onClose }) => { const { updateProfile } = useCTF(); const [password, setPassword] = useState(''); const [confirm, setConfirm] = useState(''); const [error, setError] = useState(''); const [success, setSuccess] = useState(false); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (password !== confirm) return setError('PASSWORD_MISMATCH'); try { await updateProfile(password); setSuccess(true); setTimeout(onClose, 2000); } catch (err: any) { setError('FAILED'); } }; return (

IDENTITY_SETTINGS

{success ?
UPDATED_SUCCESSFULLY
: (
setPassword(e.target.value)} required /> setConfirm(e.target.value)} required /> {error &&

{error}

}
)}
); }; const LayoutShell: React.FC = () => { const { state, currentUser, logout, loading, loadError } = useCTF(); const [showProfileModal, setShowProfileModal] = useState(false); const [showUserMenu, setShowUserMenu] = useState(false); const menuRef = useRef(null); const location = useLocation(); useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (menuRef.current && !menuRef.current.contains(event.target as Node)) { setShowUserMenu(false); } }; if (showUserMenu) { document.body.addEventListener('mousedown', handleClickOutside); } return () => document.body.removeEventListener('mousedown', handleClickOutside); }, [showUserMenu]); useEffect(() => { if (state.config && state.config.conferenceName) { document.title = state.config.conferenceName; } }, [state.config]); if (loading) return
INITIALIZING_SESSION...
; const now = Date.now(); const eventStartTime = parseInt(state.config.eventStartTime || "0"); const eventEndTime = parseInt(state.config.eventEndTime || (Date.now() + 86400000).toString()); const isEventLive = now >= eventStartTime && now <= eventEndTime && state.isStarted; const bgStyles: React.CSSProperties = { backgroundColor: state.config.bgType === 'color' ? (state.config.bgColor || '#000000') : '#000000' }; const userScore = currentUser ? calculateTeamTotalScore(currentUser.id, state.challenges, state.solves) : 0; const getPageTitle = () => { const path = location.pathname; if (path === '/') return { text: 'HOME', icon: }; if (path === '/challenges') return { text: 'CHALLENGES', icon: }; if (path === '/blog') return { text: 'BLOG', icon: }; if (path === '/scoreboard' || path === '/matrix') return { text: 'SCORES', icon: }; if (path === '/admin') return { text: 'ADMIN PANEL', icon: }; if (path === '/login') return { text: 'LOGIN', icon: }; if (path === '/register') return { text: 'REGISTER', icon: }; return { text: '', icon: null }; }; const pageTitle = getPageTitle(); return (
{loadError &&
{loadError}
} {state.config.bgType === 'image' && state.config.bgImageData && (
)}
} /> } /> } /> } /> } /> } /> } /> {currentUser?.isAdmin ? : }} /> } />
{showProfileModal && setShowProfileModal(false)} />}
); }; const App: React.FC = () => { return ( ); }; export default App;