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.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/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..6516123
--- /dev/null
+++ b/src/components/ToDoItem.js
@@ -0,0 +1,48 @@
+import React from "react";
+import { useState } from "react";
+export const ToDoItem = ({ todo, handleDelete, handleEdit }) => {
+ const [isEditing, setIsEditing] = useState(false);
+ const [editedTitle, setEditedTitle] = useState(todo.title);
+
+ 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..a6c631a
--- /dev/null
+++ b/src/components/TodoList.js
@@ -0,0 +1,120 @@
+import React 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 = () => {
+ 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) => {
+ return todo.id === todoId ? { ...todo, title: editedTitle } : todo;
+ })
+ );
+ };
+
+ // Search
+ useEffect(() => {
+ setFiltered(todoList);
+ }, [todoList]);
+ const handleSearch = (e) => {
+ const filter = todoList.filter((todo) =>
+ todo.title.toLowerCase().includes(e.target.value)
+ );
+ setFiltered(filter);
+ };
+
+ return (
+
+
+
+
+
+ {filtered.map((todo) => (
+
+ ))}
+
+
+
+
+ {error && (
+
+ {error}
+
+ )}
+
+
+
+ Add
+
+
+
+
+ );
+}
+
+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: [],
+}
+