From 4fe81113e3ec4a0931aabb7d66d2c52ceb0c9f10 Mon Sep 17 00:00:00 2001 From: Arghyadeep Date: Tue, 14 Oct 2025 15:43:27 +0530 Subject: [PATCH] feat: enhance Trivia component with review functionality and progress tracking --- src/pages/Trivia.jsx | 204 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 179 insertions(+), 25 deletions(-) diff --git a/src/pages/Trivia.jsx b/src/pages/Trivia.jsx index 99c2c17..db6cda8 100644 --- a/src/pages/Trivia.jsx +++ b/src/pages/Trivia.jsx @@ -28,62 +28,216 @@ export default function Trivia() { const [loading, setLoading] = useState(false); const [error, setError] = useState(null); const [score, setScore] = useState(0); + const [showReview, setShowReview] = useState(false); - useEffect(() => { fetchQuestions(); }, [category]); + useEffect(() => { + fetchQuestions(); + }, [category]); async function fetchQuestions() { try { - setLoading(true); setError(null); setScore(0); - const res = await fetch(`https://opentdb.com/api.php?amount=5&category=${category}&type=multiple`); + setLoading(true); + setError(null); + setScore(0); + setShowReview(false); + + const res = await fetch( + `https://opentdb.com/api.php?amount=5&category=${category}&type=multiple` + ); if (!res.ok) throw new Error('Failed to fetch'); const json = await res.json(); - const qs = json.results.map(q => ({ + + const qs = json.results.map((q) => ({ ...q, answers: shuffle([q.correct_answer, ...q.incorrect_answers]), - picked: null + picked: null, })); setQuestions(qs); - } catch (e) { setError(e); } finally { setLoading(false); } + } catch (e) { + setError(e); + } finally { + setLoading(false); + } } - function shuffle(arr) { return arr.sort(() => Math.random() - 0.5); } + function shuffle(arr) { + return arr.sort(() => Math.random() - 0.5); + } function pick(qIndex, answer) { - setQuestions(qs => qs.map((q,i) => i===qIndex ? { ...q, picked: answer } : q)); - if (questions[qIndex].correct_answer === answer) setScore(s => s+1); + setQuestions((qs) => + qs.map((q, i) => (i === qIndex ? { ...q, picked: answer } : q)) + ); + if (questions[qIndex].correct_answer === answer) { + setScore((s) => s + 1); + } + } + + function decodeHtml(html) { + const txt = document.createElement('textarea'); + txt.innerHTML = html; + return txt.value; } + const answeredCount = questions.filter((q) => q.picked !== null).length; + const totalQuestions = questions.length; + const progressPercent = + totalQuestions > 0 ? (answeredCount / totalQuestions) * 100 : 0; + + const allAnswered = answeredCount === totalQuestions && totalQuestions > 0; + return ( -
+

Trivia Quiz

- + + {/* Loading / Error */} {loading && } -

Score: {score}

+ + {/* Progress Bar */} + {totalQuestions > 0 && ( +
+

+ Progress: {answeredCount} / {totalQuestions} answered +

+
+
+
+
+ )} + + {/* Score + Review Button */} +
+

Score: {score}

+ +
+ + {/* Quiz Cards */} {questions.map((q, idx) => ( - +
    - {q.answers.map(a => ( -
  • - -
  • - ))} + {q.answers.map((a) => { + const isPicked = q.picked === a; + const isCorrect = a === q.correct_answer; + let btnClass = ''; + + if (showReview) { + btnClass = isCorrect + ? 'correct' + : isPicked + ? 'wrong' + : 'neutral'; + } else if (isPicked) { + btnClass = isCorrect ? 'correct' : 'wrong'; + } + + return ( +
  • + +
  • + ); + })}
))} - {/* TODO: Add scoreboard persistence */} + + {/* Review Section */} + {showReview && ( +
+

🎯 Quiz Complete!

+

+ Final Score: {score} / {totalQuestions} +

+ +
+ )}
); } -function decodeHtml(html) { - const txt = document.createElement('textarea'); - txt.innerHTML = html; - return txt.value; -}