From 7d4445bb9bad3d6c945503086a07bd882536e5f6 Mon Sep 17 00:00:00 2001 From: Miqdad Date: Mon, 19 May 2025 11:02:19 +0700 Subject: fix unresponsive cart select --- src-migrate/modules/cart/components/ItemSelect.tsx | 170 +++++++++++++++------ 1 file changed, 126 insertions(+), 44 deletions(-) (limited to 'src-migrate/modules/cart/components/ItemSelect.tsx') diff --git a/src-migrate/modules/cart/components/ItemSelect.tsx b/src-migrate/modules/cart/components/ItemSelect.tsx index d4a1b537..733ee64d 100644 --- a/src-migrate/modules/cart/components/ItemSelect.tsx +++ b/src-migrate/modules/cart/components/ItemSelect.tsx @@ -1,56 +1,138 @@ -import { Checkbox, Spinner } from '@chakra-ui/react' -import React, { useState } from 'react' - -import { getAuth } from '~/libs/auth' -import { CartItem } from '~/types/cart' -import { upsertUserCart } from '~/services/cart' - -import { useCartStore } from '../stores/useCartStore' +import { Checkbox } from '@chakra-ui/react'; +import React, { useState, useCallback, useEffect } from 'react'; +import { getAuth } from '~/libs/auth'; +import { CartItem } from '~/types/cart'; +import { upsertUserCart } from '~/services/cart'; +import { useCartStore } from '../stores/useCartStore'; +import { toast } from 'react-hot-toast'; +import { + getSelectedItemsFromCookie, + updateSelectedItemInCookie, +} from '~/utils/cart'; type Props = { - item: CartItem -} + item: CartItem; +}; const CartItemSelect = ({ item }: Props) => { - const auth = getAuth() - const { updateCartItem, cart } = useCartStore() + const auth = getAuth(); + const { updateCartItem, cart, loadCart } = useCartStore(); + const [isUpdating, setIsUpdating] = useState(false); + const [localSelected, setLocalSelected] = useState(item.selected); + + // Initialize local state from cookie or server + useEffect(() => { + if (isUpdating) return; // Skip if we're currently updating + + // Check cookie first + const selectedItems = getSelectedItemsFromCookie(); + const storedState = selectedItems[item.id]; + + if (storedState !== undefined) { + // Only update local state if it differs from current state + if (localSelected !== storedState) { + setLocalSelected(storedState); + } + + // If cookie state differs from server state and we're not in the middle of an update, + // synchronize the item state with cookie + if (storedState !== item.selected) { + // Update cart item silently to match cookie + if (cart) { + const updatedCartItems = cart.products.map((cartItem) => + cartItem.id === item.id + ? { ...cartItem, selected: storedState } + : cartItem + ); + + const updatedCart = { ...cart, products: updatedCartItems }; + updateCartItem(updatedCart); + } + } + } else { + // Fall back to server state if no cookie exists + setLocalSelected(item.selected); + + // Save this state to cookie for future use + updateSelectedItemInCookie(item.id, item.selected); + } + }, [item.id, item.selected, localSelected, cart, updateCartItem, isUpdating]); + + const handleChange = useCallback( + async (e: React.ChangeEvent) => { + if (typeof auth !== 'object' || !cart || isUpdating) { + return; + } + + const newSelectedState = e.target.checked; + + // Update local state immediately for responsiveness + setLocalSelected(newSelectedState); + setIsUpdating(true); + + try { + // Update cookie immediately + updateSelectedItemInCookie(item.id, newSelectedState); + + // Update cart state immediately for UI responsiveness + const updatedCartItems = cart.products.map((cartItem) => + cartItem.id === item.id + ? { ...cartItem, selected: newSelectedState } + : cartItem + ); + + const updatedCart = { ...cart, products: updatedCartItems }; + updateCartItem(updatedCart); + + // Save to server + await upsertUserCart({ + userId: auth.id, + type: item.cart_type, + id: item.id, + qty: item.quantity, + selected: newSelectedState, + }); - const [isLoad, setIsLoad] = useState(false) + // Reload cart to ensure consistency + await loadCart(auth.id); + } catch (error) { + console.error('Failed to update item selection:', error); + toast.error('Gagal memperbarui pilihan barang'); - const handleChange = async (e: React.ChangeEvent) => { - if (typeof auth !== 'object' || !cart) return - - setIsLoad(true); - const updatedCartItems = cart.products.map(cartItem => - cartItem.id === item.id - ? { ...cartItem, selected: e.target.checked } - : cartItem - ); + // Revert local state on error + setLocalSelected(!newSelectedState); - // Update the entire cart - const updatedCart = { ...cart, products: updatedCartItems }; - updateCartItem(updatedCart); + // Update cookie back + updateSelectedItemInCookie(item.id, !newSelectedState); - setIsLoad(false); - } + // Reload cart to get server state + loadCart(auth.id); + } finally { + setIsUpdating(false); + } + }, + [auth, cart, item, isUpdating, updateCartItem, loadCart] + ); return ( -
- {isLoad && ( - - )} - - {!isLoad && ( - - )} +
+
- ) -} + ); +}; -export default CartItemSelect \ No newline at end of file +export default CartItemSelect; -- cgit v1.2.3