Skip to content

Checkout Validation

This guide explains the multi-layered validation strategy used in the Bagisto Headless storefront to ensure data integrity and a smooth checkout experience.

Overview

Validation in the checkout flow occurs at three levels:

  1. Client-Side: Immediate feedback using form validation rules.
  2. Logic-Side: Ensuring the user follows the correct sequence of steps.
  3. Server-Side: Backend validation for business rules like stock availability and payment eligibility.

1. Client-Side Form Validation

The storefront uses React Hook Form to provide real-time validation for all checkout inputs, such as email, billing addresses, and shipping details.

Example: Email Validation

The email step ensures a correctly formatted email is provided before allowing the user to proceed.

File: src/components/checkout/stepper/Email.tsx

tsx
{...register("email", {
  required: "Email is required",
  pattern: {
    value: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/,
    message: "Please enter a valid email address",
  }
})}

Example: Address & Phone Validation

The address form includes complex validation, such as minimum length requirements for phone numbers.

File: src/components/checkout/stepper/GuestAddAdressForm.tsx

tsx
{...register("billing.phone", {
  required: "Phone field is required",
  validate: (value) => {
    const cleaned = value.replace(/\D/g, '');
    return cleaned.length >= 10 || "Phone must be at least 10 digits";
  }
})}

2. Step and Sequence Validation

To prevent users from skipping essential checkout steps (e.g., trying to access the payment step without providing an address), the isCheckout helper validates the current state against the requested URL.

File: src/utils/helper.ts

typescript
export const isCheckout = (items, isGuest, email, isSeclectAddress, ...) => {
  if (!items || items.length === 0) return "/"; // Redirect to home if cart is empty

  if (isSeclectAddress && !isSelectShipping) {
    return "/checkout?step=shipping"; // Force return to shipping if address is set but shipping is not
  }
  // ... other step sequence checks
};

3. Server-Side Business Validation

When a user submits a step (like saving an address or placing an order), the request is sent to the Bagisto GraphQL API. The backend performs critical checks:

  • Stock Validation: Ensures items are still in stock at the moment of checkout.
  • Address Eligibility: Validates if shipping is available to the provided zip code/country.
  • Payment Success: Validates the selected payment method against the cart total.

Handling API Errors

If the server rejects a request, the useCheckout hook captures the error and displays it to the user via a toast notification.

File: src/utils/hooks/useCheckout.ts

typescript
onSuccess: (response) => {
  if (isObject(responseData)) {
    showToast(responseData.message, "success");
    // Proceed to next step
  } else {
    // Show backend validation error (e.g., "Out of stock")
    showToast(response?.error?.message, "warning");
  }
}

4. Visual Feedback

  • Input Errors: Validation messages appear immediately below the affected input fields.
  • Loading States: Submit buttons are disabled and show loading spinners during API validation to prevent double submissions.
  • Toasts: Real-time feedback for successful saves or server-side rejections.

Summary

  • Proactive Feedback: React Hook Form catches most errors before they reach the server.
  • Sequence Integrity: URL-based logic prevents jumping ahead in the checkout process.
  • Backend Authority: Bagisto core acts as the final validator for commerce rules (stock, taxes, shipping).
  • Graceful Error Handling: Server errors are translated into user-friendly toast notifications.

Next Steps

Released under the MIT License.