Skip to content

Commit 9d5879f

Browse files
author
Turbo
committed
Add single post page
1 parent ce23126 commit 9d5879f

File tree

9 files changed

+129
-10
lines changed

9 files changed

+129
-10
lines changed

.eslintrc.js

+5
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ module.exports = {
6868
"int32Hint": true,
6969
}
7070
],
71+
72+
// Disable react/destructuring-assignment
73+
"react/destructuring-assignment": [
74+
0,
75+
]
7176
},
7277

7378
"settings": {

content/20181101-the-thirsty-crow.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
2-
title: Kaalu – the Thirsty Crow
2+
title: Kaalu – the Thirsty Crow
3+
slug: kaali-the-thirsty-crow
34
author: Unknown
45
cover: "1.jpg"
56
date: "2018-11-01"

content/20181101-you-are-the-way-you-are.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
title: Be the way you are
3+
slug: be-the-way-you-are
34
author: P!nk
45
cover: "1.jpg"
56
date: "2017-03-01"

content/20181108-if-you-want-to-go-far.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
title: If you want to go far
3+
slug: if-you-want-to-go-far
34
author: Turbo
45
cover: "cover.jpg"
56
date: "2018-11-08"

src/App/index.js

+6
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,12 @@ export default ({ lang }) => (
4040
render={routeProps => <UniversalComponent page="Posts" {...routeProps} />}
4141
/>
4242

43+
<Route
44+
exact
45+
path="/:lang/posts/:slug"
46+
render={routeProps => <UniversalComponent page="Post" {...routeProps} />}
47+
/>
48+
4349
{/* Define Redirect logic if any */}
4450
<RedirectWithStatus httpStatus={301} exact from="/:lang" to={`/${lang}`} />
4551
<RedirectWithStatus httpStatus={301} from="/:lang/users" to="/" />

src/Components/Badge/index.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React from 'react';
2+
import styled from 'styled-components';
3+
import { Card } from 'rebass';
4+
5+
const Badge = ({ ...rest }) => (
6+
<StyledBadge {...rest} />
7+
);
8+
9+
const StyledBadge = styled(Card)`
10+
border-radius: ${props => props.theme.radius[3]}px;
11+
font-family: ${props => props.theme.fonts.body};
12+
font-weight: ${props => props.theme.fontWeights[7]};
13+
`;
14+
15+
Badge.defaultProps = {
16+
px: 2,
17+
py: 1,
18+
fontSize: 1,
19+
};
20+
21+
export default Badge;

src/Pages/Post/index.js

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
4+
import FlexBox from 'src/Components/FlexBox';
5+
import CardBox from 'src/Components/CardBox';
6+
import { H3, Span } from 'src/Components/Typo';
7+
import Head from 'src/Components/Head';
8+
import Badge from 'src/Components/Badge';
9+
10+
// Import all files inside `data` via Webpack require.context
11+
// Read more:
12+
// https://goo.gl/315fi3 - Importing Multiple Markdown files into a React Component with Webpack
13+
const postContext = require.context('../../../content', false, /\.md$/);
14+
const postFiles = postContext
15+
.keys()
16+
.map(filename => postContext(filename));
17+
18+
class Post extends React.Component {
19+
state = {
20+
post: {},
21+
}
22+
23+
componentDidMount() {
24+
const post = postFiles.find(p => p.slug === this.props.match.params.slug);
25+
console.log(post);
26+
this.setState(state => ({ ...state, post }));
27+
}
28+
29+
render() {
30+
/* eslint-disable react/no-array-index-key */
31+
const { post } = this.state;
32+
33+
return (
34+
<React.Fragment>
35+
<Head title="Posts" />
36+
<FlexBox
37+
width={[1, 1 / 2, 1 / 2]}
38+
mx="auto"
39+
mt={[2, 3, 4]}
40+
flexDirection="row"
41+
alignItems="flex-start"
42+
justifyContent="space-between"
43+
>
44+
<CardBox width={1} px={[1, 2, 3]} py={[0, 1, 2]} mx={[1, 2, 3]}>
45+
<H3 dangerouslySetInnerHTML={{ __html: post.title }} />
46+
<Span dangerouslySetInnerHTML={{ __html: post.__content }} />
47+
<FlexBox width={1}>
48+
<Badge bg="success" dangerouslySetInnerHTML={{ __html: post.category }} />
49+
<Span float="right" dangerouslySetInnerHTML={{ __html: post.date }} />
50+
</FlexBox>
51+
</CardBox>
52+
</FlexBox>
53+
</React.Fragment>
54+
);
55+
/* eslint-enable react/no-array-index-key */
56+
}
57+
}
58+
59+
Post.propTypes = {
60+
match: PropTypes.shape({
61+
params: PropTypes.shape({
62+
slug: PropTypes.string.isRequired,
63+
lang: PropTypes.string.isRequired,
64+
}),
65+
}).isRequired,
66+
};
67+
68+
export default Post;

src/Pages/Posts/index.js

+23-7
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import React from 'react';
2+
import { Link } from 'react-router-dom';
3+
import PropTypes from 'prop-types';
24

35
import truncate from 'src/helpers/truncate';
46
import FlexBox from 'src/Components/FlexBox';
57
import CardBox from 'src/Components/CardBox';
68
import { H3, Span } from 'src/Components/Typo';
79
import Head from 'src/Components/Head';
8-
import Footer from 'src/Components/Footer';
10+
import Badge from 'src/Components/Badge';
911

1012
// Import all files inside `data` via Webpack require.context
1113
// Read more:
@@ -18,17 +20,18 @@ const postFiles = postContext
1820
class Posts extends React.Component {
1921
state = {
2022
posts: [],
23+
lang: 'en',
2124
}
2225

2326
componentDidMount() {
2427
const posts = postFiles;
25-
26-
this.setState(state => ({ ...state, posts }));
28+
const { lang } = this.props.match.params;
29+
this.setState(state => ({ ...state, posts, lang }));
2730
}
2831

2932
render() {
3033
/* eslint-disable react/no-array-index-key */
31-
const { posts } = this.state;
34+
const { posts, lang } = this.state;
3235

3336
return (
3437
<React.Fragment>
@@ -43,18 +46,31 @@ class Posts extends React.Component {
4346
>
4447
{
4548
posts.map((post, i) => (
46-
<CardBox key={i} width={[1, 1/3]} px={[1, 2, 3]} py={[0, 1, 2]} mx={[1, 2, 3]}>
47-
<H3 dangerouslySetInnerHTML={{ __html: post.title }} />
49+
<CardBox width={[1, 1/3]} px={[1, 2, 3]} py={[0, 1, 2]} mx={[1, 2, 3]}>
50+
<Link key={i} to={`/${lang}/posts/${post.slug}`}>
51+
<H3 dangerouslySetInnerHTML={{ __html: post.title }} />
52+
</Link>
4853
<Span dangerouslySetInnerHTML={{ __html: truncate(post.__content) }} />
54+
<FlexBox width={1}>
55+
<Badge bg="success" dangerouslySetInnerHTML={{ __html: post.category }} />
56+
<Span float="right" dangerouslySetInnerHTML={{ __html: post.date }} />
57+
</FlexBox>
4958
</CardBox>
5059
))
5160
}
5261
</FlexBox>
53-
<Footer />
5462
</React.Fragment>
5563
);
5664
/* eslint-enable react/no-array-index-key */
5765
}
5866
}
5967

68+
Posts.propTypes = {
69+
match: PropTypes.shape({
70+
params: PropTypes.shape({
71+
lang: PropTypes.string.isRequired,
72+
}),
73+
}).isRequired,
74+
};
75+
6076
export default Posts;

src/routes.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import loadData from 'src/helpers/loadData';
99
const routes = [
1010
{ path: '/', exact: true, component: Home },
1111
{ path: '/login', component: Login },
12-
{ path: '/posts', component: Posts },
13-
{ path: '/books', component: Books, loadData: () => loadData('posts') },
12+
{ path: '/books', component: Books },
13+
{ path: '/posts', component: Posts, loadData: () => loadData('posts') },
1414
{ component: NotFound404 },
1515
];
1616

0 commit comments

Comments
 (0)