11 KiB
11 KiB
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
// Form state (existing)
const [shippingAddress, setShippingAddress] = useState<AddressForm>({...});
const [billingAddress, setBillingAddress] = useState<AddressForm>({...});
const [sameAsShipping, setSameAsShipping] = useState(true);
// New state
const [paymentMethod, setPaymentMethod] = useState<string>("cod");
const [errors, setErrors] = useState<ValidationErrors>({
contact: null,
shipping: null,
billing: null,
shippingMethod: null,
general: null,
});
Debounced Shipping Method Fetching
useEffect(() => {
if (!isAddressComplete(shippingAddress)) return;
const timer = setTimeout(() => {
fetchShippingMethods();
}, 500); // 500ms debounce
return () => clearTimeout(timer);
}, [shippingAddress]);
Validation Schema
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
-
/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
-
/src/lib/saleor/mutations/Checkout.ts- Ensure all mutations available
- Add metadata update mutation if needed
-
/src/lib/saleor/queries/Checkout.ts- Ensure checkout query returns shipping methods
Translation Files
/messages/sr.json(and other language files)- Add new translation keys for one-page checkout
- Section headers
- Validation messages
- Button labels
Styling
/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
- Development: Complete on feature branch
- Testing: Local testing with all scenarios
- Staging: Deploy to dev.manoonoils.com
- Monitoring: Check for errors, conversion rates
- 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