From 3feaad9127ff429b27f0eb69fa6ea539de2f2e8c Mon Sep 17 00:00:00 2001
From: Miqdad <ahmadmiqdad27@gmail.com>
Date: Mon, 26 May 2025 20:00:17 +0700
Subject: <miqdad> Cleaning code

---
 src-migrate/pages/shop/cart/index.tsx | 380 ++++++++++++----------------------
 1 file changed, 135 insertions(+), 245 deletions(-)

(limited to 'src-migrate/pages/shop/cart/index.tsx')

diff --git a/src-migrate/pages/shop/cart/index.tsx b/src-migrate/pages/shop/cart/index.tsx
index 798ad318..03854d79 100644
--- a/src-migrate/pages/shop/cart/index.tsx
+++ b/src-migrate/pages/shop/cart/index.tsx
@@ -2,15 +2,7 @@ import style from './cart.module.css';
 
 import React, { useEffect, useMemo, useState } from 'react';
 import Link from 'next/link';
-import {
-  Button,
-  Checkbox,
-  Spinner,
-  Tooltip,
-  Text,
-  Box,
-  Flex,
-} from '@chakra-ui/react';
+import { Button, Checkbox, Spinner, Tooltip } from '@chakra-ui/react';
 import { toast } from 'react-hot-toast';
 import { useRouter } from 'next/router';
 import { getAuth } from '~/libs/auth';
@@ -27,171 +19,65 @@ import { Trash2Icon } from 'lucide-react';
 import { useProductCartContext } from '@/contexts/ProductCartContext';
 import {
   getSelectedItemsFromCookie,
-  setSelectedItemsToCookie,
   syncSelectedItemsWithCookie,
   setAllSelectedInCookie,
   removeSelectedItemsFromCookie,
-  forceResetAllSelectedItems,
+  removeCartItemsFromCookie,
   checkboxUpdateState,
+  quantityUpdateState,
 } from '~/utils/cart';
 
