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.
4.5 KiB
4.5 KiB
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 APIaddItem(productId, quantity)- Add to cartupdateItem(itemId, quantity)- Update quantityremoveItem(itemId)- Remove from cartclearCart()- Empty cart
- Auto-fetch on mount
- See similar pattern: CLAUDE.md: useAuth
- File:
UI Components
-
Create CartItem component
-
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
- File:
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
- File:
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
- All 4 cart API endpoints work correctly
- useCart composable manages cart state
- CartItem component displays and allows editing
- CartSummary component shows total correctly
- /warenkorb page shows cart with all items
- Can add products to cart from product pages
- Can update item quantities in cart
- Can remove items from cart
- Cart total calculates correctly
- Cart persists across page reloads
- 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