From c58d576f44b0906be93d83b7cac497e18d4e1486 Mon Sep 17 00:00:00 2001 From: herb falcone Date: Thu, 22 Jun 2023 13:51:29 -0600 Subject: [PATCH 1/6] [ADD] --- package-lock.json | 15 ++++++++++ package.json | 1 + src/App.css | 38 ----------------------- src/App.js | 73 ++++++++++++++++++++++++++++++++++----------- src/CreateButton.js | 11 +++++++ src/NameCounter.js | 13 ++++++++ src/TodoFilter.js | 12 ++++++++ src/TodoItem.js | 16 ++++++++++ src/TodoList.js | 12 ++++++++ src/buttonStyle.css | 13 ++++++++ src/check.svg | 7 +++++ src/completeIcon.js | 9 ++++++ src/delete.svg | 9 ++++++ src/deleteIcon.js | 9 ++++++ src/nameCounter.css | 2 ++ src/todoFilter.css | 1 + src/todoIcon.css | 19 ++++++++++++ src/todoIcon.js | 17 +++++++++++ src/todoItem.css | 12 ++++++++ src/todoList.css | 1 + 20 files changed, 234 insertions(+), 56 deletions(-) delete mode 100644 src/App.css create mode 100644 src/CreateButton.js create mode 100644 src/NameCounter.js create mode 100644 src/TodoFilter.js create mode 100644 src/TodoItem.js create mode 100644 src/TodoList.js create mode 100644 src/buttonStyle.css create mode 100644 src/check.svg create mode 100644 src/completeIcon.js create mode 100644 src/delete.svg create mode 100644 src/deleteIcon.js create mode 100644 src/nameCounter.css create mode 100644 src/todoFilter.css create mode 100644 src/todoIcon.css create mode 100644 src/todoIcon.js create mode 100644 src/todoItem.css create mode 100644 src/todoList.css diff --git a/package-lock.json b/package-lock.json index f26ec7a8b..c84ee3f87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "react": "^18", "react-dom": "^18", + "react-icons": "^4.9.0", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" } @@ -13423,6 +13424,14 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "node_modules/react-icons": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.9.0.tgz", + "integrity": "sha512-ijUnFr//ycebOqujtqtV9PFS7JjhWg0QU6ykURVHuL4cbofvRCf3f6GMn9+fBktEFQOIVZnuAYLZdiyadRQRFg==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", @@ -25601,6 +25610,12 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "react-icons": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.9.0.tgz", + "integrity": "sha512-ijUnFr//ycebOqujtqtV9PFS7JjhWg0QU6ykURVHuL4cbofvRCf3f6GMn9+fBktEFQOIVZnuAYLZdiyadRQRFg==", + "requires": {} + }, "react-is": { "version": "17.0.2", "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", diff --git a/package.json b/package.json index 0c4b9cdc0..07e6e08c7 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "dependencies": { "react": "^18", "react-dom": "^18", + "react-icons": "^4.9.0", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" }, diff --git a/src/App.css b/src/App.css deleted file mode 100644 index 4661df052..000000000 --- a/src/App.css +++ /dev/null @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #233553; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #97ca3f; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/src/App.js b/src/App.js index 952c8f1fd..ca3bf97e7 100644 --- a/src/App.js +++ b/src/App.js @@ -1,24 +1,61 @@ -import logo from './platzi.webp'; -import './App.css'; +import {NameCounter} from "./NameCounter"; +import { TodoFilter } from "./TodoFilter"; +import { TodoList } from "./TodoList"; +import {TodoItem} from "./TodoItem"; +import { CreateButton } from "./CreateButton"; +import React from "react"; +const todo =[{ + text:"visitar alemania", completed: false +}, +{ + text:"completar el curso fullstack", completed: false +}, +{ + text:"renderizar un array", completed: true +}, +{ + text:"agregar todo", completed: true +},] + function App() { + const [todos, setTodos] = React.useState(todo) + const [state, setState] = React.useState("") + const newtodo = todos.filter(e=>e.text.toLocaleLowerCase().includes(state.toLocaleLowerCase())) + //tolocalelowercase no distingue entre acentos + const completedTodo = (i)=>{ + const newT = [...todos,] + const find = newT.findIndex(e=> e.text === i) + newT[find].completed = true + return setTodos(newT) + } + const completeTodo = (text) => { + const newTodos = [...todos]; + const todoIndex = newTodos.findIndex( + (todo) => todo.text == text + ); + newTodos[todoIndex].completed = true; + setTodos(newTodos); + }; + + const deleteTodo = (i)=>{ + const newT = [...todos,] + const find = newT.findIndex(e=> e.text === i) + newT.splice(find, 1) + setTodos(newT) + } return ( -
-
- logo -

- Edita el archivo src/App.js y guarda para recargar. -

