pay flow: initial commit
This commit is contained in:
@@ -46,6 +46,7 @@
|
|||||||
"dineIn": "تناول",
|
"dineIn": "تناول",
|
||||||
"pickup": "استلام",
|
"pickup": "استلام",
|
||||||
"car": "سيارة",
|
"car": "سيارة",
|
||||||
|
"pay": "الدفع",
|
||||||
"sendGift": "إرسال هدية",
|
"sendGift": "إرسال هدية",
|
||||||
"roomService": "خدمة الغرف",
|
"roomService": "خدمة الغرف",
|
||||||
"officeDelivery": "توصيل للمكتب",
|
"officeDelivery": "توصيل للمكتب",
|
||||||
@@ -392,5 +393,13 @@
|
|||||||
"validation": {
|
"validation": {
|
||||||
"phoneRequired": "رقم الهاتف مطلوب",
|
"phoneRequired": "رقم الهاتف مطلوب",
|
||||||
"invalidPhone": "رقم الهاتف غير صالح"
|
"invalidPhone": "رقم الهاتف غير صالح"
|
||||||
|
},
|
||||||
|
"pay": {
|
||||||
|
"title": "الدفع",
|
||||||
|
"description": "الدفع للطلب",
|
||||||
|
"pay": "الدفع",
|
||||||
|
"payDescription": "الدفع للطلب",
|
||||||
|
"payButton": "الدفع",
|
||||||
|
"payButtonDescription": "الدفع للطلب"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
"dineIn": "Dine-in",
|
"dineIn": "Dine-in",
|
||||||
"pickup": "Pickup",
|
"pickup": "Pickup",
|
||||||
"car": "Car",
|
"car": "Car",
|
||||||
|
"pay": "Pay",
|
||||||
"sendGift": "Send a Gift",
|
"sendGift": "Send a Gift",
|
||||||
"roomService": "Room Service",
|
"roomService": "Room Service",
|
||||||
"officeDelivery": "Office Delivery",
|
"officeDelivery": "Office Delivery",
|
||||||
@@ -404,5 +405,13 @@
|
|||||||
"validation": {
|
"validation": {
|
||||||
"phoneRequired": "Phone number is required",
|
"phoneRequired": "Phone number is required",
|
||||||
"invalidPhone": "Invalid phone number"
|
"invalidPhone": "Invalid phone number"
|
||||||
|
},
|
||||||
|
"pay": {
|
||||||
|
"title": "Pay",
|
||||||
|
"description": "Pay for your order",
|
||||||
|
"pay": "Pay",
|
||||||
|
"payDescription": "Pay for your order",
|
||||||
|
"payButton": "Pay",
|
||||||
|
"payButtonDescription": "Pay for your order"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,16 +3,19 @@ import ArabicPrice from "components/ArabicPrice";
|
|||||||
import ProInputCard from "components/ProInputCard/ProInputCard";
|
import ProInputCard from "components/ProInputCard/ProInputCard";
|
||||||
import ProText from "components/ProText";
|
import ProText from "components/ProText";
|
||||||
import { selectCart } from "features/order/orderSlice";
|
import { selectCart } from "features/order/orderSlice";
|
||||||
|
import { OrderType } from "pages/checkout/hooks/types.ts";
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { Link, useParams } from "react-router-dom";
|
||||||
import { useAppSelector } from "redux/hooks";
|
import { useAppSelector } from "redux/hooks";
|
||||||
|
import { colors } from "ThemeConstants";
|
||||||
import styles from "../../address/address.module.css";
|
import styles from "../../address/address.module.css";
|
||||||
import { OrderType } from "pages/checkout/hooks/types.ts";
|
|
||||||
|
|
||||||
export default function BriefMenu() {
|
export default function BriefMenu() {
|
||||||
const { tables, items } = useAppSelector(selectCart);
|
const { tables, items } = useAppSelector(selectCart);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { orderType } = useAppSelector(selectCart);
|
const { orderType } = useAppSelector(selectCart);
|
||||||
|
const { subdomain } = useParams();
|
||||||
|
|
||||||
const menuItems = useMemo(
|
const menuItems = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@@ -46,7 +49,18 @@ export default function BriefMenu() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ProInputCard title={cardTitle}>
|
<ProInputCard
|
||||||
|
title={cardTitle}
|
||||||
|
titleRight={
|
||||||
|
orderType === OrderType.Pay ? (
|
||||||
|
<Link to={`/${subdomain}/menu?orderType=${OrderType.Pay}`} style={{ textDecoration: "none" }}>
|
||||||
|
<ProText style={{ color: colors.primary }}>
|
||||||
|
{t("menu.title")}
|
||||||
|
</ProText>
|
||||||
|
</Link>
|
||||||
|
) : undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
<div className={styles.briefMenuContainer}>{menuItems}</div>
|
<div className={styles.briefMenuContainer}>{menuItems}</div>
|
||||||
</ProInputCard>
|
</ProInputCard>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -246,4 +246,5 @@ export enum OrderType {
|
|||||||
ToRoom = "room",
|
ToRoom = "room",
|
||||||
ToOffice = "office",
|
ToOffice = "office",
|
||||||
Booking = "booking",
|
Booking = "booking",
|
||||||
|
Pay = "pay"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Form, Layout } from "antd";
|
import { Form, Layout } from "antd";
|
||||||
|
import InputCard from "components/InputCard";
|
||||||
import OrderSummary from "components/OrderSummary/OrderSummary";
|
import OrderSummary from "components/OrderSummary/OrderSummary";
|
||||||
import PaymentMethods from "components/PaymentMethods/PaymentMethods";
|
import PaymentMethods from "components/PaymentMethods/PaymentMethods";
|
||||||
import ProHeader from "components/ProHeader/ProHeader";
|
import ProHeader from "components/ProHeader/ProHeader";
|
||||||
@@ -9,11 +10,9 @@ import styles from "../address/address.module.css";
|
|||||||
import { AddressSummary } from "./components/AddressSummary";
|
import { AddressSummary } from "./components/AddressSummary";
|
||||||
import BriefMenu from "./components/BriefMenu";
|
import BriefMenu from "./components/BriefMenu";
|
||||||
import CheckoutButton from "./components/CheckoutButton";
|
import CheckoutButton from "./components/CheckoutButton";
|
||||||
import { GiftDetails } from "./components/GiftDetails";
|
|
||||||
import PhoneCard from "./components/phoneCard";
|
|
||||||
import InputCard from "components/InputCard";
|
|
||||||
import { OrderType } from "./hooks/types";
|
|
||||||
import { GiftCard } from "./components/GiftCard";
|
import { GiftCard } from "./components/GiftCard";
|
||||||
|
import PhoneCard from "./components/phoneCard";
|
||||||
|
import { OrderType } from "./hooks/types";
|
||||||
|
|
||||||
export default function CheckoutPage() {
|
export default function CheckoutPage() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Badge, Button } from "antd";
|
import { Badge, Button } from "antd";
|
||||||
import CartIcon from "components/Icons/cart/CartIcon";
|
import CartIcon from "components/Icons/cart/CartIcon";
|
||||||
import { selectCartItems } from "features/order/orderSlice";
|
import { selectCartItems } from "features/order/orderSlice";
|
||||||
|
import { OrderType } from "pages/checkout/hooks/types";
|
||||||
import { useCallback } from "react";
|
import { useCallback } from "react";
|
||||||
import { useNavigate, useParams } from "react-router-dom";
|
import { useNavigate, useParams } from "react-router-dom";
|
||||||
import { useAppSelector } from "redux/hooks";
|
import { useAppSelector } from "redux/hooks";
|
||||||
@@ -11,10 +12,17 @@ export function CartButton() {
|
|||||||
const { subdomain } = useParams();
|
const { subdomain } = useParams();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const items = useAppSelector(selectCartItems);
|
const items = useAppSelector(selectCartItems);
|
||||||
|
const { orderType } = useAppSelector((s) => s.order);
|
||||||
|
|
||||||
const onCartClick = useCallback(() => {
|
const onCartClick = useCallback(() => {
|
||||||
navigate(`/${subdomain}/cart`);
|
console.log(orderType);
|
||||||
}, [navigate, subdomain]);
|
|
||||||
|
navigate(
|
||||||
|
orderType === OrderType.Pay
|
||||||
|
? `/${subdomain}/pay`
|
||||||
|
: `/${subdomain}/menu?orderType=${orderType}`,
|
||||||
|
);
|
||||||
|
}, [navigate, subdomain, orderType]);
|
||||||
|
|
||||||
const totalItems = items.reduce((sum, item) => sum + item.quantity, 0);
|
const totalItems = items.reduce((sum, item) => sum + item.quantity, 0);
|
||||||
|
|
||||||
@@ -26,7 +34,7 @@ export function CartButton() {
|
|||||||
right: !isRTL ? "auto" : "20px",
|
right: !isRTL ? "auto" : "20px",
|
||||||
left: !isRTL ? "20px" : "auto",
|
left: !isRTL ? "20px" : "auto",
|
||||||
}}
|
}}
|
||||||
className={'cart-button'}
|
className={"cart-button"}
|
||||||
>
|
>
|
||||||
<Badge count={totalItems} size="default" className={styles.badge}>
|
<Badge count={totalItems} size="default" className={styles.badge}>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import CartIcon from "components/Icons/cart/CartIcon";
|
|||||||
import ProText from "components/ProText";
|
import ProText from "components/ProText";
|
||||||
import { selectCartItems } from "features/order/orderSlice";
|
import { selectCartItems } from "features/order/orderSlice";
|
||||||
import useBreakPoint from "hooks/useBreakPoint";
|
import useBreakPoint from "hooks/useBreakPoint";
|
||||||
|
import { OrderType } from "pages/checkout/hooks/types";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Link, useParams } from "react-router-dom";
|
import { Link, useParams } from "react-router-dom";
|
||||||
import { useAppSelector } from "redux/hooks";
|
import { useAppSelector } from "redux/hooks";
|
||||||
@@ -14,9 +15,11 @@ export function MenuFooter() {
|
|||||||
const { isMobile, isTablet } = useBreakPoint();
|
const { isMobile, isTablet } = useBreakPoint();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { subdomain } = useParams();
|
const { subdomain } = useParams();
|
||||||
|
const { orderType } = useAppSelector((s) => s.order);
|
||||||
const totalItems = items.length;
|
const totalItems = items.length;
|
||||||
|
|
||||||
|
console.log(orderType);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{(isMobile || isTablet) && (
|
{(isMobile || isTablet) && (
|
||||||
@@ -37,7 +40,11 @@ export function MenuFooter() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Link
|
<Link
|
||||||
to={`/${subdomain}/cart`}
|
to={
|
||||||
|
orderType === OrderType.Pay
|
||||||
|
? `/${subdomain}/pay`
|
||||||
|
: `/${subdomain}/cart`
|
||||||
|
}
|
||||||
style={{
|
style={{
|
||||||
width: "100%",
|
width: "100%",
|
||||||
padding: "0 16px",
|
padding: "0 16px",
|
||||||
|
|||||||
66
src/pages/pay/page.tsx
Normal file
66
src/pages/pay/page.tsx
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { Form, Layout } from "antd";
|
||||||
|
import InputCard from "components/InputCard";
|
||||||
|
import OrderSummary from "components/OrderSummary/OrderSummary";
|
||||||
|
import PaymentMethods from "components/PaymentMethods/PaymentMethods";
|
||||||
|
import ProHeader from "components/ProHeader/ProHeader";
|
||||||
|
import { selectCart } from "features/order/orderSlice";
|
||||||
|
import { AddressSummary } from "pages/checkout/components/AddressSummary";
|
||||||
|
import BriefMenu from "pages/checkout/components/BriefMenu";
|
||||||
|
import CheckoutButton from "pages/checkout/components/CheckoutButton";
|
||||||
|
import { GiftCard } from "pages/checkout/components/GiftCard";
|
||||||
|
import PhoneCard from "pages/checkout/components/phoneCard";
|
||||||
|
import { OrderType } from "pages/checkout/hooks/types";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { useAppSelector } from "redux/hooks";
|
||||||
|
import styles from "../address/address.module.css";
|
||||||
|
|
||||||
|
|
||||||
|
export default function PayPage() {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const [form] = Form.useForm();
|
||||||
|
const { phone, order, orderType } = useAppSelector(selectCart);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Form
|
||||||
|
form={form}
|
||||||
|
initialValues={{
|
||||||
|
phone,
|
||||||
|
}}
|
||||||
|
layout="vertical"
|
||||||
|
>
|
||||||
|
<Layout>
|
||||||
|
<ProHeader>{t("pay.title")}</ProHeader>
|
||||||
|
<Layout.Content className={styles.checkoutContainer}>
|
||||||
|
<AddressSummary />
|
||||||
|
{orderType === OrderType.ToRoom && (
|
||||||
|
<InputCard
|
||||||
|
title={t("address.roomNo")}
|
||||||
|
name="roomNumber"
|
||||||
|
placeholder={t("address.roomNo")}
|
||||||
|
value={order?.roomNumber}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{orderType === OrderType.ToOffice && (
|
||||||
|
<InputCard
|
||||||
|
title={t("address.officeNo")}
|
||||||
|
name="officeNumber"
|
||||||
|
placeholder={t("address.officeNo")}
|
||||||
|
value={order?.officeNumber}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{orderType === OrderType.Gift && <GiftCard />}
|
||||||
|
{/* <RoomDetails />
|
||||||
|
<OfficeDetails /> */}
|
||||||
|
{/* <GiftDetails /> */}
|
||||||
|
<BriefMenu />
|
||||||
|
<OrderSummary />
|
||||||
|
<PhoneCard />
|
||||||
|
<PaymentMethods />
|
||||||
|
</Layout.Content>
|
||||||
|
|
||||||
|
<CheckoutButton form={form} />
|
||||||
|
</Layout>
|
||||||
|
</Form>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
0
src/pages/pay/pay.module.css
Normal file
0
src/pages/pay/pay.module.css
Normal file
@@ -1,7 +1,6 @@
|
|||||||
import { ScheduleFilled } from "@ant-design/icons";
|
import { ScheduleFilled } from "@ant-design/icons";
|
||||||
import { Card } from "antd";
|
import { Card } from "antd";
|
||||||
import BackIcon from "components/Icons/BackIcon";
|
import BackIcon from "components/Icons/BackIcon";
|
||||||
import BookingIcon from "components/Icons/BookingIcon";
|
|
||||||
import DeliveryIcon from "components/Icons/DeliveryIcon";
|
import DeliveryIcon from "components/Icons/DeliveryIcon";
|
||||||
import DineInIcon from "components/Icons/DineInIcon";
|
import DineInIcon from "components/Icons/DineInIcon";
|
||||||
import NextIcon from "components/Icons/NextIcon";
|
import NextIcon from "components/Icons/NextIcon";
|
||||||
@@ -33,7 +32,7 @@ export default function RestaurantServices() {
|
|||||||
gift,
|
gift,
|
||||||
toRoom,
|
toRoom,
|
||||||
toOffice,
|
toOffice,
|
||||||
is_booking_enabled,
|
// is_booking_enabled,
|
||||||
delivery,
|
delivery,
|
||||||
is_schedule_order_enabled,
|
is_schedule_order_enabled,
|
||||||
pickup_type,
|
pickup_type,
|
||||||
@@ -113,6 +112,7 @@ export default function RestaurantServices() {
|
|||||||
},
|
},
|
||||||
]) ||
|
]) ||
|
||||||
[]),
|
[]),
|
||||||
|
|
||||||
// ...((is_booking_enabled && [
|
// ...((is_booking_enabled && [
|
||||||
// {
|
// {
|
||||||
// id: OrderType.Booking,
|
// id: OrderType.Booking,
|
||||||
@@ -158,6 +158,21 @@ export default function RestaurantServices() {
|
|||||||
},
|
},
|
||||||
]) ||
|
]) ||
|
||||||
[]),
|
[]),
|
||||||
|
...((true && [
|
||||||
|
{
|
||||||
|
id: OrderType.Pay,
|
||||||
|
title: t("common.pay"),
|
||||||
|
description: t("home.services.pay"),
|
||||||
|
icon: (
|
||||||
|
<ToOfficeIcon
|
||||||
|
className={styles.serviceIcon + " " + styles.officeIcon}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
color: "bg-orange-50 text-orange-600",
|
||||||
|
href: `/${subdomain}/pay`,
|
||||||
|
},
|
||||||
|
]) ||
|
||||||
|
[]),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Determine grid class based on number of services
|
// Determine grid class based on number of services
|
||||||
|
|||||||
@@ -31,9 +31,7 @@ export const branchApi = baseApi.injectEndpoints({
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
transformResponse: (response: any) => {
|
transformResponse: (response: any) => {
|
||||||
return response?.result?.restaurants?.find(
|
return response?.result?.restaurants?.[0]
|
||||||
(restaurant: RestaurantDetails) => restaurant.distance === 595,
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
providesTags: ["Restaurant"],
|
providesTags: ["Restaurant"],
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import MenuPage from "pages/menu/page";
|
|||||||
import OrderPage from "pages/order/page";
|
import OrderPage from "pages/order/page";
|
||||||
import OrdersPage from "pages/orders/page";
|
import OrdersPage from "pages/orders/page";
|
||||||
import OtpPage from "pages/otp/page";
|
import OtpPage from "pages/otp/page";
|
||||||
|
import PayPage from "pages/pay/page";
|
||||||
import ProductDetailPage from "pages/product/page";
|
import ProductDetailPage from "pages/product/page";
|
||||||
import RestaurantPage from "pages/restaurant/page";
|
import RestaurantPage from "pages/restaurant/page";
|
||||||
import SearchPage from "pages/search/page";
|
import SearchPage from "pages/search/page";
|
||||||
@@ -136,12 +137,16 @@ export const router = createHashRouter([
|
|||||||
element: <PageWrapper children={<OtpPage />} />,
|
element: <PageWrapper children={<OtpPage />} />,
|
||||||
errorElement: <ErrorPage />,
|
errorElement: <ErrorPage />,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
path: "order/:orderId",
|
path: "order/:orderId",
|
||||||
element: <PageWrapper children={<OrderPage />} />,
|
element: <PageWrapper children={<OrderPage />} />,
|
||||||
errorElement: <ErrorPage />,
|
errorElement: <ErrorPage />,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "pay",
|
||||||
|
element: <PageWrapper children={<PayPage />} />,
|
||||||
|
errorElement: <ErrorPage />,
|
||||||
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user