apply items validation and fix taxes list viewing

This commit is contained in:
2026-01-17 10:04:34 +03:00
parent 4dfa08d26c
commit 8083e9ec96
4 changed files with 55 additions and 27 deletions

View File

@@ -287,8 +287,8 @@
"cannotSelectPastDate": "لا يمكنك اختيار تاريخ سابق. يرجى اختيار اليوم أو تاريخ مستقبلي.", "cannotSelectPastDate": "لا يمكنك اختيار تاريخ سابق. يرجى اختيار اليوم أو تاريخ مستقبلي.",
"checkRequiredFields": "يرجى التحقق من الحقول المطلوبة", "checkRequiredFields": "يرجى التحقق من الحقول المطلوبة",
"loyalty": "ولاء", "loyalty": "ولاء",
"vatTax": "ضريبة (القيمة المضافة)", "vat": "ضريبة القيمة المضافة ({{value}}%))",
"otherTaxes": "ضريبة (أخرى)" "otherTaxes": "{{name}} ({{value}}%)"
}, },
"checkout": { "checkout": {
"addCarDetails": "إضافة تفاصيل السيارة", "addCarDetails": "إضافة تفاصيل السيارة",
@@ -333,7 +333,8 @@
"change": "تغيير", "change": "تغيير",
"pickup": "استلام", "pickup": "استلام",
"setPickupTime": "تحديد وقت الاستلام", "setPickupTime": "تحديد وقت الاستلام",
"carPlateNumber": "رقم لوحة السيارة" "carPlateNumber": "رقم لوحة السيارة",
"noItems": "لا يوجد عناصر في السلة"
}, },
"address": { "address": {
"title": "العنوان", "title": "العنوان",

View File

@@ -304,8 +304,8 @@
"checkRequiredFields": "Please check required fields", "checkRequiredFields": "Please check required fields",
"applyYourAvailableRewardsToGetDiscountsOnItemsInYourCart": "Apply your available rewards to get discounts on items in your cart", "applyYourAvailableRewardsToGetDiscountsOnItemsInYourCart": "Apply your available rewards to get discounts on items in your cart",
"loyalty": "Loyalty", "loyalty": "Loyalty",
"vatTax": "Tax (Vat)", "vat": "Vat ({{value}}%)",
"otherTaxes": "Tax (Other)" "otherTaxes": "{{name}} ({{value}}%)"
}, },
"checkout": { "checkout": {
"addCarDetails": "Add Car Details", "addCarDetails": "Add Car Details",
@@ -352,7 +352,8 @@
"change": "Change", "change": "Change",
"pickup": "Pickup", "pickup": "Pickup",
"setPickupTime": "Set Pickup Time", "setPickupTime": "Set Pickup Time",
"carPlateNumber": "Car Plate Number" "carPlateNumber": "Car Plate Number",
"noItems": "No items in cart"
}, },
"address": { "address": {
"title": "Address", "title": "Address",

View File

@@ -1,4 +1,4 @@
import { Card, Checkbox, Divider, Space, Tag } from "antd"; import { Card, Divider, Space, Tag } from "antd";
import ArabicPrice from "components/ArabicPrice"; import ArabicPrice from "components/ArabicPrice";
import { import {
selectCart, selectCart,
@@ -6,7 +6,6 @@ import {
selectDiscountTotal, selectDiscountTotal,
selectGrandTotal, selectGrandTotal,
selectHighestPricedLoyaltyItem, selectHighestPricedLoyaltyItem,
selectTaxAmount,
} from "features/order/orderSlice"; } from "features/order/orderSlice";
import { OrderType } from "pages/checkout/hooks/types"; import { OrderType } from "pages/checkout/hooks/types";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -16,7 +15,7 @@ import { useAppSelector } from "redux/hooks";
import ProText from "../ProText"; import ProText from "../ProText";
import ProTitle from "../ProTitle"; import ProTitle from "../ProTitle";
import styles from "./OrderSummary.module.css"; import styles from "./OrderSummary.module.css";
import { CSSProperties } from "react"; import { CSSProperties, useMemo } from "react";
export default function OrderSummary() { export default function OrderSummary() {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -26,7 +25,6 @@ export default function OrderSummary() {
const { orderType } = useAppSelector(selectCart); const { orderType } = useAppSelector(selectCart);
const subtotal = useAppSelector(selectCartTotal); const subtotal = useAppSelector(selectCartTotal);
const highestLoyaltyItem = useAppSelector(selectHighestPricedLoyaltyItem); const highestLoyaltyItem = useAppSelector(selectHighestPricedLoyaltyItem);
const taxAmount = useAppSelector(selectTaxAmount);
const grandTotal = useAppSelector(selectGrandTotal); const grandTotal = useAppSelector(selectGrandTotal);
const discountAmount = useAppSelector(selectDiscountTotal); const discountAmount = useAppSelector(selectDiscountTotal);
@@ -44,7 +42,27 @@ export default function OrderSummary() {
textAlign: "center", textAlign: "center",
}; };
const vat = ((restaurant?.vat ?? 0) / 100) * subtotal || 0; const vat = ((restaurant?.vat ?? 0) / 100) * (subtotal - discountAmount) || 0;
// Calculate individual taxes
const taxesList = useMemo(() => {
if (!restaurant?.taxes) return [];
const subtotalAfterDiscount = subtotal - discountAmount;
return restaurant.taxes
.filter((tax) => tax.is_active === 1)
.map((tax) => {
const amount = ((Number(tax.percentage) || 0) / 100) * subtotalAfterDiscount;
return {
id: tax.id,
name: tax.name,
name_local: tax.name_local,
percentage: tax.percentage,
amount,
};
});
}, [restaurant?.taxes, subtotal, discountAmount]);
return ( return (
<> <>
@@ -156,10 +174,10 @@ export default function OrderSummary() {
/> />
</div> </div>
)} )}
{orderType !== OrderType.Redeem && ( {orderType !== OrderType.Redeem && restaurant?.vat && (
<div className={styles.summaryRow}> <div className={styles.summaryRow}>
<ProText type="secondary" style={titlesStyle}> <ProText type="secondary" style={titlesStyle}>
{t("cart.vatTax")} {t("cart.vat", { value: restaurant.vat })}
</ProText> </ProText>
<ArabicPrice <ArabicPrice
price={vat} price={vat}
@@ -167,17 +185,21 @@ export default function OrderSummary() {
/> />
</div> </div>
)} )}
{orderType !== OrderType.Redeem && ( {orderType !== OrderType.Redeem &&
<div className={styles.summaryRow}> taxesList.map((tax) => (
<ProText type="secondary" style={titlesStyle}> <div key={tax.id} className={styles.summaryRow}>
{t("cart.otherTaxes")} <ProText type="secondary" style={titlesStyle}>
</ProText> {t("cart.otherTaxes", {
<ArabicPrice name: tax.name || tax.name_local,
price={taxAmount - vat || 0} value: tax.percentage,
textStyle={{ ...titlesStyle, color: "#434E5C" }} })}
/> </ProText>
</div> <ArabicPrice
)} price={tax.amount}
textStyle={{ ...titlesStyle, color: "#434E5C" }}
/>
</div>
))}
{orderType !== OrderType.Redeem && splitBillAmount > 0 && ( {orderType !== OrderType.Redeem && splitBillAmount > 0 && (
<div className={styles.summaryRow}> <div className={styles.summaryRow}>
<ProText type="secondary" style={titlesStyle}> <ProText type="secondary" style={titlesStyle}>

View File

@@ -1,4 +1,4 @@
import { Button, FormInstance, Layout } from "antd"; import { Button, FormInstance, Layout, message } from "antd";
import { selectCart, updateSplitBillAmount } from "features/order/orderSlice"; import { selectCart, updateSplitBillAmount } from "features/order/orderSlice";
import { OrderType } from "pages/checkout/hooks/types.ts"; import { OrderType } from "pages/checkout/hooks/types.ts";
import { useCallback, useMemo, useState } from "react"; import { useCallback, useMemo, useState } from "react";
@@ -18,7 +18,7 @@ type SplitWay = "customAmount" | "equality" | "payForItems" | null;
export default function CheckoutButton({ form }: { form: FormInstance }) { export default function CheckoutButton({ form }: { form: FormInstance }) {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { t } = useTranslation(); const { t } = useTranslation();
const { orderType, giftDetails } = useAppSelector(selectCart); const { orderType, giftDetails, items } = useAppSelector(selectCart);
const { handleCreateOrder } = useOrder(); const { handleCreateOrder } = useOrder();
const { handleCreateGiftAmount } = useGidtAmount(); const { handleCreateGiftAmount } = useGidtAmount();
const [selectedSplitWay, setSelectedSplitWay] = useState<SplitWay>(null); const [selectedSplitWay, setSelectedSplitWay] = useState<SplitWay>(null);
@@ -56,7 +56,11 @@ export default function CheckoutButton({ form }: { form: FormInstance }) {
) { ) {
handleCreateGiftAmount(); handleCreateGiftAmount();
} else { } else {
handleCreateOrder(); if (items.length > 0) {
handleCreateOrder();
} else {
message.error(t("checkout.noItems"));
}
} }
} catch (error) { } catch (error) {
console.log(error); console.log(error);