Thursday, April 11, 2024
HomeReact JsBuilding a Credit Card Form in React.js: A Complete Guide

Building a Credit Card Form in React.js: A Complete Guide

Hey everyone Today, we’re diving into the world of React.js to build something really cool — a credit card form. Building a user-friendly credit card form is essential for many web applications, especially those dealing with e-commerce or subscription-based services. In this vlog, we’ll be using Formik, Yup, and Material UI to create a seamless experience for our users. So let’s jump right in!

Section 1: Setting Up the Project

To kick things off, let’s set up our project. Instead of the traditional Create React App, we’ll be using Vite, a blazing-fast build tool for modern web development.

If you’re not familiar with Vite, you can learn more about it on their website here. After you setup our project using Vite.

Now that we have our project set up, let’s install the dependencies we need:

npm install formik yup @material-ui @material-ui/icons

Section 2: Creating the Credit Card Form

Now that our project is set up, let’s start building our credit card form.
Setting Up Formik and Yup
Firstly, we’ll set up Formik and Yup, two powerful libraries for handling form state and validation in React. Formik simplifies the process of managing form data and submissions, while Yup provides a schema-based validation system. Import Statements: Import necessary libraries and components at the beginning of your file.
import React from "react";
import { useFormik } from "formik";
import * as Yup from "yup";
import {
  Box,
  Button,
  FormControl,
  FormControlLabel,
  Grid,
  IconButton,
  InputAdornment,
  InputLabel,
  Radio,
  RadioGroup,
  Typography,
  TextField as Input,
} from "@mui/material";
import { CalendarToday, CreditCard } from "@mui/icons-material";
Defining the Validation Schema

To ensure data integrity and accuracy, we’ll define a validation schema using Yup. This schema will specify the structure and validation rules for each form field, such as card number format, expiry date validity, and CVV length.

export const paySchema = yup.object({
    cardNumber: yup
      .string()
      // .matches(/^[0-9]{16}$/, "Invalid card number")
      .required("Card number is required"),
    // expiryDate: yup.string().required("Expiry date is required"),
    expiryDate: yup
      .string()
      .required("Expiry date is required")
      .test("valid-month", "Invalid month", function (value) {
        if (!value) {
          return false;
        }
  
        const [month] = value.split("/").map((item) => parseInt(item, 10));
  
        return month >= 1 && month <= 12;
      })
      .test(
        "is-future-date",
        "Expiry date must be in the future",
        function (value) {
          if (!value) {
            return false;
          }
  
          const currentDate = new Date();
          const [month, year] = value
            .split("/")
            .map((item) => parseInt(item, 10));
  
          // Adding 1 to the month because JavaScript months are zero-indexed
          const expiryDate = new Date(year + 2000, month, 1);
  
          return expiryDate > currentDate;
        }
      ),
    name: yup.string().required("Name is required"),
    cvv: yup
      .string()
      .matches(/^[0-9]{3,4}$/, "Invalid CVV")
      .required("CVV is required"),
  });
Building the Credit Card Form

With the groundwork laid, we’ll proceed to create the credit card form using Formik. We’ll define the form structure and include input fields for cardholder name, card number, expiry date, and CVV

const PaymentForm = () => {
  // Formik hook and form submission logic
  const formik = useFormik({
    initialValues: {
      name: "",
      cardNumber: "",
      expiryDate: "",
      cvv: "",
    },
    validationSchema: paySchema,
    onSubmit: async (values) => {
      // Implement payment logic here
      console.log("Processing payment...", values);
    },
  });

  // Formatting functions
 
export const formatCardNumber = (value) => {
    return value
      .replace(/\D/g, "")
      .replace(/(.{4})/g, "$1 ")
      .trim();
  };
  
  export const formatExpiryDate = (value) => {
    // Remove non-numeric characters
    const numericValue = value.replace(/\D/g, "");
  
    // Limit to four numeric characters
    const formattedValue = numericValue.slice(0, 4);
  
    // Add the '/' separator after the first two characters
    if (formattedValue.length > 2) {
      return formattedValue.slice(0, 2) + " / " + formattedValue.slice(2);
    } else {
      return formattedValue;
    }
  };

  return (
    <>
      {/* JSX code for the form */}
    </>
  );
};
JSX Structure

Within the return statement of your component, include the JSX structure for your form. This includes form elements such as text inputs, buttons, and labels.

