85 lines
2.5 KiB
TypeScript
85 lines
2.5 KiB
TypeScript
import { create } from 'zustand'
|
|
import { persist } from 'zustand/middleware'
|
|
|
|
export interface CartItem {
|
|
menuItemId: string
|
|
name: string
|
|
price: number
|
|
quantity: number
|
|
specialRequest?: string
|
|
}
|
|
|
|
interface CartStore {
|
|
restaurantId: string | null
|
|
restaurantName: string | null
|
|
restaurantSlug: string | null
|
|
items: CartItem[]
|
|
|
|
addItem: (restaurantId: string, restaurantName: string, restaurantSlug: string, item: Omit<CartItem, 'quantity'>) => void
|
|
removeItem: (menuItemId: string) => void
|
|
updateQuantity: (menuItemId: string, quantity: number) => void
|
|
clearCart: () => void
|
|
|
|
// Computed
|
|
subtotal: () => number
|
|
itemCount: () => number
|
|
deliveryFee: number
|
|
}
|
|
|
|
export const useCart = create<CartStore>()(
|
|
persist(
|
|
(set, get) => ({
|
|
restaurantId: null,
|
|
restaurantName: null,
|
|
restaurantSlug: null,
|
|
items: [],
|
|
deliveryFee: 5.00,
|
|
|
|
addItem: (restaurantId, restaurantName, restaurantSlug, item) => {
|
|
// Coerce price to number (PostgreSQL returns DECIMAL as string)
|
|
item = { ...item, price: Number(item.price) }
|
|
const { restaurantId: currentRestId, items } = get()
|
|
|
|
// Switching restaurant — clear cart first
|
|
if (currentRestId && currentRestId !== restaurantId) {
|
|
set({ restaurantId, restaurantName, restaurantSlug, items: [{ ...item, quantity: 1 }] })
|
|
return
|
|
}
|
|
|
|
const existing = items.find((i) => i.menuItemId === item.menuItemId)
|
|
if (existing) {
|
|
set({
|
|
items: items.map((i) =>
|
|
i.menuItemId === item.menuItemId ? { ...i, quantity: i.quantity + 1 } : i,
|
|
),
|
|
})
|
|
} else {
|
|
set({
|
|
restaurantId,
|
|
restaurantName,
|
|
restaurantSlug,
|
|
items: [...items, { ...item, quantity: 1 }],
|
|
})
|
|
}
|
|
},
|
|
|
|
removeItem: (menuItemId) =>
|
|
set({ items: get().items.filter((i) => i.menuItemId !== menuItemId) }),
|
|
|
|
updateQuantity: (menuItemId, quantity) => {
|
|
if (quantity <= 0) {
|
|
get().removeItem(menuItemId)
|
|
return
|
|
}
|
|
set({ items: get().items.map((i) => (i.menuItemId === menuItemId ? { ...i, quantity } : i)) })
|
|
},
|
|
|
|
clearCart: () => set({ restaurantId: null, restaurantName: null, restaurantSlug: null, items: [] }),
|
|
|
|
subtotal: () => get().items.reduce((sum, i) => sum + Number(i.price) * i.quantity, 0),
|
|
itemCount: () => get().items.reduce((sum, i) => sum + i.quantity, 0),
|
|
}),
|
|
{ name: 'vibe-cart' },
|
|
),
|
|
)
|