Skip to content

Commit 9402f85

Browse files
bengineerdavislpatmoangelocordon
authored
Adding MaterialUI.Typography JSX tags to resource page (#123)
Create Resource Page. Add React Query library. Add Axios to utility query. Co-authored-by: Ben Davis <[email protected]> Co-authored-by: Linda Peng <[email protected]> Co-authored-by: Angelo Cordon <[email protected]>
1 parent 4a7c184 commit 9402f85

File tree

7 files changed

+156
-41
lines changed

7 files changed

+156
-41
lines changed

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
SKIP_PREFLIGHT_CHECK = true
1+
SKIP_PREFLIGHT_CHECK=true

.eslintrc.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
"react/prop-types": "error",
2929
"react/no-unescaped-entities": 0,
3030
"comma-dangle": ["error", "only-multiline"],
31-
"no-unused-vars": [2, { "vars": "all", "args": "after-used" }]
31+
"no-unused-vars": [2, { "vars": "all", "args": "after-used" }],
32+
"camelcase": 0
3233
}
3334
}

package-lock.json

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
},
1919
"proxy": "http://localhost:8000",
2020
"dependencies": {
21+
"@babel/runtime": "^7.9.2",
2122
"@hapi/joi": "17.1.1",
22-
"@babel/runtime": "^7.11.2",
2323
"@material-ui/core": "4.11.0",
2424
"@material-ui/icons": "4.9.1",
2525
"@material-ui/lab": "^4.0.0-alpha.56",
@@ -30,8 +30,9 @@
3030
"react": "16.11.0",
3131
"react-dom": "16.11.0",
3232
"react-hook-form": "5.5.1",
33-
"react-router-dom": "5.2.0",
34-
"react-scripts": "^3.4.3",
33+
"react-query": "^2.5.14",
34+
"react-router-dom": "5.1.2",
35+
"react-scripts": "^3.4.0",
3536
"react-select": "3.0.8",
3637
"unfurl.js": "5.0.1"
3738
},
@@ -89,4 +90,4 @@
8990
"git add"
9091
]
9192
}
92-
}
93+
}

src/components/Resources/ResourcePage.js

Lines changed: 91 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,104 @@
1-
import React, { useState, useEffect } from 'react';
1+
import React from 'react';
22
import PropTypes from 'prop-types';
3+
import { useQuery } from 'react-query';
34
import { Link } from 'react-router-dom';
4-
import axios from 'axios';
5+
import { getResource } from '../../utils/queries';
56
import PersonalMenu from '../PersonalMenu';
6-
import { Grid, Breadcrumbs, Typography } from '@material-ui/core';
7+
import { Grid, Breadcrumbs, Typography, Chip, Box } from '@material-ui/core';
78
import NavigateNextIcon from '@material-ui/icons/NavigateNext';
9+
import { makeStyles } from '@material-ui/core/styles';
10+
11+
const useStyles = makeStyles({
12+
subtitle: {
13+
display: 'flex',
14+
justifyContent: 'space-between',
15+
},
16+
});
817

