1
0
mirror of https://github.com/kamranahmedse/developer-roadmap.git synced 2025-09-25 08:35:42 +02:00
This commit is contained in:
Arik Chakma
2025-06-27 01:10:54 +06:00
parent 1ebc8134b1
commit a4a52f6ac4
4 changed files with 376 additions and 0 deletions

View File

@@ -0,0 +1,133 @@
import {
BookIcon,
BrainIcon,
ClipboardIcon,
CodeIcon,
FileCheckIcon,
FileQuestionIcon,
MinusIcon,
PlusIcon,
} from 'lucide-react';
import { SectionHeader } from './SectionHeader';
import { useState } from 'react';
import { cn } from '../../lib/classname';
type Feature = {
title: string;
description: string;
icon: React.ElementType;
imgUrl: string;
};
export function CourseFeatures() {
const features: Feature[] = [
{
title: 'AI Tutor',
description:
'Powerful AI tutor to help you with your queries, provide additional explanations and help if you get stuck.',
icon: BrainIcon,
imgUrl: 'https://assets.roadmap.sh/guest/ai-integration.png',
},
{
title: 'Real-world Challenges',
description:
'The course is packed with practical challenges and quizzes, allowing you to test your knowledge and skills.',
icon: FileQuestionIcon,
imgUrl: 'https://assets.roadmap.sh/guest/coding-challenges.png',
},
{
title: 'Coding Environment',
description:
'With the integrated IDE, you can practice your SQL queries in real-time, getting instant feedback on your results.',
icon: CodeIcon,
imgUrl: 'https://assets.roadmap.sh/guest/coding-environment.png',
},
{
title: 'Textual Course',
description:
'Unlike video-based courses where you have to learn at the pace of the instructor, this course is text-based, allowing you to learn at your own pace.',
icon: BookIcon,
imgUrl: 'https://assets.roadmap.sh/guest/textual-course.png',
},
{
title: 'Take Notes',
description:
'The course allows you to take notes, where you can write down your thoughts and ideas. You can visit them later to review your progress.',
icon: ClipboardIcon,
imgUrl: 'https://assets.roadmap.sh/guest/course-notes.png',
},
{
title: 'Completion Certificate',
description:
'The course provides a completion certificate, which you can share with your potential employers.',
icon: FileCheckIcon,
imgUrl: 'https://assets.roadmap.sh/guest/course-certificate.jpg',
},
];
return (
<div>
<SectionHeader
title="Not your average SQL course"
description="Built around a text-based interactive approach and packed with practical challenges, this comprehensive SQL bootcamp stands out with features that make it truly unique."
/>
<div className="mx-auto mt-10 w-full max-w-3xl divide-y divide-zinc-800 overflow-hidden rounded-xl border border-zinc-800">
{features.map((feature, index) => (
<CourseFeature
key={feature.title}
{...feature}
isExpanded={index === 0}
/>
))}
</div>
</div>
);
}
type CourseFeatureProps = Feature & {
isExpanded?: boolean;
};
function CourseFeature(props: CourseFeatureProps) {
const {
title,
description,
icon: Icon,
imgUrl,
isExpanded: isDefaultExpanded = false,
} = props;
const [isExpanded, setIsExpanded] = useState(isDefaultExpanded);
return (
<div>
<div className="flex items-center justify-between gap-2 px-5 py-3">
<div className="flex items-center gap-2">
<Icon className="h-5 w-5 shrink-0 text-yellow-600" />
<h3 className={cn('text-lg', isExpanded && 'text-zinc-200')}>
{title}
</h3>
</div>
<button
className="text-zinc-400 hover:text-zinc-300"
onClick={() => setIsExpanded(!isExpanded)}
>
{isExpanded ? (
<MinusIcon className="h-5 w-5" />
) : (
<PlusIcon className="h-5 w-5" />
)}
</button>
</div>
{isExpanded && (
<div className="grid grid-cols-2 gap-4 px-5 py-3">
<p className="text-lg text-balance text-white">{description}</p>
<img src={imgUrl} alt={title} className="h-full w-full rounded-lg" />
</div>
)}
</div>
);
}

View File

