157 lines
4.5 KiB
Markdown
157 lines
4.5 KiB
Markdown
# Phase 5: Cart (Shopping Cart)
|
|
|
|
**Status:** ⏳ Todo
|
|
**Progress:** 0/12 tasks (0%)
|
|
**Started:** -
|
|
**Completed:** -
|
|
**Assigned to:** -
|
|
|
|
---
|
|
|
|
## 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)
|
|
- ✅ Phase 4: Products must be completed (products needed in cart)
|
|
|
|
---
|
|
|
|
## Tasks
|
|
|
|
### API Endpoints
|
|
|
|
- [ ] 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 }
|
|
|
|
- [ ] 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
|
|
|
|
- [ ] Create /api/cart/items/[id].patch.ts endpoint
|
|
- Update cart item quantity (body: {quantity})
|
|
- Validate quantity > 0
|
|
- Validate stock availability
|
|
- Return: Updated cart item
|
|
|
|
- [ ] Create /api/cart/items/[id].delete.ts endpoint
|
|
- Remove item from cart
|
|
- Delete cart_item record
|
|
- Return: 204 No Content
|
|
|
|
### Composables
|
|
|
|
- [ ] 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
|
|
|
|
- [ ] 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
|
|
|
|
- [ ] 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
|
|
|
|
- [ ] 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
|
|
|
|
- [ ] 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
|
|
|
|
- [ ] 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)
|
|
|
|
- [ ] Optimize cart queries
|
|
- Ensure product details are fetched efficiently (join, not N+1)
|
|
- Test with 10+ items in cart
|
|
- Add indexes if needed
|
|
|
|
- [ ] 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)
|