918
function ResourcePage({ matchProps }) {
10-
const [resource, setResource] = useState({});
11-
12-
useEffect(() => {
13-
axios
14-
.get('/api/v1/resources/' + matchProps.match.params.guid)
15-
.then(function(response) {
16-
// handle success
17-
setResource(response.data);
18-
})
19-
.catch(function(error) {
20-
// handle error
21-
console.log(error);
22-
});
23-
}, [matchProps.match.params.id]);
19+
const resourceId = matchProps.match.params.guid;
20+
// TODO: Handle Error cases
21+
const { isLoading, data } = useQuery(['resource', resourceId], getResource);
22+
const classes = useStyles();
23+
24+
if (isLoading) {
25+
return <p>Loading...</p>;
26+
}
27+
28+
const {
29+
title,
30+
url,
31+
author,
32+
tags,
33+
media_type,
34+
description,
35+
user,
36+
date_published,
37+
modified,
38+
paid,
39+
} = data;
2440

2541
return (
26-
<>
27-
<Grid container spacing={1}>
28-
<Grid item lg={3}>
29-
<PersonalMenu />
30-
</Grid>
31-
<Grid item lg={9}>
32-
<Breadcrumbs
33-
separator={<NavigateNextIcon fontSize="small" />}
34-
aria-label="breadcrumb"
35-
>
36-
<Link color="inherit" to="/resources">
37-
Resources
42+
<Grid container spacing={1}>
43+
<Grid item lg={3}>
44+
<PersonalMenu />
45+
</Grid>
46+
<Grid item lg={9}>
47+
<Breadcrumbs
48+
separator={<NavigateNextIcon fontSize="small" />}
49+
aria-label="breadcrumb"
50+
>
51+
<Link color="inherit" to="/resources">
52+
Resources
53+
</Link>
54+
<Typography color="textPrimary">{title}</Typography>
55+
</Breadcrumbs>
56+
57+
<Typography variant="h2" gutterBottom>
58+
{title}
59+
</Typography>
60+
61+
<div className={classes.subtitle}>
62+
<Typography variant="subtitle1" gutterBottom>
63+
<Link target="_blank" rel="noopener noreferrer" to={url}>
64+
{url}
3865
</Link>
39-
<Typography color="textPrimary">{resource.title}</Typography>
40-
</Breadcrumbs>
41-
<h2>{resource.title}</h2>
42-
<pre>{JSON.stringify(resource, 0, 2)}</pre>
43-
</Grid>
66+
</Typography>
67+
<Typography variant="subtitle1" gutterBottom>
68+
<strong>Author:</strong> {author}
69+
</Typography>
70+
</div>
71+
72+
{tags &&
73+
tags.map(tag => {
74+
return <Chip key={tag.slug} label={tag.name} />;
75+
})}
76+
77+
<div>
78+
<Box pt={3}>
79+
<Typography variant="subtitle1" gutterBottom>
80+
Paid: {paid ? 'yes' : 'no'}
81+
</Typography>
82+
</Box>
83+
<Typography variant="subtitle1" gutterBottom>
84+
Media Type: {media_type}
85+
</Typography>
86+
<Typography variant="subtitle2" gutterBottom>
87+
Added by <strong>{user.username}</strong> on {date_published}
88+
</Typography>
89+
</div>
90+
91+
<Typography variant="subtitle2" gutterBottom>
92+
Modified by <strong>"someone"</strong> {modified}
93+
</Typography>
94+
95+
<br></br>
96+
97+
<Typography variant="body1" gutterBottom>
98+
{description}
99+
</Typography>
44100
</Grid>
45-
</>
101+
</Grid>
46102
);
47103
}
48104

src/utils/queries.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import axios from 'axios';
2+
3+
const API_URL = '/api/v1';
4+
5+
const getResource = async (_key, id) => {
6+
const { data } = await axios.get(`${API_URL}/resources/${id}`);
7+
return data;
8+
};
9+
10+
export { getResource };

src/utils/queries.test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { getResource } from './queries';
2+
import axios from 'axios';
3+
4+
jest.mock('axios');
5+
6+
describe('getResource', () => {
7+
it('returns `data` object when successfully fetched', async () => {
8+
const data = {
9+
title: 'Just You Wait',
10+
url: 'www.manythingstodo.com',
11+
author: 'Alexander Hamilton',
12+
media_type: 'song',
13+
description: '3 hour epic ballad',
14+
user: 'harrypotter321',
15+
date_published: '10-11-2020',
16+
};
17+
18+
axios.get.mockImplementationOnce(() => Promise.resolve({ data }));
19+
20+
await expect(getResource('resourceQuery', 'resource-url')).resolves.toEqual(
21+
data
22+
);
23+
});
24+
25+
it('returns `error` object when unable to fetch', async () => {
26+
const errorMessage = 'No such resource';
27+
axios.get.mockImplementationOnce(() =>
28+
Promise.reject(new Error(errorMessage))
29+
);
30+
await expect(
31+
getResource('resourceQuery', 'a-very-wrong-url')
32+
).rejects.toThrow(errorMessage);
33+
});
34+
});

0 commit comments

Comments
 (0)