You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
5.2 KiB
5.2 KiB
Phase 5: Checkout (Forms & Flow) ⚡ PRIORITY
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 4: 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,CheckoutDatatype
- File:
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
- File:
-
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
- File:
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
- File:
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
- Checkout schema is defined with Zod
- CheckoutForm component is functional and styled
- AddressForm component is reusable
- Address pre-fills from user profile if available
- "Save address" checkbox works correctly
- /kasse page is protected (requires auth)
- Form validation works (VeeValidate + Zod)
- Field-level and form-level errors display correctly
- Loading states show during async operations
- Mobile checkout UX is optimized
- Address is saved to user profile after successful checkout
- 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