Build a Next.js Interactive Web-Based Simple Age Calculator

Written by

in

In this tutorial, we’ll embark on a journey to build a simple yet functional age calculator using Next.js. This project is perfect for beginners and intermediate developers looking to hone their skills in Next.js, React, and JavaScript. We’ll cover everything from setting up your development environment to deploying your application. By the end, you’ll have a fully working age calculator and a solid understanding of how to build interactive web applications with Next.js.

Why Build an Age Calculator?

Age calculators might seem simple, but they serve as an excellent learning tool. They introduce you to:

  • Date and Time Manipulation: Working with dates and times is a fundamental skill in many applications.
  • User Input and Validation: Handling user input and ensuring its validity is crucial for a good user experience.
  • State Management: Understanding how to manage and update the application’s state based on user input.
  • Basic UI Design: Creating a clean and intuitive user interface.

Furthermore, building this project gives you a practical application of Next.js features like server-side rendering (SSR), which can improve your application’s performance and SEO.

Prerequisites

Before we dive in, make sure you have the following:

  • Node.js and npm (or yarn): Installed on your computer.
  • A Code Editor: Such as Visual Studio Code, Sublime Text, or Atom.
  • Basic Knowledge of JavaScript: Understanding of variables, functions, and DOM manipulation is helpful.
  • Basic Understanding of React: Familiarity with components, JSX, and state management.

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 age-calculator
cd age-calculator

This command creates a new Next.js project named “age-calculator” and navigates you into the project directory. You can choose to use TypeScript, ESLint, Tailwind CSS, and other configurations as prompted during the setup. If you’re unsure, you can safely choose the defaults for now.

Project Structure Overview

Your project directory should look something like this:

age-calculator/
├── node_modules/
├── pages/
│   ├── _app.js
│   ├── index.js
│   └── api/
│       └── hello.js
├── public/
├── .gitignore
├── next.config.js
├── package-lock.json
├── package.json
└── README.md
  • pages/: This directory contains your application’s pages. Each file in this directory represents a route. For example, pages/index.js will be the home page (/).
  • public/: This directory is for static assets like images, fonts, and other files.
  • package.json: Contains project metadata and dependencies.
  • next.config.js: Configuration file for Next.js.

Building the User Interface (UI)

Let’s create the UI for our age calculator. We’ll modify the pages/index.js file. Replace the existing content with the following:

import { useState } from 'react';