@@ -0,0 +1,209 @@
import {
ChevronLeftIcon,
ChevronRightIcon,
StarIcon,
User2Icon,
} from 'lucide-react';
import { useState } from 'react';
import { markdownToHtml } from '../../lib/markdown';
type Review = {
name: string;
role: string;
rating: number;
text: string | string[];
avatarUrl?: string;
isProminent?: boolean;
isSecondaryProminent?: boolean;
};
export function ReviewCarousel() {
const reviews: Review[] = [
{
name: 'Robin Wieruch',
role: 'Author - Multiple best-selling books',
rating: 5,
text: [
'Kamran has been in the **educative space for a long time**, and it shows in the way he teaches SQL: clear, structured, and straight to the point.',
"He breaks down SQL fundamentals in a way that's both **intuitive and practical**, helping you not just write queries, but truly understand how databases work.",
"Even if you've used SQL before, this **course will fill in gaps you didn't even realize you had**. Get ready to level up your database skills!",
],
avatarUrl: 'https://assets.roadmap.sh/guest/robin.jpeg',
isProminent: true,
},
{
name: 'William Imoh',
role: 'Founder and Data Enthusiast',
rating: 5,
text: [
'I have been working with SQL and databases for a long time, I bought this course for the advanced chapters but ended up completing the entire course. I learned a lot of new things and it was **well worth the investment**.',
'No matter your SQL experience, this course is **a must-have** if you want to level up your SQL and data analysis skills. Highly recommended!',
],
avatarUrl: 'https://assets.roadmap.sh/guest/william-imoh-sd2dk.jpg',
isProminent: true,
},
{
name: 'Tomáš Janků',
role: 'Software Engineer',
rating: 5,
text: "The course and it's interactivity is excellent and I'd honestly say it's **one of the best** on the SQL theme I've seen out there.",
avatarUrl: 'https://assets.roadmap.sh/guest/tomas-janku-6bg89.jpeg',
},
{
name: 'Gourav Khunger',
role: 'Software Engineer',
rating: 5,
text: 'This course was **absolutely brilliant!** The integrated database environment to practice what I learned was the best part.',
avatarUrl: 'https://assets.roadmap.sh/guest/gourav-h2f3a.png',
},
{
name: 'Meabed',
role: 'CTO',
rating: 5,
text: 'Kamran has **clearly put a lot of thought** into this course. The content, structure and exercises were all great.',
avatarUrl: 'https://assets.roadmap.sh/guest/meabed-fu83q.jpeg',
},
{
name: 'Mohsin Aheer',
role: 'Sr. Software Engineer',
rating: 5,
text: 'I already knew SQL but this course **taught me a bunch of new things.** Practical examples and challenges were great. Highly recommended!',
avatarUrl: 'https://assets.roadmap.sh/guest/mohsinaheer-szchu.jpeg',
},
{
name: 'Reeve Tee',
role: 'Software Engineer',
rating: 5,
text: 'I found the course **highly comprehensive and incredibly valuable**. I would love to see more courses like this!',
avatarUrl: '',
},
{
name: 'Zeeshan',
role: 'Sr. Software Engineer',
rating: 5,
text: 'Loved the teaching style and the way the course was structured. The **AI tutor was a great help** when I got stuck.',
avatarUrl: 'https://assets.roadmap.sh/guest/ziishaned-qjepj.png',
},
{
name: 'Adnan Ahmed',
role: 'Engineering Manager',
rating: 5,
text: 'Having the integrated IDE made a huge difference. Being able to **immediately practice** what I learned was **invaluable**.',
avatarUrl: 'https://assets.roadmap.sh/guest/idnan-fzps5.jpeg',
},
{
name: 'Kalvin Chakma',
role: 'Jr. Software Engineer',
rating: 5,
text: "Best SQL course I've taken. The progression from basic to advanced concepts is **well thought out**, and the challenges are **excellent**.",
avatarUrl: 'https://assets.roadmap.sh/guest/kalvin-d65ol.jpeg',
},
{
name: 'Faisal Ahsan',
role: 'Software Engineer',
rating: 5,
text: 'The course and the learning experience was great. What I really liked was the **no-fluff explanations** and **practical examples**.',
avatarUrl: 'https://assets.roadmap.sh/guest/faisal-q78p2.jpeg',
},
];
const batchSize = 2;
const maxBatchNumber = Math.ceil(reviews.length / batchSize);
const [currentBatchNumber, setCurrentBatchNumber] = useState(0);
const currentBatch = reviews.slice(
currentBatchNumber * batchSize,
(currentBatchNumber + 1) * batchSize,
);
const handleNextBatch = () => {
setCurrentBatchNumber((prev) => (prev + 1) % maxBatchNumber);
};
const handlePreviousBatch = () => {
setCurrentBatchNumber(
(prev) => (prev - 1 + maxBatchNumber) % maxBatchNumber,
);
};
return (
<div className="mt-24">
<h3 className="text-center text-2xl font-medium text-zinc-200 md:text-3xl">
What other learners said
</h3>
<div className="mt-10 flex gap-4">
<div className="flex shrink-0 flex-col items-center justify-center">
<button
onClick={handlePreviousBatch}
className="flex items-center justify-center rounded-full bg-zinc-800 p-2 hover:bg-zinc-700"
>
<ChevronLeftIcon className="h-6 w-6 stroke-[2.5] text-white" />
</button>
</div>
<div className="grid grid-cols-2 gap-2">
{currentBatch.map((review, index) => (
<div
key={index}
className="review-testimonial relative overflow-hidden rounded-2xl bg-linear-to-br from-yellow-500/10 via-yellow-500/5 to-transparent p-8 backdrop-blur-sm [&_strong]:font-normal [&_strong]:text-yellow-300/70"
>
<div className="absolute -top-8 -right-8 h-32 w-32 rounded-full bg-yellow-500/5" />
<div className="flex items-center gap-4">
{review.avatarUrl && (
<img
src={review.avatarUrl}
alt={review.name}
className="h-16 w-16 rounded-full border-2 border-yellow-500/20 object-cover"
/>
)}
{!review.avatarUrl && (
<div className="flex h-16 w-16 items-center justify-center rounded-full bg-zinc-800">
<User2Icon className="h-8 w-8 text-zinc-400" />
</div>
)}
<div>
<h3 className="text-lg font-semibold text-zinc-100">
{review.name}
</h3>
<p className="text-sm text-yellow-500/70">{review.role}</p>
<div className="mt-1 flex">
{Array.from({ length: review.rating }).map((_, i) => (
<StarIcon
key={i}
className="h-4 w-4 fill-yellow-500 text-yellow-500"
/>
))}
</div>
</div>
</div>
<div className="mt-4 flex flex-col gap-3">
{(typeof review.text === 'string'
? [review.text]
: review.text
).map((text, index) => (
<p
key={index}
className="text-zinc-400 [&_strong]:font-semibold! [&_strong]:text-white!"
dangerouslySetInnerHTML={{
__html: markdownToHtml(text),
}}
/>
))}
</div>
</div>
))}
</div>
<div className="flex shrink-0 flex-col items-center justify-center">
<button
onClick={handleNextBatch}
className="flex items-center justify-center rounded-full bg-zinc-800 p-2 hover:bg-zinc-700"
>
<ChevronRightIcon className="h-6 w-6 stroke-[2.5] text-white" />
</button>
</div>
</div>
</div>
);
}

