diff --git a/src/components/CommonNav.tsx b/src/components/CommonNav.tsx index c804311..f128de9 100644 --- a/src/components/CommonNav.tsx +++ b/src/components/CommonNav.tsx @@ -300,7 +300,7 @@ const CommonNav: React.FC = () => { aria-expanded={open} aria-haspopup="true" > -
+
{user ? ( {(user?.name?.slice(0, 2)).toUpperCase()} diff --git a/src/components/process/processStepOne/ProcessStepOne.tsx b/src/components/process/processStepOne/ProcessStepOne.tsx index 1249a3e..b7dfb30 100644 --- a/src/components/process/processStepOne/ProcessStepOne.tsx +++ b/src/components/process/processStepOne/ProcessStepOne.tsx @@ -39,6 +39,11 @@ const ProcessStepOne = () => { dispatch(toggleToTemplates()); } + const [editCase , setEditCase] = useState("") + const [editRecipient , setEditRecipient] = useState({}) + + + // if (!accountId || !transactionId) { // window.location.href = "/"; // return null; @@ -57,6 +62,7 @@ const ProcessStepOne = () => { console.log("selectedRecipients", selectedRecipients) useEffect(() => { +<<<<<<< HEAD // Fetching Transaction Details - START (async () => { try { @@ -68,6 +74,12 @@ const ProcessStepOne = () => { })() // Fetching Transaction Details - END +======= + (async () => { + const res = await api.get(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`) + console.log(res.data); + })() +>>>>>>> origin/main selectedRecipients.length === 0 && dispatch(fetchRecipients({ accountId, transactionId })); selectedDocuments.length === 0 && dispatch(fetchDocuments({ accountId, transactionId })); @@ -164,7 +176,9 @@ const ProcessStepOne = () => { accessCodeDelivery: true, language: "en", name: `${recipient.firstName} ${recipient.lastName}`, - roleName: recipient.roleName + roleName: recipient.roleName, + allowSenderToEdit: recipient.allowSenderToEdit , + allowSenderToDelete: recipient.allowSenderToDelete, })); let recipientsDataTemp = recipientsData; @@ -334,9 +348,9 @@ const ProcessStepOne = () => { { signType !== SignTypeEnum.selfSign &&
- + {/* {signType !== "self-sign" && } */} - +
} diff --git a/src/components/process/processStepOne/RecipientAddCard.tsx b/src/components/process/processStepOne/RecipientAddCard.tsx index eeff5c0..8711c50 100644 --- a/src/components/process/processStepOne/RecipientAddCard.tsx +++ b/src/components/process/processStepOne/RecipientAddCard.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef, useState } from "react"; import { FaPlus } from "react-icons/fa"; -import { addRecipient, Recipient, recipientType } from "../../../store/slices/selectedRecipientsSlice"; +import { addRecipient, Recipient, recipientType, updateRecipient } from "../../../store/slices/selectedRecipientsSlice"; import { useDispatch } from "react-redux"; import { AppDispatch } from "../../../store/store"; import api from "../../../config/api"; @@ -8,6 +8,8 @@ import ContactModal from "./ContactModal"; import useDebouncedEffect from "../../../utlity/useDebounce"; import { IoIosSettings } from "react-icons/io"; import { FiEdit, FiTrash } from "react-icons/fi"; +import { v4 as uuidv4 } from 'uuid'; + interface ContactType { id: string; @@ -21,7 +23,8 @@ export interface ContactTypeObj { contacts: ContactType[]; } -const RecipientAddCard = ({ transactionTemplateToggle }) => { + +const RecipientAddCard = ({ transactionTemplateToggle, editRecipient, editCase ,setEditRecipient, setEditCase }) => { const [contactData, setContactData] = useState({ type: "", contacts: [] }); const [openContactModal, setOpenContactModal] = useState(false); @@ -29,29 +32,79 @@ const RecipientAddCard = ({ transactionTemplateToggle }) => { const dispatch = useDispatch(); const formRef = useRef(null); - const [recipient, setRecipients] = useState({ firstName: "", lastName: "", email: "", hostName: "", hostEmail: "", roleName: "", type: recipientType.SIGNER, allowSenderToEdit: Boolean, allowSenderToRemove: Boolean }); + const [recipient, setRecipients] = useState({ uuid:null, newOne:false, firstName: "", lastName: "", email: "", hostName: "", hostEmail: "", roleName: "", type: recipientType.SIGNER, allowSenderToEdit: false, allowSenderToDelete: false }); const [showAdvanceSettings, setShowAdvanceSettings] = useState(false) console.log(recipient) - const handleRecipientAdd = (e: React.FormEvent) => { - e.preventDefault(); - - if (recipient.lastName === "" || recipient.email === "" || !recipient.type) return; - - // Validate Email Format - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - if (!emailRegex.test(recipient.email)) { - console.log("Invalid email format"); - return; + useEffect(() => { + if (editCase === "Edit" && editRecipient) { + setRecipients({ + // id:editRecipient.id, + firstName: editRecipient.firstName || "", + lastName: editRecipient.lastName || "", + email: editRecipient.email || "", + hostName: editRecipient.hostName || "", + hostEmail: editRecipient.hostEmail || "", + roleName: editRecipient.roleName || "", + type: editRecipient.type || recipientType.SIGNER, + allowSenderToEdit: editRecipient.allowSenderToEdit ?? false, + allowSenderToDelete: editRecipient.allowSenderToDelete ?? false, + uuid: String(editRecipient?.id ?? editRecipient?.uuid ?? ''), + newOne:editRecipient.newOne ?? false + }); } - // Validation Ends + }, [editCase, editRecipient]); - dispatch(addRecipient(recipient)); - setRecipients({ firstName: "", lastName: "", email: "", hostName: "", hostEmail: "", roleName: "", type: recipientType.SIGNER, allowSenderToEdit: Boolean, allowSenderToRemove: Boolean }); - formRef.current?.reset(); + + const handleRecipientAdd = (e: React.FormEvent) => { + e.preventDefault(); + + console.log("recipientrecipient",recipient) + + if (!recipient.lastName || !recipient.email || !recipient.type) return; + + // ✅ Email format validation + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (!emailRegex.test(recipient.email)) { + console.log("Invalid email format"); + return; } + if (editCase === 'Edit') { + dispatch(updateRecipient(recipient)); + } else { + dispatch(addRecipient({ + ...recipient, + uuid:uuidv4(), + newOne:true + })); + } + + // ✅ Reset state and form + setRecipients({ + firstName: "", + lastName: "", + email: "", + hostName: "", + hostEmail: "", + roleName: "", + type: recipientType.SIGNER, + allowSenderToEdit: false, + allowSenderToDelete: false, + uuid:"", + newOne:false + }); + + // setRecipients(null), + setEditCase("") + + formRef.current?.reset(); +}; + + + + // useEffect(() => { // if (!recipient.firstName.length) return; @@ -133,10 +186,10 @@ const RecipientAddCard = ({ transactionTemplateToggle }) => { } overflow-hidden`} >
- {recipient.allowSenderToEdit && recipient.allowSenderToRemove && "Full permissions granted"} - {recipient.allowSenderToEdit && !recipient.allowSenderToRemove && "Edit permission granted"} - {!recipient.allowSenderToEdit && recipient.allowSenderToRemove && "Delete permission granted"} - {!recipient.allowSenderToEdit && !recipient.allowSenderToRemove && "No permissions granted"} + {recipient.allowSenderToEdit && recipient.allowSenderToDelete && "Full permissions granted"} + {recipient.allowSenderToEdit && !recipient.allowSenderToDelete && "Edit permission granted"} + {!recipient.allowSenderToEdit && recipient.allowSenderToDelete && "Delete permission granted"} + {!recipient.allowSenderToEdit && !recipient.allowSenderToDelete && "No permissions granted"}
{/* Animated Permission Controls */} @@ -178,23 +231,23 @@ const RecipientAddCard = ({ transactionTemplateToggle }) => { {/* Delete Permission */}
@@ -332,7 +385,7 @@ const RecipientAddCard = ({ transactionTemplateToggle }) => { type="submit" className="inline-flex items-center gap-2 bg-[var(--primary)] hover:bg-[var(--primaryLight2)] text-white text-sm font-semibold px-5 py-2 rounded-md transition" > - Add Recipient + {editCase === "Edit" ? "Edit Recipient" : "Add Recipient"}
diff --git a/src/components/process/processStepOne/RecipientCards.tsx b/src/components/process/processStepOne/RecipientCards.tsx index 412c067..3492139 100644 --- a/src/components/process/processStepOne/RecipientCards.tsx +++ b/src/components/process/processStepOne/RecipientCards.tsx @@ -13,6 +13,7 @@ import { useState } from "react"; import SigningOrderDiagram from "../../../SigningOrderDiagram "; import { IoCloseOutline } from "react-icons/io5"; import { useParams } from "react-router-dom"; +import { FiEdit } from "react-icons/fi"; const getInitials = (name: string) => { if (!name) return ""; @@ -23,7 +24,13 @@ const getInitials = (name: string) => { .toUpperCase(); }; -const RecipientCards = () => { +type CardsData = { + setEditRecipient: (recipient: any) => void; // Replace `any` with the actual type if known + setEditCase: (string: any) => void; + transactionTemplateToggle: string +}; + +const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateToggle }: CardsData) => { const templateId = useParams<{ templateId: string }>().templateId; let { accountId, transactionId } = useParams<{ accountId: string, transactionId: string }>(); @@ -32,9 +39,9 @@ const RecipientCards = () => { if (!transactionId) { transactionId = templateId; } - + const recipients = useSelector((state: RootState) => state.selectedRecipients.recipients); - console.log("recipients.length",recipients) + console.log("recipients.length", recipients) // const signingOrder = useSelector((state: RootState) => state.selectedRecipients.signingOrder); const signType = useSelector((state: RootState) => state.selectedDocuments.signType); @@ -44,8 +51,15 @@ const RecipientCards = () => { dispatch(updateRecipientOrder({ id, routingOrder: value })); }; + const handleEditRecipient = (recipient) => { + // alert(JSON.stringify(recipient)) + setEditCase('Edit') + setEditRecipient(recipient) + } + const handleRemoveRecipient = (recipient) => { if (!accountId || !transactionId) return; +<<<<<<< HEAD // dispatch(removeSelectedRecipient(recipient)) dispatch(removeRecipientAsync([{ recipientId: recipient.id, @@ -53,6 +67,18 @@ const RecipientCards = () => { accountId: accountId, transactionId: transactionId, }])) +======= + if (recipient.uuid) { + dispatch(removeSelectedRecipient(recipient)) + } else { + dispatch(removeRecipientAsync({ + recipientId: recipient.id, + email: recipient.email, + accountId: accountId, + transactionId: transactionId, + })) + } +>>>>>>> origin/main if (recipients.length === 2) { let leftRecipient = recipients.filter((obj) => { if ("id" in obj && "id" in recipient) { @@ -144,14 +170,45 @@ const RecipientCards = () => {
{signType !== "self-sign" && ( - +
+ {/* Edit Button */} + + + {/* Delete Button */} + +
+ + )} ))} diff --git a/src/components/process/processStepTwo/DocumentContainer.tsx b/src/components/process/processStepTwo/DocumentContainer.tsx index ecaa313..8f7286b 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,304 @@ 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 */} -
+ 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}

-
+ // Add this new handler function to your parent component +const handleDirectPositionChange = (newLeft: number, newTop: number) => { + console.log("handleDirectPositionChange",newLeft,newTop) + if (!selectedTag) return; -
- { - doc.pages && doc.pages.length > 0 && doc.pages.map((page, indx) => { - const key = `${doc.id}_${page.index}`; - return ( -
handleDrop(e, doc.id, indxDoc, page.index)} - onDragOver={handleDragOver} - className='drop-page-in shadow-md relative' - > + if (!currentItem) return; - {/* DROPPED ITEMS - Render only the dropped items for this specific docId and page - STARTS */} - {droppedItems[key]?.map((item, index) => { - if (item.isDeleted) return; + // Ensure values are not negative + const clampedLeft = Math.max(0, newLeft); + const clampedTop = Math.max(0, newTop); - 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` - }} - > + setDroppedItems({ + ...droppedItems, + [key]: Array.isArray(droppedItems[key]) + ? droppedItems[key].map((item, i) => + i === index + ? { + ...item, + dimensions: { + ...item.dimensions, + left: clampedLeft, + top: clampedTop + }, + update: true + } + : item + ) + : [], + }); +}; + + return ( + <> + {/* Center Doc Container - START */} +
+ + { + selectedDocuments.length > 0 ? selectedDocuments.map((doc, indxDoc) => { + return ( +
+
+

{doc.name}

+
+ +
+ { + doc.pages && doc.pages.length > 0 && doc.pages.map((page, indx) => { + const key = `${doc.id}_${page.index}`; + return ( +
handleDrop(e, doc.id, indxDoc, page.index)} + onDragOver={handleDragOver} + className='drop-page-in shadow-md relative' + > + + {/* 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 +1215,34 @@ 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/DirectionalControls.tsx b/src/components/process/processStepTwo/rightSideBar/DirectionalControls.tsx index 95bb714..493e4b8 100644 --- a/src/components/process/processStepTwo/rightSideBar/DirectionalControls.tsx +++ b/src/components/process/processStepTwo/rightSideBar/DirectionalControls.tsx @@ -1,8 +1,9 @@ -import React, { useEffect, useRef } from 'react'; -import { FaArrowUp, FaArrowDown, FaArrowLeft, FaArrowRight, FaRegCircle } from 'react-icons/fa'; +import React, { useEffect, useRef, useState } from 'react'; +import { FaArrowUp, FaArrowDown, FaArrowLeft, FaArrowRight } from 'react-icons/fa'; interface DirectionalControlsProps { onMove: (direction: 'up' | 'down' | 'left' | 'right', stepSize?: number) => void; + onPositionChange?: (left: number, top: number) => void; disabled?: boolean; stepSize?: number; className?: string; @@ -16,23 +17,67 @@ interface DirectionalControlsProps { const DirectionalControls: React.FC = ({ onMove, + onPositionChange, disabled = false, stepSize = 1, className = '', selectedType, }) => { const onMoveRef = useRef(onMove); + const [leftValue, setLeftValue] = useState(''); + const [topValue, setTopValue] = useState(''); useEffect(() => { onMoveRef.current = onMove; }, [onMove]); + useEffect(() => { + const { top = 0, left = 0 } = selectedType || {}; + setLeftValue(Math.round(left).toString()); + setTopValue(Math.round(top).toString()); + }, [selectedType]); + const handleMove = (direction: 'up' | 'down' | 'left' | 'right') => { if (!disabled) { onMoveRef.current(direction, stepSize); } }; + const handlePositionInputChange = (type: 'left' | 'top', value: string) => { + if (type === 'left') { + setLeftValue(value); + } else { + setTopValue(value); + } + }; + + const handlePositionInputBlur = (type: 'left' | 'top') => { + if (!onPositionChange) return; + + const numericValue = parseFloat(type === 'left' ? leftValue : topValue); + if (isNaN(numericValue)) { + const { top = 0, left = 0 } = selectedType || {}; + if (type === 'left') { + setLeftValue(Math.round(left).toString()); + } else { + setTopValue(Math.round(top).toString()); + } + return; + } + + const { top = 0, left = 0 } = selectedType || {}; + const newLeft = type === 'left' ? numericValue : left; + const newTop = type === 'top' ? numericValue : top; + + onPositionChange(newLeft, newTop); + }; + + const handleKeyPress = (e: React.KeyboardEvent, type: 'left' | 'top') => { + if (e.key === 'Enter') { + handlePositionInputBlur(type); + } + }; + useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (disabled) return; @@ -64,57 +109,113 @@ const DirectionalControls: React.FC = ({ const buttonClass = ` p-1 rounded-sm transition-all duration-200 border shadow-sm text-[10px] ${disabled - ? 'bg-gray-100 text-gray-400 cursor-not-allowed' - : 'bg-white text-gray-600 hover:bg-blue-100 active:bg-blue-200 cursor-pointer'} - flex items-center justify-center w-6 h-6 -`; + ? 'bg-gray-100 text-gray-400 cursor-not-allowed' + : 'bg-white text-gray-600 hover:bg-blue-100 active:bg-blue-200 cursor-pointer'} + flex items-center justify-center w-6 h-6 `; + const inputClass = ` + w-12 h-6 text-[10px] text-center border rounded px-1 bg-white + ${disabled + ? 'bg-gray-100 text-gray-400 cursor-not-allowed border-gray-300' + : 'text-gray-600 border-gray-300 focus:border-blue-400 focus:outline-none'} + `; const { top = 0, left = 0, width = 0, height = 0 } = selectedType || {}; - const right = left + width; - const bottom = top + height; - return ( -
- {/* Top Row */} -
-
- - Top: {Math.round(top)}px -
-
- - {/* Middle Row */} -
- - Left: {Math.round(left)}px +
+ {/* Top Button */} +
+
+ + Top +
-
+ {/* Middle Row: Left - Center (Inputs) - Right */} +
+ {/* Left Button */} +
+ + Left +
-
- - {/* Right: {Math.round(right)}px */} + {/* Center Panel */} +
+ {/* Floating dimensions tooltip */} +
+ handlePositionInputChange('left', e.target.value)} + onBlur={() => handlePositionInputBlur('left')} + onKeyPress={(e) => handleKeyPress(e, 'left')} + disabled={disabled} + className="w-[40px] h-[16px] text-[10px] text-center border-none focus:outline-none text-black font-mono" + /> + × + handlePositionInputChange('top', e.target.value)} + onBlur={() => handlePositionInputBlur('top')} + onKeyPress={(e) => handleKeyPress(e, 'top')} + disabled={disabled} + className="w-[40px] h-[16px] text-[10px] text-center border-none focus:outline-none text-black font-mono" + /> +
+
+ + + {/* Right Button */} +
+ + Right +
- {/* Bottom Row */} -
-
- - {/* Bottom: {Math.round(bottom)}px */} + {/* Bottom Button */} +
+
+ + Bottom +
-
); + }; -export default DirectionalControls; +export default DirectionalControls; \ No newline at end of file diff --git a/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx b/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx index 211f67f..ec08e9c 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,24 +175,34 @@ 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 } - setDroppedItems((prev) => ( - { + console.log("val", val) + + setDroppedItems((prev) => { + const updatedArray = Array.isArray(prev[selTagKey]) + ? prev[selTagKey].map((item, i) => { + if (i === selTagIndx) { + const updatedItem = { ...item, [changeTo]: changeWith + " " + val, update: true }; + console.log('Updating item at index', i, 'with:', updatedItem); + return updatedItem; + } + return item; + }) + : []; + + return { ...prev, - [selTagKey]: Array.isArray(prev[selTagKey]) // Ensure it's an array - ? prev[selTagKey].map((item, i) => - i === selTagIndx ? { ...item, [changeTo]: changeWith + " " + val, update: true } : item - ) - : [], - }// Provide a fallback in case it's undefined or not an array - )); + [selTagKey]: updatedArray, + }; + }); + } else { setDroppedItems((prev) => { - console.log('Previous state:', prev); const updatedItems = Array.isArray(prev[selTagKey]) ? prev[selTagKey].map((item, i) => @@ -302,7 +321,7 @@ const RightSideBar: React.FC = ({ selectedTag, setDroppedItems } - + {selectedTag.label && @@ -388,7 +407,7 @@ const RightSideBar: React.FC = ({ selectedTag, setDroppedItems - { + {(selectedTag.type.toLowerCase() !== TagsTypes.SIGNATURE && selectedTag.type.toLowerCase() !== TagsTypes.INITIALS) &&
setStyleOpen(!styleOpen)} diff --git a/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx b/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx index dfc42bf..0d07995 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) => { @@ -84,6 +86,7 @@ const TemporalDateAttr: React.FC = ({ subType, format, drop val = val + " " + timeFormats[1].format; } } + console.log('line 89' , val ) return (
= ({ getAllSignatures, editingSignature }) => { - const [activeTab, setActiveTab] = useState<'TYPE' | 'DRAW' | 'UPLOAD' | 'SELECT'>('TYPE'); + const [activeTab, setActiveTab] = useState<'TYPE' | 'DRAW' | 'UPLOAD' >('TYPE'); const [fullName, setFullName] = useState(''); const [initials, setInitials] = useState(''); const [isSubmitting, setIsSubmitting] = useState(false); @@ -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: "" } ); @@ -105,7 +110,7 @@ const AddSignatureModal: React.FC = ({ { id: 'TYPE', label: 'TYPE', icon: }, { id: 'DRAW', label: 'DRAW', icon: }, { id: 'UPLOAD', label: 'UPLOAD', icon: }, - { id: 'SELECT', label: 'SELECT', icon: }, + // { id: 'SELECT', label: 'SELECT', icon: }, ]; // Initialize form with editing signature data @@ -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,16 +394,14 @@ const AddSignatureModal: React.FC = ({
); - - - case 'SELECT': - return ( -
-
-

Select Signature

-
-
- ); + // case 'SELECT': + // return ( + //
+ //
+ //

Select Signature

+ //
+ //
+ // ); default: return null; } @@ -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/setting/Signature/Signature.tsx b/src/components/setting/Signature/Signature.tsx index 45074b7..5ff4581 100644 --- a/src/components/setting/Signature/Signature.tsx +++ b/src/components/setting/Signature/Signature.tsx @@ -232,7 +232,7 @@ const SignatureManager: React.FC = () => { {/* Empty State (if no signatures) */} {signatures.length === 0 && ( -
+
diff --git a/src/components/templates/Templates.tsx b/src/components/templates/Templates.tsx index 52a25f8..47c22c6 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 */}