refactor calculation code

- implement fee
- centralize the code
This commit is contained in:
2025-10-27 08:08:22 +03:00
parent 251e7a9369
commit cd49a3756f
13 changed files with 395 additions and 284 deletions

View File

@@ -9,6 +9,7 @@ interface ArabicPriceProps {
strong?: boolean;
type?: "secondary" | "success" | "warning" | "danger";
className?: string;
hideCurrency?: boolean;
}
const ArabicPrice: React.FC<ArabicPriceProps> = ({
@@ -17,6 +18,7 @@ const ArabicPrice: React.FC<ArabicPriceProps> = ({
strong = false,
type,
className,
hideCurrency = false,
}) => {
const { t } = useTranslation();
const { isRTL } = useAppSelector((state) => state.locale);
@@ -32,12 +34,12 @@ const ArabicPrice: React.FC<ArabicPriceProps> = ({
style={{
display: "inline-flex",
alignItems: "baseline",
gap: "0.1em",
gap: "0.2em",
lineHeight: 1,
...style,
}}
>
{isRTL ? (
{isRTL && !hideCurrency ? (
<>
<span
style={{
@@ -47,7 +49,6 @@ const ArabicPrice: React.FC<ArabicPriceProps> = ({
>
{formattedPrice}
</span>
<span style={{margin: "0 0.1em"}} />
<span
style={{
fontSize: "0.9em",
@@ -60,7 +61,7 @@ const ArabicPrice: React.FC<ArabicPriceProps> = ({
{t("common.omanCurrency")}
</span>
</>
) : (
) : !hideCurrency ? (
<>
<span
style={{
@@ -82,6 +83,8 @@ const ArabicPrice: React.FC<ArabicPriceProps> = ({
{t("common.omanCurrency")}
</span>
</>
) : (
<>{formattedPrice}</>
)}
</ProText>
);

View File

@@ -3,11 +3,13 @@ import ArabicPrice from "components/ArabicPrice";
import {
selectCart,
selectCartTotal,
selectCartTotalWithLoyaltyDiscount,
selectGrandTotal,
selectHighestPricedLoyaltyItem,
selectLoyaltyValidation,
selectTaxAmount,
updateUseLoyaltyPoints,
} from "features/order/orderSlice";
import { OrderType } from "pages/checkout/hooks/types";
import { useTranslation } from "react-i18next";
import { useGetRestaurantDetailsQuery } from "redux/api/others";
import { useAppDispatch, useAppSelector } from "redux/hooks";
@@ -18,19 +20,15 @@ import styles from "./OrderSummary.module.css";
export default function OrderSummary() {
const { t } = useTranslation();
const { useLoyaltyPoints } = useAppSelector(selectCart);
const { data: restaurant } = useGetRestaurantDetailsQuery("595");
const { orderType } = useAppSelector(selectCart);
const dispatch = useAppDispatch();
const subtotal = useAppSelector(selectCartTotal);
const subtotalWithLoyaltyDiscount = useAppSelector(
selectCartTotalWithLoyaltyDiscount,
);
const loyaltyValidation = useAppSelector(selectLoyaltyValidation);
const highestLoyaltyItem = useAppSelector(selectHighestPricedLoyaltyItem);
const taxAmount = useAppSelector(selectTaxAmount);
const grandTotal = useAppSelector(selectGrandTotal);
const tax = subtotalWithLoyaltyDiscount * 0.1; // 10% tax on discounted amount
const total = subtotalWithLoyaltyDiscount + tax;
const loyaltyDiscountAmount = subtotal - subtotalWithLoyaltyDiscount;
const { data: restaurant } = useGetRestaurantDetailsQuery("595");
const isHasLoyaltyGift =
(restaurant?.loyalty_stamps ?? 0) -
(restaurant?.customer_loyalty_points ?? 0) <=
@@ -46,20 +44,24 @@ export default function OrderSummary() {
<ProText type="secondary">{t("cart.basketTotal")}</ProText>
<ArabicPrice price={subtotal} />
</div>
{orderType != OrderType.DineIn && <div className={styles.summaryRow}>
<ProText type="secondary">{t("cart.deliveryFee")}</ProText>
<ArabicPrice price={Number(restaurant?.delivery_fees || 0)} />
</div>}
<div className={styles.summaryRow}>
<ProText type="secondary">{t("cart.discount")}</ProText>
<ArabicPrice price={loyaltyDiscountAmount} />
<ArabicPrice price={highestLoyaltyItem?.price || 0} />
</div>
<div className={styles.summaryRow}>
<ProText type="secondary">{t("cart.riderTip")}</ProText>
<ArabicPrice price={tax} />
<ProText type="secondary">{t("cart.tax")}</ProText>
<ArabicPrice price={taxAmount || 0} />
</div>
<Divider className={styles.summaryDivider} />
<div className={`${styles.summaryRow} ${styles.totalRow}`}>
<ProText strong type="secondary">
{t("cart.totalAmount")}
</ProText>
<ArabicPrice price={total} strong />
<ArabicPrice price={grandTotal} />
</div>
</Space>
@@ -88,7 +90,7 @@ export default function OrderSummary() {
<div style={{ marginTop: 8, color: "green", fontSize: "12px" }}>
{t("cart.loyaltyDiscountApplied", {
itemName: highestLoyaltyItem.name,
amount: Math.round(loyaltyDiscountAmount).toFixed(2),
amount: Math.round(highestLoyaltyItem.price || 0).toFixed(2),
})}
</div>
)}

View File

@@ -3,7 +3,11 @@ import { Group } from "antd/es/radio";
import ArabicPrice from "components/ArabicPrice";
import DifferentCardIcon from "components/Icons/paymentMethods/DifferentCardIcon";
import ProText from "components/ProText";
import { selectCart, updatePaymentMethod } from "features/order/orderSlice";
import {
selectCart,
selectGrandTotal,
updatePaymentMethod,
} from "features/order/orderSlice";
import { useTranslation } from "react-i18next";
import { useAppDispatch, useAppSelector } from "redux/hooks";
import { colors, ProGray1 } from "../../ThemeConstants";
@@ -14,6 +18,7 @@ const PaymentMethods = () => {
const { t } = useTranslation();
const { paymentMethod, orderType } = useAppSelector(selectCart);
const dispatch = useAppDispatch();
const grandTotal = useAppSelector(selectGrandTotal);
const options: {
label: string;
@@ -21,26 +26,35 @@ const PaymentMethods = () => {
price?: string;
icon?: React.ReactNode;
style?: React.CSSProperties;
hideCurrency?: boolean;
}[] = [
...(orderType !== "gift"
? [
{
label: t("checkout.creditDebitCard"),
value: "creditDebitCard",
price: t("checkout.expiresIn") + ":12/26",
label: t("checkout.cash"),
value: "cash",
price: grandTotal.toString(),
style: {
color: colors.primary,
},
},
]
: []),
{
label: t("checkout.creditDebitCard"),
value: "creditDebitCard",
price: t("checkout.expiresIn") + ":12/26",
hideCurrency: true,
},
{
label: t("checkout.differentCard"),
value: "differentCard",
icon: (
<div className={styles.differentCardIcon}>
{" "}
<DifferentCardIcon />
</div>
),
hideCurrency: true,
},
{
label: t("checkout.fascanoWallet"),
@@ -108,6 +122,7 @@ const PaymentMethods = () => {
{!option.icon ? (
<ArabicPrice
price={option.price || 0}
hideCurrency={option.hideCurrency}
style={{
fontSize: "0.75rem",
color: ProGray1,