diff options
Diffstat (limited to 'src-migrate/modules/cart/components/ItemAction.tsx')
| -rw-r--r-- | src-migrate/modules/cart/components/ItemAction.tsx | 125 |
1 files changed, 109 insertions, 16 deletions
diff --git a/src-migrate/modules/cart/components/ItemAction.tsx b/src-migrate/modules/cart/components/ItemAction.tsx index eea0cbe9..4dcebd9e 100644 --- a/src-migrate/modules/cart/components/ItemAction.tsx +++ b/src-migrate/modules/cart/components/ItemAction.tsx @@ -15,7 +15,11 @@ import { useProductCartContext } from '@/contexts/ProductCartContext'; import { removeSelectedItemsFromCookie, removeCartItemsFromCookie, + quantityUpdateState, + getCartDataFromCookie, + setCartDataToCookie, } from '~/utils/cart'; + import { toast } from 'react-hot-toast'; type Props = { @@ -30,25 +34,24 @@ const CartItemAction = ({ item }: Props) => { const [quantity, setQuantity] = useState<number>(item.quantity); - const { loadCart, cart, updateCartItem } = useCartStore(); // TAMBAHKAN cart dan updateCartItem + const { loadCart, cart, updateCartItem } = useCartStore(); const limitQty = item.limit_qty?.transaction || 0; - // PERBAIKI FUNCTION INI const handleDelete = async () => { if (typeof auth !== 'object') return; setIsLoadDelete(true); try { - // Step 1: Delete from server + // Delete from server await deleteUserCart(auth.id, [item.cart_id]); - // Step 2: Clean up cookies IMMEDIATELY + // Clean up cookies immediately removeSelectedItemsFromCookie([item.id]); removeCartItemsFromCookie([item.cart_id]); - // Step 3: Update local cart state optimistically + // Update local cart state optimistically if (cart) { const updatedProducts = cart.products.filter( (product) => product.id !== item.id @@ -61,7 +64,7 @@ const CartItemAction = ({ item }: Props) => { updateCartItem(updatedCart); } - // Step 4: Reload from server to ensure consistency + // Reload from server and refresh context await loadCart(auth.id); setRefreshCart(true); @@ -77,12 +80,47 @@ const CartItemAction = ({ item }: Props) => { } }; + const updateQuantityInCookie = (productId, cartId, newQuantity) => { + try { + const cartData = getCartDataFromCookie(); + let itemFound = false; + + // Find item by cart_id key or search within objects + if (cartData[cartId]) { + cartData[cartId].quantity = newQuantity; + itemFound = true; + } else { + // Search by product id or cart_id within objects + for (const key in cartData) { + const item = cartData[key]; + if (item.id === productId || item.cart_id === cartId) { + item.quantity = newQuantity; + itemFound = true; + break; + } + } + } + + if (itemFound) { + setCartDataToCookie(cartData); + return true; + } + + return false; + } catch (error) { + console.error('Error updating quantity in cookie:', error); + return false; + } + }; + const decreaseQty = () => { setQuantity((quantity) => (quantity -= 1)); }; + const increaseQty = () => { setQuantity((quantity) => (quantity += 1)); }; + const debounceQty = useDebounce(quantity, 1000); useEffect(() => { @@ -93,18 +131,73 @@ const CartItemAction = ({ item }: Props) => { useEffect(() => { const updateCart = async () => { if (typeof auth !== 'object' || isNaN(debounceQty)) return; + if (debounceQty === item.quantity) return; + quantityUpdateState.startUpdate(item.id); setIsLoadQuantity(true); - await upsertUserCart({ - userId: auth.id, - type: item.cart_type, - id: item.id, - qty: debounceQty, - selected: item.selected, - }); - await loadCart(auth.id); - setIsLoadQuantity(false); + + try { + // Update cookie immediately for responsive UI + updateQuantityInCookie(item.id, item.cart_id, debounceQty); + + // Update local cart state optimistically + if (cart) { + const updatedProducts = cart.products.map((product) => + product.id === item.id + ? { ...product, quantity: debounceQty } + : product + ); + const updatedCart = { + ...cart, + products: updatedProducts, + }; + updateCartItem(updatedCart); + } + + // Send update to server + await upsertUserCart({ + userId: auth.id, + type: item.cart_type, + id: item.id, + qty: debounceQty, + selected: item.selected, + }); + + // Reload from server to ensure consistency + await loadCart(auth.id); + + // Re-update cookie if server reload overwrote it + const currentCookieData = getCartDataFromCookie(); + let needsReUpdate = false; + + for (const key in currentCookieData) { + const cookieItem = currentCookieData[key]; + if ( + (cookieItem.id === item.id || + cookieItem.cart_id === item.cart_id) && + cookieItem.quantity !== debounceQty + ) { + needsReUpdate = true; + break; + } + } + + if (needsReUpdate) { + updateQuantityInCookie(item.id, item.cart_id, debounceQty); + } + } catch (error) { + console.error('Error updating quantity:', error); + toast.error('Gagal mengupdate quantity'); + + // Revert changes on error + updateQuantityInCookie(item.id, item.cart_id, item.quantity); + loadCart(auth.id); + } finally { + setIsLoadQuantity(false); + quantityUpdateState.endUpdate(item.id); + } }; + updateCart(); //eslint-disable-next-line react-hooks/exhaustive-deps }, [debounceQty]); @@ -156,4 +249,4 @@ const CartItemAction = ({ item }: Props) => { ); }; -export default CartItemAction; +export default CartItemAction;
\ No newline at end of file |
