cart & checkout: UI enhacnements

This commit is contained in:
2025-12-25 21:13:25 +03:00
parent 90e729cdce
commit ce9092d634
24 changed files with 167 additions and 86 deletions

View File

@@ -605,3 +605,8 @@
outline: 2px solid #ffffff;
outline-offset: 2px;
}
.deleteIcon {
position: relative;
top: 1px;
}

View File

@@ -24,7 +24,7 @@ export default function CarPlateCard() {
placeholder={t("cart.plateNumber")}
size="large"
autoFocus={false}
style={{ padding: "7px 11px", height: 50, borderRadius: 888 }}
style={{ padding: "7px 11px", height: 48, borderRadius: 888 }}
value={plateCar}
onChange={(e) => {
dispatch(updatePlateCar(e.target.value));

View File

@@ -1,5 +1,4 @@
import { PlusOutlined } from "@ant-design/icons";
import { Card, Divider, Space, Layout } from "antd";
import { Card, Divider, Space, Layout, Button } from "antd";
import ArabicPrice from "components/ArabicPrice";
import CartActionsButtons from "components/CartActionsButtons/CartActionsButtons.tsx";
import ImageWithFallback from "components/ImageWithFallback";
@@ -9,8 +8,7 @@ import ProTitle from "components/ProTitle.tsx";
import { selectCart } from "features/order/orderSlice.ts";
import styles from "pages/cart/cart.module.css";
import YouMightAlsoLike from "pages/cart/components/youMayLike/YouMightAlsoLike.tsx";
import { Link, useParams } from "react-router-dom";
import { colors } from "ThemeConstants.ts";
import { Link, useNavigate, useParams } from "react-router-dom";
import { useAppSelector } from "redux/hooks.ts";
@@ -18,13 +16,14 @@ import { FormInstance } from "antd";
import useBreakPoint from "hooks/useBreakPoint.ts";
import CarPlateCard from "pages/cart/components/CarPlateCard.tsx";
import CartFooter from "pages/cart/components/cartFooter/CartFooter.tsx";
import CouponCard from "pages/cart/components/CouponCard.tsx";
import SpecialRequestCard from "pages/cart/components/specialRequest/SpecialRequestCard.tsx";
import TableNumberCard from "pages/cart/components/TableNumberCard.tsx";
import TimeEstimateCard from "pages/cart/components/timeEstimate/TimeEstimateCard.tsx";
import { OrderType } from "pages/checkout/hooks/types";
import { useTranslation } from "react-i18next";
import { Variant } from "utils/types/appTypes";
import DeleteIcon from "components/Icons/DeleteIcon";
import PlusIcon from "components/Icons/PlusIcon";
interface CartMobileTabletLayoutProps {
form: FormInstance;
@@ -39,8 +38,8 @@ export default function CartMobileTabletLayout({
const { subdomain } = useParams();
const { pickup_type } = useAppSelector((state) => state.order.restaurant);
const { isMobile, isTablet } = useBreakPoint();
const getResponsiveClass = () => (isTablet ? "tablet" : "mobile");
const navigate = useNavigate();
const getMenuItemImageStyle = () => {
if (isMobile) {
@@ -82,11 +81,21 @@ export default function CartMobileTabletLayout({
>
<div
style={{
marginTop: 10,
marginTop: 3,
boxSizing: "border-box", // Explicit box model definition
}}
>
<ProTitle level={5} style={{ whiteSpace: "nowrap" }}>
<ProTitle
level={5}
style={{
whiteSpace: "nowrap",
fontWeight: 500,
fontStyle: "Medium",
fontSize: 18,
lineHeight: "140%",
letterSpacing: 0,
}}
>
{t("cart.yourOrder")}
</ProTitle>
</div>
@@ -100,25 +109,29 @@ export default function CartMobileTabletLayout({
textAlign: "end",
}}
>
<div
<Button
shape="circle"
iconPlacement="start"
icon={
<DeleteIcon
className={styles.deleteIcon}
color={"#C0BFC4"}
dimension={16}
/>
}
size="small"
className={styles.addButton}
style={{
color: colors.primary,
width: 32,
height: 32,
border: "1px solid #DEDEE0",
}}
>
<PlusOutlined
style={{
color: colors.primary,
marginLeft: 5,
marginTop: 15,
}}
/>
{t("cart.addMore")}
</div>
/>
</Link>
</div>
{items.length >= 1 && (
<Divider style={{ margin: "0px 0px 10px 0px" }} />
<Divider style={{ margin: "8px 0px 12px 0px" }} />
)}
{items.map((item, index) => (
<div key={index} style={{ position: "relative" }}>
@@ -230,6 +243,16 @@ export default function CartMobileTabletLayout({
)}
</div>
))}
<Button
style={{ width: "100%", marginTop: 24, color: "#4C4A58" }}
onClick={() => {
navigate(`/${subdomain}/menu?${
orderType ? `orderType=${orderType}` : ""
}`);
}}
>
<PlusIcon dimesion="18" /> {t("cart.addMore")}
</Button>
</Card>
</div>
</div>

View File

@@ -83,7 +83,7 @@ export default function CouponCard() {
placeholder={t("cart.couponCode")}
size="large"
autoFocus={false}
style={{ padding: "7px 11px", height: 50 }}
style={{ padding: "7px 11px", height: 48 }}
onChange={(e) => {
dispatch(updateCoupon(e.target.value));
}}

View File

@@ -1,5 +1,12 @@
.inputField {
height: 50px;
border-radius: 8px !important;
justify-content: space-between;
padding-top: 12px;
padding-right: 16px;
padding-bottom: 12px;
padding-left: 16px;
opacity: 1;
border-width: 1px;
}
.editButton {

View File

@@ -9,13 +9,13 @@ import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useAppDispatch, useAppSelector } from "redux/hooks.ts";
import styles from "./SpecialRequestCard.module.css";
import TextArea from "antd/es/input/TextArea";
export default function SpecialRequestCard() {
const { t } = useTranslation();
const { isDesktop } = useBreakPoint();
const dispatch = useAppDispatch();
const { specialRequest } = useAppSelector(selectCart);
const { isRTL } = useAppSelector((state) => state.locale);
const [isSpecialRequestOpen, setIsSpecialRequestOpen] = useState(false);
const handleSpecialRequestSave = (value: string) => {
@@ -32,12 +32,8 @@ export default function SpecialRequestCard() {
title={t("cart.specialRequest")}
dividerStyle={{ margin: "5px 0 0 0" }}
>
<Form.Item
label={t("cart.specialRequest")}
name="specialRequest"
style={{ position: "relative", top: -5 }}
>
<Input
<Form.Item name="specialRequest" style={{ marginTop: 12 }}>
{/* <Input
placeholder={t("cart.specialRequest")}
size="large"
autoFocus={false}
@@ -51,6 +47,13 @@ export default function SpecialRequestCard() {
<u>{t("cart.editNote")}</u> {isRTL ? <LeftOutlined /> : <RightOutlined />}
</div>
}
/> */}
<TextArea
placeholder={t("cart.leaveANoteHere")}
rows={2}
autoFocus={false}
className={styles.inputField}
onChange={(e) => handleSpecialRequestSave(e.target.value)}
/>
</Form.Item>
</ProInputCard>

View File

@@ -22,8 +22,8 @@ export function BottomSheet({
title={t("cart.selectTimeEstimate")}
showCloseButton={true}
initialSnap={1}
height={555}
snapPoints={["65vh"]}
height={495}
snapPoints={[495]}
>
<Content onSave={onSave} onClose={onClose} />
</ProBottomSheet>

View File

@@ -0,0 +1,3 @@
.customerInformationCard {
height: 215px !important;
}

View File

@@ -0,0 +1,44 @@
import ProInputCard from "components/ProInputCard/ProInputCard.tsx";
import ProPhoneInput from "components/ProPhoneInput";
import { selectCart, updateCustomerName } from "features/order/orderSlice";
import { OrderType } from "pages/checkout/hooks/types.ts";
import { useTranslation } from "react-i18next";
import { useAppDispatch, useAppSelector } from "redux/hooks";
import { Form, Input } from "antd";
import styles from "./CustomerInformationCard.module.css";
export default function CustomerInformationCard() {
const { t } = useTranslation();
const { orderType } = useAppSelector(selectCart);
const dispatch = useAppDispatch();
const customerName = useAppSelector((state) => state.order.customerName);
return (
orderType !== OrderType.Gift && (
<>
<ProInputCard
title={t("checkout.customerInformation")}
className={styles.customerInformationCard}
>
<div style={{ position: "relative", top: -25 }}>
<Form.Item label={t("checkout.customerName")} name="customerName">
<Input
placeholder={t("checkout.customerName")}
size="large"
autoFocus={false}
style={{ padding: "7px 11px", height: 48, borderRadius: 888 }}
value={customerName}
onChange={(e) => {
dispatch(updateCustomerName(e.target.value));
}}
/>
</Form.Item>
</div>
<div style={{ position: "relative", top: -30 }}>
<ProPhoneInput label={t("login.phone")} propName="phone" />
</div>
</ProInputCard>
</>
)
);
}

View File

@@ -1,3 +0,0 @@
.phoneCard {
height: 150px !important;
}

View File

@@ -1,27 +0,0 @@
import ProInputCard from "components/ProInputCard/ProInputCard.tsx";
import ProPhoneInput from "components/ProPhoneInput";
import { selectCart } from "features/order/orderSlice";
import { OrderType } from "pages/checkout/hooks/types.ts";
import { useTranslation } from "react-i18next";
import { useAppSelector } from "redux/hooks";
import styles from "./PhoneCard.module.css";
export default function PhoneCard() {
const { t } = useTranslation();
const { orderType } = useAppSelector(selectCart);
return (
orderType !== OrderType.Gift && (
<>
<ProInputCard
title={t("checkout.phoneNumber")}
className={styles.phoneCard}
>
<div style={{ position: "relative", top: -20 }}>
<ProPhoneInput label={t("login.phone")} propName="phone" />
</div>
</ProInputCard>
</>
)
);
}

View File

@@ -15,8 +15,8 @@ import RewardWaiterCard from "pages/cart/components/RewardWaiterCard";
import ProInputCard from "components/ProInputCard/ProInputCard";
import ProRatioGroups from "components/ProRatioGroups/ProRatioGroups";
import CouponCard from "pages/cart/components/CouponCard";
import PhoneCard from "./components/PhoneCard";
import BriefMenuCard from "./components/BriefMenuCard";
import CustomerInformationCard from "./components/CustomerInformationCard";
export default function CheckoutPage() {
const { t } = useTranslation();
@@ -37,7 +37,7 @@ export default function CheckoutPage() {
<ProHeader>{t("checkout.title")}</ProHeader>
<Layout.Content className={styles.checkoutContainer}>
<PaymentMethods />
{!token && <PhoneCard />}
{!token && <CustomerInformationCard />}
<AddressSummary />
{orderType === OrderType.ToRoom && (
<InputCard

View File

@@ -7,18 +7,19 @@ import { selectCart } from "features/order/orderSlice";
import { AddressSummary } from "pages/checkout/components/AddressSummary";
import BriefMenu from "pages/checkout/components/BriefMenu";
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";
import PayButton from "./components/PayButton";
import CustomerInformationCard from "pages/checkout/components/CustomerInformationCard";
export default function PayPage() {
const { t } = useTranslation();
const [form] = Form.useForm();
const { phone, order, orderType } = useAppSelector(selectCart);
const { token } = useAppSelector((state) => state.auth);
return (
<>
<Form
@@ -54,7 +55,7 @@ export default function PayPage() {
{/* <GiftDetails /> */}
<BriefMenu />
<OrderSummary />
<PhoneCard />
{!token && <CustomerInformationCard />}
<PaymentMethods />
</Layout.Content>