134 lines
6.2 KiB
TypeScript
134 lines
6.2 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { BookOpen, Calendar, ChevronRight, FolderOpen, Info, Presentation, Users } from 'lucide-react';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '../../components/ui/card';
|
|
import { Button } from '../../components/ui/button';
|
|
import { Progress } from '../../components/ui/progress';
|
|
import { useGetAssignedHrProgrammesQuery } from '../../redux/services/learnersApi';
|
|
|
|
const ProgrammesPage: React.FC = () => {
|
|
const { data, isLoading, isError } = useGetAssignedHrProgrammesQuery({
|
|
limit: 10,
|
|
start: 0,
|
|
});
|
|
const [openProgrammeId, setOpenProgrammeId] = useState<string | null>(null);
|
|
|
|
const programmeItems = data?.data.programme_items ?? [];
|
|
|
|
const formatDate = (date: string) =>
|
|
new Date(date).toLocaleDateString('en-GB', {
|
|
day: '2-digit',
|
|
month: 'short',
|
|
year: 'numeric',
|
|
});
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<h1 className="text-3xl font-bold tracking-tight">My Programs</h1>
|
|
|
|
{isLoading && <p className="text-sm text-muted-foreground">Loading programmes...</p>}
|
|
|
|
{isError && <p className="text-sm text-red-600">Failed to load programmes. Please try again.</p>}
|
|
|
|
{!isLoading && !isError && programmeItems.length === 0 && (
|
|
<p className="text-sm text-muted-foreground">No programmes found.</p>
|
|
)}
|
|
|
|
<div className="space-y-4">
|
|
{programmeItems.map((programme) => {
|
|
const isOpen = openProgrammeId === programme.id;
|
|
|
|
return (
|
|
<Card
|
|
key={programme.id}
|
|
className="gap-0 overflow-hidden border border-violet-100 bg-gradient-to-br from-violet-50 via-white to-fuchsia-50"
|
|
>
|
|
<CardHeader
|
|
className={`cursor-pointer !pt-4 !pb-4 transition-colors duration-200 ${isOpen ? 'border-b border-violet-100' : 'border-b border-transparent'}`}
|
|
onClick={() => setOpenProgrammeId((prev) => (prev === programme.id ? null : programme.id))}
|
|
>
|
|
<div className="flex items-start justify-between gap-3">
|
|
<div className="flex items-start gap-2">
|
|
<ChevronRight
|
|
className={`mt-1 h-5 w-5 text-violet-800 transition-transform ${isOpen ? 'rotate-90' : 'rotate-0'}`}
|
|
/>
|
|
<div className="space-y-2">
|
|
<CardTitle className="text-xl font-semibold leading-tight text-violet-950">{programme.programme_title}</CardTitle>
|
|
<div className="flex flex-wrap items-center gap-4 text-sm text-muted-foreground">
|
|
<span>{programme.progress ?? 0}% Complete</span>
|
|
<span className="flex items-center gap-1">
|
|
<Calendar className="h-4 w-4" />
|
|
Ends: {formatDate(programme.end_date)}
|
|
</span>
|
|
<span className="flex items-center gap-1">
|
|
<BookOpen className="h-4 w-4" />
|
|
{programme.courses} Courses
|
|
</span>
|
|
<span className="flex items-center gap-1">
|
|
<Presentation className="h-4 w-4" />
|
|
{programme.webinars} Webinars
|
|
</span>
|
|
<span className="flex items-center gap-1">
|
|
<FolderOpen className="h-4 w-4" />
|
|
{programme.resources} Resources
|
|
</span>
|
|
<span className="flex items-center gap-1">
|
|
<Users className="h-4 w-4" />
|
|
{programme.classes} Classes
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<Button variant="outline" className="shrink-0 border-violet-300 text-violet-800">
|
|
<Info className="mr-2 h-4 w-4" />
|
|
Programme Info
|
|
</Button>
|
|
</div>
|
|
</CardHeader>
|
|
|
|
<div
|
|
className={`grid transition-all duration-300 ease-in-out ${isOpen ? 'grid-rows-[1fr] opacity-100' : 'pointer-events-none grid-rows-[0fr] opacity-0'}`}
|
|
>
|
|
<div className="overflow-hidden">
|
|
<CardContent className="space-y-5 pt-4">
|
|
<div className="space-y-2 border-b border-violet-100 pb-4">
|
|
<h3 className="text-lg font-semibold leading-tight text-foreground">Programme Summary</h3>
|
|
<div className="flex flex-wrap items-center gap-4 text-sm text-muted-foreground">
|
|
<span className="flex items-center gap-1">
|
|
<BookOpen className="h-4 w-4 text-[#061a72]" />
|
|
{programme.courses} Courses
|
|
</span>
|
|
<span className="flex items-center gap-1">
|
|
<FolderOpen className="h-4 w-4 text-[#061a72]" />
|
|
{programme.resources} Resources
|
|
</span>
|
|
<span className="flex items-center gap-1">
|
|
<Presentation className="h-4 w-4 text-[#061a72]" />
|
|
{programme.webinars} Webinars
|
|
</span>
|
|
<span className="flex items-center gap-1">
|
|
<Users className="h-4 w-4 text-[#061a72]" />
|
|
{programme.classes} Classes
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="space-y-1">
|
|
<div className="flex items-center justify-between text-sm">
|
|
<span className="font-medium">Progress</span>
|
|
<span className="font-medium">{programme.progress ?? 0}%</span>
|
|
</div>
|
|
<Progress value={programme.progress ?? 0} className="h-2 bg-slate-200" />
|
|
</div>
|
|
</CardContent>
|
|
</div>
|
|
</div>
|
|
</Card>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ProgrammesPage;
|