'use client' import React, { useState, useEffect } from 'react' import { useRouter, useParams } from 'next/navigation' import { Users, Trophy, Clock, Play, Square, RefreshCw, Settings, Upload, Plus, UserMinus, AlertCircle, Timer, TestTube, Award } from 'lucide-react' /* ---------- Enhanced Models ---------- */ interface TestCase { input: string expected_output: string description: string is_public: boolean points: number } interface Example { input: string expected_output: string description: string } 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 correct_solution: Record scoring_method: string total_points: number } 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 passed_tests?: number total_tests?: number points_earned?: number total_points?: number } /* ---------- Enhanced Host Panel Component ---------- */ export default function EnhancedHostPanel() { const params = useParams() const router = useRouter() const examCode = params.examCode as string /* ------- Global state ------- */ const [examInfo, setExamInfo] = useState(null) const [participants, setParticipants] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState('') /* ------- UI state ------- */ const [activeTab, setActiveTab] = useState<'overview' | 'participants' | 'questions'>('overview') const [showUploader, setShowUploader] = useState(false) const [showDurationEdit, setShowDurationEdit] = useState(false) const [customDuration, setCustomDuration] = useState(30) /* ------- Enhanced 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, points: 25 }], examples: [{ input: '', expected_output: '', description: 'Example 1' }], constraints: [''], time_limit: 1000, memory_limit: '128MB', correct_solution: { python: '', java: '', javascript: '' }, scoring_method: 'test_cases', total_points: 100 } const [draft, setDraft] = useState({ ...blankQuestion }) /* ------------------------------------------------------------------- */ /* API CALLS */ /* ------------------------------------------------------------------- */ const fetchExamInfo = async () => { setLoading(true) try { const res = await fetch(`http://127.0.0.1:5000/api/exam/info/${examCode}`) const data = await res.json() if (data.success) { setExamInfo(data.exam_info) setCustomDuration(data.exam_info.duration_minutes) setError('') } else { setError(data.error || 'Unable to load exam') } } catch { setError('Backend unreachable') } finally { setLoading(false) } } const fetchParticipants = async () => { try { const res = await fetch(`http://127.0.0.1:5000/api/exam/participants/${examCode}`) const data = await res.json() if (data.success) setParticipants(data.participants) } catch { /** ignore */ } } useEffect(() => { fetchExamInfo() fetchParticipants() // eslint-disable-next-line react-hooks/exhaustive-deps }, [examCode]) /* ---------- Enhanced Question Upload ---------- */ const uploadQuestion = async () => { if (!draft.title.trim() || !draft.description.trim()) { alert('Title & description required') return } // Validate test cases const validTestCases = draft.test_cases.filter(tc => tc.expected_output.trim() !== '' ) if (validTestCases.length === 0) { alert('At least one test case with expected output is required') return } // Ensure points add up to total const totalTestPoints = validTestCases.reduce((sum, tc) => sum + tc.points, 0) if (totalTestPoints !== draft.total_points) { if (!confirm(`Test case points (${totalTestPoints}) don't equal total points (${draft.total_points}). Continue anyway?`)) { return } } try { const enhancedQuestion = { ...draft, test_cases: validTestCases, id: Date.now().toString() } 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: enhancedQuestion }) }) const data = await res.json() if (data.success) { alert(`✅ Enhanced question uploaded with ${validTestCases.length} test cases!`) setShowUploader(false) setDraft({ ...blankQuestion }) fetchExamInfo() } else { alert(`❌ ${data.error}`) } } catch { alert('❌ Network error') } } /* ---------- Test Case Management ---------- */ const addTestCase = () => { const newPoints = Math.floor(draft.total_points / (draft.test_cases.length + 1)) setDraft(prev => ({ ...prev, test_cases: [...prev.test_cases, { input: '', expected_output: '', description: `Test case ${prev.test_cases.length + 1}`, is_public: false, points: newPoints }] })) } const updateTestCase = (index: number, field: keyof TestCase, value: any) => { setDraft(prev => ({ ...prev, test_cases: prev.test_cases.map((tc, i) => i === index ? { ...tc, [field]: value } : tc ) })) } const removeTestCase = (index: number) => { if (draft.test_cases.length <= 1) { alert('At least one test case is required') return } setDraft(prev => ({ ...prev, test_cases: prev.test_cases.filter((_, i) => i !== index) })) } /* ---------- Duration Update ---------- */ const updateDuration = async () => { if (customDuration < 5) { alert('Minimum 5 minutes') return } 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') setShowDurationEdit(false) fetchExamInfo() } else alert(`❌ ${data.error}`) } catch { alert('❌ Network error') } } /* ---------- Enhanced Question Upload Form ---------- */ const EnhancedQuestionUploadForm = () => (

📝 Create Question with Dynamic Scoring

{/* Basic Question Info */}
setDraft(prev => ({...prev, title: e.target.value}))} className="w-full p-3 bg-gray-700 rounded border border-gray-600" />