enhance otp desktop screen styles

This commit is contained in:
2025-11-29 21:46:50 +03:00
parent 48bbd9ae85
commit 961164f842
2 changed files with 156 additions and 53 deletions

View File

@@ -22,6 +22,25 @@
justify-content: center;
}
.restaurantCoverContainer {
display: none;
}
.restaurantCover {
width: 100%;
height: 100%;
object-fit: cover;
border-radius: 0;
}
.otpContentWrapper {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.otpContainer {
width: 100%;
max-width: 100%;
@@ -88,6 +107,68 @@
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}
/* Desktop devices (min-width: 1025px) */
@media (min-width: 1025px) {
.otpPage {
padding: 0;
align-items: stretch;
max-width: 100%;
margin: 0;
height: 100vh;
overflow: hidden;
}
.otpWrapper {
display: grid;
grid-template-columns: 1fr 1fr;
height: 100vh;
width: 100%;
max-width: 1920px;
margin: 0 auto;
}
.restaurantCoverContainer {
display: block;
width: 100%;
height: 100%;
overflow: hidden;
position: relative;
}
.restaurantCover {
width: 100%;
height: 100%;
object-fit: cover;
}
.otpContentWrapper {
background-color: var(--background);
padding: 60px 10vw;
border-radius: 0;
box-shadow: none;
display: flex;
flex-direction: column;
justify-content: center;
overflow-y: auto;
margin: 0 auto;
width: 100%;
height: 100vh;
}
.otpContainer {
max-width: 100%;
width: 100%;
}
}
:global(.ant-app-rtl) .otpWrapper {
direction: rtl;
}
:global(.ant-app-rtl) .otpWrapper {
grid-template-columns: 1fr 1fr;
}
.productContainer :global(.ant-radio-wrapper:last-child) {
width: 100% !important;
}

View File

@@ -1,18 +1,21 @@
import { Button, Layout, Space, message } from "antd";
import ImageWithFallback from "components/ImageWithFallback";
import OtpIcon from "components/Icons/otpIcon.tsx";
import OtpInput from "components/OtpInput/OtpInput";
import ProHeader from "components/ProHeader/ProHeader";
import ProText from "components/ProText";
import ProTitle from "components/ProTitle";
import { loginSuccess } from "features/auth/authSlice";
import useBreakPoint from "hooks/useBreakPoint";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate, useParams } from "react-router-dom";
import { useConfirmOtpMutation, useSendOtpMutation } from "redux/api/auth";
import { useGetRestaurantDetailsQuery } from "redux/api/others";
import { useAppDispatch } from "redux/hooks";
import { ProGray1 } from "ThemeConstants";
import { default_image } from "utils/constants";
import styles from "./otp.module.css";
import ProHeader from "components/ProHeader/ProHeader";
import useBreakPoint from "hooks/useBreakPoint";
export default function OtpPage() {
const { subdomain } = useParams();
@@ -22,6 +25,9 @@ export default function OtpPage() {
const [confirmOtp, { isLoading: isConfirmLoading }] = useConfirmOtpMutation();
const [otp, setOtp] = useState<string>("");
const { isTablet } = useBreakPoint();
const { data: restaurant } = useGetRestaurantDetailsQuery(subdomain, {
skip: !subdomain,
});
const handleOtpSave = (otp: string) => {
try {
setOtp(otp);
@@ -35,58 +41,74 @@ export default function OtpPage() {
<Layout className={styles.otpPage}>
{isTablet ? <ProHeader>{t("otp.verification")}</ProHeader> : null}
<Layout.Content className={styles.otpWrapper}>
<div className={styles.otpContainer}>
<OtpIcon />
<div className={styles.otpContent}>
<ProTitle level={4} className={styles.otpTitle}>
{t("otp.verification")}
</ProTitle>
<ProText style={{ color: ProGray1 }}>
{t("otp.enterThe4DigitCodeThatSentToYourPhoneNumber")}
</ProText>
<br />
<ProText style={{ color: ProGray1 }}>
{localStorage.getItem("otp")}
</ProText>
</div>
<div className={styles.otpInputContainer}>
<Space size="small">
<OtpInput
length={5}
onComplete={handleOtpSave}
resendOtp={() =>
sendOtp({
phone: localStorage.getItem("userPhone") || "",
})
}
isLoading={isLoading || isConfirmLoading}
/>
</Space>
</div>
<Button
type="primary"
shape="round"
className={styles.otpButton}
disabled={!otp || otp.length < 5 || isConfirmLoading}
onClick={() => {
confirmOtp({
otp: otp,
phone: localStorage.getItem("userPhone"),
})
.unwrap()
.then((response) => {
dispatch(loginSuccess(response));
message.info(t("otp.confirmOTPSuccess"));
navigate(`/${subdomain}/menu`);
});
}}
>
{t("otp.continue")}
</Button>
<div className={styles.otpWrapper}>
{/* Restaurant Cover Image - Desktop Only */}
<div className={styles.restaurantCoverContainer}>
<ImageWithFallback
src={restaurant?.restaurant_cover}
fallbackSrc={default_image}
alt={t("otp.restaurantCover")}
className={styles.restaurantCover}
width="100%"
height="100%"
preview={false}
/>
</div>
</Layout.Content>
{/* OTP Form Container */}
<Layout.Content className={styles.otpContentWrapper}>
<div className={styles.otpContainer}>
<OtpIcon />
<div className={styles.otpContent}>
<ProTitle level={4} className={styles.otpTitle}>
{t("otp.verification")}
</ProTitle>
<ProText style={{ color: ProGray1 }}>
{t("otp.enterThe4DigitCodeThatSentToYourPhoneNumber")}
</ProText>
<br />
<ProText style={{ color: ProGray1 }}>
{localStorage.getItem("otp")}
</ProText>
</div>
<div className={styles.otpInputContainer}>
<Space size="small">
<OtpInput
length={5}
onComplete={handleOtpSave}
resendOtp={() =>
sendOtp({
phone: localStorage.getItem("userPhone") || "",
})
}
isLoading={isLoading || isConfirmLoading}
/>
</Space>
</div>
<Button
type="primary"
shape="round"
className={styles.otpButton}
disabled={!otp || otp.length < 5 || isConfirmLoading}
onClick={() => {
confirmOtp({
otp: otp,
phone: localStorage.getItem("userPhone"),
})
.unwrap()
.then((response) => {
dispatch(loginSuccess(response));
message.info(t("otp.confirmOTPSuccess"));
navigate(`/${subdomain}/menu`);
});
}}
>
{t("otp.continue")}
</Button>
</div>
</Layout.Content>
</div>
</Layout>
);
}