Daily Activity Planner App with Next.js
Managing your tasks is one of the most important things in a hectic routine. In this article, we will see step-by-step procedure of creating a task manager app from scratch.
Output Preview: Let us have a look at how the final output will look like.
Prerequisites :
Approach to create Daily Activity Planner:
- State Management: For efficient task and input field handling, use useState.
- Input Handling: Put in place handlers for the name, priority, and deadline of each task.
- Task Functions: Task operations are managed by functions such as addTask, EditTask, DeleteTask, and markDone.
- Improve user experience (UX) by using filtered tasks to effortlessly filter tasks according to user-specified requirements.
Steps to create the Next JS Application:
Step 1: Create a new Next.js project using the following command
npx create-next-app task-manager-app
Step 2: Change to the project directory:
cd task-manager-app
Project Structure:
The updated Dependencies in package.json file will look like:
"dependencies": {
"react": "^18",
"react-dom": "^18",
"next": "14.1.0"
}
Example: Create the required files as seen on folder structure and paste the code components as per the structure.
/* Home.module.css */
.App {
font-family: 'Arial', sans-serif;
margin: 30px auto;
padding: 20px;
max-width: 800px;
background-color: #ffdbac;
box-shadow: 0 2px 16px rgba(0, 0, 0, 0.1);
border-radius: 15px;
}
.taskHeader {
text-align: center;
background-color: #f1c27d;
color: #3b3b3a;
padding: 10px 0;
margin-bottom: 20px;
border-radius: 8px 8px 0 0;
}
.taskForm {
margin-bottom: 20px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.taskNameInput,
.taskPrioritySelect,
.taskDeadlineInput,
.addTaskButton {
margin: 5px;
padding: 10px;
border: 1px solid #3e3730;
border-radius: 4px;
flex-grow: 1;
font-size: 16px;
color: #f5f5f5;
}
.taskPrioritySelect {
cursor: pointer;
background-color: #e0ac69;
}
.addTaskButton {
background-color: #e0ac69;
color: rgb(253, 253, 253);
border: none;
cursor: pointer;
transition: background-color 0.3s;
}
.addTaskButton:hover {
background-color: #e4c193d4;
}
.searchFilter {
display: flex;
justify-content: space-between;
align-items: center;
}
.searchInput,
.filterPrioritySelect {
padding: 10px;
border: 1px solid #b8b8b8f6;
border-radius: 4px;
flex-grow: 1;
font-size: 16px;
}
.heading {
color: black;
text-align: center;
font-weight: 400;
}
.completedHeading {
color: black;
text-align: center;
font-weight: 400;
}
.taskTable {
width: 100%;
border-collapse: collapse;
background-color: #8d5524;
}
.taskTable th,
.taskTable td {
padding: 10px;
text-align: center;
}
.taskTable th {
background-color: #a88a63;
color: white;
}
.taskTable tbody tr:nth-child(even) {
background-color: #836338;
}
.completedTable {
width: 100%;
border-collapse: collapse;
background-color: #8d5524;
}
.completedTable th,
.completedTable td {
padding: 10px;
text-align: center;
}
.completedTable th {
background-color: #a88a63;
color: white;
}
.completedTable tbody tr:nth-child(even) {
background-color: #836338;
}
.deleteTaskButton {
margin-right: 5px;
cursor: pointer;
padding: 12px;
background: rgba(224, 43, 43, 0.595);
border-radius: 10px;
border: none;
color: white;
}
.deleteTaskButton:hover {
background: red;
}
.markDoneButton,
.editTaskButton {
margin-right: 5px;
cursor: pointer;
padding: 12px;
background: #218a1574;
border-radius: 10px;
border: none;
color: white;
}
.markDoneButton:hover {
background: rgb(23, 175, 23);
}
.editTaskButton:hover {
background: rgb(23, 175, 23);
}
@media (max-width: 600px) {
.taskForm {
flex-direction: column;
}
.searchFilter {
flex-direction: column;
}
}
// pages/index.js
import TaskScheduler from "../components/TaskScheduler";
export default TaskScheduler;
// src/components/CompletedTaskList.js
import React from 'react';
import styles from '../styles/Home.module.css';
const CompletedTaskList = ({ completedTasks }) => {
return (
<div className={styles.completedTaskList}>
<h2 className={styles.completedHeading}>Completed Tasks</h2>
<table className={styles.completedTable}>
<thead>
<tr>
<th>Task Name</th>
<th>Priority</th>
<th>Deadline</th>
</tr>
</thead>
<tbody>
{completedTasks.map((ct) => (
<tr key={ct.id}>
<td>{ct.task}</td>
<td>{ct.priority}</td>
<td>{ct.deadline}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default CompletedTaskList;
// src/components/TaskForm.js
import styles from "../styles/Home.module.css";
const TaskForm = ({
taskName,
taskPriority,
taskDeadline,
handleTaskNameChange,
handleTaskPriorityChange,
handleTaskDeadlineChange,
addTask
}) => {
return (
<div className={styles.taskForm}>
<input
type="text"
className={styles.taskNameInput}
placeholder="Enter task..."
value={taskName}
onChange={handleTaskNameChange}
/>
<select
className={styles.taskPrioritySelect}
value={taskPriority}
onChange={handleTaskPriorityChange}
>
<option value="Top">High Priority</option>
<option value="Middle">Medium Priority</option>
<option value="Low">Not Important</option>
</select>
<input
type="date"
className={styles.taskDeadlineInput}
value={taskDeadline}
onChange={handleTaskDeadlineChange}
/>
<button className={styles.addTaskButton} onClick={addTask}>
Add Task
</button>
</div>
);
};
export default TaskForm;
// src/components/TaskList.js
import React from 'react';
import styles from '../styles/Home.module.css';
const TaskList = ({
tasks,
markDone,
handleEditTask,
handleDeleteTask
}) => {
return (
<div className={styles.taskList}>
<table className={styles.taskTable}>
<thead>
<tr>
<th>Name</th>
<th>Priority</th>
<th>Deadline</th>
<th>State</th>
</tr>
</thead>
<tbody>
{tasks.map((t) => (
<tr key={t.id}>
<td>{t.task}</td>
<td>{t.priority}</td>
<td>{t.deadline}</td>
<td>
{!t.done && (
<div>
<button
className={styles.markDoneButton}
onClick={() => markDone(t.id)}
>
Done
</button>
<button
className={styles.editTaskButton}
onClick={() => handleEditTask(t.id)}
>
Edit
</button>
<button
className={styles.deleteTaskButton}
onClick={() => handleDeleteTask(t.id)}
>
Delete
</button>
</div>
)}
</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default TaskList;
// src/components/TaskScheduler.js
import React, { useState, useEffect } from "react";
import Head from "next/head";
import styles from "../styles/Home.module.css";
import TaskForm from '../components/TaskForm';
import TaskList from '../components/TaskList';
import CompletedTaskList from '../components/CompletedTaskList';
const TaskScheduler = () => {
const [tasks, setTasks] = useState([]);
const [completedTasks, setCompletedTasks] = useState([]);
const [taskName, setTaskName] = useState("");
const [taskPriority, setTaskPriority] = useState("Top");
const [taskVal, setTaskDeadline] = useState("");
const [searchKeyword, setSearchKeyword] = useState("");
const [filterPriority, setFilterPriority] = useState("");
const TASKS_STORAGE_KEY = "tasks";
const COMPLETED_TASKS_STORAGE_KEY = "completedTasks";
useEffect(() => {
const storedTasks = JSON.parse(localStorage.getItem(TASKS_STORAGE_KEY));
if (storedTasks) {
setTasks(storedTasks);
}
const storedCompletedTasks = JSON.parse(localStorage.getItem(COMPLETED_TASKS_STORAGE_KEY));
if (storedCompletedTasks) {
setCompletedTasks(storedCompletedTasks);
}
}, []);
useEffect(() => {
localStorage.setItem(TASKS_STORAGE_KEY, JSON.stringify(tasks));
}, [tasks]);
useEffect(() => {
localStorage.setItem(COMPLETED_TASKS_STORAGE_KEY, JSON.stringify(completedTasks));
}, [completedTasks]);
const handleTaskNameChange = (e) => {
6
setTaskName(e.target.value);
};
const handleTaskPriorityChange = (e) => {
setTaskPriority(e.target.value);
};
const handleTaskDeadlineChange = (e) => {
setTaskDeadline(e.target.value);
};
const addTask = () => {
if (taskName.trim() === "" || taskVal === "") {
alert("Enter a task, Must not Empty!!!");
return;
}
const selDate = new Date(taskVal);
const currDate = new Date();
if (selDate <= currDate) {
alert("Can't go back in time.");
return;
}
const newTask = {
id: tasks.length + 1,
task: taskName,
priority: taskPriority,
deadline: taskVal,
done: false,
};
// Fetch existing tasks from local storage
const existingTasks = JSON.parse(localStorage.getItem(TASKS_STORAGE_KEY)) || [];
// Append the new task to existing tasks
const updatedTasks = [...existingTasks, newTask];
// Update tasks state
setTasks(updatedTasks);
// Update local storage with combined old and new tasks
localStorage.setItem(TASKS_STORAGE_KEY, JSON.stringify(updatedTasks));
setTaskName("");
setTaskPriority("Top");
setTaskDeadline("");
};
const handleEditTask = (id) => {
const taskToEdit = tasks.find((t) => t.id === id);
setTaskName(taskToEdit.task);
setTaskPriority(taskToEdit.priority);
setTaskDeadline(taskToEdit.deadline);
const updatedTasks = tasks.filter((t) => t.id !== id);
setTasks(updatedTasks);
};
const handleDeleteTask = (id) => {
const updatedTasks = tasks.filter((t) => t.id !== id);
setTasks(updatedTasks);
};
const markDone = (id) => {
const updatedTasks = tasks.map((t) =>
t.id === id ? { ...t, done: true } : t
);
setTasks(updatedTasks);
const completedTask = tasks.find((t) => t.id === id);
if (completedTask) {
setCompletedTasks([...completedTasks, completedTask]);
}
};
const filteredTasks = tasks
.filter((t) => !t.done)
.filter((t) =>
t.task.toLowerCase().includes(searchKeyword.toLowerCase())
)
.filter((t) => (filterPriority ? t.priority === filterPriority : true));
return (
<div className={styles.App}>
<Head>
<title>Task Manager - w3wiki.org</title>
</Head>
<header className={styles.taskHeader}>
<h1>Task Manager</h1>
</header>
<main>
<TaskForm
taskName={taskName}
taskPriority={taskPriority}
taskDeadline={taskVal}
handleTaskNameChange={handleTaskNameChange}
handleTaskPriorityChange={handleTaskPriorityChange}
handleTaskDeadlineChange={handleTaskDeadlineChange}
addTask={addTask}
/>
{/* Search and Filter Component */}
<div className={styles.searchFilter}>
<input
type="text"
className={styles.searchInput}
placeholder="Search tasks"
value={searchKeyword}
onChange={(e) => setSearchKeyword(e.target.value)}
/>
<select
className={styles.filterPrioritySelect}
value={filterPriority}
onChange={(e) => setFilterPriority(e.target.value)}
>
<option value="">All</option>
<option value="Top">High Priority</option>
<option value="Middle">Medium Priority</option>
<option value="Low">Not Important</option>
</select>
</div>
<h2 className={styles.heading}>Tasks</h2>
<TaskList
tasks={filteredTasks}
markDone={markDone}
handleEditTask={handleEditTask}
handleDeleteTask={handleDeleteTask}
/>
<CompletedTaskList completedTasks={completedTasks} />
</main>
</div>
);
};
export default TaskScheduler;
Steps to run the application:
Step 1: Run this command to start the application:
npm run dev
Step 2: Visit the URL:
http://localhost:3000
Output:
Contact Us