Build a Simple Next.js Interactive Web-Based Task Scheduler

Written by

in

In today’s fast-paced world, staying organized is crucial. Whether you’re juggling work projects, personal errands, or creative endeavors, a well-structured task scheduler can be a game-changer. This tutorial will guide you through building a simple, yet functional, interactive task scheduler using Next.js. We’ll cover everything from setting up the project to implementing core features like adding, editing, deleting, and marking tasks as complete. By the end, you’ll have a practical tool to manage your daily activities and a solid understanding of Next.js fundamentals.

Why Build a Task Scheduler?

Task schedulers offer several benefits:

  • Enhanced Productivity: By breaking down large goals into smaller, manageable tasks, you can focus your energy more effectively.
  • Improved Organization: A clear overview of your commitments reduces stress and helps you prioritize.
  • Better Time Management: Scheduling tasks allows you to allocate time for each activity, preventing procrastination and ensuring you meet deadlines.
  • Increased Accountability: Tracking your progress and seeing completed tasks provides a sense of accomplishment and motivates you to keep going.

Building a task scheduler is also an excellent learning experience. You’ll gain practical experience with Next.js, including its routing, state management, and component-based architecture. This project will solidify your understanding of front-end development principles and prepare you for more complex web applications.

Prerequisites

Before we begin, ensure you have the following installed on your system:

  • Node.js and npm (or yarn): These are essential for managing project dependencies and running the development server.
  • A code editor: Visual Studio Code, Sublime Text, or any other editor you prefer.
  • Basic knowledge of HTML, CSS, and JavaScript: Familiarity with these languages will help you understand the code.

Setting Up Your Next.js Project

Let’s start by creating a new Next.js project. Open your terminal and run the following command:

npx create-next-app task-scheduler

This command will create a new directory named “task-scheduler” and set up a basic Next.js project structure. Navigate into the project directory:

cd task-scheduler

Next, start the development server:

npm run dev

or

yarn dev

Open your browser and go to http://localhost:3000. You should see the default Next.js welcome page.

Project Structure Overview

Before diving into the code, let’s understand the project structure:

  • pages/: This directory contains your application’s pages. Each file in this directory represents a route. For our task scheduler, we’ll primarily work with the “index.js” file, which will serve as our main page.
  • components/: This directory will hold reusable UI components, such as task items and input fields.
  • styles/: This directory is for your CSS stylesheets.
  • public/: This directory stores static assets like images and fonts.

Creating the Task Input Component

Let’s create a component to handle the task input. Create a new file named “TaskInput.js” inside the “components” directory. Add the following code:

// components/TaskInput.js
import { useState } from 'react';

function TaskInput({ addTask }) {
  const [taskText, setTaskText] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (taskText.trim() !== '') {
      addTask(taskText);
      setTaskText('');
    }
  };

  return (
    <form onSubmit={handleSubmit} className="mb-4">
      <input
        type="text"
        value={taskText}
        onChange={(e) => setTaskText(e.target.value)}
        placeholder="Add a task..."
        className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
      />
      <button
        type="submit"
        className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline mt-2"
      >
        Add Task
      </button>
    </form>
  );
}

export default TaskInput;

This component uses the `useState` hook to manage the input field’s value. The `handleSubmit` function is called when the form is submitted. It prevents the default form submission behavior, calls the `addTask` function (passed as a prop), and clears the input field. The component also includes basic styling using Tailwind CSS classes for a cleaner look.

Creating the Task Item Component

Now, let’s create a component to display each task. Create a new file named “TaskItem.js” inside the “components” directory. Add the following code:

// components/TaskItem.js
function TaskItem({ task, onDelete, onToggleComplete }) {
  return (
    <div className="flex items-center justify-between py-2 border-b border-gray-200">
      <div className="flex items-center">
        <input
          type="checkbox"
          checked={task.completed}
          onChange={() => onToggleComplete(task.id)}
          className="mr-2"
        />
        <span className={task.completed ? 'line-through text-gray-400' : ''}>
          {task.text}
        </span>
      </div>
      <button
        onClick={() => onDelete(task.id)}
        className="text-red-500 hover:text-red-700 font-bold"
      >
        Delete
      </button>
    </div>
  );
}

export default TaskItem;

This component receives a `task` object as a prop, which includes the task’s text, completion status, and ID. It renders a checkbox to mark the task as complete, the task text, and a delete button. The `onDelete` and `onToggleComplete` functions are passed as props to handle deleting and toggling task completion, respectively. The component uses conditional styling to apply a line-through effect to completed tasks.

Building the Main Page (index.js)

Now, let’s modify the “pages/index.js” file to integrate the components and implement the core task management logic. Replace the existing code with the following:

// pages/index.js
import { useState } from 'react';
import TaskInput from '../components/TaskInput';
import TaskItem from '../components/TaskItem';

