diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 7aad4877..721d9865 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,9 +1,15 @@ module.exports = { - extends: ['@deriv-com/eslint-config-deriv'], - plugins: ['simple-import-sort'], + extends: ['@deriv-com/eslint-config-deriv', 'eslint:recommended', 'plugin:react/recommended'], + plugins: ['simple-import-sort', 'sort-destructure-keys', 'typescript-sort-keys'], rules: { 'global-require': 'off', + '@typescript-eslint/array-type': 'error', + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-unused-vars': 'error', + '@typescript-eslint/sort-type-constituents': 'error', 'import/newline-after-import': 'error', + 'react/jsx-sort-props': 'error', + 'simple-import-sort/exports': 'error', 'simple-import-sort/imports': [ 'error', { @@ -32,6 +38,10 @@ module.exports = { ], }, ], + 'sort-destructure-keys/sort-destructure-keys': 'error', + 'sort-keys': 'error', + 'typescript-sort-keys/interface': 'error', + 'typescript-sort-keys/string-enum': 'error', }, overrides: [ { diff --git a/package-lock.json b/package-lock.json index 055922d2..f5ecb297 100644 --- a/package-lock.json +++ b/package-lock.json @@ -70,9 +70,12 @@ "@typescript-eslint/parser": "^6.0.0", "autoprefixer": "^10.4.14", "eslint": "^8.56.0", + "eslint-plugin-local-rules": "^2.0.1", "eslint-plugin-prettier": "^5.0.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.5", + "eslint-plugin-sort-destructure-keys": "^2.0.0", + "eslint-plugin-typescript-sort-keys": "^3.2.0", "husky": "^7.0.0", "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", @@ -4491,6 +4494,170 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/experimental-utils/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/@typescript-eslint/parser": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", @@ -8180,6 +8347,12 @@ "dev": true, "peer": true }, + "node_modules/eslint-plugin-local-rules": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-local-rules/-/eslint-plugin-local-rules-2.0.1.tgz", + "integrity": "sha512-AJhGd+GcI5r2dbjiGPixM8jnBl0XFxqoVbqzwKbYz+nTk+Cj5dNE3+OlhC176bl5r25KsGsIthLi1VqIW5Ga+A==", + "dev": true + }, "node_modules/eslint-plugin-playwright": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-0.9.0.tgz", @@ -8345,6 +8518,21 @@ "eslint": ">=5.0.0" } }, + "node_modules/eslint-plugin-sort-destructure-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sort-destructure-keys/-/eslint-plugin-sort-destructure-keys-2.0.0.tgz", + "integrity": "sha512-4w1UQCa3o/YdfWaLr9jY8LfGowwjwjmwClyFLxIsToiyIdZMq3x9Ti44nDn34DtTPP7PWg96tUONKVmATKhYGQ==", + "dev": true, + "dependencies": { + "natural-compare-lite": "^1.4.0" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": "5 - 9" + } + }, "node_modules/eslint-plugin-testing-library": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.2.2.tgz", @@ -8516,6 +8704,25 @@ "dev": true, "peer": true }, + "node_modules/eslint-plugin-typescript-sort-keys": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-typescript-sort-keys/-/eslint-plugin-typescript-sort-keys-3.2.0.tgz", + "integrity": "sha512-GutszvriaVtwmn7pQjuj9/9o0iXhD7XZs0/424+zsozdRr/fdg5e8206t478Vnqnqi1GjuxcAolj1kf74KnhPA==", + "dev": true, + "dependencies": { + "@typescript-eslint/experimental-utils": "^5.0.0", + "json-schema": "^0.4.0", + "natural-compare-lite": "^1.4.0" + }, + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6 || ^7", + "eslint": "^7 || ^8", + "typescript": "^3 || ^4 || ^5" + } + }, "node_modules/eslint-rule-docs": { "version": "1.1.235", "resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.235.tgz", @@ -8528,7 +8735,6 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "devOptional": true, - "peer": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -8542,7 +8748,6 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "devOptional": true, - "peer": true, "engines": { "node": ">=4.0" } @@ -12626,6 +12831,12 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -13800,6 +14011,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -17738,7 +17955,6 @@ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, - "peer": true, "dependencies": { "tslib": "^1.8.1" }, @@ -17753,8 +17969,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "peer": true + "dev": true }, "node_modules/type-check": { "version": "0.4.0", @@ -21842,6 +22057,104 @@ } } }, + "@typescript-eslint/experimental-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.62.0.tgz", + "integrity": "sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "5.62.0" + }, + "dependencies": { + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + } + }, + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } + } + }, "@typescript-eslint/parser": { "version": "6.21.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", @@ -24731,6 +25044,12 @@ "eslint-plugin-playwright": "^0.9.0" } }, + "eslint-plugin-local-rules": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-local-rules/-/eslint-plugin-local-rules-2.0.1.tgz", + "integrity": "sha512-AJhGd+GcI5r2dbjiGPixM8jnBl0XFxqoVbqzwKbYz+nTk+Cj5dNE3+OlhC176bl5r25KsGsIthLi1VqIW5Ga+A==", + "dev": true + }, "eslint-plugin-playwright": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/eslint-plugin-playwright/-/eslint-plugin-playwright-0.9.0.tgz", @@ -24843,6 +25162,15 @@ "peer": true, "requires": {} }, + "eslint-plugin-sort-destructure-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-sort-destructure-keys/-/eslint-plugin-sort-destructure-keys-2.0.0.tgz", + "integrity": "sha512-4w1UQCa3o/YdfWaLr9jY8LfGowwjwjmwClyFLxIsToiyIdZMq3x9Ti44nDn34DtTPP7PWg96tUONKVmATKhYGQ==", + "dev": true, + "requires": { + "natural-compare-lite": "^1.4.0" + } + }, "eslint-plugin-testing-library": { "version": "6.2.2", "resolved": "https://registry.npmjs.org/eslint-plugin-testing-library/-/eslint-plugin-testing-library-6.2.2.tgz", @@ -24951,6 +25279,17 @@ } } }, + "eslint-plugin-typescript-sort-keys": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-typescript-sort-keys/-/eslint-plugin-typescript-sort-keys-3.2.0.tgz", + "integrity": "sha512-GutszvriaVtwmn7pQjuj9/9o0iXhD7XZs0/424+zsozdRr/fdg5e8206t478Vnqnqi1GjuxcAolj1kf74KnhPA==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "^5.0.0", + "json-schema": "^0.4.0", + "natural-compare-lite": "^1.4.0" + } + }, "eslint-rule-docs": { "version": "1.1.235", "resolved": "https://registry.npmjs.org/eslint-rule-docs/-/eslint-rule-docs-1.1.235.tgz", @@ -24963,7 +25302,6 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "devOptional": true, - "peer": true, "requires": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -24973,8 +25311,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "devOptional": true, - "peer": true + "devOptional": true } } }, @@ -27806,6 +28143,12 @@ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true + }, "json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -28704,6 +29047,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -31539,7 +31888,6 @@ "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, - "peer": true, "requires": { "tslib": "^1.8.1" }, @@ -31548,8 +31896,7 @@ "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "peer": true + "dev": true } } }, diff --git a/package.json b/package.json index 970bd150..dffbb52f 100644 --- a/package.json +++ b/package.json @@ -76,9 +76,12 @@ "@typescript-eslint/parser": "^6.0.0", "autoprefixer": "^10.4.14", "eslint": "^8.56.0", + "eslint-plugin-local-rules": "^2.0.1", "eslint-plugin-prettier": "^5.0.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.5", + "eslint-plugin-sort-destructure-keys": "^2.0.0", + "eslint-plugin-typescript-sort-keys": "^3.2.0", "husky": "^7.0.0", "identity-obj-proxy": "^3.0.0", "jest": "^29.7.0", diff --git a/src/components/AdvertsTableRow/AdvertsTableRow.tsx b/src/components/AdvertsTableRow/AdvertsTableRow.tsx index bbd247ac..7daa3bbd 100644 --- a/src/components/AdvertsTableRow/AdvertsTableRow.tsx +++ b/src/components/AdvertsTableRow/AdvertsTableRow.tsx @@ -1,11 +1,11 @@ -import { Fragment, memo, useEffect, useRef, useState } from 'react'; +import { Fragment, memo, useEffect, useRef } from 'react'; import clsx from 'clsx'; import { useHistory } from 'react-router-dom'; import { TAdvertiserPaymentMethod, TAdvertsTableRowRenderer, TCurrency, TExchangeRate, TPaymentMethod } from 'types'; import { Badge, BuySellForm, PaymentMethodLabel, StarRating, UserAvatar } from '@/components'; import { ADVERTISER_URL, BUY_SELL } from '@/constants'; import { api } from '@/hooks'; -import { useIsAdvertiser } from '@/hooks/custom-hooks'; +import { useIsAdvertiser, useModalManager } from '@/hooks/custom-hooks'; import { generateEffectiveRate, getCurrentRoute } from '@/utils'; import { LabelPairedChevronRightMdRegularIcon } from '@deriv/quill-icons'; import { useExchangeRates } from '@deriv-com/api-hooks'; @@ -15,7 +15,7 @@ import './AdvertsTableRow.scss'; const BASE_CURRENCY = 'USD'; const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => { - const [isModalOpen, setIsModalOpen] = useState(false); + const { hideModal, isModalOpenFor, showModal } = useModalManager({ shouldReinitializeModals: false }); const { subscribeRates } = useExchangeRates(); const { isDesktop, isMobile } = useDevice(); const history = useHistory(); @@ -127,12 +127,12 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => { )} {isMobile && ( - + Rate (1 USD) )} - + {isMobile && 'Limits:'} {min_order_amount_limit_display}-{max_order_amount_limit_display}{' '} {account_currency} @@ -148,7 +148,12 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => {
{payment_method_names ? ( payment_method_names.map((method: string, idx: number) => ( - + )) ) : ( @@ -168,15 +173,15 @@ const AdvertsTableRow = memo((props: TAdvertsTableRowRenderer) => { )}
)} - {isModalOpen && ( + {isModalOpenFor('BuySellForm') && ( { balanceAvailable={data?.balance_available ?? 0} displayEffectiveRate={displayEffectiveRate} effectiveRate={effectiveRate} - isModalOpen={isModalOpen} - onRequestClose={() => setIsModalOpen(false)} + isModalOpen={!!isModalOpenFor('BuySellForm')} + onRequestClose={hideModal} paymentMethods={paymentMethods as TPaymentMethod[]} /> )} diff --git a/src/components/BuySellForm/BuySellAmount/BuySellAmount.scss b/src/components/BuySellForm/BuySellAmount/BuySellAmount.scss index 266f4ae9..e7436c96 100644 --- a/src/components/BuySellForm/BuySellAmount/BuySellAmount.scss +++ b/src/components/BuySellForm/BuySellAmount/BuySellAmount.scss @@ -13,4 +13,16 @@ font-size: 1.2rem; } } + &__value { + display: flex; + flex-direction: column; + width: 100%; + padding: 1.5rem 2.4rem 0 0; + margin: auto; + + @include mobile { + padding-top: 0; + padding-left: 1.6rem; + } + } } diff --git a/src/components/BuySellForm/BuySellAmount/BuySellAmount.tsx b/src/components/BuySellForm/BuySellAmount/BuySellAmount.tsx index dd5ebece..1bf78284 100644 --- a/src/components/BuySellForm/BuySellAmount/BuySellAmount.tsx +++ b/src/components/BuySellForm/BuySellAmount/BuySellAmount.tsx @@ -2,8 +2,9 @@ import { useEffect, useState } from 'react'; import { Controller, useForm } from 'react-hook-form'; import { TCurrency } from 'types'; import { LightDivider } from '@/components'; -import { floatingPointValidator } from '@/utils'; -import { Input, Text, useDevice } from '@deriv-com/ui'; +import { VALID_SYMBOLS_PATTERN } from '@/constants'; +import { floatingPointValidator, getTextFieldError } from '@/utils'; +import { Input, Text, TextArea, useDevice } from '@deriv-com/ui'; import { FormatUtils } from '@deriv-com/utils'; import './BuySellAmount.scss'; @@ -17,6 +18,7 @@ type TBuySellAmountProps = { localCurrency: TCurrency; maxLimit: string; minLimit: string; + paymentMethodNames?: string[]; }; const BuySellAmount = ({ accountCurrency, @@ -28,6 +30,7 @@ const BuySellAmount = ({ localCurrency, maxLimit, minLimit, + paymentMethodNames, }: TBuySellAmountProps) => { const { isMobile } = useDevice(); const labelSize = isMobile ? 'sm' : 'xs'; @@ -43,66 +46,150 @@ const BuySellAmount = ({ }, [calculatedRate, inputValue, localCurrency]); return ( -
- - {`Enter ${isBuy ? 'sell' : 'buy'} amount`} - -
- ( -
- { - setInputValue(event.target.value); - onChange(event); - }} - onKeyDown={event => { - if (!floatingPointValidator(event.key)) { - event.preventDefault(); +
+
+
+ + {`Enter ${isBuy ? 'sell' : 'buy'} amount`} + + ( +
+ { + setInputValue(event.target.value); + onChange(event); + }} + onKeyDown={event => { + if (!floatingPointValidator(event.key)) { + event.preventDefault(); + } + }} + rightPlaceholder={ + + {accountCurrency} + } + step='any' + type='number' + value={value} + /> +
+ )} + rules={{ + max: { + message: `Maximum is ${maxLimit}${accountCurrency}`, + value: maxLimit, + }, + min: { + message: `Minimum is ${minLimit}${accountCurrency}`, + value: minLimit, + }, + required: 'Enter a valid amount', + }} + /> +
+ {isMobile && } + {!isMobile && ( +
+ {`You'll ${isBuy ? 'receive' : 'send'}`} + + {buySellAmount} {localCurrency} + +
+ )} +
+ {isBuy && ( +
+ {!paymentMethodNames?.length && ( + <> + + { + return ( +
+