Add related questions below roadmaps

pull/4630/head^2
Kamran Ahmed 1 year ago
parent cf78628c0c
commit 7da244fe10
  1. 100
      src/components/RelatedRoadmaps.astro
  2. 2
      src/data/roadmaps/angular/angular.md
  3. 2
      src/data/roadmaps/backend/backend.md
  4. 3
      src/data/roadmaps/frontend/frontend.md
  5. 3
      src/data/roadmaps/javascript/javascript.md
  6. 2
      src/data/roadmaps/nodejs/nodejs.md
  7. 3
      src/data/roadmaps/react/react.md
  8. 2
      src/data/roadmaps/vue/vue.md
  9. 33
      src/lib/question-group.ts
  10. 17
      src/lib/roadmap.ts
  11. 3
      src/pages/[roadmapId]/index.astro

@ -1,5 +1,7 @@
---
import { getQuestionGroupsByIds } from '../lib/question-group';
import { getRoadmapsByIds, RoadmapFrontmatter } from '../lib/roadmap';
import { Map, Clipboard } from 'lucide-react';
export interface Props {
roadmap: RoadmapFrontmatter;
@ -8,35 +10,87 @@ export interface Props {
const { roadmap } = Astro.props;
const relatedRoadmaps = roadmap.relatedRoadmaps || [];
if (!relatedRoadmaps.length) {
return null;
}
const relatedRoadmapDetails = await getRoadmapsByIds(relatedRoadmaps);
const relatedQuestions = roadmap.relatedQuestions || [];
const relatedQuestionDetails = await getQuestionGroupsByIds(relatedQuestions);
---
<div class='border-t bg-gray-100'>
<div class='container'>
<div class='flex justify-between relative -top-5'>
<span class='text-md font-medium py-1 px-3 border bg-white rounded-md'>Related Roadmaps</span>
<a href='/roadmaps' class='text-md font-medium py-1 px-3 border bg-white rounded-md hover:bg-gray-50'>
<span class='hidden sm:inline'>All Roadmaps &rarr;</span>
<span class='inline sm:hidden'>More &rarr;</span>
</a>
{
relatedQuestionDetails.length > 0 && (
<div class='border-t bg-gray-100 pb-3'>
<div class='container'>
<div class='relative -top-5 flex justify-between'>
<span class='text-md flex items-center rounded-md border bg-white px-3 py-1 font-medium'>
<Clipboard className='mr-1.5 text-black' size='17px' />
Test your Knowledge
<span class='ml-2 rounded-md border border-yellow-300 bg-yellow-100 px-1 py-0.5 text-xs uppercase'>
New
</span>
</span>
<a
href='/roadmaps'
class='text-md rounded-md border bg-white px-3 py-1 font-medium hover:bg-gray-50'
>
<span class='hidden sm:inline'>All Quizzes &rarr;</span>
<span class='inline sm:hidden'>More &rarr;</span>
</a>
</div>
<div class='flex flex-col gap-1 pb-8'>
{relatedQuestionDetails.map((relatedQuestionGroup) => (
<a
href={`/questions/${relatedQuestionGroup.id}`}
class='flex flex-col gap-0.5 rounded-md border bg-white px-3.5 py-2 hover:bg-gray-50 sm:flex-row sm:gap-0'
>
<span class='inline-block min-w-[150px] font-medium'>
{relatedQuestionGroup.title}
</span>
<span class='text-gray-500'>
{relatedQuestionGroup.description}
</span>
</a>
))}
</div>
</div>
</div>
)
}
<div class='flex flex-col gap-1 pb-8'>
{
relatedRoadmapDetails.map((relatedRoadmap) => (
{
relatedRoadmaps.length && (
<div class='border-t bg-gray-100'>
<div class='container'>
<div class='relative -top-5 flex justify-between'>
<span class='text-md flex items-center rounded-md border bg-white px-3 py-1 font-medium'>
<Map className='text-black mr-1.5' size='17px' />
Related Roadmaps
</span>
<a
href={`/${relatedRoadmap.id}`}
class='py-2 px-3.5 bg-white border rounded-md hover:bg-gray-50 flex flex-col sm:flex-row gap-0.5 sm:gap-0'
href='/roadmaps'
class='text-md rounded-md border bg-white px-3 py-1 font-medium hover:bg-gray-50'
>
<span class='font-medium inline-block min-w-[150px]'>{relatedRoadmap.frontmatter.briefTitle}</span>
<span class='text-gray-500'>{relatedRoadmap.frontmatter.briefDescription}</span>
<span class='hidden sm:inline'>All Roadmaps &rarr;</span>
<span class='inline sm:hidden'>More &rarr;</span>
</a>
))
}
</div>
<div class='flex flex-col gap-1 pb-8'>
{relatedRoadmapDetails.map((relatedRoadmap) => (
<a
href={`/${relatedRoadmap.id}`}
class='flex flex-col gap-0.5 rounded-md border bg-white px-3.5 py-2 hover:bg-gray-50 sm:flex-row sm:gap-0'
>
<span class='inline-block min-w-[150px] font-medium'>
{relatedRoadmap.frontmatter.briefTitle}
</span>
<span class='text-gray-500'>
{relatedRoadmap.frontmatter.briefDescription}
</span>
</a>
))}
</div>
</div>
</div>
</div>
</div>
)
}

@ -37,6 +37,8 @@ relatedRoadmaps:
- 'react'
- 'vue'
- 'nodejs'
relatedQuestions:
- 'javascript'
sitemap:
priority: 1
changefreq: 'monthly'

@ -63,6 +63,8 @@ relatedRoadmaps:
- 'javascript'
- 'nodejs'
- 'postgresql-dba'
relatedQuestions:
- 'javascript'
sitemap:
priority: 1
changefreq: 'monthly'

@ -61,6 +61,9 @@ relatedRoadmaps:
- 'angular'
- 'vue'
- 'design-system'
relatedQuestions:
- 'javascript'
- 'react'
sitemap:
priority: 1
changefreq: 'monthly'

@ -45,6 +45,9 @@ relatedRoadmaps:
- 'react'
- 'angular'
- 'vue'
relatedQuestions:
- 'javascript'
- 'react'
sitemap:
priority: 1
changefreq: 'monthly'

@ -75,6 +75,8 @@ relatedRoadmaps:
- 'system-design'
- 'graphql'
- 'frontend'
relatedQuestions:
- 'javascript'
sitemap:
priority: 1
changefreq: 'monthly'

@ -40,6 +40,9 @@ relatedRoadmaps:
- 'vue'
- 'nodejs'
- 'design-system'
relatedQuestions:
- 'react'
- 'javascript'
sitemap:
priority: 1
changefreq: 'monthly'

@ -49,6 +49,8 @@ relatedRoadmaps:
- 'react'
- 'angular'
- 'nodejs'
relatedQuestions:
- 'javascript'
sitemap:
priority: 1
changefreq: 'monthly'

@ -54,7 +54,7 @@ export async function getAllQuestionGroups(): Promise<QuestionGroupType[]> {
`/src/data/question-groups/*/*.md`,
{
eager: true,
}
},
);
const answerFilesMap = await import.meta.glob<string>(
@ -63,7 +63,7 @@ export async function getAllQuestionGroups(): Promise<QuestionGroupType[]> {
{
eager: true,
as: 'raw',
}
},
);
return Object.values(questionGroupFilesMap)
@ -116,3 +116,32 @@ export async function getAllQuestionGroups(): Promise<QuestionGroupType[]> {
})
.sort((a, b) => a.frontmatter.order - b.frontmatter.order);
}
export async function getQuestionGroupsByIds(
ids: string[],
): Promise<{ id: string; title: string; description: string }[]> {
if (!ids?.length) {
return [];
}
const questionGroupFilesMap = import.meta.glob<
MarkdownFileType<RawQuestionGroupFrontmatter>
>(`/src/data/question-groups/*/*.md`, {
eager: true,
});
return Object.values(questionGroupFilesMap)
.map((group) => {
const fileId = group?.file?.split('/')?.pop()?.replace('.md', '');
const frontmatter = group.frontmatter;
return {
id: fileId!,
title: frontmatter.briefTitle,
description: `${frontmatter.questions.length} Questions`,
};
})
.filter((group) => {
return ids.includes(group.id);
});
}

