'use client' import React, { useState, useEffect } from 'react' import { useRouter, useParams } from 'next/navigation' import { Users, Trophy, Clock, Play, Square, UserMinus, RefreshCw, Settings, Upload, Plus, Code, TestTube, AlertCircle, Check, Timer } from 'lucide-react' interface Question { id: string title: string description: string difficulty: 'easy' | 'medium' | 'hard' function_name: string starter_code: Record test_cases: TestCase[] examples: Example[] constraints: string[] time_limit?: number memory_limit?: string } interface TestCase { input: string expected_output: string description: string is_public: boolean } interface Example { input: string expected_output: string description: string } interface ExamInfo { title: string status: 'waiting' | 'active' | 'completed' duration_minutes: number participants_count: number max_participants: number problem_title: string problem_description?: string languages: string[] created_at: string host_name: string } interface Participant { name: string score: number completed: boolean joined_at: string submitted_at?: string } export default function HostPanel() { const params = useParams() const router = useRouter() const examCode = params.examCode as string const [examInfo, setExamInfo] = useState(null) const [participants, setParticipants] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState('') // ✅ NEW STATE - Tab management and question upload const [activeTab, setActiveTab] = useState<'overview'|'participants'|'questions'>('overview') const [showUploader, setShowUploader] = useState(false) const [customDuration, setCustomDuration] = useState(30) const [showDurationEdit, setShowDurationEdit] = useState(false) // ✅ Empty "question draft" const blankQuestion: Question = { id: '', title: '', description: '', difficulty: 'medium', function_name: 'solve', starter_code: { python: 'def solve():\n # Write your solution here\n pass', java: 'public class Solution {\n public void solve() {\n // Write your solution here\n }\n}', javascript: 'function solve() {\n // Write your solution here\n}' }, test_cases: [{ input:'', expected_output:'', description:'Test case 1', is_public:true }], examples: [{ input:'', expected_output:'', description:'Example 1' }], constraints: [''], time_limit: 1000, memory_limit: '128MB' } const [draft, setDraft] = useState(blankQuestion) useEffect(() => { if (examCode) { fetchExamInfo() fetchParticipants() } }, [examCode]) const fetchExamInfo = async () => { try { console.log(`🔍 Fetching exam info for: ${examCode}`) const response = await fetch(`http://127.0.0.1:5000/api/exam/info/${examCode}`) const data = await response.json() console.log('📦 Exam info response:', data) if (data.success) { setExamInfo(data.exam_info) setCustomDuration(data.exam_info.duration_minutes) setError('') } else { setError(data.error || 'Failed to load exam information') } } catch (error) { console.error('❌ Error fetching exam info:', error) setError('Network error: Could not connect to backend') } finally { setLoading(false) } } const fetchParticipants = async () => { try { const response = await fetch(`http://127.0.0.1:5000/api/exam/participants/${examCode}`) const data = await response.json() if (data.success) { setParticipants(data.participants) } } catch (error) { console.error('Failed to fetch participants') } } // ✅ UPLOAD HANDLER const uploadQuestion = async () => { if (!draft.title.trim() || !draft.description.trim()) { alert('Title & description are required') return } try { const res = await fetch('http://127.0.0.1:5000/api/exam/upload-question', { method: 'POST', headers: { 'Content-Type':'application/json' }, body: JSON.stringify({ exam_code: examCode, question: draft }) }) const data = await res.json() if (data.success) { alert('✅ Question saved') setShowUploader(false) setDraft(blankQuestion) fetchExamInfo() // refresh current question/name } else { alert(`❌ ${data.error}`) } } catch (error) { console.error('Upload error:', error) alert('❌ Network error occurred') } } // ✅ UPDATE DURATION const updateDuration = async () => { try { const res = await fetch('http://127.0.0.1:5000/api/exam/update-duration', { method: 'POST', headers: { 'Content-Type':'application/json' }, body: JSON.stringify({ exam_code: examCode, duration_minutes: customDuration }) }) const data = await res.json() if (data.success) { alert(`✅ Duration updated to ${customDuration} minutes`) setShowDurationEdit(false) fetchExamInfo() } else { alert(`❌ ${data.error}`) } } catch (error) { alert('❌ Network error occurred') } } // ✅ ADD TEST CASE const addTestCase = () => { setDraft(prev => ({ ...prev, test_cases: [ ...prev.test_cases, { input: '', expected_output: '', description: `Test case ${prev.test_cases.length + 1}`, is_public: false } ] })) } // ✅ UPDATE TEST CASE const updateTestCase = (index: number, field: string, value: string | boolean) => { setDraft(prev => ({ ...prev, test_cases: prev.test_cases.map((tc, i) => i === index ? { ...tc, [field]: value } : tc ) })) } // ✅ REMOVE TEST CASE const removeTestCase = (index: number) => { setDraft(prev => ({ ...prev, test_cases: prev.test_cases.filter((_, i) => i !== index) })) } // ✅ START EXAM const startExam = async () => { try { const response = await fetch('http://127.0.0.1:5000/api/exam/start-exam', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ exam_code: examCode }) }) const data = await response.json() if (data.success) { alert('✅ Exam started! Participants can now begin coding.') fetchExamInfo() } else { alert(`❌ Failed to start exam: ${data.error}`) } } catch (error) { alert('❌ Network error occurred') } } // ✅ STOP EXAM const stopExam = async () => { if (!confirm('Are you sure you want to stop the exam?')) return try { const response = await fetch('http://127.0.0.1:5000/api/exam/stop-exam', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ exam_code: examCode }) }) const data = await response.json() if (data.success) { alert('🛑 Exam stopped successfully!') fetchExamInfo() } else { alert(`❌ Failed to stop exam: ${data.error}`) } } catch (error) { alert('❌ Network error occurred') } } // ✅ REMOVE PARTICIPANT const removeParticipant = async (participantName: string) => { if (!confirm(`Are you sure you want to remove "${participantName}" from the exam?`)) return try { const response = await fetch('http://127.0.0.1:5000/api/exam/remove-participant', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ exam_code: examCode, participant_name: participantName }) }) const data = await response.json() if (data.success) { alert(`✅ Removed "${participantName}" from the exam`) fetchParticipants() } else { alert(`❌ Failed to remove participant: ${data.error}`) } } catch (error) { alert('❌ Network error occurred') } } if (loading) { return (

Loading host panel for exam: {examCode}

) } if (error || !examInfo) { return (

Error Loading Exam

{error}

Exam Code: {examCode}

) } return (
{/* Header */}

Host Panel

Managing exam: {examCode}

{examInfo.status.toUpperCase()}
{/* ✅ TABS IN HEADER */}
{['overview','participants','questions'].map(t => ( ))}
{/* ✅ OVERVIEW TAB */} {activeTab === 'overview' && ( <> {/* Exam Info Cards */}

Participants

{examInfo.participants_count}/{examInfo.max_participants}

Duration

{examInfo.duration_minutes}m

{examInfo.status === 'waiting' && ( )}

Problem

{examInfo.problem_title}

Host

{examInfo.host_name}

{/* Control Panel */}

Exam Controls

{examInfo.status === 'waiting' && ( )} {examInfo.status === 'active' && ( )}
)} {/* ✅ PARTICIPANTS TAB */} {activeTab === 'participants' && (

Participants ({participants.length})

{participants.map((participant, index) => ( ))}
Name Joined At Status Score Actions
{participant.name} {new Date(participant.joined_at).toLocaleTimeString()} {participant.completed ? 'Completed' : 'In Progress'} {participant.completed ? ( {participant.score}% ) : ( - )}
{participants.length === 0 && (
No participants have joined yet.
)}
)} {/* ✅ QUESTIONS TAB */} {activeTab==='questions' && (

Question Management

{examInfo.status === 'waiting' && ( )}
{/* Current problem quick view */}

{examInfo.problem_title}

{examInfo.problem_description || 'No description stored'}

{examInfo.status !== 'waiting' && (

⚠️ Questions cannot be modified after exam has started

)}
{/* ✅ UPLOAD MODAL */} {showUploader && (

Upload Question

{/* Basic Info */}
setDraft({...draft,title:e.target.value})} />
{/* Description */}