diff --git a/client/src/App.css b/client/src/App.css index 59ca807..13185fd 100644 --- a/client/src/App.css +++ b/client/src/App.css @@ -1,51 +1,60 @@ +/* Main App container */ .App { - max-width: 600px; - margin: auto; - margin-top: 2em; - padding: 1em; - background: white; - border: 1px solid #ddd; - border-radius: 8px; - box-shadow: 0 4px 8px 0px rgba(0, 0, 0, 0.1); + max-width: 600px; /* Limit width of app */ + margin: auto; /* Center horizontally */ + margin-top: 2em; /* Space from top */ + padding: 1em; /* Inner spacing */ + background: white; /* White background */ + border: 1px solid #ddd; /* Light gray border */ + border-radius: 8px; /* Rounded corners */ + box-shadow: 0 4px 8px 0px rgba(0, 0, 0, 0.1); /* Subtle shadow */ } +/* Title styles */ h1 { - font-weight: normal; - margin: 0; + font-weight: normal; /* Not bold */ + margin: 0; /* Remove default spacing */ } +/* Task list styles */ .tasks { - list-style: none; - padding: 0; + list-style: none; /* Remove bullet points */ + padding: 0; /* Remove default list padding */ } +/* Completed task style */ .done { - text-decoration: line-through; - opacity: 0.5; + text-decoration: line-through; /* Strike-through text */ + opacity: 0.5; /* Make it look faded */ } +/* Input fields (text + submit button) */ input[type="text"], input[type="submit"] { - font-size: 0.9em; - padding: 4px 8px; + font-size: 0.9em; /* Slightly smaller font */ + padding: 4px 8px; /* Inner spacing */ } +/* Task label (checkbox + title + delete button) */ label { - vertical-align: top; + vertical-align: top; /* Align with checkbox nicely */ } +/* Delete button (SVG icon) */ .delete-button { padding-top: 4px; - margin-left: 8px; - cursor: pointer; - opacity: 0.3; - visibility: hidden; + margin-left: 8px; /* Space after task text */ + cursor: pointer; /* Show pointer on hover */ + opacity: 0.3; /* Light/faded by default */ + visibility: hidden; /* Hidden until hover */ } +/* Show delete button only when task row is hovered */ li:hover .delete-button { visibility: visible; } +/* Darken delete button on hover */ .delete-button:hover { opacity: 0.6; } diff --git a/client/src/App.js b/client/src/App.js index e4ad8e4..5cf98a8 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -3,30 +3,38 @@ import './App.css'; import TasksList from './components/TaskList'; +// Main App component const App = () => { + // State: all tasks fetched from backend const [tasks, setTasks] = useState([]); + + // State: new task input value const [newTaskTitle, setNewTaskTitle] = useState(''); + // Function to fetch all tasks from backend + // useCallback used so reference of function doesn't change unnecessarily const getTasks = useCallback(() => { fetch('/api/tasks') .then(res => res.json()) - .then(setTasks); + .then(setTasks); // update tasks state }); + // Fetch tasks when component first mounts useEffect(() => { getTasks(); - }, []); + }, []); // [] means only run once on mount + // Add a new task const clickAddTask = event => { - event.preventDefault(); + event.preventDefault(); // prevent form reload fetch('/api/tasks/add', { method: 'post', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ title: newTaskTitle }), + body: JSON.stringify({ title: newTaskTitle }), // send new title }).then(() => { - setNewTaskTitle(''); - getTasks(); + setNewTaskTitle(''); // clear input + getTasks(); // refresh task list }); }; @@ -34,15 +42,17 @@ const App = () => {

My Tasks

+ {/* Task list component */} + {/* Form to add new task */}
setNewTaskTitle(event.target.value)} + onChange={event => setNewTaskTitle(event.target.value)} // update state />
diff --git a/client/src/components/TaskList.js b/client/src/components/TaskList.js index d88c58e..37a9822 100644 --- a/client/src/components/TaskList.js +++ b/client/src/components/TaskList.js @@ -1,35 +1,48 @@ import React from 'react'; +// TaskList component +// Props: +// - tasks: Array of task objects (fetched from backend) +// - updateTasks: Function to refresh tasks after add/delete/update const TaskList = ({ tasks, updateTasks }) => { + + // Function to delete a task const clickDeleteTask = (event, task) => { - event.preventDefault(); + event.preventDefault(); // Prevent default link/submit behavior + // Call backend API to delete task by ID fetch(`/api/tasks/delete/${task._id}`, { method: 'delete', }) - .then(res => res.json()) - .then(() => updateTasks()); + .then(res => res.json()) // Parse response + .then(() => updateTasks()); // Refresh task list after deletion }; + // Function to toggle task "done" status const toggleDone = task => { + // Call backend API to update "done" field (true/false) fetch(`/api/tasks/update/${task._id}`, { method: 'post', headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ done: !task.done }), - }).then(() => updateTasks()); + body: JSON.stringify({ done: !task.done }), // Toggle current state + }).then(() => updateTasks()); // Refresh tasks after update }; return (