Skip to content

Commit 6348692

Browse files
Merge pull request #1199 from OpenSignLabs/validation
2 parents 39472d6 + c36a70f commit 6348692

File tree

7 files changed

+216
-61
lines changed

7 files changed

+216
-61
lines changed

apps/OpenSign/public/locales/en/translation.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,8 @@
636636
"quota-mail-tip":"Tip: You can still sign <1>unlimited documents</1> by manually sharing the signing request links.",
637637
"quota-mail-head":"Quota Reached",
638638
"unauthorized-modal":"You don't have permission to perform this action, please contact {{adminName}}<{{adminEmail}}>.",
639-
"sent-this-month":"Sent this month"
639+
"sent-this-month":"Sent this month",
640+
"available-seats":"Available seats",
641+
"buy-users":"Buy more users"
640642

641643
}

apps/OpenSign/public/locales/fr/translation.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@
635635
"quota-mail-tip-tip":"Astuce : Vous pouvez toujours signer un nombre <1>illimité de documents</1> en partageant manuellement les liens de demande de signature.",
636636
"quota-mail-head":"Quota atteint",
637637
"unauthorized-modal":"Vous n'êtes pas autorisé à effectuer cette action, veuillez contacter {{adminName}}<{{adminEmail}}>.",
638-
"sent-this-month":"envoyé ce mois-ci"
639-
638+
"sent-this-month":"envoyé ce mois-ci",
639+
"available-seats":"Disponible sièges",
640+
"buy-users":"Acheter plus d'utilisateurs"
640641
}

apps/OpenSign/src/layout/HomeLayout.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,9 @@ const HomeLayout = () => {
252252
}
253253
};
254254

