Compare commits

..

3 Commits

31 changed files with 888 additions and 390 deletions

View File

@@ -266,6 +266,11 @@
},
"checkout": {
"customerName": "اسم العميل",
"paymentSummary": "ملخص الدفع",
"holdayGiftCard": "هدية العيد",
"messageIncluded": "الرسالة مضمنة",
"to": "ل",
"giftSummary": "ملخص الهدية",
"customerInformation": "تفاصيل العميل",
"title": "الدفع",
"cash": "كاش",
@@ -370,6 +375,12 @@
},
"order": {
"title": "الطلب",
"newOrder": "طلب جديد",
"paymentSummary": "ملخص الدفع",
"aStaffMemberWillCollectTheCashFromYouAtYourTable": "سيجمع موظف المطعم المال منك عند طاولتك",
"orderSummary": "ملخص الطلب",
"cashPaymentConfirmed": "تم الدفع بالكاش بنجاح",
"callWaiter": "اتصل بالخادم",
"yourOrder": "طلبك",
"done": "تم",
"yourOrderFromFascanoRestaurant": "طلبك من مطعم فاسكانو",
@@ -474,6 +485,12 @@
"yourPhone": "رقم هاتفك",
"keepMyNameSecret": "الاحتفاظ باسمي مخفياً",
"receiverInformation": "تفاصيل المستلم",
"costumeAmount": "مبلغ البطاقة"
"costumeAmount": "مبلغ البطاقة",
"enterCustomOucherAmount": "أدخل مبلغ البطاقة المخصص",
"amount": "المبلغ",
"eCardAmount": "مبلغ البطاقة الإلكترونية",
"receiverName": "اسم المستلم",
"edit": "تعديل",
"yourInformation": "تفاصيلك"
}
}

View File

@@ -276,6 +276,12 @@
},
"checkout": {
"customerName": "Customer Name",
"paymentSummary": "Payment Summary",
"orderSummary": "Order Summary",
"holdayGiftCard": "Holday gift card",
"messageIncluded": "Message included",
"to": "To",
"giftSummary": "Gift Summary",
"customerInformation": "Customer Information",
"title": "Checkout",
"cash": "Cash",
@@ -381,6 +387,10 @@
},
"order": {
"title": "Order",
"newOrder": "New Order",
"aStaffMemberWillCollectTheCashFromYouAtYourTable": "A staff member will collect the cash from you at your table",
"cashPaymentConfirmed": "Cash payment confirmed",
"callWaiter": "Call Waiter",
"yourOrder": "Your Order",
"done": "Done",
"yourOrderFromFascanoRestaurant": "Your order from Fascano restaurant",
@@ -486,6 +496,12 @@
"yourPhone": "Your Phone",
"keepMyNameSecret": "Keep my name secret",
"receiverInformation": "Receiver Information",
"costumeAmount": "Costume amount"
"costumeAmount": "Costume amount",
"enterCustomOucherAmount": "Enter custom oucher amount",
"amount": "Amount",
"eCardAmount": "E-Card Amount",
"receiverName": "Receiver Name",
"edit": "Edit",
"yourInformation": "Your Information"
}
}

View File

