Add roadmap rendering

This commit is contained in:
Kamran Ahmed
2021-08-29 21:29:14 +02:00
parent 74ef38cdb6
commit 67b8af3f6b
14 changed files with 121 additions and 45 deletions

View File

@ -5,6 +5,7 @@ const BlockQuote = styled.blockquote`
position: relative;
background: #e8e8e8;
border-radius: 5px;
margin-bottom: 18px;
h1, h2, h3, h4, h5, h6 {
margin-top: 0;

View File

@ -0,0 +1,10 @@
import React from 'react';
import { Code as ChakraCode } from '@chakra-ui/react';
type CodeType = {
children: React.ReactNode;
}
export default function Code(props: CodeType) {
return <ChakraCode bg='blue.500'>{props.children}</ChakraCode>;
}

View File

@ -10,6 +10,7 @@ import { BadgeLink } from './badge-link';
import Ul from './ul';
import Li from './li';
import PremiumBlock from './premium-block';
import { Code } from '@chakra-ui/react';
const MdxComponents = {
p: P,
@ -20,6 +21,7 @@ const MdxComponents = {
table: Table,
iframe: IFrame,
img: Img,
code: Code,
BadgeLink: BadgeLink,
PremiumBlock: PremiumBlock,
ul: Ul,

View File

@ -16,7 +16,7 @@ export function PageHeader(props: PageHeaderProps) {
<Heading
as='h1'
color='black'
fontSize={['25px', '25px', '35px']}
fontSize={['25px', '25px', '40px']}
fontWeight={700}
mb={['2px', '2px', '5px']}
>

View File

@ -38,6 +38,7 @@
"featured": true,
"imagePath": "/roadmaps/frontend.png",
"resourcesPath": "/roadmaps/1-frontend/resources.md",
"id": "frontend",
"url": "/frontend"
},
{
@ -79,6 +80,7 @@
"name": "Kamran Ahmed",
"url": "https://twitter.com/kamranahmedse"
},
"id": "backend",
"url": "/backend"
},
{
@ -119,6 +121,7 @@
"name": "Kamran Ahmed",
"url": "https://twitter.com/kamranahmedse"
},
"id": "devops",
"url": "/devops"
},
{
@ -157,6 +160,7 @@
"name": "Kamran Ahmed",
"url": "https://twitter.com/kamranahmedse"
},
"id": "react",
"url": "/react"
},
{
@ -199,6 +203,7 @@
"featured": true,
"detailed": false,
"versions": [],
"id": "postgresql-dba",
"url": "/postgresql-dba"
},
{
@ -237,6 +242,7 @@
"name": "Kamran Ahmed",
"url": "https://twitter.com/kamranahmedse"
},
"id": "android",
"url": "/android"
},
{
@ -269,6 +275,7 @@
"name": "Anas Fitiani",
"url": "https://github.com/anas-qa"
},
"id": "qa",
"url": "/qa"
}
]

View File

@ -5,6 +5,3 @@ Also, please note that the list below is exhaustive, and the items are listed in
![](/roadmaps/react.png)
Please note that the list is opinionated, and you might have different opinions than those of the author. Having said that, [we would love to hear your opinions](https://github.com/kamranahmedse/roadmap.sh/issues/new) and incorporate them in the picture if suitable.
<!-- @fixme add padding to the container -->
<br /><br /><br />

View File

@ -1,2 +1,11 @@
## QA Roadmap
Roadmap to becoming a QA Engineer
> **Roadmap is not ready yet**. Please check back later or [subscribe to get notified](/signup).
While we prepare the roadmap, follow this simple advice to learn anything
> Just **pick a project and start working on it**, you will learn all that you need along the way.
**&rarr;** &nbsp; [All Roadmaps](/roadmaps) &nbsp;&bull;&nbsp; [Programming guides](/guides) &nbsp;&bull;&nbsp; [Subscribe](/signup)

View File

@ -20,14 +20,12 @@ export type RoadmapType = {
contentPath?: string;
resourcesPath: string;
isCommunity: boolean;
id: string;
url: string;
};
export function getRequestedRoadmap(req: NextApiRequest): RoadmapType | undefined {
// remove trailing slashes
const normalizedUrl = req.url?.replace(/\/$/, '') || '';
return (roadmaps as RoadmapType[]).find(roadmap => normalizedUrl.startsWith(roadmap.url));
export function getRoadmapById(id: string): RoadmapType | undefined {
return (roadmaps as RoadmapType[]).find(roadmap => roadmap.id === id);
}
export function getAllRoadmaps(): RoadmapType[] {

5
package-lock.json generated
View File

@ -6100,6 +6100,11 @@
}
}
},
"prism-themes": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/prism-themes/-/prism-themes-1.8.0.tgz",
"integrity": "sha512-pj7A7C9C8juQRFkZHYeApQHdUiak5nkKYlHyWwh7n/b6WjI9KzGtqaGhxUZAIaV1PZ9Z1epJwe41Px3TUGsNJw=="
},
"prismjs": {
"version": "1.24.1",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.24.1.tgz",

View File

@ -21,6 +21,7 @@
"date-fns": "^2.23.0",
"framer-motion": "^4.1.17",
"next": "^11.1.0",
"prism-themes": "^1.8.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"styled-components": "^5.3.0"

View File

@ -1,50 +1,61 @@
import { Box, Button, Container, SimpleGrid, Stack } from '@chakra-ui/react';
import { Box, Button, Container, Stack } from '@chakra-ui/react';
import { DownloadIcon, EmailIcon } from '@chakra-ui/icons';
import styled from 'styled-components';
import Image from 'next/image';
import { GlobalHeader } from '../../components/global-header';
import { OpensourceBanner } from '../../components/opensource-banner';
import { UpdatesBanner } from '../../components/updates-banner';
import { Footer } from '../../components/footer';
import { PageHeader } from '../../components/page-header';
import { getAllRoadmaps, getRoadmapById, RoadmapType } from '../../lib/roadmap';
import MdRenderer from '../../components/md-renderer';
const RoadmapBody = styled.div`
margin-bottom: 30px;
font-size: 15px;
type RoadmapProps = {
roadmap: RoadmapType;
};
h1 {
font-size: 32px;
font-weight: 700;
function ImageRoadmap(props: RoadmapProps) {
const { roadmap } = props;
if (!roadmap.imagePath) {
return null;
}
p {
line-height: 25px;
margin-bottom: 20px
return (
<Container maxW={'900px'} position='relative'>
<Box mb='30px'>
<img alt='Frontend Roadmap' src={roadmap.imagePath} />
</Box>
</Container>
);
}
ul, ol {
margin: 0 0 20px 40px;
li + li {
margin-top: 7px;
}
function TextualRoadmap(props: RoadmapProps) {
const { roadmap } = props;
if (!roadmap.contentPath) {
return null;
}
img {
max-width: 100%;
}
`;
// Remove trailing slashes
const normalizedPath = roadmap.contentPath.replace(/^\//, '');
const RoadmapContent = require(`../../content/${normalizedPath}`).default;
export default function Roadmap() {
const isImageOnly = true;
return (
<Container maxW={'container.md'} position='relative'>
<MdRenderer>
<RoadmapContent />
</MdRenderer>
</Container>
);
}
export default function Roadmap(props: RoadmapProps) {
const { roadmap } = props;
return (
<Box bg='white' minH='100vh'>
<GlobalHeader />
<Box mb='60px'>
<PageHeader
title={'Frontend Developer'}
subtitle={'Step by step guide to becoming a modern frontend developer'}
title={ roadmap.title }
subtitle={ roadmap.description }
>
<Stack mt='20px' isInline>
<Button size='xs' py='14px' px='10px' leftIcon={<DownloadIcon />} colorScheme='yellow' variant='solid'>
@ -55,11 +66,9 @@ export default function Roadmap() {
</Button>
</Stack>
</PageHeader>
<Container maxW={ isImageOnly ? '900px': 'container.md'} position='relative'>
<RoadmapBody>
<img alt='Frontend Roadmap' src='/roadmaps/frontend.png' />
</RoadmapBody>
</Container>
<ImageRoadmap roadmap={roadmap} />
<TextualRoadmap roadmap={roadmap} />
</Box>
<OpensourceBanner />
@ -68,3 +77,37 @@ export default function Roadmap() {
</Box>
);
}
type StaticPathItem = {
params: {
roadmap: string
}
};
export async function getStaticPaths() {
const roadmaps = getAllRoadmaps();
const paramsList: StaticPathItem[] = roadmaps.map(roadmap => ({
params: { 'roadmap': roadmap.id }
}));
return {
paths: paramsList,
fallback: false
};
}
type ContextType = {
params: {
roadmap: string
}
};
export async function getStaticProps(context: ContextType) {
const roadmapId: string = context?.params?.roadmap;
return {
props: {
roadmap: getRoadmapById(roadmapId)
}
};
}

View File

@ -1,6 +1,7 @@
import type { AppProps } from 'next/app';
import { ChakraProvider } from '@chakra-ui/react';
import { roadmapTheme } from './theme';
import 'prism-themes/themes/prism-shades-of-purple.css';
function MyApp({ Component, pageProps }: AppProps) {
return (

View File

@ -82,6 +82,7 @@ export default function Home(props: HomeProps) {
{videos.map(video => (
<LinksListItem
key={video.url}
badgeText={video.isPro ? 'PRO' : ''}
hideSubtitleOnMobile
title={video.title}
subtitle={video.duration}

View File

@ -33,6 +33,7 @@ const roadmapsMeta = roadmapDirs.reduce((metaAcc, roadmapDirName) => {
...metaAcc,
{
...roadmapMeta,
id: roadmapSlug,
url: `/${roadmapSlug}`,
contentPath: contentPath,
resourcesPath: resourcesPath