From 265fb4b9839309fe3f04b97afb2ee77eedf05695 Mon Sep 17 00:00:00 2001 From: Mohammed Al-yaseen Date: Wed, 3 Dec 2025 01:53:28 +0300 Subject: [PATCH] add split bill choice bottom sheet --- src/assets/locals/ar.json | 12 ++ src/assets/locals/en.json | 12 ++ src/pages/checkout/components/BriefMenu.tsx | 2 +- src/pages/pay/components/PayButton.tsx | 66 ++++++++ .../components/splitBill/SplitBill.module.css | 48 ++++++ .../splitBill/SplitBillChoiceBottomSheet.tsx | 150 ++++++++++++++++++ .../splitBill/SplitBillChoiceDialog.tsx | 68 ++++++++ src/pages/pay/page.tsx | 4 +- 8 files changed, 359 insertions(+), 3 deletions(-) create mode 100644 src/pages/pay/components/PayButton.tsx create mode 100644 src/pages/pay/components/splitBill/SplitBill.module.css create mode 100644 src/pages/pay/components/splitBill/SplitBillChoiceBottomSheet.tsx create mode 100644 src/pages/pay/components/splitBill/SplitBillChoiceDialog.tsx diff --git a/src/assets/locals/ar.json b/src/assets/locals/ar.json index 321d435..53d06f7 100644 --- a/src/assets/locals/ar.json +++ b/src/assets/locals/ar.json @@ -401,5 +401,17 @@ "payDescription": "الدفع للطلب", "payButton": "الدفع", "payButtonDescription": "الدفع للطلب" + }, + "splitBill": { + "title": "تقسيم الفاتورة", + "description": "تقسيم الفاتورة", + "splitBill": "تقسيم الفاتورة", + "splitBillDescription": "تقسيم الفاتورة", + "splitBillButton": "تقسيم الفاتورة", + "splitBillButtonDescription": "تقسيم الفاتورة", + "payAsCustomAmount": "دفع كمبلغ مخصص", + "payAsSplitAmount": "دفع كمبلغ مقسم", + "divideTheBillEqually": "تقسيم الفاتورة الى حسب العدد", + "payForYourItems": "دفع للطلبات الخاصة بي" } } diff --git a/src/assets/locals/en.json b/src/assets/locals/en.json index 7198bf8..10dd2bb 100644 --- a/src/assets/locals/en.json +++ b/src/assets/locals/en.json @@ -413,5 +413,17 @@ "payDescription": "Pay for your order", "payButton": "Pay", "payButtonDescription": "Pay for your order" + }, + "splitBill": { + "title": "Split Bill", + "description": "Split Bill", + "splitBill": "Split Bill", + "splitBillDescription": "Split Bill", + "splitBillButton": "Split Bill", + "splitBillButtonDescription": "Split Bill", + "payAsCustomAmount": "Pay as Custom Amount", + "payAsSplitAmount": "Pay as Split Amount", + "divideTheBillEqually": "Divide the Bill Equally", + "payForYourItems": "Pay for Your Items" } } diff --git a/src/pages/checkout/components/BriefMenu.tsx b/src/pages/checkout/components/BriefMenu.tsx index 399019a..b5adfa5 100644 --- a/src/pages/checkout/components/BriefMenu.tsx +++ b/src/pages/checkout/components/BriefMenu.tsx @@ -42,7 +42,7 @@ export default function BriefMenu() { const cardTitle = useMemo( () => - orderType === OrderType.DineIn + orderType === OrderType.DineIn || orderType === OrderType.Pay ? t("checkout.table") + " " + tables : t("checkout.items"), [orderType, t, tables], diff --git a/src/pages/pay/components/PayButton.tsx b/src/pages/pay/components/PayButton.tsx new file mode 100644 index 0000000..73385e5 --- /dev/null +++ b/src/pages/pay/components/PayButton.tsx @@ -0,0 +1,66 @@ +import { Button, FormInstance, Layout } from "antd"; +import { selectCart } from "features/order/orderSlice"; +import { OrderType } from "pages/checkout/hooks/types.ts"; +import useOrder from "pages/checkout/hooks/useOrder"; +import { useCallback, useMemo, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { useAppSelector } from "redux/hooks"; +import styles from "../../address/address.module.css"; +import { SplitBillChoiceBottomSheet } from "./splitBill/SplitBillChoiceBottomSheet"; + +export default function PayButton({ form }: { form: FormInstance }) { + const { t } = useTranslation(); + const { orderType } = useAppSelector(selectCart); + const { handleCreateOrder } = useOrder(); + const [ + isSplitBillChoiceBottomSheetOpen, + setIsSplitBillChoiceBottomSheetOpen, + ] = useState(false); + + const handleSplitBillClick = useCallback(() => { + setIsSplitBillChoiceBottomSheetOpen(true); + }, []); + + const handlePlaceOrderClick = useCallback(async () => { + try { + await form.validateFields(); + handleCreateOrder(); + } catch (error) { + console.log(error); + } + }, [handleCreateOrder, form]); + + const shouldShowSplitBill = useMemo( + () => orderType === OrderType.DineIn || orderType === OrderType.Pay, + [orderType], + ); + + return ( + <> + + {shouldShowSplitBill && ( + + )} + + + + + setIsSplitBillChoiceBottomSheetOpen(false)} + /> + + ); +} diff --git a/src/pages/pay/components/splitBill/SplitBill.module.css b/src/pages/pay/components/splitBill/SplitBill.module.css new file mode 100644 index 0000000..e26b37e --- /dev/null +++ b/src/pages/pay/components/splitBill/SplitBill.module.css @@ -0,0 +1,48 @@ +.inputField { + height: 50px; +} + +.editButton { + color: var(--primary); + font-size: 14px; + cursor: pointer; +} + +.textArea { + border-radius: 24px; + margin: 40px 0; +} + +.actionButton { + border-radius: 24px; + width: 100% !important; + height: 48px !important; +} + + +.backToHomePage { + 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; +} + +.backToHomePage :global(.ant-card-body) { + padding: 0px !important; + text-align: start; + width: 100%; +} + +.nextIcon { + width: 24px; + height: 24px; +} + +.backIcon { + width: 24px; + height: 24px; +} diff --git a/src/pages/pay/components/splitBill/SplitBillChoiceBottomSheet.tsx b/src/pages/pay/components/splitBill/SplitBillChoiceBottomSheet.tsx new file mode 100644 index 0000000..347652c --- /dev/null +++ b/src/pages/pay/components/splitBill/SplitBillChoiceBottomSheet.tsx @@ -0,0 +1,150 @@ +import { Card } from "antd"; +import { ProBottomSheet } from "components/ProBottomSheet/ProBottomSheet.tsx"; +import { useTranslation } from "react-i18next"; + +import BackIcon from "components/Icons/BackIcon"; +import NextIcon from "components/Icons/NextIcon"; +import ProTitle from "components/ProTitle"; +import { useNavigate, useParams } from "react-router-dom"; +import { useGetRestaurantDetailsQuery } from "redux/api/others"; +import { useAppSelector } from "redux/hooks"; +import styles from "./SplitBill.module.css"; + +interface SplitBillChoiceBottomSheetProps { + isOpen: boolean; + onClose: () => void; + onSave?: (value: string) => void; +} + +export function SplitBillChoiceBottomSheet({ + isOpen, + onClose, + // onSave, +}: SplitBillChoiceBottomSheetProps) { + const { t } = useTranslation(); + // const [value, setValue] = useState(initialValue); + const { isRTL } = useAppSelector((state) => state.locale); + const { subdomain } = useParams(); + const navigate = useNavigate(); + const { data: restaurant } = useGetRestaurantDetailsQuery(subdomain, { + skip: !subdomain, + }); + + // const handleSave = () => { + // onSave(value); + // onClose(); + // }; + + const handleCancel = () => { + // setValue(initialValue); + onClose(); + }; + + return ( + +
+ navigate(`/${restaurant?.subdomain}`)} + > +
+ + {t("splitBill.payAsCustomAmount")} + + + {isRTL ? ( + + ) : ( + + )} +
+
+ + navigate(`/${restaurant?.subdomain}`)} + > +
+ + {t("splitBill.divideTheBillEqually")} + + + {isRTL ? ( + + ) : ( + + )} +
+
+ + navigate(`/${restaurant?.subdomain}`)} + > +
+ + {t("splitBill.payForYourItems")} + + + {isRTL ? ( + + ) : ( + + )} +
+
+
+
+ ); +} diff --git a/src/pages/pay/components/splitBill/SplitBillChoiceDialog.tsx b/src/pages/pay/components/splitBill/SplitBillChoiceDialog.tsx new file mode 100644 index 0000000..873a15e --- /dev/null +++ b/src/pages/pay/components/splitBill/SplitBillChoiceDialog.tsx @@ -0,0 +1,68 @@ +import { Button, Input, Modal } from "antd"; +import { useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import styles from "./SplitBill.module.css"; + +const { TextArea } = Input; + +interface SplitBillChoiceDialogProps { + isOpen: boolean; + onClose: () => void; + initialValue: string; + onSave: (value: string) => void; +} + +export function SplitBillChoiceDialog({ + isOpen, + onClose, + initialValue, + onSave, +}: SplitBillChoiceDialogProps) { + const { t } = useTranslation(); + const [value, setValue] = useState(initialValue); + + useEffect(() => { + setValue(initialValue); + }, [initialValue]); + + const handleSave = () => { + onSave(value); + onClose(); + }; + + const handleCancel = () => { + setValue(initialValue); + onClose(); + }; + + return ( + + {t("cart.save")} + , + ]} + width={500} + destroyOnHidden + > +
+