diff --git a/src/App.jsx b/src/App.jsx index fca1b6b..b7fd00b 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,12 +1,13 @@ // AppRoutes.jsx -import React, { useEffect, useState, useRef, } from 'react'; +import React, { useEffect, useState, useRef, lazy, } from 'react'; import { Routes, Route } from 'react-router-dom'; import { useNavigate } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; import ProtectedRoutes from './ProtectedRoutes'; -import SelfBooking from './Pages/SelfBooking/SelfBooking.jsx' + +import SelfBooking from './Pages/SelfBooking/SelfBooking.jsx' import { isMobile, isIOS } from "react-device-detect"; -// const { routesConfig }=lazy(()=>import('./routesConfig')); +// const { routesConfig } = lazy(() => import('./routesConfig')); import { routesConfig } from './routesConfig'; import { ChangeAppExpDateData, @@ -31,6 +32,10 @@ const subDirectory = import.meta.env.ENV_BASE_URL; import "../ownLib/my-ui-lib.css" import CustomerMenuPage from './Pages/Reports/MenuQRCode/CustomerMenuPage.jsx'; import WeightScaleApp from './Pages/BookingScreen/WeightscaleApp.jsx'; + +import { getPurchasedAppDetails, postInvoice } from './Features/BookingScreen/Pricing/Pricing.js'; +import { sendSms } from './Features/Payment/PaymentDetails/PaymentDetails.js'; +import ExtendSubscriptionModal from './Pages/ExtentedModal/ExtendSubscriptionModal.jsx'; const AppRoutes = () => { const navigate = useNavigate(); const dispatch = useDispatch(); @@ -39,6 +44,7 @@ const AppRoutes = () => { const prevRemainingDays = useRef(null); const [sessionData, setSessionData] = useState(null); const [devToolsOpen, setDevToolsOpen] = useState(false); + const [extendModel, setExtendModel] = useState(false); useEffect(() => { const handlePopState = (e) => { const SessionId = getSession('SessionId'); @@ -62,12 +68,12 @@ const AppRoutes = () => { }; }, []); - //cmd it start - // useEffect(() => { - // sessionCheckFun() - // }, [navigate, ItemCard]); + //cmd it start + // useEffect(() => { + // sessionCheckFun() + // }, [navigate, ItemCard]); - //cmd it End + //cmd it End useEffect(() => { @@ -118,15 +124,22 @@ const AppRoutes = () => { dispatch(ChangeAppExpDateData(expData)); dispatch(changeHeightforExpDate(expData.RemainingDays)); + + + + if ( expData.RemainingDays < 1 && expData.RemainingHours < 1 && expData.RemainingMinutes < 1 && expData.RemainingSeconds < 1 ) { + + + if ( - UserType !== 'Super Admin' || - UserType !== 'Super Admin User' + (UserType !== 'Super Admin' || + UserType !== 'Super Admin User') && (expData?.PlanType?.toLowerCase() == "extend expired") ) { console.log('Subscription expired, logging out...'); alert( @@ -134,8 +147,24 @@ const AppRoutes = () => { ); Logout(); } + else if ( + (UserType !== 'Super Admin' || + UserType !== 'Super Admin User') && (expData?.PlanType?.toLowerCase() == "plan expired") + ) { + setExtendModel(true) + // "Extend Expired" + + + + + // alert( + // 'Subscription expired, logging out. Redirecting to login...' + // ); + // Logout(); + } } } + } else { console.log('No subscription data found, logging out...'); alert( @@ -170,95 +199,203 @@ const AppRoutes = () => { console.error('Logout failed:', error); } }; - // mohan - // useEffect(() => { - // if (isMobile || isIOS) { - // console.log("📱 Mobile/iOS device → skipping DevTools detection"); - // return; - // } - // const checkDevTools = setInterval(() => { - // if (devtools.isOpen && !devToolsOpen) { - // setDevToolsOpen(true); - // document.body.innerHTML = - // "

Close Inspect to continue using the application.

"; - // } - // else if (!devtools.isOpen && devToolsOpen) { - // setDevToolsOpen(false); - - // setTimeout(() => { - // window.location.reload(); - // }, 100); - - // clearInterval(checkDevTools); - // } - - // if (!devtools.isOpen) { - // let before = performance.now(); - - // let after = performance.now(); - - // let executionDelay = after - before; - - // if (executionDelay > 100) { - // setDevToolsOpen(true); - // document.body.innerHTML = - // "

Close Inspect to continue using the application.

