React WordPress Online Order Form

React WordPress Online Order Form

A Persian RTL React SPA for WooCommerce stores that lets customers place orders through a dedicated online form—outside wp-admin. Phone OTP...

JavaScript Tailwind CSS WordPress Plugin Development WordPress Vite React TypeScript
Responsive Design REST API Authentication SEO Optimized File Upload
★ 0.0 (0 ratings)

Share

Overview

React WordPress Online Order Form is a portfolio-grade customer-facing SPA built for MG+ Store and similar Iranian WooCommerce shops. Instead of forcing buyers through a cluttered theme checkout, it delivers a focused /order/ experience: SMS OTP authentication, live product catalog from WooCommerce via a custom WordPress plugin REST namespace (mgplus/v1), province/city address selection, quantity-based cart summary, optional bank-receipt upload, and a post-submit invoice page with Jalali formatting—all in Persian RTL with BYekan typography and a soft-green glass UI.

The Challenge

The client sold herbal and wellness products on WooCommerce but needed a simpler, mobile-first order channel for Instagram and phone customers who struggled with the default checkout. Requirements included Iranian phone validation, OTP instead of passwords, province/city dropdowns, syncing WooCommerce products without duplicating catalog management, receipt photo upload for bank transfers, and a shareable invoice—while keeping admin workflows inside WordPress, not in the React app.

Approach

Shipped a Vite-built React 19 SPA deployed as a static subdomain (order.mgplusstore) with Apache SPA rewrites. The frontend talks exclusively to a companion WordPress plugin exposing /wp-json/mgplus/v1 endpoints for OTP, products, orders, and receipt upload. Product categories are derived client-side from WooCommerce category arrays. Formik + Yup handle validation; TanStack React Query caches catalog data and manages mutations. OrderForm is split into composable sections (personal info, location, address, product picker, summary, receipt). AuthContext persists token and form_user_id in localStorage; Axios interceptors attach Bearer tokens and force re-login on 401.

Architecture

Entry: main.tsx → QueryProvider → AuthProvider → App with lazy-loaded routes (/, /verify, /order, /invoice/:orderId). API layer in src/api/ (axiosClient, authApi, orderApi, wooCommerceApi). Hooks wrap React Query mutations (useAuthApi, useOrderApi, useWooCommerceQuery). Province/city data lazy-loads from province-city.json. Product images normalize WordPress upload URLs via imageUtils. Config centralizes VITE_API_BASE_URL, timeouts (60s default, 120s for uploads), and storage keys. Backend plugin (not in this repo) stores orders in wp_mgplus_orders, sends SMS OTP, and proxies WooCommerce products—admin panel lives in WordPress.

Trade-offs

Frontend and WordPress plugin are separate deliverables—this repo is the SPA only, so portfolio demos require both deployed. No GitHub repo published yet. Logout hook exists but no UI button. html2canvas is installed but invoice screenshot is manual. Product categories have no dedicated API endpoint—they are computed from product payloads. Special local /photo/ overrides for one category require deploy-time assets. WooCommerce checkout and this form coexist; orders land in a custom table rather than native WC orders unless synced server-side.

Results

Customers get a fast, RTL order funnel: enter phone → verify OTP → pick products by category → submit with optional receipt → view printable invoice. Store staff keep catalog and order management in WordPress. The codebase demonstrates production SPA patterns—code splitting, typed API contracts, optimistic error toasts via SweetAlert2, accessible form sections, and environment-based API configuration—making it a credible pitch artifact for bespoke React + WordPress order portals.

Key Learnings

Deriving categories client-side avoids an extra endpoint but couples UI to product payload shape—document the contract clearly. Lazy-loading large province-city JSON keeps initial bundle lean. Filtering zero-price products before submit prevents backend rejection. Passing order data via router state gives instant invoice rendering while GET /orders/:id serves refresh/deep-link cases. Bearer-token interceptors plus 401 cleanup are essential when OTP sessions expire mid-form. Apache .htaccess SPA rules and hashed Vite assets must ship together for subdomain deployment.