Merge pull request 'jai' (#13) from jai into main
Reviewed-on: http://git.hicglobalsolutions.in/BhawanSingh/SME-Web/pulls/13
This commit is contained in:
commit
78efdc0829
|
|
@ -26,6 +26,7 @@
|
||||||
"react-draggable": "^4.4.6",
|
"react-draggable": "^4.4.6",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-id-generator": "^3.0.2",
|
"react-id-generator": "^3.0.2",
|
||||||
|
"react-joyride": "^2.9.3",
|
||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0",
|
||||||
"react-router-dom": "^7.2.0",
|
"react-router-dom": "^7.2.0",
|
||||||
"react-sortablejs": "^6.1.4",
|
"react-sortablejs": "^6.1.4",
|
||||||
|
|
@ -921,6 +922,12 @@
|
||||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
"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": {
|
"node_modules/@humanfs/core": {
|
||||||
"version": "0.19.1",
|
"version": "0.19.1",
|
||||||
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
|
"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": {
|
"node_modules/deep-is": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
|
||||||
|
|
@ -2665,6 +2678,15 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/delayed-stream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
|
@ -3438,6 +3460,12 @@
|
||||||
"node": ">=0.10.0"
|
"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": {
|
"node_modules/is-number": {
|
||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
|
||||||
|
|
@ -4163,6 +4191,17 @@
|
||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"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": {
|
"node_modules/postcss": {
|
||||||
"version": "8.5.6",
|
"version": "8.5.6",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
|
||||||
|
|
@ -4323,12 +4362,84 @@
|
||||||
"react": ">= 16.8.0"
|
"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": {
|
"node_modules/react-is": {
|
||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/react-redux": {
|
||||||
"version": "9.2.0",
|
"version": "9.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz",
|
||||||
|
|
@ -4623,6 +4734,18 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"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": {
|
"node_modules/semver": {
|
||||||
"version": "6.3.1",
|
"version": "6.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||||
|
|
@ -4890,6 +5013,16 @@
|
||||||
"integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==",
|
"integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==",
|
||||||
"license": "MIT"
|
"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": {
|
"node_modules/ts-api-utils": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
|
||||||
|
|
@ -4934,6 +5067,18 @@
|
||||||
"node": ">= 0.8.0"
|
"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": {
|
"node_modules/typescript": {
|
||||||
"version": "5.7.3",
|
"version": "5.7.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz",
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@
|
||||||
"react-draggable": "^4.4.6",
|
"react-draggable": "^4.4.6",
|
||||||
"react-icons": "^5.5.0",
|
"react-icons": "^5.5.0",
|
||||||
"react-id-generator": "^3.0.2",
|
"react-id-generator": "^3.0.2",
|
||||||
|
"react-joyride": "^2.9.3",
|
||||||
"react-redux": "^9.2.0",
|
"react-redux": "^9.2.0",
|
||||||
"react-router-dom": "^7.2.0",
|
"react-router-dom": "^7.2.0",
|
||||||
"react-sortablejs": "^6.1.4",
|
"react-sortablejs": "^6.1.4",
|
||||||
|
|
|
||||||
14
src/App.tsx
14
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 Dashboard from "./components/dashboard/Dashboard"
|
||||||
import Home from "./components/home/Home"
|
import Home from "./components/home/Home"
|
||||||
import Login from "./components/login/Login";
|
import Login from "./components/login/Login";
|
||||||
|
|
@ -20,11 +20,15 @@ import Account from "./components/accounts/Account";
|
||||||
import TransactionView from "./components/transactions/TransactionView";
|
import TransactionView from "./components/transactions/TransactionView";
|
||||||
import Templates from "./components/templates/Templates";
|
import Templates from "./components/templates/Templates";
|
||||||
import DocumentCompletionScreen from "./components/process/CompletionScreen/DocumentCompletionScreen";
|
import DocumentCompletionScreen from "./components/process/CompletionScreen/DocumentCompletionScreen";
|
||||||
|
import JoyrideController from "./utlity/JoyRideTour";
|
||||||
import Contacts from "./components/contacts/Contacts";
|
import Contacts from "./components/contacts/Contacts";
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
|
|
||||||
{/* <HashRouter> */}
|
{/* <HashRouter> */}
|
||||||
<ToastContainer />
|
<ToastContainer />
|
||||||
|
|
||||||
|
|
@ -44,9 +48,10 @@ const App = () => {
|
||||||
<Route path="/accounts/:accountId/transactions/:transactionId" element={<TransactionView />} />
|
<Route path="/accounts/:accountId/transactions/:transactionId" element={<TransactionView />} />
|
||||||
{/* <Route path="/transactions/:filterParam" element={<Transactions />} /> */}
|
{/* <Route path="/transactions/:filterParam" element={<Transactions />} /> */}
|
||||||
<Route path="/templates" element={<Templates />} />
|
<Route path="/templates" element={<Templates />} />
|
||||||
<Route path="/contacts" element={<Contacts />} />
|
|
||||||
{/* </Route> */}
|
{/* </Route> */}
|
||||||
|
|
||||||
|
<Route path="/contacts" element={<Contacts />} />
|
||||||
|
|
||||||
<Route path="/s/:page1" element={<Setting />} />
|
<Route path="/s/:page1" element={<Setting />} />
|
||||||
</Route>
|
</Route>
|
||||||
|
|
||||||
|
|
@ -95,8 +100,13 @@ const App = () => {
|
||||||
{/* Links work wothout Login */}
|
{/* Links work wothout Login */}
|
||||||
</Routes>
|
</Routes>
|
||||||
|
|
||||||
|
<JoyrideController />
|
||||||
|
|
||||||
{/* </HashRouter> */}
|
{/* </HashRouter> */}
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
|
|
||||||
|
</>
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ const CommonNav: React.FC<AccountNavProps> = () => {
|
||||||
if (item) {
|
if (item) {
|
||||||
const userData = {
|
const userData = {
|
||||||
id: item?.id,
|
id: item?.id,
|
||||||
name : item?.firstName + " " + item?.lastName ,
|
name: item?.firstName + " " + item?.lastName,
|
||||||
email: item?.email,
|
email: item?.email,
|
||||||
language: "",
|
language: "",
|
||||||
account: {
|
account: {
|
||||||
|
|
@ -162,7 +162,7 @@ const CommonNav: React.FC<AccountNavProps> = () => {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
console.log("userData",userData)
|
console.log("userData", userData)
|
||||||
|
|
||||||
setUser(userData);
|
setUser(userData);
|
||||||
sessionStorage.setItem('userDetails', JSON.stringify(userData));
|
sessionStorage.setItem('userDetails', JSON.stringify(userData));
|
||||||
|
|
@ -295,6 +295,7 @@ const CommonNav: React.FC<AccountNavProps> = () => {
|
||||||
<div className="flex items-center space-x-2">
|
<div className="flex items-center space-x-2">
|
||||||
<div className="relative" ref={dropdownRef}>
|
<div className="relative" ref={dropdownRef}>
|
||||||
<button
|
<button
|
||||||
|
id='user-details-avatar'
|
||||||
className="flex items-center space-x-2 p-1 cursor-pointer rounded-lg transition-colors"
|
className="flex items-center space-x-2 p-1 cursor-pointer rounded-lg transition-colors"
|
||||||
onClick={handleMainDropdownToggle}
|
onClick={handleMainDropdownToggle}
|
||||||
aria-expanded={open}
|
aria-expanded={open}
|
||||||
|
|
|
||||||
|
|
@ -213,10 +213,6 @@ const Account = () => {
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const handleTransactionClick = (id: number) => {
|
|
||||||
navigate(`/accounts/${activeAccountId}/transactions/${id}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleInvite = async (data: { i_accountName: number; email: string; role: string }) => {
|
const handleInvite = async (data: { i_accountName: number; email: string; role: string }) => {
|
||||||
setInviteLoading(true);
|
setInviteLoading(true);
|
||||||
try {
|
try {
|
||||||
|
|
@ -249,6 +245,7 @@ const Account = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
||||||
<Cards type="transactions" onOpenModal={handleOpenModal} cards={cards}
|
<Cards type="transactions" onOpenModal={handleOpenModal} cards={cards}
|
||||||
isLoading={isLoading} />
|
isLoading={isLoading} />
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,9 @@ import api from '../../config/api';
|
||||||
import { Transaction } from '../transactions/Transactions';
|
import { Transaction } from '../transactions/Transactions';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { FaCheck } from 'react-icons/fa';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const formatDate = (timestamp: number) => {
|
const formatDate = (timestamp: number) => {
|
||||||
|
|
@ -21,7 +24,7 @@ const TransactionDataTable = () => {
|
||||||
const fetchTransactions = async () => {
|
const fetchTransactions = async () => {
|
||||||
console.log("fetchTransactions")
|
console.log("fetchTransactions")
|
||||||
try {
|
try {
|
||||||
const response = await api(`/api/accounts/${activeAccountId}/transactions`);
|
const response = await api.get(`/api/accounts/${activeAccountId}/transactions?sortBy=lastModifiedAt desc`);
|
||||||
setTransactions(response.data || []);
|
setTransactions(response.data || []);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching transactions:", error);
|
console.error("Error fetching transactions:", error);
|
||||||
|
|
@ -30,6 +33,10 @@ const TransactionDataTable = () => {
|
||||||
|
|
||||||
const [transactions, setTransactions] = useState<Transaction[]>([]);
|
const [transactions, setTransactions] = useState<Transaction[]>([]);
|
||||||
|
|
||||||
|
const handleTransactionClick = (id: number) => {
|
||||||
|
navigate(`/accounts/${activeAccountId}/transactions/${id}`);
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (activeAccountId) {
|
if (activeAccountId) {
|
||||||
fetchTransactions();
|
fetchTransactions();
|
||||||
|
|
@ -42,9 +49,7 @@ const TransactionDataTable = () => {
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
const handleTransactionClick = (transactionId) => {
|
|
||||||
navigate(`/accounts/${activeAccountId}/transactions/${transactionId}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ interface DocumentPagesInterface {
|
||||||
|
|
||||||
const DocumentPages = ({ selectedDocuments, setDropDownTogglePage, dropDownTogglePage }: DocumentPagesInterface) => {
|
const DocumentPages = ({ selectedDocuments, setDropDownTogglePage, dropDownTogglePage }: DocumentPagesInterface) => {
|
||||||
return (
|
return (
|
||||||
<div className='col-span-2 bg-white h-full p-4 overflow-y-auto'>
|
<div className='bg-white h-full p-4 overflow-y-auto'>
|
||||||
|
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
{selectedDocuments && selectedDocuments.length && selectedDocuments.map((document, indx) => {
|
{selectedDocuments && selectedDocuments.length && selectedDocuments.map((document, indx) => {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { useEffect, useState } from "react";
|
||||||
import axios from "axios"
|
import axios from "axios"
|
||||||
import { RootState } from "../../store/store";
|
import { RootState } from "../../store/store";
|
||||||
import { useParams } from "react-router-dom"
|
import { useParams } from "react-router-dom"
|
||||||
import { DroppedItem, DroppedItemsObj } from "../../utlity/types";
|
import { DroppedItem, DroppedItemsObj, TagsTypes } from "../../utlity/types";
|
||||||
|
|
||||||
import Loader from "../dashboard/Loader";
|
import Loader from "../dashboard/Loader";
|
||||||
import SignCon from "../signature/SignCon";
|
import SignCon from "../signature/SignCon";
|
||||||
|
|
@ -172,6 +172,8 @@ const SignDocument = () => {
|
||||||
const [hideTags, setHideTags] = useState<boolean>(false);
|
const [hideTags, setHideTags] = useState<boolean>(false);
|
||||||
const [transparentTags, setTransparentTags] = useState<boolean>(false);
|
const [transparentTags, setTransparentTags] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const [provideTags, setProvideTags] = useState(false)
|
||||||
|
|
||||||
const [saved, setSaved] = useState<SaveType>({
|
const [saved, setSaved] = useState<SaveType>({
|
||||||
saveType: null,
|
saveType: null,
|
||||||
save: false,
|
save: false,
|
||||||
|
|
@ -308,6 +310,10 @@ const SignDocument = () => {
|
||||||
setTransaction(res.data.transaction)
|
setTransaction(res.data.transaction)
|
||||||
setRecSignStatus(res.data.status)
|
setRecSignStatus(res.data.status)
|
||||||
|
|
||||||
|
if ("provideOwnTags" in res.data.details && res.data.details.provideOwnTags) {
|
||||||
|
setProvideTags(true)
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
dispatch(hideLoader());
|
dispatch(hideLoader());
|
||||||
}, 600);
|
}, 600);
|
||||||
|
|
@ -850,7 +856,9 @@ const SignDocument = () => {
|
||||||
{(!transparentTags && !hideTags) ? <button
|
{(!transparentTags && !hideTags) ? <button
|
||||||
// onClick={() => handleFormSubmitBtnClick()}
|
// onClick={() => handleFormSubmitBtnClick()}
|
||||||
className='flex items-center gap-2 cursor-pointer text-xs px-4 py-2 ml-3 rounded-sm bg-[var(--primary)] outline-none'>
|
className='flex items-center gap-2 cursor-pointer text-xs px-4 py-2 ml-3 rounded-sm bg-[var(--primary)] outline-none'>
|
||||||
<p className='tracking-wide text-white'>
|
<p
|
||||||
|
id="sign-client-side-btn"
|
||||||
|
className='tracking-wide text-white'>
|
||||||
Sign
|
Sign
|
||||||
</p>
|
</p>
|
||||||
<FaSignature className='text-white text-md' />
|
<FaSignature className='text-white text-md' />
|
||||||
|
|
@ -870,9 +878,10 @@ const SignDocument = () => {
|
||||||
|
|
||||||
{/* Left Side pages start */}
|
{/* Left Side pages start */}
|
||||||
{/* <div className="lg:col-span-2 bg-slate-100 h-full p-4 overflow-y-auto"></div> */}
|
{/* <div className="lg:col-span-2 bg-slate-100 h-full p-4 overflow-y-auto"></div> */}
|
||||||
|
<div
|
||||||
<div className='col-span-2 bg-white h-full p-4 overflow-y-auto'>
|
id="tags-list-client-side"
|
||||||
{recipientId && <FieldList color={"#8f87f1"} recipientId={Number(recipientId)} recipientIndx={0} acntId={"1"} />}
|
className={`col-span-2 h-full p-4 overflow-y-auto ${provideTags ? "bg-white" : "order-last"}`}>
|
||||||
|
{recipientId && provideTags && <FieldList color={"#8f87f1"} recipientId={Number(recipientId)} recipientIndx={0} acntId={"1"} />}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1188,6 +1197,31 @@ const SignDocument = () => {
|
||||||
{/* TEMPORAL FIELD - END */}
|
{/* TEMPORAL FIELD - END */}
|
||||||
|
|
||||||
|
|
||||||
|
{/* Attachment Field - START */}
|
||||||
|
{item.type.toLowerCase() === TagsTypes.ATTACHMENT &&
|
||||||
|
<div
|
||||||
|
tabIndex={1}
|
||||||
|
id={item.id}
|
||||||
|
// onClick={() => handleStampClick(index)}
|
||||||
|
className={`flex justify-center items-center h-full w-full rounded cursor-pointer ${transparentTags || hideTags ? "pointer-events-none" : "bg-slate-200 shadow-sm border-slate-100 opacity-80"}`}
|
||||||
|
// style={{ height: item.dimensions.height + "px" }}
|
||||||
|
>
|
||||||
|
{!transparentTags && !hideTags ?
|
||||||
|
(
|
||||||
|
<p className="text-lg text-slate-600">
|
||||||
|
{typeToIconMap.ATTACHMENT}
|
||||||
|
</p>
|
||||||
|
)
|
||||||
|
:
|
||||||
|
(
|
||||||
|
<p className="text-lg text-slate-600">
|
||||||
|
{typeToIconMap.ATTACHMENT}
|
||||||
|
</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</div>}
|
||||||
|
{/* Attachment Field - END */}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{/* Focus Show Element */}
|
{/* Focus Show Element */}
|
||||||
|
|
@ -1257,9 +1291,12 @@ const SignDocument = () => {
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div className={`col-span-2 ${provideTags ? "" : "order-first"}`}>
|
||||||
<DocumentPages selectedDocuments={selectedDocuments} setDropDownTogglePage={setDropDownTogglePage} dropDownTogglePage={dropDownTogglePage} />
|
<DocumentPages
|
||||||
|
selectedDocuments={selectedDocuments}
|
||||||
|
setDropDownTogglePage={setDropDownTogglePage}
|
||||||
|
dropDownTogglePage={dropDownTogglePage} />
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Right Side - START */}
|
{/* Right Side - START */}
|
||||||
{/* <div className="col-span-2 bg-slate-100 h-full p-4 overflow-y-auto">
|
{/* <div className="col-span-2 bg-slate-100 h-full p-4 overflow-y-auto">
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import api from '../../config/api';
|
||||||
import ContactFormModal, { ContactData } from './ContactsFormModal';
|
import ContactFormModal, { ContactData } from './ContactsFormModal';
|
||||||
import { Bounce, toast } from 'react-toastify';
|
import { Bounce, toast } from 'react-toastify';
|
||||||
import { IoMdAdd } from 'react-icons/io';
|
import { IoMdAdd } from 'react-icons/io';
|
||||||
|
import LoaderUi from '../../helper/LoaderUi';
|
||||||
|
|
||||||
type ContactSchema = [{
|
type ContactSchema = [{
|
||||||
id: number,
|
id: number,
|
||||||
|
|
@ -25,6 +26,7 @@ const Contacts = () => {
|
||||||
console.log("editJsonData", editJsonData)
|
console.log("editJsonData", editJsonData)
|
||||||
|
|
||||||
const fetchContacts = async () => {
|
const fetchContacts = async () => {
|
||||||
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
const res = await api.get(`/api/accounts/${activeAccountId}/contacts`);
|
const res = await api.get(`/api/accounts/${activeAccountId}/contacts`);
|
||||||
setContacts(res.data.content || []);
|
setContacts(res.data.content || []);
|
||||||
|
|
@ -83,11 +85,11 @@ const Contacts = () => {
|
||||||
|
|
||||||
const handleContactSubmit = async (data: ContactData, type: "") => {
|
const handleContactSubmit = async (data: ContactData, type: "") => {
|
||||||
try {
|
try {
|
||||||
let res ;
|
let res;
|
||||||
setCreateAndInviteLoader(true);
|
setCreateAndInviteLoader(true);
|
||||||
if (type === 'Edit') {
|
if (type === 'Edit') {
|
||||||
res = await api.put(`/api/accounts/${activeAccountId}/contacts`, [data])
|
res = await api.put(`/api/accounts/${activeAccountId}/contacts`, [data])
|
||||||
}else{
|
} else {
|
||||||
res = await api.post(`/api/accounts/${activeAccountId}/contacts`, [data]);
|
res = await api.post(`/api/accounts/${activeAccountId}/contacts`, [data]);
|
||||||
}
|
}
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
|
|
@ -115,6 +117,7 @@ const Contacts = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<div className='px-1.5'>
|
||||||
<div className='flex justify-end my-2 cursor-pointer'>
|
<div className='flex justify-end my-2 cursor-pointer'>
|
||||||
<div
|
<div
|
||||||
onClick={() => setShowModal((prev) => !prev)}
|
onClick={() => setShowModal((prev) => !prev)}
|
||||||
|
|
@ -139,7 +142,7 @@ const Contacts = () => {
|
||||||
<tbody className="divide-y divide-gray-200">
|
<tbody className="divide-y divide-gray-200">
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan="4" className="text-center py-4">Loading...</td>
|
<td colSpan="4" className="relative h-100"><LoaderUi/></td>
|
||||||
</tr>
|
</tr>
|
||||||
) : contacts.length === 0 ? (
|
) : contacts.length === 0 ? (
|
||||||
<tr>
|
<tr>
|
||||||
|
|
@ -192,6 +195,7 @@ const Contacts = () => {
|
||||||
loading={createAndInviteLoader} setShowModal={setShowModal} actionStatus={actionStatus} editJsonData={editJsonData} />
|
loading={createAndInviteLoader} setShowModal={setShowModal} actionStatus={actionStatus} editJsonData={editJsonData} />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import React from 'react'
|
|
||||||
import { LuSignature } from "react-icons/lu";
|
import { LuSignature } from "react-icons/lu";
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { RootState } from '../../store/store';
|
import { RootState } from '../../store/store';
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,9 @@ const SendForSign: React.FC<Props> = ({ showSideBar }) => {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='relative max-h-max pb-3'
|
<div
|
||||||
|
id='send-for-sign-self-sign-btn'
|
||||||
|
className='relative max-h-max pb-3'
|
||||||
tabIndex={0}
|
tabIndex={0}
|
||||||
ref={dropDownRef}
|
ref={dropDownRef}
|
||||||
onBlur={() => setSendForSignDropdown(false)}
|
onBlur={() => setSendForSignDropdown(false)}
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,9 @@ const SideBar: React.FC<SideBarProps> = ({ showSideBar, setShowSideBar }) => {
|
||||||
{showSideBar ? 'Sign Made Easy' : 'SME'}
|
{showSideBar ? 'Sign Made Easy' : 'SME'}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div className={`flex flex-col mt-4 ${showSideBar ? '' : 'items-center'}`}>
|
<div
|
||||||
|
id="nav-link-dash"
|
||||||
|
className={`flex flex-col mt-4 ${showSideBar ? '' : 'items-center'}`}>
|
||||||
<SendForSign showSideBar={showSideBar} />
|
<SendForSign showSideBar={showSideBar} />
|
||||||
<NavLink to="/" icon={<FaHome />} label="Home" showSideBar={showSideBar} menuPathMap={menuPathMap} />
|
<NavLink to="/" icon={<FaHome />} label="Home" showSideBar={showSideBar} menuPathMap={menuPathMap} />
|
||||||
<NavLink to="/templates" icon={<HiTemplate />} label="Templates" showSideBar={showSideBar} menuPathMap={menuPathMap} />
|
<NavLink to="/templates" icon={<HiTemplate />} label="Templates" showSideBar={showSideBar} menuPathMap={menuPathMap} />
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ const StartNow = () => {
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
onClick={() => fileInputRef.current?.click()}
|
onClick={() => fileInputRef.current?.click()}
|
||||||
|
id='start-now-upload-con'
|
||||||
className="group cursor-pointer border-slate-300 rounded-lg bg-white/60 transition-all duration-200 p-4 flex flex-col items-center justify-center gap-2 text-center shadow-sm hover:shadow-md">
|
className="group cursor-pointer border-slate-300 rounded-lg bg-white/60 transition-all duration-200 p-4 flex flex-col items-center justify-center gap-2 text-center shadow-sm hover:shadow-md">
|
||||||
{/* Upload icon with subtle animation */}
|
{/* Upload icon with subtle animation */}
|
||||||
<div className="p-2 text-blue-600 group-hover:text-blue-700 transition-colors">
|
<div className="p-2 text-blue-600 group-hover:text-blue-700 transition-colors">
|
||||||
|
|
|
||||||
|
|
@ -65,10 +65,29 @@ const ProcessStepOne = () => {
|
||||||
console.log("selectedRecipients", selectedRecipients)
|
console.log("selectedRecipients", selectedRecipients)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// <<<<<<< HEAD
|
||||||
|
// Fetching Transaction Details - START
|
||||||
(async () => {
|
(async () => {
|
||||||
const res = await api.get(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`)
|
try {
|
||||||
console.log(res.data);
|
const res = await api.get(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`);
|
||||||
|
setTransactionDetails(res.data)
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Error - transactions details")
|
||||||
|
}
|
||||||
})()
|
})()
|
||||||
|
// Fetching Transaction Details - END
|
||||||
|
|
||||||
|
// =======
|
||||||
|
// (async () => {
|
||||||
|
// const res = await api.get(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`)
|
||||||
|
// console.log(res.data);
|
||||||
|
// })()
|
||||||
|
// >>>>>>> origin/main
|
||||||
|
|
||||||
|
// (async () => {
|
||||||
|
// const res = await api.get(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`)
|
||||||
|
// console.log(res.data);
|
||||||
|
// })()
|
||||||
|
|
||||||
selectedRecipients.length === 0 && dispatch(fetchRecipients({ accountId, transactionId }));
|
selectedRecipients.length === 0 && dispatch(fetchRecipients({ accountId, transactionId }));
|
||||||
selectedDocuments.length === 0 && dispatch(fetchDocuments({ accountId, transactionId }));
|
selectedDocuments.length === 0 && dispatch(fetchDocuments({ accountId, transactionId }));
|
||||||
|
|
@ -297,12 +316,14 @@ const ProcessStepOne = () => {
|
||||||
<p className="text-base font-normal text-gray-700 border-l pl-4">Add Recipient and Message</p>
|
<p className="text-base font-normal text-gray-700 border-l pl-4">Add Recipient and Message</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex items-center gap-3'>
|
<div
|
||||||
|
id="add-tags-btn-step-one"
|
||||||
|
className='flex items-center gap-3'>
|
||||||
<button
|
<button
|
||||||
onClick={() => handleNextClick(false)}
|
onClick={() => handleNextClick(false)}
|
||||||
className="text-sm px-4 py-2 rounded bg-[var(--primary)] text-white shadow hover:bg-[var(--primaryLight2)] transition"
|
className="text-sm px-4 py-2 rounded bg-[var(--primary)] text-white shadow hover:bg-[var(--primaryLight2)] transition"
|
||||||
>
|
>
|
||||||
Add Tags
|
{signType === SignTypeEnum.selfSign ? "Sign" : "Next"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -272,6 +272,7 @@ useEffect(() => {
|
||||||
<form
|
<form
|
||||||
ref={formRef}
|
ref={formRef}
|
||||||
onSubmit={handleRecipientAdd}
|
onSubmit={handleRecipientAdd}
|
||||||
|
id="add-recipient-step-one"
|
||||||
className="w-full bg-white border border-gray-200 rounded-lg shadow-md px-6 py-4 space-y-3 relative"
|
className="w-full bg-white border border-gray-200 rounded-lg shadow-md px-6 py-4 space-y-3 relative"
|
||||||
>
|
>
|
||||||
{transactionTemplateToggle === 'templates' && (
|
{transactionTemplateToggle === 'templates' && (
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,15 @@ const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateTogg
|
||||||
|
|
||||||
const handleRemoveRecipient = (recipient) => {
|
const handleRemoveRecipient = (recipient) => {
|
||||||
if (!accountId || !transactionId) return;
|
if (!accountId || !transactionId) return;
|
||||||
|
// <<<<<<< HEAD
|
||||||
|
// dispatch(removeSelectedRecipient(recipient))
|
||||||
|
// dispatch(removeRecipientAsync([{
|
||||||
|
// recipientId: recipient.id,
|
||||||
|
// email: recipient.email,
|
||||||
|
// accountId: accountId,
|
||||||
|
// transactionId: transactionId,
|
||||||
|
// }]))
|
||||||
|
// =======
|
||||||
if (recipient.uuid) {
|
if (recipient.uuid) {
|
||||||
dispatch(removeSelectedRecipient(recipient))
|
dispatch(removeSelectedRecipient(recipient))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -69,6 +78,7 @@ const RecipientCards = ({ setEditRecipient, setEditCase, transactionTemplateTogg
|
||||||
transactionId: transactionId,
|
transactionId: transactionId,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
// >>>>>>> origin/main
|
||||||
if (recipients.length === 2) {
|
if (recipients.length === 2) {
|
||||||
let leftRecipient = recipients.filter((obj) => {
|
let leftRecipient = recipients.filter((obj) => {
|
||||||
if ("id" in obj && "id" in recipient) {
|
if ("id" in obj && "id" in recipient) {
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,9 @@ const SelectedDocuments = ({transactionTemplateToggle}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{/* Upload Card First */}
|
{/* Upload Card First */}
|
||||||
<div className="flex flex-wrap gap-3">
|
<div
|
||||||
|
id='upload-doc-step-one'
|
||||||
|
className="flex flex-wrap gap-3">
|
||||||
{/* Uploaded documents */}
|
{/* Uploaded documents */}
|
||||||
<ReactSortable
|
<ReactSortable
|
||||||
className="flex flex-wrap gap-3"
|
className="flex flex-wrap gap-3"
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { RootState } from '../../../store/store'
|
||||||
import api from '../../../config/api';
|
import api from '../../../config/api';
|
||||||
|
|
||||||
import RightSideBar from './rightSideBar/RightSideBar';
|
import RightSideBar from './rightSideBar/RightSideBar';
|
||||||
import { DroppedItem } from '../../../utlity/types';
|
import { DroppedItem, TagsTypes } from '../../../utlity/types';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import { IoMdClose } from 'react-icons/io';
|
import { IoMdClose } from 'react-icons/io';
|
||||||
|
|
@ -19,6 +19,7 @@ import { IoAdd } from 'react-icons/io5';
|
||||||
import Loader from '../../dashboard/Loader';
|
import Loader from '../../dashboard/Loader';
|
||||||
// import { TRANSACTION_TEMPLATE_TOGGLE } from "../../../store/slices/selectedRecipientsSlice";
|
// import { TRANSACTION_TEMPLATE_TOGGLE } from "../../../store/slices/selectedRecipientsSlice";
|
||||||
import { handleGroupBorderPosition } from '../../../utlity/tagGroupConUtils';
|
import { handleGroupBorderPosition } from '../../../utlity/tagGroupConUtils';
|
||||||
|
import { hideLoader, showLoader } from '../../../store/slices/loaderSlice';
|
||||||
|
|
||||||
export interface DroppedItemsObj {
|
export interface DroppedItemsObj {
|
||||||
[key: string]: DroppedItem[]
|
[key: string]: DroppedItem[]
|
||||||
|
|
@ -65,7 +66,7 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
// const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments)
|
// const selectedDocuments = useSelector((state: RootState) => state.selectedDocuments.selectedDocuments)
|
||||||
const selectedDocuments = useSelector((state: RootState) => state.documents.documents)
|
const selectedDocuments = useSelector((state: RootState) => state.documents.documents)
|
||||||
|
|
||||||
console.log("selectedDocuments",selectedDocuments)
|
console.log("selectedDocuments", selectedDocuments)
|
||||||
|
|
||||||
const [droppedItems, setDroppedItems] = useState<DroppedItemsObj>({});
|
const [droppedItems, setDroppedItems] = useState<DroppedItemsObj>({});
|
||||||
console.log("droppedItems", droppedItems)
|
console.log("droppedItems", droppedItems)
|
||||||
|
|
@ -190,7 +191,7 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isSend === null) return;
|
if (isSend === null) return;
|
||||||
|
|
||||||
// dispatch(showLoader("Creating Transaction"))
|
dispatch(showLoader("Loading ..."))
|
||||||
|
|
||||||
let updatedTags = { ...droppedItems }
|
let updatedTags = { ...droppedItems }
|
||||||
|
|
||||||
|
|
@ -209,7 +210,6 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
for (const dropTag of updatedTags[dropPageIds]) {
|
for (const dropTag of updatedTags[dropPageIds]) {
|
||||||
let mask = null
|
let mask = null
|
||||||
|
|
||||||
|
|
||||||
// console.log(dropTag, "line 132")
|
// console.log(dropTag, "line 132")
|
||||||
|
|
||||||
// if (dropTag.subType?.toLowerCase() === "password") {
|
// if (dropTag.subType?.toLowerCase() === "password") {
|
||||||
|
|
@ -248,8 +248,8 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
"color": "black",
|
"color": "black",
|
||||||
"textSize": 0
|
"textSize": 0
|
||||||
},
|
},
|
||||||
// "required": (dropTag.type.toUpperCase() !== "SIGNATURE" && dropTag.type.toUpperCase() !== "INITIALS") ? dropTag.required : true,
|
"required": (dropTag.type.toUpperCase() !== "SIGNATURE" && dropTag.type.toUpperCase() !== "INITIALS") ? dropTag.required : true,
|
||||||
"required": "required" in dropTag ? dropTag.required : true,
|
// "required": "required" in dropTag ? dropTag.required : ,
|
||||||
"update": "update" in dropTag ? dropTag.update : false,
|
"update": "update" in dropTag ? dropTag.update : false,
|
||||||
"readOnly": false,
|
"readOnly": false,
|
||||||
}
|
}
|
||||||
|
|
@ -292,13 +292,17 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
// for(const recipient of selectedRecipients) {
|
// for(const recipient of selectedRecipients) {
|
||||||
// const recrecipient
|
// const recrecipient
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
tagsData = groupByRecipientId(tagsData);
|
tagsData = groupByRecipientId(tagsData);
|
||||||
|
|
||||||
sendTagsToRecipients(tagsData, accountId, transactionId);
|
sendTagsToRecipients(tagsData, accountId, transactionId);
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
const res = await api.put(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`, { status: "SENT" })
|
const res = await api.put(`/api/accounts/${accountId}/${transactionTemplateToggle}/${transactionId}`, { status: "SENT" })
|
||||||
// const res = await api.put(`/api/accounts/${accountId}/transactions/${transactionId}`, { status: "SENT" })
|
// const res = await api.put(`/api/accounts/${accountId}/transactions/${transactionId}`, { status: "SENT" })
|
||||||
console.log(res, "Check123")
|
console.log(res, "Check123")
|
||||||
|
dispatch(hideLoader())
|
||||||
})()
|
})()
|
||||||
}, [isSend])
|
}, [isSend])
|
||||||
// Save Tags - END
|
// Save Tags - END
|
||||||
|
|
@ -331,6 +335,19 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
const key = `${docId}_${pageIndex}`;
|
const key = `${docId}_${pageIndex}`;
|
||||||
// const IconComponent = typeToIconMap[field.type] || <FaQuestionCircle />;
|
// const IconComponent = typeToIconMap[field.type] || <FaQuestionCircle />;
|
||||||
|
|
||||||
|
// 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 = {
|
let prepData = {
|
||||||
properties: data.properties,
|
properties: data.properties,
|
||||||
icon: typeToIconMap[field.label.toUpperCase()] || <FaQuestionCircle />,
|
icon: typeToIconMap[field.label.toUpperCase()] || <FaQuestionCircle />,
|
||||||
|
|
@ -355,6 +372,7 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
pageIndex: pageIndex,
|
pageIndex: pageIndex,
|
||||||
recipientId: dragElemData.recipientId,
|
recipientId: dragElemData.recipientId,
|
||||||
recipientIndx: dragElemData.recipientIndx,
|
recipientIndx: dragElemData.recipientIndx,
|
||||||
|
required: (dragElemData.label !== TagsTypes.SIGNATURE && dragElemData.label !== TagsTypes.INITIALS) ? false : true,
|
||||||
update: true,
|
update: true,
|
||||||
isDeleted: false
|
isDeleted: false
|
||||||
}
|
}
|
||||||
|
|
@ -726,7 +744,7 @@ const DocumentContainer: React.FC<DocumentContainerProps> = ({ isSend }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Enhanced handleGroupBorderPosition with better positioning logic
|
// Enhanced handleGroupBorderPosition with better positioning logic
|
||||||
const handleGroupBorderPosition = (groupElements: NodeListOf<HTMLElement>, containerRect: DOMRect, offsetX: number, offsetY: number) => {
|
const handleGroupBorderPosition = (groupElements: NodeListOf<HTMLElement>, containerRect: DOMRect, offsetX: number, offsetY: number) => {
|
||||||
if (!groupElements || groupElements.length === 0) return;
|
if (!groupElements || groupElements.length === 0) return;
|
||||||
|
|
||||||
const groupId = groupElements[0].getAttribute('group');
|
const groupId = groupElements[0].getAttribute('group');
|
||||||
|
|
@ -823,7 +841,7 @@ const handleGroupBorderPosition = (groupElements: NodeListOf<HTMLElement>, conta
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAddGroupItemClicked = (key: string, item: any) => {
|
const handleAddGroupItemClicked = (key: string, item: any) => {
|
||||||
console.log("handleAddGroupItemClicked", item);
|
console.log("handleAddGroupItemClicked", item);
|
||||||
|
|
@ -835,6 +853,12 @@ const handleGroupBorderPosition = (groupElements: NodeListOf<HTMLElement>, conta
|
||||||
'group' in existingItem && existingItem.group === groupId
|
'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
|
// Find the bottom-most item in the group
|
||||||
let bottomMostItem = item;
|
let bottomMostItem = item;
|
||||||
if (existingGroupItems.length > 0) {
|
if (existingGroupItems.length > 0) {
|
||||||
|
|
@ -893,113 +917,9 @@ const handleGroupBorderPosition = (groupElements: NodeListOf<HTMLElement>, conta
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
return () => clearTimeout(timeoutId);
|
return () => clearTimeout(timeoutId);
|
||||||
}, [droppedItems]); // Re-run when droppedItems changes
|
}, [droppedItems]); // Re-run when droppedItems changes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// const handleAddRadio = (e: React.MouseEvent<HTMLElement>, 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<HTMLDivElement>, 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) => {
|
const handleDirectionalMove = (direction: 'up' | 'down' | 'left' | 'right', stepSize: number = 5) => {
|
||||||
if (!selectedTag) return;
|
if (!selectedTag) return;
|
||||||
|
|
||||||
|
|
@ -1043,8 +963,8 @@ const handleGroupBorderPosition = (groupElements: NodeListOf<HTMLElement>, conta
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add this new handler function to your parent component
|
// Add this new handler function to your parent component
|
||||||
const handleDirectPositionChange = (newLeft: number, newTop: number) => {
|
const handleDirectPositionChange = (newLeft: number, newTop: number) => {
|
||||||
console.log("handleDirectPositionChange",newLeft,newTop)
|
console.log("handleDirectPositionChange", newLeft, newTop)
|
||||||
if (!selectedTag) return;
|
if (!selectedTag) return;
|
||||||
|
|
||||||
const { key, index } = selectedTag;
|
const { key, index } = selectedTag;
|
||||||
|
|
@ -1074,7 +994,7 @@ const handleDirectPositionChange = (newLeft: number, newTop: number) => {
|
||||||
)
|
)
|
||||||
: [],
|
: [],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -1149,7 +1069,7 @@ const handleDirectPositionChange = (newLeft: number, newTop: number) => {
|
||||||
|
|
||||||
|
|
||||||
{/* Expand Circle - STARTS */}
|
{/* Expand Circle - STARTS */}
|
||||||
{item.type !== "radio" && <div
|
{item.type !== "radio" && item.type !== "checkbox" && <div
|
||||||
onPointerDown={(e) => handleExpandTag(e, key, index)}
|
onPointerDown={(e) => 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'>
|
className='w-2.5 h-2.5 absolute bg-red-400 rounded-full bottom-[-8px] right-[-8px] cursor-nw-resize hover:bg-blue-400'>
|
||||||
</div>}
|
</div>}
|
||||||
|
|
@ -1178,8 +1098,6 @@ const handleDirectPositionChange = (newLeft: number, newTop: number) => {
|
||||||
{
|
{
|
||||||
"group" in item && item.group && "isGroupExist" in item && !item.isGroupExist &&
|
"group" in item && item.group && "isGroupExist" in item && !item.isGroupExist &&
|
||||||
<>
|
<>
|
||||||
|
|
||||||
|
|
||||||
<div className="group-border" border-group={item.group} border-pos="top"></div>
|
<div className="group-border" border-group={item.group} border-pos="top"></div>
|
||||||
<div className="group-border" border-group={item.group} border-pos="right"></div>
|
<div className="group-border" border-group={item.group} border-pos="right"></div>
|
||||||
<div className="group-border bottom-border" border-group={item.group} border-pos="bottom">
|
<div className="group-border bottom-border" border-group={item.group} border-pos="bottom">
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@ const LeftSideBar: React.FC<LeftSideBarProps> = ({ isFields, selectedRecipientIn
|
||||||
<>
|
<>
|
||||||
{/* Left Side Bar - START */}
|
{/* Left Side Bar - START */}
|
||||||
{
|
{
|
||||||
selectedRecipients.length && <div className='col-span-2 bg-white h-full p-4 overflow-y-auto'>
|
selectedRecipients.length > 0 && <div className='col-span-2 bg-white h-full p-4 overflow-y-auto'>
|
||||||
{isFields && <>
|
{isFields && <>
|
||||||
{/* Fields List and Recipeint - Start */}
|
{/* Fields List and Recipeint - Start */}
|
||||||
{/* Side Bar showing Recipients */}
|
{/* Side Bar showing Recipients */}
|
||||||
|
|
@ -74,6 +74,7 @@ const LeftSideBar: React.FC<LeftSideBarProps> = ({ isFields, selectedRecipientIn
|
||||||
onBlur={() => setDropDownToggle(false)}>
|
onBlur={() => setDropDownToggle(false)}>
|
||||||
{/* Selected Recipient */}
|
{/* Selected Recipient */}
|
||||||
<div
|
<div
|
||||||
|
id='switch-recipients-left'
|
||||||
onClick={() => setDropDownToggle(!dropDownToggle)}
|
onClick={() => 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'>
|
className='flex items-center justify-between gap-2 w-full p-2 text-xs rounded-sm border-1 border-slate-200 cursor-pointer'>
|
||||||
<div className='flex items-center gap-1.5'>
|
<div className='flex items-center gap-1.5'>
|
||||||
|
|
@ -110,7 +111,9 @@ const LeftSideBar: React.FC<LeftSideBarProps> = ({ isFields, selectedRecipientIn
|
||||||
{/* Side Bar showing Recipients - ENDS*/}
|
{/* Side Bar showing Recipients - ENDS*/}
|
||||||
|
|
||||||
{/* Drag Drop Tags Start */}
|
{/* Drag Drop Tags Start */}
|
||||||
<div className='mt-4'>
|
<div
|
||||||
|
id='tags-con-dash-left'
|
||||||
|
className='mt-4'>
|
||||||
<FieldList color={selectedRecipient?.color || '#2d2d2d'} recipientId={selectedRecipient.id} recipientIndx={selectedRecipientIndx} />
|
<FieldList color={selectedRecipient?.color || '#2d2d2d'} recipientId={selectedRecipient.id} recipientIndx={selectedRecipientIndx} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -262,6 +262,7 @@ const NavTwo: React.FC<NavTwoProps> = ({ isFields, setIsFields, isSend, setIsSen
|
||||||
|
|
||||||
{/* Send */}
|
{/* Send */}
|
||||||
<div
|
<div
|
||||||
|
id='send-sign-dash-btn'
|
||||||
onClick={() => handleSend()}
|
onClick={() => handleSend()}
|
||||||
className='flex items-center gap-2 cursor-pointer text-xs px-4 py-2 ml-3 rounded-sm bg-[var(--primary)]'>
|
className='flex items-center gap-2 cursor-pointer text-xs px-4 py-2 ml-3 rounded-sm bg-[var(--primary)]'>
|
||||||
<p className='tracking-wide text-white'>Send</p>
|
<p className='tracking-wide text-white'>Send</p>
|
||||||
|
|
|
||||||
|
|
@ -44,11 +44,8 @@ const DirectionalControls: React.FC<DirectionalControlsProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePositionInputChange = (type: 'left' | 'top', value: string) => {
|
const handlePositionInputChange = (type: 'left' | 'top', value: string) => {
|
||||||
if (type === 'left') {
|
if (type === 'left') setLeftValue(value);
|
||||||
setLeftValue(value);
|
else setTopValue(value);
|
||||||
} else {
|
|
||||||
setTopValue(value);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePositionInputBlur = (type: 'left' | 'top') => {
|
const handlePositionInputBlur = (type: 'left' | 'top') => {
|
||||||
|
|
@ -57,11 +54,8 @@ const DirectionalControls: React.FC<DirectionalControlsProps> = ({
|
||||||
const numericValue = parseFloat(type === 'left' ? leftValue : topValue);
|
const numericValue = parseFloat(type === 'left' ? leftValue : topValue);
|
||||||
if (isNaN(numericValue)) {
|
if (isNaN(numericValue)) {
|
||||||
const { top = 0, left = 0 } = selectedType || {};
|
const { top = 0, left = 0 } = selectedType || {};
|
||||||
if (type === 'left') {
|
|
||||||
setLeftValue(Math.round(left).toString());
|
setLeftValue(Math.round(left).toString());
|
||||||
} else {
|
|
||||||
setTopValue(Math.round(top).toString());
|
setTopValue(Math.round(top).toString());
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,9 +67,7 @@ const DirectionalControls: React.FC<DirectionalControlsProps> = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleKeyPress = (e: React.KeyboardEvent, type: 'left' | 'top') => {
|
const handleKeyPress = (e: React.KeyboardEvent, type: 'left' | 'top') => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') handlePositionInputBlur(type);
|
||||||
handlePositionInputBlur(type);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -84,20 +76,11 @@ const DirectionalControls: React.FC<DirectionalControlsProps> = ({
|
||||||
|
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case 'ArrowUp':
|
case 'ArrowUp':
|
||||||
event.preventDefault();
|
|
||||||
handleMove('up');
|
|
||||||
break;
|
|
||||||
case 'ArrowDown':
|
case 'ArrowDown':
|
||||||
event.preventDefault();
|
|
||||||
handleMove('down');
|
|
||||||
break;
|
|
||||||
case 'ArrowLeft':
|
case 'ArrowLeft':
|
||||||
event.preventDefault();
|
|
||||||
handleMove('left');
|
|
||||||
break;
|
|
||||||
case 'ArrowRight':
|
case 'ArrowRight':
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
handleMove('right');
|
handleMove(event.key.replace('Arrow', '').toLowerCase() as any);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -107,39 +90,65 @@ const DirectionalControls: React.FC<DirectionalControlsProps> = ({
|
||||||
}, [disabled, stepSize]);
|
}, [disabled, stepSize]);
|
||||||
|
|
||||||
const buttonClass = `
|
const buttonClass = `
|
||||||
p-1 rounded-sm transition-all duration-200 border shadow-sm text-[10px]
|
w-8 h-8 flex items-center justify-center rounded-full border shadow-sm text-[12px]
|
||||||
${disabled
|
${disabled
|
||||||
? 'bg-gray-100 text-gray-400 cursor-not-allowed'
|
? 'bg-gray-100 text-gray-400 cursor-not-allowed'
|
||||||
: 'bg-white text-gray-600 hover:bg-blue-100 active:bg-blue-200 cursor-pointer'}
|
: 'bg-white text-gray-700 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 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 (
|
return (
|
||||||
<div className={`flex flex-col items-center space-y-4 text-[10px] text-gray-700 ${className}`}>
|
<div className={`inline-flex flex-col items-center space-y-2 text-[12px] ${className}`}>
|
||||||
{/* Top Button */}
|
{/* Top */}
|
||||||
<div className="flex justify-center me-4">
|
<button onClick={() => handleMove('up')} disabled={disabled} className={buttonClass} title="Move Up">
|
||||||
<div className="flex flex-col items-center">
|
<FaArrowUp />
|
||||||
<button
|
|
||||||
onClick={() => handleMove('up')}
|
|
||||||
disabled={disabled}
|
|
||||||
className={buttonClass}
|
|
||||||
title="Move up"
|
|
||||||
type="button"
|
|
||||||
>
|
|
||||||
<FaArrowUp size={12} />
|
|
||||||
</button>
|
</button>
|
||||||
<span className="mt-1">Top</span>
|
|
||||||
</div>
|
{/* Middle: Left / Inputs / Right */}
|
||||||
|
<div className="flex items-center space-x-3">
|
||||||
|
<button onClick={() => handleMove('left')} disabled={disabled} className={buttonClass} title="Move Left">
|
||||||
|
<FaArrowLeft />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{/* Input fields */}
|
||||||
|
<div className="flex flex-col items-center space-y-1">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={leftValue}
|
||||||
|
onChange={(e) => handlePositionInputChange('left', e.target.value)}
|
||||||
|
onBlur={() => handlePositionInputBlur('left')}
|
||||||
|
onKeyPress={(e) => handleKeyPress(e, 'left')}
|
||||||
|
disabled={disabled}
|
||||||
|
className={inputClass}
|
||||||
|
placeholder="Left"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
value={topValue}
|
||||||
|
onChange={(e) => handlePositionInputChange('top', e.target.value)}
|
||||||
|
onBlur={() => handlePositionInputBlur('top')}
|
||||||
|
onKeyPress={(e) => handleKeyPress(e, 'top')}
|
||||||
|
disabled={disabled}
|
||||||
|
className={inputClass}
|
||||||
|
placeholder="Top"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<button onClick={() => handleMove('right')} disabled={disabled} className={buttonClass} title="Move Right">
|
||||||
|
<FaArrowRight />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Bottom */}
|
||||||
|
<button onClick={() => handleMove('down')} disabled={disabled} className={buttonClass} title="Move Down">
|
||||||
|
<FaArrowDown />
|
||||||
|
</button>
|
||||||
{/* Middle Row: Left - Center (Inputs) - Right */}
|
{/* Middle Row: Left - Center (Inputs) - Right */}
|
||||||
<div className="flex items-center space-x-1">
|
<div className="flex items-center space-x-1">
|
||||||
{/* Left Button */}
|
{/* Left Button */}
|
||||||
|
|
@ -215,7 +224,6 @@ const DirectionalControls: React.FC<DirectionalControlsProps> = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DirectionalControls;
|
export default DirectionalControls;
|
||||||
|
|
@ -122,28 +122,26 @@ const RightSideBar: React.FC<DroppedItemProps> = ({ selectedTag, setDroppedItems
|
||||||
console.log("changeTo", changeTo, "changeWith", changeWith)
|
console.log("changeTo", changeTo, "changeWith", changeWith)
|
||||||
if (changeTo === '' || changeWith === '') return
|
if (changeTo === '' || changeWith === '') return
|
||||||
|
|
||||||
if (changeWith === "paragraph") {
|
// if (changeTo === "subType" && (changeWith === TEMPORAL.DATE || changeWith === TEMPORAL.DATE_TIME || changeWith === TEMPORAL.TIME)) {
|
||||||
return
|
// // 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)) {
|
// } else
|
||||||
// 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") {
|
if (changeTo === "subType" && typeof changeWith === "string" && changeWith.toLowerCase() === "password") {
|
||||||
console.log("Second check")
|
console.log("Second check")
|
||||||
console.log("Line 161")
|
console.log("Line 161")
|
||||||
setDroppedItems((prev) => (
|
setDroppedItems((prev) => (
|
||||||
|
|
@ -174,13 +172,26 @@ const RightSideBar: React.FC<DroppedItemProps> = ({ selectedTag, setDroppedItems
|
||||||
}// Provide a fallback in case it's undefined or not an array
|
}// 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")
|
console.log("Fourth Check")
|
||||||
let val = timeFormats[0].format;
|
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
|
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) => {
|
setDroppedItems((prev) => {
|
||||||
const updatedArray = Array.isArray(prev[selTagKey])
|
const updatedArray = Array.isArray(prev[selTagKey])
|
||||||
|
|
@ -199,9 +210,9 @@ const RightSideBar: React.FC<DroppedItemProps> = ({ selectedTag, setDroppedItems
|
||||||
[selTagKey]: updatedArray,
|
[selTagKey]: updatedArray,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
} else {
|
|
||||||
setDroppedItems((prev) => {
|
setDroppedItems((prev) => {
|
||||||
|
|
||||||
const updatedItems = Array.isArray(prev[selTagKey])
|
const updatedItems = Array.isArray(prev[selTagKey])
|
||||||
|
|
@ -284,6 +295,7 @@ const RightSideBar: React.FC<DroppedItemProps> = ({ selectedTag, setDroppedItems
|
||||||
const tagHeight = selectedTag?.dimensions?.height - 18;
|
const tagHeight = selectedTag?.dimensions?.height - 18;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
selectedTag.type === TagsTypes.TEXT &&
|
||||||
selectedTag.subType !== TEXT.PASSWORD &&
|
selectedTag.subType !== TEXT.PASSWORD &&
|
||||||
selectedTag.subType !== TEXT.PARAGRAPH &&
|
selectedTag.subType !== TEXT.PARAGRAPH &&
|
||||||
tagHeight > fontSize * 2
|
tagHeight > fontSize * 2
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ const SelectTagAttr: React.FC<SelectTagAttrInt> = ({ options, selTagKey, selTagI
|
||||||
return newState;
|
return newState;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const handleSelectOptionDel = (indx: number) => {
|
const handleSelectOptionDel = (indx: number) => {
|
||||||
|
|
@ -65,14 +65,11 @@ const SelectTagAttr: React.FC<SelectTagAttrInt> = ({ options, selTagKey, selTagI
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
onChange={(e) => setSelectedOption(e.target.value)}
|
onChange={(e) => setSelectedOption(e.target.value)}
|
||||||
value={selectedOption}
|
// value={selectedOption}
|
||||||
onKeyUp={(e) => {
|
onKeyUp={(e) => {
|
||||||
if (e.code === "Enter") {
|
if (e.code === "Enter") {
|
||||||
// if (selectedOption) {
|
e.currentTarget.value = "";
|
||||||
// setSelectedOptions((prev) => [...prev, selectedOption]);
|
handleAddSelectOption();
|
||||||
// setSelectedOption("");
|
|
||||||
// }
|
|
||||||
handleAddSelectOption()
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
className="bg-slate-100 w-full outline-none p-2 rounded" />
|
className="bg-slate-100 w-full outline-none p-2 rounded" />
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ const TemporalDateAttr: React.FC<TemporalDateAttrInt> = ({ subType, format, drop
|
||||||
const [is24Hrs, setIs24Hrs] = useState<boolean>(true);
|
const [is24Hrs, setIs24Hrs] = useState<boolean>(true);
|
||||||
|
|
||||||
const handleIs24HrsClick = (checked: boolean) => {
|
const handleIs24HrsClick = (checked: boolean) => {
|
||||||
|
console.log(is24Hrs, checked, "line 30")
|
||||||
if (subType === TEMPORAL.TIME) {
|
if (subType === TEMPORAL.TIME) {
|
||||||
if (!checked) {
|
if (!checked) {
|
||||||
handlePropertyChange("format", timeFormats[1].format, is24Hrs)
|
handlePropertyChange("format", timeFormats[1].format, is24Hrs)
|
||||||
|
|
@ -34,6 +35,9 @@ const TemporalDateAttr: React.FC<TemporalDateAttrInt> = ({ subType, format, drop
|
||||||
handlePropertyChange("format", timeFormats[0].format, is24Hrs)
|
handlePropertyChange("format", timeFormats[0].format, is24Hrs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (subType === TEMPORAL.DATE_TIME) {
|
||||||
|
handlePropertyChange("format", (format.split(" ").slice(0, -1).join(" ")), !is24Hrs)
|
||||||
|
}
|
||||||
setIs24Hrs(checked)
|
setIs24Hrs(checked)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,11 +90,11 @@ const TemporalDateAttr: React.FC<TemporalDateAttrInt> = ({ subType, format, drop
|
||||||
val = val + " " + timeFormats[1].format;
|
val = val + " " + timeFormats[1].format;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('line 89' , val )
|
console.log('line 89', val)
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={indx}
|
key={indx}
|
||||||
onClick={() => handlePropertyChange("format", valObj["format"])}
|
onClick={() => handlePropertyChange("format", valObj["format"], is24Hrs)}
|
||||||
className="px-2 py-1 hover:bg-slate-200 cursor-pointer"
|
className="px-2 py-1 hover:bg-slate-200 cursor-pointer"
|
||||||
>
|
>
|
||||||
{val}
|
{val}
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ const Templates = () => {
|
||||||
console.log("handleAddTemplate called");
|
console.log("handleAddTemplate called");
|
||||||
try {
|
try {
|
||||||
const res = await api.post(`/api/accounts/${activeAccountId}/templates`);
|
const res = await api.post(`/api/accounts/${activeAccountId}/templates`);
|
||||||
navigate(`/process-step-one/${activeAccountId}/template/${res.data}`)
|
navigate(`/process-step-one/${activeAccountId}/template/${res.data.id}`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error)
|
console.log(error)
|
||||||
}
|
}
|
||||||
|
|
@ -136,7 +136,15 @@ const Templates = () => {
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
{templates.length > 0 ? (
|
{loading ? (
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td colSpan="6" className="relative h-100">
|
||||||
|
<LoaderUi />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
) : templates.length > 0 ? (
|
||||||
<tbody className="divide-y divide-gray-200">
|
<tbody className="divide-y divide-gray-200">
|
||||||
{templates.map((item, index) => {
|
{templates.map((item, index) => {
|
||||||
return (
|
return (
|
||||||
|
|
@ -200,18 +208,12 @@ const Templates = () => {
|
||||||
) : (
|
) : (
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan="5">
|
<td colSpan="6" className="text-center py-10 text-gray-500">
|
||||||
<div className="relative flex justify-center items-center h-100 w-full">
|
No templates found.
|
||||||
{/* Pulsing background div */}
|
|
||||||
<div className="absolute inset-0 bg-gradient-to-r from-gray-200 to-white animate-pulse"></div>
|
|
||||||
|
|
||||||
{/* Loader stays on top, no animation */}
|
|
||||||
<LoaderUi classStyle="relative h-16 w-16" />
|
|
||||||
</div>
|
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { AiFillSignature } from 'react-icons/ai';
|
import { AiFillSignature } from 'react-icons/ai';
|
||||||
import { Link, useParams } from 'react-router-dom';
|
import { Link, useNavigate, useParams } from 'react-router-dom';
|
||||||
import { LuGitGraph } from 'react-icons/lu';
|
import { LuGitGraph } from 'react-icons/lu';
|
||||||
import AccountNav from '../accounts/AccountNav';
|
import AccountNav from '../accounts/AccountNav';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
|
@ -7,6 +7,8 @@ import api from '../../config/api';
|
||||||
import SigningOrderDiagram from '../../SigningOrderDiagram ';
|
import SigningOrderDiagram from '../../SigningOrderDiagram ';
|
||||||
import { IoCloseOutline } from 'react-icons/io5';
|
import { IoCloseOutline } from 'react-icons/io5';
|
||||||
import { MdEditDocument } from "react-icons/md";
|
import { MdEditDocument } from "react-icons/md";
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { RootState } from '../../store/store';
|
||||||
|
|
||||||
// Sample recipient data — you can replace this with actual API data later
|
// Sample recipient data — you can replace this with actual API data later
|
||||||
const recipients = [
|
const recipients = [
|
||||||
|
|
@ -30,8 +32,8 @@ const recipients = [
|
||||||
|
|
||||||
const TransactionView = () => {
|
const TransactionView = () => {
|
||||||
const { accountId, transactionId } = useParams<{ accountId: string, transactionId: string }>();
|
const { accountId, transactionId } = useParams<{ accountId: string, transactionId: string }>();
|
||||||
console.log("account" , accountId , transactionId)
|
|
||||||
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
if (!accountId || !transactionId) {
|
if (!accountId || !transactionId) {
|
||||||
window.location.href = "/";
|
window.location.href = "/";
|
||||||
|
|
@ -40,6 +42,8 @@ const TransactionView = () => {
|
||||||
|
|
||||||
const [transactionDetails, setTransactionDetails] = useState(null);
|
const [transactionDetails, setTransactionDetails] = useState(null);
|
||||||
const [signingOrderModal, setSigningOrderModal] = useState({ open: false });
|
const [signingOrderModal, setSigningOrderModal] = useState({ open: false });
|
||||||
|
const user = useSelector((state: RootState) => state.user)
|
||||||
|
|
||||||
console.log(transactionDetails, "line 37");
|
console.log(transactionDetails, "line 37");
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
|
|
@ -56,6 +60,11 @@ const TransactionView = () => {
|
||||||
fetchData()
|
fetchData()
|
||||||
}, [accountId, transactionId])
|
}, [accountId, transactionId])
|
||||||
|
|
||||||
|
|
||||||
|
const handleNavigateToSign = (id: number) => {
|
||||||
|
window.open(`./../../../../sign/${id}`)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{transactionDetails &&
|
{transactionDetails &&
|
||||||
|
|
@ -64,17 +73,17 @@ const TransactionView = () => {
|
||||||
<div className="w-full px-6 py-4 rounded-tl-sm text-xs border-r-2 border-gray-200 overflow-y-auto">
|
<div className="w-full px-6 py-4 rounded-tl-sm text-xs border-r-2 border-gray-200 overflow-y-auto">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<h1 className='text-lg font-semibold text-gray-800'>
|
<h1 className='text-lg font-semibold text-gray-800'>
|
||||||
Complete with Forms Made Easy: <span className='text-slate-600'>{ transactionDetails?.transaction?.subject ?? "Untitled"}</span>
|
Complete with Forms Made Easy: <span className='text-slate-600'>{transactionDetails?.transaction?.subject ?? "Untitled"}</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div className='mt-2'>
|
<div className='mt-2'>
|
||||||
{/* new Date(transactionDetails?.transaction?.lastModifiedAt * 1000) */}
|
{/* new Date(transactionDetails?.transaction?.lastModifiedAt * 1000) */}
|
||||||
<p className='text-slate-600'>From <span className='text-blue-600'>Shanu.R</span></p>
|
<p className='text-slate-600'>From <span className='text-blue-600'>{transactionDetails?.transaction.createdBy.firstName + " " + transactionDetails?.transaction.createdBy.lastName}</span></p>
|
||||||
<p className=''><span className='text-slate-600 font-semibold'>Last Change on</span> <span className='text-slate-400'>{new Date(transactionDetails?.transaction?.lastModifiedAt * 1000).toISOString()}</span></p>
|
<p className=''><span className='text-slate-600 font-semibold'>Last Change on</span> <span className='text-slate-400'>{new Date(transactionDetails?.transaction?.lastModifiedAt * 1000).toISOString()}</span></p>
|
||||||
<p className='text-slate-600'>Created at <span>{new Date(transactionDetails?.transaction?.createdAt * 1000).toISOString()}</span></p>
|
<p className='text-slate-600'>Created at <span>{new Date(transactionDetails?.transaction?.createdAt * 1000).toISOString()}</span></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p className='text-slate-600 text-[0.98rem] mt-2 font-semibold'>Draft</p>
|
<p className='text-slate-600 text-[0.98rem] mt-2 font-semibold'>{transactionDetails?.transaction.status}</p>
|
||||||
|
|
||||||
{/* Buttons */}
|
{/* Buttons */}
|
||||||
<div className='my-2 flex gap-2'>
|
<div className='my-2 flex gap-2'>
|
||||||
|
|
@ -112,19 +121,27 @@ const TransactionView = () => {
|
||||||
<div key={index}>
|
<div key={index}>
|
||||||
<div className='mt-2 flex justify-between items-center'>
|
<div className='mt-2 flex justify-between items-center'>
|
||||||
<div className='flex gap-8 items-center'>
|
<div className='flex gap-8 items-center'>
|
||||||
<p className='text-slate-600'>{recipient.id}</p>
|
{/* <p className='text-slate-600'>{index+1}</p> */}
|
||||||
<div>
|
<div>
|
||||||
<p className='text-slate-600 font-semibold'>{recipient.name}</p>
|
<p className='text-slate-600 font-semibold'>{recipient.name}</p>
|
||||||
<p className='text-slate-600'>{recipient.email}</p>
|
<p className='text-slate-600'>{recipient.email}</p>
|
||||||
{recipient.hostEmail !== null && <p className='text-xs'><i><b>Host: {recipient.hostEmail}</b></i></p>}
|
{recipient.hostEmail !== null && recipient.hostEmail !== "" && <p className='text-xs'><i><b>Host: {recipient.hostEmail}</b></i></p>}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='flex flex-col leading-4.5 items-start text-md text-slate-600 pr-18'>
|
<div className='flex flex-col leading-4.5 items-start text-md text-slate-600'>
|
||||||
|
<div className='flex gap-3 items-center relative'>
|
||||||
<div className='flex gap-1 items-center relative'>
|
<div className='flex gap-1 items-center relative'>
|
||||||
<AiFillSignature className='absolute left-[-30px] text-[1rem]' />
|
<AiFillSignature className='absolute left-[-30px] text-[1rem]' />
|
||||||
<p className='text-black font-semibold'>{recipient.status}</p>
|
<p className='text-black font-semibold'>{recipient.status}</p>
|
||||||
</div>
|
</div>
|
||||||
|
{recipient.email === user.email &&
|
||||||
|
<p
|
||||||
|
onClick={() => handleNavigateToSign(recipient.id)}
|
||||||
|
className='text-white rounded-sm bg-[var(--primary)] px-3 py-1 font-semibold'>
|
||||||
|
Sign
|
||||||
|
</p>}
|
||||||
|
</div>
|
||||||
{recipient.status !== "PENDING" && <p>on {recipient.completedAt}</p>}
|
{recipient.status !== "PENDING" && <p>on {recipient.completedAt}</p>}
|
||||||
{/* <a href={recipient.viewLink} className='text-blue-600 hover:underline'>
|
{/* <a href={recipient.viewLink} className='text-blue-600 hover:underline'>
|
||||||
View signed location
|
View signed location
|
||||||
|
|
@ -138,10 +155,17 @@ const TransactionView = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{transactionDetails?.transaction?.subject !== "" &&
|
||||||
|
<div>
|
||||||
|
<h2 className='text-lg mt-4 font-semibold text-gray-800 cursor-pointer'>Subject</h2>
|
||||||
|
<p className='mt-2 text-slate-600'>{`${transactionDetails?.transaction?.subject ? transactionDetails?.transaction?.subject : "Not Found"} `}</p>
|
||||||
|
</div>}
|
||||||
|
|
||||||
|
{transactionDetails?.transaction?.message !== "" &&
|
||||||
<div>
|
<div>
|
||||||
<h2 className='text-lg mt-4 font-semibold text-gray-800 cursor-pointer'>Message</h2>
|
<h2 className='text-lg mt-4 font-semibold text-gray-800 cursor-pointer'>Message</h2>
|
||||||
<p className='mt-2 text-slate-600'>{ transactionDetails?.transaction?.message ?? "No Message Found...!"}</p>
|
<p className='mt-2 text-slate-600'>{`${transactionDetails?.transaction?.message ? transactionDetails?.transaction?.message : "Not Found"} `}</p>
|
||||||
</div>
|
</div>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='w-[210px] text-xs rounded-sm '>
|
<div className='w-[210px] text-xs rounded-sm '>
|
||||||
|
|
@ -153,7 +177,7 @@ const TransactionView = () => {
|
||||||
<div className='bg-slate-100 p-2 absolute w-full bottom-[0px]'>
|
<div className='bg-slate-100 p-2 absolute w-full bottom-[0px]'>
|
||||||
<p className='text-[0.7rem] text-slate-500 flex justify-between items-center'>
|
<p className='text-[0.7rem] text-slate-500 flex justify-between items-center'>
|
||||||
<span> 1 of 10</span>
|
<span> 1 of 10</span>
|
||||||
<span className='cursor-pointer'><Link to={`/process-step-two/${accountId}/${transactionId}`}><MdEditDocument size={16}/></Link></span>
|
<span className='cursor-pointer'><Link to={`/process-step-two/${accountId}/${transactionId}`}><MdEditDocument size={16} /></Link></span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,22 @@
|
||||||
|
import { LuSignature } from "react-icons/lu";
|
||||||
|
|
||||||
interface StyleProps {
|
interface StyleProps {
|
||||||
classStyle : string
|
classStyle?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const LoaderUi = ({ classStyle }:StyleProps) => {
|
const LoaderUi = ({ classStyle = '' }: StyleProps) => {
|
||||||
return (
|
return (
|
||||||
<div className={classStyle}>
|
<div className={`absolute inset-0 flex items-center justify-center z-50 ${classStyle}`}>
|
||||||
<svg viewBox="0 0 240 240" height="240" width="240" className="pl">
|
{/* Overlay */}
|
||||||
<circle strokeLinecap="round" strokeDashoffset="-330" strokeDasharray="0 660" strokeWidth="20" stroke="#000" fill="none" r="105" cy="120" cx="120" className="pl__ring pl__ring--a"></circle>
|
<div className="absolute inset-0 bg-black/30 opacity-60"></div>
|
||||||
<circle strokeLinecap="round" strokeDashoffset="-110" strokeDasharray="0 220" strokeWidth="20" stroke="#000" fill="none" r="35" cy="120" cx="120" className="pl__ring pl__ring--b"></circle>
|
|
||||||
<circle strokeLinecap="round" strokeDasharray="0 440" strokeWidth="20" stroke="#000" fill="none" r="70" cy="120" cx="85" className="pl__ring pl__ring--c"></circle>
|
|
||||||
<circle strokeLinecap="round" strokeDasharray="0 440" strokeWidth="20" stroke="#000" fill="none" r="70" cy="120" cx="155" className="pl__ring pl__ring--d"></circle>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default LoaderUi
|
{/* Loader box */}
|
||||||
|
<div className="relative z-10 bg-[var(--loaderBg)] flex flex-col justify-center items-center gap-2 px-16 py-8 rounded-md shadow-lg">
|
||||||
|
<LuSignature className="text-4xl font-bold animate-text" />
|
||||||
|
<p>Loading...!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default LoaderUi;
|
||||||
|
|
|
||||||
|
|
@ -120,7 +120,7 @@ canvas {
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom-border>div:hover {
|
.bottom-border>div:hover {
|
||||||
background-color: var(--primaryLight2) ;
|
background-color: var(--primaryLight2);
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
transition: all 0.3s ease-in-out;
|
transition: all 0.3s ease-in-out;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
@ -129,8 +129,8 @@ canvas {
|
||||||
/* Group Border - END */
|
/* Group Border - END */
|
||||||
|
|
||||||
|
|
||||||
/* Loader CSS */
|
/* Loader CSS */
|
||||||
/* From Uiverse.io by Juanes200122 */
|
/* From Uiverse.io by Juanes200122 */
|
||||||
.pl {
|
.pl {
|
||||||
width: 6em;
|
width: 6em;
|
||||||
height: 6em;
|
height: 6em;
|
||||||
|
|
@ -159,9 +159,11 @@ canvas {
|
||||||
stroke: #41644A;
|
stroke: #41644A;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Animations */
|
/* Animations */
|
||||||
@keyframes ringA {
|
@keyframes ringA {
|
||||||
from, 4% {
|
|
||||||
|
from,
|
||||||
|
4% {
|
||||||
stroke-dasharray: 0 660;
|
stroke-dasharray: 0 660;
|
||||||
stroke-width: 20;
|
stroke-width: 20;
|
||||||
stroke-dashoffset: -330;
|
stroke-dashoffset: -330;
|
||||||
|
|
@ -179,7 +181,8 @@ canvas {
|
||||||
stroke-dashoffset: -595;
|
stroke-dashoffset: -595;
|
||||||
}
|
}
|
||||||
|
|
||||||
40%, 54% {
|
40%,
|
||||||
|
54% {
|
||||||
stroke-dasharray: 0 660;
|
stroke-dasharray: 0 660;
|
||||||
stroke-width: 20;
|
stroke-width: 20;
|
||||||
stroke-dashoffset: -660;
|
stroke-dashoffset: -660;
|
||||||
|
|
@ -197,7 +200,8 @@ canvas {
|
||||||
stroke-dashoffset: -925;
|
stroke-dashoffset: -925;
|
||||||
}
|
}
|
||||||
|
|
||||||
90%, to {
|
90%,
|
||||||
|
to {
|
||||||
stroke-dasharray: 0 660;
|
stroke-dasharray: 0 660;
|
||||||
stroke-width: 20;
|
stroke-width: 20;
|
||||||
stroke-dashoffset: -990;
|
stroke-dashoffset: -990;
|
||||||
|
|
@ -205,7 +209,9 @@ canvas {
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes ringB {
|
@keyframes ringB {
|
||||||
from, 12% {
|
|
||||||
|
from,
|
||||||
|
12% {
|
||||||
stroke-dasharray: 0 220;
|
stroke-dasharray: 0 220;
|
||||||
stroke-width: 20;
|
stroke-width: 20;
|
||||||
stroke-dashoffset: -110;
|
stroke-dashoffset: -110;
|
||||||
|
|
@ -223,7 +229,8 @@ canvas {
|
||||||
stroke-dashoffset: -195;
|
stroke-dashoffset: -195;
|
||||||
}
|
}
|
||||||
|
|
||||||
48%, 62% {
|
48%,
|
||||||
|
62% {
|
||||||
stroke-dasharray: 0 220;
|
stroke-dasharray: 0 220;
|
||||||
stroke-width: 20;
|
stroke-width: 20;
|
||||||
stroke-dashoffset: -220;
|
stroke-dashoffset: -220;
|
||||||
|
|
@ -241,7 +248,8 @@ canvas {
|
||||||
stroke-dashoffset: -305;
|
stroke-dashoffset: -305;
|
||||||
}
|
}
|
||||||
|
|
||||||
98%, to {
|
98%,
|
||||||
|
to {
|
||||||
stroke-dasharray: 0 220;
|
stroke-dasharray: 0 220;
|
||||||
stroke-width: 20;
|
stroke-width: 20;
|
||||||
stroke-dashoffset: -330;
|
stroke-dashoffset: -330;
|
||||||
|
|
@ -267,7 +275,8 @@ canvas {
|
||||||
stroke-dashoffset: -175;
|
stroke-dashoffset: -175;
|
||||||
}
|
}
|
||||||
|
|
||||||
36%, 58% {
|
36%,
|
||||||
|
58% {
|
||||||
stroke-dasharray: 0 440;
|
stroke-dasharray: 0 440;
|
||||||
stroke-width: 20;
|
stroke-width: 20;
|
||||||
stroke-dashoffset: -220;
|
stroke-dashoffset: -220;
|
||||||
|
|
@ -285,7 +294,8 @@ canvas {
|
||||||
stroke-dashoffset: -395;
|
stroke-dashoffset: -395;
|
||||||
}
|
}
|
||||||
|
|
||||||
94%, to {
|
94%,
|
||||||
|
to {
|
||||||
stroke-dasharray: 0 440;
|
stroke-dasharray: 0 440;
|
||||||
stroke-width: 20;
|
stroke-width: 20;
|
||||||
stroke-dashoffset: -440;
|
stroke-dashoffset: -440;
|
||||||
|
|
@ -293,7 +303,9 @@ canvas {
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes ringD {
|
@keyframes ringD {
|
||||||
from, 8% {
|
|
||||||
|
from,
|
||||||
|
8% {
|
||||||
stroke-dasharray: 0 440;
|
stroke-dasharray: 0 440;
|
||||||
stroke-width: 20;
|
stroke-width: 20;
|
||||||
stroke-dashoffset: 0;
|
stroke-dashoffset: 0;
|
||||||
|
|
@ -311,7 +323,8 @@ canvas {
|
||||||
stroke-dashoffset: -175;
|
stroke-dashoffset: -175;
|
||||||
}
|
}
|
||||||
|
|
||||||
44%, 50% {
|
44%,
|
||||||
|
50% {
|
||||||
stroke-dasharray: 0 440;
|
stroke-dasharray: 0 440;
|
||||||
stroke-width: 20;
|
stroke-width: 20;
|
||||||
stroke-dashoffset: -220;
|
stroke-dashoffset: -220;
|
||||||
|
|
@ -329,14 +342,16 @@ canvas {
|
||||||
stroke-dashoffset: -395;
|
stroke-dashoffset: -395;
|
||||||
}
|
}
|
||||||
|
|
||||||
86%, to {
|
86%,
|
||||||
|
to {
|
||||||
stroke-dasharray: 0 440;
|
stroke-dasharray: 0 440;
|
||||||
stroke-width: 20;
|
stroke-width: 20;
|
||||||
stroke-dashoffset: -440;
|
stroke-dashoffset: -440;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.bottom-border>div:hover {
|
.bottom-border>div:hover {
|
||||||
background-color: var(--primaryLight2) ;
|
background-color: var(--primaryLight2);
|
||||||
opacity: 0.9;
|
opacity: 0.9;
|
||||||
transition: all 0.3s ease-in-out;
|
transition: all 0.3s ease-in-out;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
@ -344,3 +359,11 @@ canvas {
|
||||||
|
|
||||||
/* Group Border - END */
|
/* Group Border - END */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* JoyRide - START */
|
||||||
|
.__floater__body > div > button:last-child {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* JoyRide - END */
|
||||||
|
|
@ -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<Step[]>([]);
|
||||||
|
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: (
|
||||||
|
<div>
|
||||||
|
<p>Easy Navigation to see transaction and templates.</p>
|
||||||
|
<p>
|
||||||
|
<strong>Templates:</strong> you can save all recipient documents and tags and
|
||||||
|
use them multiple times on one click.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
placement: "left",
|
||||||
|
disableBeacon: true,
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
target: "#start-now-upload-con",
|
||||||
|
content: (
|
||||||
|
<div>
|
||||||
|
<p>Let's Start Some Action</p>
|
||||||
|
<p>
|
||||||
|
Click On <strong>Start Now</strong> To upload your first document for signature
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
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: (
|
||||||
|
<div>
|
||||||
|
<p>👋 Welcome To process step one</p>
|
||||||
|
<p>
|
||||||
|
Here we have to add core two ingredients <strong>Document, Recipient</strong> to start cooking
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
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: (
|
||||||
|
<div>
|
||||||
|
<p>👋 This is Final Step</p>
|
||||||
|
<br />
|
||||||
|
<p>Here we can add tags in documents and assign them to recipients</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
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: <div>
|
||||||
|
<p>When setisfied with all the change, Click on <strong>Send</strong></p>
|
||||||
|
</div>,
|
||||||
|
placement: "right",
|
||||||
|
disableBeacon: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
} else if (location.pathname.includes("/sign/")) {
|
||||||
|
currentSteps = [
|
||||||
|
{
|
||||||
|
target: "body", // This makes the welcome step show in center of screen
|
||||||
|
content: (
|
||||||
|
<div>
|
||||||
|
<p>👋 Hi there! Welcome to SME. Let’s start signing.</p>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
placement: "center",
|
||||||
|
disableBeacon: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
target: "#tags-list-client-side",
|
||||||
|
content: <div>
|
||||||
|
<p>Drag and drop tags onto the document to fill or sign.</p>
|
||||||
|
</div>,
|
||||||
|
placement: "right",
|
||||||
|
disableBeacon: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
target: "#sign-client-side-btn",
|
||||||
|
content: <div>
|
||||||
|
<p>Check your document carefully When you're satisfied Click on Sign button</p>
|
||||||
|
</div>,
|
||||||
|
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 (
|
||||||
|
<Joyride
|
||||||
|
steps={steps}
|
||||||
|
run={runTour}
|
||||||
|
callback={handleJoyrideCallback}
|
||||||
|
continuous
|
||||||
|
scrollToFirstStep
|
||||||
|
showProgress
|
||||||
|
showSkipButton
|
||||||
|
disableOverlayClose
|
||||||
|
styles={{
|
||||||
|
options: {
|
||||||
|
zIndex: 9999,
|
||||||
|
primaryColor: "#3D74B6", // Changes "Next"/"Done" button
|
||||||
|
textColor: "#111827", // Content text color
|
||||||
|
backgroundColor: "#F9FAFB",// Tooltip background
|
||||||
|
arrowColor: "#F9FAFB", // Arrow background
|
||||||
|
},
|
||||||
|
buttonNext: {
|
||||||
|
backgroundColor: "#3D74B6", // Indigo
|
||||||
|
color: "#FFFFFF",
|
||||||
|
},
|
||||||
|
buttonBack: {
|
||||||
|
color: "#4F46E5", // Indigo text
|
||||||
|
},
|
||||||
|
buttonSkip: {
|
||||||
|
color: "#EF4444", // Red skip button
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
locale={{
|
||||||
|
back: "Back",
|
||||||
|
close: "Close",
|
||||||
|
last: "Done",
|
||||||
|
next: "Next",
|
||||||
|
skip: "Skip",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default JoyrideController;
|
||||||
Loading…
Reference in New Issue