summaryrefslogtreecommitdiff
path: root/src-migrate/modules/cart/components/Summary.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src-migrate/modules/cart/components/Summary.tsx')
-rw-r--r--src-migrate/modules/cart/components/Summary.tsx201
1 files changed, 169 insertions, 32 deletions
diff --git a/src-migrate/modules/cart/components/Summary.tsx b/src-migrate/modules/cart/components/Summary.tsx
index 0af5ab18..68db6323 100644
--- a/src-migrate/modules/cart/components/Summary.tsx
+++ b/src-migrate/modules/cart/components/Summary.tsx
@@ -1,20 +1,19 @@
-import style from '../styles/summary.module.css'
-
-import React from 'react'
-import formatCurrency from '~/libs/formatCurrency'
-import clsxm from '~/libs/clsxm'
-import { Skeleton } from '@chakra-ui/react'
-import _ from 'lodash'
+import style from '../styles/summary.module.css';
+import React, { useEffect, useState, useMemo } from 'react';
+import formatCurrency from '~/libs/formatCurrency';
+import clsxm from '~/libs/clsxm';
+import { Skeleton, Box, useColorModeValue, Text } from '@chakra-ui/react';
type Props = {
- total?: number
- discount?: number
- subtotal?: number
- tax?: number
- shipping?: number
- grandTotal?: number
- isLoaded: boolean
-}
+ total?: number;
+ discount?: number;
+ subtotal?: number;
+ tax?: number;
+ shipping?: number;
+ grandTotal?: number;
+ isLoaded: boolean;
+ products?: any[]; // Added to detect changes in selected products
+};
const CartSummary = ({
total,
@@ -24,53 +23,191 @@ const CartSummary = ({
shipping,
grandTotal,
isLoaded = false,
+ products = [],
}: Props) => {
- const PPN : number = process.env.NEXT_PUBLIC_PPN ? parseFloat(process.env.NEXT_PUBLIC_PPN) : 0;
- return (
- <>
- <div className='text-h-sm font-medium'>Ringkasan Pesanan</div>
+ const PPN: number = process.env.NEXT_PUBLIC_PPN
+ ? parseFloat(process.env.NEXT_PUBLIC_PPN)
+ : 0;
+ const [isMounted, setIsMounted] = useState(false);
+
+ // Local state to store calculated values
+ const [summaryValues, setSummaryValues] = useState({
+ subtotal: 0,
+ discount: 0,
+ total: 0,
+ tax: 0,
+ shipping: 0,
+ grandTotal: 0,
+ });
+
+ // This fixes hydration issues by ensuring the component only renders fully after mounting
+ useEffect(() => {
+ setIsMounted(true);
+ }, []);
+
+ // Calculate summary based on products whenever products change
+ useMemo(() => {
+ if (!products || products.length === 0) return;
+
+ // Only count selected products
+ const selectedProducts = products.filter((product) => product.selected);
+
+ // Calculate values based on selected products
+ let calculatedSubtotal = 0;
+ let calculatedDiscount = 0;
+
+ selectedProducts.forEach((product) => {
+ // Get raw price and discount from product
+ const productBasePrice = product.price?.price || 0;
+ const productQty = product.quantity || 1;
+ const productDiscountedPrice =
+ product.price?.price_discount || productBasePrice;
+ const productDiscount = productBasePrice - productDiscountedPrice;
+
+ calculatedSubtotal += productBasePrice * productQty;
+ calculatedDiscount += productDiscount * productQty;
+ });
+
+ const calculatedTotal = calculatedSubtotal - calculatedDiscount;
+ const calculatedTax = calculatedTotal * (PPN - 1);
+ const calculatedShipping = shipping || 0;
+ const calculatedGrandTotal =
+ calculatedTotal + calculatedTax + calculatedShipping;
+
+ // If calculated values are different from props, use calculated ones
+ const shouldUpdateValues =
+ Math.abs((subtotal || 0) - calculatedSubtotal) > 0.01 ||
+ Math.abs((discount || 0) - calculatedDiscount) > 0.01 ||
+ Math.abs((total || 0) - calculatedTotal) > 0.01 ||
+ Math.abs((tax || 0) - calculatedTax) > 0.01 ||
+ Math.abs((grandTotal || 0) - calculatedGrandTotal) > 0.01;
- <div className="h-6" />
+ if (shouldUpdateValues && isLoaded) {
+ setSummaryValues({
+ subtotal: calculatedSubtotal,
+ discount: calculatedDiscount,
+ total: calculatedTotal,
+ tax: calculatedTax,
+ shipping: calculatedShipping,
+ grandTotal: calculatedGrandTotal,
+ });
+ } else if (isLoaded) {
+ // Use values from props when available
+ setSummaryValues({
+ subtotal: subtotal || 0,
+ discount: discount || 0,
+ total: total || 0,
+ tax: tax || 0,
+ shipping: shipping || 0,
+ grandTotal: grandTotal || 0,
+ });
+ }
+ }, [
+ products,
+ isLoaded,
+ subtotal,
+ discount,
+ total,
+ tax,
+ shipping,
+ grandTotal,
+ PPN,
+ ]);
+
+ // Update local values whenever props change
+ useEffect(() => {
+ if (isLoaded) {
+ setSummaryValues({
+ subtotal: subtotal || 0,
+ discount: discount || 0,
+ total: total || 0,
+ tax: tax || 0,
+ shipping: shipping || 0,
+ grandTotal: grandTotal || 0,
+ });
+ }
+ }, [isLoaded, subtotal, discount, total, tax, shipping, grandTotal]);
+
+ if (!isMounted) {
+ return (
+ <Box p={4} borderWidth='1px' borderRadius='lg' boxShadow='sm'>
+ <Text fontSize='lg' fontWeight='medium' mb={4}>
+ Ringkasan Pesanan
+ </Text>
+ {Array(6)
+ .fill(0)
+ .map((_, index) => (
+ <Skeleton key={index} height='24px' my={2} />
+ ))}
+ </Box>
+ );
+ }
+
+ // Use local state for rendering to ensure responsiveness
+ const {
+ subtotal: displaySubtotal,
+ discount: displayDiscount,
+ total: displayTotal,
+ tax: displayTax,
+ shipping: displayShipping,
+ grandTotal: displayGrandTotal,
+ } = summaryValues;
+
+ return (
+ <div className={style.summaryContainer}>
+ <Text fontSize='lg' fontWeight='medium' mb={4}>
+ Ringkasan Pesanan
+ </Text>
<div className='flex flex-col gap-y-3'>
<Skeleton isLoaded={isLoaded} className={style.line}>
<span className={style.label}>Total Belanja</span>
- <span className={style.value}>Rp {formatCurrency(subtotal || 0)}</span>
+ <span className={style.value}>
+ Rp {formatCurrency(displaySubtotal)}
+ </span>
</Skeleton>
<Skeleton isLoaded={isLoaded} className={style.line}>
<span className={style.label}>Total Diskon</span>
- <span className={clsxm(style.value, style.discount)}>- Rp {formatCurrency(discount || 0)}</span>
+ <span className={clsxm(style.value, style.discount)}>
+ - Rp {formatCurrency(displayDiscount)}
+ </span>
</Skeleton>
<div className={style.divider} />
<Skeleton isLoaded={isLoaded} className={style.line}>
<span className={style.label}>Subtotal</span>
- <span className={style.value}>Rp {formatCurrency(total || 0)}</span>
+ <span className={style.value}>Rp {formatCurrency(displayTotal)}</span>
</Skeleton>
<Skeleton isLoaded={isLoaded} className={style.line}>
- <span className={style.label}>Tax {((PPN - 1) * 100).toFixed(0)}%</span>
- <span className={style.value}>Rp {formatCurrency(tax || 0)}</span>
+ <span className={style.label}>
+ Tax {((PPN - 1) * 100).toFixed(0)}%
+ </span>
+ <span className={style.value}>Rp {formatCurrency(displayTax)}</span>
</Skeleton>
<Skeleton isLoaded={isLoaded} className={style.line}>
<span className={style.label}>Biaya Kirim</span>
- <span className={style.value}>Rp {formatCurrency(shipping || 0)}</span>
+ <span className={style.value}>
+ Rp {formatCurrency(displayShipping)}
+ </span>
</Skeleton>
<div className={style.divider} />
- <Skeleton isLoaded={isLoaded} className={style.line}>
+ <Skeleton isLoaded={isLoaded}>
<span className={clsxm(style.label, style.grandTotal)}>
Grand Total
</span>
- <span className={style.value}>Rp {formatCurrency(grandTotal || 0)}</span>
+ <span className={clsxm(style.value, style.grandTotalValue)}>
+ Rp {formatCurrency(displayGrandTotal)}
+ </span>
</Skeleton>
</div>
- </>
- )
-}
+ </div>
+ );
+};
-export default CartSummary \ No newline at end of file
+export default CartSummary;