Implement shopping cart functionality with UI components and API integration

- Added CartItem, CartSummary, CartEmpty, CartSidebar, and CartSheet components for managing cart display and interactions.
- Integrated useCart and useCartUI composables for cart state management and UI control.
- Implemented API endpoints for cart operations, including fetching, adding, updating, and removing items.
- Enhanced user experience with loading states and notifications using vue-sonner for cart actions.
- Configured session management for guest and authenticated users, ensuring cart persistence across sessions.

This commit completes the shopping cart feature, enabling users to add items, view their cart, and proceed to checkout.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
This commit is contained in:
Bastian Masanek
2025-11-03 12:43:13 +01:00
parent 9d0e77fc98
commit b372e2cf78
44 changed files with 2209 additions and 123 deletions

View File

@@ -0,0 +1,77 @@
<script setup lang="ts">
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
} from '@/components/ui/sheet'
import { ScrollArea } from '@/components/ui/scroll-area'
import CartEmpty from './CartEmpty.vue'
import CartItem from './CartItem.vue'
import CartSummary from './CartSummary.vue'
// Get cart state and UI controls
const { items, itemCount, total, loading, updateItem, removeItem } = useCart()
const { isOpen, close } = useCartUI()
// Handle quantity update
async function handleUpdateQuantity(itemId: string, quantity: number) {
await updateItem(itemId, quantity)
}
// Handle item removal
async function handleRemoveItem(itemId: string) {
await removeItem(itemId)
}
// Navigate to checkout
function handleCheckout() {
close()
navigateTo('/checkout')
}
</script>
<template>
<Sheet :open="isOpen" @update:open="(open) => !open && close()">
<SheetContent side="right" class="w-full sm:w-[400px] p-0 flex flex-col">
<!-- Header -->
<SheetHeader class="px-6 py-4 border-b">
<SheetTitle class="text-xl font-bold">
Warenkorb ({{ itemCount }})
</SheetTitle>
</SheetHeader>
<!-- Empty State -->
<div v-if="itemCount === 0" class="flex-1 flex items-center justify-center px-6">
<CartEmpty />
</div>
<!-- Cart Items + Summary -->
<template v-else>
<!-- Scrollable Items List -->
<ScrollArea class="flex-1 px-6">
<div class="space-y-4 py-4">
<CartItem
v-for="item in items"
:key="item.id"
:item="item"
:loading="loading"
@update:quantity="(qty) => handleUpdateQuantity(item.id, qty)"
@remove="handleRemoveItem(item.id)"
/>
</div>
</ScrollArea>
<!-- Sticky Footer with Summary -->
<div class="border-t px-6 py-4 bg-background">
<CartSummary
:items="items"
:total="total"
:loading="loading"
@checkout="handleCheckout"
/>
</div>
</template>
</SheetContent>
</Sheet>
</template>