From f13c66b5bfe553303d6c230c7fb1cbe8219f0faf Mon Sep 17 00:00:00 2001 From: Cherrerotinoco Date: Tue, 21 Sep 2021 15:38:21 +0200 Subject: [PATCH 01/23] Set up the minimun project components --- .husky/.gitignore | 1 + package.json | 1 + src/App.js | 36 +++++++++++++++++++-- src/components/AddToDoTask/AddToDoTask.js | 38 +++++++++++++++++++++++ src/components/TodoList/TodoList.js | 28 +++++++++++++++++ src/components/TodoList/index.js | 2 ++ src/utils/localStorage.js | 8 +++++ src/utils/updateState.js | 15 +++++++++ 8 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 .husky/.gitignore create mode 100644 src/components/AddToDoTask/AddToDoTask.js create mode 100644 src/components/TodoList/TodoList.js create mode 100644 src/components/TodoList/index.js create mode 100644 src/utils/localStorage.js create mode 100644 src/utils/updateState.js diff --git a/.husky/.gitignore b/.husky/.gitignore new file mode 100644 index 00000000..31354ec1 --- /dev/null +++ b/.husky/.gitignore @@ -0,0 +1 @@ +_ diff --git a/package.json b/package.json index 18a1117b..223770de 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "clsx": "^1.1.1", "cypress": "^7.5.0", "formik": "^2.2.6", + "lodash": "^4.17.21", "prop-types": "^15.7.2", "react": "^17.0.2", "react-dom": "^17.0.2", diff --git a/src/App.js b/src/App.js index de524524..7e4b2458 100644 --- a/src/App.js +++ b/src/App.js @@ -1,11 +1,43 @@ -import React from "react"; +/* eslint-disable prettier/prettier */ +import React, { useState } from "react"; +import _ from "lodash"; + +import AddToDoTask from "./components/AddToDoTask/AddToDoTask"; + +import { saveItem } from "./utils/localStorage"; +import TodoList from "./components/TodoList"; + function App() { + + const [tasks, updateTasks] = useState([]) + + const handlerToDoTask = (task) => { + // Save in localStorage + const unique = _.uniqueId() + const taskObj = { + id: unique, + text: task.title, + done: false, + isEditing: false + } + saveItem(taskObj) + + // Update tasks state + updateTasks((prevTasks) => { + return [...prevTasks, taskObj] + }) + + } + + + return (
-

Hola mundo

+ +
diff --git a/src/components/AddToDoTask/AddToDoTask.js b/src/components/AddToDoTask/AddToDoTask.js new file mode 100644 index 00000000..673602f9 --- /dev/null +++ b/src/components/AddToDoTask/AddToDoTask.js @@ -0,0 +1,38 @@ +/* eslint-disable prettier/prettier */ +import React from 'react' + +// Improve the render of the component + +export default class AddToDoTask extends React.Component { + + constructor(props) { + super(props) + this.state = { + title: 'Default' + } + } + + formSubmit = (event) => { + event.preventDefault() + + const {handlerToDoTask} = this.props + handlerToDoTask(this.state) + } + + updateState = (event) => { + this.setState(() => { + return {title: event.target.value} + }) + } + + render() { + const {title} = this.state + + return ( +
+ +
+ ) + } + +} \ No newline at end of file diff --git a/src/components/TodoList/TodoList.js b/src/components/TodoList/TodoList.js new file mode 100644 index 00000000..8f2e0965 --- /dev/null +++ b/src/components/TodoList/TodoList.js @@ -0,0 +1,28 @@ +/* eslint-disable prettier/prettier */ +import React from 'react' + +// Improve the render of the component + +export default class TodoList extends React.Component { + + constructor(props) { + super(props) + this.state = {} + } + + render() { + const {tasks} = this.props + return ( + <> + { + tasks.length === 0 ? +

No hay todos

