import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout'; import { Head, router } from '@inertiajs/react'; import { Button } from '@/Components/ui/button'; import { Card } from '@/Components/ui/card'; import { useState, useEffect, useCallback } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Check, X, Volume2, RotateCw } from 'lucide-react'; import { cn } from '@/lib/utils'; import { Progress } from '@/Components/ui/progress'; interface ReviewItem { type: 'review' | 'new'; id: string; // Vocabulary ID srs_id?: string; word: string; reading: string; meaning: string; audio_url?: string; } export default function SrsPractice({ items }: { items: ReviewItem[] }) { const [currentIndex, setCurrentIndex] = useState(0); const [isFlipped, setIsFlipped] = useState(false); const [sessionQueue, setSessionQueue] = useState(items); const [completedCount, setCompletedCount] = useState(0); const currentItem = sessionQueue[currentIndex]; const isFinished = !currentItem; const progress = items.length > 0 ? (completedCount / items.length) * 100 : 0; const handleFlip = useCallback(() => { if (!isFlipped && !isFinished) { setIsFlipped(true); if (currentItem?.audio_url) { new Audio(currentItem.audio_url).play().catch(() => {}); } } }, [isFlipped, isFinished, currentItem]); const handleGrade = useCallback((grade: number) => { if (!isFlipped || isFinished) return; // Optimistic UI update const itemToSubmit = currentItem; // Submit in background router.post(route('srs.store'), { vocabulary_id: itemToSubmit.id, grade: grade }, { preserveScroll: true, preserveState: true, // Keep our local state intact onSuccess: () => { // Determine if we should requeue (Again/1) or remove // For simplicity in this version, we move to next regardless, // but real apps might requeue failed cards. } }); // Move to next setIsFlipped(false); setCompletedCount(prev => prev + 1); setCurrentIndex(prev => prev + 1); }, [isFlipped, isFinished, currentItem]); // Keyboard Shortcuts useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (isFinished) return; if (e.code === 'Space') { e.preventDefault(); if (!isFlipped) handleFlip(); } else if (isFlipped) { if (e.key === '1') handleGrade(1); if (e.key === '2') handleGrade(2); if (e.key === '3') handleGrade(3); if (e.key === '4') handleGrade(4); } }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, [handleFlip, handleGrade, isFinished, isFlipped]); return (

SRS Practice

Power up your Japanese memory

Progress {completedCount} / {items.length}
}>
{isFinished ? (

Otsukaresama! 🎉

Sesi ulasan Anda telah selesai dengan luar biasa.

) : (
{/* Flashcard Area */}
{/* Front Side */}
{currentItem.type === 'new' ? 'New Discovery' : 'Active Review'}

{currentItem.word}

Klik untuk Membalik
{/* Back Side */}

{currentItem.reading}

{currentItem.meaning}

Kosa Kata N5

{currentItem.audio_url && ( )}
{/* Controls */}
{[ { val: 1, label: 'Again', desc: 'Lupakan', color: 'red' }, { val: 2, label: 'Hard', desc: 'Sulit', color: 'orange' }, { val: 3, label: 'Good', desc: 'Bagus', color: 'blue' }, { val: 4, label: 'Easy', desc: 'Mudah', color: 'green' } ].map((btn) => ( ))}
{/* Keyboard Tips */}

Tips: Gunakan angka 1 - 4 di keyboard Anda

)}
); }