diff --git a/.eslintrc.cjs b/.eslintrc.cjs index fb155b9..802a363 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,18 +1,24 @@ module.exports = { - root: true, - env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', + root: true, + env: { browser: true, es2020: true }, + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:react-hooks/recommended", + ], + ignorePatterns: ["dist", ".eslintrc.cjs"], + parser: "@typescript-eslint/parser", + plugins: ["react-refresh"], + rules: { + "react-refresh/only-export-components": [ + "warn", + { allowConstantExport: true }, ], - ignorePatterns: ['dist', '.eslintrc.cjs'], - parser: '@typescript-eslint/parser', - plugins: ['react-refresh'], - rules: { - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], - }, - } \ No newline at end of file + // temporarily convert some errors to ignore + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-types": "off", + "react-hooks/rules-of-hooks": "off", + "react-hooks/exhaustive-deps": "off", + "no-case-declarations": "off", + }, +}; diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 9b1a940..c9c3c3b 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -1,4 +1,4 @@ -name: Build and Deploy +name: Build, Lint, Test, and Deploy on: push: @@ -12,8 +12,49 @@ env: IMAGE_NAME: ${{ github.repository }} jobs: + lint: + runs-on: ubuntu-latest + + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install dependencies + run: npm ci + + - name: Run linter + run: npm run lint + + test_e2e: + runs-on: ubuntu-latest + needs: lint + + steps: + - name: Checkout the repository + uses: actions/checkout@v4 + + - name: Install Node.js + uses: actions/setup-node@v4 + with: + node-version: "20" + + - name: Install dependencies + run: npm ci + + - name: Install Playwright browsers + run: npx playwright install --with-deps + + - name: Run E2E tests + run: npm run test:e2e + build_and_push: runs-on: ubuntu-latest + needs: test_e2e steps: - name: Checkout the repository diff --git a/.gitignore b/.gitignore index 1cac559..dd900c3 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,9 @@ dist dist-ssr *.local +playwright-report +test-results + # Editor directories and files .vscode/* !.vscode/extensions.json diff --git a/package-lock.json b/package-lock.json index 90dce53..2a85078 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,15 +9,19 @@ "version": "0.0.0", "dependencies": { "@carbon/react": "^1.62.1", + "@types/react-input-mask": "^3.0.5", "body-parser": "^1.20.2", "carbon-components-react": "^8.62.1", "cors": "^2.8.5", "date-fns": "^3.6.0", "express": "^4.19.2", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-currency-mask": "^1.3.2", + "react-dom": "^18.3.1", + "react-input-mask": "^3.0.0-alpha.2" }, "devDependencies": { + "@playwright/test": "^1.46.1", "@types/carbon-components-react": "^7.55.13", "@types/node": "^22.0.0", "@types/react": "^18.3.3", @@ -60,9 +64,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.2.tgz", - "integrity": "sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -108,12 +112,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.0.tgz", - "integrity": "sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==", + "version": "7.25.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.5.tgz", + "integrity": "sha512-abd43wyLfbWoxC6ahM8xTkqLpGB2iWBVyuKC9/srhFunCd1SDNrV1s72bBpK4hLj8KLzHBBcOblvLQZBNw9r3w==", "dev": true, "dependencies": { - "@babel/types": "^7.25.0", + "@babel/types": "^7.25.4", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -256,10 +260,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.0.tgz", - "integrity": "sha512-CzdIU9jdP0dg7HdyB+bHvDJGagUv+qtzZt5rYCWwW6tITNqV9odjp6Qu41gkG0ca5UfdDUWrKkiAnHHdGRnOrA==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.4.tgz", + "integrity": "sha512-nq+eWrOgdtu3jG5Os4TQP3x3cLA8hR8TvJNjD8vnPa20WGycimcparWnLK4jJhElTK6SDyuJo1weMKO/5LpmLA==", "dev": true, + "dependencies": { + "@babel/types": "^7.25.4" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -298,9 +305,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.25.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.0.tgz", - "integrity": "sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.4.tgz", + "integrity": "sha512-DSgLeL/FNcpXuzav5wfYvHCGvynXkJbn3Zvc3823AEe9nPwW9IK4UoCSS5yGymmQzN0pCPvivtgS6/8U2kkm1w==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -323,16 +330,16 @@ } }, "node_modules/@babel/traverse": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.2.tgz", - "integrity": "sha512-s4/r+a7xTnny2O6FcZzqgT6nE4/GHEdcqj4qAeglbUOh0TeglEfmNJFAd/OLoVtGd6ZhAO8GCVvCNUO5t/VJVQ==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.4.tgz", + "integrity": "sha512-VJ4XsrD+nOvlXyLzmLzUs/0qjFS4sK30te5yEFlvbbUNEgKaVb2BHZUpAL+ttLPQAHNrsI3zZisbfha5Cvr8vg==", "dev": true, "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.25.0", - "@babel/parser": "^7.25.0", + "@babel/generator": "^7.25.4", + "@babel/parser": "^7.25.4", "@babel/template": "^7.25.0", - "@babel/types": "^7.25.2", + "@babel/types": "^7.25.4", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -341,9 +348,9 @@ } }, "node_modules/@babel/types": { - "version": "7.25.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.2.tgz", - "integrity": "sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==", + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.4.tgz", + "integrity": "sha512-zQ1ijeeCXVEh+aNL0RlmkPkG8HUiDcU2pzQQFjtbntgAczRASFzj4H+6+bV+dy1ntKR14I/DypeuRG1uma98iQ==", "dev": true, "dependencies": { "@babel/helper-string-parser": "^7.24.8", @@ -355,49 +362,49 @@ } }, "node_modules/@carbon/colors": { - "version": "11.23.0", - "resolved": "https://registry.npmjs.org/@carbon/colors/-/colors-11.23.0.tgz", - "integrity": "sha512-xXcD064+JPk/tFRN3e3UAOHYpayo9Z6MMcHTt2Vb4U5/+6UUxaDReMPnSL+UNSrf75d4epomB+GrpN0tbmgMCA==", + "version": "11.24.0", + "resolved": "https://registry.npmjs.org/@carbon/colors/-/colors-11.24.0.tgz", + "integrity": "sha512-yeLXQ0xs3T/rKvg7od+AvGs1jyQuRqbpZE0gPYFvFdNtiFJ81ZiYz9mE/yiuBU6c4+DdqQlmH6bU7WloKHMX8A==", "hasInstallScript": true, "dependencies": { "@ibm/telemetry-js": "^1.5.0" } }, "node_modules/@carbon/feature-flags": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/@carbon/feature-flags/-/feature-flags-0.20.0.tgz", - "integrity": "sha512-OEYrazJa0nEEHbBDyarXIz6kjWgqsJggjbNAcVOxx0Nvma1nZBd+SwXKwdbMkBZagSSC816dV12oZJtr+GIZZg==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@carbon/feature-flags/-/feature-flags-0.21.0.tgz", + "integrity": "sha512-Xih4xxEVGro0abBu2SW9DBm8ldyhacFMIj2kUXikSsnYITryIRY2cgy+hcPY0pM4taLSP/h7xh2mF6oAEkkqMQ==", "hasInstallScript": true, "dependencies": { "@ibm/telemetry-js": "^1.5.0" } }, "node_modules/@carbon/grid": { - "version": "11.24.0", - "resolved": "https://registry.npmjs.org/@carbon/grid/-/grid-11.24.0.tgz", - "integrity": "sha512-1HYS5FhLqLBBsmHA/oWikRXVq0C639DUZf0VGw+Dl7Nl7UasHDzFkErN0W3pNyMXPVr/rxSZV3ihJJTBsgVuhg==", + "version": "11.25.0", + "resolved": "https://registry.npmjs.org/@carbon/grid/-/grid-11.25.0.tgz", + "integrity": "sha512-9iqrdZk7Jdw6cVyRUaUaAa7WFZw/mNu5c5Q0pCQAUk2XpTzCCnbFCcgq71SsaGmiygRQGDQGFFLRijVwzwAS6Q==", "hasInstallScript": true, "dependencies": { - "@carbon/layout": "^11.23.0", + "@carbon/layout": "^11.24.0", "@ibm/telemetry-js": "^1.5.0" } }, "node_modules/@carbon/icon-helpers": { - "version": "10.49.0", - "resolved": "https://registry.npmjs.org/@carbon/icon-helpers/-/icon-helpers-10.49.0.tgz", - "integrity": "sha512-GSx22ch7ahJ3u/7ZRIykeO8h/uBx3Qruybz3VYi5JBIM+smHDLldXRpJTQk65JsXuSiPWWGepIb1FlhV99fgtw==", + "version": "10.50.0", + "resolved": "https://registry.npmjs.org/@carbon/icon-helpers/-/icon-helpers-10.50.0.tgz", + "integrity": "sha512-R+RnTIQCvrLuWBdiEyzr6zqluLpzMTawmYO97prAJ59OCoo3+mMgWjhKuggb1s0dW1zRVplrUkKusGKH+0pDnQ==", "hasInstallScript": true, "dependencies": { "@ibm/telemetry-js": "^1.5.0" } }, "node_modules/@carbon/icons-react": { - "version": "11.45.0", - "resolved": "https://registry.npmjs.org/@carbon/icons-react/-/icons-react-11.45.0.tgz", - "integrity": "sha512-QTf+K4BT4Vn2e9c5HDZGqTOztVOXG+4k2dAxDgAyg+18zif/kJsZKPnaFJsthxVezzELJ9cbmlXC0acbiE/zjA==", + "version": "11.47.1", + "resolved": "https://registry.npmjs.org/@carbon/icons-react/-/icons-react-11.47.1.tgz", + "integrity": "sha512-GHwOTi/UKkf55qhPhAr4csb6rrv2MpESP3L4LeuCTa61BCC0q1G01TvfoeXhZCoRhX8OvgYKrD8STuRq54+G3A==", "hasInstallScript": true, "dependencies": { - "@carbon/icon-helpers": "^10.49.0", + "@carbon/icon-helpers": "^10.50.0", "@ibm/telemetry-js": "^1.5.0", "prop-types": "^15.7.2" }, @@ -406,34 +413,34 @@ } }, "node_modules/@carbon/layout": { - "version": "11.23.0", - "resolved": "https://registry.npmjs.org/@carbon/layout/-/layout-11.23.0.tgz", - "integrity": "sha512-7YFTFG9mqtvFp67h+qO2z2BG7QmbHc0jVgUevwtOHSCdVHRwhYqEFNGCCE4+MhMHetUjl/z3ut4rNfHleoyOWg==", + "version": "11.24.0", + "resolved": "https://registry.npmjs.org/@carbon/layout/-/layout-11.24.0.tgz", + "integrity": "sha512-xS23hIMZNYdhwh2v5b5ylE9lPjrIJlHRdw1gaA+m+YLLDAy/rlr6tGX79fJeLH3Mk1p8PfYDVq3HmWYCNcjh1w==", "hasInstallScript": true, "dependencies": { "@ibm/telemetry-js": "^1.5.0" } }, "node_modules/@carbon/motion": { - "version": "11.19.0", - "resolved": "https://registry.npmjs.org/@carbon/motion/-/motion-11.19.0.tgz", - "integrity": "sha512-lv8uBNbpciul9vBEOiFsGBkNsJJdfLEcQUFpiK2YyAtpkM4pD6uSw2kb4Pi+mx3htKfqH0/GS4iEtCUXf92w0Q==", + "version": "11.20.0", + "resolved": "https://registry.npmjs.org/@carbon/motion/-/motion-11.20.0.tgz", + "integrity": "sha512-8E4sqHQpinV/HVCei4vmHLgCTg+rThfSPL2eZ0CgtcK1iQd1rrz3CYSC2kc00lngYOcBf34+oBRNjksf3zoPUg==", "hasInstallScript": true, "dependencies": { "@ibm/telemetry-js": "^1.5.0" } }, "node_modules/@carbon/react": { - "version": "1.62.1", - "resolved": "https://registry.npmjs.org/@carbon/react/-/react-1.62.1.tgz", - "integrity": "sha512-EELKamTtg3+pf1cS25asIoGYhahH7Nab8fywgkex6PHF+BQ0vgyw89JzaQeAx89ViHjx9PjOv0/sqcf7A5lbWg==", + "version": "1.64.1", + "resolved": "https://registry.npmjs.org/@carbon/react/-/react-1.64.1.tgz", + "integrity": "sha512-On7QcOzFR3j6wqA60XrZABD4iX49ipioD1qns4yH4xG/OOuFbmwJHVhER3wxGsCc3uHhFeELG7Ih11U+SDolDA==", "hasInstallScript": true, "dependencies": { - "@babel/runtime": "^7.18.3", - "@carbon/feature-flags": "^0.20.0", - "@carbon/icons-react": "^11.45.0", - "@carbon/layout": "^11.23.0", - "@carbon/styles": "^1.61.0", + "@babel/runtime": "^7.24.7", + "@carbon/feature-flags": "^0.21.0", + "@carbon/icons-react": "^11.47.1", + "@carbon/layout": "^11.24.0", + "@carbon/styles": "^1.63.1", "@floating-ui/react": "^0.26.0", "@ibm/telemetry-js": "^1.5.0", "classnames": "2.5.1", @@ -443,10 +450,10 @@ "invariant": "^2.2.3", "lodash.debounce": "^4.0.8", "lodash.findlast": "^4.5.0", - "lodash.isequal": "^4.5.0", "lodash.omit": "^4.5.0", "lodash.throttle": "^4.1.1", "prop-types": "^15.7.2", + "react-fast-compare": "^3.2.2", "react-is": "^18.2.0", "tabbable": "^6.2.0", "use-resize-observer": "^6.0.0", @@ -459,18 +466,18 @@ } }, "node_modules/@carbon/styles": { - "version": "1.61.0", - "resolved": "https://registry.npmjs.org/@carbon/styles/-/styles-1.61.0.tgz", - "integrity": "sha512-9FPbAm7SySP8ktTMX+y8rW0/uSLV2n47E2vKAoAPN+CXIPMVkqZM/Ns/+UVuiBHjhTsVqKe4zEVCKAw25BqdRw==", + "version": "1.63.1", + "resolved": "https://registry.npmjs.org/@carbon/styles/-/styles-1.63.1.tgz", + "integrity": "sha512-PO1S1fR1iUrv9voCYnSP3gv8KTwKR7RfoMqsDKcAScYRTIa18Aa9hip9oyXQ0cHHAY+LYOEFXSQbuhos82Ozyg==", "hasInstallScript": true, "dependencies": { - "@carbon/colors": "^11.23.0", - "@carbon/feature-flags": "^0.20.0", - "@carbon/grid": "^11.24.0", - "@carbon/layout": "^11.23.0", - "@carbon/motion": "^11.19.0", - "@carbon/themes": "^11.37.0", - "@carbon/type": "^11.28.0", + "@carbon/colors": "^11.24.0", + "@carbon/feature-flags": "^0.21.0", + "@carbon/grid": "^11.25.0", + "@carbon/layout": "^11.24.0", + "@carbon/motion": "^11.20.0", + "@carbon/themes": "^11.38.0", + "@carbon/type": "^11.29.0", "@ibm/plex": "6.0.0-next.6", "@ibm/telemetry-js": "^1.5.0" }, @@ -484,26 +491,26 @@ } }, "node_modules/@carbon/themes": { - "version": "11.37.0", - "resolved": "https://registry.npmjs.org/@carbon/themes/-/themes-11.37.0.tgz", - "integrity": "sha512-nGsU4x13190Mrm1beb6Oy9Vacv9NNKhRSX/9DYXa6uB9anMy14vzZMLBZ5L1ubL6Eh8GRD06y7TO9lq2xqEkvw==", + "version": "11.38.0", + "resolved": "https://registry.npmjs.org/@carbon/themes/-/themes-11.38.0.tgz", + "integrity": "sha512-1xR1fBUHYHF/zRbDJ+4Ufqsasklx0ZQiN8y4HX6SgyeyZZ/xvtQ8he588M5jqhDFi+hmSR5tfeN9KGELsvQNFg==", "hasInstallScript": true, "dependencies": { - "@carbon/colors": "^11.23.0", - "@carbon/layout": "^11.23.0", - "@carbon/type": "^11.28.0", + "@carbon/colors": "^11.24.0", + "@carbon/layout": "^11.24.0", + "@carbon/type": "^11.29.0", "@ibm/telemetry-js": "^1.5.0", "color": "^4.0.0" } }, "node_modules/@carbon/type": { - "version": "11.28.0", - "resolved": "https://registry.npmjs.org/@carbon/type/-/type-11.28.0.tgz", - "integrity": "sha512-c0iJXuZgsCr8WARe8h3aMzdYuxM7pW81b+j6AP2Ra2n+/13jK0zlDLLel4pp3U0UAd/qSrlk6PKlwVLH76eLEg==", + "version": "11.29.0", + "resolved": "https://registry.npmjs.org/@carbon/type/-/type-11.29.0.tgz", + "integrity": "sha512-zGbSTSkHs/ShZvHSQRVP84bS7eHdCxepRyOeItBGvdnxtVwsidci34ItoypC90eUPjvEoAV1A5dw/8e7eLyZxQ==", "hasInstallScript": true, "dependencies": { - "@carbon/grid": "^11.24.0", - "@carbon/layout": "^11.23.0", + "@carbon/grid": "^11.25.0", + "@carbon/layout": "^11.24.0", "@ibm/telemetry-js": "^1.5.0" } }, @@ -969,29 +976,29 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.6.5", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.5.tgz", - "integrity": "sha512-8GrTWmoFhm5BsMZOTHeGD2/0FLKLQQHvO/ZmQga4tKempYRLz8aqJGqXVuQgisnMObq2YZ2SgkwctN1LOOxcqA==", + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz", + "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==", "dependencies": { - "@floating-ui/utils": "^0.2.5" + "@floating-ui/utils": "^0.2.7" } }, "node_modules/@floating-ui/dom": { - "version": "1.6.8", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.8.tgz", - "integrity": "sha512-kx62rP19VZ767Q653wsP1XZCGIirkE09E0QUGNYTM/ttbbQHqcGPdSfWFxUyyNLc/W6aoJRBajOSXhP6GXjC0Q==", + "version": "1.6.10", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz", + "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==", "dependencies": { "@floating-ui/core": "^1.6.0", - "@floating-ui/utils": "^0.2.5" + "@floating-ui/utils": "^0.2.7" } }, "node_modules/@floating-ui/react": { - "version": "0.26.20", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.20.tgz", - "integrity": "sha512-RixKJJG92fcIsVoqrFr4Onpzh7hlOx4U7NV4aLhMLmtvjZ5oTB/WzXaANYUZATKqXvvW7t9sCxtzejip26N5Ag==", + "version": "0.26.23", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.23.tgz", + "integrity": "sha512-9u3i62fV0CFF3nIegiWiRDwOs7OW/KhSUJDNx2MkQM3LbE5zQOY01sL3nelcVBXvX7Ovvo3A49I8ql+20Wg/Hw==", "dependencies": { "@floating-ui/react-dom": "^2.1.1", - "@floating-ui/utils": "^0.2.5", + "@floating-ui/utils": "^0.2.7", "tabbable": "^6.0.0" }, "peerDependencies": { @@ -1012,9 +1019,9 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.5.tgz", - "integrity": "sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ==" + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", + "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", @@ -1082,9 +1089,9 @@ } }, "node_modules/@ibm/telemetry-js": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@ibm/telemetry-js/-/telemetry-js-1.6.0.tgz", - "integrity": "sha512-XXdsXhoZwKaJ1/24w/uCqx/YeDQeTu8SAl+7bHQxn62yiFUQ6/D20HhpQVdlG9/Jpv3nYJHFiDH0vGkQbXNFWg==", + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/@ibm/telemetry-js/-/telemetry-js-1.6.1.tgz", + "integrity": "sha512-ds45f2bz4qVvJPK84VcSMJTvTZI+qXu6wVlBcy9/hAlmzOcxeX6rh8W0De4H133HPONsZWvs0lV/H2aUcznCxw==", "bin": { "ibmtelemetry": "dist/collect.js" } @@ -1172,10 +1179,25 @@ "node": ">= 8" } }, + "node_modules/@playwright/test": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.46.1.tgz", + "integrity": "sha512-Fq6SwLujA/DOIvNC2EL/SojJnkKf/rAwJ//APpJJHRyMi1PdKrY3Az+4XNQ51N4RTbItbIByQ0jgd1tayq1aeA==", + "dev": true, + "dependencies": { + "playwright": "1.46.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.19.1.tgz", - "integrity": "sha512-XzqSg714++M+FXhHfXpS1tDnNZNpgxxuGZWlRG/jSj+VEPmZ0yg6jV4E0AL3uyBKxO8mO3xtOsP5mQ+XLfrlww==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.21.1.tgz", + "integrity": "sha512-2thheikVEuU7ZxFXubPDOtspKn1x0yqaYQwvALVtEcvFhMifPADBrgRPyHV0TF3b+9BgvgjgagVyvA/UqPZHmg==", "cpu": [ "arm" ], @@ -1186,9 +1208,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.19.1.tgz", - "integrity": "sha512-thFUbkHteM20BGShD6P08aungq4irbIZKUNbG70LN8RkO7YztcGPiKTTGZS7Kw+x5h8hOXs0i4OaHwFxlpQN6A==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.21.1.tgz", + "integrity": "sha512-t1lLYn4V9WgnIFHXy1d2Di/7gyzBWS8G5pQSXdZqfrdCGTwi1VasRMSS81DTYb+avDs/Zz4A6dzERki5oRYz1g==", "cpu": [ "arm64" ], @@ -1199,9 +1221,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.19.1.tgz", - "integrity": "sha512-8o6eqeFZzVLia2hKPUZk4jdE3zW7LCcZr+MD18tXkgBBid3lssGVAYuox8x6YHoEPDdDa9ixTaStcmx88lio5Q==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.21.1.tgz", + "integrity": "sha512-AH/wNWSEEHvs6t4iJ3RANxW5ZCK3fUnmf0gyMxWCesY1AlUj8jY7GC+rQE4wd3gwmZ9XDOpL0kcFnCjtN7FXlA==", "cpu": [ "arm64" ], @@ -1212,9 +1234,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.19.1.tgz", - "integrity": "sha512-4T42heKsnbjkn7ovYiAdDVRRWZLU9Kmhdt6HafZxFcUdpjlBlxj4wDrt1yFWLk7G4+E+8p2C9tcmSu0KA6auGA==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.21.1.tgz", + "integrity": "sha512-dO0BIz/+5ZdkLZrVgQrDdW7m2RkrLwYTh2YMFG9IpBtlC1x1NPNSXkfczhZieOlOLEqgXOFH3wYHB7PmBtf+Bg==", "cpu": [ "x64" ], @@ -1225,9 +1247,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.19.1.tgz", - "integrity": "sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.21.1.tgz", + "integrity": "sha512-sWWgdQ1fq+XKrlda8PsMCfut8caFwZBmhYeoehJ05FdI0YZXk6ZyUjWLrIgbR/VgiGycrFKMMgp7eJ69HOF2pQ==", "cpu": [ "arm" ], @@ -1238,9 +1260,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.19.1.tgz", - "integrity": "sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.21.1.tgz", + "integrity": "sha512-9OIiSuj5EsYQlmwhmFRA0LRO0dRRjdCVZA3hnmZe1rEwRk11Jy3ECGGq3a7RrVEZ0/pCsYWx8jG3IvcrJ6RCew==", "cpu": [ "arm" ], @@ -1251,9 +1273,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.19.1.tgz", - "integrity": "sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.21.1.tgz", + "integrity": "sha512-0kuAkRK4MeIUbzQYu63NrJmfoUVicajoRAL1bpwdYIYRcs57iyIV9NLcuyDyDXE2GiZCL4uhKSYAnyWpjZkWow==", "cpu": [ "arm64" ], @@ -1264,9 +1286,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.19.1.tgz", - "integrity": "sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.21.1.tgz", + "integrity": "sha512-/6dYC9fZtfEY0vozpc5bx1RP4VrtEOhNQGb0HwvYNwXD1BBbwQ5cKIbUVVU7G2d5WRE90NfB922elN8ASXAJEA==", "cpu": [ "arm64" ], @@ -1277,9 +1299,9 @@ ] }, "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.19.1.tgz", - "integrity": "sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.21.1.tgz", + "integrity": "sha512-ltUWy+sHeAh3YZ91NUsV4Xg3uBXAlscQe8ZOXRCVAKLsivGuJsrkawYPUEyCV3DYa9urgJugMLn8Z3Z/6CeyRQ==", "cpu": [ "ppc64" ], @@ -1290,9 +1312,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.19.1.tgz", - "integrity": "sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.21.1.tgz", + "integrity": "sha512-BggMndzI7Tlv4/abrgLwa/dxNEMn2gC61DCLrTzw8LkpSKel4o+O+gtjbnkevZ18SKkeN3ihRGPuBxjaetWzWg==", "cpu": [ "riscv64" ], @@ -1303,9 +1325,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.19.1.tgz", - "integrity": "sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.21.1.tgz", + "integrity": "sha512-z/9rtlGd/OMv+gb1mNSjElasMf9yXusAxnRDrBaYB+eS1shFm6/4/xDH1SAISO5729fFKUkJ88TkGPRUh8WSAA==", "cpu": [ "s390x" ], @@ -1316,9 +1338,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.19.1.tgz", - "integrity": "sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.21.1.tgz", + "integrity": "sha512-kXQVcWqDcDKw0S2E0TmhlTLlUgAmMVqPrJZR+KpH/1ZaZhLSl23GZpQVmawBQGVhyP5WXIsIQ/zqbDBBYmxm5w==", "cpu": [ "x64" ], @@ -1329,9 +1351,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.19.1.tgz", - "integrity": "sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.21.1.tgz", + "integrity": "sha512-CbFv/WMQsSdl+bpX6rVbzR4kAjSSBuDgCqb1l4J68UYsQNalz5wOqLGYj4ZI0thGpyX5kc+LLZ9CL+kpqDovZA==", "cpu": [ "x64" ], @@ -1342,9 +1364,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.19.1.tgz", - "integrity": "sha512-88brja2vldW/76jWATlBqHEoGjJLRnP0WOEKAUbMcXaAZnemNhlAHSyj4jIwMoP2T750LE9lblvD4e2jXleZsA==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.21.1.tgz", + "integrity": "sha512-3Q3brDgA86gHXWHklrwdREKIrIbxC0ZgU8lwpj0eEKGBQH+31uPqr0P2v11pn0tSIxHvcdOWxa4j+YvLNx1i6g==", "cpu": [ "arm64" ], @@ -1355,9 +1377,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.19.1.tgz", - "integrity": "sha512-LdxxcqRVSXi6k6JUrTah1rHuaupoeuiv38du8Mt4r4IPer3kwlTo+RuvfE8KzZ/tL6BhaPlzJ3835i6CxrFIRQ==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.21.1.tgz", + "integrity": "sha512-tNg+jJcKR3Uwe4L0/wY3Ro0H+u3nrb04+tcq1GSYzBEmKLeOQF2emk1whxlzNqb6MMrQ2JOcQEpuuiPLyRcSIw==", "cpu": [ "ia32" ], @@ -1368,9 +1390,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.19.1.tgz", - "integrity": "sha512-2bIrL28PcK3YCqD9anGxDxamxdiJAxA+l7fWIwM5o8UqNy1t3d1NdAweO2XhA0KTDJ5aH1FsuiT5+7VhtHliXg==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.21.1.tgz", + "integrity": "sha512-xGiIH95H1zU7naUyTKEyOA/I0aexNMUdO9qRv0bLKN3qu25bBdrxZHqA3PTJ24YNN/GdMzG4xkDcd/GvjuhfLg==", "cpu": [ "x64" ], @@ -1444,25 +1466,23 @@ "dev": true }, "node_modules/@types/node": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.0.0.tgz", - "integrity": "sha512-VT7KSYudcPOzP5Q0wfbowyNLaVR8QWUdw+088uFWwfvpY6uCWaXpqV6ieLAu9WBcnTa7H4Z5RLK8I5t2FuOcqw==", + "version": "22.5.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.0.tgz", + "integrity": "sha512-DkFrJOe+rfdHTqqMg0bSNlGlQ85hSoh2TPzZyhHsXnMtligRWpxUySiyw8FY14ITt24HVCiQPWxS3KO/QlGmWg==", "dev": true, "dependencies": { - "undici-types": "~6.11.1" + "undici-types": "~6.19.2" } }, "node_modules/@types/prop-types": { "version": "15.7.12", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", - "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", - "dev": true + "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==" }, "node_modules/@types/react": { - "version": "18.3.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", - "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", - "dev": true, + "version": "18.3.4", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.4.tgz", + "integrity": "sha512-J7W30FTdfCxDDjmfRM+/JqLHBIyl7xUIp9kwK637FGmY7+mkSFSe6L4jpZzhj5QMfLssSDP4/i75AKkrdC7/Jw==", "dependencies": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -1477,6 +1497,14 @@ "@types/react": "*" } }, + "node_modules/@types/react-input-mask": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/react-input-mask/-/react-input-mask-3.0.5.tgz", + "integrity": "sha512-vQ1x6ykwjDrDrJZq1zw5/uQ+nqGHUV6bWscsVZJ/qsNwNXWxZm7KRBHLJ5k6TQt3MHjhpoYHzPH6FwjVSZODHA==", + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "7.18.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", @@ -1865,9 +1893,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", - "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "dev": true, "funding": [ { @@ -1884,9 +1912,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001640", - "electron-to-chromium": "^1.4.820", - "node-releases": "^2.0.14", + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { @@ -1932,9 +1960,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001644", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001644.tgz", - "integrity": "sha512-YGvlOZB4QhZuiis+ETS0VXR+MExbFf4fZYYeMTEE0aTQd/RdIjkTyZjLrbYVKnHzppDvnOhritRVv+i7Go6mHw==", + "version": "1.0.30001653", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001653.tgz", + "integrity": "sha512-XGWQVB8wFQ2+9NZwZ10GxTYC5hk0Fa+q8cSkr0tgvMhYhMHP/QC+WTgrePMDBWiWc/pV+1ik82Al20XOK25Gcw==", "dev": true, "funding": [ { @@ -1952,13 +1980,13 @@ ] }, "node_modules/carbon-components-react": { - "version": "8.62.1", - "resolved": "https://registry.npmjs.org/carbon-components-react/-/carbon-components-react-8.62.1.tgz", - "integrity": "sha512-+wGLpEK8uxZcvZ8+JNFU9Y8f8u40jOUOoAT/qe+bbBgKldpQSgE2S+p9eskfm721Oj/AhBkybbgkB/XZXXmn2w==", + "version": "8.64.1", + "resolved": "https://registry.npmjs.org/carbon-components-react/-/carbon-components-react-8.64.1.tgz", + "integrity": "sha512-uveLmynL7MRW+tS1bZ13RA21LGNV1G/W5Eh3gCAtu/suaNAMfALzFMw2ctjEiUG2QyLpSKqQb1VcRx2jU1SQQw==", "hasInstallScript": true, "dependencies": { - "@carbon/react": "^1.62.1", - "@carbon/styles": "^1.61.0", + "@carbon/react": "^1.64.1", + "@carbon/styles": "^1.63.1", "@ibm/telemetry-js": "^1.5.0", "chalk": "1.1.3" }, @@ -2352,8 +2380,7 @@ "node_modules/csstype": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/date-fns": { "version": "3.6.0", @@ -2465,9 +2492,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.3.tgz", - "integrity": "sha512-QNdYSS5i8D9axWp/6XIezRObRHqaav/ur9z1VzCDUCH1XIFOr9WQk5xmgunhsTpjjgDy3oLxO/WMOVZlpUQrlA==", + "version": "1.5.13", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", + "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", "dev": true }, "node_modules/emoji-regex": { @@ -2631,9 +2658,9 @@ } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.9", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.9.tgz", - "integrity": "sha512-QK49YrBAo5CLNLseZ7sZgvgTy21E6NEw22eZqc4teZfH8pxV3yXc9XXOYfUI6JNpw7mfHNkAeWtBxrTyykB6HA==", + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.11.tgz", + "integrity": "sha512-wrAKxMbVr8qhXTtIKfXqAn5SAtRZt0aXxe5P23Fh4pUAdC6XEsybGLB8P0PI4j1yYqOgUEUlzKAGDfo7rJOjcw==", "dev": true, "peerDependencies": { "eslint": ">=7" @@ -3079,9 +3106,9 @@ "dev": true }, "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "hasInstallScript": true, "optional": true, "os": [ @@ -3335,9 +3362,9 @@ } }, "node_modules/ignore": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", - "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "engines": { "node": ">= 4" @@ -3586,11 +3613,6 @@ "resolved": "https://registry.npmjs.org/lodash.findlast/-/lodash.findlast-4.6.0.tgz", "integrity": "sha512-+OGwb1FVKjhc2aIEQ9vKqNDW1a0/HaCLr0iCIK10jfVif3dBE0nhQD0jOZNZLh7zOlmFUTrk+vt85eXoH4vKuA==" }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==" - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3658,9 +3680,9 @@ } }, "node_modules/micromatch": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", - "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "dependencies": { "braces": "^3.0.3", @@ -3932,10 +3954,40 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/playwright": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.1.tgz", + "integrity": "sha512-oPcr1yqoXLCkgKtD5eNUPLiN40rYEM39odNpIb6VE6S7/15gJmA1NzVv6zJYusV0e7tzvkU/utBFNa/Kpxmwng==", + "dev": true, + "dependencies": { + "playwright-core": "1.46.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.46.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.46.1.tgz", + "integrity": "sha512-h9LqIQaAv+CYvWzsZ+h3RsrqCStkBHlgo6/TJlFst3cOTlLghBQlJwPOZKQJTKNaD3QIB7aAVQ+gfWbN3NXB7A==", + "dev": true, + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/postcss": { - "version": "8.4.40", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", - "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", + "version": "8.4.41", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.41.tgz", + "integrity": "sha512-TesUflQ0WKZqAvg52PWL6kHgLKP6xB6heTOdoYM0Wt2UHyxNa4K25EZZMgKns3BH1RLVbZCREPpLY0rhnNoHVQ==", "dev": true, "funding": [ { @@ -4072,6 +4124,14 @@ "node": ">=0.10.0" } }, + "node_modules/react-currency-mask": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/react-currency-mask/-/react-currency-mask-1.3.2.tgz", + "integrity": "sha512-+1LVLyuFWZXpdGULGpNayVUxm7r2u6WYJdzz+uDReuO4Vswie4S59nRFSRLu7MubtrF5QLtBDqwcKzWzgCotPQ==", + "dependencies": { + "react": "^18.0.0" + } + }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", @@ -4084,6 +4144,25 @@ "react": "^18.3.1" } }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==" + }, + "node_modules/react-input-mask": { + "version": "3.0.0-alpha.2", + "resolved": "https://registry.npmjs.org/react-input-mask/-/react-input-mask-3.0.0-alpha.2.tgz", + "integrity": "sha512-9U7qL+mvDMOJcbOFPdt6Vj+zzmCMNnBjhhjGDrL8BGQmymgvMVKhu/oOVfAkl+5VWOsLr+G3EhZOmae5fBcAkA==", + "dependencies": { + "invariant": "^2.2.4", + "prop-types": "^15.7.2", + "warning": "^4.0.3" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -4165,9 +4244,9 @@ } }, "node_modules/rollup": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.19.1.tgz", - "integrity": "sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw==", + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.21.1.tgz", + "integrity": "sha512-ZnYyKvscThhgd3M5+Qt3pmhO4jIRR5RGzaSovB6Q7rGNrK5cUncrtLmcTTJVSdcKXyZjW8X8MB0JMSuH9bcAJg==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -4180,22 +4259,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.19.1", - "@rollup/rollup-android-arm64": "4.19.1", - "@rollup/rollup-darwin-arm64": "4.19.1", - "@rollup/rollup-darwin-x64": "4.19.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.19.1", - "@rollup/rollup-linux-arm-musleabihf": "4.19.1", - "@rollup/rollup-linux-arm64-gnu": "4.19.1", - "@rollup/rollup-linux-arm64-musl": "4.19.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.19.1", - "@rollup/rollup-linux-riscv64-gnu": "4.19.1", - "@rollup/rollup-linux-s390x-gnu": "4.19.1", - "@rollup/rollup-linux-x64-gnu": "4.19.1", - "@rollup/rollup-linux-x64-musl": "4.19.1", - "@rollup/rollup-win32-arm64-msvc": "4.19.1", - "@rollup/rollup-win32-ia32-msvc": "4.19.1", - "@rollup/rollup-win32-x64-msvc": "4.19.1", + "@rollup/rollup-android-arm-eabi": "4.21.1", + "@rollup/rollup-android-arm64": "4.21.1", + "@rollup/rollup-darwin-arm64": "4.21.1", + "@rollup/rollup-darwin-x64": "4.21.1", + "@rollup/rollup-linux-arm-gnueabihf": "4.21.1", + "@rollup/rollup-linux-arm-musleabihf": "4.21.1", + "@rollup/rollup-linux-arm64-gnu": "4.21.1", + "@rollup/rollup-linux-arm64-musl": "4.21.1", + "@rollup/rollup-linux-powerpc64le-gnu": "4.21.1", + "@rollup/rollup-linux-riscv64-gnu": "4.21.1", + "@rollup/rollup-linux-s390x-gnu": "4.21.1", + "@rollup/rollup-linux-x64-gnu": "4.21.1", + "@rollup/rollup-linux-x64-musl": "4.21.1", + "@rollup/rollup-win32-arm64-msvc": "4.21.1", + "@rollup/rollup-win32-ia32-msvc": "4.21.1", + "@rollup/rollup-win32-x64-msvc": "4.21.1", "fsevents": "~2.3.2" } }, @@ -4570,9 +4649,9 @@ } }, "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, "node_modules/type-check": { "version": "0.4.0", @@ -4624,9 +4703,9 @@ } }, "node_modules/undici-types": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.11.1.tgz", - "integrity": "sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, "node_modules/unpipe": { @@ -4705,14 +4784,14 @@ } }, "node_modules/vite": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.5.tgz", - "integrity": "sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==", + "version": "5.4.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.2.tgz", + "integrity": "sha512-dDrQTRHp5C1fTFzcSaMxjk6vdpKvT+2/mIdE07Gw2ykehT49O0z/VHS3zZ8iV/Gh8BJJKHWOe5RjaNrW5xf/GA==", "dev": true, "dependencies": { "esbuild": "^0.21.3", - "postcss": "^8.4.39", - "rollup": "^4.13.0" + "postcss": "^8.4.41", + "rollup": "^4.20.0" }, "bin": { "vite": "bin/vite.js" @@ -4731,6 +4810,7 @@ "less": "*", "lightningcss": "^1.21.0", "sass": "*", + "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.4.0" @@ -4748,6 +4828,9 @@ "sass": { "optional": true }, + "sass-embedded": { + "optional": true + }, "stylus": { "optional": true }, @@ -4759,6 +4842,28 @@ } } }, + "node_modules/vite/node_modules/fsevents": { + "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": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 0cd6220..811366a 100644 --- a/package.json +++ b/package.json @@ -7,19 +7,25 @@ "dev": "vite", "build": "tsc -b && vite build", "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0", - "preview": "vite preview" + "preview": "vite preview", + "test:e2e": "concurrently \"npm run dev\" \"npx playwright test\" --kill-others --success first", + "test:ci": "BASE_URL=http://localhost:8080 npx playwright test" }, "dependencies": { "@carbon/react": "^1.62.1", + "@types/react-input-mask": "^3.0.5", "body-parser": "^1.20.2", "carbon-components-react": "^8.62.1", "cors": "^2.8.5", "date-fns": "^3.6.0", "express": "^4.19.2", "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-currency-mask": "^1.3.2", + "react-dom": "^18.3.1", + "react-input-mask": "^3.0.0-alpha.2" }, "devDependencies": { + "@playwright/test": "^1.46.1", "@types/carbon-components-react": "^7.55.13", "@types/node": "^22.0.0", "@types/react": "^18.3.3", diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..f87f6fd --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,21 @@ +import { defineConfig, devices } from "@playwright/test"; + +const baseURL = process.env.BASE_URL || "http://localhost:5173"; + +export default defineConfig({ + testDir: "./tests/e2e", + fullyParallel: true, + reporter: [["html", { open: "never" }]], + use: { + baseURL, + launchOptions: { + timeout: 30000, + }, + }, + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + ], +}); diff --git a/src/App.css b/src/App.css index 4214cfd..b19a099 100644 --- a/src/App.css +++ b/src/App.css @@ -1,29 +1,32 @@ .group-container { - border: 1px solid #ccc; - padding: 15px; - margin-bottom: 20px; - border-radius: 5px; + border: 1px solid #ccc; + padding: 15px; + margin-bottom: 20px; + border-radius: 5px; } .fixed-save-buttons { - position: fixed; - top: 0; - left: 0; - width: 100%; - background-color: #fff; - padding: 10px 20px; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - display: flex; - justify-content: space-between; - z-index: 1000; /* Ensure it's on top of other content */ - } - - .fixed-save-buttons button { - margin: 0 10px; - } + position: fixed; + top: 0; + left: 0; + width: 100%; + background-color: #fff; + padding: 10px 20px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + display: flex; + justify-content: space-between; + z-index: 1000; /* Ensure it's on top of other content */ +} + +.fixed-save-buttons button { + margin: 0 10px; +} - .content-wrapper { - padding-top: 60px; /* Adjust based on the height of the fixed header */ - - } - - \ No newline at end of file +.content-wrapper { + padding-top: 60px; /* Adjust based on the height of the fixed header */ +} + +.required-asterisk { + color: #b30000; /* Darker red for better contrast */ + font-weight: bold; /* Make the asterisk bold */ + margin-left: 2px; +} diff --git a/src/Renderer.tsx b/src/Renderer.tsx index 86367cc..0425560 100644 --- a/src/Renderer.tsx +++ b/src/Renderer.tsx @@ -1,643 +1,994 @@ import "./App.css"; -import { useState, useEffect } from "react"; +import React, { useState, useEffect } from "react"; import { - TextInput, - Dropdown, - Checkbox, - Toggle, - DatePicker, - DatePickerInput, - Row, - Column, - TextArea, - Button, - NumberInput, - Link, - FileUploader, - RadioButton, - RadioButtonGroup, - Select, - SelectItem, + TextInput, + Dropdown, + Checkbox, + Toggle, + DatePicker, + DatePickerInput, + Row, + Column, + TextArea, + Button, + NumberInput, + Link, + FileUploader, + RadioButton, + RadioButtonGroup, + Select, + SelectItem, } from "carbon-components-react"; import DynamicTable from "./DynamicTable"; import { parseISO, format } from "date-fns"; import { Heading, FlexGrid } from "@carbon/react"; +import InputMask from "react-input-mask"; +import { CurrencyInput } from "react-currency-mask"; interface Item { + type: string; + label?: string; + placeholder?: string; + id: string; + mask?: string; + codeContext?: { name: string }; + header?: string; + offText?: string; + onText?: string; + size?: string; + listItems?: { value: string; text: string }[]; + groupItems?: { fields: Item[] }[]; + repeater?: boolean; + style?: { marginBottom?: string; fontSize?: string }; + labelText: string; + helperText?: string; + value?: string; + filenameStatus?: string; + labelDescription?: string; + initialRows?: string; + initialColumns?: string; + initialHeaderNames?: string; + validation?: { type: string; - label?: string; - placeholder?: string; - id: string; - codeContext?: { name: string }; - header?: string; - offText?: string; - onText?: string; - size?: string; - listItems?: { value: string; text: string }[]; - groupItems?: { fields: Item[] }[]; - repeater?: boolean; - style?: { marginBottom?: string, fontSize?: string }; - labelText: string; - helperText?: string; - value?: string; - filenameStatus?:string; - labelDescription?:string; - initialRows?:string; - initialColumns?:string; - initialHeaderNames?:string; - + value: string | number | boolean; + errorMessage: string; + }[]; } interface Template { - version: string; - ministry_id: string; - id: string; - lastModified: string; - title: string; - data: { - items: Item[]; - }; + version: string; + ministry_id: string; + id: string; + lastModified: string; + title: string; + data: { + items: Item[]; + }; } interface SavedFieldData { - [key: string]: FieldValue | GroupFieldValueItem[]; // The key can either point to a single field value or an array of group items + [key: string]: FieldValue | GroupFieldValueItem[]; // The key can either point to a single field value or an array of group items } type FieldValue = string | boolean | number | { [key: string]: any }; // The value can be of various types, including nested objects interface GroupFieldValueItem { - [key: string]: FieldValue; // Each group item is a map of field IDs to field values + [key: string]: FieldValue; // Each group item is a map of field IDs to field values } - interface SavedData { - data:SavedFieldData, - form_definition:Template, - metadata:{} - + data: SavedFieldData; + form_definition: Template; + metadata: {}; } type GroupState = { [key: string]: string }[]; // New type definition const componentMapping: { [key: string]: React.ElementType } = { - "text-input": TextInput, - dropdown: Dropdown, - checkbox: Checkbox, - toggle: Toggle, - "date-picker": DatePicker, - "text-area": TextArea, - "button":Button, - "number-input":NumberInput, - "text-info": Heading, - "link":Link, - "file":FileUploader, - "table":DynamicTable, - "group":FlexGrid, - "radio":RadioButtonGroup, - "select":Select + "text-input": TextInput, + dropdown: Dropdown, + checkbox: Checkbox, + toggle: Toggle, + "date-picker": DatePicker, + "text-area": TextArea, + button: Button, + "number-input": NumberInput, + "text-info": Heading, + link: Link, + file: FileUploader, + table: DynamicTable, + group: FlexGrid, + radio: RadioButtonGroup, + select: Select, + "currency-input":TextInput, }; interface RendererProps { - data: any; + data: any; } +const generateUniqueId = ( + groupId: string | number, + groupIndex: number, + fieldId: string +) => `${groupId}-${groupIndex}-${fieldId}`; -const generateUniqueId = (groupId: string | number, groupIndex: number, fieldId: string) => `${groupId}-${groupIndex}-${fieldId}`; - -const Renderer: React.FC = ({ data }) => { - const [formStates, setFormStates] = useState<{ [key: string]: string }>({}); - const [groupStates, setGroupStates] = useState<{ [key: string]: GroupState }>({}); - - const [formData, setFormData] = useState