import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
import { Head, Link, router } from '@inertiajs/react';
import { useState, useEffect } from 'react';
import { Plyr } from 'plyr-react';
import 'plyr-react/plyr.css';
import {
CheckCircle2,
ChevronLeft,
Circle,
FileText,
Play,
Video,
Menu,
Volume2,
BookOpen,
ArrowRight,
Trophy
} from 'lucide-react';
import { Button } from '@/Components/ui/button';
import { Progress } from '@/Components/ui/progress';
import { FuriganaText } from '@/lib/furigana';
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger
} from "@/Components/ui/sheet";
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;
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;
}
interface ProgressData {
completed_count: number;
total_count: number;
percentage: number;
}
interface PlayerProps {
course: CourseData;
currentLesson: CurrentLessonData;
progress: ProgressData;
auth: {
user: any;
};
[key: string]: any;
}
// Helper to get YouTube video ID
function getYouTubeId(url: string | null): string | null {
if (!url) return null;
const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/;
const match = url.match(regExp);
return (match && match[2].length === 11) ? match[2] : null;
}
/**
* Sub-component for Navigation Content
*/
function NavigationContent({ course, currentLesson }: { course: CourseData, currentLesson: CurrentLessonData }) {
return (
Daftar Materi
{course.modules.map((module) => (
{module.lessons.map((lesson) => (
-
{lesson.is_completed ? (
) : lesson.id === currentLesson.id ? (
) : (
)}
{lesson.title}
))}
))}
);
}
export default function Player({ course, currentLesson, progress, auth }: PlayerProps) {
const [sidebarOpen, setSidebarOpen] = useState(true);
const [isPlaying, setIsPlaying] = useState(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: [], // Prevent any data reload to keep it "silent"
// @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);
};
const videoSource = currentLesson.video_url ? {
type: 'video' as const,
sources: [{
src: getYouTubeId(currentLesson.video_url) || currentLesson.video_url,
provider: currentLesson.video_url.includes('youtube') ? 'youtube' as const : 'html5' as const,
}],
} : null;
return (
{/* Mobile Navigation Trigger */}
{course.title}
Kurikulum Kursus
{auth.user.xp_points} XP
}
>
{/* Main Content Area */}
{/* 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 && (
)}
{/* Vocabulary Section */}
{currentLesson.vocabularies && currentLesson.vocabularies.length > 0 && (
{currentLesson.vocabularies.map((vocab) => (
vocab.audio_url && playAudio(vocab.audio_url, vocab.id)}
className={`w-12 h-12 rounded-2xl flex items-center justify-center transition-all cursor-pointer ${
isPlaying === vocab.id ? 'bg-nihonbuzz-red text-white scale-95 shadow-inner' : 'bg-gray-50 text-gray-400 group-hover:bg-nihonbuzz-red/5 group-hover:text-nihonbuzz-red'
}`}
>
{isPlaying === vocab.id ? : }
{vocab.reading || ''}
{vocab.type || ''}
{vocab.meaning_id || ''}
{vocab.romaji || ''}
))}
)}
{/* Navigation Footer */}
NihonBuzz Academy
Master Japanese Effortlessly
{/* Sidebar - Desktop Navigation */}
);
}