Files
my2/tasks/06-checkout.md
Bastian Masanek 6e50ec7034 Init
2025-10-30 08:24:44 +01:00

172 lines
5.2 KiB
Markdown

# Phase 6: Checkout (Forms & Flow)
**Status:** ⏳ Todo
**Progress:** 0/15 tasks (0%)
**Started:** -
**Completed:** -
**Assigned to:** -
---
## Overview
Implement checkout flow: billing address form, validation, address pre-fill from user profile, save address to profile option.
**Goal:** Users can enter billing information and proceed to payment.
---
## Dependencies
- ✅ Phase 2: Database (users table with address fields)
- ✅ Phase 3: Authentication (user session needed)
- ✅ Phase 5: Cart (checkout requires items in cart)
---
## Tasks
### Schema & Validation
- [ ] Create checkout schema (Zod)
- File: `server/utils/schemas/checkout.ts`
- Fields: salutation, firstName, lastName, dateOfBirth, street, postCode, city, countryCode
- Validation rules: required fields, date format, postal code format
- Export: `checkoutSchema`, `CheckoutData` type
### API Endpoints
- [ ] Create /api/checkout/validate.post.ts endpoint
- Validates checkout data (Zod)
- Checks if user is logged in
- Checks if cart has items
- Returns: validation result or errors
### UI Components
- [ ] Create CheckoutForm component
- File: `components/Checkout/CheckoutForm.vue`
- Uses: VeeValidate + Zod schema
- Fields: All billing address fields
- Checkbox: "Adresse für zukünftige Bestellungen speichern"
- Pre-checked if user has no saved address
- Button: "Weiter zur Zahlung"
- See: [CLAUDE.md: Checkout Pattern](../CLAUDE.md#checkout-with-saved-address-pattern)
- [ ] Create AddressForm component (reusable)
- File: `components/Checkout/AddressForm.vue`
- Props: modelValue (address object), errors
- Emits: @update:modelValue
- Fields: Salutation dropdown, Name fields, Address fields
- Can be reused in profile settings later
### Core Functionality
- [ ] Implement address pre-fill from user profile
- In CheckoutForm: fetch user data from useAuth
- If user has saved address (user.street exists): pre-fill all fields
- If no saved address: show empty form
- [ ] Implement save address to profile
- After successful checkout: if checkbox checked, save address to user record
- Update users table: salutation, dateOfBirth, street, postCode, city, countryCode
- API endpoint: PATCH /api/user/profile (or include in order creation)
### Pages
- [ ] Create checkout page
- File: `pages/kasse.vue` (German route)
- Middleware: `auth` (requires login)
- Shows: CheckoutForm component
- Shows: Order summary (cart items + total)
- Redirects to /warenkorb if cart is empty
### Validation & Error Handling
- [ ] Add form validation (VeeValidate)
- Install VeeValidate + @vee-validate/zod
- Configure VeeValidate with Zod integration
- Show field-level errors
- Show form-level errors (e.g., "Cart is empty")
- [ ] Add error handling
- Handle validation errors gracefully
- Show user-friendly error messages
- Disable submit button while submitting
- Show loading spinner during submission
- [ ] Add loading states
- Loading: fetching user profile
- Loading: validating checkout data
- Loading: processing payment (next phase)
### Testing
- [ ] Test checkout flow
- Login as user with saved address → verify pre-fill
- Login as new user → verify empty form
- Fill form and submit → verify validation
- Submit with invalid data → verify error messages
- Submit with valid data → proceed to payment (next phase)
- [ ] Test address save/load
- Submit checkout with "save address" checked
- Verify user record updated in DB
- Start new checkout → verify address pre-filled
- [ ] Test mobile checkout
- Test form on mobile device/emulator
- Verify fields are easy to tap and type
- Verify keyboard shows correct type (e.g., numeric for postal code)
- [ ] Optimize checkout UX
- Autofocus first field
- Tab order is logical
- Error messages are clear and helpful
- Button placement is accessible
- [ ] Document checkout logic
- Document address save/load flow
- Document validation rules
- Document error handling strategy
---
## Acceptance Criteria
- [x] Checkout schema is defined with Zod
- [x] CheckoutForm component is functional and styled
- [x] AddressForm component is reusable
- [x] Address pre-fills from user profile if available
- [x] "Save address" checkbox works correctly
- [x] /kasse page is protected (requires auth)
- [x] Form validation works (VeeValidate + Zod)
- [x] Field-level and form-level errors display correctly
- [x] Loading states show during async operations
- [x] Mobile checkout UX is optimized
- [x] Address is saved to user profile after successful checkout
- [x] Checkout flow is documented
---
## Notes
- **Required Fields:** All address fields are required at checkout (even though optional in DB)
- **Date of Birth:** Required for annual pass registration
- **Salutation:** Dropdown with values: "Herr", "Frau", "Keine Angabe" (maps to HERR, FRAU, K_ANGABE in X-API)
- **Country Code:** Default to "DE", allow selection for international customers
---
## Blockers
- None currently
---
## Related Documentation
- [docs/PRD.md: F-006](../docs/PRD.md#f-006-checkout-prozess)
- [docs/ARCHITECTURE.md: Users Table](../docs/ARCHITECTURE.md#users)
- [CLAUDE.md: Checkout Pattern](../CLAUDE.md#checkout-with-saved-address-pattern)