import React, { useState, useRef, useEffect } from "react"; import axios from "axios"; import "../css/./signature.css"; import Modal from "react-bootstrap/Modal"; import sign from "../assests/sign3.png"; import stamp from "../assests/stamp2.png"; import { themeColor } from "../utils/ThemeColor/backColor"; import { DndProvider } from "react-dnd"; import { HTML5Backend } from "react-dnd-html5-backend"; import { useDrag, useDrop } from "react-dnd"; import RenderAllPdfPage from "./component/renderAllPdfPage"; import FieldsComponent from "./component/fieldsComponent"; import Tour from "reactour"; import { useLocation, useParams } from "react-router-dom"; import Loader from "./component/loader"; import HandleError from "./component/HandleError"; import Nodata from "./component/Nodata"; import SignerListPlace from "./component/signerListPlace"; import Header from "./component/header"; import { pdfNewWidthFun, contractDocument, contractUsers, getHostUrl, addZIndex, randomId } from "../utils/Utils"; import RenderPdf from "./component/renderPdf"; import ModalComponent from "./component/modalComponent"; import { useNavigate } from "react-router-dom"; import PlaceholderCopy from "./component/PlaceholderCopy"; import LinkUserModal from "./component/LinkUserModal"; import Title from "./component/Title"; import TourContentWithBtn from "../premitives/TourContentWithBtn"; import ModalUi from "../premitives/ModalUi"; function PlaceHolderSign() { const navigate = useNavigate(); const { state } = useLocation(); const [pdfDetails, setPdfDetails] = useState([]); const [isMailSend, setIsMailSend] = useState(false); const [allPages, setAllPages] = useState(null); const numPages = 1; const [pageNumber, setPageNumber] = useState(1); const [signBtnPosition, setSignBtnPosition] = useState([]); const [xySignature, setXYSignature] = useState({}); const [dragKey, setDragKey] = useState(); const [signersdata, setSignersData] = useState(); const [signerObjId, setSignerObjId] = useState(); const [signerPos, setSignerPos] = useState([]); const [isSelectListId, setIsSelectId] = useState(); const [isSendAlert, setIsSendAlert] = useState({}); const [isSend, setIsSend] = useState(false); const [isLoading, setIsLoading] = useState({ isLoad: true, message: "This might take some time" }); const [handleError, setHandleError] = useState(); const [currentId, setCurrentId] = useState(""); const [pdfNewWidth, setPdfNewWidth] = useState(); const [placeholderTour, setPlaceholderTour] = useState(true); const [checkTourStatus, setCheckTourStatus] = useState(false); const [tourStatus, setTourStatus] = useState([]); const [signerUserId, setSignerUserId] = useState(); const [noData, setNoData] = useState(false); const [pdfOriginalWidth, setPdfOriginalWidth] = useState(); const [contractName, setContractName] = useState(""); const [containerWH, setContainerWH] = useState(); const { docId } = useParams(); const signRef = useRef(null); const dragRef = useRef(null); const divRef = useRef(null); const [isShowEmail, setIsShowEmail] = useState(false); const [selectedEmail, setSelectedEmail] = useState(false); const [isResize, setIsResize] = useState(false); const [zIndex, setZIndex] = useState(1); const [signKey, setSignKey] = useState(); const [pdfLoadFail, setPdfLoadFail] = useState({ status: false, type: "load" }); const [isPageCopy, setIsPageCopy] = useState(false); const [uniqueId, setUniqueId] = useState(""); const [roleName, setRoleName] = useState(""); const [isAddUser, setIsAddUser] = useState({}); const [signerExistModal, setSignerExistModal] = useState(false); const [isDontShow, setIsDontShow] = useState(false); const color = [ "#93a3db", "#e6c3db", "#c0e3bc", "#bce3db", "#b8ccdb", "#ceb8db", "#ffccff", "#99ffcc", "#cc99ff", "#ffcc99", "#66ccff", "#ffffcc" ]; const isMobile = window.innerWidth < 767; const [{ isOver }, drop] = useDrop({ accept: "BOX", drop: (item, monitor) => addPositionOfSignature(item, monitor), collect: (monitor) => ({ isOver: !!monitor.isOver() }) }); const [{ isDragSign }, dragSignature] = useDrag({ type: "BOX", item: { type: "BOX", id: 1, text: "drag me" }, collect: (monitor) => ({ isDragSign: !!monitor.isDragging() }) }); const [{ isDragStamp }, dragStamp] = useDrag({ type: "BOX", item: { type: "BOX", id: 2, text: "drag me" }, collect: (monitor) => ({ isDragStamp: !!monitor.isDragging() }) }); const [{ isDragSignatureSS }, dragSignatureSS] = useDrag({ type: "BOX", item: { type: "BOX", id: 3, text: "drag me" }, collect: (monitor) => ({ isDragSignatureSS: !!monitor.isDragging() }) }); const [{ isDragStampSS }, dragStampSS] = useDrag({ type: "BOX", item: { type: "BOX", id: 4, text: "drag me" }, collect: (monitor) => ({ isDragStampSS: !!monitor.isDragging() }) }); const rowLevel = localStorage.getItem("rowlevel") && JSON.parse(localStorage.getItem("rowlevel")); const objectId = rowLevel && rowLevel.id ? rowLevel.id : rowLevel?.objectId && rowLevel.objectId; const documentId = docId ? docId : objectId && objectId; const senderUser = localStorage.getItem( `Parse/${localStorage.getItem("parseAppId")}/currentUser` ) && localStorage.getItem( `Parse/${localStorage.getItem("parseAppId")}/currentUser` ); const jsonSender = JSON.parse(senderUser); useEffect(() => { if (documentId) { getDocumentDetails(); } }, []); useEffect(() => { if (divRef.current) { const pdfWidth = pdfNewWidthFun(divRef); setPdfNewWidth(pdfWidth); setContainerWH({ width: divRef.current.offsetWidth, height: divRef.current.offsetHeight }); } }, [divRef.current]); //function for get document details const getDocumentDetails = async () => { //getting document details const documentData = await contractDocument(documentId); if (documentData && documentData.length > 0) { // const alreadyPlaceholder = // documentData[0].Placeholders && documentData[0].Placeholders; // if (alreadyPlaceholder && alreadyPlaceholder.length > 0) { // setIsAlreadyPlace(true); // } // setSignersData(documentData[0]); // setIsSelectId(0); // setSignerObjId(documentData[0].Signers[0].objectId); // setContractName(documentData[0].Signers[0].className); setPdfDetails(documentData); if (documentData[0].Signers && documentData[0].Signers.length > 0) { const currEmail = documentData[0].ExtUserPtr.Email; setCurrentId(currEmail); setSignerObjId(documentData[0].Signers[0].objectId); setContractName(documentData[0].Signers[0].className); setIsSelectId(0); if ( documentData[0].Placeholders && documentData[0].Placeholders.length > 0 ) { setSignerPos(documentData[0].Placeholders); let signers = [...documentData[0].Signers]; let updatedSigners = documentData[0].Placeholders.map((x) => { let matchingSigner = signers.find( (y) => x.signerObjId && x.signerObjId === y.objectId ); if (matchingSigner) { return { ...matchingSigner, Role: x.Role ? x.Role : matchingSigner.Role, Id: x.Id, blockColor: x.blockColor }; } else { return { Role: x.Role, Id: x.Id, blockColor: x.blockColor }; } }); setSignersData(updatedSigners); setUniqueId(updatedSigners[0].Id); } else { const updatedSigners = documentData[0].Signers.map((x, index) => ({ ...x, Id: randomId(), Role: "User " + (index + 1) })); setSignersData(updatedSigners); setUniqueId(updatedSigners[0].Id); } } else { setRoleName("User 1"); if ( documentData[0].Placeholders && documentData[0].Placeholders.length > 0 ) { let updatedSigners = documentData[0].Placeholders.map((x) => { return { Role: x.Role, Id: x.Id, blockColor: x.blockColor }; }); setSignerPos(documentData[0].Placeholders); setSignersData(updatedSigners); setIsSelectId(0); setUniqueId(updatedSigners[0].Id); } } } else if ( documentData === "Error: Something went wrong!" || (documentData.result && documentData.result.error) ) { const loadObj = { isLoad: false }; setHandleError("Error: Something went wrong!"); setIsLoading(loadObj); } else { setNoData(true); const loadObj = { isLoad: false }; setIsLoading(loadObj); } const res = await contractUsers(jsonSender.email); if (res[0] && res.length) { setSignerUserId(res[0].objectId); const tourstatus = res[0].TourStatus && res[0].TourStatus; if (tourstatus && tourstatus.length > 0) { setTourStatus(tourstatus); const checkTourRecipients = tourstatus.filter( (data) => data.placeholder ); if (checkTourRecipients && checkTourRecipients.length > 0) { setCheckTourStatus(checkTourRecipients[0].placeholder); } } const loadObj = { isLoad: false }; setIsLoading(loadObj); } else if (res === "Error: Something went wrong!") { const loadObj = { isLoad: false }; setHandleError("Error: Something went wrong!"); setIsLoading(loadObj); } else if (res.length === 0) { setNoData(true); const loadObj = { isLoad: false }; setIsLoading(loadObj); } }; //function for setting position after drop signature button over pdf const addPositionOfSignature = (item, monitor) => { getSignerPos(item, monitor); }; const getSignerPos = (item, monitor) => { setSignerObjId(""); setContractName(""); if (uniqueId) { const signer = signersdata.find((x) => x.Id === uniqueId); if (signer) { const posZIndex = zIndex + 1; setZIndex(posZIndex); const newWidth = containerWH.width; const scale = pdfOriginalWidth / newWidth; const key = randomId(); // let filterSignerPos = signerPos.filter( // (data) => data.signerObjId === signerObjId // ); let filterSignerPos = signerPos.filter((data) => data.Id === uniqueId); let dropData = []; let placeHolder; if (item === "onclick") { const dropObj = { xPosition: window.innerWidth / 2 - 100, yPosition: window.innerHeight / 2 - 60, isStamp: monitor, key: key, isDrag: false, scale: scale, isMobile: isMobile, yBottom: window.innerHeight / 2 - 60, zIndex: posZIndex }; dropData.push(dropObj); placeHolder = { pageNumber: pageNumber, pos: dropData }; } else if (item.type === "BOX") { const offset = monitor.getClientOffset(); //adding and updating drop position in array when user drop signature button in div const containerRect = document .getElementById("container") .getBoundingClientRect(); const x = offset.x - containerRect.left; const y = offset.y - containerRect.top; const ybottom = containerRect.bottom - offset.y; const dropObj = { xPosition: signBtnPosition[0] ? x - signBtnPosition[0].xPos : x, yPosition: signBtnPosition[0] ? y - signBtnPosition[0].yPos : y, isStamp: isDragStamp || isDragStampSS ? true : false, key: key, isDrag: false, firstXPos: signBtnPosition[0] && signBtnPosition[0].xPos, firstYPos: signBtnPosition[0] && signBtnPosition[0].yPos, yBottom: ybottom, scale: scale, isMobile: isMobile, zIndex: posZIndex }; dropData.push(dropObj); placeHolder = { pageNumber: pageNumber, pos: dropData }; } const { blockColor, Role } = signer; //adding placholder in existing signer pos array (placaholder) if (filterSignerPos.length > 0) { const getPlaceHolder = filterSignerPos[0].placeHolder; const updatePlace = getPlaceHolder.filter( (data) => data.pageNumber !== pageNumber ); const getPageNumer = getPlaceHolder.filter( (data) => data.pageNumber === pageNumber ); //add entry of position for same signer on multiple page if (getPageNumer.length > 0) { const getPos = getPageNumer[0].pos; const newSignPos = getPos.concat(dropData); let xyPos = { pageNumber: pageNumber, pos: newSignPos }; updatePlace.push(xyPos); const updatesignerPos = signerPos.map((x) => x.Id === uniqueId ? { ...x, placeHolder: updatePlace } : x ); setSignerPos(updatesignerPos); } else { const updatesignerPos = signerPos.map((x) => x.Id === uniqueId ? { ...x, placeHolder: [...x.placeHolder, placeHolder] } : x ); setSignerPos(updatesignerPos); } } else { //adding new placeholder for selected signer in pos array (placeholder) let placeHolderPos; if (contractName) { placeHolderPos = { signerPtr: { __type: "Pointer", className: `${contractName}`, objectId: signerObjId }, signerObjId: signerObjId, blockColor: blockColor ? blockColor : color[isSelectListId], placeHolder: [placeHolder], Role: Role ? Role : roleName, Id: uniqueId }; } else { placeHolderPos = { signerPtr: {}, signerObjId: "", blockColor: blockColor ? blockColor : color[isSelectListId], placeHolder: [placeHolder], Role: Role ? Role : roleName, Id: uniqueId }; } setSignerPos((prev) => [...prev, placeHolderPos]); } } } }; //function for get pdf page details const pageDetails = async (pdf) => { const load = { status: true }; setPdfLoadFail(load); pdf.getPage(1).then((pdfPage) => { const pageWidth = pdfPage.view[2]; setPdfOriginalWidth(pageWidth); }); }; //function for save x and y position and show signature tab on that position const handleTabDrag = (key, signerId) => { setDragKey(key); }; //function for set and update x and y postion after drag and drop signature tab const handleStop = (event, dragElement, signerId, key) => { if (!isResize) { const dataNewPlace = addZIndex(signerPos, key, setZIndex); let updateSignPos = [...signerPos]; updateSignPos.splice(0, updateSignPos.length, ...dataNewPlace); // signerPos.splice(0, signerPos.length, ...dataNewPlace); const containerRect = document .getElementById("container") .getBoundingClientRect(); const signId = signerId ? signerId : uniqueId; //? signerId : signerObjId; const keyValue = key ? key : dragKey; const ybottom = containerRect.height - dragElement.y; if (keyValue >= 0) { const filterSignerPos = updateSignPos.filter( (data) => data.Id === signId ); if (filterSignerPos.length > 0) { const getPlaceHolder = filterSignerPos[0].placeHolder; const getPageNumer = getPlaceHolder.filter( (data) => data.pageNumber === pageNumber ); if (getPageNumer.length > 0) { const getXYdata = getPageNumer[0].pos; const getPosData = getXYdata; const addSignPos = getPosData.map((url, ind) => { if (url.key === keyValue) { return { ...url, xPosition: dragElement.x, yPosition: dragElement.y, isDrag: true, yBottom: ybottom }; } return url; }); const newUpdateSignPos = getPlaceHolder.map((obj, ind) => { if (obj.pageNumber === pageNumber) { return { ...obj, pos: addSignPos }; } return obj; }); const newUpdateSigner = updateSignPos.map((obj, ind) => { if (obj.Id === signId) { return { ...obj, placeHolder: newUpdateSignPos }; } return obj; }); setSignerPos(newUpdateSigner); } } } } }; //function for delete signature block const handleDeleteSign = (key, Id) => { const updateData = []; // const filterSignerPos = signerPos.filter( // (data) => data.signerObjId === signerId // ); const filterSignerPos = signerPos.filter((data) => data.Id === Id); if (filterSignerPos.length > 0) { const getPlaceHolder = filterSignerPos[0].placeHolder; const getPageNumer = getPlaceHolder.filter( (data) => data.pageNumber === pageNumber ); if (getPageNumer.length > 0) { const getXYdata = getPageNumer[0].pos.filter( (data, ind) => data.key !== key ); if (getXYdata.length > 0) { updateData.push(getXYdata); const newUpdatePos = getPlaceHolder.map((obj, ind) => { if (obj.pageNumber === pageNumber) { return { ...obj, pos: updateData[0] }; } return obj; }); const newUpdateSigner = signerPos.map((obj, ind) => { if (obj.Id === Id) { return { ...obj, placeHolder: newUpdatePos }; } return obj; }); setSignerPos(newUpdateSigner); } else { const updateFilter = signerPos.filter((data) => data.Id !== Id); const getRemainPage = filterSignerPos[0].placeHolder.filter( (data) => data.pageNumber !== pageNumber ); if (getRemainPage && getRemainPage.length > 0) { const newUpdatePos = filterSignerPos.map((obj, ind) => { if (obj.Id === Id) { return { ...obj, placeHolder: getRemainPage }; } return obj; }); let signerupdate = []; signerupdate = signerPos.filter((data) => data.Id !== Id); signerupdate.push(newUpdatePos[0]); setSignerPos(signerupdate); } else { setSignerPos(updateFilter); } } } } }; //function for change page function changePage(offset) { setSignBtnPosition([]); setPageNumber((prevPageNumber) => prevPageNumber + offset); } //function for capture position on hover signature button const handleDivClick = (e) => { const divRect = e.currentTarget.getBoundingClientRect(); const mouseX = e.clientX - divRect.left; const mouseY = e.clientY - divRect.top; const xyPosition = { xPos: mouseX, yPos: mouseY }; setXYSignature(xyPosition); }; //function for capture position of x and y on hover signature button last position const handleMouseLeave = (e) => { setSignBtnPosition([xySignature]); }; const alertSendEmail = async () => { if (signerPos.length === signersdata.length) { const IsSignerNotExist = signerPos?.some((x) => !x.signerObjId); if (IsSignerNotExist) { setSignerExistModal(true); } else { const alert = { mssg: "confirm", alert: true }; setIsSendAlert(alert); } } else { const alert = { mssg: "sure", alert: true }; setIsSendAlert(alert); } }; const sendEmailToSigners = async () => { const loadObj = { isLoad: true, message: "This might take some time" }; setIsLoading(loadObj); setIsSendAlert({}); let sendMail; // console.log("pdfDetails", pdfDetails); const expireDate = pdfDetails?.[0].ExpiryDate.iso; const newDate = new Date(expireDate); const localExpireDate = newDate.toLocaleDateString("en-US", { day: "numeric", month: "long", year: "numeric" }); let sender = pdfDetails?.[0].ExtUserPtr.Email; const signerMail = signersdata; for (let i = 0; i < signerMail.length; i++) { try { const imgPng = "https://qikinnovation.ams3.digitaloceanspaces.com/logo.png"; let url = `${localStorage.getItem("baseUrl")}functions/sendmailv3/`; const headers = { "Content-Type": "application/json", "X-Parse-Application-Id": localStorage.getItem("parseAppId"), sessionToken: localStorage.getItem("accesstoken") }; const serverUrl = localStorage.getItem("baseUrl"); const newServer = serverUrl.replaceAll("/", "%2F"); const objectId = signerMail[i].objectId; const serverParams = `${newServer}&${localStorage.getItem( "parseAppId" )}&${localStorage.getItem("_appName")}`; const hostUrl = window.location.origin + "/loadmf/signmicroapp"; let signPdf = `${hostUrl}/login/${pdfDetails?.[0].objectId}/${signerMail[i].Email}/${objectId}/${serverParams}`; const openSignUrl = "https://www.opensignlabs.com/"; const themeBGcolor = themeColor(); let params = { recipient: signerMail[i].Email, subject: `${pdfDetails?.[0].ExtUserPtr.Name} has requested you to sign ${pdfDetails?.[0].Name}`, from: sender, html: "
Digital Signature Request
This is an automated email from OpenSign. For any queries regarding this email, please contact the sender " + sender + " directly.If you think this email is inappropriate or spam, you may file a complaint with OpenSign here.
Please add field for all recipients.
) : ( isSendAlert.mssg === "confirm" && (Are you sure you want to send out this document for signatures?
) )} {isSendAlert.mssg === "confirm" && ( )}You have successfully sent mails to all recipients!
{currentId && (Do you want to sign documents right now ?
)} {currentId ? ( <> > ) : ( )}Please assign signers to all placeholders