View File

@@ -11,6 +11,8 @@ import { RoadmapLogoIcon } from '../ReactIcons/RoadmapLogo';
import { AuthorCredentials } from './AuthorCredentials';
import { PlatformDemo } from './PlatformDemo';
import { PurchaseBanner } from './PurchaseBanner';
import { ReviewCarousel } from './ReviewCarousel';
import { CourseFeatures } from './CourseFeatures';
export function SQLCourseVariantPage() {
return (
@@ -72,6 +74,10 @@ export function SQLCourseVariantPage() {
</div>
<PurchaseBanner />
<ReviewCarousel />
<CourseFeatures />
</div>
</div>
</>

View File

@@ -0,0 +1,28 @@
import { cn } from '../../lib/classname';
type SectionHeaderProps = {
title: string;
description: string | React.ReactNode;
className?: string;
};
export function SectionHeader(props: SectionHeaderProps) {
const { title, description, className } = props;
return (
<div className={cn('mx-auto mt-24 w-full text-center', className)}>
<div className="relative w-full">
<h4 className="text-2xl font-medium text-zinc-200 md:text-3xl">
{title}
</h4>
</div>
{typeof description === 'string' ? (
<p className="mt-2 text-center text-lg text-balance text-zinc-400 md:mt-5 md:text-xl">
{description}
</p>
) : (
description
)}
</div>
);
}