├── public ├── _redirects └── index.html ├── src ├── index.css ├── index.js ├── components │ ├── Footer.js │ ├── Header.js │ ├── TaskList.js │ ├── AddTask.js │ └── TaskItem.js ├── App.css └── App.js ├── postcss.config.js ├── tailwind.config.js ├── .gitignore ├── package.json └── README.md /public/_redirects: -------------------------------------------------------------------------------- 1 | /* /index.html 200 -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{js,jsx,ts,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import App from "./App"; 4 | import "./index.css"; 5 | 6 | const root = ReactDOM.createRoot(document.getElementById("root")); 7 | root.render( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | To-Do app 8 | 9 | 10 |
11 | 12 | 13 | -------------------------------------------------------------------------------- /src/components/Footer.js: -------------------------------------------------------------------------------- 1 | const Footer = () => { 2 | return ( 3 | 6 | ); 7 | }; 8 | 9 | export default Footer; 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /src/components/Header.js: -------------------------------------------------------------------------------- 1 | import { HiDocumentText } from "react-icons/hi"; 2 | 3 | const Header = () => { 4 | return ( 5 |
6 |

7 | 8 | 9 | 10 | To Do App 11 |

12 |
13 | ); 14 | }; 15 | 16 | export default Header; 17 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/components/TaskList.js: -------------------------------------------------------------------------------- 1 | import TaskItem from "./TaskItem"; 2 | const TaskList = ({ 3 | tasks, 4 | error, 5 | loading, 6 | handleEditSubmitter, 7 | editedText, 8 | setEditedText, 9 | }) => { 10 | return ( 11 |
12 | {loading ? ( 13 |

{error ? error : "Loading..."}

14 | ) : ( 15 | tasks.length === 0 &&

No task to show

16 | )} 17 | {tasks.map((task) => ( 18 | 25 | ))} 26 |
27 | ); 28 | }; 29 | 30 | export default TaskList; 31 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-to-do-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.2.0", 10 | "react-dom": "^18.2.0", 11 | "react-icons": "^4.6.0", 12 | "react-scripts": "5.0.1", 13 | "web-vitals": "^2.1.4" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": [ 23 | "react-app", 24 | "react-app/jest" 25 | ] 26 | }, 27 | "browserslist": { 28 | "production": [ 29 | ">0.2%", 30 | "not dead", 31 | "not op_mini all" 32 | ], 33 | "development": [ 34 | "last 1 chrome version", 35 | "last 1 firefox version", 36 | "last 1 safari version" 37 | ] 38 | }, 39 | "devDependencies": { 40 | "autoprefixer": "^10.4.13", 41 | "postcss": "^8.4.19", 42 | "tailwindcss": "^3.2.4" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/components/AddTask.js: -------------------------------------------------------------------------------- 1 | import { useRef, useState } from "react"; 2 | 3 | const AddTask = ({ tasks, setTasks }) => { 4 | const [task, setTask] = useState(""); 5 | 6 | const inputRef = useRef(null); 7 | 8 | //add task handle event 9 | const addTaskHandler = (e) => { 10 | e.preventDefault(); 11 | 12 | //post task into server 13 | taskPosting(task); 14 | inputRef.current.blur(); 15 | setTask(""); 16 | }; 17 | 18 | //task posting 19 | 20 | const taskPosting = async (text) => { 21 | const res = await fetch( 22 | "https://delightful-pool-astronaut.glitch.me/tasks", 23 | { 24 | method: "POST", 25 | headers: { 26 | "Content-type": "application/json", 27 | }, 28 | body: JSON.stringify({ text }), 29 | } 30 | ); 31 | const data = await res.json(); 32 | //real time data updation 33 | setTasks([...tasks, data]); 34 | }; 35 | 36 | return ( 37 |
41 | setTask(e.target.value)} 45 | required 46 | type="text" 47 | placeholder="What things to do" 48 | className="bg-transparent outline-none border-b-2 border-gray-400 py-2 px-5 focus:border-teal-600 " 49 | /> 50 | 56 |
57 | ); 58 | }; 59 | 60 | export default AddTask; 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # To-Do-App 2 | 3 | To-Do-App is a task management website built using React.js, React Router, and Tailwind CSS. This project provides a platform for managing tasks and keeping track of deadlines. 4 | 5 | ## Project Description 6 | 7 | To-Do-App offers the following features: 8 | 9 | - Users can add tasks to their to-do list and set deadlines for each task. 10 | - The website uses React Router to provide a seamless user experience with its dynamic routing functionality. 11 | - Users can mark tasks as complete and remove them from their to-do list. 12 | - The website is designed with Tailwind CSS, providing a modern and responsive user interface. 13 | 14 | ## Tools Used 15 | 16 | To-Do-App was built using the following tools: 17 | 18 | - React.js 19 | - React Router 20 | - Tailwind CSS 21 | 22 | ## Installation 23 | 24 | To run To-Do-App on your local machine, follow these steps: 25 | 26 | 1. Clone the repository using the command: 27 | 28 | ` 29 | git clone https://github.com/your-username/to-do-app.git 30 | ` 31 | 32 | 2. Navigate to the project directory using the command: 33 | 34 | ` 35 | cd to-do-app 36 | ` 37 | 38 | 3. Install the required dependencies using the command: 39 | 40 | ` 41 | npm install 42 | ` 43 | 44 | 4. Start the development server using the command: 45 | 46 | ` 47 | npm start 48 | ` 49 | 50 | 5. Open your web browser and navigate to http://localhost:3000 51 | 52 | ## Conclusion 53 | 54 | In conclusion, To-Do-App is a task management website built using React.js, React Router, and Tailwind CSS. This project only implements the frontend part of the application. The website provides a seamless user experience with its dynamic routing functionality and modern user interface. To-Do-App is a useful tool for managing tasks and staying organized. 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /src/components/TaskItem.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { useContext } from "react"; 3 | import { FiEdit, FiTrash } from "react-icons/fi"; 4 | 5 | import { DeleteHandlerContext, EditHandlerContext } from "../App"; 6 | 7 | const TaskItem = ({ task, handleEditSubmitter, editedText, setEditedText }) => { 8 | const [isChecked, setIsChecked] = useState(false); 9 | const handleDelete = useContext(DeleteHandlerContext); 10 | const handleEdit = useContext(EditHandlerContext); 11 | 12 | return ( 13 |
14 |
15 | 16 | setIsChecked(!isChecked)} 21 | /> 22 | 23 | 24 | {task.isEditable && ( 25 |
handleEditSubmitter(e, task.id)}> 26 | { 32 | setEditedText(e.target.value); 33 | }} 34 | /> 35 |
36 | )} 37 | 38 | {!task.isEditable && ( 39 |

46 | {task.text} 47 |

48 | )} 49 |
50 |
51 | 54 | 57 |
58 |
59 | ); 60 | }; 61 | 62 | export default TaskItem; 63 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import { createContext } from "react"; 2 | import { useEffect } from "react"; 3 | import { useState } from "react"; 4 | import AddTask from "./components/AddTask"; 5 | import Footer from "./components/Footer"; 6 | import Header from "./components/Header"; 7 | import TaskList from "./components/TaskList"; 8 | 9 | export const DeleteHandlerContext = createContext(); 10 | export const EditHandlerContext = createContext(); 11 | 12 | const App = () => { 13 | const [tasks, setTasks] = useState([]); 14 | const [loading, setLoading] = useState(true); 15 | const [error, setError] = useState(""); 16 | 17 | const [editedText, setEditedText] = useState(""); 18 | const [toggleEditMode, setToggleEditMode] = useState(true); 19 | 20 | useEffect(() => { 21 | //getting data from the server 22 | 23 | fetchingData(); 24 | }, []); 25 | 26 | //fetching data 27 | 28 | const fetchingData = async () => { 29 | try { 30 | const res = await fetch( 31 | "https://delightful-pool-astronaut.glitch.me/tasks" 32 | ); 33 | if (!res.ok) throw new Error("Something went wrong"); 34 | const data = await res.json(); 35 | setTasks(data); 36 | setLoading(false); 37 | } catch (error) { 38 | setError(error.message); 39 | } 40 | }; 41 | 42 | // delete event 43 | const handleDelete = (id) => { 44 | //delete data 45 | deleteData(id); 46 | //set updated task 47 | setTasks(tasks.filter((task) => id !== task.id)); 48 | }; 49 | 50 | const deleteData = async (id) => { 51 | await fetch(`https://delightful-pool-astronaut.glitch.me/tasks/${id}`, { 52 | method: "DELETE", 53 | headers: { 54 | "Content-type": "application/json", 55 | }, 56 | }); 57 | }; 58 | 59 | //editing event 60 | 61 | const handleEdit = (id) => { 62 | const [editableTarget] = tasks.filter((task) => id === task.id); 63 | editableTarget.isEditable = true; 64 | setEditedText(editableTarget.text); 65 | 66 | setTasks([...tasks]); 67 | setToggleEditMode(false); 68 | 69 | ///re-arrenge 70 | 71 | tasks 72 | .filter((task) => task.id !== id) 73 | .map((targetedEl) => (targetedEl.isEditable = false)); 74 | }; 75 | 76 | //editing task form handler 77 | 78 | const handleEditSubmitter = (e, id) => { 79 | e.preventDefault(); 80 | 81 | setToggleEditMode(!toggleEditMode); 82 | 83 | //persist data 84 | 85 | const editPersistance = { 86 | text: editedText, 87 | id: id, 88 | }; 89 | 90 | //put request 91 | 92 | puttingRequest(id, editPersistance); 93 | 94 | //real time update 95 | const [editableTarget] = tasks.filter((task) => id === task.id); 96 | editableTarget.isEditable = false; 97 | editableTarget.text = editPersistance.text; 98 | 99 | setTasks([...tasks]); 100 | }; 101 | 102 | const puttingRequest = async (id, newData) => { 103 | fetch(`https://delightful-pool-astronaut.glitch.me/tasks/${id}`, { 104 | method: "PUT", 105 | headers: { 106 | "Content-type": "application/json", 107 | }, 108 | body: JSON.stringify(newData), 109 | }); 110 | }; 111 | 112 | return ( 113 |
114 | 115 | 116 |
117 | 118 | 126 |
130 | ); 131 | }; 132 | 133 | export default App; 134 | --------------------------------------------------------------------------------