Build a Task Management App using Next JS
A Task management app is a useful web application that assists in efficiently organizing and managing tasks. It provides various functionalities such as creating tasks, assigning priorities and deadlines, marking complete tasks, and enabling task search based on keywords and priorities.
Preview of final output: Let us have a look at how the final output will look like
Prerequisites :
Approach :
- The useState hook is employed to effectively manage component state, ensuring smooth handling of tasks and input fields related to task management, search, and filtering.
- To handle task-related information such as name, priority, and deadline, three input handlers are implemented to update their respective state variables.
- The addTask function is responsible for both validating and adding tasks, while the handleEditTask function facilitates task editing and removal.
- Additionally, the handleDeleteTask function removes tasks when necessary, whereas the markDone function marks tasks as completed and moves them to the completedTasks section.
- To further enhance user experience, filteredTasks effectively filters upcoming tasks based on user-defined criteria such as searching and filtering by priority.
Steps to create the Next JS Application:
Step 1: Create a new Next.js project using the following command
npx create-next-app task-management-app
Step 2: Change to the project directory:
cd task-management-app
Project Structure:
The updated dependencies in package.json file will look like :
"dependencies": {
"next": "^13.0.6",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
Example: In this example, we will create the Task Management App Using Next Js.
Javascript
//index.js import { useState } from "react" ; import Head from "next/head" ; import styles from "../styles/Home.module.css" ; export default function TaskScheduler() { const [tasks, setTasks] = useState([]); const [completedTasks, setCompletedTasks] = useState([]); const [taskName, setTaskName] = useState( "" ); const [taskPriority, setTaskPriority] = useState( "Top" ); const [taskDeadline, setTaskDeadline] = useState( "" ); const [searchKeyword, setSearchKeyword] = useState( "" ); const [filterPriority, setFilterPriority] = useState( "" ); const handleTaskNameChange = (e) => { setTaskName(e.target.value); }; const handleTaskPriorityChange = (e) => { setTaskPriority(e.target.value); }; const handleTaskDeadlineChange = (e) => { setTaskDeadline(e.target.value); }; const addTask = () => { if (taskName.trim() === "" || taskDeadline === "" ) { alert( "Please enter a task and select a valid deadline." ); return ; } const selectedDate = new Date(taskDeadline); const currentDate = new Date(); if (selectedDate <= currentDate) { alert( "Please select a future date for the deadline." ); return ; } const newTask = { id: tasks.length + 1, task: taskName, priority: taskPriority, deadline: taskDeadline, done: false , }; setTasks([...tasks, newTask]); 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 Management - w3wiki.net</title> </Head> <header className={styles.taskHeader}> <h1>Task Management</h1> </header> <main> <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" >Top Priority</option> <option value= "Middle" >Middle Priority</option> <option value= "Low" >Less Priority</option> </select> <input type= "date" className={styles.taskDeadlineInput} value={taskDeadline} onChange={handleTaskDeadlineChange} /> <button className={styles.addTaskButton} onClick={addTask}> Add Task </button> </div> <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 Priorities</option> <option value= "Top" >Top Priority</option> <option value= "Middle" >Middle Priority</option> <option value= "Low" >Less Priority</option> </select> </div> <h2 className={styles.heading}>Upcoming Tasks</h2> <div className={styles.taskList}> <table className={styles.taskTable}> <thead> <tr> <th>Task Name</th> <th>Priority</th> <th>Deadline</th> <th>Action</th> </tr> </thead> <tbody> {filteredTasks.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) } > Mark 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> <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> </main> </div> ); } |
CSS
/* global.css */ .App { font-family : 'Arial' , sans-serif ; margin : 30px auto ; padding : 20px ; max-width : 800px ; background-color : white ; box-shadow: 0 2px 16px rgba( 0 , 0 , 0 , 0.1 ); border-radius: 15px ; } .taskHeader { text-align : center ; background-color : #007bff ; color : white ; 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 #ccc ; border-radius: 4px ; flex-grow: 1 ; font-size : 16px ; } .taskPrioritySelect { cursor : pointer ; background-color : #f0f0f0 ; } .addTaskButton { background-color : #007bff ; color : white ; border : none ; cursor : pointer ; transition: background-color 0.3 s; } .addTaskButton:hover { background-color : #0056b3 ; } .searchFilter { display : flex; justify- content : space-between; align-items: center ; } .searchInput, .filterPrioritySelect { padding : 10px ; border : 1px solid #ccc ; border-radius: 4px ; flex-grow: 1 ; font-size : 16px ; } .taskTable { width : 100% ; border-collapse : collapse ; background-color : white ; } .taskTable th, .taskTable td { padding : 10px ; text-align : left ; } .taskTable th { background-color : #007bff ; color : white ; } .taskTable tbody tr:nth-child(even) { background-color : #f5f5f5 ; } .completedTable { width : 100% ; border-collapse : collapse ; background-color : white ; } .completedTable th, .completedTable td { padding : 10px ; text-align : left ; } .completedTable th { background-color : #007bff ; color : white ; } .completedTable tbody tr:nth-child(even) { background-color : #f5f5f5 ; } .deleteTaskButton { margin-right : 5px ; cursor : pointer ; padding : 12px ; background : crimson; border-radius: 10px ; border : none ; color : white ; } .markDoneButton, .editTaskButton { margin-right : 5px ; cursor : pointer ; padding : 12px ; background : #007bff ; border-radius: 10px ; border : none ; color : white ; } @media ( max-width : 600px ) { .taskForm { flex- direction : column; } .searchFilter { flex- direction : column; } } |
Steps to run the application:
Step 1: Run this command to start the application:
npm run dev
Step 2: To run the next.js application use the following command and then go to this URL:
http://localhost:3000
Output: