Seed: education template (18 files)

This commit is contained in:
2026-07-23 22:12:22 +00:00
parent 09e73a6186
commit 571ddcbded
+118
View File
@@ -0,0 +1,118 @@
import { useState } from "react";
import { Link } from "react-router-dom";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Card, CardContent } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Search, Star, Clock, BookOpen, Users } from "lucide-react";
const courses = [
{ id: 1, title: "Full-Stack Web Development Bootcamp", instructor: "Dr. Sarah Chen", category: "Web Dev", level: "Beginner", duration: "40h", lessons: 120, rating: 4.9, reviews: 1240, price: "$89", gradient: "from-indigo-500 to-purple-600" },
{ id: 2, title: "Data Science & Machine Learning A-Z", instructor: "Prof. James Rivera", category: "Data Science", level: "Intermediate", duration: "35h", lessons: 95, rating: 4.8, reviews: 980, price: "$79", gradient: "from-amber-500 to-orange-600" },
{ id: 3, title: "UI/UX Design Masterclass", instructor: "Maya Patel", category: "Design", level: "Beginner", duration: "25h", lessons: 68, rating: 4.9, reviews: 870, price: "$69", gradient: "from-emerald-500 to-teal-600" },
{ id: 4, title: "AI & Deep Learning with Python", instructor: "Dr. Alex Kim", category: "AI/ML", level: "Advanced", duration: "50h", lessons: 140, rating: 4.7, reviews: 650, price: "$99", gradient: "from-rose-500 to-pink-600" },
{ id: 5, title: "Digital Business Strategy", instructor: "Rachel Torres", category: "Business", level: "Intermediate", duration: "20h", lessons: 55, rating: 4.8, reviews: 720, price: "$59", gradient: "from-cyan-500 to-blue-600" },
{ id: 6, title: "Growth Marketing & Analytics", instructor: "David Park", category: "Marketing", level: "Beginner", duration: "18h", lessons: 48, rating: 4.6, reviews: 540, price: "$69", gradient: "from-violet-500 to-fuchsia-600" },
];
export default function CoursesPage() {
const [search, setSearch] = useState("");
const [category, setCategory] = useState("all");
const [level, setLevel] = useState("all");
const filtered = courses.filter((c) => {
if (search && !c.title.toLowerCase().includes(search.toLowerCase())) return false;
if (category !== "all" && c.category !== category) return false;
if (level !== "all" && c.level !== level) return false;
return true;
});
return (
<div className="min-h-screen bg-white dark:bg-slate-950">
<Header />
<section className="pt-32 pb-8">
<div className="mx-auto max-w-7xl px-6">
<h1 className="text-3xl sm:text-4xl font-bold mb-2 animate-fade-up">Explore Our Courses</h1>
<p className="text-muted-foreground mb-8 animate-fade-up" style={{ animationDelay: "0.05s" }}>Find the perfect course to advance your skills and career.</p>
<div className="flex flex-col md:flex-row gap-4 mb-8 animate-fade-up" style={{ animationDelay: "0.1s" }}>
<div className="relative flex-1">
<Search className="absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" />
<Input placeholder="Search courses..." value={search} onChange={(e) => setSearch(e.target.value)} className="pl-10 rounded-xl" />
</div>
<Select value={category} onValueChange={setCategory}>
<SelectTrigger className="w-full md:w-48 rounded-xl"><SelectValue placeholder="Category" /></SelectTrigger>
<SelectContent>
<SelectItem value="all">All Categories</SelectItem>
<SelectItem value="Web Dev">Web Dev</SelectItem>
<SelectItem value="Data Science">Data Science</SelectItem>
<SelectItem value="Design">Design</SelectItem>
<SelectItem value="AI/ML">AI/ML</SelectItem>
<SelectItem value="Business">Business</SelectItem>
<SelectItem value="Marketing">Marketing</SelectItem>
</SelectContent>
</Select>
<Select value={level} onValueChange={setLevel}>
<SelectTrigger className="w-full md:w-44 rounded-xl"><SelectValue placeholder="Level" /></SelectTrigger>
<SelectContent>
<SelectItem value="all">All Levels</SelectItem>
<SelectItem value="Beginner">Beginner</SelectItem>
<SelectItem value="Intermediate">Intermediate</SelectItem>
<SelectItem value="Advanced">Advanced</SelectItem>
</SelectContent>
</Select>
</div>
</div>
</section>
<section className="pb-20">
<div className="mx-auto max-w-7xl px-6">
<div className="grid sm:grid-cols-2 lg:grid-cols-3 gap-6">
{filtered.map((c, i) => (
<Card key={c.id} className="group bg-white/70 dark:bg-slate-900/70 backdrop-blur border-slate-200/60 dark:border-slate-800/60 rounded-2xl overflow-hidden hover:-translate-y-1 hover:shadow-xl transition-all duration-300 animate-fade-up" style={{ animationDelay: `\${i * 0.08}s` }}>
<div className={`h-40 bg-gradient-to-br \${c.gradient} flex items-center justify-center`}>
<BookOpen className="h-12 w-12 text-white/80" />
</div>
<CardContent className="p-5">
<div className="flex gap-2 mb-2">
<Badge variant="secondary" className="text-xs">{c.category}</Badge>
<Badge variant="outline" className="text-xs">{c.level}</Badge>
</div>
<h3 className="font-semibold text-lg leading-snug mb-1">{c.title}</h3>
<p className="text-sm text-muted-foreground mb-3">{c.instructor}</p>
<div className="flex items-center gap-4 text-xs text-muted-foreground mb-3">
<span className="flex items-center gap-1"><Clock className="h-3.5 w-3.5" />{c.duration}</span>
<span className="flex items-center gap-1"><BookOpen className="h-3.5 w-3.5" />{c.lessons} lessons</span>
</div>
<div className="flex items-center justify-between">
<div className="flex items-center gap-1">
<Star className="h-4 w-4 fill-amber-400 text-amber-400" />
<span className="text-sm font-medium">{c.rating}</span>
<span className="text-xs text-muted-foreground">({c.reviews.toLocaleString()})</span>
</div>
<span className="text-lg font-bold text-indigo-600 dark:text-indigo-400">{c.price}</span>
</div>
<Button asChild className="w-full mt-4 bg-indigo-600 hover:bg-indigo-700 text-white rounded-full active:scale-[0.97] transition-all">
<Link to={`/course/\${c.id}`}>View Course</Link>
</Button>
</CardContent>
</Card>
))}
</div>
{filtered.length === 0 && (
<div className="text-center py-16 text-muted-foreground">
<BookOpen className="h-12 w-12 mx-auto mb-4 opacity-40" />
<p>No courses match your filters. Try adjusting your search.</p>
</div>
)}
</div>
</section>
<Footer />
</div>
);
}