function HomePage() {
  const [tasks, setTasks] = useState([]);

  const addTask = (text) => {
    const newTask = {
      id: Date.now(), // Generate a unique ID
      text,
      completed: false,
    };
    setTasks([...tasks, newTask]);
  };

  const deleteTask = (id) => {
    setTasks(tasks.filter((task) => task.id !== id));
  };

  const toggleComplete = (id) => {
    setTasks(
      tasks.map((task) =>
        task.id === id ? { ...task, completed: !task.completed } : task
      )
    );
  };

  return (
    <div className="container mx-auto p-4">
      <h1 className="text-2xl font-bold mb-4">Task Scheduler</h1>
      <TaskInput addTask={addTask} />
      <div>
        {tasks.map((task) => (
          <TaskItem
            key={task.id}
            task={task}
            onDelete={deleteTask}
            onToggleComplete={toggleComplete}
          />
        ))}
      </div>
    </div>
  );
}

export default HomePage;

This code imports the `TaskInput` and `TaskItem` components and uses the `useState` hook to manage the list of tasks. The `addTask` function adds a new task to the list, the `deleteTask` function removes a task, and the `toggleComplete` function toggles a task’s completion status. The component renders the `TaskInput` component and then maps over the `tasks` array to render a `TaskItem` component for each task. The `key` prop is essential for React to efficiently update the list.

Adding Basic Styling (Optional – Using Tailwind CSS)

For a cleaner look, let’s add some basic styling using Tailwind CSS. If you haven’t already, install Tailwind CSS in your project:

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Then, configure Tailwind CSS by adding the paths to all of your template files in your `tailwind.config.js` file:

// tailwind.config.js
module.exports = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx}',
    './components/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

And add the Tailwind directives to your CSS file (usually in `styles/globals.css`):

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

Now, you can use Tailwind CSS classes in your components. The provided code snippets already include Tailwind CSS classes. You can customize the styling further by modifying these classes or adding new ones.

Testing Your Task Scheduler

Save all the files and go back to your browser. You should now be able to:

  • Enter tasks in the input field and add them to the list.
  • See each task displayed with a checkbox and a delete button.
  • Mark tasks as complete by clicking the checkbox.
  • Delete tasks by clicking the delete button.

Congratulations, you’ve built a functional task scheduler!

Common Mistakes and How to Fix Them

Here are some common mistakes and how to avoid them:

  • Incorrect Component Imports: Make sure you import components correctly using the right file paths. Double-check your import statements.
  • Missing Keys in Lists: When rendering lists in React, always provide a unique `key` prop to each element. This helps React efficiently update the list.
  • Incorrect State Updates: When updating state, make sure you’re using the correct methods (e.g., `setTasks` with the spread operator for adding tasks). Avoid directly mutating the state.
  • Incorrect Event Handling: Ensure you’re passing the correct event handlers to your components (e.g., `addTask`, `deleteTask`, `toggleComplete`).
  • Not Using `trim()`: Ensure that you trim the input text to avoid adding empty tasks.

Enhancements and Next Steps

This is a basic task scheduler, but you can enhance it in many ways:

  • Local Storage: Persist tasks in local storage so they are saved even when the browser is closed.
  • Edit Task Functionality: Add the ability to edit existing tasks.
  • Task Categories/Tags: Implement categories or tags to organize tasks.
  • Due Dates/Reminders: Add due dates and reminders for tasks.
  • Drag-and-Drop Reordering: Allow users to reorder tasks by dragging and dropping them.
  • More Advanced Styling: Customize the appearance of the task scheduler with more advanced styling techniques.
  • Backend Integration: Connect to a backend (e.g., Firebase, Supabase) to store and manage tasks in a database.

Summary / Key Takeaways

In this tutorial, we’ve successfully built a simple, interactive task scheduler using Next.js. We’ve covered the essential concepts of component creation, state management, event handling, and basic styling. This project provides a solid foundation for understanding Next.js and building more complex web applications. Remember to break down complex problems into smaller, manageable components. Practice regularly and experiment with different features to enhance your skills. The key to mastering any technology is consistent practice and a willingness to explore. By continually building and refining your projects, you’ll become proficient in Next.js and other web development technologies.

FAQ

  1. How can I deploy this task scheduler?

    You can deploy your Next.js application to platforms like Vercel, Netlify, or AWS. These platforms provide easy deployment workflows and handle the server-side rendering and build process for you.

  2. How do I add styling to my task scheduler?

    You can use CSS, CSS-in-JS libraries (like styled-components or Emotion), or CSS frameworks like Tailwind CSS (as shown in this tutorial) to style your application. Choose the approach that best fits your needs and preferences.

  3. How can I handle more complex state management?

    For more complex applications, consider using a state management library like Redux, Zustand, or Recoil. These libraries provide more advanced features for managing application state.

  4. Can I use this task scheduler on mobile devices?

    Yes, the task scheduler is responsive and can be used on mobile devices. You can further optimize the user experience by adding responsive design techniques (e.g., media queries) and mobile-specific styling.

The journey of learning web development is a continuous one. Every project you undertake, every line of code you write, adds to your skillset. Continue to explore, experiment, and embrace the challenges that come your way, and you’ll find yourself not just building applications, but crafting solutions. This simple task scheduler, while modest in its scope, is a testament to the power of breaking down complex ideas into manageable steps, and the satisfaction of bringing a functional application to life.