diff --git a/src/assets/locals/ar.json b/src/assets/locals/ar.json
index d9b9f69..ead7256 100644
--- a/src/assets/locals/ar.json
+++ b/src/assets/locals/ar.json
@@ -268,10 +268,13 @@
"checkRequiredFields": "يرجى التحقق من الحقول المطلوبة"
},
"checkout": {
+ "addCarDetails": "إضافة تفاصيل السيارة",
+ "soTheRestaurantCanRecognizeYourCarWhenYouArrive": "لتتمكن المطعم من التعرف على سيارتك عند وصولك.",
"customerName": "اسم العميل",
"paymentSummary": "ملخص الدفع",
"holdayGiftCard": "هدية العيد",
"messageIncluded": "الرسالة مضمنة",
+ "save":"حفظ",
"to": "ل",
"giftSummary": "ملخص الهدية",
"customerInformation": "تفاصيل العميل",
@@ -505,5 +508,9 @@
"add": "أضف",
"senderNameRequired": "يجب أن يكون اسم المرسل مطلوب",
"receiverNameRequired": "يجب أن يكون اسم المستلم مطلوب"
+ },
+ "car":{
+ "addCar":"إضافة سيارة",
+ "selectCar":"اختر السيارة"
}
}
diff --git a/src/assets/locals/en.json b/src/assets/locals/en.json
index 81fb41e..a9ce846 100644
--- a/src/assets/locals/en.json
+++ b/src/assets/locals/en.json
@@ -279,7 +279,10 @@
"checkRequiredFields": "Please check required fields"
},
"checkout": {
+ "addCarDetails": "Add Car Details",
+ "soTheRestaurantCanRecognizeYourCarWhenYouArrive": "So the restaurant can recognize your car when you arrive.",
"customerName": "Customer Name",
+ "save": "Save",
"paymentSummary": "Payment Summary",
"orderSummary": "Order Summary",
"holdayGiftCard": "Holday gift card",
@@ -517,5 +520,9 @@
"add": "Add",
"senderNameRequired": "Sender name is required",
"receiverNameRequired": "Receiver name is required"
+ },
+ "car": {
+ "addCar": "Add Car",
+ "selectCar": "Select Car"
}
}
diff --git a/src/components/CustomBottomSheet/CustomBottomSheet.module.css b/src/components/CustomBottomSheet/CustomBottomSheet.module.css
index 5815189..829494a 100644
--- a/src/components/CustomBottomSheet/CustomBottomSheet.module.css
+++ b/src/components/CustomBottomSheet/CustomBottomSheet.module.css
@@ -17,8 +17,6 @@
width: 100%;
}
-
-
.serviceIcon path {
stroke: #ea1f22;
}
@@ -32,3 +30,96 @@
width: 24px;
height: 24px;
}
+
+/* Make AntD checkbox look like a circular check indicator (scoped via CSS modules) */
+.circleCheckbox :global(.ant-checkbox-inner) {
+ width: 24px;
+ height: 24px;
+ border-radius: 50% !important;
+ border: 1.5px solid #d5d8da;
+ background: transparent;
+}
+
+.circleCheckbox :global(.ant-checkbox-checked .ant-checkbox-inner) {
+ border-radius: 50% !important;
+ background: transparent;
+ border-color: #ffb700;
+}
+
+/* Replace AntD checkmark with a filled inner circle when checked (match SVG) */
+.circleCheckbox :global(.ant-checkbox-inner::after) {
+ content: "";
+ border: 0 !important;
+ transform: none !important;
+ width: 0;
+ height: 0;
+ left: 50%;
+ top: 50%;
+}
+
+:global(.ant-app-rtl) .circleCheckbox :global(.ant-checkbox-inner::after) {
+ left: auto;
+ right: 50%;
+}
+
+.circleCheckbox :global(.ant-checkbox-checked .ant-checkbox-inner::after) {
+ width: 18px;
+ height: 18px;
+ margin-left: -9px;
+ margin-top: -9px;
+ border-radius: 50%;
+ background: #ffb700;
+}
+
+:global(.ant-app-rtl)
+ .circleCheckbox
+ :global(.ant-checkbox-checked .ant-checkbox-inner::after) {
+ margin-left: auto;
+ margin-right: -9px;
+}
+
+/* Apply same circular style to Radio buttons */
+.radioCheckbox :global(.ant-radio-inner) {
+ width: 24px;
+ height: 24px;
+ border-radius: 50% !important;
+ border: 1.5px solid #d5d8da;
+ background: transparent;
+}
+
+.radioCheckbox :global(.ant-radio-checked .ant-radio-inner) {
+ border-radius: 50% !important;
+ background: transparent;
+ border-color: #ffb700;
+}
+
+.radioCheckbox :global(.ant-radio-inner::after) {
+ content: "";
+ border: 0 !important;
+ transform: none !important;
+ width: 0;
+ height: 0;
+ left: 50%;
+ top: 50%;
+}
+
+:global(.ant-app-rtl) .radioCheckbox :global(.ant-radio-inner::after) {
+ left: auto;
+ right: 50%;
+}
+
+.radioCheckbox :global(.ant-radio-checked .ant-radio-inner::after) {
+ width: 18px;
+ height: 18px;
+ margin-left: -9px;
+ margin-top: -9px;
+ border-radius: 50%;
+ background: #ffb700;
+}
+
+:global(.ant-app-rtl)
+ .radioCheckbox
+ :global(.ant-radio-checked .ant-radio-inner::after) {
+ margin-left: auto;
+ margin-right: -9px;
+}
diff --git a/src/components/CustomBottomSheet/TipBottomSheet.tsx b/src/components/CustomBottomSheet/TipBottomSheet.tsx
index 57ce385..eb87ce5 100644
--- a/src/components/CustomBottomSheet/TipBottomSheet.tsx
+++ b/src/components/CustomBottomSheet/TipBottomSheet.tsx
@@ -1,10 +1,11 @@
-import { Button, Input } from "antd";
+import { Button, Input, InputNumber } from "antd";
import WaiterRewardingIcon from "components/Icons/waiter/WaiterRewardingIcon";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { ProBottomSheet } from "../ProBottomSheet/ProBottomSheet";
import { updateTip } from "features/order/orderSlice";
import { useAppDispatch } from "redux/hooks";
+import ProText from "components/ProText";
interface TipBottomSheetProps {
isOpen: boolean;
@@ -42,8 +43,8 @@ export function TipBottomSheet({
onClose={handleCancel}
title={t("cart.tip")}
initialSnap={1}
- height={370}
- snapPoints={[370]}
+ height={380}
+ snapPoints={[380]}
>
-
+
+ {t("cart.amount")}
+
-
setValue(e.target.value)}
+ onChange={(value) => setValue(value?.toString() || "")}
placeholder={t("cart.amount")}
autoFocus={false}
size="large"
- style={{ height: 48 }}
+ style={{ height: 48, width: "100%", marginBottom: 8 }}
+ min={"0"}
/>
-
-
diff --git a/src/components/Icons/CarIcon.tsx b/src/components/Icons/CarIcon.tsx
new file mode 100644
index 0000000..fcc61e4
--- /dev/null
+++ b/src/components/Icons/CarIcon.tsx
@@ -0,0 +1,35 @@
+interface CarIconType {
+ className?: string;
+ onClick?: () => void;
+}
+
+const CarIcon = ({ className, onClick }: CarIconType) => {
+ return (
+
+ );
+};
+
+export default CarIcon;
diff --git a/src/components/Icons/PlusIcon.tsx b/src/components/Icons/PlusIcon.tsx
index dd6d36d..8de5842 100644
--- a/src/components/Icons/PlusIcon.tsx
+++ b/src/components/Icons/PlusIcon.tsx
@@ -1,15 +1,15 @@
interface PlusIconType {
className?: string;
onClick?: () => void;
- dimesion?: string
+ dimension?: string
color?: string
}
-const PlusIcon = ({ className, onClick, dimesion, color }: PlusIconType) => {
+const PlusIcon = ({ className, onClick, dimension, color }: PlusIconType) => {
return (
diff --git a/src/pages/cart/components/RewardWaiterCard.tsx b/src/pages/cart/components/RewardWaiterCard.tsx
index 2cb6160..df40896 100644
--- a/src/pages/cart/components/RewardWaiterCard.tsx
+++ b/src/pages/cart/components/RewardWaiterCard.tsx
@@ -161,19 +161,34 @@ export default function RewardWaiterCard() {
iconPlacement="start"
onClick={() => setIsTipOpen(true)}
>
-
- {tip && !isDefaultTip ? tip : t("cart.other")}
-
+ {tip && !isDefaultTip ? (
+
+ ) : (
+
+ {t("cart.other")}
+
+ )}
diff --git a/src/pages/checkout/checkout.module.css b/src/pages/checkout/checkout.module.css
index e69de29..c5ea490 100644
--- a/src/pages/checkout/checkout.module.css
+++ b/src/pages/checkout/checkout.module.css
@@ -0,0 +1,13 @@
+.carCard {
+ gap: 20px;
+ opacity: 1;
+ border-radius: 6px;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+}
+
+.plusIcon {
+ position: relative;
+ top: 2px;
+}
diff --git a/src/pages/checkout/components/CarBottomSheet.tsx b/src/pages/checkout/components/CarBottomSheet.tsx
new file mode 100644
index 0000000..26fe9c6
--- /dev/null
+++ b/src/pages/checkout/components/CarBottomSheet.tsx
@@ -0,0 +1,112 @@
+import { useState } from "react";
+import { useTranslation } from "react-i18next";
+import { ProBottomSheet } from "components/ProBottomSheet/ProBottomSheet";
+import { colors } from "ThemeConstants";
+import { Button, Card } from "antd";
+import CarRatioGroups from "./CarRatioGroups/CarRatioGroups";
+import PlusIcon from "components/Icons/PlusIcon";
+import styles from "../checkout.module.css";
+
+interface CarBottomSheetProps {
+ isOpen: boolean;
+ onClose: () => void;
+}
+
+export function CarBottomSheet({ isOpen, onClose }: CarBottomSheetProps) {
+ const { t } = useTranslation();
+ const [value, setValue] = useState(null);
+
+ const handleCancel = () => {
+ setValue(null);
+ onClose();
+ };
+
+ const handleSave = () => {
+ onClose();
+ setValue(value);
+ };
+
+ return (
+
+
+ setValue(value)}
+ optionsStyle={{
+ fontSize: 12,
+ fontWeight: 500,
+ color: "#5F6C7B",
+ }}
+ valueStyle={{
+ fontSize: 12,
+ fontWeight: 500,
+ color: colors.primary,
+ }}
+ />
+ }
+ >
+ {t("car.addCar")}
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/pages/checkout/components/CarCard.tsx b/src/pages/checkout/components/CarCard.tsx
new file mode 100644
index 0000000..f069767
--- /dev/null
+++ b/src/pages/checkout/components/CarCard.tsx
@@ -0,0 +1,78 @@
+import ProText from "components/ProText";
+import { useTranslation } from "react-i18next";
+import { useAppSelector } from "redux/hooks";
+import BackIcon from "components/Icons/BackIcon";
+import NextIcon from "components/Icons/NextIcon";
+import CarIcon from "components/Icons/CarIcon";
+import { Button, Card } from "antd";
+import styles from "../checkout.module.css";
+import { useState } from "react";
+import { CarBottomSheet } from "./CarBottomSheet";
+
+export function CarCard() {
+ const { t } = useTranslation();
+ const { isRTL } = useAppSelector((state) => state.locale);
+ const [isCarBottomSheetOpen, setIsCarBottomSheetOpen] = useState(false);
+ return (
+ <>
+ {
+ setIsCarBottomSheetOpen(true);
+ }}>
+
+
}
+ style={{
+ backgroundColor: "var(--background)",
+ border: "none",
+ width: 32,
+ height: 32,
+ minWidth: 32,
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ boxShadow: "0 0 10px 0 rgba(0, 0, 0, 0.1)",
+ }}
+ />
+
+
+ {t("checkout.addCarDetails")}
+
+
+
+ {t("checkout.soTheRestaurantCanRecognizeYourCarWhenYouArrive")}
+
+
+ {isRTL ?
:
}
+
+
+ setIsCarBottomSheetOpen(false)}
+ />
+ >
+ );
+}
diff --git a/src/pages/checkout/components/CarRatioGroups/CarRatioGroups.module.css b/src/pages/checkout/components/CarRatioGroups/CarRatioGroups.module.css
new file mode 100644
index 0000000..43e2439
--- /dev/null
+++ b/src/pages/checkout/components/CarRatioGroups/CarRatioGroups.module.css
@@ -0,0 +1,122 @@
+.proRatioGroups :global(.ant-radio-wrapper:last-child) {
+ width: 100% !important;
+}
+
+.proRatioGroups :global(.ant-radio-label) {
+ width: 100% !important;
+}
+
+/* radio.module.css */
+.proRatioGroups :global(.ant-radio-inner) {
+ width: 24px !important;
+ height: 24px !important;
+ border-radius: 30px !important;
+}
+
+.proRatioGroups :global(.ant-radio) {
+ width: 24px !important;
+ height: 24px !important;
+}
+
+.circleCheckbox {
+ border: 1px solid #5f6c7b1f;
+ height: 62px;
+ justify-content: space-between;
+ opacity: 1;
+ border-radius: 888px;
+ padding: 8px 12px;
+ border-width: 1px;
+}
+
+/* Make AntD checkbox look like a circular check indicator (scoped via CSS modules) */
+.circleCheckbox :global(.ant-checkbox-inner) {
+ width: 24px;
+ height: 24px;
+ border-radius: 50% !important;
+ border: 1.5px solid #d5d8da;
+ background: transparent;
+}
+
+.circleCheckbox :global(.ant-checkbox-checked .ant-checkbox-inner) {
+ border-radius: 50% !important;
+ background: transparent;
+ border-color: #ffb700;
+}
+
+/* Replace AntD checkmark with a filled inner circle when checked (match SVG) */
+.circleCheckbox :global(.ant-checkbox-inner::after) {
+ content: "";
+ border: 0 !important;
+ transform: none !important;
+ width: 0;
+ height: 0;
+ left: 50%;
+ top: 50%;
+}
+
+:global(.ant-app-rtl) .circleCheckbox :global(.ant-checkbox-inner::after) {
+ left: auto;
+ right: 50%;
+}
+
+.circleCheckbox :global(.ant-checkbox-checked .ant-checkbox-inner::after) {
+ width: 18px;
+ height: 18px;
+ margin-left: -9px;
+ margin-top: -9px;
+ border-radius: 50%;
+ background: #ffb700;
+}
+
+:global(.ant-app-rtl)
+ .circleCheckbox
+ :global(.ant-checkbox-checked .ant-checkbox-inner::after) {
+ margin-left: auto;
+ margin-right: -9px;
+}
+
+/* Apply same circular style to Radio buttons */
+.circleCheckbox :global(.ant-radio-inner) {
+ width: 24px;
+ height: 24px;
+ border-radius: 50% !important;
+ border: 1.5px solid #d5d8da;
+ background: transparent;
+}
+
+.circleCheckbox :global(.ant-radio-checked .ant-radio-inner) {
+ border-radius: 50% !important;
+ background: transparent;
+ border-color: #ffb700;
+}
+
+.circleCheckbox :global(.ant-radio-inner::after) {
+ content: "";
+ border: 0 !important;
+ transform: none !important;
+ width: 0;
+ height: 0;
+ left: 50%;
+ top: 50%;
+}
+
+:global(.ant-app-rtl) .circleCheckbox :global(.ant-radio-inner::after) {
+ left: auto;
+ right: 50%;
+}
+
+.circleCheckbox :global(.ant-radio-checked .ant-radio-inner::after) {
+ width: 18px;
+ height: 18px;
+ margin-left: -9px;
+ margin-top: -9px;
+ border-radius: 50%;
+ background: #ffb700;
+}
+
+:global(.ant-app-rtl)
+ .circleCheckbox
+ :global(.ant-radio-checked .ant-radio-inner::after) {
+ margin-left: auto;
+ margin-right: -9px;
+}
diff --git a/src/pages/checkout/components/CarRatioGroups/CarRatioGroups.tsx b/src/pages/checkout/components/CarRatioGroups/CarRatioGroups.tsx
new file mode 100644
index 0000000..7595b14
--- /dev/null
+++ b/src/pages/checkout/components/CarRatioGroups/CarRatioGroups.tsx
@@ -0,0 +1,132 @@
+import { Button, Card, Divider, Radio, RadioChangeEvent, Space } from "antd";
+import ProText from "components/ProText";
+import styles from "./CarRatioGroups.module.css";
+import { useTranslation } from "react-i18next";
+import CarIcon from "components/Icons/CarIcon";
+
+interface CarRatioGroupsProps {
+ options: { label: string; value: string; price?: string }[];
+ onRatioClick?: (value: string) => void;
+ onChange?: (e: RadioChangeEvent) => void;
+ value?: string;
+ optionsStyle?: React.CSSProperties;
+ valueStyle?: React.CSSProperties;
+ showDivider?: boolean;
+}
+
+const CarRatioGroups = ({
+ options,
+ onRatioClick,
+ onChange,
+ value,
+ optionsStyle,
+ valueStyle,
+ showDivider = false,
+ ...props
+}: CarRatioGroupsProps) => {
+ const { t } = useTranslation();
+ const handleChange = (e: RadioChangeEvent) => {
+ console.log(e.target.value);
+ // If onChange is provided (from Form.Item), use it
+ if (onChange) {
+ onChange(e);
+ }
+ // Also call onRatioClick if provided (for backward compatibility)
+ if (onRatioClick) {
+ onRatioClick(e.target.value);
+ }
+ };
+
+ return (
+
+
+
+ {options.map((option) => (
+ <>
+
+
+
+
+
+ Optima
+
+
+
+ 42322, blue
+
+
+
+
+
}
+ style={{
+ backgroundColor: "var(--background)",
+ border: "none",
+ width: 32,
+ height: 32,
+ minWidth: 32,
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ boxShadow: "0 0 10px 0 rgba(0, 0, 0, 0.1)",
+ }}
+ />
+
+
+ {showDivider && options.length !== options.length - 1 && (
+
+ )}
+ >
+ ))}
+
+
+
+ );
+};
+
+export default CarRatioGroups;
diff --git a/src/pages/checkout/page.tsx b/src/pages/checkout/page.tsx
index 83db955..829471f 100644
--- a/src/pages/checkout/page.tsx
+++ b/src/pages/checkout/page.tsx
@@ -20,6 +20,7 @@ import CustomerInformationCard from "./components/CustomerInformationCard";
import Ads1 from "components/Ads/Ads1";
import TimeEstimateCard from "pages/cart/components/timeEstimate/TimeEstimateCard";
import { useEffect } from "react";
+import { CarCard } from "./components/CarCard";
export default function CheckoutPage() {
const { t } = useTranslation();
@@ -46,6 +47,7 @@ export default function CheckoutPage() {
{(orderType === OrderType.Pickup ||
orderType === OrderType.ScheduledOrder) && }
+ {orderType === OrderType.Pickup && }
{orderType === OrderType.Gift && }
{!token && }