DEV Community

Bukunmi Odugbesan
Bukunmi Odugbesan

Posted on

Coding Challenge Practice - Question 7

Today's Question

Create a React app that helps employees validate and update their existing information through a survey form.

Solution

The boilerplate code provided:

import React from "react";

function EmployeeValidationForm() {
  return (
    <div className="layout-column align-items-center mt-20 ">
      <div className="layout-column align-items-start mb-10 w-50" data-testid="input-name">
        <input
          className="w-100"
          type="text"
          name="name"
          value="User"
          placeholder="Name"
          data-testid="input-name-test"
        />
        {/* <p className="error mt-2">
          Name must be at least 4 characters long and only contain letters and spaces
        </p> */}
      </div>
      <div className="layout-column align-items-start mb-10 w-50" data-testid="input-email">
        <input
          className="w-100"
          type="text"
          name="email"
          value="user@email.com"
          placeholder="Email"
        />
        {/* <p className="error mt-2">Email must be a valid email address</p> */}
      </div>
      <div className="layout-column align-items-start mb-10 w-50" data-testid="input-employee-id">
        <input
          className="w-100"
          type="text"
          name="employeeId"
          value={123}
          placeholder="Employee ID"
        />
        {/* <p className="error mt-2">Employee ID must be exactly 6 digits</p> */}
      </div>
      <div className="layout-column align-items-start mb-10 w-50" data-testid="input-joining-date">
        <input
          className="w-100"
          type="date"
          name="joiningDate"
          value="2023-12-04"
          placeholder="Joining Date"
        />
        <p className="error mt-2">Joining Date cannot be in the future</p>
      </div>
      <button data-testid="submit-btn" type="submit">
        Submit
      </button>
    </div>
  );
}

export default EmployeeValidationForm;

Enter fullscreen mode Exit fullscreen mode

There are 4 form fields, each with a criterion to be met for the input field to be valid. First, the state variables for each of the input fields are created

const [name, setName] = useState("");
const [email, setEmail] = useState("");
const [employeeId, setEmployeeId] = useState("");
const [joiningDate, setJoiningDate] = useState("");

Enter fullscreen mode Exit fullscreen mode

The state variable for validating the form, i.e if all the criteria for submission have been met, will also be created. In addition, the state variable for the error messages when the criterion for any of the fields is not met will be created.

const [errors, setErrors] = useState({
    name: "",
    email: "",
    employeeId: "",
    joiningDate: ""
  });
const [isValid, setIsValid] = useState(false);
Enter fullscreen mode Exit fullscreen mode

Next, we will create the function that validates if the criteria for each of the form fields have been met, which is required for submission.

  const validateForm = () => {
    // Name validation: at least 4 characters, only letters and spaces
    const nameRegex = /^[a-zA-Z\s]{4,}$/;
    const isNameValid = nameRegex.test(name);

    // Email validation
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    const isEmailValid = emailRegex.test(email);

    // Employee ID validation: exactly 6 digits
    const idRegex = /^\d{6}$/;
    const isEmployeeIdValid = idRegex.test(employeeId);

    // Joining date validation: not in the future
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const selectedDate = new Date(joiningDate);
    const isJoiningDateValid = joiningDate && selectedDate <= today;

    setErrors({
      name: isNameValid ? "" : "Name must be at least 4 characters long and only contain letters and spaces",
      email: isEmailValid ? "" : "Email must be a valid email address",
      employeeId: isEmployeeIdValid ? "" : "Employee ID must be exactly 6 digits",
      joiningDate: isJoiningDateValid ? "" : "Joining Date cannot be in the future"
    });

    setIsValid(isNameValid && isEmailValid && isEmployeeIdValid && isJoiningDateValid);
  };
Enter fullscreen mode Exit fullscreen mode

For each of the first 3 input fields (name, email, employee id), the fields can be validated to determine if the criteria for submission are met by using regex. A regex, which is short for regular expression, is a pattern used to validate character combinations in strings. For example, if an input field indicates that only numbers are allowed, or there must be a mixture of uppercase and lowercase letters, a regex is what we use to validate if all that is listed is present. In this solution, variables which contain the regular expressions were created to validate if each field meets its specified criteria.

For the joining date field, the current date in which the form is being completed is obtained, and it's checked against the date which is selected on the form.

After each of the validation variables has been completed, we set the error messages to display as appropriate.

Finally, the error messages are to be displayed immediately after the form is loaded. To achieve that, the function that validates the form is called on page load, thereby displaying the error messages because the fields are empty, which means each criterion hasn't been met.

useEffect(() => {
    validateForm();
  }, [name, email, employeeId, joiningDate]);
Enter fullscreen mode Exit fullscreen mode

The completed solution looks like this:

import React, { useState, useEffect } from "react";

function EmployeeValidationForm() {
  const [name, setName] = useState("");
  const [email, setEmail] = useState("");
  const [employeeId, setEmployeeId] = useState("");
  const [joiningDate, setJoiningDate] = useState("");
  const [errors, setErrors] = useState({
    name: "",
    email: "",
    employeeId: "",
    joiningDate: ""
  });
  const [isValid, setIsValid] = useState(false);

  useEffect(() => {
    validateForm();
  }, [name, email, employeeId, joiningDate]);

  const validateForm = () => {
    // Name validation: at least 4 characters, only letters and spaces
    const nameRegex = /^[a-zA-Z\s]{4,}$/;
    const isNameValid = nameRegex.test(name);

    // Email validation
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    const isEmailValid = emailRegex.test(email);

    // Employee ID validation: exactly 6 digits
    const idRegex = /^\d{6}$/;
    const isEmployeeIdValid = idRegex.test(employeeId);

    // Joining date validation: not in the future
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const selectedDate = new Date(joiningDate);
    const isJoiningDateValid = joiningDate && selectedDate <= today;

    setErrors({
      name: isNameValid ? "" : "Name must be at least 4 characters long and only contain letters and spaces",
      email: isEmailValid ? "" : "Email must be a valid email address",
      employeeId: isEmployeeIdValid ? "" : "Employee ID must be exactly 6 digits",
      joiningDate: isJoiningDateValid ? "" : "Joining Date cannot be in the future"
    });

    setIsValid(isNameValid && isEmailValid && isEmployeeIdValid && isJoiningDateValid);
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    if (!isValid) return;

    // Form submission logic here
    console.log("Form submitted:", { name, email, employeeId, joiningDate });

    // Reset form
    setName("");
    setEmail("");
    setEmployeeId("");
    setJoiningDate("");
  };

  return (
    <div className="layout-column align-items-center mt-20">
      <form onSubmit={handleSubmit} className="layout-column align-items-center">
        <div className="layout-column align-items-start mb-10 w-50" data-testid="input-name">
          <input
            className="w-100"
            type="text"
            name="name"
            value={name}
            onChange={(e) => setName(e.target.value)}
            placeholder="Name"
            data-testid="input-name-test"
          />
          {errors.name && <p className="error mt-2" data-testid="name-error">{errors.name}</p>}
        </div>
        <div className="layout-column align-items-start mb-10 w-50" data-testid="input-email">
          <input
            className="w-100"
            type="text"
            name="email"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
            placeholder="Email"
            data-testid="input-email-test"
          />
          {errors.email && <p className="error mt-2" data-testid="email-error">{errors.email}</p>}
        </div>
        <div className="layout-column align-items-start mb-10 w-50" data-testid="input-employee-id">
          <input
            className="w-100"
            type="text"
            name="employeeId"
            value={employeeId}
            onChange={(e) => setEmployeeId(e.target.value)}
            placeholder="Employee ID"
            data-testid="input-employee-id-test"
          />
          {errors.employeeId && <p className="error mt-2" data-testid="employee-id-error">{errors.employeeId}</p>}
        </div>
        <div className="layout-column align-items-start mb-10 w-50" data-testid="input-joining-date">
          <input
            className="w-100"
            type="date"
            name="joiningDate"
            value={joiningDate}
            onChange={(e) => setJoiningDate(e.target.value)}
            placeholder="Joining Date"
            data-testid="input-joining-date-test"
          />
          {errors.joiningDate && <p className="error mt-2" data-testid="joining-date-error">{errors.joiningDate}</p>}
        </div>
        <button 
          data-testid="submit-btn" 
          type="submit" 
          disabled={!isValid}
        >
          Submit
        </button>
      </form>
    </div>
  );
}

export default EmployeeValidationForm;
Enter fullscreen mode Exit fullscreen mode

That's all folks!

Top comments (0)