146 lines
4.1 KiB
TypeScript
146 lines
4.1 KiB
TypeScript
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
|
import type { CartData as SharedCartData } from '@packages/shared'
|
|
|
|
type CartType = 'regular' | 'flash'
|
|
|
|
interface CartItem {
|
|
id: number
|
|
skuId: number
|
|
quantity: number
|
|
storeId: number | null
|
|
addedAt: number
|
|
slotId?: number | null
|
|
deliveryDate?: string | null
|
|
}
|
|
|
|
type CartData = SharedCartData<CartItem>
|
|
|
|
function getCartKey(cartType: CartType): string {
|
|
return `local-cart-${cartType}`
|
|
}
|
|
|
|
function readCart(cartType: CartType): CartItem[] {
|
|
try {
|
|
const raw = localStorage.getItem(getCartKey(cartType))
|
|
return raw ? JSON.parse(raw) : []
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
function writeCart(cartType: CartType, items: CartItem[]) {
|
|
localStorage.setItem(getCartKey(cartType), JSON.stringify(items))
|
|
}
|
|
|
|
// Build the exact shape useGetCart returns, so setQueryData matches the cache.
|
|
function toCartData(items: CartItem[]): CartData {
|
|
const totalItems = items.reduce((sum, item) => sum + item.quantity, 0)
|
|
return { items, totalItems, totalAmount: 0 }
|
|
}
|
|
|
|
export function useGetCart(cartType: CartType = 'regular') {
|
|
return useQuery({
|
|
queryKey: [getCartKey(cartType)],
|
|
queryFn: () => toCartData(readCart(cartType)),
|
|
})
|
|
}
|
|
|
|
export function useAddToCart(cartType: CartType = 'regular') {
|
|
const queryClient = useQueryClient()
|
|
|
|
return useMutation({
|
|
mutationFn: async ({
|
|
skuId,
|
|
quantity,
|
|
storeId,
|
|
slotId,
|
|
deliveryDate,
|
|
}: {
|
|
skuId: number
|
|
quantity: number
|
|
storeId?: number | null
|
|
slotId?: number | null
|
|
deliveryDate?: string | null
|
|
}) => {
|
|
const items = readCart(cartType)
|
|
const existing = items.find((i) => i.skuId === skuId)
|
|
if (existing) {
|
|
existing.quantity += quantity
|
|
if (slotId) existing.slotId = slotId
|
|
if (deliveryDate) existing.deliveryDate = deliveryDate
|
|
} else {
|
|
items.push({
|
|
id: Date.now(),
|
|
skuId,
|
|
quantity,
|
|
storeId: storeId ?? null,
|
|
addedAt: Date.now(),
|
|
slotId: slotId ?? null,
|
|
deliveryDate: deliveryDate ?? null,
|
|
})
|
|
}
|
|
writeCart(cartType, items)
|
|
// Optimistically update the cache so the UI reflects the cart instantly,
|
|
// before any refetch completes.
|
|
queryClient.setQueryData([getCartKey(cartType)], toCartData(items))
|
|
},
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: [getCartKey(cartType)] })
|
|
},
|
|
})
|
|
}
|
|
|
|
export function useUpdateCartItem(cartType: CartType = 'regular') {
|
|
const queryClient = useQueryClient()
|
|
|
|
return useMutation({
|
|
mutationFn: async ({
|
|
skuId,
|
|
quantity,
|
|
slotId,
|
|
deliveryDate,
|
|
}: {
|
|
skuId: number
|
|
quantity: number
|
|
slotId?: number | null
|
|
deliveryDate?: string | null
|
|
}) => {
|
|
let items = readCart(cartType)
|
|
const existing = items.find((i) => i.skuId === skuId)
|
|
if (!existing) return
|
|
if (quantity <= 0) {
|
|
// Quantity hit 0 — remove the item from the cart entirely
|
|
items = items.filter((i) => i.skuId !== skuId)
|
|
} else {
|
|
existing.quantity = quantity
|
|
if (slotId !== undefined) existing.slotId = slotId
|
|
if (deliveryDate !== undefined) existing.deliveryDate = deliveryDate
|
|
}
|
|
writeCart(cartType, items)
|
|
queryClient.setQueryData([getCartKey(cartType)], toCartData(items))
|
|
},
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: [getCartKey(cartType)] })
|
|
},
|
|
})
|
|
}
|
|
|
|
export function useRemoveFromCart(cartType: CartType = 'regular') {
|
|
const queryClient = useQueryClient()
|
|
|
|
return useMutation({
|
|
mutationFn: async (skuId: number) => {
|
|
let items = readCart(cartType)
|
|
items = items.filter((i) => i.skuId !== skuId)
|
|
writeCart(cartType, items)
|
|
queryClient.setQueryData([getCartKey(cartType)], toCartData(items))
|
|
},
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: [getCartKey(cartType)] })
|
|
},
|
|
})
|
|
}
|
|
|
|
export function clearLocalCart(cartType: CartType = 'regular') {
|
|
localStorage.removeItem(getCartKey(cartType))
|
|
}
|