apply restaurant decimails formating & fix tax calcualtions
This commit is contained in:
@@ -27,7 +27,7 @@ const ArabicPrice: React.FC<ArabicPriceProps> = ({
|
|||||||
|
|
||||||
// Format the price to ensure it has 2 decimal places
|
// Format the price to ensure it has 2 decimal places
|
||||||
const formattedPrice =
|
const formattedPrice =
|
||||||
typeof price === "number" ? formatPriceUi(price, 3) : price;
|
typeof price === "number" ? formatPriceUi(price, restaurant?.currency_decimals ?? 3) : price;
|
||||||
const { textDecoration, ...restStyle } = style;
|
const { textDecoration, ...restStyle } = style;
|
||||||
const decorationStyle = textDecoration
|
const decorationStyle = textDecoration
|
||||||
? ({ textDecoration } as React.CSSProperties)
|
? ({ textDecoration } as React.CSSProperties)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ const PaymentMethods = () => {
|
|||||||
const { paymentMethod, orderType } = useAppSelector(selectCart);
|
const { paymentMethod, orderType } = useAppSelector(selectCart);
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const grandTotal = useAppSelector(selectGrandTotal);
|
const grandTotal = useAppSelector(selectGrandTotal);
|
||||||
|
const { restaurant } = useAppSelector((state) => state.order);
|
||||||
// const { isRTL } = useAppSelector((state) => state.locale);
|
// const { isRTL } = useAppSelector((state) => state.locale);
|
||||||
|
|
||||||
const options: {
|
const options: {
|
||||||
@@ -50,7 +51,7 @@ const PaymentMethods = () => {
|
|||||||
</>
|
</>
|
||||||
),
|
),
|
||||||
value: "cash",
|
value: "cash",
|
||||||
price: formatPriceUi(grandTotal, 3),
|
price: formatPriceUi(grandTotal, restaurant.currency_decimals ?? 3),
|
||||||
style: {
|
style: {
|
||||||
color: colors.primary,
|
color: colors.primary,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -771,23 +771,21 @@ export const {
|
|||||||
|
|
||||||
// Tax calculation helper functions
|
// Tax calculation helper functions
|
||||||
const calculateTaxAmount = (
|
const calculateTaxAmount = (
|
||||||
state: RootState,
|
|
||||||
amount: number,
|
amount: number,
|
||||||
tax: Tax,
|
tax: Tax,
|
||||||
): number => {
|
): number => {
|
||||||
const percentage = parseFloat(tax.percentage);
|
const percentage = parseFloat(tax.percentage);
|
||||||
return (((state.order.restaurant?.vat || 0) + percentage) * amount) / 100;
|
return (percentage * amount) / 100;
|
||||||
};
|
};
|
||||||
|
|
||||||
const calculateTotalTax = (
|
const calculateTotalTax = (
|
||||||
state: RootState,
|
|
||||||
subtotal: number,
|
subtotal: number,
|
||||||
taxes: Tax[],
|
taxes: Tax[],
|
||||||
): number => {
|
): number => {
|
||||||
return taxes
|
return taxes
|
||||||
.filter((tax) => tax.is_active === 1)
|
.filter((tax) => tax.is_active === 1)
|
||||||
.reduce(
|
.reduce(
|
||||||
(total, tax) => total + calculateTaxAmount(state, subtotal, tax),
|
(total, tax) => total + calculateTaxAmount(subtotal, tax),
|
||||||
0,
|
0,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -838,7 +836,7 @@ export const selectHighestPricedLoyaltyItem = (state: RootState) => {
|
|||||||
export const selectDiscountTotal = (state: RootState) =>
|
export const selectDiscountTotal = (state: RootState) =>
|
||||||
(state.order.discount.value / 100) * selectCartTotal(state) +
|
(state.order.discount.value / 100) * selectCartTotal(state) +
|
||||||
(state.order.useLoyaltyPoints &&
|
(state.order.useLoyaltyPoints &&
|
||||||
state.order.restaurant?.is_loyalty_enabled === 1
|
state.order.restaurant?.is_loyalty_enabled === 1
|
||||||
? selectHighestPricedLoyaltyItem(state)?.price || 0
|
? selectHighestPricedLoyaltyItem(state)?.price || 0
|
||||||
: 0);
|
: 0);
|
||||||
|
|
||||||
@@ -861,25 +859,29 @@ export const selectTaxes = (state: RootState) => state.order.restaurant.taxes;
|
|||||||
export const selectTaxAmount = (state: RootState) => {
|
export const selectTaxAmount = (state: RootState) => {
|
||||||
const subtotal = selectCartTotal(state) - selectDiscountTotal(state);
|
const subtotal = selectCartTotal(state) - selectDiscountTotal(state);
|
||||||
const taxes = selectTaxes(state);
|
const taxes = selectTaxes(state);
|
||||||
return calculateTotalTax(state, subtotal, taxes || []);
|
return calculateTotalTax(subtotal, taxes || []);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const selectGrandTotal = (state: RootState) => {
|
export const selectGrandTotal = (state: RootState) => {
|
||||||
const totalDiscount = selectDiscountTotal(state);
|
const totalDiscount = selectDiscountTotal(state);
|
||||||
const taxAmount = selectTaxAmount(state);
|
const taxAmount = selectTaxAmount(state);
|
||||||
|
const vatAmount = ((state.order.restaurant?.vat || 0) / 100) * (selectCartTotal(state) - selectDiscountTotal(state));
|
||||||
const subtotal = selectCartTotal(state);
|
const subtotal = selectCartTotal(state);
|
||||||
const deliveryFee =
|
const deliveryFee =
|
||||||
state.order.orderType === OrderType.Delivery
|
state.order.orderType === OrderType.Delivery
|
||||||
? Number(state.order.restaurant?.delivery_fees) || 0
|
? Number(state.order.restaurant?.delivery_fees) || 0
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
|
console.log(subtotal, totalDiscount, taxAmount, deliveryFee);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
subtotal +
|
subtotal -
|
||||||
taxAmount -
|
|
||||||
totalDiscount +
|
totalDiscount +
|
||||||
deliveryFee -
|
taxAmount +
|
||||||
state.order.splitBillAmount +
|
vatAmount -
|
||||||
Number(state.order.tip)
|
deliveryFee
|
||||||
|
// state.order.splitBillAmount +
|
||||||
|
// Number(state.order.tip)
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -13,13 +13,14 @@ import "react-phone-input-2/lib/style.css";
|
|||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { useSendOtpMutation } from "redux/api/auth";
|
import { useSendOtpMutation } from "redux/api/auth";
|
||||||
import { useGetRestaurantDetailsQuery } from "redux/api/others";
|
import { useGetRestaurantDetailsQuery } from "redux/api/others";
|
||||||
import { useAppSelector } from "redux/hooks";
|
import { useAppDispatch, useAppSelector } from "redux/hooks";
|
||||||
import { colors, DisabledColor, ProGray1 } from "ThemeConstants";
|
import { colors, DisabledColor, ProGray1 } from "ThemeConstants";
|
||||||
import { default_image } from "utils/constants";
|
import { default_image } from "utils/constants";
|
||||||
import styles from "./login.module.css";
|
import styles from "./login.module.css";
|
||||||
import { Layout } from "antd";
|
import { Layout } from "antd";
|
||||||
import ProHeader from "components/ProHeader/ProHeader";
|
import ProHeader from "components/ProHeader/ProHeader";
|
||||||
import useBreakPoint from "hooks/useBreakPoint";
|
import useBreakPoint from "hooks/useBreakPoint";
|
||||||
|
import { updateCustomerName } from "features/order/orderSlice";
|
||||||
|
|
||||||
export default function LoginPage() {
|
export default function LoginPage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -32,7 +33,7 @@ export default function LoginPage() {
|
|||||||
skip: !subdomain,
|
skip: !subdomain,
|
||||||
});
|
});
|
||||||
const { isTablet } = useBreakPoint();
|
const { isTablet } = useBreakPoint();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
// const [phone, setPhone] = useState<string>("");
|
// const [phone, setPhone] = useState<string>("");
|
||||||
const [selectedDate, setSelectedDate] = useState<string>("");
|
const [selectedDate, setSelectedDate] = useState<string>("");
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
@@ -113,6 +114,10 @@ export default function LoginPage() {
|
|||||||
height: 50,
|
height: 50,
|
||||||
fontSize: 14,
|
fontSize: 14,
|
||||||
}}
|
}}
|
||||||
|
onBlur={(e) => {
|
||||||
|
dispatch(updateCustomerName(e.target.value));
|
||||||
|
}}
|
||||||
|
disabled={isLoading}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
|||||||
@@ -37,13 +37,14 @@ import NewRateIcon from "components/Icons/order/NewRateIcon";
|
|||||||
import NoteIcon from "components/Icons/NoteIcon";
|
import NoteIcon from "components/Icons/NoteIcon";
|
||||||
import SuccessIcon from "components/Icons/SuccessIcon";
|
import SuccessIcon from "components/Icons/SuccessIcon";
|
||||||
import { SplitBillParticipantsBottomSheet } from "./components/SplitBillParticipantsBottomSheet";
|
import { SplitBillParticipantsBottomSheet } from "./components/SplitBillParticipantsBottomSheet";
|
||||||
|
import { OrderType } from "pages/checkout/hooks/types";
|
||||||
|
|
||||||
export default function OrderPage() {
|
export default function OrderPage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { orderId } = useParams();
|
const { orderId } = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { isRTL } = useAppSelector((state) => state.locale);
|
const { isRTL } = useAppSelector((state) => state.locale);
|
||||||
const { restaurant } = useAppSelector((state) => state.order);
|
const { restaurant, orderType } = useAppSelector((state) => state.order);
|
||||||
const hasRefetchedRef = useRef(false);
|
const hasRefetchedRef = useRef(false);
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [isRateOrderOpen, setIsRateOrderOpen] = useState(false);
|
const [isRateOrderOpen, setIsRateOrderOpen] = useState(false);
|
||||||
@@ -429,7 +430,7 @@ export default function OrderPage() {
|
|||||||
<Stepper statuses={orderDetails?.status} />
|
<Stepper statuses={orderDetails?.status} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{!hasClosedStatus && (
|
{!hasClosedStatus && orderType === OrderType.DineIn && (
|
||||||
<div className={styles.orderNotes}>
|
<div className={styles.orderNotes}>
|
||||||
<NoteIcon className={styles.noteIcon} />
|
<NoteIcon className={styles.noteIcon} />
|
||||||
<div
|
<div
|
||||||
@@ -464,7 +465,7 @@ export default function OrderPage() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{hasClosedStatus && (
|
{hasClosedStatus && orderType === OrderType.DineIn && (
|
||||||
<div className={styles.orderNotesClosed}>
|
<div className={styles.orderNotesClosed}>
|
||||||
<SuccessIcon className={styles.noteIcon} />
|
<SuccessIcon className={styles.noteIcon} />
|
||||||
<ProText
|
<ProText
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { Extra as ExtraType } from "utils/types/appTypes";
|
import { Extra as ExtraType } from "utils/types/appTypes";
|
||||||
import styles from "../product.module.css";
|
import styles from "../product.module.css";
|
||||||
import { formatPriceUi } from "utils/helpers";
|
import { formatPriceUi } from "utils/helpers";
|
||||||
|
import { useAppSelector } from "redux/hooks";
|
||||||
|
|
||||||
export default function Extra({
|
export default function Extra({
|
||||||
extrasList,
|
extrasList,
|
||||||
@@ -17,7 +18,7 @@ export default function Extra({
|
|||||||
setSelectedExtras: Dispatch<SetStateAction<ExtraType[]>>;
|
setSelectedExtras: Dispatch<SetStateAction<ExtraType[]>>;
|
||||||
}) {
|
}) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const { restaurant } = useAppSelector((state) => state.order);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{extrasList.length > 0 && (
|
{extrasList.length > 0 && (
|
||||||
@@ -46,7 +47,7 @@ export default function Extra({
|
|||||||
return {
|
return {
|
||||||
value: value.id.toString(),
|
value: value.id.toString(),
|
||||||
label: value.name,
|
label: value.name,
|
||||||
price: `+${formatPriceUi(value.price, 3)}`,
|
price: `+${formatPriceUi(value.price, restaurant.currency_decimals ?? 3)}`,
|
||||||
};
|
};
|
||||||
})}
|
})}
|
||||||
value={selectedExtras.map((ex) => ex.id.toString())}
|
value={selectedExtras.map((ex) => ex.id.toString())}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export default function Variants({
|
|||||||
const { isRTL } = useAppSelector((state) => state.locale);
|
const { isRTL } = useAppSelector((state) => state.locale);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { isDesktop } = useBreakPoint();
|
const { isDesktop } = useBreakPoint();
|
||||||
|
const { restaurant } = useAppSelector((state) => state.order);
|
||||||
// Determine variant levels based on options array length
|
// Determine variant levels based on options array length
|
||||||
const variantLevels = useMemo(() => {
|
const variantLevels = useMemo(() => {
|
||||||
if (!variantsList || variantsList.length === 0) return [];
|
if (!variantsList || variantsList.length === 0) return [];
|
||||||
@@ -170,7 +170,7 @@ export default function Variants({
|
|||||||
value: value,
|
value: value,
|
||||||
label: value,
|
label: value,
|
||||||
price: variant
|
price: variant
|
||||||
? `+${formatPriceUi(variant.price, 3)}`
|
? `+${formatPriceUi(variant.price, restaurant.currency_decimals ?? 3)}`
|
||||||
: "",
|
: "",
|
||||||
};
|
};
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -534,6 +534,7 @@ export interface RestaurantDetails {
|
|||||||
closingTime: string;
|
closingTime: string;
|
||||||
isOpened: boolean;
|
isOpened: boolean;
|
||||||
isFav: boolean;
|
isFav: boolean;
|
||||||
|
currency_decimals: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Banner {
|
export interface Banner {
|
||||||
|
|||||||
Reference in New Issue
Block a user