import { useEffect, useRef, useState } from "react"; import axios from "axios" import { RootState } from "../../store/store"; import { useNavigate, useParams } from "react-router-dom" import { DroppedItem, TagsTypes } from "../../utlity/types"; import Loader from "../dashboard/Loader"; import ClientSignCon from "../signature/ClientSignCon"; import { Bounce, toast } from "react-toastify"; import { useDispatch, useSelector } from "react-redux"; import { hideLoader, showLoader } from "../../store/slices/loaderSlice"; import { FaCheck, FaQuestionCircle, FaDownload, FaAngleUp, FaPrint } from 'react-icons/fa' import { IoIosDocument, IoMdClose } from 'react-icons/io' import { MdKeyboardArrowDown, MdNavigateNext } from 'react-icons/md' import confetti from 'canvas-confetti' import dayjs from "dayjs"; import StampUpload from "../stamp/StampUpload"; import DocumentPages from "./DocumentPages"; import FieldList from "../process/processStepTwo/FieldList"; import typeToIconMap from "../../helper/iconMap"; import TagProperties from "../process/processStepTwo/tagProperties/TagProperties"; import TagsCon from "./TagsCon"; import ConsentScreen from "./ConsentScreen"; import SignButton from "./SignButton"; import DeclineModal from "./DeclineModal"; import ReassignModal from "./ReassignModal"; import ClientAuditModal from "./ClientAuditModal"; import axiosInstance from "../../config/axiosInstance"; import "./style.css"; import ConfirmSignModal from "./ConfirmSignModal"; import { AiOutlineAudit, AiOutlineDownload } from "react-icons/ai"; import { SlPrinter } from "react-icons/sl"; import { CgPrinter } from "react-icons/cg"; import { ImPrinter } from "react-icons/im"; import { RiFileHistoryFill } from "react-icons/ri"; import { IoDocumentsOutline } from "react-icons/io5"; interface RecipientType { id: string; firstName: string | null; lastName: string; fullName: string | null; email: string; title: string | null; initials: string | null; company: string | null; website: string | null; phone: string | null; index: number; type: string; provideOwnTags: boolean; recipientStatus: string; authType: string | null; language: string | null; transaction: string | null; acceptedTerms: boolean; name: string | null; } interface pagesType { index: number; type: string; src: string; height: number; width: number; } export interface DocumentType { documentId: string; pages: pagesType[]; name: string; } interface TransactionType { status: string; transationId: string; } interface TagSubmitData { id: string; type?: string; subType?: string; signed: boolean; value: string; } interface TagSubmitRecData { recipientId: string; } export enum SaveTypeEnum { DRAW = "DRAW", TYPE = "TEXT", UPLOAD = "IMAGE", SELECT = "SELECT", } export interface SaveType { signatureId: string | null saveType: SaveTypeEnum | null; save: boolean; signature: string | null; initial: string | null; isDefaultAndClicked?: boolean; font?: string; } interface TagsSubmitDataObj { tags: TagSubmitData[]; recipient?: TagSubmitRecData } interface SignConfType { accepted: boolean; index: number; } export interface SignConfTypeObj { [key: number]: SignConfType; } export interface StampTypeObj { open: boolean; blob: string; } interface FIT { label: string, value: number | null } const fitObj = [ { label: "Fit", value: "FIT" }, { label: "50%", value: "50" }, { label: "130%", value: "130" }, { label: "150%", value: "150" }, { label: "200%", value: "200" }, { label: "250%", value: "250" }, { label: "300%", value: "300" }, { label: "350%", value: "350" }, { label: "400%", value: "400" }, ] enum RightSideNav { ATTRIBUTES = "attributes", PAGES = "pages" } const SignDocument = () => { const windowWidth = window.innerWidth; const { recipientId } = useParams(); const dispatch = useDispatch(); const imageRefs = useRef<{ [key: string]: HTMLImageElement | null }>({}); // Signer data - START const [selectedDocuments, setSelectedDocuments] = useState(null); const [imageSizes, setImageSizes] = useState>({}); const [selectedTag, setSelectedTag] = useState<{ key: string, index: number } | null>(null); const [isPages, setIsPages] = useState(true); const [recipient, setRecipient] = useState(null); const [tagJson, setTagJson] = useState([]); const [transaction, setTransaction] = useState(null); const [recSignStatus, setRecSignStatus] = useState(null); const [droppedItems, setDroppedItems] = useState([]); const [signTagId, setSignTagId] = useState(0) const [showConfetti, setShowConfetti] = useState(false) const [pageScales, setPageScales] = useState>({}); const [requiredFilled, setRequiredFilled] = useState(false); const [horizontalFormLoader, setHorizontalFormLoader] = useState<{ requiredFilled: number, totalRequired: number | null }>({ requiredFilled: 0, totalRequired: null }); const [stamp, setStamp] = useState({ open: false, blob: "" }); const [signerConsent, setSignerConsent] = useState<{ consent: boolean; decline: boolean }>({ consent: false, decline: false }); const [declineOpen, setDeclineOpen] = useState(false); const [reassignOpen, setReassignOpen] = useState(false); const [auditHistoryOpen, setAuditHistoryOpen] = useState(false); const [rightSideNavToggle, setRightSideNavToggle] = useState(RightSideNav.PAGES); // Show is fields - Showing all fields There const [isFields, setIsFields] = useState(true); const [isFitDd, setIsFitDd] = useState(false) const [selFitIndx, setSelFitIndx] = useState(windowWidth > 638 ? 3 : 0); const globalLoader = useSelector((state: RootState) => state.loader) const [openSign, setOpenSign] = useState(false); const [focusElement, setFocusElement] = useState(null); const [dropDownTogglePage, setDropDownTogglePage] = useState(""); const [nav2DocToggle, setNav2DocToggle] = useState(false); const [hideTags, setHideTags] = useState(false); const [transparentTags, setTransparentTags] = useState(false); const [provideTags, setProvideTags] = useState(false) const [showCompletionScreen, setShowCompletionScreen] = useState(false) const [zoomScale, setZoomScale] = useState(windowWidth > 638 ? 150 : 100) const scaleFactor: number = (zoomScale ?? 100) / 100; // Handle Confirm Sign Modal - Start // Add state const [confirmSignOpen, setConfirmSignOpen] = useState(false); const [confirmSignLoading, setConfirmSignLoading] = useState(false); // Wrap handleFormSubmit const handleConfirmSign = async () => { setConfirmSignLoading(true); await handleFormSubmit(); setConfirmSignLoading(false); setConfirmSignOpen(false); }; // Handle Confirm Sign Modal - END // To center the container on every zoom scale change - START useEffect(() => { const container = document.getElementById("doc-con"); if (!container) return; const prevScrollRatio = container.scrollTop / (container.scrollHeight || 1); const newScrollTop = prevScrollRatio * container.scrollHeight; const newScrollLeft = (container.scrollWidth - container.clientWidth) / 2; container.scrollTo({ top: newScrollTop, left: newScrollLeft, behavior: "instant" as ScrollBehavior }); }, [zoomScale]); // To center the container on every zoom scale change - END // Handle Tags and Image Size - START useEffect(() => { const observers: ResizeObserver[] = []; Object.keys(imageRefs.current).forEach((key) => { const el = imageRefs.current[key]; if (!el) return; const observer = new ResizeObserver((entries) => { for (const entry of entries) { const { width, height } = entry.contentRect; setImageSizes((prev) => ({ ...prev, [key]: { width, height }, })); } }); observer.observe(el); observers.push(observer); }); return () => observers.forEach((o) => o.disconnect()); }, [selectedDocuments]); // re-run when documents load // Handle Tags anf Image Size = END const [saved, setSaved] = useState({ signatureId: null, saveType: null, save: false, signature: null, initial: null, }); enum NavigationTagPosEnum { ABOVE = "above", BELOW = "below", VISIBLE = "VISIBLE" } const [navigationTagPos, setNavigationTagPos] = useState(NavigationTagPosEnum.VISIBLE); const navigate = useNavigate(); const [signConfObj, setSignConfObj] = useState({}); const handleFitSelect = (indx: number) => { setSelFitIndx(indx); let value = fitObj[indx].value; if (value === "FIT") value = "100"; setZoomScale?.(Number(value)); } // const zoom = (percentage: number, contentClass: string) => { // const content = document.querySelector(`.${contentClass}`); // if (content) { // (content as HTMLElement).style.zoom = `${percentage}%`; // } // } // useEffect(() => { // let indx = fitObj[selFitIndx].value // if (indx == "FIT") { // indx = "100"; // } // zoom(Number(indx), 'zoom-con') // }, [selFitIndx]) const handleTagClick = (key: string, index: number) => { setSelectedTag({ key, index }) } useEffect(() => { dispatch(showLoader("Loading ...")); fetchData(); }, []) // Ping Request - START useEffect(() => { const intervalId = setInterval(() => { axiosInstance.get( `/api/v1/session/ping?sessionId=${recipientId}`, { maxRedirects: 5, headers: { "ngrok-skip-browser-warning": "69420" }, } ).catch(err => console.error("Ping failed:", err)); }, 60000); // first call happens after 1 min return () => clearInterval(intervalId); // cleanup on unmount }, [recipientId]); // Ping Request - END useEffect(() => { if (!focusElement) { if (droppedItems && droppedItems.length) { setFocusElement({ ...droppedItems[0], focusElementIndx: 0 }); } if (focusElement == null || !("focusElementIndx" in focusElement)) return; // const docCon = document.getElementById("doc-con"); // document.addEventListener("keydown", (e) => { // if (e.key == "Tab") { // e.preventDefault(); // console.log("Listening Tab Key Press") // let focusIndx = focusElement?.focusElementIndx; // if (focusIndx >= droppedItems.length - 1) focusIndx = -1 // setFocusElement({ ...droppedItems[++focusIndx], focusElementIndx: ++focusIndx }) // } // }) } }, [droppedItems]) useEffect(() => { if (showConfetti) { const duration = 3000; const end = Date.now() + duration; const interval = setInterval(() => { if (Date.now() > end) { clearInterval(interval); return; } confetti({ particleCount: 5, // fewer particles per burst for smoothness angle: 90, // falling straight down spread: 30, // slight spread startVelocity: 8, // gentle falling speed origin: { x: Math.random(), // random horizontal position across the top y: 0, }, scalar: 1, zIndex: 9999, }); }, 50); // fire every 50ms for continuous effect return () => clearInterval(interval); } }, [showConfetti]); useEffect(() => { if (recSignStatus == "COMPLETED") { // setHideTags(true); setTransparentTags(true); } else { setHideTags(false); } }, [recSignStatus]) useEffect(() => { if (saved.save && Object.keys(signConfObj).length) { const keys = Object.keys(signConfObj) const index = keys[0] const newObj = { accepted: true, index: index } setSignConfObj((prev) => { return ( { ...prev, [index]: { ...newObj } } ) }); } }, [saved]) const fetchData = (isSign: boolean = false) => { axiosInstance.get(`/api/v1/sign/${recipientId}`, { maxRedirects: 5, headers: { "ngrok-skip-browser-warning": "69420", } }) .then((res) => { if (res.status == 200) { setSelectedDocuments(res?.data?.documents) setRecipient(res?.data?.details) const sortedDroppedItems = res?.data?.tags.sort((a, b) => a.navigationOrder - b.navigationOrder); setDroppedItems(sortedDroppedItems) setFocusElement({ ...sortedDroppedItems[0], focusElementIndx: 0 }); setTransaction(res?.data?.transaction) setRecSignStatus(res?.data?.status) if (res?.data?.details.provideOwnTags) setRightSideNavToggle(RightSideNav.ATTRIBUTES) // Removed this functionality - REMOVED // if ("provideOwnTags" in res?.data?.details && res?.data?.details.provideOwnTags) { // setProvideTags(true) // } // Removed this functionality - REMOVED if (windowWidth > 638) { setIsFields(false) } if (res?.data?.status == "COMPLETED" || res?.data?.status == "DECLINED" || res?.data?.details.type == "CC") { // setShowCompletionScreen(true) setTransparentTags(true) setHideTags(true) } if (res?.data?.tags && res?.data?.tags.length > 0) { for (const tag of res?.data?.tags) { if (tag.type == "SIGNATURE" && "value" in tag && tag.value) { axiosInstance.get(`/api/v1/sign/${recipientId}/signatures/${tag.value}`).then((res) => { console.log(res, "line 386") }).catch((err) => { console.log(err) }) // const [saved, setSaved] = useState({ // signatureId: null, // saveType: null, // save: false, // signature: null, // initial: null, // }); } else if (tag.type == "INITIALS") { } } } dispatch(hideLoader()); } }) .catch((err) => { console.log(err) }); } const handleFormSubmit = async () => { let newSignatureIdForCreateDefault = null; if (saved.isDefaultAndClicked) { try { const res = await axiosInstance.post(`/api/v1/sign/${recipientId}/signatures`, { signatureId: saved.signatureId }); if (res.status == 201 || res.status == 202) { newSignatureIdForCreateDefault = res.data.id; } } catch (err) { console.log(err); } } const submitData: TagsSubmitDataObj = { tags: [] } const createTagsAndSubmit: TagsSubmitDataObj = { tags: [] } if (!droppedItems) return; let signInitialsCount = 0; for (let i = 0; i < droppedItems.length; i++) { if (droppedItems[i].type == "SIGNATURE" || droppedItems[i].type == "INITIALS") { signInitialsCount += 1; } } if (signInitialsCount != Object.keys(signConfObj).length) { // handleToastError("Please ensure all signature and initials are signed") return; } for (let tag of droppedItems) { if ("required" in tag && tag.required && ((tag.type != "SIGNATURE" && tag.type != "INITIALS") && (tag.value == undefined || tag.value == null || tag.value == "" || !("value" in tag)))) { // handleToastError(`${tag.label} is required`) return; } if ("id" in tag && (tag.type == "SIGNATURE" || tag.type == "INITIALS")) { const tagData: TagSubmitData = { id: tag.id as string, type: tag.type, // subType: saved.saveType as string, signed: true, value: saved.signatureId as string } submitData.tags.push(tagData) } else if ("id" in tag) { const tagData: TagSubmitData = { id: tag.id as string, type: tag.type, // subType: tag.subType ? tag.subType : "", signed: true, value: tag.value ? tag.value as string : "" } submitData.tags.push(tagData); } else if (tag.type == "SIGNATURE" || tag.type == "INITIALS") { // Not getting recipient id in details it is undefined - not working self sign tag.recipientId = recipient.id; tag.documentId = tag.documentId createTagsAndSubmit.tags.push( { ...tag, type: tag.type, // subType: saved.saveType as string, signed: true, value: newSignatureIdForCreateDefault as string }) } else { tag.recipientId = recipient.id tag.documentId = tag.documentId createTagsAndSubmit.tags.push( { ...tag, type: tag.type, // subType: tag.subType ? tag.subType : "", signed: true, value: tag.value ? tag.value as string : "" }) } } // return; try { dispatch(showLoader("Signing ...")); if (submitData.tags.length) { await axiosInstance.put(`/api/v1/sign/${recipientId}/tags`, submitData, { headers: { "ngrok-skip-browser-warning": "69420", } }) } else if (createTagsAndSubmit.tags.length) { await axiosInstance.post(`/api/v1/sign/${recipientId}/tags`, createTagsAndSubmit, { headers: { "ngrok-skip-browser-warning": "69420", } }) } const signRes = await axiosInstance.post(`/api/v1/sign/${recipientId}`, {}, { headers: { "ngrok-skip-browser-warning": "69420", } }) if (signRes.status == 200) { setTransparentTags(true) // setShowConfetti(true) // setShowCompletionScreen(true) setSelectedTag(null) // navigate("/transaction-complete") dispatch(hideLoader()); window.location.href = `/transaction-complete/${recipientId}` } dispatch(hideLoader()); } catch (e) { dispatch(hideLoader()); } }; const handleTagNavClick = (action: "N" | "P") => { // debugger if (!droppedItems || !droppedItems.length) return // If FocusElement is Null Setting up 0 th Tag if (!focusElement) { setFocusElement({ ...droppedItems[0], focusElementIndx: 0 }); return; } if (requiredFilled && focusElement.required == true) { setConfirmSignOpen(true); return; } // If FocusElement is present updating in Based on Next and Prev const currFocusElemIndx = focusElement.focusElementIndx; if (currFocusElemIndx == undefined) return; let updIndx = (action == "N") ? (currFocusElemIndx + 1) : (currFocusElemIndx - 1) if (updIndx >= droppedItems.length || updIndx < 0 || !droppedItems[updIndx].id) updIndx = 0; scrollToElement(droppedItems[updIndx].navigationOrder) setFocusElement({ ...droppedItems[updIndx], focusElementIndx: updIndx }) } const scrollToElement = (elementId: string) => { const element = document.getElementById(elementId); if (element) { element.scrollIntoView({ behavior: "smooth", block: "center" }); } } const handlePrefillValues = () => { const prefilledTags = ["NAME", "EMAIL", "TEXT", "COMPANY", "TEMPORAL"] const updatedItems = droppedItems.map((item, index) => { if (prefilledTags.includes(item.type)) { let value = null; let isUpdate = false switch (item.type) { case "NAME": value = recipient?.firstName + " " + recipient?.lastName; isUpdate = true; break; case "EMAIL": value = recipient?.email; isUpdate = true; break; case "TEXT": value = item.value; isUpdate = true; break; case "COMPANY": value = item.value; isUpdate = true; break; case "TEMPORAL": if (item.currentTimeStamp) isUpdate = true; if (isUpdate) { value = dayjs(Date.now()).format(item.format); } break; default: break; } return { ...item, value } } else { return item } }) setDroppedItems(updatedItems); } useEffect(() => { if (droppedItems.length > 0) { handlePrefillValues(); } }, [droppedItems.length]) useEffect(() => { const allRequiredFields = droppedItems.filter((item, idx) => { if (!item.required) return false if (item.type == "SIGNATURE" || item.type == "INITIALS") { if ( (item.id != null && item.id != undefined && item.id != "") ? ( (`${item.id}`) in signConfObj && signConfObj[`${item.id}`].accepted ) : ( (`${idx}`) in signConfObj && signConfObj[`${idx}`].accepted ) ) { return false } else { return true } } if (!("value" in item)) { return true } else if (item.value === null || item.value === undefined || item.value === "") { return true } return false; }) const totalRequiredFields = droppedItems.reduce((acc, obj) => { if (obj.required == true) return acc + 1; return acc; }, 0) setHorizontalFormLoader({ requiredFilled: (totalRequiredFields - allRequiredFields.length), totalRequired: totalRequiredFields }) setRequiredFilled(allRequiredFields.length || !droppedItems.length ? false : true) }, [droppedItems, signConfObj]) // HANDLE DROP - START const handleDrop = (event: React.DragEvent, docId: string, documentId: number, pageIndex: number) => { event.preventDefault(); const data = window.dragElemData; window.dragElemData = null; if (!data) return; const dragElemData = JSON.parse(data); // Get the dropped label const field = { ...dragElemData } if (!field.label) return; const dropZone = event.currentTarget.getBoundingClientRect(); const x = event.clientX - dropZone.left - dragElemData.offsetX; const y = event.clientY - dropZone.top - dragElemData.offsetY; const key = `${docId}_${pageIndex}`; let prepData = { ...data.properties, icon: typeToIconMap[field.label.toUpperCase()] || , type: dragElemData.label.toUpperCase(), label: dragElemData.label, dimensions: { left: x, top: y, width: dragElemData.width, height: dragElemData.height, }, styles: dragElemData.label == "text" ? { "font": "Great Vibes", "italic": false, "bold": false, "underline": false, "color": "black", "textSize": 14.0 } : null, documentId: docId, pageIndex: pageIndex, recipientId: dragElemData.recipientId, recipientIndx: dragElemData.recipientIndx, required: (dragElemData.label != TagsTypes.SIGNATURE && dragElemData.label != TagsTypes.INITIALS) ? false : true, update: true, isDeleted: false } if (prepData.type == "NAME") { prepData.firstName = true prepData.lastName = true } if ("group" in dragElemData) { prepData.group = dragElemData.group; prepData.isGroupExist = false; } if (prepData.type.toLowerCase() == "temporal") { prepData.currentTimeStamp = true; } if (prepData.type.toLowerCase() == "number") { prepData.decimalPlace = 0; prepData.isCurrency = false; } if (prepData.type.toLowerCase() == TagsTypes.SIGNATURE || prepData.type.toLowerCase() == TagsTypes.INITIALS) { const currDocTags = droppedItems.filter((val) => val.pageIndex == prepData.pageIndex) setSignConfObj({ ...signConfObj, [currDocTags.length]: { accepted: true, index: currDocTags.length } }) } setDroppedItems((prev) => [...prev, prepData]); }; // HANDLE DROP - END const handleDragOver = (event: React.DragEvent) => { event.preventDefault(); // Allows the drop event to work }; const handleSetIsFields = (setTo: boolean) => { if (setTo != isFields) setIsFields(setTo); } const handleOnConsent = () => { setSignerConsent((prev) => { return { ...prev, consent: true } }); } const handleDeclineConfirm = async (reason: string, comments: string) => { try { await axiosInstance.post(`/api/v1/sign/${recipientId}/decline`, { reason: reason + ", " + comments }); setSignerConsent((prev) => ({ ...prev, decline: true })); setRecSignStatus("DECLINED"); // setShowCompletionScreen(true); // navigate("/transaction-declined") window.location.href = `/transaction-declined` } catch (e) { } } const handleReassignConfirm = (data: { firstName: string; lastName: string; email: string; message: string }) => { axiosInstance.post(`/api/v1/sign/${recipientId}/reassign`, { name: data.firstName ? data.firstName + " " + data.lastName : data.lastName, email: data.email, message: data.message, language: "en" }) .then((res) => { if (res.status == 202) { // setShowCompletionScreen(true); // navigate("/transaction-reassigned") window.location.href = `/transaction-reassigned` } }) .catch((err) => { console.log(err) }); } // Simple throttle function throttle(fn: Function, wait: number) { let lastTime = 0; return (...args: any[]) => { const now = Date.now(); if (now - lastTime >= wait) { lastTime = now; fn(...args); } }; } function printDocConDiv() { var printContents = document.getElementById(divId).innerHTML; var originalContents = document.body.innerHTML; document.body.innerHTML = printContents; window.print(); document.body.innerHTML = originalContents; } useEffect(() => { const docCon = document.getElementById("doc-con"); if (!docCon) return; const checkPosition = throttle(() => { let el = document.getElementById("tag-navigation-btn"); if (!el) return; const elRect = el.getBoundingClientRect(); const containerRect = docCon.getBoundingClientRect(); if (elRect.bottom < containerRect.top) { setNavigationTagPos(NavigationTagPosEnum.ABOVE) } else if (elRect.top > containerRect.bottom) { setNavigationTagPos(NavigationTagPosEnum.BELOW) } else { setNavigationTagPos(NavigationTagPosEnum.VISIBLE) } }, 10); // Initial check checkPosition(); docCon.addEventListener("scroll", checkPosition); window.addEventListener("resize", checkPosition); // container may resize return () => { docCon.removeEventListener("scroll", checkPosition); window.removeEventListener("resize", checkPosition); }; }, []); // if (showCompletionScreen) { // if (recSignStatus == "COMPLETED") { // return // } else if (recSignStatus == "DECLINED") { // return // } else { // return // } // } return ( <>
{/* */} {/* {showCompletionScreen && } */}
) => handleFormSubmit(e)} > {/* Nav Two - Options - START */}
{/* DOWNLOAD AND PRINT OPTION - START */} {/*

*/} {/*
*/} {/* DOWNLOAD AND PRINT OPTION - START */} {/* FIT - START */}
setIsFitDd(false)} >
setIsFitDd(!isFitDd)} className='text-white flex items-center gap-1 cursor-pointer text-xs px-2 py-1 rounded-sm ml-2'>

