diff --git a/src/assets/locals/ar.json b/src/assets/locals/ar.json index 989dfd2..2414c4d 100644 --- a/src/assets/locals/ar.json +++ b/src/assets/locals/ar.json @@ -220,7 +220,8 @@ "plateNumberPlaceholder": "أدخل رقم السيارة", "inYourCart": "في سلة المشتريات", "updatedSuccessfully": "تم التحديث بنجاح", - "editNote": "تعديل الملاحظة" + "editNote": "تعديل الملاحظة", + "selectTimeEstimate": "أدخل وقت التقديم" }, "checkout": { "title": "الدفع", diff --git a/src/assets/locals/en.json b/src/assets/locals/en.json index 04a3fb9..7946853 100644 --- a/src/assets/locals/en.json +++ b/src/assets/locals/en.json @@ -229,7 +229,8 @@ "Cash": "Cash", "e-payment": "e-payment", "plateNumber": "Plate Number", - "plateNumberPlaceholder": "Enter plate number" + "plateNumberPlaceholder": "Enter plate number", + "selectTimeEstimate": "Select Estimate Time" }, "checkout": { "title": "Checkout", diff --git a/src/components/CustomBottomSheet/EstimateTimeBottomSheet.tsx b/src/components/CustomBottomSheet/EstimateTimeBottomSheet.tsx deleted file mode 100644 index aae647a..0000000 --- a/src/components/CustomBottomSheet/EstimateTimeBottomSheet.tsx +++ /dev/null @@ -1,265 +0,0 @@ -// import { useGlobals } from "../../hooks/useGlobals"; -import { Button, Divider } from "antd"; -import BackIcon from "components/Icons/BackIcon"; -import NextIcon from "components/Icons/NextIcon"; -import { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; -import { ProBottomSheet } from "../ProBottomSheet/ProBottomSheet"; -import styles from "./CustomBottomSheet.module.css"; - -interface EstimateTimeBottomSheetProps { - isOpen: boolean; - onClose: () => void; - onSave: (date: Date, time: string) => void; - initialDate?: Date; -} - -export function EstimateTimeBottomSheet({ - isOpen, - onClose, - onSave, - initialDate = new Date(), -}: EstimateTimeBottomSheetProps) { - const { t } = useTranslation(); - const isRTL = false; // Default to LTR - const [selectedDate, setSelectedDate] = useState(initialDate); - const [selectedTime, setSelectedTime] = useState("12:00"); - const [isAM, setIsAM] = useState(true); - - useEffect(() => { - setSelectedDate(initialDate); - }, [initialDate]); - - const formatDate = (date: Date) => { - return date.toLocaleDateString("en-US", { - weekday: "long", - month: "short", - day: "numeric", - }); - }; - - const goToPreviousDay = () => { - const newDate = new Date(selectedDate); - newDate.setDate(newDate.getDate() - 1); - setSelectedDate(newDate); - }; - - const goToNextDay = () => { - const newDate = new Date(selectedDate); - newDate.setDate(newDate.getDate() + 1); - setSelectedDate(newDate); - }; - - const handleTimeSelect = (time: string) => { - setSelectedTime(time); - }; - - const handleSave = () => { - const [hours, minutes] = selectedTime.split(":"); - const date = new Date(selectedDate); - date.setHours( - isAM ? parseInt(hours) : parseInt(hours) + 12, - parseInt(minutes), - 0, - 0 - ); - - onSave(date, `${selectedTime} ${isAM ? "AM" : "PM"}`); - onClose(); - }; - - const timeSlots = [ - "12:00", - "1:00", - "2:00", - "3:00", - "4:00", - "5:00", - "6:00", - "7:00", - "8:00", - "9:00", - "10:00", - "11:00", - ]; - - return ( - -
- {/* Day Selection */} -
-
-
-
- - {/* Time Selection */} -
- {/* AM/PM Toggle */} -
- - -
- - {/* Time Slots Grid */} -
- {timeSlots.map((time) => ( - - ))} -
- - - - {/* Save Button */} - -
-
-
- ); -} diff --git a/src/pages/cart/components/CartDesktopLayout.tsx b/src/pages/cart/components/CartDesktopLayout.tsx index 6c09ad9..071f1b0 100644 --- a/src/pages/cart/components/CartDesktopLayout.tsx +++ b/src/pages/cart/components/CartDesktopLayout.tsx @@ -18,6 +18,8 @@ import CouponCard from "pages/cart/components/CouponCard.tsx"; import RewardWaiterCard from "pages/cart/components/RewardWaiterCard.tsx"; import TableNumberCard from "pages/cart/components/TableNumberCard.tsx"; import CarPlateCard from "pages/cart/components/CarPlateCard.tsx"; +import YouMightAlsoLike from "pages/cart/components/YouMightAlsoLike.tsx"; +import TimeEstimateCard from "pages/cart/components/timeEstimate/TimeEstimateCard.tsx"; export default function CartDesktopLayout() { const { t } = useTranslation(); @@ -170,6 +172,8 @@ export default function CartDesktopLayout() { {/* Sidebar Column */}
+ +
@@ -183,6 +187,10 @@ export default function CartDesktopLayout() { {orderType === "pickup" && } + {(orderType === "delivery" || orderType === "pickup") && ( + + )} +
state.theme); const orderType = localStorage.getItem("orderType"); - const [estimateWay, setEstimateWay] = useState("now"); - const [isEstimateTimeOpen, setIsEstimateTimeOpen] = useState(false); - - const handleEstimateTimeSave = (date: Date, time: string) => { - dispatch(updateEstimateTime({ date, time })); - message.success(t("cart.estimateTime") + " " + t("updatedSuccessfully")); - }; - - const handleEstimateTimeClose = () => { - setIsEstimateTimeOpen(false); - }; - const getMenuItemImageStyle = () => { if (isMobile) { return { @@ -239,24 +224,7 @@ export default function CartMobileTabletLayout() { {/* Estimate Time */} {(orderType === "delivery" || orderType === "pickup") && ( - - { - if (value === "now") { - setEstimateWay(value); - handleEstimateTimeSave(new Date(), "now"); - } else { - setEstimateWay(value); - setIsEstimateTimeOpen(true); - } - }} - /> - + )} {/* Collection Method */} @@ -353,13 +321,6 @@ export default function CartMobileTabletLayout() {
{/* Mobile/Tablet Bottom Sheets */} - - ); } diff --git a/src/pages/cart/components/timeEstimate/BottomSheet.tsx b/src/pages/cart/components/timeEstimate/BottomSheet.tsx new file mode 100644 index 0000000..82b6e89 --- /dev/null +++ b/src/pages/cart/components/timeEstimate/BottomSheet.tsx @@ -0,0 +1,33 @@ +import { useTranslation } from "react-i18next"; +import { ProBottomSheet } from "components/ProBottomSheet/ProBottomSheet.tsx"; +import Content from "pages/cart/components/timeEstimate/Content.tsx"; + +interface EstimateTimeBottomSheetProps { + isOpen: boolean; + onClose: () => void; + onSave: (date: Date, time: string) => void; + initialDate?: Date; +} + +export function BottomSheet({ + isOpen, + onClose, + onSave, + initialDate = new Date(), +}: EstimateTimeBottomSheetProps) { + const { t } = useTranslation(); + + return ( + + + + ); +} diff --git a/src/pages/cart/components/timeEstimate/Content.tsx b/src/pages/cart/components/timeEstimate/Content.tsx new file mode 100644 index 0000000..7c3054c --- /dev/null +++ b/src/pages/cart/components/timeEstimate/Content.tsx @@ -0,0 +1,248 @@ +import { Button, Divider } from "antd"; +import NextIcon from "components/Icons/NextIcon.tsx"; +import styles from "components/CustomBottomSheet/CustomBottomSheet.module.css"; +import BackIcon from "components/Icons/BackIcon.tsx"; +import { useState, useEffect } from "react"; +import { useTranslation } from "react-i18next"; + +const timeSlots = [ + "12:00", + "1:00", + "2:00", + "3:00", + "4:00", + "5:00", + "6:00", + "7:00", + "8:00", + "9:00", + "10:00", + "11:00", +]; +interface EstimateTimeContentProps { + onSave: (date: Date, time: string) => void; + initialDate: Date; + onClose: () => void; +} + +export default function Content({ + onSave, + initialDate, + onClose, +}: EstimateTimeContentProps) { + const { t } = useTranslation(); + const isRTL = false; // Default to LTR + const [selectedDate, setSelectedDate] = useState(initialDate); + const [selectedTime, setSelectedTime] = useState("12:00"); + const [isAM, setIsAM] = useState(true); + + useEffect(() => { + setSelectedDate(initialDate); + }, [initialDate]); + + const formatDate = (date: Date) => { + return date.toLocaleDateString("en-US", { + weekday: "long", + month: "short", + day: "numeric", + }); + }; + + const goToPreviousDay = () => { + const newDate = new Date(selectedDate); + newDate.setDate(newDate.getDate() - 1); + setSelectedDate(newDate); + }; + + const goToNextDay = () => { + const newDate = new Date(selectedDate); + newDate.setDate(newDate.getDate() + 1); + setSelectedDate(newDate); + }; + + const handleTimeSelect = (time: string) => { + setSelectedTime(time); + }; + + const handleSave = () => { + const [hours, minutes] = selectedTime.split(":"); + const date = new Date(selectedDate); + date.setHours( + isAM ? parseInt(hours) : parseInt(hours) + 12, + parseInt(minutes), + 0, + 0, + ); + + onSave(date, `${selectedTime} ${isAM ? "AM" : "PM"}`); + onClose(); + }; + + return ( +
+ {/* Day Selection */} +
+
+
+
+ + {/* Time Selection */} +
+ {/* AM/PM Toggle */} +
+ + +
+ + {/* Time Slots Grid */} +
+ {timeSlots.map((time) => ( + + ))} +
+ + + + {/* Save Button */} + +
+
+ ); +} diff --git a/src/pages/cart/components/timeEstimate/Dialog.tsx b/src/pages/cart/components/timeEstimate/Dialog.tsx new file mode 100644 index 0000000..2e1e50e --- /dev/null +++ b/src/pages/cart/components/timeEstimate/Dialog.tsx @@ -0,0 +1,37 @@ +import { Button, Modal } from "antd"; +import { useTranslation } from "react-i18next"; + +import Content from "pages/cart/components/timeEstimate/Content.tsx"; + +interface EstimateTimeDialogProps { + isOpen: boolean; + onClose: () => void; + onSave: (date: Date, time: string) => void; + initialDate?: Date; +} + +export function Dialog({ + isOpen, + onClose, + onSave, + initialDate = new Date(), +}: EstimateTimeDialogProps) { + const { t } = useTranslation(); + + return ( + + {t("cart.cancel")} + , + ]} + width={500} + destroyOnHidden + > + + + ); +} diff --git a/src/pages/cart/components/timeEstimate/TimeEstimateCard.tsx b/src/pages/cart/components/timeEstimate/TimeEstimateCard.tsx new file mode 100644 index 0000000..43cec61 --- /dev/null +++ b/src/pages/cart/components/timeEstimate/TimeEstimateCard.tsx @@ -0,0 +1,66 @@ +import ProRatioGroups from "components/ProRatioGroups/ProRatioGroups.tsx"; +import ProInputCard from "components/ProInputCard/ProInputCard.tsx"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import { updateEstimateTime, selectCart } from "features/order/orderSlice.ts"; +import { message } from "antd"; +import { BottomSheet } from "pages/cart/components/timeEstimate/BottomSheet.tsx"; +import { useAppDispatch, useAppSelector } from "redux/hooks.ts"; +import useBreakPoint from "hooks/useBreakPoint.ts"; +import { Dialog } from "pages/cart/components/timeEstimate/Dialog.tsx"; + +export default function TimeEstimateCard() { + const { t } = useTranslation(); + const dispatch = useAppDispatch(); + const { estimateTimeDate } = useAppSelector(selectCart); + const { isDesktop } = useBreakPoint(); + const [estimateWay, setEstimateWay] = useState("now"); + const [isEstimateTimeOpen, setIsEstimateTimeOpen] = useState(false); + + const handleEstimateTimeSave = (date: Date, time: string) => { + dispatch(updateEstimateTime({ date, time })); + message.success(t("cart.estimateTime") + " " + t("updatedSuccessfully")); + }; + + const handleEstimateTimeClose = () => { + setIsEstimateTimeOpen(false); + }; + + return ( + <> + + { + if (value === "now") { + setEstimateWay(value); + handleEstimateTimeSave(new Date(), "now"); + } else { + setEstimateWay(value); + setIsEstimateTimeOpen(true); + } + }} + /> + + {isDesktop ? ( + + ) : ( + + )} + + ); +}