- - Learn React - -
-
+ + <> + !!e.completed ).length}/> + + + + {newtodo.map(e=> (completeTodo(e.text)} + onDelete={()=>deleteTodo(e.text)}/> ))} + + + ); } diff --git a/src/CreateButton.js b/src/CreateButton.js new file mode 100644 index 000000000..17c38099a --- /dev/null +++ b/src/CreateButton.js @@ -0,0 +1,11 @@ +import "./buttonStyle.css" + +const CreateButton = ()=>{ + + return( + + ) + + } + + export {CreateButton} \ No newline at end of file diff --git a/src/NameCounter.js b/src/NameCounter.js new file mode 100644 index 000000000..8e3b8faf2 --- /dev/null +++ b/src/NameCounter.js @@ -0,0 +1,13 @@ +import "./nameCounter.css" +const NameCounter = ({total, completed})=>{ + + + return( +

+ has completado {completed} de {total} ToDo's +

+ ) + + } + + export {NameCounter} \ No newline at end of file diff --git a/src/TodoFilter.js b/src/TodoFilter.js new file mode 100644 index 000000000..fb396e1d3 --- /dev/null +++ b/src/TodoFilter.js @@ -0,0 +1,12 @@ +import React from "react" +import "./todoFilter.css" +const TodoFilter = ({setState})=>{ + + return( + <> setState(e.target.value)}/> + ) + +} + +export {TodoFilter} + \ No newline at end of file diff --git a/src/TodoItem.js b/src/TodoItem.js new file mode 100644 index 000000000..3d61fcab1 --- /dev/null +++ b/src/TodoItem.js @@ -0,0 +1,16 @@ +import CompleteIcon from "./completeIcon.js"; +import DeleteIcon from "./deleteIcon.js"; +import "./todoItem.css"; + +const TodoItem = ({element, completed,onComplete, onDelete})=>{ + return( +
  • + +

    {element.text}

    + +
  • + ) + +} + +export {TodoItem} \ No newline at end of file diff --git a/src/TodoList.js b/src/TodoList.js new file mode 100644 index 000000000..fa8565345 --- /dev/null +++ b/src/TodoList.js @@ -0,0 +1,12 @@ +import "./todoList.css" + +const TodoList = (props)=>{ + + return( +
      + {props.children} +
    + ) +} + +export {TodoList} diff --git a/src/buttonStyle.css b/src/buttonStyle.css new file mode 100644 index 000000000..6200433c5 --- /dev/null +++ b/src/buttonStyle.css @@ -0,0 +1,13 @@ +.CreateTodoButton{background-color:#61dafa; + box-shadow:0 5px 25px rgba(97,218,250,.5); + border:none; + border-radius:50%;cursor:pointer; + font-size:50px;position:fixed; + bottom:24px; + right:24px;font-weight:700; + color:#fafafa;display:flex; + justify-content:center; + align-items:center;height:64px;width:64px; + transform:rotate(0);transition:.3s ease} + + .CreateTodoButton:hover{transform:rotate(224deg)} \ No newline at end of file diff --git a/src/check.svg b/src/check.svg new file mode 100644 index 000000000..bbaf4184a --- /dev/null +++ b/src/check.svg @@ -0,0 +1,7 @@ + + + diff --git a/src/completeIcon.js b/src/completeIcon.js new file mode 100644 index 000000000..b2a5d9cc9 --- /dev/null +++ b/src/completeIcon.js @@ -0,0 +1,9 @@ +import {React} from 'react' +import TodoIcon from './todoIcon'; +const completeIcon = ({complete, oncomplete}) => { + return ( + + ); +} + +export default completeIcon \ No newline at end of file diff --git a/src/delete.svg b/src/delete.svg new file mode 100644 index 000000000..afad0d559 --- /dev/null +++ b/src/delete.svg @@ -0,0 +1,9 @@ + + + diff --git a/src/deleteIcon.js b/src/deleteIcon.js new file mode 100644 index 000000000..c388e84cd --- /dev/null +++ b/src/deleteIcon.js @@ -0,0 +1,9 @@ +import {React} from 'react' +import TodoIcon from './todoIcon'; +const deleteIcon = ({onDelete}) => { + return ( + + ); +} + +export default deleteIcon \ No newline at end of file diff --git a/src/nameCounter.css b/src/nameCounter.css new file mode 100644 index 000000000..459a579f3 --- /dev/null +++ b/src/nameCounter.css @@ -0,0 +1,2 @@ + +.TodoCounter{font-size:24px;text-align:center;margin:0;padding:48px;font-weight:400}.TodoCounter span{font-weight:700} \ No newline at end of file diff --git a/src/todoFilter.css b/src/todoFilter.css new file mode 100644 index 000000000..c1d4233f8 --- /dev/null +++ b/src/todoFilter.css @@ -0,0 +1 @@ +.TodoSearch{background:#f9fbfc;border-radius:2px;border:2px solid #202329;margin:0 24px;height:64px;width:calc(100% - 62px);font-size:24px;text-align:center;font-family:montserrat;font-weight:400;color:#1e1e1f;box-shadow:0 5px 50px rgba(32,35,41,.25)}.TodoSearch::placeholder{color:#a5a5a5;font-family:montserrat;font-weight:400}.TodoSearch:focus{outline-color:#61dafa} \ No newline at end of file diff --git a/src/todoIcon.css b/src/todoIcon.css new file mode 100644 index 000000000..0eb782cee --- /dev/null +++ b/src/todoIcon.css @@ -0,0 +1,19 @@ +.Icon-container{cursor:pointer; + display:flex; + justify-content:center; + align-items:center; + height:48px;width:48px; + font-size:24px; + font-weight:700} +.Icon-container-check{position:absolute;left:12px} +.Icon-container-check--active{color:#4caf50} +.Icon-container-delete{position:absolute;top:-24px;right:0} +.Icon-container-delete:hover{color:red} + +.Icon-svg{ + width: 24px; + height: 24px; +} + +.Icon-container-delete:hover .Icon-svg{fill:red} +.Icon-container-check:hover .Icon-svg{fill:green} diff --git a/src/todoIcon.js b/src/todoIcon.js new file mode 100644 index 000000000..ffdc0ca2f --- /dev/null +++ b/src/todoIcon.js @@ -0,0 +1,17 @@ +import {React} from 'react'; +import { ReactComponent as CheckIcon} from './check.svg'; +import { ReactComponent as DeleteIcon } from './delete.svg'; +import "./todoIcon.css" +const todoIcon = ({type, color, click}) => { + const iconType = { + "check": color=>, + "delete": color => + } + return ( + click()}> + {iconType[type](color)} + + ); +} + +export default todoIcon; \ No newline at end of file diff --git a/src/todoItem.css b/src/todoItem.css new file mode 100644 index 000000000..c7f6ef500 --- /dev/null +++ b/src/todoItem.css @@ -0,0 +1,12 @@ + +.TodoItem{background-color:#fafafa; + position:relative;display:flex; + justify-content:center; + align-items:center; + margin-top:24px; + box-shadow:0 5px 50px rgba(32,35,41,.15)} +.TodoItem-p{margin:24px 0 24px 24px; + width:calc(100% - 120px); + font-size:18px;line-height:24px; + font-weight:400} +.TodoItem-p--complete{text-decoration:line-through} diff --git a/src/todoList.css b/src/todoList.css new file mode 100644 index 000000000..02d4b4152 --- /dev/null +++ b/src/todoList.css @@ -0,0 +1 @@ +.TodoList{margin:0;padding:0 0 56px;list-style:none} \ No newline at end of file From a462f331dff2bbfec4bdec733a2e883423c1ce27 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 22 Jun 2023 16:30:32 -0600 Subject: [PATCH 2/6] [ADD] localStorage --- src/App.js | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/App.js b/src/App.js index ca3bf97e7..edd408c65 100644 --- a/src/App.js +++ b/src/App.js @@ -4,45 +4,40 @@ import { TodoList } from "./TodoList"; import {TodoItem} from "./TodoItem"; import { CreateButton } from "./CreateButton"; import React from "react"; -const todo =[{ - text:"visitar alemania", completed: false -}, -{ - text:"completar el curso fullstack", completed: false -}, -{ - text:"renderizar un array", completed: true -}, -{ - text:"agregar todo", completed: true -},] + +const localStorageTodos = localStorage.getItem("TODOS_V1") +let parsedTodos; +if(!localStorageTodos){ + localStorage.setItem("TODOS_V1",JSON.stringify([])) + parsedTodos = [] +}else{ + parsedTodos = JSON.parse(localStorageTodos) +} function App() { - const [todos, setTodos] = React.useState(todo) + const [todos, setTodos] = React.useState(parsedTodos) const [state, setState] = React.useState("") const newtodo = todos.filter(e=>e.text.toLocaleLowerCase().includes(state.toLocaleLowerCase())) //tolocalelowercase no distingue entre acentos - const completedTodo = (i)=>{ - const newT = [...todos,] - const find = newT.findIndex(e=> e.text === i) - newT[find].completed = true - return setTodos(newT) + const savedTodos = (newTodos)=>{ + localStorage.setItem("TODOS_V1", JSON.stringify(newTodos)) + setTodos(newTodos) } const completeTodo = (text) => { const newTodos = [...todos]; const todoIndex = newTodos.findIndex( - (todo) => todo.text == text + (todo) => todo.text === text ); newTodos[todoIndex].completed = true; - setTodos(newTodos); + savedTodos(newTodos); }; const deleteTodo = (i)=>{ const newT = [...todos,] const find = newT.findIndex(e=> e.text === i) newT.splice(find, 1) - setTodos(newT) + savedTodos(newT) } return ( From 9775b90662facedaa115625e4cfadcb16affbc84 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 24 Jun 2023 17:38:46 -0600 Subject: [PATCH 3/6] [ADD] tidy my files in it's folders --- src/App.js | 57 ------------------ src/App/App.js | 33 ++++++++++ src/App/logica.js | 19 ++++++ .../CreateButton/index.js} | 2 +- .../NameCounter/index.js} | 2 +- .../TodoFilter/index.js} | 2 +- .../TodoItem/index.js} | 6 +- .../TodoList/index.js} | 2 +- src/{ => Components/todoIcon}/completeIcon.js | 2 +- src/{ => Components/todoIcon}/deleteIcon.js | 2 +- .../todoIcon/index.js} | 6 +- src/hooks/useLocalStorage.js | 22 +++++++ src/{ => icons}/check.svg | 0 src/{ => icons}/delete.svg | 0 src/index.js | 4 +- src/platzi.webp | Bin 1008 -> 0 bytes src/{ => styles}/buttonStyle.css | 0 src/{ => styles}/index.css | 0 src/{ => styles}/nameCounter.css | 0 src/{ => styles}/todoFilter.css | 0 src/{ => styles}/todoIcon.css | 0 src/{ => styles}/todoItem.css | 0 src/{ => styles}/todoList.css | 0 23 files changed, 88 insertions(+), 71 deletions(-) delete mode 100644 src/App.js create mode 100644 src/App/App.js create mode 100644 src/App/logica.js rename src/{CreateButton.js => Components/CreateButton/index.js} (78%) rename src/{NameCounter.js => Components/NameCounter/index.js} (83%) rename src/{TodoFilter.js => Components/TodoFilter/index.js} (85%) rename src/{TodoItem.js => Components/TodoItem/index.js} (71%) rename src/{TodoList.js => Components/TodoList/index.js} (80%) rename src/{ => Components/todoIcon}/completeIcon.js (85%) rename src/{ => Components/todoIcon}/deleteIcon.js (83%) rename src/{todoIcon.js => Components/todoIcon/index.js} (71%) create mode 100644 src/hooks/useLocalStorage.js rename src/{ => icons}/check.svg (100%) rename src/{ => icons}/delete.svg (100%) delete mode 100644 src/platzi.webp rename src/{ => styles}/buttonStyle.css (100%) rename src/{ => styles}/index.css (100%) rename src/{ => styles}/nameCounter.css (100%) rename src/{ => styles}/todoFilter.css (100%) rename src/{ => styles}/todoIcon.css (100%) rename src/{ => styles}/todoItem.css (100%) rename src/{ => styles}/todoList.css (100%) diff --git a/src/App.js b/src/App.js deleted file mode 100644 index edd408c65..000000000 --- a/src/App.js +++ /dev/null @@ -1,57 +0,0 @@ -import {NameCounter} from "./NameCounter"; -import { TodoFilter } from "./TodoFilter"; -import { TodoList } from "./TodoList"; -import {TodoItem} from "./TodoItem"; -import { CreateButton } from "./CreateButton"; -import React from "react"; - -const localStorageTodos = localStorage.getItem("TODOS_V1") -let parsedTodos; -if(!localStorageTodos){ - localStorage.setItem("TODOS_V1",JSON.stringify([])) - parsedTodos = [] -}else{ - parsedTodos = JSON.parse(localStorageTodos) -} - - -function App() { - const [todos, setTodos] = React.useState(parsedTodos) - const [state, setState] = React.useState("") - const newtodo = todos.filter(e=>e.text.toLocaleLowerCase().includes(state.toLocaleLowerCase())) - //tolocalelowercase no distingue entre acentos - const savedTodos = (newTodos)=>{ - localStorage.setItem("TODOS_V1", JSON.stringify(newTodos)) - setTodos(newTodos) - } - const completeTodo = (text) => { - const newTodos = [...todos]; - const todoIndex = newTodos.findIndex( - (todo) => todo.text === text - ); - newTodos[todoIndex].completed = true; - savedTodos(newTodos); - }; - - const deleteTodo = (i)=>{ - const newT = [...todos,] - const find = newT.findIndex(e=> e.text === i) - newT.splice(find, 1) - savedTodos(newT) - } - return ( - - <> - !!e.completed ).length}/> - - - - {newtodo.map(e=> (completeTodo(e.text)} - onDelete={()=>deleteTodo(e.text)}/> ))} - - - - ); -} - -export default App; diff --git a/src/App/App.js b/src/App/App.js new file mode 100644 index 000000000..5f2c6a989 --- /dev/null +++ b/src/App/App.js @@ -0,0 +1,33 @@ +import React from "react"; +import {useLocalStorage} from "../hooks/useLocalStorage" +import { Logica } from "./logica"; + +function App() { + const [todos, saveItem] = useLocalStorage("TODOS_V1",[]) + const [state, setState] = React.useState("") + const newtodo = todos.filter(e=>e.text.toLocaleLowerCase().includes(state.toLocaleLowerCase())) + //tolocalelowercase no distingue entre acentos + + const completeTodo = (text) => { + const newTodos = [...todos]; + const todoIndex = newTodos.findIndex( + (todo) => todo.text === text + ); + newTodos[todoIndex].completed = true; + saveItem(newTodos); + }; + + const deleteTodo = (i)=>{ + const newT = [...todos,] + const find = newT.findIndex(e=> e.text === i) + newT.splice(find, 1) + saveItem(newT) + } + //se separan entre statefull y stateless + return ( + + + ); +} + +export default App; diff --git a/src/App/logica.js b/src/App/logica.js new file mode 100644 index 000000000..9a8f73e60 --- /dev/null +++ b/src/App/logica.js @@ -0,0 +1,19 @@ +import {NameCounter} from "../Components/NameCounter/index"; +import { TodoFilter } from "../Components/TodoFilter/index"; +import { TodoList } from "../Components/TodoList/index"; +import {TodoItem} from "../Components/TodoItem/index"; +import { CreateButton } from "../Components/CreateButton/index"; + +const Logica = ({todos,completeTodo,deleteTodo,newtodo,setState})=>{ + return( <> + !!e.completed ).length}/> + + + + {newtodo.map(e=> (completeTodo(e.text)} + onDelete={()=>deleteTodo(e.text)}/> ))} + + ) +} + +export {Logica} \ No newline at end of file diff --git a/src/CreateButton.js b/src/Components/CreateButton/index.js similarity index 78% rename from src/CreateButton.js rename to src/Components/CreateButton/index.js index 17c38099a..57fbdf702 100644 --- a/src/CreateButton.js +++ b/src/Components/CreateButton/index.js @@ -1,4 +1,4 @@ -import "./buttonStyle.css" +import "../../styles/buttonStyle.css" const CreateButton = ()=>{ diff --git a/src/NameCounter.js b/src/Components/NameCounter/index.js similarity index 83% rename from src/NameCounter.js rename to src/Components/NameCounter/index.js index 8e3b8faf2..4f930e179 100644 --- a/src/NameCounter.js +++ b/src/Components/NameCounter/index.js @@ -1,4 +1,4 @@ -import "./nameCounter.css" +import "../../styles/nameCounter.css" const NameCounter = ({total, completed})=>{ diff --git a/src/TodoFilter.js b/src/Components/TodoFilter/index.js similarity index 85% rename from src/TodoFilter.js rename to src/Components/TodoFilter/index.js index fb396e1d3..89b46c50a 100644 --- a/src/TodoFilter.js +++ b/src/Components/TodoFilter/index.js @@ -1,5 +1,5 @@ import React from "react" -import "./todoFilter.css" +import "../../styles/todoFilter.css" const TodoFilter = ({setState})=>{ return( diff --git a/src/TodoItem.js b/src/Components/TodoItem/index.js similarity index 71% rename from src/TodoItem.js rename to src/Components/TodoItem/index.js index 3d61fcab1..1c043b9fe 100644 --- a/src/TodoItem.js +++ b/src/Components/TodoItem/index.js @@ -1,6 +1,6 @@ -import CompleteIcon from "./completeIcon.js"; -import DeleteIcon from "./deleteIcon.js"; -import "./todoItem.css"; +import CompleteIcon from "../todoIcon/completeIcon.js"; +import DeleteIcon from "../todoIcon/deleteIcon.js"; +import "../../styles/todoItem.css"; const TodoItem = ({element, completed,onComplete, onDelete})=>{ return( diff --git a/src/TodoList.js b/src/Components/TodoList/index.js similarity index 80% rename from src/TodoList.js rename to src/Components/TodoList/index.js index fa8565345..cea8dd3de 100644 --- a/src/TodoList.js +++ b/src/Components/TodoList/index.js @@ -1,4 +1,4 @@ -import "./todoList.css" +import "../../styles/todoList.css" const TodoList = (props)=>{ diff --git a/src/completeIcon.js b/src/Components/todoIcon/completeIcon.js similarity index 85% rename from src/completeIcon.js rename to src/Components/todoIcon/completeIcon.js index b2a5d9cc9..b0f18baa1 100644 --- a/src/completeIcon.js +++ b/src/Components/todoIcon/completeIcon.js @@ -1,5 +1,5 @@ import {React} from 'react' -import TodoIcon from './todoIcon'; +import TodoIcon from '.'; const completeIcon = ({complete, oncomplete}) => { return ( diff --git a/src/deleteIcon.js b/src/Components/todoIcon/deleteIcon.js similarity index 83% rename from src/deleteIcon.js rename to src/Components/todoIcon/deleteIcon.js index c388e84cd..ec7935b86 100644 --- a/src/deleteIcon.js +++ b/src/Components/todoIcon/deleteIcon.js @@ -1,5 +1,5 @@ import {React} from 'react' -import TodoIcon from './todoIcon'; +import TodoIcon from '.'; const deleteIcon = ({onDelete}) => { return ( diff --git a/src/todoIcon.js b/src/Components/todoIcon/index.js similarity index 71% rename from src/todoIcon.js rename to src/Components/todoIcon/index.js index ffdc0ca2f..e0aa50942 100644 --- a/src/todoIcon.js +++ b/src/Components/todoIcon/index.js @@ -1,7 +1,7 @@ import {React} from 'react'; -import { ReactComponent as CheckIcon} from './check.svg'; -import { ReactComponent as DeleteIcon } from './delete.svg'; -import "./todoIcon.css" +import { ReactComponent as CheckIcon} from '../../icons/check.svg'; +import { ReactComponent as DeleteIcon } from '../../icons/delete.svg'; +import "../../styles/todoIcon.css" const todoIcon = ({type, color, click}) => { const iconType = { "check": color=>, diff --git a/src/hooks/useLocalStorage.js b/src/hooks/useLocalStorage.js new file mode 100644 index 000000000..e5cacaa72 --- /dev/null +++ b/src/hooks/useLocalStorage.js @@ -0,0 +1,22 @@ +import React from 'react' +const useLocalStorage = (itemName, initialValue)=>{ + let parsedItem; + const localStorageItem = localStorage.getItem(itemName) + + if(!localStorageItem){ + localStorage.setItem(itemName,JSON.stringify(initialValue)) + parsedItem = initialValue + }else{ + parsedItem = JSON.parse(localStorageItem) + } + + const [item, setItem] = React.useState(parsedItem) + const saveItem = (newTodos)=>{ + localStorage.setItem(itemName, JSON.stringify(newTodos)) + setItem(newTodos) + } + + return [item, saveItem] + } + + export {useLocalStorage} \ No newline at end of file diff --git a/src/check.svg b/src/icons/check.svg similarity index 100% rename from src/check.svg rename to src/icons/check.svg diff --git a/src/delete.svg b/src/icons/delete.svg similarity index 100% rename from src/delete.svg rename to src/icons/delete.svg diff --git a/src/index.js b/src/index.js index 793e2b837..449f6eb19 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; -import './index.css'; -import App from './App'; +import './styles/index.css'; +import App from './App/App'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render(); diff --git a/src/platzi.webp b/src/platzi.webp deleted file mode 100644 index a84536756882549cc895dade9ebe7295c17a9a2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1008 zcmVaj*r`-jiplutb{28Zb zBa^nNf4$i~0zruWpTz}|Ix>k+^{+I?OGQ4y6sc8 zZPU<1srJ|mlTFKG8$``RJ7#k&ji`HLsUfuj@;2G%KSTj~9O%2xT@bK`Zl-?K3Wc{b zZJbtUyyFbh2O;v%6Mj}iA@i8Xu4;tP8>WjkK`1?J*jhOo31d1Gau9MKc)B^&YhH-~ zUm=IFDToOV6E6NAj0hEe6hl6uFeMDeWQD`!@hqi0?w38e5~gK$eV0%Ex@<+)6a8Jc zm-5x$XWE<25cbcq#2;H-=?xHhh2Z!u%lxf-k5$&P2EnP6!k|WLrUZgSgHCi1bs`I% zBL*JDtk4NVy_ouJFmP#8+ZG^@DdfsF2wEa(N)YtK5ilZPRIFKgLcpoM;u-+jf?v|o z@WQKGI-8^6CO5q1h0i<)f!bxyL{tj+)bYTfZc!8(6od*g(4ZpF3^}r(B*@^ESYT56 z8kqz|=?Bgvkm*b3kpni3U*^LU(5dvPxAnhPyBYN+0`S2rD)ykJh>oSoPDEg)PD#OD)Re1|jdj~)+?0dT z)U&S}ueo_iz4i6>rly<-Y|qV02<%8rIWX9TnyXM4GdE#18lGDgTOuZCyD&i;hzQGnqfqk`GEt>mk zqtL1j)qTkl*!@s;3_wtJT z%gb^vug$%@K>zY8-OEdLFR$0Tyy(`yymI&Q^4+Uz;9gw__v&i6SC_=Sx-Rb3#c{8$ zkb8BR+^cKlTwSm>dskP@y}ESn)%EkPE~0yNCB3W5>1SP2ri(hJy0G5W)%C6}v3GTy eovVxOU0reK>asgm*WR?}>fZ(M>~|G@3H}2yCHam3 diff --git a/src/buttonStyle.css b/src/styles/buttonStyle.css similarity index 100% rename from src/buttonStyle.css rename to src/styles/buttonStyle.css diff --git a/src/index.css b/src/styles/index.css similarity index 100% rename from src/index.css rename to src/styles/index.css diff --git a/src/nameCounter.css b/src/styles/nameCounter.css similarity index 100% rename from src/nameCounter.css rename to src/styles/nameCounter.css diff --git a/src/todoFilter.css b/src/styles/todoFilter.css similarity index 100% rename from src/todoFilter.css rename to src/styles/todoFilter.css diff --git a/src/todoIcon.css b/src/styles/todoIcon.css similarity index 100% rename from src/todoIcon.css rename to src/styles/todoIcon.css diff --git a/src/todoItem.css b/src/styles/todoItem.css similarity index 100% rename from src/todoItem.css rename to src/styles/todoItem.css diff --git a/src/todoList.css b/src/styles/todoList.css similarity index 100% rename from src/todoList.css rename to src/styles/todoList.css From 3959fcf44f44cb292621df8dedb586c0d9d4c682 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 27 Jun 2023 13:43:23 -0600 Subject: [PATCH 4/6] [ADD] loading and error animations --- src/App/App.js | 14 ++++++--- src/App/EmptyTodos.js | 9 ++++++ src/App/TodosError.js | 9 ++++++ src/App/TodosLoading.js | 14 +++++++++ src/App/logica.js | 28 ++++++++++++++--- src/hooks/useLocalStorage.js | 52 +++++++++++++++++++++---------- src/styles/TodosLoading.css | 59 ++++++++++++++++++++++++++++++++++++ 7 files changed, 160 insertions(+), 25 deletions(-) create mode 100644 src/App/EmptyTodos.js create mode 100644 src/App/TodosError.js create mode 100644 src/App/TodosLoading.js create mode 100644 src/styles/TodosLoading.css diff --git a/src/App/App.js b/src/App/App.js index 5f2c6a989..9a2d3edc5 100644 --- a/src/App/App.js +++ b/src/App/App.js @@ -3,13 +3,17 @@ import {useLocalStorage} from "../hooks/useLocalStorage" import { Logica } from "./logica"; function App() { - const [todos, saveItem] = useLocalStorage("TODOS_V1",[]) + const {item, + saveItem, + loading, + error, + } = useLocalStorage("TODOS_V1",[]) const [state, setState] = React.useState("") - const newtodo = todos.filter(e=>e.text.toLocaleLowerCase().includes(state.toLocaleLowerCase())) + const newtodo = item.filter(e=>e.text.toLocaleLowerCase().includes(state.toLocaleLowerCase())) //tolocalelowercase no distingue entre acentos const completeTodo = (text) => { - const newTodos = [...todos]; + const newTodos = [...item]; const todoIndex = newTodos.findIndex( (todo) => todo.text === text ); @@ -18,14 +22,14 @@ function App() { }; const deleteTodo = (i)=>{ - const newT = [...todos,] + const newT = [...item,] const find = newT.findIndex(e=> e.text === i) newT.splice(find, 1) saveItem(newT) } //se separan entre statefull y stateless return ( - + ); } diff --git a/src/App/EmptyTodos.js b/src/App/EmptyTodos.js new file mode 100644 index 000000000..6b0604948 --- /dev/null +++ b/src/App/EmptyTodos.js @@ -0,0 +1,9 @@ +import React from 'react'; + +function EmptyTodos() { + return ( +

    ¡Crea tu primer TODO!

    + ); +} + +export { EmptyTodos }; \ No newline at end of file diff --git a/src/App/TodosError.js b/src/App/TodosError.js new file mode 100644 index 000000000..70fd21a6b --- /dev/null +++ b/src/App/TodosError.js @@ -0,0 +1,9 @@ +import React from 'react'; + +function TodosError() { + return ( +

    Error...

    + ); +} + +export { TodosError }; \ No newline at end of file diff --git a/src/App/TodosLoading.js b/src/App/TodosLoading.js new file mode 100644 index 000000000..2978dea06 --- /dev/null +++ b/src/App/TodosLoading.js @@ -0,0 +1,14 @@ +import React from 'react'; +import '../styles/TodosLoading.css'; + +function TodosLoading() { + return ( +
    + +

    + +
    + ); +} + +export { TodosLoading }; \ No newline at end of file diff --git a/src/App/logica.js b/src/App/logica.js index 9a8f73e60..4a1a968fa 100644 --- a/src/App/logica.js +++ b/src/App/logica.js @@ -3,16 +3,36 @@ import { TodoFilter } from "../Components/TodoFilter/index"; import { TodoList } from "../Components/TodoList/index"; import {TodoItem} from "../Components/TodoItem/index"; import { CreateButton } from "../Components/CreateButton/index"; +import {TodosLoading} from "./TodosLoading" +import {TodosError} from "./TodosError" +import {EmptyTodos} from "./EmptyTodos" -const Logica = ({todos,completeTodo,deleteTodo,newtodo,setState})=>{ +const Logica = ({todos,completeTodo,deleteTodo,newtodo,setState, loading, error})=>{ return( <> !!e.completed ).length}/> - - {newtodo.map(e=> (completeTodo(e.text)} - onDelete={()=>deleteTodo(e.text)}/> ))} + {loading && ( + <> + + + + + )} + {error && } + {(!loading && newtodo.length === 0) && } + + {newtodo.map(todo => ( + completeTodo(todo.text)} + onDelete={() => deleteTodo(todo.text)} + /> + ))} + ) } diff --git a/src/hooks/useLocalStorage.js b/src/hooks/useLocalStorage.js index e5cacaa72..0219b3758 100644 --- a/src/hooks/useLocalStorage.js +++ b/src/hooks/useLocalStorage.js @@ -1,22 +1,42 @@ import React from 'react' const useLocalStorage = (itemName, initialValue)=>{ - let parsedItem; - const localStorageItem = localStorage.getItem(itemName) + const [item, setItem] = React.useState(initialValue) + const [loading, setLoading] = React.useState(true) + const [error, setError] = React.useState(false) + React.useEffect(() => { + setTimeout(() => { + try { + const localStorageItem = localStorage.getItem(itemName); - if(!localStorageItem){ - localStorage.setItem(itemName,JSON.stringify(initialValue)) - parsedItem = initialValue - }else{ - parsedItem = JSON.parse(localStorageItem) + let parsedItem; + + if (!localStorageItem) { + localStorage.setItem(itemName, JSON.stringify(initialValue)); + parsedItem = initialValue; + } else { + parsedItem = JSON.parse(localStorageItem); + setItem(parsedItem); + } + + setLoading(false); + } catch(error) { + setLoading(false); + setError(true); } - - const [item, setItem] = React.useState(parsedItem) - const saveItem = (newTodos)=>{ - localStorage.setItem(itemName, JSON.stringify(newTodos)) - setItem(newTodos) - } - - return [item, saveItem] - } + }, 2000); + }); + + const saveItem = (newItem) => { + localStorage.setItem(itemName, JSON.stringify(newItem)); + setItem(newItem); + }; + + return { + item, + saveItem, + loading, + error, + }; +} export {useLocalStorage} \ No newline at end of file diff --git a/src/styles/TodosLoading.css b/src/styles/TodosLoading.css new file mode 100644 index 000000000..ee8b60ce4 --- /dev/null +++ b/src/styles/TodosLoading.css @@ -0,0 +1,59 @@ +.LoadingTodo-container { + position: relative; + display: flex; + justify-content: center; + align-items: center; + margin-top: 24px; + box-shadow: 0px 5px 50px rgba(32, 35, 41, 0.15); + border-radius: 10px; + padding: 12px 0; + } + + .LoadingTodo-text { + margin: 24px 0 24px 24px; + width: calc(100% - 120px); + font-size: 18px; + line-height: 24px; + font-weight: 400; + } + + .LoadingTodo-completeIcon, + .LoadingTodo-deleteIcon { + cursor: pointer; + display: flex; + justify-content: center; + align-items: center; + border-radius: 50px; + height: 48px; + width: 48px; + } + .LoadingTodo-completeIcon { + position: absolute; + left: 12px; + } + .LoadingTodo-deleteIcon { + position: absolute; + top: -24px; + right: 0; + } + + + .LoadingTodo-container, + .LoadingTodo-completeIcon, + .LoadingTodo-deleteIcon { + background: linear-gradient(90deg, rgba(250,250,250,1), rgb(200, 199, 199)); + background-size: 400% 400%; + animation: loadingAnimation 3s ease-in-out infinite; + } + + @keyframes loadingAnimation { + 0% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0% 50%; + } + } \ No newline at end of file From a99250d44684c77298607c61d9da7c6db6c91e77 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 11 Jul 2023 16:04:35 -0600 Subject: [PATCH 5/6] finishing project --- public/index.html | 1 + src/App/App.js | 30 ++----------- src/App/Modal.js | 10 +++++ src/App/logica.js | 18 +++++--- src/Components/CreateButton/index.js | 4 +- src/Components/NameCounter/index.js | 7 ++- src/Components/TodoFilter/index.js | 8 ++-- src/Contexts/todoContext.js | 67 ++++++++++++++++++++++++++++ 8 files changed, 107 insertions(+), 38 deletions(-) create mode 100644 src/App/Modal.js create mode 100644 src/Contexts/todoContext.js diff --git a/public/index.html b/public/index.html index e5b37b15c..4094d1912 100644 --- a/public/index.html +++ b/public/index.html @@ -29,6 +29,7 @@
    +