remove extra bottom sheet in checkout page make all them inside the page iteslef

This commit is contained in:
2025-12-02 01:51:14 +03:00
parent cf5babeaa5
commit 2af2c34826
8 changed files with 266 additions and 43 deletions

View File

@@ -0,0 +1,43 @@
import { Form, Input } from "antd";
import ProInputCard from "components/ProInputCard/ProInputCard.tsx";
import { updateOrder } from "features/order/orderSlice";
import { useAppDispatch } from "redux/hooks";
interface InputCardProps {
title: string;
name: string;
placeholder: string;
value: string;
}
export default function InputCard({
title,
name,
placeholder,
value,
}: InputCardProps) {
const dispatch = useAppDispatch();
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
dispatch(updateOrder({ [name]: e.target.value }));
};
return (
<>
<ProInputCard title={title} dividerStyle={{ margin: "5px 0 0 0" }}>
<Form.Item
label={title}
name={name}
style={{ position: "relative", top: -5 }}
>
<Input
placeholder={placeholder}
size="large"
autoFocus={false}
style={{ padding: "7px 11px", height: 50, borderRadius: 888 }}
value={value}
onChange={handleChange}
/>
</Form.Item>
</ProInputCard>
</>
);
}

View File

@@ -1,6 +1,5 @@
import { Form } from "antd"; import { Form } from "antd";
import useFormInstance from "antd/es/form/hooks/useFormInstance"; import useFormInstance from "antd/es/form/hooks/useFormInstance";
import { TitleProps } from "antd/es/typography/Title";
import { PhoneNumberUtil } from "google-libphonenumber"; import { PhoneNumberUtil } from "google-libphonenumber";
import { FunctionComponent, useMemo } from "react"; import { FunctionComponent, useMemo } from "react";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
@@ -8,16 +7,20 @@ import PhoneInput from "react-phone-input-2";
import { useAppSelector } from "redux/hooks"; import { useAppSelector } from "redux/hooks";
import { ProBlack1 } from "ThemeConstants"; import { ProBlack1 } from "ThemeConstants";
interface ProPhoneInput extends TitleProps { interface ProPhoneInput {
propName?: string; propName?: string;
label?: string; label?: string;
getValueCallback?: (value: string) => void; getValueCallback?: (value: string) => void;
value?: string;
onChange?: (value: string) => void;
} }
const ProPhoneInput: FunctionComponent<ProPhoneInput> = ({ const ProPhoneInput: FunctionComponent<ProPhoneInput> = ({
propName, propName,
label, label,
getValueCallback, getValueCallback,
value,
onChange,
}) => { }) => {
const form = useFormInstance(); const form = useFormInstance();
const { t } = useTranslation(); const { t } = useTranslation();
@@ -51,8 +54,9 @@ const ProPhoneInput: FunctionComponent<ProPhoneInput> = ({
onChange={(value) => { onChange={(value) => {
form.setFieldValue(propName, value); form.setFieldValue(propName, value);
getValueCallback?.(value); getValueCallback?.(value);
onChange?.(value);
}} }}
phone={form.getFieldValue(propName)} phone={value || form.getFieldValue(propName)}
themeName={themeName} themeName={themeName}
placeholder={t("login.mobileNumber")} placeholder={t("login.mobileNumber")}
propName={propName} propName={propName}

View File

@@ -68,6 +68,7 @@ interface CartState {
pickupDate: string; pickupDate: string;
pickupTime: string; pickupTime: string;
pickupType: string; pickupType: string;
order: any;
} }
// localStorage keys // localStorage keys
@@ -97,6 +98,7 @@ export const CART_STORAGE_KEYS = {
PICKUP_DATE: "fascano_pickup_date", PICKUP_DATE: "fascano_pickup_date",
PICKUP_TIME: "fascano_pickup_time", PICKUP_TIME: "fascano_pickup_time",
PICKUP_TYPE: "fascano_pickup_type", PICKUP_TYPE: "fascano_pickup_type",
ORDER: "fascano_order",
} as const; } as const;
// Utility functions for localStorage // Utility functions for localStorage
@@ -182,6 +184,7 @@ const initialState: CartState = {
pickupDate: getFromLocalStorage(CART_STORAGE_KEYS.PICKUP_DATE, ""), pickupDate: getFromLocalStorage(CART_STORAGE_KEYS.PICKUP_DATE, ""),
pickupTime: getFromLocalStorage(CART_STORAGE_KEYS.PICKUP_TIME, ""), pickupTime: getFromLocalStorage(CART_STORAGE_KEYS.PICKUP_TIME, ""),
pickupType: getFromLocalStorage(CART_STORAGE_KEYS.PICKUP_TYPE, ""), pickupType: getFromLocalStorage(CART_STORAGE_KEYS.PICKUP_TYPE, ""),
order: getFromLocalStorage(CART_STORAGE_KEYS.ORDER, null),
}; };
const orderSlice = createSlice({ const orderSlice = createSlice({
@@ -623,6 +626,12 @@ const orderSlice = createSlice({
); );
} }
}, },
updateOrder(state, action: PayloadAction<any>) {
state.order = action.payload;
if (typeof window !== "undefined") {
localStorage.setItem(CART_STORAGE_KEYS.ORDER, JSON.stringify(state.order));
}
},
}, },
}); });
@@ -659,6 +668,7 @@ export const {
updatePickupDate, updatePickupDate,
updatePickupTime, updatePickupTime,
updatePickUpType, updatePickUpType,
updateOrder,
} = orderSlice.actions; } = orderSlice.actions;
// Tax calculation helper functions // Tax calculation helper functions

