veza/apps/web/src/components/education/CourseCard.tsx

108 lines
4.2 KiB
TypeScript

import React from 'react';
import { Card } from '../ui/card';
import { ProgressBar } from '../ui/progress';
import { Course } from '../../types';
import { PlayCircle, Clock, Star, Users, CheckCircle } from 'lucide-react';
interface CourseCardProps {
course: Course;
onClick: (course: Course) => void;
showProgress?: boolean;
}
export const CourseCard: React.FC<CourseCardProps> = ({
course,
onClick,
showProgress = false,
}) => {
return (
<Card
variant="default"
className="group p-0 overflow-hidden cursor-pointer hover:border-kodo-cyan/50 transition-all flex flex-col h-full"
onClick={() => onClick(course)}
>
{/* Cover */}
<div className="relative aspect-video bg-gray-900 overflow-hidden">
<img
src={course.thumbnailUrl}
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110 opacity-90 group-hover:opacity-100"
alt={course.title}
/>
<div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center backdrop-blur-sm">
<PlayCircle className="w-12 h-12 text-white fill-current opacity-80" />
</div>
{course.certificateAvailable && (
<div className="absolute top-2 right-2 bg-kodo-gold/90 text-black text-[10px] font-bold px-2 py-0.5 rounded shadow-lg flex items-center gap-1">
<Star className="w-3 h-3 fill-current" /> CERTIFIED
</div>
)}
<div className="absolute bottom-2 left-2 bg-black/70 text-white text-xs px-2 py-1 rounded font-mono flex items-center gap-1">
<Clock className="w-3 h-3" /> {course.duration}
</div>
</div>
{/* Content */}
<div className="p-4 flex flex-col flex-1">
<div className="flex justify-between items-start mb-2">
<span
className={`text-[10px] px-2 py-0.5 rounded uppercase font-bold ${
course.level === 'Advanced'
? 'bg-kodo-red/20 text-kodo-red'
: course.level === 'Intermediate'
? 'bg-kodo-gold/20 text-kodo-gold'
: 'bg-kodo-lime/20 text-kodo-lime'
}`}
>
{course.level}
</span>
{course.rating && (
<div className="flex items-center gap-1 text-xs text-kodo-gold font-bold">
<Star className="w-3 h-3 fill-current" /> {course.rating}
</div>
)}
</div>
<h3 className="font-bold text-white text-base mb-1 line-clamp-2 group-hover:text-kodo-cyan transition-colors">
{course.title}
</h3>
<p className="text-gray-400 text-xs mb-3">by {course.instructor}</p>
<div className="mt-auto pt-2">
{showProgress && course.progress !== undefined ? (
<div className="space-y-2">
<div className="flex justify-between text-xs text-gray-400">
<span>Progress</span>
<span
className={
course.progress === 100 ? 'text-kodo-lime' : 'text-white'
}
>
{course.progress}%
</span>
</div>
<ProgressBar
value={course.progress}
color={course.progress === 100 ? 'lime' : 'cyan'}
/>
{course.progress === 100 && (
<div className="flex items-center gap-1 text-xs text-kodo-lime mt-1 font-bold">
<CheckCircle className="w-3 h-3" /> Completed
</div>
)}
</div>
) : (
<div className="flex justify-between items-center border-t border-white/5 pt-3">
<div className="flex items-center gap-1 text-xs text-gray-500">
<Users className="w-3 h-3" />{' '}
{(course.studentCount || 0).toLocaleString()} students
</div>
<span className="font-mono font-bold text-white">
{course.price && course.price > 0 ? `$${course.price}` : 'Free'}
</span>
</div>
)}
</div>
</div>
</Card>
);
};