From 1f625d7bf408339695d91f8e1491c35a64ac25d8 Mon Sep 17 00:00:00 2001 From: "Builder.io" Date: Wed, 12 Nov 2025 04:54:51 +0000 Subject: [PATCH] Create Foundation Curriculum public page cgen-33562ee7c31840ee95fc445e4ec56dda --- .../pages/foundation/FoundationCurriculum.tsx | 333 ++++++++++++++++++ 1 file changed, 333 insertions(+) create mode 100644 client/pages/foundation/FoundationCurriculum.tsx diff --git a/client/pages/foundation/FoundationCurriculum.tsx b/client/pages/foundation/FoundationCurriculum.tsx new file mode 100644 index 00000000..f0d66434 --- /dev/null +++ b/client/pages/foundation/FoundationCurriculum.tsx @@ -0,0 +1,333 @@ +import { useState, useEffect } from "react"; +import Layout from "@/components/Layout"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; +import { useNavigate, useSearchParams } from "react-router-dom"; +import { Badge } from "@/components/ui/badge"; +import { + ArrowLeft, + BookOpen, + Clock, + Users, + Search, + Loader2, +} from "lucide-react"; +import { Input } from "@/components/ui/input"; + +interface Course { + id: string; + slug: string; + title: string; + description: string; + category: string; + difficulty: string; + instructor_id: string; + instructor_name: string; + instructor_avatar?: string; + cover_image_url: string; + estimated_hours: number; +} + +const CATEGORIES = [ + { value: "game-dev", label: "Game Development" }, + { value: "web-dev", label: "Web Development" }, + { value: "ai-ml", label: "AI & Machine Learning" }, + { value: "design", label: "Design" }, + { value: "business", label: "Business" }, +]; + +const DIFFICULTIES = [ + { value: "beginner", label: "Beginner" }, + { value: "intermediate", label: "Intermediate" }, + { value: "advanced", label: "Advanced" }, +]; + +const difficultyColors: Record = { + beginner: "bg-green-500/20 text-green-300", + intermediate: "bg-amber-500/20 text-amber-300", + advanced: "bg-red-500/20 text-red-300", +}; + +export default function FoundationCurriculum() { + const navigate = useNavigate(); + const [searchParams, setSearchParams] = useSearchParams(); + const [courses, setCourses] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [search, setSearch] = useState(searchParams.get("search") || ""); + const [selectedCategory, setSelectedCategory] = useState( + searchParams.get("category") || null, + ); + const [selectedDifficulty, setSelectedDifficulty] = useState( + searchParams.get("difficulty") || null, + ); + + useEffect(() => { + const fetchCourses = async () => { + setIsLoading(true); + try { + const params = new URLSearchParams(); + if (selectedCategory) params.set("category", selectedCategory); + if (selectedDifficulty) params.set("difficulty", selectedDifficulty); + + const response = await fetch(`/api/foundation/courses?${params}`); + if (!response.ok) throw new Error("Failed to fetch courses"); + + let data = await response.json(); + + // Client-side filtering by search + if (search) { + data = data.filter( + (course: Course) => + course.title.toLowerCase().includes(search.toLowerCase()) || + course.description.toLowerCase().includes(search.toLowerCase()), + ); + } + + setCourses(data); + } catch (error) { + console.error("Failed to fetch courses:", error); + setCourses([]); + } finally { + setIsLoading(false); + } + }; + + fetchCourses(); + }, [selectedCategory, selectedDifficulty]); + + const handleSearch = (e: React.FormEvent) => { + e.preventDefault(); + const params = new URLSearchParams(); + if (search) params.set("search", search); + if (selectedCategory) params.set("category", selectedCategory); + if (selectedDifficulty) params.set("difficulty", selectedDifficulty); + setSearchParams(params); + }; + + return ( + +
+ {/* Background */} +
+
+
+
+ +
+ {/* Header */} +
+
+ +
+ +

Curriculum

+
+

+ Learn from industry experts with free and premium courses +

+
+
+ + {/* Search & Filters */} +
+
+ {/* Search */} +
+
+ + setSearch(e.target.value)} + className="pl-10 bg-slate-800 border-slate-700 text-white" + /> + +
+
+ + {/* Category Filter */} +
+

+ Category +

+
+ + {CATEGORIES.map((cat) => ( + + ))} +
+
+ + {/* Difficulty Filter */} +
+

+ Difficulty +

+
+ + {DIFFICULTIES.map((diff) => ( + + ))} +
+
+
+
+ + {/* Courses Grid */} +
+
+ {isLoading ? ( +
+ +
+ ) : courses.length === 0 ? ( + + + +

+ No courses found matching your criteria +

+
+
+ ) : ( +
+ {courses.map((course) => ( + + navigate( + `/foundation/curriculum/${course.slug}`, + ) + } + > + {course.cover_image_url && ( + {course.title} + )} + +
+
+

+ {course.title} +

+

+ {course.description} +

+
+
+ +
+ + {course.difficulty.charAt(0).toUpperCase() + + course.difficulty.slice(1)} + + {course.category && ( + + {course.category} + + )} +
+ +
+
+ + {course.estimated_hours} hours +
+ {course.instructor_name && ( +
+ + {course.instructor_name} +
+ )} +
+ + +
+
+ ))} +
+ )} +
+
+
+
+ + ); +}