0% found this document useful (0 votes)
4 views10 pages

ToDoApp

The document outlines the structure and components of a Task Management application built using React. It includes the main App component, various modals for adding, editing, and deleting tasks, and a context for managing task state and API interactions. The application features a filter bar for task status and a responsive design utilizing Tailwind CSS for styling.

Uploaded by

bisipo2526
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views10 pages

ToDoApp

The document outlines the structure and components of a Task Management application built using React. It includes the main App component, various modals for adding, editing, and deleting tasks, and a context for managing task state and API interactions. The application features a filter bar for task status and a responsive design utilizing Tailwind CSS for styling.

Uploaded by

bisipo2526
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 10

To do App:

App.js

import Filterbar from './Components/Filterbar';


import Navbar from './Components/Navbar';
import { TaskProvider } from './Context/TaskContext';
import Tasks from "./Components/TaskList"

function App() {
return (
<>
<TaskProvider>
<Navbar />
<Filterbar />
<Tasks />
</TaskProvider>
</>
);
}

export default App;

index.css

@tailwind base;
@tailwind components;
@tailwind utilities;

body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto',
'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}

index.js

import React from 'react';


import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));


root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

// If you want to start measuring performance in your app, pass a function


// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();

src/Modals/AddTaskModals.jsx

import React, { useState } from 'react';


import { useTaskContext } from '../Context/TaskContext';

function AddTaskModal({ isOpen, closeModal }) {


const { addTask } = useTaskContext();
const [title, setTitle] = useState('');
const [description, setDescription] = useState('');
const [status, setStatus] = useState('todo'); // Default status

const handleSubmit = () => {


addTask(title, description, status);
setTitle('');
setDescription('');
setStatus('todo'); // Reset status to default
closeModal();
};

return (
<div className={`modal ${isOpen ? 'block' : 'hidden'} fixed inset-0 z-10
overflow-y-auto`} style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}>
<div className="modal-container bg-white w-full md:w-1/3 mx-auto mt-20 p-6
rounded shadow-lg">
<div className="modal-header flex justify-between items-center">
<h3 className="text-lg font-semibold">Add New Task</h3>
<button className="text-gray-500 hover:text-gray-800"
onClick={closeModal}>X</button>
</div>
<div className="modal-body mt-4">
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2"
htmlFor="title">Title</label>
<input className="border rounded w-full py-2 px-3 text-gray-700 leading-
tight focus:outline-none focus:shadow-outline" id="title" type="text"
value={title} onChange={(e) => setTitle(e.target.value)} />
</div>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2"
htmlFor="description">Description</label>
<input className="border rounded w-full py-2 px-3 text-gray-700 leading-
tight focus:outline-none focus:shadow-outline" id="description" type="text"
value={description} onChange={(e) => setDescription(e.target.value)} />
</div>
<button className="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2
px-4 rounded" onClick={handleSubmit}>Add Task</button>
</div>
</div>
</div>
);
}

export default AddTaskModal;

src/Modals/DeleteModal.jsx

import React from 'react';


import { useTaskContext } from '../Context/TaskContext';

function DeleteModal({ isOpen, closeModal, taskId }) {


const { deleteTask } = useTaskContext();

const handleDelete = () => {


deleteTask(taskId);
closeModal();
};

return (
<div className={`modal ${isOpen ? 'block' : 'hidden'} fixed inset-0 z-10
overflow-y-auto`} style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}>
<div className="modal-container bg-white w-full md:w-1/3 mx-auto mt-20 p-6
rounded shadow-lg">
<div className="modal-header flex justify-between items-center">
<h3 className="text-lg font-semibold">Confirm Delete</h3>
<button className="text-gray-500 hover:text-gray-800"
onClick={closeModal}>X</button>
</div>
<div className="modal-body mt-4">
<p>Are you sure you want to delete this task?</p>
<div className="flex justify-end mt-4">
<button className="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-
4 rounded mr-2" onClick={handleDelete}>Delete</button>
<button className="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-
2 px-4 rounded" onClick={closeModal}>Cancel</button>
</div>
</div>
</div>
</div>
);
}

export default DeleteModal;

src/Modals/EditModal.jsx

import React, { useState } from 'react';


import { useTaskContext } from '../Context/TaskContext';