: + tasks.map(task => ( +

{task.text}

+ )) + } + + ) + } + +} \ No newline at end of file diff --git a/src/components/TodoList/index.js b/src/components/TodoList/index.js new file mode 100644 index 00000000..b219c99e --- /dev/null +++ b/src/components/TodoList/index.js @@ -0,0 +1,2 @@ +/* eslint-disable prettier/prettier */ +export { default } from "./TodoList" \ No newline at end of file diff --git a/src/utils/localStorage.js b/src/utils/localStorage.js new file mode 100644 index 00000000..43415017 --- /dev/null +++ b/src/utils/localStorage.js @@ -0,0 +1,8 @@ +/* eslint-disable prettier/prettier */ +export function saveItem(item) { + window.localStorage.setItem(item.id, JSON.stringify(item)) +} + +export function getItem(id) { + window.localStorage.getItem(id) +} \ No newline at end of file diff --git a/src/utils/updateState.js b/src/utils/updateState.js new file mode 100644 index 00000000..68225997 --- /dev/null +++ b/src/utils/updateState.js @@ -0,0 +1,15 @@ +/* eslint-disable prettier/prettier */ + +// Reusable function to update state from component +/* +import {useState} from "react" + +export default function updateState(event) { + + const [state, setState] = useState() + + setState(() => { + return event.target.value + }) +} +*/ \ No newline at end of file From fc902c9a44eb534d70ac29e82702966e7eadea10 Mon Sep 17 00:00:00 2001 From: Cherrerotinoco Date: Tue, 21 Sep 2021 18:07:41 +0200 Subject: [PATCH 02/23] Add to do list --- src/App.js | 15 ++++++---- src/components/AddToDoTask/AddToDoTask.js | 35 +++++++++++++++++------ src/components/TodoList/TodoList.js | 13 +++++++-- 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/App.js b/src/App.js index 7e4b2458..e9e6e106 100644 --- a/src/App.js +++ b/src/App.js @@ -12,11 +12,13 @@ function App() { const [tasks, updateTasks] = useState([]) + const [defaultValues, setDefaultValues] = useState({}) + const handlerToDoTask = (task) => { // Save in localStorage - const unique = _.uniqueId() + const key = task.id !== '' ? task.id : _.uniqueId() const taskObj = { - id: unique, + id: key, text: task.title, done: false, isEditing: false @@ -25,19 +27,22 @@ function App() { // Update tasks state updateTasks((prevTasks) => { - return [...prevTasks, taskObj] + return task.id === '' ? [...prevTasks, taskObj] : [prevTasks] }) } + const editTaskText = (newText, newId) => { + setDefaultValues({id: newId, text: newText}) + } return (
- - + +
diff --git a/src/components/AddToDoTask/AddToDoTask.js b/src/components/AddToDoTask/AddToDoTask.js index 673602f9..8960b456 100644 --- a/src/components/AddToDoTask/AddToDoTask.js +++ b/src/components/AddToDoTask/AddToDoTask.js @@ -7,8 +7,21 @@ export default class AddToDoTask extends React.Component { constructor(props) { super(props) + this.state = { - title: 'Default' + id: '', + title: 'Default', + isEditing: false + } + } + + componentDidUpdate() { + const { defaultValues } = this.props + const {text , id} = defaultValues + const {title} = this.state + + if (id !== '' && text !== title) { + this.updateState({id, text, isEditing: true}) } } @@ -17,20 +30,26 @@ export default class AddToDoTask extends React.Component { const {handlerToDoTask} = this.props handlerToDoTask(this.state) + + this.updateState({}) } - updateState = (event) => { - this.setState(() => { - return {title: event.target.value} - }) + updateState = ({id = '', text = '', isEditing = false}) => { + this.setState({id: id, title: text, isEditing: isEditing}) } - render() { - const {title} = this.state + handlerInput = (event) => { + const text = event.target.value + const {id} = this.state + console.log(text) + this.updateState({id, text}) + } + render() { + const { title } = this.state return (
- +
) } diff --git a/src/components/TodoList/TodoList.js b/src/components/TodoList/TodoList.js index 8f2e0965..11f4bad1 100644 --- a/src/components/TodoList/TodoList.js +++ b/src/components/TodoList/TodoList.js @@ -1,6 +1,5 @@ /* eslint-disable prettier/prettier */ import React from 'react' - // Improve the render of the component export default class TodoList extends React.Component { @@ -9,6 +8,16 @@ export default class TodoList extends React.Component { super(props) this.state = {} } + + editHandler = (event) => { + const taskId = event.target.id + const text = event.target.innerText + + // Make text editable + const {editTaskText} = this.props + editTaskText(text, taskId) + + } render() { const {tasks} = this.props @@ -18,7 +27,7 @@ export default class TodoList extends React.Component { tasks.length === 0 ?

No hay todos

: tasks.map(task => ( -

{task.text}

+ )) } From c1c5b5db31871a66281b326d48d922c4aa5b325e Mon Sep 17 00:00:00 2001 From: Cherrerotinoco Date: Wed, 22 Sep 2021 13:45:36 +0200 Subject: [PATCH 03/23] Fix functionality and add styles to TodoTask component --- .eslintignore | 2 +- src/App.js | 16 ++---- src/components/AddToDoTask/AddToDoTask.js | 22 ++------ src/components/TodoList/TodoList.js | 22 +++----- src/components/TodoTask/TodoTask.js | 68 +++++++++++++++++++++++ src/components/TodoTask/TodoTask.scss | 17 ++++++ src/components/TodoTask/index.js | 1 + src/index.js | 1 + src/index.scss | 0 src/utils/localStorage.js | 4 ++ 10 files changed, 109 insertions(+), 44 deletions(-) create mode 100644 src/components/TodoTask/TodoTask.js create mode 100644 src/components/TodoTask/TodoTask.scss create mode 100644 src/components/TodoTask/index.js create mode 100644 src/index.scss diff --git a/.eslintignore b/.eslintignore index d8b83df9..483a9c42 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1 @@ -package-lock.json +package-lock.json \ No newline at end of file diff --git a/src/App.js b/src/App.js index e9e6e106..f4981229 100644 --- a/src/App.js +++ b/src/App.js @@ -12,14 +12,12 @@ function App() { const [tasks, updateTasks] = useState([]) - const [defaultValues, setDefaultValues] = useState({}) - const handlerToDoTask = (task) => { // Save in localStorage - const key = task.id !== '' ? task.id : _.uniqueId() + const key = _.uniqueId() const taskObj = { id: key, - text: task.title, + inputValue: task.title, done: false, isEditing: false } @@ -27,22 +25,18 @@ function App() { // Update tasks state updateTasks((prevTasks) => { - return task.id === '' ? [...prevTasks, taskObj] : [prevTasks] + return [...prevTasks, taskObj] }) } - const editTaskText = (newText, newId) => { - setDefaultValues({id: newId, text: newText}) - } - return (
- - + +
diff --git a/src/components/AddToDoTask/AddToDoTask.js b/src/components/AddToDoTask/AddToDoTask.js index 8960b456..f10da983 100644 --- a/src/components/AddToDoTask/AddToDoTask.js +++ b/src/components/AddToDoTask/AddToDoTask.js @@ -9,19 +9,7 @@ export default class AddToDoTask extends React.Component { super(props) this.state = { - id: '', - title: 'Default', - isEditing: false - } - } - - componentDidUpdate() { - const { defaultValues } = this.props - const {text , id} = defaultValues - const {title} = this.state - - if (id !== '' && text !== title) { - this.updateState({id, text, isEditing: true}) + title: 'Default' } } @@ -34,15 +22,13 @@ export default class AddToDoTask extends React.Component { this.updateState({}) } - updateState = ({id = '', text = '', isEditing = false}) => { - this.setState({id: id, title: text, isEditing: isEditing}) + updateState = ({text = ''}) => { + this.setState({title: text}) } handlerInput = (event) => { const text = event.target.value - const {id} = this.state - console.log(text) - this.updateState({id, text}) + this.updateState({text}) } render() { diff --git a/src/components/TodoList/TodoList.js b/src/components/TodoList/TodoList.js index 11f4bad1..79a067b8 100644 --- a/src/components/TodoList/TodoList.js +++ b/src/components/TodoList/TodoList.js @@ -1,6 +1,7 @@ /* eslint-disable prettier/prettier */ import React from 'react' // Improve the render of the component +import TodoTask from '../TodoTask/TodoTask' export default class TodoList extends React.Component { @@ -8,16 +9,6 @@ export default class TodoList extends React.Component { super(props) this.state = {} } - - editHandler = (event) => { - const taskId = event.target.id - const text = event.target.innerText - - // Make text editable - const {editTaskText} = this.props - editTaskText(text, taskId) - - } render() { const {tasks} = this.props @@ -26,12 +17,15 @@ export default class TodoList extends React.Component { { tasks.length === 0 ?

No hay todos

: - tasks.map(task => ( - - )) +
+ { + tasks.map(task => ( + + )) + } +
} ) } - } \ No newline at end of file diff --git a/src/components/TodoTask/TodoTask.js b/src/components/TodoTask/TodoTask.js new file mode 100644 index 00000000..b8e5418c --- /dev/null +++ b/src/components/TodoTask/TodoTask.js @@ -0,0 +1,68 @@ +/* eslint-disable prettier/prettier */ +import React from 'react' +import { deleteItem, saveItem } from '../../utils/localStorage' + +import "./TodoTask.scss" + +export default class TodoTask extends React.Component { + + constructor(props) { + super(props) + + const {id, inputValue} = this.props + + this.state = { + id: id, + done: false, + isEditing: false, + inputValue: inputValue + } + } + + completeHandler = () => { + const {done} = this.state + !done ? this.setState({done: true}) : this.setState({done: false}) + } + + deleteHanlder = () => { + const {id} = this.state + deleteItem(id) + this.setState({id: ''}) + } + + handlerSubmit = (event) => { + event.preventDefault() + saveItem({...this.state, isEditing: false}) + this.setState({isEditing: false}) + } + + editHandler = (event) => { + this.setState({inputValue: event.target.value}) + } + + render() { + + const {inputValue, id, isEditing, done} = this.state + + if (id === '') return null + + return( +
+ +
+ this.setState({isEditing: true})} + onBlur={() => this.setState({isEditing: false})} + /> +
+ +
+ + ) + } +} \ No newline at end of file diff --git a/src/components/TodoTask/TodoTask.scss b/src/components/TodoTask/TodoTask.scss new file mode 100644 index 00000000..61f83df4 --- /dev/null +++ b/src/components/TodoTask/TodoTask.scss @@ -0,0 +1,17 @@ +.todo-task { + border: solid; + + &.editing { + border-color: red + } +} +.done { + + border-color: green; + opacity: 0.75; + + .input-task { + text-decoration: line-through; + } + +} diff --git a/src/components/TodoTask/index.js b/src/components/TodoTask/index.js new file mode 100644 index 00000000..686c87c9 --- /dev/null +++ b/src/components/TodoTask/index.js @@ -0,0 +1 @@ +export { default } from "./TodoTask"; diff --git a/src/index.js b/src/index.js index 19bb154c..5516f597 100644 --- a/src/index.js +++ b/src/index.js @@ -2,6 +2,7 @@ import React from "react"; import ReactDOM from "react-dom"; import "bootstrap/dist/css/bootstrap.min.css"; +import "./index.scss"; import App from "./App"; import reportWebVitals from "./reportWebVitals"; diff --git a/src/index.scss b/src/index.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/utils/localStorage.js b/src/utils/localStorage.js index 43415017..c437afda 100644 --- a/src/utils/localStorage.js +++ b/src/utils/localStorage.js @@ -5,4 +5,8 @@ export function saveItem(item) { export function getItem(id) { window.localStorage.getItem(id) +} + +export function deleteItem(id) { + window.localStorage.removeItem(id) } \ No newline at end of file From 9f58eadc25ed357ab1ca547eb0f41aa016cea8bc Mon Sep 17 00:00:00 2001 From: Cherrerotinoco Date: Wed, 22 Sep 2021 17:31:36 +0200 Subject: [PATCH 04/23] Add validation to form --- src/App.js | 20 ++++++------ src/components/AddToDoTask/AddToDoTask.js | 34 +++++++++++++-------- src/components/AddToDoTask/AddToDoTask.scss | 7 +++++ src/components/AddToDoTask/index.js | 3 ++ src/components/TodoList/TodoList.js | 1 + src/components/TodoTask/TodoTask.js | 2 +- src/utils/localStorage.js | 6 +++- 7 files changed, 50 insertions(+), 23 deletions(-) create mode 100644 src/components/AddToDoTask/AddToDoTask.scss create mode 100644 src/components/AddToDoTask/index.js diff --git a/src/App.js b/src/App.js index f4981229..2513eba4 100644 --- a/src/App.js +++ b/src/App.js @@ -1,10 +1,8 @@ /* eslint-disable prettier/prettier */ -import React, { useState } from "react"; -import _ from "lodash"; - +import React, { useState, useEffect } from "react"; import AddToDoTask from "./components/AddToDoTask/AddToDoTask"; -import { saveItem } from "./utils/localStorage"; +import { generateNewKey, getItem, saveItem } from "./utils/localStorage"; import TodoList from "./components/TodoList"; @@ -12,9 +10,16 @@ function App() { const [tasks, updateTasks] = useState([]) + // Get localStorage Items + useEffect(() => { + const localStorageTasks = Object.keys(localStorage).map(key => JSON.parse(getItem(parseInt(key, 10)))) + updateTasks((prevTasks) => [...prevTasks, ...localStorageTasks]) + }, []) + + // Add to do task to list const handlerToDoTask = (task) => { // Save in localStorage - const key = _.uniqueId() + const key = generateNewKey() const taskObj = { id: key, inputValue: task.title, @@ -24,10 +29,7 @@ function App() { saveItem(taskObj) // Update tasks state - updateTasks((prevTasks) => { - return [...prevTasks, taskObj] - }) - + updateTasks((prevTasks) => [...prevTasks, taskObj]) } diff --git a/src/components/AddToDoTask/AddToDoTask.js b/src/components/AddToDoTask/AddToDoTask.js index f10da983..e5b83398 100644 --- a/src/components/AddToDoTask/AddToDoTask.js +++ b/src/components/AddToDoTask/AddToDoTask.js @@ -1,6 +1,6 @@ /* eslint-disable prettier/prettier */ import React from 'react' - +import './AddToDoTask.scss' // Improve the render of the component export default class AddToDoTask extends React.Component { @@ -9,34 +9,44 @@ export default class AddToDoTask extends React.Component { super(props) this.state = { - title: 'Default' + title: 'Do the homework...', + error: false } } formSubmit = (event) => { event.preventDefault() - - const {handlerToDoTask} = this.props - handlerToDoTask(this.state) - this.updateState({}) - } + const {error} = this.state + if (!error) { + // Send new task to parent + const {handlerToDoTask} = this.props + handlerToDoTask(this.state) + this.updateState({}) + } - updateState = ({text = ''}) => { - this.setState({title: text}) } handlerInput = (event) => { const text = event.target.value - this.updateState({text}) + const error = text.length === 0 + console.log(error) + this.updateState({text, error}) + } + + updateState = ({text = '', error}) => { + this.setState({title: text, error: error}) } render() { - const { title } = this.state + const { title, error } = this.state return ( + <>
- +
+ Please enter at least one character + ) } diff --git a/src/components/AddToDoTask/AddToDoTask.scss b/src/components/AddToDoTask/AddToDoTask.scss new file mode 100644 index 00000000..f0bc119b --- /dev/null +++ b/src/components/AddToDoTask/AddToDoTask.scss @@ -0,0 +1,7 @@ +.show { + display: block; + color: red; +} +.hide { + display: none; +} \ No newline at end of file diff --git a/src/components/AddToDoTask/index.js b/src/components/AddToDoTask/index.js new file mode 100644 index 00000000..b020c385 --- /dev/null +++ b/src/components/AddToDoTask/index.js @@ -0,0 +1,3 @@ +import AddToDoTask from "./AddToDoTask"; + +export default AddToDoTask; diff --git a/src/components/TodoList/TodoList.js b/src/components/TodoList/TodoList.js index 79a067b8..1997e0c3 100644 --- a/src/components/TodoList/TodoList.js +++ b/src/components/TodoList/TodoList.js @@ -20,6 +20,7 @@ export default class TodoList extends React.Component {
{ tasks.map(task => ( + )) } diff --git a/src/components/TodoTask/TodoTask.js b/src/components/TodoTask/TodoTask.js index b8e5418c..8fa201e6 100644 --- a/src/components/TodoTask/TodoTask.js +++ b/src/components/TodoTask/TodoTask.js @@ -54,7 +54,7 @@ export default class TodoTask extends React.Component {
- this.setState({isEditing: true})} onBlur={() => this.setState({isEditing: false})} diff --git a/src/utils/localStorage.js b/src/utils/localStorage.js index c437afda..46287c0f 100644 --- a/src/utils/localStorage.js +++ b/src/utils/localStorage.js @@ -4,9 +4,13 @@ export function saveItem(item) { } export function getItem(id) { - window.localStorage.getItem(id) + return window.localStorage.getItem(id) } export function deleteItem(id) { window.localStorage.removeItem(id) +} + +export function generateNewKey() { + return Object.keys(localStorage).length > 0 ? Math.max(...Object.keys(localStorage)) + 1 : 1 } \ No newline at end of file From d5b0eab89bc7bdbe64681ac2048d2bc0eb4803df Mon Sep 17 00:00:00 2001 From: Cherrerotinoco Date: Wed, 22 Sep 2021 17:33:15 +0200 Subject: [PATCH 05/23] Add validation to form --- src/components/AddToDoTask/AddToDoTask.js | 2 +- src/components/TodoList/TodoList.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/AddToDoTask/AddToDoTask.js b/src/components/AddToDoTask/AddToDoTask.js index e5b83398..9c189f98 100644 --- a/src/components/AddToDoTask/AddToDoTask.js +++ b/src/components/AddToDoTask/AddToDoTask.js @@ -30,7 +30,7 @@ export default class AddToDoTask extends React.Component { handlerInput = (event) => { const text = event.target.value const error = text.length === 0 - console.log(error) + this.updateState({text, error}) } diff --git a/src/components/TodoList/TodoList.js b/src/components/TodoList/TodoList.js index 1997e0c3..acc83c4e 100644 --- a/src/components/TodoList/TodoList.js +++ b/src/components/TodoList/TodoList.js @@ -16,7 +16,7 @@ export default class TodoList extends React.Component { <> { tasks.length === 0 ? -

No hay todos

: +

There is any to do yet 😥

:
{ tasks.map(task => ( From a6314e6381553bb81f91b5fe8f6a196b8f406188 Mon Sep 17 00:00:00 2001 From: Cherrerotinoco Date: Thu, 23 Sep 2021 10:51:22 +0200 Subject: [PATCH 06/23] Add Header,Main,Footer components --- src/App.js | 34 ++++++++++++++++++++----- src/components/FilterToDo/FilterToDo.js | 34 +++++++++++++++++++++++++ src/components/Footer/Footer.js | 20 +++++++++++++++ src/components/Footer/index.js | 1 + src/components/Header/Header.js | 20 +++++++++++++++ src/components/Header/index.js | 1 + src/components/Main/Main.js | 20 +++++++++++++++ src/components/Main/index.js | 1 + src/components/TodoList/TodoList.js | 19 +++++++++++--- src/components/TodoTask/TodoTask.js | 9 ++++++- 10 files changed, 149 insertions(+), 10 deletions(-) create mode 100644 src/components/FilterToDo/FilterToDo.js create mode 100644 src/components/Footer/Footer.js create mode 100644 src/components/Footer/index.js create mode 100644 src/components/Header/Header.js create mode 100644 src/components/Header/index.js create mode 100644 src/components/Main/Main.js create mode 100644 src/components/Main/index.js diff --git a/src/App.js b/src/App.js index 2513eba4..ecf1b074 100644 --- a/src/App.js +++ b/src/App.js @@ -1,10 +1,16 @@ /* eslint-disable prettier/prettier */ import React, { useState, useEffect } from "react"; +import { BrowserRouter, Switch, Route } from "react-router-dom"; + import AddToDoTask from "./components/AddToDoTask/AddToDoTask"; -import { generateNewKey, getItem, saveItem } from "./utils/localStorage"; -import TodoList from "./components/TodoList"; +import Header from "./components/Header/Header"; +import Main from "./components/Main/Main"; +import Footer from "./components/Footer/Footer"; +import { generateNewKey, saveItem } from "./utils/localStorage"; +import TodoList from "./components/TodoList"; +import FilterToDo from "./components/FilterToDo/FilterToDo"; function App() { @@ -12,8 +18,8 @@ function App() { // Get localStorage Items useEffect(() => { - const localStorageTasks = Object.keys(localStorage).map(key => JSON.parse(getItem(parseInt(key, 10)))) - updateTasks((prevTasks) => [...prevTasks, ...localStorageTasks]) + const localStorageTasks = Object.values(localStorage).map(elm => JSON.parse(elm)) + localStorageTasks.length > 0 ? updateTasks((prevTasks) => [...prevTasks, ...localStorageTasks]) : null }, []) // Add to do task to list @@ -32,13 +38,29 @@ function App() { updateTasks((prevTasks) => [...prevTasks, taskObj]) } + const handlerFilter = () => { + + } return (
- - + +
+ +
+
+ + }/> + } /> + } /> + +
+
+ +
+
diff --git a/src/components/FilterToDo/FilterToDo.js b/src/components/FilterToDo/FilterToDo.js new file mode 100644 index 00000000..c2bb0d85 --- /dev/null +++ b/src/components/FilterToDo/FilterToDo.js @@ -0,0 +1,34 @@ +/* eslint-disable prettier/prettier */ +import React from 'react' +import {BrowserRouter, Link } from 'react-router-dom' + +export default class FilterToDo extends React.Component { + + constructor(props) { + super(props) + this.state = {} + } + + + render() { + const {counter} = this.props + + return ( + <> +
+ +

{counter}

+ + + All + Active + Completed + + + + +
+ + ) + } +} \ No newline at end of file diff --git a/src/components/Footer/Footer.js b/src/components/Footer/Footer.js new file mode 100644 index 00000000..5fb0376d --- /dev/null +++ b/src/components/Footer/Footer.js @@ -0,0 +1,20 @@ +/* eslint-disable prettier/prettier */ +import React from 'react' + +export default class Footer extends React.Component { + + constructor(props) { + super(props) + this.state = {} + } + + + render() { + const {children} = this.props + return ( + <> + {children} + + ) + } +} \ No newline at end of file diff --git a/src/components/Footer/index.js b/src/components/Footer/index.js new file mode 100644 index 00000000..3738288b --- /dev/null +++ b/src/components/Footer/index.js @@ -0,0 +1 @@ +export { default } from "./Footer"; diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js new file mode 100644 index 00000000..1c02bde7 --- /dev/null +++ b/src/components/Header/Header.js @@ -0,0 +1,20 @@ +/* eslint-disable prettier/prettier */ +import React from 'react' + +export default class Header extends React.Component { + + constructor(props) { + super(props) + this.state = {} + } + + + render() { + const {children} = this.props + return ( + <> + {children} + + ) + } +} \ No newline at end of file diff --git a/src/components/Header/index.js b/src/components/Header/index.js new file mode 100644 index 00000000..2764567d --- /dev/null +++ b/src/components/Header/index.js @@ -0,0 +1 @@ +export { default } from "./Header"; diff --git a/src/components/Main/Main.js b/src/components/Main/Main.js new file mode 100644 index 00000000..042c78ed --- /dev/null +++ b/src/components/Main/Main.js @@ -0,0 +1,20 @@ +/* eslint-disable prettier/prettier */ +import React from 'react' + +export default class Main extends React.Component { + + constructor(props) { + super(props) + this.state = {} + } + + + render() { + const {children} = this.props + return ( + <> + {children} + + ) + } +} \ No newline at end of file diff --git a/src/components/Main/index.js b/src/components/Main/index.js new file mode 100644 index 00000000..0fdf55f5 --- /dev/null +++ b/src/components/Main/index.js @@ -0,0 +1 @@ +export { default } from "./Main"; diff --git a/src/components/TodoList/TodoList.js b/src/components/TodoList/TodoList.js index acc83c4e..b99193ab 100644 --- a/src/components/TodoList/TodoList.js +++ b/src/components/TodoList/TodoList.js @@ -7,11 +7,24 @@ export default class TodoList extends React.Component { constructor(props) { super(props) + this.state = {} } + handlerTaskDeleted = (task) => { + console.log(task) + + // Find in state deleted task + + // Update state with new array + + // Then render again the child components + + } + render() { - const {tasks} = this.props + const {tasks} = this.props + return ( <> { @@ -20,11 +33,11 @@ export default class TodoList extends React.Component {
{ tasks.map(task => ( - - + )) }
+ } ) diff --git a/src/components/TodoTask/TodoTask.js b/src/components/TodoTask/TodoTask.js index 8fa201e6..7ceefacf 100644 --- a/src/components/TodoTask/TodoTask.js +++ b/src/components/TodoTask/TodoTask.js @@ -18,7 +18,14 @@ export default class TodoTask extends React.Component { inputValue: inputValue } } - + + /* + componentWillUnmount() { + const {callBackFromParent} = this.prop + callBackFromParent(this.state) + } + */ + completeHandler = () => { const {done} = this.state !done ? this.setState({done: true}) : this.setState({done: false}) From bd267cc2a9db1c11e5c2b33c6778dc23be27b623 Mon Sep 17 00:00:00 2001 From: Cherrerotinoco Date: Thu, 23 Sep 2021 17:39:58 +0200 Subject: [PATCH 07/23] Finish basic CRUD functionalities --- src/App.js | 118 ++++++++++++---------- src/components/AddToDoTask/AddToDoTask.js | 25 +++-- src/components/FilterToDo/FilterToDo.js | 8 +- src/components/Main/Main.js | 20 ---- src/components/Main/index.js | 1 - src/components/MainList/MainList.js | 34 +++++++ src/components/MainList/index.js | 1 + src/components/TodoList/TodoList.js | 19 +--- src/components/TodoTask/TodoTask.js | 37 +++---- src/pages/Active/Active.js | 24 +++++ src/pages/Active/index.js | 1 + src/pages/Completed/Completed.js | 25 +++++ src/pages/Completed/index.js | 1 + src/pages/Home/Home.js | 20 ++++ src/pages/Home/index.js | 1 + 15 files changed, 211 insertions(+), 124 deletions(-) delete mode 100644 src/components/Main/Main.js delete mode 100644 src/components/Main/index.js create mode 100644 src/components/MainList/MainList.js create mode 100644 src/components/MainList/index.js create mode 100644 src/pages/Active/Active.js create mode 100644 src/pages/Active/index.js create mode 100644 src/pages/Completed/Completed.js create mode 100644 src/pages/Completed/index.js create mode 100644 src/pages/Home/Home.js create mode 100644 src/pages/Home/index.js diff --git a/src/App.js b/src/App.js index ecf1b074..0b1e897e 100644 --- a/src/App.js +++ b/src/App.js @@ -1,70 +1,80 @@ /* eslint-disable prettier/prettier */ -import React, { useState, useEffect } from "react"; -import { BrowserRouter, Switch, Route } from "react-router-dom"; +import React from "react"; +import { BrowserRouter } from "react-router-dom"; -import AddToDoTask from "./components/AddToDoTask/AddToDoTask"; - -import Header from "./components/Header/Header"; -import Main from "./components/Main/Main"; +import AddToDoTask from "./components/AddToDoTask"; import Footer from "./components/Footer/Footer"; - -import { generateNewKey, saveItem } from "./utils/localStorage"; -import TodoList from "./components/TodoList"; +import Header from "./components/Header"; +import MainList from "./components/MainList"; import FilterToDo from "./components/FilterToDo/FilterToDo"; +import { deleteItem, saveItem } from "./utils/localStorage"; -function App() { - const [tasks, updateTasks] = useState([]) +export default class App extends React.Component { - // Get localStorage Items - useEffect(() => { - const localStorageTasks = Object.values(localStorage).map(elm => JSON.parse(elm)) - localStorageTasks.length > 0 ? updateTasks((prevTasks) => [...prevTasks, ...localStorageTasks]) : null - }, []) - - // Add to do task to list - const handlerToDoTask = (task) => { - // Save in localStorage - const key = generateNewKey() - const taskObj = { - id: key, - inputValue: task.title, - done: false, - isEditing: false + constructor(props) { + super(props) + + this.state = { + tasks: [] } - saveItem(taskObj) - // Update tasks state - updateTasks((prevTasks) => [...prevTasks, taskObj]) + } + + componentDidMount() { + // Then re-render MainList (props: task) & Footer (props: lenght) + this.refreshState() } - const handlerFilter = () => { - + handlerNewToDo = (task) => { + // Save Todo en localStorage + saveItem(task) + // Refresh state with new localStorage + this.refreshState() } + + handlerDeleteTask = (id) => { + // Delete item from locaStorage + deleteItem(id) - return ( -
-
-
- + // Refresh state + this.refreshState() + } + + handlerClearCompleted = () => { + Object.values(localStorage).forEach(elm => { + const task = JSON.parse(elm) + task.done ? deleteItem(task.id) : null + }) + this.refreshState() + } + + refreshState = () => { + // Get items from localStorage + const localStorageTasks = Object.values(localStorage).map(elm => JSON.parse(elm)) + // Refresh state with new localStorage + localStorageTasks.length > 0 ? this.setState({tasks: [...localStorageTasks]}) : this.setState({tasks: []}) + } + + render() { + const {tasks} = this.state + + return ( +
+
+
- +
-
- - }/> - } /> - } /> - -
-
- -
- -
-
-
- ); + + +
+ +
+
+
+
+
+ ) + } } - -export default App; diff --git a/src/components/AddToDoTask/AddToDoTask.js b/src/components/AddToDoTask/AddToDoTask.js index 9c189f98..81637e83 100644 --- a/src/components/AddToDoTask/AddToDoTask.js +++ b/src/components/AddToDoTask/AddToDoTask.js @@ -1,6 +1,7 @@ /* eslint-disable prettier/prettier */ import React from 'react' import './AddToDoTask.scss' +import { generateNewKey } from '../../utils/localStorage' // Improve the render of the component export default class AddToDoTask extends React.Component { @@ -17,12 +18,24 @@ export default class AddToDoTask extends React.Component { formSubmit = (event) => { event.preventDefault() - const {error} = this.state - if (!error) { - // Send new task to parent - const {handlerToDoTask} = this.props - handlerToDoTask(this.state) - this.updateState({}) + const {error, title} = this.state + const {handlerNewToDo} = this.props + + if (!error && title !== '') { + + const key = generateNewKey() + const taskObj = { + id: key, + inputValue: title, + done: false, + isEditing: false + } + + // Send new task to App + handlerNewToDo(taskObj) + + // Reset input state + this.updateState({title: '', error: false}) } } diff --git a/src/components/FilterToDo/FilterToDo.js b/src/components/FilterToDo/FilterToDo.js index c2bb0d85..57c550e1 100644 --- a/src/components/FilterToDo/FilterToDo.js +++ b/src/components/FilterToDo/FilterToDo.js @@ -1,6 +1,6 @@ /* eslint-disable prettier/prettier */ import React from 'react' -import {BrowserRouter, Link } from 'react-router-dom' +import { Link } from 'react-router-dom' export default class FilterToDo extends React.Component { @@ -11,7 +11,7 @@ export default class FilterToDo extends React.Component { render() { - const {counter} = this.props + const {counter, handlerClearCompleted} = this.props return ( <> @@ -19,13 +19,11 @@ export default class FilterToDo extends React.Component {

{counter}

- All Active Completed - - +
diff --git a/src/components/Main/Main.js b/src/components/Main/Main.js deleted file mode 100644 index 042c78ed..00000000 --- a/src/components/Main/Main.js +++ /dev/null @@ -1,20 +0,0 @@ -/* eslint-disable prettier/prettier */ -import React from 'react' - -export default class Main extends React.Component { - - constructor(props) { - super(props) - this.state = {} - } - - - render() { - const {children} = this.props - return ( - <> - {children} - - ) - } -} \ No newline at end of file diff --git a/src/components/Main/index.js b/src/components/Main/index.js deleted file mode 100644 index 0fdf55f5..00000000 --- a/src/components/Main/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from "./Main"; diff --git a/src/components/MainList/MainList.js b/src/components/MainList/MainList.js new file mode 100644 index 00000000..aeba7a7f --- /dev/null +++ b/src/components/MainList/MainList.js @@ -0,0 +1,34 @@ +/* eslint-disable prettier/prettier */ +import React from 'react' +import { Switch, Route } from "react-router-dom"; +import Home from "../../pages/Home" +import Active from "../../pages/Active" +import Completed from "../../pages/Completed" + +export default class MainList extends React.Component { + + constructor(props) { + super(props) + this.state = { + + } + } + + render() { + return ( + <> + + + + + + + + + + + + + ) + } +} \ No newline at end of file diff --git a/src/components/MainList/index.js b/src/components/MainList/index.js new file mode 100644 index 00000000..f03c1bec --- /dev/null +++ b/src/components/MainList/index.js @@ -0,0 +1 @@ +export { default } from "./MainList"; diff --git a/src/components/TodoList/TodoList.js b/src/components/TodoList/TodoList.js index b99193ab..83cfa0ab 100644 --- a/src/components/TodoList/TodoList.js +++ b/src/components/TodoList/TodoList.js @@ -1,7 +1,7 @@ /* eslint-disable prettier/prettier */ import React from 'react' // Improve the render of the component -import TodoTask from '../TodoTask/TodoTask' +import TodoTask from "../TodoTask" export default class TodoList extends React.Component { @@ -11,17 +11,6 @@ export default class TodoList extends React.Component { this.state = {} } - handlerTaskDeleted = (task) => { - console.log(task) - - // Find in state deleted task - - // Update state with new array - - // Then render again the child components - - } - render() { const {tasks} = this.props @@ -30,13 +19,13 @@ export default class TodoList extends React.Component { { tasks.length === 0 ?

There is any to do yet 😥

: -
+
    { tasks.map(task => ( - + )) } -
+ } diff --git a/src/components/TodoTask/TodoTask.js b/src/components/TodoTask/TodoTask.js index 7ceefacf..9fd38dc8 100644 --- a/src/components/TodoTask/TodoTask.js +++ b/src/components/TodoTask/TodoTask.js @@ -1,6 +1,6 @@ /* eslint-disable prettier/prettier */ import React from 'react' -import { deleteItem, saveItem } from '../../utils/localStorage' +import { saveItem } from '../../utils/localStorage' import "./TodoTask.scss" @@ -9,32 +9,22 @@ export default class TodoTask extends React.Component { constructor(props) { super(props) - const {id, inputValue} = this.props + const {task} = this.props this.state = { - id: id, - done: false, - isEditing: false, - inputValue: inputValue + id: task.id, + done: task.done, + isEditing: task.isEditing, + inputValue: task.inputValue } } - /* - componentWillUnmount() { - const {callBackFromParent} = this.prop - callBackFromParent(this.state) - } - */ - completeHandler = () => { const {done} = this.state - !done ? this.setState({done: true}) : this.setState({done: false}) - } - - deleteHanlder = () => { - const {id} = this.state - deleteItem(id) - this.setState({id: ''}) + !done ? + ( saveItem({...this.state, done: true}) , this.setState({done: true}) ) + : + ( saveItem({...this.state, done: false}) , this.setState({done: false}) ) } handlerSubmit = (event) => { @@ -50,11 +40,12 @@ export default class TodoTask extends React.Component { render() { const {inputValue, id, isEditing, done} = this.state + const {handlerDeleteTask} = this.props if (id === '') return null return( -
+
  • -
  • + + ) } diff --git a/src/pages/Active/Active.js b/src/pages/Active/Active.js new file mode 100644 index 00000000..21f1cb59 --- /dev/null +++ b/src/pages/Active/Active.js @@ -0,0 +1,24 @@ +/* eslint-disable prettier/prettier */ +import React from "react"; +import TodoList from "../../components/TodoList"; + +export default class Active extends React.Component { + + constructor(props) { + super(props) + this.state = {} + } + + + render() { + + const {tasks} = this.props + const activeTasks = tasks.filter(task => !task.done) + + return ( + <> + + + ) + } +} \ No newline at end of file diff --git a/src/pages/Active/index.js b/src/pages/Active/index.js new file mode 100644 index 00000000..bfae90d4 --- /dev/null +++ b/src/pages/Active/index.js @@ -0,0 +1 @@ +export { default } from "./Active"; diff --git a/src/pages/Completed/Completed.js b/src/pages/Completed/Completed.js new file mode 100644 index 00000000..817a159c --- /dev/null +++ b/src/pages/Completed/Completed.js @@ -0,0 +1,25 @@ +/* eslint-disable prettier/prettier */ +import React from "react"; +import TodoList from "../../components/TodoList"; + + +export default class Completed extends React.Component { + + constructor(props) { + super(props) + this.state = {} + } + + + render() { + + const {tasks} = this.props + const completedTasks = tasks.filter(task => task.done) + + return ( + <> + + + ) + } +} \ No newline at end of file diff --git a/src/pages/Completed/index.js b/src/pages/Completed/index.js new file mode 100644 index 00000000..2472503b --- /dev/null +++ b/src/pages/Completed/index.js @@ -0,0 +1 @@ +export { default } from "./Completed"; diff --git a/src/pages/Home/Home.js b/src/pages/Home/Home.js new file mode 100644 index 00000000..3620b49b --- /dev/null +++ b/src/pages/Home/Home.js @@ -0,0 +1,20 @@ +/* eslint-disable prettier/prettier */ +import React from "react"; +import TodoList from "../../components/TodoList"; + +export default class Home extends React.Component { + + constructor(props) { + super(props) + this.state = {} + } + + + render() { + return ( + <> + + + ) + } +} \ No newline at end of file diff --git a/src/pages/Home/index.js b/src/pages/Home/index.js new file mode 100644 index 00000000..ffa79319 --- /dev/null +++ b/src/pages/Home/index.js @@ -0,0 +1 @@ +export { default } from "./Home"; From 953bda10c627b0f474aa26ba45a8e20ae7fd82f6 Mon Sep 17 00:00:00 2001 From: ParisArcos <84467828+ParisArcos@users.noreply.github.com> Date: Fri, 24 Sep 2021 11:46:22 +0100 Subject: [PATCH 08/23] problems --- src/components/Header/Header.js | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/components/Header/Header.js diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js new file mode 100644 index 00000000..2a389605 --- /dev/null +++ b/src/components/Header/Header.js @@ -0,0 +1,14 @@ +/* eslint-disable prettier/prettier */ +import React from "react"; + +export default class Header extends React.Component { + constructor(props) { + super(props); + this.state = {}; + } + + render() { + const { children } = this.props; + return <>{children}; + } +} From fbb7cf6861ff5e1cf79d854a1ae9cf0cf3dc83cb Mon Sep 17 00:00:00 2001 From: ParisArcos <84467828+ParisArcos@users.noreply.github.com> Date: Fri, 24 Sep 2021 12:17:07 +0100 Subject: [PATCH 09/23] sd --- src/index.scss | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/index.scss diff --git a/src/index.scss b/src/index.scss new file mode 100644 index 00000000..e69de29b From a0cc25fd3a87c7684abd4d5cede3476e5261a5a6 Mon Sep 17 00:00:00 2001 From: Cherrerotinoco Date: Mon, 27 Sep 2021 09:49:56 +0200 Subject: [PATCH 10/23] Add styles to AddToDoTask component --- src/components/AddToDoTask/AddToDoTask.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/AddToDoTask/AddToDoTask.js b/src/components/AddToDoTask/AddToDoTask.js index 81637e83..0c824ab3 100644 --- a/src/components/AddToDoTask/AddToDoTask.js +++ b/src/components/AddToDoTask/AddToDoTask.js @@ -2,6 +2,8 @@ import React from 'react' import './AddToDoTask.scss' import { generateNewKey } from '../../utils/localStorage' + + // Improve the render of the component export default class AddToDoTask extends React.Component { @@ -56,9 +58,9 @@ export default class AddToDoTask extends React.Component { return ( <>
    - +
    - Please enter at least one character +
    Please enter at least one character
    ) } From c29abc2ffe5f08497ba4cd1fd961292b7a7a8570 Mon Sep 17 00:00:00 2001 From: Cherrerotinoco Date: Mon, 27 Sep 2021 10:53:24 +0200 Subject: [PATCH 11/23] Add styles in ToDo list and footer filter bar --- src/components/FilterToDo/FilterToDo.js | 21 ++++++++++----------- src/components/FilterToDo/FilterToDo.scss | 8 ++++++++ src/components/FilterToDo/index.js | 1 + src/components/TodoList/TodoList.js | 2 +- src/components/TodoTask/TodoTask.js | 6 +++--- src/components/TodoTask/TodoTask.scss | 13 +++++++------ 6 files changed, 30 insertions(+), 21 deletions(-) create mode 100644 src/components/FilterToDo/FilterToDo.scss create mode 100644 src/components/FilterToDo/index.js diff --git a/src/components/FilterToDo/FilterToDo.js b/src/components/FilterToDo/FilterToDo.js index 57c550e1..933f1a6c 100644 --- a/src/components/FilterToDo/FilterToDo.js +++ b/src/components/FilterToDo/FilterToDo.js @@ -1,6 +1,7 @@ /* eslint-disable prettier/prettier */ import React from 'react' import { Link } from 'react-router-dom' +import './FilterToDo.scss' export default class FilterToDo extends React.Component { @@ -15,17 +16,15 @@ export default class FilterToDo extends React.Component { return ( <> -
    - -

    {counter}

    - - All - Active - Completed - - - -
    + ) } diff --git a/src/components/FilterToDo/FilterToDo.scss b/src/components/FilterToDo/FilterToDo.scss new file mode 100644 index 00000000..db722455 --- /dev/null +++ b/src/components/FilterToDo/FilterToDo.scss @@ -0,0 +1,8 @@ +.nav-link { + padding: 10px; + color: var(--gray-dark); + + &:hover { + color: var(--secondary); + } +} \ No newline at end of file diff --git a/src/components/FilterToDo/index.js b/src/components/FilterToDo/index.js new file mode 100644 index 00000000..090bb22d --- /dev/null +++ b/src/components/FilterToDo/index.js @@ -0,0 +1 @@ +export { default } from "./FilterToDo"; diff --git a/src/components/TodoList/TodoList.js b/src/components/TodoList/TodoList.js index 83cfa0ab..8d188f8b 100644 --- a/src/components/TodoList/TodoList.js +++ b/src/components/TodoList/TodoList.js @@ -19,7 +19,7 @@ export default class TodoList extends React.Component { { tasks.length === 0 ?

    There is any to do yet 😥

    : -