diff --git a/src/components/process/processStepOne/RecipientAddCard.tsx b/src/components/process/processStepOne/RecipientAddCard.tsx index eeff5c0..aa26f85 100644 --- a/src/components/process/processStepOne/RecipientAddCard.tsx +++ b/src/components/process/processStepOne/RecipientAddCard.tsx @@ -48,7 +48,7 @@ const RecipientAddCard = ({ transactionTemplateToggle }) => { // Validation Ends dispatch(addRecipient(recipient)); - setRecipients({ firstName: "", lastName: "", email: "", hostName: "", hostEmail: "", roleName: "", type: recipientType.SIGNER, allowSenderToEdit: Boolean, allowSenderToRemove: Boolean }); + setRecipients({ firstName: "", lastName: "", email: "", hostName: "", hostEmail: "", roleName: "", type: recipientType.SIGNER, allowSenderToEdit: false, allowSenderToRemove: false }); formRef.current?.reset(); } diff --git a/src/components/process/processStepTwo/DocumentContainer.tsx b/src/components/process/processStepTwo/DocumentContainer.tsx index ecaa313..c6b44a4 100644 --- a/src/components/process/processStepTwo/DocumentContainer.tsx +++ b/src/components/process/processStepTwo/DocumentContainer.tsx @@ -65,6 +65,11 @@ const DocumentContainer: React.FC = ({ isSend }) => { // const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments) const selectedDocuments = useSelector((state: RootState) => state.documents.documents) + console.log("selectedDocuments",selectedDocuments) + + const [droppedItems, setDroppedItems] = useState({}); + console.log("droppedItems", droppedItems) + // const [uniqGroupIds, setUniqGroupIds] = useState([]); @@ -106,7 +111,7 @@ const DocumentContainer: React.FC = ({ isSend }) => { // FETCHING TAG - END - const [droppedItems, setDroppedItems] = useState({}); + const [droppedItemsCounter, setDroppedItemsCounter] = useState(1); const [selectedTag, setSelectedTag] = useState<{ key: string, index: number } | null>(null); @@ -312,6 +317,7 @@ const DocumentContainer: React.FC = ({ isSend }) => { const dragElemData = JSON.parse(data); // Get the dropped label + const field = { ...dragElemData } if (!field.label) return; @@ -329,8 +335,8 @@ const DocumentContainer: React.FC = ({ isSend }) => { properties: data.properties, icon: typeToIconMap[field.label.toUpperCase()] || , type: dragElemData.label, - subType: (dragElemData.label in droppedTagsDefaultField) ? droppedTagsDefaultField[dragElemData.label] : '', label: dragElemData.label, + subType: (dragElemData.label in droppedTagsDefaultField) ? droppedTagsDefaultField[dragElemData.label] : '', dimensions: { left: x, top: y, @@ -369,6 +375,8 @@ const DocumentContainer: React.FC = ({ isSend }) => { prepData.currentTimeStamp = true; } + + if (prepData.type.toLowerCase() === "number") { prepData.decimalPlace = 0; prepData.isCurrency = false; @@ -412,6 +420,7 @@ const DocumentContainer: React.FC = ({ isSend }) => { // setDroppedItems(dataToSet); // } + console.log("data311", dataToSet) setDroppedItems(dataToSet); setDroppedItemsCounter((prev) => prev + 1); @@ -423,13 +432,11 @@ const DocumentContainer: React.FC = ({ isSend }) => { // HANDLE DROP - END // HANDLE TAG MOUSE DOWN - START + // Updated handleTagMouseDown function with proper group border positioning const handleTagMouseDown = (event: React.MouseEvent, key: string, index: number) => { event.preventDefault(); let targetContainer = event?.currentTarget?.parentElement?.parentElement; - - console.log(targetContainer, "targetContainer line 421") - let targetElement = event?.currentTarget?.parentElement; if (!targetContainer || !targetElement) return; @@ -450,9 +457,11 @@ const DocumentContainer: React.FC = ({ isSend }) => { groupId = event.currentTarget.getAttribute("group"); } - let groupElements: NodeListOf | null = null + let groupElements: NodeListOf | null = null; if (isGroupAttr && groupId) { groupElements = document.querySelectorAll(`div[group="${groupId}"]`); + // Show initial border position during drag start + handleGroupBorderPosition(groupElements, containerRect, offsetX, offsetY); } const handleMouseMove = (event: MouseEvent) => { @@ -460,26 +469,52 @@ const DocumentContainer: React.FC = ({ isSend }) => { let left = event.clientX - containerRect.left - offsetX; let top = event.clientY - containerRect.top - offsetY; - - // **Restrict movement within container bounds** + // Restrict movement within container bounds left = Math.max(0, Math.min(left, conScrollWidth - elementRect.width)); top = Math.max(0, Math.min(top, conScrollHeight - elementRect.height)); - if (groupElements != null && groupElements.length) handleGroupBorderPosition(groupElements, containerRect, offsetX, offsetY); - - // Apply the movement to the element - setDroppedItems({ - ...droppedItems, - [key]: Array.isArray(droppedItems[key]) // Ensure it's an array - ? droppedItems[key].map((item, i) => + // Apply the movement to the element first + setDroppedItems(prevState => ({ + ...prevState, + [key]: Array.isArray(prevState[key]) + ? prevState[key].map((item, i) => i === index ? { ...item, dimensions: { ...item.dimensions, left, top }, update: true } : item ) - : [], // Provide a fallback in case it's undefined or not an array - }); + : [], + })); + // Update group border position during drag if it's a group element + if (groupElements != null && groupElements.length) { + // Use a small timeout to ensure DOM is updated before recalculating borders + requestAnimationFrame(() => { + handleGroupBorderPosition(groupElements!, containerRect, offsetX, offsetY); + }); + } }; const handleMouseUp = () => { + // CRITICAL: Ensure group borders are properly positioned after drag ends + if (groupElements != null && groupElements.length && groupId) { + // Multiple approaches to ensure the positioning works: + + // 1. Immediate update + setTimeout(() => { + handleIGroupBorderPosition(groupId); + }, 10); + + // 2. Secondary update to ensure it's properly positioned + setTimeout(() => { + handleIGroupBorderPosition(groupId); + }, 100); + + // 3. Final update using requestAnimationFrame for DOM sync + requestAnimationFrame(() => { + setTimeout(() => { + handleIGroupBorderPosition(groupId); + }, 50); + }); + } + document.removeEventListener("pointermove", handleMouseMove); document.removeEventListener("pointerup", handleMouseUp); }; @@ -550,13 +585,14 @@ const DocumentContainer: React.FC = ({ isSend }) => { setSelectedTag({ key, index }) } + // Updated handleRemoveTag function with your existing API logic and group handling const handleRemoveTag = (key: string, targetIndex: number) => { 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) { @@ -564,40 +600,301 @@ const DocumentContainer: React.FC = ({ isSend }) => { return; } } - setSelectedTag(null) - setDroppedItems(prevState => ({ - ...prevState, - [key]: prevState[key].map((item, index) => - index === targetIndex ? { ...item, isDeleted: true } : item - ) - })); + + 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 + ) + })); + } })() - } + }; + + // Helper function to remove group border elements from DOM + const removeGroupBorders = (groupId: string) => { + console.log(`Removing borders for group: ${groupId}`); + + const borderPositions = ['top', 'right', 'bottom', 'left']; + + borderPositions.forEach(position => { + const borderElement = document.querySelector(`[border-group='${groupId}'][border-pos='${position}']`); + if (borderElement && borderElement.parentNode) { + borderElement.parentNode.removeChild(borderElement); + } + }); + }; // const handleAddRadioClick = (key:string) => { // console.log("Handle Radio Clicled", key) // console.log(droppedItems, "line 525") // } + const handleIGroupBorderPosition = (groupId: string) => { + console.log("handleIGroupBorderPosition for group:", groupId); + + const groupElements: NodeListOf = document.querySelectorAll(`div[group="${groupId}"]`); + + if (groupElements.length === 0) { + console.log("No group elements found for:", groupId); + return; + } + + let targetContainer = groupElements[0].parentElement?.parentElement; + + if (!targetContainer) { + console.log("No target container found"); + return; + } + + const containerRect = targetContainer.getBoundingClientRect(); + + // Use consistent offset values + const offsetX = 10; + const offsetY = 10; + + // Ensure DOM is fully updated before positioning + requestAnimationFrame(() => { + requestAnimationFrame(() => { + handleGroupBorderPosition(groupElements, containerRect, offsetX, offsetY); + }); + }); + }; + + // Enhanced handleGroupBorderPosition with better positioning logic +const handleGroupBorderPosition = (groupElements: NodeListOf, containerRect: DOMRect, offsetX: number, offsetY: number) => { + if (!groupElements || groupElements.length === 0) return; - const handleAddGroupItemClicked = (key: string, item) => { + const groupId = groupElements[0].getAttribute('group'); + if (!groupId) return; + + // Calculate the bounding box of all group elements + let minLeft = Infinity, minTop = Infinity, maxRight = -Infinity, maxBottom = -Infinity; + + groupElements.forEach(element => { + const parentElement = element.parentElement; + if (!parentElement) return; + + const rect = parentElement.getBoundingClientRect(); + const relativeLeft = rect.left - containerRect.left; + const relativeTop = rect.top - containerRect.top; + const relativeRight = relativeLeft + rect.width; + const relativeBottom = relativeTop + rect.height; + + minLeft = Math.min(minLeft, relativeLeft); + minTop = Math.min(minTop, relativeTop); + maxRight = Math.max(maxRight, relativeRight); + maxBottom = Math.max(maxBottom, relativeBottom); + }); + + // Add some padding around the group + const padding = 10; + minLeft -= padding; + minTop -= padding; + maxRight += padding; + maxBottom += padding; + + const width = maxRight - minLeft; + const height = maxBottom - minTop; + + // Update or create border elements + const borderPositions = ['top', 'right', 'bottom', 'left']; + + borderPositions.forEach(position => { + let borderElement = document.querySelector(`[border-group='${groupId}'][border-pos='${position}']`) as HTMLElement; + + if (!borderElement) { + // Create border element if it doesn't exist + borderElement = document.createElement('div'); + borderElement.className = `group-border ${position === 'bottom' ? 'bottom-border' : ''}`; + borderElement.setAttribute('border-group', groupId); + borderElement.setAttribute('border-pos', position); + + // Add the + icon for bottom border + if (position === 'bottom') { + const addIcon = document.createElement('div'); + addIcon.innerHTML = ''; // You might need to adjust this based on your icon system + addIcon.onclick = () => { + // Find the original item to pass to handleAddGroupItemClicked + const originalItem = droppedItems[key]?.find(item => 'group' in item && item.group === groupId); + if (originalItem) { + handleAddGroupItemClicked(key, originalItem); + } + }; + borderElement.appendChild(addIcon); + } + + // Append to container + groupElements[0].parentElement?.parentElement?.appendChild(borderElement); + } + + // Position the border element + borderElement.style.position = 'absolute'; + borderElement.style.pointerEvents = position === 'bottom' ? 'auto' : 'none'; + + switch (position) { + case 'top': + borderElement.style.left = `${minLeft}px`; + borderElement.style.top = `${minTop}px`; + borderElement.style.width = `${width}px`; + borderElement.style.height = '2px'; + break; + case 'right': + borderElement.style.left = `${maxRight - 2}px`; + borderElement.style.top = `${minTop}px`; + borderElement.style.width = '2px'; + borderElement.style.height = `${height}px`; + break; + case 'bottom': + borderElement.style.left = `${minLeft}px`; + borderElement.style.top = `${maxBottom - 2}px`; + borderElement.style.width = `${width}px`; + borderElement.style.height = '2px'; + break; + case 'left': + borderElement.style.left = `${minLeft}px`; + borderElement.style.top = `${minTop}px`; + borderElement.style.width = '2px'; + borderElement.style.height = `${height}px`; + break; + } + }); +}; + const handleAddGroupItemClicked = (key: string, item: any) => { + console.log("handleAddGroupItemClicked", item); - const groupId = item.group; + const groupId = item.group; - item = { ...item, dimensions: { ...item.dimensions, top: item.dimensions.top + item.dimensions.height + 20 } } + // Find all existing items in this group to determine the bottom-most position + const existingGroupItems = droppedItems[key]?.filter(existingItem => + 'group' in existingItem && existingItem.group === groupId + ) || []; - // dimensions: { ...item.dimensions, left: newLeft, top: newTop } + // Find the bottom-most item in the group + let bottomMostItem = item; + if (existingGroupItems.length > 0) { + bottomMostItem = existingGroupItems.reduce((lowest, current) => { + const currentBottom = current.dimensions.top + current.dimensions.height; + const lowestBottom = lowest.dimensions.top + lowest.dimensions.height; + return currentBottom > lowestBottom ? current : lowest; + }); + } - setTimeout(() => { - handleIGroupBorderPosition(item.group) - }, 0) + // Calculate new position: place below the bottom-most item + const spacing = 10; // Adjust spacing as needed + const newTop = bottomMostItem.dimensions.top + bottomMostItem.dimensions.height + spacing; + // Use the same left position as the parent (original) item + const newItem = { + ...item, + dimensions: { + ...item.dimensions, + left: item.dimensions.left, // Keep same horizontal position as parent + top: newTop // Position below the bottom-most item + }, + isGroupExist: true + }; + + // Update the dropped items setDroppedItems({ ...droppedItems, - [key]: [...droppedItems[key], { ...item, isGroupExist: true }], + [key]: [...droppedItems[key], newItem], }); - } + + // Update group borders after adding the new item + // Use setTimeout to ensure state update is processed + setTimeout(() => { + handleIGroupBorderPosition(groupId); + }, 50); // Slightly longer timeout to ensure DOM updates + }; + + + useEffect(() => { + // Initialize group borders for all existing groups after component updates + const timeoutId = setTimeout(() => { + const allGroupElements = document.querySelectorAll('[group]'); + const groupIds = new Set(); + + allGroupElements.forEach((element) => { + const groupId = element.getAttribute('group'); + if (groupId) { + groupIds.add(groupId); + } + }); + + groupIds.forEach((groupId) => { + handleIGroupBorderPosition(groupId); + }); + }, 100); + + return () => clearTimeout(timeoutId); +}, [droppedItems]); // Re-run when droppedItems changes + // const handleAddRadio = (e: React.MouseEvent, key: string, index: number) => { @@ -610,288 +907,270 @@ const DocumentContainer: React.FC = ({ isSend }) => { // // }], // // } - // // const lastRadioElemRect = e.currentTarget?.parentElement.previousSibling.getBoundingClientRect(); - // // console.log(lastRadioElemRect, "lastRadioElemRect") + // // const lastRadioElemRect = e.currentTarget?.parentElement.previousSibling.getBoundingClientRect(); + // // console.log(lastRadioElemRect, "lastRadioElemRect") - // const setNewData = droppedItems; + // const setNewData = droppedItems; - // if (Array.isArray(setNewData[key][index].radioGroups) && setNewData[key][index].radioGroups?.length > 0) { - // setNewData[key][index].radioGroups?.push(setNewData[key][index].radioGroups[0]) - // } + // if (Array.isArray(setNewData[key][index].radioGroups) && setNewData[key][index].radioGroups?.length > 0) { + // setNewData[key][index].radioGroups?.push(setNewData[key][index].radioGroups[0]) + // } - // setDroppedItems(setNewData); - // }; + // setDroppedItems(setNewData); + // }; - // const handleRadioTagMouseDown = (event: React.MouseEvent, key: string, index: number, radioIndex: number) => { + // const handleRadioTagMouseDown = (event: React.MouseEvent, key: string, index: number, radioIndex: number) => { - // event.preventDefault(); + // event.preventDefault(); - // let targetContainer = event?.currentTarget?.parentElement; - // let targetElement = event?.currentTarget; + // let targetContainer = event?.currentTarget?.parentElement; + // let targetElement = event?.currentTarget; - // if (!targetContainer || !targetElement) return; + // if (!targetContainer || !targetElement) return; - // const containerRect = targetContainer.getBoundingClientRect(); - // const elementRect = targetElement.getBoundingClientRect(); + // const containerRect = targetContainer.getBoundingClientRect(); + // const elementRect = targetElement.getBoundingClientRect(); - // // Calculate the initial offset (where the mouse was clicked inside the element) - // const offsetX = event.clientX - elementRect.left; - // const offsetY = event.clientY - elementRect.top; + // // Calculate the initial offset (where the mouse was clicked inside the element) + // const offsetX = event.clientX - elementRect.left; + // const offsetY = event.clientY - elementRect.top; - // const handleMouseMove = (event: PointerEvent) => { - // // Get new X and Y positions relative to the container - // // let x = offsetX; - // // let y = offsetY; + // const handleMouseMove = (event: PointerEvent) => { + // // Get new X and Y positions relative to the container + // // let x = offsetX; + // // let y = offsetY; - // let x = event.clientX - elementRect.left; - // let y = event.clientY - elementRect.top; + // let x = event.clientX - elementRect.left; + // let y = event.clientY - elementRect.top; - // const newData = droppedItems; + // const newData = droppedItems; - // if (newData[key][index].radioGroups && newData[key][index].radioGroups.length > 0) { - // newData[key][index].radioGroups[radioIndex].dimensions.left = x; - // newData[key][index].radioGroups[radioIndex].dimensions.top = y; + // if (newData[key][index].radioGroups && newData[key][index].radioGroups.length > 0) { + // newData[key][index].radioGroups[radioIndex].dimensions.left = x; + // newData[key][index].radioGroups[radioIndex].dimensions.top = y; - // let topMin = Number.POSITIVE_INFINITY; - // let topMax = Number.NEGATIVE_INFINITY; - // let leftMin = Number.POSITIVE_INFINITY; - // let leftMax = Number.NEGATIVE_INFINITY; + // let topMin = Number.POSITIVE_INFINITY; + // let topMax = Number.NEGATIVE_INFINITY; + // let leftMin = Number.POSITIVE_INFINITY; + // let leftMax = Number.NEGATIVE_INFINITY; - // for (const radio of newData[key][index].radioGroups) { - // if (radio.dimensions.left < leftMin) { - // leftMin = radio.dimensions.left; - // } - // if (radio.dimensions.left > leftMax) { - // leftMax = radio.dimensions.left; - // } - // if (radio.dimensions.top < topMin) { - // topMin = radio.dimensions.top; - // } - // if (radio.dimensions.top > topMax) { - // topMax = radio.dimensions.top; - // } - // } + // for (const radio of newData[key][index].radioGroups) { + // if (radio.dimensions.left < leftMin) { + // leftMin = radio.dimensions.left; + // } + // if (radio.dimensions.left > leftMax) { + // leftMax = radio.dimensions.left; + // } + // if (radio.dimensions.top < topMin) { + // topMin = radio.dimensions.top; + // } + // if (radio.dimensions.top > topMax) { + // topMax = radio.dimensions.top; + // } + // } - // newData[key][index].radioPosition = { - // topMin: topMin, - // topMax: topMax, - // leftMin: leftMin, - // leftMax: leftMax, - // width: leftMax - leftMin, - // height: topMax - topMin - // } + // newData[key][index].radioPosition = { + // topMin: topMin, + // topMax: topMax, + // leftMin: leftMin, + // leftMax: leftMax, + // width: leftMax - leftMin, + // height: topMax - topMin + // } - // newData[key][index].dimensions.left = x; - // newData[key][index].dimensions.top = y; - // } + // newData[key][index].dimensions.left = x; + // newData[key][index].dimensions.top = y; + // } - // setDroppedItems({ ...newData }); - // }; + // setDroppedItems({ ...newData }); + // }; - // const handleMouseUp = () => { - // document.removeEventListener("pointermove", handleMouseMove); - // document.removeEventListener("pointerup", handleMouseUp); - // }; + // const handleMouseUp = () => { + // document.removeEventListener("pointermove", handleMouseMove); + // document.removeEventListener("pointerup", handleMouseUp); + // }; - // // Add event listeners - // document.addEventListener("pointermove", handleMouseMove); - // document.addEventListener("pointerup", handleMouseUp); - // } + // // Add event listeners + // document.addEventListener("pointermove", handleMouseMove); + // document.addEventListener("pointerup", handleMouseUp); + // } - // NEW DIRECTIONAL MOVEMENT HANDLER - START - const handleDirectionalMove = (direction: 'up' | 'down' | 'left' | 'right', stepSize: number = 5) => { - if (!selectedTag) return; + // NEW DIRECTIONAL MOVEMENT HANDLER - START + const handleDirectionalMove = (direction: 'up' | 'down' | 'left' | 'right', stepSize: number = 5) => { + if (!selectedTag) return; - const { key, index } = selectedTag; - const currentItem = droppedItems[key]?.[index]; + const { key, index } = selectedTag; + const currentItem = droppedItems[key]?.[index]; - if (!currentItem) return; + if (!currentItem) return; - let newLeft = currentItem.dimensions.left; - let newTop = currentItem.dimensions.top; + let newLeft = currentItem.dimensions.left; + let newTop = currentItem.dimensions.top; - switch (direction) { - case 'up': - newTop = Math.max(0, newTop - stepSize); - break; - case 'down': - newTop = newTop + stepSize; - break; - case 'left': - newLeft = Math.max(0, newLeft - stepSize); - break; - case 'right': - newLeft = newLeft + stepSize; - break; - } - - setDroppedItems({ - ...droppedItems, - [key]: Array.isArray(droppedItems[key]) - ? droppedItems[key].map((item, i) => - i === index - ? { ...item, dimensions: { ...item.dimensions, left: newLeft, top: newTop }, update: true } - : item - ) - : [], - }); - }; - - // Create a wrapper that matches DirectionalControls' expected signature - const directionalControlsHandler = (direction: 'up' | 'down' | 'left' | 'right') => { - handleDirectionalMove(direction, 5); // Use default stepSize of 5 - }; - - - - - function handleIGroupBorderPosition(groupId: string) { - - const groupElements: NodeListOf = document.querySelectorAll(`div[group="${groupId}"]`); - - let targetContainer = groupElements[0].parentElement?.parentElement; - console.log(targetContainer, "targetContainer line 421") - let targetElement = groupElements[0].parentElement; - - if (!targetContainer || !targetElement) return; - const containerRect = targetContainer.getBoundingClientRect(); - - handleGroupBorderPosition(groupElements, containerRect, 40, 40); + switch (direction) { + case 'up': + newTop = Math.max(0, newTop - stepSize); + break; + case 'down': + newTop = newTop + stepSize; + break; + case 'left': + newLeft = Math.max(0, newLeft - stepSize); + break; + case 'right': + newLeft = newLeft + stepSize; + break; } + setDroppedItems({ + ...droppedItems, + [key]: Array.isArray(droppedItems[key]) + ? droppedItems[key].map((item, i) => + i === index + ? { ...item, dimensions: { ...item.dimensions, left: newLeft, top: newTop }, update: true } + : item + ) + : [], + }); + }; - return ( - <> - {/* Center Doc Container - START */} -
+ // Create a wrapper that matches DirectionalControls' expected signature + const directionalControlsHandler = (direction: 'up' | 'down' | 'left' | 'right') => { + handleDirectionalMove(direction, 5); // Use default stepSize of 5 + }; - { - selectedDocuments.length > 0 ? selectedDocuments.map((doc, indxDoc) => { - return ( -
-
-

{doc.name}

-
+ return ( + <> + {/* Center Doc Container - START */} +
-
- { - doc.pages && doc.pages.length > 0 && doc.pages.map((page, indx) => { - const key = `${doc.id}_${page.index}`; - return ( -
0 ? selectedDocuments.map((doc, indxDoc) => { + return ( +
+
+

{doc.name}

+
- id={`${doc.id}${indx}`} - onDrop={(e) => handleDrop(e, doc.id, indxDoc, page.index)} - onDragOver={handleDragOver} - className='drop-page-in shadow-md relative' - > +
+ { + doc.pages && doc.pages.length > 0 && doc.pages.map((page, indx) => { + const key = `${doc.id}_${page.index}`; + return ( +
{ - if (item.isDeleted) return; + id={`${doc.id}${indx}`} + onDrop={(e) => handleDrop(e, doc.id, indxDoc, page.index)} + onDragOver={handleDragOver} + className='drop-page-in shadow-md relative' + > - const type = item.type.toUpperCase(); - const IconComponent = typeToIconMap[type] || ; - const selectedRecipient = selectedRecipients.filter((obj, indx) => obj.id === item.recipientId); - return ( - <> -
handleTagClick(key, index)} - style={{ - left: `${item.dimensions.left}px`, - top: `${item.dimensions.top}px`, - width: item.type === "radio" ? `${item.dimensions.width + 20}px` : `${item.dimensions.width}px`, - height: item.type === "radio" ? `max-content` : `${item.dimensions.height}px` - }} - > + {/* DROPPED ITEMS - Render only the dropped items for this specific docId and page - STARTS */} + {droppedItems[key]?.map((item, index) => { + if (item.isDeleted) return; + + const type = item.type.toUpperCase(); + const IconComponent = typeToIconMap[type] || ; + const selectedRecipient = selectedRecipients.filter((obj, indx) => obj.id === item.recipientId); + return ( + <> +
handleTagClick(key, index)} + style={{ + left: `${item.dimensions.left}px`, + top: `${item.dimensions.top}px`, + width: item.type === "radio" ? `${item.dimensions.width + 20}px` : `${item.dimensions.width}px`, + height: item.type === "radio" ? `max-content` : `${item.dimensions.height}px` + }} + > - {/* If Selected Tag Recipient Info- START */} - {selectedTag?.key && selectedTag.key === key && selectedTag.index === index && -
-
-

-

{IconComponent} -

-

{item.label}

- { - e.stopPropagation(); - handleRemoveTag(key, index) - }} className='cursor-pointer' /> -
-
} - {/* If Selected Tag Recipient Info- END */} - - - - - {/* Expand Circle - STARTS */} - {item.type !== "radio" &&
handleExpandTag(e, key, index)} - className='w-2.5 h-2.5 absolute bg-red-400 rounded-full bottom-[-8px] right-[-8px] cursor-nw-resize hover:bg-blue-400'> -
} - {/* Expand Circle - ENDS */} - - {/* Tag - START */} - { -
handleTagMouseDown(e, key, index)} - className='p-2 rounded-sm h-full shadow opacity-40 cursor-grab w-full' - style={{ background: selectedRecipient[0]?.color }} - > + {/* If Selected Tag Recipient Info- START */} + {selectedTag?.key && selectedTag.key === key && selectedTag.index === index && +
+
+

- {IconComponent} + className=''>{IconComponent}

+

{item.label}

+ { + e.stopPropagation(); + handleRemoveTag(key, index) + }} className='cursor-pointer' />
- } - {/* Tag - END */} +
} + {/* If Selected Tag Recipient Info- END */} -
+ + + {/* Expand Circle - STARTS */} + {item.type !== "radio" &&
handleExpandTag(e, key, index)} + className='w-2.5 h-2.5 absolute bg-red-400 rounded-full bottom-[-8px] right-[-8px] cursor-nw-resize hover:bg-blue-400'> +
} + {/* Expand Circle - ENDS */} + + {/* Tag - START */} { - "group" in item && item.group && "isGroupExist" in item && !item.isGroupExist && - <> - - -
-
-
-
handleAddGroupItemClicked(key, item)}>
-
-
- - +
handleTagMouseDown(e, key, index)} + className='p-2 rounded-sm h-full shadow opacity-40 cursor-grab w-full' + style={{ background: selectedRecipient[0]?.color }} + > +

+ {IconComponent} +

+
} + {/* Tag - END */} - - ) - } +
- )} - {/* Render only the dropped items for this specific docId and page - ENDS */} + { + "group" in item && item.group && "isGroupExist" in item && !item.isGroupExist && + <> - + +
+
+
+
handleAddGroupItemClicked(key, item)}>
+
+
+ + + } + + + ) + } + + )} + {/* Render only the dropped items for this specific docId and page - ENDS */} + + @@ -902,33 +1181,33 @@ const DocumentContainer: React.FC = ({ isSend }) => { {/*

Document {indxDoc + 1} {doc.name}

*/} - {/* Side details of documents Pages and document Name - END */} - - -
- ) - }) - } -
+ {/* Side details of documents Pages and document Name - END */} +
+ ) + }) + }
- ) - }) : - } -
+
+ ) + }) : + } - {selectedTag && } - {/* Center Doc Container - END */} - - ) - } - export default DocumentContainer; +
+ + {selectedTag && } + {/* Center Doc Container - END */} + + ) +} + +export default DocumentContainer; diff --git a/src/components/process/processStepTwo/rightSideBar/CommonAttrDropDown.tsx b/src/components/process/processStepTwo/rightSideBar/CommonAttrDropDown.tsx index 5ac385e..6d2c5d6 100644 --- a/src/components/process/processStepTwo/rightSideBar/CommonAttrDropDown.tsx +++ b/src/components/process/processStepTwo/rightSideBar/CommonAttrDropDown.tsx @@ -12,6 +12,8 @@ interface CommonAttrDropDownInt { const CommonAttrDropDown: React.FC = ({selectedType, subType, dropDownToggle, setDropDownToggle, handlePropertyChange}) => { + console.log("selectedType, subType,",selectedType, subType) + return (
diff --git a/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx b/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx index 211f67f..1666439 100644 --- a/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx +++ b/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx @@ -33,9 +33,9 @@ export interface DroppedItemProps { selTagIndx: number, DirectionalControlsProps: { onMove: (direction: 'up' | 'down' | 'left' | 'right', stepSize?: number) => void; - disabled?: boolean; - stepSize?: number; - className?: string; + disabled?: boolean; + stepSize?: number; + className?: string; } } @@ -107,7 +107,7 @@ const RightSideBar: React.FC = ({ selectedTag, setDroppedItems const selectedType = selectedTag.type in enumMap && enumMap[selectedTag.type as keyof typeof enumMap]; - // console.log("selectedTag", selectedTag, selectedType) + console.log("selectedTag", selectedTag, selectedType) @@ -118,25 +118,33 @@ const RightSideBar: React.FC = ({ selectedTag, setDroppedItems const [styleOpen, setStyleOpen] = useState(false); const handlePropertyChange = (changeTo: string, changeWith: string | boolean | number, is24Hrs = null) => { - console.log("Handle Property Change Called", "changeTo", changeTo, "changeWith", changeWith) + + console.log("changeTo", changeTo, "changeWith", changeWith) if (changeTo === '' || changeWith === '') return + if (changeWith === "paragraph") { + return + } + if (changeTo === "subType" && (changeWith === TEMPORAL.DATE || changeWith === TEMPORAL.DATE_TIME || changeWith === TEMPORAL.TIME)) { // let change: string = changeWith; // if (change === "DATE TIME") { // change = "DATE_TIME" // } - setDroppedItems((prev) => ( - { + setDroppedItems((prev) => { + console.log("Temporal30", prev); + return { ...prev, [selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array ? prev[selTagKey].map((item, i) => i === selTagIndx ? { ...item, [changeTo]: changeWith || "", format: "", update: true } : item ) - : [], - }// Provide a fallback in case it's undefined or not an array - )); + : [], // Fallback in case it's undefined or not an array + }; + }); + } else if (changeTo === "subType" && typeof changeWith === "string" && changeWith.toLowerCase() === "password") { + console.log("Second check") console.log("Line 161") setDroppedItems((prev) => ( { @@ -150,6 +158,7 @@ const RightSideBar: React.FC = ({ selectedTag, setDroppedItems )); } else if (changeTo === "subType" && (changeWith === NUMBER.CURRENCY || changeWith === NUMBER.INTEGER || changeWith === NUMBER.DECIMAL)) { + console.log("Third check") let decPlace = changeWith !== NUMBER.DECIMAL ? 0 : decimalPlace; const isCurrency = changeWith === NUMBER.CURRENCY; // const currencyType = null @@ -166,6 +175,7 @@ const RightSideBar: React.FC = ({ selectedTag, setDroppedItems )); } else if (changeTo === "format" && selectedTag.subType === TEMPORAL.DATE_TIME) { + console.log("Fourth Check") let val = timeFormats[0].format; if (!is24Hrs) { val = timeFormats[1].format @@ -183,7 +193,6 @@ const RightSideBar: React.FC = ({ selectedTag, setDroppedItems } else { setDroppedItems((prev) => { - console.log('Previous state:', prev); const updatedItems = Array.isArray(prev[selTagKey]) ? prev[selTagKey].map((item, i) => @@ -302,7 +311,7 @@ const RightSideBar: React.FC = ({ selectedTag, setDroppedItems } - + {selectedTag.label && diff --git a/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx b/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx index dfc42bf..d47aca8 100644 --- a/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx +++ b/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx @@ -22,6 +22,8 @@ interface TemporalDateAttrInt { } const TemporalDateAttr: React.FC = ({ subType, format, dropDownToggle, setDropDownToggle, handlePropertyChange }) => { + + const [is24Hrs, setIs24Hrs] = useState(true); const handleIs24HrsClick = (checked: boolean) => { diff --git a/src/components/setting/Signature/AddSignatureModal.tsx b/src/components/setting/Signature/AddSignatureModal.tsx index 285a997..1b05709 100644 --- a/src/components/setting/Signature/AddSignatureModal.tsx +++ b/src/components/setting/Signature/AddSignatureModal.tsx @@ -6,6 +6,7 @@ import DrawSignatureCanvas from './DrawSignatureCanvas'; import { FaSpinner } from "react-icons/fa"; import { GrCheckboxSelected } from "react-icons/gr"; import { Bounce, toast } from "react-toastify"; +import { FiCheck } from 'react-icons/fi'; interface Signature { id: string; @@ -72,6 +73,10 @@ const AddSignatureModal: React.FC = ({ { id: 6, name: 'classic', initials: 'LA', style: 'classic' }, ]; + const [checked, setChecked] = useState(false); + + const toggleCheckbox = () => setChecked(!checked); + const [selectedSignature, setSelectedSignature] = useState( signatureOptions.length > 0 ? { id: signatureOptions[0].id, style: signatureOptions[0].style } : { id: 0, style: "" } ); @@ -134,6 +139,10 @@ const AddSignatureModal: React.FC = ({ setPreview2(`data:image/png;base64,${editingSignature.initialsBlob}`); } } + + if (editingSignature.default) { + setChecked(editingSignature.default) + } } }, [editingSignature]); @@ -197,7 +206,8 @@ const AddSignatureModal: React.FC = ({ initialsBase64: signatures.initials, firstName: fullName.split(' ')[0] || user.firstName, lastName: fullName.split(' ')[1] || user.lastName, - font: selectedSignature.style + font: selectedSignature.style, + default:checked }; let res; @@ -384,8 +394,6 @@ const AddSignatureModal: React.FC = ({
); - - case 'SELECT': return (
@@ -430,7 +438,7 @@ const AddSignatureModal: React.FC = ({
-

Add Signature

+

Add Signature

Create your digital signature

@@ -505,6 +513,35 @@ const AddSignatureModal: React.FC = ({ */} {renderContent()}
+
+ + + {/* Caption text below */} +
{/* Footer Buttons in Main Area */}
diff --git a/src/components/templates/Templates.tsx b/src/components/templates/Templates.tsx index 52a25f8..d281a71 100644 --- a/src/components/templates/Templates.tsx +++ b/src/components/templates/Templates.tsx @@ -61,9 +61,28 @@ const Templates = () => { return new Date(timestamp * 1000).toLocaleString(); }; -const handleUseFun = (id) => { -alert(id) -} + const handleUseClick = async (item: any) => { + try { + const payload = { + name: item?.name ?? "", + subject: item.subject, + message: item.message, + description: item.description, + expireAfter: item.expireAfter, + enableIdStamping: item.enableIdStamping, + allowViewAudit: item.allowViewAudit, + allowReassign: item.allowReassign, + enableSignatureIdStamping: item.enableSignatureIdStamping, + templateId: item.id, + }; + let res = await api.post(`/api/accounts/${activeAccountId}/transactions`, payload) + console.log("handleUseClick", res.data) + // /process-step-one/:accountId/:transactionId + navigate(`/process-step-one/${activeAccountId}/${res?.data?.id}`); + } catch (error) { + console.log(error) + } + } @@ -130,7 +149,7 @@ alert(id) {item.name || 'Dummy'} {formatDate(item.createdAt)} {formatDate(item.lastModifiedAt)} - handleUseFun(item.id)}>Use + handleUseClick(item)}>Use {/* Dropdown Trigger + Tooltip */}