function EditModal({ isOpen, closeModal, taskId, initialTitle = '' }) {


const { editTask } = useTaskContext();
const [title, setTitle] = useState(initialTitle);

const handleSubmit = () => {


editTask(taskId, title);
closeModal();
};

return (
<div className={`modal ${isOpen ? 'block' : 'hidden'} fixed inset-0 z-10
overflow-y-auto`} style={{ backgroundColor: 'rgba(0, 0, 0, 0.5)' }}>
<div className="modal-container bg-white w-full md:w-1/3 mx-auto mt-20 p-6
rounded shadow-lg">
<div className="modal-header flex justify-between items-center">
<h3 className="text-lg font-semibold">Edit Task</h3>
<button className="text-gray-500 hover:text-gray-800"
onClick={closeModal}>X</button>
</div>
<div className="modal-body mt-4">
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2"
htmlFor="title">Title</label>
<input className="border rounded w-full py-2 px-3 text-gray-700 leading-
tight focus:outline-none focus:shadow-outline" id="title" type="text"
value={title} onChange={(e) => setTitle(e.target.value)} />
</div>
<div className="flex justify-end mt-4">
<button className="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2
px-4 rounded mr-2" onClick={handleSubmit}>Save</button>
<button className="bg-gray-300 hover:bg-gray-400 text-gray-800 font-bold py-
2 px-4 rounded" onClick={closeModal}>Cancel</button>
</div>
</div>
</div>
</div>
);
}

export default EditModal;

src/Context/TaskContent.js

import React, { createContext, useContext, useEffect, useState } from


'react';
import axios from 'axios';

const TaskContext = createContext();

const apiUrl = process.env.REACT_APP_API_URL || 'http://localhost:5000';

export const useTaskContext = () => {


return useContext(TaskContext);
};

export const TaskProvider = ({ children }) => {


const [tasks, setTasks] = useState([]);
const [filteredTasks, setFilteredTasks] = useState([]);
const [totalTasks, setTotalTasks] = useState(0);
const [completedTasks, setCompletedTasks] = useState(0);
const [todoTasks, setTodoTasks] = useState(0);

useEffect(() => {
fetchData();
}, [totalTasks]);

const fetchData = async () => {


try {
const response = await axios.get(`${apiUrl}/tasks`);
setTasks(response.data);
setFilteredTasks(response.data);
setTotalTasks(response.data.length);
const completedCount = response.data.filter(task => task.status ===
'completed').length;
setCompletedTasks(completedCount);
setTodoTasks(response.data.length - completedCount);
} catch (err) {
console.error('Error fetching data:', err);
}
};

const handleFilterClick = (status) => {


if (status === 'all') {
setFilteredTasks(tasks);
} else {
const filtered = tasks.filter(task => task.status === status);
setFilteredTasks(filtered);
}
};

const addTask = async (title, description, status) => {


try {
const response = await axios.post(`${apiUrl}/tasks`, { title, description,
status });
setTasks([...tasks, response.data]);
if (status === 'completed') {
setCompletedTasks(prev => prev + 1);
} else {
setTodoTasks(prev => prev + 1);
}
setTotalTasks(prev => prev + 1);
} catch (err) {
console.error('Error adding task:', err);
}
};

const deleteTask = async (taskId) => {


try {
await axios.delete(`${apiUrl}/tasks/${taskId}`);
const updatedTasks = tasks.filter(task => task.id !== taskId);
setTasks(updatedTasks);
setFilteredTasks(updatedTasks);
setTotalTasks(prev => prev - 1);
const completedCount = updatedTasks.filter(task => task.status ===
'completed').length;
setCompletedTasks(completedCount);
setTodoTasks(updatedTasks.length - completedCount);
} catch (err) {
console.error('Error deleting task:', err);
}
};

const editTask = async (taskId, updatedTitle, updatedDescription,


updatedStatus) => {
try {
await axios.put(`${apiUrl}/tasks/${taskId}`, { title: updatedTitle,
description: updatedDescription, status: updatedStatus });
fetchData();
} catch (err) {
console.error('Error editing task:', err);
}
};

const updateTaskStatus = async (taskId, status) => {


try {
await axios.put(`${apiUrl}/tasks/${taskId}`, { status });
const updatedTasks = tasks.map(task => task._id === taskId ? { ...task,
status } : task);
setTasks(updatedTasks);
setFilteredTasks(updatedTasks);
setCompletedTasks(prev => status === 'completed' ? prev + 1 : prev - 1);
setTodoTasks(prev => status !== 'completed' ? prev + 1 : prev - 1);
} catch (err) {
console.error('Error updating task status:', err);
}
};

return (
<TaskContext.Provider value={{ filteredTasks, totalTasks, completedTasks,
todoTasks, handleFilterClick, addTask, deleteTask, editTask,
updateTaskStatus }}>
{children}
</TaskContext.Provider>
);
};

src/Components/Filter.jsx

import React from 'react';


import { useTaskContext } from '../Context/TaskContext';

