Merge branch 'master' of https://git.shiblysolution.id/TPAY/dashboard
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@ -27,4 +27,6 @@ yarn.lock
|
|||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
**/src/*.js
|
**/src/*.js
|
||||||
.env
|
.env
|
||||||
|
|
||||||
|
package-lock.json
|
||||||
|
|||||||
143
package-lock.json
generated
143
package-lock.json
generated
@ -71,6 +71,7 @@
|
|||||||
"styled-components": "^6.1.13",
|
"styled-components": "^6.1.13",
|
||||||
"stylis": "^4.3.4",
|
"stylis": "^4.3.4",
|
||||||
"stylis-plugin-rtl": "^2.1.1",
|
"stylis-plugin-rtl": "^2.1.1",
|
||||||
|
"tabs": "^0.2.0",
|
||||||
"tailwind-merge": "^2.5.4",
|
"tailwind-merge": "^2.5.4",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"vite-plugin-windicss": "^1.9.3",
|
"vite-plugin-windicss": "^1.9.3",
|
||||||
@ -106,7 +107,6 @@
|
|||||||
"version": "5.2.0",
|
"version": "5.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
|
||||||
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
|
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
},
|
},
|
||||||
@ -1593,7 +1593,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"aix"
|
"aix"
|
||||||
@ -1609,7 +1608,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"android"
|
"android"
|
||||||
@ -1625,7 +1623,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"android"
|
"android"
|
||||||
@ -1641,7 +1638,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"android"
|
"android"
|
||||||
@ -1657,7 +1653,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
@ -1673,7 +1668,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
@ -1689,7 +1683,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"freebsd"
|
"freebsd"
|
||||||
@ -1705,7 +1698,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"freebsd"
|
"freebsd"
|
||||||
@ -1721,7 +1713,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -1737,7 +1728,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -1753,7 +1743,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -1769,7 +1758,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -1785,7 +1773,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"mips64el"
|
"mips64el"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -1801,7 +1788,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -1817,7 +1803,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -1833,7 +1818,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -1849,7 +1833,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -1865,7 +1848,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"netbsd"
|
"netbsd"
|
||||||
@ -1881,7 +1863,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"openbsd"
|
"openbsd"
|
||||||
@ -1897,7 +1878,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"sunos"
|
"sunos"
|
||||||
@ -1913,7 +1893,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
@ -1929,7 +1908,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
@ -1945,7 +1923,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
@ -2448,7 +2425,6 @@
|
|||||||
"version": "8.0.2",
|
"version": "8.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||||
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
|
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"string-width": "^5.1.2",
|
"string-width": "^5.1.2",
|
||||||
"string-width-cjs": "npm:string-width@^4.2.0",
|
"string-width-cjs": "npm:string-width@^4.2.0",
|
||||||
@ -2465,7 +2441,6 @@
|
|||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@ -2477,7 +2452,6 @@
|
|||||||
"version": "6.2.1",
|
"version": "6.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
@ -2488,14 +2462,12 @@
|
|||||||
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
|
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
|
||||||
"version": "9.2.2",
|
"version": "9.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/@isaacs/cliui/node_modules/string-width": {
|
"node_modules/@isaacs/cliui/node_modules/string-width": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
||||||
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"eastasianwidth": "^0.2.0",
|
"eastasianwidth": "^0.2.0",
|
||||||
"emoji-regex": "^9.2.2",
|
"emoji-regex": "^9.2.2",
|
||||||
@ -2512,7 +2484,6 @@
|
|||||||
"version": "7.1.0",
|
"version": "7.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
||||||
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-regex": "^6.0.1"
|
"ansi-regex": "^6.0.1"
|
||||||
},
|
},
|
||||||
@ -2527,7 +2498,6 @@
|
|||||||
"version": "8.1.0",
|
"version": "8.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
||||||
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": "^6.1.0",
|
"ansi-styles": "^6.1.0",
|
||||||
"string-width": "^5.0.1",
|
"string-width": "^5.0.1",
|
||||||
@ -2920,7 +2890,6 @@
|
|||||||
"version": "0.11.0",
|
"version": "0.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||||
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
|
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
@ -3939,7 +3908,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"android"
|
"android"
|
||||||
@ -3952,7 +3920,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"android"
|
"android"
|
||||||
@ -3965,7 +3932,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
@ -3978,7 +3944,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"darwin"
|
"darwin"
|
||||||
@ -3991,7 +3956,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"freebsd"
|
"freebsd"
|
||||||
@ -4004,7 +3968,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"freebsd"
|
"freebsd"
|
||||||
@ -4017,7 +3980,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -4030,7 +3992,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -4043,7 +4004,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -4056,7 +4016,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -4069,7 +4028,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -4082,7 +4040,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -4095,7 +4052,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -4108,7 +4064,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -4121,7 +4076,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"linux"
|
"linux"
|
||||||
@ -4134,7 +4088,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
@ -4147,7 +4100,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"ia32"
|
"ia32"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
@ -4160,7 +4112,6 @@
|
|||||||
"cpu": [
|
"cpu": [
|
||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
"win32"
|
"win32"
|
||||||
@ -4265,8 +4216,7 @@
|
|||||||
"node_modules/@types/estree": {
|
"node_modules/@types/estree": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
|
||||||
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
|
"integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/@types/geojson": {
|
"node_modules/@types/geojson": {
|
||||||
"version": "7946.0.14",
|
"version": "7946.0.14",
|
||||||
@ -4330,7 +4280,7 @@
|
|||||||
"version": "18.3.1",
|
"version": "18.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
|
||||||
"integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
|
"integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/react": "*"
|
"@types/react": "*"
|
||||||
}
|
}
|
||||||
@ -4668,14 +4618,12 @@
|
|||||||
"node_modules/any-promise": {
|
"node_modules/any-promise": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
|
||||||
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
|
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/anymatch": {
|
"node_modules/anymatch": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
|
||||||
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"normalize-path": "^3.0.0",
|
"normalize-path": "^3.0.0",
|
||||||
"picomatch": "^2.0.4"
|
"picomatch": "^2.0.4"
|
||||||
@ -4701,8 +4649,7 @@
|
|||||||
"node_modules/arg": {
|
"node_modules/arg": {
|
||||||
"version": "5.0.2",
|
"version": "5.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
|
||||||
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
|
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/argparse": {
|
"node_modules/argparse": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
@ -4803,7 +4750,6 @@
|
|||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
|
||||||
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
},
|
},
|
||||||
@ -4815,7 +4761,6 @@
|
|||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0"
|
"balanced-match": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -4907,7 +4852,6 @@
|
|||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
|
||||||
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
|
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
@ -4959,7 +4903,6 @@
|
|||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||||
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"anymatch": "~3.1.2",
|
"anymatch": "~3.1.2",
|
||||||
"braces": "~3.0.2",
|
"braces": "~3.0.2",
|
||||||
@ -4983,7 +4926,6 @@
|
|||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-glob": "^4.0.1"
|
"is-glob": "^4.0.1"
|
||||||
},
|
},
|
||||||
@ -5077,7 +5019,6 @@
|
|||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
|
||||||
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
|
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
@ -5111,7 +5052,6 @@
|
|||||||
"version": "7.0.6",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||||
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"path-key": "^3.1.0",
|
"path-key": "^3.1.0",
|
||||||
@ -5326,14 +5266,12 @@
|
|||||||
"node_modules/didyoumean": {
|
"node_modules/didyoumean": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
|
||||||
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
|
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/dlv": {
|
"node_modules/dlv": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
|
||||||
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
|
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/dom-helpers": {
|
"node_modules/dom-helpers": {
|
||||||
"version": "5.2.1",
|
"version": "5.2.1",
|
||||||
@ -5347,8 +5285,7 @@
|
|||||||
"node_modules/eastasianwidth": {
|
"node_modules/eastasianwidth": {
|
||||||
"version": "0.2.0",
|
"version": "0.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/electron-to-chromium": {
|
"node_modules/electron-to-chromium": {
|
||||||
"version": "1.5.48",
|
"version": "1.5.48",
|
||||||
@ -5391,7 +5328,6 @@
|
|||||||
"version": "0.21.5",
|
"version": "0.21.5",
|
||||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
|
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
|
||||||
"integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
|
"integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
|
||||||
"dev": true,
|
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"esbuild": "bin/esbuild"
|
"esbuild": "bin/esbuild"
|
||||||
@ -5853,7 +5789,6 @@
|
|||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
|
||||||
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
|
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cross-spawn": "^7.0.0",
|
"cross-spawn": "^7.0.0",
|
||||||
"signal-exit": "^4.0.1"
|
"signal-exit": "^4.0.1"
|
||||||
@ -5923,7 +5858,6 @@
|
|||||||
"version": "2.3.3",
|
"version": "2.3.3",
|
||||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
"dev": true,
|
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@ -6008,7 +5942,6 @@
|
|||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
|
||||||
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
|
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-glob": "^4.0.3"
|
"is-glob": "^4.0.3"
|
||||||
},
|
},
|
||||||
@ -6221,7 +6154,6 @@
|
|||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
|
||||||
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"binary-extensions": "^2.0.0"
|
"binary-extensions": "^2.0.0"
|
||||||
},
|
},
|
||||||
@ -6281,14 +6213,12 @@
|
|||||||
"node_modules/isexe": {
|
"node_modules/isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/jackspeak": {
|
"node_modules/jackspeak": {
|
||||||
"version": "3.4.3",
|
"version": "3.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
|
||||||
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
|
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@isaacs/cliui": "^8.0.2"
|
"@isaacs/cliui": "^8.0.2"
|
||||||
},
|
},
|
||||||
@ -6411,7 +6341,6 @@
|
|||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
|
||||||
"integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
|
"integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
@ -6563,7 +6492,6 @@
|
|||||||
"version": "9.0.5",
|
"version": "9.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
|
||||||
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"brace-expansion": "^2.0.1"
|
"brace-expansion": "^2.0.1"
|
||||||
},
|
},
|
||||||
@ -6578,7 +6506,6 @@
|
|||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
}
|
}
|
||||||
@ -6601,7 +6528,6 @@
|
|||||||
"version": "2.7.0",
|
"version": "2.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
|
||||||
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
|
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"any-promise": "^1.0.0",
|
"any-promise": "^1.0.0",
|
||||||
"object-assign": "^4.0.1",
|
"object-assign": "^4.0.1",
|
||||||
@ -6658,7 +6584,6 @@
|
|||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@ -6712,7 +6637,6 @@
|
|||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
|
||||||
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
|
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
@ -6791,8 +6715,7 @@
|
|||||||
"node_modules/package-json-from-dist": {
|
"node_modules/package-json-from-dist": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
||||||
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
|
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/parent-module": {
|
"node_modules/parent-module": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@ -6843,7 +6766,6 @@
|
|||||||
"version": "3.1.1",
|
"version": "3.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
@ -6857,7 +6779,6 @@
|
|||||||
"version": "1.11.1",
|
"version": "1.11.1",
|
||||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
|
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
|
||||||
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
|
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"lru-cache": "^10.2.0",
|
"lru-cache": "^10.2.0",
|
||||||
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
|
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||||
@ -6872,8 +6793,7 @@
|
|||||||
"node_modules/path-scurry/node_modules/lru-cache": {
|
"node_modules/path-scurry/node_modules/lru-cache": {
|
||||||
"version": "10.4.3",
|
"version": "10.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
|
||||||
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
|
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/path-type": {
|
"node_modules/path-type": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
@ -6903,7 +6823,6 @@
|
|||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||||
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
|
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
@ -6912,7 +6831,6 @@
|
|||||||
"version": "4.0.6",
|
"version": "4.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
|
||||||
"integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
|
"integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
@ -6921,7 +6839,6 @@
|
|||||||
"version": "8.4.49",
|
"version": "8.4.49",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
|
||||||
"integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
|
"integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@ -7299,7 +7216,6 @@
|
|||||||
"version": "15.1.0",
|
"version": "15.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
|
||||||
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
|
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"postcss-value-parser": "^4.0.0",
|
"postcss-value-parser": "^4.0.0",
|
||||||
"read-cache": "^1.0.0",
|
"read-cache": "^1.0.0",
|
||||||
@ -7316,7 +7232,6 @@
|
|||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
|
||||||
"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
|
"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"camelcase-css": "^2.0.1"
|
"camelcase-css": "^2.0.1"
|
||||||
},
|
},
|
||||||
@ -7363,7 +7278,6 @@
|
|||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
|
||||||
"integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
|
"integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@ -7398,7 +7312,6 @@
|
|||||||
"version": "3.1.2",
|
"version": "3.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
|
||||||
"integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
|
"integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
},
|
},
|
||||||
@ -7410,7 +7323,6 @@
|
|||||||
"version": "2.6.0",
|
"version": "2.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
|
||||||
"integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
|
"integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
|
||||||
"dev": true,
|
|
||||||
"bin": {
|
"bin": {
|
||||||
"yaml": "bin.mjs"
|
"yaml": "bin.mjs"
|
||||||
},
|
},
|
||||||
@ -7446,7 +7358,6 @@
|
|||||||
"version": "6.2.0",
|
"version": "6.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
|
||||||
"integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
|
"integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
@ -7471,7 +7382,6 @@
|
|||||||
"version": "6.1.2",
|
"version": "6.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
|
||||||
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
|
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cssesc": "^3.0.0",
|
"cssesc": "^3.0.0",
|
||||||
"util-deprecate": "^1.0.2"
|
"util-deprecate": "^1.0.2"
|
||||||
@ -8025,6 +7935,7 @@
|
|||||||
"version": "5.4.3",
|
"version": "5.4.3",
|
||||||
"resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.3.tgz",
|
"resolved": "https://registry.npmjs.org/react-number-format/-/react-number-format-5.4.3.tgz",
|
||||||
"integrity": "sha512-VCY5hFg/soBighAoGcdE+GagkJq0230qN6jcS5sp8wQX1qy1fYN/RX7/BXkrs0oyzzwqR8/+eSUrqXbGeywdUQ==",
|
"integrity": "sha512-VCY5hFg/soBighAoGcdE+GagkJq0230qN6jcS5sp8wQX1qy1fYN/RX7/BXkrs0oyzzwqR8/+eSUrqXbGeywdUQ==",
|
||||||
|
"license": "MIT",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
"react": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||||
"react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
"react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||||
@ -8188,7 +8099,6 @@
|
|||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
|
||||||
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
|
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"pify": "^2.3.0"
|
"pify": "^2.3.0"
|
||||||
}
|
}
|
||||||
@ -8197,7 +8107,6 @@
|
|||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
|
||||||
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"picomatch": "^2.2.1"
|
"picomatch": "^2.2.1"
|
||||||
},
|
},
|
||||||
@ -8275,7 +8184,6 @@
|
|||||||
"version": "4.24.2",
|
"version": "4.24.2",
|
||||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.2.tgz",
|
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.2.tgz",
|
||||||
"integrity": "sha512-do/DFGq5g6rdDhdpPq5qb2ecoczeK6y+2UAjdJ5trjQJj5f1AiVdLRWRc9A9/fFukfvJRgM0UXzxBIYMovm5ww==",
|
"integrity": "sha512-do/DFGq5g6rdDhdpPq5qb2ecoczeK6y+2UAjdJ5trjQJj5f1AiVdLRWRc9A9/fFukfvJRgM0UXzxBIYMovm5ww==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/estree": "1.0.6"
|
"@types/estree": "1.0.6"
|
||||||
},
|
},
|
||||||
@ -8375,7 +8283,6 @@
|
|||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"shebang-regex": "^3.0.0"
|
"shebang-regex": "^3.0.0"
|
||||||
},
|
},
|
||||||
@ -8387,7 +8294,6 @@
|
|||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
@ -8413,7 +8319,6 @@
|
|||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
},
|
},
|
||||||
@ -8464,7 +8369,6 @@
|
|||||||
"version": "4.2.3",
|
"version": "4.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"emoji-regex": "^8.0.0",
|
"emoji-regex": "^8.0.0",
|
||||||
"is-fullwidth-code-point": "^3.0.0",
|
"is-fullwidth-code-point": "^3.0.0",
|
||||||
@ -8490,7 +8394,6 @@
|
|||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-regex": "^5.0.1"
|
"ansi-regex": "^5.0.1"
|
||||||
},
|
},
|
||||||
@ -8617,7 +8520,6 @@
|
|||||||
"version": "3.35.0",
|
"version": "3.35.0",
|
||||||
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
|
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
|
||||||
"integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
|
"integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/gen-mapping": "^0.3.2",
|
"@jridgewell/gen-mapping": "^0.3.2",
|
||||||
"commander": "^4.0.0",
|
"commander": "^4.0.0",
|
||||||
@ -8639,7 +8541,6 @@
|
|||||||
"version": "10.4.5",
|
"version": "10.4.5",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
||||||
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
|
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"foreground-child": "^3.1.0",
|
"foreground-child": "^3.1.0",
|
||||||
"jackspeak": "^3.1.2",
|
"jackspeak": "^3.1.2",
|
||||||
@ -8777,6 +8678,12 @@
|
|||||||
"url": "https://opencollective.com/unts"
|
"url": "https://opencollective.com/unts"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tabs": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tabs/-/tabs-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-q6mo8KWq/Zi+zGR3ZvGq6S6ckc3JNbGRGtAwIhtnp2GlS1goTqFnWX3MkyDKYSQuzwBqBAy2fYGHQI+3HMnXZQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/tailwind-merge": {
|
"node_modules/tailwind-merge": {
|
||||||
"version": "2.5.4",
|
"version": "2.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz",
|
||||||
@ -8790,7 +8697,6 @@
|
|||||||
"version": "3.4.14",
|
"version": "3.4.14",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz",
|
||||||
"integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==",
|
"integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alloc/quick-lru": "^5.2.0",
|
"@alloc/quick-lru": "^5.2.0",
|
||||||
"arg": "^5.0.2",
|
"arg": "^5.0.2",
|
||||||
@ -8835,7 +8741,6 @@
|
|||||||
"version": "6.1.2",
|
"version": "6.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
|
||||||
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
|
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"cssesc": "^3.0.0",
|
"cssesc": "^3.0.0",
|
||||||
"util-deprecate": "^1.0.2"
|
"util-deprecate": "^1.0.2"
|
||||||
@ -8854,7 +8759,6 @@
|
|||||||
"version": "3.3.1",
|
"version": "3.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
|
||||||
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
|
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"any-promise": "^1.0.0"
|
"any-promise": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -8863,7 +8767,6 @@
|
|||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
|
||||||
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
|
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"thenify": ">= 3.1.0 < 4"
|
"thenify": ">= 3.1.0 < 4"
|
||||||
},
|
},
|
||||||
@ -8912,8 +8815,7 @@
|
|||||||
"node_modules/ts-interface-checker": {
|
"node_modules/ts-interface-checker": {
|
||||||
"version": "0.1.13",
|
"version": "0.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
|
||||||
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
|
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/tslib": {
|
"node_modules/tslib": {
|
||||||
"version": "2.8.0",
|
"version": "2.8.0",
|
||||||
@ -8947,7 +8849,7 @@
|
|||||||
"version": "5.6.3",
|
"version": "5.6.3",
|
||||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
|
||||||
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
|
"integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
|
||||||
"dev": true,
|
"devOptional": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
@ -9089,7 +8991,6 @@
|
|||||||
"version": "5.4.11",
|
"version": "5.4.11",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz",
|
||||||
"integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==",
|
"integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.21.3",
|
"esbuild": "^0.21.3",
|
||||||
"postcss": "^8.4.43",
|
"postcss": "^8.4.43",
|
||||||
@ -9165,7 +9066,6 @@
|
|||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"isexe": "^2.0.0"
|
"isexe": "^2.0.0"
|
||||||
},
|
},
|
||||||
@ -9217,7 +9117,6 @@
|
|||||||
"version": "7.0.0",
|
"version": "7.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": "^4.0.0",
|
"ansi-styles": "^4.0.0",
|
||||||
"string-width": "^4.1.0",
|
"string-width": "^4.1.0",
|
||||||
|
|||||||
@ -77,6 +77,7 @@
|
|||||||
"styled-components": "^6.1.13",
|
"styled-components": "^6.1.13",
|
||||||
"stylis": "^4.3.4",
|
"stylis": "^4.3.4",
|
||||||
"stylis-plugin-rtl": "^2.1.1",
|
"stylis-plugin-rtl": "^2.1.1",
|
||||||
|
"tabs": "^0.2.0",
|
||||||
"tailwind-merge": "^2.5.4",
|
"tailwind-merge": "^2.5.4",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"vite-plugin-windicss": "^1.9.3",
|
"vite-plugin-windicss": "^1.9.3",
|
||||||
|
|||||||
@ -181,6 +181,7 @@ export const DataGridProvider = <TData extends object>(props: TDataGridProps<TDa
|
|||||||
reload: loadData
|
reload: loadData
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
{loading && <div className="fixed inset-0 flex items-center justify-center z-50"></div>}
|
||||||
{props.children ? props.children : <DataGridInner />}
|
{props.children ? props.children : <DataGridInner />}
|
||||||
</DataGridContext.Provider>
|
</DataGridContext.Provider>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -5,10 +5,10 @@ export const DataGridLoader = () => {
|
|||||||
const { props } = useDataGrid();
|
const { props } = useDataGrid();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
|
<div className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 flex items-center gap-6 min-w-[160px] bg-card text-muted-foreground px-4 py-2 font-medium leading-none text-sm border shadow-sm rounded-md">
|
||||||
<div className="text-muted-foreground bg-card flex items-center gap-2 px-4 py-2 font-medium leading-none text-sm border shadow-sm rounded-md">
|
<div className="text-muted-foreground bg-card flex items-center gap-2 px-4 py-2 font-medium leading-none text-sm border shadow-sm rounded-md">
|
||||||
<svg
|
<svg
|
||||||
className="animate-spin -ml-1 h-5 w-5 text-muted-foreground"
|
className="animate-spin -ml-1 h-5 w-5 text-muted-foreground flex-shrink-0"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
fill="none"
|
fill="none"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
|
|||||||
@ -1,6 +1,12 @@
|
|||||||
import { Container, DataGridInner } from '@/components';
|
import { Container, DataGridInner } from '@/components';
|
||||||
import { ManageConversionContextProvider } from './hooks/ManageConversionContext';
|
import { ManageConversionContextProvider } from './hooks/ManageConversionContext';
|
||||||
import { Breadcrumbs, Link } from '@mui/material';
|
import { Breadcrumbs, Link } from '@mui/material';
|
||||||
|
import AddDialog from './blocks/AddDialog';
|
||||||
|
import EditDialog from './blocks/EditDialog';
|
||||||
|
import { Delete } from 'lucide-react';
|
||||||
|
import DeleteDialog from './blocks/DeleteDialog';
|
||||||
|
|
||||||
|
// import EditDialog from './blocks/EditDialog';
|
||||||
|
|
||||||
const ConversionMaster = () => {
|
const ConversionMaster = () => {
|
||||||
return (
|
return (
|
||||||
@ -24,6 +30,10 @@ const ConversionMaster = () => {
|
|||||||
<div className="grid gap-5 lg:gap-7.5">
|
<div className="grid gap-5 lg:gap-7.5">
|
||||||
<DataGridInner />
|
<DataGridInner />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<AddDialog />
|
||||||
|
<EditDialog/>
|
||||||
|
<DeleteDialog/>
|
||||||
</Container>
|
</Container>
|
||||||
</ManageConversionContextProvider>
|
</ManageConversionContextProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -0,0 +1,287 @@
|
|||||||
|
import { apiConfig } from '@/config/api.config';
|
||||||
|
import { Alert, useDataGrid } from '@/components';
|
||||||
|
import { useCallApi } from '@/hooks';
|
||||||
|
import { getAuth } from '@/auth';
|
||||||
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
import { toast } from 'sonner';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogBody,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { NumericFormat } from 'react-number-format';
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandInput,
|
||||||
|
CommandItem,
|
||||||
|
CommandList
|
||||||
|
} from '@/components/ui/command';
|
||||||
|
import { set } from 'date-fns';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
import { useManageConversionContext } from '../hooks/useManageConversionContext';
|
||||||
|
interface CurrencyProps {
|
||||||
|
ID: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const API_URL = apiConfig.service_wallet;
|
||||||
|
|
||||||
|
const AddDialog = () => {
|
||||||
|
const parentRef = useRef<any | null>(null);
|
||||||
|
const { showAddDialog, handleAddDialog, selectedConversion } = useManageConversionContext();
|
||||||
|
const { reload } = useDataGrid();
|
||||||
|
const { PostData, GetData } = useCallApi();
|
||||||
|
const parsedUser = getAuth()?.user;
|
||||||
|
const [currencies, setCurrencies] = useState<CurrencyProps[]>([]);
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [alert, setAlert] = useState({
|
||||||
|
show: false,
|
||||||
|
message: ''
|
||||||
|
});
|
||||||
|
const initialState = {
|
||||||
|
status: '',
|
||||||
|
id_currency_origin: '',
|
||||||
|
id_currency_destination: '',
|
||||||
|
buy: 0,
|
||||||
|
sell: 0,
|
||||||
|
created_by: '',
|
||||||
|
created_at: ''
|
||||||
|
};
|
||||||
|
const [formField, setFormField] = useState(initialState);
|
||||||
|
const created_time = new Date();
|
||||||
|
const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' ');
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
setFormField(initialState);
|
||||||
|
setAlert({ show: false, message: '' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const doCreateConversion = useCallback(
|
||||||
|
async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const response = await PostData(`${API_URL}/dashboard/conversion`, formField);
|
||||||
|
|
||||||
|
if (response?.status) {
|
||||||
|
resetForm();
|
||||||
|
handleAddDialog(false);
|
||||||
|
toast.success('Success Create Conversion');
|
||||||
|
reload();
|
||||||
|
} else {
|
||||||
|
toast.error('Error Create Conversion');
|
||||||
|
setAlert({ show: true, message: 'Failed to create Conversion. Please try again.' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[formField]
|
||||||
|
);
|
||||||
|
|
||||||
|
const doFetchCurrency = async (sorting: any) => {
|
||||||
|
try {
|
||||||
|
sorting = sorting.length == 0 ? [{ id: 'name', desc: false }] : sorting;
|
||||||
|
const response = await GetData(`${API_URL}/dashboard/currency/`, {
|
||||||
|
limit: 1000,
|
||||||
|
page: 1,
|
||||||
|
with_deleted: false,
|
||||||
|
order_field: sorting[0].id,
|
||||||
|
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC'
|
||||||
|
});
|
||||||
|
|
||||||
|
setCurrencies(response?.data.list);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching currency', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (
|
||||||
|
formField.id_currency_origin === '' ||
|
||||||
|
formField.id_currency_destination === '' ||
|
||||||
|
formField.buy === 0 ||
|
||||||
|
formField.sell === 0 ||
|
||||||
|
formField.status === ''
|
||||||
|
) {
|
||||||
|
setAlert({ show: true, message: 'Please fill in all required fields.' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
doCreateConversion(e);
|
||||||
|
console.log(formField);
|
||||||
|
setAlert({ show: false, message: '' });
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showAddDialog) {
|
||||||
|
setFormField({
|
||||||
|
...formField,
|
||||||
|
created_by: parsedUser.username,
|
||||||
|
created_at: formattedTime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [formattedTime]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
doFetchCurrency([{ id: 'name', desc: false }]);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showAddDialog === false) {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
}, [showAddDialog]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={showAddDialog} onOpenChange={(open) => handleAddDialog(open)}>
|
||||||
|
<DialogContent className="container-fixed max-w-[768px] flex flex-col p-5 overflow-hidden">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Conversion - Create</DialogTitle>
|
||||||
|
<DialogDescription></DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogBody ref={parentRef}>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{alert.show && (
|
||||||
|
<Alert variant="danger">
|
||||||
|
<h3>{alert.message}</h3>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="card-body grid gap-5">
|
||||||
|
<div className="w-full">
|
||||||
|
<label className="form-label">
|
||||||
|
Currency Origin <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<Select
|
||||||
|
value={formField.id_currency_origin}
|
||||||
|
onValueChange={(id_currency_origin) =>
|
||||||
|
setFormField((prev) => ({ ...prev, id_currency_origin }))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select Currency" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{currencies.map((currency, idx) => (
|
||||||
|
<SelectItem value={currency.ID} key={currency.ID}>
|
||||||
|
{currency.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="w-full">
|
||||||
|
<label className="form-label">
|
||||||
|
Currency Destination <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<Select
|
||||||
|
value={formField.id_currency_destination}
|
||||||
|
onValueChange={(id_currency_destination) =>
|
||||||
|
setFormField((prev) => ({ ...prev, id_currency_destination }))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select Currency" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{currencies.map((currency, idx) => (
|
||||||
|
<SelectItem value={currency.ID} key={currency.ID}>
|
||||||
|
{currency.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="w-full">
|
||||||
|
<label className="form-label">
|
||||||
|
Buy<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<NumericFormat
|
||||||
|
className="input"
|
||||||
|
value={formField.buy}
|
||||||
|
thousandSeparator="."
|
||||||
|
decimalSeparator=","
|
||||||
|
allowNegative={false}
|
||||||
|
onValueChange={(values) => {
|
||||||
|
setFormField((prev) => ({
|
||||||
|
...prev,
|
||||||
|
buy: values.floatValue || 0
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
placeholder="Enter Buy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-full">
|
||||||
|
<label className="form-label">
|
||||||
|
Sell
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<NumericFormat
|
||||||
|
className="input"
|
||||||
|
value={formField.sell}
|
||||||
|
thousandSeparator="."
|
||||||
|
decimalSeparator=","
|
||||||
|
allowNegative={false}
|
||||||
|
onValueChange={(values) => {
|
||||||
|
setFormField((prev) => ({
|
||||||
|
...prev,
|
||||||
|
sell: values.floatValue || 0
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
placeholder="Enter Sell"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-full">
|
||||||
|
<label className="form-label">
|
||||||
|
Status
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div className="grow">
|
||||||
|
<Select
|
||||||
|
value={formField.status}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
setFormField((prev) => ({ ...prev, status: value }))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="Y">Active</SelectItem>
|
||||||
|
<SelectItem value="N">Inactive</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-end gap-5">
|
||||||
|
<Button type="button" variant="outline" onClick={resetForm}>
|
||||||
|
Reset
|
||||||
|
</Button>
|
||||||
|
<Button variant="default">Save Changes</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</DialogBody>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddDialog;
|
||||||
|
|||||||
79
src/pages/master/conversion/blocks/DeleteDialog.tsx
Normal file
79
src/pages/master/conversion/blocks/DeleteDialog.tsx
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
import { Alert, useDataGrid } from '@/components';
|
||||||
|
import { useManageConversionContext } from '../hooks/useManageConversionContext';
|
||||||
|
import { useCallback, useState } from 'react';
|
||||||
|
import { apiConfig } from '@/config/api.config';
|
||||||
|
import { useCallApi } from '@/hooks';
|
||||||
|
import { toast } from 'sonner';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { DialogDescription } from '@radix-ui/react-dialog';
|
||||||
|
|
||||||
|
const API_URL = apiConfig.service_wallet;
|
||||||
|
|
||||||
|
const DeleteDialog = () => {
|
||||||
|
const { showDeleteDialog, handleDeleteDialog, selectedConversion } = useManageConversionContext();
|
||||||
|
const { reload } = useDataGrid();
|
||||||
|
const { DeleteData } = useCallApi();
|
||||||
|
const [alert, setAlert] = useState({
|
||||||
|
show: false,
|
||||||
|
message: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const doDeleteConversion = useCallback(async () => {
|
||||||
|
if (!selectedConversion) {
|
||||||
|
toast.error('No Conversion selected');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log(selectedConversion);
|
||||||
|
const response = await DeleteData(
|
||||||
|
`${API_URL}/dashboard/conversion/${selectedConversion}`,
|
||||||
|
{ id: selectedConversion }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response?.status) {
|
||||||
|
setAlert({ show: false, message: '' });
|
||||||
|
handleDeleteDialog(false, null);
|
||||||
|
toast.success('Success Delete Conversion');
|
||||||
|
reload();
|
||||||
|
} else {
|
||||||
|
setAlert({ show: true, message: response?.message });
|
||||||
|
toast.error('Failed Delete Conversion');
|
||||||
|
}
|
||||||
|
}, [selectedConversion, DeleteData, handleDeleteDialog, reload]);
|
||||||
|
console.log(selectedConversion);
|
||||||
|
return (
|
||||||
|
<Dialog open={showDeleteDialog} onOpenChange={(open) => handleDeleteDialog(open, null)}>
|
||||||
|
<DialogContent className="container-fixed max-w-md flex flex-col p-5 overflow-hidden [&>button]:hidden">
|
||||||
|
<DialogHeader className="p-0 border-0 block">
|
||||||
|
<DialogTitle></DialogTitle>
|
||||||
|
<DialogDescription></DialogDescription>
|
||||||
|
<Alert variant="warning">
|
||||||
|
<h3 className="text-lg">Are you sure?</h3>
|
||||||
|
<span className="text-sm">You will delete this data!</span>
|
||||||
|
</Alert>
|
||||||
|
{alert.show && (
|
||||||
|
<Alert variant="danger">
|
||||||
|
<h3>{alert.message}</h3>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogFooter className="flex justify-end items-center gap-4 mt-3">
|
||||||
|
<Button variant="outline" onClick={() => handleDeleteDialog(false, null)}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button variant="destructive" onClick={doDeleteConversion}>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeleteDialog;
|
||||||
299
src/pages/master/conversion/blocks/EditDialog.tsx
Normal file
299
src/pages/master/conversion/blocks/EditDialog.tsx
Normal file
@ -0,0 +1,299 @@
|
|||||||
|
import { apiConfig } from '@/config/api.config';
|
||||||
|
import { Alert, useDataGrid } from '@/components';
|
||||||
|
import { useCallApi } from '@/hooks';
|
||||||
|
import { getAuth } from '@/auth';
|
||||||
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
|
import { toast } from 'sonner';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogBody,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { NumericFormat } from 'react-number-format';
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
|
||||||
|
import {
|
||||||
|
Command,
|
||||||
|
CommandEmpty,
|
||||||
|
CommandGroup,
|
||||||
|
CommandInput,
|
||||||
|
CommandItem,
|
||||||
|
CommandList
|
||||||
|
} from '@/components/ui/command';
|
||||||
|
import { set } from 'date-fns';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
import { useManageConversionContext } from '../hooks/useManageConversionContext';
|
||||||
|
interface CurrencyProps {
|
||||||
|
ID: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const API_URL = apiConfig.service_wallet;
|
||||||
|
|
||||||
|
const EditDialog = () => {
|
||||||
|
const parentRef = useRef<any | null>(null);
|
||||||
|
const { showEditDialog, handleEditDialog, selectedConversion } = useManageConversionContext();
|
||||||
|
const { reload } = useDataGrid();
|
||||||
|
const { PostData, GetData, PutData } = useCallApi();
|
||||||
|
const parsedUser = getAuth()?.user;
|
||||||
|
const [currencies, setCurrencies] = useState<CurrencyProps[]>([]);
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const [alert, setAlert] = useState({
|
||||||
|
show: false,
|
||||||
|
message: ''
|
||||||
|
});
|
||||||
|
const initialState = {
|
||||||
|
status: '',
|
||||||
|
id_currency_origin: '',
|
||||||
|
id_currency_destination: '',
|
||||||
|
buy: 0,
|
||||||
|
sell: 0,
|
||||||
|
created_by: '',
|
||||||
|
created_at: ''
|
||||||
|
};
|
||||||
|
const [formField, setFormField] = useState(initialState);
|
||||||
|
const updated_time = new Date();
|
||||||
|
const formattedTime = updated_time.toISOString().slice(0, 19).replace('T', ' ');
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
setFormField(initialState);
|
||||||
|
setAlert({ show: false, message: '' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const doUpdateConversion = useCallback(
|
||||||
|
async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if(!showEditDialog) return;
|
||||||
|
const response = await PutData(`${API_URL}/dashboard/conversion/${selectedConversion}`,{
|
||||||
|
...formField
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response?.status) {
|
||||||
|
resetForm();
|
||||||
|
handleEditDialog(false, null);
|
||||||
|
toast.success('Success Update Conversion');
|
||||||
|
reload();
|
||||||
|
} else {
|
||||||
|
toast.error('Error Create Conversion');
|
||||||
|
setAlert({ show: true, message: 'Failed to Update Conversion. Please try again.' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[formField]
|
||||||
|
);
|
||||||
|
|
||||||
|
const doGetCurrency = async (sorting: any) => {
|
||||||
|
if (!showEditDialog)return;
|
||||||
|
try {
|
||||||
|
sorting = sorting.length == 0 ? [{ id: 'name', desc: false }] : sorting;
|
||||||
|
const response = await GetData(`${API_URL}/dashboard/currency/`, {
|
||||||
|
limit: 1000,
|
||||||
|
page: 1,
|
||||||
|
with_deleted: false,
|
||||||
|
order_field: sorting[0].id,
|
||||||
|
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC'
|
||||||
|
});
|
||||||
|
|
||||||
|
setCurrencies(response?.data.list);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching currency', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const doGetConversionById = useCallback(async (id: string) => {
|
||||||
|
const response = await GetData(`${API_URL}/dashboard/conversion/${id}`, { id });
|
||||||
|
console.log('Transaction Type: ', response?.data);
|
||||||
|
if (response?.status) {
|
||||||
|
setFormField((prev) => ({
|
||||||
|
...prev,
|
||||||
|
status: response.data.status,
|
||||||
|
id_currency_origin: response.data.id_currency_origin,
|
||||||
|
id_currency_destination: response.data.id_currency_destination,
|
||||||
|
buy: response.data.buy,
|
||||||
|
sell: response.data.sell,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
// console.log('form fieldd Transaction Type: ', formField);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedConversion) {
|
||||||
|
doGetConversionById(selectedConversion);
|
||||||
|
}
|
||||||
|
}, [selectedConversion]);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showEditDialog) {
|
||||||
|
setFormField({
|
||||||
|
...formField,
|
||||||
|
created_by: parsedUser.username,
|
||||||
|
created_at: formattedTime
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [formattedTime]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showEditDialog) {
|
||||||
|
doGetCurrency([{ id: 'name', desc: false }]);
|
||||||
|
}
|
||||||
|
}, [showEditDialog]);
|
||||||
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showEditDialog === false) {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
}, [showEditDialog]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={showEditDialog} onOpenChange={(open) => handleEditDialog(open,null)}>
|
||||||
|
<DialogContent className="container-fixed max-w-[768px] flex flex-col p-5 overflow-hidden">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Conversion - Update</DialogTitle>
|
||||||
|
<DialogDescription></DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogBody ref={parentRef}>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{alert.show && (
|
||||||
|
<Alert variant="danger">
|
||||||
|
<h3>{alert.message}</h3>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<form onSubmit={doUpdateConversion}>
|
||||||
|
<div className="card-body grid gap-5">
|
||||||
|
<div className="w-full">
|
||||||
|
<label className="form-label">
|
||||||
|
Currency Origin <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<Select
|
||||||
|
value={formField.id_currency_origin}
|
||||||
|
onValueChange={(id_currency_origin) =>
|
||||||
|
setFormField((prev) => ({ ...prev, id_currency_origin }))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select Currency" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{currencies.map((currency, idx) => (
|
||||||
|
<SelectItem value={currency.ID} key={currency.ID}>
|
||||||
|
{currency.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="w-full">
|
||||||
|
<label className="form-label">
|
||||||
|
Currency Destination <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<Select
|
||||||
|
value={formField.id_currency_destination}
|
||||||
|
onValueChange={(id_currency_destination) =>
|
||||||
|
setFormField((prev) => ({ ...prev, id_currency_destination }))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select Currency" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{currencies.map((currency, idx) => (
|
||||||
|
<SelectItem value={currency.ID} key={currency.ID}>
|
||||||
|
{currency.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="w-full">
|
||||||
|
<label className="form-label">
|
||||||
|
Buy<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<NumericFormat
|
||||||
|
className="input"
|
||||||
|
value={formField.buy}
|
||||||
|
thousandSeparator="."
|
||||||
|
decimalSeparator=","
|
||||||
|
allowNegative={false}
|
||||||
|
onValueChange={(values) => {
|
||||||
|
setFormField((prev) => ({
|
||||||
|
...prev,
|
||||||
|
buy: values.floatValue || 0
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
placeholder="Enter Buy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-full">
|
||||||
|
<label className="form-label">
|
||||||
|
Sell
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<NumericFormat
|
||||||
|
className="input"
|
||||||
|
value={formField.sell}
|
||||||
|
thousandSeparator="."
|
||||||
|
decimalSeparator=","
|
||||||
|
allowNegative={false}
|
||||||
|
onValueChange={(values) => {
|
||||||
|
setFormField((prev) => ({
|
||||||
|
...prev,
|
||||||
|
sell: values.floatValue || 0
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
placeholder="Enter Sell"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-full">
|
||||||
|
<label className="form-label">
|
||||||
|
Status
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div className="grow">
|
||||||
|
<Select
|
||||||
|
value={formField.status}
|
||||||
|
onValueChange={(value) =>
|
||||||
|
setFormField((prev) => ({ ...prev, status: value }))
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="Y">Active</SelectItem>
|
||||||
|
<SelectItem value="N">Inactive</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-end gap-5">
|
||||||
|
<Button type="button" variant="outline" onClick={resetForm}>
|
||||||
|
Reset
|
||||||
|
</Button>
|
||||||
|
<Button variant="default">Save Changes</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</DialogBody>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditDialog;
|
||||||
@ -11,7 +11,7 @@ const ListToolbar = () => {
|
|||||||
<div className="flex flex-wrap gap-2 lg:gap-5 w-full">
|
<div className="flex flex-wrap gap-2 lg:gap-5 w-full">
|
||||||
<div className="flex justify-between w-full items-center">
|
<div className="flex justify-between w-full items-center">
|
||||||
<div className="flex w-[50%] gap-3 items-center">
|
<div className="flex w-[50%] gap-3 items-center">
|
||||||
<label className="input input-sm w-1/3">
|
{/* <label className="input input-sm w-1/3">
|
||||||
<KeenIcon icon="magnifier" />
|
<KeenIcon icon="magnifier" />
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@ -19,7 +19,7 @@ const ListToolbar = () => {
|
|||||||
value={(table.getColumn('name')?.getFilterValue() as string) ?? ''}
|
value={(table.getColumn('name')?.getFilterValue() as string) ?? ''}
|
||||||
onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)}
|
onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label> */}
|
||||||
{/* <DefaultTooltip title={'Filter'} placement={'top'}>
|
{/* <DefaultTooltip title={'Filter'} placement={'top'}>
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
|
|||||||
@ -3,79 +3,123 @@ import { Toaster } from '@/components/ui/sonner';
|
|||||||
import { apiConfig } from '@/config/api.config';
|
import { apiConfig } from '@/config/api.config';
|
||||||
import { useCallApi } from '@/hooks';
|
import { useCallApi } from '@/hooks';
|
||||||
import { ColumnDef } from '@tanstack/react-table';
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
import { createContext, useCallback, useMemo, useState } from 'react';
|
import { createContext, useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import ListToolbar from '../blocks/ListToolbar';
|
import ListToolbar from '../blocks/ListToolbar';
|
||||||
|
|
||||||
interface ConversionProps {
|
interface CurrencyProps {
|
||||||
id: string;
|
ID: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface Conversion {
|
||||||
|
id: string;
|
||||||
|
id_currency_origin: string;
|
||||||
|
id_currency_destination: string;
|
||||||
|
buy: number;
|
||||||
|
sell: number;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
interface ContextProps {
|
interface ContextProps {
|
||||||
conversion: ConversionProps[];
|
|
||||||
showAddDialog: boolean;
|
|
||||||
handleAddDialog: (show: boolean) => void;
|
|
||||||
showEditDialog: boolean;
|
showEditDialog: boolean;
|
||||||
handleEditDialog: (show: boolean, selected_conversion: string | null) => void;
|
handleEditDialog: (show: boolean, selected_conversion: string | null) => void;
|
||||||
|
showAddDialog: boolean;
|
||||||
|
handleAddDialog: (show: boolean) => void;
|
||||||
showDeleteDialog: boolean;
|
showDeleteDialog: boolean;
|
||||||
handleDeleteDialog: (show: boolean, selected_conversion: string | null) => void;
|
handleDeleteDialog: (show: boolean, selected_conversion: string | null) => void;
|
||||||
selectedConversion: string | null;
|
selectedConversion: string | null;
|
||||||
getConversionLists: (
|
conversion: string | null;
|
||||||
limit: number,
|
|
||||||
page: number,
|
|
||||||
with_deleted: boolean,
|
|
||||||
order_field: any,
|
|
||||||
order_direction: any
|
|
||||||
) => Promise<{ data: ConversionProps[]; totalCount: number } | undefined>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialProps: ContextProps = {
|
const initialProps: ContextProps = {
|
||||||
conversion: [],
|
|
||||||
showAddDialog: false,
|
|
||||||
handleAddDialog: () => {},
|
|
||||||
showEditDialog: false,
|
showEditDialog: false,
|
||||||
handleEditDialog: () => {},
|
handleEditDialog: () => {},
|
||||||
|
showAddDialog: false,
|
||||||
|
handleAddDialog: () => {},
|
||||||
showDeleteDialog: false,
|
showDeleteDialog: false,
|
||||||
handleDeleteDialog: () => {},
|
handleDeleteDialog: () => {},
|
||||||
selectedConversion: null,
|
selectedConversion: null,
|
||||||
getConversionLists: async () => undefined
|
conversion: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ManageConversionContext = createContext<ContextProps>(initialProps);
|
const ManageConversionContext = createContext<ContextProps>(initialProps);
|
||||||
const API_URL_WALLET = apiConfig.service_wallet;
|
const API_URL = apiConfig.service_wallet;
|
||||||
|
|
||||||
const ManageConversionContextProvider = ({ children }: { children: React.ReactNode }) => {
|
const ManageConversionContextProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
const [conversions, setConversions] = useState<ConversionProps[]>([]);
|
|
||||||
const [showAddDialog, setShowAddDialog] = useState(false);
|
|
||||||
const [showEditDialog, setShowEditDialog] = useState(false);
|
const [showEditDialog, setShowEditDialog] = useState(false);
|
||||||
|
const [showAddDialog, setShowAddDialog] = useState(false);
|
||||||
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
||||||
const [selectedConversion, setSelectedConversion] = useState<string | null>(null);
|
|
||||||
const { GetData } = useCallApi();
|
const { GetData } = useCallApi();
|
||||||
|
const [selectedConversion, setSelectedConversion] = useState<string | null>(null);
|
||||||
|
const [conversion, setConversion] = useState<string | null>(null);
|
||||||
|
|
||||||
|
const handleEditDialog = useCallback((show: boolean, selected_conversion: string | null) => {
|
||||||
|
setSelectedConversion(show ? selected_conversion : null);
|
||||||
|
setShowEditDialog(show);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleAddDialog = useCallback((show: boolean) => {
|
const handleAddDialog = useCallback((show: boolean) => {
|
||||||
setShowAddDialog(show);
|
setShowAddDialog(show);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleEditDialog = useCallback((show: boolean, selected_conversion: string | null) => {
|
|
||||||
setShowEditDialog(show);
|
|
||||||
setSelectedConversion(show ? selected_conversion : null);
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const handleDeleteDialog = useCallback((show: boolean, selected_conversion: string | null) => {
|
const handleDeleteDialog = useCallback((show: boolean, selected_conversion: string | null) => {
|
||||||
setShowEditDialog(show);
|
setShowDeleteDialog(show);
|
||||||
setSelectedConversion(show ? selected_conversion : null);
|
setSelectedConversion(show ? selected_conversion : null);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const columns = useMemo<ColumnDef<any>[]>(
|
const columns = useMemo<ColumnDef<any>[]>(
|
||||||
() => [
|
() => [
|
||||||
{
|
{
|
||||||
accessorFn: (row) => row.name,
|
accessorFn: (row) => row.currency_origin.name,
|
||||||
id: 'name',
|
id: 'id_currency_origin',
|
||||||
header: ({ column }) => <DataGridColumnHeader title="Name" column={column} />,
|
header: ({ column }) => <DataGridColumnHeader title="Currency Origin" column={column} />,
|
||||||
enableSorting: true,
|
enableSorting: true,
|
||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
meta: {
|
meta: { headerClassName: 'w-[150px]' }
|
||||||
headerClassName: 'w-[250px]'
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.currency_destination.name,
|
||||||
|
id: 'id_currency_destination',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Currency Destination" column={column} />,
|
||||||
|
enableSorting: true,
|
||||||
|
enableHiding: false,
|
||||||
|
meta: { headerClassName: 'w-[150px]' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.buy,
|
||||||
|
id: 'buy',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Buy" column={column} />,
|
||||||
|
enableSorting: true,
|
||||||
|
enableHiding: false,
|
||||||
|
meta: { headerClassName: 'w-[150px]' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.sell,
|
||||||
|
id: 'sell',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Sell" column={column} />,
|
||||||
|
enableSorting: true,
|
||||||
|
enableHiding: false,
|
||||||
|
meta: { headerClassName: 'w-[150px]' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.status,
|
||||||
|
id: 'status',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Status" column={column} />,
|
||||||
|
enableSorting: true,
|
||||||
|
enableHiding: false,
|
||||||
|
meta: { headerClassName: 'w-[150px]' },
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const isActive = row.original.status === 'Y';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={`px-2 py-1 text-xs font-semibold rounded-full ${
|
||||||
|
isActive ? 'bg-green-100 text-green-600' : 'bg-red-100 text-red-600'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{isActive ? 'Active' : 'Inactive'}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -89,79 +133,80 @@ const ManageConversionContextProvider = ({ children }: { children: React.ReactNo
|
|||||||
<>
|
<>
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-icon btn-clear btn-light"
|
className="btn btn-sm btn-icon btn-clear btn-light"
|
||||||
onClick={() => handleEditDialog(true, row.id)}
|
onClick={() => handleEditDialog(true, row.ID)}
|
||||||
>
|
>
|
||||||
<KeenIcon icon="notepad-edit" />
|
<KeenIcon icon="notepad-edit" />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-icon btn-clear btn-light"
|
className="btn btn-sm btn-icon btn-clear btn-light"
|
||||||
onClick={() => handleDeleteDialog(true, row.id)}
|
onClick={() => handleDeleteDialog(true, row.ID)}
|
||||||
>
|
>
|
||||||
<KeenIcon icon="trash" />
|
<KeenIcon icon="trash" />
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
meta: {
|
meta: { headerClassName: 'w-[100px]', cellClassName: 'text-center' }
|
||||||
headerClassName: 'w-[100px]',
|
|
||||||
cellClassName: 'text-center'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
[]
|
[handleEditDialog, handleDeleteDialog]
|
||||||
);
|
);
|
||||||
|
const doGetConversion = async (
|
||||||
const getConversionLists = async (page: number, limit: number, sorting: any, filter: any) => {
|
page: number,
|
||||||
try {
|
limit: number,
|
||||||
sorting = sorting.length == 0 ? [{ id: 'name', desc: false }] : sorting;
|
sorting: any,
|
||||||
filter = filter.length == 0 ? {} : { any: filter[0].value?.toLowerCase() };
|
filter: any
|
||||||
const response = await GetData(`${API_URL_WALLET}/dashboard/conversion`, {
|
) => {
|
||||||
limit,
|
sorting = sorting.length == 0 ? [{ id: 'name', desc: true }] : sorting;
|
||||||
page: page + 1,
|
filter = filter.length == 0 ? {} : { any: filter[0].value?.toLowerCase() };
|
||||||
with_deleted: false,
|
console.log(sorting);
|
||||||
order_field: sorting[0].id,
|
const response = await GetData(`${API_URL}/dashboard/conversion/`, {
|
||||||
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC',
|
limit: limit,
|
||||||
filter: JSON.stringify(filter)
|
page: page + 1,
|
||||||
});
|
with_deleted: false,
|
||||||
console.log(response?.data);
|
order_field: sorting[0].id,
|
||||||
setConversions(response?.data.list);
|
order_direction: sorting[0].desc ? 'ASC' : 'DESC',
|
||||||
return { data: response?.data.list, totalCount: response?.data.total_count };
|
filter: JSON.stringify(filter)
|
||||||
} catch (error) {
|
});
|
||||||
console.error('Error fetching Conversion', error);
|
console.log(response?.data);
|
||||||
}
|
return { data: response?.data.list, totalCount: response?.data.total_count };
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ManageConversionContext.Provider
|
<div className="min-h-screen">
|
||||||
value={{
|
<ManageConversionContext.Provider
|
||||||
conversion: conversions,
|
value={{
|
||||||
showAddDialog,
|
showEditDialog,
|
||||||
handleAddDialog,
|
handleEditDialog,
|
||||||
showEditDialog,
|
showAddDialog,
|
||||||
handleEditDialog,
|
handleAddDialog,
|
||||||
showDeleteDialog,
|
showDeleteDialog,
|
||||||
handleDeleteDialog,
|
handleDeleteDialog,
|
||||||
selectedConversion,
|
selectedConversion,
|
||||||
getConversionLists
|
conversion
|
||||||
}}
|
}}
|
||||||
>
|
|
||||||
<Toaster expand visibleToasts={9} duration={3000} />
|
|
||||||
<DataGridProvider
|
|
||||||
columns={columns}
|
|
||||||
pagination={{ size: 10 }}
|
|
||||||
toolbar={<ListToolbar />}
|
|
||||||
layout={{ card: true }}
|
|
||||||
sorting={[{ id: 'id', desc: false }]}
|
|
||||||
serverSide={true}
|
|
||||||
onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) =>
|
|
||||||
getConversionLists(pageIndex, pageSize, sorting, columnFilters)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{children}
|
<Toaster expand visibleToasts={9} duration={3000} />
|
||||||
</DataGridProvider>
|
|
||||||
</ManageConversionContext.Provider>
|
<div className="px-4">
|
||||||
|
<DataGridProvider
|
||||||
|
columns={columns}
|
||||||
|
pagination={{ size: 10 }}
|
||||||
|
layout={{ card: true }}
|
||||||
|
toolbar={<ListToolbar />}
|
||||||
|
sorting={[{ id: 'ID', desc: true }]}
|
||||||
|
serverSide={true}
|
||||||
|
onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) =>
|
||||||
|
doGetConversion(pageIndex, pageSize, sorting, columnFilters)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</DataGridProvider>
|
||||||
|
</div>
|
||||||
|
</ManageConversionContext.Provider>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { ManageConversionContext, ManageConversionContextProvider };
|
export { ManageConversionContext, ManageConversionContextProvider };
|
||||||
export type { ConversionProps };
|
export type { Conversion };
|
||||||
|
|||||||
@ -109,8 +109,22 @@ const ManageProviderContextProvider = ({ children }: { children: React.ReactNode
|
|||||||
header: ({ column }) => <DataGridColumnHeader title="Status" column={column} />,
|
header: ({ column }) => <DataGridColumnHeader title="Status" column={column} />,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const isActive = row.original.provider_status === 'Y';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={`px-2 py-1 text-xs font-semibold rounded-full ${
|
||||||
|
isActive ? 'bg-green-100 text-green-600' : 'bg-red-100 text-red-600'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{isActive ? 'Active' : 'Inactive'}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
meta: {
|
meta: {
|
||||||
headerClassName: 'w-[100px]'
|
headerClassName: 'w-[100px]',
|
||||||
|
cellClassName: 'text-center'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -158,7 +172,7 @@ const ManageProviderContextProvider = ({ children }: { children: React.ReactNode
|
|||||||
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC',
|
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC',
|
||||||
filter: JSON.stringify(filter)
|
filter: JSON.stringify(filter)
|
||||||
});
|
});
|
||||||
// console.log(response?.data);
|
console.log(response?.data);
|
||||||
setProvider(response?.data.list);
|
setProvider(response?.data.list);
|
||||||
return { data: response?.data.list, totalCount: response?.data.total_count };
|
return { data: response?.data.list, totalCount: response?.data.total_count };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
37
src/pages/master/wallet/WalletMaster.tsx
Normal file
37
src/pages/master/wallet/WalletMaster.tsx
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { Container, DataGridInner } from '@/components';
|
||||||
|
import { ManageWalletContextProvider } from './hooks/ManageWalletContext';
|
||||||
|
import { Breadcrumbs, Link } from '@mui/material';
|
||||||
|
import AddDialog from './blocks/AddDialog';
|
||||||
|
import EditDialog from './blocks/EditDialog';
|
||||||
|
import DeleteDialog from './blocks/DeleteDialog';
|
||||||
|
|
||||||
|
const WalletMaster = () => {
|
||||||
|
return (
|
||||||
|
<ManageWalletContextProvider>
|
||||||
|
<Container>
|
||||||
|
<h1 className="text-xl font-medium leading-none text-gray-900 mb-3">Manage Wallet</h1>
|
||||||
|
<Breadcrumbs sx={{ mb: 2 }}>
|
||||||
|
<Link underline="none" color="inherit" href="/">
|
||||||
|
<span className="text-sm hover:underline">Dashboard</span>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link underline="none" color="inherit">
|
||||||
|
<span className="text-sm">Master Data</span>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link underline="none" color="inherit">
|
||||||
|
<span className="text-sm">Manage Wallet</span>
|
||||||
|
</Link>
|
||||||
|
</Breadcrumbs>
|
||||||
|
<div className="grid gap-5 lg:gap-7.5">
|
||||||
|
<DataGridInner />
|
||||||
|
</div>
|
||||||
|
<AddDialog />
|
||||||
|
<EditDialog />
|
||||||
|
<DeleteDialog />
|
||||||
|
</Container>
|
||||||
|
</ManageWalletContextProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WalletMaster;
|
||||||
298
src/pages/master/wallet/blocks/AddDialog.tsx
Normal file
298
src/pages/master/wallet/blocks/AddDialog.tsx
Normal file
@ -0,0 +1,298 @@
|
|||||||
|
import { useCallApi } from '@/hooks';
|
||||||
|
import { useManageWalletContext } from '../hooks/useManageWalletContext';
|
||||||
|
import { Alert, useDataGrid } from '@/components';
|
||||||
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { apiConfig } from '@/config/api.config';
|
||||||
|
import { toast } from 'sonner';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogBody,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { Checkbox } from '@/components/ui/checkbox';
|
||||||
|
|
||||||
|
interface CurrencyProps {
|
||||||
|
ID: string;
|
||||||
|
code: string;
|
||||||
|
name: string;
|
||||||
|
prefix: string;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GroupProps {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const API_URL_WALLET = apiConfig.service_wallet;
|
||||||
|
const API_URL_MASTER_DATA = apiConfig.service_master_data;
|
||||||
|
|
||||||
|
const AddDialog = () => {
|
||||||
|
const { showAddDialog, handleAddDialog } = useManageWalletContext();
|
||||||
|
const { GetData, PostData } = useCallApi();
|
||||||
|
const { reload } = useDataGrid();
|
||||||
|
const [alert, setAlert] = useState({
|
||||||
|
show: false,
|
||||||
|
message: ''
|
||||||
|
});
|
||||||
|
const initialState: {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
status: string;
|
||||||
|
group: string[];
|
||||||
|
currency_id: string;
|
||||||
|
} = {
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
status: '',
|
||||||
|
group: [],
|
||||||
|
currency_id: ''
|
||||||
|
};
|
||||||
|
const [formField, setFormField] = useState(initialState);
|
||||||
|
const [currencies, setCurrencies] = useState<CurrencyProps[]>([]);
|
||||||
|
const [groups, setGroups] = useState<GroupProps[]>([]);
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
setFormField(initialState);
|
||||||
|
setAlert({ show: false, message: '' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleGroupChange = (groupId: string) => {
|
||||||
|
setFormField((prevState) => {
|
||||||
|
const isSelected = prevState.group.includes(groupId);
|
||||||
|
|
||||||
|
if (isSelected) {
|
||||||
|
// Remove the group if already selected
|
||||||
|
return {
|
||||||
|
...prevState,
|
||||||
|
group: prevState.group.filter((id) => id !== groupId)
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// Add the group if not selected
|
||||||
|
return {
|
||||||
|
...prevState,
|
||||||
|
group: [...prevState.group, groupId]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const doCreateWallet = useCallback(
|
||||||
|
async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const response = await PostData(`${API_URL_MASTER_DATA}/wallet/create`, formField);
|
||||||
|
|
||||||
|
if (response?.status) {
|
||||||
|
handleAddDialog(false);
|
||||||
|
toast.success('Success Create Wallet');
|
||||||
|
reload();
|
||||||
|
} else {
|
||||||
|
toast.error('Failed Create Wallet');
|
||||||
|
setAlert({ show: true, message: 'Failed Create Wallet' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[formField]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (
|
||||||
|
formField.name.trim() === '' ||
|
||||||
|
formField.description.trim() === '' ||
|
||||||
|
formField.status.trim() === '' ||
|
||||||
|
formField.group.length === 0 ||
|
||||||
|
formField.currency_id.trim() === ''
|
||||||
|
) {
|
||||||
|
setAlert({ show: true, message: 'Please fill in all required fields.' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(formField);
|
||||||
|
doCreateWallet(e);
|
||||||
|
setAlert({ show: false, message: '' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCurrencyLists = async (sorting: any) => {
|
||||||
|
try {
|
||||||
|
const response = await GetData(`${API_URL_WALLET}/dashboard/currency`, {
|
||||||
|
limit: 100,
|
||||||
|
page: 1,
|
||||||
|
with_deleted: false,
|
||||||
|
order_field: sorting[0].id,
|
||||||
|
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC'
|
||||||
|
});
|
||||||
|
// console.log('Currency: ', response?.data);
|
||||||
|
setCurrencies(response?.data.list);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching currency', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getGroupLists = async (sorting: any) => {
|
||||||
|
try {
|
||||||
|
const response = await GetData(`${API_URL_MASTER_DATA}/groups/list`, {
|
||||||
|
limit: 100,
|
||||||
|
page: 1,
|
||||||
|
with_deleted: false,
|
||||||
|
order_field: sorting[0].id,
|
||||||
|
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC'
|
||||||
|
});
|
||||||
|
// console.log('Group: ', response?.data);
|
||||||
|
setGroups(response?.data.list);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching group', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getCurrencyLists([{ id: 'name', desc: false }]);
|
||||||
|
getGroupLists([{ id: 'name', desc: false }]);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showAddDialog === false) {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
}, [showAddDialog]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={showAddDialog} onOpenChange={(open) => handleAddDialog(open)}>
|
||||||
|
<DialogContent className="container-fixed max-w-[768px] flex flex-col p-5 overflow-hidden">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Wallet - Create</DialogTitle>
|
||||||
|
<DialogDescription></DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogBody className="scrollable">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{alert.show && (
|
||||||
|
<Alert variant="danger">
|
||||||
|
<h3>{alert.message}</h3>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="card-body grid gap-5">
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Wallet Name<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
value={formField.name}
|
||||||
|
onChange={(e) => setFormField({ ...formField, name: e.target.value })}
|
||||||
|
placeholder="Wallet Name"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Description<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
value={formField.description}
|
||||||
|
onChange={(e) => setFormField({ ...formField, description: e.target.value })}
|
||||||
|
placeholder="Description"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Status<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<Select
|
||||||
|
value={formField.status}
|
||||||
|
onValueChange={(value) => setFormField({ ...formField, status: value })}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select Status" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="Y">Active</SelectItem>
|
||||||
|
<SelectItem value="N">Inactive</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Currency<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<Select
|
||||||
|
value={formField.currency_id}
|
||||||
|
onValueChange={(value) => setFormField({ ...formField, currency_id: value })}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select Currency Type" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{currencies.map((currency) => (
|
||||||
|
<SelectItem key={currency.ID} value={currency.ID}>
|
||||||
|
{currency.name}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Groups<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<div className="flex flex-wrap gap-3">
|
||||||
|
{groups.map((group) => (
|
||||||
|
<label key={group.id} className="inline-flex items-center">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
className="h-4 w-4"
|
||||||
|
checked={formField.group.includes(group.id)}
|
||||||
|
onChange={() => handleGroupChange(group.id)}
|
||||||
|
/>
|
||||||
|
<span className="ml-2">{group.name}</span>
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex justify-end gap-5">
|
||||||
|
<Button type="button" variant="outline" onClick={resetForm}>
|
||||||
|
Reset
|
||||||
|
</Button>
|
||||||
|
<Button variant="default">Create</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</DialogBody>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddDialog;
|
||||||
78
src/pages/master/wallet/blocks/DeleteDialog.tsx
Normal file
78
src/pages/master/wallet/blocks/DeleteDialog.tsx
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
import { useCallApi } from '@/hooks';
|
||||||
|
import { useManageWalletContext } from '../hooks/useManageWalletContext';
|
||||||
|
import { Alert, useDataGrid } from '@/components';
|
||||||
|
import { useCallback, useState } from 'react';
|
||||||
|
import { toast } from 'sonner';
|
||||||
|
import { apiConfig } from '@/config/api.config';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
|
||||||
|
const API_URL = apiConfig.service_master_data;
|
||||||
|
|
||||||
|
const DeleteDialog = () => {
|
||||||
|
const { showDeleteDialog, handleDeleteDialog, selectedWallet } = useManageWalletContext();
|
||||||
|
const { DeleteData } = useCallApi();
|
||||||
|
const { reload } = useDataGrid();
|
||||||
|
const [alert, setAlert] = useState({ show: false, message: '' });
|
||||||
|
|
||||||
|
const doDeleteWallet = useCallback(async () => {
|
||||||
|
if (!selectedWallet) {
|
||||||
|
toast.error('No wallet selected');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await DeleteData(
|
||||||
|
`${API_URL}/wallet/delete/${selectedWallet.Wallet_id}/false`,
|
||||||
|
{
|
||||||
|
id: selectedWallet.Wallet_id
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response?.status) {
|
||||||
|
setAlert({ show: false, message: '' });
|
||||||
|
handleDeleteDialog(false, null);
|
||||||
|
toast.success('Success Delete Wallet');
|
||||||
|
reload();
|
||||||
|
} else {
|
||||||
|
setAlert({ show: true, message: response?.message });
|
||||||
|
toast.error('Failed Delete Wallet');
|
||||||
|
}
|
||||||
|
}, [selectedWallet, handleDeleteDialog, DeleteData, reload]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={showDeleteDialog} onOpenChange={(open) => handleDeleteDialog(open, null)}>
|
||||||
|
<DialogContent className="container-fixed max-w-md flex flex-col p-5 overflow-hidden">
|
||||||
|
<DialogHeader className="p-0 border-0 block">
|
||||||
|
<DialogTitle></DialogTitle>
|
||||||
|
<DialogDescription></DialogDescription>
|
||||||
|
<Alert variant="warning">
|
||||||
|
<h3 className="text-lg">Are you sure?</h3>
|
||||||
|
<span className="text-sm">You will delete this data!</span>
|
||||||
|
</Alert>
|
||||||
|
{alert.show && (
|
||||||
|
<Alert variant="danger">
|
||||||
|
<h3>{alert.message}</h3>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogFooter className="flex justify-end items-center gap-4 mt-3">
|
||||||
|
<Button variant="outline" onClick={() => handleDeleteDialog(false, null)}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button variant="destructive" onClick={doDeleteWallet}>
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DeleteDialog;
|
||||||
278
src/pages/master/wallet/blocks/EditDialog.tsx
Normal file
278
src/pages/master/wallet/blocks/EditDialog.tsx
Normal file
@ -0,0 +1,278 @@
|
|||||||
|
import { Alert, useDataGrid } from '@/components';
|
||||||
|
import { useManageWalletContext } from '../hooks/useManageWalletContext';
|
||||||
|
import { useCallApi } from '@/hooks';
|
||||||
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
|
import { apiConfig } from '@/config/api.config';
|
||||||
|
import { toast } from 'sonner';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogBody,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
import { Input } from '@/components/ui/input';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
|
||||||
|
interface CurrencyProps {
|
||||||
|
ID: string;
|
||||||
|
code: string;
|
||||||
|
name: string;
|
||||||
|
prefix: string;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GroupProps {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const API_URL_WALLET = apiConfig.service_wallet;
|
||||||
|
const API_URL_MASTER_DATA = apiConfig.service_master_data;
|
||||||
|
|
||||||
|
const EditDialog = () => {
|
||||||
|
const { showEditDialog, handleEditDialog, selectedWallet } = useManageWalletContext();
|
||||||
|
const { reload } = useDataGrid();
|
||||||
|
const { GetData, PutData } = useCallApi();
|
||||||
|
const [alert, setAlert] = useState({
|
||||||
|
show: false,
|
||||||
|
message: ''
|
||||||
|
});
|
||||||
|
const initialState: {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
status: string;
|
||||||
|
group: string[];
|
||||||
|
currency_id: string;
|
||||||
|
} = {
|
||||||
|
name: '',
|
||||||
|
description: '',
|
||||||
|
status: '',
|
||||||
|
group: [],
|
||||||
|
currency_id: ''
|
||||||
|
};
|
||||||
|
const [formField, setFormField] = useState(initialState);
|
||||||
|
const [currencies, setCurrencies] = useState<CurrencyProps[]>([]);
|
||||||
|
const [groups, setGroups] = useState<GroupProps[]>([]);
|
||||||
|
|
||||||
|
const resetForm = () => {
|
||||||
|
setFormField(initialState);
|
||||||
|
setAlert({ show: false, message: '' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const doUpdateWallet = useCallback(
|
||||||
|
async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const response = await PutData(
|
||||||
|
`${API_URL_MASTER_DATA}/wallet/update/${selectedWallet?.Wallet_id}`,
|
||||||
|
formField
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response?.status) {
|
||||||
|
handleEditDialog(false, null);
|
||||||
|
toast.success('Success Update Wallet');
|
||||||
|
reload();
|
||||||
|
} else {
|
||||||
|
toast.error('Failed Update Wallet');
|
||||||
|
setAlert({ show: true, message: 'Failed Update Wallet' });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[formField]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
console.log(formField);
|
||||||
|
doUpdateWallet(e);
|
||||||
|
setAlert({ show: false, message: '' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const doFetchData = useCallback(async (id: string) => {
|
||||||
|
const response = await GetData(`${API_URL_MASTER_DATA}/wallet/detail/${id}`, {
|
||||||
|
id
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(response);
|
||||||
|
if (response?.status) {
|
||||||
|
setFormField((prev) => ({
|
||||||
|
...prev,
|
||||||
|
name: response?.data.name,
|
||||||
|
description: response?.data.description,
|
||||||
|
status: response?.data.status,
|
||||||
|
currency_id: response?.data.id_currency,
|
||||||
|
group: Array.isArray(response?.data.group)
|
||||||
|
? response?.data.group.map((target: GroupProps) => target.id)
|
||||||
|
: []
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const getCurrencyLists = async (sorting: any) => {
|
||||||
|
try {
|
||||||
|
const response = await GetData(`${API_URL_WALLET}/dashboard/currency`, {
|
||||||
|
limit: 100,
|
||||||
|
page: 1,
|
||||||
|
with_deleted: false,
|
||||||
|
order_field: sorting[0].id,
|
||||||
|
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC'
|
||||||
|
});
|
||||||
|
// console.log('Currency: ', response?.data);
|
||||||
|
setCurrencies(response?.data.list);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching currency', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getGroupLists = async (sorting: any) => {
|
||||||
|
try {
|
||||||
|
const response = await GetData(`${API_URL_MASTER_DATA}/groups/list`, {
|
||||||
|
limit: 100,
|
||||||
|
page: 1,
|
||||||
|
with_deleted: false,
|
||||||
|
order_field: sorting[0].id,
|
||||||
|
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC'
|
||||||
|
});
|
||||||
|
// console.log('Group: ', response?.data);
|
||||||
|
setGroups(response?.data.list);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching group', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectedGroupNames = groups
|
||||||
|
.filter((g) => formField.group.includes(g.id))
|
||||||
|
.map((g) => g.name)
|
||||||
|
.join(', ');
|
||||||
|
|
||||||
|
const selectedCurrency = currencies.find((currency) => currency.ID === formField.currency_id);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getCurrencyLists([{ id: 'name', desc: false }]);
|
||||||
|
getGroupLists([{ id: 'name', desc: false }]);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedWallet) {
|
||||||
|
// setFormField((prev) => ({
|
||||||
|
// ...prev,
|
||||||
|
// name: selectedWallet?.Wallet_name,
|
||||||
|
// description: selectedWallet?.Wallet_description,
|
||||||
|
// status: selectedWallet?.Wallet_status,
|
||||||
|
// currency_id: selectedWallet?.Wallet_currency_id,
|
||||||
|
// group: selectedWallet?.Wallet_group
|
||||||
|
// }));
|
||||||
|
doFetchData(selectedWallet?.Wallet_id);
|
||||||
|
}
|
||||||
|
}, [selectedWallet]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (showEditDialog === false) {
|
||||||
|
resetForm();
|
||||||
|
}
|
||||||
|
}, [showEditDialog]);
|
||||||
|
// console.log(selectedWallet);
|
||||||
|
return (
|
||||||
|
<Dialog open={showEditDialog} onOpenChange={(open) => handleEditDialog(open, null)}>
|
||||||
|
<DialogContent className="container-fixed max-w-[768px] flex flex-col p-5 overflow-hidden">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Wallet - Update</DialogTitle>
|
||||||
|
<DialogDescription></DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogBody className="scrollable">
|
||||||
|
<div className="flex flex-col">
|
||||||
|
{alert.show && (
|
||||||
|
<Alert variant="danger">
|
||||||
|
<h3>{alert.message}</h3>
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="card-body grid gap-5">
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Wallet Name
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
value={formField.name}
|
||||||
|
onChange={(e) => setFormField({ ...formField, name: e.target.value })}
|
||||||
|
placeholder="Wallet Name"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Description
|
||||||
|
</label>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
value={formField.description}
|
||||||
|
onChange={(e) => setFormField({ ...formField, description: e.target.value })}
|
||||||
|
placeholder="Description"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label className="form-label flex items-center gap-1 max-w-56">Status</label>
|
||||||
|
<Select
|
||||||
|
value={formField.status}
|
||||||
|
onValueChange={(value) => setFormField({ ...formField, status: value })}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select Status" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="Y">Active</SelectItem>
|
||||||
|
<SelectItem value="N">Inactive</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label className="form-label flex items-center gap-1 max-w-56">Currency</label>
|
||||||
|
<Input type="text" placeholder='Empty' value={selectedCurrency?.name || ''} readOnly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full">
|
||||||
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label className="form-label flex items-center gap-1 max-w-56">Groups</label>
|
||||||
|
<Input type="text" placeholder='Empty' value={selectedGroupNames} readOnly />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex justify-end gap-5">
|
||||||
|
<Button type="button" variant="outline" onClick={resetForm}>
|
||||||
|
Reset
|
||||||
|
</Button>
|
||||||
|
<Button variant="default">Update</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</DialogBody>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditDialog;
|
||||||
55
src/pages/master/wallet/blocks/ListToolbar.tsx
Normal file
55
src/pages/master/wallet/blocks/ListToolbar.tsx
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { useManageWalletContext } from '../hooks/useManageWalletContext';
|
||||||
|
|
||||||
|
const ListToolbar = () => {
|
||||||
|
const { reload, table } = useDataGrid();
|
||||||
|
const { handleAddDialog } = useManageWalletContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="card-header flex-wrap gap-2 border-b-0 px-5">
|
||||||
|
<div className="flex flex-wrap gap-2 lg:gap-5 w-full">
|
||||||
|
<div className="flex justify-between w-full items-center">
|
||||||
|
<div className="flex w-[50%] gap-3 items-center">
|
||||||
|
<label className="input input-sm w-1/3">
|
||||||
|
<KeenIcon icon="magnifier" />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Search Provider"
|
||||||
|
value={(table.getColumn('name')?.getFilterValue() as string) ?? ''}
|
||||||
|
onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
{/* <DefaultTooltip title={'Filter'} placement={'top'}>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="h-7.5 disabled:bg-gray-400"
|
||||||
|
// disabled={isLoading}
|
||||||
|
// onClick={handleFilterData}
|
||||||
|
>
|
||||||
|
{loadingButton === 'filter' ? <ContentLoader /> : <KeenIcon icon="filter" />}
|
||||||
|
<KeenIcon icon="filter" />
|
||||||
|
</Button>
|
||||||
|
</DefaultTooltip> */}
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-3 items-center">
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="h-7.5 text-[0.8rem]"
|
||||||
|
onClick={() => handleAddDialog(true)}
|
||||||
|
>
|
||||||
|
Add Data
|
||||||
|
</Button>
|
||||||
|
<DefaultTooltip title={'Refresh'} placement={'top'}>
|
||||||
|
<Button variant="outline" className="h-7.5" onClick={() => reload()}>
|
||||||
|
<KeenIcon icon="arrows-circle" />
|
||||||
|
</Button>
|
||||||
|
</DefaultTooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ListToolbar;
|
||||||
205
src/pages/master/wallet/hooks/ManageWalletContext.tsx
Normal file
205
src/pages/master/wallet/hooks/ManageWalletContext.tsx
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
import { DataGridColumnHeader, DataGridProvider, KeenIcon } from '@/components';
|
||||||
|
import { apiConfig } from '@/config/api.config';
|
||||||
|
import { useCallApi } from '@/hooks';
|
||||||
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
|
import React, { createContext, useCallback, useMemo, useState } from 'react';
|
||||||
|
import { Toaster } from 'sonner';
|
||||||
|
import ListToolbar from '../blocks/ListToolbar';
|
||||||
|
|
||||||
|
interface WalletProps {
|
||||||
|
Wallet_id: string;
|
||||||
|
Wallet_name: string;
|
||||||
|
Wallet_status: string;
|
||||||
|
Wallet_description: string;
|
||||||
|
Wallet_group: string[];
|
||||||
|
Wallet_currency_id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ContextProps {
|
||||||
|
wallet: WalletProps[];
|
||||||
|
showAddDialog: boolean;
|
||||||
|
handleAddDialog: (show: boolean) => void;
|
||||||
|
showEditDialog: boolean;
|
||||||
|
handleEditDialog: (show: boolean, selected_wallet: WalletProps | null) => void;
|
||||||
|
showDeleteDialog: boolean;
|
||||||
|
handleDeleteDialog: (show: boolean, selected_wallet: WalletProps | null) => void;
|
||||||
|
selectedWallet: WalletProps | null;
|
||||||
|
getWalletLists: (
|
||||||
|
limit: number,
|
||||||
|
page: number,
|
||||||
|
with_deleted: boolean,
|
||||||
|
order_field: any,
|
||||||
|
order_direction: any
|
||||||
|
) => Promise<{ data: WalletProps[]; totalCount: number } | undefined>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialProps: ContextProps = {
|
||||||
|
wallet: [],
|
||||||
|
showAddDialog: false,
|
||||||
|
handleAddDialog: (show: boolean) => {},
|
||||||
|
showEditDialog: false,
|
||||||
|
handleEditDialog: (show: boolean, selected_wallet: WalletProps | null) => {},
|
||||||
|
showDeleteDialog: false,
|
||||||
|
handleDeleteDialog: (show: boolean, selected_wallet: WalletProps | null) => {},
|
||||||
|
selectedWallet: null,
|
||||||
|
getWalletLists: async () => ({ data: [], totalCount: 0 })
|
||||||
|
};
|
||||||
|
|
||||||
|
const ManageWalletContext = createContext<ContextProps>(initialProps);
|
||||||
|
const API_URL_MASTER_DATA = apiConfig.service_master_data;
|
||||||
|
|
||||||
|
const ManageWalletContextProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
|
const [wallets, setWallets] = useState<WalletProps[]>([]);
|
||||||
|
const [showAddDialog, setShowAddDialog] = useState(false);
|
||||||
|
const [showEditDialog, setShowEditDialog] = useState(false);
|
||||||
|
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
||||||
|
const [selectedWallet, setSelectedWallet] = useState<WalletProps | null>(null);
|
||||||
|
const { GetData } = useCallApi();
|
||||||
|
|
||||||
|
const handleAddDialog = useCallback((show: boolean) => {
|
||||||
|
setShowAddDialog(show);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleEditDialog = useCallback((show: boolean, selected_wallet: WalletProps | null) => {
|
||||||
|
setShowEditDialog(show);
|
||||||
|
setSelectedWallet(show ? selected_wallet : null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleDeleteDialog = useCallback((show: boolean, selected_wallet: WalletProps | null) => {
|
||||||
|
setShowDeleteDialog(show);
|
||||||
|
setSelectedWallet(show ? selected_wallet : null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const columns = useMemo<ColumnDef<any>[]>(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.Wallet_name,
|
||||||
|
id: 'name',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Name" column={column} />,
|
||||||
|
enableSorting: true,
|
||||||
|
enableHiding: false,
|
||||||
|
meta: {
|
||||||
|
headerClassName: 'w-[250px]'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.Wallet_description,
|
||||||
|
id: 'description',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Description" column={column} />,
|
||||||
|
enableSorting: true,
|
||||||
|
enableHiding: false,
|
||||||
|
meta: {
|
||||||
|
headerClassName: 'w-[250px]'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.Wallet_status,
|
||||||
|
id: 'status',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Status" column={column} />,
|
||||||
|
enableSorting: true,
|
||||||
|
enableHiding: false,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const isActive = row.original.Wallet_status === 'Y';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={`px-2 py-1 text-xs font-semibold rounded-full ${
|
||||||
|
isActive ? 'bg-green-100 text-green-600' : 'bg-red-100 text-red-600'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{isActive ? 'Active' : 'Inactive'}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
headerClassName: 'w-[100px] text-center',
|
||||||
|
cellClassName: 'text-center'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'actions',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Actions" column={column} />,
|
||||||
|
enableSorting: false,
|
||||||
|
enableHiding: false,
|
||||||
|
cell: (data) => {
|
||||||
|
const row = data.row.original;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<button
|
||||||
|
className="btn btn-sm btn-icon btn-clear btn-light"
|
||||||
|
onClick={() => handleEditDialog(true, row)}
|
||||||
|
>
|
||||||
|
<KeenIcon icon="notepad-edit" />
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className="btn btn-sm btn-icon btn-clear btn-light"
|
||||||
|
onClick={() => handleDeleteDialog(true, row)}
|
||||||
|
>
|
||||||
|
<KeenIcon icon="trash" />
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
headerClassName: 'w-[100px] text-center',
|
||||||
|
cellClassName: 'text-center'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const getWalletLists = async (page: number, limit: number, sorting: any, filter: any) => {
|
||||||
|
try {
|
||||||
|
sorting = sorting.length == 0 ? [{ id: 'name', desc: false }] : sorting;
|
||||||
|
filter = filter.length == 0 ? {} : { any: filter[0].value?.toLowerCase() };
|
||||||
|
const response = await GetData(`${API_URL_MASTER_DATA}/wallet/list`, {
|
||||||
|
limit,
|
||||||
|
page: page + 1,
|
||||||
|
with_deleted: false,
|
||||||
|
order_field: sorting[0].id,
|
||||||
|
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC',
|
||||||
|
filter: JSON.stringify(filter)
|
||||||
|
});
|
||||||
|
// console.log(response?.data);
|
||||||
|
setWallets(response?.data.list);
|
||||||
|
return { data: response?.data.list, totalCount: response?.data.total_count };
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching Wallet', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ManageWalletContext.Provider
|
||||||
|
value={{
|
||||||
|
wallet: wallets,
|
||||||
|
showAddDialog,
|
||||||
|
handleAddDialog,
|
||||||
|
showEditDialog,
|
||||||
|
handleEditDialog,
|
||||||
|
showDeleteDialog,
|
||||||
|
handleDeleteDialog,
|
||||||
|
selectedWallet,
|
||||||
|
getWalletLists
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Toaster expand visibleToasts={9} duration={3000} />
|
||||||
|
<DataGridProvider
|
||||||
|
columns={columns}
|
||||||
|
pagination={{ size: 25 }}
|
||||||
|
toolbar={<ListToolbar />}
|
||||||
|
layout={{ card: true }}
|
||||||
|
sorting={[{ id: 'id', desc: false }]}
|
||||||
|
serverSide={true}
|
||||||
|
onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) =>
|
||||||
|
getWalletLists(pageIndex, pageSize, sorting, columnFilters)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</DataGridProvider>
|
||||||
|
</ManageWalletContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { ManageWalletContext, ManageWalletContextProvider };
|
||||||
|
export type { WalletProps };
|
||||||
12
src/pages/master/wallet/hooks/useManageWalletContext.tsx
Normal file
12
src/pages/master/wallet/hooks/useManageWalletContext.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { useContext } from 'react';
|
||||||
|
import { ManageWalletContext } from './ManageWalletContext';
|
||||||
|
|
||||||
|
const useManageWalletContext = () => {
|
||||||
|
const context = useContext(ManageWalletContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('useManageWalletContext must be used within a ManageWalletContextProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { useManageWalletContext };
|
||||||
@ -105,15 +105,7 @@ const AddDialog = () => {
|
|||||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (
|
if (formField.id_group.trim() === '' || formField.status.trim() === '') {
|
||||||
formField.id_group.trim() === '' ||
|
|
||||||
formField.max_transaction_per_day === 0 ||
|
|
||||||
formField.balance_minimum === 0 ||
|
|
||||||
formField.balance_maximum === 0 ||
|
|
||||||
formField.credit_limit === 0 ||
|
|
||||||
formField.monthly_limit === 0 ||
|
|
||||||
formField.status.trim() === ''
|
|
||||||
) {
|
|
||||||
setAlert({ show: true, message: 'Please fill in all required fields.' });
|
setAlert({ show: true, message: 'Please fill in all required fields.' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,15 +108,7 @@ const EditDialog = () => {
|
|||||||
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (
|
if (formField.id_group.trim() === '' || formField.status.trim() === '') {
|
||||||
formField.id_group.trim() === '' ||
|
|
||||||
formField.max_transaction_per_day === 0 ||
|
|
||||||
formField.balance_minimum === 0 ||
|
|
||||||
formField.balance_maximum === 0 ||
|
|
||||||
formField.credit_limit === 0 ||
|
|
||||||
formField.monthly_limit === 0 ||
|
|
||||||
formField.status.trim() === ''
|
|
||||||
) {
|
|
||||||
setAlert({ show: true, message: 'Please fill in all required fields.' });
|
setAlert({ show: true, message: 'Please fill in all required fields.' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -137,10 +137,24 @@ const ManageWalletRuleContextProvider = ({ children }: { children: React.ReactNo
|
|||||||
accessorFn: (row) => row.status,
|
accessorFn: (row) => row.status,
|
||||||
id: 'status',
|
id: 'status',
|
||||||
header: ({ column }) => <DataGridColumnHeader title="Status" column={column} />,
|
header: ({ column }) => <DataGridColumnHeader title="Status" column={column} />,
|
||||||
enableSorting: true,
|
enableSorting: false,
|
||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const isActive = row.original.status === 'Y';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={`px-2 py-1 text-xs font-semibold rounded-full ${
|
||||||
|
isActive ? 'bg-green-100 text-green-600' : 'bg-red-100 text-red-600'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{isActive ? 'Active' : 'Inactive'}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
meta: {
|
meta: {
|
||||||
headerClassName: 'w-[250px]'
|
headerClassName: 'w-[100px]',
|
||||||
|
cellClassName: 'text-center'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -12,16 +12,22 @@ import {
|
|||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle
|
DialogTitle
|
||||||
} from '@/components/ui/dialog';
|
} from '@/components/ui/dialog';
|
||||||
import { FormControl,NativeSelect } from "@mui/material";
|
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
|
||||||
const API_URL = apiConfig.service_dashboard;
|
const API_URL = apiConfig.service_dashboard;
|
||||||
const AddDialog = () => {
|
const AddDialog = () => {
|
||||||
const parentRef = useRef<any | null>(null);
|
|
||||||
const { showAddDialog, handleAddDialog, parents } = useManageMenusContext();
|
const { showAddDialog, handleAddDialog, parents } = useManageMenusContext();
|
||||||
const { reload } = useDataGrid();
|
const { reload } = useDataGrid();
|
||||||
const { PostData } = useCallApi();
|
const { PostData } = useCallApi();
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
const [alert, setAlert] = useState({
|
const [alert, setAlert] = useState({
|
||||||
show: false,
|
show: false,
|
||||||
message: ''
|
message: ''
|
||||||
@ -51,8 +57,11 @@ const AddDialog = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('Data dikirim ke API:', formField);
|
||||||
const response = await PostData(`${API_URL}/menus/create`, formField);
|
const response = await PostData(`${API_URL}/menus/create`, formField);
|
||||||
|
|
||||||
|
console.log('Response from API:', response);
|
||||||
|
|
||||||
if (response?.status) {
|
if (response?.status) {
|
||||||
handleAddDialog(false);
|
handleAddDialog(false);
|
||||||
resetForm();
|
resetForm();
|
||||||
@ -67,7 +76,10 @@ const AddDialog = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
setFormField(initialState);
|
setFormField({
|
||||||
|
...initialState,
|
||||||
|
status: formField.status // Pertahankan nilai status terpilih
|
||||||
|
});
|
||||||
setAlert({ show: false, message: '' });
|
setAlert({ show: false, message: '' });
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,7 +90,7 @@ const AddDialog = () => {
|
|||||||
<DialogTitle>Menu - Create</DialogTitle>
|
<DialogTitle>Menu - Create</DialogTitle>
|
||||||
<DialogDescription></DialogDescription>
|
<DialogDescription></DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<DialogBody ref={parentRef}>
|
<DialogBody className="scrollable">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
{alert.show && (
|
{alert.show && (
|
||||||
<Alert variant="danger">
|
<Alert variant="danger">
|
||||||
@ -133,24 +145,21 @@ const AddDialog = () => {
|
|||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
<label className="form-label flex items-center gap-1 max-w-56">Parent</label>
|
<label className="form-label flex items-center gap-1 max-w-56">Parent</label>
|
||||||
<FormControl fullWidth margin="dense">
|
<Select
|
||||||
<NativeSelect
|
value={formField.id_parent}
|
||||||
defaultValue={30}
|
onValueChange={(value) => setFormField({ ...formField, id_parent: value })}
|
||||||
value={formField.id_parent}
|
>
|
||||||
onChange={(e: any) => setFormField({ ...formField, id_parent: e.target.value })}
|
<SelectTrigger>
|
||||||
inputProps={{
|
<SelectValue placeholder="Select As Parent" />
|
||||||
name: 'id_parent',
|
</SelectTrigger>
|
||||||
id: 'uncontrolled-native',
|
<SelectContent>
|
||||||
}}
|
{parents.map((parent: any) => (
|
||||||
>
|
<SelectItem key={parent.id} value={parent.id}>
|
||||||
<option value={''}>As Parent</option>
|
{parent.name}
|
||||||
{
|
</SelectItem>
|
||||||
parents ? parents.map((el: any) => (
|
))}
|
||||||
<option key={el.id} value={el.id}>{el.name}</option>
|
</SelectContent>
|
||||||
)) : ''
|
</Select>
|
||||||
}
|
|
||||||
</NativeSelect>
|
|
||||||
</FormControl>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -190,21 +199,18 @@ const AddDialog = () => {
|
|||||||
<label className="form-label flex items-center gap-1 max-w-56">
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
Status<span className="text-red-500">*</span>
|
Status<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<FormControl fullWidth margin="dense">
|
<Select
|
||||||
<NativeSelect
|
value={formField.status}
|
||||||
defaultValue={30}
|
onValueChange={(value) => setFormField({ ...formField, status: value })}
|
||||||
value={formField.status}
|
>
|
||||||
onChange={(e: any) => setFormField({ ...formField, status: e.target.value })}
|
<SelectTrigger>
|
||||||
inputProps={{
|
<SelectValue placeholder="Select Status" />
|
||||||
name: 'status',
|
</SelectTrigger>
|
||||||
id: 'uncontrolled-native',
|
<SelectContent>
|
||||||
}}
|
<SelectItem value="Y">Active</SelectItem>
|
||||||
>
|
<SelectItem value="N">Inactive</SelectItem>
|
||||||
<option value={''}>Select</option>
|
</SelectContent>
|
||||||
<option value={"Y"}>Active</option>
|
</Select>
|
||||||
<option value={"N"}>Inactive</option>
|
|
||||||
</NativeSelect>
|
|
||||||
</FormControl>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,14 @@ import { Alert, useDataGrid } from '@/components';
|
|||||||
import { useCallApi } from '@/hooks';
|
import { useCallApi } from '@/hooks';
|
||||||
import { ChangeEvent, useCallback, useState } from 'react';
|
import { ChangeEvent, useCallback, useState } from 'react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
import { EnforceSwitch } from '@/components/switch';
|
import { EnforceSwitch } from '@/components/switch';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
|
||||||
@ -13,14 +20,13 @@ const DeleteDialog = () => {
|
|||||||
const { showDeleteDialog, handleDeleteDialog, selectedMenu }: any = useManageMenusContext();
|
const { showDeleteDialog, handleDeleteDialog, selectedMenu }: any = useManageMenusContext();
|
||||||
const { reload } = useDataGrid();
|
const { reload } = useDataGrid();
|
||||||
const { DeleteData } = useCallApi();
|
const { DeleteData } = useCallApi();
|
||||||
const [enforce, setEnforce] = useState(false);
|
|
||||||
const [alert, setAlert] = useState({
|
const [alert, setAlert] = useState({
|
||||||
show: false,
|
show: false,
|
||||||
message: ''
|
message: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
const doDeleteMenu = async () => {
|
const doDeleteMenu = async () => {
|
||||||
const response = await DeleteData(`${API_URL}/menus/delete/${selectedMenu.id}/${enforce}`, {
|
const response = await DeleteData(`${API_URL}/menus/delete/${selectedMenu.id}/false`, {
|
||||||
id: selectedMenu.id
|
id: selectedMenu.id
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -44,15 +50,6 @@ const DeleteDialog = () => {
|
|||||||
<Alert variant="warning">
|
<Alert variant="warning">
|
||||||
<h3 className="text-lg">Are you sure?</h3>
|
<h3 className="text-lg">Are you sure?</h3>
|
||||||
<span className="text-sm">you will delete this data!</span>
|
<span className="text-sm">you will delete this data!</span>
|
||||||
<div className="mt-2 flex items-center gap-x-2">
|
|
||||||
<label className="form-label max-w-56">Hard Delete</label>
|
|
||||||
<EnforceSwitch
|
|
||||||
enforce={enforce}
|
|
||||||
onChange={(e: ChangeEvent<HTMLInputElement>) => {
|
|
||||||
setEnforce(e.target.checked);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Alert>
|
</Alert>
|
||||||
{alert.show && (
|
{alert.show && (
|
||||||
<Alert variant="danger">
|
<Alert variant="danger">
|
||||||
|
|||||||
@ -12,15 +12,25 @@ import {
|
|||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle
|
DialogTitle
|
||||||
} from '@/components/ui/dialog';
|
} from '@/components/ui/dialog';
|
||||||
import { FormControl,NativeSelect } from "@mui/material";
|
import { FormControl, NativeSelect } from '@mui/material';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import {
|
||||||
|
Select,
|
||||||
|
SelectContent,
|
||||||
|
SelectItem,
|
||||||
|
SelectTrigger,
|
||||||
|
SelectValue
|
||||||
|
} from '@/components/ui/select';
|
||||||
|
|
||||||
const API_URL = apiConfig.service_dashboard;
|
const API_URL = apiConfig.service_dashboard;
|
||||||
|
|
||||||
const EditDialog = () => {
|
const EditDialog = () => {
|
||||||
const { showEditDialog, handleEditDialog, selectedMenu, setSelectedMenu, parents }: any = useManageMenusContext();
|
const { showEditDialog, handleEditDialog, selectedMenu, setSelectedMenu, parents }: any =
|
||||||
|
useManageMenusContext();
|
||||||
const { reload } = useDataGrid();
|
const { reload } = useDataGrid();
|
||||||
const { PutData } = useCallApi();
|
const { PutData } = useCallApi();
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
const [alert, setAlert] = useState({
|
const [alert, setAlert] = useState({
|
||||||
show: false,
|
show: false,
|
||||||
message: ''
|
message: ''
|
||||||
@ -38,11 +48,12 @@ const EditDialog = () => {
|
|||||||
|
|
||||||
const handleUpdate = async (e: React.FormEvent<HTMLFormElement>) => {
|
const handleUpdate = async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
selectedMenu.module === '' ||
|
selectedMenu.module === '' ||
|
||||||
selectedMenu.name === '' ||
|
selectedMenu.name === '' ||
|
||||||
selectedMenu.link === '' ||
|
selectedMenu.link === '' ||
|
||||||
|
selectedMenu.id_parent === '' ||
|
||||||
selectedMenu.order_number === 0 ||
|
selectedMenu.order_number === 0 ||
|
||||||
selectedMenu.status === ''
|
selectedMenu.status === ''
|
||||||
) {
|
) {
|
||||||
@ -51,8 +62,8 @@ const EditDialog = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const updateMenu = selectedMenu;
|
const updateMenu = selectedMenu;
|
||||||
if (updateMenu.id_parent === null) updateMenu.id_parent = "";
|
if (updateMenu.id_parent === null) updateMenu.id_parent = '';
|
||||||
delete updateMenu.parentName
|
delete updateMenu.parentName;
|
||||||
const response = await PutData(`${API_URL}/menus/update/${selectedMenu.id}`, selectedMenu);
|
const response = await PutData(`${API_URL}/menus/update/${selectedMenu.id}`, selectedMenu);
|
||||||
if (response?.status) {
|
if (response?.status) {
|
||||||
handleEditDialog(false, null);
|
handleEditDialog(false, null);
|
||||||
@ -67,7 +78,7 @@ const EditDialog = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
setSelectedMenu(initialState)
|
setSelectedMenu(initialState);
|
||||||
setAlert({ show: false, message: '' });
|
setAlert({ show: false, message: '' });
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,7 +89,7 @@ const EditDialog = () => {
|
|||||||
<DialogTitle>Menu - Update</DialogTitle>
|
<DialogTitle>Menu - Update</DialogTitle>
|
||||||
<DialogDescription></DialogDescription>
|
<DialogDescription></DialogDescription>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<DialogBody>
|
<DialogBody className="scrollable">
|
||||||
<div className="flex flex-col">
|
<div className="flex flex-col">
|
||||||
{alert.show && (
|
{alert.show && (
|
||||||
<Alert variant="danger">
|
<Alert variant="danger">
|
||||||
@ -132,24 +143,27 @@ const EditDialog = () => {
|
|||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
<label className="form-label flex items-center gap-1 max-w-56">ID Parent</label>
|
<label className="form-label flex items-center gap-1 max-w-56">Parent</label>
|
||||||
<FormControl fullWidth margin="dense">
|
<Select
|
||||||
<NativeSelect
|
value={selectedMenu.id_parent || ''}
|
||||||
defaultValue={30}
|
onValueChange={(value) => {
|
||||||
value={selectedMenu.id_parent}
|
setSelectedMenu({
|
||||||
onChange={(e: any) => setSelectedMenu({ ...selectedMenu, id_parent: e.target.value })}
|
...selectedMenu,
|
||||||
inputProps={{
|
id_parent: value === '' ? null : value
|
||||||
name: 'id_parent',
|
});
|
||||||
id: 'uncontrolled-native',
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<SelectTrigger>
|
||||||
{
|
<SelectValue placeholder="Select As Parent" />
|
||||||
parents ? parents.map((el: any) => (
|
</SelectTrigger>
|
||||||
<option key={el.id} value={el.id}>{el.name}</option>
|
<SelectContent>
|
||||||
)) : ''
|
{parents.map((parent: any) => (
|
||||||
}
|
<SelectItem key={parent.id} value={parent.id}>
|
||||||
</NativeSelect>
|
{parent.name}
|
||||||
</FormControl>
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -165,7 +179,10 @@ const EditDialog = () => {
|
|||||||
value={selectedMenu.order_number === 0 ? '' : selectedMenu.order_number}
|
value={selectedMenu.order_number === 0 ? '' : selectedMenu.order_number}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const value = parseInt(e.target.value, 10);
|
const value = parseInt(e.target.value, 10);
|
||||||
setSelectedMenu({ ...selectedMenu, order_number: isNaN(value) ? 0 : value });
|
setSelectedMenu({
|
||||||
|
...selectedMenu,
|
||||||
|
order_number: isNaN(value) ? 0 : value
|
||||||
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -184,6 +201,26 @@ const EditDialog = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Status<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
<Select
|
||||||
|
value={selectedMenu.status}
|
||||||
|
onValueChange={(value) => setSelectedMenu({ ...selectedMenu, status: value })}
|
||||||
|
>
|
||||||
|
<SelectTrigger>
|
||||||
|
<SelectValue placeholder="Select Status" />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value="Y">Active</SelectItem>
|
||||||
|
<SelectItem value="N">Inactive</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <div className="w-full">
|
||||||
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
<label className="form-label flex items-center gap-1 max-w-56">
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
Status<span className="text-red-500">*</span>
|
Status<span className="text-red-500">*</span>
|
||||||
@ -203,7 +240,7 @@ const EditDialog = () => {
|
|||||||
</NativeSelect>
|
</NativeSelect>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<div className="flex justify-end">
|
<div className="flex justify-end">
|
||||||
<Button className="btn btn-primary">Save Changes</Button>
|
<Button className="btn btn-primary">Save Changes</Button>
|
||||||
|
|||||||
@ -133,12 +133,27 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode })
|
|||||||
meta: { headerClassName: 'w-[250px]' }
|
meta: { headerClassName: 'w-[250px]' }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorFn: (row) => row.status,
|
accessorKey: 'status',
|
||||||
id: 'status',
|
|
||||||
header: ({ column }) => <DataGridColumnHeader title="Status" column={column} />,
|
header: ({ column }) => <DataGridColumnHeader title="Status" column={column} />,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
meta: { headerClassName: 'w-[100px]', cellClassName: 'text-center' }
|
cell: ({ row }) => {
|
||||||
|
const isActive = row.original.status === 'Y';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={`px-2 py-1 text-xs font-semibold rounded-full ${
|
||||||
|
isActive ? 'bg-green-100 text-green-600' : 'bg-red-100 text-red-600'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{isActive ? 'Active' : 'Inactive'}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
headerClassName: 'w-[100px]',
|
||||||
|
cellClassName: 'text-center'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'actions',
|
id: 'actions',
|
||||||
@ -211,7 +226,7 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode })
|
|||||||
link: child.link,
|
link: child.link,
|
||||||
id_parent: child.id_parent,
|
id_parent: child.id_parent,
|
||||||
status: child.status,
|
status: child.status,
|
||||||
order_number: child.order_number
|
order_number: parent.order_number
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -242,7 +257,7 @@ const ManageMenusContextProvider = ({ children }: { children: React.ReactNode })
|
|||||||
const total_count = transformedData.length;
|
const total_count = transformedData.length;
|
||||||
const paginatedData = transformedData.slice(page * limit, (page + 1) * limit);
|
const paginatedData = transformedData.slice(page * limit, (page + 1) * limit);
|
||||||
|
|
||||||
console.log(response.data);
|
console.log('data', paginatedData);
|
||||||
// setMenus(transformedData);
|
// setMenus(transformedData);
|
||||||
return { data: paginatedData, totalCount: total_count };
|
return { data: paginatedData, totalCount: total_count };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -8,6 +8,8 @@ import { ListToolBar } from '../blocks';
|
|||||||
import { useCallApi } from '@/hooks';
|
import { useCallApi } from '@/hooks';
|
||||||
|
|
||||||
interface ContextProps {
|
interface ContextProps {
|
||||||
|
showSearchDialog: boolean;
|
||||||
|
handleSearchDialog: (show: boolean) => void;
|
||||||
showEditDialog: boolean;
|
showEditDialog: boolean;
|
||||||
handleEditDialog: (show: boolean, selected_user: string | null) => void;
|
handleEditDialog: (show: boolean, selected_user: string | null) => void;
|
||||||
showAddDialog: boolean;
|
showAddDialog: boolean;
|
||||||
@ -35,6 +37,8 @@ interface RoleListProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const initialProps: ContextProps = {
|
const initialProps: ContextProps = {
|
||||||
|
showSearchDialog: false,
|
||||||
|
handleSearchDialog: (show: boolean) => {},
|
||||||
showEditDialog: false,
|
showEditDialog: false,
|
||||||
handleEditDialog: () => {},
|
handleEditDialog: () => {},
|
||||||
showAddDialog: false,
|
showAddDialog: false,
|
||||||
@ -52,6 +56,7 @@ const API_URL = apiConfig.service_dashboard;
|
|||||||
const ManageUserContextProvider = ({ children }: { children: React.ReactNode }) => {
|
const ManageUserContextProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
/* state */
|
/* state */
|
||||||
const [showEditDialog, setShowEditDialog] = useState(false);
|
const [showEditDialog, setShowEditDialog] = useState(false);
|
||||||
|
const [showSearchDialog, setShowSearchDialog] = useState(false);
|
||||||
const [showAddDialog, setShowAddDialog] = useState(false);
|
const [showAddDialog, setShowAddDialog] = useState(false);
|
||||||
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
||||||
const [selectedUser, setSelectedUser] = useState<string | null>(null);
|
const [selectedUser, setSelectedUser] = useState<string | null>(null);
|
||||||
@ -59,6 +64,10 @@ const ManageUserContextProvider = ({ children }: { children: React.ReactNode })
|
|||||||
const { GetData } = useCallApi();
|
const { GetData } = useCallApi();
|
||||||
|
|
||||||
/* action */
|
/* action */
|
||||||
|
const handleSearchDialog = useCallback((show: boolean) => {
|
||||||
|
setShowSearchDialog(show);
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleEditDialog = useCallback((show: boolean, selected_user: string | null) => {
|
const handleEditDialog = useCallback((show: boolean, selected_user: string | null) => {
|
||||||
setSelectedUser(show ? selected_user : null);
|
setSelectedUser(show ? selected_user : null);
|
||||||
setShowEditDialog(show);
|
setShowEditDialog(show);
|
||||||
@ -219,6 +228,8 @@ const ManageUserContextProvider = ({ children }: { children: React.ReactNode })
|
|||||||
return (
|
return (
|
||||||
<ManageUserContext.Provider
|
<ManageUserContext.Provider
|
||||||
value={{
|
value={{
|
||||||
|
showSearchDialog,
|
||||||
|
handleSearchDialog,
|
||||||
showEditDialog,
|
showEditDialog,
|
||||||
handleEditDialog,
|
handleEditDialog,
|
||||||
selectedUser,
|
selectedUser,
|
||||||
|
|||||||
@ -13,7 +13,7 @@ const Transaction = () => {
|
|||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link underline="none" color="inherit">
|
<Link underline="none" color="inherit">
|
||||||
<span className="text-sm">Master Data</span>
|
<span className="text-sm">Transaction</span>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Link underline="none" color="inherit">
|
<Link underline="none" color="inherit">
|
||||||
|
|||||||
538
src/pages/transaction/blocks/DetailTransaction.tsx
Normal file
538
src/pages/transaction/blocks/DetailTransaction.tsx
Normal file
@ -0,0 +1,538 @@
|
|||||||
|
import { useTransactionContext } from '../hooks/useTransactionContext';
|
||||||
|
import { useCallApi } from '@/hooks';
|
||||||
|
import { apiConfig } from '@/config/api.config';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogBody,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle
|
||||||
|
} from '@/components/ui/dialog';
|
||||||
|
|
||||||
|
const API_URL = apiConfig.transaction;
|
||||||
|
|
||||||
|
const DetailTransaction = () => {
|
||||||
|
const { GetData } = useCallApi();
|
||||||
|
const {
|
||||||
|
showDetailDialog,
|
||||||
|
setShowDetailDialog,
|
||||||
|
selectedTransactionId
|
||||||
|
} = useTransactionContext();
|
||||||
|
|
||||||
|
const [transactionDetails, setTransactionDetails] = useState<any>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchTransactionDetails = async () => {
|
||||||
|
if (selectedTransactionId) {
|
||||||
|
try {
|
||||||
|
const response = await GetData(`${API_URL}/transaction/history/detail/${selectedTransactionId}`, {
|
||||||
|
id: selectedTransactionId
|
||||||
|
});
|
||||||
|
// console.log(response?.data);
|
||||||
|
setTransactionDetails(response?.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching transaction', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (showDetailDialog && selectedTransactionId) {
|
||||||
|
fetchTransactionDetails();
|
||||||
|
}
|
||||||
|
}, [showDetailDialog, selectedTransactionId, GetData]);
|
||||||
|
|
||||||
|
const [activeTab, setActiveTab] = useState('detail'); // 'detail', 'log', 'approve'
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={showDetailDialog} onOpenChange={setShowDetailDialog}>
|
||||||
|
<DialogContent className="container-fixed max-w-[1024px] flex flex-col p-5 overflow-hidden">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Transaction Details</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<DialogBody>
|
||||||
|
{/* Tabs Navigation */}
|
||||||
|
<div className="flex border-b border-gray-200">
|
||||||
|
<button
|
||||||
|
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'detail' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
||||||
|
onClick={() => setActiveTab('detail')}
|
||||||
|
>
|
||||||
|
Detail Transaction
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'origincustomer' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
||||||
|
onClick={() => setActiveTab('origincustomer')}
|
||||||
|
>
|
||||||
|
Origin Customer
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'log' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
||||||
|
onClick={() => setActiveTab('log')}
|
||||||
|
>
|
||||||
|
Transaction Log
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'approve' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
||||||
|
onClick={() => setActiveTab('approve')}
|
||||||
|
>
|
||||||
|
Approval Log
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
className={`py-2 px-4 font-medium text-sm focus:outline-none ${activeTab === 'p24' ? 'text-blue-600 border-b-2 border-blue-600' : 'text-gray-500 hover:text-gray-700'}`}
|
||||||
|
onClick={() => setActiveTab('p24')}
|
||||||
|
>
|
||||||
|
Log P24
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Tab Content */}
|
||||||
|
<div className="py-4 overflow-y-auto max-h-[400px]">
|
||||||
|
{activeTab === 'detail' && transactionDetails?.kind === 'P' && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="font-semibold flex items-center">
|
||||||
|
Transaction Information
|
||||||
|
<span className="ml-2 bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">
|
||||||
|
Info
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Transaction Date</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.transaction_date}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Full Name</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.origin_customer.fullname}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Amount</p>
|
||||||
|
<p className="font-medium">{new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(transactionDetails?.purchase.amount)}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Fee</p>
|
||||||
|
<p className="font-medium">
|
||||||
|
{transactionDetails?.kind === 'P'
|
||||||
|
? transactionDetails?.purchase.fee_amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' })
|
||||||
|
: transactionDetails?.transfer.fee_amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' })}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Status</p>
|
||||||
|
<p className="font-medium">
|
||||||
|
{(() => {
|
||||||
|
let status;
|
||||||
|
if (transactionDetails?.status === 'C') {
|
||||||
|
status = 'COMPLETE';
|
||||||
|
} else if (transactionDetails?.status === 'F') {
|
||||||
|
status = 'FAILED';
|
||||||
|
} else if (transactionDetails?.status === 'O') {
|
||||||
|
status = 'ON PROCESS';
|
||||||
|
} else {
|
||||||
|
status = 'PENDING';
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
})()}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Transaction Type</p>
|
||||||
|
<p className="font-medium">
|
||||||
|
{(() => {
|
||||||
|
let kind;
|
||||||
|
if (transactionDetails?.kind === 'T') {
|
||||||
|
kind = 'TRANSFER';
|
||||||
|
} else if (transactionDetails?.kind === 'P') {
|
||||||
|
kind = 'PURCHASE';
|
||||||
|
} else if (transactionDetails?.kind === 'W') {
|
||||||
|
kind = 'WITHDRAW';
|
||||||
|
} else if (transactionDetails?.kind === 'U') {
|
||||||
|
kind = 'TOP UP';
|
||||||
|
} else if (transactionDetails?.kind === 'R') {
|
||||||
|
kind = 'RETURN';
|
||||||
|
}
|
||||||
|
return kind;
|
||||||
|
})()}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Description</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.description}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Name</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.type.name}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="font-semibold flex items-center">
|
||||||
|
Origin Wallet
|
||||||
|
<span className="ml-2 bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">
|
||||||
|
Wallet
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Name</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.origin_wallet.name}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Description</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.origin_wallet.description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="font-semibold flex items-center">
|
||||||
|
Purchase
|
||||||
|
<span className="ml-2 bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">
|
||||||
|
Purchase
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Amount</p>
|
||||||
|
<p className="font-medium">{new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(transactionDetails?.purchase.amount)}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Cashback</p>
|
||||||
|
<p className="font-medium">{new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(transactionDetails?.purchase.cashback)}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Cashback Point</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.purchase.cashback_point}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Fee Amount</p>
|
||||||
|
<p className="font-medium">{new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(transactionDetails?.purchase.fee_amount)}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{activeTab === 'detail' && transactionDetails?.kind != 'P' && transactionDetails?.transfer!=null && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="font-semibold flex items-center">
|
||||||
|
Transaction Information
|
||||||
|
<span className="ml-2 bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">
|
||||||
|
Info
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Transaction Date</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.transaction_date}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Full Name</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.origin_customer.fullname}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Amount</p>
|
||||||
|
<p className="font-medium">{new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(transactionDetails?.transfer.amount)}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Fee</p>
|
||||||
|
<p className="font-medium">
|
||||||
|
{transactionDetails?.transfer.fee_amount.toLocaleString('en-US', { style: 'currency', currency: 'USD' })}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Status</p>
|
||||||
|
<p className="font-medium">
|
||||||
|
{(() => {
|
||||||
|
let status;
|
||||||
|
if (transactionDetails?.status === 'C') {
|
||||||
|
status = 'COMPLETE';
|
||||||
|
} else if (transactionDetails?.status === 'F') {
|
||||||
|
status = 'FAILED';
|
||||||
|
} else if (transactionDetails?.status === 'O') {
|
||||||
|
status = 'ON PROCESS';
|
||||||
|
} else {
|
||||||
|
status = 'PENDING';
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
})()}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Transaction Type</p>
|
||||||
|
<p className="font-medium">
|
||||||
|
{(() => {
|
||||||
|
let kind;
|
||||||
|
if (transactionDetails?.kind === 'T') {
|
||||||
|
kind = 'TRANSFER';
|
||||||
|
} else if (transactionDetails?.kind === 'P') {
|
||||||
|
kind = 'PURCHASE';
|
||||||
|
} else if (transactionDetails?.kind === 'W') {
|
||||||
|
kind = 'WITHDRAW';
|
||||||
|
} else if (transactionDetails?.kind === 'U') {
|
||||||
|
kind = 'TOP UP';
|
||||||
|
} else if (transactionDetails?.kind === 'R') {
|
||||||
|
kind = 'RETURN';
|
||||||
|
}
|
||||||
|
return kind;
|
||||||
|
})()}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Description</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.description}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Name</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.type.name}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Reference</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.transfer.reference}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Destination Iban</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.transfer.destination_iban}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="font-semibold flex items-center">
|
||||||
|
Destination Wallet
|
||||||
|
<span className="ml-2 bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">
|
||||||
|
Wallet
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Name</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.transfer.destination_wallet.name}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Description</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.transfer.destination_wallet.description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="font-semibold flex items-center">
|
||||||
|
Destination Customer
|
||||||
|
<span className="ml-2 bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">
|
||||||
|
Destination Customer
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Name</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.transfer.destination_customer.fullname}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">MSISDN</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.transfer.destination_customer.msisdn}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Email</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.transfer.destination_customer.email}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">MSISDN</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.transfer.destination_customer.username}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="font-semibold flex items-center">
|
||||||
|
Origin Wallet
|
||||||
|
<span className="ml-2 bg-blue-100 text-blue-800 text-xs font-semibold mr-2 px-2.5 py-0.5 rounded">
|
||||||
|
Wallet
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Name</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.origin_wallet.name}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Description</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.origin_wallet.description}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
{activeTab === 'origincustomer' && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="font-semibold">Origin Customer</h3>
|
||||||
|
<div className="grid grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Full Name</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.origin_customer.fullname}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Phone Number</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.origin_customer.msisdn}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Email</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.origin_customer.email}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-sm text-gray-500">Username</p>
|
||||||
|
<p className="font-medium">{transactionDetails?.origin_customer.username}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{activeTab === 'log' && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="font-semibold">Transaction Logs</h3>
|
||||||
|
<div className="border rounded-lg overflow-x-auto">
|
||||||
|
<table className="min-w-full table-auto">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-gray-100">
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Status</th>
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Date</th>
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Body</th>
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Body</th>
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Code</th>
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Request End Point</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{transactionDetails?.log && transactionDetails?.log.length > 0 ? (
|
||||||
|
transactionDetails.log.map((log: { request_endpoint: string, status: string; request_date: string; response_date: string; request_body: string; response_body: string; response_code: number }, index: number) => (
|
||||||
|
<tr key={index} className="border-t">
|
||||||
|
<td className="px-4 py-2 font-medium">
|
||||||
|
{(() => {
|
||||||
|
let status;
|
||||||
|
if (log.status === 'P') {
|
||||||
|
status = 'PENDING';
|
||||||
|
} else if (log.status === 'O') {
|
||||||
|
status = 'ON PROCESS';
|
||||||
|
} else if (log.status === 'F') {
|
||||||
|
status = 'FAILED';
|
||||||
|
} else if (log.status === 'C') {
|
||||||
|
status = 'COMPLETE';
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
})()}
|
||||||
|
</td>
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.request_date ?? '-'}</td>
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.response_date ?? '-'}</td>
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.request_body ?? '-'}</td>
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.response_body ?? '-'}</td>
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.request_endpoint ?? '-'}</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<tr>
|
||||||
|
<td colSpan={3} className="px-4 py-2 text-center text-sm text-gray-500">
|
||||||
|
No logs available
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{activeTab === 'approve' && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="font-semibold">Approval Logs</h3>
|
||||||
|
{transactionDetails?.log_approve.length === 0 ? (
|
||||||
|
<p className="text-sm text-gray-500">No data available</p>
|
||||||
|
) : (
|
||||||
|
<div className="border rounded-lg overflow-x-auto">
|
||||||
|
<table className="min-w-full table-auto">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-gray-100">
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Status</th>
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Created At</th>
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Updated At</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{transactionDetails?.log_approve && transactionDetails?.log_approve.length > 0 ? (
|
||||||
|
transactionDetails.log_approve.map((log: { created_at: string; status: string; updated_at: string }, index: number) => (
|
||||||
|
<tr key={index} className="border-t">
|
||||||
|
<td className="px-4 py-2 font-medium">
|
||||||
|
{(() => {
|
||||||
|
let status;
|
||||||
|
if (log.status === 'W') {
|
||||||
|
status = 'WAITING';
|
||||||
|
} else if (log.status === 'Y') {
|
||||||
|
status = 'APPROVE';
|
||||||
|
} else if (log.status === 'N') {
|
||||||
|
status = 'REJECT';
|
||||||
|
} else if (log.status === 'T') {
|
||||||
|
status = 'NO NEED';
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
})()}
|
||||||
|
</td>
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.created_at}</td>
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.updated_at}</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<tr>
|
||||||
|
<td colSpan={3} className="px-4 py-2 text-center text-sm text-gray-500">
|
||||||
|
No logs available
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{activeTab === 'p24' && (
|
||||||
|
<div className="space-y-4">
|
||||||
|
<h3 className="font-semibold">P24 Logs</h3>
|
||||||
|
{transactionDetails?.p24.length === 0 ? (
|
||||||
|
<p className="text-sm text-gray-500">No data available</p>
|
||||||
|
) : (
|
||||||
|
<div className="border rounded-lg overflow-x-auto">
|
||||||
|
<table className="min-w-full table-auto">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-gray-100">
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Type</th>
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Date</th>
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Body</th>
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Body</th>
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Response Code</th>
|
||||||
|
<th className="px-4 py-2 text-left text-sm text-gray-500">Request Endpoint</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{transactionDetails?.p24 && transactionDetails?.p24.length > 0 ? (
|
||||||
|
transactionDetails.p24.map((log: { request_endpoint: string, type: string; request_date: string; response_date: string; request_body: string; response_body: string; response_code: number }, index: number) => (
|
||||||
|
<tr key={index} className="border-t">
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.type}</td>
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.request_date}</td>
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.response_date}</td>
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.request_body}</td>
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.response_body}</td>
|
||||||
|
<td className="px-4 py-2 text-sm text-gray-500">{log.request_endpoint ?? '-'}</td>
|
||||||
|
</tr>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<tr>
|
||||||
|
<td colSpan={3} className="px-4 py-2 text-center text-sm text-gray-500">
|
||||||
|
No logs available
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</DialogBody>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DetailTransaction;
|
||||||
@ -8,6 +8,7 @@ import { useCallApi } from '@/hooks';
|
|||||||
import ListToolbar from '../blocks/ListToolbar';
|
import ListToolbar from '../blocks/ListToolbar';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
|
import DetailTransaction from '../blocks/DetailTransaction';
|
||||||
|
|
||||||
interface TransactionProps {
|
interface TransactionProps {
|
||||||
id: number;
|
id: number;
|
||||||
@ -23,16 +24,26 @@ interface ContextProps {
|
|||||||
order_direction: any,
|
order_direction: any,
|
||||||
filter: any
|
filter: any
|
||||||
) => Promise<{ data: TransactionProps[]; totalCount: number } | undefined>;
|
) => Promise<{ data: TransactionProps[]; totalCount: number } | undefined>;
|
||||||
|
showDetailDialog: boolean;
|
||||||
|
setShowDetailDialog: React.Dispatch<React.SetStateAction<boolean>>;
|
||||||
|
selectedTransactionId: number | null;
|
||||||
|
setSelectedTransactionId: React.Dispatch<React.SetStateAction<number | null>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialProps: ContextProps = {
|
const initialProps: ContextProps = {
|
||||||
getTransactionLists: async () => ({ data: [], totalCount: 0 })
|
getTransactionLists: async () => ({ data: [], totalCount: 0 }),
|
||||||
|
showDetailDialog: false,
|
||||||
|
setShowDetailDialog: () => { },
|
||||||
|
selectedTransactionId: null,
|
||||||
|
setSelectedTransactionId: () => { }
|
||||||
};
|
};
|
||||||
|
|
||||||
const ManageTransactionContext = createContext<ContextProps>(initialProps);
|
const ManageTransactionContext = createContext<ContextProps>(initialProps);
|
||||||
const API_URL = apiConfig.transaction;
|
const API_URL = apiConfig.transaction;
|
||||||
|
|
||||||
const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
|
const [showDetailDialog, setShowDetailDialog] = useState(false);
|
||||||
|
const [selectedTransactionId, setSelectedTransactionId] = useState<number | null>(null);
|
||||||
const [transaction, setTransaction] = useState<TransactionProps[]>([]);
|
const [transaction, setTransaction] = useState<TransactionProps[]>([]);
|
||||||
const { GetData } = useCallApi();
|
const { GetData } = useCallApi();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -42,6 +53,15 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
|
|
||||||
const columns = useMemo<ColumnDef<any>[]>(
|
const columns = useMemo<ColumnDef<any>[]>(
|
||||||
() => [
|
() => [
|
||||||
|
// {
|
||||||
|
// accessorKey: 'transaction_date',
|
||||||
|
// header: ({ column }) => <DataGridColumnHeader title="Transaction Date" column={column} />,
|
||||||
|
// enableSorting: false,
|
||||||
|
// enableHiding: false,
|
||||||
|
// meta: {
|
||||||
|
// headerClassName: 'w-[250px]'
|
||||||
|
// }
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
accessorKey: 'transaction_date',
|
accessorKey: 'transaction_date',
|
||||||
header: ({ column }) => <DataGridColumnHeader title="Transaction Date" column={column} />,
|
header: ({ column }) => <DataGridColumnHeader title="Transaction Date" column={column} />,
|
||||||
@ -49,8 +69,22 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
meta: {
|
meta: {
|
||||||
headerClassName: 'w-[250px]'
|
headerClassName: 'w-[250px]'
|
||||||
|
},
|
||||||
|
cell: ({ row }) => {
|
||||||
|
// Memformat tanggal dan waktu dari ISO ke format biasa (DD-MM-YYYY HH:MM:SS)
|
||||||
|
const transactionDate = new Date(row.original.transaction_date);
|
||||||
|
const formattedDateTime = transactionDate.toLocaleString('en-GB', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
|
year: 'numeric',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
second: '2-digit',
|
||||||
|
hour12: false // Gunakan format 24 jam
|
||||||
|
});
|
||||||
|
return formattedDateTime; // Format DD-MM-YYYY HH:MM:SS (menggunakan waktu yang sudah ada)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: 'origin_customer.fullname',
|
accessorKey: 'origin_customer.fullname',
|
||||||
header: ({ column }) => <DataGridColumnHeader title="Full Name" column={column} />,
|
header: ({ column }) => <DataGridColumnHeader title="Full Name" column={column} />,
|
||||||
@ -61,8 +95,12 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorFn: (row) =>
|
accessorFn: (row) => {
|
||||||
new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(row.purchase.amount),
|
const purchaseAmount = row?.purchase?.amount;
|
||||||
|
const transferAmount = row?.transfer?.amount;
|
||||||
|
|
||||||
|
return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(purchaseAmount ?? transferAmount ?? 0);
|
||||||
|
},
|
||||||
id: 'amount',
|
id: 'amount',
|
||||||
header: ({ column }) => <DataGridColumnHeader title="Amount" column={column} />,
|
header: ({ column }) => <DataGridColumnHeader title="Amount" column={column} />,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
@ -73,19 +111,13 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorFn: (row) => {
|
accessorFn: (row) => {
|
||||||
let fee;
|
const purchaseAmount = row?.purchase?.fee_amount;
|
||||||
if (row.kind === 'P') {
|
const transferAmount = row?.transfer?.fee_amount;
|
||||||
fee = row.purchase.fee_amount;
|
|
||||||
} else {
|
return new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(purchaseAmount ?? transferAmount ?? 0);
|
||||||
fee = row.transfer.fee_amount;
|
|
||||||
}
|
|
||||||
return fee.toLocaleString('en-US', {
|
|
||||||
style: 'currency',
|
|
||||||
currency: 'USD',
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
accessorKey: 'fee',
|
id: 'feeamount',
|
||||||
header: ({ column }) => <DataGridColumnHeader title="Fee" column={column} />,
|
header: ({ column }) => <DataGridColumnHeader title="Fee Amount" column={column} />,
|
||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
meta: {
|
meta: {
|
||||||
@ -97,9 +129,9 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
let status;
|
let status;
|
||||||
if (row.status === 'C') {
|
if (row.status === 'C') {
|
||||||
status = 'COMPLETE';
|
status = 'COMPLETE';
|
||||||
} else if(row.status === 'F') {
|
} else if (row.status === 'F') {
|
||||||
status = 'FAILED';
|
status = 'FAILED';
|
||||||
} else if(row.status === 'O') {
|
} else if (row.status === 'O') {
|
||||||
status = 'ON PROCESS';
|
status = 'ON PROCESS';
|
||||||
} else {
|
} else {
|
||||||
status = 'PENDING';
|
status = 'PENDING';
|
||||||
@ -138,13 +170,19 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
enableSorting: false,
|
enableSorting: false,
|
||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
cell: (data) => {
|
cell: (data) => {
|
||||||
const row = data.row.original.id;
|
const row = data.row.original;
|
||||||
return (
|
return (
|
||||||
<>
|
<div key={`actions-${row.id}`}>
|
||||||
<button className="btn btn-sm btn-icon btn-clear btn-light">
|
<button
|
||||||
|
className="btn btn-sm btn-icon btn-clear btn-light"
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedTransactionId(row.id);
|
||||||
|
setShowDetailDialog(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
<KeenIcon icon="eye" />
|
<KeenIcon icon="eye" />
|
||||||
</button>
|
</button>
|
||||||
</>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
meta: {
|
meta: {
|
||||||
@ -161,25 +199,25 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
let enddate;
|
let enddate;
|
||||||
let formattedFilter;
|
let formattedFilter;
|
||||||
|
|
||||||
if (filter == undefined || filter.length==0) {
|
if (filter == undefined || filter.length == 0) {
|
||||||
const today = new Date();
|
const today = new Date();
|
||||||
const nextWeek = new Date();
|
const nextWeek = new Date();
|
||||||
nextWeek.setDate(today.getDate() + 7);
|
nextWeek.setDate(today.getDate() + 7);
|
||||||
|
|
||||||
startdate = today.toISOString().split('T')[0];
|
startdate = today.toISOString().split('T')[0];
|
||||||
enddate = nextWeek.toISOString().split('T')[0];
|
enddate = nextWeek.toISOString().split('T')[0];
|
||||||
}else if (filter != undefined || filter.length!=0) {
|
} else if (filter != undefined || filter.length != 0) {
|
||||||
startdate = filter[0].value.from;
|
startdate = filter[0].value.from;
|
||||||
enddate = filter[0].value.to;
|
enddate = filter[0].value.to;
|
||||||
}
|
}
|
||||||
|
|
||||||
formattedFilter = {
|
formattedFilter = {
|
||||||
"Transactions.transaction_date": {
|
"Transactions.transaction_date": {
|
||||||
from: startdate+" 00:00:00",
|
from: startdate + " 00:00:00",
|
||||||
to: enddate+" 23:59:59"
|
to: enddate + " 23:59:59"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await GetData(`${API_URL}/transaction/history`, {
|
const response = await GetData(`${API_URL}/transaction/history`, {
|
||||||
limit,
|
limit,
|
||||||
page: page + 1,
|
page: page + 1,
|
||||||
@ -199,10 +237,15 @@ const TransactionProvider = ({ children }: { children: React.ReactNode }) => {
|
|||||||
return (
|
return (
|
||||||
<ManageTransactionContext.Provider
|
<ManageTransactionContext.Provider
|
||||||
value={{
|
value={{
|
||||||
getTransactionLists
|
getTransactionLists,
|
||||||
|
showDetailDialog,
|
||||||
|
setShowDetailDialog,
|
||||||
|
selectedTransactionId,
|
||||||
|
setSelectedTransactionId
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Toaster expand visibleToasts={9} duration={3000} />
|
<Toaster expand visibleToasts={9} duration={3000} />
|
||||||
|
<DetailTransaction />
|
||||||
|
|
||||||
<DataGridProvider
|
<DataGridProvider
|
||||||
columns={columns}
|
columns={columns}
|
||||||
|
|||||||
@ -150,9 +150,7 @@ const AddFeeDialog = () => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
for (const key in formField) {
|
for (const key in formField) {
|
||||||
if (
|
if (
|
||||||
formField[key as keyof typeof formField] === '' ||
|
formField[key as keyof typeof formField] === '' ) {
|
||||||
formField[key as keyof typeof formField] === 0
|
|
||||||
) {
|
|
||||||
setAlert({ show: true, message: 'All fields must be filled out' });
|
setAlert({ show: true, message: 'All fields must be filled out' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -163,7 +161,7 @@ const AddFeeDialog = () => {
|
|||||||
...formField
|
...formField
|
||||||
});
|
});
|
||||||
if (response?.status) {
|
if (response?.status) {
|
||||||
toast.success('Success Create Transfer Fee');
|
// toast.success('Success Create Transfer Fee');
|
||||||
reload();
|
reload();
|
||||||
resetForm();
|
resetForm();
|
||||||
handleAddFeeDialog(false);
|
handleAddFeeDialog(false);
|
||||||
@ -225,7 +223,7 @@ const AddFeeDialog = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Minimum Amount <span className="text-red-500">*</span></label>
|
<label className="form-label">Minimum Amount</label>
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
className="input"
|
className="input"
|
||||||
value={formField.minimum_amount}
|
value={formField.minimum_amount}
|
||||||
@ -242,7 +240,7 @@ const AddFeeDialog = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Maximum Amount <span className="text-red-500">*</span></label>
|
<label className="form-label">Maximum Amount</label>
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
className="input"
|
className="input"
|
||||||
value={formField.maximum_amount}
|
value={formField.maximum_amount}
|
||||||
@ -283,7 +281,7 @@ const AddFeeDialog = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Deduct Amount <span className="text-red-500">*</span></label>
|
<label className="form-label">Deduct Amount</label>
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
className="input"
|
className="input"
|
||||||
value={formField.deduct_amount}
|
value={formField.deduct_amount}
|
||||||
@ -300,7 +298,7 @@ const AddFeeDialog = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Deduct Percentage <span className="text-red-500">*</span></label>
|
<label className="form-label">Deduct Percentage</label>
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
className="input"
|
className="input"
|
||||||
value={formField.deduct_percentage}
|
value={formField.deduct_percentage}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog';
|
import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle , DialogDescription} from '@/components/ui/dialog';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Alert, useDataGrid } from '@/components';
|
import { Alert, useDataGrid } from '@/components';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
@ -6,7 +6,6 @@ import { apiConfig } from '@/config/api.config';
|
|||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import { useCallApi } from '@/hooks';
|
import { useCallApi } from '@/hooks';
|
||||||
import { useManageTransferFeeContext } from '../hooks/useManageTransferFeeContext';
|
import { useManageTransferFeeContext } from '../hooks/useManageTransferFeeContext';
|
||||||
import { DialogDescription } from '@radix-ui/react-dialog';
|
|
||||||
|
|
||||||
const API_URL = apiConfig.service_transaction;
|
const API_URL = apiConfig.service_transaction;
|
||||||
|
|
||||||
@ -27,10 +26,10 @@ const DeleteDialog = () => {
|
|||||||
if (response?.status) {
|
if (response?.status) {
|
||||||
setAlert({ show: false, message: '' });
|
setAlert({ show: false, message: '' });
|
||||||
handleDeleteFeeDialog(false, null);
|
handleDeleteFeeDialog(false, null);
|
||||||
toast.success('Success Delete Product');
|
// toast.success('Success Delete Transaction Fee');
|
||||||
reload();
|
reload();
|
||||||
} else {
|
} else {
|
||||||
toast.error('Failed Delete Product');
|
// toast.error('Failed Delete Transaction Fee');
|
||||||
setAlert({ show: true, message: response?.message });
|
setAlert({ show: true, message: response?.message });
|
||||||
}
|
}
|
||||||
}, [selectedTransferFee]);
|
}, [selectedTransferFee]);
|
||||||
|
|||||||
@ -96,10 +96,11 @@ const EditFeeDialog = () => {
|
|||||||
async (e: React.FormEvent<HTMLFormElement>) => {
|
async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const response = await PutData(`${API_URL}/transactionfees/update/${selectedTransferFee}`, {
|
const response = await PutData(`${API_URL}/transactionfees/update/${selectedTransferFee}`, {
|
||||||
...formField, });
|
...formField
|
||||||
|
});
|
||||||
if (response?.status) {
|
if (response?.status) {
|
||||||
handleEditFeeDialog(false, null);
|
handleEditFeeDialog(false, null);
|
||||||
toast.success('Success Update User');
|
// toast.success('Success Update Transaction Fee');
|
||||||
reload();
|
reload();
|
||||||
} else {
|
} else {
|
||||||
setAlert((prev) => ({ ...prev, show: true, message: response?.message }));
|
setAlert((prev) => ({ ...prev, show: true, message: response?.message }));
|
||||||
@ -252,7 +253,9 @@ const EditFeeDialog = () => {
|
|||||||
<div className="card flex flex-col gap-5">
|
<div className="card flex flex-col gap-5">
|
||||||
<div className="card-body grid gap-5 p-0">
|
<div className="card-body grid gap-5 p-0">
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Transfer Free Name <span className="text-red-500">*</span></label>
|
<label className="form-label">
|
||||||
|
Transfer Free Name <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<Input
|
<Input
|
||||||
className="input"
|
className="input"
|
||||||
type="text"
|
type="text"
|
||||||
@ -264,7 +267,9 @@ const EditFeeDialog = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Description <span className="text-red-500">*</span></label>
|
<label className="form-label">
|
||||||
|
Description <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<Input
|
<Input
|
||||||
className="input"
|
className="input"
|
||||||
type="text"
|
type="text"
|
||||||
@ -276,7 +281,9 @@ const EditFeeDialog = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Minimum Amount <span className="text-red-500">*</span></label>
|
<label className="form-label">
|
||||||
|
Minimum Amount
|
||||||
|
</label>
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
className="input"
|
className="input"
|
||||||
value={formField.minimum_amount}
|
value={formField.minimum_amount}
|
||||||
@ -293,7 +300,9 @@ const EditFeeDialog = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Maximum Amount <span className="text-red-500">*</span></label>
|
<label className="form-label">
|
||||||
|
Maximum Amount
|
||||||
|
</label>
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
className="input"
|
className="input"
|
||||||
value={formField.maximum_amount}
|
value={formField.maximum_amount}
|
||||||
@ -310,7 +319,9 @@ const EditFeeDialog = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Period Start <span className="text-red-500">*</span></label>
|
<label className="form-label">
|
||||||
|
Period Start <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<Input
|
<Input
|
||||||
className="input"
|
className="input"
|
||||||
type="date"
|
type="date"
|
||||||
@ -322,7 +333,9 @@ const EditFeeDialog = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Period End <span className="text-red-500">*</span></label>
|
<label className="form-label">
|
||||||
|
Period End <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<Input
|
<Input
|
||||||
className="input"
|
className="input"
|
||||||
type="date"
|
type="date"
|
||||||
@ -334,7 +347,8 @@ const EditFeeDialog = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Deduct Amount <span className="text-red-500">*</span></label>
|
<label className="form-label">
|
||||||
|
Deduct Amount</label>
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
className="input"
|
className="input"
|
||||||
value={formField.deduct_amount}
|
value={formField.deduct_amount}
|
||||||
@ -351,7 +365,8 @@ const EditFeeDialog = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Deduct Percentage <span className="text-red-500">*</span></label>
|
<label className="form-label">
|
||||||
|
Deduct Percentage </label>
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
className="input"
|
className="input"
|
||||||
value={formField.deduct_percentage}
|
value={formField.deduct_percentage}
|
||||||
@ -368,7 +383,9 @@ const EditFeeDialog = () => {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Transacsion Type ID <span className="text-red-500">*</span></label>
|
<label className="form-label">
|
||||||
|
Transacsion Type ID <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<Select
|
<Select
|
||||||
value={formField.transaction_type}
|
value={formField.transaction_type}
|
||||||
onValueChange={(transaction_type) =>
|
onValueChange={(transaction_type) =>
|
||||||
@ -388,7 +405,9 @@ const EditFeeDialog = () => {
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Status <span className="text-red-500">*</span></label>
|
<label className="form-label">
|
||||||
|
Status <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<Select
|
<Select
|
||||||
value={formField.status}
|
value={formField.status}
|
||||||
onValueChange={(value) => setFormField({ ...formField, status: value })}
|
onValueChange={(value) => setFormField({ ...formField, status: value })}
|
||||||
@ -403,7 +422,9 @@ const EditFeeDialog = () => {
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Status Included <span className="text-red-500">*</span></label>
|
<label className="form-label">
|
||||||
|
Status Included <span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<Select
|
<Select
|
||||||
value={formField.status_include}
|
value={formField.status_include}
|
||||||
onValueChange={(value) =>
|
onValueChange={(value) =>
|
||||||
@ -420,20 +441,22 @@ const EditFeeDialog = () => {
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<label className="form-label">Priority <span className="text-red-500">*</span></label>
|
<label className="form-label">
|
||||||
<Select
|
Priority <span className="text-red-500">*</span>
|
||||||
value={formField.priority}
|
</label>
|
||||||
onValueChange={(value) => setFormField({ ...formField, priority: value })}
|
<Select
|
||||||
>
|
value={formField.priority}
|
||||||
<SelectTrigger>
|
onValueChange={(value) => setFormField({ ...formField, priority: value })}
|
||||||
<SelectValue placeholder="Select Priority" />
|
>
|
||||||
</SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectContent>
|
<SelectValue placeholder="Select Priority" />
|
||||||
<SelectItem value="Y">Yes</SelectItem>
|
</SelectTrigger>
|
||||||
<SelectItem value="N">No</SelectItem>
|
<SelectContent>
|
||||||
</SelectContent>
|
<SelectItem value="Y">Yes</SelectItem>
|
||||||
</Select>
|
<SelectItem value="N">No</SelectItem>
|
||||||
</div>
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* <div className="w-full">
|
{/* <div className="w-full">
|
||||||
<label className="form-label">Priotity <span className="text-red-500">*</span></label>
|
<label className="form-label">Priotity <span className="text-red-500">*</span></label>
|
||||||
|
|||||||
@ -10,10 +10,10 @@ import { EditFeeDialog } from '../blocks/EditDialog';
|
|||||||
|
|
||||||
interface ContextProps {
|
interface ContextProps {
|
||||||
showEditFeeDialog: boolean;
|
showEditFeeDialog: boolean;
|
||||||
handleEditFeeDialog: (show: boolean, selectedTransferFee: string | null) => void;
|
handleEditFeeDialog: (show: boolean, selected_TransferFee: string | null) => void;
|
||||||
showAddFeeDialog: boolean;
|
showAddFeeDialog: boolean;
|
||||||
handleAddFeeDialog: (show: boolean) => void;
|
handleAddFeeDialog: (show: boolean) => void;
|
||||||
handleDeleteFeeDialog: (show: boolean, selectedTransferFee: string | null) => void;
|
handleDeleteFeeDialog: (show: boolean, selected_TransferFee: string | null) => void;
|
||||||
showDeleteFeeDialog: boolean;
|
showDeleteFeeDialog: boolean;
|
||||||
selectedTransferFee: string | null;
|
selectedTransferFee: string | null;
|
||||||
}
|
}
|
||||||
@ -39,8 +39,8 @@ const ManageTransferFeeContextProvider = ({ children }: { children: React.ReactN
|
|||||||
const [selectedTransferFee, setSelectedTransferFee] = useState<string | null>(null);
|
const [selectedTransferFee, setSelectedTransferFee] = useState<string | null>(null);
|
||||||
const { GetData } = useCallApi();
|
const { GetData } = useCallApi();
|
||||||
|
|
||||||
const handleEditFeeDialog = useCallback((show: boolean, selectedTransferFee: string | null) => {
|
const handleEditFeeDialog = useCallback((show: boolean, selected_TransferFee: string | null) => {
|
||||||
setSelectedTransferFee(show ? selectedTransferFee : null);
|
setSelectedTransferFee(show ? selected_TransferFee : null);
|
||||||
setShowEditFeeDialog(show);
|
setShowEditFeeDialog(show);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -48,8 +48,8 @@ const ManageTransferFeeContextProvider = ({ children }: { children: React.ReactN
|
|||||||
setShowAddFeeDialog(show);
|
setShowAddFeeDialog(show);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const handleDeleteFeeDialog = useCallback((show: boolean, selectedTransferFee: string | null) => {
|
const handleDeleteFeeDialog = useCallback((show: boolean, selected_TransferFee: string | null) => {
|
||||||
setSelectedTransferFee(show ? selectedTransferFee : null);
|
setSelectedTransferFee(show ? selected_TransferFee : null);
|
||||||
setShowDeleteFeeDialog(show);
|
setShowDeleteFeeDialog(show);
|
||||||
}, []);
|
}, []);
|
||||||
const doGetTransferFeeListData = async (
|
const doGetTransferFeeListData = async (
|
||||||
@ -62,7 +62,7 @@ const ManageTransferFeeContextProvider = ({ children }: { children: React.ReactN
|
|||||||
filter = filter.length == 0 ? {} : { any: filter[0].value.toLowerCase() };
|
filter = filter.length == 0 ? {} : { any: filter[0].value.toLowerCase() };
|
||||||
const response = await GetData(`${API_URL}/transactionfees/list`, {
|
const response = await GetData(`${API_URL}/transactionfees/list`, {
|
||||||
limit: limit,
|
limit: limit,
|
||||||
page: 1,
|
page: page+1,
|
||||||
with_deleted: false,
|
with_deleted: false,
|
||||||
order_field: sorting[0].id,
|
order_field: sorting[0].id,
|
||||||
order_direction: sorting[0].desc ? 'ASC' : 'DESC',
|
order_direction: sorting[0].desc ? 'ASC' : 'DESC',
|
||||||
@ -203,9 +203,9 @@ const ManageTransferFeeContextProvider = ({ children }: { children: React.ReactN
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto py-5">
|
<div className="container mx-auto py-5">
|
||||||
<div className="flex justify-between items-center mb-4">
|
<div className="flex justify-between items-center mt-6">
|
||||||
<h1 className="text-2xl font-semibold">Manage Transaction Fee</h1>
|
<h1 className="text-xl font-semibold text-gray-900">Manage Transaction Fee</h1>
|
||||||
</div>
|
</div>
|
||||||
<ManageTransferFeeContext.Provider
|
<ManageTransferFeeContext.Provider
|
||||||
value={{
|
value={{
|
||||||
showEditFeeDialog,
|
showEditFeeDialog,
|
||||||
|
|||||||
@ -165,10 +165,7 @@ const AddDialog = () => {
|
|||||||
async (e: React.FormEvent<HTMLFormElement>) => {
|
async (e: React.FormEvent<HTMLFormElement>) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
for (const key in formField) {
|
for (const key in formField) {
|
||||||
if (
|
if (formField[key as keyof typeof formField] === '') {
|
||||||
formField[key as keyof typeof formField] === '' ||
|
|
||||||
formField[key as keyof typeof formField] === 0
|
|
||||||
) {
|
|
||||||
setAlert({ show: true, message: 'All fields must be filled out' });
|
setAlert({ show: true, message: 'All fields must be filled out' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -229,6 +226,7 @@ const AddDialog = () => {
|
|||||||
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
<label className="form-label flex items-center gap-1 max-w-56">
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
Transfer Type Name
|
Transfer Type Name
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<Input
|
<Input
|
||||||
className="input"
|
className="input"
|
||||||
@ -246,6 +244,7 @@ const AddDialog = () => {
|
|||||||
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
<label className="form-label flex items-center gap-1 max-w-56">
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
Description
|
Description
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<Input
|
<Input
|
||||||
className="input"
|
className="input"
|
||||||
@ -325,7 +324,10 @@ const AddDialog = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-center flex-wrap gap-2.5">
|
<div className="flex items-center flex-wrap gap-2.5">
|
||||||
<label className="form-label max-w-56">From Account</label>
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
From Account
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
<Select
|
<Select
|
||||||
value={formField.wallet_origin}
|
value={formField.wallet_origin}
|
||||||
@ -350,7 +352,10 @@ const AddDialog = () => {
|
|||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-center flex-wrap gap-2.5">
|
<div className="flex items-center flex-wrap gap-2.5">
|
||||||
<label className="form-label max-w-56">To Account</label>
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
To Account
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
<Select
|
<Select
|
||||||
value={formField.wallet_destination}
|
value={formField.wallet_destination}
|
||||||
@ -374,7 +379,10 @@ const AddDialog = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-center flex-wrap gap-2.5">
|
<div className="flex items-center flex-wrap gap-2.5">
|
||||||
<label className="form-label max-w-56">Wallet Destination Fee</label>
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Wallet Destination Fee
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
<Select
|
<Select
|
||||||
value={formField.wallet_fee_destination}
|
value={formField.wallet_fee_destination}
|
||||||
@ -398,7 +406,10 @@ const AddDialog = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-center flex-wrap gap-2.5">
|
<div className="flex items-center flex-wrap gap-2.5">
|
||||||
<label className="form-label max-w-56">Customer Fee Destination</label>
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Customer Fee Destination
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
<Select
|
<Select
|
||||||
value={formField.customer_fee_destination}
|
value={formField.customer_fee_destination}
|
||||||
@ -423,7 +434,10 @@ const AddDialog = () => {
|
|||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-center flex-wrap gap-2.5">
|
<div className="flex items-center flex-wrap gap-2.5">
|
||||||
<label className="form-label max-w-56">Status Approval</label>
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Status Approval
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
<Select
|
<Select
|
||||||
@ -446,7 +460,10 @@ const AddDialog = () => {
|
|||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-center flex-wrap gap-2.5">
|
<div className="flex items-center flex-wrap gap-2.5">
|
||||||
<label className="form-label max-w-56">Status</label>
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Status
|
||||||
|
<span className="text-red-500"> *</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
<Select
|
<Select
|
||||||
|
|||||||
@ -34,7 +34,7 @@ const DeleteDialog = () => {
|
|||||||
setAlert({ show: false, message: '' });
|
setAlert({ show: false, message: '' });
|
||||||
handleDeleteDialog(false, null);
|
handleDeleteDialog(false, null);
|
||||||
reload();
|
reload();
|
||||||
setTimeout(() => toast.success('Success Delete Product'), 0);
|
setTimeout(() => toast.success('Success Delete Transaction Type'), 0);
|
||||||
} else {
|
} else {
|
||||||
setAlert({ show: true, message: response?.message });
|
setAlert({ show: true, message: response?.message });
|
||||||
setTimeout(() => toast.error('Failed Delete Product'), 0);
|
setTimeout(() => toast.error('Failed Delete Product'), 0);
|
||||||
|
|||||||
@ -124,7 +124,7 @@ const EditDialog = () => {
|
|||||||
});
|
});
|
||||||
if (response?.status) {
|
if (response?.status) {
|
||||||
handleEditDialog(false, null);
|
handleEditDialog(false, null);
|
||||||
toast.success('Success Update User');
|
toast.success('Success Update Transfer Type');
|
||||||
reload();
|
reload();
|
||||||
} else {
|
} else {
|
||||||
setAlert((prev) => ({ ...prev, show: true, message: response?.message }));
|
setAlert((prev) => ({ ...prev, show: true, message: response?.message }));
|
||||||
@ -240,7 +240,7 @@ const EditDialog = () => {
|
|||||||
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
<label className="form-label flex items-center gap-1 max-w-56">
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
Transfer Type Name
|
Transfer Type Name
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<Input
|
<Input
|
||||||
className="input"
|
className="input"
|
||||||
@ -258,7 +258,7 @@ const EditDialog = () => {
|
|||||||
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
<label className="form-label flex items-center gap-1 max-w-56">
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
Description
|
Description
|
||||||
<span className="text-red-500">*</span>
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<Input
|
<Input
|
||||||
className="input"
|
className="input"
|
||||||
@ -276,7 +276,6 @@ const EditDialog = () => {
|
|||||||
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
<label className="form-label flex items-center gap-1 max-w-56">
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
Minimum Amount
|
Minimum Amount
|
||||||
<span className="text-red-500">*</span>
|
|
||||||
</label>
|
</label>
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
className="input"
|
className="input"
|
||||||
@ -287,7 +286,7 @@ const EditDialog = () => {
|
|||||||
onValueChange={(values) => {
|
onValueChange={(values) => {
|
||||||
setFormField((prev) => ({
|
setFormField((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
maximum_amount: values.floatValue || 0
|
minimum_amount: values.floatValue || 0
|
||||||
}));
|
}));
|
||||||
}}
|
}}
|
||||||
placeholder="Enter Minimum Amount"
|
placeholder="Enter Minimum Amount"
|
||||||
@ -299,7 +298,6 @@ const EditDialog = () => {
|
|||||||
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
<label className="form-label flex items-center gap-1 max-w-56">
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
Maximum Amount
|
Maximum Amount
|
||||||
<span className="text-red-500">*</span>
|
|
||||||
</label>
|
</label>
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
className="input"
|
className="input"
|
||||||
@ -320,8 +318,7 @@ const EditDialog = () => {
|
|||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
<div className="flex items-baseline flex-wrap lg:flex-nowrap gap-2.5">
|
||||||
<label className="form-label flex items-center gap-1 max-w-56">
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
Maximum Transaction per day
|
Max Transaction per day
|
||||||
<span className="text-red-500">*</span>
|
|
||||||
</label>
|
</label>
|
||||||
<NumericFormat
|
<NumericFormat
|
||||||
className="input"
|
className="input"
|
||||||
@ -341,7 +338,9 @@ const EditDialog = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-center flex-wrap gap-2.5">
|
<div className="flex items-center flex-wrap gap-2.5">
|
||||||
<label className="form-label max-w-56">From Account<span className="text-red-500">*</span>
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
From Account
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
<Select
|
<Select
|
||||||
@ -354,8 +353,8 @@ const EditDialog = () => {
|
|||||||
<SelectValue placeholder="Select Wallet" />
|
<SelectValue placeholder="Select Wallet" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{wallets.map((wallet) => (
|
{wallets.map((wallet, idx) => (
|
||||||
<SelectItem value={wallet.Wallet_id} key={wallet.Wallet_id}>
|
<SelectItem value={wallet.Wallet_id} key={wallet.Wallet_name}>
|
||||||
{wallet.Wallet_name}
|
{wallet.Wallet_name}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
@ -367,7 +366,9 @@ const EditDialog = () => {
|
|||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-center flex-wrap gap-2.5">
|
<div className="flex items-center flex-wrap gap-2.5">
|
||||||
<label className="form-label max-w-56">To Account<span className="text-red-500">*</span>
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
To Account
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
<Select
|
<Select
|
||||||
@ -381,7 +382,7 @@ const EditDialog = () => {
|
|||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{wallets.map((wallet, idx) => (
|
{wallets.map((wallet, idx) => (
|
||||||
<SelectItem value={wallet.Wallet_id} key={wallet.Wallet_name}>
|
<SelectItem value={wallet.Wallet_id} key={wallet.Wallet_id}>
|
||||||
{wallet.Wallet_name}
|
{wallet.Wallet_name}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
@ -392,7 +393,9 @@ const EditDialog = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-center flex-wrap gap-2.5">
|
<div className="flex items-center flex-wrap gap-2.5">
|
||||||
<label className="form-label max-w-56">Wallet Fee Destination<span className="text-red-500">*</span>
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Wallet Destination Fee
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
<Select
|
<Select
|
||||||
@ -406,7 +409,7 @@ const EditDialog = () => {
|
|||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{wallets.map((wallet, idx) => (
|
{wallets.map((wallet, idx) => (
|
||||||
<SelectItem value={wallet.Wallet_id} key={wallet.Wallet_name}>
|
<SelectItem value={wallet.Wallet_id} key={wallet.Wallet_id}>
|
||||||
{wallet.Wallet_name}
|
{wallet.Wallet_name}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
@ -417,7 +420,9 @@ const EditDialog = () => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-center flex-wrap gap-2.5">
|
<div className="flex items-center flex-wrap gap-2.5">
|
||||||
<label className="form-label max-w-56">Select Customer<span className="text-red-500">*</span>
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Customer Fee Destination
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
<Select
|
<Select
|
||||||
@ -427,7 +432,7 @@ const EditDialog = () => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<SelectTrigger>
|
<SelectTrigger>
|
||||||
<SelectValue placeholder="Select" />
|
<SelectValue placeholder="Select Customer" />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{customers.map((customer, idx) => (
|
{customers.map((customer, idx) => (
|
||||||
@ -440,9 +445,12 @@ const EditDialog = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-center flex-wrap gap-2.5">
|
<div className="flex items-center flex-wrap gap-2.5">
|
||||||
<label className="form-label max-w-56">Status Approval<span className="text-red-500">*</span>
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Status Approval
|
||||||
|
<span className="text-red-500">*</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
@ -466,7 +474,9 @@ const EditDialog = () => {
|
|||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="flex items-center flex-wrap gap-2.5">
|
<div className="flex items-center flex-wrap gap-2.5">
|
||||||
<label className="form-label max-w-56">Status<span className="text-red-500">*</span>
|
<label className="form-label flex items-center gap-1 max-w-56">
|
||||||
|
Status
|
||||||
|
<span className="text-red-500"> *</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div className="grow">
|
<div className="grow">
|
||||||
@ -487,6 +497,7 @@ const EditDialog = () => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex justify-end pt-2.5 gap-5">
|
<div className="flex justify-end pt-2.5 gap-5">
|
||||||
<Button
|
<Button
|
||||||
variant={'outline'}
|
variant={'outline'}
|
||||||
|
|||||||
@ -85,6 +85,14 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React
|
|||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
meta: { headerClassName: 'w-[250px]' }
|
meta: { headerClassName: 'w-[250px]' }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.description,
|
||||||
|
id: 'description',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Description" column={column} />,
|
||||||
|
enableSorting: true,
|
||||||
|
enableHiding: false,
|
||||||
|
meta: { headerClassName: 'w-[250px]' }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
accessorFn: (row) => row.wallet_origin?.name || 'N/A',
|
accessorFn: (row) => row.wallet_origin?.name || 'N/A',
|
||||||
id: 'wallet_origin',
|
id: 'wallet_origin',
|
||||||
@ -127,14 +135,6 @@ const ManageTransferTypeContextProvider = ({ children }: { children: React.React
|
|||||||
enableHiding: false,
|
enableHiding: false,
|
||||||
meta: { headerClassName: 'w-[250px]' }
|
meta: { headerClassName: 'w-[250px]' }
|
||||||
},
|
},
|
||||||
{
|
|
||||||
accessorFn: (row) => row.description,
|
|
||||||
id: 'description',
|
|
||||||
header: ({ column }) => <DataGridColumnHeader title="Description" column={column} />,
|
|
||||||
enableSorting: true,
|
|
||||||
enableHiding: false,
|
|
||||||
meta: { headerClassName: 'w-[250px]' }
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
accessorFn: (row) => row.wallet_fee_destination.name,
|
accessorFn: (row) => row.wallet_fee_destination.name,
|
||||||
id: 'wallet_fee_destination',
|
id: 'wallet_fee_destination',
|
||||||
|
|||||||
32
src/pages/wallet/wallet-history/WalletHistory.tsx
Normal file
32
src/pages/wallet/wallet-history/WalletHistory.tsx
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { Container, DataGridInner } from '@/components';
|
||||||
|
import { ManageWalletContextProvider } from './hooks/ManageWalletHistoryContext';
|
||||||
|
import { Breadcrumbs, Link } from '@mui/material';
|
||||||
|
|
||||||
|
const WalletHistory = () => {
|
||||||
|
return (
|
||||||
|
<ManageWalletContextProvider>
|
||||||
|
<Container>
|
||||||
|
<h1 className="text-xl font-medium leading-none text-gray-900 mb-5">Wallet History</h1>
|
||||||
|
<Breadcrumbs sx={{ mb: 2 }}>
|
||||||
|
<Link underline="none" color="inherit" href="/">
|
||||||
|
<span className="text-sm hover:underline">Dashboard</span>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link underline="none" color="inherit">
|
||||||
|
<span className="text-sm">Wallet</span>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
<Link underline="none" color="inherit">
|
||||||
|
<span className="text-sm">Wallet History</span>
|
||||||
|
</Link>
|
||||||
|
</Breadcrumbs>
|
||||||
|
|
||||||
|
<div className="grid gap-5 lg:gap-7.5">
|
||||||
|
<DataGridInner />
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
</ManageWalletContextProvider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WalletHistory;
|
||||||
48
src/pages/wallet/wallet-history/blocks/ListToolbar.tsx
Normal file
48
src/pages/wallet/wallet-history/blocks/ListToolbar.tsx
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components';
|
||||||
|
import { useManageWalletContext } from '../hooks/useManageWalletHistoryContext';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
|
||||||
|
const ListToolbar = () => {
|
||||||
|
const { table, reload } = useDataGrid();
|
||||||
|
const { handleAddDialog } = useManageWalletContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="card-header flex-wrap gap-2 border-b-0 px-5">
|
||||||
|
<div className="flex flex-wrap gap-2 lg:gap-5 w-full">
|
||||||
|
<div className="flex justify-between w-full items-center">
|
||||||
|
<div className="flex w-[50%] gap-3 items-center">
|
||||||
|
<label className="input input-sm w-1/3">
|
||||||
|
<KeenIcon icon="magnifier" />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Search Wallet"
|
||||||
|
value={(table.getColumn('name')?.getFilterValue() as string) ?? ''}
|
||||||
|
onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
{/* <DefaultTooltip title={'Filter'} placement={'top'}>
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="h-7.5 disabled:bg-gray-400"
|
||||||
|
// disabled={isLoading}
|
||||||
|
// onClick={handleFilterData}
|
||||||
|
>
|
||||||
|
{loadingButton === 'filter' ? <ContentLoader /> : <KeenIcon icon="filter" />}
|
||||||
|
<KeenIcon icon="filter" />
|
||||||
|
</Button>
|
||||||
|
</DefaultTooltip> */}
|
||||||
|
</div>
|
||||||
|
<div className="flex gap-3 items-center">
|
||||||
|
<DefaultTooltip title={'Refresh'} placement={'top'}>
|
||||||
|
<Button variant="outline" className="h-7.5" onClick={() => reload()}>
|
||||||
|
<KeenIcon icon="arrows-circle" />
|
||||||
|
</Button>
|
||||||
|
</DefaultTooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ListToolbar;
|
||||||
@ -0,0 +1,211 @@
|
|||||||
|
import { DataGridColumnHeader, DataGridProvider, KeenIcon } from '@/components';
|
||||||
|
import { Toaster } from '@/components/ui/sonner';
|
||||||
|
import { apiConfig } from '@/config/api.config';
|
||||||
|
import { useCallApi } from '@/hooks';
|
||||||
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
|
import React, { createContext, useCallback, useMemo, useState } from 'react';
|
||||||
|
import ListToolbar from '../blocks/ListToolbar';
|
||||||
|
|
||||||
|
interface WalletProps {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
id_currency: string;
|
||||||
|
status: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ContextProps {
|
||||||
|
wallets: WalletProps[];
|
||||||
|
showAddDialog: boolean;
|
||||||
|
handleAddDialog: (show: boolean) => void;
|
||||||
|
showEditDialog: boolean;
|
||||||
|
handleEditDialog: (show: boolean, selected_wallet: WalletProps | null) => void;
|
||||||
|
showDeleteDialog: boolean;
|
||||||
|
handleDeleteDialog: (show: boolean, selected_wallet: WalletProps | null) => void;
|
||||||
|
selectedWallet: WalletProps | null;
|
||||||
|
getWalletLists: (
|
||||||
|
limit: number,
|
||||||
|
page: number,
|
||||||
|
with_deleted: boolean,
|
||||||
|
order_field: any,
|
||||||
|
order_direction: any
|
||||||
|
) => Promise<{ data: WalletProps[]; totalCount: number } | undefined>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialProps: ContextProps = {
|
||||||
|
wallets: [],
|
||||||
|
showAddDialog: false,
|
||||||
|
handleAddDialog: (show: boolean) => {},
|
||||||
|
showEditDialog: false,
|
||||||
|
handleEditDialog: (show: boolean, selected_wallet: object | null) => {},
|
||||||
|
showDeleteDialog: false,
|
||||||
|
handleDeleteDialog: (show: boolean, selected_wallet: object | null) => {},
|
||||||
|
selectedWallet: null,
|
||||||
|
getWalletLists: async () => undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
const ManageWalletContext = createContext<ContextProps>(initialProps);
|
||||||
|
const API_URL_WALLET = apiConfig.service_wallet;
|
||||||
|
|
||||||
|
const ManageWalletContextProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
|
const [wallets, setWallets] = useState<WalletProps[]>([]);
|
||||||
|
const [showAddDialog, setShowAddDialog] = useState(false);
|
||||||
|
const [showEditDialog, setShowEditDialog] = useState(false);
|
||||||
|
const [showDeleteDialog, setShowDeleteDialog] = useState(false);
|
||||||
|
const [selectedWallet, setSelectedWallet] = useState<WalletProps | null>(null);
|
||||||
|
const { GetData } = useCallApi();
|
||||||
|
|
||||||
|
const handleAddDialog = useCallback((show: boolean) => {
|
||||||
|
setShowAddDialog(show);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleEditDialog = useCallback((show: boolean, selected_wallet: WalletProps | null) => {
|
||||||
|
setShowEditDialog(show);
|
||||||
|
setSelectedWallet(show ? selected_wallet : null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleDeleteDialog = useCallback((show: boolean, selected_wallet: WalletProps | null) => {
|
||||||
|
setShowDeleteDialog(show);
|
||||||
|
setSelectedWallet(show ? selected_wallet : null);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const columns = useMemo<ColumnDef<any>[]>(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.name,
|
||||||
|
id: 'name',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Wallet Name" column={column} />,
|
||||||
|
enableSorting: true,
|
||||||
|
enableHiding: false,
|
||||||
|
meta: {
|
||||||
|
headerClassName: 'w-[550px]',
|
||||||
|
cellClassName: 'p-[20px]'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.currency.name,
|
||||||
|
id: 'currency_name',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Currency" column={column} />,
|
||||||
|
enableSorting: false,
|
||||||
|
enableHiding: false,
|
||||||
|
meta: {
|
||||||
|
headerClassName: 'w-[200px]'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.currency.prefix,
|
||||||
|
id: 'currency_prefix',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Prefix" column={column} />,
|
||||||
|
enableSorting: false,
|
||||||
|
enableHiding: false,
|
||||||
|
meta: {
|
||||||
|
headerClassName: 'w-[200px]'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorFn: (row) => row.status,
|
||||||
|
id: 'status',
|
||||||
|
header: ({ column }) => <DataGridColumnHeader title="Status" column={column} />,
|
||||||
|
enableSorting: false,
|
||||||
|
enableHiding: false,
|
||||||
|
cell: ({ row }) => {
|
||||||
|
const isActive = row.original.status === 'Y';
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={`px-2 py-1 text-xs font-semibold rounded-full ${
|
||||||
|
isActive ? 'bg-green-100 text-green-600' : 'bg-red-100 text-red-600'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{isActive ? 'Active' : 'Inactive'}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
meta: {
|
||||||
|
headerClassName: 'w-[100px]',
|
||||||
|
cellClassName: 'text-center'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// {
|
||||||
|
// id: 'actions',
|
||||||
|
// header: ({ column }) => <DataGridColumnHeader title="Actions" column={column} />,
|
||||||
|
// cell: (data) => {
|
||||||
|
// const row = data.row.original;
|
||||||
|
// return (
|
||||||
|
// <>
|
||||||
|
// <button
|
||||||
|
// className="btn btn-sm btn-icon btn-clear btn-light"
|
||||||
|
// onClick={() => handleEditDialog(true, row)}
|
||||||
|
// >
|
||||||
|
// <KeenIcon icon="notepad-edit" />
|
||||||
|
// </button>
|
||||||
|
// <button
|
||||||
|
// className="btn btn-sm btn-icon btn-clear btn-light"
|
||||||
|
// onClick={() => handleDeleteDialog(true, row)}
|
||||||
|
// >
|
||||||
|
// <KeenIcon icon="trash" />
|
||||||
|
// </button>
|
||||||
|
// </>
|
||||||
|
// );
|
||||||
|
// },
|
||||||
|
// meta: {
|
||||||
|
// headerClassName: 'w-[150px]'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
],
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const getWalletLists = async (page: number, limit: number, sorting: any, filter: any) => {
|
||||||
|
try {
|
||||||
|
sorting = sorting.length == 0 ? [{ id: 'name', desc: false }] : sorting;
|
||||||
|
filter = filter.length == 0 ? {} : { name: filter[0].value?.toLowerCase() };
|
||||||
|
const response = await GetData(`${API_URL_WALLET}/dashboard/wallet`, {
|
||||||
|
limit,
|
||||||
|
page: page + 1,
|
||||||
|
with_deleted: false,
|
||||||
|
order_field: sorting[0].id,
|
||||||
|
order_direction: sorting[0].desc == false ? 'ASC' : 'DESC',
|
||||||
|
// filter: JSON.stringify(filter)
|
||||||
|
});
|
||||||
|
console.log(response?.data);
|
||||||
|
setWallets(response?.data.list);
|
||||||
|
return { data: response?.data.list, totalCount: response?.data.total_count };
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching Wallet', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ManageWalletContext.Provider
|
||||||
|
value={{
|
||||||
|
wallets,
|
||||||
|
showAddDialog,
|
||||||
|
handleAddDialog,
|
||||||
|
showEditDialog,
|
||||||
|
handleEditDialog,
|
||||||
|
showDeleteDialog,
|
||||||
|
handleDeleteDialog,
|
||||||
|
selectedWallet,
|
||||||
|
getWalletLists
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Toaster expand visibleToasts={9} duration={3000} />
|
||||||
|
<DataGridProvider
|
||||||
|
columns={columns}
|
||||||
|
pagination={{ size: 5 }}
|
||||||
|
toolbar={<ListToolbar />}
|
||||||
|
layout={{ card: true }}
|
||||||
|
sorting={[{ id: 'id', desc: false }]}
|
||||||
|
serverSide={true}
|
||||||
|
onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) =>
|
||||||
|
getWalletLists(pageIndex, pageSize, sorting, columnFilters)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</DataGridProvider>
|
||||||
|
</ManageWalletContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { ManageWalletContext, ManageWalletContextProvider };
|
||||||
|
export type { WalletProps };
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
import { useContext } from 'react';
|
||||||
|
import { ManageWalletContext } from './ManageWalletHistoryContext';
|
||||||
|
|
||||||
|
const useManageWalletContext = () => {
|
||||||
|
const context = useContext(ManageWalletContext);
|
||||||
|
if (!context) {
|
||||||
|
throw new Error('useManageWalletContext must be used within a ManageWalletContextProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
|
|
||||||
|
export { useManageWalletContext };
|
||||||
@ -34,6 +34,8 @@ import ProductsMaster from '@/pages/master/products/ProductsMaster';
|
|||||||
import ProviderMaster from '@/pages/master/provider/ProviderMaster';
|
import ProviderMaster from '@/pages/master/provider/ProviderMaster';
|
||||||
import ConversionMaster from '@/pages/master/conversion/ConversionMaster';
|
import ConversionMaster from '@/pages/master/conversion/ConversionMaster';
|
||||||
import WalletRuleMaster from '@/pages/master/walletRule/WalletRuleMaster';
|
import WalletRuleMaster from '@/pages/master/walletRule/WalletRuleMaster';
|
||||||
|
import WalletHistory from '@/pages/wallet/wallet-history/WalletHistory';
|
||||||
|
import WalletMaster from '@/pages/master/wallet/WalletMaster';
|
||||||
|
|
||||||
const AppRoutingSetup = (): ReactElement => {
|
const AppRoutingSetup = (): ReactElement => {
|
||||||
return (
|
return (
|
||||||
@ -55,6 +57,9 @@ const AppRoutingSetup = (): ReactElement => {
|
|||||||
element={<PostoAdmsMaster />}
|
element={<PostoAdmsMaster />}
|
||||||
/>
|
/>
|
||||||
<Route path="/master-data/conversion" element={<ConversionMaster />} />
|
<Route path="/master-data/conversion" element={<ConversionMaster />} />
|
||||||
|
|
||||||
|
<Route path="/master-data/wallet" element={<WalletMaster />} />
|
||||||
|
|
||||||
<Route path="/master-data/wallet-rule" element={<WalletRuleMaster />} />
|
<Route path="/master-data/wallet-rule" element={<WalletRuleMaster />} />
|
||||||
|
|
||||||
<Route path="/account/home/user-profile" element={<AccountUserProfilePage />} />
|
<Route path="/account/home/user-profile" element={<AccountUserProfilePage />} />
|
||||||
@ -72,6 +77,8 @@ const AppRoutingSetup = (): ReactElement => {
|
|||||||
|
|
||||||
<Route path="/transfer-type/transfer-type-management" element={<TransferType />} />
|
<Route path="/transfer-type/transfer-type-management" element={<TransferType />} />
|
||||||
|
|
||||||
|
<Route path="/wallet/wallet-history" element={<WalletHistory />} />
|
||||||
|
|
||||||
<Route path="/notification/notification-management" element={<ManageNotification />} />
|
<Route path="/notification/notification-management" element={<ManageNotification />} />
|
||||||
|
|
||||||
<Route path="/transaction" element={<Transaction />} />
|
<Route path="/transaction" element={<Transaction />} />
|
||||||
|
|||||||
74
yarn.lock
74
yarn.lock
@ -39,7 +39,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.0.tgz"
|
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.0.tgz"
|
||||||
integrity sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==
|
integrity sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==
|
||||||
|
|
||||||
"@babel/core@^7.25.2":
|
"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.25.2":
|
||||||
version "7.26.0"
|
version "7.26.0"
|
||||||
resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz"
|
resolved "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz"
|
||||||
integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==
|
integrity sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==
|
||||||
@ -564,7 +564,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz"
|
resolved "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz"
|
||||||
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
|
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
|
||||||
|
|
||||||
"@emotion/react@^11.13.3":
|
"@emotion/react@^11.0.0-rc.0", "@emotion/react@^11.13.3", "@emotion/react@^11.4.1", "@emotion/react@^11.5.0":
|
||||||
version "11.13.3"
|
version "11.13.3"
|
||||||
resolved "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz"
|
resolved "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz"
|
||||||
integrity sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==
|
integrity sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==
|
||||||
@ -594,7 +594,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz"
|
resolved "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz"
|
||||||
integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
|
integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
|
||||||
|
|
||||||
"@emotion/styled@^11.13.0":
|
"@emotion/styled@^11.13.0", "@emotion/styled@^11.3.0":
|
||||||
version "11.13.0"
|
version "11.13.0"
|
||||||
resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz"
|
resolved "https://registry.npmjs.org/@emotion/styled/-/styled-11.13.0.tgz"
|
||||||
integrity sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==
|
integrity sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==
|
||||||
@ -631,10 +631,10 @@
|
|||||||
resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz"
|
resolved "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz"
|
||||||
integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==
|
integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==
|
||||||
|
|
||||||
"@esbuild/win32-x64@0.21.5":
|
"@esbuild/darwin-arm64@0.21.5":
|
||||||
version "0.21.5"
|
version "0.21.5"
|
||||||
resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz"
|
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz"
|
||||||
integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==
|
integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==
|
||||||
|
|
||||||
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
|
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
|
||||||
version "4.4.1"
|
version "4.4.1"
|
||||||
@ -704,7 +704,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@faker-js/faker/-/faker-9.1.0.tgz"
|
resolved "https://registry.npmjs.org/@faker-js/faker/-/faker-9.1.0.tgz"
|
||||||
integrity sha512-GJvX9iM9PBtKScJVlXQ0tWpihK3i0pha/XAhzQa1hPK/ILLa1Wq3I63Ij7lRtqTwmdTxRCyrUhLC5Sly9SLbug==
|
integrity sha512-GJvX9iM9PBtKScJVlXQ0tWpihK3i0pha/XAhzQa1hPK/ILLa1Wq3I63Ij7lRtqTwmdTxRCyrUhLC5Sly9SLbug==
|
||||||
|
|
||||||
"@firebase/app@^0.10.15":
|
"@firebase/app@^0.10.15", "@firebase/app@0.x":
|
||||||
version "0.10.15"
|
version "0.10.15"
|
||||||
resolved "https://registry.npmjs.org/@firebase/app/-/app-0.10.15.tgz"
|
resolved "https://registry.npmjs.org/@firebase/app/-/app-0.10.15.tgz"
|
||||||
integrity sha512-he6qlG3pmwL+LHdG/BrSMBQeJzzutciq4fpXN3lGa1uSwYSijJ24VtakS/bP2X9SiDf8jGywJ4u+OgXAenJsNg==
|
integrity sha512-he6qlG3pmwL+LHdG/BrSMBQeJzzutciq4fpXN3lGa1uSwYSijJ24VtakS/bP2X9SiDf8jGywJ4u+OgXAenJsNg==
|
||||||
@ -991,7 +991,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime" "^7.26.0"
|
"@babel/runtime" "^7.26.0"
|
||||||
|
|
||||||
"@mui/material@^6.1.6":
|
"@mui/material@^6.1.6", "@mui/material@^6.4.6":
|
||||||
version "6.4.8"
|
version "6.4.8"
|
||||||
resolved "https://registry.npmjs.org/@mui/material/-/material-6.4.8.tgz"
|
resolved "https://registry.npmjs.org/@mui/material/-/material-6.4.8.tgz"
|
||||||
integrity sha512-5S9UTjKZZBd9GfbcYh/nYfD9cv6OXmj5Y7NgKYfk7JcSoshp8/pW5zP4wecRiroBSZX8wcrywSgogpVNO+5W0Q==
|
integrity sha512-5S9UTjKZZBd9GfbcYh/nYfD9cv6OXmj5Y7NgKYfk7JcSoshp8/pW5zP4wecRiroBSZX8wcrywSgogpVNO+5W0Q==
|
||||||
@ -1580,10 +1580,10 @@
|
|||||||
resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz"
|
resolved "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz"
|
||||||
integrity sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==
|
integrity sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==
|
||||||
|
|
||||||
"@rollup/rollup-win32-x64-msvc@4.24.2":
|
"@rollup/rollup-darwin-arm64@4.24.2":
|
||||||
version "4.24.2"
|
version "4.24.2"
|
||||||
resolved "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.2.tgz"
|
resolved "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.2.tgz"
|
||||||
integrity sha512-2mLH46K1u3r6uwc95hU+OR9q/ggYMpnS7pSp83Ece1HUQgF9Nh/QwTK5rcgbFnV9j+08yBrU5sA/P0RK2MSBNA==
|
integrity sha512-/UhrIxobHYCBfhi5paTkUDQ0w+jckjRZDZ1kcBL132WeHZQ6+S5v9jQPVGLVrLbNUebdIRpIt00lQ+4Z7ys4Rg==
|
||||||
|
|
||||||
"@tanstack/query-core@5.59.20":
|
"@tanstack/query-core@5.59.20":
|
||||||
version "5.59.20"
|
version "5.59.20"
|
||||||
@ -1672,7 +1672,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/geojson" "*"
|
"@types/geojson" "*"
|
||||||
|
|
||||||
"@types/node@^22.9.0", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
|
"@types/node@^18.0.0 || >=20.0.0", "@types/node@^22.9.0", "@types/node@>=12.12.47", "@types/node@>=13.7.0":
|
||||||
version "22.9.0"
|
version "22.9.0"
|
||||||
resolved "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz"
|
resolved "https://registry.npmjs.org/@types/node/-/node-22.9.0.tgz"
|
||||||
integrity sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==
|
integrity sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==
|
||||||
@ -1689,7 +1689,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz"
|
resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz"
|
||||||
integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==
|
integrity sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==
|
||||||
|
|
||||||
"@types/react-dom@^18.3.1":
|
"@types/react-dom@*", "@types/react-dom@^18.3.1":
|
||||||
version "18.3.1"
|
version "18.3.1"
|
||||||
resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz"
|
resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz"
|
||||||
integrity sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==
|
integrity sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==
|
||||||
@ -1708,7 +1708,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz"
|
resolved "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz"
|
||||||
integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==
|
integrity sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==
|
||||||
|
|
||||||
"@types/react@*", "@types/react@^18.3.12", "@types/react@16 || 17 || 18":
|
"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^16.9.0 || ^17.0.0 || ^18.0.0", "@types/react@^17.0.0 || ^18.0.0", "@types/react@^17.0.0 || ^18.0.0 || ^19.0.0", "@types/react@^18.3.12", "@types/react@16 || 17 || 18":
|
||||||
version "18.3.12"
|
version "18.3.12"
|
||||||
resolved "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz"
|
resolved "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz"
|
||||||
integrity sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==
|
integrity sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==
|
||||||
@ -1750,7 +1750,7 @@
|
|||||||
natural-compare "^1.4.0"
|
natural-compare "^1.4.0"
|
||||||
ts-api-utils "^1.3.0"
|
ts-api-utils "^1.3.0"
|
||||||
|
|
||||||
"@typescript-eslint/parser@^8.14.0", "@typescript-eslint/parser@8.14.0":
|
"@typescript-eslint/parser@^8.0.0 || ^8.0.0-alpha.0", "@typescript-eslint/parser@^8.14.0", "@typescript-eslint/parser@8.14.0":
|
||||||
version "8.14.0"
|
version "8.14.0"
|
||||||
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz"
|
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.14.0.tgz"
|
||||||
integrity sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==
|
integrity sha512-2p82Yn9juUJq0XynBXtFCyrBDb6/dJombnz6vbo6mgQEtWHfvHbQuEa9kAOVIt1c9YFwi7H6WxtPj1kg+80+RA==
|
||||||
@ -1859,7 +1859,7 @@ acorn-jsx@^5.3.2:
|
|||||||
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
||||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||||
|
|
||||||
acorn@^8.12.0:
|
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.12.0:
|
||||||
version "8.14.0"
|
version "8.14.0"
|
||||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz"
|
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz"
|
||||||
integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
|
integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
|
||||||
@ -1909,7 +1909,7 @@ anymatch@~3.1.2:
|
|||||||
normalize-path "^3.0.0"
|
normalize-path "^3.0.0"
|
||||||
picomatch "^2.0.4"
|
picomatch "^2.0.4"
|
||||||
|
|
||||||
apexcharts@3.52.0:
|
apexcharts@^3.41.0, apexcharts@3.52.0:
|
||||||
version "3.52.0"
|
version "3.52.0"
|
||||||
resolved "https://registry.npmjs.org/apexcharts/-/apexcharts-3.52.0.tgz"
|
resolved "https://registry.npmjs.org/apexcharts/-/apexcharts-3.52.0.tgz"
|
||||||
integrity sha512-7dg0ADKs8AA89iYMZMe2sFDG0XK5PfqllKV9N+i3hKHm3vEtdhwz8AlXGm+/b0nJ6jKiaXsqci5LfVxNhtB+dA==
|
integrity sha512-7dg0ADKs8AA89iYMZMe2sFDG0XK5PfqllKV9N+i3hKHm3vEtdhwz8AlXGm+/b0nJ6jKiaXsqci5LfVxNhtB+dA==
|
||||||
@ -2025,7 +2025,7 @@ broadcast-channel@^3.4.1:
|
|||||||
rimraf "3.0.2"
|
rimraf "3.0.2"
|
||||||
unload "2.2.0"
|
unload "2.2.0"
|
||||||
|
|
||||||
browserslist@^4.23.1, browserslist@^4.23.3, browserslist@^4.24.0:
|
browserslist@^4.23.1, browserslist@^4.23.3, browserslist@^4.24.0, "browserslist@>= 4.21.0":
|
||||||
version "4.24.2"
|
version "4.24.2"
|
||||||
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz"
|
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz"
|
||||||
integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==
|
integrity sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==
|
||||||
@ -2239,12 +2239,12 @@ cssjanus@^2.0.1:
|
|||||||
resolved "https://registry.npmjs.org/cssjanus/-/cssjanus-2.3.0.tgz"
|
resolved "https://registry.npmjs.org/cssjanus/-/cssjanus-2.3.0.tgz"
|
||||||
integrity sha512-ZZXXn51SnxRxAZ6fdY7mBDPmA4OZd83q/J9Gdqz3YmE9TUq+9tZl+tdOnCi7PpNygI6PEkehj9rgifv5+W8a5A==
|
integrity sha512-ZZXXn51SnxRxAZ6fdY7mBDPmA4OZd83q/J9Gdqz3YmE9TUq+9tZl+tdOnCi7PpNygI6PEkehj9rgifv5+W8a5A==
|
||||||
|
|
||||||
csstype@^3.0.2, csstype@^3.1.3, csstype@3.1.3:
|
csstype@^3.0.10, csstype@^3.0.2, csstype@^3.1.3, csstype@3.1.3:
|
||||||
version "3.1.3"
|
version "3.1.3"
|
||||||
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
|
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz"
|
||||||
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
||||||
|
|
||||||
date-fns@^3.0.0:
|
"date-fns@^2.28.0 || ^3.0.0", date-fns@^3.0.0:
|
||||||
version "3.6.0"
|
version "3.6.0"
|
||||||
resolved "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz"
|
resolved "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz"
|
||||||
integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==
|
integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==
|
||||||
@ -2386,7 +2386,7 @@ escape-string-regexp@^4.0.0:
|
|||||||
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
|
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
|
||||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||||
|
|
||||||
eslint-config-prettier@^9.1.0:
|
eslint-config-prettier@*, eslint-config-prettier@^9.1.0:
|
||||||
version "9.1.0"
|
version "9.1.0"
|
||||||
resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz"
|
resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz"
|
||||||
integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==
|
integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==
|
||||||
@ -2427,7 +2427,7 @@ eslint-visitor-keys@^4.1.0:
|
|||||||
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz"
|
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz"
|
||||||
integrity sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==
|
integrity sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==
|
||||||
|
|
||||||
eslint@^9.13.0:
|
"eslint@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", "eslint@^8.57.0 || ^9.0.0", eslint@^9.13.0, eslint@>=7, eslint@>=7.0.0, eslint@>=8.0.0:
|
||||||
version "9.13.0"
|
version "9.13.0"
|
||||||
resolved "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz"
|
resolved "https://registry.npmjs.org/eslint/-/eslint-9.13.0.tgz"
|
||||||
integrity sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==
|
integrity sha512-EYZK6SX6zjFHST/HRytOdA/zE72Cq/bfw45LSyuwrdvcclb/gqV8RRQxywOBEWO2+WDpva6UZa4CcDeJKzUCFA==
|
||||||
@ -2625,6 +2625,11 @@ fs.realpath@^1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||||
|
|
||||||
|
fsevents@~2.3.2, fsevents@~2.3.3:
|
||||||
|
version "2.3.3"
|
||||||
|
resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz"
|
||||||
|
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
|
||||||
|
|
||||||
function-bind@^1.1.2:
|
function-bind@^1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
|
resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz"
|
||||||
@ -2877,7 +2882,7 @@ jackspeak@^3.1.2:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@pkgjs/parseargs" "^0.11.0"
|
"@pkgjs/parseargs" "^0.11.0"
|
||||||
|
|
||||||
jiti@^1.18.2, jiti@^1.21.0:
|
jiti@*, jiti@^1.18.2, jiti@^1.21.0:
|
||||||
version "1.21.6"
|
version "1.21.6"
|
||||||
resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz"
|
resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz"
|
||||||
integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==
|
integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==
|
||||||
@ -2941,7 +2946,7 @@ kolorist@^1.8.0:
|
|||||||
resolved "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz"
|
resolved "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz"
|
||||||
integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==
|
integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==
|
||||||
|
|
||||||
leaflet@^1.9.4:
|
leaflet@^1.9.0, leaflet@^1.9.4:
|
||||||
version "1.9.4"
|
version "1.9.4"
|
||||||
resolved "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz"
|
resolved "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz"
|
||||||
integrity sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==
|
integrity sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==
|
||||||
@ -3612,7 +3617,7 @@ postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2, postcss-value-parser@^
|
|||||||
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
|
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
|
||||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||||
|
|
||||||
postcss@^8.4.23, postcss@^8.4.43, postcss@^8.4.49:
|
postcss@^8, postcss@^8.0.0, postcss@^8.0.3, postcss@^8.1.0, postcss@^8.2.14, postcss@^8.4, postcss@^8.4.21, postcss@^8.4.23, postcss@^8.4.43, postcss@^8.4.49, postcss@^8.4.6, postcss@>=8.0.9:
|
||||||
version "8.4.49"
|
version "8.4.49"
|
||||||
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz"
|
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz"
|
||||||
integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==
|
integrity sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==
|
||||||
@ -3642,7 +3647,7 @@ prettier-linter-helpers@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fast-diff "^1.1.2"
|
fast-diff "^1.1.2"
|
||||||
|
|
||||||
prettier@^3.3.3:
|
prettier@^3.3.3, prettier@>=3.0.0:
|
||||||
version "3.3.3"
|
version "3.3.3"
|
||||||
resolved "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz"
|
resolved "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz"
|
||||||
integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==
|
integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==
|
||||||
@ -3713,7 +3718,7 @@ react-day-picker@^8.10.1:
|
|||||||
resolved "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz"
|
resolved "https://registry.npmjs.org/react-day-picker/-/react-day-picker-8.10.1.tgz"
|
||||||
integrity sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==
|
integrity sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA==
|
||||||
|
|
||||||
react-dom@^18.3.1:
|
"react-dom@^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^17.0.0 || ^18.0.0", "react-dom@^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom@^18 || ^19 || ^19.0.0-rc", react-dom@^18.0.0, "react-dom@^18.0.0 || ^19.0.0 || ^19.0.0-rc", react-dom@^18.3.1, "react-dom@>= 16.8.0", react-dom@>=16.6.0, react-dom@>=16.8, react-dom@>=16.8.0:
|
||||||
version "18.3.1"
|
version "18.3.1"
|
||||||
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz"
|
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz"
|
||||||
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
|
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
|
||||||
@ -3887,7 +3892,7 @@ react-transition-group@^4.4.5:
|
|||||||
loose-envify "^1.4.0"
|
loose-envify "^1.4.0"
|
||||||
prop-types "^15.6.2"
|
prop-types "^15.6.2"
|
||||||
|
|
||||||
react@^18.3.1:
|
"react@^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.3.0 || ^17.0.0 || ^18.0.0", "react@^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc", "react@^16.6.0 || ^17.0.0 || ^18.0.0", "react@^16.6.0 || 17 || 18", "react@^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react@^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^17.0.0 || ^18.0.0", "react@^17.0.0 || ^18.0.0 || ^19.0.0", "react@^18 || ^19", "react@^18 || ^19 || ^19.0.0-rc", react@^18.0.0, "react@^18.0.0 || ^19.0.0 || ^19.0.0-rc", react@^18.3.1, "react@>= 16.8.0", react@>=0.13, react@>=16.3.0, react@>=16.6.0, react@>=16.8, react@>=16.8.0, "react@16.8 - 18":
|
||||||
version "18.3.1"
|
version "18.3.1"
|
||||||
resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz"
|
resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz"
|
||||||
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
|
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
|
||||||
@ -4134,7 +4139,7 @@ stylis-plugin-rtl@^2.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
cssjanus "^2.0.1"
|
cssjanus "^2.0.1"
|
||||||
|
|
||||||
stylis@^4.3.4:
|
stylis@^4.3.4, stylis@4.x:
|
||||||
version "4.3.4"
|
version "4.3.4"
|
||||||
resolved "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz"
|
resolved "https://registry.npmjs.org/stylis/-/stylis-4.3.4.tgz"
|
||||||
integrity sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==
|
integrity sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==
|
||||||
@ -4237,6 +4242,11 @@ synckit@^0.9.1:
|
|||||||
"@pkgr/core" "^0.1.0"
|
"@pkgr/core" "^0.1.0"
|
||||||
tslib "^2.6.2"
|
tslib "^2.6.2"
|
||||||
|
|
||||||
|
tabs@^0.2.0:
|
||||||
|
version "0.2.0"
|
||||||
|
resolved "https://registry.npmjs.org/tabs/-/tabs-0.2.0.tgz"
|
||||||
|
integrity sha512-q6mo8KWq/Zi+zGR3ZvGq6S6ckc3JNbGRGtAwIhtnp2GlS1goTqFnWX3MkyDKYSQuzwBqBAy2fYGHQI+3HMnXZQ==
|
||||||
|
|
||||||
tailwind-merge@^2.5.4:
|
tailwind-merge@^2.5.4:
|
||||||
version "2.5.4"
|
version "2.5.4"
|
||||||
resolved "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz"
|
resolved "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.4.tgz"
|
||||||
@ -4247,7 +4257,7 @@ tailwindcss-animate@^1.0.7:
|
|||||||
resolved "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz"
|
resolved "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz"
|
||||||
integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==
|
integrity sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==
|
||||||
|
|
||||||
tailwindcss@^3.4.14:
|
tailwindcss@^3.4.14, "tailwindcss@>=3.0.0 || insiders":
|
||||||
version "3.4.14"
|
version "3.4.14"
|
||||||
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz"
|
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz"
|
||||||
integrity sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==
|
integrity sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==
|
||||||
@ -4357,7 +4367,7 @@ typescript-eslint@^8.14.0:
|
|||||||
"@typescript-eslint/parser" "8.14.0"
|
"@typescript-eslint/parser" "8.14.0"
|
||||||
"@typescript-eslint/utils" "8.14.0"
|
"@typescript-eslint/utils" "8.14.0"
|
||||||
|
|
||||||
typescript@^5.6.3:
|
"typescript@^4.7 || 5", typescript@^5.6.3, typescript@>=4.2.0:
|
||||||
version "5.6.3"
|
version "5.6.3"
|
||||||
resolved "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz"
|
resolved "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz"
|
||||||
integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==
|
integrity sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==
|
||||||
@ -4425,7 +4435,7 @@ vite-plugin-windicss@^1.9.3:
|
|||||||
kolorist "^1.8.0"
|
kolorist "^1.8.0"
|
||||||
windicss "^3.5.6"
|
windicss "^3.5.6"
|
||||||
|
|
||||||
vite@^5.4.11:
|
"vite@^2.0.1 || ^3.0.0 || ^4.0.0 || ^5.0.0", "vite@^4.2.0 || ^5.0.0", vite@^5.4.11:
|
||||||
version "5.4.11"
|
version "5.4.11"
|
||||||
resolved "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz"
|
resolved "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz"
|
||||||
integrity sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==
|
integrity sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==
|
||||||
|
|||||||
Reference in New Issue
Block a user