Skip to content

Commit 58a4148

Browse files
authored
Merge pull request #23 from howtographql/FullstackCourse-Cards
Fullstack course cards
2 parents 34a6261 + 65dbaa1 commit 58a4148

File tree

4 files changed

+160
-12
lines changed

4 files changed

+160
-12
lines changed

packages/gatsby-theme/src/components/overview/ProgressBar.tsx renamed to packages/gatsby-theme/src/components/ProgressBar.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
2-
import { styled } from '../../styles';
3-
import { Text } from '../shared/base';
2+
import { styled } from '../styles';
3+
import { Text } from './shared/base';
44

55
interface ProgressBarProps extends FillerProps, ContainerProps {}
66

@@ -21,7 +21,7 @@ const ProgressBar: React.FunctionComponent<ProgressBarProps> = ({
2121
};
2222

2323
interface ContainerProps {
24-
width: number;
24+
width?: number;
2525
}
2626

2727
const Container = styled.div<ContainerProps>`

packages/gatsby-theme/src/components/overview/TutorialHeader.tsx renamed to packages/gatsby-theme/src/components/TutorialHeader.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { Box, Image, Heading, Text } from '../shared/base';
2+
import { Box, Image, Heading, Text } from './shared/base';
33

44
interface TutorialHeaderProps {
55
title: string | null;
@@ -16,7 +16,7 @@ const TutorialHeader: React.FunctionComponent<TutorialHeaderProps> = ({
1616
<Box p={2}>
1717
<Image
1818
width={[0.25, 0.25, 0.25]}
19-
src="https://cdn-images-1.medium.com/max/1200/1*yTMBzO8zfEhKr4Lky6pjZQ.png"
19+
src="https://i.ibb.co/TcKwmwR/Icons.png"
2020
/>
2121
<Heading> {title} </Heading>
2222
<Text>{description} </Text>

packages/gatsby-theme/src/components/templates/TutorialOverview.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ import Layout from '../layout';
33
import Chapter from '../Chapter';
44
import { TutorialOverviewQuery } from 'src/graphqlTypes';
55
import AuthorList from '../AuthorList';
6-
import TutorialHeader from '../overview/TutorialHeader';
6+
import TutorialHeader from '../TutorialHeader';
77
import { Heading, Flex, Box } from '../shared/base';
8-
import ProgressBar from '../overview/ProgressBar';
8+
import ProgressBar from '../ProgressBar';
99
import { GithubButton, SpectrumButton, TutorialButton } from '../buttons';
1010
import { Content } from '../shared/styledHelpers';
1111
import { authors } from '../../utils/sampleData';
Lines changed: 153 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,167 @@
11
import * as React from 'react';
22
import Layout from '../components/layout';
33
import { Content } from '../components/shared/styledHelpers';
4-
import { Heading, Text } from '../components/shared/base';
4+
import {
5+
Heading,
6+
Text,
7+
Card,
8+
Flex,
9+
Image,
10+
Box,
11+
} from '../components/shared/base';
12+
import { TutorialButton } from '../components/buttons';
13+
import { getTutorialOverviewSlug } from '../utils/getTutorialSlug';
14+
import ProgressBar from '../components/ProgressBar';
515

6-
const courses = () => {
16+
const courses = data => {
17+
const courseSectionData = [
18+
{
19+
heading: `Frontend`,
20+
body: `Implement a web frontend for a Hacker News app that talks to a GraphQL
21+
API. We provide a hosted GraphQL API for you so that you can test your
22+
app in a real world environment.`,
23+
data: data.data.frontend.edges,
24+
},
25+
{
26+
heading: `Backend`,
27+
body: `Implement a GraphQL API that's backed by a database. The tutorial
28+
teach schema design and implement features like authentication,
29+
filtering, pagination and a lot more`,
30+
data: data.data.backend.edges,
31+
},
32+
];
733
return (
834
<Layout>
935
<Content>
1036
<Heading> Fullstack Course </Heading>
11-
<Text>A general introduction to GraphQL for frontend and backend developers.</Text>
12-
<Text> Read this tutorial to learn about GraphQL's basic concepts and prepare
13-
yourself for a hands-on beginner tutorial.</Text>
37+
<Text>
38+
A general introduction to GraphQL for frontend and backend developers.
39+
</Text>
40+
<Text>
41+
Read this tutorial to learn about GraphQL's basic concepts and prepare
42+
yourself for a hands-on beginner tutorial.
43+
</Text>
44+
{courseSectionData.map(section => (
45+
<div key={section.heading}>
46+
<CourseSection {...section} />
47+
</div>
48+
))}
1449
</Content>
1550
</Layout>
1651
);
1752
};
1853

54+
type CourseSectionProps = {
55+
heading: string;
56+
body: string;
57+
data: [QueryData];
58+
};
59+
60+
type QueryData = {
61+
node: Node;
62+
};
63+
64+
type Node = {
65+
id: string;
66+
fileAbsolutePath: string;
67+
frontmatter: Frontmatter;
68+
};
69+
70+
type Frontmatter = {
71+
tutorialTitle: string;
72+
description: string;
73+
};
74+
75+
const CourseSection: React.FunctionComponent<CourseSectionProps> = ({
76+
heading,
77+
body,
78+
data,
79+
}) => {
80+
return (
81+
<Flex m={[1, 1, 1]}>
82+
<Box width={[0.2, 0.2, 0.2]}>
83+
<Heading> {heading} </Heading>
84+
<Text>{body}</Text>
85+
</Box>
86+
<Box width={[0.8, 0.8, 0.8]}>
87+
<Flex alignItems="top" justifyContent="center" flexWrap="wrap">
88+
{data.map(tutorial => (
89+
<Box width={[1, 0.8, 0.4]} key={tutorial.node.id}>
90+
<CourseCard
91+
tutorialTitle={tutorial.node.frontmatter.tutorialTitle}
92+
fileAbsolutePath={tutorial.node.fileAbsolutePath}
93+
/>
94+
</Box>
95+
))}
96+
</Flex>
97+
</Box>
98+
</Flex>
99+
);
100+
};
101+
102+
type CourseCardProps = {
103+
tutorialTitle: string;
104+
fileAbsolutePath: string;
105+
};
106+
107+
const CourseCard: React.FunctionComponent<CourseCardProps> = ({
108+
tutorialTitle,
109+
fileAbsolutePath,
110+
}) => {
111+
return (
112+
<Card m={[1, 1, 1]} p={[2, 2, 2]}>
113+
<Flex flexDirection="column" alignItems="center" justifyContent="center">
114+
<Image
115+
width={[0.5, 0.5, 0.5]}
116+
src="https://i.ibb.co/TcKwmwR/Icons.png"
117+
/>
118+
<h3>{tutorialTitle}</h3>
119+
<ProgressBar percentage={Math.floor(Math.random() * 100)} width={80} />
120+
<a href={getTutorialOverviewSlug(fileAbsolutePath)}>
121+
<TutorialButton>Start Tutorial</TutorialButton>
122+
</a>
123+
</Flex>
124+
</Card>
125+
);
126+
};
127+
128+
export const query = graphql`
129+
query FullStackCourseQuery {
130+
frontend: allMdx(
131+
filter: {
132+
frontmatter: { tutorialTitle: { ne: null } }
133+
fileAbsolutePath: { regex: "/courses/frontend/" }
134+
}
135+
) {
136+
edges {
137+
node {
138+
id
139+
fileAbsolutePath
140+
frontmatter {
141+
tutorialTitle
142+
description
143+
}
144+
}
145+
}
146+
}
147+
backend: allMdx(
148+
filter: {
149+
frontmatter: { tutorialTitle: { ne: null } }
150+
fileAbsolutePath: { regex: "/courses/backend/" }
151+
}
152+
) {
153+
edges {
154+
node {
155+
id
156+
fileAbsolutePath
157+
frontmatter {
158+
tutorialTitle
159+
description
160+
}
161+
}
162+
}
163+
}
164+
}
165+
`;
166+
19167
export default courses;

0 commit comments

Comments
 (0)