import React, { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react'; import { Challenge, Team, Solve, CTFState, BlogPost } from './types'; import { api } from './services/api'; interface CTFContextType { state: CTFState; currentUser: Team | null; login: (name: string, pass: string) => Promise; register: (name: string, pass: string) => Promise; logout: () => void; submitFlag: (challengeId: string, flag: string) => Promise; toggleCtf: () => Promise; resetScores: () => Promise; upsertChallenge: (data: FormData, id?: string) => Promise; deleteChallenge: (id: string) => Promise; deleteAllChallenges: () => Promise; exportChallenges: () => Promise<{ challenges: any[] }>; importChallenges: (file: File) => Promise; backupDatabase: () => Promise; restoreDatabase: (file: File) => Promise; updateTeam: (id: string, data: any) => Promise; updateProfile: (password?: string) => Promise; deleteTeam: (id: string) => Promise; createBlogPost: (data: { title: string, content: string }) => Promise; updateBlogPost: (id: string, data: { title: string, content: string }) => Promise; deleteBlogPost: (id: string) => Promise; updateConfig: (formData: FormData) => Promise; refreshState: () => Promise; loading: boolean; loadError: string | null; } const CTFContext = createContext(null); export const useCTF = () => { const context = useContext(CTFContext); if (!context) throw new Error('useCTF must be used within provider'); return context; }; export const CTFProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { const [state, setState] = useState({ isStarted: false, startTime: null, teams: [], challenges: [], solves: [], blogs: [], config: {} }); const [currentUser, setCurrentUser] = useState(null); const [loading, setLoading] = useState(true); const [loadError, setLoadError] = useState(null); // Fix: Removed return value to match refreshState: () => Promise interface const refreshState = useCallback(async () => { try { const newState = await api.getState(); setState(newState); } catch (err: any) { console.error("State refresh failed:", err); throw err; } }, []); useEffect(() => { const init = async () => { const session = localStorage.getItem('hip6_session'); if (session) { try { const { team } = JSON.parse(session); setCurrentUser(team); } catch (e) {} } const safetyTimeout = setTimeout(() => { setLoading(false); setLoadError("CONNECTION_TIMED_OUT: RETRYING..."); }, 6000); try { await refreshState(); setLoadError(null); } catch (err: any) { setLoadError("COMMUNICATION_FAULT: RECONNECTING..."); } finally { clearTimeout(safetyTimeout); setLoading(false); } }; init(); const interval = setInterval(() => { refreshState().catch(() => {}); }, 30000); return () => clearInterval(interval); }, [refreshState]); const login = async (n: string, p: string) => { try { const { team, token } = await api.login(n, p); localStorage.setItem('hip6_session', JSON.stringify({ team, token })); setCurrentUser(team); await refreshState(); return true; } catch (e) { return false; } }; const register = async (n: string, p: string) => { const { team, token } = await api.register(n, p); localStorage.setItem('hip6_session', JSON.stringify({ team, token })); setCurrentUser(team); await refreshState(); }; const logout = () => { localStorage.removeItem('hip6_session'); setCurrentUser(null); }; const submitFlag = async (cid: string, f: string) => { const res = await api.submitFlag(cid, f); await refreshState(); return res.success; }; const toggleCtf = async () => { await api.toggleCtf(); await refreshState(); }; const resetScores = async () => { if (window.confirm("Reset all scores to 0?")) { await api.resetScores(); await refreshState(); }}; const upsertChallenge = async (d: FormData, id?: string) => { await api.upsertChallenge(d, id); await refreshState(); }; const deleteChallenge = async (id: string) => { if (window.confirm("DELETE_CHALLENGE?")) { await api.deleteChallenge(id); await refreshState(); } }; const deleteAllChallenges = async () => { if (window.confirm("Delete all challenges?")) {await api.deleteAllChallenges(); await refreshState(); }}; const exportChallenges = async () => await api.exportChallenges(); const importChallenges = async (f: File) => { await api.importChallenges(f); await refreshState(); }; const backupDatabase = async () => await api.backupDatabase(); const restoreDatabase = async (f: File) => await api.restoreDatabase(f); const updateTeam = async (id: string, d: any) => { await api.updateTeam(id, d); await refreshState(); }; const updateProfile = async (p?: string) => { await api.updateProfile({ password: p }); await refreshState(); }; const deleteTeam = async (id: string) => { if (window.confirm("EXPEL_OPERATOR?")) { await api.deleteTeam(id); await refreshState(); } }; const createBlogPost = async (d: any) => { await api.createBlogPost(d); await refreshState(); }; const updateBlogPost = async (id: string, d: any) => { await api.updateBlogPost(id, d); await refreshState(); }; const deleteBlogPost = async (id: string) => { await api.deleteBlogPost(id); await refreshState(); }; const updateConfig = async (d: FormData) => { await api.updateConfig(d); await refreshState(); }; return ( {children} ); };