summaryrefslogtreecommitdiff
path: root/src-migrate/modules/cart
diff options
context:
space:
mode:
authorMiqdad <ahmadmiqdad27@gmail.com>2025-05-22 10:05:09 +0700
committerMiqdad <ahmadmiqdad27@gmail.com>2025-05-22 10:05:09 +0700
commit09cebc9020c4f1995a73305187bc1576e339d183 (patch)
tree7617d74533d23277690886709fe6b9d68006814d /src-migrate/modules/cart
parent7d4445bb9bad3d6c945503086a07bd882536e5f6 (diff)
<miqdad> disable button when updating checkboxes and change summary design
Diffstat (limited to 'src-migrate/modules/cart')
-rw-r--r--src-migrate/modules/cart/components/ItemSelect.tsx43
-rw-r--r--src-migrate/modules/cart/components/Summary.tsx28
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>
);
};