Compare commits
6 Commits
ce9092d634
...
b261f3508f
| Author | SHA1 | Date | |
|---|---|---|---|
| b261f3508f | |||
| 86c12e2c53 | |||
| a87d1d7716 | |||
| 4bf18087cc | |||
| 611f26f6ff | |||
| a2f8b943a1 |
@@ -108,6 +108,7 @@
|
|||||||
"email_label": "البريد الإلكتروني"
|
"email_label": "البريد الإلكتروني"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
|
"orderTypes": "طرق الطلب",
|
||||||
"meal": "الوجبة",
|
"meal": "الوجبة",
|
||||||
"title": "القائمة",
|
"title": "القائمة",
|
||||||
"ourMenu": "قائمتنا",
|
"ourMenu": "قائمتنا",
|
||||||
@@ -386,7 +387,8 @@
|
|||||||
"pleaseLoginToAllowRating": "يرجى تسجيل الدخول لتمكين التقييم",
|
"pleaseLoginToAllowRating": "يرجى تسجيل الدخول لتمكين التقييم",
|
||||||
"remainingTime": "الوقت المتبقي",
|
"remainingTime": "الوقت المتبقي",
|
||||||
"sec": "ثانية",
|
"sec": "ثانية",
|
||||||
"min": "دقيقة"
|
"min": "دقيقة",
|
||||||
|
"inviteToBill": "دع الجميع يدفعوا معك"
|
||||||
},
|
},
|
||||||
"orderTypes": {
|
"orderTypes": {
|
||||||
"dine-in": "في المطعم",
|
"dine-in": "في المطعم",
|
||||||
|
|||||||
@@ -124,6 +124,7 @@
|
|||||||
"email_label": "Email"
|
"email_label": "Email"
|
||||||
},
|
},
|
||||||
"menu": {
|
"menu": {
|
||||||
|
"orderTypes": "Order Types",
|
||||||
"meal": "Meal",
|
"meal": "Meal",
|
||||||
"title": "Menu",
|
"title": "Menu",
|
||||||
"ourMenu": "Our Menu",
|
"ourMenu": "Our Menu",
|
||||||
@@ -397,7 +398,8 @@
|
|||||||
"pleaseLoginToAllowRating": "Please login to allow rating",
|
"pleaseLoginToAllowRating": "Please login to allow rating",
|
||||||
"remainingTime": "Remaining Time",
|
"remainingTime": "Remaining Time",
|
||||||
"sec": "Sec",
|
"sec": "Sec",
|
||||||
"min": "Min"
|
"min": "Min",
|
||||||
|
"inviteToBill": "Invite to Bill"
|
||||||
},
|
},
|
||||||
"orderTypes": {
|
"orderTypes": {
|
||||||
"dine-in": "Dine In",
|
"dine-in": "Dine In",
|
||||||
|
|||||||
150
src/components/CustomBottomSheet/OrderTypesBottomSheet.tsx
Normal file
150
src/components/CustomBottomSheet/OrderTypesBottomSheet.tsx
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
import { Button } from "antd";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { ProBottomSheet } from "../ProBottomSheet/ProBottomSheet";
|
||||||
|
import NextIcon from "components/Icons/NextIcon";
|
||||||
|
import { useAppSelector } from "redux/hooks";
|
||||||
|
import { OrderType } from "pages/checkout/hooks/types";
|
||||||
|
import { useSearchParams } from "react-router-dom";
|
||||||
|
|
||||||
|
interface OrderTypesBottomSheetBottomSheetProps {
|
||||||
|
isOpen: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function OrderTypesBottomSheet({
|
||||||
|
isOpen,
|
||||||
|
onClose,
|
||||||
|
}: OrderTypesBottomSheetBottomSheetProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { restaurant, orderType, hiddenServices } = useAppSelector(
|
||||||
|
(state) => state.order,
|
||||||
|
);
|
||||||
|
const [searchParams, setSearchParams] = useSearchParams();
|
||||||
|
const buttonStyle = {
|
||||||
|
height: 48,
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calculate height: base 620px, subtract 48px for each hidden service
|
||||||
|
const calculatedHeight = 620 - hiddenServices * 64;
|
||||||
|
|
||||||
|
const handleOrderTypeSelect = (selectedOrderType: OrderType) => {
|
||||||
|
searchParams.set("orderType", selectedOrderType);
|
||||||
|
setSearchParams(searchParams);
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ProBottomSheet
|
||||||
|
isOpen={isOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
title={t("menu.orderTypes")}
|
||||||
|
initialSnap={1}
|
||||||
|
height={calculatedHeight}
|
||||||
|
snapPoints={[calculatedHeight.toString()]}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: 16,
|
||||||
|
margin: "16px 0",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{restaurant?.dineIn == true && (
|
||||||
|
<Button
|
||||||
|
icon={<NextIcon />}
|
||||||
|
iconPlacement="end"
|
||||||
|
style={buttonStyle}
|
||||||
|
type={orderType === OrderType.DineIn ? "primary" : "default"}
|
||||||
|
onClick={() => handleOrderTypeSelect(OrderType.DineIn)}
|
||||||
|
>
|
||||||
|
{t("orderTypes.dine-in")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{restaurant?.delivery == true && (
|
||||||
|
<Button
|
||||||
|
icon={<NextIcon />}
|
||||||
|
iconPlacement="end"
|
||||||
|
style={buttonStyle}
|
||||||
|
type={orderType === OrderType.Delivery ? "primary" : "default"}
|
||||||
|
onClick={() => handleOrderTypeSelect(OrderType.Delivery)}
|
||||||
|
>
|
||||||
|
{t("orderTypes.delivery")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{restaurant?.pickup == true && (
|
||||||
|
<Button
|
||||||
|
icon={<NextIcon />}
|
||||||
|
iconPlacement="end"
|
||||||
|
style={buttonStyle}
|
||||||
|
type={orderType === OrderType.Pickup ? "primary" : "default"}
|
||||||
|
onClick={() => handleOrderTypeSelect(OrderType.Pickup)}
|
||||||
|
>
|
||||||
|
{t("orderTypes.pickup")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{restaurant?.gift == true && (
|
||||||
|
<Button
|
||||||
|
icon={<NextIcon />}
|
||||||
|
iconPlacement="end"
|
||||||
|
style={buttonStyle}
|
||||||
|
type={orderType === OrderType.Gift ? "primary" : "default"}
|
||||||
|
onClick={() => handleOrderTypeSelect(OrderType.Gift)}
|
||||||
|
>
|
||||||
|
{t("orderTypes.gift")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{restaurant?.toRoom == true && (
|
||||||
|
<Button
|
||||||
|
icon={<NextIcon />}
|
||||||
|
iconPlacement="end"
|
||||||
|
style={buttonStyle}
|
||||||
|
type={orderType === OrderType.ToRoom ? "primary" : "default"}
|
||||||
|
onClick={() => handleOrderTypeSelect(OrderType.ToRoom)}
|
||||||
|
>
|
||||||
|
{t("orderTypes.room")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{restaurant?.toOffice == true && (
|
||||||
|
<Button
|
||||||
|
icon={<NextIcon />}
|
||||||
|
iconPlacement="end"
|
||||||
|
style={buttonStyle}
|
||||||
|
type={orderType === OrderType.ToOffice ? "primary" : "default"}
|
||||||
|
onClick={() => handleOrderTypeSelect(OrderType.ToOffice)}
|
||||||
|
>
|
||||||
|
{t("orderTypes.office")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{restaurant?.is_schedule_order_enabled == 1 && (
|
||||||
|
<Button
|
||||||
|
icon={<NextIcon />}
|
||||||
|
iconPlacement="end"
|
||||||
|
style={buttonStyle}
|
||||||
|
type={
|
||||||
|
orderType === OrderType.ScheduledOrder ? "primary" : "default"
|
||||||
|
}
|
||||||
|
onClick={() => handleOrderTypeSelect(OrderType.ScheduledOrder)}
|
||||||
|
>
|
||||||
|
{t("orderTypes.scheduled_order")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
{restaurant?.is_booking_enabled == 1 && (
|
||||||
|
<Button
|
||||||
|
icon={<NextIcon />}
|
||||||
|
iconPlacement="end"
|
||||||
|
style={buttonStyle}
|
||||||
|
type={orderType === OrderType.Booking ? "primary" : "default"}
|
||||||
|
onClick={() => handleOrderTypeSelect(OrderType.Booking)}
|
||||||
|
>
|
||||||
|
{t("orderTypes.booking")}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</ProBottomSheet>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
// import { useGlobals } from "../../hooks/useGlobals";
|
// import { useGlobals } from "../../hooks/useGlobals";
|
||||||
import { Button, Card, message } from "antd";
|
import { Button, Card, message } from "antd";
|
||||||
import BackIcon from "components/Icons/BackIcon";
|
|
||||||
import NextIcon from "components/Icons/NextIcon";
|
|
||||||
import RateIcon from "components/Icons/order/RateIcon";
|
import RateIcon from "components/Icons/order/RateIcon";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
|||||||
@@ -71,6 +71,9 @@ interface CartState {
|
|||||||
order: any;
|
order: any;
|
||||||
splitBillAmount: number;
|
splitBillAmount: number;
|
||||||
customerName: string;
|
customerName: string;
|
||||||
|
totalServices: number;
|
||||||
|
hiddenServices: number;
|
||||||
|
visibleServices: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// localStorage keys
|
// localStorage keys
|
||||||
@@ -101,6 +104,9 @@ export const CART_STORAGE_KEYS = {
|
|||||||
PICKUP_TIME: "fascano_pickup_time",
|
PICKUP_TIME: "fascano_pickup_time",
|
||||||
PICKUP_TYPE: "fascano_pickup_type",
|
PICKUP_TYPE: "fascano_pickup_type",
|
||||||
ORDER: "fascano_order",
|
ORDER: "fascano_order",
|
||||||
|
TOTAL_SERVICES: "fascano_total_services",
|
||||||
|
HIDDEN_SERVICES: "fascano_hidden_services",
|
||||||
|
VISIBLE_SERVICES: "fascano_visible_services",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
// Utility functions for localStorage
|
// Utility functions for localStorage
|
||||||
@@ -189,6 +195,9 @@ const initialState: CartState = {
|
|||||||
order: getFromLocalStorage(CART_STORAGE_KEYS.ORDER, null),
|
order: getFromLocalStorage(CART_STORAGE_KEYS.ORDER, null),
|
||||||
splitBillAmount: 0,
|
splitBillAmount: 0,
|
||||||
customerName: "",
|
customerName: "",
|
||||||
|
totalServices: 8,
|
||||||
|
hiddenServices: 0,
|
||||||
|
visibleServices: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const orderSlice = createSlice({
|
const orderSlice = createSlice({
|
||||||
@@ -200,11 +209,35 @@ const orderSlice = createSlice({
|
|||||||
},
|
},
|
||||||
updateRestaurant(state, action: PayloadAction<Partial<RestaurantDetails>>) {
|
updateRestaurant(state, action: PayloadAction<Partial<RestaurantDetails>>) {
|
||||||
state.restaurant = action.payload;
|
state.restaurant = action.payload;
|
||||||
|
state.visibleServices = [
|
||||||
|
action.payload.dineIn,
|
||||||
|
action.payload.delivery,
|
||||||
|
action.payload.pickup,
|
||||||
|
action.payload.gift,
|
||||||
|
action.payload.toRoom,
|
||||||
|
action.payload.toOffice,
|
||||||
|
action.payload.is_schedule_order_enabled,
|
||||||
|
action.payload.is_booking_enabled,
|
||||||
|
].filter(Boolean).length;
|
||||||
|
state.hiddenServices = state.totalServices - state.visibleServices;
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
CART_STORAGE_KEYS.RESTAURANT,
|
CART_STORAGE_KEYS.RESTAURANT,
|
||||||
JSON.stringify(state.restaurant),
|
JSON.stringify(state.restaurant),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
localStorage.setItem(
|
||||||
|
CART_STORAGE_KEYS.TOTAL_SERVICES,
|
||||||
|
JSON.stringify(state.totalServices),
|
||||||
|
);
|
||||||
|
localStorage.setItem(
|
||||||
|
CART_STORAGE_KEYS.HIDDEN_SERVICES,
|
||||||
|
JSON.stringify(state.hiddenServices),
|
||||||
|
);
|
||||||
|
localStorage.setItem(
|
||||||
|
CART_STORAGE_KEYS.VISIBLE_SERVICES,
|
||||||
|
JSON.stringify(state.visibleServices),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
addItem(
|
addItem(
|
||||||
@@ -633,7 +666,10 @@ const orderSlice = createSlice({
|
|||||||
updateOrder(state, action: PayloadAction<any>) {
|
updateOrder(state, action: PayloadAction<any>) {
|
||||||
state.order = action.payload;
|
state.order = action.payload;
|
||||||
if (typeof window !== "undefined") {
|
if (typeof window !== "undefined") {
|
||||||
localStorage.setItem(CART_STORAGE_KEYS.ORDER, JSON.stringify(state.order));
|
localStorage.setItem(
|
||||||
|
CART_STORAGE_KEYS.ORDER,
|
||||||
|
JSON.stringify(state.order),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
updateSplitBillAmount(state, action: PayloadAction<number>) {
|
updateSplitBillAmount(state, action: PayloadAction<number>) {
|
||||||
@@ -787,7 +823,13 @@ export const selectGrandTotal = (state: RootState) => {
|
|||||||
? Number(state.order.restaurant?.delivery_fees) || 0
|
? Number(state.order.restaurant?.delivery_fees) || 0
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
return subtotal + taxAmount - totalDiscount + deliveryFee - state.order.splitBillAmount;
|
return (
|
||||||
|
subtotal +
|
||||||
|
taxAmount -
|
||||||
|
totalDiscount +
|
||||||
|
deliveryFee -
|
||||||
|
state.order.splitBillAmount
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default orderSlice.reducer;
|
export default orderSlice.reducer;
|
||||||
|
|||||||
@@ -6,13 +6,24 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { useAppSelector } from "redux/hooks";
|
import { useAppSelector } from "redux/hooks";
|
||||||
import { selectCart } from "features/order/orderSlice";
|
import { selectCart } from "features/order/orderSlice";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
|
import { useGetOrderDetailsQuery } from "redux/api/others";
|
||||||
|
|
||||||
export default function BriefMenuCard() {
|
export default function BriefMenuCard() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { items } = useAppSelector(selectCart);
|
const { items } = useAppSelector(selectCart);
|
||||||
const totalItems = items.length;
|
const { subdomain, orderId } = useParams();
|
||||||
const { subdomain } = useParams();
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { data: orderDetails } = useGetOrderDetailsQuery(
|
||||||
|
{
|
||||||
|
orderID: orderId || "",
|
||||||
|
restaurantID: localStorage.getItem("restaurantID") || "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
skip: !orderId,
|
||||||
|
// return it t0 60000 after finish testing
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const totalItems = items.length || orderDetails?.orderItems.length;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -1,23 +1,59 @@
|
|||||||
import { Button, FormInstance, Layout } from "antd";
|
import { Button, FormInstance, Layout } from "antd";
|
||||||
import { selectCart } 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 } from "react";
|
import { useCallback, useMemo, useState } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useAppDispatch, useAppSelector } from "redux/hooks";
|
||||||
import { useAppSelector } from "redux/hooks";
|
|
||||||
import styles from "../../address/address.module.css";
|
import styles from "../../address/address.module.css";
|
||||||
import useOrder from "../hooks/useOrder";
|
import useOrder from "../hooks/useOrder";
|
||||||
|
import { EqualltyChoiceBottomSheet } from "pages/pay/components/splitBill/EqualltyChoiceBottomSheet";
|
||||||
|
import { SplitBillChoiceBottomSheet } from "pages/pay/components/splitBill/SplitBillChoiceBottomSheet";
|
||||||
|
import { CustomAmountChoiceBottomSheet } from "pages/pay/components/splitBill/CustomAmountChoiceBottomSheet";
|
||||||
|
import { PayForYourItemsChoiceBottomSheet } from "pages/pay/components/splitBill/PayForYourItemsChoiceBottomSheet";
|
||||||
|
|
||||||
|
type SplitWay = "customAmount" | "equality" | "payForItems" | null;
|
||||||
|
|
||||||
export default function CheckoutButton({ form }: { form: FormInstance }) {
|
export default function CheckoutButton({ form }: { form: FormInstance }) {
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { orderType } = useAppSelector(selectCart);
|
const { orderType } = useAppSelector(selectCart);
|
||||||
const navigate = useNavigate();
|
|
||||||
const { handleCreateOrder } = useOrder();
|
const { handleCreateOrder } = useOrder();
|
||||||
const { subdomain } = useParams();
|
const [selectedSplitWay, setSelectedSplitWay] = useState<SplitWay>(null);
|
||||||
|
const [
|
||||||
|
isSplitBillChoiceBottomSheetOpen,
|
||||||
|
setIsSplitBillChoiceBottomSheetOpen,
|
||||||
|
] = useState(false);
|
||||||
|
const [isCustomAmountOpen, setIsCustomAmountOpen] = useState(false);
|
||||||
|
const [isEqualityOpen, setIsEqualityOpen] = useState(false);
|
||||||
|
const [isPayForItemsOpen, setIsPayForItemsOpen] = useState(false);
|
||||||
|
|
||||||
const handleSplitBillClick = useCallback(() => {
|
const handleSplitBillClick = useCallback(() => {
|
||||||
navigate(`/${subdomain}/split-bill`);
|
if (selectedSplitWay === "customAmount") {
|
||||||
}, [navigate, subdomain]);
|
setIsCustomAmountOpen(true);
|
||||||
|
} else if (selectedSplitWay === "equality") {
|
||||||
|
setIsEqualityOpen(true);
|
||||||
|
} else if (selectedSplitWay === "payForItems") {
|
||||||
|
setIsPayForItemsOpen(true);
|
||||||
|
} else {
|
||||||
|
setIsSplitBillChoiceBottomSheetOpen(true);
|
||||||
|
}
|
||||||
|
}, [selectedSplitWay]);
|
||||||
|
|
||||||
|
const handleRemoveSplitWay = useCallback(() => {
|
||||||
|
setSelectedSplitWay(null);
|
||||||
|
dispatch(updateSplitBillAmount(0));
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
const getSplitButtonTitle = useMemo(() => {
|
||||||
|
if (selectedSplitWay === "customAmount") {
|
||||||
|
return t("splitBill.payAsCustomAmount");
|
||||||
|
} else if (selectedSplitWay === "equality") {
|
||||||
|
return t("splitBill.divideTheBillEqually");
|
||||||
|
} else if (selectedSplitWay === "payForItems") {
|
||||||
|
return t("splitBill.payForYourItems");
|
||||||
|
}
|
||||||
|
return t("checkout.splitBill");
|
||||||
|
}, [selectedSplitWay, t]);
|
||||||
|
|
||||||
const handlePlaceOrderClick = useCallback(async () => {
|
const handlePlaceOrderClick = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
@@ -34,24 +70,56 @@ export default function CheckoutButton({ form }: { form: FormInstance }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout.Footer className={styles.checkoutButtonContainer}>
|
<>
|
||||||
{shouldShowSplitBill && (
|
<Layout.Footer className={styles.checkoutButtonContainer}>
|
||||||
<Button
|
{shouldShowSplitBill && (
|
||||||
className={styles.splitBillButton}
|
<Button
|
||||||
onClick={handleSplitBillClick}
|
className={styles.splitBillButton}
|
||||||
>
|
onClick={handleSplitBillClick}
|
||||||
{t("checkout.splitBill")}
|
>
|
||||||
</Button>
|
{getSplitButtonTitle}
|
||||||
)}
|
</Button>
|
||||||
|
)}
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
shape="round"
|
shape="round"
|
||||||
className={styles.placeOrderButton}
|
className={styles.placeOrderButton}
|
||||||
onClick={handlePlaceOrderClick}
|
onClick={handlePlaceOrderClick}
|
||||||
>
|
>
|
||||||
{t("checkout.placeOrder")}
|
{t("checkout.placeOrder")}
|
||||||
</Button>
|
</Button>
|
||||||
</Layout.Footer>
|
</Layout.Footer>
|
||||||
|
|
||||||
|
<SplitBillChoiceBottomSheet
|
||||||
|
isOpen={isSplitBillChoiceBottomSheetOpen}
|
||||||
|
onClose={() => setIsSplitBillChoiceBottomSheetOpen(false)}
|
||||||
|
onSelectSplitWay={setSelectedSplitWay}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<CustomAmountChoiceBottomSheet
|
||||||
|
isOpen={isCustomAmountOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setIsCustomAmountOpen(false);
|
||||||
|
}}
|
||||||
|
onRemoveSplitWay={handleRemoveSplitWay}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<EqualltyChoiceBottomSheet
|
||||||
|
isOpen={isEqualityOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setIsEqualityOpen(false);
|
||||||
|
}}
|
||||||
|
onRemoveSplitWay={handleRemoveSplitWay}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<PayForYourItemsChoiceBottomSheet
|
||||||
|
isOpen={isPayForItemsOpen}
|
||||||
|
onClose={() => {
|
||||||
|
setIsPayForItemsOpen(false);
|
||||||
|
}}
|
||||||
|
onRemoveSplitWay={handleRemoveSplitWay}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export default function CustomerInformationCard() {
|
|||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ position: "relative", top: -30 }}>
|
<div style={{ position: "relative", top: -35 }}>
|
||||||
<ProPhoneInput label={t("login.phone")} propName="phone" />
|
<ProPhoneInput label={t("login.phone")} propName="phone" />
|
||||||
</div>
|
</div>
|
||||||
</ProInputCard>
|
</ProInputCard>
|
||||||
|
|||||||
@@ -189,7 +189,10 @@ export function CategoriesList({ categories }: CategoriesListProps) {
|
|||||||
data-category-id={category.id}
|
data-category-id={category.id}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
border: "none",
|
borderTop: "none",
|
||||||
|
borderRight: "none",
|
||||||
|
borderBottom: "none",
|
||||||
|
borderLeft: "none",
|
||||||
backgroundColor: isCategoriesSticky ? "transparent" : "var(--background)",
|
backgroundColor: isCategoriesSticky ? "transparent" : "var(--background)",
|
||||||
}}
|
}}
|
||||||
styles={{
|
styles={{
|
||||||
@@ -232,7 +235,7 @@ export function CategoriesList({ categories }: CategoriesListProps) {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<Space
|
<Space
|
||||||
direction="vertical"
|
orientation="vertical"
|
||||||
size="small"
|
size="small"
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
@@ -274,7 +277,6 @@ export function CategoriesList({ categories }: CategoriesListProps) {
|
|||||||
width: 104,
|
width: 104,
|
||||||
height: 30,
|
height: 30,
|
||||||
marginBottom: 1,
|
marginBottom: 1,
|
||||||
border: "none",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ProText
|
<ProText
|
||||||
|
|||||||
@@ -24,8 +24,6 @@ export function MenuFooter() {
|
|||||||
const grandTotal = useAppSelector(selectGrandTotal);
|
const grandTotal = useAppSelector(selectGrandTotal);
|
||||||
const { isRTL } = useAppSelector((state) => state.locale);
|
const { isRTL } = useAppSelector((state) => state.locale);
|
||||||
|
|
||||||
console.log(orderType);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{(isMobile || isTablet) && (
|
{(isMobile || isTablet) && (
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import useBreakPoint from "hooks/useBreakPoint";
|
|||||||
import { useRestaurant } from "hooks/useRestaurant";
|
import { useRestaurant } from "hooks/useRestaurant";
|
||||||
import { OrderType } from "pages/checkout/hooks/types.ts";
|
import { OrderType } from "pages/checkout/hooks/types.ts";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { useParams, useSearchParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
useGetMenuQuery,
|
useGetMenuQuery,
|
||||||
useGetRestaurantDetailsQuery,
|
useGetRestaurantDetailsQuery,
|
||||||
@@ -33,11 +33,10 @@ import NextIcon from "components/Icons/NextIcon";
|
|||||||
import { OpeningTimesBottomSheet } from "components/CustomBottomSheet/OpeningTimesBottomSheet";
|
import { OpeningTimesBottomSheet } from "components/CustomBottomSheet/OpeningTimesBottomSheet";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import BackIcon from "components/Icons/BackIcon";
|
import BackIcon from "components/Icons/BackIcon";
|
||||||
|
import { OrderTypesBottomSheet } from "components/CustomBottomSheet/OrderTypesBottomSheet";
|
||||||
|
|
||||||
function MenuPage() {
|
function MenuPage() {
|
||||||
const { subdomain } = useParams();
|
const { subdomain } = useParams();
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
const [_, setSearchParams] = useSearchParams();
|
|
||||||
const { isRTL } = useAppSelector((state) => state.locale);
|
const { isRTL } = useAppSelector((state) => state.locale);
|
||||||
const { orderType } = useAppSelector((state) => state.order);
|
const { orderType } = useAppSelector((state) => state.order);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -55,6 +54,7 @@ function MenuPage() {
|
|||||||
const { isMobile, isTablet, isDesktop } = useBreakPoint();
|
const { isMobile, isTablet, isDesktop } = useBreakPoint();
|
||||||
const isLoading = isLoadingRestaurant || isLoadingMenu;
|
const isLoading = isLoadingRestaurant || isLoadingMenu;
|
||||||
const [isOpeningTimesOpen, setIsOpeningTimesOpen] = useState(false);
|
const [isOpeningTimesOpen, setIsOpeningTimesOpen] = useState(false);
|
||||||
|
const [isOrderTypesOpen, setIsOrderTypesOpen] = useState(false);
|
||||||
const orderTypeOptions = enumToSelectOptions(OrderType, t, "orderTypes");
|
const orderTypeOptions = enumToSelectOptions(OrderType, t, "orderTypes");
|
||||||
|
|
||||||
// Automatically load restaurant taxes when restaurant data is available
|
// Automatically load restaurant taxes when restaurant data is available
|
||||||
@@ -99,16 +99,18 @@ function MenuPage() {
|
|||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
value={orderType}
|
value={orderType}
|
||||||
onChange={(value) => {
|
|
||||||
setSearchParams({ orderType: value });
|
|
||||||
}}
|
|
||||||
options={orderTypeOptions}
|
options={orderTypeOptions}
|
||||||
|
open={false}
|
||||||
|
onOpenChange={() => false}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setIsOrderTypesOpen(true);
|
||||||
|
}}
|
||||||
variant="borderless"
|
variant="borderless"
|
||||||
size="small"
|
size="small"
|
||||||
className={styles.orderTypeSelect}
|
className={styles.orderTypeSelect}
|
||||||
classNames={{ popup: { root: "order-type-select-dropdown" } }}
|
classNames={{ popup: { root: "order-type-select-dropdown" } }}
|
||||||
listHeight={150}
|
listHeight={150}
|
||||||
disabled
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<SearchButton />
|
<SearchButton />
|
||||||
@@ -139,7 +141,7 @@ function MenuPage() {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
iconPosition="end"
|
iconPlacement="end"
|
||||||
onClick={() => setIsOpeningTimesOpen(true)}
|
onClick={() => setIsOpeningTimesOpen(true)}
|
||||||
>
|
>
|
||||||
{restaurant?.isOpened ? t("menu.open") : t("menu.close")}
|
{restaurant?.isOpened ? t("menu.open") : t("menu.close")}
|
||||||
@@ -185,6 +187,10 @@ function MenuPage() {
|
|||||||
isOpen={isOpeningTimesOpen}
|
isOpen={isOpeningTimesOpen}
|
||||||
onClose={() => setIsOpeningTimesOpen(false)}
|
onClose={() => setIsOpeningTimesOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
<OrderTypesBottomSheet
|
||||||
|
isOpen={isOrderTypesOpen}
|
||||||
|
onClose={() => setIsOrderTypesOpen(false)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -244,4 +244,19 @@
|
|||||||
height: 24px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inviteToBillCard {
|
||||||
|
width: 100%;
|
||||||
|
height: 48px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: 12px 18px !important;
|
||||||
|
row-gap: 10px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
border-radius: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inviteToBillCard :global(.ant-card-body) {
|
||||||
|
padding: 0px !important;
|
||||||
|
text-align: start;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import TimeIcon from "components/Icons/order/TimeIcon";
|
|||||||
import OrderDishIcon from "components/Icons/OrderDishIcon";
|
import OrderDishIcon from "components/Icons/OrderDishIcon";
|
||||||
import PaymentDetails from "components/PaymentDetails/PaymentDetails";
|
import PaymentDetails from "components/PaymentDetails/PaymentDetails";
|
||||||
import ProHeader from "components/ProHeader/ProHeader";
|
import ProHeader from "components/ProHeader/ProHeader";
|
||||||
import ProInputCard from "components/ProInputCard/ProInputCard";
|
|
||||||
import ProText from "components/ProText";
|
import ProText from "components/ProText";
|
||||||
import ProTitle from "components/ProTitle";
|
import ProTitle from "components/ProTitle";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
@@ -24,6 +23,8 @@ import styles from "./order.module.css";
|
|||||||
import BackIcon from "components/Icons/BackIcon";
|
import BackIcon from "components/Icons/BackIcon";
|
||||||
import NextIcon from "components/Icons/NextIcon";
|
import NextIcon from "components/Icons/NextIcon";
|
||||||
import { RateBottomSheet } from "components/CustomBottomSheet/RateBottomSheet";
|
import { RateBottomSheet } from "components/CustomBottomSheet/RateBottomSheet";
|
||||||
|
import BriefMenuCard from "pages/checkout/components/BriefMenuCard";
|
||||||
|
import { QRBottomSheet } from "pages/pay/components/splitBill/QRBottomSheet";
|
||||||
|
|
||||||
export default function OrderPage() {
|
export default function OrderPage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@@ -32,6 +33,7 @@ export default function OrderPage() {
|
|||||||
const { restaurant } = useAppSelector((state) => state.order);
|
const { restaurant } = useAppSelector((state) => state.order);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const hasRefetchedRef = useRef(false);
|
const hasRefetchedRef = useRef(false);
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const { data: orderDetails } = useGetOrderDetailsQuery(
|
const { data: orderDetails } = useGetOrderDetailsQuery(
|
||||||
{
|
{
|
||||||
@@ -346,7 +348,7 @@ export default function OrderPage() {
|
|||||||
|
|
||||||
<Ads2 />
|
<Ads2 />
|
||||||
|
|
||||||
<ProInputCard
|
{/* <ProInputCard
|
||||||
title={
|
title={
|
||||||
<div style={{ marginBottom: 7 }}>
|
<div style={{ marginBottom: 7 }}>
|
||||||
<ProText style={{ fontSize: "1rem" }}>
|
<ProText style={{ fontSize: "1rem" }}>
|
||||||
@@ -393,7 +395,9 @@ export default function OrderPage() {
|
|||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</ProInputCard>
|
</ProInputCard> */}
|
||||||
|
|
||||||
|
<BriefMenuCard />
|
||||||
|
|
||||||
<PaymentDetails order={orderDetails?.order} />
|
<PaymentDetails order={orderDetails?.order} />
|
||||||
|
|
||||||
@@ -439,6 +443,34 @@ export default function OrderPage() {
|
|||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
|
<Card
|
||||||
|
className={styles.inviteToBillCard}
|
||||||
|
onClick={() => setIsOpen(true)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "center",
|
||||||
|
marginTop: 1,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: "flex", flexDirection: "row", gap: 10 }}>
|
||||||
|
<ProTitle
|
||||||
|
level={5}
|
||||||
|
style={{
|
||||||
|
marginTop: 1,
|
||||||
|
fontSize: 14,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("order.inviteToBill")}
|
||||||
|
</ProTitle>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
<QRBottomSheet isOpen={isOpen} onClose={() => setIsOpen(false)} />
|
||||||
|
|
||||||
<RateBottomSheet />
|
<RateBottomSheet />
|
||||||
|
|
||||||
<CancelOrderBottomSheet />
|
<CancelOrderBottomSheet />
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import { useAppDispatch, useAppSelector } from "redux/hooks";
|
|||||||
import ProText from "components/ProText";
|
import ProText from "components/ProText";
|
||||||
import ArabicPrice from "components/ArabicPrice";
|
import ArabicPrice from "components/ArabicPrice";
|
||||||
import styles from "./SplitBill.module.css";
|
import styles from "./SplitBill.module.css";
|
||||||
import { QRBottomSheet } from "./QRBottomSheet";
|
|
||||||
|
|
||||||
interface SplitBillChoiceBottomSheetProps {
|
interface SplitBillChoiceBottomSheetProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -32,7 +31,6 @@ export function CustomAmountChoiceBottomSheet({
|
|||||||
const [amount, setAmount] = useState<string>(
|
const [amount, setAmount] = useState<string>(
|
||||||
splitBillAmount > 0 ? splitBillAmount.toString() : "",
|
splitBillAmount > 0 ? splitBillAmount.toString() : "",
|
||||||
);
|
);
|
||||||
const [isQROpen, setIsQROpen] = useState(false);
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen && splitBillAmount > 0) {
|
if (isOpen && splitBillAmount > 0) {
|
||||||
setAmount(splitBillAmount.toString());
|
setAmount(splitBillAmount.toString());
|
||||||
@@ -42,7 +40,6 @@ export function CustomAmountChoiceBottomSheet({
|
|||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
const numAmount = parseFloat(amount) || 0;
|
const numAmount = parseFloat(amount) || 0;
|
||||||
dispatch(updateSplitBillAmount(numAmount));
|
dispatch(updateSplitBillAmount(numAmount));
|
||||||
setIsQROpen(true);
|
|
||||||
onClose();
|
onClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -62,7 +59,6 @@ export function CustomAmountChoiceBottomSheet({
|
|||||||
const previewRemaining = originalTotalBill - currentAmount;
|
const previewRemaining = originalTotalBill - currentAmount;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
|
||||||
<ProBottomSheet
|
<ProBottomSheet
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
onClose={onClose}
|
onClose={onClose}
|
||||||
@@ -193,7 +189,5 @@ export function CustomAmountChoiceBottomSheet({
|
|||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</ProBottomSheet>
|
</ProBottomSheet>
|
||||||
<QRBottomSheet isOpen={isQROpen} onClose={() => setIsQROpen(false)} />
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import { ProGray1 } from "ThemeConstants";
|
|||||||
import PayForActions from "../../../split-bill/components/PayForActions";
|
import PayForActions from "../../../split-bill/components/PayForActions";
|
||||||
import TotalPeopleActions from "../../../split-bill/components/TotalPeopleActions";
|
import TotalPeopleActions from "../../../split-bill/components/TotalPeopleActions";
|
||||||
import styles from "./SplitBill.module.css";
|
import styles from "./SplitBill.module.css";
|
||||||
import { QRBottomSheet } from "./QRBottomSheet";
|
|
||||||
|
|
||||||
interface SplitBillChoiceBottomSheetProps {
|
interface SplitBillChoiceBottomSheetProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -38,7 +37,6 @@ export function EqualltyChoiceBottomSheet({
|
|||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { tmp, splitBillAmount } = useAppSelector(selectCart);
|
const { tmp, splitBillAmount } = useAppSelector(selectCart);
|
||||||
const grandTotal = useAppSelector(selectGrandTotal);
|
const grandTotal = useAppSelector(selectGrandTotal);
|
||||||
const [isQROpen, setIsQROpen] = useState(false);
|
|
||||||
const splitBillTmp = tmp as SplitBillTmp;
|
const splitBillTmp = tmp as SplitBillTmp;
|
||||||
const totalPeople = splitBillTmp?.totalPeople || 2;
|
const totalPeople = splitBillTmp?.totalPeople || 2;
|
||||||
const payFor = splitBillTmp?.payFor || 1;
|
const payFor = splitBillTmp?.payFor || 1;
|
||||||
@@ -56,7 +54,6 @@ export function EqualltyChoiceBottomSheet({
|
|||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
dispatch(updateSplitBillAmount(splitAmount));
|
dispatch(updateSplitBillAmount(splitAmount));
|
||||||
setIsQROpen(true);
|
|
||||||
onClose();
|
onClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -67,284 +64,281 @@ export function EqualltyChoiceBottomSheet({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ProBottomSheet
|
||||||
<ProBottomSheet
|
isOpen={isOpen}
|
||||||
isOpen={isOpen}
|
onClose={onClose}
|
||||||
onClose={onClose}
|
title={t("splitBill.divideTheBillEqually")}
|
||||||
title={t("splitBill.divideTheBillEqually")}
|
showCloseButton={true}
|
||||||
showCloseButton={true}
|
initialSnap={1}
|
||||||
initialSnap={1}
|
height={630}
|
||||||
height={630}
|
snapPoints={[630]}
|
||||||
snapPoints={[630]}
|
contentStyle={{
|
||||||
contentStyle={{
|
padding: 0,
|
||||||
padding: 0,
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
marginTop: 20,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{/* Spinner Visualization - Blank Spin Wheel */}
|
||||||
|
{totalPeople > 0 && (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: 12,
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: "relative",
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
margin: "0 auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
width="200"
|
||||||
|
height="200"
|
||||||
|
viewBox="0 0 200 200"
|
||||||
|
style={{
|
||||||
|
transform: "rotate(-90deg)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{Array.from({ length: totalPeople }).map((_, index) => {
|
||||||
|
const anglePerSlice = 360 / totalPeople;
|
||||||
|
const startAngle = index * anglePerSlice;
|
||||||
|
const endAngle = (index + 1) * anglePerSlice;
|
||||||
|
const isSelected = index < payFor;
|
||||||
|
|
||||||
|
// Convert angles to radians
|
||||||
|
const startAngleRad = (startAngle * Math.PI) / 180;
|
||||||
|
const endAngleRad = (endAngle * Math.PI) / 180;
|
||||||
|
|
||||||
|
// Calculate path for pie slice (fit 200x200 viewBox)
|
||||||
|
const radius = 90;
|
||||||
|
const centerX = 100;
|
||||||
|
const centerY = 100;
|
||||||
|
|
||||||
|
const x1 = centerX + radius * Math.cos(startAngleRad);
|
||||||
|
const y1 = centerY + radius * Math.sin(startAngleRad);
|
||||||
|
const x2 = centerX + radius * Math.cos(endAngleRad);
|
||||||
|
const y2 = centerY + radius * Math.sin(endAngleRad);
|
||||||
|
|
||||||
|
const largeArcFlag = anglePerSlice > 180 ? 1 : 0;
|
||||||
|
|
||||||
|
const pathData = [
|
||||||
|
`M ${centerX} ${centerY}`,
|
||||||
|
`L ${x1} ${y1}`,
|
||||||
|
`A ${radius} ${radius} 0 ${largeArcFlag} 1 ${x2} ${y2}`,
|
||||||
|
"Z",
|
||||||
|
].join(" ");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<path
|
||||||
|
key={index}
|
||||||
|
d={pathData}
|
||||||
|
fill={
|
||||||
|
isSelected ? "var(--primary)" : "rgba(0, 0, 0, 0.1)"
|
||||||
|
}
|
||||||
|
stroke="#fff"
|
||||||
|
strokeWidth="5"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</svg>
|
||||||
|
{/* Center circle with total bill amount */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
position: "absolute",
|
||||||
|
top: "50%",
|
||||||
|
left: "50%",
|
||||||
|
transform: "translate(-50%, -50%)",
|
||||||
|
// Keep the SVG at 200x200, but make the center content smaller
|
||||||
|
// so the wheel remains visible around it.
|
||||||
|
width: 160,
|
||||||
|
height: 160,
|
||||||
|
borderRadius: "50%",
|
||||||
|
backgroundColor: "var(--secondary-background)",
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
zIndex: 10,
|
||||||
|
padding: 10,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 600,
|
||||||
|
color: "var(--primary)",
|
||||||
|
lineHeight: 1.1,
|
||||||
|
textAlign: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ArabicPrice
|
||||||
|
price={originalTotalBill}
|
||||||
|
style={{
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: 600,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ProText
|
||||||
|
style={{
|
||||||
|
fontSize: 11,
|
||||||
|
color: ProGray1,
|
||||||
|
marginTop: 6,
|
||||||
|
textAlign: "center",
|
||||||
|
lineHeight: 1.2,
|
||||||
|
fontWeight: 400,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("splitBill.totalBill")}
|
||||||
|
</ProText>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
marginTop: 20,
|
gap: "1rem",
|
||||||
|
padding: 20,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Spinner Visualization - Blank Spin Wheel */}
|
|
||||||
{totalPeople > 0 && (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
gap: 12,
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
position: "relative",
|
|
||||||
width: 200,
|
|
||||||
height: 200,
|
|
||||||
margin: "0 auto",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
width="200"
|
|
||||||
height="200"
|
|
||||||
viewBox="0 0 200 200"
|
|
||||||
style={{
|
|
||||||
transform: "rotate(-90deg)",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{Array.from({ length: totalPeople }).map((_, index) => {
|
|
||||||
const anglePerSlice = 360 / totalPeople;
|
|
||||||
const startAngle = index * anglePerSlice;
|
|
||||||
const endAngle = (index + 1) * anglePerSlice;
|
|
||||||
const isSelected = index < payFor;
|
|
||||||
|
|
||||||
// Convert angles to radians
|
|
||||||
const startAngleRad = (startAngle * Math.PI) / 180;
|
|
||||||
const endAngleRad = (endAngle * Math.PI) / 180;
|
|
||||||
|
|
||||||
// Calculate path for pie slice (fit 200x200 viewBox)
|
|
||||||
const radius = 90;
|
|
||||||
const centerX = 100;
|
|
||||||
const centerY = 100;
|
|
||||||
|
|
||||||
const x1 = centerX + radius * Math.cos(startAngleRad);
|
|
||||||
const y1 = centerY + radius * Math.sin(startAngleRad);
|
|
||||||
const x2 = centerX + radius * Math.cos(endAngleRad);
|
|
||||||
const y2 = centerY + radius * Math.sin(endAngleRad);
|
|
||||||
|
|
||||||
const largeArcFlag = anglePerSlice > 180 ? 1 : 0;
|
|
||||||
|
|
||||||
const pathData = [
|
|
||||||
`M ${centerX} ${centerY}`,
|
|
||||||
`L ${x1} ${y1}`,
|
|
||||||
`A ${radius} ${radius} 0 ${largeArcFlag} 1 ${x2} ${y2}`,
|
|
||||||
"Z",
|
|
||||||
].join(" ");
|
|
||||||
|
|
||||||
return (
|
|
||||||
<path
|
|
||||||
key={index}
|
|
||||||
d={pathData}
|
|
||||||
fill={
|
|
||||||
isSelected ? "var(--primary)" : "rgba(0, 0, 0, 0.1)"
|
|
||||||
}
|
|
||||||
stroke="#fff"
|
|
||||||
strokeWidth="5"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</svg>
|
|
||||||
{/* Center circle with total bill amount */}
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
position: "absolute",
|
|
||||||
top: "50%",
|
|
||||||
left: "50%",
|
|
||||||
transform: "translate(-50%, -50%)",
|
|
||||||
// Keep the SVG at 200x200, but make the center content smaller
|
|
||||||
// so the wheel remains visible around it.
|
|
||||||
width: 160,
|
|
||||||
height: 160,
|
|
||||||
borderRadius: "50%",
|
|
||||||
backgroundColor: "var(--secondary-background)",
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
zIndex: 10,
|
|
||||||
padding: 10,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: 600,
|
|
||||||
color: "var(--primary)",
|
|
||||||
lineHeight: 1.1,
|
|
||||||
textAlign: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ArabicPrice
|
|
||||||
price={originalTotalBill}
|
|
||||||
style={{
|
|
||||||
fontSize: 20,
|
|
||||||
fontWeight: 600,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<ProText
|
|
||||||
style={{
|
|
||||||
fontSize: 11,
|
|
||||||
color: ProGray1,
|
|
||||||
marginTop: 6,
|
|
||||||
textAlign: "center",
|
|
||||||
lineHeight: 1.2,
|
|
||||||
fontWeight: 400,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("splitBill.totalBill")}
|
|
||||||
</ProText>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
gap: "1rem",
|
gap: "1rem",
|
||||||
padding: 20,
|
padding: 8,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<ProText
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
fontSize: "1rem",
|
||||||
flexDirection: "row",
|
marginTop: 3,
|
||||||
justifyContent: "space-between",
|
color: ProGray1,
|
||||||
gap: "1rem",
|
|
||||||
padding: 8,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ProText
|
{t("checkout.totalPeople")}
|
||||||
style={{
|
</ProText>
|
||||||
fontSize: "1rem",
|
|
||||||
marginTop: 3,
|
|
||||||
color: ProGray1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("checkout.totalPeople")}
|
|
||||||
</ProText>
|
|
||||||
|
|
||||||
<TotalPeopleActions />
|
<TotalPeopleActions />
|
||||||
|
|
||||||
<ProText
|
<ProText
|
||||||
style={{
|
|
||||||
fontSize: "1rem",
|
|
||||||
marginTop: 3,
|
|
||||||
color: ProGray1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("checkout.totalPeople")}
|
|
||||||
</ProText>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
fontSize: "1rem",
|
||||||
flexDirection: "row",
|
marginTop: 3,
|
||||||
justifyContent: "space-between",
|
color: ProGray1,
|
||||||
gap: "1rem",
|
|
||||||
padding: 8,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ProText
|
{t("checkout.totalPeople")}
|
||||||
style={{
|
</ProText>
|
||||||
fontSize: "1rem",
|
|
||||||
marginTop: 2,
|
|
||||||
color: ProGray1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("checkout.payFor")}
|
|
||||||
</ProText>
|
|
||||||
|
|
||||||
<PayForActions />
|
|
||||||
|
|
||||||
<ProText
|
|
||||||
style={{
|
|
||||||
fontSize: "1rem",
|
|
||||||
marginTop: 2,
|
|
||||||
color: ProGray1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("checkout.payFor")}
|
|
||||||
</ProText>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "row",
|
||||||
backgroundColor: "var(--background)",
|
justifyContent: "space-between",
|
||||||
padding: 20,
|
gap: "1rem",
|
||||||
opacity: 1,
|
padding: 8,
|
||||||
gap: 8,
|
|
||||||
borderTopLeftRadius: 24,
|
|
||||||
borderTopRightRadius: 24,
|
|
||||||
paddingTop: 12,
|
|
||||||
paddingRight: 24,
|
|
||||||
paddingBottom: 24,
|
|
||||||
paddingLeft: 24,
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className={styles.summaryRow}>
|
<ProText
|
||||||
<ProText
|
|
||||||
style={{
|
|
||||||
fontWeight: 400,
|
|
||||||
fontStyle: "Regular",
|
|
||||||
fontSize: 14,
|
|
||||||
lineHeight: "140%",
|
|
||||||
letterSpacing: "0%",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{t("splitBill.yourShare")}
|
|
||||||
</ProText>
|
|
||||||
<ArabicPrice price={splitAmount} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
gap: 12,
|
|
||||||
margin: 20,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Button
|
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
fontSize: "1rem",
|
||||||
backgroundColor: "#FEEDED",
|
marginTop: 2,
|
||||||
color: "#DD4143",
|
color: ProGray1,
|
||||||
boxShadow: "none",
|
|
||||||
border: "none",
|
|
||||||
}}
|
}}
|
||||||
onClick={handleRemoveSplitWay}
|
|
||||||
>
|
>
|
||||||
{t("splitBill.removeSplit")}
|
{t("checkout.payFor")}
|
||||||
</Button>
|
</ProText>
|
||||||
<Button
|
|
||||||
type="primary"
|
<PayForActions />
|
||||||
style={{ flex: 1, boxShadow: "none" }}
|
|
||||||
onClick={handleSave}
|
<ProText
|
||||||
|
style={{
|
||||||
|
fontSize: "1rem",
|
||||||
|
marginTop: 2,
|
||||||
|
color: ProGray1,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{t("cart.save")}
|
{t("checkout.payFor")}
|
||||||
</Button>
|
</ProText>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ProBottomSheet>
|
|
||||||
<QRBottomSheet isOpen={isQROpen} onClose={() => setIsQROpen(false)} />
|
<div
|
||||||
</>
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
backgroundColor: "var(--background)",
|
||||||
|
padding: 20,
|
||||||
|
opacity: 1,
|
||||||
|
gap: 8,
|
||||||
|
borderTopLeftRadius: 24,
|
||||||
|
borderTopRightRadius: 24,
|
||||||
|
paddingTop: 12,
|
||||||
|
paddingRight: 24,
|
||||||
|
paddingBottom: 24,
|
||||||
|
paddingLeft: 24,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className={styles.summaryRow}>
|
||||||
|
<ProText
|
||||||
|
style={{
|
||||||
|
fontWeight: 400,
|
||||||
|
fontStyle: "Regular",
|
||||||
|
fontSize: 14,
|
||||||
|
lineHeight: "140%",
|
||||||
|
letterSpacing: "0%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("splitBill.yourShare")}
|
||||||
|
</ProText>
|
||||||
|
<ArabicPrice price={splitAmount} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
gap: 12,
|
||||||
|
margin: 20,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
backgroundColor: "#FEEDED",
|
||||||
|
color: "#DD4143",
|
||||||
|
boxShadow: "none",
|
||||||
|
border: "none",
|
||||||
|
}}
|
||||||
|
onClick={handleRemoveSplitWay}
|
||||||
|
>
|
||||||
|
{t("splitBill.removeSplit")}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
style={{ flex: 1, boxShadow: "none" }}
|
||||||
|
onClick={handleSave}
|
||||||
|
>
|
||||||
|
{t("cart.save")}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ProBottomSheet>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import ProText from "components/ProText";
|
|||||||
import { selectCart, updateSplitBillAmount } from "features/order/orderSlice";
|
import { selectCart, updateSplitBillAmount } from "features/order/orderSlice";
|
||||||
import { useAppDispatch, useAppSelector } from "redux/hooks";
|
import { useAppDispatch, useAppSelector } from "redux/hooks";
|
||||||
import styles from "./SplitBill.module.css";
|
import styles from "./SplitBill.module.css";
|
||||||
import { QRBottomSheet } from "./QRBottomSheet";
|
|
||||||
|
|
||||||
interface SplitBillChoiceBottomSheetProps {
|
interface SplitBillChoiceBottomSheetProps {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
@@ -26,7 +25,6 @@ export function PayForYourItemsChoiceBottomSheet({
|
|||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const { items } = useAppSelector(selectCart);
|
const { items } = useAppSelector(selectCart);
|
||||||
const [selectedItems, setSelectedItems] = useState<Set<string>>(new Set());
|
const [selectedItems, setSelectedItems] = useState<Set<string>>(new Set());
|
||||||
const [isQROpen, setIsQROpen] = useState(false);
|
|
||||||
// Calculate total for selected items
|
// Calculate total for selected items
|
||||||
const selectedTotal = items
|
const selectedTotal = items
|
||||||
.filter((item) => selectedItems.has(item.uniqueId || item.id.toString()))
|
.filter((item) => selectedItems.has(item.uniqueId || item.id.toString()))
|
||||||
@@ -57,7 +55,6 @@ export function PayForYourItemsChoiceBottomSheet({
|
|||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
dispatch(updateSplitBillAmount(selectedTotal));
|
dispatch(updateSplitBillAmount(selectedTotal));
|
||||||
setIsQROpen(true);
|
|
||||||
onClose();
|
onClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -69,162 +66,159 @@ export function PayForYourItemsChoiceBottomSheet({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ProBottomSheet
|
||||||
<ProBottomSheet
|
isOpen={isOpen}
|
||||||
isOpen={isOpen}
|
onClose={onClose}
|
||||||
onClose={onClose}
|
title={t("splitBill.payForYourItems")}
|
||||||
title={t("splitBill.payForYourItems")}
|
showCloseButton={true}
|
||||||
showCloseButton={true}
|
initialSnap={1}
|
||||||
initialSnap={1}
|
height={720}
|
||||||
height={720}
|
snapPoints={[720]}
|
||||||
snapPoints={[720]}
|
contentStyle={{ padding: 0 }}
|
||||||
contentStyle={{ padding: 0 }}
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: 20,
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: 12,
|
||||||
|
maxHeight: "455px",
|
||||||
|
minHeight: "455px",
|
||||||
|
overflowY: "auto",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{items.length === 0 ? (
|
||||||
|
<ProText
|
||||||
|
type="secondary"
|
||||||
|
style={{ textAlign: "center", padding: 20 }}
|
||||||
|
>
|
||||||
|
{t("cart.emptyCart")}
|
||||||
|
</ProText>
|
||||||
|
) : (
|
||||||
|
items.map((item) => {
|
||||||
|
const itemId = item.uniqueId || item.id.toString();
|
||||||
|
const isSelected = selectedItems.has(itemId);
|
||||||
|
const itemTotal = item.price * item.quantity;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card
|
||||||
|
key={itemId}
|
||||||
|
style={{
|
||||||
|
border: "none",
|
||||||
|
cursor: "pointer",
|
||||||
|
padding: 0,
|
||||||
|
}}
|
||||||
|
onClick={() => handleItemToggle(itemId)}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: 12,
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Image
|
||||||
|
src={item.image}
|
||||||
|
alt={item.name}
|
||||||
|
width={60}
|
||||||
|
height={60}
|
||||||
|
preview={false}
|
||||||
|
style={{
|
||||||
|
borderRadius: 8,
|
||||||
|
objectFit: "cover",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 1,
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: 4,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ProText style={{ fontSize: 14, fontWeight: 500 }}>
|
||||||
|
{item.name}
|
||||||
|
</ProText>
|
||||||
|
<ArabicPrice price={itemTotal} />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
minWidth: 32,
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
onClick={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
|
<Checkbox
|
||||||
|
className={styles.circleCheckbox}
|
||||||
|
checked={isSelected}
|
||||||
|
onChange={() => handleItemToggle(itemId)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
{item !== items[items.length - 1] && (
|
||||||
|
<Divider style={{ margin: "0" }} />
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
})
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
padding: 16,
|
||||||
|
backgroundColor: "rgba(255, 183, 0, 0.08)",
|
||||||
|
borderRadius: 8,
|
||||||
|
marginTop: 8,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
padding: 20,
|
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
justifyContent: "space-between",
|
||||||
gap: 12,
|
alignItems: "center",
|
||||||
maxHeight: "455px",
|
|
||||||
minHeight: "455px",
|
|
||||||
overflowY: "auto",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{items.length === 0 ? (
|
<ProText style={{ fontSize: 16, fontWeight: 600 }}>
|
||||||
<ProText
|
{t("splitBill.selectedTotal")}:
|
||||||
type="secondary"
|
</ProText>
|
||||||
style={{ textAlign: "center", padding: 20 }}
|
<ArabicPrice price={selectedTotal} />
|
||||||
>
|
|
||||||
{t("cart.emptyCart")}
|
|
||||||
</ProText>
|
|
||||||
) : (
|
|
||||||
items.map((item) => {
|
|
||||||
const itemId = item.uniqueId || item.id.toString();
|
|
||||||
const isSelected = selectedItems.has(itemId);
|
|
||||||
const itemTotal = item.price * item.quantity;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Card
|
|
||||||
key={itemId}
|
|
||||||
style={{
|
|
||||||
border: "none",
|
|
||||||
cursor: "pointer",
|
|
||||||
padding: 0,
|
|
||||||
}}
|
|
||||||
onClick={() => handleItemToggle(itemId)}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
gap: 12,
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Image
|
|
||||||
src={item.image}
|
|
||||||
alt={item.name}
|
|
||||||
width={60}
|
|
||||||
height={60}
|
|
||||||
preview={false}
|
|
||||||
style={{
|
|
||||||
borderRadius: 8,
|
|
||||||
objectFit: "cover",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
flex: 1,
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
gap: 4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ProText style={{ fontSize: 14, fontWeight: 500 }}>
|
|
||||||
{item.name}
|
|
||||||
</ProText>
|
|
||||||
<ArabicPrice price={itemTotal} />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: 32,
|
|
||||||
height: 32,
|
|
||||||
minWidth: 32,
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
}}
|
|
||||||
onClick={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
<Checkbox
|
|
||||||
className={styles.circleCheckbox}
|
|
||||||
checked={isSelected}
|
|
||||||
onChange={() => handleItemToggle(itemId)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
{item !== items[items.length - 1] && (
|
|
||||||
<Divider style={{ margin: "0" }} />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
})
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
</div>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
gap: 12,
|
||||||
|
margin: 20,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
style={{
|
style={{
|
||||||
padding: 16,
|
flex: 1,
|
||||||
backgroundColor: "rgba(255, 183, 0, 0.08)",
|
backgroundColor: "#FEEDED",
|
||||||
borderRadius: 8,
|
color: "#DD4143",
|
||||||
marginTop: 8,
|
boxShadow: "none",
|
||||||
|
border: "none",
|
||||||
}}
|
}}
|
||||||
|
onClick={handleRemoveSplitWay}
|
||||||
>
|
>
|
||||||
<div
|
{t("splitBill.removeSplit")}
|
||||||
style={{
|
</Button>
|
||||||
display: "flex",
|
<Button
|
||||||
justifyContent: "space-between",
|
type="primary"
|
||||||
alignItems: "center",
|
style={{ flex: 1, boxShadow: "none" }}
|
||||||
}}
|
onClick={handleSave}
|
||||||
>
|
disabled={selectedTotal === 0}
|
||||||
<ProText style={{ fontSize: 16, fontWeight: 600 }}>
|
|
||||||
{t("splitBill.selectedTotal")}:
|
|
||||||
</ProText>
|
|
||||||
<ArabicPrice price={selectedTotal} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
gap: 12,
|
|
||||||
margin: 20,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Button
|
{t("cart.save")}
|
||||||
style={{
|
</Button>
|
||||||
flex: 1,
|
</div>
|
||||||
backgroundColor: "#FEEDED",
|
</ProBottomSheet>
|
||||||
color: "#DD4143",
|
|
||||||
boxShadow: "none",
|
|
||||||
border: "none",
|
|
||||||
}}
|
|
||||||
onClick={handleRemoveSplitWay}
|
|
||||||
>
|
|
||||||
{t("splitBill.removeSplit")}
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
style={{ flex: 1, boxShadow: "none" }}
|
|
||||||
onClick={handleSave}
|
|
||||||
disabled={selectedTotal === 0}
|
|
||||||
>
|
|
||||||
{t("cart.save")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</ProBottomSheet>
|
|
||||||
<QRBottomSheet isOpen={isQROpen} onClose={() => setIsQROpen(false)} />
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,126 +55,123 @@ export function SplitBillChoiceBottomSheet({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ProBottomSheet
|
<ProBottomSheet
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
onClose={handleCancel}
|
onClose={handleCancel}
|
||||||
title={t("splitBill.title")}
|
title={t("splitBill.title")}
|
||||||
showCloseButton={false}
|
showCloseButton={false}
|
||||||
initialSnap={1}
|
initialSnap={1}
|
||||||
height={290}
|
height={290}
|
||||||
snapPoints={[290]}
|
snapPoints={[290]}
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
marginTop: 20,
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
gap: 10,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<Card
|
<div
|
||||||
className={styles.backToHomePage}
|
style={{
|
||||||
onClick={handleCustomAmountClick}
|
marginTop: 20,
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
gap: 10,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<Card
|
||||||
style={{
|
className={styles.backToHomePage}
|
||||||
display: "flex",
|
onClick={handleCustomAmountClick}
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
marginTop: 1,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<ProTitle
|
<div
|
||||||
level={5}
|
|
||||||
style={{
|
style={{
|
||||||
fontSize: 14,
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginTop: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("splitBill.payAsCustomAmount")}
|
<ProTitle
|
||||||
</ProTitle>
|
level={5}
|
||||||
|
style={{
|
||||||
|
fontSize: 14,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("splitBill.payAsCustomAmount")}
|
||||||
|
</ProTitle>
|
||||||
|
|
||||||
{isRTL ? (
|
{isRTL ? (
|
||||||
<BackIcon className={styles.serviceIcon} />
|
<BackIcon className={styles.serviceIcon} />
|
||||||
) : (
|
) : (
|
||||||
<NextIcon className={styles.serviceIcon} />
|
<NextIcon className={styles.serviceIcon} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card
|
<Card className={styles.backToHomePage} onClick={handleEqualityClick}>
|
||||||
className={styles.backToHomePage}
|
<div
|
||||||
onClick={handleEqualityClick}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
marginTop: 1,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ProTitle
|
|
||||||
level={5}
|
|
||||||
style={{
|
style={{
|
||||||
fontSize: 14,
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginTop: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("splitBill.divideTheBillEqually")}
|
<ProTitle
|
||||||
</ProTitle>
|
level={5}
|
||||||
|
style={{
|
||||||
|
fontSize: 14,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("splitBill.divideTheBillEqually")}
|
||||||
|
</ProTitle>
|
||||||
|
|
||||||
{isRTL ? (
|
{isRTL ? (
|
||||||
<BackIcon className={styles.serviceIcon} />
|
<BackIcon className={styles.serviceIcon} />
|
||||||
) : (
|
) : (
|
||||||
<NextIcon className={styles.serviceIcon} />
|
<NextIcon className={styles.serviceIcon} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
<Card
|
<Card
|
||||||
className={styles.backToHomePage}
|
className={styles.backToHomePage}
|
||||||
onClick={handlePayForItemsClick}
|
onClick={handlePayForItemsClick}
|
||||||
>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "row",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
marginTop: 1,
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<ProTitle
|
<div
|
||||||
level={5}
|
|
||||||
style={{
|
style={{
|
||||||
fontSize: 14,
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginTop: 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("splitBill.payForYourItems")}
|
<ProTitle
|
||||||
</ProTitle>
|
level={5}
|
||||||
|
style={{
|
||||||
|
fontSize: 14,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{t("splitBill.payForYourItems")}
|
||||||
|
</ProTitle>
|
||||||
|
|
||||||
{isRTL ? (
|
{isRTL ? (
|
||||||
<BackIcon className={styles.serviceIcon} />
|
<BackIcon className={styles.serviceIcon} />
|
||||||
) : (
|
) : (
|
||||||
<NextIcon className={styles.serviceIcon} />
|
<NextIcon className={styles.serviceIcon} />
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</ProBottomSheet>
|
</ProBottomSheet>
|
||||||
|
|
||||||
<CustomAmountChoiceBottomSheet
|
<CustomAmountChoiceBottomSheet
|
||||||
isOpen={isCustomAmountOpen}
|
isOpen={isCustomAmountOpen}
|
||||||
onClose={() => setIsCustomAmountOpen(false)}
|
onClose={() => setIsCustomAmountOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<EqualltyChoiceBottomSheet
|
<EqualltyChoiceBottomSheet
|
||||||
isOpen={isEqualityOpen}
|
isOpen={isEqualityOpen}
|
||||||
onClose={() => setIsEqualityOpen(false)}
|
onClose={() => setIsEqualityOpen(false)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<PayForYourItemsChoiceBottomSheet
|
<PayForYourItemsChoiceBottomSheet
|
||||||
isOpen={isPayForItemsOpen}
|
isOpen={isPayForItemsOpen}
|
||||||
onClose={() => setIsPayForItemsOpen(false)}
|
onClose={() => setIsPayForItemsOpen(false)}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,21 +158,21 @@ export default function RestaurantServices() {
|
|||||||
},
|
},
|
||||||
]) ||
|
]) ||
|
||||||
[]),
|
[]),
|
||||||
...((true && [
|
// ...((true && [
|
||||||
{
|
// {
|
||||||
id: OrderType.Pay,
|
// id: OrderType.Pay,
|
||||||
title: t("common.pay"),
|
// title: t("common.pay"),
|
||||||
description: t("home.services.pay"),
|
// description: t("home.services.pay"),
|
||||||
icon: (
|
// icon: (
|
||||||
<ToOfficeIcon
|
// <ToOfficeIcon
|
||||||
className={styles.serviceIcon + " " + styles.officeIcon}
|
// className={styles.serviceIcon + " " + styles.officeIcon}
|
||||||
/>
|
// />
|
||||||
),
|
// ),
|
||||||
color: "bg-orange-50 text-orange-600",
|
// color: "bg-orange-50 text-orange-600",
|
||||||
href: `/${subdomain}/pay`,
|
// href: `/${subdomain}/pay`,
|
||||||
},
|
// },
|
||||||
]) ||
|
// ]) ||
|
||||||
[]),
|
// []),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Determine grid class based on number of services
|
// Determine grid class based on number of services
|
||||||
|
|||||||
Reference in New Issue
Block a user