183 lines
5.4 KiB
Plaintext
183 lines
5.4 KiB
Plaintext
---
|
|
import { getGuideTableOfContent, type HeadingGroupType } from '../../lib/guide';
|
|
import { markdownToHtml } from '../../lib/markdown';
|
|
import {
|
|
type QuestionGroupType,
|
|
type QuestionType,
|
|
} from '../../lib/question-group';
|
|
import { slugify } from '../../lib/slugger';
|
|
import { RelatedGuides } from '../Guide/RelatedGuides';
|
|
import MarkdownFile from '../MarkdownFile.astro';
|
|
import { TableOfContent } from '../TableOfContent/TableOfContent';
|
|
import { QuestionsList } from './QuestionsList';
|
|
|
|
interface Props {
|
|
questionGroup: QuestionGroupType;
|
|
}
|
|
|
|
const { questionGroup } = Astro.props;
|
|
|
|
const { frontmatter: guideFrontmatter, author } = questionGroup;
|
|
|
|
// Group questions by topics
|
|
const questionsGroupedByTopics = questionGroup.questions.reduce(
|
|
(acc, question) => {
|
|
question.topics?.forEach((topic) => {
|
|
acc[topic] = [...(acc[topic] || []), question];
|
|
});
|
|
return acc;
|
|
},
|
|
{} as Record<string, QuestionType[]>,
|
|
);
|
|
|
|
// Get all unique topics in the order they appear in the questions array
|
|
const topicsInOrder: string[] = [];
|
|
questionGroup.questions.forEach((question) => {
|
|
question.topics?.forEach((topic) => {
|
|
if (!topicsInOrder.includes(topic)) {
|
|
topicsInOrder.push(topic);
|
|
}
|
|
});
|
|
});
|
|
|
|
const allHeadings = questionGroup.getHeadings();
|
|
let tableOfContent: HeadingGroupType[] = [
|
|
...getGuideTableOfContent(allHeadings),
|
|
{
|
|
depth: 2,
|
|
children: [],
|
|
slug: 'test-with-flashcards',
|
|
text: 'Test yourself with Flashcards',
|
|
},
|
|
{
|
|
depth: 2,
|
|
children: topicsInOrder.map((topic) => {
|
|
let topicText = topic;
|
|
let topicSlug = slugify(topic);
|
|
if (topic.toLowerCase() === 'beginners') {
|
|
topicText = 'Beginner Level';
|
|
topicSlug = 'beginner-level';
|
|
} else if (topic.toLowerCase() === 'intermediate') {
|
|
topicText = 'Intermediate Level';
|
|
topicSlug = 'intermediate-level';
|
|
} else if (topic.toLowerCase() === 'advanced') {
|
|
topicText = 'Advanced Level';
|
|
topicSlug = 'advanced-level';
|
|
}
|
|
|
|
return {
|
|
depth: 2,
|
|
children: [],
|
|
slug: topicSlug,
|
|
text: topicText,
|
|
};
|
|
}),
|
|
slug: 'questions-list',
|
|
text: 'Questions List',
|
|
},
|
|
];
|
|
|
|
const showTableOfContent = tableOfContent.length > 0;
|
|
---
|
|
|
|
<article class='lg:grid lg:max-w-full lg:grid-cols-[1fr_minmax(0,700px)_1fr]'>
|
|
{
|
|
showTableOfContent && (
|
|
<div class='bg-linear-to-r from-gray-50 py-0 lg:col-start-3 lg:col-end-4 lg:row-start-1'>
|
|
<RelatedGuides
|
|
relatedTitle={guideFrontmatter?.relatedTitle}
|
|
relatedGuides={questionGroup?.relatedGuides || {}}
|
|
client:load
|
|
/>
|
|
<TableOfContent toc={tableOfContent} client:load />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
<div
|
|
class:list={[
|
|
'col-start-2 col-end-3 row-start-1 mx-auto max-w-[700px] py-5 sm:py-10',
|
|
{
|
|
'lg:border-r': showTableOfContent,
|
|
},
|
|
]}
|
|
>
|
|
<MarkdownFile>
|
|
<h1 class='mb-3 text-4xl font-bold text-balance'>
|
|
{guideFrontmatter.title}
|
|
</h1>
|
|
{
|
|
author && (
|
|
<p class='my-0 flex items-center justify-start text-sm text-gray-400'>
|
|
<a
|
|
href={`/authors/${author?.id}`}
|
|
class='inline-flex items-center font-medium underline-offset-2 hover:text-gray-600 hover:underline'
|
|
>
|
|
<img
|
|
alt={author.frontmatter.name}
|
|
src={author.frontmatter.imageUrl}
|
|
class='mr-2 mb-0 inline h-5 w-5 rounded-full'
|
|
/>
|
|
{author.frontmatter.name}
|
|
</a>
|
|
<span class='mx-2 hidden sm:inline'>·</span>
|
|
<a
|
|
class='hidden underline-offset-2 hover:text-gray-600 sm:inline'
|
|
href={`https://github.com/kamranahmedse/developer-roadmap/tree/master/src/data/question-groups/${questionGroup.id}`}
|
|
target='_blank'
|
|
>
|
|
Improve this Guide
|
|
</a>
|
|
</p>
|
|
)
|
|
}
|
|
<questionGroup.Content />
|
|
|
|
<h2 id='test-with-flashcards'>Test yourself with Flashcards</h2>
|
|
<p>
|
|
You can either use these flashcards or jump to the questions list
|
|
section below to see them in a list format.
|
|
</p>
|
|
<div class='mx-0 sm:-mb-32'>
|
|
<QuestionsList
|
|
groupId={questionGroup.id}
|
|
questions={questionGroup.questions}
|
|
client:load
|
|
/>
|
|
</div>
|
|
|
|
<h2 id='questions-list'>Questions List</h2>
|
|
<p>
|
|
If you prefer to see the questions in a list format, you can find them
|
|
below.
|
|
</p>
|
|
|
|
{
|
|
topicsInOrder.map((questionLevel) => (
|
|
<div class='mb-5'>
|
|
<h3 id={slugify(questionLevel)} class='mb-0 capitalize'>
|
|
{questionLevel.toLowerCase() === 'beginners' ? 'Beginner Level' :
|
|
questionLevel.toLowerCase() === 'intermediate' ? 'Intermediate Level' :
|
|
questionLevel.toLowerCase() === 'advanced' ? 'Advanced Level' :
|
|
questionLevel}
|
|
</h3>
|
|
{questionsGroupedByTopics[questionLevel].map((q) => (
|
|
<div class='mb-5'>
|
|
<h4>{q.question}</h4>
|
|
<div set:html={markdownToHtml(q.answer, false)} />
|
|
</div>
|
|
))}
|
|
</div>
|
|
))
|
|
}
|
|
{
|
|
questionGroup.ending && (
|
|
<div class='mb-5'>
|
|
<div set:html={markdownToHtml(questionGroup.ending, false)} />
|
|
</div>
|
|
)
|
|
}
|
|
</MarkdownFile>
|
|
</div>
|
|
</article>
|