generated from dwd/boilarplate-remix-tailwind-antd
164 lines
7.5 KiB
TypeScript
164 lines
7.5 KiB
TypeScript
import React, { useState, useEffect } from "react";
|
|
import '../../public/assets/custom-radio.css'
|
|
import QuizHeader from '~/components/QuizHeader'
|
|
|
|
interface Questiondata {
|
|
questionId: number;
|
|
questionText: string;
|
|
option1: string;
|
|
option2: string;
|
|
option3: string;
|
|
option4: string;
|
|
correctAnswer: string;
|
|
quizId: string | null;
|
|
moduleId: string;
|
|
}
|
|
|
|
interface Answerdata {
|
|
questionId: number;
|
|
selectedOption: number;
|
|
}
|
|
|
|
export default function QuizIndex() {
|
|
const [questionData, setQuestionsData] = useState<Questiondata[]>([]);
|
|
const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
|
|
const [selectedOption, setSelectedOption] = useState<number | null>(null);
|
|
const [answers, setAnswers] = useState<Answerdata[]>([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState<Error | null>(null);
|
|
const [timeLeft, setTimeLeft] = useState(120); // 120 seconds timer
|
|
const [newQuizIds, setNewQuizIds] = useState();
|
|
useEffect(() => {
|
|
fetch(`http://localhost:5174/api/question-list`)
|
|
.then(res => {
|
|
if (!res.ok) {
|
|
throw new Error('Network response was not ok');
|
|
}
|
|
return res.json();
|
|
})
|
|
.then(data => {
|
|
console.log('Question Data', data);
|
|
setQuestionsData(data);
|
|
setNewQuizIds(data[0].newQuizId)
|
|
setLoading(false);
|
|
})
|
|
.catch(error => {
|
|
console.error('An error occurred', error);
|
|
setError(error);
|
|
setLoading(false);
|
|
});
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
if (timeLeft > 0) {
|
|
const timerId = setInterval(() => setTimeLeft(timeLeft - 1), 1000);
|
|
return () => clearInterval(timerId);
|
|
} else {
|
|
handleSubmit();
|
|
}
|
|
}, [timeLeft]);
|
|
|
|
if (loading) {
|
|
return <div>Loading...</div>;
|
|
}
|
|
|
|
if (error) {
|
|
return <div>Error: {error.message}</div>;
|
|
}
|
|
|
|
const handleOptionChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
setSelectedOption(parseInt(event.target.value));
|
|
};
|
|
|
|
const handleNextQuestion = () => {
|
|
if (selectedOption !== null) {
|
|
const newAnswer = {
|
|
questionId: questionData[currentQuestionIndex].questionId,
|
|
selectedOption: selectedOption,
|
|
quizId: newQuizIds
|
|
};
|
|
setAnswers([...answers, newAnswer]);
|
|
setSelectedOption(null);
|
|
setCurrentQuestionIndex((prevIndex) => (prevIndex + 1) % questionData.length);
|
|
console.log([...answers, newAnswer]);
|
|
} else {
|
|
alert("Please select an option before proceeding to the next question.");
|
|
}
|
|
};
|
|
|
|
const handleSubmit = () => {
|
|
if (selectedOption !== null) {
|
|
const newAnswer = {
|
|
questionId: questionData[currentQuestionIndex].questionId,
|
|
selectedOption: selectedOption,
|
|
quizId: newQuizIds
|
|
};
|
|
const finalAnswers = [...answers, newAnswer];
|
|
setAnswers(finalAnswers);
|
|
console.log('Console Answers ', finalAnswers);
|
|
const apiUrl = 'http://localhost:5174/api/save-quiz-response';
|
|
fetch(apiUrl, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json'
|
|
},
|
|
body: JSON.stringify(finalAnswers)
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if(data.success === true){
|
|
console.log('Find Success Message True')
|
|
window.location.href = `/quiz/result?id=${newQuizIds}`
|
|
}
|
|
console.log('Success:', data);
|
|
})
|
|
.catch((error) => {
|
|
console.error('Error:', error);
|
|
});
|
|
} else {
|
|
alert("Please select an option before submitting the quiz.");
|
|
}
|
|
};
|
|
|
|
const currentQuestion = questionData[currentQuestionIndex];
|
|
|
|
return (
|
|
<div className="">
|
|
<QuizHeader />
|
|
<div className="container mx-auto max-w-[890px] mt-[100px] flex justify-end"><h2 className="text-[20px] font-[600]">Time left: {timeLeft} seconds</h2></div>
|
|
<section className="container mx-auto max-w-[890px] shadow-xl rounded-xl px-10 py-8 mb-8 border-[1px] border-[#DCDCDC] rounded-[10px] bg-[#FCFCFC] ">
|
|
<div>
|
|
<div key={currentQuestion.questionId}>
|
|
<h2 className="text-[32px] font-[700] ">{`Q${currentQuestion.questionId}. ${currentQuestion.questionText}`}</h2>
|
|
<div className="flex flex-col space-y-6 mt-8">
|
|
<label htmlFor={`${currentQuestion.questionId}-option1`} className={`flex flex-row space-x-3 border-[1px] rounded-[10px] p-3 bg-[#FFF] ${selectedOption === 1 ? 'border-[#000]' : 'border-[#D3D3D3]'}`}>
|
|
<input className="custom-radio" type="radio" value="1" id={`${currentQuestion.questionId}-option1`} checked={selectedOption === 1} onChange={handleOptionChange}/>
|
|
<span>{currentQuestion.option1}</span>
|
|
</label>
|
|
<label htmlFor={`${currentQuestion.questionId}-option2`} className={`flex flex-row space-x-3 border-[1px] rounded-[10px] p-3 bg-[#FFF] ${selectedOption === 2 ? 'border-[#000]' : 'border-[#D3D3D3]'}`}>
|
|
<input className="custom-radio" type="radio" value="2" id={`${currentQuestion.questionId}-option2`} checked={selectedOption === 2} onChange={handleOptionChange}/>
|
|
<span>{currentQuestion.option2}</span>
|
|
</label>
|
|
<label htmlFor={`${currentQuestion.questionId}-option3`} className={`flex flex-row space-x-3 border-[1px] rounded-[10px] p-3 bg-[#FFF] ${selectedOption === 3 ? 'border-[#000]' : 'border-[#D3D3D3]'}`}>
|
|
<input className="custom-radio" type="radio" value="3" id={`${currentQuestion.questionId}-option3`} checked={selectedOption === 3} onChange={handleOptionChange}/>
|
|
<span>{currentQuestion.option3}</span>
|
|
</label>
|
|
<label htmlFor={`${currentQuestion.questionId}-option4`} className={`flex flex-row space-x-3 border-[1px] rounded-[10px] p-3 bg-[#FFF] ${selectedOption === 4 ? 'border-[#000]' : 'border-[#D3D3D3]'}`}>
|
|
<input className="custom-radio" type="radio" value="4" id={`${currentQuestion.questionId}-option4`} checked={selectedOption === 4} onChange={handleOptionChange}/>
|
|
<span>{currentQuestion.option4}</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
<div className="container mx-auto max-w-[890px] flex justify-end mt-[30px]">
|
|
{currentQuestionIndex < questionData.length - 1 ? (
|
|
<button className="bg-[#000] text-[#FFF] text-[18px] font-[600] rounded-[8px] px-[70px] py-[15px]" onClick={handleNextQuestion}>Next Question</button>
|
|
) : (
|
|
<button className="bg-[#000] text-[#FFF] text-[18px] font-[600] rounded-[8px] px-[70px] py-[15px]" onClick={handleSubmit}>Submit</button>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|