diff --git a/README.md b/README.md index 7c5284b..32a0e29 100644 --- a/README.md +++ b/README.md @@ -100,3 +100,5 @@ Este proyecto está bajo la Licencia MIT. Consulta el archivo [LICENSE](LICENSE) [![Web](https://img.shields.io/badge/GitHub-Jack-FFA500?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://github.com/JackDev21) [![Web](https://img.shields.io/badge/GitHub-Adrian-FFA500?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://github.com/AdrianGonzalo) + +[![Web](https://img.shields.io/badge/GitHub-Jose-FFA500?style=for-the-badge&logo=github&logoColor=white&labelColor=101010)](https://github.com/j0sep0z0) diff --git a/api/data/data.js b/api/data/data.js index e69de29..aad3db8 100644 --- a/api/data/data.js +++ b/api/data/data.js @@ -0,0 +1,113 @@ +import fs from "fs" + + +const data = {} + +data.findTasks = (condition, callback) => { + + fs.readFile('./data/tasks.json', 'utf-8', (error, tasksJson) => { + if (error) { + + console.log(error) + callback(error.message) + return + } + + if (!tasksJson) { + tasksJson = '[]' + } + + const tasks = JSON.parse(tasksJson) + + const filtered = tasks.filter(condition) + + callback(null, filtered) + }) +} + + +data.insertTask = (task, callback) => { + fs.readFile('./data/tasks.json', 'utf-8', (error, tasksJson) => { + if (error) { + console.log(error) + + return + } + + if (!tasksJson) { + tasksJson = '[]' + } + const tasks = JSON.parse(tasksJson) + + task.id = `${Math.random().toString().slice(2)}-${Date.now()}` + + tasks.push(task) + + const jsonTasks = JSON.stringify(tasks) + + fs.writeFile('./data/tasks.json', jsonTasks, (error) => { + if (error) { + console.log(error) + + return + } + + callback(null) + }) + }) +} + +data.findOneTask = (condition, callback) => { + fs.readFile("./data/tasks.json", "utf-8", (error, tasksJson) => { + if (error) { + callback(new Error(error)) + + return + } + + if (!tasksJson) { + tasksJson = "[]" + } + + const tasks = JSON.parse(tasksJson) + const taskFind = tasks.find(condition) + + callback(null, taskFind) + }) +} + + +data.deleteTask = (condition, callback) => { + + fs.readFile("./data/tasks.json", "utf8", (error, tasksJson) => { + if (error) { + callback(new Error(error.message)) + return + } + + if (!tasksJson) { + tasksJson = "[]" + } + const tasks = JSON.parse(tasksJson) + + const index = tasks.findIndex(condition) + + if (index > -1) { + const deletedTask = tasks.splice(index, 1)[0] + const newJson = JSON.stringify(tasks) + + fs.writeFile("./data/tasks.json", newJson, (error) => { + if (error) { + callback(new Error(error.message)) + return + } + + callback(null, deletedTask) + }) + } else { + callback(null) + } + }) +} + +export default data \ No newline at end of file diff --git a/api/data/tasks.json b/api/data/tasks.json new file mode 100644 index 0000000..0637a08 --- /dev/null +++ b/api/data/tasks.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/api/index.js b/api/index.js new file mode 100644 index 0000000..d756786 --- /dev/null +++ b/api/index.js @@ -0,0 +1,80 @@ +import express from 'express' +import cors from 'cors' + +import logic from '../api/logic/logic.js' + +const api = express() + +api.use(cors()) + + +const jsonBodyParser = express.json({ strict: true, type: 'application/json' }) + +api.get('/', (req, res) => { + res.send('Hello World!') +}) + + +api.get("/tasks", (req, res) => { + + try { + logic.getAllTasks((error, tasks) => { + if (error) { + res.status(500).json({ error: error.message }) + return + } + res.json(tasks) + }) + + } catch (error) { + res.status(500).json({ error: error.message }) + } +}) + + +api.post("/tasks", jsonBodyParser, (req, res) => { + + const { text } = req.body + + try { + logic.createTask(text, (error) => { + if (error) { + res.status(500).json({ error: error }) + + return + } + + res.status(201).send({ message: 'task inserted, seguimos Laiiifff!!!' }) + }) + + } catch (error) { + console.log(error) + } +}) + +api.delete("/tasks/:taskId", (req, res) => { + + const { taskId } = req.params + + try { + logic.deleteTask(taskId, (error) => { + if (error) { + res.status(500).json({ error: error }) + return + } + + res.status(204).send() + }) + + } catch (error) { + + res.status(500).json({ error: error }) + } +}) + +api.listen(3001, () => console.log('Tamosss Laifff!!! http://localhost:3001')) + + + + + diff --git a/api/logic/index.test.js b/api/logic/index.test.js new file mode 100644 index 0000000..81ea2af --- /dev/null +++ b/api/logic/index.test.js @@ -0,0 +1,47 @@ +import logic from "./logic.js" + +// try { +// logic.getAllTasks(() => true, (error, tasks) => { +// if (error) { +// console.log(error) + +// } + +// console.log(tasks) + +// }) +// } catch (error) { + +// console.log(error) +// } + + + +// try { +// logic.createTask('Prueba', (error) => { +// if (error) { +// console.log(error) + +// return +// } +// console.log('task inserted, seguimos Laiiifff!!!') + +// }) + +// } catch (error) { +// console.log(error) +// } + +try { + logic.deleteTask("8322284392957846-1718037846180", (error) => { + if (error) { + console.log("error") + return + } + + console.log("task deleted") + }) + +} catch (error) { + console.log(error) +} \ No newline at end of file diff --git a/api/logic/logic.js b/api/logic/logic.js index e69de29..b39ecc7 100644 --- a/api/logic/logic.js +++ b/api/logic/logic.js @@ -0,0 +1,58 @@ + +import data from "../data/data.js" + +const logic = {} + +logic.getAllTasks = (callback) => { + + data.findTasks(() => true, (error, tasks) => { + + if (error) { + callback(error) + return + } + + callback(null, tasks) + }) +} + +logic.createTask = (text, callback) => { + const task = { + text: text, + } + + data.insertTask(task, error => { + + if (error) { + callback(error) + return + } + + callback(null) + }) +} + +logic.deleteTask = (taskId, callback) => { + + data.findOneTask(task => task.id === taskId, (error, task) => { + if (error) { + callback(error) + return + } + + if (!task) { + callback(console.error(error.message)) + } + + data.deleteTask(task => task.id === taskId, (error) => { + if (error) { + callback(error) + return + } + + callback(null) + }) + }) +} + +export default logic \ No newline at end of file diff --git a/api/package.json b/api/package.json index 8c721ca..d214543 100644 --- a/api/package.json +++ b/api/package.json @@ -1,18 +1,20 @@ { - "dependencies": { - "cors": "^2.8.5", - "express": "^4.19.2" - }, - "name": "api", - "version": "1.0.0", - "main": "index.js", - "devDependencies": {}, - "scripts": { - "start": "node .", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [], - "author": "", - "license": "ISC", - "description": "" -} \ No newline at end of file + "dependencies": { + "cors": "^2.8.5", + "express": "^4.19.2" + }, + "name": "api", + "version": "1.0.0", + "type": "module", + "main": "index.js", + "devDependencies": {}, + "scripts": { + "debug": "node --inspect-brk .", + "start": "node .", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "" +} diff --git a/app/src/component/TaskList.css b/app/src/component/TaskList.css index 77f7383..319e91c 100644 --- a/app/src/component/TaskList.css +++ b/app/src/component/TaskList.css @@ -2,13 +2,13 @@ display: flex; flex-direction: column; align-items: center; - width: auto; + width: 55rem; height: auto; gap: 1rem; border: 2px solid black; border-radius: 15px; padding: 1.5rem; - background-color: rgba(250, 235, 215, 0.541); + background-color: #ffffff6c } @@ -20,11 +20,10 @@ width: 100%; } - .TaskList>form { display: flex; align-items: center; - gap: 0.2rem; + gap: 0.5rem; } .TaskList>form>input { @@ -34,6 +33,7 @@ font-size: 1.5rem; text-align: center; background-color: rgba(255, 255, 255, 0.685); + box-shadow: -2px -2px 10px 0px rgb(0, 0, 0); } .TaskList>form>button { @@ -41,15 +41,15 @@ width: 10rem; height: 3rem; border-radius: 15px; + box-shadow: -2px -2px 10px 0px rgb(0, 0, 0); + transition: background-color 0.5s ease; } .TaskList>form>button:hover { - background-color: rgb(0, 0, 0); - color: white; + background-color: rgb(54, 44, 30); + color: rgb(255, 255, 255); } - - .TaskContainer { display: flex; justify-content: center; @@ -78,10 +78,20 @@ border: 2px solid black; color: rgb(0, 0, 0); border-radius: 5px; - background-color: rgb(255, 166, 0); + background-color: #ffffff; + transition: 0.5s ease; +} + +.TaskContainer>ul>li:hover { + background-color: rgb(253, 217, 172); +} + +.TaskContainer>ul>.Completed { + background-color: black; } -.Completed { +.TaskContainer>ul>li .Completed { + color: orange; text-decoration: line-through; } @@ -95,5 +105,4 @@ cursor: pointer; font-size: 1.5rem; position: relative; - } \ No newline at end of file diff --git a/app/src/component/TaskList.jsx b/app/src/component/TaskList.jsx index a710acd..98b4a84 100644 --- a/app/src/component/TaskList.jsx +++ b/app/src/component/TaskList.jsx @@ -1,4 +1,6 @@ -import { useState } from "react" +import { useState, useEffect } from "react" + +import logic from "../logic" import Title from "./Title" @@ -16,16 +18,64 @@ function TaskList() { const handleSubmitTask = (event) => { event.preventDefault() - if (task.trim()) { - setTasks([...tasks, { text: task, completed: false }]) - setTask("") + + try { + logic.createTask(task, (error) => { + if (error) { + alert(error.meessage) + + return + } + if (task.trim()) { + setTasks([...tasks, { text: task, completed: false }]) + } + loadTasks() + }) + } catch (error) { + alert(error.message) + return } + setTask("") } - const handleDeleteTask = (indexToDelete) => { - const taskUpdated = [...tasks] - taskUpdated.splice(indexToDelete, 1) - setTasks(taskUpdated) + useEffect(() => { + loadTasks() + }, []) + + const loadTasks = () => { + try { + logic.getAllTasks((error, tasks) => { + if (error) { + console.error(error) + alert(error.message) + return + } + + setTasks(tasks) + }) + } catch (error) { + if (error) { + console.error(error) + alert(error.message) + } + } + } + + const handleDeleteTask = (indexToDelete, taskId) => { + try { + logic.deleteTask(taskId, (error) => { + if (error) { + console.error(error) + alert(error.message) + } + const taskUpdated = [...tasks] + taskUpdated.splice(indexToDelete, 1) + setTasks(taskUpdated) + }) + } catch (error) { + console.error(error) + alert(error.message) + } } const handleTaskCompleted = (indexToComplete) => { @@ -40,7 +90,7 @@ function TaskList() {
- +
@@ -48,11 +98,11 @@ function TaskList() {
diff --git a/app/src/component/Title.css b/app/src/component/Title.css index d87421b..ba8b8ce 100644 --- a/app/src/component/Title.css +++ b/app/src/component/Title.css @@ -1,8 +1,9 @@ .Title { - width: 100%; display: flex; justify-content: center; font-size: 4rem; - color: dodgerblue; + color: #ad9e95; margin-bottom: 3rem; + flex-shrink: 1; + } \ No newline at end of file diff --git a/app/src/global.css b/app/src/global.css index 0e2f23f..775b258 100644 --- a/app/src/global.css +++ b/app/src/global.css @@ -10,5 +10,10 @@ } body { - background-color: rgb(255, 254, 180); + display: flex; + justify-content: center; + align-items: center; + background-color: #2b180e; + + flex-grow: 1; } \ No newline at end of file diff --git a/app/src/logic.js b/app/src/logic.js new file mode 100644 index 0000000..aba5a02 --- /dev/null +++ b/app/src/logic.js @@ -0,0 +1,89 @@ +const logic = {} + +logic.createTask = (text, callback) => { + + if (typeof text !== "string" || !text.length || text.length > 50) { + alert("No puedes crear una tarea vacia o con mas de 20 caracteres") + return + } + + + const xhr = new XMLHttpRequest + + xhr.onload = () => { + + if (xhr.status === 201) { + + callback(null) + console.log("task inserted, seguimos Laiiifff!!!") + return + } + + const { error, message } = JSON.parse(xhr.response) + + callback({ error, message }) + } + + + const body = { + text: text + } + const json = JSON.stringify(body) + + + xhr.open("POST", "http://localhost:3001/tasks") + xhr.setRequestHeader("Content-Type", "application/json") + xhr.send(json) +} + + +logic.getAllTasks = (callback) => { + + const xhr = new XMLHttpRequest + + xhr.onload = () => { + if (xhr.status === 200) { + const tasks = JSON.parse(xhr.response) + + callback(null, tasks) + console.log("Tasks loaded") + return + } + + const { error, message } = JSON.parse(xhr.response) + + callback({ error, message }) + } + + xhr.open("GET", "http://localhost:3001/tasks") + xhr.send() +} + +logic.deleteTask = (taskId, callback) => { + + const confirmDelete = confirm("¿Estas seguro de querer borrar esta tarea?") + + if (!confirmDelete) { + return + } else { + + const xhr = new XMLHttpRequest + + xhr.onload = () => { + if (xhr.status === (204)) { + callback(null) + return + } + + const { error, message } = JSON.parse(xhr.response) + + callback({ error, message }) + } + + xhr.open("DELETE", `http://localhost:3001/tasks/${taskId}`) + xhr.send() + } + +} + +export default logic \ No newline at end of file diff --git a/app/src/main.jsx b/app/src/main.jsx index bec5e7d..34075cc 100644 --- a/app/src/main.jsx +++ b/app/src/main.jsx @@ -1,5 +1,5 @@ -import ReactDOM from "react-dom/client"; -import App from "./App.jsx"; -import "./global.css"; +import ReactDOM from "react-dom/client" +import App from "./App.jsx" +import "./global.css" -ReactDOM.createRoot(document.getElementById("root")).render(); +ReactDOM.createRoot(document.getElementById("root")).render()