368 lines
11 KiB
Markdown
368 lines
11 KiB
Markdown
# 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<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
|
|
|
|
```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
|