Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 46 additions & 11 deletions apps/OpenSign/src/pages/PdfRequestFiles.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -216,12 +216,18 @@ function PdfRequestFiles(
return () => clearTimeout(timer);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [divRef.current, isSidebar, windowSize?.width]);
const redirectUrl = pdfDetails?.[0]?.RedirectUrl || "";
const rawRedirectUrl = pdfDetails?.[0]?.RedirectUrl || "";
const redirectUrl = rawRedirectUrl
? rawRedirectUrl.startsWith("http://") || rawRedirectUrl.startsWith("https://")
? rawRedirectUrl
: `https://${rawRedirectUrl}`
: "";

useEffect(() => {
if (isredirectCanceled) return; // Stop the redirect timer if canceled
if (redirectUrl) {
if (redirectTimeLeft === 0) {
openInNewTab(redirectUrl, "_self"); // Replace with your target URL
window.location.href = redirectUrl;
}
const timer = setTimeout(() => {
setRedirectTimeLeft((prev) => prev - 1); // Decrement the timer
Expand Down Expand Up @@ -789,6 +795,9 @@ function PdfRequestFiles(
setIsSigned(true);
setSignedSigners([]);
setUnSignedSigners([]);
if (redirectUrl) {
setIsredirectCanceled(false);
}
const isSuccessRoute = pdfDetails?.[0]?.RedirectUrl
? false
: window.location?.pathname?.includes("load");
Expand All @@ -799,22 +808,22 @@ function PdfRequestFiles(
contactId
);
const index =
updatedDoc.updatedPdfDetails?.[0]?.Signers.findIndex(
updatedDoc?.updatedPdfDetails?.[0]?.Signers?.findIndex(
(x) => x.objectId === contactId
);
) ?? -1;
const removePrefill =
updatedDoc.updatedPdfDetails?.[0]?.Placeholders?.filter(
updatedDoc?.updatedPdfDetails?.[0]?.Placeholders?.filter(
(x) => x.Role !== "prefill"
);
) || [];
// Skip viewer placeholders when computing the next signer
// to notify (viewers do not gate sequential signing).
let newIndex = index + 1;
let newIndex = index >= 0 ? index + 1 : 0;
const usermail = {
Email: removePrefill[newIndex]?.email || ""
Email: removePrefill?.[newIndex]?.email || ""
};
const user = usermail?.Email
? usermail
: updatedDoc.updatedPdfDetails?.[0]?.Signers[newIndex];
: updatedDoc?.updatedPdfDetails?.[0]?.Signers?.[newIndex];
if (
sendmail !== "false" &&
sendInOrder
Expand Down Expand Up @@ -1177,6 +1186,10 @@ function PdfRequestFiles(
const currentDecline = { currnt: "YouDeclined", isDeclined: true };
setIsDecline(currentDecline);
setIsUiLoading(false);
// Trigger redirect timer if a RedirectUrl is configured
if (redirectUrl) {
setIsredirectCanceled(false);
}
}
})
.catch((err) => {
Expand Down Expand Up @@ -1871,12 +1884,34 @@ function PdfRequestFiles(
{/* this modal is used to show decline alert */}
<PdfDeclineModal
show={isDecline.isDeclined}
headMsg={t("document-declined")}
headMsg={
isDecline.currnt === "Sure"
? pdfDetails?.[0]?.Name
? `${t("decline")} "${pdfDetails[0].Name}"`
: t("decline-document")
: t("document-declined")
}
bodyMssg={
isDecline.currnt === "Sure"
? t("decline-alert-1")
: isDecline.currnt === "YouDeclined"
? t("decline-alert-2")
? (
<div>
<p className="mb-3">{t("decline-alert-2")}</p>
{!isredirectCanceled && redirectUrl ? (
<div className="flex flex-row gap-1 items-center justify-center p-3 bg-base-200 rounded-lg text-sm">
<p>{t("redirecting-you-in", { redirectTimeLeft })}</p>
<button
type="button"
onClick={handleRedirectCancel}
className="underline cursor-pointer op-text-primary focus:outline-none ml-2"
>
{t("cancel")}
</button>
</div>
) : null}
</div>
)
: isDecline.currnt === "another" && handleDeclineMssg()
}
footerMessage={isDecline.currnt === "Sure"}
Expand Down
114 changes: 71 additions & 43 deletions apps/OpenSign/src/primitives/PdfDeclineModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,110 +31,138 @@ function CustomModal(props) {

return (
props.show && (
<dialog className="op-modal op-modal-open absolute z-[448]">
<div className="w-[95%] md:w-[60%] lg:w-[40%] op-modal-box p-0 overflow-y-auto hide-scrollbar text-sm">
<dialog className="op-modal op-modal-open" style={{ zIndex: 448 }}>
<div className="w-[90%] max-w-[440px] op-modal-box p-6 bg-base-100 rounded-2xl shadow-2xl relative max-h-[90vh] overflow-y-auto hide-scrollbar text-sm">
{props?.isLoader && (
<div className="absolute h-full w-full flex flex-col justify-center items-center z-[999] bg-[#e6f2f2]/80">
<div className="absolute inset-0 flex flex-col justify-center items-center z-[999] bg-base-100/80 backdrop-blur-sm rounded-2xl">
<Loader />
</div>
)}
<h3 className="text-base-content font-bold text-lg pt-[15px] px-[20px]">
{props?.headMsg && props?.headMsg}
</h3>
{!isExtendExpiry && (
<div className="p-[10px] px-[20px] text-[15px] text-base-content">
{props.bodyMssg && props.bodyMssg}

{/* Close button for info-only state */}
{!props.footerMessage && !isCreator && !props.isDownloadBtn && (
<button
className="text-base-content/60 hover:text-base-content op-btn op-btn-xs op-btn-circle op-btn-ghost absolute right-3.5 top-3.5 z-40"
onClick={() => props.setIsDecline && props.setIsDecline({ isDeclined: false })}
>
</button>
)}

{/* Header Title */}
<div className="mb-3">
<h3 className="text-base-content font-bold text-lg leading-snug">
{props?.headMsg && props.headMsg}
</h3>
</div>

{/* Body message */}
{!isExtendExpiry && props.bodyMssg && (
<div className="text-sm leading-relaxed text-base-content/80 mb-4">
{props.bodyMssg}
</div>
)}
{!isExtendExpiry && (
<div className="flex flex-row items-center">

{/* Buttons for Creator Extend / Download */}
{!isExtendExpiry && (isCreator || props.isDownloadBtn) && (
<div className="flex flex-row items-center justify-end gap-2 mt-4">
{isCreator && (
<button
className="op-btn op-btn-primary px-6 ml-[20px] mb-3 mt-1"
className="op-btn op-btn-primary op-btn-sm rounded-xl px-4 font-semibold"
onClick={() => handleExtendBtn()}
>
{t("extend")}
</button>
)}
{props.isDownloadBtn && (
<button
className="op-btn op-btn-secondary ml-[10px] mb-3 mt-1"
className="op-btn op-btn-secondary op-btn-sm rounded-xl px-4 font-semibold"
onClick={() => props.handleDownloadBtn()}
>
{t("download")}
</button>
)}
</div>
)}

{/* Decline Confirmation Form */}
{props.footerMessage && (
<>
<div className="mx-3 text-base-content">
<textarea
rows={3}
placeholder="Reason (optional)"
className="px-4 op-textarea op-textarea-bordered focus:outline-none hover:border-base-content w-full text-xs"
value={reason}
onChange={(e) => setReason(e.target.value)}
></textarea>
</div>
<div className="m-[15px]">
<div className="mt-3">
<label className="block text-xs font-semibold text-base-content/70 mb-1.5">
{t("reason")} <span className="font-normal text-base-content/50">({t("optional")})</span>
</label>
<textarea
rows={3}
placeholder={t("reason")}
className="px-3.5 py-2.5 op-textarea op-textarea-bordered w-full text-xs rounded-xl focus:outline-none hover:border-base-content transition-all resize-none"
value={reason}
onChange={(e) => setReason(e.target.value)}
/>
<div className="flex flex-row items-center justify-end gap-2 mt-4">
<button
className="op-btn op-btn-primary mr-2 px-6"
type="button"
className="op-btn op-btn-ghost op-btn-sm rounded-xl font-semibold text-base-content"
onClick={() => {
props.declineDoc(reason);
setReason("");
props.setIsDecline({ isDeclined: false });
}}
>
{t("yes")}
{t("cancel")}
</button>
<button
type="button"
className="op-btn op-btn-secondary"
className="op-btn op-btn-primary op-btn-sm rounded-xl px-5 font-semibold"
onClick={() => {
props.declineDoc(reason);
setReason("");
props.setIsDecline({ isDeclined: false });
}}
>
{t("close")}
{t("yes")}
</button>
</div>
</>
</div>
)}

{/* Extend Expiry Form */}
{isExtendExpiry && (
<form className="mx-3 mb-3" onSubmit={handleUpdateExpiry}>
<label
htmlFor="expiryDate"
className="ml-2 mt-2 text-base-content"
>
{t("expiry-date")} {"(dd-mm-yyyy)"}
<form className="mt-3" onSubmit={handleUpdateExpiry}>
<label htmlFor="expiryDate" className="block text-xs font-semibold text-base-content/70 mb-1.5">
{t("expiry-date")} (dd-mm-yyyy)
</label>
<input
id="expiryDate"
type="date"
onClick={(e) => e?.currentTarget?.showPicker?.()}
className="rounded-full w-full px-4 op-input op-input-bordered op-input-md text-base-content focus:outline-none hover:border-base-content"
className="w-full px-3.5 py-2 rounded-xl op-input op-input-bordered text-xs text-base-content focus:outline-none hover:border-base-content"
defaultValue={props?.doc?.ExpiryDate?.iso?.split("T")?.[0]}
onChange={(e) => setExpiryDate(e.target.value)}
/>
<div className="flex flex-row items-center mt-2">
<button type="submit" className="op-btn op-btn-primary mr-2">
{t("update")}
</button>
<div className="flex flex-row items-center justify-end gap-2 mt-4">
<button
type="button"
className="op-btn op-btn-secondary"
className="op-btn op-btn-ghost op-btn-sm rounded-xl font-semibold text-base-content"
onClick={() => {
setExpiryDate("");
setIsExtendExpiry(false);
}}
>
{t("cancel")}
</button>
<button type="submit" className="op-btn op-btn-primary op-btn-sm rounded-xl px-5 font-semibold">
{t("update")}
</button>
</div>
</form>
)}
</div>

{/* Backdrop overlay */}
{!props.footerMessage && (
<div
className="op-modal-backdrop"
onClick={() => props.setIsDecline && props.setIsDecline({ isDeclined: false })}
/>
)}
</dialog>
)
);
Expand Down