"; - // } else { - // setDevToolsOpen(false); - // } - // } - // }, 1000); - - // return () => clearInterval(checkDevTools); - // }, [devToolsOpen]); - - const sessionCheckFun = async () => { - const UserId = getSession('UserId'); - const sessionId = getSession('SessionId'); - const IsLogout = getSession('Mode'); - let encryptedLoginType = TokendecryptedValuesFun( - sessionStorage.getItem('LoginType') - ); - if (encryptedLoginType != 'Kiosk') { - const res = await dispatch(checkSession({ UserId, sessionId })).unwrap(); - if (res?.data?.statusCode === 1) { - if (res?.data?.response === 'False') { - if (IsLogout !== 'Logout') { - alert('Session invalid. Redirecting to login...'); - } - clearSession(); - window.location.replace(commonSubDir); + // mohan + // useEffect(() => { + // if (isMobile || isIOS) { + // console.log("📱 Mobile/iOS device → skipping DevTools detection"); + // return; + // } + // const checkDevTools = setInterval(() => { + // if (devtools.isOpen && !devToolsOpen) { + // setDevToolsOpen(true); + // document.body.innerHTML = + // "

Close Inspect to continue using the application.

"; + // } + // else if (!devtools.isOpen && devToolsOpen) { + // setDevToolsOpen(false); + + // setTimeout(() => { + // window.location.reload(); + // }, 100); + + // clearInterval(checkDevTools); + // } + + // if (!devtools.isOpen) { + // let before = performance.now(); + + // let after = performance.now(); + + // let executionDelay = after - before; + + // if (executionDelay > 100) { + // setDevToolsOpen(true); + // document.body.innerHTML = + // "

Close Inspect to continue using the application.

"; + // } else { + // setDevToolsOpen(false); + // } + // } + // }, 1000); + + // return () => clearInterval(checkDevTools); + // }, [devToolsOpen]); + + const sessionCheckFun = async () => { + const UserId = getSession('UserId'); + const sessionId = getSession('SessionId'); + const IsLogout = getSession('Mode'); + let encryptedLoginType = TokendecryptedValuesFun( + sessionStorage.getItem('LoginType') + ); + if (encryptedLoginType != 'Kiosk') { + const res = await dispatch(checkSession({ UserId, sessionId })).unwrap(); + if (res?.data?.statusCode === 1) { + if (res?.data?.response === 'False') { + if (IsLogout !== 'Logout') { + alert('Session invalid. Redirecting to login...'); } + clearSession(); + window.location.replace(commonSubDir); } } - }; - + } + }; + + // ---------------- DATE UTILS ---------------- + function formatDate(date) { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + const milliseconds = String(date.getMilliseconds()).padStart(3, '0'); + + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}.${milliseconds}`; + } + + function addDays(dateString, days) { + // Make it ISO-safe for iOS / WebView + const isoDate = dateString.replace(' ', 'T'); + const currentDate = new Date(isoDate); + + currentDate.setDate(currentDate.getDate() + Number(days)); + + return formatDate(currentDate); + } + + // ---------------- MAIN FUNCTION ---------------- + const freeExtend = async () => { + try { + const { CompId, AppId, BranchId, UserType } = sessionData; + const UserId = getSession('UserId'); + + // Current date + const now = new Date(); + const currentDate = formatDate(now); + + // 1️⃣ Get purchased app details + const response1 = await dispatch( + getPurchasedAppDetails({ AppId, UserId }) + ).unwrap(); + + const PurchasedDetails = response1?.data?.data; + + if (!PurchasedDetails || !PurchasedDetails.length) { + console.error('No purchased details found'); + return; + } + + // 2️⃣ Prepare post data + const postData = { + UserId: UserId, + AppId: AppId, + PricingId: PurchasedDetails[0]?.PricingId, + PurDate: currentDate, + NoofDays: 30, + PaymentMode: 27, + PaymentStatus: 'S', + LicenseStatus: PurchasedDetails[0]?.LicenseStatus, + Price: PurchasedDetails[0]?.Price ?? 0, + TaxId: PurchasedDetails[0]?.TaxId ?? 0, + NetPrice: PurchasedDetails[0]?.ExistingPlanNetPrice ?? 0, + ValidityStart: currentDate, + ValidityEnd: addDays( + currentDate, + PurchasedDetails[0]?.NoOfDays + ), + CreatedBy: UserId, + TaxAmount: PurchasedDetails[0]?.TaxAmount ?? 0, + MobileNo: getSession('MobileNo'), + MailId: 'ts@gmmail.com', + Type: "FreeExtend" + }; + + // 3️⃣ Post invoice + const response = await dispatch(postInvoice(postData)).unwrap(); + + // 4️⃣ Send SMS if required + if (response?.data?.statusCode === 1 && response?.data?.SMSbody) { + await dispatch( + sendSms({ body: response.data.SMSbody }) + ); + setExtendModel(false) + + } + + } catch (error) { + console.error('freeExtend error:', error); + } + }; + const handleCancel = () => { + Logout(); + setExtendModel(false) + + } + const handlePay = () => { + setExtendModel(false) + let AppName = getSession("AppName") + navigate(`${subDirectory}PricingPage`, { state: { AppName: AppName } }); + } + + if (extendModel) { + return ( + + ); + } + return ( - - } - /> - } - /> + <> + } - /> - } /> - - } - /> - } - /> - + path={`${subDirectory}selfBooking/:SelfBookingId`} + element={} + /> + } + /> + } + /> + } /> + } + /> + } + /> + + ); }; diff --git a/src/Pages/ExtentedModal/ExtendSubscriptionModal.jsx b/src/Pages/ExtentedModal/ExtendSubscriptionModal.jsx new file mode 100644 index 0000000..2dd1d48 --- /dev/null +++ b/src/Pages/ExtentedModal/ExtendSubscriptionModal.jsx @@ -0,0 +1,48 @@ +import { Tooltip } from "antd"; +import "./extendSubscribtionModel.scss"; +import { IoClose } from "react-icons/io5"; + +const ExtendSubscriptionModal = ({ + onClose, + onPayNow, + onContinueWithCredits +}) => { + return ( +
+
+
+

