# One-Page Checkout Implementation Plan **Branch:** `feature/one-page-checkout` **Status:** In Development **Priority:** High **Phone Requirement:** Required (not optional) --- ## Overview Convert the current two-phase checkout into a streamlined one-page checkout experience where customers can see all fields at once and complete their order in a single action. ### Current State - **Phase 1:** Collect email, shipping address → fetch shipping methods - **Phase 2:** Select shipping method, billing address → complete order - **Total API calls:** 6-7 sequential requests across 2 user interactions ### Target State - **Single Page:** All fields visible simultaneously - **Dynamic updates:** Shipping methods fetch automatically when address changes - **Single submit:** One "Complete Order" button - **Optimized API:** 3-4 sequential steps (parallel where possible) --- ## Requirements ### Must-Have - [ ] All checkout fields visible on single page - [ ] Phone number is **required** (strict validation) - [ ] Shipping methods fetch automatically (debounced) when address changes - [ ] Real-time total calculation (updates when shipping method selected) - [ ] Single "Complete Order" submit button - [ ] Section-based validation with inline errors - [ ] Auto-scroll to first error on validation failure - [ ] Preserve form data on error ### UX Requirements - [ ] Clear visual hierarchy (Contact → Shipping → Billing → Shipping Method → Payment) - [ ] Collapsible sections (optional - all expanded by default) - [ ] Loading states for shipping method fetching - [ ] Disabled submit button until all required fields valid - [ ] Success confirmation page (existing) ### Technical Requirements - [ ] Debounced shipping method API calls (500ms) - [ ] Optimistic UI updates where possible - [ ] Proper error handling per section - [ ] Analytics events for checkout steps - [ ] Mobile-responsive layout --- ## UI Layout ### Left Column (Form - 60% width on desktop) ``` ┌─────────────────────────────────────┐ │ 1. Contact Information │ │ ├─ Email * [________________] │ │ └─ Phone * [________________] │ │ [+381... format hint] │ ├─────────────────────────────────────┤ │ 2. Shipping Address │ │ ├─ First Name * [____________] │ │ ├─ Last Name * [_____________] │ │ ├─ Country * [▼ Serbia ▼] │ │ ├─ Street Address * [________] │ │ ├─ Apt/Suite [______________] │ │ ├─ City * [_________________] │ │ └─ Postal Code * [__________] │ ├─────────────────────────────────────┤ │ 3. Billing Address │ │ [✓] Same as shipping address │ │ (Fields hidden when checked) │ ├─────────────────────────────────────┤ │ 4. Shipping Method │ │ (Loading... / Select to see │ │ available options) │ │ ○ Standard (2-3 days) 400 RSD │ │ ○ Express (1-2 days) 800 RSD │ ├─────────────────────────────────────┤ │ 5. Payment Method │ │ ● Cash on Delivery │ │ (Additional payment methods TBD) │ ├─────────────────────────────────────┤ │ [ Complete Order - 3,600 RSD ] │ │ Loading spinner when processing │ └─────────────────────────────────────┘ ``` ### Right Column (Order Summary - 40% width on desktop) ``` ┌─────────────────────────────────────┐ │ Order Summary │ ├─────────────────────────────────────┤ │ Product Image Serum x1 3,200 │ │ RSD │ ├─────────────────────────────────────┤ │ Subtotal 3,200 RSD │ │ Shipping 400 RSD │ │ ───────────────────────────────── │ │ Total 3,600 RSD │ └─────────────────────────────────────┘ ``` ### Mobile Layout Single column, stacked sections with sticky order summary at bottom. --- ## Technical Implementation ### State Management ```typescript // Form state (existing) const [shippingAddress, setShippingAddress] = useState({...}); const [billingAddress, setBillingAddress] = useState({...}); const [sameAsShipping, setSameAsShipping] = useState(true); // New state const [paymentMethod, setPaymentMethod] = useState("cod"); const [errors, setErrors] = useState({ contact: null, shipping: null, billing: null, shippingMethod: null, general: null, }); ``` ### Debounced Shipping Method Fetching ```typescript useEffect(() => { if (!isAddressComplete(shippingAddress)) return; const timer = setTimeout(() => { fetchShippingMethods(); }, 500); // 500ms debounce return () => clearTimeout(timer); }, [shippingAddress]); ``` ### Validation Schema ```typescript const validationRules = { email: (value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value), phone: (value) => { // Country-specific validation // Serbia: +381 XX XXX XXXX // Bosnia: +387 XX XXX XXX // etc. }, required: (value) => value.trim().length > 0, postalCode: (value, country) => { // Country-specific postal code validation }, }; ``` ### API Call Sequence **Optimized Flow (parallel + sequential):** ``` Step 1: Validation (client-side) ├─ Validate all fields └─ Show inline errors Step 2: Parallel Independent Calls ├─ Update Email └─ Update Shipping Address (Both can run simultaneously) Step 3: Conditional Call └─ Update Billing Address (if different from shipping) Step 4: Sequential Dependent Calls ├─ Update Shipping Method ├─ Update Metadata (phone, language, payment method) └─ Complete Checkout Total: 4 sequential steps vs current 7+ ``` ### Error Handling Strategy **Field-level:** - Real-time validation on blur - Visual indicators (red border, error message) - Prevent submit if validation fails **Section-level:** - Group errors by section - Show section header in red if has errors - Expand section if collapsed and has errors **Form-level:** - On submit: validate all fields - If errors: scroll to first error, show summary - If API error: show in relevant section, preserve data **API-level:** - Map Saleor errors to form fields when possible - Generic error: show at top of form - Network error: show retry button --- ## Files to Modify ### Primary Files 1. **`/src/app/[locale]/checkout/page.tsx`** - Major refactor of checkout flow - Combine Phase 1 & Phase 2 into single component - Add debounced shipping method fetching - Implement section-based validation - Optimize API call sequence 2. **`/src/lib/saleor/mutations/Checkout.ts`** - Ensure all mutations available - Add metadata update mutation if needed 3. **`/src/lib/saleor/queries/Checkout.ts`** - Ensure checkout query returns shipping methods ### Translation Files 4. **`/messages/sr.json`** (and other language files) - Add new translation keys for one-page checkout - Section headers - Validation messages - Button labels ### Styling 5. **`/src/app/globals.css`** (or Tailwind config) - Ensure consistent form styling - Add validation state styles - Loading spinner styles --- ## Implementation Phases ### Phase 1: Core Structure (Day 1-2) - [ ] Refactor checkout page layout - [ ] Display all sections simultaneously - [ ] Keep existing form logic working - [ ] Test existing flow still works ### Phase 2: Dynamic Shipping Methods (Day 3) - [ ] Implement debounced fetching - [ ] Add loading states - [ ] Display shipping methods inline - [ ] Update total when method selected ### Phase 3: Validation & Error Handling (Day 4) - [ ] Implement field-level validation - [ ] Add section-based error display - [ ] Auto-scroll to errors - [ ] Test all validation scenarios ### Phase 4: Optimization (Day 5) - [ ] Optimize API call sequence - [ ] Add parallel mutation execution - [ ] Improve loading states - [ ] Add optimistic updates ### Phase 5: Polish (Day 6) - [ ] Mobile responsiveness - [ ] Analytics events - [ ] Accessibility improvements - [ ] Final testing --- ## Testing Checklist ### Functionality Tests - [ ] Fill all fields, submit successfully - [ ] Verify order created in Saleor - [ ] Verify emails sent - [ ] Change shipping method, verify total updates - [ ] Change address, verify shipping methods refetch ### Validation Tests - [ ] Submit with empty email → email error - [ ] Submit with empty phone → phone error - [ ] Submit with invalid email format → format error - [ ] Submit with invalid phone → format error - [ ] Submit with empty required fields → field errors - [ ] Submit without selecting shipping method → shipping error ### Edge Cases - [ ] Slow network (test debouncing) - [ ] No shipping methods available - [ ] API failure during submission - [ ] Partial API failure (some mutations succeed) - [ ] Browser refresh (preserve data?) ### Mobile Tests - [ ] Layout works on iPhone SE - [ ] Layout works on iPhone 14 Pro Max - [ ] Touch targets large enough - [ ] Scroll behavior smooth ### Accessibility Tests - [ ] Tab navigation works - [ ] Screen reader friendly - [ ] Error announcements - [ ] Focus management --- ## Rollout Strategy 1. **Development:** Complete on feature branch 2. **Testing:** Local testing with all scenarios 3. **Staging:** Deploy to dev.manoonoils.com 4. **Monitoring:** Check for errors, conversion rates 5. **Production:** Merge to master and deploy --- ## Success Metrics - **Conversion Rate:** Should increase (fewer steps = less drop-off) - **Time to Complete:** Should decrease (single page vs two phases) - **Error Rate:** Should decrease (better validation) - **Mobile Completion:** Should improve (optimized for mobile) --- ## Future Enhancements (Out of Scope) - [ ] Save addresses for logged-in users - [ ] Address autocomplete (Google Maps) - [ ] Multiple payment methods (Stripe, etc.) - [ ] Guest checkout improvements - [ ] Order notes/comments field - [ ] Gift wrapping options - [ ] Promo code input --- ## Notes - Phone number is **strictly required** - validate format per country - Keep existing checkout success page - Maintain multi-language support - Ensure analytics tracking works - Don't break existing cart functionality --- **Created:** March 28, 2026 **Branch:** feature/one-page-checkout **Next Step:** Start Phase 1 - Core Structure