# Phase 4: Cart (Shopping Cart) ⚡ PRIORITY

**Status:** ✅ Done
**Progress:** 12/12 tasks (100%)
**Started:** 2025-11-03
**Completed:** 2025-11-03
**Assigned to:** Bastian

---

## Overview

Implement shopping cart functionality: API endpoints for cart operations, cart composable, and UI components for cart display and management.

**Goal:** Users can add products to cart, update quantities, and remove items.

---

## Dependencies

- ✅ Phase 2: Database must be completed (carts, cart_items tables needed)
- ✅ Phase 3: Authentication should be completed (for user-specific carts)
- ⚠️ **Note:** Products can be seeded manually for testing (Phase 6 can be done after Cart)

---

## Tasks

### API Endpoints

- [x] Create /api/cart/index.get.ts endpoint
  - Get current user's cart (or session cart for guests)
  - Include cart items with product details (join)
  - Calculate total price
  - Return: { cart, items: [{product, quantity, subtotal}], total }

- [x] Create /api/cart/items.post.ts endpoint
  - Add item to cart (body: {productId, quantity})
  - Validate product exists and has stock
  - Create cart if doesn't exist
  - Upsert cart_item (update quantity if already exists)
  - Return: Updated cart

- [x] Create /api/cart/items/[id].patch.ts endpoint
  - Update cart item quantity (body: {quantity})
  - Validate quantity > 0
  - Validate stock availability
  - Return: Updated cart item

- [x] Create /api/cart/items/[id].delete.ts endpoint
  - Remove item from cart
  - Delete cart_item record
  - Return: 204 No Content

### Composables

- [x] Create useCart composable
  - File: `composables/useCart.ts`
  - State: cart (ref), items (computed), total (computed), itemCount (computed)
  - Functions:
    - `fetchCart()` - Load cart from API
    - `addItem(productId, quantity)` - Add to cart
    - `updateItem(itemId, quantity)` - Update quantity
    - `removeItem(itemId)` - Remove from cart
    - `clearCart()` - Empty cart
  - Auto-fetch on mount
  - See similar pattern: [CLAUDE.md: useAuth](../CLAUDE.md#oauth2-login-flow-pattern)

### UI Components

- [x] Create CartItem component
  - File: `components/Cart/CartItem.vue`
  - Props: item (object with product, quantity, subtotal)
  - Display: Product image, name, price, quantity input, subtotal
  - Actions: Update quantity, Remove button
  - Emits: @update, @remove

- [x] Create CartSummary component
  - File: `components/Cart/CartSummary.vue`
  - Props: items (array), total (number)
  - Display: Items count, subtotal, VAT, total
  - Button: "Zur Kasse" (to checkout)
  - Styling: shadcn-nuxt Card

### Pages

- [x] Create cart page
  - File: `pages/warenkorb.vue` (German route)
  - Uses: useCart composable
  - Shows: List of CartItem components + CartSummary
  - Empty state: "Ihr Warenkorb ist leer" with link to /produkte
  - Loading state while fetching

### Testing

- [x] Test cart operations
  - Add product to cart from product page
  - Verify cart count updates (header badge)
  - Visit /warenkorb page
  - Update quantity via input
  - Remove item via button
  - Verify total updates correctly

- [x] Add cart persistence
  - For logged-in users: cart stored in DB (user_id)
  - For guests: cart stored in DB (session_id)
  - Test cart persists across page reloads
  - Test cart merges when guest logs in (optional, can defer)

- [x] Optimize cart queries
  - Ensure product details are fetched efficiently (join, not N+1)
  - Test with 10+ items in cart
  - Add indexes if needed

- [x] Document cart logic
  - Document cart/session relationship
  - Document cart item uniqueness (cart_id + product_id)
  - Document cart cleanup strategy (old carts)

---

## Acceptance Criteria

- [x] All 4 cart API endpoints work correctly
- [x] useCart composable manages cart state
- [x] CartItem component displays and allows editing
- [x] CartSummary component shows total correctly
- [x] /warenkorb page shows cart with all items
- [x] Can add products to cart from product pages
- [x] Can update item quantities in cart
- [x] Can remove items from cart
- [x] Cart total calculates correctly
- [x] Cart persists across page reloads
- [x] Empty cart shows helpful message

---

## Notes

- **Guest Carts:** Use session_id for guest carts (cookie-based)
- **Cart Merge:** When guest logs in, merge guest cart with user cart (optional for MVP)
- **Stock Validation:** Ensure quantity doesn't exceed stock when adding/updating
- **VAT:** 7% VAT for annual passes (hardcoded for MVP)

---

## Blockers

- None currently

---

## Related Documentation

- [docs/PRD.md: F-005](../docs/PRD.md#f-005-warenkorb)
- [docs/ARCHITECTURE.md: Carts Tables](../docs/ARCHITECTURE.md#carts)
