// static/js/testReview.jsx
function TestReview({ testId }) {
const { token, setView } = useContext(AuthContext);
const [loading, setLoading] = useState(true);
const [data, setData] = useState(null);
const [error, setError] = useState("");
useEffect(() => {
let isMounted = true;
async function loadReview() {
try {
setLoading(true);
setError("");
const review = await API.userReviewTestAnswers(token, testId);
if (isMounted) {
setData(review);
}
} catch (e) {
console.error(e);
if (isMounted) {
setError(e.message || "Не удалось загрузить ответы");
}
} finally {
if (isMounted) {
setLoading(false);
}
}
}
loadReview();
return () => {
isMounted = false;
};
}, [token, testId]);
if (loading) {
return (
);
}
if (error) {
return (
{error}
);
}
const result = data.result || {};
const percent = typeof result.percent === 'number' ? result.percent.toFixed(1) : '0.0';
return (
{data.test.title}
Баллы: {result.score}
{typeof result.max_score === 'number' ? ` из ${result.max_score}` : ''} ({percent}%)
{(data.questions || []).map((q, idx) => {
const earnedFull = Number(q.score_awarded || 0) >= Number(q.score || 0) && Number(q.score || 0) > 0;
return (
{idx + 1}. {q.text}
{q.score_awarded || 0} / {q.score || 0}
{(q.options || []).length > 0 ? (
{q.options.map(opt => {
let cls = "border rounded p-3 text-sm";
if (opt.is_correct) cls += " border-green-300 bg-green-50";
else if (opt.selected) cls += " border-red-300 bg-red-50";
else cls += " border-gray-200 bg-gray-50";
return (
{opt.is_correct ? "Верно" : (opt.selected ? "Ваш ответ" : "")}
{opt.text}
);
})}
) : (
Ваш ответ:
{q.text_answer || "Нет ответа"}
{q.correct_text && (
Правильный ответ:
{q.correct_text}
)}
)}
);
})}
);
}