255-
const handleLoginBtn = () => {
255+
const handleLoginBtn = async () => {
256256
try {
257-
Parse?.User?.logOut();
257+
await Parse?.User?.logOut();
258258
} catch (err) {
259259
console.log("err ", err);
260260
} finally {

apps/OpenSign/src/pages/PlanSubscriptions.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,9 @@ const PlanSubscriptions = () => {
121121
};
122122
const handleLogout = async () => {
123123
try {
124-
Parse?.User?.logOut();
124+
await Parse?.User?.logOut();
125125
} catch (err) {
126-
console.log("Err", err);
126+
console.log("Err while logging out", err);
127127
}
128128
let appdata = localStorage.getItem("userSettings");
129129
let applogo = localStorage.getItem("appLogo");

apps/OpenSign/src/pages/UserList.js

Lines changed: 200 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Tooltip from "../primitives/Tooltip";
99
import AddUser from "../components/AddUser";
1010
import SubscribeCard from "../primitives/SubscribeCard";
1111
import { isEnableSubscription } from "../constant/const";
12-
import { checkIsSubscribed } from "../constant/Utils";
12+
import { fetchSubscriptionInfo } from "../constant/Utils";
1313
import Title from "../components/Title";
1414
import { validplan } from "../json/plansArr";
1515
import { useTranslation } from "react-i18next";
@@ -19,17 +19,28 @@ const UserList = () => {
1919
const { t } = useTranslation();
2020
const [userList, setUserList] = useState([]);
2121
const [isLoader, setIsLoader] = useState(false);
22-
const [isModal, setIsModal] = useState(false);
22+
const [isModal, setIsModal] = useState({
23+
form: false,
24+
addseats: false,
25+
options: false
26+
});
2327
const location = useLocation();
2428
const isDashboard =
2529
location?.pathname === "/dashboard/35KBoSgoAK" ? true : false;
2630
const [currentPage, setCurrentPage] = useState(1);
2731
const [isAlert, setIsAlert] = useState({ type: "success", msg: "" });
2832
const [isActiveModal, setIsActiveModal] = useState({});
2933
const [isActLoader, setIsActLoader] = useState({});
30-
const [isSubscribe, setIsSubscribe] = useState({ plan: "", isValid: false });
34+
const [isSubscribe, setIsSubscribe] = useState({
35+
plan: "",
36+
isValid: false,
37+
priceperUser: 0
38+
});
3139
const [isAdmin, setIsAdmin] = useState(false);
3240
const [formHeader, setFormHeader] = useState(t("add-user"));
41+
const [usersCount, setUserCounts] = useState({ allowed: 0, totalAllowed: 0 });
42+
const [amount, setAmount] = useState({ quantity: 1, price: 0 });
43+
const [isBuyLoader, setIsBuyLoader] = useState(false);
3344
const recordperPage = 10;
3445
const startIndex = (currentPage - 1) * recordperPage; // user per page
3546

@@ -81,7 +92,6 @@ const UserList = () => {
8192
pages.push(lastPageIndex);
8293
}
8394
}
84-
8595
return pages;
8696
};
8797
const pageNumbers = getPaginationRange();
@@ -96,13 +106,44 @@ const UserList = () => {
96106
async function fetchUserList() {
97107
try {
98108
setIsLoader(true);
109+
const extUser =
110+
localStorage.getItem("Extand_Class") &&
111+
JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
99112
if (isEnableSubscription) {
100-
const subscribe = await checkIsSubscribed();
101-
setIsSubscribe(subscribe);
113+
const subscribe = await fetchSubscriptionInfo();
114+
if (subscribe?.plan_code?.includes("team")) {
115+
const isSupAdmin =
116+
subscribe?.adminId && extUser?.objectId === subscribe?.adminId;
117+
setIsSubscribe({
118+
plan: subscribe.plan_code,
119+
isValid: true,
120+
adminId: subscribe.adminId,
121+
priceperUser: subscribe.price,
122+
isSuperAdmin: isSupAdmin
123+
});
124+
setAmount((prev) => ({ ...prev, price: subscribe.price }));
125+
try {
126+
const res = await Parse.Cloud.run("allowedusers");
127+
console.log("res ", res);
128+
setUserCounts((obj) => ({
129+
...obj,
130+
allowed: res,
131+
totalAllowed: subscribe?.totalAllowedUser || 0
132+
}));
133+
} catch (err) {
134+
console.log("err while get users", err);
135+
}
136+
} else {
137+
setIsSubscribe({
138+
plan: subscribe.plan_code,
139+
isValid: false,
140+
adminId: subscribe.adminId
141+
});
142+
}
102143
} else {
103144
setIsSubscribe({ plan: "teams-yearly", isValid: true });
104145
}
105-
const extUser = JSON.parse(localStorage.getItem("Extand_Class"))?.[0];
146+
106147
if (extUser) {
107148
const admin =
108149
extUser?.UserRole &&
@@ -121,14 +162,12 @@ const UserList = () => {
121162
console.log("Err in fetch userlist", err);
122163
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
123164
} finally {
124-
setTimeout(() => {
125-
setIsAlert({ type: "success", msg: "" });
126-
}, 1500);
165+
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 1500);
127166
setIsLoader(false);
128167
}
129168
}
130-
const handleFormModal = () => {
131-
setIsModal(!isModal);
169+
const handleModal = (modalName) => {
170+
setIsModal((obj) => ({ ...obj, [modalName]: !obj[modalName] }));
132171
};
133172

134173
// Change page
@@ -196,6 +235,39 @@ const UserList = () => {
196235
const handleToggleBtn = (user) => {
197236
setIsActiveModal({ [user.objectId]: true });
198237
};
238+
239+
const handleAddOnSubmit = async (e) => {
240+
e.preventDefault();
241+
e.stopPropagation();
242+
setIsBuyLoader(true);
243+
try {
244+
const resAddon = await Parse.Cloud.run("buyaddonusers", {
245+
users: amount.quantity
246+
});
247+
if (resAddon) {
248+
const _resAddon = JSON.parse(JSON.stringify(resAddon));
249+
if (_resAddon.status === "success") {
250+
setUserCounts((obj) => ({
251+
...obj,
252+
allowed: obj.allowed + amount.quantity,
253+
totalAllowed: _resAddon.addon
254+
}));
255+
}
256+
}
257+
} catch (err) {
258+
console.log("Err in buy addon", err);
259+
setIsAlert({ type: "danger", msg: t("something-went-wrong-mssg") });
260+
} finally {
261+
setTimeout(() => setIsAlert({ type: "success", msg: "" }), 2000);
262+
setIsBuyLoader(false);
263+
handleModal("addseats");
264+
}
265+
};
266+
const handlePricePerUser = (e) => {
267+
const quantity = e.target.value;
268+
const price = e.target?.value > 0 ? isSubscribe.priceperUser * quantity : 0;
269+
setAmount((prev) => ({ ...prev, quantity: quantity, price: price }));
270+
};
199271
return (
200272
<div className="relative">
201273
<Title title={isAdmin ? "Users" : "Page not found"} />
@@ -205,7 +277,7 @@ const UserList = () => {
205277
</div>
206278
)}
207279
{Object.keys(isActLoader)?.length > 0 && (
208-
<div className="absolute w-full h-full flex justify-center items-center bg-black bg-opacity-30 z-30 rounded-box">
280+
<div className="absolute w-full h-full flex justify-center items-center bg-black/30 z-30 rounded-box">
209281
<Loader />
210282
</div>
211283
)}
@@ -216,19 +288,46 @@ const UserList = () => {
216288
{isAlert.msg && <Alert type={isAlert.type}>{isAlert.msg}</Alert>}
217289
<div className="flex flex-row items-center justify-between my-2 mx-3 text-[20px] md:text-[23px]">
218290
<div className="font-light">
219-
{t("report-name.Users")}
291+
{t("report-name.Users")}{" "}
220292
<span className="text-xs md:text-[13px] font-normal">
221293
<Tooltip message={t("users-from-teams")} />
222294
</span>
223295
</div>
224-
<div
225-
className="cursor-pointer"
226-
onClick={() => handleFormModal()}
227-
>
228-
<i className="fa-light fa-square-plus text-accent text-[40px]"></i>
296+
<div className="flex flex-row gap-2 items-center">
297+
{isEnableSubscription && isSubscribe?.isSuperAdmin && (
298+
<div
299+
className="hidden md:flex op-btn op-btn-sm h-[35px] op-btn-primary op-btn-outline text-xs mb-0.5"
300+
onClick={() => handleModal("addseats")}
301+
>
302+
{t("buy-users")}
303+
</div>
304+
)}
305+
<div
306+
className="cursor-pointer"
307+
onClick={() => handleModal("form")}
308+
>
309+
<i className="fa-light fa-square-plus text-accent text-[30px] md:text-[40px]"></i>
310+
</div>
311+
{isEnableSubscription && isSubscribe?.isSuperAdmin && (
312+
<div
313+
className="cursor-pointer relative md:hidden mb-0.5"
314+
onClick={() => handleModal("options")}
315+
>
316+
<i className="fa-light fa-ellipsis-vertical fa-xl"></i>
317+
{isModal?.options && (
318+
<ul className="absolute -right-3 top-auto z-[70] w-max op-menu op-menu-xs shadow bg-base-100 text-base-content rounded-box border">
319+
<li onClick={() => handleModal("addseats")}>
320+
<span className="text-[13px] capitalize font-medium">
321+
{t("buy-users")}
322+
</span>
323+
</li>
324+
</ul>
325+
)}
326+
</div>
327+
)}
229328
</div>
230329
</div>
231-
<div className={` overflow-x-auto w-full`}>
330+
<div className="overflow-x-auto w-full">
232331
<table className="op-table border-collapse w-full">
233332
<thead className="text-[14px]">
234333
<tr className="border-y-[1px]">
@@ -313,34 +412,42 @@ const UserList = () => {
313412
</tbody>
314413
</table>
315414
</div>
316-
<div className="op-join flex flex-wrap items-center p-2">
317-
{userList.length > recordperPage && (
318-
<button
319-
onClick={() => paginateBack()}
320-
className="op-join-item op-btn op-btn-sm"
321-
>
322-
{t("prev")}
323-
</button>
324-
)}
325-
{pageNumbers.map((x, i) => (
326-
<button
327-
key={i}
328-
onClick={() => setCurrentPage(x)}
329-
disabled={x === "..."}
330-
className={`${
331-
x === currentPage ? "op-btn-active" : ""
332-
} op-join-item op-btn op-btn-sm`}
333-
>
334-
{x}
335-
</button>
336-
))}
337-
{userList.length > recordperPage && (
338-
<button
339-
onClick={() => paginateFront()}
340-
className="op-join-item op-btn op-btn-sm"
341-
>
342-
{t("next")}
343-
</button>
415+
<div className="flex flex-row justify-between items-center text-xs font-medium">
416+
<div className="op-join flex flex-wrap items-center p-2">
417+
{userList.length > recordperPage && (
418+
<button
419+
onClick={() => paginateBack()}
420+
className="op-join-item op-btn op-btn-sm"
421+
>
422+
{t("prev")}
423+
</button>
424+
)}
425+
{pageNumbers.map((x, i) => (
426+
<button
427+
key={i}
428+
onClick={() => setCurrentPage(x)}
429+
disabled={x === "..."}
430+
className={`${
431+
x === currentPage ? "op-btn-active" : ""
432+
} op-join-item op-btn op-btn-sm`}
433+
>
434+
{x}
435+
</button>
436+
))}
437+
{userList.length > recordperPage && (
438+
<button
439+
onClick={() => paginateFront()}
440+
className="op-join-item op-btn op-btn-sm"
441+
>
442+
{t("next")}
443+
</button>
444+
)}
445+
</div>
446+
{isEnableSubscription && isSubscribe?.isSuperAdmin && (
447+
<div>
448+
{t("available-seats")}: {usersCount.allowed}/
449+
{usersCount.totalAllowed}
450+
</div>
344451
)}
345452
</div>
346453
{userList?.length <= 0 && (
@@ -362,17 +469,59 @@ const UserList = () => {
362469
</div>
363470
)}
364471
<ModalUi
365-
isOpen={isModal}
472+
isOpen={isModal.form}
366473
title={formHeader}
367-
handleClose={handleFormModal}
474+
handleClose={() => handleModal("form")}
368475
>
369476
<AddUser
370477
setIsAlert={setIsAlert}
371478
handleUserData={handleUserData}
372-
closePopup={handleFormModal}
479+
closePopup={() => handleModal("form")}
373480
setFormHeader={setFormHeader}
374481
/>
375482
</ModalUi>
483+
<ModalUi
484+
isOpen={isModal.addseats}
485+
title="Add Seats"
486+
handleClose={() => handleModal("addseats")}
487+
>
488+
{isBuyLoader && (
489+
<div className="absolute w-full h-full inset-0 flex justify-center items-center bg-base-content/30 z-50">
490+
<Loader />
491+
</div>
492+
)}
493+
<form onSubmit={handleAddOnSubmit} className=" px-3 pb-6 pt-6">
494+
<div className="mb-3 flex justify-between">
495+
<label
496+
htmlFor="quantity"
497+
className="block text-xs text-gray-700 font-semibold"
498+
>
499+
{t("Quantity-of-users")}
500+
<span className="text-[red] text-[13px]"> *</span>
501+
</label>
502+
<input
503+
type="number"
504+
name="quantity"
505+
value={amount.quantity}
506+
onChange={(e) => handlePricePerUser(e)}
507+
className="w-1/4 op-input op-input-bordered op-input-sm focus:outline-none hover:border-base-content text-xs"
508+
required
509+
/>
510+
</div>
511+
<div className="mb-3 flex justify-between">
512+
<label className="block text-xs text-gray-700 font-semibold">
513+
{t("Price")} (1 * {isSubscribe.priceperUser})
514+
</label>
515+
<div className="w-1/4 flex justify-center items-center text-sm">
516+
USD {amount.price}
517+
</div>
518+
</div>
519+
<hr className="text-base-content mb-3" />
520+
<button className="op-btn op-btn-primary w-full">
521+
{t("Proceed")}
522+
</button>
523+
</form>
524+
</ModalUi>
376525
</div>
377526
) : (
378527
<div className="flex items-center justify-center h-screen w-full bg-base-100 text-base-content rounded-box">

0 commit comments

Comments
 (0)