From 444de539f46b79c0b5e9adbbf330f8437fe161f5 Mon Sep 17 00:00:00 2001 From: =bhagwanSingh <=bhagwan.r@hicglobalsolutions.com> Date: Tue, 5 Aug 2025 13:03:25 +0530 Subject: [PATCH] Default Sign Fill Done --- src/components/client/SignDocument.tsx | 197 ++++++++++++++++-- .../processStepTwo/DocumentContainer.tsx | 13 -- .../process/processStepTwo/FieldList.tsx | 21 +- src/components/signature/SignCon.tsx | 16 +- 4 files changed, 207 insertions(+), 40 deletions(-) diff --git a/src/components/client/SignDocument.tsx b/src/components/client/SignDocument.tsx index 076c84c..5bdb472 100644 --- a/src/components/client/SignDocument.tsx +++ b/src/components/client/SignDocument.tsx @@ -12,7 +12,7 @@ import { useDispatch, useSelector } from "react-redux"; import { hideLoader, showLoader } from "../../store/slices/loaderSlice"; import { FaRegImage, FaFileAlt, FaSignature, FaStamp, FaCheck, FaQuestionCircle } from 'react-icons/fa' -import { IoIosDocument } from 'react-icons/io' +import { IoIosDocument, IoMdClose } from 'react-icons/io' import { MdKeyboardArrowDown } from 'react-icons/md' import { TbChevronsDownLeft, TbSignature } from "react-icons/tb"; import { BsFileArrowDownFill } from "react-icons/bs"; @@ -139,6 +139,8 @@ const SignDocument = () => { // Signer data - START const [selectedDocuments, setSelectedDocuments] = useState(null); + const [selectedTag, setSelectedTag] = useState<{ key: string, index: number } | null>(null); + const [recipient, setRecipient] = useState(null); const [tagJson, setTagJson] = useState([]); const [transaction, setTransaction] = useState(null); @@ -194,6 +196,10 @@ const SignDocument = () => { } } + const handleTagClick = (key: string, index: number) => { + setSelectedTag({ key, index }) + } + useEffect(() => { let indx = fitObj[selFitIndx].value if (indx === "FIT") { @@ -680,6 +686,17 @@ const SignDocument = () => { // setDroppedItems(dataToSet); // } + 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]); // setDroppedItemsCounter((prev) => prev + 1); @@ -696,6 +713,8 @@ const SignDocument = () => { // HANDLE TAG MOUSE DOWN - START const handleTagMouseDown = (event: React.MouseEvent, key: string, index: number) => { + setSelectedTag({ key, index }) + event.preventDefault(); let targetContainer = event?.currentTarget?.parentElement?.parentElement; @@ -759,6 +778,99 @@ const SignDocument = () => { // HANDLE TAG MOUSE DOWN - END + // Updated handleRemoveTag function with your existing API logic and group handling + const handleRemoveTag = (key: string, targetIndex: number) => { + + console.log(droppedItems, "Line 784") + + const tag = droppedItems[key][targetIndex]; + const recipientId = tag.recipientId; + + (async () => { + if ("id" in tag) { + try { + const response = await api.delete(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}/recipients/${recipientId}/tags/${tag.id}`) + if (response.status !== 200) throw "Tag Deletion error" + } catch (err) { + console.error("Tag Deletion error") + return; + } + } + + setSelectedTag(null); + + // Check if this item has a group for special group handling + if ('group' in tag && tag.group) { + const groupId = tag.group; + + // Find all items in the same group + const groupItems = droppedItems[key] + .map((item, idx) => ({ item, index: idx })) + .filter(({ item }) => 'group' in item && item.group === groupId && !item.isDeleted); + + // Sort group items by their top position to identify the parent (top-most) + groupItems.sort((a, b) => a.item.dimensions.top - b.item.dimensions.top); + + // Check if the item being removed is the parent (top-most item) + const isParentItem = groupItems.length > 0 && groupItems[0].index === targetIndex; + + if (isParentItem && groupItems.length > 1) { + // If removing the parent and there are child items, mark all items in the group as deleted + console.log(`Removing parent item and all children for group: ${groupId}`); + + // Get indices of all group items to mark as deleted + const indicesToDelete = groupItems.map(({ index }) => index); + + setDroppedItems(prevState => ({ + ...prevState, + [key]: prevState[key].map((item, index) => + indicesToDelete.includes(index) ? { ...item, isDeleted: true } : item + ) + })); + + // Remove group border elements after state update + // setTimeout(() => { + // removeGroupBorders(groupId); + // }, 100); + + } else { + // If removing a child item or the only item in group, just mark this item as deleted + console.log(`Removing individual item from group: ${groupId}`); + + setDroppedItems(prevState => ({ + ...prevState, + [key]: prevState[key].map((item, index) => + index === targetIndex ? { ...item, isDeleted: true } : item + ) + })); + + // Check if this was the last item in the group after state update + // setTimeout(() => { + // const remainingGroupItems = droppedItems[key].filter(item => + // 'group' in item && item.group === groupId && !item.isDeleted + // ); + + // if (remainingGroupItems.length === 0) { + // // Remove group borders if no items left + // removeGroupBorders(groupId); + // } else { + // // Update group borders for remaining items + // handleIGroupBorderPosition(groupId); + // } + // }, 100); + } + } else { + // Handle non-group item removal (your existing logic) + setDroppedItems(prevState => ({ + ...prevState, + [key]: prevState[key].map((item, index) => + index === targetIndex ? { ...item, isDeleted: true } : item + ) + })); + } + })() + }; + console.log(droppedItems, "DROPPED ITEMS LINE 680") // const [showTerms, setShowTerms] = useState(true); @@ -928,6 +1040,7 @@ const SignDocument = () => { console.log(item, "micCheck 842") if (item.pageIndex !== page.index) return; return ( +
setFocusElement({ ...item, focusElementIndx: index })} @@ -946,8 +1059,29 @@ const SignDocument = () => { }} > + <> + {selectedTag?.key && selectedTag.key === key && selectedTag.index === index && +
+
+

+

+ {/*

{IconComponent} +

*/} +

{item.label}

+ { + e.stopPropagation(); + handleRemoveTag(key, index) + }} className='cursor-pointer' /> +
+
} + + {/* TEXT FIELD - START */} - {item.type === "TEXT" && + { + item.type === "TEXT" &&
{ className="outline-none whitespace-nowrap w-full max-h-max" >

} -
} +
+ } {/* TEXT FIELD - END */} {/* CHECKBOX FIELD - START */} - {item.type === "CHECKBOX" && + { + item.type === "CHECKBOX" &&
{ // style={{ height: item.dimensions.height + "px" }} className="w-full px-2 outline-none" type="checkbox" /> -
} + + } {/* CHECKBOX FIELD - END */} {/* SIGNATURE FIELD - START */} - {item.type === "SIGNATURE" && + { + item.type === "SIGNATURE" &&
{ src={`data:image/png;base64,${saved.signature}`} /> } -
} + + } {/* SIGNATURE FIELD - END */} {/* INITIALS FIELD - START */} - {item.type === "INITIALS" && + { + item.type === "INITIALS" &&
{ src={`data:image/png;base64,${saved.initial}`} /> } -
} + + } {/* INITIALS FIELD - END */} {/* STAMP FIELD - START */} - {item.type === "STAMP" && + { + item.type === "STAMP" &&
{ : } -
} + + } {/* STAMP FIELD - END */} {/* IMAGE FIELD - START */} - {item.type === "FILE" && + { + item.type === "FILE" &&
{ : } -
} + + } {/* IMAGE FIELD - END */} {/* SELECT FIELD - START */} - {item.type === "SELECT" && + { + item.type === "SELECT" &&
{ }) } -
} + + } {/* SELECT FIELD - END */} @@ -1154,7 +1301,8 @@ const SignDocument = () => { {/* TEMPORAL FIELD - START */} - {item.type === "TEMPORAL" && + { + item.type === "TEMPORAL" &&
{ type={`${item.subType?.toLowerCase() === "date" ? "date" : (item.subType?.toLowerCase() === "time" ? "time" : "datetime-local")}`} /> -
} + + } {/* TEMPORAL FIELD - END */} {/* Attachment Field - START */} - {item.type.toLowerCase() === TagsTypes.ATTACHMENT && + { + item.type.toLowerCase() === TagsTypes.ATTACHMENT &&
{

) } -
} + + } {/* Attachment Field - END */} {/* Focus Show Element */} - {(!transparentTags && !hideTags) && (focusElement && focusElement.documentId === item.documentId && focusElement.focusElementIndx === index) && + { + (!transparentTags && !hideTags) && (focusElement && focusElement.documentId === item.documentId && focusElement.focusElementIndx === index) && <>
{ }
+ ) }) } @@ -1260,7 +1413,7 @@ const SignDocument = () => { {/* Side details of documents Pages and document Name - START */} -

+ < p className='absolute top-[50%] translate-y-[-50%] rotate-[-90deg] text-xs left-[-60px] text-slate-600' > page {indx + 1} of {doc.pages && doc.pages.length}

{/* Side details of documents Pages and document Name - END */} @@ -1333,7 +1486,7 @@ const SignDocument = () => { */} {globalLoader.isLoading && } - + ) } diff --git a/src/components/process/processStepTwo/DocumentContainer.tsx b/src/components/process/processStepTwo/DocumentContainer.tsx index 5663c1a..8ca80b9 100644 --- a/src/components/process/processStepTwo/DocumentContainer.tsx +++ b/src/components/process/processStepTwo/DocumentContainer.tsx @@ -363,19 +363,6 @@ const DocumentContainer: React.FC = ({ transactionSaving const key = `${docId}_${pageIndex}`; // const IconComponent = typeToIconMap[field.type] || ; - // Handling Initia Width and height of Some tags - START - if (dragElemData.label === TagsTypes.STAMP) { - dragElemData.width = 160 - dragElemData.height = 160 - } else if (dragElemData.label === TagsTypes.SIGNATURE) { - dragElemData.width = 200 - dragElemData.height = 75 - } else if (dragElemData.label === TagsTypes.INITIALS) { - dragElemData.width = 85 - dragElemData.height = 75 - } - // Handling Initia Width and height of Some tags - END - let prepData = { properties: data.properties, icon: typeToIconMap[field.label.toUpperCase()] || , diff --git a/src/components/process/processStepTwo/FieldList.tsx b/src/components/process/processStepTwo/FieldList.tsx index b5a01bf..5c9cac0 100644 --- a/src/components/process/processStepTwo/FieldList.tsx +++ b/src/components/process/processStepTwo/FieldList.tsx @@ -4,7 +4,7 @@ import fields from '../../../helper/fieldsListData'; import { useParams } from 'react-router-dom'; import typeToIconMap from '../../../helper/iconMap'; import { FaQuestionCircle } from 'react-icons/fa'; -import { TagsProperties } from '../../../utlity/types'; +import { TagsProperties, TagsTypes } from '../../../utlity/types'; import { v4 as uuidv4 } from "uuid"; import axios from 'axios'; @@ -13,12 +13,25 @@ const handlePointerDown = (event: React.DragEvent, label: string let width = dragElemRect.width let height = dragElemRect.height - if (label === "radio" || label === "checkbox") { + if (label === TagsTypes.RADIO || label === TagsTypes.CHECKBOX) { const innerIconConRect = event.currentTarget.children[0].getBoundingClientRect(); width = innerIconConRect.width + 10 height = innerIconConRect.height + 10 } + // Handling Initia Width and height of Some tags - START + if (label === TagsTypes.STAMP) { + width = 160 + height = 160 + } else if (label === TagsTypes.SIGNATURE) { + width = 200 + height = 75 + } else if (label === TagsTypes.INITIALS) { + width = 85 + height = 75 + } + // Handling Initia Width and height of Some tags - END + const offsetX = event.clientX - dragElemRect.left; const offsetY = event.clientY - dragElemRect.top; @@ -46,12 +59,12 @@ interface FieldListProps { } const FieldList: React.FC = ({ color, recipientId, recipientIndx, acntId = null }) => { - + const [tagsData, setTagsData] = useState([]); let { accountId } = useParams<{ accountId: string }>(); - if(acntId) { + if (acntId) { accountId = acntId; } diff --git a/src/components/signature/SignCon.tsx b/src/components/signature/SignCon.tsx index 191dab3..31c5545 100644 --- a/src/components/signature/SignCon.tsx +++ b/src/components/signature/SignCon.tsx @@ -26,7 +26,7 @@ import { FaSpinner } from "react-icons/fa"; import { GrCheckboxSelected } from "react-icons/gr"; import { Bounce, toast } from "react-toastify"; import axios from 'axios'; -import { SaveType } from '../client/SignDocument'; +import { SaveType, SaveTypeEnum } from '../client/SignDocument'; import { CiSaveDown1 } from 'react-icons/ci'; import api from '../../config/api'; @@ -160,6 +160,20 @@ const AddSignatureModal: React.FC = ({ }) if (res?.data) { let preSavedSignatures = res?.data + if (res.data.length) { + const defaultVal = res.data.filter((obj, indx) => "default" in obj && obj.default); + const { initialsBlob, signatureBlob } = defaultVal[0]; + + if (initialsBlob && signatureBlob) { + setSaved({ + saveType: SaveTypeEnum.DRAW, + save: true, + signature: signatureBlob, + initial: initialsBlob, + }); + console.log("saved Called Line 174") + } + } setPreSaveSignatures(preSavedSignatures) } })()