Yimaru-Admin/src/pages/content-management/ProgramDetailPage.tsx
2026-04-24 15:20:51 +03:00

274 lines
10 KiB
TypeScript

import { Link, useParams, useNavigate } from "react-router-dom";
import {
ArrowLeft,
Plus,
FileText,
ClipboardList,
ListChecks,
ChevronRight,
X,
Upload,
} from "lucide-react";
import { Button } from "../../components/ui/button";
import { Card } from "../../components/ui/card";
import {
Dialog,
DialogContent,
DialogHeader,
DialogTitle,
DialogTrigger,
DialogClose,
} from "../../components/ui/dialog";
import { Input } from "../../components/ui/input";
import { Select } from "../../components/ui/select";
import uploadIcon from "../../assets/icons/upload.png";
export function ProgramDetailPage() {
const navigate = useNavigate();
const { programType } = useParams<{ programType: string }>();
// Mock data for "proficiency" program type
const programs: Record<string, any> = {
proficiency: {
title: "English Proficiency Exams",
description:
"Manage exam-based learning programs such as Duolingo and IELTS.",
courses: [
{
id: "duolingo",
name: "Duolingo English Test",
description:
"Adaptive exam-style practice for speaking, writing, reading, and listening.",
coursesCount: 6,
questionTypesCount: 13,
logo: (
<div className="h-14 w-14 rounded-full bg-[#FFB800] flex items-center justify-center relative overflow-hidden">
{/* Simple Duolingo-like representation if image not available */}
<div className="absolute inset-0 bg-gradient-to-br from-white/20 to-transparent" />
<div className="h-8 w-8 bg-white rounded-full flex items-center justify-center">
<div className="h-4 w-4 bg-[#FFB800] rounded-sm transform rotate-45" />
</div>
</div>
),
buttonText: "Manage Detail",
},
{
id: "ielts",
name: "IELTS Academic",
description:
"Full preparation for IELTS speaking, writing, listening, and reading.",
coursesCount: 4,
questionTypesCount: 18,
logo: (
<div className="flex items-center gap-1">
<span className="text-[28px] font-black tracking-tighter text-[#E11D48] ">
IELTS
</span>
<span className="text-[8px] font-bold text-[#E11D48] mt-2 tracking-widest uppercase">
</span>
</div>
),
buttonText: "View Detail",
},
],
},
"skill-based": {
title: "Skill-Based Courses",
description:
"Practice-focused communication and skills training for real-world scenarios.",
courses: [], // To be implemented or shown if needed
},
};
const currentProgram =
programs[programType || "proficiency"] || programs.proficiency;
return (
<div className="space-y-8 animate-in fade-in duration-500 pb-10">
{/* Navigation */}
<Link
to="/new-content/courses"
className="flex items-center gap-2.5 text-[15px] font-semibold text-grayScale-600 hover:text-brand-500 transition-colors pt-4 group"
>
<ArrowLeft className="h-5 w-5 transition-transform group-hover:-translate-x-1" />
Back
</Link>
{/* Header section */}
<div className="flex items-start justify-between">
<div className="space-y-2">
<h1 className="text-[26px] font-medium tracking-tight text-grayScale-900">
{currentProgram.title}
</h1>
<p className="max-w-2xl text-[15px] font-medium text-grayScale-500">
{currentProgram.description}
</p>
</div>
<div className="flex items-center gap-3 pt-2">
<Dialog>
<DialogTrigger asChild>
<Button className="h-10 px-6 rounded-[6px] bg-brand-500 font-bold text-white transition-all flex items-center gap-2">
<Plus className="h-5 w-5" />
Create Course
</Button>
</DialogTrigger>
<DialogContent className="max-w-[600px] p-0 border-none rounded-[16px] overflow-hidden">
<div className="bg-white">
<DialogHeader className="px-8 py-6 border-b border-grayScale-200 flex flex-row items-center justify-between">
<DialogTitle className="text-[20px] font-bold relative top-2 text-grayScale-900">
Create Course
</DialogTitle>
</DialogHeader>
<div className="p-8 space-y-8">
<div className="space-y-3">
<label className="text-[15px] text-grayScale-800">
Name
</label>
<Input
placeholder="e.g. TOEFL, IELTS"
className="h-12 border-grayScale-400 rounded-[8px] px-4 placeholder:text-grayScale-400 text-[15px] focus:ring-brand-500/20"
/>
</div>
<div className="space-y-3">
<label className="text-[15px] text-grayScale-800">
Course Order
</label>
<Select defaultValue="1">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</Select>
</div>
{/* Thumbnail Field */}
<div className="space-y-3">
<label className="text-[15px] text-grayScale-800">
Thumbnail
</label>
<div className="relative group cursor-pointer">
<div className="flex flex-col items-center justify-center rounded-[12px] border-2 border-dashed border-grayScale-400 bg-white py-8 px-10 transition-all ">
<div className="mb-4">
<img
src={uploadIcon}
alt="Upload icon"
className="h-10 w-10"
/>
</div>
<p className="text-[15px]">
<span className="text-brand-500 font-bold hover:underline">
Click to upload
</span>{" "}
<span className="text-grayScale-500">
or drag and drop
</span>
</p>
<p className="mt-1.5 text-[12px] text-grayScale-400 uppercase tracking-widest">
JPG, PNG (MAX 1 MB)
</p>
</div>
</div>
</div>
</div>
<div className="px-8 py-6 bg-grayScale-50/30 border-t border-grayScale-50 flex justify-end gap-3">
<DialogClose asChild>
<Button
variant="outline"
className="h-11 px-8 rounded-[8px] border-grayScale-200 text-grayScale-700 font-bold"
>
Cancel
</Button>
</DialogClose>
<Button className="h-11 px-8 rounded-[8px] bg-brand-500 text-white font-bold hover:bg-brand-600">
Create Program
</Button>
</div>
</div>
</DialogContent>
</Dialog>
<Button
variant="outline"
className="h-10 px-6 rounded-[6px] border-brand-500 text-brand-500 font-bold flex items-center gap-2"
onClick={() =>
navigate(`/new-content/courses/${programType}/attach-practice`)
}
>
<FileText className="h-5 w-5" />
Attach Practice
</Button>
</div>
</div>
{/* Gradient Divider */}
<div className="relative">
<div className="absolute inset-0 flex items-center" aria-hidden="true">
<div className="w-full border-t border-grayScale-200" />
</div>
<div className="relative flex justify-center">
<div
className="h-[0.5px] w-full opacity-20 rounded-full"
style={{
background: "gray",
}}
/>
</div>
</div>
{/* Cards Grid */}
<div className="flex flex-wrap gap-8 mt-10">
{currentProgram.courses.map((course: any) => (
<Card
key={course.id}
className="bg-white w-[500px] rounded-[20px] border border-grayScale-100 p-6 flex flex-col items-start shadow-sm hover:shadow-md transition-shadow"
>
{/* Logo */}
<div className="h-16 flex items-center">{course.logo}</div>
{/* Content */}
<div className="space-y-4 pt-2 flex-1">
<h3 className="text-[18px] font-medium text-grayScale-900">
{course.name}
</h3>
<p className="text-[14px] text-grayScale-500 font-medium">
{course.description}
</p>
</div>
{/* Badges/Stats */}
<div className="flex items-center pt-4 gap-4">
<div className="h-10 px-4 rounded-[6px] bg-grayScale-100 border border-grayScale-100 flex items-center gap-2 text-grayScale-700">
<ClipboardList className="h-3 w-3 text-grayScale-400" />
<span className="text-[12px] ">
{course.coursesCount} Courses
</span>
</div>
<div className="h-10 px-4 rounded-[6px] bg-grayScale-100 border border-grayScale-100 flex items-center gap-2 text-grayScale-700">
<ListChecks className="h-3 w-3 text-grayScale-400" />
<span className="text-[12px] ">
{course.questionTypesCount} Question Types
</span>
</div>
</div>
{/* Action Button */}
<Button
className="w-full mt-4 h-10 bg-brand-500 text-white rounded-[8px] font-bold flex items-center justify-center gap-2 group/btn"
onClick={() =>
navigate(`/new-content/courses/${programType}/${course.id}`)
}
>
{course.buttonText}
<ChevronRight className="h-5 w-5 transition-transform group-hover/btn:translate-x-1" />
</Button>
</Card>
))}
</div>
</div>
);
}