function Filterbar() {
const { handleFilterClick } = useTaskContext();

return (
<div className="flex justify-center mt-8">
<button
className="filter-button bg-blue-500 hover:bg-blue-600 text-white font-bold
py-2 px-4 rounded-l"
onClick={() => handleFilterClick('all')}
>
All
</button>
<button
className="filter-button bg-blue-500 hover:bg-blue-600 text-white font-bold
py-2 px-4"
onClick={() => handleFilterClick('completed')}
>
Completed
</button>
<button
className="filter-button bg-blue-500 hover:bg-blue-600 text-white font-bold
py-2 px-4 rounded-r"
onClick={() => handleFilterClick('todo')}
>
To Do
</button>
</div>
);
}

export default Filterbar;

src/Components/Navbar.jsx

import React, { useState } from 'react';


import AddTaskModal from '../Modals/AddTaskModal';

function Navbar() {
const [isModalOpen, setIsModalOpen] = useState(false);

const openModal = () => {


setIsModalOpen(true);
};

const closeModal = () => {


setIsModalOpen(false);
};

return (
<nav className="bg-gray-800 py-4">
<div className="max-w-7xl mx-auto px-4 flex justify-between items-center">
<div>
<span className="text-white text-lg font-bold">Task Manager</span>
</div>

<div>
<button className="bg-blue-500 hover:bg-blue-600 text-white font-bold py-2
px-4 rounded" onClick={openModal}>
Add
</button>
</div>
</div>
<AddTaskModal isOpen={isModalOpen} closeModal={closeModal} />
</nav>
);
}

export default Navbar;

src/Components/TaskList.jsx
import React, { useState } from 'react';
import { useTaskContext } from '../Context/TaskContext';
import DeleteModal from '../Modals/DeleteModal';
import EditModal from '../Modals/EditModal';

function TaskList() {
const { filteredTasks, updateTaskStatus } = useTaskContext();
const [taskId, setTaskId] = useState('');
const [taskTitle, setTaskTitle] = useState('');
const [taskDescription, setTaskDescription] = useState('');
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
const [openDropdownId, setOpenDropdownId] = useState(null);

const handleDelete = (taskId) => {


setTaskId(taskId);
setIsDeleteModalOpen(true);
setOpenDropdownId(null);
};

const handleEdit = (taskId, taskTitle, taskDescription) => {


setTaskId(taskId);
setTaskTitle(taskTitle);
setTaskDescription(taskDescription);
setIsEditModalOpen(true);
setOpenDropdownId(null);
};

const handleComplete = (taskId) => {


updateTaskStatus(taskId, 'completed');
setOpenDropdownId(null);
};

const toggleDropdown = (taskId) => {


setOpenDropdownId(openDropdownId === taskId ? null : taskId);
};

const isDropdownOpen = (taskId) => {


return openDropdownId === taskId;
};

const getStatusColor = (status) => {


switch (status) {
case 'todo':
return 'bg-yellow-200'; // Yellow color for "To Do" tasks
case 'completed':
return 'bg-green-200'; // Green color for "Completed" tasks
default:
return 'bg-gray-200'; // Default gray color for other tasks
}
};
return (
<div className="my-8 grid gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3
lg:grid-cols-4 xl:grid-cols-5">
{filteredTasks.map(task => (
<div key={task._id} className={`relative rounded-md shadow-md $
{getStatusColor(task.status)}`}>
<div className="p-4">
<div className="flex justify-between items-center mb-2">
<h3 className="text-lg font-semibold">{task.title}</h3>
<button onClick={() => toggleDropdown(task._id)} className="text-gray-500
hover:text-gray-700">
<svg className="w-6 h-6" fill="none" viewBox="0 0 24 24"
stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4
6h16M4 12h16M4 18h16" />
</svg>
</button>
</div>
<p className="text-sm text-gray-600 mb-4">{task.description}</p>
</div>
{isDropdownOpen(task._id) && (
<div className="absolute top-full right-0 mt-2 w-48 bg-white border rounded-
md shadow-md z-10">
<button className="block w-full py-2 px-4 text-left hover:bg-gray-100"
onClick={() => handleEdit(task._id, task.title,
task.description)}>Edit</button>
<button className="block w-full py-2 px-4 text-left text-red-600 hover:bg-
red-100" onClick={() => handleDelete(task._id)}>Delete</button>
{task.status !== 'completed' && (
<button className="block w-full py-2 px-4 text-left hover:bg-gray-100"
onClick={() => handleComplete(task._id)}>Mark as Completed</button>
)}
</div>
)}
</div>
))}
<DeleteModal isOpen={isDeleteModalOpen} closeModal={() =>
setIsDeleteModalOpen(false)} taskId={taskId} />
<EditModal isOpen={isEditModalOpen} closeModal={() =>
setIsEditModalOpen(false)} taskId={taskId} initialTitle={taskTitle}
initialDescription={taskDescription} />
</div>
);
}

export default TaskList;

You might also like