Quizify / frontend /src /components /ResultsView.jsx
hetsheta's picture
Migrate frontend to React + Vite with glassmorphism UI
5d00a33
Raw
History Blame Contribute Delete
2.92 kB
import { useEffect, useRef } from 'react';
const scoreMessage = (pct) => {
if (pct === 100) return 'Perfect score — absolutely outstanding! 🎉';
if (pct >= 80) return 'Excellent command of the material.';
if (pct >= 60) return 'Good effort — room to grow.';
if (pct >= 40) return 'Keep studying — you\'ll get there.';
return 'Review the material and try again.';
};
function ResultCard({ r, index }) {
const correct = r.correct;
return (
<div
className={`r-card ${correct ? 'r-correct' : 'r-incorrect'}`}
style={{ animationDelay: `${index * 0.07}s` }}
>
<div className={`r-badge ${correct ? 'badge-ok' : 'badge-no'}`}>
{correct ? '✓ Correct' : '✗ Incorrect'}
</div>
<div className="r-question">Q{index + 1}. {r.question}</div>
{!correct && (
<>
<div className="answer-grid">
<div>
<div className="a-label">Your Answer</div>
<div className="a-val-wrong">{r.user_answer || '—'}</div>
</div>
<div>
<div className="a-label">Correct Answer</div>
<div className="a-val-right">{r.correct_answer}</div>
</div>
</div>
{r.explanation && (
<div className="expl-box">
<div className="expl-label">Explanation</div>
<div className="expl-text">{r.explanation}</div>
</div>
)}
{r.concept && (
<div className="concept-pill">✦ {r.concept}</div>
)}
</>
)}
</div>
);
}
export default function ResultsView({ result, onReset }) {
const { score, total, results } = result;
const pct = total ? (score / total) * 100 : 0;
const barRef = useRef(null);
useEffect(() => {
// Animate bar after mount
const t = setTimeout(() => {
if (barRef.current) barRef.current.style.width = `${pct.toFixed(1)}%`;
}, 150);
return () => clearTimeout(t);
}, [pct]);
return (
<div>
{/* Score Hero */}
<div className="score-wrap">
<div className="score-num">
{score}<span className="score-denom">/{total}</span>
</div>
<div className="score-label-text">Final Score</div>
<div className="score-bar-bg">
<div className="score-bar-fill" ref={barRef} />
</div>
<div className="score-msg">{scoreMessage(pct)}</div>
</div>
{/* Detailed Review */}
<div className="step-header" style={{ marginTop: '1.5rem' }}>
<div className="step-badge">✦</div>
<div className="step-title">Detailed Review</div>
</div>
{results.map((r, i) => (
<ResultCard key={i} r={r} index={i} />
))}
<div className="spacer" />
<button className="btn btn-ghost" onClick={onReset} id="btn-try-again">
↺ &nbsp; Try Again
</button>
</div>
);
}