redeem: initial commit

This commit is contained in:
2026-01-08 23:26:45 +03:00
parent ebe9928091
commit 6271c14eff
26 changed files with 1577 additions and 491 deletions

View File

@@ -1,16 +1,7 @@
import { Button, Card, Divider, Image } from "antd";
import Ads2 from "components/Ads/Ads2";
import { CancelOrderBottomSheet } from "components/CustomBottomSheet/CancelOrderBottomSheet";
import LocationIcon from "components/Icons/LocationIcon";
import InvoiceIcon from "components/Icons/order/InvoiceIcon";
import TimeIcon from "components/Icons/order/TimeIcon";
import OrderDishIcon from "components/Icons/OrderDishIcon";
import PaymentDetails from "components/PaymentDetails/PaymentDetails";
import { Button, Card, Image, Layout, Skeleton } from "antd";
import ProHeader from "components/ProHeader/ProHeader";
import ProInputCard from "components/ProInputCard/ProInputCard";
import ProText from "components/ProText";
import ProTitle from "components/ProTitle";
import dayjs from "dayjs";
import { useEffect, useRef } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate, useParams } from "react-router-dom";
@@ -18,31 +9,30 @@ import {
useGetOrderDetailsQuery,
useGetRestaurantDetailsQuery,
} from "redux/api/others";
import { useAppSelector } from "redux/hooks";
import styles from "./redeem.module.css";
import BackIcon from "components/Icons/BackIcon";
import NextIcon from "components/Icons/NextIcon";
import { RateBottomSheet } from "components/CustomBottomSheet/RateBottomSheet";
import Stepper from "pages/order/components/Stepper";
import QRIcon from "components/Icons/QRIcon";
import CopyIcon from "components/Icons/CopyIcon";
import { useAppSelector } from "redux/hooks";
import { LocationCard } from "./components/LocationCard.tsx";
import { GiftItemsCard } from "./components/GiftItemsCard.tsx";
import { VoucherBalanceCard } from "./components/VoucherBalanceCard.tsx";
import { OrderType } from "pages/checkout/hooks/types.ts";
export default function RedeemPage() {
const { t } = useTranslation();
const { orderId } = useParams();
const { isRTL } = useAppSelector((state) => state.locale);
const { voucherId } = useParams();
const { restaurant } = useAppSelector((state) => state.order);
const navigate = useNavigate();
const hasRefetchedRef = useRef(false);
const navigate = useNavigate();
const { subdomain } = useParams();
const { data: orderDetails } = useGetOrderDetailsQuery(
const { data: orderDetails, isLoading } = useGetOrderDetailsQuery(
{
orderID: orderId || "",
orderID: voucherId || "",
restaurantID: localStorage.getItem("restaurantID") || "",
},
{
skip: !orderId,
// return it t0 60000 after finish testing
pollingInterval: 10000,
refetchOnMountOrArgChange: true,
skip: !voucherId,
},
);
@@ -58,7 +48,7 @@ export default function RedeemPage() {
// Reset refetch flag when orderId changes
useEffect(() => {
hasRefetchedRef.current = false;
}, [orderId]);
}, [voucherId]);
// Refetch restaurant details when order status has alias "closed"
useEffect(() => {
@@ -74,190 +64,225 @@ export default function RedeemPage() {
}
}, [orderDetails?.status, restaurantSubdomain, refetchRestaurantDetails]);
const handleCheckout = () => {
navigate(`/${subdomain}/menu?orderType=${OrderType.Redeem}`);
};
return (
<>
<ProHeader>{t("order.title")}</ProHeader>
<div
style={{
display: "flex",
flexDirection: "column",
height: "92vh",
padding: 16,
gap: 16,
overflow: "auto",
scrollbarWidth: "none",
}}
>
<Card className={styles.orderCard}>
<Layout>
<ProHeader>{t("redeem.title")}</ProHeader>
<Layout.Content className={styles.redeemContainer}>
<div
style={{
textAlign: "center",
display: "flex",
flexDirection: "row",
gap: "1rem",
backgroundColor: "rgba(255, 183, 0, 0.08)",
borderRadius: "12px",
padding: 16,
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
margin: "32px 28px 21px 28px",
gap: 8,
}}
>
<Button
type="text"
shape="circle"
style={{
backgroundColor: "rgba(255, 183, 0, 0.08)",
}}
<ProText
style={{ fontSize: 16, fontWeight: 600, color: "#333333" }}
>
<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>
{t("redeem.addGiftDetails")}
</ProText>
<ProText
style={{ fontSize: 14, fontWeight: 400, color: "#95949C" }}
>
{t("redeem.description")}
</ProText>
</div>
<OrderDishIcon className={styles.orderDishIcon} />
{isLoading || !orderDetails?.restaurant_iimage ? (
<div className={styles.carouselContainer}>
<div className={styles.cardWrapper}>
<Skeleton.Image
active
style={{
width: 205,
height: 134,
borderRadius: 8,
}}
/>
</div>
</div>
) : (
<div className={styles.carouselContainer}>
<div className={styles.cardWrapper}>
<Image
src={orderDetails?.restaurant_iimage}
width={205}
height={134}
className={styles.cardImage}
/>
</div>
</div>
)}
<div>
<ProTitle
level={5}
<div
style={{
textAlign: "center",
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
margin: "18px 28px 26px 28px",
gap: 12,
}}
>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
textAlign: "center",
color: "#95949C",
}}
>
{t("redeem.description")}
</ProText>
<ProText
style={{
fontWeight: 600,
fontSize: "18px",
marginBottom: "0.75rem",
fontStyle: "SemiBold",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
textAlign: "center",
color: "#333333",
}}
>
{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} />
{t("redeem.addGiftDetails")}
</ProText>
</div>
</Card>
<Ads2 />
<ProInputCard
title={
<div style={{ marginBottom: 7 }}>
<ProText style={{ fontSize: "1rem" }}>
{t("order.yourOrderFrom")}
</ProText>
<br />
<ProText type="secondary">
<LocationIcon className={styles.locationIcon} />{" "}
{t("order.muscat")}
</ProText>
</div>
}
>
<div
style={{ display: "flex", flexDirection: "column", gap: "1rem" }}
>
{orderDetails?.orderItems.map((item, index) => (
<div key={item.id}>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "flex-start",
gap: "1rem",
}}
>
<Button
type="text"
shape="circle"
style={{
backgroundColor: "rgba(255, 183, 0, 0.08)",
}}
>
{index + 1}X
</Button>
<div>
<ProText
style={{ fontSize: "1rem", position: "relative", top: 8 }}
>
{item.name}
</ProText>
</div>
</div>
</div>
))}
</div>
</ProInputCard>
<PaymentDetails order={orderDetails?.order} />
<Card
className={styles.backToHomePage}
onClick={() => navigate(`/${restaurant?.subdomain}`)}
>
<div
<Card
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
marginTop: 1,
borderRadius: 0,
borderTopRightRadius: 16,
borderTopLeftRadius: 16,
border: "1px solid transparent",
borderImageSource:
"radial-gradient(38.92% 103.83% at 49.85% -3.83%, #FFB700 0%, rgba(255, 233, 179, 0) 100%)",
borderImageSlice: 1,
}}
styles={{
body: {
display: "flex",
flexDirection: "column",
gap: 24,
alignItems: "center",
justifyContent: "center",
padding: 32,
},
}}
>
<Image
src={restaurant?.restautantImage}
width={30}
height={30}
preview={false}
style={{
borderRadius: "50%",
objectFit: "cover",
position: "relative",
top: -4,
}}
/>
<ProTitle
level={5}
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
color: "#95949C",
alignItems: "center",
}}
>
{isRTL ? restaurant?.nameAR : restaurant?.restautantName}
</ProTitle>
{t("redeem.showThisCodeAtTheRestaurant")}
</ProText>
<QRIcon />
<div style={{ display: "flex", flexDirection: "column", gap: 12 }}>
<Button
style={{
height: 40,
borderRadius: 888,
gap: 16,
opacity: 1,
borderWidth: 1,
backgroundColor: "var(--background)",
}}
icon={<CopyIcon className={styles.copyIcon} />}
iconPlacement="end"
>
GFT - 92KD - 7X84
</Button>
<ProText
style={{
fontWeight: 400,
fontStyle: "Regular",
fontSize: 14,
lineHeight: "140%",
letterSpacing: "0%",
color: "#95949C",
alignItems: "center",
}}
>
{t("redeem.useThisCodeIfScanningNotPossible")}
</ProText>
</div>
</Card>
{isRTL ? (
<BackIcon className={styles.serviceIcon} />
) : (
<NextIcon className={styles.serviceIcon} />
)}
<div
style={{
width: "100%",
height: 44,
opacity: 1,
borderBottomRightRadius: 16,
borderBottomLeftRadius: 16,
paddingTop: 12,
paddingBottom: 12,
gap: 10,
borderTopWidth: 1,
background: "#FFF9E6",
borderTop: "1px solid #FFEDB0",
textAlign: "center",
}}
>
<ProText
style={{
fontSize: 14,
fontWeight: 500,
fontStyle: "Medium",
lineHeight: "140%",
letterSpacing: "0%",
textAlign: "center",
color: "#E8B400",
}}
>
Active - Expires in 12 days
</ProText>
</div>
</Card>
{/* <RateBottomSheet /> */}
<div
style={{
margin: "20px 0",
display: "flex",
flexDirection: "column",
gap: 16,
}}
>
<GiftItemsCard />
<VoucherBalanceCard />
<LocationCard />
</div>
</Layout.Content>
<CancelOrderBottomSheet />
</div>
<Layout.Footer className={styles.checkoutButtonContainer}>
<Button
type="primary"
shape="round"
className={styles.checkoutButton}
onClick={handleCheckout}
>
{t("redeem.redeemNow")}
</Button>
</Layout.Footer>
</Layout>
</>
);
}