mirror of
https://github.com/nihonbuzz/nihonbuzz-academy.git
synced 2026-01-26 05:25:37 +07:00
122 lines
4.9 KiB
TypeScript
122 lines
4.9 KiB
TypeScript
import DashboardLayout from '@/Layouts/DashboardLayout';
|
|
import { Head, Link, useForm } from '@inertiajs/react';
|
|
import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/Components/ui/card";
|
|
import { Button } from "@/Components/ui/button";
|
|
import { Badge } from "@/Components/ui/badge";
|
|
import { BookOpen, CheckCircle2, Play } from "lucide-react";
|
|
|
|
interface Course {
|
|
id: string;
|
|
title: string;
|
|
description: string;
|
|
thumbnail: string;
|
|
slug: string;
|
|
modulesCount: number;
|
|
isEnrolled: boolean;
|
|
}
|
|
|
|
interface Level {
|
|
id: string;
|
|
name: string;
|
|
code: string;
|
|
courses: Course[];
|
|
}
|
|
|
|
interface Props {
|
|
levels: Level[];
|
|
}
|
|
|
|
export default function Library({ levels }: Props) {
|
|
return (
|
|
<DashboardLayout
|
|
header={
|
|
<div className="flex flex-col gap-1">
|
|
<h2 className="text-2xl font-bold tracking-tight">Galeri Kursus</h2>
|
|
<p className="text-muted-foreground text-sm">Pilih materi yang ingin kamu pelajari hari ini.</p>
|
|
</div>
|
|
}
|
|
>
|
|
<Head title="Galeri Kursus" />
|
|
|
|
<div className="space-y-12 animate-in fade-in duration-700">
|
|
{levels.length > 0 ? levels.map((level) => (
|
|
<div key={level.id} className="space-y-6">
|
|
<div className="flex items-center gap-3">
|
|
<div className="h-8 w-1 bg-primary rounded-full" />
|
|
<h3 className="text-xl font-black tracking-tight">{level.name} ({level.code})</h3>
|
|
</div>
|
|
|
|
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
{level.courses.map((course) => (
|
|
<CourseCard key={course.id} course={course} />
|
|
))}
|
|
</div>
|
|
</div>
|
|
)) : (
|
|
<div className="text-center py-20">
|
|
<p className="text-muted-foreground">Belum ada materi tersedia saat ini.</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</DashboardLayout>
|
|
);
|
|
}
|
|
|
|
function CourseCard({ course }: { course: Course }) {
|
|
const { post, processing } = useForm();
|
|
|
|
const handleEnroll = () => {
|
|
post(route('courses.enroll', course.slug));
|
|
};
|
|
|
|
return (
|
|
<Card className="group border-border/40 bg-card/40 backdrop-blur-xl overflow-hidden hover:shadow-2xl hover:shadow-primary/5 transition-all duration-500 hover:-translate-y-1 flex flex-col h-full">
|
|
<div className="relative aspect-video overflow-hidden">
|
|
<img
|
|
src={course.thumbnail}
|
|
alt={course.title}
|
|
className="object-cover w-full h-full transition-transform duration-700 group-hover:scale-110"
|
|
/>
|
|
<div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent opacity-0 group-hover:opacity-100 transition-opacity" />
|
|
|
|
{course.isEnrolled && (
|
|
<Badge className="absolute top-3 right-3 bg-green-500 hover:bg-green-600 text-white border-none gap-1">
|
|
<CheckCircle2 size={12} />
|
|
Terdaftar
|
|
</Badge>
|
|
)}
|
|
</div>
|
|
|
|
<CardHeader className="p-5 flex-1">
|
|
<div className="flex items-center gap-2 mb-2">
|
|
<Badge variant="outline" className="text-[10px] font-bold uppercase tracking-widest border-primary/20 text-primary">
|
|
{course.modulesCount} Materi
|
|
</Badge>
|
|
</div>
|
|
<CardTitle className="text-lg font-bold group-hover:text-primary transition-colors">{course.title}</CardTitle>
|
|
<CardDescription className="line-clamp-2 text-xs mt-2 font-medium leading-relaxed">
|
|
{course.description}
|
|
</CardDescription>
|
|
</CardHeader>
|
|
|
|
<CardFooter className="p-5 pt-0 mt-auto">
|
|
{course.isEnrolled ? (
|
|
<Button asChild className="w-full rounded-xl font-bold bg-primary/10 hover:bg-primary/20 text-primary shadow-none border-none">
|
|
<Link href={route('courses.learn', course.slug)}>
|
|
Lanjutkan Belajar <Play className="ml-2 w-3 h-3 fill-current" />
|
|
</Link>
|
|
</Button>
|
|
) : (
|
|
<Button
|
|
onClick={handleEnroll}
|
|
disabled={processing}
|
|
className="w-full rounded-xl font-bold bg-primary hover:bg-primary/90 shadow-lg shadow-primary/20"
|
|
>
|
|
{processing ? 'Memproses...' : 'Daftar Sekarang'}
|
|
</Button>
|
|
)}
|
|
</CardFooter>
|
|
</Card>
|
|
);
|
|
}
|