From 68f0185c7646444c317293d89b4191050267b6ad Mon Sep 17 00:00:00 2001 From: =bhagwanSingh <=bhagwan.r@hicglobalsolutions.com> Date: Mon, 13 Oct 2025 19:38:34 +0530 Subject: [PATCH] 13-10 | 07:38 --- src/components/client/SignDocument.tsx | 25 ++- src/components/client/TagsCon.tsx | 40 +++-- .../processStepTwo/DocumentContainer.tsx | 64 ++++--- .../processStepTwo/DroppedItemsTagsCon.tsx | 12 +- .../process/processStepTwo/FieldList.tsx | 9 +- .../process/processStepTwo/LeftSideBar.tsx | 161 +++++++----------- .../process/processStepTwo/NavTwo.tsx | 24 +-- .../setting/Signature/AddSignatureModal.tsx | 8 +- src/components/signature/ClientSignCon.tsx | 10 +- src/components/templates/TemplateTable.tsx | 7 + 10 files changed, 189 insertions(+), 171 deletions(-) diff --git a/src/components/client/SignDocument.tsx b/src/components/client/SignDocument.tsx index 2c3e692..056e112 100644 --- a/src/components/client/SignDocument.tsx +++ b/src/components/client/SignDocument.tsx @@ -626,22 +626,29 @@ const SignDocument = () => { useEffect(() => { const allRequiredFields = droppedItems.filter((item, idx) => { if (!item.required) return false - if ((item.required && item.value && item.type != "SIGNATURE" && item.type != "INITIALS") || - - ( + 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 - return true + return false; }) const totalRequiredFields = droppedItems.reduce((acc, obj) => { @@ -1043,7 +1050,9 @@ const SignDocument = () => { doc.pages && doc.pages.length > 0 && doc.pages.map((page, indx) => { const key = `${doc.documentId}_${page.index}`; // const tagJsonData = [...droppedItems]; - const currDocTags = droppedItems.filter((val) => val.pageIndex == page.index) + 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 (
= ({ }; const handleTagUpdate = (updateIndx: number, updateValue: string) => { + console.log(currDocTags) if (droppedItems && droppedItems.length) { const updatedTag = droppedItems.map((val, indx) => { if (indx == updateIndx) { @@ -238,8 +239,8 @@ const TagsCon: React.FC = ({ // }); } - const handleSignClick = async (index: number, id: number | undefined) => { - id = (id != undefined && id != null) ? id : index + const handleSignClick = async (index: number, id: string | undefined) => { + id = (id !== undefined && id !== null) ? id : index setSignTagId(id) if (saved.save) { if (saved.isDefaultAndClicked) { @@ -392,9 +393,9 @@ const TagsCon: React.FC = ({ !item.multiLine && !item.maskType &&

{ + onChange={(e) => { const val = e.currentTarget.textContent; - handleTagUpdate(index, val as string); + handleTagUpdate(item.originalIndex, val as string); }} onKeyDown={(e) => { if (e.key == "Enter") e.preventDefault(); @@ -408,7 +409,7 @@ const TagsCon: React.FC = ({ suppressContentEditableWarning onBlur={(e) => { const val = e.currentTarget.textContent; - handleTagUpdate(index, val as string); + handleTagUpdate(item.originalIndex, val as string); }} contentEditable={true} className="w-full outline-none max-h-max" @@ -418,7 +419,7 @@ const TagsCon: React.FC = ({ "maskType" in item && "maskCharacter" in item && item.maskType &&

{ // const val = e.currentTarget.textContent; - // handleTagUpdate(index, val as string); + // handleTagUpdate(item.originalIndex, val as string); // }} onKeyDown={(e) => { if (e.key == "Enter") e.preventDefault(); @@ -427,7 +428,7 @@ const TagsCon: React.FC = ({ // }} onBlur={(e) => { let val = e.target.textContent; - handleTagUpdate(index, val as string); + handleTagUpdate(item.originalIndex, val as string); if (typeof item.maskType == "string" && typeof val == "string" && item.maskCharacter) { val = val.replace(/ /g, ""); e.target.textContent = maskUtils(item.maskType, val, item.maskCharacter) @@ -455,7 +456,7 @@ const TagsCon: React.FC = ({ // style={{ height: item.dimensions.height + "px" }} onInput={(e) => { const val = e.currentTarget.textContent; - handleTagUpdate(index, val as string); + handleTagUpdate(item.originalIndex, val as string); }} onKeyDown={(e) => { if (e.key == "Enter") { @@ -464,7 +465,7 @@ const TagsCon: React.FC = ({ if (val && !emailRegex.test(val)) { alert("Please enter a valid email address"); - handleTagUpdate(index, "" as string) + handleTagUpdate(item.originalIndex, "" as string) e.currentTarget.textContent = ""; e.currentTarget.focus(); // Optional: return focus if invalid } @@ -478,7 +479,7 @@ const TagsCon: React.FC = ({ if (val && !emailRegex.test(val)) { alert("Please enter a valid email address"); - handleTagUpdate(index, "" as string) + handleTagUpdate(item.originalIndex, "" as string) e.currentTarget.textContent = ""; e.currentTarget.focus(); // Optional: return focus if invalid } @@ -508,7 +509,7 @@ const TagsCon: React.FC = ({ // style={{ height: item.dimensions.height + "px" }} onInput={(e) => { const val = e.currentTarget.textContent; - handleTagUpdate(index, val as string); + handleTagUpdate(item.originalIndex, val as string); }} onKeyDown={(e) => { if (e.key == "Enter") { @@ -540,9 +541,14 @@ const TagsCon: React.FC = ({ > { { + if (e.key == "e" || e.key == "E") { + e.preventDefault() + }; + }} onInput={(e) => { const val = e.currentTarget.value; - handleTagUpdate(index, val as string); + handleTagUpdate(item.originalIndex, val as string); }} type="number" className="outline-none h-full max-w-max" @@ -568,7 +574,7 @@ const TagsCon: React.FC = ({ // style={{ height: item.dimensions.height + "px" }} onInput={(e) => { const val = e.currentTarget.textContent; - handleTagUpdate(index, val as string); + handleTagUpdate(item.originalIndex, val as string); }} onKeyDown={(e) => { if (e.key == "Enter") { @@ -630,7 +636,7 @@ const TagsCon: React.FC = ({ )) ? ( ) : saved && saved.saveType != null && saved.saveType == "SELECT" ? ( - <>{saved.signature} + <>{saved.signature} ) : ( = ({ )) ? : saved && saved.saveType != null && saved.saveType == "SELECT" ? ( - <>{saved.initial} + <>{saved.initial} ) : ( = ({ className="outline-none" onInput={(e) => { const val = e.currentTarget.value; - handleTagUpdate(index, val as string); + handleTagUpdate(item.originalIndex, val as string); }} > @@ -797,7 +803,7 @@ const TagsCon: React.FC = ({ }} onInput={(e) => { const val = e.currentTarget.value; - handleTagUpdate(index, val as string); + handleTagUpdate(item.originalIndex, val as string); }} style={{ opacity: `${item.id == isDateOpen ? "100" : "0"}` }} className="w-full px-2 outline-none absolute" diff --git a/src/components/process/processStepTwo/DocumentContainer.tsx b/src/components/process/processStepTwo/DocumentContainer.tsx index 1ce10ba..a25cd9f 100644 --- a/src/components/process/processStepTwo/DocumentContainer.tsx +++ b/src/components/process/processStepTwo/DocumentContainer.tsx @@ -234,6 +234,9 @@ const DocumentContainer = forwardRef { + + if (TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES === transactionTemplateToggle) save = true; + dispatch(showLoader("Saving Tags ...")) if (Object.keys(droppedItems).length == 0) return; // if (!save) return; @@ -257,6 +260,9 @@ const DocumentContainer = forwardRef, docId: string, documentId: number, pageIndex: number) => { + const handleDrop = (event: React.DragEvent, docId: string, documentId: number, pageIndex: number, originalWidth: number, originalHeight: number) => { event.preventDefault(); + const imageElement = document.getElementById(`${docId}-${pageIndex}`) as HTMLImageElement; + + const currentWidth = imageElement.offsetWidth; + const currentHeight = imageElement.offsetHeight; + + const scaleX = currentWidth / originalWidth; // 350 / 700 = 0.5 + const scaleY = currentHeight / originalHeight; // 225 / 450 = 0.5 const data = window.dragElemData; if (!data) return; @@ -299,27 +312,33 @@ const DocumentContainer = forwardRef; let prepData = { @@ -340,7 +359,7 @@ const DocumentContainer = forwardRef { const tagIndex = key in droppedItems ? droppedItems[key].length : 0; setSelectedTag({ key, index: tagIndex }) - }, 0) + }, 1000) }; // HANDLE DROP - END @@ -517,16 +536,20 @@ const DocumentContainer = forwardRef handleDocumentFocus(key)} key={indx} id={`${doc.id}${indx}`} - onDrop={(e) => handleDrop(e, doc.id, indxDoc, page.index)} + onDrop={(e) => handleDrop(e, doc.id, indxDoc, page.index, page.width, page.height)} onDragOver={handleDragOver} className='drop-page-in shadow-md relative' + style={{ aspectRatio: `${page.width}/${page.height}` }} > +

{selectedTag && selectedTag != null && "key" in selectedTag && "index" in selectedTag && diff --git a/src/components/process/processStepTwo/FieldList.tsx b/src/components/process/processStepTwo/FieldList.tsx index d241e5f..c38c2bc 100644 --- a/src/components/process/processStepTwo/FieldList.tsx +++ b/src/components/process/processStepTwo/FieldList.tsx @@ -20,6 +20,8 @@ const handlePointerDown = (event: React.DragEvent, label: string height = innerIconConRect.height + 10 } + let fontSize = 14.0; + switch (label) { case TagsTypes.STAMP: { width = 160 @@ -29,11 +31,13 @@ const handlePointerDown = (event: React.DragEvent, label: string case TagsTypes.SIGNATURE: { width = 200 height = 75 + fontSize = 42.0 break; } case TagsTypes.INITIALS: { width = 85 height = 75 + fontSize = 42.0 break; } case TagsTypes.COMPANY: { @@ -89,7 +93,8 @@ const handlePointerDown = (event: React.DragEvent, label: string recipientIndx: recipientIndx, width, height, - properties: tagsProperties + properties: tagsProperties, + fontSize: fontSize } if (obj.label.toLowerCase() == "radio" || obj.label.toLowerCase() == "checkbox") obj.group = uuidv4(); @@ -306,7 +311,7 @@ const FieldList: React.FC = ({ color, recipientId, recipientIndx // ); return ( -
+
{tagsData.map((field, index) => { const IconComponent = typeToIconMap[field.type] || ; diff --git a/src/components/process/processStepTwo/LeftSideBar.tsx b/src/components/process/processStepTwo/LeftSideBar.tsx index ac752ac..d560a5e 100644 --- a/src/components/process/processStepTwo/LeftSideBar.tsx +++ b/src/components/process/processStepTwo/LeftSideBar.tsx @@ -91,13 +91,13 @@ const LeftSideBar: React.FC = ({ isFields, isPages, selectedRe <> {/* Left Side Bar - START */} { - (isPages || isFields) &&
+ (isPages || isFields) &&
{ handleSetIsPages(false) handleSetIsFields(false) }} - className='absolute top-[5px] right-[5px] bg-white rounded-full'> + className='absolute sm:hidden top-[5px] right-[10px] bg-white rounded-full text-2xl z-50'>
@@ -121,67 +121,72 @@ const LeftSideBar: React.FC = ({ isFields, isPages, selectedRe {selectedRecipients.length > 0 && isFields && <> {/* Fields List and Recipeint - Start */} {/* Side Bar showing Recipients */} -
setDropDownToggle(false)}> - {/* Selected Recipient */} -
setDropDownToggle(!dropDownToggle)} - className='flex items-center justify-between gap-2 w-full p-2 text-xs rounded-sm border-1 border-slate-200 cursor-pointer'> -
-

- {/* */} -

- { - selectedRecipient.firstName.length == 0 && selectedRecipient.lastName.length == 0 ? - (selectedRecipient.email.length == 0 ? selectedRecipient.roleName : selectedRecipient.email) : - `${selectedRecipient.firstName + " " + selectedRecipient.lastName}` - } -

+
+ +
setDropDownToggle(false)}> + {/* Selected Recipient */} +
setDropDownToggle(!dropDownToggle)} + className='flex items-center justify-between gap-2 w-[75%] sm:w-full p-2 text-xs rounded-sm border-1 border-slate-200 cursor-pointer'> +
+

+ {/* */} +

+ { + selectedRecipient.firstName.length == 0 && selectedRecipient.lastName.length == 0 ? + (selectedRecipient.email.length == 0 ? selectedRecipient.roleName : selectedRecipient.email) : + `${selectedRecipient.firstName + " " + selectedRecipient.lastName}` + } +

+
+
- -
+
+ {selectedRecipients.length && selectedRecipients.map((recipient, indx) => { + if (recipient.type == recipientType.CC) return null; // Skip CC recipients + return (
{ + setSelectedRecipient(indx); + setTimeout(() => { + setDropDownToggle(false); + }, 0) + }} + > +
+

+ {/* */} +

+ { + recipient.firstName.length == 0 && recipient.lastName.length == 0 ? + (recipient.email.length == 0 ? recipient.roleName : recipient.email) : + `${recipient.firstName + " " + recipient.lastName}` + } +

+
+ {selectedRecipientIndx == indx && } +
) + })} +
+
+ {/* Side Bar showing Recipients - ENDS*/} + + {/* Drag Drop Tags Start */}
- {selectedRecipients.length && selectedRecipients.map((recipient, indx) => { - if (recipient.type == recipientType.CC) return null; // Skip CC recipients - return (
{ - setSelectedRecipient(indx); - setTimeout(() => { - setDropDownToggle(false); - }, 0) - }} - > -
-

- {/* */} -

- { - recipient.firstName.length == 0 && recipient.lastName.length == 0 ? - (recipient.email.length == 0 ? recipient.roleName : recipient.email) : - `${recipient.firstName + " " + recipient.lastName}` - } -

-
- {selectedRecipientIndx == indx && } -
) - })} + id='tags-con-dash-left' + className='mt-4 w-full'> +
-
- {/* Side Bar showing Recipients - ENDS*/} - {/* Drag Drop Tags Start */} -
-
+ {/* Fields List and Recipeint - End */} } @@ -280,54 +285,10 @@ const LeftSideBar: React.FC = ({ isFields, isPages, selectedRe {/* Small Devices - START */} -
- - {/* Left Side Pages */} - {!isPages &&
{ - handleSetIsPages(true) - handleSetIsFields(false) - }} - className='sm:hidden fixed top-[8%] left-0 bg-[var(--primary)] z-50 flex items-center text-white rounded-tr-md rounded-br-md cursor-pointer opacity-30 hover:opacity-100 transition-all duration-300'> -
- -

- P - A - G - E - S -

-
-
} - - -
{ - handleSetIsPages(false) - handleSetIsFields(true) - }} - > -
- -

- T - A - G - S -

-
-
- - -
{/* Small Devices - END */} - - ) } diff --git a/src/components/process/processStepTwo/NavTwo.tsx b/src/components/process/processStepTwo/NavTwo.tsx index 4ca7dcc..ebbc600 100644 --- a/src/components/process/processStepTwo/NavTwo.tsx +++ b/src/components/process/processStepTwo/NavTwo.tsx @@ -172,8 +172,8 @@ const NavTwo: React.FC = ({ function handleSend(isSignSend: boolean = false) { // dispatch(showLoader("Loading ...")); - const transactionSendValidationObj = transactionSendValidation() - if(transactionSendValidationObj.oneSignerIsRequiredError) { + const transactionSendValidationObj = transactionSendValidation() + if (transactionSendValidationObj.oneSignerIsRequiredError) { return } @@ -183,16 +183,16 @@ const NavTwo: React.FC = ({ // setIsSend(!isSend); // setTimeout(() => { - if (transactionTemplateToggle == TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS) { - if (isSignSend) { - window.open(`./../../../sign/${selfUserSign.recipientId}`, "_self"); - } - else { - onSendClick(); - } - } else { - navigate(`/templates`); + if (transactionTemplateToggle == TRANSACTION_TEMPLATE_TOGGLE.TRANSACTIONS) { + if (isSignSend) { + window.open(`./../../../sign/${selfUserSign.recipientId}`, "_self"); } + else { + onSendClick(); + } + } else { + onSendClick(); + } // }, 1000) } @@ -435,7 +435,7 @@ const NavTwo: React.FC = ({
{/* Right Side - ENDS */} -
+
{/* Nav Two - Oprions - End */} ) diff --git a/src/components/setting/Signature/AddSignatureModal.tsx b/src/components/setting/Signature/AddSignatureModal.tsx index 7271430..3e3ed20 100644 --- a/src/components/setting/Signature/AddSignatureModal.tsx +++ b/src/components/setting/Signature/AddSignatureModal.tsx @@ -306,7 +306,7 @@ const AddSignatureModal: React.FC = ({ Confirm your name and choose signature style. *Are required fields. -
+
{/* Signature Style Options */} -
+
{fontsMap.map((opt) => (
= ({ ? "ring-2 ring-[var(--mainPrimaryBtn)]" : "hover:shadow-md"}`} > -
+
{fullName || "Full Name"}
{initials || "AB"}
diff --git a/src/components/signature/ClientSignCon.tsx b/src/components/signature/ClientSignCon.tsx index 56b215c..82a29f7 100644 --- a/src/components/signature/ClientSignCon.tsx +++ b/src/components/signature/ClientSignCon.tsx @@ -345,7 +345,7 @@ const ClientSignCon: React.FC = ({ Confirm your name and choose signature style. *Are required fields. -
+
{/* Signature Style Options */} -
+
{fontsMap.map((opt) => (
setSelectedSignature({ id: opt.acronym, style: opt.style })} - className={`cursor-pointer border border-slate-200 rounded-xl p-4 text-center bg-white transition + className={`cursor-pointer border border-slate-200 rounded-xl p-1 text-center bg-white transition ${selectedSignature.id == opt.acronym ? "ring-2 ring-[var(--mainPrimaryBtn)]" : "hover:shadow-md"}`} > -
+
{fullName || "Full Name"}
{initials || "AB"}
diff --git a/src/components/templates/TemplateTable.tsx b/src/components/templates/TemplateTable.tsx index 6cfe9cc..5570a48 100644 --- a/src/components/templates/TemplateTable.tsx +++ b/src/components/templates/TemplateTable.tsx @@ -5,6 +5,10 @@ import logoRecord from "../../assets/record.svg"; import Loader from "../dashboard/Loader"; import api from "../../config/api"; import TemplateDeleteWarnModal from "./TemplateDeleteWarnModal"; +import { resetRecipients } from "../../store/slices/selectedRecipientsSlice"; +import { resetDocuments } from "../../store/slices/documentSlice"; +import { AppDispatch } from "../../store/store"; +import { useDispatch } from "react-redux"; interface Template { id: number; @@ -23,6 +27,7 @@ const formatDate = (isoString: string) => { }; const TemplateTable = () => { + const dispatch = useDispatch(); const [activeAccountId, setActiveAccountId] = useState( JSON.parse(sessionStorage.getItem('activeAccountId') || 'null') @@ -75,6 +80,8 @@ const TemplateTable = () => { const handleUseClick = async (item: Template) => { try { + await dispatch(resetRecipients()) + await dispatch(resetDocuments()) const payload = { name: item.name ?? "", subject: item.description,