export default function Home() {
  const [birthDate, setBirthDate] = useState('');
  const [age, setAge] = useState(null);

  const calculateAge = () => {
    if (!birthDate) {
      setAge('Please enter a birthdate.');
      return;
    }

    const birthDateObj = new Date(birthDate);
    const today = new Date();
    let ageYears = today.getFullYear() - birthDateObj.getFullYear();
    let ageMonths = today.getMonth() - birthDateObj.getMonth();
    let ageDays = today.getDate() - birthDateObj.getDate();

    if (ageMonths < 0 || (ageMonths === 0 && ageDays < 0)) {
      ageYears--;
      ageMonths += 12;
      if (ageDays  setBirthDate(e.target.value)}
          style={{ marginLeft: '10px', padding: '5px', borderRadius: '5px', border: '1px solid #ccc' }}
        />
      </div>
      <button onClick={calculateAge} style={{ padding: '10px 20px', backgroundColor: '#4CAF50', color: 'white', border: 'none', borderRadius: '5px', cursor: 'pointer' }}>
        Calculate Age
      </button>
      {age && (
        <div style={{ marginTop: '20px', fontWeight: 'bold' }}>Your age: {age}</div>
      )}
    </div>
  );
}

Let’s break down the code:

  • Importing useState: We import the useState hook from React to manage the state of the birth date and the calculated age.
  • State Variables: We declare two state variables: birthDate (to store the user’s input) and age (to store the calculated age).
  • Input Field: We create an input field of type “date” for the user to enter their birthdate. The onChange event updates the birthDate state.
  • Calculate Age Button: When the button is clicked, the calculateAge function is called.
  • calculateAge Function: This function does the following:
    • Validates that a birthdate is entered.
    • Calculates the age in years, months, and days.
    • Updates the age state with the calculated result.
  • Displaying the Age: The calculated age is displayed below the button, conditionally rendered only if the age state has a value.

Styling the UI (Optional)

The code above includes basic inline styles for simplicity. However, for a more structured approach, you can use CSS modules, styled-components, or a CSS framework like Tailwind CSS. Let’s quickly see how you might use Tailwind CSS, assuming you’ve set it up during project initialization (or later).

First, install Tailwind CSS and its dependencies:

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

Then, modify your tailwind.config.js file (created when you ran the init command) to include the paths to all of your template files (including pages and components):


/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./app/**/*.{js,ts,jsx,tsx,mdx",
    "./pages/**/*.{js,ts,jsx,tsx,mdx",
    "./components/**/*.{js,ts,jsx,tsx,mdx}",

    // Or if using `src` directory:
    "./src/**/*.{js,ts,jsx,tsx,mdx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Finally, update your pages/_app.js file to include the Tailwind directives:

import '../styles/globals.css'

export default function App({ Component, pageProps }) {
  return <Component {...pageProps} />
}

And in your styles/globals.css file, add the Tailwind directives:

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

Now, you can apply Tailwind classes to your components. For example, to style the button and input field:

<button onClick={calculateAge} className="bg-green-500 hover:bg-green-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline">
  Calculate Age
</button>

<input
  type="date"
  id="birthDate"
  value={birthDate}
  onChange={(e) => setBirthDate(e.target.value)}
  className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
/>

Replace the inline styles with these Tailwind classes and run your app. You’ll have a more visually appealing and easily customizable UI.

Implementing the Age Calculation Logic

The core of our application is the calculateAge function. Let’s review it in more detail:

const calculateAge = () => {
  if (!birthDate) {
    setAge('Please enter a birthdate.');
    return;
  }

  const birthDateObj = new Date(birthDate);
  const today = new Date();
  let ageYears = today.getFullYear() - birthDateObj.getFullYear();
  let ageMonths = today.getMonth() - birthDateObj.getMonth();
  let ageDays = today.getDate() - birthDateObj.getDate();

  if (ageMonths < 0 || (ageMonths === 0 && ageDays < 0)) {
    ageYears--;
    ageMonths += 12;
    if (ageDays < 0) {
      const lastMonth = new Date(today.getFullYear(), today.getMonth() - 1, 0);
      ageDays += lastMonth.getDate();
      ageMonths--;
    }
  }

  setAge(`${ageYears} years, ${ageMonths} months, and ${ageDays} days`);
};

Here’s a breakdown:

  • Input Validation: The function first checks if a birthdate is entered. If not, it sets the age state to an error message and returns. This is crucial for preventing unexpected behavior.
  • Date Objects: It creates two Date objects: birthDateObj (from the user’s input) and today (for the current date).
  • Calculating Years, Months, and Days: It calculates the difference in years, months, and days.
  • Adjusting for Incomplete Years/Months: The if statement handles cases where the birthdate hasn’t yet occurred this year or this month. It correctly adjusts the age calculations. The nested if handles day differences.
  • Setting the Age: Finally, it sets the age state with the formatted age string.

Running Your Application

To run your application, open your terminal and navigate to your project directory. Then, run the following command:

npm run dev
# or
yarn dev

This will start the development server. Open your web browser and go to the address provided (usually http://localhost:3000). You should see your age calculator! Enter your birthdate and click the button to see your age calculated.

Handling Edge Cases and Improving the User Experience

While our age calculator works, we can improve it further. Let’s address some potential issues and enhance the user experience:

  • Error Handling: Currently, the error message is basic. You could provide more specific error messages (e.g., “Invalid date format”) or use a different UI element to display errors.
  • Input Validation (Client-Side): You can add client-side validation to the input field to ensure the user enters a valid date. This can prevent unnecessary requests to the server and improve the user experience. You can use the HTML5 date input’s built-in validation or a JavaScript library like date-fns.
  • Accessibility: Ensure your application is accessible to users with disabilities. Use semantic HTML, provide alt text for images, and ensure sufficient color contrast.
  • Responsiveness: Make sure your application looks good on different screen sizes. Use responsive design techniques (e.g., media queries or a responsive CSS framework).
  • Clear Input Field: Add a clear button to remove the date from the input field.

Here’s an example of adding client-side validation using the HTML5 date input’s built-in validation. We can add a check to make sure the user enters a date prior to today’s date:


const calculateAge = () => {
  if (!birthDate) {
    setAge('Please enter a birthdate.');
    return;
  }

  const birthDateObj = new Date(birthDate);
  const today = new Date();

  if (birthDateObj > today) {
      setAge('Birthdate cannot be in the future.');
      return;
  }

  // ... rest of the calculation logic ...
};

This example adds a simple check to ensure the birthdate is not in the future. You can also add more advanced validation to validate the date format.

Deployment

Once you’re satisfied with your age calculator, you’ll want to deploy it so others can use it. Next.js makes deployment straightforward. Here are a few popular options:

  • Vercel: Vercel is the platform created by the team behind Next.js. It offers seamless deployment and is highly recommended. Simply push your code to a Git repository (e.g., GitHub, GitLab, Bitbucket), and Vercel will automatically build and deploy your application.
  • Netlify: Netlify is another excellent platform for deploying static sites and web applications. It also supports automatic deployments from Git repositories.
  • Other Platforms: You can deploy to other platforms like AWS, Google Cloud, or Azure. These options often require more configuration.

Let’s use Vercel as an example:

  1. Sign Up/Log In: Create an account on Vercel (if you don’t already have one) and log in.
  2. Connect Your Git Repository: On the Vercel dashboard, click “Import Project” and connect your Git repository (e.g., GitHub).
  3. Configure Deployment (If Necessary): Vercel will usually detect your Next.js project automatically. You might need to specify the build command (npm run build or yarn build) and the output directory (usually .next). In most cases, the defaults will work.
  4. Deploy: Click “Deploy.” Vercel will build and deploy your application.
  5. Access Your Application: Once the deployment is complete, Vercel will provide a URL where you can access your age calculator.

For Netlify, the process is similar. You connect your Git repository, configure the build settings (if needed), and deploy.

Common Mistakes and Troubleshooting

Here are some common mistakes and how to fix them:

  • Incorrect Date Format: Make sure the date format in your code matches the format expected by the Date object (YYYY-MM-DD). If you have issues, validate the date format on the front end using a library like date-fns, or handle the date parsing more robustly.
  • Timezone Issues: The Date object in JavaScript is sensitive to timezones. If the birthdate is entered in a different timezone than the user’s, you might get incorrect results. Consider using a library like Moment.js or date-fns to handle timezone conversions if needed. Using the UTC version of the date functions can help avoid timezone issues.
  • State Not Updating: Double-check that you’re correctly using the useState hook to update the state variables. Make sure you’re calling the setter functions (e.g., setBirthDate, setAge) correctly.
  • UI Not Rendering: Inspect your browser’s console for any errors. Make sure your JSX is valid and that you’re importing all necessary components.
  • Build Errors: If you encounter build errors during deployment, carefully review the error messages. They often provide clues about the problem. Check your dependencies, your Next.js configuration, and your code for any syntax errors or logical issues.

Key Takeaways

  • Next.js Fundamentals: You’ve learned how to set up a Next.js project, create pages, and handle user input.
  • React State Management: You’ve used the useState hook to manage the application’s state.
  • Date and Time Manipulation: You’ve worked with the Date object to calculate the age.
  • UI Design and Styling: You’ve created a basic UI and explored styling options (inline styles and Tailwind CSS).
  • Deployment: You’ve learned how to deploy your application to a platform like Vercel.

Frequently Asked Questions (FAQ)

  1. Can I use this age calculator on mobile devices? Yes, the age calculator is built with HTML and JavaScript, so it should work on any device with a web browser. However, you may need to adjust the UI to be responsive for the best user experience on mobile devices.
  2. How can I customize the appearance of the age calculator? You can customize the appearance by modifying the CSS styles. You can use inline styles, CSS modules, styled-components, or a CSS framework like Tailwind CSS.
  3. How do I handle time zones? The basic age calculation in this tutorial does not explicitly handle time zones. For more accurate results, especially if you expect users from different time zones, consider using a library like Moment.js or date-fns to handle timezone conversions.
  4. What other features can I add? You could add features like a date of death calculator, a countdown to a specific date, or the ability to save birthdates. You could also add more advanced UI elements, such as a calendar picker.
  5. Is this project suitable for production use? While this age calculator is a great learning tool, it might require additional features and testing before being used in a production environment. Consider adding more robust error handling, client-side and server-side validation, and thorough testing.

Building this age calculator provides a solid foundation for understanding Next.js and web development principles. As you experiment with different features and styling techniques, you’ll gain even deeper insights into the framework. The ability to create interactive web applications is a valuable skill in today’s world, and this project equips you with the fundamental knowledge to get started. By continually building and refining your skills, you’ll be well on your way to becoming a proficient Next.js developer, capable of tackling more complex projects with confidence. Embrace the learning process, and enjoy the journey of creating web applications that solve problems and provide value to users.