From 4a5ede2891f7c353c03fe606d5feb91f209d41bb Mon Sep 17 00:00:00 2001 From: =bhagwanSingh <=bhagwan.r@hicglobalsolutions.com> Date: Tue, 29 Jul 2025 16:38:32 +0530 Subject: [PATCH] Added Tour --- package-lock.json | 145 ++++++ package.json | 1 + src/App.tsx | 119 ++--- src/components/CommonNav.tsx | 11 +- src/components/client/DocumentPages.tsx | 2 +- src/components/client/SignDocument.tsx | 53 ++- src/components/dashboard/SendForSign.tsx | 4 +- src/components/dashboard/SideBar.tsx | 4 +- src/components/home/StartNow.tsx | 1 + .../process/processStepOne/ProcessStepOne.tsx | 20 +- .../processStepOne/RecipientAddCard.tsx | 1 + .../process/processStepOne/RecipientCards.tsx | 18 +- .../processStepOne/SelectedDocuments.tsx | 4 +- .../processStepTwo/DocumentContainer.tsx | 444 +++++++----------- .../process/processStepTwo/LeftSideBar.tsx | 7 +- .../process/processStepTwo/NavTwo.tsx | 1 + .../rightSideBar/DirectionalControls.tsx | 179 +++---- .../rightSideBar/RightSideBar.tsx | 66 +-- .../rightSideBar/SelectTagAttr.tsx | 55 +-- .../rightSideBar/TemporalDateAttr.tsx | 10 +- src/utlity/JoyRideTour.tsx | 244 ++++++++++ 21 files changed, 853 insertions(+), 536 deletions(-) create mode 100644 src/utlity/JoyRideTour.tsx diff --git a/package-lock.json b/package-lock.json index 8a15b3b..3c842d6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "react-draggable": "^4.4.6", "react-icons": "^5.5.0", "react-id-generator": "^3.0.2", + "react-joyride": "^2.9.3", "react-redux": "^9.2.0", "react-router-dom": "^7.2.0", "react-sortablejs": "^6.1.4", @@ -921,6 +922,12 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@gilbarbara/deep-equal": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@gilbarbara/deep-equal/-/deep-equal-0.3.1.tgz", + "integrity": "sha512-I7xWjLs2YSVMc5gGx1Z3ZG1lgFpITPndpi8Ku55GeEIKpACCPQNS/OTqQbxgTCfq0Ncvcc+CrFov96itVh6Qvw==", + "license": "MIT" + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -2658,6 +2665,12 @@ } } }, + "node_modules/deep-diff": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-1.0.2.tgz", + "integrity": "sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==", + "license": "MIT" + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -2665,6 +2678,15 @@ "dev": true, "license": "MIT" }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3438,6 +3460,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-lite": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-lite/-/is-lite-1.2.1.tgz", + "integrity": "sha512-pgF+L5bxC+10hLBgf6R2P4ZZUBOQIIacbdo8YvuCP8/JvsWxG7aZ9p10DYuLtifFci4l3VITphhMlMV4Y+urPw==", + "license": "MIT" + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -4163,6 +4191,17 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/postcss": { "version": "8.5.6", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", @@ -4323,12 +4362,84 @@ "react": ">= 16.8.0" } }, + "node_modules/react-innertext": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/react-innertext/-/react-innertext-1.1.5.tgz", + "integrity": "sha512-PWAqdqhxhHIv80dT9znP2KvS+hfkbRovFp4zFYHFFlOoQLRiawIic81gKb3U1wEyJZgMwgs3JoLtwryASRWP3Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": ">=0.0.0 <=99", + "react": ">=0.0.0 <=99" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, + "node_modules/react-joyride": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/react-joyride/-/react-joyride-2.9.3.tgz", + "integrity": "sha512-1+Mg34XK5zaqJ63eeBhqdbk7dlGCFp36FXwsEvgpjqrtyywX2C6h9vr3jgxP0bGHCw8Ilsp/nRDzNVq6HJ3rNw==", + "license": "MIT", + "dependencies": { + "@gilbarbara/deep-equal": "^0.3.1", + "deep-diff": "^1.0.2", + "deepmerge": "^4.3.1", + "is-lite": "^1.2.1", + "react-floater": "^0.7.9", + "react-innertext": "^1.1.5", + "react-is": "^16.13.1", + "scroll": "^3.0.1", + "scrollparent": "^2.1.0", + "tree-changes": "^0.11.2", + "type-fest": "^4.27.0" + }, + "peerDependencies": { + "react": "15 - 18", + "react-dom": "15 - 18" + } + }, + "node_modules/react-joyride/node_modules/react-floater": { + "version": "0.7.9", + "resolved": "https://registry.npmjs.org/react-floater/-/react-floater-0.7.9.tgz", + "integrity": "sha512-NXqyp9o8FAXOATOEo0ZpyaQ2KPb4cmPMXGWkx377QtJkIXHlHRAGer7ai0r0C1kG5gf+KJ6Gy+gdNIiosvSicg==", + "license": "MIT", + "dependencies": { + "deepmerge": "^4.3.1", + "is-lite": "^0.8.2", + "popper.js": "^1.16.0", + "prop-types": "^15.8.1", + "tree-changes": "^0.9.1" + }, + "peerDependencies": { + "react": "15 - 18", + "react-dom": "15 - 18" + } + }, + "node_modules/react-joyride/node_modules/react-floater/node_modules/@gilbarbara/deep-equal": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@gilbarbara/deep-equal/-/deep-equal-0.1.2.tgz", + "integrity": "sha512-jk+qzItoEb0D0xSSmrKDDzf9sheQj/BAPxlgNxgmOaA3mxpUa6ndJLYGZKsJnIVEQSD8zcTbyILz7I0HcnBCRA==", + "license": "MIT" + }, + "node_modules/react-joyride/node_modules/react-floater/node_modules/is-lite": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/is-lite/-/is-lite-0.8.2.tgz", + "integrity": "sha512-JZfH47qTsslwaAsqbMI3Q6HNNjUuq6Cmzzww50TdP5Esb6e1y2sK2UAaZZuzfAzpoI2AkxoPQapZdlDuP6Vlsw==", + "license": "MIT" + }, + "node_modules/react-joyride/node_modules/react-floater/node_modules/tree-changes": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/tree-changes/-/tree-changes-0.9.3.tgz", + "integrity": "sha512-vvvS+O6kEeGRzMglTKbc19ltLWNtmNt1cpBoSYLj/iEcPVvpJasemKOlxBrmZaCtDJoF+4bwv3m01UKYi8mukQ==", + "license": "MIT", + "dependencies": { + "@gilbarbara/deep-equal": "^0.1.1", + "is-lite": "^0.8.2" + } + }, "node_modules/react-redux": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", @@ -4623,6 +4734,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/scroll": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scroll/-/scroll-3.0.1.tgz", + "integrity": "sha512-pz7y517OVls1maEzlirKO5nPYle9AXsFzTMNJrRGmT951mzpIBy7sNHOg5o/0MQd/NqliCiWnAi0kZneMPFLcg==", + "license": "MIT" + }, + "node_modules/scrollparent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/scrollparent/-/scrollparent-2.1.0.tgz", + "integrity": "sha512-bnnvJL28/Rtz/kz2+4wpBjHzWoEzXhVg/TE8BeVGJHUqE8THNIRnDxDWMktwM+qahvlRdvlLdsQfYe+cuqfZeA==", + "license": "ISC" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -4890,6 +5013,16 @@ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", "license": "MIT" }, + "node_modules/tree-changes": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/tree-changes/-/tree-changes-0.11.3.tgz", + "integrity": "sha512-r14mvDZ6tqz8PRQmlFKjhUVngu4VZ9d92ON3tp0EGpFBE6PAHOq8Bx8m8ahbNoGE3uI/npjYcJiqVydyOiYXag==", + "license": "MIT", + "dependencies": { + "@gilbarbara/deep-equal": "^0.3.1", + "is-lite": "^1.2.1" + } + }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -4934,6 +5067,18 @@ "node": ">= 0.8.0" } }, + "node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "5.7.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", diff --git a/package.json b/package.json index 5343a7b..020c2a9 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "react-draggable": "^4.4.6", "react-icons": "^5.5.0", "react-id-generator": "^3.0.2", + "react-joyride": "^2.9.3", "react-redux": "^9.2.0", "react-router-dom": "^7.2.0", "react-sortablejs": "^6.1.4", diff --git a/src/App.tsx b/src/App.tsx index 5270316..f0e6439 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import { BrowserRouter, Route, Routes } from "react-router-dom" +import { BrowserRouter, Route, Routes, useLocation } from "react-router-dom" import Dashboard from "./components/dashboard/Dashboard" import Home from "./components/home/Home" import Login from "./components/login/Login"; @@ -20,81 +20,90 @@ import Account from "./components/accounts/Account"; import TransactionView from "./components/transactions/TransactionView"; import Templates from "./components/templates/Templates"; import DocumentCompletionScreen from "./components/process/CompletionScreen/DocumentCompletionScreen"; +import JoyrideController from "./utlity/JoyRideTour"; const App = () => { + return ( - - {/* */} - + <> + - + {/* */} + - - - - }> - } /> - {/* } /> */} - {/* }> */} + + + + + + }> + } /> + {/* } /> */} + {/* }> */} } /> } /> } /> } /> {/* } /> */} } /> - {/* */} + {/* */} - } /> - + } /> + - - - - } /> + + + + } /> - - - - } /> + + + + } /> - - - - } /> + + + + } /> - - - - } /> + + + + } /> - - - - } /> + + + + } /> - - - - } /> + + + + } /> - {/* Links work wothout Login */} - } /> - } /> - } /> - } /> + {/* Links work wothout Login */} + } /> + } /> + } /> + } /> - {/* Links work wothout Login */} - + {/* Links work wothout Login */} + + + + + {/* */} + + + - {/* */} - ) } diff --git a/src/components/CommonNav.tsx b/src/components/CommonNav.tsx index f128de9..38732d7 100644 --- a/src/components/CommonNav.tsx +++ b/src/components/CommonNav.tsx @@ -152,7 +152,7 @@ const CommonNav: React.FC = () => { if (item) { const userData = { id: item?.id, - name : item?.firstName + " " + item?.lastName , + name: item?.firstName + " " + item?.lastName, email: item?.email, language: "", account: { @@ -162,15 +162,15 @@ const CommonNav: React.FC = () => { }, }; - console.log("userData",userData) + console.log("userData", userData) - setUser(userData); + setUser(userData); sessionStorage.setItem('userDetails', JSON.stringify(userData)); sessionStorage.setItem('activeAccountId', JSON.stringify(userData.account.id)); - + // Dispatch event for initial load dispatchSessionStorageChange('activeAccountId', userData.account.id); - + console.log("Data is saved in sessionStorage"); } @@ -295,6 +295,7 @@ const CommonNav: React.FC = () => {
diff --git a/src/components/process/processStepOne/RecipientAddCard.tsx b/src/components/process/processStepOne/RecipientAddCard.tsx index 8711c50..3157d3c 100644 --- a/src/components/process/processStepOne/RecipientAddCard.tsx +++ b/src/components/process/processStepOne/RecipientAddCard.tsx @@ -159,6 +159,7 @@ const RecipientAddCard = ({ transactionTemplateToggle, editRecipient, editCase ,
{transactionTemplateToggle === 'templates' && ( diff --git a/src/components/process/processStepOne/RecipientCards.tsx b/src/components/process/processStepOne/RecipientCards.tsx index 3492139..cecb18d 100644 --- a/src/components/process/processStepOne/RecipientCards.tsx +++ b/src/components/process/processStepOne/RecipientCards.tsx @@ -59,15 +59,15 @@ const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateTogg const handleRemoveRecipient = (recipient) => { if (!accountId || !transactionId) return; -<<<<<<< HEAD +// <<<<<<< HEAD // dispatch(removeSelectedRecipient(recipient)) - dispatch(removeRecipientAsync([{ - recipientId: recipient.id, - email: recipient.email, - accountId: accountId, - transactionId: transactionId, - }])) -======= + // dispatch(removeRecipientAsync([{ + // recipientId: recipient.id, + // email: recipient.email, + // accountId: accountId, + // transactionId: transactionId, + // }])) +// ======= if (recipient.uuid) { dispatch(removeSelectedRecipient(recipient)) } else { @@ -78,7 +78,7 @@ const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateTogg transactionId: transactionId, })) } ->>>>>>> origin/main +// >>>>>>> origin/main if (recipients.length === 2) { let leftRecipient = recipients.filter((obj) => { if ("id" in obj && "id" in recipient) { diff --git a/src/components/process/processStepOne/SelectedDocuments.tsx b/src/components/process/processStepOne/SelectedDocuments.tsx index fc92937..9aa6829 100644 --- a/src/components/process/processStepOne/SelectedDocuments.tsx +++ b/src/components/process/processStepOne/SelectedDocuments.tsx @@ -87,7 +87,9 @@ const SelectedDocuments = ({transactionTemplateToggle}) => { return ( <> {/* Upload Card First */} -
+
{/* Uploaded documents */} = ({ isSend }) => { // const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments) const selectedDocuments = useSelector((state: RootState) => state.documents.documents) - console.log("selectedDocuments",selectedDocuments) + console.log("selectedDocuments", selectedDocuments) const [droppedItems, setDroppedItems] = useState({}); console.log("droppedItems", droppedItems) @@ -190,7 +191,7 @@ const DocumentContainer: React.FC = ({ isSend }) => { useEffect(() => { if (isSend === null) return; - // dispatch(showLoader("Creating Transaction")) + dispatch(showLoader("Loading ...")) let updatedTags = { ...droppedItems } @@ -209,7 +210,6 @@ const DocumentContainer: React.FC = ({ isSend }) => { for (const dropTag of updatedTags[dropPageIds]) { let mask = null - // console.log(dropTag, "line 132") // if (dropTag.subType?.toLowerCase() === "password") { @@ -248,8 +248,8 @@ const DocumentContainer: React.FC = ({ isSend }) => { "color": "black", "textSize": 0 }, - // "required": (dropTag.type.toUpperCase() !== "SIGNATURE" && dropTag.type.toUpperCase() !== "INITIALS") ? dropTag.required : true, - "required": "required" in dropTag ? dropTag.required : true, + "required": (dropTag.type.toUpperCase() !== "SIGNATURE" && dropTag.type.toUpperCase() !== "INITIALS") ? dropTag.required : true, + // "required": "required" in dropTag ? dropTag.required : , "update": "update" in dropTag ? dropTag.update : false, "readOnly": false, } @@ -292,13 +292,17 @@ const DocumentContainer: React.FC = ({ isSend }) => { // for(const recipient of selectedRecipients) { // const recrecipient // } + + tagsData = groupByRecipientId(tagsData); + sendTagsToRecipients(tagsData, accountId, transactionId); (async () => { const res = await api.put(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`, { status: "SENT" }) // const res = await api.put(`/api/accounts/${accountId}/transactions/${transactionId}`, { status: "SENT" }) console.log(res, "Check123") + dispatch(hideLoader()) })() }, [isSend]) // Save Tags - END @@ -331,6 +335,19 @@ const DocumentContainer: React.FC = ({ isSend }) => { const key = `${docId}_${pageIndex}`; // const IconComponent = typeToIconMap[field.type] || ; + // Handling Initia Width and height of Some tags - START + if (dragElemData.label === TagsTypes.STAMP) { + dragElemData.width = 160 + dragElemData.height = 160 + } else if (dragElemData.label === TagsTypes.SIGNATURE) { + dragElemData.width = 200 + dragElemData.height = 75 + } else if (dragElemData.label === TagsTypes.INITIALS) { + dragElemData.width = 85 + dragElemData.height = 75 + } + // Handling Initia Width and height of Some tags - END + let prepData = { properties: data.properties, icon: typeToIconMap[field.label.toUpperCase()] || , @@ -355,6 +372,7 @@ const DocumentContainer: React.FC = ({ isSend }) => { pageIndex: pageIndex, recipientId: dragElemData.recipientId, recipientIndx: dragElemData.recipientIndx, + required: (dragElemData.label !== TagsTypes.SIGNATURE && dragElemData.label !== TagsTypes.INITIALS) ? false : true, update: true, isDeleted: false } @@ -726,104 +744,104 @@ const DocumentContainer: React.FC = ({ isSend }) => { }; // Enhanced handleGroupBorderPosition with better positioning logic -const handleGroupBorderPosition = (groupElements: NodeListOf, containerRect: DOMRect, offsetX: number, offsetY: number) => { - if (!groupElements || groupElements.length === 0) return; - - 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); + const handleGroupBorderPosition = (groupElements: NodeListOf, containerRect: DOMRect, offsetX: number, offsetY: number) => { + if (!groupElements || groupElements.length === 0) return; + + 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); } - - // 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; - } - }); -}; + + // 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); @@ -835,6 +853,12 @@ const handleGroupBorderPosition = (groupElements: NodeListOf, conta 'group' in existingItem && existingItem.group === groupId ) || []; + const existingGroupItem = droppedItems[key]?.filter(existingItem => + 'group' in existingItem && existingItem.group === groupId + ) || []; + + existingGroupItem[0].options + // Find the bottom-most item in the group let bottomMostItem = item; if (existingGroupItems.length > 0) { @@ -875,131 +899,27 @@ const handleGroupBorderPosition = (groupElements: NodeListOf, conta 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 + // 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) => { - // // const dataToSet: DroppedItemsObj = { - // // ...droppedItems, - // // [key]: [...(droppedItems[key] || []), - // // { - // // ...prepData, - // // radioGroups: dragElemData.label === "radio" ? [{ ...prepData }] : [] - // // }], - // // } - - // // const lastRadioElemRect = e.currentTarget?.parentElement.previousSibling.getBoundingClientRect(); - // // console.log(lastRadioElemRect, "lastRadioElemRect") - - // 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]) - // } - - // setDroppedItems(setNewData); - // }; - - - - // const handleRadioTagMouseDown = (event: React.MouseEvent, key: string, index: number, radioIndex: number) => { - - // event.preventDefault(); - - // let targetContainer = event?.currentTarget?.parentElement; - // let targetElement = event?.currentTarget; - - // if (!targetContainer || !targetElement) return; - - // 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; - - // 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; - - // 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; - - // 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; - // } - // } - - // 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; - // } - - // setDroppedItems({ ...newData }); - // }; - - // const handleMouseUp = () => { - // document.removeEventListener("pointermove", handleMouseMove); - // document.removeEventListener("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; @@ -1043,38 +963,38 @@ const handleGroupBorderPosition = (groupElements: NodeListOf, conta }; // Add this new handler function to your parent component -const handleDirectPositionChange = (newLeft: number, newTop: number) => { - console.log("handleDirectPositionChange",newLeft,newTop) - if (!selectedTag) return; + const handleDirectPositionChange = (newLeft: number, newTop: number) => { + console.log("handleDirectPositionChange", newLeft, newTop) + 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; - // Ensure values are not negative - const clampedLeft = Math.max(0, newLeft); - const clampedTop = Math.max(0, newTop); + // Ensure values are not negative + const clampedLeft = Math.max(0, newLeft); + const clampedTop = Math.max(0, newTop); - 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 - ) - : [], - }); -}; + 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 ( <> @@ -1128,7 +1048,7 @@ const handleDirectPositionChange = (newLeft: number, newTop: number) => { {/* If Selected Tag Recipient Info- START */} {selectedTag?.key && selectedTag.key === key && selectedTag.index === index && -
+

{ {/* 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'>
} @@ -1178,8 +1098,6 @@ const handleDirectPositionChange = (newLeft: number, newTop: number) => { { "group" in item && item.group && "isGroupExist" in item && !item.isGroupExist && <> - -
@@ -1208,11 +1126,11 @@ const handleDirectPositionChange = (newLeft: number, newTop: number) => { - {/* Side details of documents Pages and document Name - START */} -

- page {indx + 1} of {doc.pages && doc.pages.length} -

- {/*

+ {/* Side details of documents Pages and document Name - START */} +

+ page {indx + 1} of {doc.pages && doc.pages.length} +

+ {/*

Document {indxDoc + 1} {doc.name}

*/} {/* Side details of documents Pages and document Name - END */} diff --git a/src/components/process/processStepTwo/LeftSideBar.tsx b/src/components/process/processStepTwo/LeftSideBar.tsx index a687121..bcd5417 100644 --- a/src/components/process/processStepTwo/LeftSideBar.tsx +++ b/src/components/process/processStepTwo/LeftSideBar.tsx @@ -65,7 +65,7 @@ const LeftSideBar: React.FC = ({ isFields, selectedRecipientIn <> {/* Left Side Bar - START */} { - selectedRecipients.length &&
+ selectedRecipients.length > 0 &&
{isFields && <> {/* Fields List and Recipeint - Start */} {/* Side Bar showing Recipients */} @@ -74,6 +74,7 @@ const LeftSideBar: React.FC = ({ isFields, selectedRecipientIn onBlur={() => setDropDownToggle(false)}> {/* Selected Recipient */}
setDropDownToggle(!dropDownToggle)} className='flex items-center justify-between gap-2 w-full p-2 text-xs rounded-sm border-1 border-slate-200 cursor-pointer'>
@@ -110,7 +111,9 @@ const LeftSideBar: React.FC = ({ isFields, selectedRecipientIn {/* Side Bar showing Recipients - ENDS*/} {/* Drag Drop Tags Start */} -
+
diff --git a/src/components/process/processStepTwo/NavTwo.tsx b/src/components/process/processStepTwo/NavTwo.tsx index 533d067..1602604 100644 --- a/src/components/process/processStepTwo/NavTwo.tsx +++ b/src/components/process/processStepTwo/NavTwo.tsx @@ -262,6 +262,7 @@ const NavTwo: React.FC = ({ isFields, setIsFields, isSend, setIsSen {/* Send */}
handleSend()} className='flex items-center gap-2 cursor-pointer text-xs px-4 py-2 ml-3 rounded-sm bg-[var(--primary)]'>

Send

diff --git a/src/components/process/processStepTwo/rightSideBar/DirectionalControls.tsx b/src/components/process/processStepTwo/rightSideBar/DirectionalControls.tsx index 493e4b8..fe79bb8 100644 --- a/src/components/process/processStepTwo/rightSideBar/DirectionalControls.tsx +++ b/src/components/process/processStepTwo/rightSideBar/DirectionalControls.tsx @@ -44,11 +44,8 @@ const DirectionalControls: React.FC = ({ }; const handlePositionInputChange = (type: 'left' | 'top', value: string) => { - if (type === 'left') { - setLeftValue(value); - } else { - setTopValue(value); - } + if (type === 'left') setLeftValue(value); + else setTopValue(value); }; const handlePositionInputBlur = (type: 'left' | 'top') => { @@ -57,11 +54,8 @@ const DirectionalControls: React.FC = ({ 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()); - } + setLeftValue(Math.round(left).toString()); + setTopValue(Math.round(top).toString()); return; } @@ -73,9 +67,7 @@ const DirectionalControls: React.FC = ({ }; const handleKeyPress = (e: React.KeyboardEvent, type: 'left' | 'top') => { - if (e.key === 'Enter') { - handlePositionInputBlur(type); - } + if (e.key === 'Enter') handlePositionInputBlur(type); }; useEffect(() => { @@ -84,20 +76,11 @@ const DirectionalControls: React.FC = ({ switch (event.key) { case 'ArrowUp': - event.preventDefault(); - handleMove('up'); - break; case 'ArrowDown': - event.preventDefault(); - handleMove('down'); - break; case 'ArrowLeft': - event.preventDefault(); - handleMove('left'); - break; case 'ArrowRight': event.preventDefault(); - handleMove('right'); + handleMove(event.key.replace('Arrow', '').toLowerCase() as any); break; } }; @@ -107,115 +90,67 @@ const DirectionalControls: React.FC = ({ }, [disabled, stepSize]); 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 `; - - const inputClass = ` - w-12 h-6 text-[10px] text-center border rounded px-1 bg-white + w-8 h-8 flex items-center justify-center rounded-full border shadow-sm text-[12px] ${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'} + ? 'bg-gray-100 text-gray-400 cursor-not-allowed' + : 'bg-white text-gray-700 hover:bg-blue-100 active:bg-blue-200 cursor-pointer'} `; - const { top = 0, left = 0, width = 0, height = 0 } = selectedType || {}; + const inputClass = ` + w-14 text-center text-[12px] rounded border px-1 py-0.5 bg-white + ${disabled + ? 'bg-gray-100 text-gray-400 cursor-not-allowed' + : 'border-gray-300 text-gray-700 focus:outline-none focus:ring focus:border-blue-400'} + `; return ( -
- {/* Top Button */} -
-
- + + {/* Middle: Left / Inputs / Right */} +
+ + + {/* Input fields */} +
+ handlePositionInputChange('left', e.target.value)} + onBlur={() => handlePositionInputBlur('left')} + onKeyPress={(e) => handleKeyPress(e, 'left')} disabled={disabled} - className={buttonClass} - title="Move up" - type="button" - > - - - Top + className={inputClass} + placeholder="Left" + /> + handlePositionInputChange('top', e.target.value)} + onBlur={() => handlePositionInputBlur('top')} + onKeyPress={(e) => handleKeyPress(e, 'top')} + disabled={disabled} + className={inputClass} + placeholder="Top" + />
+ +
- {/* Middle Row: Left - Center (Inputs) - Right */} -
- {/* Left Button */} -
- - Left -
- - {/* 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 Button */} -
-
- - Bottom -
-
+ {/* Bottom */} +
); - }; -export default DirectionalControls; \ No newline at end of file +export default DirectionalControls; diff --git a/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx b/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx index ec08e9c..227accc 100644 --- a/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx +++ b/src/components/process/processStepTwo/rightSideBar/RightSideBar.tsx @@ -122,28 +122,26 @@ const RightSideBar: React.FC = ({ selectedTag, setDroppedItems 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) => { + // 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 + // ) + // : [], // Fallback in case it's undefined or not an array + // }; + // }); - 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) => { - 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 - ) - : [], // Fallback in case it's undefined or not an array - }; - }); - - } else if (changeTo === "subType" && typeof changeWith === "string" && changeWith.toLowerCase() === "password") { + // } else + + if (changeTo === "subType" && typeof changeWith === "string" && changeWith.toLowerCase() === "password") { console.log("Second check") console.log("Line 161") setDroppedItems((prev) => ( @@ -174,13 +172,26 @@ const RightSideBar: React.FC = ({ selectedTag, setDroppedItems }// Provide a fallback in case it's undefined or not an array )); - } else if (changeTo === "format" && selectedTag.subType === TEMPORAL.DATE_TIME) { + } + + + + else if (changeTo === "format" && selectedTag.subType === TEMPORAL.DATE_TIME) { console.log("Fourth Check") let val = timeFormats[0].format; - if (!is24Hrs) { + console.log(is24Hrs, "is24Hrs Line 176") + if (is24Hrs === null) { + val = timeFormats[0].format + } else if(!is24Hrs) { val = timeFormats[1].format + } else { + val = timeFormats[0].format } - console.log("val", val) + // console.log("val", val, is24Hrs) + + // if(is24Hrs === null) { + // changeWith = changeWith + " " + val; + // } setDroppedItems((prev) => { const updatedArray = Array.isArray(prev[selTagKey]) @@ -199,9 +210,9 @@ const RightSideBar: React.FC = ({ selectedTag, setDroppedItems [selTagKey]: updatedArray, }; }); - - - } else { + } + + else { setDroppedItems((prev) => { const updatedItems = Array.isArray(prev[selTagKey]) @@ -284,6 +295,7 @@ const RightSideBar: React.FC = ({ selectedTag, setDroppedItems const tagHeight = selectedTag?.dimensions?.height - 18; if ( + selectedTag.type === TagsTypes.TEXT && selectedTag.subType !== TEXT.PASSWORD && selectedTag.subType !== TEXT.PARAGRAPH && tagHeight > fontSize * 2 diff --git a/src/components/process/processStepTwo/rightSideBar/SelectTagAttr.tsx b/src/components/process/processStepTwo/rightSideBar/SelectTagAttr.tsx index 0ec0d4b..721dd3e 100644 --- a/src/components/process/processStepTwo/rightSideBar/SelectTagAttr.tsx +++ b/src/components/process/processStepTwo/rightSideBar/SelectTagAttr.tsx @@ -15,31 +15,31 @@ const SelectTagAttr: React.FC = ({ options, selTagKey, selTagI const [selectedOption, setSelectedOption] = useState() const handleAddSelectOption = () => { - if (selectedOption && selectedOption.length) { - setDroppedItems((prev) => { - console.log("Previous droppedItems:", prev); + if (selectedOption && selectedOption.length) { + setDroppedItems((prev) => { + console.log("Previous droppedItems:", prev); - const newState = { - ...prev, - [selTagKey]: Array.isArray(prev[selTagKey]) - ? prev[selTagKey].map((item, i) => { - if (i === selTagIndx) { - return { - ...item, - options: item.options ? [...item.options, selectedOption] : [selectedOption], - update: true, - }; - } - return item; - }) - : [], - }; + const newState = { + ...prev, + [selTagKey]: Array.isArray(prev[selTagKey]) + ? prev[selTagKey].map((item, i) => { + if (i === selTagIndx) { + return { + ...item, + options: item.options ? [...item.options, selectedOption] : [selectedOption], + update: true, + }; + } + return item; + }) + : [], + }; - console.log("New droppedItems state:", newState); - return newState; - }); - } -}; + console.log("New droppedItems state:", newState); + return newState; + }); + } + }; const handleSelectOptionDel = (indx: number) => { @@ -65,14 +65,11 @@ const SelectTagAttr: React.FC = ({ options, selTagKey, selTagI setSelectedOption(e.target.value)} - value={selectedOption} + // value={selectedOption} onKeyUp={(e) => { if (e.code === "Enter") { - // if (selectedOption) { - // setSelectedOptions((prev) => [...prev, selectedOption]); - // setSelectedOption(""); - // } - handleAddSelectOption() + e.currentTarget.value = ""; + handleAddSelectOption(); } }} className="bg-slate-100 w-full outline-none p-2 rounded" /> diff --git a/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx b/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx index 0d07995..f8977df 100644 --- a/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx +++ b/src/components/process/processStepTwo/rightSideBar/TemporalDateAttr.tsx @@ -23,10 +23,11 @@ interface TemporalDateAttrInt { const TemporalDateAttr: React.FC = ({ subType, format, dropDownToggle, setDropDownToggle, handlePropertyChange }) => { - + const [is24Hrs, setIs24Hrs] = useState(true); const handleIs24HrsClick = (checked: boolean) => { + console.log(is24Hrs, checked, "line 30") if (subType === TEMPORAL.TIME) { if (!checked) { handlePropertyChange("format", timeFormats[1].format, is24Hrs) @@ -34,6 +35,9 @@ const TemporalDateAttr: React.FC = ({ subType, format, drop handlePropertyChange("format", timeFormats[0].format, is24Hrs) } } + else if (subType === TEMPORAL.DATE_TIME) { + handlePropertyChange("format", (format.split(" ").slice(0, -1).join(" ")), !is24Hrs) + } setIs24Hrs(checked) } @@ -86,11 +90,11 @@ const TemporalDateAttr: React.FC = ({ subType, format, drop val = val + " " + timeFormats[1].format; } } - console.log('line 89' , val ) + console.log('line 89', val) return (
handlePropertyChange("format", valObj["format"])} + onClick={() => handlePropertyChange("format", valObj["format"], is24Hrs)} className="px-2 py-1 hover:bg-slate-200 cursor-pointer" > {val} diff --git a/src/utlity/JoyRideTour.tsx b/src/utlity/JoyRideTour.tsx new file mode 100644 index 0000000..b582928 --- /dev/null +++ b/src/utlity/JoyRideTour.tsx @@ -0,0 +1,244 @@ +import { useLocation } from "react-router-dom"; +import { useEffect, useState } from "react"; +import Joyride, { CallBackProps, STATUS, Step } from "react-joyride"; + +const JoyrideController = () => { + const location = useLocation(); + const [runTour, setRunTour] = useState(false); + const [steps, setSteps] = useState([]); + const [stepIndex, setStepIndex] = useState(0); + + useEffect(() => { + let timeout: NodeJS.Timeout; + + const tryStartTour = () => { + let currentSteps: Step[] = []; + + if (location.pathname === "/") { + currentSteps = [ + { + target: "body", // This makes the welcome step show in center of screen + content: "👋 Welcome to the SME! Let's take a quick tour.", + placement: "center", + disableBeacon: true, + }, + { + target: "#user-details-avatar", + content: "User Details", + placement: "left", + disableBeacon: true, + + }, + { + target: "#send-for-sign-self-sign-btn", + content: "Send document for signature, or for Self Sign", + placement: "left", + disableBeacon: true, + + }, + { + target: "#nav-link-dash", + content: ( +
+

Easy Navigation to see transaction and templates.

+

+ Templates: you can save all recipient documents and tags and + use them multiple times on one click. +

+
+ ), + placement: "left", + disableBeacon: true, + + }, + { + target: "#start-now-upload-con", + content: ( +
+

Let's Start Some Action

+

+ Click On Start Now To upload your first document for signature +

+
+ ), + placement: "top", + disableBeacon: true, + + }, + ]; + } else if (location.pathname.includes("/process-step-one")) { + currentSteps = [ + { + target: "body", // This makes the welcome step show in center of screen + content: ( +
+

👋 Welcome To process step one

+

+ Here we have to add core two ingredients Document, Recipient to start cooking +

+
+ ), + placement: "center", + disableBeacon: true, + }, + { + target: "#upload-doc-step-one", + content: "Add Documents", + placement: "right", + disableBeacon: true, + + }, + { + target: "#add-recipient-step-one", + content: "Add recipient for sign", + placement: "right", + disableBeacon: true, + + }, + { + target: "#add-tags-btn-step-one", + content: "Click On Add Tags", + placement: "right", + disableBeacon: true, + + }, + ]; + } else if (location.pathname.includes("/process-step-two")) { + currentSteps = [ + { + target: "body", // This makes the welcome step show in center of screen + content: ( +
+

👋 This is Final Step

+
+

Here we can add tags in documents and assign them to recipients

+
+ ), + placement: "center", + disableBeacon: true, + }, + { + target: "#switch-recipients-left", + content: "Switch Recipients", + placement: "right", + disableBeacon: true, + }, + { + target: "#tags-con-dash-left", + content: "All Tags, Drag and drop on the document", + placement: "right", + disableBeacon: true, + }, + { + target: "#send-sign-dash-btn", + content:
+

When setisfied with all the change, Click on Send

+
, + placement: "right", + disableBeacon: true, + }, + ]; + } else if (location.pathname.includes("/sign/")) { + currentSteps = [ + { + target: "body", // This makes the welcome step show in center of screen + content: ( +
+

👋 Welcome to SME, Let's Start the tour

+
+ ), + placement: "center", + disableBeacon: true, + }, + { + target: "#tags-list-client-side", + content:
+

Drag and drop tags onto the document to fill or sign.

+
, + placement: "right", + disableBeacon: true, + }, + { + target: "#sign-client-side-btn", + content:
+

Check your document carefully When you're satisfied Click on Sign button

+
, + placement: "right", + disableBeacon: true, + }, + ]; + } + + const allTargetsExist = currentSteps.every((step) => + step.target === "body" ? true : document.querySelector(step.target) + ); + + if (allTargetsExist) { + setSteps(currentSteps); + setRunTour(true); + setStepIndex(0); + } else { + // Try again after slight delay (in case DOM not ready yet) + timeout = setTimeout(tryStartTour, 300); + } + }; + + setRunTour(false); + setSteps([]); + setStepIndex(0); + timeout = setTimeout(tryStartTour, 300); + + return () => clearTimeout(timeout); + }, [location]); + + // Optional: handle callback (e.g. restart, stop, next) + const handleJoyrideCallback = (data: CallBackProps) => { + const { status, type } = data; + const finished = [STATUS.FINISHED, STATUS.SKIPPED].includes(status); + if (finished) { + setRunTour(false); + } + }; + + return ( + + + ); +}; + +export default JoyrideController;