diff --git a/microfrontends/SignDocuments/package-lock.json b/microfrontends/SignDocuments/package-lock.json index 98359a78d..2c4f6bc78 100644 --- a/microfrontends/SignDocuments/package-lock.json +++ b/microfrontends/SignDocuments/package-lock.json @@ -30,6 +30,7 @@ "react-dom": "^18.2.0", "react-draggable": "^4.4.6", "react-helmet": "^6.1.0", + "react-konva": "^18.2.10", "react-pdf": "^7.4.0", "react-rnd": "^10.4.1", "react-router-dom": "^6.16.0", @@ -6442,6 +6443,14 @@ "@types/react": "*" } }, + "node_modules/@types/react-reconciler": { + "version": "0.28.8", + "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.8.tgz", + "integrity": "sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@types/react-transition-group": { "version": "4.4.7", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.7.tgz", @@ -12523,6 +12532,17 @@ "set-function-name": "^2.0.1" } }, + "node_modules/its-fine": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-1.1.1.tgz", + "integrity": "sha512-v1Ia1xl20KbuSGlwoaGsW0oxsw8Be+TrXweidxD9oT/1lAh6O3K3/GIM95Tt6WCiv6W+h2M7RB1TwdoAjQyyKw==", + "dependencies": { + "@types/react-reconciler": "^0.28.0" + }, + "peerDependencies": { + "react": ">=18.0" + } + }, "node_modules/jake": { "version": "10.8.7", "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.7.tgz", @@ -14685,6 +14705,26 @@ "node": ">= 8" } }, + "node_modules/konva": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/konva/-/konva-9.3.2.tgz", + "integrity": "sha512-I4CFGVbWKpzgYi1I0pmoHz8iYfmGc/A61yfltzcuBHMFuBwDsR2VnQo4+eFQ1dGyEAmHcdvTumJ871KqkhuGng==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/lavrton" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/konva" + }, + { + "type": "github", + "url": "https://github.com/sponsors/lavrton" + } + ], + "peer": true + }, "node_modules/language-subtag-registry": { "version": "0.3.22", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", @@ -17904,6 +17944,36 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-konva": { + "version": "18.2.10", + "resolved": "https://registry.npmjs.org/react-konva/-/react-konva-18.2.10.tgz", + "integrity": "sha512-ohcX1BJINL43m4ynjZ24MxFI1syjBdrXhqVxYVDw2rKgr3yuS0x/6m1Y2Z4sl4T/gKhfreBx8KHisd0XC6OT1g==", + "funding": [ + { + "type": "patreon", + "url": "https://www.patreon.com/lavrton" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/konva" + }, + { + "type": "github", + "url": "https://github.com/sponsors/lavrton" + } + ], + "dependencies": { + "@types/react-reconciler": "^0.28.2", + "its-fine": "^1.1.1", + "react-reconciler": "~0.29.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "konva": "^8.0.1 || ^7.2.5 || ^9.0.0", + "react": ">=18.0.0", + "react-dom": ">=18.0.0" + } + }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", @@ -17950,6 +18020,21 @@ "node": ">=6" } }, + "node_modules/react-reconciler": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.29.0.tgz", + "integrity": "sha512-wa0fGj7Zht1EYMRhKWwoo1H9GApxYLBuhoAuXN0TlltESAjDssB+Apf0T/DngVqaMyPypDmabL37vw/2aRM98Q==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", diff --git a/microfrontends/SignDocuments/package.json b/microfrontends/SignDocuments/package.json index 1eae68515..b1b4f8eba 100644 --- a/microfrontends/SignDocuments/package.json +++ b/microfrontends/SignDocuments/package.json @@ -26,6 +26,7 @@ "react-dom": "^18.2.0", "react-draggable": "^4.4.6", "react-helmet": "^6.1.0", + "react-konva": "^18.2.10", "react-pdf": "^7.4.0", "react-rnd": "^10.4.1", "react-router-dom": "^6.16.0", diff --git a/microfrontends/SignDocuments/src/Component/DebugUi.js b/microfrontends/SignDocuments/src/Component/DebugUi.js new file mode 100644 index 000000000..94ff9bdf8 --- /dev/null +++ b/microfrontends/SignDocuments/src/Component/DebugUi.js @@ -0,0 +1,432 @@ +import React, { useEffect, useState, useRef } from "react"; +import RenderAllPdfPage from "./component/renderAllPdfPage"; +import "../css/./signature.css"; +import { pdfNewWidthFun } from "../utils/Utils"; +import "../css/AddUser.css"; +import Title from "./component/Title"; +import ModalUi from "../premitives/ModalUi"; +import RenderDebugPdf from "./component/RenderDebugPdf"; +import { pdfjs } from "react-pdf"; +import Alert from "../premitives/Alert"; + +function processDimensions(x, y, width, height) { + if (width < 0) { + x -= Math.abs(width); + width = Math.abs(width); + } + + if (height < 0) { + y -= Math.abs(height); + height = Math.abs(height); + } + + return { + x: Math.floor(x), + y: Math.floor(y), + width: Math.floor(width), + height: Math.floor(height) + }; +} +const DebugUi = () => { + const divRef = useRef(null); + const isMobile = window.innerWidth < 767; + const [pdf, setPdf] = useState(""); + const [isModal, setIsModal] = useState(true); + const [allPages, setAllPages] = useState(null); + const [pageNumber, setPageNumber] = useState(1); + const [pdfNewWidth, setPdfNewWidth] = useState(); + const [containerWH, setContainerWH] = useState(); + const [pdfOriginalWidth, setPdfOriginalWidth] = useState(); + const [pdfLoadFail, setPdfLoadFail] = useState({ + status: false, + type: "load" + }); + const [pdfDetails, setPdfDetails] = useState({ + name: "", + pdftype: "", + totalPages: "", + currentPage: 1, + x: 0, + y: 0, + base64: "" + }); + const [hoverCoordinates, setHoverCoordinates] = useState({ x: 0, y: 0 }); + const [drawing, setDrawing] = useState(false); + const [pdfDimension, setPdfDimension] = useState({ width: 0, height: 0 }); + const [annotations, setAnnotations] = useState([]); + const [newAnnotation, setNewAnnotation] = useState([]); + const [copied, setCopied] = useState(false); + useEffect(() => { + if (divRef.current) { + const pdfWidth = pdfNewWidthFun(divRef); + setPdfNewWidth(pdfWidth); + setContainerWH({ + width: divRef.current.offsetWidth, + height: divRef.current.offsetHeight + }); + } + }, [divRef.current]); + + useEffect(() => { + if (pdf && pdf.name) { + const fetchPdfMetadata = async () => { + try { + const pdfDataURL = URL.createObjectURL(pdf); // Convert File to data URL + console.log("pdfDataURL ", pdfDataURL); + const pdfInfo = await pdfjs.getDocument({ url: pdfDataURL }).promise; + const pdfType = await inferPdfType(pdfInfo); + setPdfDetails((prevDetails) => ({ + ...prevDetails, + pdftype: pdfType + })); + } catch (error) { + console.error("Error fetching PDF metadata:", error); + } + }; + + fetchPdfMetadata(); + } + }, [pdf]); + + const inferPdfType = async (pdf) => { + try { + const firstPage = await pdf.getPage(1); + const scale = 1; + const { width, height } = firstPage.getViewport({ scale }); + setPdfDimension({ width: width, height: height }); + + // Assuming a standard DPI of 72, you can adjust this value if needed + const dpi = 72; + + const widthInInches = width / dpi; + const heightInInches = height / dpi; + + const isA1 = widthInInches > 23.39 && heightInInches > 16.54; + const isA2 = widthInInches > 16.54 && heightInInches > 11.69; + const isA3 = widthInInches > 11.69 && heightInInches > 8.27; + const isA4 = widthInInches > 8.27 && heightInInches > 5.83; + const isLegal = widthInInches > 8.5 && heightInInches > 14; + const isLetter = widthInInches > 8.5 && heightInInches > 11; + const isLedger = widthInInches > 11 && heightInInches > 17; + + if (isA1) return "A1"; + if (isA2) return "A2"; + if (isA3) return "A3"; + if (isA4) return "A4"; + if (isLegal) return "Legal"; + if (isLetter) return "Letter"; + if (isLedger) return "Ledger"; + + return "Unknown"; + } catch (error) { + console.error("Error getting page dimensions:", error); + return "Unknown"; + } + }; + + const handleSubmit = (e) => { + e.preventDefault(); + setIsModal(false); + setPdfDetails((prevData) => ({ ...prevData, name: pdf?.name })); + }; + + //function for get pdf page details + const pageDetails = async ({ numPages }) => { + const load = { + status: true + }; + setPdfDetails((prevDetails) => ({ ...prevDetails, totalPages: numPages })); + setPdfLoadFail(load); + }; + + const handleMouseMoveDiv = (event) => { + setHoverCoordinates({ + x: event.nativeEvent.offsetX, + y: event.nativeEvent.offsetY + }); + }; + const handleMouseDown = (event) => { + if (newAnnotation.length === 0) { + const { x, y } = event.target.getStage().getPointerPosition(); + setNewAnnotation([{ x, y, width: 0, height: 0, key: "0" }]); + } + }; + + const handleMouseUp = (event) => { + if (newAnnotation.length === 1) { + const sx = newAnnotation[0].x; + const sy = newAnnotation[0].y; + const { x, y } = event.target.getStage().getPointerPosition(); + const result = processDimensions(sx, sy, x - sx, y - sy); + const annotationToAdd = { ...result, key: annotations.length + 1 }; + annotations.push(annotationToAdd); + setNewAnnotation([]); + setAnnotations(annotations); + setPdfDetails((prevDetails) => ({ + ...prevDetails, + x: result.x, + y: result.y + })); + } + }; + + const handleMouseMove = (event) => { + if (newAnnotation.length === 1) { + const sx = newAnnotation[0].x; + const sy = newAnnotation[0].y; + const { x, y } = event.target.getStage().getPointerPosition(); + setNewAnnotation([ + { + x: sx, + y: sy, + width: x - sx, + height: y - sy, + key: "0" + } + ]); + } + }; + + const annotationsToDraw = [...annotations, ...newAnnotation]; + + const handlePageLoadSuccess = (page) => { + setPdfDetails((prevDetails) => ({ + ...prevDetails, + currentPage: page.pageNumber + })); + }; + + const copytoclipboard = (text) => { + navigator.clipboard.writeText(text); + setCopied(true); + setTimeout(() => { + setCopied(false); + }, 1500); // Reset copied state after 1.5 seconds + }; + const handleFileChange = (files) => { + const file = files[0]; + setPdf(file); + + if (file && file.type === "application/pdf") { + const reader = new FileReader(); + + reader.onloadend = () => { + const base64String = reader.result.split(",")[1]; + setPdfDetails((prevdata) => ({ ...prevdata, base64: base64String })); + }; + + reader.readAsDataURL(file); + } + }; + const handleDelete = (key) => { + const updateAnnotations = annotations.filter((x) => x.key !== key); + setAnnotations(updateAnnotations); + }; + return ( +
+ {copied && Copied} + + {!isModal && ( + <div className="signatureContainer" ref={divRef}> + {/* this component used to render all pdf pages in left side */} + <RenderAllPdfPage + signPdfUrl={pdf} + allPages={allPages} + setAllPages={setAllPages} + setPageNumber={setPageNumber} + pageNumber={pageNumber} + /> + {/* pdf render view */} + <div + style={{ + marginLeft: !isMobile && pdfOriginalWidth > 500 && "20px", + marginRight: !isMobile && pdfOriginalWidth > 500 && "20px" + }} + > + <div data-tut="reactourThird"> + {containerWH && ( + <RenderDebugPdf + pdfUrl={pdf} + pageDetails={pageDetails} + pageNumber={pageNumber} + pdfOriginalWidth={pdfOriginalWidth} + pdfNewWidth={pdfNewWidth} + setPdfLoadFail={setPdfLoadFail} + pdfLoadFail={pdfLoadFail} + handlePageLoadSuccess={handlePageLoadSuccess} + handleMouseMove={handleMouseMove} + handleMouseUp={handleMouseUp} + handleMouseDown={handleMouseDown} + hoverCoordinates={hoverCoordinates} + annotations={annotationsToDraw} + pdfDimension={pdfDimension} + handleMouseMoveDiv={handleMouseMoveDiv} + /> + )} + </div> + </div> + <div style={{ backgroundColor: "white", width: 220 }}> + <div + style={{ + fontSize: 18, + fontWeight: 500, + padding: "10px 12px", + borderBottom: "1px solid grey" + }} + > + PDF details + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + Name: {pdfDetails?.name} + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + Pdf type: {pdfDetails?.pdftype} + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + Total Pages: {pdfDetails?.totalPages} + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + Current Page: {pdfDetails?.currentPage} + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + Base64 : {pdfDetails?.base64.slice(0, 10)}... + <span + style={{ + borderRadius: 4, + padding: "3px 5px", + border: "1px solid gray", + fontSize: 12, + margin: 2, + cursor: "pointer" + }} + onClick={() => copytoclipboard(pdfDetails?.base64)} + > + <i className="fa-solid fa-copy"></i> + </span> + </div> + <div + style={{ + fontSize: 18, + fontWeight: 500, + padding: "10px 12px", + borderBottom: "1px solid grey" + }} + > + Last click + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + x co-ordinate: {pdfDetails?.x} + </div> + <div style={{ fontSize: 14, padding: "5px 12px" }}> + y co-ordinate: {pdfDetails?.y} + </div> + + <div + style={{ + fontSize: 18, + fontWeight: 500, + padding: "10px 12px", + borderBottom: "1px solid grey", + borderTop: "1px solid grey" + }} + > + Annotation + </div> + <ul + style={{ + listStyle: "none", + padding: 10, + height: 500, + overflowY: "auto", + scrollbarWidth: 5 + }} + > + {annotations.map((coord, index) => ( + <li key={index}> + <span style={{ fontSize: 13, fontWeight: 500 }}>{`Box ${ + index + 1 + }:`}</span> + <code + style={{ fontSize: 12, color: "black", cursor: "pointer" }} + > + {` ["x": ${coord.x}, "y": ${coord.y}, "w": ${coord.width}, "h": ${coord.height}]`} + </code> + <span + style={{ + borderRadius: 4, + padding: "3px 5px", + border: "1px solid gray", + fontSize: 12, + margin: 2, + cursor: "pointer" + }} + onClick={() => + copytoclipboard( + `["x": ${coord.x}, "y": ${coord.y}, "w": ${coord.width}, "h": ${coord.height}]` + ) + } + > + <i className="fa-solid fa-copy"></i> + </span> + <span + style={{ + borderRadius: 4, + padding: "3px 5px", + border: "1px solid gray", + fontSize: 12, + margin: 2, + cursor: "pointer" + }} + onClick={() => handleDelete(coord.key)} + > + <i className="fa-solid fa-trash-can"></i> + </span> + </li> + ))} + </ul> + </div> + </div> + )} + + <ModalUi title={"Select PDF"} isOpen={isModal}> + <form onSubmit={handleSubmit} style={{ margin: "10px" }}> + <input + type="file" + onChange={(e) => handleFileChange(e.target.files)} + style={{ + width: "100%", + border: "1px solid grey", + borderRadius: "4px", + padding: "5px", + fontSize: 12 + }} + accept=".pdf" + required + /> + <div style={{ borderTop: "1px solid grey", margin: "10px 0" }}></div> + <button + style={{ + background: "#32a3ac", + borderRadius: "2px", + boxShadow: + "0 2px 4px rgba(0, 0, 0, 0.1), 0 2px 4px rgba(0, 0, 0, 0.18)", + border: "none", + textTransform: "uppercase", + fontSize: "13px", + fontWeight: "600", + padding: "0.375rem 0.75rem", + textAlign: "center", + color: "#ffffff", + outline: "none" + }} + type="submit" + > + Submit + </button> + </form> + </ModalUi> + </div> + ); +}; + +export default DebugUi; diff --git a/microfrontends/SignDocuments/src/Component/component/RenderDebugPdf.js b/microfrontends/SignDocuments/src/Component/component/RenderDebugPdf.js new file mode 100644 index 000000000..5c31d56c8 --- /dev/null +++ b/microfrontends/SignDocuments/src/Component/component/RenderDebugPdf.js @@ -0,0 +1,83 @@ +import React from "react"; +import { Document, Page, pdfjs } from "react-pdf"; +import { Stage, Layer, Rect } from "react-konva"; +const RenderDebugPdf = (props) => { + pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`; + + return ( + <div> + <div + style={{ + position: "sticky", + top: 0, + padding: 10, + zIndex: 1, + backgroundColor: "white", + border: "1px solid grey", + margin: "5px 0" + }} + > + {`Co-ordinates: X - ${props.hoverCoordinates.x}, Y - ${props.hoverCoordinates.y}`} + </div> + <div + style={{ + flex: 1, + position: "relative", + border: "1px solid grey", + overflow: "auto" + }} + onMouseMove={props.handleMouseMoveDiv} + > + <Document + onLoadError={(e) => { + const load = { + status: false, + type: "failed" + }; + props.setPdfLoadFail(load); + }} + loading={"Loading Document.."} + onLoadSuccess={props.pageDetails} + ref={props.pdfRef} + file={props.pdfUrl} + > + <Page + onLoadSuccess={props.handlePageLoadSuccess} + pageNumber={props.pageNumber} + renderAnnotationLayer={false} + renderTextLayer={false} + onGetAnnotationsError={(error) => { + console.log("annotation error", error); + }} + /> + </Document> + + <Stage + onMouseMove={props.handleMouseMove} + onMouseDown={props.handleMouseDown} + onMouseUp={props.handleMouseUp} + width={props.pdfDimension.width} + height={props.pdfDimension.height} + style={{ position: "absolute", top: 0, left: 0 }} + > + <Layer> + {props.annotations.map((value) => { + return ( + <Rect + x={value.x} + y={value.y} + width={value.width} + height={value.height} + fill="transparent" + stroke="black" + /> + ); + })} + </Layer> + </Stage> + </div> + </div> + ); +}; + +export default RenderDebugPdf; diff --git a/microfrontends/SignDocuments/src/Routes.js b/microfrontends/SignDocuments/src/Routes.js index 58039a599..117ea04fe 100644 --- a/microfrontends/SignDocuments/src/Routes.js +++ b/microfrontends/SignDocuments/src/Routes.js @@ -10,7 +10,7 @@ import LegaDrive from "./Component/LegaDrive/LegaDrive"; import PageNotFound from "./Component/PageNotFound"; import TemplatePlaceHolder from "./Component/TemplatePlaceholder"; import Parse from "parse"; -import GuestLogin from "./premitives/GuestLogin"; +import DebugUi from "./Component/DebugUi"; Parse.serverURL = localStorage.getItem("baseUrl"); Parse.initialize(localStorage.getItem("parseAppId")); // `AppRoutes` is used to define route path of app and @@ -51,8 +51,7 @@ function AppRoutes() { <Route path="/legadrive" element={<LegaDrive />} /> {/* Page Not Found */} <Route path="/template/:templateId" element={<TemplatePlaceHolder />} /> - <Route path="/guestlogin" element={<GuestLogin />} /> - + <Route path="/debugpdf" element={<DebugUi />} /> <Route path="*" element={<PageNotFound />} /> </Routes> </div> diff --git a/microfrontends/SignDocuments/src/premitives/Alert.js b/microfrontends/SignDocuments/src/premitives/Alert.js index 72e3d1458..0f10cf3c8 100644 --- a/microfrontends/SignDocuments/src/premitives/Alert.js +++ b/microfrontends/SignDocuments/src/premitives/Alert.js @@ -5,20 +5,47 @@ const Alert = ({ children, type }) => { function theme(color) { switch (color) { case "success": - return "border-[#c3e6cb] bg-[#d4edda] text-[#155724]"; + return { + border: `1px solid #c3e6cb`, // Border color + backgroundColor: "#d4edda", // Background color + color: "#155724" // Text color + }; + case "info": - return "border-[#adcdeb] bg-[#c1daf0] text-[#153756]"; + return { + border: `1px solid #adcdeb`, // Border color + backgroundColor: "#c1daf0", // Background color + color: "#153756" // Text color + }; case "danger": - return "border-[#f0a8a8] bg-[#f4bebe] text-[#c42121]"; + return { + border: `1px solid #f0a8a8`, // Border color + backgroundColor: "#f4bebe", // Background color + color: "#c42121" // Text color + }; default: - return "border-[#d6d6d6] bg-[#d9d9d9] text-[#575757]"; + return { + border: `1px solid #d6d6d6`, // Border color + backgroundColor: "#d9d9d9", // Background color + color: "#575757" // Text color + }; } } return ( <> {children && ( <div - className={`z-40 fixed top-20 left-1/2 transform -translate-x-1/2 border-[1px] text-sm ${textcolor} rounded py-[.75rem] px-[1.25rem] `} + style={{ + ...textcolor, + position: "fixed", + top: "20px", + left: "50%", + transform: "translateX(-50%)", + fontSize: "0.875rem", // Corresponds to text-sm in Tailwind CSS + borderRadius: "5px", // Rounded corners + padding: "10px 15px", // Padding + zIndex: 40 + }} > {children} </div> diff --git a/microfrontends/SignDocuments/src/premitives/GuestLogin.js b/microfrontends/SignDocuments/src/premitives/GuestLogin.js deleted file mode 100644 index 4df8a9960..000000000 --- a/microfrontends/SignDocuments/src/premitives/GuestLogin.js +++ /dev/null @@ -1,294 +0,0 @@ -import React, { useState } from "react"; -import ModalUi from './ModalUi' -import "../css/LoginPage.css"; -import loader from "../assests/loader2.gif"; -import axios from "axios"; -import { useParams } from "react-router-dom"; -import { themeColor } from "../utils/ThemeColor/backColor"; -import { useEffect } from "react"; -import { useNavigate } from "react-router-dom"; -import GuestSign from "./GuestSign"; - -function GuestLogin({children, userdetails}) { - const { id, userMail, contactBookId, serverUrl } = useParams(); - let navigate = useNavigate(); - const [email, setEmail] = useState(userMail || "prafull.navkar@nxglabs.com"); - const [OTP, setOTP] = useState(""); - const [EnterOTP, setEnterOtp] = useState(false); - const [loading, setLoading] = useState(false); - const [isLoading, setIsLoading] = useState(true); - - useEffect(() => { - handleServerUrl(); - }, []); - - //function generate serverUrl and parseAppId from url and save it in local storage - const handleServerUrl = () => { - //split url in array from '&' - localStorage.clear(); - // const checkSplit = serverUrl?.split("&"); - // const server = checkSplit?.[0]; - // const parseId = checkSplit?.[1]; - // const appName = checkSplit?.[2]; - - // const newServer = server.replaceAll("%2F", "/"); - // localStorage.setItem("baseUrl", newServer); - // localStorage.setItem("parseAppId", parseId); - // localStorage.setItem("_appName", appName); - - localStorage.setItem("baseUrl", "https://staging-app.opensignlabs.com/api/app/"); - localStorage.setItem("parseAppId", "opensignstgn"); - localStorage.setItem("_appName", "contracts"); - setIsLoading(false); - }; - - const handleChange = (event) => { - const { value } = event.target; - setOTP(value); - }; - - //send email OTP function - const SendOtp = async (e) => { - const serverUrl = - localStorage.getItem("baseUrl") && localStorage.getItem("baseUrl"); - const parseId = - localStorage.getItem("parseAppId") && localStorage.getItem("parseAppId"); - if (serverUrl && localStorage) { - setLoading(true); - e.preventDefault(); - setEmail(email); - - try { - let url = `${serverUrl}functions/SendOTPMailV1/`; - const headers = { - "Content-Type": "application/json", - "X-Parse-Application-Id": parseId - }; - let body = { - email: email.toString() - }; - let Otp = await axios.post(url, body, { headers: headers }); - - if (Otp) { - setLoading(false); - setEnterOtp(true); - } - } catch (error) { - alert("something went wrong!"); - } - } else { - alert("something went wrong!"); - } - }; - - //verify OTP send on via email - const VerifyOTP = async (e) => { - e.preventDefault(); - const serverUrl = - localStorage.getItem("baseUrl") && localStorage.getItem("baseUrl"); - const parseId = - localStorage.getItem("parseAppId") && localStorage.getItem("parseAppId"); - if (OTP) { - setLoading(true); - try { - let url = `${serverUrl}functions/AuthLoginAsMail/`; - const headers = { - "Content-Type": "application/json", - "X-Parse-Application-Id": parseId - }; - let body = { - email: email, - otp: OTP - }; - let user = await axios.post(url, body, { headers: headers }); - if (user.data.result === "Invalid Otp") { - alert("Invalid Otp"); - setLoading(false); - } else if (user.data.result === "user not found!") { - alert("User not found!"); - setLoading(false); - } else { - let _user = user.data.result; - const parseId = localStorage.getItem("parseAppId"); - localStorage.setItem("UserInformation", JSON.stringify(_user)); - localStorage.setItem( - `Parse/${parseId}/currentUser`, - JSON.stringify(_user) - ); - localStorage.setItem("username", _user.name); - localStorage.setItem("accesstoken", _user.sessionToken); - //save isGuestSigner true in local to handle login flow header in mobile view - localStorage.setItem("isGuestSigner", true); - setLoading(false); - // uKymQWaYL6 - navigate( - `/loadmf/signmicroapp/recipientSignPdf/${id}/${contactBookId}` - ); - } - } catch (error) {} - } else { - alert("Please Enter OTP!"); - } - }; - - return ( - <div style={{ padding: "2rem" }}> - <ModalUi isOpen> -<> - {isLoading ? ( - <div - style={{ - display: "flex", - justifyContent: "center", - alignItems: "center", - height: "100vh", - flexDirection: "column" - }} - > - <img - alt="no img" - src={loader} - style={{ width: "80px", height: "80px" }} - /> - <span style={{ fontSize: "13px", color: "gray" }}> - {isLoading.message} - </span> - </div> - ) : ( - <div - style={{ - margin: "10px", - border: "0.5px solid #c5c7c9", - padding: "30px", - boxShadow: "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px" - }} - > - <div className="main_head"> - <div className="main-logo"> - <img - alt="sign img" - src="https://qikinnovation.ams3.digitaloceanspaces.com/logo.png" - width="100%" - /> - </div> - </div> - - {!EnterOTP ? ( - <div > - <div > - <span className="welcomeText">Welcome Back !</span> - <br /> - <span className="KNLO"> - Verification code is sent to your email - </span> - <div className="card card-box" style={{ borderRadius: "0px" }}> - <div className="card-body"> - <input - type="email" - name="mobile" - value={email} - disabled - className="loginInput" - /> - <br /> - </div> - </div> - <div className="btnContainer"> - {loading ? ( - <button - type="button" - style={{ - background: themeColor(), - color: "white" - }} - className="verifyBtn" - disabled - > - <span - className="spinner-border spinner-border-sm " - role="status" - aria-hidden="true" - ></span> - Loading... - </button> - ) : ( - <button - className="verifyBtn" - style={{ - background: themeColor(), - color: "white", - marginLeft: "0px !important" - }} - onClick={(e) => SendOtp(e)} - > - Send OTP - </button> - )} - </div> - </div> - </div> - ) : ( - <div > - <div > - <span className="welcomeText">Welcome Back !</span> - <br /> - <span className="KNLO">You will get a OTP via Email</span> - <div className="card card-box"> - <div className="card-body"> - <label>Enter Verification Code</label> - <input - type="number" - className="loginInput" - name="OTP" - value={OTP} - onChange={handleChange} - /> - - <br /> - </div> - </div> - <div> - {loading ? ( - <button - style={{ - background: themeColor(), - color: "white" - }} - className="verifyBtn" - type="button" - disabled - > - <span - className="spinner-border spinner-border-sm " - role="status" - aria-hidden="true" - ></span> - Loading... - </button> - ) : ( - <button - type="button" - onClick={(e) => VerifyOTP(e)} - style={{ - background: themeColor(), - color: "white" - }} - className="verifyBtn" - > - Verify - </button> - )} - </div> - </div> - </div> - )} - </div> - )} - </> - </ModalUi> - <div><GuestSign /></div> - </div> - ); -} - -export default GuestLogin;