View File

@@ -0,0 +1,37 @@
import { Form, Input } from "antd";
import ProInputCard from "components/ProInputCard/ProInputCard.tsx";
import { updatePlateCar } from "features/order/orderSlice";
import { useTranslation } from "react-i18next";
import { useAppDispatch, useAppSelector } from "redux/hooks";
export default function CarPlateCard() {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const plateCar = useAppSelector((state) => state.order.plateCar);
return (
<>
<ProInputCard
title={t("cart.plateNumber")}
dividerStyle={{ margin: "5px 0 0 0" }}
>
<Form.Item
label={t("cart.plateNumber")}
name="plateNumber"
style={{ position: "relative", top: -5 }}
>
<Input
placeholder={t("cart.plateNumber")}
size="large"
autoFocus={false}
style={{ padding: "7px 11px", height: 50, borderRadius: 888 }}
value={plateCar}
onChange={(e) => {
dispatch(updatePlateCar(e.target.value));
}}
/>
</Form.Item>
</ProInputCard>
</>
);
}

View File

@@ -0,0 +1,114 @@
import { Checkbox, Form, Input } from "antd";
import ProInputCard from "components/ProInputCard/ProInputCard";
import ProPhoneInput from "components/ProPhoneInput";
import ProText from "components/ProText";
import { selectCart, updateOrder } from "features/order/orderSlice";
import { useTranslation } from "react-i18next";
import { useAppDispatch, useAppSelector } from "redux/hooks";
const { TextArea } = Input;
export function GiftCard() {
const { t } = useTranslation();
const { order } = useAppSelector(selectCart);
const dispatch = useAppDispatch();
return (
<>
<ProInputCard title={t("address.giftDetails")}>
<ProPhoneInput
propName="receiverPhone"
label={t("address.receiverPhone")}
value={order?.receiverPhone}
onChange={(e) => {
dispatch(updateOrder({ ...order, receiverPhone: e }));
}}
/>
<Form.Item name="message" label={t("address.message")}>
<TextArea
placeholder={t("address.message")}
size="large"
style={{
fontSize: 14,
borderRadius: 10,
}}
rows={2}
autoFocus={false}
value={order?.senderName}
onChange={(e) => {
dispatch(updateOrder({ ...order, senderName: e.target.value }));
}}
/>
</Form.Item>
<Form.Item
name="senderName"
label={t("address.senderName")}
rules={[{ required: true, message: "" }]}
colon={false}
>
<Input
placeholder={t("address.senderName")}
size="large"
style={{
fontSize: 14,
height: 50,
}}
autoFocus={false}
value={order?.senderPhone}
onChange={(e) => {
dispatch(updateOrder({ ...order, senderPhone: e.target.value }));
}}
/>
</Form.Item>
<ProPhoneInput
propName="senderPhone"
label={t("address.receiverPhone")}
/>
<Form.Item
name="senderEmail"
label={t("address.senderEmail")}
rules={[{ required: true, message: "" }]}
colon={false}
>
<Input
placeholder={t("address.senderEmail")}
size="large"
style={{
fontSize: 14,
height: 50,
}}
autoFocus={false}
value={order?.senderEmail}
onChange={(e) => {
dispatch(updateOrder({ ...order, senderEmail: e.target.value }));
}}
/>
</Form.Item>
<Form.Item
name="isSecret"
rules={[{ required: true, message: "" }]}
colon={false}
>
<Checkbox
style={{
fontSize: 14,
}}
autoFocus={false}
checked={order?.isSecret}
onChange={(e) => {
dispatch(updateOrder({ ...order, isSecret: e.target.checked }));
}}
>
<ProText>{t("address.keepMyNameSecret")}</ProText>
</Checkbox>
</Form.Item>
</ProInputCard>
</>
);
}

