From cd49a3756f930db4c26447b3331c3224b5939117 Mon Sep 17 00:00:00 2001 From: Mohammed Al-yaseen Date: Mon, 27 Oct 2025 08:08:22 +0300 Subject: [PATCH] refactor calculation code - implement fee - centralize the code --- src/assets/locals/ar.json | 6 +- src/assets/locals/en.json | 6 +- src/components/ArabicPrice/ArabicPrice.tsx | 11 +- src/components/OrderSummary/OrderSummary.tsx | 30 +- .../PaymentMethods/PaymentMethods.tsx | 27 +- src/features/order/orderSlice.ts | 63 ++- src/hooks/useRestaurant.ts | 18 + src/pages/checkout/hooks/types.ts | 464 +++++++++--------- src/pages/checkout/hooks/useOrder.ts | 6 +- src/pages/menu/page.tsx | 4 + src/pages/restaurant/page.tsx | 13 +- .../split-bill/components/PayForActions.tsx | 11 +- .../split-bill/components/PaymentSummary.tsx | 20 +- 13 files changed, 395 insertions(+), 284 deletions(-) create mode 100644 src/hooks/useRestaurant.ts diff --git a/src/assets/locals/ar.json b/src/assets/locals/ar.json index cb18ec9..33737a9 100644 --- a/src/assets/locals/ar.json +++ b/src/assets/locals/ar.json @@ -159,7 +159,7 @@ "browseMenu": "تصفح القائمة", "paymentSummary": "ملخص الدفعة", "subtotal": "المجموع الفرعي", - "tax": "الضريبة (10%)", + "tax": "الضريبة", "remove": "حذف", "proceedToCheckout": "المتابعة إلى الدفع", "totalAmount": "المجموع الكلي", @@ -234,10 +234,12 @@ "useLoyaltyPoints": "استخدام نقاط الولاء", "noLoyaltyItemsInCart": "لا توجد عناصر ولاء في سلة المشتريات", "pleaseAddLoyaltyItems": "يرجى إضافة عناصر ولاء إلى سلة المشتريات لاستخدام نقاط الولاء", - "loyaltyDiscountApplied": "تم تطبيق خصم الولاء: {{itemName}} (خصم {{amount}})" + "loyaltyDiscountApplied": "تم تطبيق خصم الولاء: {{itemName}} (خصم {{amount}})", + "deliveryFee": "رسوم التوصيل" }, "checkout": { "title": "الدفع", + "cash": "كاش", "creditDebitCard": "بطاقة ائتمان/ائتمان", "differentCard": "بطاقة اخرى", "fascanoWallet": "محفظة فاسكانو", diff --git a/src/assets/locals/en.json b/src/assets/locals/en.json index 9e76eb4..185b494 100644 --- a/src/assets/locals/en.json +++ b/src/assets/locals/en.json @@ -171,7 +171,7 @@ "browseMenu": "Browse Menu", "paymentSummary": "Payment Summary", "subtotal": "Subtotal", - "tax": "Tax (10%)", + "tax": "Tax", "remove": "Remove", "proceedToCheckout": "Proceed to Checkout", "basketTotal": "Basket Total", @@ -244,10 +244,12 @@ "useLoyaltyPoints": "Use Loyalty Points", "noLoyaltyItemsInCart": "No loyalty items found in your cart", "pleaseAddLoyaltyItems": "Please add loyalty items to your cart to use loyalty points", - "loyaltyDiscountApplied": "Loyalty discount applied: {{itemName}} ({{amount}} off)" + "loyaltyDiscountApplied": "Loyalty discount applied: {{itemName}} ({{amount}} off)", + "deliveryFee": "Delivery Fee" }, "checkout": { "title": "Checkout", + "cash": "Cash", "creditDebitCard": "Credit/Debit Card", "differentCard": "Different Card", "fascanoWallet": "Fascano Wallet", diff --git a/src/components/ArabicPrice/ArabicPrice.tsx b/src/components/ArabicPrice/ArabicPrice.tsx index 1c74489..ee103e3 100644 --- a/src/components/ArabicPrice/ArabicPrice.tsx +++ b/src/components/ArabicPrice/ArabicPrice.tsx @@ -9,6 +9,7 @@ interface ArabicPriceProps { strong?: boolean; type?: "secondary" | "success" | "warning" | "danger"; className?: string; + hideCurrency?: boolean; } const ArabicPrice: React.FC = ({ @@ -17,6 +18,7 @@ const ArabicPrice: React.FC = ({ strong = false, type, className, + hideCurrency = false, }) => { const { t } = useTranslation(); const { isRTL } = useAppSelector((state) => state.locale); @@ -32,12 +34,12 @@ const ArabicPrice: React.FC = ({ style={{ display: "inline-flex", alignItems: "baseline", - gap: "0.1em", + gap: "0.2em", lineHeight: 1, ...style, }} > - {isRTL ? ( + {isRTL && !hideCurrency ? ( <> = ({ > {formattedPrice} - = ({ {t("common.omanCurrency")} - ) : ( + ) : !hideCurrency ? ( <> = ({ {t("common.omanCurrency")} + ) : ( + <>{formattedPrice} )} ); diff --git a/src/components/OrderSummary/OrderSummary.tsx b/src/components/OrderSummary/OrderSummary.tsx index 456f074..b8fb973 100644 --- a/src/components/OrderSummary/OrderSummary.tsx +++ b/src/components/OrderSummary/OrderSummary.tsx @@ -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() { {t("cart.basketTotal")} + {orderType != OrderType.DineIn &&
+ {t("cart.deliveryFee")} + +
}
{t("cart.discount")} - +
- {t("cart.riderTip")} - + {t("cart.tax")} +
{t("cart.totalAmount")} - +
@@ -88,7 +90,7 @@ export default function OrderSummary() {
{t("cart.loyaltyDiscountApplied", { itemName: highestLoyaltyItem.name, - amount: Math.round(loyaltyDiscountAmount).toFixed(2), + amount: Math.round(highestLoyaltyItem.price || 0).toFixed(2), })}
)} diff --git a/src/components/PaymentMethods/PaymentMethods.tsx b/src/components/PaymentMethods/PaymentMethods.tsx index 8956b92..18d41c3 100644 --- a/src/components/PaymentMethods/PaymentMethods.tsx +++ b/src/components/PaymentMethods/PaymentMethods.tsx @@ -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: (
- {" "}
), + hideCurrency: true, }, { label: t("checkout.fascanoWallet"), @@ -108,6 +122,7 @@ const PaymentMethods = () => { {!option.icon ? ( ; items: CartItem[]; - tmp: any; + tmp: unknown; specialRequest: string; location: LocationData | null; roomDetails: RoomDetailsType | null; @@ -76,6 +78,7 @@ export const CART_STORAGE_KEYS = { ORDER_TYPE: "fascano_order_type", USE_LOYALTY_POINTS: "fascano_use_loyalty_points", LOYALTY_VALIDATION_ERROR: "fascano_loyalty_validation_error", + RESTAURANT: "fascano_restaurant", } as const; // Utility functions for localStorage @@ -133,6 +136,7 @@ const initialState: CartState = { CART_STORAGE_KEYS.LOYALTY_VALIDATION_ERROR, null, ), + restaurant: getFromLocalStorage(CART_STORAGE_KEYS.RESTAURANT, { taxes: [] }), }; const orderSlice = createSlice({ @@ -142,6 +146,15 @@ const orderSlice = createSlice({ reset() { return initialState; }, + updateRestaurant(state, action: PayloadAction>) { + state.restaurant = action.payload; + if (typeof window !== "undefined") { + localStorage.setItem( + CART_STORAGE_KEYS.RESTAURANT, + JSON.stringify(state.restaurant), + ); + } + }, addItem( state, action: PayloadAction<{ @@ -520,8 +533,21 @@ export const { validateLoyaltyPoints, clearLoyaltyValidationError, reset, + updateRestaurant, } = orderSlice.actions; +// Tax calculation helper functions +const calculateTaxAmount = (amount: number, tax: Tax): number => { + const percentage = parseFloat(tax.percentage); + return (percentage * amount) / 100; +}; + +const calculateTotalTax = (subtotal: number, taxes: Tax[]): number => { + return taxes + .filter((tax) => tax.is_active === 1) + .reduce((total, tax) => total + calculateTaxAmount(subtotal, tax), 0); +}; + // Selectors export const selectCart = (state: RootState) => state.order; export const selectCartItems = (state: RootState) => state.order.items; @@ -549,18 +575,6 @@ export const selectHighestPricedLoyaltyItem = (state: RootState) => { ); }; -export const selectCartTotalWithLoyaltyDiscount = (state: RootState) => { - const total = selectCartTotal(state); - const useLoyaltyPoints = state.order.useLoyaltyPoints; - const highestLoyaltyItem = selectHighestPricedLoyaltyItem(state); - - if (useLoyaltyPoints && highestLoyaltyItem) { - return total - highestLoyaltyItem.price; - } - - return total; -}; - export const selectLoyaltyValidation = (state: RootState) => { const useLoyaltyPoints = state.order.useLoyaltyPoints; const loyaltyItems = selectLoyaltyItems(state); @@ -576,4 +590,25 @@ export const selectLoyaltyValidation = (state: RootState) => { }; }; +// Tax selectors +export const selectTaxes = (state: RootState) => state.order.restaurant.taxes; + +export const selectTaxAmount = (state: RootState) => { + const subtotal = selectCartTotal(state); + const taxes = selectTaxes(state); + return calculateTotalTax(subtotal, taxes || []); +}; + +export const selectGrandTotal = (state: RootState) => { + const loyaltyDiscount = selectHighestPricedLoyaltyItem(state)?.price || 0; + const taxAmount = selectTaxAmount(state); + const subtotal = selectCartTotal(state); + const deliveryFee = + state.order.orderType != OrderType.DineIn + ? Number(state.order.restaurant?.delivery_fees) || 0 + : 0; + + return subtotal + taxAmount - loyaltyDiscount + deliveryFee; +}; + export default orderSlice.reducer; diff --git a/src/hooks/useRestaurant.ts b/src/hooks/useRestaurant.ts new file mode 100644 index 0000000..17a639a --- /dev/null +++ b/src/hooks/useRestaurant.ts @@ -0,0 +1,18 @@ +import { updateRestaurant } from "features/order/orderSlice"; +import { useEffect } from "react"; +import { useAppDispatch } from "redux/hooks"; +import { RestaurantDetails } from "utils/types/appTypes"; + +/** + * Custom hook to automatically load restaurant into Redux store + * when restaurant data is available + */ +export const useRestaurant = (restaurant: RestaurantDetails | undefined) => { + const dispatch = useAppDispatch(); + + useEffect(() => { + if (restaurant) { + dispatch(updateRestaurant(restaurant)); + } + }, [restaurant, dispatch]); +}; diff --git a/src/pages/checkout/hooks/types.ts b/src/pages/checkout/hooks/types.ts index 30efe65..666841f 100644 --- a/src/pages/checkout/hooks/types.ts +++ b/src/pages/checkout/hooks/types.ts @@ -1,228 +1,248 @@ -import { Variant } from "pages/orders/types" -import { Extra3 } from "utils/types/appTypes" +import { Variant } from "pages/orders/types"; +import { Extra3 } from "utils/types/appTypes"; export interface OrderDetails { - orderItems: OrderItem[] - order: Order - status: Status[] - laststatus: Status2[] - restaurant: string - restaurantAR: string - restaurantID: number - global_currency: string - local_currency: string - address: string - phone: string - restaurant_iimage: string - itemsImagePrefixOld: string - itemsImagePrefix: string - } - - export interface OrderItem { - id: number - is_loyalty_used: number - no_of_stamps_give: number - isHasLoyalty: boolean - is_vat_disabled: number - name: string - price: number - qty: number - variant_price: string - image: string - imageName: string - variantName: string - variantLocalName?: string - extras: any[] - itemline: string - itemlineAR: string - itemlineAREN: string - extrasgroups: any[] - itemComment: string - variant?: Variant - itemExtras: any[] - AvaiilableVariantExtras: Extra3[] - isPrinted: number - category_id: number - pos_order_id: string - updated_at: string - created_at: string - old_qty: number - new_qty: number - last_printed_qty: number - deleted_qty: number - discount_value: any - discount_type_id: any - original_price: number - pricing_method: string - is_already_paid: number - hash_item: string - } + orderItems: OrderItem[]; + order: Order; + status: Status[]; + laststatus: Status2[]; + restaurant: string; + restaurantAR: string; + restaurantID: number; + global_currency: string; + local_currency: string; + address: string; + phone: string; + restaurant_iimage: string; + itemsImagePrefixOld: string; + itemsImagePrefix: string; +} - export interface Order { - id: number - pos_order_id: string - created_at: string - updated_at: string - table: string - phone: string - user_name: string - restaurant_name: string - lat: string - lng: string - restaurant_icon: string - location: any - status: string - status_id: number - delivery_method: number - orderItems: OrderItem2[] - discount: string - vat: number - total_price: number - comment: string - pickup_comments: any - car_plate: string - pickup_time: any - pickup_date: any - delivery_pickup_interval: any - office_no: any - room_no: any - time_to_prepare: any - last_status_id: number - currency: string - gift_id: any - is_loyalty_used: number - payment_status: string - created_by: string - split_order_group_id: any - split_sequence: any - is_split_order: number - split_at: any - split_by_user_id: any - } - - export interface OrderItem2 { - id: number - is_loyalty_used: number - no_of_stamps_give: number - isHasLoyalty: boolean - is_vat_disabled: number - name: string - price: number - qty: number - variant_price: string - image: string - imageName: string - variantName: string - variantLocalName?: string - extras: any[] - itemline: string - itemlineAR: string - itemlineAREN: string - extrasgroups: any[] - itemComment: string - variant?: Variant2 - itemExtras: any[] - AvaiilableVariantExtras: AvaiilableVariantExtra2[] - isPrinted: number - category_id: number - pos_order_id: string - updated_at: string - created_at: string - old_qty: number - new_qty: number - last_printed_qty: number - deleted_qty: number - discount_value: any - discount_type_id: any - original_price: number - pricing_method: string - is_already_paid: number - hash_item: string - } - - export interface Status { - id: number - name: string - alias: string - pivot: Pivot5 - } - - export interface Pivot5 { - order_id: number - status_id: number - user_id: number - created_at: string - comment: string - } - - export interface Status2 { - id: number - name: string - alias: string - pivot: Pivot6 - } +export interface OrderItem { + id: number; + is_loyalty_used: number; + no_of_stamps_give: number; + isHasLoyalty: boolean; + is_vat_disabled: number; + name: string; + price: number; + qty: number; + variant_price: string; + image: string; + imageName: string; + variantName: string; + variantLocalName?: string; + extras: any[]; + itemline: string; + itemlineAR: string; + itemlineAREN: string; + extrasgroups: any[]; + itemComment: string; + variant?: Variant; + itemExtras: any[]; + AvaiilableVariantExtras: Extra3[]; + isPrinted: number; + category_id: number; + pos_order_id: string; + updated_at: string; + created_at: string; + old_qty: number; + new_qty: number; + last_printed_qty: number; + deleted_qty: number; + discount_value: any; + discount_type_id: any; + original_price: number; + pricing_method: string; + is_already_paid: number; + hash_item: string; +} - export interface Pivot6 { - order_id: number - status_id: number - user_id: number - created_at: string - comment: string - } +export interface Order { + id: number; + pos_order_id: string; + created_at: string; + updated_at: string; + table: string; + phone: string; + user_name: string; + restaurant_name: string; + lat: string; + lng: string; + restaurant_icon: string; + location: any; + status: string; + status_id: number; + delivery_method: number; + orderItems: OrderItem2[]; + discount: string; + vat: number; + total_price: number; + comment: string; + pickup_comments: any; + car_plate: string; + pickup_time: any; + pickup_date: any; + delivery_pickup_interval: any; + office_no: any; + room_no: any; + time_to_prepare: any; + last_status_id: number; + currency: string; + gift_id: any; + is_loyalty_used: number; + payment_status: string; + created_by: string; + split_order_group_id: any; + split_sequence: any; + is_split_order: number; + split_at: any; + split_by_user_id: any; +} - export interface Variant2 { - id: number - price: number - options: string - local_name: any - optionsArray: OptionsArray2[] - OptionsList: string - extras: Extra2[] - } - - export interface OptionsArray2 { - id: number - name: string - } - - export interface Extra2 { - id: number - item_id: number - price: number - name: string - nameAR: string - created_at: string - updated_at: string - deleted_at: any - extra_for_all_variants: number - is_custome: number - is_available: number - modifier_id: any - pivot: Pivot3 - } - - export interface Pivot3 { - variant_id: number - extra_id: number - } - - export interface AvaiilableVariantExtra2 { - id: number - item_id: number - price: number - name: string - nameAR: string - created_at: string - updated_at: string - deleted_at: any - extra_for_all_variants: number - is_custome: number - is_available: number - modifier_id: any - pivot: Pivot4 - } +export interface OrderItem2 { + id: number; + is_loyalty_used: number; + no_of_stamps_give: number; + isHasLoyalty: boolean; + is_vat_disabled: number; + name: string; + price: number; + qty: number; + variant_price: string; + image: string; + imageName: string; + variantName: string; + variantLocalName?: string; + extras: any[]; + itemline: string; + itemlineAR: string; + itemlineAREN: string; + extrasgroups: any[]; + itemComment: string; + variant?: Variant2; + itemExtras: any[]; + AvaiilableVariantExtras: AvaiilableVariantExtra2[]; + isPrinted: number; + category_id: number; + pos_order_id: string; + updated_at: string; + created_at: string; + old_qty: number; + new_qty: number; + last_printed_qty: number; + deleted_qty: number; + discount_value: any; + discount_type_id: any; + original_price: number; + pricing_method: string; + is_already_paid: number; + hash_item: string; +} - export interface Pivot4 { - variant_id: number - extra_id: number - } \ No newline at end of file +export interface Status { + id: number; + name: string; + alias: string; + pivot: Pivot5; +} + +export interface Pivot5 { + order_id: number; + status_id: number; + user_id: number; + created_at: string; + comment: string; +} + +export interface Status2 { + id: number; + name: string; + alias: string; + pivot: Pivot6; +} + +export interface Pivot6 { + order_id: number; + status_id: number; + user_id: number; + created_at: string; + comment: string; +} + +export interface Variant2 { + id: number; + price: number; + options: string; + local_name: any; + optionsArray: OptionsArray2[]; + OptionsList: string; + extras: Extra2[]; +} + +export interface OptionsArray2 { + id: number; + name: string; +} + +export interface Extra2 { + id: number; + item_id: number; + price: number; + name: string; + nameAR: string; + created_at: string; + updated_at: string; + deleted_at: any; + extra_for_all_variants: number; + is_custome: number; + is_available: number; + modifier_id: any; + pivot: Pivot3; +} + +export interface Pivot3 { + variant_id: number; + extra_id: number; +} + +export interface AvaiilableVariantExtra2 { + id: number; + item_id: number; + price: number; + name: string; + nameAR: string; + created_at: string; + updated_at: string; + deleted_at: any; + extra_for_all_variants: number; + is_custome: number; + is_available: number; + modifier_id: any; + pivot: Pivot4; +} + +export interface Pivot4 { + variant_id: number; + extra_id: number; +} + +export enum DeliveryMethod { + DineIn = 3, + Delivery = 1, + Pickup = 2, + Gift = 10, + ScheduledOrder = 9, + ToRoom = 5, + ToOffice = 4, +} + +export enum OrderType { + DineIn = "dine-in", + Delivery = "delivery", + Pickup = "pickup", + Gift = "gift", + ScheduledOrder = "scheduled_order", + ToRoom = "room", + ToOffice = "office", +} diff --git a/src/pages/checkout/hooks/useOrder.ts b/src/pages/checkout/hooks/useOrder.ts index e152323..ac60ddb 100644 --- a/src/pages/checkout/hooks/useOrder.ts +++ b/src/pages/checkout/hooks/useOrder.ts @@ -2,8 +2,8 @@ import { message } from "antd"; import { clearCart, selectCart, - selectCartTotalWithLoyaltyDiscount, - selectHighestPricedLoyaltyItem, + selectGrandTotal, + selectHighestPricedLoyaltyItem } from "features/order/orderSlice"; import { useCallback } from "react"; import { useTranslation } from "react-i18next"; @@ -37,7 +37,7 @@ export default function useOrder() { const highestLoyaltyItem = useAppSelector(selectHighestPricedLoyaltyItem); const { useLoyaltyPoints } = useAppSelector(selectCart); - const orderPrice = useAppSelector(selectCartTotalWithLoyaltyDiscount); + const orderPrice = useAppSelector(selectGrandTotal); const [createOrder] = useCreateOrderMutation(); diff --git a/src/pages/menu/page.tsx b/src/pages/menu/page.tsx index 1be1fb0..f9aaa09 100644 --- a/src/pages/menu/page.tsx +++ b/src/pages/menu/page.tsx @@ -7,6 +7,7 @@ import ProText from "components/ProText"; import ProTitle from "components/ProTitle"; import { useScrollHandler } from "contexts/ScrollHandlerContext"; import useBreakPoint from "hooks/useBreakPoint"; +import { useRestaurant } from "hooks/useRestaurant"; import { useTranslation } from "react-i18next"; import { useParams } from "react-router-dom"; import { @@ -44,6 +45,9 @@ function MenuPage() { const { isMobile, isTablet, isDesktop } = useBreakPoint(); const isLoading = isLoadingRestaurant || isLoadingMenu; + // Automatically load restaurant taxes when restaurant data is available + useRestaurant(restaurant); + return ( <> diff --git a/src/pages/restaurant/page.tsx b/src/pages/restaurant/page.tsx index f2bc80a..cdec5c9 100644 --- a/src/pages/restaurant/page.tsx +++ b/src/pages/restaurant/page.tsx @@ -12,6 +12,7 @@ import RestaurantServices from "./RestaurantServices"; // Import the Client Component for localStorage handling import Ads1 from "components/Ads/Ads1"; import { Loader } from "components/Loader/Loader"; +import { useRestaurant } from "hooks/useRestaurant"; import { useParams } from "react-router-dom"; import { useGetRestaurantDetailsQuery } from "redux/api/others"; import LocalStorageHandler from "../menu/components/LocalStorageHandler"; @@ -19,12 +20,12 @@ import LocalStorageHandler from "../menu/components/LocalStorageHandler"; export default function RestaurantPage() { const param = useParams(); const { isRTL } = useAppSelector((state) => state.locale); - const { data: restaurant, isLoading } = useGetRestaurantDetailsQuery( - "595", - { - skip: !param.id, - }, - ); + const { data: restaurant, isLoading } = useGetRestaurantDetailsQuery("595", { + skip: !param.id, + }); + + // Automatically load restaurant taxes when restaurant data is available + useRestaurant(restaurant); if (isLoading) { return ; diff --git a/src/pages/split-bill/components/PayForActions.tsx b/src/pages/split-bill/components/PayForActions.tsx index 686c3bf..1325aa4 100644 --- a/src/pages/split-bill/components/PayForActions.tsx +++ b/src/pages/split-bill/components/PayForActions.tsx @@ -2,15 +2,20 @@ import ActionsButtons from "components/ActionsButtons/ActionsButtons"; import { selectCart, setTmp } from "features/order/orderSlice"; import { useAppDispatch, useAppSelector } from "redux/hooks"; +interface SplitBillTmp { + totalPeople?: number; + payFor?: number; +} + export default function PayForActions() { const dispatch = useAppDispatch(); const { tmp } = useAppSelector(selectCart); return ( dispatch(setTmp({ ...tmp, payFor: value }))} - max={tmp?.totalPeople || 10} + quantity={(tmp as SplitBillTmp)?.payFor || 1} + setQuantity={(value) => dispatch(setTmp({ ...(tmp as SplitBillTmp), payFor: value }))} + max={(tmp as SplitBillTmp)?.totalPeople || 10} min={1} /> ); diff --git a/src/pages/split-bill/components/PaymentSummary.tsx b/src/pages/split-bill/components/PaymentSummary.tsx index 2fcb2da..049d883 100644 --- a/src/pages/split-bill/components/PaymentSummary.tsx +++ b/src/pages/split-bill/components/PaymentSummary.tsx @@ -1,23 +1,27 @@ import { Card, Divider, Space } from "antd"; import ArabicPrice from "components/ArabicPrice"; import ProText from "components/ProText"; -import { selectCart, selectCartTotal } from "features/order/orderSlice"; +import { + selectCart, + selectGrandTotal +} from "features/order/orderSlice"; import { useTranslation } from "react-i18next"; import { useAppSelector } from "redux/hooks"; import { ProGray1 } from "ThemeConstants"; import styles from "../SplitBillPage.module.css"; +interface SplitBillTmp { + totalPeople?: number; + payFor?: number; +} + export default function PaymentSummary() { const { t } = useTranslation(); const { tmp } = useAppSelector(selectCart); - const getTotal = useAppSelector(selectCartTotal); + const total = useAppSelector(selectGrandTotal); - const subtotal = getTotal; - const tax = subtotal * 0.1; // 10% tax - const total = subtotal + tax; - - const costPerPerson = total / (tmp?.totalPeople || 1); - const remainingAmount = total - (tmp?.payFor || 1) * costPerPerson; + const costPerPerson = total / ((tmp as SplitBillTmp)?.totalPeople || 1); + const remainingAmount = total - ((tmp as SplitBillTmp)?.payFor || 1) * costPerPerson; return (