diff --git a/.env.development b/.env.development index 58a088c..5845f2e 100644 --- a/.env.development +++ b/.env.development @@ -2,6 +2,9 @@ VITE_APP_NAME=tpay-dashboard-tl VITE_APP_VERSION=1=9.1.1 GENERATE_SOURCEMAP=false +# VITE_APP_API_URL= +VITE_APP_API_URL=http://127.0.0.1:4003/apitest VITE_APP_API_URL=https://tpay.shiblysolution.id/api -# VITE_APP_API_URL=http://127.0.0.1:4003/api +# VITE_APP_URL_TRANSACTION=https://tpay.shiblysolution.id/test/x/api +# VITE_APP_API_URL=http://127.0.0.1:4003/apitesting VITE_ENV=development diff --git a/.gitignore b/.gitignore index d2a16d3..8d6f61e 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,8 @@ yarn-debug.log* yarn-error.log* pnpm-debug.log* lerna-debug.log* +yarn.lock + .env node_modules @@ -24,4 +26,5 @@ yarn.lock *.njsproj *.sln *.sw? -**/src/*.js \ No newline at end of file +**/src/*.js +.env \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 95dac4a..afeabe7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "metronic-tailwind-react", "version": "9.1.2", + "license": "ISC", "dependencies": { "@auth0/auth0-spa-js": "^2.1.3", "@emotion/cache": "^11.13.1", @@ -104,7 +105,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, "engines": { "node": ">=10" }, @@ -1462,13 +1462,14 @@ "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, "node_modules/@emotion/cache": { - "version": "11.13.1", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz", - "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==", + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz", + "integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==", + "license": "MIT", "dependencies": { "@emotion/memoize": "^0.9.0", "@emotion/sheet": "^1.4.0", - "@emotion/utils": "^1.4.0", + "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } @@ -1520,14 +1521,15 @@ } }, "node_modules/@emotion/serialize": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz", - "integrity": "sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz", + "integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==", + "license": "MIT", "dependencies": { "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/unitless": "^0.10.0", - "@emotion/utils": "^1.4.1", + "@emotion/utils": "^1.4.2", "csstype": "^3.0.2" } }, @@ -1572,9 +1574,10 @@ } }, "node_modules/@emotion/utils": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz", - "integrity": "sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==" + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz", + "integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==", + "license": "MIT" }, "node_modules/@emotion/weak-memoize": { "version": "0.4.0", @@ -1588,7 +1591,6 @@ "cpu": [ "ppc64" ], - "dev": true, "optional": true, "os": [ "aix" @@ -1604,7 +1606,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "android" @@ -1620,7 +1621,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -1636,7 +1636,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "android" @@ -1652,7 +1651,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -1668,7 +1666,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -1684,7 +1681,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -1700,7 +1696,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -1716,7 +1711,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1732,7 +1726,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1748,7 +1741,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1764,7 +1756,6 @@ "cpu": [ "loong64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1780,7 +1771,6 @@ "cpu": [ "mips64el" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1796,7 +1786,6 @@ "cpu": [ "ppc64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1812,7 +1801,6 @@ "cpu": [ "riscv64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1828,7 +1816,6 @@ "cpu": [ "s390x" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1844,7 +1831,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -1860,7 +1846,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "netbsd" @@ -1876,7 +1861,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "openbsd" @@ -1892,7 +1876,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "sunos" @@ -1908,7 +1891,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1924,7 +1906,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -1940,7 +1921,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -2443,7 +2423,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -2460,7 +2439,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, "engines": { "node": ">=12" }, @@ -2472,7 +2450,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, "engines": { "node": ">=12" }, @@ -2483,14 +2460,12 @@ "node_modules/@isaacs/cliui/node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" }, "node_modules/@isaacs/cliui/node_modules/string-width": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -2507,7 +2482,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -2522,7 +2496,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -2639,9 +2612,10 @@ } }, "node_modules/@mui/core-downloads-tracker": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.1.6.tgz", - "integrity": "sha512-nz1SlR9TdBYYPz4qKoNasMPRiGb4PaIHFkzLzhju0YVYS5QSuFF2+n7CsiHMIDcHv3piPu/xDWI53ruhOqvZwQ==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-6.4.8.tgz", + "integrity": "sha512-vjP4+A1ybyCRhDZC7r5EPWu/gLseFZxaGyPdDl94vzVvk6Yj6gahdaqcjbhkaCrJjdZj90m3VioltWPAnWF/zw==", + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/mui-org" @@ -2673,21 +2647,22 @@ } }, "node_modules/@mui/material": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.1.6.tgz", - "integrity": "sha512-1yvejiQ/601l5AK3uIdUlAVElyCxoqKnl7QA+2oFB/2qYPWfRwDgavW/MoywS5Y2gZEslcJKhe0s2F3IthgFgw==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@mui/material/-/material-6.4.8.tgz", + "integrity": "sha512-5S9UTjKZZBd9GfbcYh/nYfD9cv6OXmj5Y7NgKYfk7JcSoshp8/pW5zP4wecRiroBSZX8wcrywSgogpVNO+5W0Q==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/core-downloads-tracker": "^6.1.6", - "@mui/system": "^6.1.6", - "@mui/types": "^7.2.19", - "@mui/utils": "^6.1.6", + "@mui/core-downloads-tracker": "^6.4.8", + "@mui/system": "^6.4.8", + "@mui/types": "~7.2.24", + "@mui/utils": "^6.4.8", "@popperjs/core": "^2.11.8", - "@types/react-transition-group": "^4.4.11", + "@types/react-transition-group": "^4.4.12", "clsx": "^2.1.1", "csstype": "^3.1.3", "prop-types": "^15.8.1", - "react-is": "^18.3.1", + "react-is": "^19.0.0", "react-transition-group": "^4.4.5" }, "engines": { @@ -2700,7 +2675,7 @@ "peerDependencies": { "@emotion/react": "^11.5.0", "@emotion/styled": "^11.3.0", - "@mui/material-pigment-css": "^6.1.6", + "@mui/material-pigment-css": "^6.4.8", "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react": "^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" @@ -2720,13 +2695,20 @@ } } }, + "node_modules/@mui/material/node_modules/react-is": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz", + "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==", + "license": "MIT" + }, "node_modules/@mui/private-theming": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.1.6.tgz", - "integrity": "sha512-ioAiFckaD/fJSnTrUMWgjl9HYBWt7ixCh7zZw7gDZ+Tae7NuprNV6QJK95EidDT7K0GetR2rU3kAeIR61Myttw==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-6.4.8.tgz", + "integrity": "sha512-sWwQoNSn6elsPTAtSqCf+w5aaGoh7AASURNmpy+QTTD/zwJ0Jgwt0ZaaP6mXq2IcgHxYnYloM/+vJgHPMkRKTQ==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/utils": "^6.1.6", + "@mui/utils": "^6.4.8", "prop-types": "^15.8.1" }, "engines": { @@ -2747,13 +2729,14 @@ } }, "node_modules/@mui/styled-engine": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.1.6.tgz", - "integrity": "sha512-I+yS1cSuSvHnZDBO7e7VHxTWpj+R7XlSZvTC4lS/OIbUNJOMMSd3UDP6V2sfwzAdmdDNBi7NGCRv2SZ6O9hGDA==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-6.4.8.tgz", + "integrity": "sha512-oyjx1b1FvUCI85ZMO4trrjNxGm90eLN3Ohy0AP/SqK5gWvRQg1677UjNf7t6iETOKAleHctJjuq0B3aXO2gtmw==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", - "@emotion/cache": "^11.13.1", - "@emotion/serialize": "^1.3.2", + "@emotion/cache": "^11.13.5", + "@emotion/serialize": "^1.3.3", "@emotion/sheet": "^1.4.0", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -2780,15 +2763,16 @@ } }, "node_modules/@mui/system": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.1.6.tgz", - "integrity": "sha512-qOf1VUE9wK8syiB0BBCp82oNBAVPYdj4Trh+G1s+L+ImYiKlubWhhqlnvWt3xqMevR+D2h1CXzA1vhX2FvA+VQ==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@mui/system/-/system-6.4.8.tgz", + "integrity": "sha512-gV7iBHoqlsIenU2BP0wq14BefRoZcASZ/4LeyuQglayBl+DfLX5rEd3EYR3J409V2EZpR0NOM1LATAGlNk2cyA==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/private-theming": "^6.1.6", - "@mui/styled-engine": "^6.1.6", - "@mui/types": "^7.2.19", - "@mui/utils": "^6.1.6", + "@mui/private-theming": "^6.4.8", + "@mui/styled-engine": "^6.4.8", + "@mui/types": "~7.2.24", + "@mui/utils": "^6.4.8", "clsx": "^2.1.1", "csstype": "^3.1.3", "prop-types": "^15.8.1" @@ -2819,9 +2803,10 @@ } }, "node_modules/@mui/types": { - "version": "7.2.19", - "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.19.tgz", - "integrity": "sha512-6XpZEM/Q3epK9RN8ENoXuygnqUQxE+siN/6rGRi2iwJPgBUR25mphYQ9ZI87plGh58YoZ5pp40bFvKYOCDJ3tA==", + "version": "7.2.24", + "resolved": "https://registry.npmjs.org/@mui/types/-/types-7.2.24.tgz", + "integrity": "sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw==", + "license": "MIT", "peerDependencies": { "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" }, @@ -2832,16 +2817,17 @@ } }, "node_modules/@mui/utils": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.1.6.tgz", - "integrity": "sha512-sBS6D9mJECtELASLM+18WUcXF6RH3zNxBRFeyCRg8wad6NbyNrdxLuwK+Ikvc38sTZwBzAz691HmSofLqHd9sQ==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-6.4.8.tgz", + "integrity": "sha512-C86gfiZ5BfZ51KqzqoHi1WuuM2QdSKoFhbkZeAfQRB+jCc4YNhhj11UXFVMMsqBgZ+Zy8IHNJW3M9Wj/LOwRXQ==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.26.0", - "@mui/types": "^7.2.19", - "@types/prop-types": "^15.7.13", + "@mui/types": "~7.2.24", + "@types/prop-types": "^15.7.14", "clsx": "^2.1.1", "prop-types": "^15.8.1", - "react-is": "^18.3.1" + "react-is": "^19.0.0" }, "engines": { "node": ">=14.0.0" @@ -2860,6 +2846,12 @@ } } }, + "node_modules/@mui/utils/node_modules/react-is": { + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.0.0.tgz", + "integrity": "sha512-H91OHcwjZsbq3ClIDHMzBShc1rotbfACdWENsmEf0IFvZ3FgGPtdHMcsv45bQ1hAbgdfiA8SnxTKfDS+x/8m2g==", + "license": "MIT" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2896,7 +2888,6 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, "optional": true, "engines": { "node": ">=14" @@ -3915,7 +3906,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "android" @@ -3928,7 +3918,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "android" @@ -3941,7 +3930,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -3954,7 +3942,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "darwin" @@ -3967,7 +3954,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -3980,7 +3966,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "freebsd" @@ -3993,7 +3978,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -4006,7 +3990,6 @@ "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -4019,7 +4002,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -4032,7 +4014,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -4045,7 +4026,6 @@ "cpu": [ "ppc64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -4058,7 +4038,6 @@ "cpu": [ "riscv64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -4071,7 +4050,6 @@ "cpu": [ "s390x" ], - "dev": true, "optional": true, "os": [ "linux" @@ -4084,7 +4062,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -4097,7 +4074,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "linux" @@ -4110,7 +4086,6 @@ "cpu": [ "arm64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -4123,7 +4098,6 @@ "cpu": [ "ia32" ], - "dev": true, "optional": true, "os": [ "win32" @@ -4136,7 +4110,6 @@ "cpu": [ "x64" ], - "dev": true, "optional": true, "os": [ "win32" @@ -4241,8 +4214,7 @@ "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==" }, "node_modules/@types/geojson": { "version": "7946.0.14", @@ -4288,9 +4260,10 @@ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==" }, "node_modules/@types/prop-types": { - "version": "15.7.13", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", - "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==" + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "license": "MIT" }, "node_modules/@types/react": { "version": "18.3.12", @@ -4305,7 +4278,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", - "dev": true, + "devOptional": true, "dependencies": { "@types/react": "*" } @@ -4320,10 +4293,11 @@ } }, "node_modules/@types/react-transition-group": { - "version": "4.4.11", - "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz", - "integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==", - "dependencies": { + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz", + "integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==", + "license": "MIT", + "peerDependencies": { "@types/react": "*" } }, @@ -4642,14 +4616,12 @@ "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -4675,8 +4647,7 @@ "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" }, "node_modules/argparse": { "version": "2.0.1", @@ -4777,7 +4748,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, "engines": { "node": ">=8" }, @@ -4789,7 +4759,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -4881,7 +4850,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, "engines": { "node": ">= 6" } @@ -4933,7 +4901,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -4957,7 +4924,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -5051,7 +5017,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, "engines": { "node": ">= 6" } @@ -5085,7 +5050,6 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -5300,14 +5264,12 @@ "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, "node_modules/dom-helpers": { "version": "5.2.1", @@ -5321,8 +5283,7 @@ "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" }, "node_modules/electron-to-chromium": { "version": "1.5.48", @@ -5365,7 +5326,6 @@ "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -5827,7 +5787,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -5897,7 +5856,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -5982,7 +5940,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -6195,7 +6152,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -6255,14 +6211,12 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -6385,7 +6339,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", - "dev": true, "engines": { "node": ">=10" } @@ -6537,7 +6490,6 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -6552,7 +6504,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, "engines": { "node": ">=16 || 14 >=14.17" } @@ -6575,7 +6526,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -6632,7 +6582,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -6686,7 +6635,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, "engines": { "node": ">= 6" } @@ -6765,8 +6713,7 @@ "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" }, "node_modules/parent-module": { "version": "1.0.1", @@ -6817,7 +6764,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "engines": { "node": ">=8" } @@ -6831,7 +6777,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -6846,8 +6791,7 @@ "node_modules/path-scurry/node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" }, "node_modules/path-type": { "version": "4.0.0", @@ -6877,7 +6821,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -6886,7 +6829,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, "engines": { "node": ">= 6" } @@ -6895,7 +6837,6 @@ "version": "8.4.49", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -7273,7 +7214,6 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -7290,7 +7230,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, "dependencies": { "camelcase-css": "^2.0.1" }, @@ -7337,7 +7276,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -7372,7 +7310,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", - "dev": true, "engines": { "node": ">=14" }, @@ -7384,7 +7321,6 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", - "dev": true, "bin": { "yaml": "bin.mjs" }, @@ -7420,7 +7356,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -7445,7 +7380,6 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -8153,7 +8087,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, "dependencies": { "pify": "^2.3.0" } @@ -8162,7 +8095,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -8240,7 +8172,6 @@ "version": "4.24.2", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.2.tgz", "integrity": "sha512-do/DFGq5g6rdDhdpPq5qb2ecoczeK6y+2UAjdJ5trjQJj5f1AiVdLRWRc9A9/fFukfvJRgM0UXzxBIYMovm5ww==", - "dev": true, "dependencies": { "@types/estree": "1.0.6" }, @@ -8340,7 +8271,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -8352,7 +8282,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "engines": { "node": ">=8" } @@ -8378,7 +8307,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "engines": { "node": ">=14" }, @@ -8429,7 +8357,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -8455,7 +8382,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -8582,7 +8508,6 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", @@ -8604,7 +8529,6 @@ "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", @@ -8755,7 +8679,6 @@ "version": "3.4.14", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", - "dev": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -8800,7 +8723,6 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -8819,7 +8741,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, "dependencies": { "any-promise": "^1.0.0" } @@ -8828,7 +8749,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -8877,8 +8797,7 @@ "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" }, "node_modules/tslib": { "version": "2.8.0", @@ -8912,7 +8831,7 @@ "version": "5.6.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -9054,7 +8973,6 @@ "version": "5.4.11", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", - "dev": true, "dependencies": { "esbuild": "^0.21.3", "postcss": "^8.4.43", @@ -9130,7 +9048,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -9182,7 +9099,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", diff --git a/package.json b/package.json index 551e853..8121a93 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "react-inlinesvg": "^4.1.4", "react-intl": "^6.8.7", "react-leaflet": "^4.2.1", + "react-number-format": "^5.4.3", "react-query": "^3.39.3", "react-router": "^6.28.0", "react-router-dom": "^6.28.0", @@ -105,5 +106,9 @@ "typescript": "^5.6.3", "typescript-eslint": "^8.14.0", "vite": "^5.4.11" - } + }, + "description": "## Quick Setup", + "main": "postcss.config.js", + "author": "", + "license": "ISC" } diff --git a/src/components/data-grid/DataGridContext.tsx b/src/components/data-grid/DataGridContext.tsx index a684184..9e95494 100644 --- a/src/components/data-grid/DataGridContext.tsx +++ b/src/components/data-grid/DataGridContext.tsx @@ -151,7 +151,10 @@ export const DataGridProvider = (props: TDataGridProps !loading && setSorting(newSorting), - onColumnFiltersChange: (newFilters) => !loading && setColumnFilters(newFilters), + onColumnFiltersChange: (newFilters) => { + console.log('New Filters:', newFilters); // Debugging + !loading && setColumnFilters(newFilters); + }, onColumnVisibilityChange: setColumnVisibility, onPaginationChange: (newPagination) => !loading && setPagination(newPagination), getCoreRowModel: getCoreRowModel(), @@ -165,6 +168,8 @@ export const DataGridProvider = (props: TDataGridProps {
{currentYear}© - + Brillian Dev.
diff --git a/src/pages/master/aldeias/AldeiasMaster.tsx b/src/pages/master/aldeias/AldeiasMaster.tsx index a3d0ad7..3ebb197 100644 --- a/src/pages/master/aldeias/AldeiasMaster.tsx +++ b/src/pages/master/aldeias/AldeiasMaster.tsx @@ -9,7 +9,7 @@ const AldeiasMaster = () => { return ( -

Aldeias

+

Aldeias

Dashboard diff --git a/src/pages/master/aldeias/blocks/AddDialog.tsx b/src/pages/master/aldeias/blocks/AddDialog.tsx index af089ef..f678f33 100644 --- a/src/pages/master/aldeias/blocks/AddDialog.tsx +++ b/src/pages/master/aldeias/blocks/AddDialog.tsx @@ -46,7 +46,7 @@ const AddDialog = () => { }); const initialState = { name: '', - sucos_id: 0, + sucosId: 0, created_by: '', created_at: '' }; @@ -99,7 +99,7 @@ const AddDialog = () => { const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); - if (formField.name === '' || formField.sucos_id === 0) { + if (formField.name === '' || formField.sucosId === 0) { setAlert({ show: true, message: 'Please fill in all required fields.' }); return; } @@ -168,11 +168,14 @@ const AddDialog = () => { - + e.stopPropagation()} + > @@ -181,11 +184,11 @@ const AddDialog = () => { {sucos.map((suco) => ( { setFormField({ ...formField, - sucos_id: suco.sucos_id + sucosId: suco.sucos_id }); setOpen(false); }} diff --git a/src/pages/master/aldeias/blocks/DeleteDialog.tsx b/src/pages/master/aldeias/blocks/DeleteDialog.tsx index 44fc4c1..17c4954 100644 --- a/src/pages/master/aldeias/blocks/DeleteDialog.tsx +++ b/src/pages/master/aldeias/blocks/DeleteDialog.tsx @@ -2,38 +2,42 @@ import { apiConfig } from '@/config/api.config'; import { useManageAldeiasContext } from '../hooks/useManageAldeiasContext'; import { Alert, useDataGrid } from '@/components'; import { useCallApi } from '@/hooks'; -import { ChangeEvent, useCallback, useState } from 'react'; +import { useCallback, useState } from 'react'; import { toast } from 'sonner'; import { Dialog, DialogContent, DialogFooter, DialogHeader } from '@/components/ui/dialog'; -import { EnforceSwitch } from '@/components/switch'; import { Button } from '@/components/ui/button'; const API_URL = apiConfig.service_master_data; + const DeleteDialog = () => { const { showDeleteDialog, handleDeleteDialog, selectedAldeias } = useManageAldeiasContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); - const [enforce, setEnforce] = useState(false); const [alert, setAlert] = useState({ show: false, message: '' - }) + }); const doDeleteAldeias = useCallback(async () => { - const response = await DeleteData(`${API_URL}/aldeias/delete/${selectedAldeias}/${enforce}`, { + if (!selectedAldeias) { + toast.error('No Aldeias selected'); + return; + } + + const response = await DeleteData(`${API_URL}/aldeias/delete/${selectedAldeias}/false`, { id: selectedAldeias }); if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); + setAlert({ show: false, message: '' }); handleDeleteDialog(false, null); toast.success('Success Delete Aldeias'); reload(); } else { + setAlert({ show: true, message: response?.message }); toast.error('Failed Delete Aldeias'); - setAlert((prev) => ({ ...prev, show: true, message: response?.message })); } - }, [selectedAldeias, enforce]); + }, [selectedAldeias, DeleteData, handleDeleteDialog, reload]); return ( handleDeleteDialog(open, null)}> @@ -41,16 +45,7 @@ const DeleteDialog = () => {

Are you sure?

- you will delete this data! -
- - ) => { - setEnforce(e.target.checked); - }} - /> -
+ You will delete this data!
{alert.show && ( diff --git a/src/pages/master/aldeias/blocks/EditDialog.tsx b/src/pages/master/aldeias/blocks/EditDialog.tsx index d69981e..449197d 100644 --- a/src/pages/master/aldeias/blocks/EditDialog.tsx +++ b/src/pages/master/aldeias/blocks/EditDialog.tsx @@ -45,7 +45,7 @@ const EditDialog = () => { }); const initialState = { name: '', - sucos_id: 0, + sucosId: 0, updated_by: '', updated_at: '' }; @@ -102,13 +102,13 @@ const EditDialog = () => { setFormField((prev) => ({ ...prev, name: response.data.name, - sucos_id: response.data.sucos.id + sucosId: response.data.sucos.id })); } else { setFormField((prev) => ({ ...prev, name: '', - sucos_id: 0 + sucosId: 0 })); } }, []); @@ -116,7 +116,7 @@ const EditDialog = () => { const handleUpdate = (e: React.FormEvent) => { e.preventDefault(); - if (formField.name === '' || formField.sucos_id === 0) { + if (formField.name === '' || formField.sucosId === 0) { setAlert({ show: true, message: 'Please fill in all required fields.' }); return; } @@ -191,7 +191,7 @@ const EditDialog = () => { @@ -208,7 +208,7 @@ const EditDialog = () => { onSelect={() => { setFormField({ ...formField, - sucos_id: suco.sucos_id + sucosId: suco.sucos_id }); setOpen(false); }} diff --git a/src/pages/master/aldeias/hooks/ManageAldeiasContext.tsx b/src/pages/master/aldeias/hooks/ManageAldeiasContext.tsx index f0b9aff..6dcce41 100644 --- a/src/pages/master/aldeias/hooks/ManageAldeiasContext.tsx +++ b/src/pages/master/aldeias/hooks/ManageAldeiasContext.tsx @@ -77,16 +77,6 @@ const ManageAldeiasContextProvider = ({ children }: { children: React.ReactNode const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.id, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { accessorFn: (row) => row.name, id: 'name', diff --git a/src/pages/master/conversion/hooks/ManageConversionContext.tsx b/src/pages/master/conversion/hooks/ManageConversionContext.tsx index fe96cb0..21f8c78 100644 --- a/src/pages/master/conversion/hooks/ManageConversionContext.tsx +++ b/src/pages/master/conversion/hooks/ManageConversionContext.tsx @@ -68,16 +68,6 @@ const ManageConversionContextProvider = ({ children }: { children: React.ReactNo const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.id, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { accessorFn: (row) => row.name, id: 'name', diff --git a/src/pages/master/municipios/blocks/DeleteDialog.tsx b/src/pages/master/municipios/blocks/DeleteDialog.tsx index 0605ab5..f7e6f5d 100644 --- a/src/pages/master/municipios/blocks/DeleteDialog.tsx +++ b/src/pages/master/municipios/blocks/DeleteDialog.tsx @@ -1,69 +1,56 @@ import { Alert, useDataGrid } from '@/components'; import { useManageMunicipiosContext } from '../hooks/useManageMunicipiosContext'; -import { ChangeEvent, useCallback, useState } from 'react'; -import axios from 'axios'; +import { useCallback, useState } from 'react'; import { apiConfig } from '@/config/api.config'; import { useCallApi } from '@/hooks'; import { toast } from 'sonner'; -import { Dialog, DialogContent, DialogFooter, DialogHeader } from '@/components/ui/dialog'; -import { EnforceSwitch } from '@/components/switch'; +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; -import { doSaveLogActivity } from '@/actions/GlobalActions'; +import { DialogDescription } from '@radix-ui/react-dialog'; const API_URL = apiConfig.service_master_data; const DeleteDialog = () => { - const { showDeleteDialog, handleDeleteDialog, selectedMunicipios, municipios } = - useManageMunicipiosContext(); + const { showDeleteDialog, handleDeleteDialog, selectedMunicipios } = useManageMunicipiosContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); - const [enforce, setEnforce] = useState(false); const [alert, setAlert] = useState({ show: false, message: '' }); const doDeleteMunicipio = useCallback(async () => { + if (!selectedMunicipios) { + toast.error('No Municipio selected'); + return; + } + const response = await DeleteData( - `${API_URL}/municipios/delete/${selectedMunicipios}/${enforce}`, - { - id: selectedMunicipios - } + `${API_URL}/municipios/delete/${selectedMunicipios}/false`, + { id: selectedMunicipios } ); if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); + setAlert({ show: false, message: '' }); handleDeleteDialog(false, null); toast.success('Success Delete Municipio'); reload(); - // const createActivity = { - // module: 'Manage Municipio', - // description: `Delete Municipio => ${selectedMunicipios}`, - // action: 'D' - // }; - - // doSaveLogActivity(createActivity); } else { - setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + setAlert({ show: true, message: response?.message }); + toast.error('Failed Delete Municipio'); } - }, [selectedMunicipios, enforce]); + }, [selectedMunicipios, DeleteData, handleDeleteDialog, reload]); return ( handleDeleteDialog(open, null)}> + + +

Are you sure?

- you will delete this data! -
- - ) => { - setEnforce(e.target.checked); - }} - /> -
+ You will delete this data!
{alert.show && ( @@ -72,10 +59,10 @@ const DeleteDialog = () => { )}
- - diff --git a/src/pages/master/municipios/hooks/ManageMunicipiosContext.tsx b/src/pages/master/municipios/hooks/ManageMunicipiosContext.tsx index 80c208a..5a95477 100644 --- a/src/pages/master/municipios/hooks/ManageMunicipiosContext.tsx +++ b/src/pages/master/municipios/hooks/ManageMunicipiosContext.tsx @@ -102,16 +102,6 @@ const ManageMunicipiosProvider = ({ children }: { children: React.ReactNode }) = const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.id, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { // accessorFn: (row) => row.name, // id: 'name', diff --git a/src/pages/master/postoadms/blocks/AddDialog.tsx b/src/pages/master/postoadms/blocks/AddDialog.tsx index fa7c7dd..eaa8b1e 100644 --- a/src/pages/master/postoadms/blocks/AddDialog.tsx +++ b/src/pages/master/postoadms/blocks/AddDialog.tsx @@ -174,10 +174,13 @@ const AddDialog = () => { ?.name || 'Select Municipios'} - + e.stopPropagation()} + > - + No Municipio found. {municipios.map((municipio) => ( diff --git a/src/pages/master/postoadms/blocks/DeleteDialog.tsx b/src/pages/master/postoadms/blocks/DeleteDialog.tsx index f969485..fca5448 100644 --- a/src/pages/master/postoadms/blocks/DeleteDialog.tsx +++ b/src/pages/master/postoadms/blocks/DeleteDialog.tsx @@ -1,11 +1,10 @@ import { Alert, useDataGrid } from '@/components'; import { useManagePostoAdmsContext } from '../hooks/useManagePostoAdmsContext'; import { useCallApi } from '@/hooks'; -import { ChangeEvent, useCallback, useState } from 'react'; +import { useCallback, useState } from 'react'; import { apiConfig } from '@/config/api.config'; import { toast } from 'sonner'; -import { Dialog, DialogContent, DialogFooter, DialogHeader } from '@/components/ui/dialog'; -import { EnforceSwitch } from '@/components/switch'; +import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; import { Button } from '@/components/ui/button'; const API_URL = apiConfig.service_master_data; @@ -14,46 +13,42 @@ const DeleteDialog = () => { const { showDeleteDialog, handleDeleteDialog, selectedPostoAdms } = useManagePostoAdmsContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); - const [enforce, setEnforce] = useState(false); const [alert, setAlert] = useState({ show: false, message: '' }); const doDeletePostoAdm = useCallback(async () => { + if (!selectedPostoAdms) { + toast.error('No Posto Adm selected'); + return; + } + const response = await DeleteData( - `${API_URL}/postoadms/delete/${selectedPostoAdms}/${enforce}`, - { - id: selectedPostoAdms - } + `${API_URL}/postoadms/delete/${selectedPostoAdms}/false`, + { id: selectedPostoAdms } ); if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); + setAlert({ show: false, message: '' }); handleDeleteDialog(false, null); toast.success('Success Delete Posto Adm'); reload(); } else { - setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + setAlert({ show: true, message: response?.message }); + toast.error('Failed Delete Posto Adm'); } - }, [selectedPostoAdms, enforce]); + }, [selectedPostoAdms, DeleteData, handleDeleteDialog, reload]); return ( handleDeleteDialog(open, null)}> + +

Are you sure?

- you will delete this data! -
- - ) => { - setEnforce(e.target.checked); - }} - /> -
+ You will delete this data!
{alert.show && ( @@ -62,10 +57,10 @@ const DeleteDialog = () => { )}
- - diff --git a/src/pages/master/postoadms/blocks/ListToolbar.tsx b/src/pages/master/postoadms/blocks/ListToolbar.tsx index 60ab7d2..04742a3 100644 --- a/src/pages/master/postoadms/blocks/ListToolbar.tsx +++ b/src/pages/master/postoadms/blocks/ListToolbar.tsx @@ -18,9 +18,7 @@ const ListToolbar = () => { type="text" placeholder="Search Postu" 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)} /> {/* diff --git a/src/pages/master/postoadms/hooks/ManagePostoAdmsContext.tsx b/src/pages/master/postoadms/hooks/ManagePostoAdmsContext.tsx index 5c2f500..ef6f7b5 100644 --- a/src/pages/master/postoadms/hooks/ManagePostoAdmsContext.tsx +++ b/src/pages/master/postoadms/hooks/ManagePostoAdmsContext.tsx @@ -83,17 +83,6 @@ const ManagePostoAdmsContextProvider = ({ children }: { children: React.ReactNod const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.PostoAdms_id, - id: 'id', - // accessorKey: 'PostoAdms_id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { accessorFn: (row) => row.PostoAdms_name, id: 'name', @@ -110,7 +99,7 @@ const ManagePostoAdmsContextProvider = ({ children }: { children: React.ReactNod { accessorFn: (row) => row.municipios_name, id: 'municipios_name', - header: ({ column }) => , + header: ({ column }) => , enableSorting: false, enableHiding: false, meta: { diff --git a/src/pages/master/products/blocks/AddDialog.tsx b/src/pages/master/products/blocks/AddDialog.tsx index 343e076..f5b7a57 100644 --- a/src/pages/master/products/blocks/AddDialog.tsx +++ b/src/pages/master/products/blocks/AddDialog.tsx @@ -40,17 +40,17 @@ const AddDialog = () => { message: '' }); const initialState = { - products_name: '', - products_code: '', - products_type: '', - products_description: '', - products_price_point: 0, - products_price_cash: 0, - products_cashback_point: 0, - products_cashback_cash: 0, - products_status: '', - products_provider: '', - products_process_on_third_party: '', + name: '', + code: '', + type: '', + description: '', + price_point: 0, + price_cash: 0, + cashback_point: 0, + cashback_cash: 0, + status: '', + provider: '', + process_on_third_party: '', created_by: '', created_at: '' }; @@ -104,15 +104,15 @@ const AddDialog = () => { e.preventDefault(); if ( - formField.products_name.trim() === '' || - formField.products_type.trim() === '' || - formField.products_code.trim() === '' || - formField.products_description.trim() === '' || - formField.products_price_point === 0 || - formField.products_price_cash === 0 || - formField.products_cashback_point === 0 || - formField.products_cashback_cash === 0 || - formField.products_status.trim() === '' || + formField.name.trim() === '' || + formField.type.trim() === '' || + formField.code.trim() === '' || + formField.description.trim() === '' || + formField.price_point === 0 || + formField.price_cash === 0 || + formField.cashback_point === 0 || + formField.cashback_cash === 0 || + formField.status.trim() === '' || formField.created_by.trim() === '' || formField.created_at.trim() === '' ) { @@ -155,9 +155,11 @@ const AddDialog = () => {
{alert.show && ( - -

{alert.message}

-
+
+ +

{alert.message}

+
+
)}
@@ -170,9 +172,9 @@ const AddDialog = () => { - setFormField({ ...formField, products_name: e.target.value }) + setFormField({ ...formField, name: e.target.value }) } />
@@ -186,9 +188,9 @@ const AddDialog = () => { - setFormField({ ...formField, products_type: e.target.value }) + setFormField({ ...formField, type: e.target.value }) } />
@@ -202,9 +204,9 @@ const AddDialog = () => { - setFormField({ ...formField, products_code: e.target.value }) + setFormField({ ...formField, code: e.target.value }) } /> @@ -218,9 +220,9 @@ const AddDialog = () => { - setFormField({ ...formField, products_description: e.target.value }) + setFormField({ ...formField, description: e.target.value }) } /> @@ -236,12 +238,12 @@ const AddDialog = () => { type="number" min={0} step={0.01} - value={formField.products_price_point} + value={formField.price_point} onChange={(e) => { const value = parseFloat(e.target.value); setFormField({ ...formField, - products_price_point: isNaN(value) ? 0 : value + price_point: isNaN(value) ? 0 : value }); }} /> @@ -258,12 +260,12 @@ const AddDialog = () => { type="number" min={0} step={0.01} - value={formField.products_price_cash} + value={formField.price_cash} onChange={(e) => { const value = parseFloat(e.target.value); setFormField({ ...formField, - products_price_cash: isNaN(value) ? 0 : value + price_cash: isNaN(value) ? 0 : value }); }} /> @@ -280,12 +282,12 @@ const AddDialog = () => { type="number" min={0} step={0.01} - value={formField.products_cashback_point} + value={formField.cashback_point} onChange={(e) => { const value = parseFloat(e.target.value); setFormField({ ...formField, - products_cashback_point: isNaN(value) ? 0 : value + cashback_point: isNaN(value) ? 0 : value }); }} /> @@ -302,12 +304,12 @@ const AddDialog = () => { type="number" min={0} step={0.01} - value={formField.products_cashback_cash} + value={formField.cashback_cash} onChange={(e) => { const value = parseFloat(e.target.value); setFormField({ ...formField, - products_cashback_cash: isNaN(value) ? 0 : value + cashback_cash: isNaN(value) ? 0 : value }); }} /> @@ -320,9 +322,9 @@ const AddDialog = () => { Status* - setFormField({ ...formField, products_provider: value.toString() }) + setFormField({ ...formField, provider: value.toString() }) } > @@ -370,9 +372,9 @@ const AddDialog = () => { Process on Third Party* - setFormField({ ...formField, transactionTypeId: value }) + setFormField({ ...formField, transaction_type: value }) } > @@ -290,8 +294,8 @@ const AddDialog = () => { @@ -302,17 +306,17 @@ const AddDialog = () => { {customers.map((customer) => ( { setFormField({ ...formField, - agentId: customer.msisdn + agent: customer.id }); setOpen(false); }} > - {customer.fullname} + {customer.username} ))} diff --git a/src/pages/master/provider/blocks/DeleteDialog.tsx b/src/pages/master/provider/blocks/DeleteDialog.tsx index 9be7895..41e0bef 100644 --- a/src/pages/master/provider/blocks/DeleteDialog.tsx +++ b/src/pages/master/provider/blocks/DeleteDialog.tsx @@ -2,64 +2,49 @@ import { apiConfig } from '@/config/api.config'; import { useManageProviderContext } from '../hooks/useManageProviderContext'; import { Alert, useDataGrid } from '@/components'; import { useCallApi } from '@/hooks'; -import { ChangeEvent, useCallback, useState } from 'react'; +import { useCallback, useState } from 'react'; import { toast } from 'sonner'; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle -} from '@/components/ui/dialog'; -import { EnforceSwitch } from '@/components/switch'; +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, selectedProvider } = useManageProviderContext(); const { reload } = useDataGrid(); const { DeleteData } = useCallApi(); - const [enforce, setEnforce] = useState(false); - const [alert, setAlert] = useState({ - show: false, - message: '' - }); + const [alert, setAlert] = useState({ show: false, message: '' }); const doDeleteProvider = useCallback(async () => { - const response = await DeleteData(`${API_URL}/provider/delete/${selectedProvider}/${enforce}`, { + if (!selectedProvider) { + toast.error('No provider selected'); + return; + } + + const response = await DeleteData(`${API_URL}/provider/delete/${selectedProvider}/false`, { id: selectedProvider }); if (response?.status) { - setAlert((prev) => ({ ...prev, show: false, message: '' })); + setAlert({ show: false, message: '' }); handleDeleteDialog(false, null); toast.success('Success Delete Provider'); reload(); } else { - setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + setAlert({ show: true, message: response?.message }); toast.error('Failed Delete Provider'); } - }, [selectedProvider, enforce]); + }, [selectedProvider, DeleteData, handleDeleteDialog, reload]); return ( handleDeleteDialog(open, null)}> - +

Are you sure?

- you will delete this data! -
- - ) => { - setEnforce(e.target.checked); - }} - /> -
+ You will delete this data!
{alert.show && ( @@ -68,10 +53,10 @@ const DeleteDialog = () => { )}
- - diff --git a/src/pages/master/provider/blocks/EditDialog.tsx b/src/pages/master/provider/blocks/EditDialog.tsx index 93b487e..d60d4c2 100644 --- a/src/pages/master/provider/blocks/EditDialog.tsx +++ b/src/pages/master/provider/blocks/EditDialog.tsx @@ -55,7 +55,7 @@ const EditDialog = () => { description: '', type: '', status: '', - transactionTypeId: '', + transaction_type: '', agent: '', updated_by: '', updated_at: '' @@ -136,8 +136,8 @@ const EditDialog = () => { description: response?.data.description, type: response?.data.type, status: response?.data.status, - transactionTypeId: response?.data.transactionTypeId, - agent: response?.data.agent + transaction_type: response?.data.transaction_type.id, + agent: response?.data.agent.id })); } }, []); @@ -150,7 +150,7 @@ const EditDialog = () => { formField.description.trim() === '' || formField.type.trim() === '' || formField.status.trim() === '' || - formField.transactionTypeId.trim() === '' || + formField.transaction_type.trim() === '' || formField.agent.trim() === '' ) { setAlert({ show: true, message: 'Please fill in all required fields.' }); @@ -185,10 +185,10 @@ const EditDialog = () => { }, [formattedTime]); useEffect(() => { - getCustomerList([{ id: 'msisdn', desc: false }]); + getCustomerList([{ id: 'id', desc: false }]); getTransactionTypeList([{ id: 'name', desc: false }]); }, []); - + // console.log(selectedProvider); return ( handleEditDialog(open, null)}> @@ -282,9 +282,9 @@ const EditDialog = () => { Transaction Type Id* table.getColumn('sucos_name')?.setFilterValue(event.target.value) } diff --git a/src/pages/master/sucos/hooks/ManageSucosContext.tsx b/src/pages/master/sucos/hooks/ManageSucosContext.tsx index ddcd6c6..81e38a6 100644 --- a/src/pages/master/sucos/hooks/ManageSucosContext.tsx +++ b/src/pages/master/sucos/hooks/ManageSucosContext.tsx @@ -85,19 +85,13 @@ const ManageSucosContextProvider = ({ children }: { children: React.ReactNode }) const columns = useMemo[]>( () => [ - { - accessorKey: 'sucos_id', - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, { accessorFn: (row) => row.sucos_name, id: 'sucos_name', + filterFn: (row, columnId, filterValue) => { + const value = row.getValue(columnId); + return String(value).includes(String(filterValue)); + }, header: ({ column }) => , enableSorting: true, enableHiding: false, @@ -106,8 +100,12 @@ const ManageSucosContextProvider = ({ children }: { children: React.ReactNode }) } }, { - accessorFn: (row) => row.posto_name, + accessorKey: 'posto_name', id: 'posto_name', + filterFn: (row, columnId, filterValue) => { + const value = row.getValue(columnId); + return String(value).includes(String(filterValue)); + }, header: ({ column }) => , enableSorting: true, enableHiding: false, diff --git a/src/pages/master/walletRule/blocks/ListToolbar.tsx b/src/pages/master/walletRule/blocks/ListToolbar.tsx index fb78c55..2a2df4f 100644 --- a/src/pages/master/walletRule/blocks/ListToolbar.tsx +++ b/src/pages/master/walletRule/blocks/ListToolbar.tsx @@ -15,7 +15,7 @@ const ListToolbar = () => { table.getColumn('name')?.setFilterValue(event.target.value)} /> diff --git a/src/pages/master/walletRule/hooks/ManageWalletRuleContext.tsx b/src/pages/master/walletRule/hooks/ManageWalletRuleContext.tsx index e196eaa..b71f086 100644 --- a/src/pages/master/walletRule/hooks/ManageWalletRuleContext.tsx +++ b/src/pages/master/walletRule/hooks/ManageWalletRuleContext.tsx @@ -69,26 +69,6 @@ const ManageWalletRuleContextProvider = ({ children }: { children: React.ReactNo const columns = useMemo[]>( () => [ - { - accessorFn: (row) => row.ID, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, - { - accessorFn: (row) => row.IDWallet, - id: 'name', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[250px]' - } - }, { accessorFn: (row) => row.balance_minimum, id: 'balance_minimum', @@ -221,7 +201,7 @@ const ManageWalletRuleContextProvider = ({ children }: { children: React.ReactNo } layout={{ card: true }} sorting={[{ id: 'id', desc: false }]} diff --git a/src/pages/menu/manage-menu/blocks/ListToolbar.tsx b/src/pages/menu/manage-menu/blocks/ListToolbar.tsx index 784c705..9ed6b64 100644 --- a/src/pages/menu/manage-menu/blocks/ListToolbar.tsx +++ b/src/pages/menu/manage-menu/blocks/ListToolbar.tsx @@ -16,11 +16,11 @@ const ListToolbar = () => { table.getColumn('subMenu')?.setFilterValue(event.target.value)} + value={(table.getColumn('name')?.getFilterValue() as string) ?? ''} + onChange={(event) => table.getColumn('name')?.setFilterValue(event.target.value)} /> - + {/* - + */}
-
- + */}
+ + ); + }, + meta: { + headerClassName: 'w-[100px]', + cellClassName: 'text-center' + } + } + ], + []); + + const getTransactionLists = async (page: number, limit: number, sorting: any, filter: any) => { + try { + let startdate; + let enddate; + let formattedFilter; + + if (filter == undefined || filter.length==0) { + const today = new Date(); + const nextWeek = new Date(); + nextWeek.setDate(today.getDate() + 7); + + startdate = today.toISOString().split('T')[0]; + enddate = nextWeek.toISOString().split('T')[0]; + }else if (filter != undefined || filter.length!=0) { + startdate = filter[0].value.from; + enddate = filter[0].value.to; + } + + formattedFilter = { + "Transactions.transaction_date": { + from: startdate+" 00:00:00", + to: enddate+" 23:59:59" + } + }; + + const response = await GetData(`${API_URL}/transaction/history`, { + limit, + page: page + 1, + with_deleted: false, + order_field: "Transactions.created_at", + order_direction: 'DESC', + filter: JSON.stringify(formattedFilter) + }); + + setTransaction(response?.data.list); + return { data: response?.data.list, totalCount: response?.data.total_count }; + } catch (error) { + console.error('Error fetching transaction', error); + } + }; + + return ( + + + + } + layout={{ card: true }} + sorting={[{ id: 'id', desc: false }]} + serverSide={true} + onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) => + getTransactionLists(pageIndex, pageSize, sorting, columnFilters) + } + > + {children} + + + ); +}; + +export { TransactionProvider, ManageTransactionContext }; +export type { TransactionProps }; diff --git a/src/pages/transaction/hooks/useTransactionContext.tsx b/src/pages/transaction/hooks/useTransactionContext.tsx new file mode 100644 index 0000000..4af7036 --- /dev/null +++ b/src/pages/transaction/hooks/useTransactionContext.tsx @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import { ManageTransactionContext } from './TransactionContext'; + +const useTransactionContext = () => { + const context = useContext(ManageTransactionContext); + + if (!context) throw new Error('useTransactionContext must be used within AuthProvider'); + + return context; +}; + +export { useTransactionContext }; diff --git a/src/pages/transaction/transaction.tsx b/src/pages/transaction/transaction.tsx deleted file mode 100644 index 4fcba47..0000000 --- a/src/pages/transaction/transaction.tsx +++ /dev/null @@ -1,12 +0,0 @@ -const Transaction = () => { - return ( -
-
-

Transaction

-
-
- ); - }; - - export default Transaction; - \ No newline at end of file diff --git a/src/pages/transfer/blocks/AddDialog.tsx b/src/pages/transfer/blocks/AddDialog.tsx deleted file mode 100644 index 300425e..0000000 --- a/src/pages/transfer/blocks/AddDialog.tsx +++ /dev/null @@ -1,294 +0,0 @@ -import { apiConfig } from '@/config/api.config'; -import { useRef, useState } from 'react'; -import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; -import { Alert, KeenIcon, useDataGrid } from '@/components'; -import { useCallApi } from '@/hooks'; -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 CreateTransferTypeParams { - transfer_type_name: string; - description: string; - from_account: string; - to_account: string; - minimal_amount: number; - maximum_amount: number; - otp_threshold: number; - maximum_transaction_perDay: number; -} - -const API_URL = apiConfig.service_dashboard; - -const AddDialog = () => { - const parentRef = useRef(null); - const { showAddDialog, handleAddDialog, accounts } = useManageTransferTypeContext(); - const { reload } = useDataGrid(); - const { PostData, PutData } = useCallApi(); - const [alert, setAlert] = useState({ - show: false, - message: '' - }); - - const initialState = { - transfer_type_name: '', - description: '', - from_account: '', - to_account: '', - minimal_amount: 0, - maximum_amount: 0, - otp_threshold: 0, - maximum_transaction_perDay: 0 - }; - - const [formField, setFormField] = useState(initialState); - const resetForm = () => { - setFormField(initialState); - }; - const [isSubmitting, setIsSubmitting] = useState(false); - - const handleSubmit = (e: React.FormEvent) => { - e.preventDefault(); - // setIsSubmitting(true); - const payload = { - transfer_type_name: formField.transfer_type_name, - description: formField.description, - from_account: formField.from_account, - to_account: formField.to_account, - minimal_amount: formField.minimal_amount, - maximum_amount: formField.maximum_amount, - otp_threshold: formField.otp_threshold, - maximum_transaction_perDay: formField.maximum_transaction_perDay - }; - console.log(payload); - }; - - return ( - handleAddDialog(open)}> - - -
-
-

- Create Transfer Type -

-
-
-
{ - handleAddDialog(false); - resetForm(); - }} - > - -
-
-
- -
- {alert.show && ( - -

{alert.message}

-
- )} - -
-
-
- - - setFormField((prev) => ({ ...prev, transfer_type_name: target.value })) - } - /> -
-
- -
-
- - - setFormField((prev) => ({ ...prev, description: target.value })) - } - /> -
-
- -
-
- - -
- -
-
-
- -
-
- - -
- -
-
-
- -
-
- - - setFormField((prev) => ({ - ...prev, - minimal_amount: Number(target.value) - })) - } - /> -
-
- -
-
- - - setFormField((prev) => ({ - ...prev, - maximum_amount: Number(target.value) - })) - } - /> -
-
- -
-
- - - setFormField((prev) => ({ - ...prev, - otp_threshold: Number(target.value) - })) - } - /> -
-
- -
-
- - - setFormField((prev) => ({ - ...prev, - maximum_transaction_perDay: Number(target.value) - })) - } - /> -
-
- -
- - -
-
- -
-
-
-
- ); -}; - -export default AddDialog; diff --git a/src/pages/transfer/hooks/ManageTransferTypeContext.tsx b/src/pages/transfer/hooks/ManageTransferTypeContext.tsx deleted file mode 100644 index f41c7fd..0000000 --- a/src/pages/transfer/hooks/ManageTransferTypeContext.tsx +++ /dev/null @@ -1,175 +0,0 @@ -import { DataGridColumnHeader, DataGridProvider } 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 { createContext, useCallback, useEffect, useMemo, useState } from 'react'; -import ListToolbar from '../blocks/ListToolBar'; - -interface SelectedUser { - id: string; - name: string; - internal_name: string; - description: string; -} - -interface AccountProps { - id: string; - name: string; -} - -const accounts: string[] = [ - 'eMoney Account', - 'Topup Account', - 'Merchant Account', - 'Deposit Account', - 'Cash out/in' -]; - -interface ContextProps { - showEditDialog: boolean; - handleEditDialog: (show: boolean, selected_user: string | null) => void; - showAddDialog: boolean; - handleAddDialog: (show: boolean) => void; - selectedUser: string | null; - accounts: AccountProps[]; -} - -const initialProps: ContextProps = { - showEditDialog: false, - handleEditDialog: () => {}, - showAddDialog: false, - handleAddDialog: () => {}, - selectedUser: null, - accounts: [] -}; - -const ManageTransferTypeContext = createContext(initialProps); -const API_URL = apiConfig.service_dashboard; - -const ManageTransferTypeContextProvider = ({ children }: { children: React.ReactNode }) => { - const [showEditDialog, setShowEditDialog] = useState(false); - const [showAddDialog, setShowAddDialog] = useState(false); - const [selectedUser, setSelectedUser] = useState(null); - const [accounts, setAccount] = useState([]); - const { GetData } = useCallApi(); - - useEffect(() => { - setAccount([ - { id: '1', name: 'eMoney Account' }, - { id: '2', name: 'Topup Account' }, - { id: '3', name: 'Merchant Account' }, - { id: '4', name: 'Deposit Account' }, - { id: '5', name: 'Cash in/out Account' } - ]); - }, []); - - const handleEditDialog = useCallback((show: boolean, selected_user: string | null) => { - setSelectedUser(show ? selected_user : null); - setShowEditDialog(show); - }, []); - - const handleAddDialog = useCallback((show: boolean) => { - setShowAddDialog(show); - }, []); - - const columns = useMemo[]>( - () => [ - { - accessorFn: (row) => row.id, - id: 'id', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[100px]' - } - }, - { - accessorFn: (row) => row.name, - id: 'name', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[250px]' - } - }, - { - accessorFn: (row) => row.internal_name, - id: 'internal_name', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[250px]' - } - }, - { - accessorFn: (row) => row.description, - id: 'description', - header: ({ column }) => , - enableSorting: true, - enableHiding: false, - meta: { - headerClassName: 'w-[250px]' - } - }, - { - id: 'actions', - enableSorting: false, - header: ({ column }) => , - cell: ({ row }) => { - return ( - <> - - - - ); - }, - meta: { - headerClassName: 'w-[100px]', - cellClassName: 'text-center' - } - } - ], - [handleAddDialog, handleEditDialog] - ); - - return ( -
- - - } - sorting={[{ id: 'id', desc: true }]} - serverSide={true} - > - {children} - - -
- ); -}; - -export { ManageTransferTypeContext, ManageTransferTypeContextProvider }; -export type { SelectedUser }; diff --git a/src/pages/transfer/transferfee/blocks/AddDialog.tsx b/src/pages/transfer/transferfee/blocks/AddDialog.tsx new file mode 100644 index 0000000..73bdcfd --- /dev/null +++ b/src/pages/transfer/transferfee/blocks/AddDialog.tsx @@ -0,0 +1,410 @@ +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useManageTransferFeeContext } from '../hooks/useManageTransferFeeContext'; +import { NumericFormat } from 'react-number-format'; +import { + Alert, + Container, + DataGridColumnHeader, + DataGridInner, + KeenIcon, + useDataGrid +} from '@/components'; +import { useCallApi } from '@/hooks'; +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 { toast } from 'sonner'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; +import { getAuth } from '@/auth'; +import { + Table, + TableBody, + TableCaption, + TableCell, + TableFooter, + TableHead, + TableHeader, + TableRow +} from '@/components/ui/table'; +import { ManageTransferFeeContext } from '../hooks/ManageTransferFeeContext'; +import { ColumnDef } from '@tanstack/react-table'; +import { ManageTransferFeeContextProvider } from '../../transferfee/hooks/ManageTransferFeeContext'; +import { apiConfig } from '@/config/api.config'; +import { get } from 'http'; + +interface TransactionTypeProps { + id: string; + name: string; +} + +const API_URL = apiConfig.service_transaction; + +const AddFeeDialog = () => { + const parentRef = useRef(null); + const { reload } = useDataGrid(); + const { PostData, PutData, GetData } = useCallApi(); + const { showAddFeeDialog, handleAddFeeDialog, handleEditFeeDialog, selectedTransferFee } = + useManageTransferFeeContext(); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + const [transactionTypes, setTransactionTypes] = useState([]); + + const initialState = { + name: '', + description: '', + transaction_type: '', + minimum_amount: 0, + maximum_amount: 0, + period_start: '', + period_end: '', + deduct_amount: 0, + deduct_percentage: 0, + priority: false, + status: '', + status_include: '', + created_by: '', + created_at: '' + }; + + const [formField, setFormField] = useState(initialState); + + const resetForm = () => { + setFormField(initialState); + }; + + const [isSubmitting, setIsSubmitting] = useState(false); + const [showTransactionFeeDialog, setShowTransactionFeeDialog] = useState(false); + const parsedUser = getAuth()?.user; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + // setIsSubmitting(true); + const payload = { + name: formField.name, + description: formField.description, + period_start: formField.period_start, + period_end: formField.period_end, + minimum_amount: formField.minimum_amount, + maximum_amount: formField.maximum_amount, + deduct_amount: formField.deduct_amount, + deduct_percentage: formField.deduct_percentage, + transaction_type: formField.transaction_type, + status: formField.status, + status_include: formField.status_include, + priority: formField.priority ? 'Y' : 'N' + }; + }; + useEffect(() => { + const created_time = new Date(); + const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); + + if (showAddFeeDialog) { + setFormField({ + ...formField, + created_by: parsedUser?.username, + created_at: formattedTime + }); + } + }, [showAddFeeDialog]); + + useEffect(() => { + if (!showAddFeeDialog) return; + + const getTransactionTypeList = async (sorting: any) => { + try { + sorting = sorting.length === 0 ? [{ id: 'name', desc: false }] : sorting; + const response = await GetData(`${API_URL}/transactiontype/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'DESC' : 'ASC' + }); + setTransactionTypes(response?.data.list || []); + } catch (error) { + console.error('Error fetching customer', error); + } + }; + + getTransactionTypeList([{ id: 'id', desc: false }]); + }, [showAddFeeDialog]); + + const doCreateTransferType = useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + for (const key in formField) { + if ( + formField[key as keyof typeof formField] === '' || + formField[key as keyof typeof formField] === 0 + ) { + setAlert({ show: true, message: 'All fields must be filled out' }); + return; + } + } + + setAlert({ show: false, message: '' }); + const response = await PostData(`${API_URL}/transactionfees/create`, { + ...formField + }); + console.log(response); + if (response?.status) { + toast.success('Success Create Transfer Fee'); + reload(); + resetForm(); + handleAddFeeDialog(false); + } else { + setAlert({ show: true, message: response?.message || 'Failed to create transfer fee' }); + } + }, + [formField] + ); + + return ( + handleAddFeeDialog(open)}> + + + + +
+
+

Add Transfer Fee

+
+
{ + handleAddFeeDialog(false); + resetForm(); + }} + > + +
+
+
+ + {alert.show && {alert.message}} +
+
+
+
+ + + setFormField((prev) => ({ ...prev, name: target.value })) + } + /> +
+
+ + + setFormField((prev) => ({ ...prev, description: target.value })) + } + /> +
+
+ + { + setFormField((prev) => ({ + ...prev, + minimum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Max Transaction Per Day" + /> +
+
+ + { + setFormField((prev) => ({ + ...prev, + maximum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Max Transaction Per Day" + /> +
+
+ + + setFormField((prev) => ({ ...prev, period_start: target.value })) + } + /> +
+
+ + + setFormField((prev) => ({ ...prev, period_end: target.value })) + } + /> +
+
+ + { + setFormField((prev) => ({ + ...prev, + deduct_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Max Transaction Per Day" + /> +
+
+ + { + setFormField((prev) => ({ + ...prev, + deduct_percentage: values.floatValue || 0 + })); + }} + placeholder="Enter Max Transaction Per Day" + /> +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+
+ ); +}; + +export default AddFeeDialog; diff --git a/src/pages/transfer/transferfee/blocks/DeleteDialog.tsx b/src/pages/transfer/transferfee/blocks/DeleteDialog.tsx new file mode 100644 index 0000000..e3d2f88 --- /dev/null +++ b/src/pages/transfer/transferfee/blocks/DeleteDialog.tsx @@ -0,0 +1,69 @@ +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { Alert, useDataGrid } from '@/components'; +import { useCallback, useState } from 'react'; +import { apiConfig } from '@/config/api.config'; +import { toast } from 'sonner'; +import { useCallApi } from '@/hooks'; +import { useManageTransferFeeContext } from '../hooks/useManageTransferFeeContext'; +import { DialogDescription } from '@radix-ui/react-dialog'; + +const API_URL = apiConfig.service_transaction; + +const DeleteDialog = () => { + const { showDeleteFeeDialog, handleDeleteFeeDialog, selectedTransferFee } = useManageTransferFeeContext(); + const { reload } = useDataGrid(); + const { DeleteData } = useCallApi(); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + + const doDeleteTransferFee = useCallback(async () => { + // Kirim enforce=false untuk memastikan soft delete + const response = await DeleteData(`${API_URL}/transactionfees/delete/${selectedTransferFee}/false`, { + id: selectedTransferFee + }); + + if (response?.status) { + setAlert({ show: false, message: '' }); + handleDeleteFeeDialog(false, null); + toast.success('Success Delete Product'); + reload(); + } else { + toast.error('Failed Delete Product'); + setAlert({ show: true, message: response?.message }); + } + }, [selectedTransferFee]); + + return ( + handleDeleteFeeDialog(open, null)}> + + + Delete Transfer Type + Are you sure you want to delete this data? + +

Are you sure?

+ You will delete this data! +
+ {alert.show && ( + +

{alert.message}

+
+ )} +
+ + + + +
+
+ ); +}; + +export default DeleteDialog; +export { DeleteDialog }; diff --git a/src/pages/transfer/transferfee/blocks/EditDialog.tsx b/src/pages/transfer/transferfee/blocks/EditDialog.tsx new file mode 100644 index 0000000..34e990e --- /dev/null +++ b/src/pages/transfer/transferfee/blocks/EditDialog.tsx @@ -0,0 +1,499 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; +import { NumericFormat } from 'react-number-format'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@/components/ui/select'; + +import { + Dialog, + DialogBody, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import { useManageTransferFeeContext } from '../hooks/useManageTransferFeeContext'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { apiConfig } from '@/config/api.config'; +import { Alert, Container, DataGridInner, KeenIcon, useDataGrid } from '@/components'; +import { toast } from 'sonner'; +import { useCallApi } from '@/hooks'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; +import { getAuth } from '@/auth'; +import { ManageTransferFeeContextProvider } from '../../transferfee/hooks/ManageTransferFeeContext'; +import AddFeeDialog from '../../transferfee/blocks/AddDialog'; + +const API_URL = apiConfig.service_transaction; +const API_URL_MASTERDATA = apiConfig.service_master_data; +const API_URL_CUSTOMER = apiConfig.service_customer; + +interface WalletProps { + Wallet_id: string; + Wallet_name: string; +} + +interface CustomerProps { + id: string; + username: string; + msisdn: string; +} + +interface TransactionTypeProps { + id: string; + name: string; +} + +const EditFeeDialog = () => { + const parentRef = useRef(null); + const { showEditFeeDialog, handleEditFeeDialog, selectedTransferFee } = + useManageTransferFeeContext(); + const { reload } = useDataGrid(); + const [wallets, setWallets] = useState([]); + const { GetData, PutData } = useCallApi(); + const [isSubmitting, setIsSubmitting] = useState(false); + const [transactionTypes, setTransactionTypes] = useState([]); + const parsedUser = getAuth()?.user; + const [customers, setCustomers] = useState([]); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + const [formField, setFormField] = useState({ + name: '', + description: '', + minimum_amount: 0, + maximum_amount: 0, + period_start: '', + period_end: '', + deduct_amount: 0, + deduct_percentage: 0, + priority: false, + status: '', + status_include: '', + transaction_type: '', + updated_by: '', + updated_at: '' + }); + useEffect(() => { + const updated_time = new Date(); + const formattedTime = updated_time.toISOString().slice(0, 19).replace('T', ' '); + + if (showEditFeeDialog) { + setFormField({ + ...formField, + updated_by: parsedUser?.username, + updated_at: formattedTime + }); + } + }, [showEditFeeDialog]); + /* actions */ + const doUpdateTransferFee = useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + const response = await PutData(`${API_URL}/transactionfees/update/${selectedTransferFee}`, { + ...formField, + priority: formField.priority ? 'Y' : 'N' // Ubah ke "Y" atau "N" + }); + if (response?.status) { + handleEditFeeDialog(false, null); + toast.success('Success Update User'); + reload(); + } else { + setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + } + }, + [formField, selectedTransferFee] + ); + const fetchWallets = useCallback(async () => { + const params = { + limit: 100, + page: 1, + with_deleted: false, + order_field: 'name', + order_direction: 'ASC', + filter: JSON.stringify({ + status: 'Y' + }) + }; + const response = await GetData(`${API_URL_MASTERDATA}/wallet/list`, params); + if (response?.status && response?.data) { + setWallets(response.data.list); + } else { + setWallets([]); + } + }, []); + + useEffect(() => { + fetchWallets(); + }, [fetchWallets]); + + useEffect(() => { + if (!showEditFeeDialog) return; + + const getCustomerList = async (sorting: any) => { + try { + sorting = sorting.length === 0 ? [{ id: 'name', desc: false }] : sorting; + const response = await GetData(`${API_URL_CUSTOMER}/customer/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'DESC' : 'ASC' + }); + setCustomers(response?.data.list || []); + } catch (error) { + console.error('Error fetching customer', error); + } + }; + + getCustomerList([{ id: 'msisdn', desc: false }]); + }, []); + useEffect(() => { + if (!showEditFeeDialog) return; + + const getTransactionTypeList = async (sorting: any) => { + try { + sorting = sorting.length === 0 ? [{ id: 'name', desc: false }] : sorting; + const response = await GetData(`${API_URL}/transactiontype/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'DESC' : 'ASC' + }); + // console.log('Transaction Type: ', response?.data.list); + setTransactionTypes(response?.data.list); + } catch (error) { + console.error('Error fetching Transaction Type', error); + } + }; + + getTransactionTypeList([{ id: 'id', desc: false }]); + }, [showEditFeeDialog]); + + const fetchTransactionFee = useCallback(async (id: string) => { + const response = await GetData(`${API_URL}/transactionfees/getdata/${id}`, { id }); + + if (response?.status) { + setFormField((prev) => ({ + ...prev, + name: response.data.name, + description: response.data.description, + minimum_amount: response.data.minimum_amount, + maximum_amount: response.data.maximum_amount, + period_start: response.data.period_start, + period_end: response.data.period_end, + deduct_amount: response.data.deduct_amount, + deduct_percentage: response.data.deduct_percentage, + priority: response.data.priority === 'Y', + status: response.data.status, + status_include: response.data.status_include, + transaction_type: response.data.transaction_type.id + })); + } + }, []); + + useEffect(() => { + if (selectedTransferFee) { + fetchTransactionFee(selectedTransferFee); + } + }, [selectedTransferFee]); + const resetForm = () => { + setFormField({ + name: '', + description: '', + minimum_amount: 0, + maximum_amount: 0, + period_start: '', + period_end: '', + deduct_amount: 0, + deduct_percentage: 0, + priority: false, + status: '', + status_include: '', + transaction_type: '', + updated_by: '', + updated_at: '' + }); + }; + + return ( + handleEditFeeDialog(open, null)}> + + + + +
+
+

+ Update Transaction Fee +

+
+
+
handleEditFeeDialog(false, null)} + > + +
+
+
+ +
+ {alert.show && ( + +

{alert.message}

+
+ )} +
+
+
+
+ + + setFormField((prev) => ({ ...prev, name: target.value })) + } + /> +
+
+ + + setFormField((prev) => ({ ...prev, description: target.value })) + } + /> +
+
+ + { + setFormField((prev) => ({ + ...prev, + minimum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Minimum Amount" + /> +
+
+ + { + setFormField((prev) => ({ + ...prev, + maximum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Minimum Amount" + /> +
+
+ + + setFormField((prev) => ({ ...prev, period_start: target.value })) + } + /> +
+
+ + + setFormField((prev) => ({ ...prev, period_end: target.value })) + } + /> +
+
+ + { + setFormField((prev) => ({ + ...prev, + deduct_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Minimum Amount" + /> +
+
+ + { + setFormField((prev) => ({ + ...prev, + deduct_percentage: values.floatValue || 0 + })); + }} + placeholder="Enter Minimum Amount" + /> +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + {/*
+ + +
*/} + + {/*
+ + +
*/} +
+ + +
+
+
+
+
+
+
+
+ ); +}; + +export { EditFeeDialog }; diff --git a/src/pages/transfer/transferfee/blocks/ListToolBar.tsx b/src/pages/transfer/transferfee/blocks/ListToolBar.tsx new file mode 100644 index 0000000..9acdc39 --- /dev/null +++ b/src/pages/transfer/transferfee/blocks/ListToolBar.tsx @@ -0,0 +1,44 @@ + import { DefaultTooltip, KeenIcon, useDataGrid } from '@/components'; + import { useManageTransferFeeContext } from '../hooks/useManageTransferFeeContext'; + import { Button } from '@/components/ui/button'; + + const ListToolbar = () => { + const { table, reload } = useDataGrid(); + const { handleAddFeeDialog, handleEditFeeDialog, selectedTransferFee} = useManageTransferFeeContext(); + + return ( +
+
+
+
+ +
+
+ + + + +
+
+
+
+ ); + }; + + export default ListToolbar; diff --git a/src/pages/transfer/transferfee/hooks/ManageTransferFeeContext.tsx b/src/pages/transfer/transferfee/hooks/ManageTransferFeeContext.tsx new file mode 100644 index 0000000..8188d4d --- /dev/null +++ b/src/pages/transfer/transferfee/hooks/ManageTransferFeeContext.tsx @@ -0,0 +1,241 @@ +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 { createContext, useCallback, useEffect, useMemo, useState } from 'react'; +import ListToolbar from '../blocks/ListToolBar'; +import DeleteDialog from '../blocks/DeleteDialog'; +import { EditFeeDialog } from '../blocks/EditDialog'; + +interface ContextProps { + showEditFeeDialog: boolean; + handleEditFeeDialog: (show: boolean, selectedTransferFee: string | null) => void; + showAddFeeDialog: boolean; + handleAddFeeDialog: (show: boolean) => void; + handleDeleteFeeDialog: (show: boolean, selectedTransferFee: string | null) => void; + showDeleteFeeDialog: boolean; + selectedTransferFee: string | null; +} + +const initialProps: ContextProps = { + showEditFeeDialog: false, + handleEditFeeDialog: () => {}, + showAddFeeDialog: false, + handleAddFeeDialog: () => {}, + showDeleteFeeDialog: false, + handleDeleteFeeDialog: () => {}, + selectedTransferFee: null +}; + +const ManageTransferFeeContext = createContext(initialProps); +const API_URL = apiConfig.service_transaction; + +const ManageTransferFeeContextProvider = ({ children }: { children: React.ReactNode }) => { + const [showEditFeeDialog, setShowEditFeeDialog] = useState(false); + const [showAddFeeDialog, setShowAddFeeDialog] = useState(false); + const [showDeleteFeeDialog, setShowDeleteFeeDialog] = useState(false); + + const [selectedTransferFee, setSelectedTransferFee] = useState(null); + const { GetData } = useCallApi(); + + const handleEditFeeDialog = useCallback((show: boolean, selectedTransferFee: string | null) => { + setSelectedTransferFee(show ? selectedTransferFee : null); + setShowEditFeeDialog(show); + }, []); + + const handleAddFeeDialog = useCallback((show: boolean) => { + setShowAddFeeDialog(show); + }, []); + + const handleDeleteFeeDialog = useCallback((show: boolean, selectedTransferFee: string | null) => { + setSelectedTransferFee(show ? selectedTransferFee : null); + setShowDeleteFeeDialog(show); + }, []); + const doGetTransferFeeListData = async ( + page: number, + limit: number, + sorting: any, + filter: any + ) => { + sorting = sorting.length == 0 ? [{ id: 'id', desc: false }] : sorting; + filter = filter.length == 0 ? {} : { any: filter[0].value.toLowerCase() }; + const response = await GetData(`${API_URL}/transactionfees/list`, { + limit: limit, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'ASC' : 'DESC', + filter: JSON.stringify(filter) + }); + return { data: response?.data.list, totalCount: response?.data.total_count }; + }; + const columns = useMemo[]>( + () => [ + { + accessorFn: (row) => row.name, + id: 'name', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[200px]' } + }, + { + accessorFn: (row) => row.description, + id: 'description', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => row.minimum_amount, + id: 'minimum_amount', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.maximum_amount, + id: 'maximum_amount', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.period_start?.split('T')[0], + id: 'period_start', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[200px]' } + }, + { + accessorFn: (row) => row.period_end?.split('T')[0], + id: 'period_end', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[200px]' } + }, + { + accessorFn: (row) => row.deduct_amount, + id: 'deduct_amount', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.deduct_percentage, + id: 'deduct_percentage', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => row.transaction_type?.name, + id: 'transactionTypeId', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[250px]' } + }, + { + accessorFn: (row) => (row.priority === 'Y' ? 'Yes' : 'No'), + id: 'priority', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[100px]' } + }, + { + accessorFn: (row) => (row.status === 'Y' ? 'Active' : 'Inactieve'), + id: 'status', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + accessorFn: (row) => (row.status_include === 'Y' ? 'Yes' : 'No'), + id: 'status_include', + header: ({ column }) => , + enableSorting: true, + enableHiding: false, + meta: { headerClassName: 'w-[150px]' } + }, + { + id: 'actions', + header: ({ column }) => , + enableSorting: false, + enableHiding: false, + cell: (data) => { + const row = data.row.original; + return ( + <> + + + + ); + }, + meta: { + headerClassName: 'w-[100px]', + cellClassName: 'text-center' + } + } + ], + [handleEditFeeDialog, handleDeleteFeeDialog] + ); + + return ( +
+
+

Manage Transaction Fee

+
+ + + } + sorting={[{ id: 'id', desc: true }]} + serverSide={true} + onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) => + doGetTransferFeeListData(pageIndex, pageSize, sorting, columnFilters) + } + > + {children} + + + + +
+ ); +}; + +export { ManageTransferFeeContext, ManageTransferFeeContextProvider }; diff --git a/src/pages/transfer/transferfee/hooks/useManageTransferFeeContext.tsx b/src/pages/transfer/transferfee/hooks/useManageTransferFeeContext.tsx new file mode 100644 index 0000000..11873ba --- /dev/null +++ b/src/pages/transfer/transferfee/hooks/useManageTransferFeeContext.tsx @@ -0,0 +1,12 @@ +import { useContext } from 'react'; +import { ManageTransferFeeContext } from './ManageTransferFeeContext'; + +const useManageTransferFeeContext = () => { + const context = useContext(ManageTransferFeeContext); + + if (!context) throw new Error('useManageAccessTypeContext must be used within AuthProvider'); + + return context; +}; + +export { useManageTransferFeeContext }; diff --git a/src/pages/transfer/TransferType.tsx b/src/pages/transfer/transfertype/TransferType.tsx similarity index 79% rename from src/pages/transfer/TransferType.tsx rename to src/pages/transfer/transfertype/TransferType.tsx index 031c462..daa87c6 100644 --- a/src/pages/transfer/TransferType.tsx +++ b/src/pages/transfer/transfertype/TransferType.tsx @@ -5,12 +5,15 @@ import { } from './hooks/ManageTransferTypeContext'; import AddDialog from './blocks/AddDialog'; import { Breadcrumbs, Link } from '@mui/material'; +import { DeleteDialog } from './blocks/DeleteDialog'; +import { EditDialog } from './blocks/EditDialog'; const TransferType = () => { + return ( -

Manage Access Type

+

Manage Transaction Type

Dashboard @@ -21,13 +24,16 @@ const TransferType = () => { - Manage Access Type + Manage Transfer Type
+ + +
); diff --git a/src/pages/transfer/transfertype/blocks/AddDialog.tsx b/src/pages/transfer/transfertype/blocks/AddDialog.tsx new file mode 100644 index 0000000..453fdcf --- /dev/null +++ b/src/pages/transfer/transfertype/blocks/AddDialog.tsx @@ -0,0 +1,493 @@ +import { apiConfig } from '@/config/api.config'; +import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; +import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; +import { + Alert, + Container, + DataGridColumnHeader, + DataGridInner, + KeenIcon, + useDataGrid +} from '@/components'; +import { useCallApi } from '@/hooks'; +import { NumericFormat } from 'react-number-format'; +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 { toast } from 'sonner'; +import { getAuth } from '@/auth'; + +interface WalletProps { + Wallet_id: string; + Wallet_name: string; +} + +interface CustomerProps { + id: string; + username: string; + msisdn: string; +} + +const API_URL = apiConfig.service_transaction; +const API_URL_MASTERDATA = apiConfig.service_master_data; +const API_URL3_CUSTOMER = apiConfig.service_customer; + +const AddDialog = () => { + const parentRef = useRef(null); + const { GetData } = useCallApi(); + const { showAddDialog, handleAddDialog, selectedTransferType } = useManageTransferTypeContext(); + const [wallets, setWallets] = useState([]); + const [customers, setCustomers] = useState([]); + const { reload } = useDataGrid(); + const { PostData, PutData } = useCallApi(); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + + const initialState = { + name: '', + description: '', + wallet_origin: '', + wallet_destination: '', + wallet_fee_destination: '', + customer_fee_destination: '', + minimum_amount: 0, + maximum_amount: 0, + max_transaction_per_day: 0, + status: '', + status_approval: '', + created_by: '', + created_at: '' + }; + + const [formField, setFormField] = useState(initialState); + + const resetForm = () => { + setFormField(initialState); + }; + const [isSubmitting, setIsSubmitting] = useState(false); + + const parsedUser = getAuth()?.user; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + // setIsSubmitting(true); + const payload = { + name: formField.name, + description: formField.description, + wallet_origin: formField.wallet_origin, + wallet_destination: formField.wallet_destination, + minimum_amount: formField.minimum_amount, + maximum_amount: formField.maximum_amount, + max_transaction_per_day: formField.max_transaction_per_day, + wallet_fee_destination: formField.wallet_fee_destination, + customer_fee_destination: formField.customer_fee_destination, + status_approval: formField.status_approval, + status: formField.status + }; + }; + useEffect(() => { + const created_time = new Date(); + const formattedTime = created_time.toISOString().slice(0, 19).replace('T', ' '); + + if (showAddDialog) { + setFormField({ + ...formField, + created_by: parsedUser?.username, + created_at: formattedTime + }); + } + }, [showAddDialog]); + + useEffect(() => { + if (!showAddDialog) return; + const getCustomerList = async (sorting: any) => { + try { + sorting = sorting.length === 0 ? [{ id: 'name', desc: false }] : sorting; + + const response = await GetData(`${API_URL3_CUSTOMER}/customer/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'DESC' : 'ASC' + }); + setCustomers(response?.data.list); + console.log('CUSTOMER: ', response?.data.list); + } catch (error) { + console.error('Error fetching customer', error); + } + }; + + getCustomerList([{ id: 'id', desc: false }]); + }, [showAddDialog]); + + const fetchWallets = useCallback(async () => { + const params = { + limit: 100, + page: 1, + with_deleted: false, + order_field: 'name', + order_direction: 'ASC', + filter: JSON.stringify({ + status: 'Y' + }) + }; + const response = await GetData(`${API_URL_MASTERDATA}/wallet/list`, params); + if (response?.status && response?.data) { + setWallets(response.data.list); + } else { + setWallets([]); + } + }, []); + + useEffect(() => { + if (!showAddDialog) return; + fetchWallets(); + }, [showAddDialog]); + + const doCreateTransferType = useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + for (const key in formField) { + if ( + formField[key as keyof typeof formField] === '' || + formField[key as keyof typeof formField] === 0 + ) { + setAlert({ show: true, message: 'All fields must be filled out' }); + return; + } + } + + setAlert({ show: false, message: '' }); + + const response = await PostData(`${API_URL}/transactiontype/create`, formField); + + if (response?.status) { + setAlert({ show: false, message: '' }); + handleAddDialog(false); + toast.success('Success Create Transfer Type'); + reload(); + resetForm(); + } else { + setAlert({ show: true, message: response?.message || 'Failed to create transfer type' }); + } + handleAddDialog(false); + }, + [formField] + ); + + return ( + handleAddDialog(open)}> + + + + +
+
+

+ Addd Transaction Type +

+
+
+
{ + handleAddDialog(false); + resetForm(); + }} + > + +
+
+
+ +
+ {alert.show && ( + +

{alert.message}

+
+ )} +
+
+
+
+ + + setFormField((prev) => ({ ...prev, name: target.value })) + } + /> +
+
+ +
+
+ + + setFormField((prev) => ({ ...prev, description: target.value })) + } + /> +
+
+ +
+
+ + { + setFormField((prev) => ({ + ...prev, + minimum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Minimum Amount" + /> +
+
+ +
+
+ + { + setFormField((prev) => ({ + ...prev, + maximum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Maximum Amount" + /> +
+
+
+
+ + { + setFormField((prev) => ({ + ...prev, + max_transaction_per_day: values.floatValue || 0 + })); + }} + placeholder="Enter Max Transaction Per Day" + /> +
+
+
+
+ +
+ +
+
+
+ +
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+ +
+
+ + +
+ +
+
+
+ +
+
+ + +
+ +
+
+
+ +
+ + +
+
+
+
+
+
+
+ ); +}; + +export default AddDialog; diff --git a/src/pages/transfer/transfertype/blocks/DeleteDialog.tsx b/src/pages/transfer/transfertype/blocks/DeleteDialog.tsx new file mode 100644 index 0000000..0f610e3 --- /dev/null +++ b/src/pages/transfer/transfertype/blocks/DeleteDialog.tsx @@ -0,0 +1,74 @@ +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { Alert, useDataGrid } from '@/components'; +import { useCallback, useState } from 'react'; +import { apiConfig } from '@/config/api.config'; +import { toast } from 'sonner'; +import { useCallApi } from '@/hooks'; +import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; +import { DialogDescription } from '@radix-ui/react-dialog'; + +const API_URL = apiConfig.service_transaction; + +const DeleteDialog = () => { + const { showDeleteDialog, handleDeleteDialog, selectedTransferType } = useManageTransferTypeContext(); + const { reload } = useDataGrid(); + const { DeleteData } = useCallApi(); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + + const doDeleteTransferType = useCallback(async () => { + if (!selectedTransferType) { + toast.error('No Transfer Type selected'); + return; + } + + // Kirim enforce=false untuk memastikan soft delete + const response = await DeleteData(`${API_URL}/transactiontype/delete/${selectedTransferType}/false`, { + id: selectedTransferType + }); + + if (response?.status) { + setAlert({ show: false, message: '' }); + handleDeleteDialog(false, null); + reload(); + setTimeout(() => toast.success('Success Delete Product'), 0); + } else { + setAlert({ show: true, message: response?.message }); + setTimeout(() => toast.error('Failed Delete Product'), 0); + } + }, [selectedTransferType, DeleteData, handleDeleteDialog, reload]); + + return ( + handleDeleteDialog(open, null)}> + + + Delete Transfer Type + Are you sure you want to delete this data? + +

Are you sure?

+ You will delete this data! +
+ {alert.show && ( + +

{alert.message}

+
+ )} +
+ + + + +
+
+ ); +}; + +export default DeleteDialog; +export { DeleteDialog }; diff --git a/src/pages/transfer/transfertype/blocks/EditDialog.tsx b/src/pages/transfer/transfertype/blocks/EditDialog.tsx new file mode 100644 index 0000000..15f56e0 --- /dev/null +++ b/src/pages/transfer/transfertype/blocks/EditDialog.tsx @@ -0,0 +1,513 @@ +import { useCallback, useEffect, useRef, useState } from 'react'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue +} from '@/components/ui/select'; +import { NumericFormat } from 'react-number-format'; +import { + Dialog, + DialogBody, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle +} from '@/components/ui/dialog'; +import { useManageTransferTypeContext } from '../hooks/useManageTransferTypeContext'; +import { Input } from '@/components/ui/input'; +import { Button } from '@/components/ui/button'; +import { apiConfig } from '@/config/api.config'; +import { Alert, Container, DataGridInner, KeenIcon, useDataGrid } from '@/components'; +import { toast } from 'sonner'; +import { useCallApi } from '@/hooks'; +import { doSaveLogActivity } from '@/actions/GlobalActions'; +import { getAuth } from '@/auth'; +import { ManageTransferFeeContextProvider } from '../../transferfee/hooks/ManageTransferFeeContext'; +import AddFeeDialog from '../../transferfee/blocks/AddDialog'; + +const API_URL = apiConfig.service_transaction; +const API_URL_MASTERDATA = apiConfig.service_master_data; +const API_URL_CUSTOMER = apiConfig.service_customer; + +interface WalletProps { + Wallet_id: string; + Wallet_name: string; +} + +interface CustomerProps { + id: string; + username: string; + msisdn: string; +} + +interface TranssactionTypeProps { + name: string; + description: string; + minimum_amount: number; + maximum_amount: number; + max_transaction_per_day: number; + status_approval: string; + status: string; + wallet_origin: WalletProps; + wallet_destination: WalletProps; + wallet_fee_destination: WalletProps; + customer_fee_destination: CustomerProps; +} + +const EditDialog = () => { + const parentRef = useRef(null); + const { showEditDialog, handleEditDialog, selectedTransferType, accounts } = + useManageTransferTypeContext(); + const { reload } = useDataGrid(); + const [wallets, setWallets] = useState([]); + const { GetData, PutData } = useCallApi(); + const [isSubmitting, setIsSubmitting] = useState(false); + const parsedUser = getAuth()?.user; + const [customers, setCustomers] = useState([]); + const [transactiontypes, setTransactionTypes] = useState([]); + const [alert, setAlert] = useState({ + show: false, + message: '' + }); + const resetForm = () => { + setFormField({ + name: '', + description: '', + wallet_origin: '', + wallet_destination: '', + wallet_fee_destination: '', + customer_fee_destination: '', + minimum_amount: 0, + maximum_amount: 0, + max_transaction_per_day: 0, + status_approval: '', + status: '', + updated_by: '', + updated_at: '' + }); + }; + const [formField, setFormField] = useState({ + name: '', + description: '', + wallet_origin: '', + wallet_destination: '', + wallet_fee_destination: '', + customer_fee_destination: '', + minimum_amount: 0, + maximum_amount: 0, + max_transaction_per_day: 0, + status_approval: '', + status: '', + updated_by: '', + updated_at: '' + }); + useEffect(() => { + const updated_time = new Date(); + const formattedTime = updated_time.toISOString().slice(0, 19).replace('T', ' '); + + if (showEditDialog) { + setFormField({ + ...formField, + updated_by: parsedUser?.username, + updated_at: formattedTime + }); + } + }, [showEditDialog]); + /* actions */ + const doUpdateTransferType = useCallback( + async (e: React.FormEvent) => { + e.preventDefault(); + const response = await PutData(`${API_URL}/transactiontype/update/${selectedTransferType}`, { + ...formField + }); + if (response?.status) { + handleEditDialog(false, null); + toast.success('Success Update User'); + reload(); + } else { + setAlert((prev) => ({ ...prev, show: true, message: response?.message })); + } + }, + [formField, selectedTransferType] + ); + useEffect(() => { + const getCustomerList = async (sorting: any) => { + try { + sorting = sorting.length === 0 ? [{ id: 'name', desc: false }] : sorting; + const response = await GetData(`${API_URL_CUSTOMER}/customer/list`, { + limit: 100, + page: 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'DESC' : 'ASC' + }); + console.log('CUSTOMER: ', response?.data.list); + setCustomers(response?.data.list); + } catch (error) { + console.error('Error fetching customer', error); + } + }; + + getCustomerList([{ id: 'id', desc: false }]); + }, []); + const fetchWallets = useCallback(async () => { + const params = { + limit: 100, + page: 1, + with_deleted: false, + order_field: 'name', + order_direction: 'ASC', + filter: JSON.stringify({ + status: 'Y' + }) + }; + const response = await GetData(`${API_URL_MASTERDATA}/wallet/list`, params); + if (response?.status && response?.data) { + setWallets(response.data.list); + } else { + setWallets([]); + } + }, []); + + useEffect(() => { + fetchWallets(); + }, [fetchWallets]); + + const fetchTransactionType = useCallback(async (id: string) => { + const response = await GetData(`${API_URL}/transactiontype/getdata/${id}`, { id }); + console.log('Transaction Type: ', response?.data); + if (response?.status) { + setFormField((prev) => ({ + ...prev, + name: response.data.name, + description: response.data.description, + wallet_origin: response.data.wallet_origin.id, + wallet_destination: response.data.wallet_destination.id, + wallet_fee_destination: response.data.wallet_fee_destination.id, + customer_fee_destination: response.data.customer_fee_destination.id, + minimum_amount: response.data.minimum_amount, + maximum_amount: response.data.maximum_amount, + max_transaction_per_day: response.data.max_transaction_per_day, + status_approval: response.data.status_approval, + status: response.data.status + // updated_by: parsedUser?.username , + // updated_at: new Date().toISOString().slice(0, 19).replace('T', ' ') + })); + console.log('Transaction Type: ', formField); + } + }, []); + + useEffect(() => { + if (selectedTransferType) { + fetchTransactionType(selectedTransferType); + } + }, [selectedTransferType]); + + return ( + handleEditDialog(open, null)}> + + + + +
+
+

+ Update Transaction Type +

+
+
+
{ + handleEditDialog(false, null); + resetForm(); + }} + > + +
+
+
+ +
+ {alert.show && ( + +

{alert.message}

+
+ )} +
+
+
+
+ + + setFormField((prev) => ({ ...prev, name: target.value })) + } + /> +
+
+ +
+
+ + + setFormField((prev) => ({ ...prev, description: target.value })) + } + /> +
+
+ +
+
+ + { + setFormField((prev) => ({ + ...prev, + maximum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Minimum Amount" + /> +
+
+ +
+
+ + { + setFormField((prev) => ({ + ...prev, + maximum_amount: values.floatValue || 0 + })); + }} + placeholder="Enter Maximum Amount" + /> +
+
+
+
+ + { + setFormField((prev) => ({ + ...prev, + max_transaction_per_day: values.floatValue || 0 + })); + }} + placeholder="Enter Max Transaction Per Day" + /> +
+
+
+
+ +
+ +
+
+
+ +
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ +
+ +
+
+
+
+
+ + +
+ +
+
+
+ +
+
+ + +
+ +
+
+
+
+ + +
+
+
+ {/* Bagian Transaction Fee */} + + +
+ +
+ +
+
+
+
+
+
+ ); +}; + +export { EditDialog }; diff --git a/src/pages/transfer/blocks/ListToolBar.tsx b/src/pages/transfer/transfertype/blocks/ListToolBar.tsx similarity index 84% rename from src/pages/transfer/blocks/ListToolBar.tsx rename to src/pages/transfer/transfertype/blocks/ListToolBar.tsx index a3af2c3..7325816 100644 --- a/src/pages/transfer/blocks/ListToolBar.tsx +++ b/src/pages/transfer/transfertype/blocks/ListToolBar.tsx @@ -15,16 +15,11 @@ const ListToolbar = () => { table.getColumn('name')?.setFilterValue(event.target.value)} /> - - -
+ + + ); + }, + meta: { headerClassName: 'w-[100px]', cellClassName: 'text-center' } + } + ], + [handleEditDialog, handleDeleteDialog] + ); + const doGetTransferTypeListData = async ( + page: number, + limit: number, + sorting: any, + filter: any + ) => { + sorting = sorting.length == 0 ? [{ id: 'id', desc: false }] : sorting; + filter = filter.length == 0 ? {} : { any: filter[0].value?.toLowerCase() }; + const response = await GetData(`${API_URL}/transactiontype/list`, { + limit: limit, + page: page + 1, + with_deleted: false, + order_field: sorting[0].id, + order_direction: sorting[0].desc ? 'ASC' : 'DESC', + filter: JSON.stringify(filter) + }); + return { data: response?.data.list, totalCount: response?.data.total_count }; + }; + + return ( +
+ + + +
+ } + sorting={[{ id: 'id', desc: true }]} + serverSide={true} + onFetchData={({ pageIndex, pageSize, sorting, columnFilters }) => + doGetTransferTypeListData(pageIndex, pageSize, sorting, columnFilters) + } + > + {children} + +
+
+
+ ); +}; + +export { ManageTransferTypeContext, ManageTransferTypeContextProvider }; +export type { TransferType }; diff --git a/src/pages/transfer/hooks/useManageTransferTypeContext.tsx b/src/pages/transfer/transfertype/hooks/useManageTransferTypeContext.tsx similarity index 100% rename from src/pages/transfer/hooks/useManageTransferTypeContext.tsx rename to src/pages/transfer/transfertype/hooks/useManageTransferTypeContext.tsx diff --git a/src/partials/dropdowns/user/DropdownUser.tsx b/src/partials/dropdowns/user/DropdownUser.tsx index 0ccf0eb..c272635 100644 --- a/src/partials/dropdowns/user/DropdownUser.tsx +++ b/src/partials/dropdowns/user/DropdownUser.tsx @@ -110,7 +110,11 @@ const DropdownUser = ({ menuItemRef }: IDropdownUserProps) => { -