@ -34,6 +34,7 @@ export interface RoadmapFrontmatter {
imageUrl: string;
};
relatedRoadmaps: string[];
relatedQuestions: string[];
sitemap: {
priority: number;
changefreq: string;
@ -61,7 +62,7 @@ export async function getRoadmapIds() {
'/src/data/roadmaps/*/*.md',
{
eager: true,
}
},
);
return Object.keys(roadmapFiles).map(roadmapPathToId);
@ -74,13 +75,13 @@ export async function getRoadmapIds() {
* @returns Promisified RoadmapFileType[]
*/
export async function getRoadmapsByTag(
tag: string
tag: string,
): Promise<RoadmapFileType[]> {
const roadmapFilesMap = await import.meta.glob<RoadmapFileType>(
'/src/data/roadmaps/*/*.md',
{
eager: true,
}
},
);
const roadmapFiles = Object.values(roadmapFilesMap);
@ -92,7 +93,7 @@ export async function getRoadmapsByTag(
}));
return filteredRoadmaps.sort(
(a, b) => a.frontmatter.order - b.frontmatter.order
(a, b) => a.frontmatter.order - b.frontmatter.order,
);
}
@ -101,7 +102,7 @@ export async function getRoadmapById(id: string): Promise<RoadmapFileType> {
'/src/data/roadmaps/*/*.md',
{
eager: true,
}
},
);
const roadmapFile = Object.values(roadmapFilesMap).find((roadmapFile) => {
@ -119,7 +120,11 @@ export async function getRoadmapById(id: string): Promise<RoadmapFileType> {
}
export async function getRoadmapsByIds(
ids: string[]
ids: string[],
): Promise<RoadmapFileType[]> {
if (!ids?.length) {
return [];
}
return Promise.all(ids.map((id) => getRoadmapById(id)));
}

@ -48,7 +48,7 @@ if (roadmapData.schema) {
datePublished: roadmapSchema.datePublished,
dateModified: roadmapSchema.dateModified,
imageUrl: roadmapSchema.imageUrl,
})
}),
);
}
@ -116,6 +116,7 @@ if (roadmapFAQs.length) {
/>
<FAQs faqs={roadmapFAQs} />
<RelatedRoadmaps roadmap={roadmapData} />
</div>
</BaseLayout>

Loading…
Cancel
Save