summaryrefslogtreecommitdiff
path: root/src-migrate/modules/cart/components/ItemAction.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src-migrate/modules/cart/components/ItemAction.tsx')
-rw-r--r--src-migrate/modules/cart/components/ItemAction.tsx125
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