parent
e0c54941bd
commit
efb8478f56
4 changed files with 197 additions and 4 deletions
@ -0,0 +1,166 @@ |
||||
import { |
||||
CalendarIcon, |
||||
CodeXmlIcon, |
||||
LetterTextIcon, |
||||
ShapesIcon, |
||||
UsersIcon, |
||||
} from 'lucide-react'; |
||||
import { Rating } from '../Rating/Rating'; |
||||
import { CourseStatPill } from './CourseStatPill'; |
||||
import { useRef, useState, useEffect } from 'react'; |
||||
import { cn } from '../../lib/classname'; |
||||
|
||||
export function CourseLanding() { |
||||
const containerRef = useRef<HTMLDivElement>(null); |
||||
const [isSticky, setIsSticky] = useState(false); |
||||
|
||||
useEffect(() => { |
||||
const container = containerRef.current; |
||||
if (!container) { |
||||
return; |
||||
} |
||||
const handleScroll = () => { |
||||
setIsSticky(window.scrollY > container.offsetTop); |
||||
}; |
||||
|
||||
window.addEventListener('scroll', handleScroll); |
||||
return () => window.removeEventListener('scroll', handleScroll); |
||||
}, [containerRef]); |
||||
|
||||
return ( |
||||
<> |
||||
<div className="bg-slate-900 py-5 text-white sm:py-8"> |
||||
<div className="container grid grid-cols-5 gap-6"> |
||||
<div className="col-start-1 col-end-4 space-y-4"> |
||||
<p className="flex items-center gap-1 text-sm text-slate-400"> |
||||
<a>Home</a> / <a>Courses</a> / <a>Learn SQL</a> |
||||
</p> |
||||
|
||||
<h1 className="mt-8 text-5xl font-bold">SQL 101</h1> |
||||
|
||||
<div className="flex items-center gap-2"> |
||||
<CourseStatPill |
||||
icon={ShapesIcon} |
||||
label="Difficulty Beginner" |
||||
className="border-none p-0 text-slate-400" |
||||
/> |
||||
<CourseStatPill |
||||
icon={CalendarIcon} |
||||
label="Updated 5 days ago" |
||||
className="border-none p-0 text-slate-400" |
||||
/> |
||||
</div> |
||||
|
||||
<p className="text-sm"> |
||||
Learn everything you need to know about SQL with an interactive |
||||
playground. It comes with a built-in editor and a database to |
||||
practice your queries. |
||||
</p> |
||||
|
||||
<div className="flex items-center gap-2 text-sm"> |
||||
<span>4.5</span> |
||||
<Rating rating={4.5} /> |
||||
<span>(559 ratings)</span> |
||||
</div> |
||||
|
||||
<div className="flex items-center gap-2"> |
||||
<CourseStatPill icon={UsersIcon} label="4.5k users enrolled" /> |
||||
<CourseStatPill icon={LetterTextIcon} label="20 Lessons" /> |
||||
<CourseStatPill icon={CodeXmlIcon} label="35 Challenges" /> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div className="container grid grid-cols-5 gap-6 py-8" ref={containerRef}> |
||||
<div className="col-start-1 col-end-4 space-y-4"> |
||||
<div className="rounded-md border p-4"> |
||||
<h2 className="text-xl font-medium">What you'll learn</h2> |
||||
<ul className="mt-4 grid grid-cols-2 gap-2"> |
||||
<li>Understand SQL syntax</li> |
||||
<li>Write complex queries</li> |
||||
<li>Use SQL in real-world scenarios</li> |
||||
<li>Optimize your queries</li> |
||||
<li>Understand database design</li> |
||||
<li>Write complex queries</li> |
||||
</ul> |
||||
</div> |
||||
|
||||
<div className="rounded-md border p-4"> |
||||
<h2 className="text-xl font-medium">About this Course</h2> |
||||
|
||||
<div className="prose mt-4"> |
||||
<p> |
||||
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. |
||||
</p> |
||||
|
||||
<p> |
||||
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. |
||||
</p> |
||||
</div> |
||||
|
||||
<div className="h-[1000px]"></div> |
||||
</div> |
||||
</div> |
||||
|
||||
<div className="col-start-4 col-end-6"> |
||||
<div |
||||
className={cn( |
||||
'sticky top-8 -translate-y-1/2 overflow-hidden rounded-lg border bg-white transition-transform', |
||||
isSticky && '-translate-y-0', |
||||
)} |
||||
> |
||||
<figure> |
||||
<img |
||||
src="https://images.unsplash.com/photo-1732200584655-3511db5c24e2?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxmZWF0dXJlZC1waG90b3MtZmVlZHw5fHx8ZW58MHx8fHx8" |
||||
alt="SQL 101" |
||||
className="aspect-video w-full object-cover" |
||||
/> |
||||
</figure> |
||||
|
||||
<div className="p-2"> |
||||
<button className="flex w-full items-center justify-between gap-1 rounded-lg border p-2 px-3"> |
||||
<span>Enroll now</span> |
||||
<span>5$ / month</span> |
||||
</button> |
||||
</div> |
||||
|
||||
<div className="border-b p-2 pb-4"> |
||||
<h4 className="text-lg font-medium">Certificate of Completion</h4> |
||||
<p className="text-xs text-gray-500"> |
||||
Certificate will be issued on completion |
||||
</p> |
||||
|
||||
<figure className="mt-4"> |
||||
<img |
||||
src="https://images.unsplash.com/photo-1732465286852-a0b95393a90d?w=800&auto=format&fit=crop&q=60&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxmZWF0dXJlZC1waG90b3MtZmVlZHwxN3x8fGVufDB8fHx8fA%3D%3D" |
||||
alt="SQL 101" |
||||
className="aspect-video w-full rounded-lg object-cover" |
||||
/> |
||||
</figure> |
||||
</div> |
||||
|
||||
<div className="p-2"> |
||||
<h4 className="text-lg font-medium">What you get</h4> |
||||
<ul |
||||
role="list" |
||||
className="mt-2 list-disc pl-4 text-sm text-gray-700 marker:text-gray-400" |
||||
> |
||||
<li>Full access to all the courses</li> |
||||
<li>Personalized access using AI</li> |
||||
<li>Certificate of Completion</li> |
||||
<li>Playground for live-coding</li> |
||||
<li>Challenges / Quizes</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</> |
||||
); |
||||
} |
@ -0,0 +1,24 @@ |
||||
import type { LucideIcon } from 'lucide-react'; |
||||
import { cn } from '../../lib/classname'; |
||||
|
||||
type CourseStatPillProps = { |
||||
icon: LucideIcon; |
||||
label: string; |
||||
className?: string; |
||||
}; |
||||
|
||||
export function CourseStatPill(props: CourseStatPillProps) { |
||||
const { icon: Icon, label, className } = props; |
||||
|
||||
return ( |
||||
<div |
||||
className={cn( |
||||
'flex items-center gap-2 rounded-full border border-slate-400 px-2.5 py-1 text-sm', |
||||
className, |
||||
)} |
||||
> |
||||
<Icon className="size-3.5 shrink-0 stroke-[2.5]" /> |
||||
<span>{label}</span> |
||||
</div> |
||||
); |
||||
} |
Loading…
Reference in new issue