{fitObj[selFitIndx].label}

{isFitDd &&
{fitObj.map((val, indx) => { return (
setSelFitIndx(indx)} onClick={() => handleFitSelect(indx)} className='flex z-50 items-center justify-between gap-2 w-[70px] p-2 text-xs cursor-default hover:bg-slate-100'>

{val.label}

{selFitIndx == indx && }
) }) }
}
{/* FIT - END */}
{/* Right Side - STARTS */}
{/* Documnt Nav */} <> {selectedDocuments != null &&
setNav2DocToggle(false)}> {/*
setNav2DocToggle(!nav2DocToggle)} className='bg-white flex items-center gap-1 cursor-pointer text-xs px-2 py-1 rounded-sm'>

{selectedDocuments && selectedDocuments.length} Documents

*/}
{selectedDocuments.length && selectedDocuments.map((document, indx) => { return (
{/*

*/}

{document.name}

) })}
} {/* PRINT _ START */} {/* */} {/* PRINT _ END */} {/* Send */} {/* {(!transparentTags && !hideTags) ? :

Signed Successfully

} */} setConfirmSignOpen(true)} onDeclineClick={() => setDeclineOpen(true)} onReassignClick={() => setReassignOpen(true)} onAuditHistoryClick={() => setAuditHistoryOpen(true)} showDecAndReassign={recipient?.type != "CC"} transactionId={"1"} />
{/* Right Side - ENDS */}
{/* Horizontal Loader */} {horizontalFormLoader.totalRequired != null && !transparentTags && (
)}
{/* Nav Two - Options - End */} {/* Document Container Start */}
{/* Left Side pages start */} {/*
*/}
{ setIsPages(false) setIsFields(true) }} className='absolute sm:hidden top-[5px] right-[10px] bg-white rounded-full text-2xl z-50'>
<> {provideTags && !transparentTags &&
{provideTags && recipient?.type != "CC" &&
handleSetIsFields(true)} className={`flex items-center gap-1 cursor-pointer text-xs w-full justify-center py-1.5 rounded-2xl ${isFields ? 'bg-[var(--primary)] text-white' : ''} transition-all duration-300`} >

Tags

}
handleSetIsFields(provideTags ? false : !isFields)} >

