diff options
| author | it-fixcomart <it@fixcomart.co.id> | 2025-07-29 09:46:05 +0700 |
|---|---|---|
| committer | it-fixcomart <it@fixcomart.co.id> | 2025-07-29 09:46:05 +0700 |
| commit | 077467cf53b46d8049df8b812577cd1a03011eba (patch) | |
| tree | 0dc641a9acb1237a3caca3f7f8a157a3e938c0b8 /src-migrate/modules/cart/stores | |
| parent | 0d28dc8ff5fb8c5399e356ed6ecae4fce2019ca6 (diff) | |
| parent | dc31efb2fec4c7b79917324d922ae820c4b5bb50 (diff) | |
<hafid> merging new release
Diffstat (limited to 'src-migrate/modules/cart/stores')
| -rw-r--r-- | src-migrate/modules/cart/stores/useCartStore.ts | 214 |
1 files changed, 180 insertions, 34 deletions
diff --git a/src-migrate/modules/cart/stores/useCartStore.ts b/src-migrate/modules/cart/stores/useCartStore.ts index e7d2cdd3..be48b1ed 100644 --- a/src-migrate/modules/cart/stores/useCartStore.ts +++ b/src-migrate/modules/cart/stores/useCartStore.ts @@ -1,23 +1,39 @@ import { create } from 'zustand'; import { CartItem, CartProps } from '~/types/cart'; import { getUserCart } from '~/services/cart'; +import { + syncCartWithCookie, + getCartDataFromCookie, + getSelectedItemsFromCookie, + forceResetAllSelectedItems, +} from '~/utils/cart'; -type State = { +interface Summary { + subtotal: number; + discount: number; + total: number; + tax: number; + grandTotal: number; +} + +interface SyncResult { + cartData?: Record<string, any>; + selectedItems?: Record<number, boolean>; + needsUpdate: boolean; +} + +interface State { cart: CartProps | null; isLoadCart: boolean; - summary: { - subtotal: number; - discount: number; - total: number; - tax: number; - grandTotal: number; - }; -}; + summary: Summary; +} -type Action = { +interface Action { loadCart: (userId: number) => Promise<void>; updateCartItem: (updateCart: CartProps) => void; -}; + forceResetSelection: () => void; + clearCart: () => void; +} export const useCartStore = create<State & Action>((set, get) => ({ cart: null, @@ -29,50 +45,180 @@ export const useCartStore = create<State & Action>((set, get) => ({ tax: 0, grandTotal: 0, }, - loadCart: async (userId) => { - if (get().isLoadCart === true) return; + + loadCart: async (userId: number): Promise<void> => { + if (get().isLoadCart) return; set({ isLoadCart: true }); - const cart: CartProps = (await getUserCart(userId)) as CartProps; - set({ cart }); - set({ isLoadCart: false }); - const summary = computeSummary(cart); + try { + const cart: CartProps = (await getUserCart(userId)) as CartProps; + + // Sync with cookie data + const syncResult = syncCartWithCookie(cart) as SyncResult; + + if (syncResult?.needsUpdate && cart.products) { + const selectedItems = getSelectedItemsFromCookie() as Record< + number, + boolean + >; + + const updatedCart: CartProps = { + ...cart, + products: cart.products.map((item) => ({ + ...item, + selected: + selectedItems[item.id] !== undefined + ? selectedItems[item.id] + : item.selected, + })), + }; + + set({ cart: updatedCart }); + } else { + set({ cart }); + } + + // Update summary + const summary = computeSummary(get().cart!); + set({ summary }); + } catch (error) { + console.error('Failed to load cart:', error); + + // Fallback to cookie data + await handleFallbackFromCookie(); + } finally { + set({ isLoadCart: false }); + } + }, + + updateCartItem: (updatedCart: CartProps): void => { + set({ cart: updatedCart }); + syncCartWithCookie(updatedCart); + + const summary = computeSummary(updatedCart); set({ summary }); }, - updateCartItem: (updatedCart) => { - const cart = get().cart; + + forceResetSelection: (): void => { + const { cart } = get(); if (!cart) return; + forceResetAllSelectedItems(); + + const updatedCart: CartProps = { + ...cart, + products: cart.products.map((item) => ({ ...item, selected: false })), + }; + set({ cart: updatedCart }); + const summary = computeSummary(updatedCart); set({ summary }); }, + clearCart: (): void => { + set({ + cart: null, + summary: { + subtotal: 0, + discount: 0, + total: 0, + tax: 0, + grandTotal: 0, + }, + }); + }, })); -const computeSummary = (cart: CartProps) => { +// Helper function for cookie fallback +const handleFallbackFromCookie = async (): Promise<void> => { + try { + const cartData = getCartDataFromCookie() as Record<string, any>; + + if (Object.keys(cartData).length === 0) return; + + const products: CartItem[] = Object.values(cartData).map( + transformCookieItemToProduct + ); + + const fallbackCart: CartProps = { + product_total: products.length, + products, + }; + + useCartStore.setState({ cart: fallbackCart }); + + const summary = computeSummary(fallbackCart); + useCartStore.setState({ summary }); + } catch (error) { + console.error('Cookie fallback failed:', error); + } +}; + +// Helper function to transform cookie item to product format +const transformCookieItemToProduct = (item: any): CartItem => ({ + image_program: item.image_program || '', + cart_id: item.cart_id, + quantity: item.quantity, + selected: item.selected, + can_buy: true, + cart_type: item.cart_type, + id: item.id, + name: item.product?.name || item.program_line?.name || '', + stock: 0, + is_in_bu: false, + on_hand_qty: 0, + available_quantity: 0, + weight: 0, + attributes: [], + parent: { + id: 0, + name: '', + image: '', + }, + price: item.price || { + price: 0, + discount_percentage: 0, + price_discount: 0, + }, + manufacture: { + id: 0, + name: '', + }, + has_flashsale: false, + subtotal: 0, + code: item.code, + image: item.image, + package_price: item.package_price, +}); + +const computeSummary = (cart: CartProps): Summary => { + if (!cart?.products) { + return { subtotal: 0, discount: 0, total: 0, grandTotal: 0, tax: 0 }; + } + + const PPN = parseFloat(process.env.NEXT_PUBLIC_PPN || '1.11'); let subtotal = 0; let discount = 0; - const PPN: number = process.env.NEXT_PUBLIC_PPN ? parseFloat(process.env.NEXT_PUBLIC_PPN) : 0; - - for (const item of cart?.products) { + for (const item of cart.products) { if (!item.selected) continue; - let price = 0; - if (item.cart_type === 'promotion') - price = (item?.package_price || 0) * item.quantity; - else if (item.cart_type === 'product') - price = item.price.price * item.quantity; + const price = + item.cart_type === 'promotion' + ? (item?.package_price || 0) * item.quantity + : item.price.price * item.quantity; subtotal += price; discount += price - item.price.price_discount * item.quantity; } - let total = subtotal - discount; - let grandTotal = total * PPN; - let tax = grandTotal - total; - // let grandTotal = total + tax; - return { subtotal, discount, total, grandTotal, tax }; -};
\ No newline at end of file + const total = subtotal - discount; + + // PERBAIKAN: + const tax = total * (PPN - 1); + const grandTotal = total + tax; + + return { subtotal, discount, total, grandTotal, tax }; +}; |
