import { useEffect, useRef, useMemo } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import Box from '@mui/material/Box'; import Card from '@mui/material/Card'; import CardContent from '@mui/material/CardContent'; import Typography from '@mui/material/Typography'; import Button from '@mui/material/Button'; import BoltIcon from '@mui/icons-material/Bolt'; import { SpeechBubble } from '../components/mascot/SpeechBubble'; import { apiClient } from '../api/client'; import { playCompletionSound } from '../utils/sounds'; interface ReviewState { correctCount: number; total: number; xp: number; topicId: string; lessonId: string; hearts: number; } export function ReviewPage() { const location = useLocation(); const navigate = useNavigate(); const savedRef = useRef(false); const reviewState = location.state as ReviewState | null; useEffect(() => { if (!reviewState) { navigate('/home', { replace: true }); return; } if (savedRef.current) return; savedRef.current = true; playCompletionSound(); const score = Math.round( (reviewState.correctCount / reviewState.total) * 100, ); // Save final progress and clear in-progress lesson state apiClient .put('/api/progress', { topic_id: reviewState.topicId, lesson_id: reviewState.lessonId, score, xp_earned: reviewState.xp, }) .catch(() => { // Progress save failed silently - user can retry the lesson }); apiClient .delete(`/api/lesson-state/${reviewState.topicId}/${reviewState.lessonId}`) .catch(() => { // Cleanup failed silently - stale state will be overwritten on next attempt }); }, [reviewState, navigate]); if (!reviewState) return null; const { correctCount, total, xp, hearts } = reviewState; const percentage = Math.round((correctCount / total) * 100); const isGoodScore = percentage >= 70; const isPerfect = percentage === 100; function getMascotMood() { if (isPerfect) return 'celebrate' as const; if (isGoodScore) return 'happy' as const; if (hearts === 0) return 'sad' as const; return 'encourage' as const; } const perfectMessages = [ 'Wow, perfect! Ang galing mo talaga!', 'Hindi ka nagkamali! Napakagaling!', 'Walang mali! Ikaw na ang pinakamahusay!', 'Perfect score! Tuloy lang!', ]; const goodMessages = [ 'Magaling! Halos perfect!', 'Great job! Galing mo!', 'Nice work! Patuloy ka lang!', 'Mahusay! Konti na lang, perfect na!', ]; const failMessages = [ "Okay lang! Subukan natin ulit!", "Hindi bale, matututo ka rin!", "Kaya mo yan! Practice lang!", "Huwag sumuko! Balik tayo!", ]; const lowMessages = [ 'Malapit na! Kaya mo yan!', 'Keep going! Practice makes perfect!', 'Konting practice pa, magaling ka na!', 'Tuloy lang, nakikita ko ang progress mo!', ]; function getMessages() { if (isPerfect) return perfectMessages; if (isGoodScore) return goodMessages; if (hearts === 0) return failMessages; return lowMessages; } const rambiMessage = useMemo(() => { const msgs = getMessages(); return msgs[Math.floor(Math.random() * msgs.length)]; // eslint-disable-next-line react-hooks/exhaustive-deps }, [isPerfect, isGoodScore, hearts]); return ( {/* Score */} {correctCount}/{total} {percentage}% correct {/* XP earned */} +{isGoodScore ? xp : Math.floor(xp * (percentage / 100))} XP ); }