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:
91
server/api/cart/items.post.ts
Normal file
91
server/api/cart/items.post.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* POST /api/cart/items
|
||||
*
|
||||
* Add a product to the shopping cart
|
||||
*
|
||||
* Request Body:
|
||||
* {
|
||||
* productId: string (UUID)
|
||||
* quantity: number (positive integer, default: 1)
|
||||
* }
|
||||
*
|
||||
* Behavior:
|
||||
* - If product already in cart, increments quantity
|
||||
* - Validates product exists, is active, and has sufficient stock
|
||||
* - Checks role-based visibility permissions
|
||||
* - Creates cart if it doesn't exist
|
||||
*
|
||||
* Response:
|
||||
* {
|
||||
* success: true,
|
||||
* message: string,
|
||||
* cart: CartSummary
|
||||
* }
|
||||
*/
|
||||
|
||||
import { z } from 'zod'
|
||||
import { eq, and } from 'drizzle-orm'
|
||||
import { cartItems } from '../../database/schema'
|
||||
|
||||
// Request validation schema
|
||||
const addToCartSchema = z.object({
|
||||
productId: z.string().uuid('Invalid product ID'),
|
||||
quantity: z.number().int().positive().default(1),
|
||||
})
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
// Validate request body
|
||||
const body = await readBody(event)
|
||||
const { productId, quantity } = await addToCartSchema.parseAsync(body)
|
||||
|
||||
// Validate product availability and permissions
|
||||
const product = await validateProductForCart(event, productId, quantity)
|
||||
|
||||
// Get or create cart
|
||||
const cart = await getOrCreateCart(event)
|
||||
|
||||
const db = await useDatabase()
|
||||
|
||||
// Check if product already in cart
|
||||
const existingItem = await db.query.cartItems.findFirst({
|
||||
where: and(
|
||||
eq(cartItems.cartId, cart.id),
|
||||
eq(cartItems.productId, productId)
|
||||
),
|
||||
})
|
||||
|
||||
if (existingItem) {
|
||||
// Product already in cart - increment quantity
|
||||
const newQuantity = existingItem.quantity + quantity
|
||||
|
||||
// Validate new quantity against stock
|
||||
validateQuantityUpdate(newQuantity, product.stockQuantity)
|
||||
|
||||
// Update quantity
|
||||
await db
|
||||
.update(cartItems)
|
||||
.set({ quantity: newQuantity })
|
||||
.where(eq(cartItems.id, existingItem.id))
|
||||
} else {
|
||||
// Add new item to cart
|
||||
await db.insert(cartItems).values({
|
||||
cartId: cart.id,
|
||||
productId,
|
||||
quantity,
|
||||
})
|
||||
}
|
||||
|
||||
// Update cart timestamp
|
||||
await touchCart(cart.id)
|
||||
|
||||
// Return updated cart
|
||||
const cartSummary = await getCartWithItems(cart.id)
|
||||
|
||||
return {
|
||||
success: true,
|
||||
message: existingItem
|
||||
? `Quantity updated to ${existingItem.quantity + quantity}`
|
||||
: 'Product added to cart',
|
||||
cart: cartSummary,
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user