extendedPlan
This commit is contained in:
parent
3d4cb2f9af
commit
2333bb74bd
323
src/App.jsx
323
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 =
|
||||
// "<h1 style='color: red; text-align: center;'>Close Inspect to continue using the application.</h1>";
|
||||
// }
|
||||
// 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 =
|
||||
// "<h1 style='color: red; text-align: center;'>Close Inspect to continue using the application.</h1>";
|
||||
// } 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 =
|
||||
// "<h1 style='color: red; text-align: center;'>Close Inspect to continue using the application.</h1>";
|
||||
// }
|
||||
// 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 =
|
||||
// "<h1 style='color: red; text-align: center;'>Close Inspect to continue using the application.</h1>";
|
||||
// } 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 (
|
||||
<ExtendSubscriptionModal
|
||||
onClose={handleCancel}
|
||||
onPayNow={handlePay}
|
||||
onContinueWithCredits={freeExtend}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
<Route
|
||||
path={`${subDirectory}selfBooking/:SelfBookingId`}
|
||||
element={<SelfBooking />}
|
||||
/>
|
||||
<Route
|
||||
path={`${subDirectory}MenuQRCode`}
|
||||
element={<CustomerMenuPage />}
|
||||
/>
|
||||
<>
|
||||
<Routes>
|
||||
<Route
|
||||
path={`${subDirectory}weightscaleapp`}
|
||||
element={<WeightScaleApp />}
|
||||
/>
|
||||
<Route path={`${subDirectory}kioskSelfBooking`} element={<KisokSelBooking />} />
|
||||
|
||||
<Route
|
||||
path= {`${subDirectory}kiosk-individual-self-booking`}
|
||||
element={<IndividualBooking />}
|
||||
/>
|
||||
<Route
|
||||
path="/*"
|
||||
element={<ProtectedRoutes routesConfig={routesConfig} />}
|
||||
/>
|
||||
</Routes>
|
||||
path={`${subDirectory}selfBooking/:SelfBookingId`}
|
||||
element={<SelfBooking />}
|
||||
/>
|
||||
<Route
|
||||
path={`${subDirectory}MenuQRCode`}
|
||||
element={<CustomerMenuPage />}
|
||||
/>
|
||||
<Route
|
||||
path={`${subDirectory}weightscaleapp`}
|
||||
element={<WeightScaleApp />}
|
||||
/>
|
||||
<Route path={`${subDirectory}kioskSelfBooking`} element={<KisokSelBooking />} />
|
||||
|
||||
<Route
|
||||
path={`${subDirectory}kiosk-individual-self-booking`}
|
||||
element={<IndividualBooking />}
|
||||
/>
|
||||
<Route
|
||||
path="/*"
|
||||
element={<ProtectedRoutes routesConfig={routesConfig} />}
|
||||
/>
|
||||
</Routes>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
import { Tooltip } from "antd";
|
||||
import "./extendSubscribtionModel.scss";
|
||||
import { IoClose } from "react-icons/io5";
|
||||
|
||||
const ExtendSubscriptionModal = ({
|
||||
onClose,
|
||||
onPayNow,
|
||||
onContinueWithCredits
|
||||
}) => {
|
||||
return (
|
||||
<div className="extendmodal-backdrop">
|
||||
<div className="extendmodal">
|
||||
<div className="extendModalheader">
|
||||
<h2>Subscription Expired</h2>
|
||||
<Tooltip placement="left" title="Close">
|
||||
<IoClose
|
||||
onClick={onClose}
|
||||
className="extendModalClose"
|
||||
size={20}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Your plan has expired. Please extend to continue using the app.
|
||||
</p>
|
||||
|
||||
<div className="extendmodal-actions">
|
||||
<button
|
||||
className="CreditsBTN"
|
||||
onClick={onContinueWithCredits}
|
||||
>
|
||||
Continue with Credits
|
||||
</button>
|
||||
|
||||
<button
|
||||
className="PayNowBTN"
|
||||
onClick={onPayNow}
|
||||
>
|
||||
Pay Now
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExtendSubscriptionModal;
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue