1
0
mirror of https://github.com/kamranahmedse/developer-roadmap.git synced 2025-09-02 13:52:46 +02:00

feat: roadmap courses

This commit is contained in:
Arik Chakma
2025-08-28 14:39:09 +06:00
committed by Kamran Ahmed
parent c4c28944ee
commit f9f38101f9
4 changed files with 76 additions and 42 deletions

View File

@@ -9,6 +9,9 @@ type FAQsProps = {
export function FAQs(props: FAQsProps) {
const { faqs } = props;
if (faqs.length === 0) {
return null;
}
const [activeQuestionIndex, setActiveQuestionIndex] = useState(0);
@@ -22,18 +25,35 @@ export function FAQs(props: FAQsProps) {
</div>
<div className="flex flex-col gap-1 pb-14">
{faqs.map((faq, questionIndex) => (
<Question
key={faq._id}
isActive={questionIndex === activeQuestionIndex}
question={faq.title}
onClick={() => setActiveQuestionIndex(questionIndex)}
>
<div className="text-md rounded-br-md rounded-bl-md border-t border-t-gray-300 bg-gray-100 p-2 text-left text-sm leading-relaxed text-gray-800 sm:p-4 sm:text-base [&>p:not(:last-child)]:mb-3 [&>p>a]:text-blue-700 [&>p>a]:underline">
{guideRenderer.render(faq.description)}
</div>
</Question>
))}
{faqs.map((faq, questionIndex) => {
const isTextDescription =
typeof faq?.description === 'string' &&
faq?.description?.length > 0;
return (
<Question
key={faq._id}
isActive={questionIndex === activeQuestionIndex}
question={faq.title}
onClick={() => setActiveQuestionIndex(questionIndex)}
>
<div
className="text-md rounded-br-md rounded-bl-md border-t border-t-gray-300 bg-gray-100 p-2 text-left text-sm leading-relaxed text-gray-800 sm:p-4 sm:text-base [&>p:not(:last-child)]:mb-3 [&>p>a]:text-blue-700 [&>p>a]:underline"
{...(isTextDescription
? {
dangerouslySetInnerHTML: {
__html: faq.description,
},
}
: {})}
>
{!isTextDescription
? guideRenderer.render(faq.description)
: null}
</div>
</Question>
);
})}
</div>
</div>
</div>

View File

@@ -1,19 +1,20 @@
<!-- ---
---
import RoadmapHeader from '../../components/RoadmapHeader.astro';
import BaseLayout from '../../layouts/BaseLayout.astro';
import { getOpenGraphImageUrl } from '../../lib/open-graph';
import { type RoadmapFrontmatter, getRoadmapIds } from '../../lib/roadmap';
import CourseStep from '../../components/courses/CourseStep.astro';
import Milestone from '../../components/courses/Milestone.astro';
import { getProjectsByRoadmapId } from '../../lib/project';
import {
listOfficialRoadmaps,
officialRoadmapDetails,
} from '../../queries/official-roadmap';
export const prerender = true;
export async function getStaticPaths() {
const roadmapIds = await getRoadmapIds();
const roadmaps = await listOfficialRoadmaps();
return roadmapIds.map((roadmapId) => ({
params: { roadmapId },
return roadmaps.map((roadmap) => ({
params: { roadmapId: roadmap.slug },
}));
}
@@ -22,15 +23,14 @@ interface Params extends Record<string, string | undefined> {
}
const { roadmapId } = Astro.params as Params;
const roadmapFile = await import(
`../../data/roadmaps/${roadmapId}/${roadmapId}.md`
);
const roadmapData = roadmapFile.frontmatter as RoadmapFrontmatter;
const roadmapData = await officialRoadmapDetails(roadmapId);
if (!roadmapData) {
return Astro.redirect('/404', 404);
}
// update og for projects
const ogImageUrl =
roadmapData?.seo?.ogImageUrl ||
roadmapData?.openGraph?.image ||
getOpenGraphImageUrl({
group: 'roadmap',
resourceId: roadmapId,
@@ -43,23 +43,26 @@ const descriptionNoun: Record<string, string> = {
'Product Manager': 'Product Management',
};
const title = `${roadmapData.briefTitle} Courses`;
const description = `Premium courses to help you master ${descriptionNoun[roadmapData.briefTitle] || roadmapData.briefTitle}`;
const title = `${roadmapData?.title.card} Courses`;
const description = `Premium courses to help you master ${descriptionNoun[roadmapData?.title.card] || roadmapData?.title.card}`;
const seoTitle = `${roadmapData.briefTitle} Courses`;
const seoTitle = `${roadmapData?.title.card} Courses`;
const nounTitle =
descriptionNoun[roadmapData.briefTitle] || roadmapData.briefTitle;
descriptionNoun[roadmapData.title.card] || roadmapData.title.card;
const seoDescription = `Seeking ${nounTitle.toLowerCase()} courses to enhance your skills? Explore our top free and paid courses to help you become a ${nounTitle} expert!`;
const projects = await getProjectsByRoadmapId(roadmapId);
const courses = roadmapData.courses || [];
const question = roadmapData?.questions?.find(
(question) => question.type === 'main',
);
---
<BaseLayout
permalink={`/${roadmapId}`}
title={seoTitle}
description={seoDescription}
briefTitle={roadmapData.briefTitle}
briefTitle={roadmapData.title.card}
ogImageUrl={ogImageUrl}
keywords={roadmapData.seo.keywords}
resourceId={roadmapId}
@@ -72,10 +75,7 @@ const courses = roadmapData.courses || [];
description={description}
partner={roadmapData.partner}
roadmapId={roadmapId}
hasTopics={roadmapData.hasTopics}
isUpcoming={roadmapData.isUpcoming}
isForkable={roadmapData.isForkable}
question={roadmapData.question}
isForkable={true}
coursesCount={courses.length}
projectCount={projects.length}
activeTab='courses'
@@ -163,4 +163,4 @@ const courses = roadmapData.courses || [];
</div>
</div>
</div>
</BaseLayout> -->
</BaseLayout>

View File

@@ -83,7 +83,7 @@ if (faqs.length) {
}
const projects = await getProjectsByRoadmapId(roadmapId);
// const courses = roadmapData.courses || [];
const courses = roadmapData.courses || [];
---
<BaseLayout
@@ -123,7 +123,7 @@ const projects = await getProjectsByRoadmapId(roadmapId);
roadmapId={roadmapId}
isForkable={true}
projectCount={projects.length}
coursesCount={0}
coursesCount={courses.length}
hasAIChat={true}
/>

View File

@@ -19,8 +19,21 @@ export type OfficialRoadmapQuestion = {
description: any;
};
export interface OfficialRoadmapDocument {
export type OfficialRoadmapCourse = {
_id: string;
title: string;
description: string;
link: string;
instructor: {
name: string;
image: string;
title: string;
};
features: string[];
};
export interface OfficialRoadmapDocument {
_id?: string;
order: number;
title: {
@@ -30,12 +43,12 @@ export interface OfficialRoadmapDocument {
description: string;
slug: string;
nodes: Node[];
edges: Edge[];
nodes: any[];
edges: any[];
draft: {
nodes: Node[];
edges: Edge[];
nodes: any[];
edges: any[];
};
seo: {
@@ -59,6 +72,7 @@ export interface OfficialRoadmapDocument {
questions?: OfficialRoadmapQuestion[];
relatedRoadmaps?: string[];
courses?: OfficialRoadmapCourse[];
createdAt: Date;
updatedAt: Date;