View File

@@ -13,6 +13,7 @@ import { useCreateOrderMutation } from "redux/api/others";
import { useAppDispatch, useAppSelector } from "redux/hooks"; import { useAppDispatch, useAppSelector } from "redux/hooks";
import { PAYMENT_CONFIRMATION_URL } from "utils/constants"; import { PAYMENT_CONFIRMATION_URL } from "utils/constants";
import { Customer } from "../../otp/types"; import { Customer } from "../../otp/types";
import { Variant } from "utils/types/appTypes";
export default function useOrder() { export default function useOrder() {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
@@ -31,15 +32,14 @@ export default function useOrder() {
specialRequest, specialRequest,
phone, phone,
estimateTime, estimateTime,
officeDetails,
orderType, orderType,
giftDetails,
location, location,
discount, discount,
plateCar, plateCar,
pickupTime, pickupTime,
pickupDate, pickupDate,
pickupType, pickupType,
order,
} = useAppSelector(selectCart); } = useAppSelector(selectCart);
const highestLoyaltyItem = useAppSelector(selectHighestPricedLoyaltyItem); const highestLoyaltyItem = useAppSelector(selectHighestPricedLoyaltyItem);
const { useLoyaltyPoints } = useAppSelector(selectCart); const { useLoyaltyPoints } = useAppSelector(selectCart);
@@ -70,7 +70,7 @@ export default function useOrder() {
}); });
createOrder({ createOrder({
phone: mobilenumber || phone || giftDetails?.senderPhone, phone: mobilenumber || phone || order?.senderPhone,
comment: specialRequest, comment: specialRequest,
delivery_method: getDeliveryMethod(), delivery_method: getDeliveryMethod(),
timeslot: "", timeslot: "",
@@ -85,9 +85,10 @@ export default function useOrder() {
extras: i.extras?.map((e) => e.id) || [], extras: i.extras?.map((e) => e.id) || [],
extrasgroup: i.extrasgroup || [], extrasgroup: i.extrasgroup || [],
order_item_comment: i.comment || "", order_item_comment: i.comment || "",
variant: i.variant?.id || "", variant: (i.variant as Variant)?.id || "",
})), })),
office_no: officeDetails?.officeNo || "", office_no: order?.officeNumber || "",
room_no: order?.roomNumber || "",
vatvalue: 0, vatvalue: 0,
...(discount.isDiscount ? { couponID: coupon } : {}), ...(discount.isDiscount ? { couponID: coupon } : {}),
...(discount.isGift ? { discountGiftCode: coupon } : {}), ...(discount.isGift ? { discountGiftCode: coupon } : {}),
@@ -111,13 +112,13 @@ export default function useOrder() {
delivery_address: location?.address, delivery_address: location?.address,
...(orderType === OrderType.Gift ...(orderType === OrderType.Gift
? { ? {
receiverName: giftDetails?.receiverName, receiverName: order?.receiverName,
receiverPhone: giftDetails?.receiverPhone, receiverPhone: order?.receiverPhone,
specialMessage: giftDetails?.message, specialMessage: order?.message,
keepNameSecret: giftDetails?.isSecret, keepNameSecret: order?.isSecret,
senderEmail: giftDetails?.senderEmail, senderEmail: order?.senderEmail,
senderPhone: giftDetails?.senderPhone, senderPhone: order?.senderPhone,
senderName: giftDetails?.senderName, senderName: order?.senderName,
dineType: orderType, dineType: orderType,
} }
: {}), : {}),
@@ -166,20 +167,13 @@ export default function useOrder() {
createOrder, createOrder,
mobilenumber, mobilenumber,
phone, phone,
giftDetails?.senderPhone,
giftDetails?.receiverName,
giftDetails?.receiverPhone,
giftDetails?.message,
giftDetails?.isSecret,
giftDetails?.senderEmail,
giftDetails?.senderName,
specialRequest, specialRequest,
getDeliveryMethod, getDeliveryMethod,
tables, tables,
orderType, orderType,
restaurantID, restaurantID,
items, items,
officeDetails?.officeNo, order,
discount.isDiscount, discount.isDiscount,
discount.isGift, discount.isGift,
discount.value, discount.value,

View File

@@ -10,14 +10,15 @@ 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 { GiftDetails } from "./components/GiftDetails";
import { OfficeDetails } from "./components/OfficeDetails";
import { RoomDetails } from "./components/RoomDetails";
import PhoneCard from "./components/phoneCard"; import PhoneCard from "./components/phoneCard";
import InputCard from "components/InputCard";
import { OrderType } from "./hooks/types";
import { GiftCard } from "./components/GiftCard";
export default function CheckoutPage() { export default function CheckoutPage() {
const { t } = useTranslation(); const { t } = useTranslation();
const [form] = Form.useForm(); const [form] = Form.useForm();
const { phone } = useAppSelector(selectCart); const { phone, order, orderType } = useAppSelector(selectCart);
return ( return (
<> <>
<Form <Form
@@ -31,11 +32,28 @@ export default function CheckoutPage() {
<ProHeader>{t("checkout.title")}</ProHeader> <ProHeader>{t("checkout.title")}</ProHeader>
<Layout.Content className={styles.checkoutContainer}> <Layout.Content className={styles.checkoutContainer}>
<AddressSummary /> <AddressSummary />
<RoomDetails />
<OfficeDetails />
<GiftDetails />
<BriefMenu />
<PhoneCard /> <PhoneCard />
{orderType === OrderType.ToRoom && (
<InputCard
title={t("address.roomNumber")}
name="roomNumber"
placeholder={t("address.roomNumber")}
value={order?.roomNumber}
/>
)}
{orderType === OrderType.ToOffice && (
<InputCard
title={t("address.officeNumber")}
name="officeNumber"
placeholder={t("address.officeNumber")}
value={order?.officeNumber}
/>
)}
{orderType === OrderType.Gift && <GiftCard />}
{/* <RoomDetails />
<OfficeDetails /> */}
{/* <GiftDetails /> */}
<BriefMenu />
<PaymentMethods /> <PaymentMethods />
<OrderSummary /> <OrderSummary />
</Layout.Content> </Layout.Content>

View File

@@ -13,7 +13,11 @@ import {
import { OrderDetails } from "pages/checkout/hooks/types"; import { OrderDetails } from "pages/checkout/hooks/types";
import menuParser from "pages/menu/helper"; import menuParser from "pages/menu/helper";
import { DiscountResultType, RestaurantDetails, UserType } from "utils/types/appTypes"; import {
DiscountResultType,
RestaurantDetails,
UserType,
} from "utils/types/appTypes";
import { baseApi } from "./apiSlice"; import { baseApi } from "./apiSlice";
export const branchApi = baseApi.injectEndpoints({ export const branchApi = baseApi.injectEndpoints({
@@ -27,7 +31,9 @@ export const branchApi = baseApi.injectEndpoints({
}, },
}), }),
transformResponse: (response: any) => { transformResponse: (response: any) => {
return response?.result?.restaurants?.[0]; return response?.result?.restaurants?.find(
(restaurant: RestaurantDetails) => restaurant.distance === 595,
);
}, },
providesTags: ["Restaurant"], providesTags: ["Restaurant"],
}), }),
@@ -124,18 +130,15 @@ export const branchApi = baseApi.injectEndpoints({
return response.result; return response.result;
}, },
}), }),
getUserDetails: builder.query< getUserDetails: builder.query<UserType, void>({
UserType, query: () => ({
void url: `${USER_DETAILS_URL}`,
>({ method: "GET",
query: () => ({ }),
url: `${USER_DETAILS_URL}`, transformResponse: (response: any) => {
method: "GET", return response.result;
},
}), }),
transformResponse: (response: any) => {
return response.result;
},
}),
rateOrder: builder.mutation({ rateOrder: builder.mutation({
query: ({ query: ({
orderID, orderID,