Subscription Expired

+ + + +
+ +

+ Your plan has expired. Please extend to continue using the app. +

+ +
+ + + +
+
+
+ ); +}; + +export default ExtendSubscriptionModal; \ No newline at end of file diff --git a/src/Pages/ExtentedModal/extendSubscribtionModel.scss b/src/Pages/ExtentedModal/extendSubscribtionModel.scss new file mode 100644 index 0000000..c2df053 --- /dev/null +++ b/src/Pages/ExtentedModal/extendSubscribtionModel.scss @@ -0,0 +1,128 @@ +.extendmodal-backdrop { + position: fixed; + inset: 0; + background: rgba(0, 0, 0, 0.6); + display: flex; + justify-content: center; + align-items: center; + z-index: 999; +} + +.extendmodal { + background: #fff; + padding: 20px; + border-radius: 12px; + width: 450px; + font-family: "Poppins", sans-serif; + + h2 { + font-size: 22px; + font-weight: 600; + } + + p { + font-size: 14px; + margin-top: 8px; + color: #555; + width: 90%; + } + + @media (max-width: 600px) { + width: 90% !important; + } +} + +.extendModalheader { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + margin-bottom: 12px; + gap: 1rem; +} + +.extendModalClose { + width: 25px; + height: 25px; + display: flex; + align-items: center; + justify-content: center; + padding: 3px; + background-color: #ffecec; + color: #ef4444; + transition: all 0.2s; + border-radius: 4px; + cursor: pointer; + + &:hover { + background-color: #ffd5d5; + } +} + +.extendmodal-actions { + margin: 2rem 0 1rem 0; + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; +} + +/* Common button style */ +.PayNowBTN, +.CreditsBTN { + padding: 8px 14px; + font-family: "Poppins", sans-serif; + border: none; + outline: none; + font-weight: 500; + font-size: 14px; + cursor: pointer; + border-radius: 4px; + transition: all 0.2s; +} + +/* Pay Now */ +.PayNowBTN { + background-color: #10b981; + color: #fff; + padding: 8px 22px; + animation: payNowPulse 1.8s ease-in-out infinite; + transition: transform 0.25s ease, box-shadow 0.25s ease; + + + &:hover { + background-color: #10b981; + animation-play-state: paused; + transform: scale(1.08); + } +} + +/* Continue with Credits */ +.CreditsBTN { + background-color: #f3f4f6; + color: #111; + border: 1px solid #d1d5db; + + &:hover { + background-color: #e5e7eb; + } +} + + +/* Attention animation */ +@keyframes payNowPulse { + 0% { + transform: scale(1); + box-shadow: 0 0 0 0 #05c283; + } + + 50% { + transform: scale(1.07); + box-shadow: 0 0 0 8px #1292ee00; + } + + 100% { + transform: scale(1); + box-shadow: 0 0 0 0 #1292ee00; + } +} \ No newline at end of file