├── public
├── robots.txt
├── favicon.ico
├── logo192.png
├── logo512.png
├── manifest.json
└── index.html
├── src
├── components
│ ├── CourseGoals
│ │ ├── CourseGoalList
│ │ │ ├── CourseGoalList.css
│ │ │ └── CourseGoalList.js
│ │ ├── CourseGoalItem
│ │ │ ├── CourseGoalItem.css
│ │ │ └── CourseGoalItem.js
│ │ └── CourseInput
│ │ │ ├── CourseInput.css
│ │ │ └── CourseInput.js
│ └── UI
│ │ └── Button
│ │ ├── Button.js
│ │ └── Button.css
├── index.css
├── index.js
├── App.css
└── App.js
└── package.json
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/somekindofwallflower/course-goals-react-project/master/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/somekindofwallflower/course-goals-react-project/master/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/somekindofwallflower/course-goals-react-project/master/public/logo512.png
--------------------------------------------------------------------------------
/src/components/CourseGoals/CourseGoalList/CourseGoalList.css:
--------------------------------------------------------------------------------
1 | .goal-list {
2 | list-style: none;
3 | margin: 0;
4 | padding: 0;
5 | }
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | }
4 |
5 | html {
6 | font-family: sans-serif;
7 | }
8 |
9 | body {
10 | margin: 0;
11 | }
12 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 |
4 | import './index.css';
5 | import App from './App';
6 |
7 | ReactDOM.render(, document.getElementById('root'));
8 |
--------------------------------------------------------------------------------
/src/components/CourseGoals/CourseGoalItem/CourseGoalItem.css:
--------------------------------------------------------------------------------
1 | .goal-item {
2 | margin: 1rem 0;
3 | background: #8b005d;
4 | box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
5 | color: white;
6 | padding: 1rem 2rem;
7 | cursor: pointer;
8 | }
9 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | #goals {
2 | width: 35rem;
3 | max-width: 90%;
4 | margin: 3rem auto;
5 | }
6 |
7 | #goal-form {
8 | width: 30rem;
9 | max-width: 90%;
10 | margin: 3rem auto;
11 | padding: 2rem;
12 | box-shadow: 0 2px 12px rgba(0, 0, 0, 0.2);
13 | border-radius: 10px;
14 | }
15 |
--------------------------------------------------------------------------------
/src/components/UI/Button/Button.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import './Button.css';
4 |
5 | const Button = props => {
6 | return (
7 |
10 | );
11 | };
12 |
13 | export default Button;
14 |
--------------------------------------------------------------------------------
/src/components/UI/Button/Button.css:
--------------------------------------------------------------------------------
1 | .button {
2 | font: inherit;
3 | padding: 0.5rem 1.5rem;
4 | border: 1px solid #8b005d;
5 | color: white;
6 | background: #8b005d;
7 | box-shadow: 0 0 4px rgba(0, 0, 0, 0.26);
8 | cursor: pointer;
9 | }
10 |
11 | .button:focus {
12 | outline: none;
13 | }
14 |
15 | .button:hover,
16 | .button:active {
17 | background: #ac0e77;
18 | border-color: #ac0e77;
19 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.26);
20 | }
21 |
--------------------------------------------------------------------------------
/src/components/CourseGoals/CourseGoalItem/CourseGoalItem.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import './CourseGoalItem.css';
4 |
5 | const CourseGoalItem = props => {
6 | // const [deleteText, setDeleteText] = useState('');
7 |
8 | const deleteHandler = () => {
9 | // setDeleteText('(Deleted!)');
10 | props.onDelete(props.id);
11 | };
12 |
13 | return (
14 |
15 | {props.children}
16 |
17 | );
18 | };
19 |
20 | export default CourseGoalItem;
21 |
--------------------------------------------------------------------------------
/src/components/CourseGoals/CourseGoalList/CourseGoalList.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import CourseGoalItem from '../CourseGoalItem/CourseGoalItem';
4 | import './CourseGoalList.css';
5 |
6 | const CourseGoalList = props => {
7 | return (
8 |
9 | {props.items.map(goal => (
10 |
15 | {goal.text}
16 |
17 | ))}
18 |
19 | );
20 | };
21 |
22 | export default CourseGoalList;
23 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
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 | }
26 |
--------------------------------------------------------------------------------
/src/components/CourseGoals/CourseInput/CourseInput.css:
--------------------------------------------------------------------------------
1 | .form-control {
2 | margin: 0.5rem 0;
3 | }
4 |
5 | .form-control label {
6 | font-weight: bold;
7 | display: block;
8 | margin-bottom: 0.5rem;
9 | }
10 |
11 | .form-control input {
12 | display: block;
13 | width: 100%;
14 | border: 1px solid #ccc;
15 | font: inherit;
16 | line-height: 1.5rem;
17 | padding: 0 0.25rem;
18 | }
19 |
20 | .form-control input:focus {
21 | outline: none;
22 | background: #fad0ec;
23 | border-color: #8b005d;
24 | }
25 |
26 |
27 | .form-control.isValid input {
28 | background: #fad0ec;
29 | border-color: red;
30 | }
31 |
32 | .form-control.isValid label {
33 | color: red;
34 | }
35 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-complete-guide",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.11.6",
7 | "@testing-library/react": "^11.2.2",
8 | "@testing-library/user-event": "^12.5.0",
9 | "react": "^17.0.1",
10 | "react-dom": "^17.0.1",
11 | "react-scripts": "4.0.1",
12 | "web-vitals": "^0.2.4"
13 | },
14 | "scripts": {
15 | "start": "react-scripts start",
16 | "build": "react-scripts build",
17 | "test": "react-scripts test",
18 | "eject": "react-scripts eject"
19 | },
20 | "eslintConfig": {
21 | "extends": [
22 | "react-app",
23 | "react-app/jest"
24 | ]
25 | },
26 | "browserslist": {
27 | "production": [
28 | ">0.2%",
29 | "not dead",
30 | "not op_mini all"
31 | ],
32 | "development": [
33 | "last 1 chrome version",
34 | "last 1 firefox version",
35 | "last 1 safari version"
36 | ]
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/components/CourseGoals/CourseInput/CourseInput.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 |
3 | import Button from '../../UI/Button/Button';
4 | import './CourseInput.css';
5 |
6 | const CourseInput = props => {
7 | const [enteredValue, setEnteredValue] = useState('');
8 | const[isValid, setIsValid] = useState(true)
9 | const goalInputChangeHandler = event => {
10 | setEnteredValue(event.target.value);
11 | };
12 |
13 | const formSubmitHandler = event => {
14 | event.preventDefault();
15 | if(enteredValue.trim().length === 0) {
16 | setIsValid(false)
17 | return;
18 | }
19 | props.onAddGoal(enteredValue);
20 | setIsValid(true)
21 | setEnteredValue('')
22 | };
23 |
24 | return (
25 |
32 | );
33 | };
34 |
35 | export default CourseInput;
36 |
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 |
3 | import CourseGoalList from './components/CourseGoals/CourseGoalList/CourseGoalList';
4 | import CourseInput from './components/CourseGoals/CourseInput/CourseInput';
5 | import './App.css';
6 |
7 | const App = () => {
8 | const [courseGoals, setCourseGoals] = useState([
9 | { text: 'Do all exercises!', id: 'g1' },
10 | { text: 'Finish the course!', id: 'g2' }
11 | ]);
12 |
13 | const addGoalHandler = enteredText => {
14 | setCourseGoals(prevGoals => {
15 | const updatedGoals = [...prevGoals];
16 | updatedGoals.unshift({ text: enteredText, id: Math.random().toString() });
17 | return updatedGoals;
18 | });
19 | };
20 |
21 | const deleteItemHandler = goalId => {
22 | setCourseGoals(prevGoals => {
23 | const updatedGoals = prevGoals.filter(goal => goal.id !== goalId);
24 | return updatedGoals;
25 | });
26 | };
27 |
28 | let content = (
29 | No goals found. Maybe add one?
30 | );
31 |
32 | if (courseGoals.length > 0) {
33 | content = (
34 |
35 | );
36 | }
37 |
38 | return (
39 |
40 |
43 |
44 | {content}
45 | {/* {courseGoals.length > 0 && (
46 |
50 | ) // No goals found. Maybe add one?
51 | } */}
52 |
53 |
54 | );
55 | };
56 |
57 | export default App;
58 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
27 | React App
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------