From 0d575ce4aa8780c6342a553b3c21bf1e60e6e912 Mon Sep 17 00:00:00 2001 From: mehdi22256 Date: Wed, 20 Mar 2024 14:20:24 +0300 Subject: [PATCH 1/2] done --- package-lock.json | 22 +++++++++++-- package.json | 4 +++ src/App.js | 4 ++- src/components/ToDoItem.js | 41 +++++++++++++++++++++++++ src/components/TodoList.js | 63 ++++++++++++++++++++++++++++++++++++++ src/index.css | 3 ++ tailwind.config.js | 9 ++++++ 7 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 src/components/ToDoItem.js create mode 100644 src/components/TodoList.js create mode 100644 tailwind.config.js diff --git a/package-lock.json b/package-lock.json index e6a160a..742324e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,11 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", + "uuid": "^9.0.1", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "tailwindcss": "^3.4.1" } }, "node_modules/@aashutoshrathi/word-wrap": { @@ -15998,6 +16002,14 @@ "websocket-driver": "^0.7.4" } }, + "node_modules/sockjs/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", @@ -17325,9 +17337,13 @@ } }, "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "bin": { "uuid": "dist/bin/uuid" } diff --git a/package.json b/package.json index 88a269e..2833951 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", + "uuid": "^9.0.1", "web-vitals": "^2.1.4" }, "scripts": { @@ -34,5 +35,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "tailwindcss": "^3.4.1" } } diff --git a/src/App.js b/src/App.js index 0ff7d8a..1d11d9d 100644 --- a/src/App.js +++ b/src/App.js @@ -1,11 +1,13 @@ import "./App.css"; +import TodoList from "./components/TodoList"; // TODO: Import the todoData and pass it as a prop to the TodoList component +import todoData from "./todoData"; function App() { return (
- {/* Call the TodoList Component Here */} +
); diff --git a/src/components/ToDoItem.js b/src/components/ToDoItem.js new file mode 100644 index 0000000..17e2fcf --- /dev/null +++ b/src/components/ToDoItem.js @@ -0,0 +1,41 @@ +import React from "react"; +import { useState } from "react"; +export const ToDoItem = ({ todo, handleDelete, handleEdit }) => { + const [isEditing, setIsEditing] = useState(false); + const [editedTitle, setEditedTitle] = useState(""); + + const handleChange = (event) => { + setEditedTitle(event.target.value); + }; + const handleIsEditing = () => { + setIsEditing(!isEditing); + }; + + return ( +
+ + + ) : ( + + )} + + {isEditing ? ( + + ) : ( +

{todo.title}

+ )} +
+ ); +}; diff --git a/src/components/TodoList.js b/src/components/TodoList.js new file mode 100644 index 0000000..2b4d224 --- /dev/null +++ b/src/components/TodoList.js @@ -0,0 +1,63 @@ +import React from "react"; +import { useState } from "react"; +import { v4 as uuidv4 } from "uuid"; +import { ToDoItem } from "./ToDoItem"; + +function TodoList({ todoData }) { + const [todoList, setTodoList] = useState(todoData); + const [newTodo, setNewTodo] = useState(""); + + const handleTextChange = (event) => { + setNewTodo(event.target.value); + }; + const handleTodoCreate = () => { + const newTodoObj = { + id: uuidv4(), + title: newTodo, + done: false, + }; + // Update the array to add the new item + setTodoList([...todoList, newTodoObj]); + }; + const handleDelete = (todoId) => { + setTodoList(todoList.filter((todo) => todo.id !== todoId)); + }; + + const handleEdit = (todoId, editedTitle) => { + setTodoList( + todoList.map((todo) => { + return todo.id === todoId ? { ...todo, title: editedTitle } : todo; + }) + ); + }; + + return ( +
+
+ + +
+
+ {todoList.map((todo) => ( + + ))} +
+
+ ); +} + +export default TodoList; diff --git a/src/index.css b/src/index.css index ec2585e..651ed53 100644 --- a/src/index.css +++ b/src/index.css @@ -1,3 +1,6 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..a930689 --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,9 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./src/**/*.{js,jsx,ts,tsx}"], + theme: { + extend: {}, + }, + plugins: [], +} + From aed200cd04c0cda03be88df44b3328b2706d0c57 Mon Sep 17 00:00:00 2001 From: mehdi22256 Date: Sun, 24 Mar 2024 13:28:22 +0300 Subject: [PATCH 2/2] done --- src/App.css | 2 +- src/components/ToDoItem.js | 15 ++++-- src/components/TodoList.js | 99 ++++++++++++++++++++++++++++++-------- 3 files changed, 90 insertions(+), 26 deletions(-) diff --git a/src/App.css b/src/App.css index 13088c2..e4b8a7a 100644 --- a/src/App.css +++ b/src/App.css @@ -25,7 +25,7 @@ } .App-header { - background-color: #282c34; + background-color: #151b25; min-height: 100vh; display: flex; flex-direction: column; diff --git a/src/components/ToDoItem.js b/src/components/ToDoItem.js index 17e2fcf..6516123 100644 --- a/src/components/ToDoItem.js +++ b/src/components/ToDoItem.js @@ -2,7 +2,7 @@ import React from "react"; import { useState } from "react"; export const ToDoItem = ({ todo, handleDelete, handleEdit }) => { const [isEditing, setIsEditing] = useState(false); - const [editedTitle, setEditedTitle] = useState(""); + const [editedTitle, setEditedTitle] = useState(todo.title); const handleChange = (event) => { setEditedTitle(event.target.value); @@ -14,7 +14,8 @@ export const ToDoItem = ({ todo, handleDelete, handleEdit }) => { return (
) : ( - + )} {isEditing ? ( diff --git a/src/components/TodoList.js b/src/components/TodoList.js index 2b4d224..a6c631a 100644 --- a/src/components/TodoList.js +++ b/src/components/TodoList.js @@ -1,28 +1,47 @@ import React from "react"; -import { useState } from "react"; +import { useState, useEffect, useRef } from "react"; import { v4 as uuidv4 } from "uuid"; import { ToDoItem } from "./ToDoItem"; function TodoList({ todoData }) { const [todoList, setTodoList] = useState(todoData); const [newTodo, setNewTodo] = useState(""); - + const [error, setError] = useState(""); + const [filtered, setFiltered] = useState([]); + // Create const handleTextChange = (event) => { setNewTodo(event.target.value); }; + const clear = useRef(); const handleTodoCreate = () => { - const newTodoObj = { - id: uuidv4(), - title: newTodo, - done: false, - }; - // Update the array to add the new item - setTodoList([...todoList, newTodoObj]); + let errors = ""; + if (!newTodo.trim()) { + errors = "write something"; + } else if (/\d+/.test(newTodo)) { + errors = "must not contain numbers"; + } else if (/\W+/.test(newTodo)) { + errors = "must not contain symbols"; + } else { + const newTodoObj = { + id: uuidv4(), + title: newTodo, + done: false, + }; + // Update the array to add the new item + setTodoList([...todoList, newTodoObj]); + } + setError(errors); + if (errors.length === 0) { + clear.current.value = ""; + } }; + + // Delete const handleDelete = (todoId) => { setTodoList(todoList.filter((todo) => todo.id !== todoId)); }; + // Edit const handleEdit = (todoId, editedTitle) => { setTodoList( todoList.map((todo) => { @@ -31,24 +50,33 @@ function TodoList({ todoData }) { ); }; + // Search + useEffect(() => { + setFiltered(todoList); + }, [todoList]); + const handleSearch = (e) => { + const filter = todoList.filter((todo) => + todo.title.toLowerCase().includes(e.target.value) + ); + setFiltered(filter); + }; + return (
-
+ -
- {todoList.map((todo) => ( +
+ {filtered.map((todo) => ( ))}
+
+
+ + {error && ( + + {error} + + )} +
+
+ +
+
); }