# 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`, `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)