Pages

} {!transparentTags && isFields && recipientId && provideTags && recipient?.type != "CC" && }
{/* Pages - END */} {/* Main container */}
150 ? "overflow-x-auto" : "overflow-x-hidden"} scroll-smooth transition-all duration-200 pb-[4rem]`} >
{ selectedDocuments && selectedDocuments.length > 0 && selectedDocuments.map((doc) => { return (

{doc.name}

{ doc.pages && doc.pages.length > 0 && doc.pages.map((page, indx) => { const key = `${doc.documentId}_${page.index}`; // const tagJsonData = [...droppedItems]; const currDocTags = droppedItems .map((val, index) => ({ ...val, originalIndex: index })) // add original index .filter(val => val.pageIndex === page.index); let scale: { x: number | null, y: number | null } = { x: null, y: null } return (
handleDrop(e, doc.documentId, doc.documentId, page.index)} onDragOver={(e) => handleDragOver(e)} className='drop-page-in shadow-md relative overflow-hidden' > (imageRefs.current[page.index] = el)} onLoad={(e) => { const el = e.currentTarget; setImageSizes((prev) => ({ ...prev, [page.index]: { width: el.offsetWidth, height: el.offsetHeight, }, })); }} draggable="false" // onLoad={(imgElem) => { // setPageScales((prev) => ({ // ...prev, // [page.index]: { // x: imgElem.clientWidth / page.width, // y: imgElem.clientHeight / page.height, // }, // })); // }} width={page.width} height={page.height} src={page.src} loading='lazy' /> {!hideTags && <> } {/* Side details of documents Pages and document Name - START */}

page {indx + 1} of {doc.pages && doc.pages.length}

{/* Side details of documents Pages and document Name - END */} {!transparentTags && focusElement != null && focusElement && Object.keys(focusElement).length > 1 && focusElement.documentId == doc.documentId && focusElement.pageIndex == page.index &&
handleTagNavClick("N")} > {/* */} {requiredFilled && focusElement.required == true ? "Submit" : focusElement.type.toLowerCase()} {/* NEXT Button - END */}
}
) }) }
) }) }
{/*
*/}
{(navigationTagPos == NavigationTagPosEnum.ABOVE || navigationTagPos == NavigationTagPosEnum.BELOW) &&
scrollToElement(focusElement?.navigationOrder)} className={`hidden sm:block cursor-pointer fixed ${navigationTagPos == NavigationTagPosEnum.ABOVE ? "top-[55px]" : requiredFilled ? "bottom-[82px]" : "bottom-[55px]"} right-[8%] flex flex-col items-center`}> {/* Arrow pointing up */} {/* {navigationTagPos == NavigationTagPosEnum.ABOVE &&
} */} {/* Label box */}
{/* {focusElement?.type.toLowerCase()} */} Next
{/* {navigationTagPos == NavigationTagPosEnum.BELOW &&
} */}
}
{provideTags && selectedTag && selectedTag != null && "key" in selectedTag && "index" in selectedTag &&
{/* Right Side Attributes Section if providedTags - START */} {/* Right Side Attributes Section if providedTags - END */}
}
{/* Document Container End */}
{/* {showCompletionScreen && recSignStatus == "COMPLETED" && } {showCompletionScreen && recSignStatus == "DECLINED" && } */}
{recipient && }
{/* */} {globalLoader.isLoading && }
{ setIsPages(true) setIsFields(false) }} className='sm:hidden fixed top-[8%] left-0 bg-[var(--primary)] flex items-center text-white rounded-tr-md rounded-br-md cursor-pointer opacity-50 hover:opacity-100 transition-all duration-300'>
{/* */} {/*

P A G E S

*/}
{ !transparentTags && selectedDocuments != null && !showCompletionScreen && !signerConsent.consent && recipient?.type != "CC" && handleOnConsent()} // onDecline={() => console.log("User declined")} /> } setDeclineOpen(false)} onConfirm={({ reason, comments }) => handleDeclineConfirm(reason, comments)} /> setReassignOpen(false)} onConfirm={({ firstName, lastName, email, message }) => handleReassignConfirm({ firstName, lastName, email, message })} /> setAuditHistoryOpen(false)} recipientId={recipientId} // onConfirm={({ firstName, lastName, email, message }) => handleReassignConfirm({ firstName, lastName, email, message })} /> setConfirmSignOpen(false)} onConfirm={handleConfirmSign} loading={confirmSignLoading} recipientName={recipient ? `${recipient.firstName ?? ""} ${recipient.lastName ?? ""}`.trim() : ""} documentCount={selectedDocuments?.length ?? 1} />
{!transparentTags && recipient?.type != "CC" && (

All Set to Wrap This Up?

You've completed the required fields. Review your work, then select Finish.

)} {!transparentTags && recipient?.type !== "CC" && ( )} ) } export default SignDocument