├── .babelrc
├── .eslintrc.json
├── .github
└── workflows
│ └── linters.yml
├── .gitignore
├── .stylelintrc.json
├── README.md
├── package-lock.json
├── package.json
├── public
└── index.html
└── src
├── classBased
├── App.css
└── components
│ ├── Header.js
│ ├── InputTodo.js
│ ├── Navbar.js
│ ├── TodoContainer.js
│ ├── TodoItem.js
│ ├── TodoItem.module.css
│ └── TodosList.js
├── functionBased
├── App.css
├── components
│ ├── Header.js
│ ├── InputTodo.js
│ ├── Navbar.js
│ ├── TodoContainer.js
│ ├── TodoItem.js
│ ├── TodoItem.module.css
│ └── TodosList.js
└── pages
│ ├── About.js
│ ├── NotMatch.js
│ └── SinglePage.js
└── index.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-react"
4 | ],
5 | "plugins": ["@babel/plugin-syntax-jsx"]
6 | }
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es6": true,
5 | "jest": true
6 | },
7 | "parser": "@babel/eslint-parser",
8 | "parserOptions": {
9 | "ecmaFeatures": {
10 | "jsx": true
11 | },
12 | "ecmaVersion": 2018,
13 | "sourceType": "module"
14 | },
15 | "extends": ["airbnb", "plugin:react/recommended"],
16 | "plugins": ["react"],
17 | "rules": {
18 | "react/jsx-filename-extension": ["warn", { "extensions": [".js", ".jsx"] }],
19 | "react/react-in-jsx-scope": "off",
20 | "import/no-unresolved": "off",
21 | "no-shadow": "off"
22 | },
23 | "ignorePatterns": [
24 | "dist/",
25 | "build/"
26 | ]
27 | }
28 |
--------------------------------------------------------------------------------
/.github/workflows/linters.yml:
--------------------------------------------------------------------------------
1 | name: Linters
2 |
3 | on: pull_request
4 |
5 | env:
6 | FORCE_COLOR: 1
7 |
8 | jobs:
9 | eslint:
10 | name: ESLint
11 | runs-on: ubuntu-18.04
12 | steps:
13 | - uses: actions/checkout@v2
14 | - uses: actions/setup-node@v1
15 | with:
16 | node-version: "12.x"
17 | - name: Setup ESLint
18 | run: |
19 | npm install --save-dev eslint@7.x eslint-config-airbnb@18.x eslint-plugin-import@2.x eslint-plugin-jsx-a11y@6.x eslint-plugin-react@7.x eslint-plugin-react-hooks@4.x @babel/eslint-parser@7.x @babel/core@7.x @babel/plugin-syntax-jsx@7.x @babel/preset-env@7.x @babel/preset-react@7.x
20 | [ -f .eslintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.eslintrc.json
21 | [ -f .babelrc ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.babelrc
22 | - name: ESLint Report
23 | run: npx eslint .
24 | stylelint:
25 | name: Stylelint
26 | runs-on: ubuntu-18.04
27 | steps:
28 | - uses: actions/checkout@v2
29 | - uses: actions/setup-node@v1
30 | with:
31 | node-version: "12.x"
32 | - name: Setup Stylelint
33 | run: |
34 | npm install --save-dev stylelint@13.x stylelint-scss@3.x stylelint-config-standard@21.x stylelint-csstree-validator@1.x
35 | [ -f .stylelintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.stylelintrc.json
36 | - name: Stylelint Report
37 | run: npx stylelint "**/*.{css,scss}"
38 | nodechecker:
39 | name: node_modules checker
40 | runs-on: ubuntu-18.04
41 | steps:
42 | - uses: actions/checkout@v2
43 | - name: Check node_modules existence
44 | run: |
45 | if [ -d "node_modules/" ]; then echo -e "\e[1;31mThe node_modules/ folder was pushed to the repo. Please remove it from the GitHub repository and try again."; echo -e "\e[1;32mYou can set up a .gitignore file with this folder included on it to prevent this from happening in the future." && exit 1; fi
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["stylelint-config-standard"],
3 | "plugins": ["stylelint-scss", "stylelint-csstree-validator"],
4 | "rules": {
5 | "at-rule-no-unknown": [
6 | true,
7 | {
8 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"]
9 | }
10 | ],
11 | "scss/at-rule-no-unknown": [
12 | true,
13 | {
14 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"]
15 | }
16 | ],
17 | "csstree/validator": true
18 | },
19 | "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css", "**/*.js", "**/*.jsx"]
20 | }
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # reactToDo
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-todo-app",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@testing-library/jest-dom": "^5.16.5",
7 | "@testing-library/react": "^13.3.0",
8 | "@testing-library/user-event": "^13.5.0",
9 | "react": "^18.2.0",
10 | "react-dom": "^18.2.0",
11 | "react-router-dom": "^6.3.0",
12 | "react-scripts": "5.0.1",
13 | "uuid": "^8.3.2",
14 | "web-vitals": "^2.1.4"
15 | },
16 | "scripts": {
17 | "start": "react-scripts start",
18 | "build": "react-scripts build",
19 | "test": "react-scripts test",
20 | "eject": "react-scripts eject"
21 | },
22 | "eslintConfig": {
23 | "extends": [
24 | "react-app",
25 | "react-app/jest"
26 | ]
27 | },
28 | "browserslist": {
29 | "production": [
30 | ">0.2%",
31 | "not dead",
32 | "not op_mini all"
33 | ],
34 | "development": [
35 | "last 1 chrome version",
36 | "last 1 firefox version",
37 | "last 1 safari version"
38 | ]
39 | },
40 | "devDependencies": {
41 | "@babel/core": "^7.18.10",
42 | "@babel/eslint-parser": "^7.18.9",
43 | "@babel/plugin-syntax-jsx": "^7.18.6",
44 | "@babel/preset-env": "^7.18.10",
45 | "@babel/preset-react": "^7.18.6",
46 | "eslint": "^7.32.0",
47 | "eslint-config-airbnb": "^18.2.1",
48 | "eslint-plugin-import": "^2.26.0",
49 | "eslint-plugin-jsx-a11y": "^6.6.1",
50 | "eslint-plugin-react": "^7.30.1",
51 | "eslint-plugin-react-hooks": "^4.6.0",
52 | "stylelint": "^13.13.1",
53 | "stylelint-config-standard": "^21.0.0",
54 | "stylelint-csstree-validator": "^1.9.0",
55 | "stylelint-scss": "^3.21.0"
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
17 |
18 |
26 | React App
27 |
28 |
29 | You need to enable JavaScript to run this app.
30 |
31 |
39 |
40 |
--------------------------------------------------------------------------------
/src/classBased/App.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | margin: 0;
4 | padding: 0;
5 | }
6 |
7 | body {
8 | font-family: "Segoe UI", Arial, sans-serif;
9 | line-height: 1.4;
10 | color: #444;
11 | background: #fff;
12 | height: 100vh;
13 | }
14 |
15 | .container {
16 | display: flex;
17 | flex-direction: column;
18 | justify-content: center;
19 | align-items: center;
20 | max-width: 600px;
21 | margin: 0 auto;
22 | }
23 |
24 | .inner {
25 | width: 100%;
26 | padding: 8rem 10px 4rem;
27 | }
28 |
29 | .form-container {
30 | width: 100%;
31 | margin-bottom: 20px;
32 | display: flex;
33 | border-radius: calc(0.5 * 100px);
34 | box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.38);
35 | justify-content: space-evenly;
36 | }
37 |
38 | .input-text {
39 | font-size: 1rem;
40 | font-weight: 400;
41 | width: 85%;
42 | padding-right: 5px;
43 | padding-left: 10px;
44 | border-radius: calc(0.5 * 100px);
45 | }
46 |
47 | .input-text::placeholder {
48 | color: #000;
49 | }
50 |
51 | .input-submit {
52 | background: transparent;
53 | color: #5b5b5b;
54 | text-transform: capitalize;
55 | cursor: pointer;
56 | font-weight: 600;
57 | margin-right: 10px;
58 | }
59 |
60 | .input-text,
61 | .input-submit {
62 | height: 45px;
63 | outline: none;
64 | border: none;
65 | }
66 |
--------------------------------------------------------------------------------
/src/classBased/components/Header.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Header = () => {
4 | const headerStyle = {
5 | padding: '20px 0',
6 | lineHeight: '1.5em',
7 | };
8 |
9 | return (
10 |
11 |
22 | todos
23 |
24 |
25 | );
26 | };
27 |
28 | export default Header;
29 |
--------------------------------------------------------------------------------
/src/classBased/components/InputTodo.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React, { Component } from 'react';
3 |
4 | class InputTodo extends Component {
5 | state = {
6 | title: '',
7 | };
8 |
9 | onChange = (e) => {
10 | this.setState({
11 | [e.target.name]: e.target.value,
12 | });
13 | };
14 |
15 | handleSubmit = (e) => {
16 | e.preventDefault();
17 | if (this.state.title.trim()) {
18 | this.props.addTodoProps(this.state.title);
19 | this.setState({
20 | title: '',
21 | });
22 | } else {
23 | alert('Please write item');
24 | }
25 | }
26 |
27 | render() {
28 | return (
29 |
40 | );
41 | }
42 | }
43 |
44 | export default InputTodo;
45 |
--------------------------------------------------------------------------------
/src/classBased/components/Navbar.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DevHunter128/react-todo-app/64afc6505cac165f837551bb74a621df7958a900/src/classBased/components/Navbar.js
--------------------------------------------------------------------------------
/src/classBased/components/TodoContainer.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 | import { v4 as uuidv4 } from 'uuid';
4 | import TodosList from './TodosList';
5 | import Header from './Header';
6 | import InputTodo from './InputTodo';
7 |
8 | class TodoContainer extends React.Component {
9 | state = {
10 | todos: [],
11 | };
12 |
13 | handleChange = (id) => {
14 | this.setState((prevState) => ({
15 | todos: prevState.todos.map((todo) => {
16 | if (todo.id === id) {
17 | return {
18 | ...todo,
19 | completed: !todo.completed,
20 | };
21 | }
22 | return todo;
23 | }),
24 | }));
25 | };
26 |
27 | delTodo = (id) => {
28 | this.setState({
29 | todos: [
30 | ...this.state.todos.filter((todo) => todo.id !== id),
31 | ],
32 | });
33 | };
34 |
35 | addTodoItem = (title) => {
36 | const newTodo = {
37 | id: uuidv4(),
38 | title,
39 | completed: false,
40 | };
41 | this.setState({
42 | todos: [...this.state.todos, newTodo],
43 | });
44 | };
45 |
46 | setUpdate = (updatedTitle, id) => {
47 | this.setState({
48 | todos: this.state.todos.map((todo) => {
49 | if (todo.id === id) {
50 | todo.title = updatedTitle;
51 | }
52 | return todo;
53 | }),
54 | });
55 | }
56 |
57 | componentDidMount() {
58 | fetch('https://jsonplaceholder.typicode.com/todos?_limit=10')
59 | .then((response) => response.json())
60 | .then((data) => this.setState({ todos: data }));
61 | }
62 |
63 | // eslint-disable-next-line
64 | componentDidMount() {
65 | const temp = localStorage.getItem('todos');
66 | const loadedTodos = JSON.parse(temp);
67 | if (loadedTodos) {
68 | this.setState({
69 | todos: loadedTodos,
70 | });
71 | }
72 | }
73 |
74 | componentDidUpdate(prevProps, prevState) {
75 | if (prevState.todos !== this.state.todos) {
76 | const temp = JSON.stringify(this.state.todos);
77 | localStorage.setItem('todos', temp);
78 | }
79 | }
80 |
81 | render() {
82 | return (
83 |
84 |
85 |
86 |
87 |
93 |
94 |
95 | );
96 | }
97 | }
98 | export default TodoContainer;
99 |
--------------------------------------------------------------------------------
/src/classBased/components/TodoItem.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 | import styles from './TodoItem.module.css';
4 |
5 | class TodoItem extends React.Component {
6 | state = {
7 | editing: false,
8 | }
9 |
10 | handleEditing = () => {
11 | this.setState({
12 | editing: true,
13 | });
14 | }
15 |
16 | handleUpdatedDone = (event) => {
17 | if (event.key === 'Enter') {
18 | this.setState({ editing: false });
19 | }
20 | }
21 |
22 | componentWillUnmount() {
23 | console.log('Cleaning up...');
24 | }
25 |
26 | render() {
27 | const viewMode = {};
28 | const editMode = {};
29 |
30 | if (this.state.editing) {
31 | viewMode.display = 'none';
32 | } else {
33 | editMode.display = 'none';
34 | }
35 | const completedStyle = {
36 | fontStyle: 'italic',
37 | color: '#595959',
38 | opacity: 0.4,
39 | textDecoration: 'line-through',
40 | };
41 | const { completed, id, title } = this.props.todo;
42 | return (
43 |
44 |
45 | this.props.handleChangeProps(id)}
50 | />
51 | this.props.deleteTodoProps(id)}>
52 | Delete
53 |
54 |
55 | {title}
56 |
57 |
58 | {
64 | this.props.setUpdate(e.target.value, id);
65 | }}
66 | onKeyDown={this.handleUpdatedDone}
67 | />
68 |
69 | );
70 | }
71 | }
72 |
73 | export default TodoItem;
74 |
--------------------------------------------------------------------------------
/src/classBased/components/TodoItem.module.css:
--------------------------------------------------------------------------------
1 | .item {
2 | font-size: 1.2rem;
3 | list-style-type: none;
4 | padding: 17px 0;
5 | border-bottom: 1px solid #eaeaea;
6 | }
7 |
8 | .checkbox {
9 | margin-right: 15px;
10 | }
11 |
12 | .item button {
13 | font-size: 13px;
14 | background: #f1f3f4;
15 | border: none;
16 | cursor: pointer;
17 | float: right;
18 | outline: none;
19 | border-radius: 100px;
20 | height: 50px;
21 | width: 50px;
22 | margin: -10px 0 0 10px;
23 | }
24 |
25 | .textInput {
26 | width: 100%;
27 | padding: 10px;
28 | border: 1px solid #dfdfdf;
29 | }
30 |
--------------------------------------------------------------------------------
/src/classBased/components/TodosList.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 | import TodoItem from './TodoItem';
4 |
5 | class TodosList extends React.Component {
6 | render() {
7 | return (
8 |
9 | {this.props.todos.map((todo) => (
10 |
17 | ))}
18 |
19 | );
20 | }
21 | }
22 |
23 | export default TodosList;
24 |
--------------------------------------------------------------------------------
/src/functionBased/App.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box;
3 | margin: 0;
4 | padding: 0;
5 | }
6 |
7 | body {
8 | font-family: "Segoe UI", Arial, sans-serif;
9 | line-height: 1.4;
10 | color: #444;
11 | background: #fff;
12 | height: 100vh;
13 | }
14 |
15 | .container {
16 | display: flex;
17 | flex-direction: column;
18 | justify-content: center;
19 | align-items: center;
20 | max-width: 600px;
21 | margin: 0 auto;
22 | }
23 |
24 | .inner {
25 | width: 100%;
26 | padding: 8rem 10px 4rem;
27 | }
28 |
29 | .form-container {
30 | width: 100%;
31 | margin-bottom: 20px;
32 | display: flex;
33 | border-radius: calc(0.5 * 100px);
34 | box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.38);
35 | justify-content: space-evenly;
36 | }
37 |
38 | .input-text {
39 | font-size: 1rem;
40 | font-weight: 400;
41 | width: 85%;
42 | padding-right: 5px;
43 | padding-left: 10px;
44 | border-radius: calc(0.5 * 100px);
45 | }
46 |
47 | .input-text::placeholder {
48 | color: #000;
49 | }
50 |
51 | .input-submit {
52 | background: transparent;
53 | color: #5b5b5b;
54 | text-transform: capitalize;
55 | cursor: pointer;
56 | font-weight: 600;
57 | margin-right: 10px;
58 | }
59 |
60 | .input-text,
61 | .input-submit {
62 | height: 45px;
63 | outline: none;
64 | border: none;
65 | }
66 |
67 | .active-link {
68 | color: orangered;
69 | text-decoration: underline;
70 | }
71 |
--------------------------------------------------------------------------------
/src/functionBased/components/Header.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Header = () => {
4 | const headerStyle = {
5 | padding: '20px 0',
6 | lineHeight: '1.5em',
7 | };
8 |
9 | return (
10 |
11 |
22 | todos
23 |
24 |
25 | );
26 | };
27 |
28 | export default Header;
29 |
--------------------------------------------------------------------------------
/src/functionBased/components/InputTodo.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React, { useState } from 'react';
3 |
4 | const InputTodo = (props) => {
5 | const [inputText, setInputText] = useState({
6 | title: '',
7 | });
8 |
9 | const onChange = (e) => {
10 | setInputText({
11 | ...inputText,
12 | [e.target.name]: e.target.value,
13 | });
14 | };
15 |
16 | const handleSubmit = (e) => {
17 | e.preventDefault();
18 | if (inputText.title.trim()) {
19 | props.addTodoProps(inputText.title);
20 | setInputText({
21 | title: '',
22 | });
23 | } else {
24 | alert('Please write item');
25 | }
26 | };
27 |
28 | return (
29 |
40 | );
41 | };
42 |
43 | export default InputTodo;
44 |
--------------------------------------------------------------------------------
/src/functionBased/components/Navbar.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { NavLink } from 'react-router-dom';
3 |
4 | const Navbar = () => {
5 | const links = [
6 | {
7 | id: 1,
8 | path: '/',
9 | text: 'Home',
10 | },
11 | {
12 | id: 2,
13 | path: '/about',
14 | text: 'About',
15 | },
16 | ];
17 | return (
18 |
19 |
20 | {links.map((link) => (
21 |
22 | (isActive ? 'active-link' : 'none')}>
23 | {link.text}
24 |
25 |
26 | ))}
27 |
28 |
29 | );
30 | };
31 | export default Navbar;
32 |
--------------------------------------------------------------------------------
/src/functionBased/components/TodoContainer.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React, { useState, useEffect } from 'react';
3 | import { Routes, Route } from 'react-router-dom';
4 | import { v4 as uuidv4 } from 'uuid';
5 | import TodosList from './TodosList';
6 | import Header from './Header';
7 | import InputTodo from './InputTodo';
8 | import About from '../pages/About';
9 | import NotMatch from '../pages/NotMatch';
10 | import Navbar from './Navbar';
11 |
12 | function getInitialTodos() {
13 | const temp = localStorage.getItem('todos');
14 | const savedTodos = JSON.parse(temp);
15 | return savedTodos || [];
16 | }
17 |
18 | const TodoContainer = () => {
19 | const [todos, setTodos] = useState(getInitialTodos());
20 |
21 | const handleChange = (id) => {
22 | setTodos((prevState) => prevState.map((todo) => {
23 | if (todo.id === id) {
24 | return {
25 | ...todo,
26 | completed: !todo.completed,
27 | };
28 | }
29 | return todo;
30 | }));
31 | };
32 |
33 | const delTodo = (id) => {
34 | setTodos([
35 | ...todos.filter((todo) => todo.id !== id),
36 | ]);
37 | };
38 |
39 | const addTodoItem = (title) => {
40 | const newTodo = {
41 | id: uuidv4(),
42 | title,
43 | completed: false,
44 | };
45 | setTodos([...todos, newTodo]);
46 | };
47 |
48 | const setUpdate = (updateTitle, id) => {
49 | setTodos(
50 | todos.map((todo) => {
51 | if (todo.id === id) {
52 | todo.title = updateTitle;
53 | }
54 | return todo;
55 | }),
56 | );
57 | };
58 |
59 | /* useEffect(() => {
60 | console.log("test run")
61 | const temp = localStorage.getItem("todos")
62 | const loadedTodos = JSON.parse(temp)
63 |
64 | if (loadedTodos) {
65 | setTodos(loadedTodos)
66 | }
67 | }, [setTodos]) */
68 |
69 | useEffect(() => {
70 | const temp = JSON.stringify(todos);
71 | localStorage.setItem('todos', temp);
72 | }, [todos]);
73 |
74 | return (
75 | <>
76 |
77 |
78 |
83 |
84 |
85 |
86 |
92 |
93 |
94 | )}
95 | />
96 | } />
97 | } />
98 |
99 | >
100 | );
101 | };
102 |
103 | export default TodoContainer;
104 |
--------------------------------------------------------------------------------
/src/functionBased/components/TodoItem.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React, { useState, useEffect } from 'react';
3 | import styles from './TodoItem.module.css';
4 |
5 | const TodoItem = (props) => {
6 | const [editing, setEditing] = useState(false);
7 |
8 | const handleEditing = () => {
9 | setEditing(true);
10 | };
11 |
12 | const handleUpdateDone = (event) => {
13 | if (event.key === 'Enter') {
14 | setEditing(false);
15 | }
16 | };
17 |
18 | const completedStyle = {
19 | fontStyle: 'italic',
20 | color: '#595959',
21 | opacity: 0.4,
22 | textDecoration: 'line-through',
23 | };
24 |
25 | const { completed, id, title } = props.todo;
26 |
27 | const viewMode = {};
28 | const editMode = {};
29 |
30 | if (editing) {
31 | viewMode.display = 'none';
32 | } else {
33 | editMode.display = 'none';
34 | }
35 |
36 | useEffect(() => () => {
37 | console.log('Cleaning up...');
38 | }, []);
39 |
40 | return (
41 |
42 |
43 | props.handleChangeProps(id)}
48 | />
49 | props.deleteTodoProps(id)}>Delete
50 | {title}
51 |
52 | {
58 | props.setUpdate(e.target.value, id);
59 | }}
60 | onKeyDown={handleUpdateDone}
61 | />
62 |
63 | );
64 | };
65 |
66 | export default TodoItem;
67 |
--------------------------------------------------------------------------------
/src/functionBased/components/TodoItem.module.css:
--------------------------------------------------------------------------------
1 | .item {
2 | font-size: 1.2rem;
3 | list-style-type: none;
4 | padding: 17px 0;
5 | border-bottom: 1px solid #eaeaea;
6 | }
7 |
8 | .checkbox {
9 | margin-right: 15px;
10 | }
11 |
12 | .item button {
13 | font-size: 13px;
14 | background: #f1f3f4;
15 | border: none;
16 | cursor: pointer;
17 | float: right;
18 | outline: none;
19 | border-radius: 100px;
20 | height: 50px;
21 | width: 50px;
22 | margin: -10px 0 0 10px;
23 | }
24 |
25 | .textInput {
26 | width: 100%;
27 | padding: 10px;
28 | border: 1px solid #dfdfdf;
29 | }
30 |
--------------------------------------------------------------------------------
/src/functionBased/components/TodosList.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import React from 'react';
3 | import TodoItem from './TodoItem';
4 |
5 | const TodosList = (props) => (
6 |
7 | {props.todos.map((todo) => (
8 |
15 | ))}
16 |
17 | );
18 |
19 | export default TodosList;
20 |
--------------------------------------------------------------------------------
/src/functionBased/pages/About.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Link, Route, Routes } from 'react-router-dom';
3 | import SinglePage from './SinglePage';
4 |
5 | const About = () => (
6 |
7 |
8 |
9 |
10 | About App
11 |
12 |
13 | About Author
14 |
15 |
16 |
17 | } />
18 |
19 |
20 |
21 | );
22 | export default About;
23 |
--------------------------------------------------------------------------------
/src/functionBased/pages/NotMatch.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const NotMatch = () => (
4 |
5 |
No match for this page
6 |
7 | );
8 | export default NotMatch;
9 |
--------------------------------------------------------------------------------
/src/functionBased/pages/SinglePage.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useParams } from 'react-router-dom';
3 |
4 | const SinglePage = () => {
5 | const aboutData = [
6 | {
7 | slug: 'about-app',
8 | title: 'About the App',
9 | description:
10 | 'In this app, you can add, delete, submit and edit items. To edit items, simply double click on it. Once you are done, press the enter key to resubmit. This app will persist your data in the browser local storage. So whether you reload, close your app or reopened it, you still have access to your to-dos items.',
11 | },
12 | {
13 | slug: 'about-author',
14 | title: 'About the Author',
15 | description:
16 | 'This app was developed by Ibas Majid, a self-taught web developer and a technical writer. He is opened to freelance Gig. So go ahead and connect with ibas on Twitter @ibaslogic.',
17 | },
18 | ];
19 | const { slug } = useParams();
20 | const aboutContent = aboutData.find((item) => item.slug === slug);
21 | const { title, description } = aboutContent;
22 | return (
23 |
24 |
{title}
25 |
{description}
26 |
27 | );
28 | };
29 | export default SinglePage;
30 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { BrowserRouter as Router } from 'react-router-dom';
4 | import TodoContainer from './functionBased/components/TodoContainer';
5 | import './functionBased/App.css';
6 |
7 | ReactDOM.render(
8 |
9 |
10 |
11 |
12 | ,
13 | document.getElementById('root'),
14 | );
15 |
--------------------------------------------------------------------------------