// static/js/dashboard.jsx function UserDashboard() { const { token, setView } = useContext(AuthContext); const [tests, setTests] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(""); useEffect(() => { let isMounted = true; async function loadTests() { try { setLoading(true); setError(""); const data = await API.getAvailableTests(token); if (isMounted) { setTests(Array.isArray(data) ? data : []); } } catch (e) { console.error(e); if (isMounted) { setError(e.message || "Не удалось загрузить список тестов"); setTests([]); } } finally { if (isMounted) { setLoading(false); } } } if (token) { loadTests(); } else { setLoading(false); setTests([]); } return () => { isMounted = false; }; }, [token]); if (loading) { return (
); } return (

Доступные тесты

{error && (
{error}
)} {!error && tests.length === 0 && (
Для вас пока нет доступных тестов.
)} {tests.length > 0 && (
{tests.map(test => { const hasDetails = typeof test.last_percent === 'number' && typeof test.total_questions === 'number' && test.total_questions > 0 && typeof test.last_correct_questions === 'number'; const hasLastAttempt = test.last_score !== null && test.last_score !== undefined; let resultBoxClasses = "p-2 rounded text-xs mt-2"; let resultTitle = ""; if (test.status === 'passed') { resultBoxClasses += " bg-green-50 text-green-800 border border-green-200"; resultTitle = "Результат последней попытки — ТЕСТ СДАН"; } else if (test.status === 'failed') { resultBoxClasses += " bg-red-50 text-red-800 border border-red-200"; resultTitle = "Результат последней попытки — ТЕСТ НЕ СДАН"; } else { resultBoxClasses += " bg-gray-50 text-gray-700 border border-gray-200"; resultTitle = "Результат последней попытки"; } return (

{test.title}

{test.description}

🕒 Время: {test.time_limit ? test.time_limit + ' мин' : 'Без ограничений'}

🎯 Проходной: {test.passing_score}%

🔄 Попыток: {test.attempts_used} / {test.attempts_allowed || '∞'}

{/* Блок с результатами последней попытки — показываем, если она вообще была */} {hasLastAttempt && (
{resultTitle}
{hasDetails ? ( <>
Правильных ответов:{" "} {test.last_correct_questions} из {test.total_questions}
Баллы:{" "} {test.last_score} {typeof test.max_score === 'number' && test.max_score > 0 ? ` из ${test.max_score}` : ''} {typeof test.last_percent === 'number' && ( <> ({test.last_percent.toFixed(1)}%) )}
) : (
Баллы:{" "} {test.last_score}
)}
)}
{/* Блок с кнопкой — снизу карточки */}
{test.status === 'passed' ? (
Тест уже сдан.
) : ( )}
); })}
)}
); }