refactor: user valdation

This commit is contained in:
prafull-opensignlabs
2024-08-08 20:40:13 +05:30
parent 870a25dad1
commit 1fe1381fe2
24 changed files with 439 additions and 263 deletions
+22 -8
View File
@@ -34,7 +34,8 @@ const AddUser = (props) => {
const [planInfo, setPlanInfo] = useState({
priceperUser: 0,
price: 0,
totalPrice: 0
totalPrice: 0,
totalAllowedUser: 0
});
const [isFormLoader, setIsFormLoader] = useState(false);
const [isLoader, setIsLoader] = useState(false);
@@ -59,7 +60,8 @@ const AddUser = (props) => {
setPlanInfo((prev) => ({
...prev,
priceperUser: resSub.price,
totalPrice: resSub.totalPrice
totalPrice: resSub.totalPrice,
totalAllowedUser: resSub.totalAllowedUser
}));
setAmount((prev) => ({
...prev,
@@ -297,7 +299,10 @@ const AddUser = (props) => {
tenantId: extUser?.TenantId?.objectId
});
if (resAddon) {
setAllowedUser(amount.quantity);
const _resAddon = JSON.parse(JSON.stringify(resAddon));
if (_resAddon.status === "success") {
setAllowedUser(_resAddon.addon);
}
}
} catch (err) {
console.log("Err in buy addon", err);
@@ -330,6 +335,16 @@ const AddUser = (props) => {
<div className="w-full mx-auto">
{!isEnableSubscription || allowedUser > 0 ? (
<form onSubmit={handleSubmit}>
<p className="flex justify-center mb-1">
Remaining users{" "}
<span
className={`${
allowedUser < 2 ? "op-text-accent" : "op-text-primary"
} font-medium ml-1`}
>
{allowedUser} of {planInfo.totalAllowedUser}
</span>
</p>
<div className="mb-3">
<label
htmlFor="name"
@@ -468,9 +483,8 @@ const AddUser = (props) => {
</form>
) : (
<form onSubmit={handleAddOnSubmit}>
<p className="flex justify-center text-center mx-2 mb-3 text-base font-medium">
You have reached the limit for creating users. Please
purchase the add-on.
<p className="flex justify-center text-center mx-2 mb-3 text-base op-text-accent font-medium">
Please purchase add-on users.
</p>
<div className="mb-3 flex justify-between">
<label
@@ -494,7 +508,7 @@ const AddUser = (props) => {
Price (1 * {planInfo.priceperUser})
</label>
<div className="w-1/4 flex justify-center items-center text-sm">
{amount.price}
USD {amount.price}
</div>
</div>
<hr className="text-base-content mb-3" />
@@ -503,7 +517,7 @@ const AddUser = (props) => {
Total price for next time
</label>
<div className="w-1/4 flex justify-center items-center text-sm font-semibold">
{amount.totalPrice}
USD {amount.totalPrice}
</div>
</div>
<button className="op-btn op-btn-primary w-full mt-2">
+18 -17
View File
@@ -4,13 +4,9 @@ import FullScreenButton from "./FullScreenButton";
import { useNavigate } from "react-router-dom";
import Parse from "parse";
import { useWindowSize } from "../hook/useWindowSize";
import {
checkIsSubscribed,
checkIsSubscribedTeam,
getAppLogo,
openInNewTab
} from "../constant/Utils";
import { checkIsSubscribed, getAppLogo, openInNewTab } from "../constant/Utils";
import { isEnableSubscription, isStaging } from "../constant/const";
import { paidUrl, validplan } from "../json/plansArr";
const Header = ({ showSidebar }) => {
const navigate = useNavigate();
@@ -19,8 +15,7 @@ const Header = ({ showSidebar }) => {
const image = localStorage.getItem("profileImg") || dp;
const [isOpen, setIsOpen] = useState(false);
const [isSubscribe, setIsSubscribe] = useState(true);
const [isPro, setIsPro] = useState(false);
const [isTeam, setIsTeam] = useState(false);
const [isTeam, setIsTeam] = useState({ plan: "", isValid: false });
const [applogo, setAppLogo] = useState(
localStorage.getItem("appLogo") || " "
);
@@ -34,9 +29,8 @@ const Header = ({ showSidebar }) => {
}, []);
async function checkSubscription() {
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
const getIsTeam = await checkIsSubscribedTeam();
if (getIsSubscribe) {
const subscribe = await checkIsSubscribed();
if (subscribe.isValid) {
const applogo = await getAppLogo();
if (applogo?.logo) {
setAppLogo(applogo?.logo);
@@ -44,9 +38,8 @@ const Header = ({ showSidebar }) => {
setAppLogo(localStorage.getItem("appLogo") || "");
}
}
setIsPro(getIsSubscribe);
setIsTeam(getIsTeam);
setIsSubscribe(getIsSubscribe);
setIsTeam(subscribe);
setIsSubscribe(subscribe.isValid);
}
}
@@ -100,6 +93,14 @@ const Header = ({ showSidebar }) => {
window.open("https://console.opensignlabs.com/");
}
};
const handleNavigation = () => {
const route = paidUrl(isTeam.plan);
if (route === "/subscription") {
navigate(route);
} else {
openInNewTab(route, "_self");
}
};
return (
<div className="op-navbar bg-base-100 shadow">
<div className="flex-none">
@@ -124,18 +125,18 @@ const Header = ({ showSidebar }) => {
<div>
<button
className="text-xs md:text-sm shadow op-btn op-btn-outline op-btn-sm md:op-btn-md op-btn-accent"
onClick={() => navigate("/subscription")}
onClick={() => handleNavigation()}
>
Upgrade Now
</button>
</div>
)}
{!isTeam && isPro && (
{isTeam.isValid && !validplan[isTeam.plan] && (
<div className="w-[35px] h-[35px] bg-white rounded-full ring-[1px] ring-offset-2 ring-[#002862] text-[#002862] overflow-hidden font-semibold flex items-center justify-center">
PRO
</div>
)}
{isTeam && (
{validplan[isTeam.plan] && (
<div className="w-[35px] h-[35px] bg-white rounded-full ring-[1px] text-[13px] ring-offset-2 ring-[#002862] text-[#002862] overflow-hidden font-semibold flex items-center justify-center">
TEAM
</div>
@@ -21,8 +21,8 @@ const EditTemplate = ({ template, onSuccess }) => {
}, []);
const fetchSubscription = async () => {
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
setIsSubscribe(getIsSubscribe);
const subscribe = await checkIsSubscribed();
setIsSubscribe(subscribe.isValid);
}
};
const handleStrInput = (e) => {
+12 -27
View File
@@ -56,6 +56,8 @@ export async function fetchSubscription(
} else {
plan = tenatRes.data?.result?.result?.PlanCode;
billingDate = tenatRes.data?.result?.result?.Next_billing_date?.iso;
const allowedUsers = tenatRes.data?.result?.result?.AllowedUsers || 0;
localStorage.setItem("allowedUsers", allowedUsers);
}
return { plan, billingDate, status };
} catch (err) {
@@ -93,12 +95,14 @@ export async function fetchSubscriptionInfo() {
const plan_code =
tenatRes.data?.result?.result?.SubscriptionDetails?.data?.subscription
?.plan?.plan_code;
const totalAllowedUser = tenatRes.data?.result?.result?.AllowedUsers || 0;
return {
status: "success",
price: price,
totalPrice: totalPrice,
planId: planId,
plan_code: plan_code
plan_code: plan_code,
totalAllowedUser: totalAllowedUser
};
}
} catch (err) {
@@ -111,41 +115,22 @@ export async function checkIsSubscribed() {
try {
const res = await fetchSubscription();
if (res.plan === "freeplan") {
return false;
} else if (res.billingDate) {
if (new Date(res.billingDate) > new Date()) {
return true;
} else {
return false;
}
} else {
return false;
}
} catch (err) {
console.log("Err in fetch subscription", err);
return false;
}
}
//function to get subcripition details from subscription class
export async function checkIsSubscribedTeam() {
try {
const res = await fetchSubscription();
if (res.plan === "freeplan") {
return false;
return { plan: res.plan, isValid: false };
} else if (res.billingDate) {
const plan = validplan[res.plan] || false;
if (plan && new Date(res.billingDate) > new Date()) {
return true;
return { plan: res.plan, isValid: true };
} else if (new Date(res.billingDate) > new Date()) {
return { plan: res.plan, isValid: true };
} else {
return false;
return { plan: res.plan, isValid: false };
}
} else {
return false;
return { plan: res.plan, isValid: false };
}
} catch (err) {
console.log("Err in fetch subscription", err);
return false;
return { plan: "no-plan", isValid: false };
}
}
+2 -2
View File
@@ -9,5 +9,5 @@ export const isEnableSubscription =
process.env.REACT_APP_ENABLE_SUBSCRIPTION?.toLowerCase() === "true"
? true
: false;
export const isStaging =
window.location.origin === "https://staging-app.opensignlabs.com";
export const isStaging = "http://localhost:3001";
// window.location.origin === "https://staging-app.opensignlabs.com";
+8 -5
View File
@@ -26,7 +26,7 @@ body {
.op-bg-info {
@apply bg-info;
}
.op-bg-success{
.op-bg-success {
@apply bg-success;
}
.op-bg-warning {
@@ -43,14 +43,17 @@ body {
.op-text-info {
@apply text-info;
}
.op-text-success{
.op-text-accent {
@apply text-accent;
}
.op-text-success {
@apply text-success;
}
.op-text-warning {
@apply text-warning;
}
.op-border-primary{
@apply border-primary
.op-border-primary {
@apply border-primary;
}
/* CSS for scrollbar customization */
* {
@@ -70,4 +73,4 @@ body {
*::-webkit-scrollbar-thumb {
background-color: gray;
border-radius: 10px;
}
}
+68
View File
@@ -171,4 +171,72 @@ export const validplan = {
"enterprise-monthly": true,
"enterprise-yearly": true
};
export const paidUrl = (plan) => {
const teamperiod = {
"team-weekly": "monthly",
"team-yearly": "yearly",
"teams-monthly": "monthly",
"teams-yearly": "yearly"
};
const period = teamperiod[plan] || "";
if (period) {
const extUser =
localStorage.getItem("Extand_Class") &&
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
const user = {
name: extUser?.Name,
email: extUser?.Email,
company: extUser?.Company,
phone: extUser?.Phone
};
// console.log("userDetails ", userDetails);
const fullname = user && user.name ? user.name.split(" ") : "";
const firstname = fullname?.[0]
? "first_name=" + encodeURIComponent(fullname?.[0])
: "";
const lastname = fullname?.[1]
? "&last_name=" + encodeURIComponent(fullname?.[1])
: "";
const name = firstname ? firstname + lastname : "";
const email =
user && user.email ? "&email=" + encodeURIComponent(user.email) : "";
const company =
user && user.company
? "&company_name=" + encodeURIComponent(user.company)
: "";
const phone =
user && user.phone ? "&mobile=" + encodeURIComponent(user.phone) : "";
const allowedUsers = localStorage.getItem("allowedUsers");
const quantity = allowedUsers
? isStaging
? `addon_code%5B0%5D=extra-users&addon_quantity%5B0%5D=${allowedUsers}`
: `addon_code%5B0%5D=extra-teams-users-${period}&addon_quantity%5B0%5D=${allowedUsers}`
: "";
const details =
"?shipping_country_code=US&billing_country_code=US&billing_state_code=CA&" +
quantity +
name +
email +
company +
phone;
if (user) {
localStorage.setItem("userDetails", JSON.stringify(user));
}
const url = {
monthly: isStaging
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/team-weekly"
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af901237d0702bfaa959406306635d80f138c/teams-monthly",
yearly: isStaging
? "https://billing.zoho.in/subscribe/ed8097273a82b6bf39892c11a3bb3c381eb2705736014cfbdbde1ccf1c7a189d/team-weekly"
: "https://billing.opensignlabs.com/subscribe/ef798486e6a0a11ea65f2bae8f2af9011a864994bbeeec71fcf106188630199d/teams-yearly"
};
const planurl = url[period] + details;
return planurl;
} else {
return "/subscription";
}
};
export default plans;
+12 -4
View File
@@ -11,9 +11,10 @@ import ModalUi from "../primitives/ModalUi";
import { useNavigate, useLocation, Outlet } from "react-router-dom";
import { isEnableSubscription } from "../constant/const";
import { useCookies } from "react-cookie";
import { fetchSubscription } from "../constant/Utils";
import { fetchSubscription, openInNewTab } from "../constant/Utils";
import Loader from "../primitives/Loader";
import { showHeader } from "../redux/reducers/showHeader";
import { paidUrl } from "../json/plansArr";
const HomeLayout = () => {
const navigate = useNavigate();
@@ -86,7 +87,14 @@ const HomeLayout = () => {
domain: updateDomain
});
};
const handleNavigation = (plan) => {
const route = paidUrl(plan);
if (route === "/subscription") {
navigate(route);
} else {
openInNewTab(route, "_self");
}
};
async function checkIsSubscribed() {
if (isEnableSubscription) {
const res = await fetchSubscription();
@@ -98,10 +106,10 @@ const HomeLayout = () => {
setIsUserValid(true);
setIsLoader(false);
} else {
navigate(`/subscription`);
handleNavigation(res.plan);
}
} else {
navigate(`/subscription`);
handleNavigation(res.plan);
}
} else {
setIsUserValid(true);
+2 -2
View File
@@ -76,8 +76,8 @@ const Forms = (props) => {
}, []);
const fetchSubscription = async () => {
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
setIsSubscribe(getIsSubscribe);
const subscribe = await checkIsSubscribed();
setIsSubscribe(subscribe.isValid);
}
};
+8 -7
View File
@@ -9,6 +9,7 @@ import Tooltip from "../primitives/Tooltip";
import Loader from "../primitives/Loader";
import SubscribeCard from "../primitives/SubscribeCard";
import Tour from "reactour";
import { validplan } from "../json/plansArr";
const tourSteps = [
{
selector: '[data-tut="apisubscribe"]',
@@ -22,7 +23,7 @@ function GenerateToken() {
const [apiToken, SetApiToken] = useState("");
const [isLoader, setIsLoader] = useState(true);
const [isModal, setIsModal] = useState(false);
const [isSubscribe, setIsSubscribe] = useState(false);
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: false });
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
const [isTour, setIsTour] = useState(false);
useEffect(() => {
@@ -33,8 +34,8 @@ function GenerateToken() {
const fetchToken = async () => {
try {
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
setIsSubscribe(getIsSubscribe);
const subscribe = await checkIsSubscribed();
setIsSubscribe(subscribe);
}
const url = parseBaseUrl + "functions/getapitoken";
const headers = {
@@ -55,7 +56,7 @@ function GenerateToken() {
};
const handleSubmit = async (e) => {
e.preventDefault();
if (!isSubscribe && isEnableSubscription) {
if (!validplan[isSubscribe.plan] && isEnableSubscription) {
setIsTour(true);
} else {
setIsLoader(true);
@@ -123,7 +124,7 @@ function GenerateToken() {
<span
id="token"
className={`${
isSubscribe
validplan[isSubscribe.plan]
? ""
: "bg-white/20 pointer-events-none select-none"
} md:text-end py-2 md:py-0`}
@@ -191,9 +192,9 @@ function GenerateToken() {
</div>
</ModalUi>
</div>
{!isSubscribe && isEnableSubscription && (
{!validplan[isSubscribe.plan] && isEnableSubscription && (
<div data-tut="apisubscribe">
<SubscribeCard />
<SubscribeCard plan_code={isSubscribe.plan} />
</div>
)}
</>
+21 -13
View File
@@ -16,6 +16,7 @@ import { fetchAppInfo } from "../redux/reducers/infoReducer";
import { showTenant } from "../redux/reducers/ShowTenant";
import { fetchSubscription, getAppLogo, openInNewTab } from "../constant/Utils";
import Loader from "../primitives/Loader";
import { paidUrl } from "../json/plansArr";
function Login() {
const navigate = useNavigate();
const location = useLocation();
@@ -68,7 +69,14 @@ function Login() {
const { name, value } = event.target;
setState({ ...state, [name]: value });
};
const handlePaidRoute = (plan) => {
const route = paidUrl(plan);
if (route === "/subscription") {
navigate(route);
} else {
openInNewTab(route, "_self");
}
};
const handleSubmit = async (event) => {
localStorage.removeItem("accesstoken");
event.preventDefault();
@@ -139,9 +147,9 @@ function Login() {
JSON.stringify(LocalUserDetails)
);
const res = await fetchSubscription();
const freeplan = res.plan;
const plan = res.plan;
const billingDate = res.billingDate;
if (freeplan === "freeplan") {
if (plan === "freeplan") {
setState({ ...state, loading: false });
navigate(redirectUrl);
} else if (billingDate) {
@@ -152,11 +160,11 @@ function Login() {
navigate(redirectUrl);
} else {
setState({ ...state, loading: false });
navigate(`/subscription`, { replace: true });
handlePaidRoute(plan);
}
} else {
setState({ ...state, loading: false });
navigate(`/subscription`, { replace: true });
handlePaidRoute(plan);
}
} else {
setState({ ...state, loading: false });
@@ -311,9 +319,9 @@ function Login() {
localStorage.setItem("pageType", menu.pageType);
if (isEnableSubscription) {
const res = await fetchSubscription();
const freeplan = res.plan;
const plan = res.plan;
const billingDate = res.billingDate;
if (freeplan === "freeplan") {
if (plan === "freeplan") {
navigate(redirectUrl);
} else if (billingDate) {
if (new Date(billingDate) > new Date()) {
@@ -323,14 +331,14 @@ function Login() {
if (isFreeplan) {
navigate(redirectUrl);
} else {
navigate(`/subscription`, { replace: true });
handlePaidRoute(plan);
}
}
} else {
if (isFreeplan) {
navigate(redirectUrl);
} else {
navigate(`/subscription`, { replace: true });
handlePaidRoute(plan);
}
}
} else {
@@ -443,8 +451,8 @@ function Login() {
localStorage.setItem("userDetails", JSON.stringify(userInfo));
const res = await fetchSubscription();
const billingDate = res.billingDate;
const freeplan = res.plan;
if (freeplan === "freeplan") {
const plan = res.plan;
if (plan === "freeplan") {
navigate(redirectUrl);
} else if (billingDate) {
if (new Date(billingDate) > new Date()) {
@@ -452,10 +460,10 @@ function Login() {
// Redirect to the appropriate URL after successful login
navigate(redirectUrl);
} else {
navigate(`/subscription`);
handlePaidRoute(plan);
}
} else {
navigate(`/subscription`);
handlePaidRoute(plan);
}
} else {
// Redirect to the appropriate URL after successful login
+14 -3
View File
@@ -30,7 +30,8 @@ import {
contactBook,
handleDownloadPdf,
handleToPrint,
handleDownloadCertificate
handleDownloadCertificate,
openInNewTab
} from "../constant/Utils";
import LoaderWithMsg from "../primitives/LoaderWithMsg";
import HandleError from "../primitives/HandleError";
@@ -46,6 +47,7 @@ import { useSelector } from "react-redux";
import SignerListComponent from "../components/pdf/SignerListComponent";
import VerifyEmail from "../components/pdf/VerifyEmail";
import PdfZoom from "../components/pdf/PdfZoom";
import { paidUrl } from "../json/plansArr";
function PdfRequestFiles(props) {
const [pdfDetails, setPdfDetails] = useState([]);
@@ -228,6 +230,15 @@ function PdfRequestFiles(props) {
const currentUser = JSON.parse(localuser);
await handleSendOTP(currentUser?.email);
};
const handleNavigation = (plan) => {
const route = paidUrl(plan);
if (route === "/subscription") {
window.location.href = route;
} else {
openInNewTab(route, "_self");
}
};
async function checkIsSubscribed(extUserId, contactId) {
const isGuestSign = isGuestSignFlow || false;
const res = await fetchSubscription(extUserId, contactId, isGuestSign);
@@ -244,7 +255,7 @@ function PdfRequestFiles(props) {
if (isGuestSign) {
setIsSubscriptionExpired(true);
} else {
window.location.href = "/subscription";
handleNavigation(plan);
}
}
} else if (isGuestSign) {
@@ -258,7 +269,7 @@ function PdfRequestFiles(props) {
if (isGuestSign) {
setIsSubscriptionExpired(true);
} else {
window.location.href = "/subscription";
handleNavigation(res.plan);
}
}
}
+15 -6
View File
@@ -34,7 +34,8 @@ import {
copytoData,
fetchSubscription,
convertPdfArrayBuffer,
getContainerScale
getContainerScale,
openInNewTab
} from "../constant/Utils";
import RenderPdf from "../components/pdf/RenderPdf";
import { useNavigate } from "react-router-dom";
@@ -53,6 +54,7 @@ import Loader from "../primitives/Loader";
import { useSelector } from "react-redux";
import PdfZoom from "../components/pdf/PdfZoom";
import LottieWithLoader from "../primitives/DotLottieReact";
import { paidUrl } from "../json/plansArr";
function PlaceHolderSign() {
const editorRef = useRef();
@@ -240,22 +242,29 @@ function PlaceHolderSign() {
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current, isHeader]);
const handleNavigation = (plan) => {
const route = paidUrl(plan);
if (route === "/subscription") {
navigate(route);
} else {
openInNewTab(route, "_self");
}
};
async function checkIsSubscribed() {
const res = await fetchSubscription();
const freeplan = res.plan;
const plan = res.plan;
const billingDate = res.billingDate;
if (freeplan === "freeplan") {
if (plan === "freeplan") {
return true;
} else if (billingDate) {
if (new Date(billingDate) > new Date()) {
setIsSubscribe(true);
return true;
} else {
navigate(`/subscription`);
handleNavigation(plan);
}
} else {
navigate(`/subscription`);
handleNavigation(plan);
}
}
//function for get document details
+12 -3
View File
@@ -3,11 +3,12 @@ import { useLocation, useNavigate } from "react-router-dom";
import Parse from "parse";
import { appInfo } from "../constant/appinfo";
import { isEnableSubscription } from "../constant/const";
import { fetchSubscription } from "../constant/Utils";
import { fetchSubscription, openInNewTab } from "../constant/Utils";
import { useDispatch } from "react-redux";
import { showTenant } from "../redux/reducers/ShowTenant";
import ModalUi from "../primitives/ModalUi";
import Loader from "../primitives/Loader";
import { paidUrl } from "../json/plansArr";
const SSOVerify = () => {
const location = useLocation();
@@ -48,6 +49,14 @@ const SSOVerify = () => {
console.log("err", err.message);
}
};
const handlePaidRoute = (plan) => {
const route = paidUrl(plan);
if (route === "/subscription") {
navigate(route);
} else {
openInNewTab(route, "_self");
}
};
const checkExtUser = async (ssosign) => {
const params = { email: ssosign?.email };
try {
@@ -194,10 +203,10 @@ const SSOVerify = () => {
localStorage.removeItem("userDetails");
navigate(redirectUrl);
} else {
navigate(`/subscription`, { replace: true });
handlePaidRoute(plan);
}
} else {
navigate(`/subscription`, { replace: true });
handlePaidRoute(plan);
}
} else {
navigate(redirectUrl);
+1 -1
View File
@@ -757,7 +757,7 @@ function SignYourSelf() {
if (
tenantDetails?.CompletionBody &&
tenantDetails?.CompletionSubject &&
getIsSubscribe
getIsSubscribe.isValid
) {
isCustomCompletionMail = true;
}
+12 -7
View File
@@ -8,9 +8,10 @@ import ModalUi from "../primitives/ModalUi";
import pad from "../assets/images/pad.svg";
import AddTeam from "../components/AddTeam";
import { isEnableSubscription } from "../constant/const";
import { checkIsSubscribedTeam } from "../constant/Utils";
import { checkIsSubscribed } from "../constant/Utils";
import SubscribeCard from "../primitives/SubscribeCard";
import Title from "../components/Title";
import { validplan } from "../json/plansArr";
const heading = ["Sr.No", "Name", "Parent Team", "Active"];
const actions = [
@@ -36,7 +37,7 @@ const TeamList = () => {
const [isActiveModal, setIsActiveModal] = useState({});
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
const [isActLoader, setIsActLoader] = useState({});
const [isSubscribe, setIsSubscribe] = useState(false);
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: false });
const [isEditModal, setIsEditModal] = useState({});
const [isAdmin, setIsAdmin] = useState(false);
const startIndex = (currentPage - 1) * recordperPage; // user per page
@@ -100,8 +101,8 @@ const TeamList = () => {
try {
setIsLoader(true);
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribedTeam();
setIsSubscribe(getIsSubscribe);
const subscribe = await checkIsSubscribed();
setIsSubscribe(subscribe);
}
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
if (extUser) {
@@ -222,7 +223,7 @@ const TeamList = () => {
<Loader />
</div>
)}
{isSubscribe && isEnableSubscription && !isLoader && (
{validplan[isSubscribe.plan] && isEnableSubscription && !isLoader && (
<>
{isAdmin ? (
<div className="p-2 w-full bg-base-100 text-base-content op-card shadow-lg">
@@ -449,9 +450,13 @@ const TeamList = () => {
)}
</>
)}
{!isSubscribe && isEnableSubscription && !isLoader && (
{!validplan[isSubscribe.plan] && isEnableSubscription && !isLoader && (
<div data-tut="apisubscribe">
<SubscribeCard plan={"TEAMS"} price={"20"} />
<SubscribeCard
plan={"TEAMS"}
price={"20"}
plan_code={isSubscribe.plan}
/>
</div>
)}
</div>
+16 -5
View File
@@ -25,7 +25,8 @@ import {
textInputWidget,
radioButtonWidget,
fetchSubscription,
getContainerScale
getContainerScale,
openInNewTab
} from "../constant/Utils";
import RenderPdf from "../components/pdf/RenderPdf";
import "../styles/AddUser.css";
@@ -40,6 +41,7 @@ import DropdownWidgetOption from "../components/pdf/DropdownWidgetOption";
import Parse from "parse";
import { useSelector } from "react-redux";
import PdfZoom from "../components/pdf/PdfZoom";
import { paidUrl } from "../json/plansArr";
const TemplatePlaceholder = () => {
const navigate = useNavigate();
const isHeader = useSelector((state) => state.showHeader);
@@ -179,21 +181,30 @@ const TemplatePlaceholder = () => {
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current, isHeader]);
const handleNavigation = (plan) => {
const route = paidUrl(plan);
if (route === "/subscription") {
navigate(route);
} else {
openInNewTab(route, "_self");
}
};
async function checkIsSubscribed() {
const res = await fetchSubscription();
const freeplan = res.plan;
const plan = res.plan;
const billingDate = res.billingDate;
if (freeplan === "freeplan") {
if (plan === "freeplan") {
return true;
} else if (billingDate) {
if (new Date(billingDate) > new Date()) {
setIsSubscribe(true);
return true;
} else {
navigate(`/subscription`);
handleNavigation(plan);
}
} else {
navigate(`/subscription`);
handleNavigation(plan);
}
}
// `fetchTemplate` function in used to get Template from server and setPlaceholder ,setSigner if present
+13 -8
View File
@@ -9,8 +9,9 @@ import Tooltip from "../primitives/Tooltip";
import AddUser from "../components/AddUser";
import SubscribeCard from "../primitives/SubscribeCard";
import { isEnableSubscription } from "../constant/const";
import { checkIsSubscribedTeam } from "../constant/Utils";
import { checkIsSubscribed } from "../constant/Utils";
import Title from "../components/Title";
import { validplan } from "../json/plansArr";
const heading = ["Sr.No", "Name", "Email", "Phone", "Role", "Team", "Active"];
// const actions = [];
const UserList = () => {
@@ -24,7 +25,7 @@ const UserList = () => {
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
const [isActiveModal, setIsActiveModal] = useState({});
const [isActLoader, setIsActLoader] = useState({});
const [isSubscribe, setIsSubscribe] = useState(false);
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: false });
const [isAdmin, setIsAdmin] = useState(false);
const recordperPage = 10;
const startIndex = (currentPage - 1) * recordperPage; // user per page
@@ -88,10 +89,10 @@ const UserList = () => {
try {
setIsLoader(true);
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribedTeam();
setIsSubscribe(getIsSubscribe);
const subscribe = await checkIsSubscribed();
setIsSubscribe(subscribe);
} else {
setIsSubscribe(true);
setIsSubscribe({ plan: "teams-yearly", isValid: true });
}
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
if (extUser) {
@@ -193,7 +194,7 @@ const UserList = () => {
<Loader />
</div>
)}
{isSubscribe && !isLoader && (
{validplan[isSubscribe.plan] && !isLoader && (
<>
{isAdmin ? (
<div className="p-2 w-full bg-base-100 text-base-content op-card shadow-lg">
@@ -406,9 +407,13 @@ const UserList = () => {
)}
</>
)}
{!isSubscribe && isEnableSubscription && !isLoader && (
{!validplan[isSubscribe.plan] && isEnableSubscription && !isLoader && (
<div data-tut="apisubscribe">
<SubscribeCard plan={"TEAMS"} price={"20"} />
<SubscribeCard
plan={"TEAMS"}
price={"20"}
plan_code={isSubscribe.plan}
/>
</div>
)}
</div>
+27 -15
View File
@@ -10,12 +10,13 @@ import Tooltip from "../primitives/Tooltip";
import { isEnableSubscription } from "../constant/const";
import {
checkIsSubscribed,
checkIsSubscribedTeam,
handleSendOTP
handleSendOTP,
openInNewTab
} from "../constant/Utils";
import Upgrade from "../primitives/Upgrade";
import ModalUi from "../primitives/ModalUi";
import Loader from "../primitives/Loader";
import { paidUrl, validplan } from "../json/plansArr";
function UserProfile() {
const navigate = useNavigate();
@@ -50,7 +51,7 @@ function UserProfile() {
const [tagLine, setTagLine] = useState(
extendUser && extendUser?.[0]?.Tagline
);
const [isTeam, setIsTeam] = useState(false);
const [isPlan, setIsPlan] = useState({ plan: "", isValid: false });
useEffect(() => {
getUserDetail();
}, []);
@@ -61,10 +62,9 @@ function UserProfile() {
const jsonSender = JSON.parse(extClass);
const HeaderDocId = jsonSender[0]?.HeaderDocId;
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
const getIsTeam = await checkIsSubscribedTeam();
setIsSubscribe(getIsSubscribe);
setIsTeam(getIsTeam);
const subscribe = await checkIsSubscribed();
setIsSubscribe(subscribe.isValid);
setIsPlan(subscribe);
}
if (HeaderDocId) {
setIsDisableDocId(HeaderDocId);
@@ -184,9 +184,7 @@ function UserProfile() {
}
}
);
const res = await Parse.Cloud.run("getUserDetails", {
email: extData[0].Email
});
const res = await Parse.Cloud.run("getUserDetails");
const json = JSON.parse(JSON.stringify([res]));
const extRes = JSON.stringify(json);
@@ -303,6 +301,14 @@ function UserProfile() {
setJobTitle(extendUser?.[0]?.JobTitle);
setIsDisableDocId(extendUser?.[0]?.HeaderDocId);
};
const handlePaidRoute = () => {
const route = paidUrl(isPlan.plan);
if (route === "/subscription") {
navigate(route);
} else {
openInNewTab(route, "_self");
}
};
return (
<React.Fragment>
<Title title={"Profile"} />
@@ -516,7 +522,9 @@ function UserProfile() {
<div className="flex justify-between items-center py-2">
<span
className={
isTeam ? "font-semibold" : "font-semibold text-gray-300"
validplan[isPlan.plan]
? "font-semibold"
: "font-semibold text-gray-300"
}
>
Disable DocumentId :{" "}
@@ -525,17 +533,21 @@ function UserProfile() {
"https://docs.opensignlabs.com/docs/help/Settings/disabledocumentid"
}
/>
{!isTeam && isEnableSubscription && <Upgrade />}
{!validplan[isPlan.plan] && isEnableSubscription && (
<Upgrade />
)}
</span>
<label
className={`${
isTeam
validplan[isPlan.plan]
? `${editmode ? "cursor-pointer" : ""}`
: "pointer-events-none opacity-50"
} relative block items-center mb-0`}
>
<input
disabled={isTeam ? false : true}
disabled={
validplan[isPlan.plan] && editmode ? false : true
}
type="checkbox"
className="op-toggle transition-all checked:[--tglbg:#3368ff] checked:bg-white"
checked={isDisableDocId}
@@ -640,7 +652,7 @@ function UserProfile() {
</p>
<div className="op-card-actions justify-end">
<button
onClick={() => navigate("/subscription")}
onClick={() => handlePaidRoute()}
className="op-btn op-btn-accent"
>
Upgrade Now
+7 -6
View File
@@ -10,6 +10,7 @@ import Tooltip from "../primitives/Tooltip";
import Loader from "../primitives/Loader";
import SubscribeCard from "../primitives/SubscribeCard";
import Tour from "reactour";
import { validplan } from "../json/plansArr";
const tourSteps = [
{
selector: '[data-tut="webhooksubscribe"]',
@@ -22,7 +23,7 @@ function Webhook() {
const [webhook, setWebhook] = useState();
const [isLoader, setIsLoader] = useState(true);
const [isModal, setIsModal] = useState(false);
const [isSubscribe, setIsSubscribe] = useState(false);
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: true });
const [error, setError] = useState("");
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
const [isTour, setIsTour] = useState(false);
@@ -33,8 +34,8 @@ function Webhook() {
const fetchWebhook = async () => {
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribed();
setIsSubscribe(getIsSubscribe);
const subscribe = await checkIsSubscribed();
setIsSubscribe(subscribe);
}
try {
const extRes = await Parse.Cloud.run("getUserDetails");
@@ -87,7 +88,7 @@ function Webhook() {
};
const handleModal = () => {
if (!isSubscribe && isEnableSubscription) {
if (!validplan[isSubscribe.plan] && isEnableSubscription) {
setIsTour(true);
} else {
setIsModal(!isModal);
@@ -175,9 +176,9 @@ function Webhook() {
</div>
</ModalUi>
</div>
{!isSubscribe && isEnableSubscription && (
{!validplan[isSubscribe.plan] && isEnableSubscription && (
<div data-tut="webhooksubscribe">
<SubscribeCard />
<SubscribeCard plan_code={isSubscribe.plan} />
</div>
)}
</>
+120 -113
View File
@@ -11,7 +11,7 @@ import { RWebShare } from "react-web-share";
import Tour from "reactour";
import Parse from "parse";
import {
checkIsSubscribedTeam,
checkIsSubscribed,
copytoData,
fetchUrl,
replaceMailVaribles
@@ -27,6 +27,7 @@ import BulkSendUi from "../components/BulkSendUi";
import Loader from "./Loader";
import Select from "react-select";
import SubscribeCard from "./SubscribeCard";
import { validplan } from "../json/plansArr";
const ReportTable = (props) => {
const navigate = useNavigate();
@@ -352,10 +353,10 @@ const ReportTable = (props) => {
handleBulkSend(item);
} else if (act.action === "sharewith") {
if (isEnableSubscription) {
const getIsSubscribe = await checkIsSubscribedTeam();
setIsSubscribe(getIsSubscribe);
const subscribe = await checkIsSubscribed();
setIsSubscribe(subscribe);
} else {
setIsSubscribe(true);
setIsSubscribe({ plan: "teams-yearly", isValid: true });
}
if (item?.SharedWith && item?.SharedWith.length > 0) {
// below code is used to get existing sharewith teams and formated them as per react-select
@@ -1472,118 +1473,124 @@ const ReportTable = (props) => {
{isShareWith[item.objectId] && (
<div className="op-modal op-modal-open">
<div className="max-h-90 bg-base-100 w-[95%] md:max-w-[500px] rounded-box relative">
{isSubscribe && isEnableSubscription && (
<>
{item?.Signers?.length > 0 ? (
<div className="h-[150px] flex justify-center items-center mx-2">
<div
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-2 z-40"
onClick={() => setIsShareWith({})}
>
{validplan[isSubscribe.plan] &&
isEnableSubscription && (
<>
{item?.Signers?.length > 0 ? (
<div className="h-[150px] flex justify-center items-center mx-2">
<div
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-2 z-40"
onClick={() => setIsShareWith({})}
>
</div>
<div className="text-base-content text-base text-center">
You cannot share a template if any
roles already have contacts
assigned. Please remove all contact
assignments from the roles before
sharing the template.
</div>
</div>
<div className="text-base-content text-base text-center">
You cannot share a template if any
roles already have contacts assigned.
Please remove all contact assignments
from the roles before sharing the
template.
</div>
</div>
) : (
<>
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
Share with
</h3>
<div
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-2 z-40"
onClick={() => setIsShareWith({})}
>
</div>
<form
className="h-full w-full z-[1300] px-2 mt-3"
onSubmit={(e) =>
handleShareWith(e, item)
}
>
<Select
// onSortEnd={onSortEnd}
distance={4}
isMulti
options={teamList}
value={selectedTeam}
onChange={onChange}
closeMenuOnSelect
required={true}
noOptionsMessage={() =>
"Team not found"
) : (
<>
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
Share with
</h3>
<div
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-2 z-40"
onClick={() => setIsShareWith({})}
>
</div>
<form
className="h-full w-full z-[1300] px-2 mt-3"
onSubmit={(e) =>
handleShareWith(e, item)
}
unstyled
classNames={{
control: () =>
"op-input op-input-bordered op-input-sm border-gray-400 focus:outline-none hover:border-base-content w-full h-full text-[11px]",
valueContainer: () =>
"flex flex-row gap-x-[2px] gap-y-[2px] md:gap-y-0 w-full my-[2px]",
multiValue: () =>
"op-badge op-badge-primary h-full text-[11px]",
multiValueLabel: () => "mb-[2px]",
menu: () =>
"mt-1 shadow-md rounded-lg bg-base-200 text-base-content",
menuList: () =>
"shadow-md rounded-lg overflow-hidden",
option: () =>
"bg-base-200 text-base-content rounded-lg m-1 hover:bg-base-300 p-2",
noOptionsMessage: () =>
"p-2 bg-base-200 rounded-lg m-1 p-2"
}}
/>
<button className="op-btn op-btn-primary ml-[10px] my-3">
Submit
</button>
</form>
</>
)}
</>
)}
{!isSubscribe && isEnableSubscription && (
<>
<div
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-primary-content absolute right-2 top-2 z-40"
onClick={() => setIsShareWith({})}
>
</div>
<SubscribeCard
plan={"TEAMS"}
price={"20"}
/>
</>
)}
{isSubscribe && !isEnableSubscription && (
<>
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
Share with
</h3>
<div
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-2 z-40"
onClick={() => setIsShareWith({})}
>
</div>
<div className="px-2 mt-3 w-full h-full">
<div className="op-input op-input-bordered op-input-sm w-full h-full text-[13px] break-all">
{selectedTeam?.[0]?.label}
>
<Select
// onSortEnd={onSortEnd}
distance={4}
isMulti
options={teamList}
value={selectedTeam}
onChange={onChange}
closeMenuOnSelect
required={true}
noOptionsMessage={() =>
"Team not found"
}
unstyled
classNames={{
control: () =>
"op-input op-input-bordered op-input-sm border-gray-400 focus:outline-none hover:border-base-content w-full h-full text-[11px]",
valueContainer: () =>
"flex flex-row gap-x-[2px] gap-y-[2px] md:gap-y-0 w-full my-[2px]",
multiValue: () =>
"op-badge op-badge-primary h-full text-[11px]",
multiValueLabel: () =>
"mb-[2px]",
menu: () =>
"mt-1 shadow-md rounded-lg bg-base-200 text-base-content",
menuList: () =>
"shadow-md rounded-lg overflow-hidden",
option: () =>
"bg-base-200 text-base-content rounded-lg m-1 hover:bg-base-300 p-2",
noOptionsMessage: () =>
"p-2 bg-base-200 rounded-lg m-1 p-2"
}}
/>
<button className="op-btn op-btn-primary ml-[10px] my-3">
Submit
</button>
</form>
</>
)}
</>
)}
{!validplan[isSubscribe.plan] &&
isEnableSubscription && (
<>
<div
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-primary-content absolute right-2 top-2 z-40"
onClick={() => setIsShareWith({})}
>
</div>
</div>
<button
onClick={(e) => handleShareWith(e, item)}
className="op-btn op-btn-primary ml-[10px] my-3"
>
Submit
</button>
</>
)}
<SubscribeCard
plan={"TEAMS"}
price={"20"}
/>
</>
)}
{validplan[isSubscribe.plan] &&
!isEnableSubscription && (
<>
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
Share with
</h3>
<div
className="op-btn op-btn-sm op-btn-circle op-btn-ghost text-base-content absolute right-2 top-2 z-40"
onClick={() => setIsShareWith({})}
>
</div>
<div className="px-2 mt-3 w-full h-full">
<div className="op-input op-input-bordered op-input-sm w-full h-full text-[13px] break-all">
{selectedTeam?.[0]?.label}
</div>
</div>
<button
onClick={(e) =>
handleShareWith(e, item)
}
className="op-btn op-btn-primary ml-[10px] my-3"
>
Submit
</button>
</>
)}
</div>
</div>
)}
+12 -2
View File
@@ -1,8 +1,18 @@
import React from "react";
import { useNavigate } from "react-router-dom";
import { paidUrl } from "../json/plansArr";
import { openInNewTab } from "../constant/Utils";
const SubscribeCard = ({ plan, price }) => {
const SubscribeCard = ({ plan, price, plan_code }) => {
const navigate = useNavigate();
const handlePaidRoute = () => {
const route = paidUrl(plan_code);
if (route === "/subscription") {
navigate(route);
} else {
openInNewTab(route, "_self");
}
};
return (
<div className="op-card op-bg-primary text-primary-content w-full shadow-lg">
<div className="op-card-body">
@@ -13,7 +23,7 @@ const SubscribeCard = ({ plan, price }) => {
</p>
<div className="op-card-actions justify-end">
<button
onClick={() => navigate("/subscription")}
onClick={() => handlePaidRoute()}
className="op-btn op-btn-accent"
>
Upgrade Now
@@ -1,9 +1,9 @@
export default async function saveSubscription(request, response) {
const SubscriptionId = request.body.data.subscription.subscription_id;
const SubscriptionId = request.body?.data?.subscription?.subscription_id;
const body = request.body;
const Email = request.body.data.subscription.customer.email;
const Next_billing_date = request.body.data.subscription.next_billing_at;
const planCode = request.body.data.subscription.plan.plan_code;
const Email = request.body.data?.subscription?.customer?.email;
const Next_billing_date = request.body?.data?.subscription?.next_billing_at;
const planCode = request.body?.data?.subscription?.plan?.plan_code;
const addons = request.body?.data?.subscription?.addons || [];
const existAddon = addons.reduce((acc, curr) => acc + curr.quantity, 1);
try {
@@ -23,7 +23,11 @@ export default async function saveSubscription(request, response) {
updateSubscription.id = subscription.id;
updateSubscription.set('SubscriptionId', SubscriptionId);
updateSubscription.set('SubscriptionDetails', body);
updateSubscription.set('Next_billing_date', new Date(Next_billing_date));
if (Next_billing_date) {
updateSubscription.set('Next_billing_date', new Date(Next_billing_date));
} else {
updateSubscription.unset('Next_billing_date');
}
updateSubscription.set('PlanCode', planCode);
updateSubscription.set('AllowedUsers', parseInt(existAddon));
await updateSubscription.save(null, { useMasterKey: true });
@@ -47,7 +51,11 @@ export default async function saveSubscription(request, response) {
className: 'partners_Tenant',
objectId: extUser.get('TenantId').id,
});
createSubscription.set('Next_billing_date', new Date(Next_billing_date));
if (Next_billing_date) {
createSubscription.set('Next_billing_date', new Date(Next_billing_date));
} else {
createSubscription.unset('Next_billing_date');
}
createSubscription.set('PlanCode', planCode);
createSubscription.set('AllowedUsers', parseInt(existAddon));
await createSubscription.save(null, { useMasterKey: true });
@@ -75,7 +75,7 @@ export default async function Buyaddon(request) {
updateSub.set('SubscriptionDetails', userData.data);
updateSub.set('AllowedUsers', allowedUsers);
const resupdateSub = await updateSub.save(null, { useMasterKey: true });
return 'success';
return { status: 'success', addon: allowedUsers };
} else {
throw new Parse.Error('400', 'Invalid access token.');
}