<Box
        sx={{
          background: "var(--light-grey)",
          py: 5,
          px: { xs: 2, md: 7 },
          maxWidth: "32rem",
          margin: "0 auto",
          my: 5,
          borderRadius: "20px",
        }}
      >
        {/* <SharedLayout> */}
        <Box>
          <Typography
            variant="h5"
            className="fw-500 text-center"
            sx={{ pb: 3 }}
          >
            Pay with card
          </Typography>
          <Box sx={{ pb: 3 }} className="flex justify-content-between">
            <FormControl>
              <RadioGroup
                aria-labelledby="demo-radio-buttons-group-label"
                defaultValue="credit"
                name="radio-buttons-group"
                sx={{
                  ".Mui-checked": {
                    color: "var(--main-color) !important",
                  },
                  span: {
                    fontWeight: "500",
                  },
                }}
              >
                <FormControlLabel
                  value="credit"
                  control={<Radio />}
                  label="Credit or Debit Card"
                />
              </RadioGroup>
            </FormControl>
            <Box>
              <img
                src="/assets/svg/visa.svg"
                alt="visa"
                width={40}
                height={40}
              />
              <img
                src="/assets/svg/master_card.svg"
                alt="visa"
                width={40}
                height={40}
              />
            </Box>
          </Box>
          <Box>
            <form onSubmit={formik.handleSubmit}>
              <Grid container spacing={2}>
                <Grid item xs={12} sm={12}>
                  <Box sx={{ pb: 2 }}>
                    <InputLabel sx={{ py: 0.5, color: "#49454F" }}>
                      Cardholder Name
                    </InputLabel>
                    <Input
                      fullWidth
                      id="name"
                      name="name"
                      value={formik.values.name}
                      onChange={(e) => {
                        formik.handleChange(e);
                      }}
                      error={formik.touched.name && Boolean(formik.errors.name)}
                      helperText={formik.touched.name && formik.errors.name}
                      placeholder="e.g John Doe"
                    />
                  </Box>
                </Grid>
                <Grid item xs={12} sm={12}>
                  <Box sx={{ pb: 2 }}>
                    <InputLabel sx={{ py: 0.5, color: "#49454F" }}>
                      Card Number
                    </InputLabel>
                    <Input
                      fullWidth
                      id="cardNumber"
                      name="cardNumber"
                      value={formatCardNumber(formik.values.cardNumber)}
                      onChange={(e) => {
                        e.target.value = formatCardNumber(e.target.value);
                        formik.handleChange(e);
                      }}
                      error={
                        formik.touched.cardNumber &&
                        Boolean(formik.errors.cardNumber)
                      }
                      helperText={
                        formik.touched.cardNumber && formik.errors.cardNumber
                      }
                      sx={{
                        "& .MuiInputBase-root": {
                          paddingLeft: "8px",
                        },
                      }}
                      inputProps={{ maxLength: 19 }}
                      placeholder="1234 1234 1234 1234"
                      // placeholder="e.g John Doe"
                      InputProps={{
                        startAdornment: (
                          <InputAdornment position="end">
                            <IconButton edge="end" sx={{ p: 0 }}>
                              <CreditCard className="main-color" />
                            </IconButton>
                          </InputAdornment>
                        ),
                      }}
                    />
                  </Box>
                </Grid>
                <Grid item xs={12} sm={6}>
                  <InputLabel sx={{ py: 0.5, color: "#49454F" }}>
                    Expiry Date
                  </InputLabel>
                  <Input
                    variant="outlined"
                    fullWidth
                    id="expiryDate"
                    name="expiryDate"
                    value={formik.values.expiryDate}
                    onChange={(e) => {
                      e.target.value = formatExpiryDate(e.target.value);
                      formik.handleChange(e);
                    }}
                    error={
                      formik.touched.expiryDate &&
                      Boolean(formik.errors.expiryDate)
                    }
                    helperText={
                      formik.touched.expiryDate && formik.errors.expiryDate
                    }
                    InputProps={{
                      endAdornment: (
                        <InputAdornment position="end">
                          <CalendarToday
                            sx={{ color: "#ABABAB", width: "1rem" }}
                          />
                        </InputAdornment>
                      ),
                    }}
                    placeholder="MM/YY"
                  />
                </Grid>
                <Grid item xs={12} sm={6}>
                  <InputLabel sx={{ py: 0.5, color: "#49454F" }}>
                    CVV
                  </InputLabel>
                  <Input
                    variant="outlined"
                    fullWidth
                    id="cvv"
                    name="cvv"
                    value={formik.values.cvv}
                    onChange={formik.handleChange}
                    error={formik.touched.cvv && Boolean(formik.errors.cvv)}
                    helperText={formik.touched.cvv && formik.errors.cvv}
                    inputProps={{ maxLength: 4 }}
                    placeholder="e.g 1234"
                  />
                </Grid>
              </Grid>

              <Button
                variant="contained"
                color="primary"
                type="submit"
                sx={{
                  width: "100%",
                  mt: 4,
                  py: 1.3,
                  fontWeight: "500",
                  background: "var(--main-color)",
                }}
                className="normal-text"
              >
                Pay Now $10
              </Button>
            </form>
          </Box>
        </Box>
        {/* </SharedLayout> */}
      </Box>
Download Now
If you found this project helpful and want to support me, you can buy me a coffee at:

Buy me a coffee
Previous articlecs508 gdb solution 2023
RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Category