import { cn } from '@/lib/utils'; import CourseLayout from '@/Layouts/CourseLayout'; import { Head, router } from '@inertiajs/react'; import { useState, useEffect } from 'react'; import { Plyr } from 'plyr-react'; import 'plyr-react/plyr.css'; import { BookOpen, ArrowRight, Volume2, Play } from 'lucide-react'; import { Button } from '@/Components/ui/button'; import { FuriganaText } from '@/lib/furigana'; interface VocabularyData { id: string; word: string; reading: string; romaji: string; meaning_id: string; meaning_en: string; type: string; audio_url: string | null; } interface LessonData { id: string; title: string; slug: string; type: 'video' | 'text' | 'pdf'; is_completed: boolean; } interface ModuleData { id: string; title: string; lessons: LessonData[]; } interface CourseData { id: string; title: string; slug: string; progress_percentage: number; modules: ModuleData[]; } interface CurrentLessonData { id: string; title: string; slug: string; type: 'video' | 'text' | 'pdf'; content: string | null; video_url: string | null; content_pdf: string | null; vocabularies: VocabularyData[]; is_completed?: boolean; duration_seconds?: number; } interface PlayerProps { course: CourseData; currentLesson: CurrentLessonData; nextLesson?: LessonData | null; previousLesson?: LessonData | null; auth: { user: any; }; [key: string]: any; } // Helper to get YouTube video ID (Original Regex Logic) // Helper to get YouTube video ID (Robust) function getYouTubeId(url: string | null): string | null { if (!url) return null; try { const urlObj = new URL(url.trim()); let id = null; if (urlObj.hostname.includes('youtube.com')) { id = urlObj.searchParams.get('v'); } else if (urlObj.hostname.includes('youtu.be')) { id = urlObj.pathname.slice(1); } return id; } catch (e) { const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; const match = url.match(regExp); return (match && match[2]) ? match[2] : null; } } export default function Player({ course, currentLesson, nextLesson, previousLesson, auth }: PlayerProps) { const [isPlaying, setIsPlaying] = useState(null); // ROBUST LOGIC: // Extract ID first. If valid ID, force provider 'youtube'. const youtubeId = getYouTubeId(currentLesson.video_url); const videoSource = currentLesson.type === 'video' && currentLesson.video_url ? { type: 'video' as const, sources: [{ src: youtubeId || currentLesson.video_url, provider: youtubeId ? 'youtube' as const : 'html5' as const, }], } : null; // Learning Tracer - Heartbeat every 60 seconds useEffect(() => { const interval = setInterval(() => { // @ts-ignore router.post(route('lessons.heartbeat', { lesson: currentLesson.id }), {}, { preserveScroll: true, preserveState: true, only: [], // @ts-ignore onFinish: () => { } }); }, 60000); return () => clearInterval(interval); }, [currentLesson.id]); const handleComplete = () => { // @ts-ignore router.post(route('lessons.complete', { lesson: currentLesson.id })); }; const playAudio = (url: string, id: string) => { const audio = new Audio(url); setIsPlaying(id); audio.play(); audio.onended = () => setIsPlaying(null); }; return (
{/* Video Player */} {currentLesson.type === 'video' && videoSource && (
)} {/* Title & Stats */}
{currentLesson.type} {currentLesson.is_completed && Completed}

{/* Text Content */} {currentLesson.type === 'text' && currentLesson.content && (
)} {/* PDF Content */} {currentLesson.type === 'pdf' && currentLesson.content_pdf && (