import React, { useState, useEffect } from 'react'; import axios from 'axios'; const Quiz = ({ sessionId, onGoHome, onRetry }) => { const [questionData, setQuestionData] = useState(null); const [selectedAnswers, setSelectedAnswers] = useState([]); const [userAnswer, setUserAnswer] = useState(''); const [totalQuestions, setTotalQuestions] = useState(0); const [correctAnswerCount, setCorrectAnswersCount] = useState(0); const [incorrectAnswersCount, setIncorrectAnswersCount] = useState(0); const [correctAnswers, setCorrectAnswers] = useState(''); const [quizCompleted, setQuizCompleted] = useState(false); const [timer, setTimer] = useState(0); const [timerId, setTimerId] = useState(null); const [feedback, setFeedback] = useState(''); const [isFeedbackVisible, setIsFeedbackVisible] = useState(false); const [fadeOut, setFadeOut] = useState(false); const [showResults, setShowResults] = useState(false); // Styles const pageStyle = { backgroundColor: 'black', minHeight: '100vh', display: 'flex', justifyContent: 'center', alignItems: 'center', color: 'white', fontFamily: 'Arial, sans-serif', flexDirection: 'column', }; const timerStyle = { color: 'white', fontSize: '24px', marginBottom: '20px', }; const containerStyle = { backgroundColor: '#333', padding: '30px', borderRadius: '15px', width: '400px', height: '550px', boxShadow: '0px 4px 12px rgba(0, 0, 0, 0.5)', textAlign: 'center', overflowY: 'auto', opacity: fadeOut ? 0 : 1, transition: 'opacity 0.5s ease-out', }; const buttonStyle = { backgroundColor: '#555', color: 'white', padding: '10px 20px', border: 'none', borderRadius: '5px', cursor: 'pointer', marginTop: '15px', fontWeight: 'bold', width: '100%', }; const optionStyle = { display: 'flex', alignItems: 'center', padding: '12px', backgroundColor: '#444', borderRadius: '5px', margin: '5px 0', justifyContent: 'center', cursor: 'pointer', outline: 'none', border: '2px solid transparent', }; const selectedOptionStyle = { ...optionStyle, border: '2px solid #0072ff', }; const inputStyle = { width: '95%', padding: '10px', borderRadius: '5px', backgroundColor: '#444', color: 'white', border: 'none', textAlign: 'center', marginTop: '15px', }; const feedbackContainerStyle = { backgroundColor: '#ffcccc', padding: '15px', borderRadius: '5px', marginTop: '20px', color: 'white', border: '1px solid #d8000c', textAlign: 'center', }; const disabledOptionStyle = { ...optionStyle, opacity: 0.5, pointerEvents: 'none', }; const resultContainerStyle = { backgroundColor: '#333', padding: '30px', borderRadius: '15px', width: '400px', textAlign: 'center', boxShadow: '0px 4px 12px rgba(0, 0, 0, 0.5)', opacity: showResults ? 1 : 0, transform: showResults ? 'translateY(0)' : 'translateY(20px)', transition: 'opacity 0.5s ease-out, transform 0.5s ease-out', }; // Keyboard event handler const handleKeyPress = (event) => { if (event.key === 'Enter') { if (isFeedbackVisible) { handleContinueClick(); } else { const canSubmit = questionData.options.length > 1 ? selectedAnswers.length > 0 : userAnswer.trim() !== ''; if (canSubmit) { handleSubmit(); } } } }; // Event listeners useEffect(() => { document.addEventListener('keypress', handleKeyPress); return () => { document.removeEventListener('keypress', handleKeyPress); }; }, [isFeedbackVisible, selectedAnswers, userAnswer, questionData]); const fetchQuestion = async () => { try { const response = await axios.get(`http://10.0.0.3:8000/next-question/?session_id=${sessionId}`); console.log("Fetched Question Data:", response.data); if (response.data.message === 'Quiz complete!') { setFadeOut(true); setTimeout(() => { setQuizCompleted(true); setQuestionData(null); setTimeout(() => { setShowResults(true); }, 100); }, 500); } else { setQuestionData(response.data); setSelectedAnswers([]); setUserAnswer(''); setFeedback(''); setIsFeedbackVisible(false); } } catch (error) { alert('Error fetching question: ' + (error.response?.data?.error || error.message)); } }; const fetchQuizStats = async () => { try { const response = await axios.get(`http://10.0.0.3:8000/quiz-stats/?session_id=${sessionId}`); setTotalQuestions(response.data.total_questions); setCorrectAnswersCount(response.data.correct_answers); setIncorrectAnswersCount(response.data.incorrect_answers); } catch (error) { console.error('Error fetching quiz stats:', error); } }; const handleMultipleAnswerChange = (answerText) => { setSelectedAnswers((prev) => { if (prev.includes(answerText)) { return prev.filter((answer) => answer !== answerText); } return [...prev, answerText]; }); }; const handleAnswerChange = (answerText) => { setSelectedAnswers([answerText]); }; const handleUserAnswerChange = (event) => { setUserAnswer(event.target.value); }; const handleContinueClick = () => { setIsFeedbackVisible(false); setFeedback(''); fetchQuestion(); }; const handleSubmit = async () => { let submissionData; if (questionData.options.length > 1) { submissionData = { session_id: sessionId, selected_answers: selectedAnswers, }; } else { submissionData = { session_id: sessionId, selected_answers: [userAnswer.trim()], }; } try { const response = await axios.post('http://10.0.0.3:8000/submit-answer/', submissionData); const result = response.data.result; setFeedback(result); setIsFeedbackVisible(true); if (result === 'Correct') { fetchQuestion(); } else { setCorrectAnswers(response.data.correct_answers.join(', ')); await moveQuestionToBottom(); } fetchQuizStats(); } catch (error) { alert('Error submitting answer: ' + (error.response?.data?.error || error.message)); } }; const moveQuestionToBottom = async () => { try { const questionIndex = questionData.question_index; await axios.post(`http://10.0.0.3:8000/move-question-to-bottom/`, { session_id: sessionId, question_index: questionIndex, }); } catch (error) { alert('Error moving question to bottom: ' + (error.response?.data?.error || error.message)); } }; useEffect(() => { fetchQuestion(); fetchQuizStats(); const id = setInterval(() => setTimer((prev) => prev + 1), 1000); setTimerId(id); return () => { clearInterval(id); }; }, [sessionId]); useEffect(() => { if (quizCompleted) { clearInterval(timerId); } }, [quizCompleted, timerId]); const formatTime = (totalSeconds) => { const hours = String(Math.floor(totalSeconds / 3600)).padStart(2, '0'); const minutes = String(Math.floor((totalSeconds % 3600) / 60)).padStart(2, '0'); const seconds = String(totalSeconds % 60).padStart(2, '0'); return `${hours}:${minutes}:${seconds}`; }; if (quizCompleted) { const totalAnswered = correctAnswerCount + (totalQuestions - correctAnswerCount); const percentageCorrect = totalAnswered > 0 ? (correctAnswerCount / (correctAnswerCount + incorrectAnswersCount)) * 100 : 0; return (
{formatTime(timer)}
{percentageCorrect.toFixed(0)}% Correct
Correct answer: {correctAnswers}
{correctAnswerCount}/{totalQuestions}