From e7272dd001769e45f928723494e2739eafe5a041 Mon Sep 17 00:00:00 2001 From: Arik Chakma Date: Tue, 26 Nov 2024 08:41:55 +0600 Subject: [PATCH] feat: course landing page --- .../CourseLanding/CourseChapterItem.tsx | 91 ++++++ .../CourseLanding/CourseFloatingSidebar.tsx | 60 ++++ .../CourseLanding/CourseInfoCard.tsx | 18 ++ .../CourseLanding/CourseLanding.tsx | 284 +++++++++++++----- 4 files changed, 370 insertions(+), 83 deletions(-) create mode 100644 src/components/CourseLanding/CourseChapterItem.tsx create mode 100644 src/components/CourseLanding/CourseFloatingSidebar.tsx create mode 100644 src/components/CourseLanding/CourseInfoCard.tsx diff --git a/src/components/CourseLanding/CourseChapterItem.tsx b/src/components/CourseLanding/CourseChapterItem.tsx new file mode 100644 index 000000000..269287044 --- /dev/null +++ b/src/components/CourseLanding/CourseChapterItem.tsx @@ -0,0 +1,91 @@ +import { BookIcon, ChevronDownIcon, CodeXmlIcon } from 'lucide-react'; +import { cn } from '../../lib/classname'; +import type { LessonFrontmatter } from '../../lib/course'; +import { useMemo, useState } from 'react'; + +type CourseChapterItemProps = { + title: string; + lessons: { + type: string; + title: string; + }[]; + className?: string; +}; + +export function CourseChapterItem(props: CourseChapterItemProps) { + const { title, lessons, className } = props; + + const [isOpen, setIsOpen] = useState(false); + + const { excercises, textualLessons } = useMemo(() => { + const excercises: CourseChapterItemProps['lessons'] = []; + const textualLessons: CourseChapterItemProps['lessons'] = []; + + lessons.forEach((lesson) => { + if (lesson.type === 'quiz' || lesson.type === 'challenge') { + excercises.push(lesson); + } else { + textualLessons.push(lesson); + } + }); + + return { + excercises, + textualLessons, + }; + }, [lessons]); + + return ( +
+
setIsOpen(!isOpen)} + > + {title} + +
+ {textualLessons.length > 0 && ( + + {textualLessons.length} Lesson + {textualLessons.length > 1 ? 's' : ''} + + )} + + {excercises.length > 0 && ( + + {excercises.length} Excerice + {excercises.length > 1 ? 's' : ''} + + )} + + +
+
+ + {isOpen && ( +
+ {lessons.map((lesson, index) => { + return ( +
+ + {lesson.type === 'lesson' ? ( + + ) : ( + + )} + + {lesson.title} +
+ ); + })} +
+ )} +
+ ); +} diff --git a/src/components/CourseLanding/CourseFloatingSidebar.tsx b/src/components/CourseLanding/CourseFloatingSidebar.tsx new file mode 100644 index 000000000..60e68e81a --- /dev/null +++ b/src/components/CourseLanding/CourseFloatingSidebar.tsx @@ -0,0 +1,60 @@ +import { cn } from '../../lib/classname'; + +type CourseFloatingSidebarProps = { + isSticky: boolean; +}; + +export function CourseFloatingSidebar(props: CourseFloatingSidebarProps) { + const { isSticky } = props; + + return ( +
+
+ SQL 101 +
+ +
+ +
+ +
+

Certificate of Completion

+

+ Certificate will be issued on completion +

+
+ SQL 101 +
+
+
+

What you get

+
    +
  • Full access to all the courses
  • +
  • Personalized access using AI
  • +
  • Certificate of Completion
  • +
  • Playground for live-coding
  • +
  • Challenges / Quizes
  • +
+
+
+ ); +} diff --git a/src/components/CourseLanding/CourseInfoCard.tsx b/src/components/CourseLanding/CourseInfoCard.tsx new file mode 100644 index 000000000..133b1abea --- /dev/null +++ b/src/components/CourseLanding/CourseInfoCard.tsx @@ -0,0 +1,18 @@ +import { cn } from '../../lib/classname'; + +type CourseInfoCardProps = { + title: string; + children: React.ReactNode; + className?: string; +}; + +export function CourseInfoCard(props: CourseInfoCardProps) { + const { title, children, className } = props; + + return ( +
+

{title}

+ {children} +
+ ); +} diff --git a/src/components/CourseLanding/CourseLanding.tsx b/src/components/CourseLanding/CourseLanding.tsx index 378f5208c..6f0d084b9 100644 --- a/src/components/CourseLanding/CourseLanding.tsx +++ b/src/components/CourseLanding/CourseLanding.tsx @@ -1,4 +1,5 @@ import { + BookIcon, CalendarIcon, CodeXmlIcon, LetterTextIcon, @@ -9,6 +10,155 @@ import { Rating } from '../Rating/Rating'; import { CourseStatPill } from './CourseStatPill'; import { useRef, useState, useEffect } from 'react'; import { cn } from '../../lib/classname'; +import { CourseInfoCard } from './CourseInfoCard'; +import { ChevronDownIcon } from '../ReactIcons/ChevronDownIcon'; +import { CourseChapterItem } from './CourseChapterItem'; +import { CourseFloatingSidebar } from './CourseFloatingSidebar'; + +const DUMMY_COURSE_CONTENT = [ + { + title: 'Introduction to SQL', + lessons: [ + { + type: 'lesson', + title: 'What is SQL?', + }, + { + type: 'lesson', + title: 'Why use SQL?', + }, + { + type: 'lesson', + title: 'SQL Syntax', + }, + { + type: 'quiz', + title: 'Quiz 1', + }, + { + type: 'challenge', + title: 'Challenge 1', + }, + ], + }, + { + title: 'Basic SQL Queries', + lessons: [ + { + type: 'lesson', + title: 'SELECT Statement', + }, + { + type: 'lesson', + title: 'WHERE Clause', + }, + { + type: 'lesson', + title: 'ORDER BY Clause', + }, + { + type: 'quiz', + title: 'Quiz 2', + }, + { + type: 'challenge', + title: 'Challenge 2', + }, + ], + }, + { + title: 'Advanced SQL Queries', + lessons: [ + { + type: 'lesson', + title: 'JOIN Clause', + }, + { + type: 'lesson', + title: 'GROUP BY Clause', + }, + { + type: 'lesson', + title: 'HAVING Clause', + }, + { + type: 'quiz', + title: 'Quiz 3', + }, + { + type: 'challenge', + title: 'Challenge 3', + }, + ], + }, + { + title: 'SQL Functions', + lessons: [ + { + type: 'lesson', + title: 'COUNT() Function', + }, + { + type: 'lesson', + title: 'SUM() Function', + }, + { + type: 'lesson', + title: 'AVG() Function', + }, + { + type: 'quiz', + title: 'Quiz 4', + }, + { + type: 'challenge', + title: 'Challenge 4', + }, + ], + }, + { + title: 'Database Design', + lessons: [ + { + type: 'lesson', + title: 'Normalization', + }, + { + type: 'lesson', + title: 'Denormalization', + }, + { + type: 'lesson', + title: 'Indexes', + }, + { + type: 'quiz', + title: 'Quiz 5', + }, + { + type: 'challenge', + title: 'Challenge 5', + }, + ], + }, + { + title: 'Optimizing Queries', + lessons: [ + { + type: 'lesson', + title: 'Query Optimization', + }, + { + type: 'lesson', + title: 'Indexing', + }, + { + type: 'lesson', + title: 'Query Caching', + }, + ], + }, +]; export function CourseLanding() { const containerRef = useRef(null); @@ -72,92 +222,60 @@ export function CourseLanding() { -
-
-
-

What you'll learn

-
    -
  • Understand SQL syntax
  • -
  • Write complex queries
  • -
  • Use SQL in real-world scenarios
  • -
  • Optimize your queries
  • -
  • Understand database design
  • -
  • Write complex queries
  • -
-
- -
-

About this Course

- -
-

- SQL 101 is a beginner-friendly course that will teach you - everything you need to know about SQL. It comes with an - interactive playground where you can practice your queries. -

+
+
+
+ +
    +
  • Understand SQL syntax
  • +
  • Write complex queries
  • +
  • Use SQL in real-world scenarios
  • +
  • Optimize your queries
  • +
  • Understand database design
  • +
  • Write complex queries
  • +
+
+ +
+

+ SQL 101 is a beginner-friendly course that will teach you + everything you need to know about SQL. It comes with an + interactive playground where you can practice your queries. +

+

+ The course is divided into multiple sections, each covering a + different aspect of SQL. You'll learn how to write complex + queries, use SQL in real-world scenarios, optimize your + queries, and understand database design. +

+
+
-

- The course is divided into multiple sections, each covering a - different aspect of SQL. You'll learn how to write complex - queries, use SQL in real-world scenarios, optimize your queries, - and understand database design. -

-
+ + {DUMMY_COURSE_CONTENT.map((section, index) => { + const { title, lessons } = section; + const isFirst = index === 0; + const isLast = index === DUMMY_COURSE_CONTENT.length - 1; -
+ return ( + + ); + })} +
-
- -
-
-
- SQL 101 -
- -
- -
- -
-

Certificate of Completion

-

- Certificate will be issued on completion -

- -
- SQL 101 -
-
- -
-

What you get

-
    -
  • Full access to all the courses
  • -
  • Personalized access using AI
  • -
  • Certificate of Completion
  • -
  • Playground for live-coding
  • -
  • Challenges / Quizes
  • -
-
+
+