Skip to content

Commit adfd1b8

Browse files
committed
Create sample forum react app based on last year's
0 parents  commit adfd1b8

23 files changed

+12529
-0
lines changed

README.md

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# CVWO Assignment Sample React App
2+
3+
This sample React app is provided to help you experiment and practice web development fundamentals.
4+
It shows how certain functionality can be implemented.
5+
However, do note that this is **far from a model example**.
6+
After all, we want to see how you maximise your learning in web development
7+
and good software development practices.
8+
9+
## Getting Started
10+
11+
### Running the app
12+
13+
1. [Fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo#forking-a-repository) this repo.
14+
2. [Clone](https://docs.github.com/en/get-started/quickstart/fork-a-repo#cloning-your-forked-repository) **your** forked repo.
15+
3. Open your terminal and navigate to the directory containing your cloned project.
16+
4. Install dependencies for the project by entering this command:
17+
18+
```bash
19+
yarn install
20+
```
21+
22+
5. Run the app in development mode by entering this command:
23+
24+
```bash
25+
yarn start
26+
```
27+
28+
6. Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
29+
7. You should see a page like this.
30+
![Basic Page](public/images/BasicPage.png)
31+
32+
### Navigating the code
33+
34+
This is the main file structure
35+
36+
```
37+
.
38+
├── node_modules
39+
├── public
40+
├── src
41+
├── README.md
42+
├── tsconfig.json
43+
├── package.json
44+
├── .eslintrc.js
45+
├── .prettierrc.js
46+
└── yarn.lock
47+
```
48+
49+
Main directories/files to note:
50+
51+
- `src` usually includes all your source code. That is where most of your functional code will be.
52+
- `README.md` is a form of documentation about the project. It is what you are reading right now.
53+
- `package.json` contains important metadata, for example, the dependencies and available scripts in the project.
54+
- `.eslintrc.js` contains the configuration for ESLint. ESLint is a tool to help enforce code consistency.
55+
- `.prettierrc.js` contains the configuration for Prettier. Prettier is a tool to help format code.
56+
57+
Try changing some source code and see how the app changes.
58+
59+
## Additional Notes
60+
61+
- This project uses [Typescript](https://www.typescriptlang.org/).
62+
- The linting and code formatting rules are specified in `.eslintrc.js` and `.prettierrc.js` respectively.
63+
You may modify the rules.
64+
- The available scripts are in `package.json`.
65+
Here are some scripts that you are likely to use more often:
66+
- `yarn start`
67+
- `yarn lint:fix`
68+
- `yarn format:fix`
69+
70+
## Acknowledgements
71+
72+
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
73+
This project uses [MUI](https://mui.com/),
74+
[TypewriterJS](https://github.com/tameemsafi/typewriterjs#readme),
75+
[ESLint](https://eslint.org/), [Prettier](https://prettier.io/).

package.json

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"name": "sample",
3+
"version": "0.1.0",
4+
"private": true,
5+
"dependencies": {
6+
"@material-ui/core": "^4.12.4",
7+
"@testing-library/jest-dom": "^5.11.4",
8+
"@testing-library/react": "^11.1.0",
9+
"@testing-library/user-event": "^12.1.10",
10+
"@types/jest": "^26.0.15",
11+
"@types/material-ui": "^0.21.12",
12+
"@types/node": "^12.0.0",
13+
"@types/react": "^17.0.0",
14+
"@types/react-dom": "^17.0.0",
15+
"@types/react-router-dom": "^5.3.2",
16+
"eslint-plugin-import": "^2.25.3",
17+
"eslint-plugin-react": "^7.27.1",
18+
"react": "^17.0.2",
19+
"react-dom": "^17.0.2",
20+
"react-router-dom": "^6.0.2",
21+
"react-scripts": "4.0.3",
22+
"typescript": "^4.1.2",
23+
"typewriter-effect": "^2.18.2",
24+
"web-vitals": "^2.1.2"
25+
},
26+
"scripts": {
27+
"start": "react-scripts start",
28+
"build": "react-scripts build",
29+
"test": "react-scripts test",
30+
"eject": "react-scripts eject",
31+
"lint": "eslint --ext .js,.ts,.jsx,.tsx src",
32+
"lint:fix": "eslint --ext .js,.ts,.jsx,.tsx src --fix",
33+
"format": "prettier --check \"src/**/*.{js,ts,jsx,tsx,scss}\"",
34+
"format:fix": "prettier --write \"src/**/*.{js,ts,jsx,tsx,scss}\""
35+
},
36+
"eslintConfig": {
37+
"extends": [
38+
"react-app",
39+
"react-app/jest"
40+
]
41+
},
42+
"browserslist": {
43+
"production": [
44+
">0.2%",
45+
"not dead",
46+
"not op_mini all"
47+
],
48+
"development": [
49+
"last 1 chrome version",
50+
"last 1 firefox version",
51+
"last 1 safari version"
52+
]
53+
},
54+
"devDependencies": {
55+
"@typescript-eslint/eslint-plugin": "^5.4.0",
56+
"@typescript-eslint/parser": "^5.4.0",
57+
"eslint": "^7.32.0",
58+
"eslint-config-prettier": "^8.3.0",
59+
"eslint-config-react-app": "^6.0.0",
60+
"eslint-plugin-prettier": "^4.0.0",
61+
"prettier": "^2.4.1"
62+
}
63+
}

public/favicon.ico

3.78 KB
Binary file not shown.

public/images/BasicPage.png

15.4 KB
Loading

public/index.html

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1" />
7+
<meta name="theme-color" content="#000000" />
8+
<meta name="description" content="Web site created using create-react-app" />
9+
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
10+
<!--
11+
manifest.json provides metadata used when your web app is installed on a
12+
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
13+
-->
14+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
15+
<!--
16+
Notice the use of %PUBLIC_URL% in the tags above.
17+
It will be replaced with the URL of the `public` folder during the build.
18+
Only files inside the `public` folder can be referenced from the HTML.
19+
20+
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
21+
work correctly both with client-side routing and a non-root public URL.
22+
Learn how to configure a non-root public URL by running `npm run build`.
23+
-->
24+
<title>React App</title>
25+
</head>
26+
<body>
27+
<noscript>You need to enable JavaScript to run this app.</noscript>
28+
<div id="root"></div>
29+
<!--
30+
This HTML file is a template.
31+
If you open it directly in the browser, you will see an empty page.
32+
33+
You can add webfonts, meta tags, or analytics to this file.
34+
The build step will place the bundled scripts into the <body> tag.
35+
36+
To begin the development, run `npm start` or `yarn start`.
37+
To create a production bundle, use `npm run build` or `yarn build`.
38+
--></body>
39+
</html>

public/logo192.png

5.22 KB
Loading

public/logo512.png

9.44 KB
Loading

public/manifest.json

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"short_name": "React App",
3+
"name": "Create React App Sample",
4+
"icons": [
5+
{
6+
"src": "favicon.ico",
7+
"sizes": "64x64 32x32 24x24 16x16",
8+
"type": "image/x-icon"
9+
},
10+
{
11+
"src": "logo192.png",
12+
"type": "image/png",
13+
"sizes": "192x192"
14+
},
15+
{
16+
"src": "logo512.png",
17+
"type": "image/png",
18+
"sizes": "512x512"
19+
}
20+
],
21+
"start_url": ".",
22+
"display": "standalone",
23+
"theme_color": "#000000",
24+
"background_color": "#ffffff"
25+
}

public/robots.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# https://www.robotstxt.org/robotstxt.html
2+
User-agent: *
3+
Disallow:

src/App.css

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
.App {
2+
text-align: center;
3+
}
4+
5+
.App-logo {
6+
height: 40vmin;
7+
pointer-events: none;
8+
}
9+
10+
@media (prefers-reduced-motion: no-preference) {
11+
.App-logo {
12+
animation: App-logo-spin infinite 20s linear;
13+
}
14+
}
15+
16+
.App-header {
17+
background-color: #282c34;
18+
min-height: 100vh;
19+
display: flex;
20+
flex-direction: column;
21+
align-items: center;
22+
justify-content: center;
23+
font-size: calc(10px + 2vmin);
24+
color: white;
25+
}
26+
27+
.App-link {
28+
color: #61dafb;
29+
}
30+
31+
@keyframes App-logo-spin {
32+
from {
33+
transform: rotate(0deg);
34+
}
35+
to {
36+
transform: rotate(360deg);
37+
}
38+
}
39+
40+
li {
41+
list-style-type: none;
42+
}
43+
44+
ul {
45+
padding-inline-start: unset;
46+
}

src/App.tsx

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import Home from './pages/Home';
2+
import BasicThreadView from './pages/BasicThreadView';
3+
import StyledThreadView from './pages/StyledThreadView';
4+
import React from 'react';
5+
import './App.css';
6+
import { BrowserRouter, Route, Routes } from 'react-router-dom';
7+
import { createTheme, ThemeProvider } from '@material-ui/core';
8+
import { blue, orange } from '@material-ui/core/colors';
9+
10+
const theme = createTheme({
11+
palette: {
12+
primary: blue,
13+
secondary: orange,
14+
},
15+
});
16+
17+
const App: React.FC = () => {
18+
return (
19+
<div className="App">
20+
<ThemeProvider theme={theme}>
21+
<BrowserRouter>
22+
<Routes>
23+
<Route path="/thread/1" element={<BasicThreadView />} />
24+
<Route path="/thread/1/styled" element={<StyledThreadView />} />
25+
<Route path="/" element={<Home />} />
26+
</Routes>
27+
</BrowserRouter>
28+
</ThemeProvider>
29+
</div>
30+
);
31+
};
32+
33+
export default App;

src/components/BasicThreadList.tsx

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import '../App.css';
2+
3+
import React from 'react';
4+
import { Link } from 'react-router-dom';
5+
6+
const BasicThreadList: React.FC = () => {
7+
return (
8+
<div style={{ width: '25vw', margin: 'auto', textAlign: 'center' }}>
9+
<h4>{'Welcome to my forum!'}</h4>
10+
<ul>
11+
<li>
12+
<Link to="/thread/1">{'Inspirational Quotes'}</Link>
13+
{' by Aiken'}
14+
</li>
15+
</ul>
16+
</div>
17+
);
18+
};
19+
20+
export default BasicThreadList;

src/components/CommentItem.tsx

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import Comment from '../types/Comment';
2+
3+
import React from 'react';
4+
import { Card, CardContent, makeStyles, Typography } from '@material-ui/core';
5+
6+
type Props = {
7+
comment: Comment;
8+
styled: boolean;
9+
};
10+
11+
const useStyles = makeStyles({
12+
commentBody: {
13+
fontSize: 16,
14+
whiteSpace: 'pre-wrap',
15+
paddingBottom: '1em',
16+
},
17+
commentCard: {
18+
marginBottom: '1em',
19+
},
20+
metadata: {
21+
fontSize: 14,
22+
},
23+
});
24+
25+
const CommentItem: React.FC<Props> = ({ comment, styled }) => {
26+
const classes = useStyles();
27+
28+
if (styled) {
29+
return (
30+
<Card className={classes.commentCard}>
31+
<CardContent>
32+
<Typography variant="body2" color="textPrimary" className={classes.commentBody} component="p">
33+
{comment.body}
34+
</Typography>
35+
<Typography color="textSecondary" className={classes.metadata} gutterBottom>
36+
{'Posted by ' + comment.author + ' on ' + comment.timestamp.toLocaleString()}
37+
</Typography>
38+
</CardContent>
39+
</Card>
40+
);
41+
}
42+
43+
// unstyled
44+
return (
45+
<li className={classes.commentBody}>
46+
{comment.body}
47+
<br />
48+
<em>{'posted by ' + comment.author + ' on ' + comment.timestamp.toLocaleString()}</em>
49+
</li>
50+
);
51+
};
52+
53+
export default CommentItem;

0 commit comments

Comments
 (0)