-// Special ID for the "select all" checkbox
 const SELECT_ALL_ID = 'select_all_checkbox';
 
 const CartPage = () => {
   const router = useRouter();
   const auth = getAuth();
   const [isStepApproval, setIsStepApproval] = useState(false);
-  const [isLoad, setIsLoad] = useState<boolean>(false);
   const [isLoadDelete, setIsLoadDelete] = useState<boolean>(false);
   const { loadCart, cart, summary, updateCartItem } = useCartStore();
   const device = useDevice();
   const { setRefreshCart } = useProductCartContext();
   const [isTop, setIsTop] = useState(true);
   const [isUpdating, setIsUpdating] = useState(false);
-  const [isStateMismatch, setIsStateMismatch] = useState(false);
   const [isAnyCheckboxUpdating, setIsAnyCheckboxUpdating] = useState(false);
+  const [isAnyQuantityUpdating, setIsAnyQuantityUpdating] = useState(false);
 
-  // Subscribe to checkbox update state changes
+  // Subscribe to update state changes
   useEffect(() => {
-    const handleUpdateStateChange = (isUpdating) => {
+    const handleCheckboxUpdate = (isUpdating) =>
       setIsAnyCheckboxUpdating(isUpdating);
-    };
+    const handleQuantityUpdate = (isUpdating) =>
+      setIsAnyQuantityUpdating(isUpdating);
 
-    // Add listener for checkbox update state changes
-    checkboxUpdateState.addListener(handleUpdateStateChange);
+    checkboxUpdateState.addListener(handleCheckboxUpdate);
+    quantityUpdateState.addListener(handleQuantityUpdate);
 
-    // Cleanup listener on component unmount
     return () => {
-      checkboxUpdateState.removeListener(handleUpdateStateChange);
+      checkboxUpdateState.removeListener(handleCheckboxUpdate);
+      quantityUpdateState.removeListener(handleQuantityUpdate);
     };
   }, []);
 
-  // Function to check if cart state is inconsistent
-  const checkCartStateMismatch = () => {
-    if (!cart || !cart.products || isUpdating) return false;
-
-    try {
-      // Ambil status selected dari cookie
-      const selectedItems = getSelectedItemsFromCookie();
-
-      // Periksa ketidaksesuaian antara UI dan cookie
-      // 1. Periksa item yang selected di UI tapi tidak di cookie
-      for (const product of cart.products) {
-        const cookieState = selectedItems[product.id];
-
-        // Jika ada di cookie tapi tidak sama dengan UI
-        if (cookieState !== undefined && cookieState !== product.selected) {
-          return true;
-        }
-
-        // Jika tidak ada di cookie tapi selected di UI
-        if (cookieState === undefined && product.selected) {
-          return true;
-        }
-      }
-
-      // 2. Periksa item yang selected di cookie tapi tidak ada di cart
-      for (const productId in selectedItems) {
-        const isSelected = selectedItems[productId];
-        if (isSelected) {
-          // Cek apakah product id ini ada di cart
-          const productExists = cart.products.some(
-            (p) => p.id.toString() === productId.toString()
-          );
-          if (!productExists) {
-            // Ada item selected di cookie yang tidak ada di cart
-            return true;
-          }
-        }
-      }
-
-      return false;
-    } catch (error) {
-      console.error('Error checking cart state mismatch:', error);
-      return false;
-    }
-  };
-
-  // Function to reset all selected items when state is inconsistent
-  const handleResetSelections = () => {
-    if (!cart) return;
-
-    setIsUpdating(true);
-
-    try {
-      // Use the forceResetSelection function from the store
-      useCartStore.getState().forceResetSelection();
-
-      // Set state back to normal
-      setIsStateMismatch(false);
-
-      // Give visual feedback
-      toast.success('Semua pilihan telah direset');
-
-      // Optional: Sync with server if needed
-      if (typeof auth === 'object') {
-        const updatePromises = cart.products.map((item) =>
-          upsertUserCart({
-            userId: auth.id,
-            type: item.cart_type,
-            id: item.id,
-            qty: item.quantity,
-            selected: false,
-            purchase_tax_id: item.purchase_tax_id || null, // Fix integer field issue
-          })
-        );
-
-        Promise.all(updatePromises)
-          .then(() => loadCart(auth.id))
-          .catch((error) => {
-            console.error('Error updating selections to server:', error);
-          })
-          .finally(() => {
-            setIsUpdating(false);
-          });
-      } else {
-        setIsUpdating(false);
-      }
-    } catch (error) {
-      console.error('Error resetting selections:', error);
-      setIsUpdating(false);
-      toast.error('Gagal mereset pilihan');
-    }
-  };
-
-  // Check for state inconsistency
-  useEffect(() => {
-    if (!cart || !cart.products || isUpdating) return;
-
-    const hasMismatch = checkCartStateMismatch();
-    setIsStateMismatch(hasMismatch);
-  }, [cart, isUpdating]);
-
+  // Handle scroll for sticky header styling
   useEffect(() => {
-    const handleScroll = () => {
-      setIsTop(window.scrollY < 200);
-    };
+    const handleScroll = () => setIsTop(window.scrollY < 200);
 
     window.addEventListener('scroll', handleScroll);
-    return () => {
-      window.removeEventListener('scroll', handleScroll);
-    };
+    return () => window.removeEventListener('scroll', handleScroll);
   }, []);
 
+  // Initialize cart and sync with cookies
   useEffect(() => {
-    const loadCartWithStorage = async () => {
+    const initializeCart = async () => {
       if (typeof auth === 'object' && !cart) {
         await loadCart(auth.id);
         setIsStepApproval(auth?.feature?.soApproval);
 
-        // Sync selected items with server data using cookies
         if (cart?.products) {
           const { items, needsUpdate } = syncSelectedItemsWithCookie(
             cart.products
           );
 
-          // If there's a mismatch between cookie and server data, update the UI
           if (needsUpdate) {
             const updatedCart = {
               ...cart,
@@ -207,37 +93,47 @@ const CartPage = () => {
       }
     };
 
-    loadCartWithStorage();
-  }, [auth, cart]);
+    initializeCart();
+  }, [auth, cart, loadCart, updateCartItem]);
 
+  // Computed values
   const hasSelectedPromo = useMemo(() => {
-    if (!cart) return false;
-    return cart?.products?.some(
-      (item) => item.cart_type === 'promotion' && item.selected
+    return (
+      cart?.products?.some(
+        (item) => item.cart_type === 'promotion' && item.selected
+      ) || false
     );
   }, [cart]);
 
   const hasSelected = useMemo(() => {
-    if (!cart) return false;
-    return cart?.products?.some((item) => item.selected);
+    return cart?.products?.some((item) => item.selected) || false;
   }, [cart]);
 
   const hasSelectNoPrice = useMemo(() => {
-    if (!cart) return false;
-    return cart?.products?.some(
-      (item) => item.selected && item.price.price_discount === 0
+    return (
+      cart?.products?.some(
+        (item) => item.selected && item.price.price_discount === 0
+      ) || false
     );
   }, [cart]);
 
   const hasSelectedAll = useMemo(() => {
-    if (!cart || !Array.isArray(cart.products)) return false;
-    return (
-      cart.products.length > 0 && cart.products.every((item) => item.selected)
-    );
+    if (!cart?.products?.length) return false;
+    return cart.products.every((item) => item.selected);
   }, [cart]);
 
+  // Button states
+  const areButtonsDisabled =
+    isUpdating ||
+    isLoadDelete ||
+    isAnyCheckboxUpdating ||
+    isAnyQuantityUpdating;
+  const isSelectAllDisabled =
+    isUpdating || checkboxUpdateState.isCheckboxUpdating(SELECT_ALL_ID);
+
+  // Handlers
   const handleCheckout = () => {
-    if (isUpdating || isLoadDelete || isAnyCheckboxUpdating) {
+    if (areButtonsDisabled) {
       toast.error('Harap tunggu pembaruan selesai');
       return;
     }
@@ -245,7 +141,7 @@ const CartPage = () => {
   };
 
   const handleQuotation = () => {
-    if (isUpdating || isLoadDelete || isAnyCheckboxUpdating) {
+    if (areButtonsDisabled) {
       toast.error('Harap tunggu pembaruan selesai');
       return;
     }
@@ -256,16 +152,14 @@ const CartPage = () => {
     }
   };
 
-  const handleChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
-    if (cart && !isUpdating && typeof auth === 'object') {
-      const newSelectedState = !hasSelectedAll;
+  const handleSelectAll = async (e: React.ChangeEvent<HTMLInputElement>) => {
+    if (!cart || isUpdating || typeof auth !== 'object') return;
 
-      // Set updating flag
-      setIsUpdating(true);
-
-      // Notify checkbox update state system with the special select all ID
-      checkboxUpdateState.startUpdate(SELECT_ALL_ID);
+    const newSelectedState = !hasSelectedAll;
+    setIsUpdating(true);
+    checkboxUpdateState.startUpdate(SELECT_ALL_ID);
 
+    try {
       // Update UI immediately
       const updatedCart = {
         ...cart,
@@ -274,54 +168,47 @@ const CartPage = () => {
           selected: newSelectedState,
         })),
       };
-
       updateCartItem(updatedCart);
 
-      // Get all product IDs in cart
+      // Update cookies
       const productIds = cart.products.map((item) => item.id);
+      setAllSelectedInCookie(productIds, newSelectedState, false);
+
+      // Update server
+      const updatePromises = cart.products.map((item) =>
+        upsertUserCart({
+          userId: auth.id,
+          type: item.cart_type,
+          id: item.id,
+          qty: item.quantity,
+          selected: newSelectedState,
+          purchase_tax_id: item.purchase_tax_id || null,
+        })
+      );
 
-      // Update cookies immediately for responsive UI
-      setAllSelectedInCookie(productIds, newSelectedState, false); // We're already notifying
-
-      try {
-        // Update all items on server in background
-        const updatePromises = cart.products.map((item) =>
-          upsertUserCart({
-            userId: auth.id,
-            type: item.cart_type,
-            id: item.id,
-            qty: item.quantity,
-            selected: newSelectedState,
-            purchase_tax_id: item.purchase_tax_id || null, // Fix integer field issue
-          })
-        );
-
-        await Promise.all(updatePromises);
-        await loadCart(auth.id);
-      } catch (error) {
-        console.error('Error updating select all:', error);
-
-        // Revert changes on error
-        const revertedCart = {
-          ...cart,
-          products: cart.products.map((item) => ({
-            ...item,
-            selected: !newSelectedState,
-          })),
-        };
-
-        updateCartItem(revertedCart);
-
-        // Revert cookies
-        setAllSelectedInCookie(productIds, !newSelectedState, false);
-
-        toast.error('Gagal memperbarui pilihan');
-      } finally {
-        setIsUpdating(false);
+      await Promise.all(updatePromises);
+      await loadCart(auth.id);
+    } catch (error) {
+      console.error('Error updating select all:', error);
+      toast.error('Gagal memperbarui pilihan');
 
-        // End update notification
-        checkboxUpdateState.endUpdate(SELECT_ALL_ID);
-      }
+      // Revert on error
+      const revertedCart = {
+        ...cart,
+        products: cart.products.map((item) => ({
+          ...item,
+          selected: !newSelectedState,
+        })),
+      };
+      updateCartItem(revertedCart);
+      setAllSelectedInCookie(
+        cart.products.map((item) => item.id),
+        !newSelectedState,
+        false
+      );
+    } finally {
+      setIsUpdating(false);
+      checkboxUpdateState.endUpdate(SELECT_ALL_ID);
     }
   };
 
@@ -336,12 +223,12 @@ const CartPage = () => {
       const itemIdsToDelete = itemsToDelete.map((item) => item.id);
       const cartIdsToDelete = itemsToDelete.map((item) => item.cart_id);
 
-      // Step 1: Delete from server first
+      // Delete from server
       for (const item of itemsToDelete) {
         await deleteUserCart(auth.id, [item.cart_id]);
       }
 
-      // Step 2: Update local cart state immediately (optimistic update)
+      // Update local state optimistically
       const updatedProducts = cart.products.filter((item) => !item.selected);
       const updatedCart = {
         ...cart,
@@ -350,30 +237,20 @@ const CartPage = () => {
       };
       updateCartItem(updatedCart);
 
-      // Step 3: Clean up cookies AFTER state update
+      // Clean up cookies
       removeSelectedItemsFromCookie(itemIdsToDelete);
       removeCartItemsFromCookie(cartIdsToDelete);
 
-      // Step 4: Reload from server to ensure consistency (but don't wait for it to complete UI update)
-      loadCart(auth.id)
-        .then(() => {
-          console.log('Cart reloaded from server');
-        })
-        .catch((error) => {
-          console.error('Error reloading cart:', error);
-          // If reload fails, at least we have the optimistic update
-        });
+      // Reload from server
+      loadCart(auth.id).catch((error) =>
+        console.error('Error reloading cart:', error)
+      );
 
-      // Step 5: Trigger context refresh
       setRefreshCart(true);
-
-      // Success feedback
       toast.success('Item berhasil dihapus');
     } catch (error) {
       console.error('Failed to delete cart items:', error);
       toast.error('Gagal menghapus item');
-
-      // If deletion failed, reload cart to restore proper state
       loadCart(auth.id);
     } finally {
       setIsLoadDelete(false);
@@ -381,16 +258,41 @@ const CartPage = () => {
     }
   };
 
-  // Check if buttons should be disabled
-  const areButtonsDisabled =
-    isUpdating || isLoadDelete || isAnyCheckboxUpdating;
+  // Tooltip messages
+  const getTooltipMessage = () => {
+    if (isAnyQuantityUpdating) return 'Harap tunggu update quantity selesai';
+    if (isAnyCheckboxUpdating) return 'Harap tunggu pembaruan checkbox selesai';
+    if (isLoadDelete) return 'Harap tunggu penghapusan selesai';
+    if (isUpdating) return 'Harap tunggu pembaruan selesai';
+    return '';
+  };
 
-  // Only disable the select all checkbox if it specifically is updating
-  const isSelectAllDisabled =
-    isUpdating || checkboxUpdateState.isCheckboxUpdating(SELECT_ALL_ID);
+  const getQuotationTooltip = () => {
+    const baseMessage = getTooltipMessage();
+    if (baseMessage) return baseMessage;
+    if (hasSelectedPromo) return 'Barang promo tidak dapat dibuat quotation';
+    if (!hasSelected) return 'Tidak ada item yang dipilih';
+    return '';
+  };
+
+  const getCheckoutTooltip = () => {
+    const baseMessage = getTooltipMessage();
+    if (baseMessage) return baseMessage;
+    if (!hasSelected) return 'Tidak ada item yang dipilih';
+    if (hasSelectNoPrice) return 'Terdapat item yang tidak ada harga';
+    return '';
+  };
+
+  const getDeleteTooltip = () => {
+    const baseMessage = getTooltipMessage();
+    if (baseMessage) return baseMessage;
+    if (!hasSelected) return 'Tidak ada item yang dipilih';
+    return '';
+  };
 
   return (
     <>
+      {/* Sticky Header */}
       <div
         className={`${
           isTop ? 'border-b-[0px]' : 'border-b-[1px]'
@@ -408,7 +310,7 @@ const CartPage = () => {
               colorScheme='red'
               size='lg'
               isChecked={hasSelectedAll}
-              onChange={handleChange}
+              onChange={handleSelectAll}
               isDisabled={isSelectAllDisabled}
               opacity={isSelectAllDisabled ? 0.5 : 1}
               cursor={isSelectAllDisabled ? 'not-allowed' : 'pointer'}
@@ -422,13 +324,9 @@ const CartPage = () => {
               {hasSelectedAll ? 'Uncheck all' : 'Select all'}
             </p>
           </div>
+
           <div className='flex items-center object-center'>
-            <Tooltip
-              label={clsxm({
-                'Tidak ada item yang dipilih': !hasSelected,
-                'Harap tunggu pembaruan selesai': areButtonsDisabled,
-              })}
-            >
+            <Tooltip label={getDeleteTooltip()}>
               <Button
                 bg='#fadede'
                 variant='outline'
@@ -447,6 +345,7 @@ const CartPage = () => {
         </div>
       </div>
 
+      {/* Main Content */}
       <div className={style.content}>
         <div className={style['item-wrapper']}>
           <div className={style['item-skeleton']}>
@@ -485,6 +384,8 @@ const CartPage = () => {
             )}
           </div>
         </div>
+
+        {/* Cart Summary */}
         <div
           className={`${style['summary-wrapper']} ${
             device.isMobile && (!cart || cart?.product_total === 0)
@@ -514,13 +415,7 @@ const CartPage = () => {
                   : style['summary-buttons']
               }
             >
-              <Tooltip
-                label={clsxm({
-                  'Barang promo tidak dapat dibuat quotation': hasSelectedPromo,
-                  'Harap tunggu pembaruan selesai': areButtonsDisabled,
-                  'Tidak ada item yang dipilih': !hasSelected,
-                })}
-              >
+              <Tooltip label={getQuotationTooltip()}>
                 <Button
                   colorScheme='yellow'
                   w='full'
@@ -529,18 +424,13 @@ const CartPage = () => {
                   }
                   onClick={handleQuotation}
                 >
-                  {areButtonsDisabled ? <Spinner size='sm' mr={2} /> : null}
+                  {areButtonsDisabled && <Spinner size='sm' mr={2} />}
                   Quotation
                 </Button>
               </Tooltip>
+
               {!isStepApproval && (
-                <Tooltip
-                  label={clsxm({
-                    'Tidak ada item yang dipilih': !hasSelected,
-                    'Terdapat item yang tidak ada harga': hasSelectNoPrice,
-                    'Harap tunggu pembaruan selesai': areButtonsDisabled,
-                  })}
-                >
+                <Tooltip label={getCheckoutTooltip()}>
                   <Button
                     colorScheme='red'
                     w='full'
@@ -549,7 +439,7 @@ const CartPage = () => {
                     }
                     onClick={handleCheckout}
                   >
-                    {areButtonsDisabled ? <Spinner size='sm' mr={2} /> : null}
+                    {areButtonsDisabled && <Spinner size='sm' mr={2} />}
                     Checkout
                   </Button>
                 </Tooltip>
@@ -562,4 +452,4 @@ const CartPage = () => {
   );
 };
 
-export default CartPage;
+export default CartPage;
\ No newline at end of file
-- 
cgit v1.2.3

