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

@@ -1,6 +1,7 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { OrderType } from "pages/checkout/hooks/types";
import { RootState } from "redux/store";
import { CartItem } from "utils/types/appTypes";
import { CartItem, RestaurantDetails, Tax } from "utils/types/appTypes";
interface LocationData {
lat: number;
@@ -35,8 +36,9 @@ export interface GiftDetailsType {
}
interface CartState {
restaurant: Partial<RestaurantDetails>;
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<Partial<RestaurantDetails>>) {
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;