diff options
Diffstat (limited to 'src-migrate/modules/cart/components')
| -rw-r--r-- | src-migrate/modules/cart/components/ItemSelect.tsx | 43 | ||||
| -rw-r--r-- | src-migrate/modules/cart/components/Summary.tsx | 28 |
2 files changed, 43 insertions, 28 deletions
diff --git a/src-migrate/modules/cart/components/ItemSelect.tsx b/src-migrate/modules/cart/components/ItemSelect.tsx index 733ee64d..70b656ec 100644 --- a/src-migrate/modules/cart/components/ItemSelect.tsx +++ b/src-migrate/modules/cart/components/ItemSelect.tsx @@ -8,6 +8,7 @@ import { toast } from 'react-hot-toast'; import { getSelectedItemsFromCookie, updateSelectedItemInCookie, + checkboxUpdateState, } from '~/utils/cart'; type Props = { @@ -19,6 +20,20 @@ const CartItemSelect = ({ item }: Props) => { const { updateCartItem, cart, loadCart } = useCartStore(); const [isUpdating, setIsUpdating] = useState<boolean>(false); const [localSelected, setLocalSelected] = useState<boolean>(item.selected); + const [isGlobalUpdating, setIsGlobalUpdating] = useState<boolean>(false); + + // Subscribe to global checkbox update state + useEffect(() => { + const handleUpdateStateChange = (isUpdating) => { + setIsGlobalUpdating(isUpdating); + }; + + checkboxUpdateState.addListener(handleUpdateStateChange); + + return () => { + checkboxUpdateState.removeListener(handleUpdateStateChange); + }; + }, []); // Initialize local state from cookie or server useEffect(() => { @@ -54,7 +69,7 @@ const CartItemSelect = ({ item }: Props) => { setLocalSelected(item.selected); // Save this state to cookie for future use - updateSelectedItemInCookie(item.id, item.selected); + updateSelectedItemInCookie(item.id, item.selected, false); // don't notify for initial sync } }, [item.id, item.selected, localSelected, cart, updateCartItem, isUpdating]); @@ -70,9 +85,12 @@ const CartItemSelect = ({ item }: Props) => { setLocalSelected(newSelectedState); setIsUpdating(true); + // Start the update - notify global state with this checkbox's ID + checkboxUpdateState.startUpdate(item.id); + try { - // Update cookie immediately - updateSelectedItemInCookie(item.id, newSelectedState); + // The cookie update is now handled inside the function with notification + updateSelectedItemInCookie(item.id, newSelectedState, false); // We already started above // Update cart state immediately for UI responsiveness const updatedCartItems = cart.products.map((cartItem) => @@ -91,6 +109,7 @@ const CartItemSelect = ({ item }: Props) => { id: item.id, qty: item.quantity, selected: newSelectedState, + purchase_tax_id: item.purchase_tax_id || null, // Ensure null for numeric fields }); // Reload cart to ensure consistency @@ -102,18 +121,26 @@ const CartItemSelect = ({ item }: Props) => { // Revert local state on error setLocalSelected(!newSelectedState); - // Update cookie back - updateSelectedItemInCookie(item.id, !newSelectedState); + // Revert cookie change + updateSelectedItemInCookie(item.id, !newSelectedState, false); // Reload cart to get server state loadCart(auth.id); } finally { setIsUpdating(false); + + // End the update - notify global state with this checkbox's ID + checkboxUpdateState.endUpdate(item.id); } }, [auth, cart, item, isUpdating, updateCartItem, loadCart] ); + // Determine if THIS specific checkbox should be disabled - only disable + // if this specific checkbox is updating + const isDisabled = + isUpdating || checkboxUpdateState.isCheckboxUpdating(item.id); + return ( <div className='w-6 my-auto relative'> <Checkbox @@ -122,9 +149,9 @@ const CartItemSelect = ({ item }: Props) => { size='lg' isChecked={localSelected} onChange={handleChange} - isDisabled={isUpdating} - opacity={isUpdating ? 0.5 : 1} - cursor={isUpdating ? 'not-allowed' : 'pointer'} + isDisabled={isDisabled} + opacity={isDisabled ? 0.5 : 1} + cursor={isDisabled ? 'not-allowed' : 'pointer'} _disabled={{ opacity: 0.5, cursor: 'not-allowed', diff --git a/src-migrate/modules/cart/components/Summary.tsx b/src-migrate/modules/cart/components/Summary.tsx index b4fbab6b..68db6323 100644 --- a/src-migrate/modules/cart/components/Summary.tsx +++ b/src-migrate/modules/cart/components/Summary.tsx @@ -40,8 +40,6 @@ const CartSummary = ({ grandTotal: 0, }); - const bgHighlight = useColorModeValue('red.50', 'red.900'); - // This fixes hydration issues by ensuring the component only renders fully after mounting useEffect(() => { setIsMounted(true); @@ -156,15 +154,7 @@ const CartSummary = ({ } = summaryValues; return ( - <Box - className={style.summaryContainer} - p={4} - borderWidth='1px' - borderRadius='lg' - boxShadow='sm' - position='sticky' - top='170px' - > + <div className={style.summaryContainer}> <Text fontSize='lg' fontWeight='medium' mb={4}> Ringkasan Pesanan </Text> @@ -208,17 +198,15 @@ const CartSummary = ({ <div className={style.divider} /> <Skeleton isLoaded={isLoaded}> - <Box className={style.line} p={2} borderRadius='md' bg={bgHighlight}> - <span className={clsxm(style.label, style.grandTotal)}> - Grand Total - </span> - <span className={clsxm(style.value, style.grandTotalValue)}> - Rp {formatCurrency(displayGrandTotal)} - </span> - </Box> + <span className={clsxm(style.label, style.grandTotal)}> + Grand Total + </span> + <span className={clsxm(style.value, style.grandTotalValue)}> + Rp {formatCurrency(displayGrandTotal)} + </span> </Skeleton> </div> - </Box> + </div> ); }; |