@@ -27,8 +27,12 @@ export default function Ads1({ className }: { className?: string }) {
>
<ProTitle
style={{
marginTop: 5,
fontSize: 14,
fontFamily: "Roboto",
fontWeight: 600,
fontStyle: "SemiBold",
fontSize: 16,
lineHeight: "100%",
letterSpacing: "2%",
}}
>
{t("home.promotion.description")}
@@ -38,6 +42,7 @@ export default function Ads1({ className }: { className?: string }) {
style={{
marginTop: 5,
fontSize: 14,
color:"#00AC17"
}}
>
{t("home.promotion.title")}

View File

@@ -63,7 +63,7 @@
}
.adsCard :global(.ant-card-body) {
padding: 8px !important;
padding: 10px !important;
}
:global(.darkApp) .adsCard {

View File

@@ -8,11 +8,7 @@ import { useTranslation } from "react-i18next";
import { useAppSelector } from "redux/hooks";
import styles from "./Ads2.module.css";
export default function Ads2({
className,
}: {
className?: string;
}) {
export default function Ads2({ className }: { className?: string }) {
const { t } = useTranslation();
const { isRTL } = useAppSelector((state) => state.locale);
@@ -26,8 +22,12 @@ export default function Ads2({
<Card className={styles.adsCard}>
<ProTitle
style={{
marginTop: 5,
fontSize: 14,
fontFamily: "Roboto",
fontWeight: 600,
fontStyle: "SemiBold",
fontSize: 16,
lineHeight: "100%",
letterSpacing: "2%",
}}
>
{t("home.promotion.description")}
@@ -37,9 +37,10 @@ export default function Ads2({
style={{
marginTop: 5,
fontSize: 14,
color: "#00AC17",
}}
>
{t("home.promotion.title")}
{t("home.showDetails")}
</ProText>
<div

View File

@@ -17,22 +17,7 @@
width: 100%;
}
.rateServiceCard{
width: 100%;
height: 48px;
display: flex;
justify-content: center;
padding: 12px 18px !important;
row-gap: 10px;
transition: all 0.3s ease;
border-radius: 50px;
}
.rateServiceCard :global(.ant-card-body) {
padding: 0px !important;
text-align: start;
width: 100%;
}
.serviceIcon path {
stroke: #ea1f22;

View File

@@ -1,6 +1,6 @@
import { useTranslation } from "react-i18next";
import { ProBottomSheet } from "../ProBottomSheet/ProBottomSheet";
import { updateGiftType } from "features/order/orderSlice";
import { updateGiftDetails } from "features/order/orderSlice";
import { useAppDispatch } from "redux/hooks";
import GiftItemsBtnIcon from "components/Icons/GiftItemsBtnIcon";
import GiftBalanceBtnIcon from "components/Icons/GiftBalanceBtnIcon";
@@ -21,8 +21,8 @@ export function GiftTypeBottomSheet({
const { t } = useTranslation();
const dispatch = useAppDispatch();
const handleSave = (value: string) => {
dispatch(updateGiftType(value));
const handleSave = (giftType: string) => {
dispatch(updateGiftDetails({ giftType: giftType }));
onClose();
onSave?.();
};

View File

@@ -0,0 +1,55 @@
interface CardAmountIconType {
className?: string;
onClick?: () => void;
}
const CardAmountIcon = ({ className, onClick }: CardAmountIconType) => {
return (
<svg
width="64"
height="42"
viewBox="0 0 64 42"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
onClick={onClick}
>
<rect width="64" height="42" rx="4" fill="#FAFAFA" />
<path
opacity="0.5"
d="M26 18H30"
stroke="#E8B400"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M40.833 19H38.231C36.446 19 35 20.343 35 22C35 23.657 36.447 25 38.23 25H40.833C40.917 25 40.958 25 40.993 24.998C41.533 24.965 41.963 24.566 41.998 24.065C42 24.033 42 23.994 42 23.917V20.083C42 20.006 42 19.967 41.998 19.935C41.962 19.434 41.533 19.035 40.993 19.002C40.958 19 40.917 19 40.833 19Z"
stroke="#4C4A58"
stroke-width="1.5"
/>
<path
d="M40.965 19C40.887 17.128 40.637 15.98 39.828 15.172C38.657 14 36.771 14 33 14H30C26.229 14 24.343 14 23.172 15.172C22.001 16.344 22 18.229 22 22C22 25.771 22 27.657 23.172 28.828C24.344 29.999 26.229 30 30 30H33C36.771 30 38.657 30 39.828 28.828C40.637 28.02 40.888 26.872 40.965 25"
stroke="#4C4A58"
stroke-width="1.5"
/>
<path
opacity="0.5"
d="M26 13.9999L29.735 11.5229C30.2604 11.1816 30.8735 11 31.5 11C32.1265 11 32.7396 11.1816 33.265 11.5229L37 13.9999"
stroke="#E8B400"
stroke-width="1.5"
stroke-linecap="round"
/>
<path
opacity="0.5"
d="M37.9922 22H38.0012"
stroke="#E8B400"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
};
export default CardAmountIcon;

View File

@@ -0,0 +1,29 @@
interface NoteIconType {
className?: string;
onClick?: () => void;
}
const NoteIcon = ({ className, onClick }: NoteIconType) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
onClick={onClick}
>
<path
d="M12 16H12.008M12 8V13M3.23005 7.913L7.91005 3.23C8.06005 3.08 8.26005 3 8.48005 3H15.53C15.74 3 15.95 3.08 16.1 3.23L20.77 7.903C20.92 8.053 21 8.253 21 8.473V15.527C21 15.737 20.92 15.947 20.77 16.097L16.1 20.77C15.95 20.92 15.75 21 15.53 21H8.47005C8.36456 21.0011 8.2599 20.9814 8.16208 20.9419C8.06425 20.9025 7.9752 20.844 7.90005 20.77L3.23005 16.097C3.15602 16.0218 3.09759 15.9328 3.05812 15.835C3.01865 15.7371 2.99891 15.6325 3.00005 15.527V8.473C3.00005 8.263 3.08005 8.053 3.23005 7.903V7.913Z"
stroke="#3D3B4A"
stroke-width="1.5"
stroke-miterlimit="10"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
};
export default NoteIcon;

View File

@@ -14,7 +14,7 @@ const ScheduleOrderIcon = ({ className, onClick }: ScheduleOrderIconType) => {
className={className}
onClick={onClick}
>
<g clip-path="url(#clip0_1498_49735)">
<g clipPath="url(#clip0_1498_49735)">
<path
d="M4.96953 0.0218744C4.91016 0.0281248 4.71953 0.0625 4.54766 0.0968752C2.56328 0.490624 0.925781 1.9375 0.282031 3.86562C0.0507812 4.5625 0.0195312 4.7875 0.0195312 5.67188C0.0195312 6.55625 0.0507812 6.78125 0.282031 7.47188C1.01016 9.65937 3.01016 11.2125 5.26328 11.3406C5.62891 11.3625 6.28516 11.3344 6.41016 11.2969C6.46641 11.2781 6.46953 11.3 6.46953 12.1469C6.46953 12.8 6.47891 13.0312 6.51016 13.0656C6.52891 13.0938 7.57578 13.7625 8.83203 14.5562C10.6133 15.6813 11.1414 16 11.2195 16C11.2914 16 11.9695 15.6562 13.5727 14.8094C14.8133 14.1531 15.8633 13.5844 15.907 13.5406L15.9852 13.4688L15.9945 11.2219L16.0008 8.975L15.932 8.89375C15.8758 8.82812 13.1227 7.30625 11.6039 6.49687C11.3789 6.37813 11.2883 6.31563 11.2977 6.28125C11.3352 6.14375 11.3477 5.50313 11.3164 5.1875C11.2414 4.43125 11.0664 3.8125 10.7539 3.17188C9.92266 1.48125 8.34766 0.328125 6.47578 0.046875C6.19453 0.00312519 5.26328 -0.00937462 4.96953 0.0218744ZM6.29141 0.546875C8.26016 0.80625 9.92266 2.16875 10.5445 4.03438C10.757 4.66875 10.7977 4.93437 10.7945 5.6875C10.7914 6.05625 10.7789 6.4 10.7602 6.45C10.7289 6.55 10.7477 6.54062 8.06328 7.95937C7.26328 8.38125 6.57891 8.75625 6.54141 8.79063C6.46953 8.85313 6.46953 8.85938 6.46953 9.8125V10.7719L6.22891 10.7937C5.82266 10.8281 5.25703 10.8156 4.91953 10.7656C2.21641 10.3625 0.253906 7.86562 0.528906 5.17812C0.657031 3.95625 1.16016 2.89687 2.02891 2.03125C2.24766 1.81563 2.54766 1.55312 2.69766 1.44687C3.27578 1.04062 4.02266 0.724999 4.70703 0.596875C5.27578 0.490624 5.74766 0.474999 6.29141 0.546875ZM13.2883 8.01562L15.1852 9.04375L14.6695 9.32188L14.157 9.6L12.2258 8.54375C11.1664 7.9625 10.2727 7.47188 10.2414 7.45C10.1914 7.41875 10.2508 7.37813 10.6945 7.14687L11.2039 6.87813L11.2977 6.93437C11.3508 6.9625 12.2445 7.45 13.2883 8.01562ZM11.7664 8.85625L13.8914 10.0219L13.9008 10.6156L13.907 11.2062L13.6258 11.3844L13.3445 11.5594V10.9906C13.3445 10.5437 13.3352 10.4062 13.3008 10.3562C13.2758 10.3187 12.3195 9.78125 11.1758 9.15625C10.0289 8.53125 9.09453 8.00938 9.09453 8C9.09453 7.98125 9.59453 7.69063 9.62578 7.69063C9.63516 7.69063 10.5977 8.2125 11.7664 8.85625ZM10.5477 9.41875L12.5352 10.4938L12.3383 10.6031C11.5164 11.0531 11.2414 11.1906 11.1945 11.1719C11.0164 11.1062 7.29141 8.97813 7.31328 8.95625C7.36953 8.9 8.48828 8.31875 8.52266 8.32812C8.54453 8.33437 9.45391 8.825 10.5477 9.41875ZM9.33516 10.7406L10.9352 11.6406L10.9383 13.4625V15.2875L10.8477 15.2281C10.7977 15.1969 9.90703 14.6313 8.86328 13.9688L6.97266 12.7656L6.96953 11.0875V9.40937L7.35391 9.625C7.56328 9.74375 8.45391 10.2469 9.33516 10.7406ZM15.4383 11.3531V13.2062L15.2289 13.3187C15.1102 13.3812 14.307 13.8062 13.4383 14.2656C12.5695 14.725 11.7727 15.15 11.6664 15.2094L11.4695 15.3156V13.4937V11.6719L12.1352 11.3094L12.7977 10.9437L12.8133 11.5344C12.8289 12.0875 12.832 12.1281 12.8977 12.1906C12.9383 12.2313 13.0039 12.2594 13.057 12.2594C13.1539 12.2594 14.2727 11.6625 14.3508 11.5719C14.382 11.5344 14.3945 11.3312 14.407 10.7844L14.4227 10.0469L14.9227 9.775C15.1977 9.625 15.4258 9.5 15.432 9.5C15.4352 9.5 15.4383 10.3344 15.4383 11.3531Z"
fill="#434E5C"

View File

@@ -0,0 +1,33 @@
interface SuccessIconType {
className?: string;
onClick?: () => void;
}
const SuccessIcon = ({ className, onClick }: SuccessIconType) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
onClick={onClick}
>
<path
d="M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"
stroke="#32AD6D"
strokeWidth="1.5"
/>
<path
d="M8.5 12.5L10.5 14.5L15.5 9.5"
stroke="#32AD6D"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
};
export default SuccessIcon;

View File

@@ -0,0 +1,26 @@
interface NewRateIconType {
className?: string;
onClick?: () => void;
}
const NewRateIcon = ({ className, onClick }: NewRateIconType) => {
return (
<svg
width="28"
height="28"
viewBox="0 0 28 28"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className={className}
onClick={onClick}
>
<circle cx="14" cy="14" r="13.5" fill="black" />
<path
d="M19.2216 16.509C19.2946 16.436 19.3814 16.3995 19.4819 16.3995C19.5824 16.3995 19.6691 16.436 19.7421 16.509L20.9376 17.709C21.0106 17.782 21.0471 17.8705 21.0471 17.9745C21.0471 18.0785 21.0106 18.167 20.9376 18.24C20.8646 18.313 20.7761 18.3495 20.6721 18.3495C20.5681 18.3495 20.4796 18.313 20.4066 18.24L19.2066 17.0438C19.1336 16.9707 19.0996 16.8817 19.1046 16.7767C19.1096 16.6718 19.1491 16.5825 19.2216 16.509ZM19.7406 7.79775C19.8136 7.87075 19.8501 7.95975 19.8501 8.06475C19.8501 8.16975 19.8136 8.259 19.7406 8.3325L18.5444 9.528C18.4714 9.601 18.3846 9.6375 18.2841 9.6375C18.1836 9.6375 18.0969 9.601 18.0239 9.528C17.9509 9.455 17.9144 9.366 17.9144 9.261C17.9144 9.156 17.9509 9.06675 18.0239 8.99325L19.2096 7.79775C19.2826 7.72425 19.3711 7.6875 19.4751 7.6875C19.5791 7.6875 19.6676 7.72425 19.7406 7.79775ZM8.25963 7.812C8.33263 7.739 8.42188 7.7025 8.52737 7.7025C8.63238 7.7025 8.72162 7.739 8.79512 7.812L9.99062 8.997C10.0636 9.0705 10.1001 9.15925 10.1001 9.26325C10.1001 9.36675 10.0636 9.45525 9.99062 9.52875C9.91762 9.60175 9.82837 9.63825 9.72287 9.63825C9.61787 9.63825 9.52887 9.60175 9.45587 9.52875L8.25963 8.3325C8.18663 8.2595 8.15012 8.17275 8.15012 8.07225C8.15012 7.97175 8.18663 7.885 8.25963 7.812ZM8.77937 16.524C8.85237 16.597 8.88887 16.6838 8.88887 16.7843C8.88887 16.8847 8.85237 16.9715 8.77937 17.0445L7.58312 18.24C7.51012 18.313 7.42337 18.3495 7.32287 18.3495C7.22237 18.3495 7.13562 18.313 7.06262 18.24C6.98962 18.167 6.95312 18.0778 6.95312 17.9723C6.95312 17.8668 6.98962 17.7775 7.06262 17.7045L8.24762 16.509C8.32112 16.436 8.40987 16.4017 8.51387 16.4062C8.61737 16.4113 8.70587 16.451 8.77937 16.524ZM14.0001 17.4945L10.6139 19.527C10.5339 19.5665 10.4599 19.5825 10.3919 19.575C10.3234 19.567 10.2569 19.5435 10.1924 19.5045C10.1279 19.4645 10.0789 19.408 10.0454 19.335C10.0119 19.261 10.0089 19.1813 10.0364 19.0958L10.9341 15.2925L7.94687 12.7095C7.87937 12.6545 7.83737 12.5887 7.82087 12.5122C7.80387 12.4363 7.81087 12.363 7.84187 12.2925C7.87287 12.222 7.91412 12.1647 7.96562 12.1207C8.01712 12.0767 8.08713 12.047 8.17563 12.0315L12.1019 11.6985L13.6379 8.0865C13.6719 8.004 13.7209 7.9445 13.7849 7.908C13.8489 7.8715 13.9206 7.8535 14.0001 7.854C14.0796 7.8545 14.1516 7.87275 14.2161 7.90875C14.2806 7.94475 14.3294 8.00425 14.3624 8.08725L15.9126 11.6992L19.8389 12.0322C19.9274 12.0472 19.9974 12.0772 20.0489 12.1222C20.1009 12.1657 20.1424 12.2228 20.1734 12.2933C20.2044 12.3637 20.2114 12.437 20.1944 12.513C20.1774 12.5895 20.1351 12.6553 20.0676 12.7102L17.0811 15.2933L17.9781 19.1108C18.0061 19.1963 18.0031 19.2735 17.9691 19.3425C17.9351 19.4115 17.8861 19.4657 17.8221 19.5052C17.7576 19.5442 17.6914 19.5675 17.6234 19.575C17.5549 19.583 17.4806 19.5673 17.4006 19.5278L14.0001 17.4945Z"
fill="white"
/>
</svg>
);
};
export default NewRateIcon;

View File

@@ -14,7 +14,7 @@
}
.summaryDivider {
margin: 8px 0 !important;
margin: 0 !important;
}
.totalRow {

View File

@@ -111,7 +111,7 @@ export default function OrderSummary() {
/>
</div>
)}
<Divider className={styles.summaryDivider} style={{ margin: "0" }} />
<Divider className={styles.summaryDivider} />
<div className={`${styles.summaryRow} ${styles.totalRow}`}>
<ProText
style={{
@@ -142,13 +142,12 @@ export default function OrderSummary() {
{isHasLoyaltyGift && restaurant?.is_loyalty_enabled === 1 && (
<>
<br />
<br />
<Checkbox
checked={useLoyaltyPoints}
onChange={(value) => {
dispatch(updateUseLoyaltyPoints(value.target.checked));
}}
style={{ marginTop: 8 }}
>
{t("cart.useLoyaltyPoints")}
</Checkbox>

View File

@@ -12,7 +12,7 @@ export default function PaymentDetails({ order }: { order?: Order }) {
return (
<>
<Card className={`${styles.orderSummary}`}>
<ProTitle style={{ fontSize: 18 }}>{t("cart.orderSummary")}</ProTitle>
<ProTitle style={{ fontSize: 18 }}>{t("cart.paymentSummary")}</ProTitle>
<Divider style={{ margin: "15px 0 15px 0" }} />
<Space orientation="vertical" style={{ width: "100%" }}>
<div className={`${styles.summaryRow} ${styles.totalRow}`}>

View File

@@ -26,6 +26,7 @@ export interface OfficeDetailsType {
}
export interface GiftDetailsType {
amount: number;
receiverName: string;
receiverPhone: string;
message: string;
@@ -33,7 +34,8 @@ export interface GiftDetailsType {
senderPhone: string;
senderEmail: string;
isSecret: boolean;
cardId: string;
cardId: number;
giftType: "items" | "vouchers" | "itemsAndVouchers";
}
interface DiscountData {
@@ -69,6 +71,7 @@ interface CartState {
pickupDate: string;
pickupTime: string;
pickupType: string;
estimateWay: string;
order: any;
splitBillAmount: number;
customerName: string;
@@ -76,7 +79,6 @@ interface CartState {
hiddenServices: number;
visibleServices: number;
fee: number;
giftType: string;
}
// localStorage keys
@@ -110,7 +112,7 @@ export const CART_STORAGE_KEYS = {
TOTAL_SERVICES: "fascano_total_services",
HIDDEN_SERVICES: "fascano_hidden_services",
VISIBLE_SERVICES: "fascano_visible_services",
GIFT_TYPE: "fascano_gift_type",
ESTIMATE_WAY: "fascano_estimate_way",
} as const;
// Utility functions for localStorage
@@ -196,6 +198,7 @@ const initialState: CartState = {
pickupDate: getFromLocalStorage(CART_STORAGE_KEYS.PICKUP_DATE, ""),
pickupTime: getFromLocalStorage(CART_STORAGE_KEYS.PICKUP_TIME, ""),
pickupType: getFromLocalStorage(CART_STORAGE_KEYS.PICKUP_TYPE, ""),
estimateWay: getFromLocalStorage(CART_STORAGE_KEYS.ESTIMATE_WAY, "now"),
order: getFromLocalStorage(CART_STORAGE_KEYS.ORDER, null),
splitBillAmount: 0,
customerName: "",
@@ -203,7 +206,6 @@ const initialState: CartState = {
hiddenServices: 0,
visibleServices: 0,
fee: 0,
giftType: getFromLocalStorage(CART_STORAGE_KEYS.GIFT_TYPE, ""),
};
const orderSlice = createSlice({
@@ -676,6 +678,12 @@ const orderSlice = createSlice({
);
}
},
updateEstimateWay(state, action: PayloadAction<string>) {
state.estimateWay = action.payload;
if (typeof window !== "undefined") {
localStorage.setItem(CART_STORAGE_KEYS.ESTIMATE_WAY, JSON.stringify(state.estimateWay));
}
},
updateOrder(state, action: PayloadAction<any>) {
state.order = action.payload;
if (typeof window !== "undefined") {
@@ -691,9 +699,6 @@ const orderSlice = createSlice({
updateCustomerName(state, action: PayloadAction<string>) {
state.customerName = action.payload;
},
updateGiftType(state, action: PayloadAction<string>) {
state.giftType = action.payload;
},
},
});
@@ -730,10 +735,10 @@ export const {
updatePickupDate,
updatePickupTime,
updatePickUpType,
updateEstimateWay,
updateOrder,
updateSplitBillAmount,
updateCustomerName,
updateGiftType,
} = orderSlice.actions;
// Tax calculation helper functions

View File

@@ -15,6 +15,7 @@ import SenderformationCard from "./components/SenderformationCard/Senderformatio
import TimeEstimateCard from "pages/cart/components/timeEstimate/TimeEstimateCard";
import { useNavigate, useParams } from "react-router-dom";
import GiftAmountCard from "./components/GiftAmountCard/GiftAmountCard";
import { GiftAmountBottomSheet } from "./components/GiftAmountBottomSheet";
export default function CardDetailsPage() {
const { t } = useTranslation();
@@ -22,6 +23,7 @@ export default function CardDetailsPage() {
const { giftDetails } = useAppSelector(selectCart);
const { isRTL } = useAppSelector((state) => state.locale);
const [currentIndex, setCurrentIndex] = useState(0);
const [isGiftAmountBottomSheetOpen, setIsGiftAmountBottomSheetOpen] = useState(false);
const { subdomain } = useParams();
const navigate = useNavigate();
@@ -29,7 +31,7 @@ export default function CardDetailsPage() {
useEffect(() => {
if (cards && giftDetails?.cardId) {
const index = cards.findIndex(
(card) => card.id.toString() === giftDetails.cardId,
(card) => card?.id?.toString() === giftDetails.cardId,
);
if (index !== -1) {
setCurrentIndex(index);
@@ -55,8 +57,8 @@ export default function CardDetailsPage() {
navigate(`/${subdomain}/checkout`);
}, [subdomain]);
return (
<>
<Layout>
<ProHeader>{t("cardDetails.title")}</ProHeader>
<Layout.Content className={styles.checkoutContainer}>
@@ -132,7 +134,7 @@ export default function CardDetailsPage() {
layout="vertical"
style={{ display: "flex", flexDirection: "column", gap: 16 }}
>
<GiftAmountCard />
{giftDetails?.giftType !== "items" && <GiftAmountCard onOpen={() => setIsGiftAmountBottomSheetOpen(true)} />}
<ReceivernformationCard />
<SenderformationCard />
<TimeEstimateCard />
@@ -149,5 +151,7 @@ export default function CardDetailsPage() {
</Button>
</Layout.Footer>
</Layout>
<GiftAmountBottomSheet isOpen={isGiftAmountBottomSheetOpen} onClose={() => setIsGiftAmountBottomSheetOpen(false)} />
</>
);
}

View File

@@ -0,0 +1,109 @@
import { Button, Form } from "antd";
import { ProBottomSheet } from "components/ProBottomSheet/ProBottomSheet.tsx";
import { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import {
selectCart,
selectGrandTotal,
updateGiftDetails,
updateSplitBillAmount,
} from "features/order/orderSlice";
import { useAppDispatch, useAppSelector } from "redux/hooks";
import ProText from "components/ProText";
import { ProInputNumber } from "components/Inputs/ProInputNumber";
interface SplitBillChoiceBottomSheetProps {
isOpen: boolean;
onClose: () => void;
}
export function GiftAmountBottomSheet({
isOpen,
onClose,
}: SplitBillChoiceBottomSheetProps) {
const { t } = useTranslation();
const dispatch = useAppDispatch();
const { giftDetails, } = useAppSelector(selectCart);
const [amount, setAmount] = useState<string>(
giftDetails?.amount && giftDetails?.amount > 0 ? giftDetails?.amount?.toString() : "",
);
const handleSave = () => {
const numAmount = parseFloat(amount) || 0;
dispatch(updateGiftDetails({amount: numAmount}));
onClose();
};
return (
<ProBottomSheet
isOpen={isOpen}
onClose={onClose}
title={t("cardDetails.customAmount")}
showCloseButton={true}
initialSnap={1}
height={295}
snapPoints={[295]}
contentStyle={{
padding: 0,
}}
>
<div
style={{
padding: "20px",
display: "flex",
flexDirection: "column",
gap: 20,
}}
>
<div style={{ display: "flex", flexDirection: "column", gap: 5 }}>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 16,
lineHeight: "140%",
letterSpacing: "0%",
color:"#333333"
}}
>
{t("cardDetails.enterCustomOucherAmount")}
</ProText>
<Form.Item name="amount">
<ProInputNumber
value={amount}
onChange={(value) => {
setAmount(value?.toString() || "");
dispatch(updateSplitBillAmount(Number(value) || 0));
}}
placeholder={t("cardDetails.amount")}
min={0}
/>
</Form.Item>
</div>
</div>
<div
style={{
display: "flex",
gap: 12,
margin: 20,
}}
>
<Button
type="primary"
style={{
flex: 1,
boxShadow: "none",
height: 48,
}}
onClick={handleSave}
disabled={!amount || parseFloat(amount) <= 0}
>
{t("cardDetails.add")}
</Button>
</div>
</ProBottomSheet>
);
}

View File

@@ -6,11 +6,11 @@ import ArabicPrice from "components/ArabicPrice";
import ProText from "components/ProText";
import EditIcon from "components/Icons/EditIcon";
export default function GiftAmountCard() {
export default function GiftAmountCard({ onOpen }: { onOpen: () => void }) {
const { t } = useTranslation();
return (
<ProInputCard title={t("cardDetails.eGiftCardAmount")}>
<ProInputCard title={t("cardDetails.eCardAmount")}>
<div className={styles.customerInformationCard}>
<Button
style={{
@@ -87,6 +87,7 @@ export default function GiftAmountCard() {
}}
icon={<EditIcon className={styles.editIcon} color="#FFF" />}
iconPlacement="start"
onClick={onOpen}
>
<ProText
style={{

View File

@@ -5,7 +5,6 @@ import { useTranslation } from "react-i18next";
import { useAppDispatch, useAppSelector } from "redux/hooks";
import { Checkbox, Form, Input } from "antd";
import styles from "./SenderformationCard.module.css";
import TextArea from "antd/es/input/TextArea";
import ProText from "components/ProText";
export default function SenderformationCard() {
@@ -14,9 +13,9 @@ export default function SenderformationCard() {
const { giftDetails } = useAppSelector(selectCart);
return (
<ProInputCard title={t("cardDetails.receiverInformation")}>
<ProInputCard title={t("cardDetails.yourInformation")}>
<div className={styles.customerInformationCard}>
<Form.Item name="receiverName">
<Form.Item name="senderName">
<Input
placeholder={t("cardDetails.yourName")}
size="large"
@@ -29,7 +28,7 @@ export default function SenderformationCard() {
/>
</Form.Item>
<ProPhoneInput
propName="yourPhone"
propName="senderPhone"
value={giftDetails?.senderPhone}
onChange={(e) => {
dispatch(updateGiftDetails({ senderPhone: e }));

View File

@@ -2,17 +2,16 @@ 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";
import { useAppDispatch } 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")}>
<Form.Item name="plateNumber">
<Form.Item name="plateCar">
<Input
placeholder={t("cart.plateNumber")}
size="large"
@@ -27,7 +26,6 @@ export default function CarPlateCard() {
lineHeight: "140%",
letterSpacing: 0,
}}
value={plateCar}
onChange={(e) => {
dispatch(updatePlateCar(e.target.value));
}}

View File

@@ -18,7 +18,6 @@ import CarPlateCard from "pages/cart/components/CarPlateCard.tsx";
import CartFooter from "pages/cart/components/cartFooter/CartFooter.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";

View File

@@ -4,6 +4,8 @@ import ProInputCard from "components/ProInputCard/ProInputCard.tsx";
import ProRatioGroups from "components/ProRatioGroups/ProRatioGroups.tsx";
import dayjs from "dayjs";
import {
selectCart,
updateEstimateWay,
updatePickupDate,
updatePickupTime,
updatePickUpType,
@@ -11,9 +13,9 @@ import {
import useBreakPoint from "hooks/useBreakPoint.ts";
import { BottomSheet } from "pages/cart/components/timeEstimate/BottomSheet.tsx";
import { Dialog } from "pages/cart/components/timeEstimate/Dialog.tsx";
import { useState } from "react";
import { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { useAppDispatch } from "redux/hooks";
import { useAppDispatch, useAppSelector } from "redux/hooks";
import { SERVER_DATE_FORMAT, UI_TIME_FORMAT } from "utils/constants.ts";
export default function TimeEstimateCard() {
@@ -21,7 +23,7 @@ export default function TimeEstimateCard() {
const { t } = useTranslation();
const form = useFormInstance();
const { isDesktop } = useBreakPoint();
const [estimateWay, setEstimateWay] = useState("now");
const { estimateWay } = useAppSelector(selectCart);
const [isEstimateTimeOpen, setIsEstimateTimeOpen] = useState(false);
const handleEstimateTimeSave = (date: string, time: string) => {
@@ -34,6 +36,11 @@ export default function TimeEstimateCard() {
setIsEstimateTimeOpen(false);
};
useEffect(() => {
form.setFieldsValue({ estimateWay });
}, [estimateWay]);
return (
<>
<ProInputCard title={t("cart.estimateTime")}>
@@ -52,16 +59,16 @@ export default function TimeEstimateCard() {
value={estimateWay}
onRatioClick={(value) => {
if (value === "now") {
setEstimateWay(value);
dispatch(updateEstimateWay(value));
handleEstimateTimeSave(
dayjs().format(SERVER_DATE_FORMAT),
dayjs().format(UI_TIME_FORMAT),
);
dispatch(updatePickUpType("now"));
} else {
setEstimateWay(value);
setIsEstimateTimeOpen(true);
dispatch(updateEstimateWay(value));
dispatch(updatePickUpType(""));
setIsEstimateTimeOpen(true);
}
}}
/>

View File

@@ -10,11 +10,11 @@ import { useAppSelector } from "redux/hooks";
export default function CartPage() {
const { isDesktop } = useBreakPoint();
const [form] = Form.useForm();
const { specialRequest, coupon } = useAppSelector(selectCart);
const { specialRequest, plateCar } = useAppSelector(selectCart);
useEffect(() => {
form.setFieldsValue({ specialRequest, coupon });
}, [form, specialRequest, coupon]);
form.setFieldsValue({ specialRequest, plateCar });
}, [form, specialRequest, plateCar]);
// Prevent keyboard from appearing automatically on mobile
useEffect(() => {

View File

@@ -31,7 +31,7 @@ export default function BriefMenuCard() {
return (
<>
<ProInputCard
title={t("checkout.itemsSummary")}
title={t("checkout.orderSummary")}
dividerStyle={{ margin: "5px 0 0 0" }}
>
<div

View File

@@ -1,115 +1,181 @@
import { Checkbox, Form, Input } from "antd";
import { Divider, Image } from "antd";
import ProInputCard from "components/ProInputCard/ProInputCard";
import ProPhoneInput from "components/ProPhoneInput";
import ProText from "components/ProText";
import {
selectCart,
updateGiftDetails,
updateOrder,
} from "features/order/orderSlice";
import { selectCart } from "features/order/orderSlice";
import { EGiftCard } from "pages/CardDetails/type";
import { useTranslation } from "react-i18next";
import { useAppDispatch, useAppSelector } from "redux/hooks";
const { TextArea } = Input;
import { useGetEGiftCardsQuery } from "redux/api/others";
import { useAppSelector } from "redux/hooks";
import styles from "./GiftDetails.module.css";
import { useNavigate, useParams } from "react-router-dom";
import InvoiceIcon from "components/Icons/order/InvoiceIcon";
import BackIcon from "components/Icons/BackIcon";
import NextIcon from "components/Icons/NextIcon";
import { useMemo } from "react";
import CardAmountIcon from "components/Icons/CardAmountIcon";
import ArabicPrice from "components/ArabicPrice";
export function GiftCard() {
const { t } = useTranslation();
const { order } = useAppSelector(selectCart);
const dispatch = useAppDispatch();
const { giftDetails, items } = useAppSelector(selectCart);
const { data: cards } = useGetEGiftCardsQuery();
const currentCard = cards?.find(
(card: EGiftCard) => card.id == giftDetails?.cardId,
);
const navigate = useNavigate();
const { subdomain } = useParams();
const { isRTL } = useAppSelector((state) => state.locale);
const totalItems = useMemo(() => {
return items.length || 0;
}, [items]);
return (
<>
<ProInputCard title={t("address.giftDetails")}>
<ProPhoneInput
propName="receiverPhone"
label={t("address.receiverPhone")}
value={order?.receiverPhone}
onChange={(e) => {
dispatch(updateGiftDetails({ receiverPhone: e }));
}}
/>
<div className={styles.orderNotes}>
<Image src={currentCard?.imageURL} height={42} width={64} style={{height: 42, width: 64}} />
<div style={{ display: "flex", flexDirection: "column", gap: 4, width: "100%" }}>
<ProText
style={{
fontWeight: 500,
fontStyle: "Medium",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
color: "#333333",
}}
>
{t("checkout.giftSummary")}
</ProText>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 12,
lineHeight: "140%",
letterSpacing: "0%",
color: "#5F6C7B",
}}
>
{t("checkout.holdayGiftCard")} - {t("checkout.messageIncluded")}
</ProText>
<div style={{ display: "flex", flexDirection: "row", gap: 4 }}>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 12,
lineHeight: "140%",
letterSpacing: "0%",
color: "#040F35",
}}
>
{t("checkout.to")} :
</ProText>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 12,
lineHeight: "140%",
letterSpacing: "0%",
color: "#5F6C7B",
}}
>
{giftDetails?.receiverName}
</ProText>
</div>
</div>
{isRTL ? <BackIcon iconSize={24} /> : <NextIcon iconSize={24} />}
</div>
<Divider style={{ margin: "10px 0" }} />
<Form.Item name="message" label={t("address.message")}>
<TextArea
placeholder={t("address.message")}
size="large"
{giftDetails?.giftType === "items" && (
<div
style={{
fontSize: 14,
borderRadius: 10,
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
}}
rows={2}
autoFocus={false}
value={order?.message}
onChange={(e) => {
dispatch(updateGiftDetails({ message: 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?.senderName}
onChange={(e) => {
dispatch(updateGiftDetails({ senderName: e.target.value }));
}}
/>
</Form.Item>
<ProPhoneInput
propName="senderPhone"
label={t("address.senderPhone")}
value={order?.senderPhone}
onChange={(e) => {
dispatch(updateGiftDetails({ senderPhone: e }));
}}
/>
<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(updateGiftDetails({ senderEmail: e.target.value }));
}}
/>
</Form.Item>
<Form.Item name="isSecret" colon={false}>
<Checkbox
style={{
fontSize: 14,
}}
autoFocus={false}
checked={order?.isSecret}
onChange={(e) => {
dispatch(updateGiftDetails({ isSecret: e.target.checked }));
onClick={() => {
navigate(`/${subdomain}/cart`);
}}
>
<ProText>{t("address.keepMyNameSecret")}</ProText>
</Checkbox>
</Form.Item>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 12,
lineHeight: "140%",
letterSpacing: "0%",
color: "#777580",
cursor: "pointer",
}}
>
<span
style={{
[isRTL ? "marginLeft" : "marginRight"]: 5,
position: "relative",
top: 3.5,
}}
>
<InvoiceIcon />
</span>
{t("checkout.viewOrder")} ( {totalItems} {t("cart.items")} )
</ProText>
{isRTL ? <BackIcon /> : <NextIcon />}
</div>
)}
{giftDetails?.giftType === "vouchers" && (
<div className={styles.orderNotes}>
<div
style={{
height: 42,
width: 64,
backgroundColor: "var(--background)",
borderRadius: 8,
}}
>
<CardAmountIcon />
</div>
<div
style={{
display: "flex",
flexDirection: "column",
gap: 4,
width: "100%",
}}
>
<ProText
style={{
fontWeight: 500,
fontStyle: "Medium",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
color: "#777580",
}}
>
{t("checkout.giftSummary")}
</ProText>
<ProText
style={{
fontWeight: 500,
fontStyle: "Medium",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
color: "#333333",
}}
>
<ArabicPrice price={giftDetails?.amount || 0} />
</ProText>
</div>
{isRTL ? <BackIcon iconSize={24} /> : <NextIcon iconSize={24} />}
</div>
)}
</ProInputCard>
</>
);

View File

@@ -46,3 +46,13 @@
opacity: 0.15;
}
}
.orderNotes {
gap: 20px;
opacity: 1;
border-radius: 6px;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
}

View File

@@ -5,7 +5,7 @@ import PaymentMethods from "components/PaymentMethods/PaymentMethods";
import ProHeader from "components/ProHeader/ProHeader";
import { selectCart, updateCollectionMethod } from "features/order/orderSlice";
import { useTranslation } from "react-i18next";
import { useAppSelector } from "redux/hooks";
import { useAppDispatch, useAppSelector } from "redux/hooks";
import styles from "../address/address.module.css";
import { AddressSummary } from "./components/AddressSummary";
import CheckoutButton from "./components/CheckoutButton";
@@ -19,13 +19,18 @@ import BriefMenuCard from "./components/BriefMenuCard";
import CustomerInformationCard from "./components/CustomerInformationCard";
import Ads1 from "components/Ads/Ads1";
import TimeEstimateCard from "pages/cart/components/timeEstimate/TimeEstimateCard";
import { useEffect } from "react";
export default function CheckoutPage() {
const { t } = useTranslation();
const [form] = Form.useForm();
const { phone, order, orderType, collectionMethod } =
const { phone, order, orderType, collectionMethod, coupon } =
useAppSelector(selectCart);
const { token } = useAppSelector((state) => state.auth);
const dispatch = useAppDispatch();
useEffect(() => {
form.setFieldsValue({ coupon, collectionMethod });
}, [form, phone]);
return (
<>
@@ -41,7 +46,7 @@ export default function CheckoutPage() {
<Layout.Content className={styles.checkoutContainer}>
{(orderType === OrderType.Pickup ||
orderType === OrderType.ScheduledOrder) && <TimeEstimateCard />}
{orderType === OrderType.Gift && <GiftCard />}
<PaymentMethods />
{!token && <CustomerInformationCard />}
<AddressSummary />
@@ -61,7 +66,7 @@ export default function CheckoutPage() {
value={order?.officeNumber}
/>
)}
{orderType === OrderType.Gift && <GiftCard />}
{/* {orderType === OrderType.Gift && <GiftCard />} */}
{/* <RoomDetails />
<OfficeDetails /> */}
{/* <GiftDetails /> */}
@@ -93,9 +98,9 @@ export default function CheckoutPage() {
value={collectionMethod}
onRatioClick={(value) => {
if (value === "cod") {
updateCollectionMethod(value);
dispatch(updateCollectionMethod(value));
} else {
updateCollectionMethod(value);
dispatch(updateCollectionMethod(value));
}
}}
/>

View File

@@ -5,7 +5,6 @@ import LogoContainerIcon from "components/Icons/LogoContainerIcon";
import ImageWithFallback from "components/ImageWithFallback";
import LoyaltyCard from "components/LoyaltyCard/LoyaltyCard";
import ProText from "components/ProText";
import ProTitle from "components/ProTitle";
import { useScrollHandler } from "contexts/ScrollHandlerContext";
import useBreakPoint from "hooks/useBreakPoint";
import { useRestaurant } from "hooks/useRestaurant";

View File

@@ -15,7 +15,7 @@
}
}
.fascanoIcon {
.fascanoIcon {
position: relative;
top: 3px;
}
@@ -39,7 +39,7 @@
}
.orderCard :global(.ant-card-body) > *:not(:last-child) {
margin-bottom: 3.5rem;
margin-bottom: 0.5rem;
}
.orderSummary {
@@ -260,3 +260,91 @@
text-align: start;
width: 100%;
}
.rateServiceCard {
width: 100%;
height: 48px;
display: flex;
justify-content: center;
padding: 12px 18px !important;
row-gap: 10px;
transition: all 0.3s ease;
border-radius: 50px;
}
.rateServiceCard :global(.ant-card-body) {
padding: 0px !important;
text-align: start;
width: 100%;
}
.newRateIcon {
position: relative;
top: -3px;
}
.serviceIcon {
position: relative;
top: 2px;
}
.orderNotes {
height: 87px;
gap: 16px;
opacity: 1;
border-radius: 6px;
padding: 16px;
background-color: #f5f5f6;
display: flex;
flex-direction: row;
justify-content: flex-start;
}
.orderNotesClosed {
opacity: 1;
height: 40px;
gap: 16px;
border-radius: 6px;
padding: 8px 16px;
background-color: #edfef5;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.orderContent {
display: flex;
flex-direction: column;
padding: 16px;
gap: 16px;
overflow: auto;
scrollbar-width: none;
}
/* CheckoutButton Styles */
.checkoutButton{
width: 100%;
}
.checkoutButtonContainer {
width: 100%;
padding: 16px 16px 0;
position: sticky;
bottom: 0;
left: 0;
height: 80px;
display: flex;
flex-direction: row;
justify-content: space-around;
gap: 1rem;
background-color: var(--secondary-background);
box-shadow: none;
z-index: 999;
}
/* Dark theme styles for checkout */
:global(.darkApp) .checkoutButtonContainer {
background-color: #000000 !important;
}

View File

@@ -1,4 +1,13 @@
import { Button, Card, Divider, Flex, Image, Progress, Tooltip } from "antd";
import {
Button,
Card,
Divider,
Flex,
Image,
Layout,
Progress,
Tooltip,
} from "antd";
import Ads2 from "components/Ads/Ads2";
import { CancelOrderBottomSheet } from "components/CustomBottomSheet/CancelOrderBottomSheet";
import LocationIcon from "components/Icons/LocationIcon";
@@ -25,13 +34,16 @@ import NextIcon from "components/Icons/NextIcon";
import { RateBottomSheet } from "components/CustomBottomSheet/RateBottomSheet";
import BriefMenuCard from "pages/checkout/components/BriefMenuCard";
import { QRBottomSheet } from "pages/pay/components/splitBill/QRBottomSheet";
import NewRateIcon from "components/Icons/order/NewRateIcon";
import NoteIcon from "components/Icons/NoteIcon";
import SuccessIcon from "components/Icons/SuccessIcon";
export default function OrderPage() {
const { t } = useTranslation();
const { orderId } = useParams();
const navigate = useNavigate();
const { isRTL } = useAppSelector((state) => state.locale);
const { restaurant } = useAppSelector((state) => state.order);
const navigate = useNavigate();
const hasRefetchedRef = useRef(false);
const [isOpen, setIsOpen] = useState(false);
const [isRateOrderOpen, setIsRateOrderOpen] = useState(false);
@@ -57,6 +69,9 @@ export default function OrderPage() {
skip: !restaurantSubdomain,
},
);
const hasClosedStatus = orderDetails?.status?.some(
(status) => status?.alias === "closed",
);
// Reset refetch flag when orderId changes
useEffect(() => {
@@ -66,10 +81,6 @@ export default function OrderPage() {
// Refetch restaurant details when order status has alias "closed"
useEffect(() => {
if (orderDetails?.status && !hasRefetchedRef.current) {
const hasClosedStatus = orderDetails.status.some(
(status) => status?.alias === "closed",
);
if (hasClosedStatus && restaurantSubdomain) {
refetchRestaurantDetails();
hasRefetchedRef.current = true;
@@ -220,136 +231,182 @@ export default function OrderPage() {
return (
<>
<ProHeader customRoute={`/${restaurant?.subdomain}`}>{t("order.title")}</ProHeader>
<div
style={{
display: "flex",
flexDirection: "column",
height: "92vh",
padding: 16,
gap: 16,
overflow: "auto",
scrollbarWidth: "none",
}}
>
<Card className={styles.orderCard}>
<div
style={{
display: "flex",
flexDirection: "row",
gap: "1rem",
backgroundColor: "rgba(255, 183, 0, 0.08)",
borderRadius: "12px",
padding: 16,
}}
>
<Button
type="text"
shape="circle"
<Layout>
<ProHeader customRoute={`/${restaurant?.subdomain}`}>
{t("order.title")}
</ProHeader>
<Layout.Content className={styles.orderContent}>
<Card className={styles.orderCard}>
<div
style={{
display: "flex",
flexDirection: "row",
gap: "1rem",
backgroundColor: "rgba(255, 183, 0, 0.08)",
borderRadius: "12px",
padding: 16,
}}
>
<Image
src={orderDetails?.restaurant_iimage}
className={styles.profileImage}
width={50}
height={50}
preview={false}
/>
</Button>
<div>
<ProText style={{ fontSize: "1rem" }}>
{t("order.yourOrderFromFascanoRestaurant")}
</ProText>
<br />
<ProText type="secondary">
<LocationIcon className={styles.locationIcon} />{" "}
{isRTL ? orderDetails?.restaurantAR : orderDetails?.restaurant}
</ProText>
<Button
type="text"
shape="circle"
style={{
backgroundColor: "rgba(255, 183, 0, 0.08)",
}}
>
<Image
src={orderDetails?.restaurant_iimage}
className={styles.profileImage}
width={50}
height={50}
preview={false}
/>
</Button>
<div>
<ProText style={{ fontSize: "1rem" }}>
{t("order.yourOrderFromFascanoRestaurant")}
</ProText>
<br />
<ProText type="secondary">
<LocationIcon className={styles.locationIcon} />{" "}
{isRTL
? orderDetails?.restaurantAR
: orderDetails?.restaurant}
</ProText>
</div>
</div>
</div>
{isInProgress ? (
<Flex gap="small" wrap justify="center">
<Tooltip title="3 done / 3 in progress / 4 to do">
<div
style={{
transform: "scaleX(-1)",
}}
>
<Progress
percent={progressPercent}
format={() => (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
gap: 4,
transform: "scaleX(-1)",
}}
>
<ProText
{isInProgress ? (
<Flex gap="small" wrap justify="center">
<Tooltip title="3 done / 3 in progress / 4 to do">
<div
style={{
transform: "scaleX(-1)",
}}
>
<Progress
percent={progressPercent}
format={() => (
<div
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 18,
lineHeight: "140%",
letterSpacing: "0%",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
gap: 4,
transform: "scaleX(-1)",
}}
>
{t("order.remainingTime")}
</ProText>
{formatTimer(remainingSeconds)}
</div>
)}
strokeColor="#FFB700"
size={200}
type="dashboard"
/>
</div>
</Tooltip>
</Flex>
) : (
<OrderDishIcon className={styles.orderDishIcon} />
)}
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 18,
lineHeight: "140%",
letterSpacing: "0%",
}}
>
{t("order.remainingTime")}
</ProText>
{formatTimer(remainingSeconds)}
</div>
)}
strokeColor="#FFB700"
size={200}
type="dashboard"
/>
</div>
</Tooltip>
</Flex>
) : (
<OrderDishIcon className={styles.orderDishIcon} />
)}
<div>
<ProTitle
level={5}
style={{
fontWeight: 600,
fontSize: "18px",
marginBottom: "0.75rem",
}}
>
{t("order.inProgressOrder")} (1)
</ProTitle>
<div style={{ display: "flex", flexDirection: "row", gap: 8 }}>
<InvoiceIcon className={styles.invoiceIcon} />
<ProText type="secondary" style={{ fontSize: "14px" }}>
#{orderDetails?.order.id}
</ProText>
<TimeIcon className={styles.timeIcon} />
<ProText type="secondary" style={{ fontSize: "14px" }}>
ordered :- Today -{" "}
{dayjs(orderDetails?.status[0]?.pivot?.created_at).format(
"h:mm A",
)}
</ProText>
<div>
<ProTitle
level={5}
style={{
fontWeight: 600,
fontSize: "18px",
marginBottom: "0.75rem",
}}
>
{t("order.inProgressOrder")} (1)
</ProTitle>
<div style={{ display: "flex", flexDirection: "row", gap: 8 }}>
<InvoiceIcon className={styles.invoiceIcon} />
<ProText type="secondary" style={{ fontSize: "14px" }}>
#{orderDetails?.order.id}
</ProText>
<TimeIcon className={styles.timeIcon} />
<ProText type="secondary" style={{ fontSize: "14px" }}>
ordered :- Today -{" "}
{dayjs(orderDetails?.status[0]?.pivot?.created_at).format(
"h:mm A",
)}
</ProText>
</div>
<Divider style={{ margin: "12px 0" }} />
<Stepper statuses={orderDetails?.status} />
</div>
<Divider style={{ margin: "12px 0" }} />
{!hasClosedStatus && (
<div className={styles.orderNotes}>
<NoteIcon className={styles.noteIcon} />
<div
style={{ display: "flex", flexDirection: "column", gap: 4 }}
>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 12,
lineHeight: "140%",
letterSpacing: "0%",
color: "#777580",
}}
>
{t(
"order.aStaffMemberWillCollectTheCashFromYouAtYourTable",
)}
</ProText>
<ProText
style={{
fontWeight: 600,
fontStyle: "SemiBold",
fontSize: 12,
lineHeight: "140%",
letterSpacing: "0%",
color: "#3D3B4A",
}}
>
{t("order.callWaiter")}
</ProText>
</div>
</div>
)}
{hasClosedStatus && (
<div className={styles.orderNotesClosed}>
<SuccessIcon className={styles.noteIcon} />
<ProText
style={{
fontSize: "12px",
lineHeight: "140%",
letterSpacing: "0%",
color: "#3D3B4A",
}}
>
{t("order.cashPaymentConfirmed")}
</ProText>
</div>
)}
</Card>
<Stepper statuses={orderDetails?.status} />
</div>
</Card>
<Ads2 />
<Ads2 />
{/* <ProInputCard
{/* <ProInputCard
title={
<div style={{ marginBottom: 7 }}>
<ProText style={{ fontSize: "1rem" }}>
@@ -398,113 +455,98 @@ export default function OrderPage() {
</div>
</ProInputCard> */}
<BriefMenuCard />
<BriefMenuCard />
<PaymentDetails order={orderDetails?.order} />
<PaymentDetails order={orderDetails?.order} />
<Card
className={styles.backToHomePage}
onClick={() => navigate(`/${restaurant?.subdomain}`)}
>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
marginTop: 1,
}}
<Card
className={styles.inviteToBillCard}
onClick={() => setIsOpen(true)}
>
<Image
src={restaurant?.restautantImage}
width={30}
height={30}
preview={false}
<div
style={{
borderRadius: "50%",
objectFit: "cover",
position: "relative",
top: -4,
}}
/>
<ProTitle
level={5}
style={{
fontSize: 14,
display: "flex",
flexDirection: "row",
justifyContent: "center",
marginTop: 1,
}}
>
{isRTL ? restaurant?.nameAR : restaurant?.restautantName}
</ProTitle>
<div style={{ display: "flex", flexDirection: "row", gap: 10 }}>
<ProTitle
level={5}
style={{
marginTop: 1,
fontSize: 14,
}}
>
{t("order.inviteToBill")}
</ProTitle>
</div>
</div>
</Card>
{isRTL ? (
<BackIcon className={styles.serviceIcon} />
) : (
<NextIcon className={styles.serviceIcon} />
)}
</div>
</Card>
<QRBottomSheet isOpen={isOpen} onClose={() => setIsOpen(false)} />
<Card
className={styles.inviteToBillCard}
onClick={() => setIsOpen(true)}
>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "center",
marginTop: 1,
}}
>
<div style={{ display: "flex", flexDirection: "row", gap: 10 }}>
<ProTitle
level={5}
{hasClosedStatus && (
<Card
className={styles.backToHomePage}
onClick={() => setIsRateOrderOpen(true)}
>
<div
style={{
marginTop: 1,
fontSize: 14,
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
}}
>
{t("order.inviteToBill")}
</ProTitle>
</div>
</div>
</Card>
<div>
<NewRateIcon className={styles.newRateIcon} />
<ProText
style={{
fontWeight: 500,
fontStyle: "Medium",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
color: "#595764",
position: "relative",
margin: "0 8px",
top: -12,
}}
>
{t("order.rateOrder")}
</ProText>
</div>
<QRBottomSheet isOpen={isOpen} onClose={() => setIsOpen(false)} />
{isRTL ? (
<BackIcon className={styles.serviceIcon} />
) : (
<NextIcon className={styles.serviceIcon} />
)}
</div>
</Card>
)}
<Card
className={styles.rateServiceCard}
onClick={() => setIsRateOrderOpen(true)}
>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "center",
marginTop: 1,
<RateBottomSheet
isOpen={isRateOrderOpen}
onClose={() => setIsRateOrderOpen(false)}
/>
<CancelOrderBottomSheet />
</Layout.Content>
<Layout.Footer className={styles.checkoutButtonContainer}>
<Button
type="primary"
shape="round"
className={styles.checkoutButton}
onClick={() => {
navigate(`/${restaurant?.subdomain}/menu`);
}}
>
<div style={{ display: "flex", flexDirection: "row", gap: 10 }}>
<ProTitle
level={5}
style={{
marginTop: 1,
fontSize: 14,
}}
>
{t("order.rateOrder")}
</ProTitle>
</div>
</div>
</Card>
<RateBottomSheet
isOpen={isRateOrderOpen}
onClose={() => setIsRateOrderOpen(false)}
/>
<CancelOrderBottomSheet />
</div>
{t("order.newOrder")}
</Button>
</Layout.Footer>
</Layout>
</>
);
}