From 78221c426771bef069711798ccf3fef263ef4979 Mon Sep 17 00:00:00 2001 From: Danel Kungla Date: Fri, 19 Sep 2025 16:59:52 +0300 Subject: [PATCH 1/5] eslint refactor --- .npmrc | 1 + .../eslint.config.mjs => eslint.config.mjs | 0 package.json | 5 + packages/analytics/package.json | 1 - pnpm-lock.yaml | 246 +++++++++++++++--- true/eslint.config.ts | 11 + 6 files changed, 229 insertions(+), 35 deletions(-) rename packages/analytics/eslint.config.mjs => eslint.config.mjs (100%) create mode 100644 true/eslint.config.ts diff --git a/.npmrc b/.npmrc index dad7c34..d82064f 100644 --- a/.npmrc +++ b/.npmrc @@ -3,6 +3,7 @@ dedupe-peer-dependents=true use-lockfile-v6=true resolution-mode=highest package-manager-strict=true +ignore-workspace-root-check=true public-hoist-pattern[]=*i18next* public-hoist-pattern[]=*eslint* public-hoist-pattern[]=*prettier* diff --git a/packages/analytics/eslint.config.mjs b/eslint.config.mjs similarity index 100% rename from packages/analytics/eslint.config.mjs rename to eslint.config.mjs diff --git a/package.json b/package.json index c038bb1..4ba5290 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ "zod": "^4.1.5" }, "devDependencies": { + "@eslint/js": "^9.35.0", "@hookform/resolvers": "^5.0.1", "@jest/globals": "^30.1.2", "@kit/eslint-config": "workspace:*", @@ -109,6 +110,9 @@ "babel-plugin-react-compiler": "19.1.0-rc.2", "cssnano": "^7.0.7", "dotenv": "^16.5.0", + "eslint": "^9.35.0", + "eslint-plugin-react": "^7.37.5", + "globals": "^16.4.0", "jest": "^30.1.3", "jest-environment-node": "^30.1.2", "pino-pretty": "13.0.0", @@ -118,6 +122,7 @@ "tailwindcss-animate": "^1.0.7", "ts-jest": "^29.4.2", "typescript": "^5.8.3", + "typescript-eslint": "8.32.1", "yup": "^1.6.1" }, "prettier": "@kit/prettier-config", diff --git a/packages/analytics/package.json b/packages/analytics/package.json index 98546e8..d5c538c 100644 --- a/packages/analytics/package.json +++ b/packages/analytics/package.json @@ -5,7 +5,6 @@ "scripts": { "clean": "git clean -xdf .turbo node_modules", "format": "prettier --check \"**/*.{ts,tsx}\"", - "lint": "eslint .", "typecheck": "tsc --noEmit" }, "prettier": "@kit/prettier-config", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 08b330e..776774e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -177,6 +177,9 @@ importers: specifier: ^4.1.5 version: 4.1.5 devDependencies: + '@eslint/js': + specifier: ^9.35.0 + version: 9.35.0 '@jest/globals': specifier: ^30.1.2 version: 30.1.2 @@ -228,6 +231,15 @@ importers: dotenv: specifier: ^16.5.0 version: 16.6.1 + eslint: + specifier: ^9.35.0 + version: 9.35.0(jiti@2.5.1) + eslint-plugin-react: + specifier: ^7.37.5 + version: 7.37.5(eslint@9.35.0(jiti@2.5.1)) + globals: + specifier: ^16.4.0 + version: 16.4.0 jest: specifier: ^30.1.3 version: 30.1.3(@types/node@22.18.0)(babel-plugin-macros@3.1.0)(ts-node@10.9.2(@types/node@22.18.0)(typescript@5.9.2)) @@ -255,6 +267,9 @@ importers: typescript: specifier: ^5.8.3 version: 5.9.2 + typescript-eslint: + specifier: 8.32.1 + version: 8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) yup: specifier: ^1.6.1 version: 1.7.0 @@ -2027,6 +2042,12 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/eslint-utils@4.9.0': + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + '@eslint-community/regexpp@4.12.1': resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -2055,6 +2076,10 @@ packages: resolution: {integrity: sha512-EoyvqQnBNsV1CWaEJ559rxXL4c8V92gxirbawSmVUOWXlsRxxQXl6LmCpdUblgxgSkDIqKnhzba2SjRTI/A5Rw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/js@9.35.0': + resolution: {integrity: sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/object-schema@2.1.6': resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -7512,6 +7537,16 @@ packages: jiti: optional: true + eslint@9.35.0: + resolution: {integrity: sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + espree@10.4.0: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -7815,6 +7850,10 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} + globals@16.4.0: + resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} + engines: {node: '>=18'} + globalthis@1.0.4: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} @@ -11313,6 +11352,16 @@ snapshots: eslint: 9.34.0(jiti@2.5.1) eslint-visitor-keys: 3.4.3 + '@eslint-community/eslint-utils@4.7.0(eslint@9.35.0(jiti@2.5.1))': + dependencies: + eslint: 9.35.0(jiti@2.5.1) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/eslint-utils@4.9.0(eslint@9.35.0(jiti@2.5.1))': + dependencies: + eslint: 9.35.0(jiti@2.5.1) + eslint-visitor-keys: 3.4.3 + '@eslint-community/regexpp@4.12.1': {} '@eslint/config-array@0.21.0': @@ -11359,6 +11408,8 @@ snapshots: '@eslint/js@9.34.0': {} + '@eslint/js@9.35.0': {} + '@eslint/object-schema@2.1.6': {} '@eslint/plugin-kit@0.3.5': @@ -18576,6 +18627,23 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/eslint-plugin@8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/scope-manager': 8.32.1 + '@typescript-eslint/type-utils': 8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/utils': 8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.32.1 + eslint: 9.35.0(jiti@2.5.1) + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/eslint-plugin@8.33.1(@typescript-eslint/parser@8.33.1(eslint@8.10.0)(typescript@5.9.2))(eslint@8.10.0)(typescript@5.9.2)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -18622,6 +18690,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.32.1 + '@typescript-eslint/types': 8.32.1 + '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.32.1 + debug: 4.4.1 + eslint: 9.35.0(jiti@2.5.1) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@8.33.1(eslint@8.10.0)(typescript@5.9.2)': dependencies: '@typescript-eslint/scope-manager': 8.33.1 @@ -18680,6 +18760,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/type-utils@8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': + dependencies: + '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.9.2) + '@typescript-eslint/utils': 8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + debug: 4.4.1 + eslint: 9.35.0(jiti@2.5.1) + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/type-utils@8.33.1(eslint@8.10.0)(typescript@5.9.2)': dependencies: '@typescript-eslint/typescript-estree': 8.33.1(typescript@5.9.2) @@ -18747,6 +18838,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.35.0(jiti@2.5.1)) + '@typescript-eslint/scope-manager': 8.32.1 + '@typescript-eslint/types': 8.32.1 + '@typescript-eslint/typescript-estree': 8.32.1(typescript@5.9.2) + eslint: 9.35.0(jiti@2.5.1) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.33.1(eslint@8.10.0)(typescript@5.9.2)': dependencies: '@eslint-community/eslint-utils': 4.7.0(eslint@8.10.0) @@ -19957,7 +20059,7 @@ snapshots: eslint: 8.10.0 eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@8.10.0) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.33.1(eslint@8.10.0)(typescript@5.9.2))(eslint@8.10.0) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.33.1(eslint@8.10.0)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.10.0) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.10.0) eslint-plugin-react: 7.37.5(eslint@8.10.0) eslint-plugin-react-hooks: 5.2.0(eslint@8.10.0) @@ -19977,7 +20079,7 @@ snapshots: eslint: 9.34.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.31.0)(eslint@9.34.0(jiti@2.5.1)) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.32.1(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.5.1)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.33.1(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.5.1)) eslint-plugin-jsx-a11y: 6.10.2(eslint@9.34.0(jiti@2.5.1)) eslint-plugin-react: 7.37.5(eslint@9.34.0(jiti@2.5.1)) eslint-plugin-react-hooks: 5.2.0(eslint@9.34.0(jiti@2.5.1)) @@ -20013,7 +20115,7 @@ snapshots: tinyglobby: 0.2.14 unrs-resolver: 1.7.11 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.33.1(eslint@8.10.0)(typescript@5.9.2))(eslint@8.10.0) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.33.1(eslint@8.10.0)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.10.0) transitivePeerDependencies: - supports-color @@ -20028,7 +20130,7 @@ snapshots: tinyglobby: 0.2.14 unrs-resolver: 1.7.11 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.32.1(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.5.1)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.33.1(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color @@ -20054,36 +20156,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.32.1(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.34.0(jiti@2.5.1)): - dependencies: - '@rtsao/scc': 1.1.0 - array-includes: 3.1.9 - array.prototype.findlastindex: 1.2.6 - array.prototype.flat: 1.3.3 - array.prototype.flatmap: 1.3.3 - debug: 3.2.7 - doctrine: 2.1.0 - eslint: 9.34.0(jiti@2.5.1) - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.33.1(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.5.1)) - hasown: 2.0.2 - is-core-module: 2.16.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.8 - object.groupby: 1.0.3 - object.values: 1.2.1 - semver: 6.3.1 - string.prototype.trimend: 1.0.9 - tsconfig-paths: 3.15.0 - optionalDependencies: - '@typescript-eslint/parser': 8.32.1(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2) - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.33.1(eslint@8.10.0)(typescript@5.9.2))(eslint@8.10.0): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.33.1(eslint@8.10.0)(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@8.10.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -20112,6 +20185,35 @@ snapshots: - eslint-import-resolver-webpack - supports-color + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.33.1(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.5.1)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.9 + array.prototype.findlastindex: 1.2.6 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.34.0(jiti@2.5.1) + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.33.1(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1)(eslint@9.34.0(jiti@2.5.1)) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 8.33.1(eslint@9.34.0(jiti@2.5.1))(typescript@5.9.2) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + eslint-plugin-jsx-a11y@6.10.2(eslint@8.10.0): dependencies: aria-query: 5.3.2 @@ -20202,6 +20304,28 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 + eslint-plugin-react@7.37.5(eslint@9.35.0(jiti@2.5.1)): + dependencies: + array-includes: 3.1.9 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.2.1 + eslint: 9.35.0(jiti@2.5.1) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.9 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + eslint-plugin-turbo@2.5.6(eslint@9.34.0(jiti@2.5.1))(turbo@2.5.4): dependencies: dotenv: 16.0.3 @@ -20316,6 +20440,48 @@ snapshots: transitivePeerDependencies: - supports-color + eslint@9.35.0(jiti@2.5.1): + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0(jiti@2.5.1)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.1 + '@eslint/core': 0.15.2 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.35.0 + '@eslint/plugin-kit': 0.3.5 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.1 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + json-stable-stringify-without-jsonify: 1.0.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.4 + optionalDependencies: + jiti: 2.5.1 + transitivePeerDependencies: + - supports-color + espree@10.4.0: dependencies: acorn: 8.15.0 @@ -20624,6 +20790,8 @@ snapshots: globals@14.0.0: {} + globals@16.4.0: {} + globalthis@1.0.4: dependencies: define-properties: 1.2.1 @@ -24283,6 +24451,16 @@ snapshots: transitivePeerDependencies: - supports-color + typescript-eslint@8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2): + dependencies: + '@typescript-eslint/eslint-plugin': 8.32.1(@typescript-eslint/parser@8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2))(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/parser': 8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + '@typescript-eslint/utils': 8.32.1(eslint@9.35.0(jiti@2.5.1))(typescript@5.9.2) + eslint: 9.35.0(jiti@2.5.1) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + typescript@5.9.2: {} uglify-js@3.19.3: diff --git a/true/eslint.config.ts b/true/eslint.config.ts new file mode 100644 index 0000000..673b075 --- /dev/null +++ b/true/eslint.config.ts @@ -0,0 +1,11 @@ +import js from "@eslint/js"; +import globals from "globals"; +import tseslint from "typescript-eslint"; +import pluginReact from "eslint-plugin-react"; +import { defineConfig } from "eslint/config"; + +export default defineConfig([ + { files: ["**/*.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"], plugins: { js }, extends: ["js/recommended"], languageOptions: { globals: globals.browser } }, + tseslint.configs.recommended, + pluginReact.configs.flat.recommended, +]); From efa94b3322308c7c61e258da479457989bca4bdf Mon Sep 17 00:00:00 2001 From: Danel Kungla Date: Fri, 19 Sep 2025 17:00:44 +0300 Subject: [PATCH 2/5] Merge branch 'develop' into add-eslint From 0c2cfe6d185b169ecd62193ccdf84061fd7bb889 Mon Sep 17 00:00:00 2001 From: Danel Kungla Date: Fri, 19 Sep 2025 17:22:36 +0300 Subject: [PATCH 3/5] prettier fix --- .../(legal)/privacy-policy/page.tsx | 1 - .../(legal)/terms-of-service/page.tsx | 1 - .../site-header-account-section.tsx | 5 +- app/(marketing)/_components/site-header.tsx | 3 +- app/(marketing)/blog/[slug]/page.tsx | 1 - .../contact/_lib/server/server-actions.ts | 6 +- app/(marketing)/contact/page.tsx | 1 - app/(marketing)/faq/page.tsx | 1 - app/(marketing)/layout.tsx | 3 +- app/(marketing)/page.tsx | 4 +- app/(public)/company-offer/page.tsx | 3 +- app/(public)/layout.tsx | 3 +- app/admin/_components/admin-sidebar.tsx | 5 +- app/admin/accounts/[id]/page.tsx | 1 + app/api/billing/webhook/route.ts | 3 +- app/api/job/handler/load-env.ts | 6 +- .../job/handler/sync-analysis-groups-store.ts | 123 +- app/api/job/handler/sync-analysis-groups.ts | 87 +- app/api/job/handler/sync-analysis-results.ts | 14 +- app/api/job/handler/validate-api-key.ts | 2 +- app/api/job/medipost-retry-dispatch/route.ts | 52 +- app/api/job/send-open-jobs-emails/route.ts | 1 + .../job/sync-analysis-groups-store/route.ts | 31 +- app/api/job/sync-analysis-groups/route.ts | 31 +- app/api/job/sync-analysis-results/route.ts | 31 +- app/api/job/sync-connected-online/route.ts | 31 +- app/api/job/test-medipost-responses/route.ts | 54 +- app/api/montonio/verify-token/route.ts | 3 +- app/api/order/medipost-test-response/route.ts | 43 +- app/auth/callback/error/page.tsx | 4 +- app/auth/callback/layout.tsx | 1 - app/auth/callback/route.ts | 19 +- app/auth/confirm/layout.tsx | 1 - app/auth/confirm/route.ts | 3 +- .../membership-confirmation-notification.tsx | 2 +- app/auth/membership-confirmation/layout.tsx | 1 - app/auth/password-reset/layout.tsx | 1 - app/auth/password-reset/page.tsx | 4 +- .../components/SignInPageClientRedirect.tsx | 13 +- app/auth/sign-in/layout.tsx | 1 - app/auth/sign-in/page.tsx | 3 +- app/auth/sign-up/layout.tsx | 1 - app/auth/sign-up/page.tsx | 1 - .../_lib/schemas/update-account.schema.ts | 53 +- .../_lib/server/update-account.ts | 7 +- app/auth/update-account/layout.tsx | 1 - app/auth/verify/layout.tsx | 1 - app/auth/verify/page.tsx | 6 +- app/doctor/_components/analysis-doctor.tsx | 4 +- app/doctor/_components/analysis-level-bar.tsx | 54 +- app/doctor/_components/analysis-view.tsx | 4 +- app/doctor/_components/doctor-dashboard.tsx | 1 + app/doctor/_components/doctor-guard.tsx | 3 +- app/doctor/_components/results-table.tsx | 6 +- app/doctor/analysis/[id]/page.tsx | 2 - app/doctor/layout.tsx | 1 - app/global-error.tsx | 2 +- .../analysis-results/[id]/page.tsx | 43 +- .../_components/analysis-level-bar.tsx | 85 +- .../analysis-results/_components/analysis.tsx | 44 +- .../analysis-results/test/page.tsx | 33 +- .../analysis-results/test/test-responses.ts | 1592 +-- .../cart/montonio-callback/actions.ts | 188 +- .../montonio-callback/client-component.tsx | 13 +- .../cart/montonio-callback/error/page.tsx | 7 +- .../cart/montonio-callback/page.tsx | 6 +- app/home/(user)/(dashboard)/cart/page.tsx | 61 +- .../order-analysis-package/page.tsx | 18 +- .../(dashboard)/order-analysis/page.tsx | 16 +- .../order-health-analysis/page.tsx | 5 +- .../order/[orderId]/confirmed/page.tsx | 30 +- .../(dashboard)/order/[orderId]/page.tsx | 30 +- app/home/(user)/(dashboard)/order/page.tsx | 39 +- app/home/(user)/(dashboard)/page.tsx | 2 +- .../_components/cart/analysis-location.tsx | 90 +- .../_components/cart/cart-item-delete.tsx | 17 +- .../(user)/_components/cart/cart-item.tsx | 44 +- .../(user)/_components/cart/cart-items.tsx | 31 +- .../(user)/_components/cart/cart-timer.tsx | 44 +- .../_components/cart/discount-code-actions.ts | 13 +- .../(user)/_components/cart/discount-code.tsx | 111 +- app/home/(user)/_components/cart/index.tsx | 109 +- .../_components/cart/partner-locations.json | 2 +- app/home/(user)/_components/cart/types.ts | 14 +- .../_components/compare-packages-modal.tsx | 64 +- .../(user)/_components/dashboard-cards.tsx | 2 +- .../_components/dashboard-recommendations.tsx | 10 +- app/home/(user)/_components/dashboard.tsx | 159 +- .../_components/home-account-selector.tsx | 4 +- .../(user)/_components/home-page-header.tsx | 4 +- .../_components/order-analyses-cards.tsx | 84 +- .../(user)/_components/order/cart-totals.tsx | 76 +- .../_components/order/order-details.tsx | 24 +- .../(user)/_components/order/order-item.tsx | 34 +- .../(user)/_components/order/order-items.tsx | 45 +- app/home/(user)/_components/orders/actions.ts | 12 +- .../(user)/_components/orders/order-block.tsx | 56 +- .../_components/orders/order-items-table.tsx | 2 +- app/home/(user)/_lib/server/load-accounts.ts | 1 - app/home/(user)/_lib/server/load-analyses.ts | 41 +- .../_lib/server/load-analysis-packages.ts | 93 +- .../(user)/_lib/server/load-user-account.ts | 3 +- .../(user)/_lib/server/load-user-analysis.ts | 5 +- .../server/update-cart-partner-location.ts | 8 +- .../personal-account-checkout-form.tsx | 3 +- .../billing/_lib/server/server-actions.ts | 2 +- .../_lib/server/user-billing.service.ts | 6 +- app/home/(user)/billing/layout.tsx | 2 +- app/home/(user)/billing/page.tsx | 6 +- .../_components/account-preferences-form.tsx | 4 +- .../_components/account-settings-form.tsx | 14 +- .../_components/settings-navigation.tsx | 6 +- .../_components/settings-section-header.tsx | 4 +- app/home/(user)/settings/layout.tsx | 5 +- .../team-account-accounts-selector.tsx | 4 +- .../team-account-layout-mobile-navigation.tsx | 6 +- .../team-account-notifications.tsx | 2 - .../server/team-account-workspace.loader.ts | 9 +- .../team-account-checkout-form.tsx | 3 +- app/home/[account]/billing/page.tsx | 1 - app/home/[account]/billing/return/page.tsx | 2 +- app/home/[account]/members/page.tsx | 1 - app/home/[account]/page.tsx | 2 +- app/join/page.tsx | 6 +- app/layout.tsx | 2 +- app/not-found.tsx | 2 +- app/update-password/page.tsx | 2 +- .../(checkout)/checkout/page.tsx | 30 +- .../store/[countryCode]/(main)/layout.tsx | 4 +- jest.config.js | 49 +- lib/constants.ts | 4 +- lib/fonts.ts | 3 +- lib/services/analyses.service.ts | 24 +- lib/services/analysis-element.service.ts | 52 +- lib/services/analysis-group.service.ts | 43 +- lib/services/analysis-order.service.ts | 20 +- lib/services/audit.service.ts | 4 +- lib/services/codes.service.ts | 10 +- .../medipost/medipostMessageBase.service.ts | 26 +- .../medipostPrivateMessage.service.test.ts | 77 +- .../medipostPrivateMessage.service.ts | 242 +- .../medipost/medipostPublicMessage.service.ts | 5 +- lib/services/medipost/medipostTest.service.ts | 96 +- .../medipost/medipostValidate.service.ts | 15 +- lib/services/medipost/medipostXML.service.ts | 62 +- lib/services/medusaOrder.service.ts | 71 +- lib/services/order.service.ts | 52 +- lib/services/sync-entries.service.ts | 3 +- lib/templates/medipost-order.ts | 26 +- lib/types/analysis-response-element.ts | 5 +- lib/types/audit.ts | 8 +- lib/types/medipost.ts | 2 +- lib/utils.ts | 4 +- lib/validations/company-offer.schema.ts | 7 +- packages/analytics/README.md | 2 +- packages/billing/core/README.md | 10 +- .../billing/core/src/create-billing-schema.ts | 65 +- .../src/schema/report-billing-usage.schema.ts | 6 +- .../billing-webhook-handler.service.ts | 4 +- packages/billing/gateway/README.md | 2 +- .../src/components/embedded-checkout.tsx | 2 +- .../gateway/src/components/plan-picker.tsx | 2 +- packages/billing/lemon-squeezy/README.md | 2 +- packages/billing/montonio/README.md | 1 - .../src/schema/montonio-client-env.schema.ts | 7 +- .../src/schema/montonio-server-env.schema.ts | 25 +- .../montonio-order-handler.service.ts | 37 +- .../montonio-webhook-handler.service.ts | 88 +- packages/billing/stripe/README.md | 2 +- packages/cms/core/README.md | 2 +- packages/cms/keystatic/README.md | 2 +- packages/cms/wordpress/README.md | 2 +- packages/cms/wordpress/docker-compose.yml | 28 +- packages/database-webhooks/README.md | 3 +- ...tgres-database-webhook-verifier.service.ts | 2 +- .../src/components/common-footer.tsx | 15 +- .../patient-first-results-received.email.tsx | 2 +- .../src/locales/en/account-delete-email.json | 2 +- .../en/all-results-received-email.json | 14 +- .../src/locales/en/common.json | 2 +- .../src/locales/en/company-offer-email.json | 2 +- .../en/doctor-summary-received-email.json | 12 +- .../en/first-results-received-email.json | 16 +- .../src/locales/en/invite-email.json | 2 +- .../locales/en/new-jobs-available-email.json | 16 +- .../locales/en/order-processing-email.json | 22 +- .../patient-first-results-received-email.json | 12 +- .../patient-full-results-received-email.json | 10 +- .../src/locales/en/synlab-email.json | 22 +- .../et/all-results-received-email.json | 14 +- .../src/locales/et/common.json | 2 +- .../et/doctor-summary-received-email.json | 14 +- .../et/first-results-received-email.json | 16 +- .../locales/et/new-jobs-available-email.json | 16 +- .../locales/et/order-processing-email.json | 24 +- .../patient-first-results-received-email.json | 14 +- .../patient-full-results-received-email.json | 12 +- .../src/locales/et/synlab-email.json | 22 +- .../ru/all-results-received-email.json | 14 +- .../src/locales/ru/common.json | 2 +- .../src/locales/ru/company-offer-email.json | 2 +- .../ru/doctor-summary-received-email.json | 14 +- .../ru/first-results-received-email.json | 16 +- .../locales/ru/new-jobs-available-email.json | 16 +- .../locales/ru/order-processing-email.json | 22 +- .../patient-first-results-received-email.json | 12 +- .../patient-full-results-received-email.json | 12 +- .../src/locales/ru/synlab-email.json | 22 +- .../src/components/account-selector.tsx | 10 +- .../features/accounts/src/components/index.ts | 4 +- .../components/personal-account-dropdown.tsx | 3 +- .../mfa/multi-factor-auth-setup-dialog.tsx | 4 +- packages/features/accounts/src/server/api.ts | 3 +- .../features/accounts/src/types/accounts.ts | 16 +- .../components/admin-create-user-dialog.tsx | 4 +- .../src/lib/server/admin-server-actions.ts | 27 +- .../schema/create-user-profile.schema.ts | 13 +- .../lib/server/schema/create-user.schema.ts | 8 +- .../server/services/admin-accounts.service.ts | 3 +- .../admin/src/lib/server/utils/medusa-sdk.ts | 7 +- packages/features/admin/tsconfig.json | 4 +- .../auth/src/components/auth-layout.tsx | 2 +- .../components/password-sign-up-container.tsx | 7 +- .../components/sign-up-methods-container.tsx | 5 +- packages/features/doctor/package.json | 2 +- .../actions/table-data-fetching-actions.ts | 4 +- .../server/schema/doctor-analysis.schema.ts | 2 +- .../doctor/src/lib/server/utils/is-doctor.ts | 4 +- packages/features/doctor/tsconfig.json | 16 +- .../medusa-storefront/check-env-variables.js | 32 +- .../medusa-storefront/src/lib/config.ts | 6 +- .../medusa-storefront/src/lib/constants.tsx | 78 +- .../src/lib/context/modal-context.tsx | 24 +- .../medusa-storefront/src/lib/data/cart.ts | 173 +- .../src/lib/data/categories.ts | 25 +- .../src/lib/data/collections.ts | 39 +- .../medusa-storefront/src/lib/data/cookies.ts | 112 +- .../src/lib/data/customer.ts | 306 +- .../src/lib/data/fulfillment.ts | 51 +- .../medusa-storefront/src/lib/data/index.ts | 22 +- .../src/lib/data/onboarding.ts | 13 +- .../medusa-storefront/src/lib/data/orders.ts | 85 +- .../medusa-storefront/src/lib/data/payment.ts | 31 +- .../src/lib/data/products.ts | 121 +- .../medusa-storefront/src/lib/data/regions.ts | 57 +- .../src/lib/hooks/use-in-view.tsx | 26 +- .../src/lib/hooks/use-toggle-state.tsx | 42 +- .../src/lib/util/compare-addresses.ts | 42 +- .../medusa-storefront/src/lib/util/env.ts | 4 +- .../src/lib/util/get-precentage-diff.ts | 8 +- .../src/lib/util/get-product-price.ts | 45 +- .../medusa-storefront/src/lib/util/index.ts | 20 +- .../medusa-storefront/src/lib/util/isEmpty.ts | 10 +- .../src/lib/util/medusa-error.ts | 18 +- .../medusa-storefront/src/lib/util/money.ts | 22 +- .../medusa-storefront/src/lib/util/product.ts | 8 +- .../medusa-storefront/src/lib/util/repeat.ts | 6 +- .../src/lib/util/sort-products.ts | 36 +- .../medusa-storefront/src/middleware.ts | 44 +- .../account/components/account-info/index.tsx | 101 +- .../account/components/account-nav/index.tsx | 86 +- .../account/components/address-book/index.tsx | 27 +- .../components/address-card/add-address.tsx | 58 +- .../address-card/edit-address-modal.tsx | 82 +- .../src/modules/account/components/index.ts | 56 +- .../account/components/login/index.tsx | 39 +- .../account/components/order-card/index.tsx | 48 +- .../components/order-overview/index.tsx | 26 +- .../account/components/overview/index.tsx | 65 +- .../profile-billing-address/index.tsx | 68 +- .../components/profile-email/index.tsx | 45 +- .../account/components/profile-name/index.tsx | 54 +- .../components/profile-password/index.tsx | 34 +- .../components/profile-phone/index.tsx | 50 +- .../account/components/register/index.tsx | 53 +- .../transfer-request-form/index.tsx | 50 +- .../account/templates/account-layout.tsx | 26 +- .../src/modules/account/templates/index.ts | 8 +- .../account/templates/login-template.tsx | 17 +- .../components/cart-item-select/index.tsx | 54 +- .../components/empty-cart-message/index.tsx | 18 +- .../modules/cart/components/item/index.tsx | 93 +- .../cart/components/sign-in-prompt/index.tsx | 18 +- .../src/modules/cart/templates/index.tsx | 29 +- .../src/modules/cart/templates/items.tsx | 33 +- .../src/modules/cart/templates/preview.tsx | 35 +- .../src/modules/cart/templates/summary.tsx | 39 +- .../modules/categories/templates/index.tsx | 53 +- .../components/address-select/index.tsx | 60 +- .../checkout/components/addresses/index.tsx | 85 +- .../components/billing_address/index.tsx | 60 +- .../components/country-select/index.tsx | 30 +- .../components/discount-code/index.tsx | 93 +- .../components/error-message/index.tsx | 21 +- .../components/payment-button/index.tsx | 130 +- .../components/payment-container/index.tsx | 88 +- .../components/payment-test/index.tsx | 8 +- .../components/payment-wrapper/index.tsx | 36 +- .../payment-wrapper/stripe-wrapper.tsx | 43 +- .../checkout/components/payment/index.tsx | 144 +- .../checkout/components/review/index.tsx | 33 +- .../components/shipping-address/index.tsx | 124 +- .../checkout/components/shipping/index.tsx | 230 +- .../components/submit-button/index.tsx | 28 +- .../templates/checkout-form/index.tsx | 30 +- .../templates/checkout-summary/index.tsx | 25 +- .../modules/collections/templates/index.tsx | 30 +- .../common/components/cart-totals/index.tsx | 51 +- .../common/components/checkbox/index.tsx | 29 +- .../common/components/delete-button/index.tsx | 26 +- .../common/components/divider/index.tsx | 8 +- .../components/filter-radio-group/index.tsx | 42 +- .../src/modules/common/components/index.ts | 56 +- .../modules/common/components/input/index.tsx | 40 +- .../components/interactive-link/index.tsx | 25 +- .../components/line-item-options/index.tsx | 24 +- .../components/line-item-price/index.tsx | 44 +- .../components/line-item-unit-price/index.tsx | 40 +- .../localized-client-link/index.tsx | 29 +- .../modules/common/components/modal/index.tsx | 88 +- .../common/components/native-select/index.tsx | 31 +- .../modules/common/components/radio/index.tsx | 20 +- .../src/modules/common/icons/back.tsx | 14 +- .../src/modules/common/icons/bancontact.tsx | 14 +- .../src/modules/common/icons/chevron-down.tsx | 9 +- .../src/modules/common/icons/eye-off.tsx | 14 +- .../src/modules/common/icons/eye.tsx | 14 +- .../modules/common/icons/fast-delivery.tsx | 14 +- .../src/modules/common/icons/ideal.tsx | 14 +- .../src/modules/common/icons/index.ts | 72 +- .../src/modules/common/icons/map-pin.tsx | 14 +- .../src/modules/common/icons/medusa.tsx | 14 +- .../src/modules/common/icons/nextjs.tsx | 14 +- .../src/modules/common/icons/package.tsx | 14 +- .../src/modules/common/icons/paypal.tsx | 6 +- .../common/icons/placeholder-image.tsx | 14 +- .../src/modules/common/icons/refresh.tsx | 14 +- .../src/modules/common/icons/spinner.tsx | 14 +- .../src/modules/common/icons/trash.tsx | 14 +- .../src/modules/common/icons/user.tsx | 14 +- .../src/modules/common/icons/x.tsx | 14 +- .../components/featured-products/index.tsx | 5 +- .../featured-products/product-rail/index.tsx | 19 +- .../modules/home/components/hero/index.tsx | 18 +- .../layout/components/cart-button/index.tsx | 9 +- .../layout/components/cart-dropdown/index.tsx | 106 +- .../components/cart-mismatch-banner/index.tsx | 47 +- .../components/country-select/index.tsx | 89 +- .../src/modules/layout/components/index.ts | 24 +- .../layout/components/medusa-cta/index.tsx | 14 +- .../layout/components/side-menu/index.tsx | 57 +- .../modules/layout/templates/footer/index.tsx | 51 +- .../src/modules/layout/templates/index.tsx | 14 +- .../modules/layout/templates/nav/index.tsx | 30 +- .../modules/order/components/help/index.tsx | 15 +- .../modules/order/components/item/index.tsx | 33 +- .../modules/order/components/items/index.tsx | 31 +- .../order/components/onboarding-cta/index.tsx | 16 +- .../order/components/order-details/index.tsx | 38 +- .../order/components/order-summary/index.tsx | 26 +- .../components/payment-details/index.tsx | 37 +- .../components/shipping-details/index.tsx | 37 +- .../components/transfer-actions/index.tsx | 66 +- .../order/components/transfer-image/index.tsx | 6 +- .../templates/order-completed-template.tsx | 40 +- .../templates/order-details-template.tsx | 37 +- .../components/image-gallery/index.tsx | 29 +- .../components/product-actions/index.tsx | 119 +- .../product-actions/mobile-actions.tsx | 138 +- .../product-actions/option-select.tsx | 41 +- .../product-onboarding-cta/index.tsx | 19 +- .../components/product-preview/index.tsx | 27 +- .../components/product-preview/price.tsx | 16 +- .../components/product-price/index.tsx | 19 +- .../components/product-tabs/accordion.tsx | 67 +- .../components/product-tabs/index.tsx | 46 +- .../components/related-products/index.tsx | 45 +- .../products/components/thumbnail/index.tsx | 63 +- .../src/modules/products/templates/index.tsx | 50 +- .../product-actions-wrapper/index.tsx | 16 +- .../products/templates/product-info/index.tsx | 20 +- .../free-shipping-price-nudge/index.tsx | 95 +- .../components/skeleton-button/index.tsx | 6 +- .../skeleton-card-details/index.tsx | 12 +- .../components/skeleton-cart-item/index.tsx | 30 +- .../components/skeleton-cart-totals/index.tsx | 28 +- .../components/skeleton-code-form/index.tsx | 14 +- .../components/skeleton-line-item/index.tsx | 30 +- .../skeleton-order-confirmed-header/index.tsx | 16 +- .../skeleton-order-information/index.tsx | 40 +- .../components/skeleton-order-items/index.tsx | 38 +- .../skeleton-order-summary/index.tsx | 10 +- .../skeleton-product-preview/index.tsx | 16 +- .../templates/skeleton-cart-page/index.tsx | 41 +- .../skeleton-order-confirmed/index.tsx | 16 +- .../templates/skeleton-product-grid/index.tsx | 14 +- .../skeleton-related-products/index.tsx | 22 +- .../store/components/pagination/index.tsx | 99 +- .../components/refinement-list/index.tsx | 58 +- .../refinement-list/sort-products/index.tsx | 40 +- .../src/modules/store/templates/index.tsx | 30 +- .../store/templates/paginated-products.tsx | 62 +- .../medusa-storefront/src/styles/globals.css | 20 +- .../medusa-storefront/src/types/global.ts | 36 +- .../medusa-storefront/src/types/icon.ts | 6 +- .../src/components/success-notification.tsx | 1 - .../src/components/company-guard.tsx | 10 +- .../invite-members-dialog-container.tsx | 8 +- packages/features/team-accounts/src/index.ts | 2 +- .../src/schema/invite-members.schema.ts | 8 +- .../features/user-analyses/src/server/api.ts | 209 +- .../src/types/analysis-results.ts | 161 +- packages/mailers/core/README.md | 2 +- packages/mailers/shared/README.md | 2 +- .../shared/src/schema/smtp-config.schema.ts | 43 +- packages/monitoring/api/README.md | 2 +- packages/monitoring/baselime/README.md | 2 +- packages/monitoring/sentry/README.md | 2 +- packages/next/README.md | 2 +- packages/otp/README.md | 2 +- packages/otp/eslint.config.mjs | 2 +- packages/shared/package.json | 2 +- .../shared/src/components/auth-provider.tsx | 4 +- .../src/components/confirmation-modal.tsx | 15 +- .../src/components/sign-out-dropdown-item.tsx | 9 +- .../src/components/ui/button-tooltip.tsx | 4 +- .../src/components/ui/dropdown-link.tsx | 11 +- .../shared/src/components/ui/info-tooltip.tsx | 4 +- .../src/components/ui/submit-button.tsx | 14 +- packages/shared/src/config/app.config.ts | 14 +- .../src/config/auth-providers.service.ts | 74 +- packages/shared/src/config/auth.config.ts | 6 +- .../shared/src/config/dynamic-auth.config.ts | 27 +- .../shared/src/config/feature-flags.config.ts | 100 +- packages/shared/src/config/index.ts | 6 +- packages/shared/src/hooks/use-auth-config.ts | 12 +- packages/shared/src/logger/impl/console.ts | 4 +- .../shared/src/types/medipost-analysis.ts | 4 +- packages/supabase/README.md | 10 +- .../supabase/src/auth-callback.service.ts | 48 +- .../supabase/src/get-supabase-client-keys.ts | 15 +- .../hooks/use-sign-in-with-email-password.ts | 3 +- packages/supabase/src/hooks/use-sign-out.ts | 4 +- .../hooks/use-sign-up-with-email-password.ts | 3 +- packages/tsconfig/base.json | 2 +- packages/tsconfig/nextjs.json | 2 +- packages/tsconfig/package.json | 2 +- packages/tsconfig/react-library.json | 2 +- packages/ui/README.md | 2 +- packages/ui/src/makerkit/app-breadcrumbs.tsx | 13 +- packages/ui/src/makerkit/page.tsx | 4 +- packages/ui/src/shadcn/card.tsx | 12 +- pnpm-lock.yaml | 11110 ++++++++++++---- public/locales/en/analysis-results.json | 2 +- public/locales/en/booking.json | 14 +- public/locales/en/cart.json | 2 +- public/locales/en/common.json | 2 +- public/locales/en/dashboard.json | 40 +- public/locales/en/doctor.json | 96 +- public/locales/en/error.json | 12 +- public/locales/en/marketing.json | 2 +- public/locales/en/order-analysis-package.json | 2 +- public/locales/en/order-analysis.json | 2 +- public/locales/en/order-health-analysis.json | 2 +- public/locales/en/orders.json | 2 +- public/locales/en/product.json | 60 +- public/locales/et/analysis-results.json | 2 +- public/locales/et/cart.json | 2 +- public/locales/et/common.json | 2 +- public/locales/et/dashboard.json | 40 +- public/locales/et/doctor.json | 96 +- public/locales/et/error.json | 12 +- public/locales/et/marketing.json | 2 +- public/locales/et/order-analysis-package.json | 2 +- public/locales/et/order-analysis.json | 2 +- public/locales/et/order-health-analysis.json | 2 +- public/locales/et/orders.json | 2 +- public/locales/et/product.json | 60 +- public/locales/et/teams.json | 2 +- public/locales/ru/auth.json | 2 +- public/locales/ru/billing.json | 2 +- public/locales/ru/cart.json | 2 +- public/locales/ru/common.json | 2 +- public/locales/ru/dashboard.json | 40 +- public/locales/ru/doctor.json | 96 +- public/locales/ru/error.json | 12 +- public/locales/ru/marketing.json | 2 +- public/locales/ru/order-analysis.json | 2 +- public/locales/ru/order-health-analysis.json | 2 +- public/locales/ru/orders.json | 2 +- public/locales/ru/product.json | 60 +- public/locales/ru/teams.json | 2 +- styles/STYLE_GUIDE.md | 60 +- styles/makerkit.css | 36 +- styles/markdoc.css | 65 +- styles/theme.utilities.css | 2 +- supabase/templates/change-email-address.html | 294 +- supabase/templates/confirm-email.html | 294 +- supabase/templates/invite-user.html | 296 +- supabase/templates/magic-link.html | 296 +- supabase/templates/reset-password.html | 295 +- tooling/typescript/base.json | 2 +- true/eslint.config.ts | 17 +- tsconfig.json | 55 +- utils/medusa-product.ts | 31 +- utils/supabase/client.ts | 2 +- utils/supabase/middleware.ts | 13 +- utils/supabase/server.ts | 5 +- utils/utils.ts | 4 +- 509 files changed, 17988 insertions(+), 9920 deletions(-) diff --git a/app/(marketing)/(legal)/privacy-policy/page.tsx b/app/(marketing)/(legal)/privacy-policy/page.tsx index 995210d..b8ff856 100644 --- a/app/(marketing)/(legal)/privacy-policy/page.tsx +++ b/app/(marketing)/(legal)/privacy-policy/page.tsx @@ -2,7 +2,6 @@ import { SitePageHeader } from '~/(marketing)/_components/site-page-header'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { withI18n } from '~/lib/i18n/with-i18n'; - export async function generateMetadata() { const { t } = await createI18nServerInstance(); diff --git a/app/(marketing)/(legal)/terms-of-service/page.tsx b/app/(marketing)/(legal)/terms-of-service/page.tsx index 6de2269..ee7d0cb 100644 --- a/app/(marketing)/(legal)/terms-of-service/page.tsx +++ b/app/(marketing)/(legal)/terms-of-service/page.tsx @@ -2,7 +2,6 @@ import { SitePageHeader } from '~/(marketing)/_components/site-page-header'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { withI18n } from '~/lib/i18n/with-i18n'; - export async function generateMetadata() { const { t } = await createI18nServerInstance(); diff --git a/app/(marketing)/_components/site-header-account-section.tsx b/app/(marketing)/_components/site-header-account-section.tsx index dd62722..2d11663 100644 --- a/app/(marketing)/_components/site-header-account-section.tsx +++ b/app/(marketing)/_components/site-header-account-section.tsx @@ -7,15 +7,14 @@ import { UserWorkspace } from '@/app/home/(user)/_lib/server/load-user-workspace import { useQuery } from '@tanstack/react-query'; import { PersonalAccountDropdown } from '@kit/accounts/personal-account-dropdown'; +import { featureFlagsConfig, pathsConfig } from '@kit/shared/config'; +import { useAuthConfig } from '@kit/shared/hooks'; import { useSignOut } from '@kit/supabase/hooks/use-sign-out'; import { useSupabase } from '@kit/supabase/hooks/use-supabase'; import { Button } from '@kit/ui/button'; import { If } from '@kit/ui/if'; import { Trans } from '@kit/ui/trans'; -import { featureFlagsConfig, pathsConfig } from '@kit/shared/config'; -import { useAuthConfig } from '@kit/shared/hooks'; - const ModeToggle = dynamic(() => import('@kit/ui/mode-toggle').then((mod) => ({ default: mod.ModeToggle, diff --git a/app/(marketing)/_components/site-header.tsx b/app/(marketing)/_components/site-header.tsx index 57d5192..694239d 100644 --- a/app/(marketing)/_components/site-header.tsx +++ b/app/(marketing)/_components/site-header.tsx @@ -1,8 +1,7 @@ import { UserWorkspace } from '@/app/home/(user)/_lib/server/load-user-workspace'; -import { Header } from '@kit/ui/marketing'; - import { AppLogo } from '@kit/shared/components/app-logo'; +import { Header } from '@kit/ui/marketing'; import { SiteHeaderAccountSection } from './site-header-account-section'; diff --git a/app/(marketing)/blog/[slug]/page.tsx b/app/(marketing)/blog/[slug]/page.tsx index 76d48cb..8c4ce1c 100644 --- a/app/(marketing)/blog/[slug]/page.tsx +++ b/app/(marketing)/blog/[slug]/page.tsx @@ -8,7 +8,6 @@ import { createCmsClient } from '@kit/cms'; import { withI18n } from '~/lib/i18n/with-i18n'; - import { Post } from '../../blog/_components/post'; interface BlogPageProps { diff --git a/app/(marketing)/contact/_lib/server/server-actions.ts b/app/(marketing)/contact/_lib/server/server-actions.ts index 3b07206..dad3610 100644 --- a/app/(marketing)/contact/_lib/server/server-actions.ts +++ b/app/(marketing)/contact/_lib/server/server-actions.ts @@ -11,14 +11,16 @@ const contactEmail = z .string({ error: 'Contact email is required. Please use the environment variable CONTACT_EMAIL.', - }).describe(`The email where you want to receive the contact form submissions.`) + }) + .describe(`The email where you want to receive the contact form submissions.`) .parse(process.env.CONTACT_EMAIL); const emailFrom = z .string({ error: 'Sender email is required. Please use the environment variable EMAIL_SENDER.', - }).describe(`The email sending address.`) + }) + .describe(`The email sending address.`) .parse(process.env.EMAIL_SENDER); export const sendContactEmail = enhanceAction( diff --git a/app/(marketing)/contact/page.tsx b/app/(marketing)/contact/page.tsx index 6a6f516..8597d77 100644 --- a/app/(marketing)/contact/page.tsx +++ b/app/(marketing)/contact/page.tsx @@ -6,7 +6,6 @@ import { ContactForm } from '~/(marketing)/contact/_components/contact-form'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { withI18n } from '~/lib/i18n/with-i18n'; - export async function generateMetadata() { const { t } = await createI18nServerInstance(); diff --git a/app/(marketing)/faq/page.tsx b/app/(marketing)/faq/page.tsx index 3fcc944..5c8beee 100644 --- a/app/(marketing)/faq/page.tsx +++ b/app/(marketing)/faq/page.tsx @@ -9,7 +9,6 @@ import { SitePageHeader } from '~/(marketing)/_components/site-page-header'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { withI18n } from '~/lib/i18n/with-i18n'; - export const generateMetadata = async () => { const { t } = await createI18nServerInstance(); diff --git a/app/(marketing)/layout.tsx b/app/(marketing)/layout.tsx index 5b308e2..4a41c52 100644 --- a/app/(marketing)/layout.tsx +++ b/app/(marketing)/layout.tsx @@ -2,9 +2,8 @@ import { use } from 'react'; import { SiteFooter } from '~/(marketing)/_components/site-footer'; import { SiteHeader } from '~/(marketing)/_components/site-header'; -import { withI18n } from '~/lib/i18n/with-i18n'; - import { loadCurrentUserAccounts } from '~/home/(user)/_lib/server/load-accounts'; +import { withI18n } from '~/lib/i18n/with-i18n'; function SiteLayout(props: React.PropsWithChildren) { const accounts = use(loadCurrentUserAccounts()); diff --git a/app/(marketing)/page.tsx b/app/(marketing)/page.tsx index 1034428..722aa55 100644 --- a/app/(marketing)/page.tsx +++ b/app/(marketing)/page.tsx @@ -1,9 +1,9 @@ import Link from 'next/link'; +import { ArrowRightIcon } from 'lucide-react'; + import { MedReportLogo } from '@kit/shared/components/med-report-logo'; import { pathsConfig } from '@kit/shared/config'; -import { ArrowRightIcon } from 'lucide-react'; - import { CtaButton, Hero } from '@kit/ui/marketing'; import { Trans } from '@kit/ui/trans'; diff --git a/app/(public)/company-offer/page.tsx b/app/(public)/company-offer/page.tsx index 01cb9b7..b942bcd 100644 --- a/app/(public)/company-offer/page.tsx +++ b/app/(public)/company-offer/page.tsx @@ -1,9 +1,10 @@ import React from 'react'; import { MedReportLogo } from '@kit/shared/components/med-report-logo'; -import { withI18n } from '~/lib/i18n/with-i18n'; import { Trans } from '@kit/ui/trans'; +import { withI18n } from '~/lib/i18n/with-i18n'; + import CompanyOfferForm from './_components/company-offer-form'; function CompanyOffer() { diff --git a/app/(public)/layout.tsx b/app/(public)/layout.tsx index b897a04..bbb9b6d 100644 --- a/app/(public)/layout.tsx +++ b/app/(public)/layout.tsx @@ -1,9 +1,8 @@ import { withI18n } from '~/lib/i18n/with-i18n'; - function SiteLayout(props: React.PropsWithChildren) { return ( -
+
{props.children}
); diff --git a/app/admin/_components/admin-sidebar.tsx b/app/admin/_components/admin-sidebar.tsx index 0492b98..2e777e7 100644 --- a/app/admin/_components/admin-sidebar.tsx +++ b/app/admin/_components/admin-sidebar.tsx @@ -6,6 +6,8 @@ import { usePathname } from 'next/navigation'; import { UserWorkspace } from '@/app/home/(user)/_lib/server/load-user-workspace'; import { LayoutDashboard, Users } from 'lucide-react'; +import { AppLogo } from '@kit/shared/components/app-logo'; +import { ProfileAccountDropdownContainer } from '@kit/shared/components/personal-account-dropdown-container'; import { Sidebar, SidebarContent, @@ -19,9 +21,6 @@ import { useSidebar, } from '@kit/ui/shadcn-sidebar'; -import { AppLogo } from '@kit/shared/components/app-logo'; -import { ProfileAccountDropdownContainer } from '@kit/shared/components/personal-account-dropdown-container'; - export function AdminSidebar({ accounts, }: { diff --git a/app/admin/accounts/[id]/page.tsx b/app/admin/accounts/[id]/page.tsx index 6f17480..bc33fe1 100644 --- a/app/admin/accounts/[id]/page.tsx +++ b/app/admin/accounts/[id]/page.tsx @@ -2,6 +2,7 @@ import { cache } from 'react'; import { AdminAccountPage } from '@kit/admin/components/admin-account-page'; import { AdminGuard } from '@kit/admin/components/admin-guard'; + import { getAccount } from '~/lib/services/account.service'; interface Params { diff --git a/app/api/billing/webhook/route.ts b/app/api/billing/webhook/route.ts index d641654..2b12858 100644 --- a/app/api/billing/webhook/route.ts +++ b/app/api/billing/webhook/route.ts @@ -1,11 +1,10 @@ import { getPlanTypesMap } from '@kit/billing'; import { getBillingEventHandlerService } from '@kit/billing-gateway'; import { enhanceRouteHandler } from '@kit/next/routes'; +import { billingConfig } from '@kit/shared/config'; import { getLogger } from '@kit/shared/logger'; import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; -import { billingConfig } from '@kit/shared/config'; - /** * @description Handle the webhooks from Stripe related to checkouts */ diff --git a/app/api/job/handler/load-env.ts b/app/api/job/handler/load-env.ts index 9a218b6..c6896cf 100644 --- a/app/api/job/handler/load-env.ts +++ b/app/api/job/handler/load-env.ts @@ -2,7 +2,11 @@ import { config } from 'dotenv'; export default function loadEnv() { config({ path: `.env` }); - if (['local', 'test', 'development', 'production'].includes(process.env.NODE_ENV!)) { + if ( + ['local', 'test', 'development', 'production'].includes( + process.env.NODE_ENV!, + ) + ) { config({ path: `.env.${process.env.NODE_ENV}` }); } } diff --git a/app/api/job/handler/sync-analysis-groups-store.ts b/app/api/job/handler/sync-analysis-groups-store.ts index 7f6ee7b..12ea3c8 100644 --- a/app/api/job/handler/sync-analysis-groups-store.ts +++ b/app/api/job/handler/sync-analysis-groups-store.ts @@ -1,9 +1,13 @@ -import Medusa from "@medusajs/js-sdk" -import type { AdminProductCategory } from "@medusajs/types"; -import { listProductTypes } from "@lib/data/products"; -import { getAnalysisElements } from "~/lib/services/analysis-element.service"; -import { getAnalysisGroups } from "~/lib/services/analysis-group.service"; -import { createMedusaSyncFailEntry, createMedusaSyncSuccessEntry } from "~/lib/services/analyses.service"; +import { listProductTypes } from '@lib/data/products'; +import Medusa from '@medusajs/js-sdk'; +import type { AdminProductCategory } from '@medusajs/types'; + +import { + createMedusaSyncFailEntry, + createMedusaSyncSuccessEntry, +} from '~/lib/services/analyses.service'; +import { getAnalysisElements } from '~/lib/services/analysis-element.service'; +import { getAnalysisGroups } from '~/lib/services/analysis-group.service'; const SYNLAB_SERVICES_CATEGORY_HANDLE = 'synlab-services'; const SYNLAB_ANALYSIS_PRODUCT_TYPE_HANDLE = 'synlab-analysis'; @@ -12,7 +16,8 @@ const BASE_ANALYSIS_PRODUCT_HANDLE = 'analysis-base'; const getAdminSdk = () => { const medusaBackendUrl = process.env.MEDUSA_BACKEND_PUBLIC_URL!; - const medusaPublishableApiKey = process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY!; + const medusaPublishableApiKey = + process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY!; const key = process.env.MEDUSA_SECRET_API_KEY!; if (!medusaBackendUrl || !medusaPublishableApiKey) { @@ -23,15 +28,14 @@ const getAdminSdk = () => { debug: process.env.NODE_ENV === 'development', apiKey: key, }); -} +}; -async function createProductCategories({ - medusa, -}: { - medusa: Medusa; -}) { - const { product_categories: existingProductCategories } = await medusa.admin.productCategory.list(); - const parentCategory = existingProductCategories.find(({ handle }) => handle === SYNLAB_SERVICES_CATEGORY_HANDLE); +async function createProductCategories({ medusa }: { medusa: Medusa }) { + const { product_categories: existingProductCategories } = + await medusa.admin.productCategory.list(); + const parentCategory = existingProductCategories.find( + ({ handle }) => handle === SYNLAB_SERVICES_CATEGORY_HANDLE, + ); if (!parentCategory) { throw new Error('Parent category not found'); @@ -46,8 +50,12 @@ async function createProductCategories({ for (const analysisGroup of analysisGroups) { console.info(`Processing analysis group '${analysisGroup.name}'`); - const isExisting = existingProductCategories.find(({ name }) => name === analysisGroup.name); - const isNewlyCreated = createdCategories.find(({ name }) => name === analysisGroup.name); + const isExisting = existingProductCategories.find( + ({ name }) => name === analysisGroup.name, + ); + const isNewlyCreated = createdCategories.find( + ({ name }) => name === analysisGroup.name, + ); if (isExisting || isNewlyCreated) { console.info(`Analysis group '${analysisGroup.name}' already exists`); continue; @@ -63,18 +71,19 @@ async function createProductCategories({ analysisGroupId: analysisGroup.id, }, }); - console.info(`Successfully created category, id=${createResponse.product_category.id}`); + console.info( + `Successfully created category, id=${createResponse.product_category.id}`, + ); createdCategories.push(createResponse.product_category); } } -async function getChildProductCategories({ - medusa, -}: { - medusa: Medusa; -}) { - const { product_categories: allCategories } = await medusa.admin.productCategory.list(); - const childCategories = allCategories.filter(({ parent_category_id }) => parent_category_id !== null); +async function getChildProductCategories({ medusa }: { medusa: Medusa }) { + const { product_categories: allCategories } = + await medusa.admin.productCategory.list(); + const childCategories = allCategories.filter( + ({ parent_category_id }) => parent_category_id !== null, + ); return childCategories; } @@ -93,34 +102,34 @@ async function deleteProductCategories({ /** * In case a reset is needed */ -async function deleteProducts({ - medusa, -}: { - medusa: Medusa; -}) { +async function deleteProducts({ medusa }: { medusa: Medusa }) { const { products: existingProducts } = await medusa.admin.product.list({ fields: 'id,collection_id', limit: 1000, }); - - await Promise.all(existingProducts.filter((a) => !a.collection_id).map(({ id }) => medusa.admin.product.delete(id))); + + await Promise.all( + existingProducts + .filter((a) => !a.collection_id) + .map(({ id }) => medusa.admin.product.delete(id)), + ); } async function getAnalysisPackagesType() { const { productTypes } = await listProductTypes(); - const analysisPackagesType = productTypes.find(({ metadata }) => metadata?.handle === SYNLAB_ANALYSIS_PRODUCT_TYPE_HANDLE); + const analysisPackagesType = productTypes.find( + ({ metadata }) => metadata?.handle === SYNLAB_ANALYSIS_PRODUCT_TYPE_HANDLE, + ); if (!analysisPackagesType) { throw new Error('Synlab analysis packages type not found'); } return analysisPackagesType; } -async function getProductDefaultFields({ - medusa, -}: { - medusa: Medusa; -}) { - const baseProductsResponse = await medusa.admin.product.list({ handle: BASE_ANALYSIS_PRODUCT_HANDLE }) +async function getProductDefaultFields({ medusa }: { medusa: Medusa }) { + const baseProductsResponse = await medusa.admin.product.list({ + handle: BASE_ANALYSIS_PRODUCT_HANDLE, + }); const baseProduct = baseProductsResponse.products[0]; if (!baseProduct) { throw new Error('Base product not found'); @@ -142,25 +151,18 @@ async function getProductDefaultFields({ defaultSalesChannels, defaultProductOption, defaultProductVariant, - } + }; } -async function createProducts({ - medusa, -}: { - medusa: Medusa; -}) { - const { product_categories: allCategories } = await medusa.admin.productCategory.list(); +async function createProducts({ medusa }: { medusa: Medusa }) { + const { product_categories: allCategories } = + await medusa.admin.productCategory.list(); const [ { products: existingProducts }, analysisElements, analysisPackagesType, - { - defaultSalesChannels, - defaultProductOption, - defaultProductVariant, - } + { defaultSalesChannels, defaultProductOption, defaultProductVariant }, ] = await Promise.all([ medusa.admin.product.list({ category_id: allCategories.map(({ id }) => id), @@ -168,13 +170,17 @@ async function createProducts({ getAnalysisElements({ getAll: true }), getAnalysisPackagesType(), getProductDefaultFields({ medusa }), - ]) + ]); for (const analysisElement of analysisElements) { const { analysis_id_original: originalId } = analysisElement; - const isExisting = existingProducts.find(({ metadata }) => metadata?.analysisIdOriginal === originalId); + const isExisting = existingProducts.find( + ({ metadata }) => metadata?.analysisIdOriginal === originalId, + ); if (isExisting) { - console.info(`Analysis element '${analysisElement.analysis_name_lab}' already exists`); + console.info( + `Analysis element '${analysisElement.analysis_name_lab}' already exists`, + ); continue; } const { analysis_name_lab: name } = analysisElement; @@ -183,7 +189,10 @@ async function createProducts({ continue; } - const category = allCategories.find(({ metadata }) => metadata?.analysisGroupId === analysisElement.parent_analysis_group_id); + const category = allCategories.find( + ({ metadata }) => + metadata?.analysisGroupId === analysisElement.parent_analysis_group_id, + ); if (!category) { console.error(`Category not found for analysis element '${name}'`); continue; @@ -227,9 +236,9 @@ export default async function syncAnalysisGroupsStore() { // await deleteProductCategories({ medusa, categories }); // await deleteProducts({ medusa }); // return; - + await createProducts({ medusa }); - + await createMedusaSyncSuccessEntry(); } catch (e) { await createMedusaSyncFailEntry(JSON.stringify(e)); diff --git a/app/api/job/handler/sync-analysis-groups.ts b/app/api/job/handler/sync-analysis-groups.ts index fcbf612..c037378 100644 --- a/app/api/job/handler/sync-analysis-groups.ts +++ b/app/api/job/handler/sync-analysis-groups.ts @@ -1,16 +1,32 @@ import axios from 'axios'; import { XMLParser } from 'fast-xml-parser'; import fs from 'fs'; -import { createAnalysisGroup, getAnalysisGroups } from '~/lib/services/analysis-group.service'; -import { IMedipostPublicMessageDataParsed } from '~/lib/services/medipost/medipost.types'; -import { createAnalysis, createNoDataReceivedEntry, createNoNewDataReceivedEntry, createSyncFailEntry, createSyncSuccessEntry, getAnalyses } from '~/lib/services/analyses.service'; -import { getLastCheckedDate } from '~/lib/services/sync-entries.service'; -import { AnalysisElement, createAnalysisElement, getAnalysisElements } from '~/lib/services/analysis-element.service'; -import { createCodes } from '~/lib/services/codes.service'; -import { getLatestPublicMessageListItem } from '~/lib/services/medipost/medipostPublicMessage.service'; -import type { ICode } from '~/lib/types/code'; + import { toArray } from '@kit/shared/utils'; +import { + createAnalysis, + createNoDataReceivedEntry, + createNoNewDataReceivedEntry, + createSyncFailEntry, + createSyncSuccessEntry, + getAnalyses, +} from '~/lib/services/analyses.service'; +import { + AnalysisElement, + createAnalysisElement, + getAnalysisElements, +} from '~/lib/services/analysis-element.service'; +import { + createAnalysisGroup, + getAnalysisGroups, +} from '~/lib/services/analysis-group.service'; +import { createCodes } from '~/lib/services/codes.service'; +import { IMedipostPublicMessageDataParsed } from '~/lib/services/medipost/medipost.types'; +import { getLatestPublicMessageListItem } from '~/lib/services/medipost/medipostPublicMessage.service'; +import { getLastCheckedDate } from '~/lib/services/sync-entries.service'; +import type { ICode } from '~/lib/types/code'; + const WRITE_XML_TO_FILE = false as boolean; export default async function syncAnalysisGroups() { @@ -52,7 +68,8 @@ export default async function syncAnalysisGroups() { } const parser = new XMLParser({ ignoreAttributes: false }); - const parsed: IMedipostPublicMessageDataParsed = parser.parse(publicMessageData); + const parsed: IMedipostPublicMessageDataParsed = + parser.parse(publicMessageData); if (parsed.ANSWER?.CODE && parsed.ANSWER?.CODE !== 0) { throw new Error( @@ -77,12 +94,18 @@ export default async function syncAnalysisGroups() { const codes: ICode[] = []; for (const analysisGroup of analysisGroups) { - const existingAnalysisGroup = existingAnalysisGroups?.find(({ original_id }) => original_id === analysisGroup.UuringuGruppId); + const existingAnalysisGroup = existingAnalysisGroups?.find( + ({ original_id }) => original_id === analysisGroup.UuringuGruppId, + ); let groupExistingAnalysisElements: AnalysisElement[] = []; let analysisGroupId: number; if (existingAnalysisGroup) { - console.info(`Analysis group '${analysisGroup.UuringuGruppNimi}' already exists, only creating new analysis elements`); - groupExistingAnalysisElements = await getAnalysisElements({ analysisGroupId: existingAnalysisGroup.id }); + console.info( + `Analysis group '${analysisGroup.UuringuGruppNimi}' already exists, only creating new analysis elements`, + ); + groupExistingAnalysisElements = await getAnalysisElements({ + analysisGroupId: existingAnalysisGroup.id, + }); analysisGroupId = existingAnalysisGroup.id; } else { analysisGroupId = await createAnalysisGroup({ @@ -109,10 +132,14 @@ export default async function syncAnalysisGroups() { for (const item of analysisGroupItems) { const analysisElement = item.UuringuElement!; - const isExistingAnalysisElement = groupExistingAnalysisElements - .find(({ analysis_id_original }) => analysis_id_original === analysisElement.UuringId); + const isExistingAnalysisElement = groupExistingAnalysisElements.find( + ({ analysis_id_original }) => + analysis_id_original === analysisElement.UuringId, + ); if (isExistingAnalysisElement) { - console.info(`Analysis element '${analysisElement.UuringNimi}' already exists`); + console.info( + `Analysis element '${analysisElement.UuringNimi}' already exists`, + ); continue; } @@ -149,16 +176,24 @@ export default async function syncAnalysisGroups() { const analyses = analysisElement.UuringuElement; if (analyses?.length) { - const existingAnalyses = await getAnalyses({ originalIds: analyses.map(({ UuringId }) => UuringId) }); + const existingAnalyses = await getAnalyses({ + originalIds: analyses.map(({ UuringId }) => UuringId), + }); for (const analysis of analyses) { - const isExistingAnalysis = existingAnalyses.find(({ analysis_id_original }) => analysis_id_original === analysis.UuringId); + const isExistingAnalysis = existingAnalyses.find( + ({ analysis_id_original }) => + analysis_id_original === analysis.UuringId, + ); if (isExistingAnalysis) { console.info(`Analysis '${analysis.UuringNimi}' already exists`); continue; } - const insertedAnalysisId = await createAnalysis(analysis, analysisGroupId); + const insertedAnalysisId = await createAnalysis( + analysis, + analysisGroupId, + ); if (analysis.Kood) { const analysisCodes = toArray(analysis.Kood); @@ -187,11 +222,17 @@ export default async function syncAnalysisGroups() { await createSyncSuccessEntry(); } catch (e) { const errorMessage = e instanceof Error ? e.message : String(e); - await createSyncFailEntry(JSON.stringify({ - message: errorMessage, - stack: e instanceof Error ? e.stack : undefined, - name: e instanceof Error ? e.name : 'Unknown', - }, null, 2)); + await createSyncFailEntry( + JSON.stringify( + { + message: errorMessage, + stack: e instanceof Error ? e.stack : undefined, + name: e instanceof Error ? e.name : 'Unknown', + }, + null, + 2, + ), + ); console.error('Sync failed:', e); throw new Error( `Failed to sync public message data, error: ${errorMessage}`, diff --git a/app/api/job/handler/sync-analysis-results.ts b/app/api/job/handler/sync-analysis-results.ts index 4f394f1..b631045 100644 --- a/app/api/job/handler/sync-analysis-results.ts +++ b/app/api/job/handler/sync-analysis-results.ts @@ -1,4 +1,4 @@ -import { readPrivateMessageResponse } from "~/lib/services/medipost/medipostPrivateMessage.service"; +import { readPrivateMessageResponse } from '~/lib/services/medipost/medipostPrivateMessage.service'; type ProcessedMessage = { messageId: string; @@ -15,9 +15,9 @@ type GroupedResults = { }; export default async function syncAnalysisResults() { - console.info("Syncing analysis results"); - - let processedMessages: ProcessedMessage[] = []; + console.info('Syncing analysis results'); + + const processedMessages: ProcessedMessage[] = []; const excludedMessageIds: string[] = []; while (true) { const result = await readPrivateMessageResponse({ excludedMessageIds }); @@ -26,7 +26,7 @@ export default async function syncAnalysisResults() { } if (!result.messageId) { - console.info("No more messages to process"); + console.info('No more messages to process'); break; } @@ -59,5 +59,7 @@ export default async function syncAnalysisResults() { } return acc; }, {} as GroupedResults); - console.info(`Processed ${processedMessages.length} messages, results: ${JSON.stringify(groupedResults)}`); + console.info( + `Processed ${processedMessages.length} messages, results: ${JSON.stringify(groupedResults)}`, + ); } diff --git a/app/api/job/handler/validate-api-key.ts b/app/api/job/handler/validate-api-key.ts index 70af4ba..f2b5123 100644 --- a/app/api/job/handler/validate-api-key.ts +++ b/app/api/job/handler/validate-api-key.ts @@ -1,4 +1,4 @@ -import { NextRequest } from "next/server"; +import { NextRequest } from 'next/server'; export default function validateApiKey(request: NextRequest) { const envApiKey = process.env.JOBS_API_TOKEN; diff --git a/app/api/job/medipost-retry-dispatch/route.ts b/app/api/job/medipost-retry-dispatch/route.ts index 3ccf0f9..1fe75a0 100644 --- a/app/api/job/medipost-retry-dispatch/route.ts +++ b/app/api/job/medipost-retry-dispatch/route.ts @@ -1,10 +1,13 @@ -import { NextRequest, NextResponse } from "next/server"; -import loadEnv from "../handler/load-env"; -import validateApiKey from "../handler/validate-api-key"; -import { getOrderedAnalysisIds } from "~/lib/services/medusaOrder.service"; -import { sendOrderToMedipost } from "~/lib/services/medipost/medipostPrivateMessage.service"; -import { retrieveOrder } from "@lib/data/orders"; -import { getMedipostDispatchTries } from "~/lib/services/audit.service"; +import { NextRequest, NextResponse } from 'next/server'; + +import { retrieveOrder } from '@lib/data/orders'; + +import { getMedipostDispatchTries } from '~/lib/services/audit.service'; +import { sendOrderToMedipost } from '~/lib/services/medipost/medipostPrivateMessage.service'; +import { getOrderedAnalysisIds } from '~/lib/services/medusaOrder.service'; + +import loadEnv from '../handler/load-env'; +import validateApiKey from '../handler/validate-api-key'; export const POST = async (request: NextRequest) => { loadEnv(); @@ -19,23 +22,34 @@ export const POST = async (request: NextRequest) => { const tries = await getMedipostDispatchTries(medusaOrderId); if (tries >= 3) { - return NextResponse.json({ - message: 'Order has been retried too many times', - }, { status: 400 }); + return NextResponse.json( + { + message: 'Order has been retried too many times', + }, + { status: 400 }, + ); } try { const medusaOrder = await retrieveOrder(medusaOrderId); - const orderedAnalysisElements = await getOrderedAnalysisIds({ medusaOrder }); + const orderedAnalysisElements = await getOrderedAnalysisIds({ + medusaOrder, + }); await sendOrderToMedipost({ medusaOrderId, orderedAnalysisElements }); - console.info("Successfully sent order to medipost"); - return NextResponse.json({ - message: 'Successfully sent order to medipost', - }, { status: 200 }); + console.info('Successfully sent order to medipost'); + return NextResponse.json( + { + message: 'Successfully sent order to medipost', + }, + { status: 200 }, + ); } catch (e) { - console.error("Error sending order to medipost", e); - return NextResponse.json({ - message: 'Failed to send order to medipost', - }, { status: 500 }); + console.error('Error sending order to medipost', e); + return NextResponse.json( + { + message: 'Failed to send order to medipost', + }, + { status: 500 }, + ); } }; diff --git a/app/api/job/send-open-jobs-emails/route.ts b/app/api/job/send-open-jobs-emails/route.ts index 939f3b7..9bf4118 100644 --- a/app/api/job/send-open-jobs-emails/route.ts +++ b/app/api/job/send-open-jobs-emails/route.ts @@ -4,6 +4,7 @@ import { NotificationAction, createNotificationLog, } from '~/lib/services/audit/notificationEntries.service'; + import loadEnv from '../handler/load-env'; import sendOpenJobsEmails from '../handler/send-open-jobs-emails'; import validateApiKey from '../handler/validate-api-key'; diff --git a/app/api/job/sync-analysis-groups-store/route.ts b/app/api/job/sync-analysis-groups-store/route.ts index 96a4d90..be54509 100644 --- a/app/api/job/sync-analysis-groups-store/route.ts +++ b/app/api/job/sync-analysis-groups-store/route.ts @@ -1,7 +1,8 @@ -import { NextRequest, NextResponse } from "next/server"; -import loadEnv from "../handler/load-env"; -import validateApiKey from "../handler/validate-api-key"; -import syncAnalysisGroupsStore from "../handler/sync-analysis-groups-store"; +import { NextRequest, NextResponse } from 'next/server'; + +import loadEnv from '../handler/load-env'; +import syncAnalysisGroupsStore from '../handler/sync-analysis-groups-store'; +import validateApiKey from '../handler/validate-api-key'; export const POST = async (request: NextRequest) => { loadEnv(); @@ -14,14 +15,20 @@ export const POST = async (request: NextRequest) => { try { await syncAnalysisGroupsStore(); - console.info("Successfully synced analysis groups store"); - return NextResponse.json({ - message: 'Successfully synced analysis groups store', - }, { status: 200 }); + console.info('Successfully synced analysis groups store'); + return NextResponse.json( + { + message: 'Successfully synced analysis groups store', + }, + { status: 200 }, + ); } catch (e) { - console.error("Error syncing analysis groups store", e); - return NextResponse.json({ - message: 'Failed to sync analysis groups store', - }, { status: 500 }); + console.error('Error syncing analysis groups store', e); + return NextResponse.json( + { + message: 'Failed to sync analysis groups store', + }, + { status: 500 }, + ); } }; diff --git a/app/api/job/sync-analysis-groups/route.ts b/app/api/job/sync-analysis-groups/route.ts index e60b414..83cc6d3 100644 --- a/app/api/job/sync-analysis-groups/route.ts +++ b/app/api/job/sync-analysis-groups/route.ts @@ -1,7 +1,8 @@ -import { NextRequest, NextResponse } from "next/server"; -import syncAnalysisGroups from "../handler/sync-analysis-groups"; -import loadEnv from "../handler/load-env"; -import validateApiKey from "../handler/validate-api-key"; +import { NextRequest, NextResponse } from 'next/server'; + +import loadEnv from '../handler/load-env'; +import syncAnalysisGroups from '../handler/sync-analysis-groups'; +import validateApiKey from '../handler/validate-api-key'; export const POST = async (request: NextRequest) => { loadEnv(); @@ -14,14 +15,20 @@ export const POST = async (request: NextRequest) => { try { await syncAnalysisGroups(); - console.info("Successfully synced analysis groups"); - return NextResponse.json({ - message: 'Successfully synced analysis groups', - }, { status: 200 }); + console.info('Successfully synced analysis groups'); + return NextResponse.json( + { + message: 'Successfully synced analysis groups', + }, + { status: 200 }, + ); } catch (e) { - console.error("Error syncing analysis groups", e); - return NextResponse.json({ - message: 'Failed to sync analysis groups', - }, { status: 500 }); + console.error('Error syncing analysis groups', e); + return NextResponse.json( + { + message: 'Failed to sync analysis groups', + }, + { status: 500 }, + ); } }; diff --git a/app/api/job/sync-analysis-results/route.ts b/app/api/job/sync-analysis-results/route.ts index dc0b6eb..392be6a 100644 --- a/app/api/job/sync-analysis-results/route.ts +++ b/app/api/job/sync-analysis-results/route.ts @@ -1,7 +1,8 @@ -import { NextRequest, NextResponse } from "next/server"; -import loadEnv from "../handler/load-env"; -import validateApiKey from "../handler/validate-api-key"; -import syncAnalysisResults from "../handler/sync-analysis-results"; +import { NextRequest, NextResponse } from 'next/server'; + +import loadEnv from '../handler/load-env'; +import syncAnalysisResults from '../handler/sync-analysis-results'; +import validateApiKey from '../handler/validate-api-key'; export const POST = async (request: NextRequest) => { loadEnv(); @@ -14,14 +15,20 @@ export const POST = async (request: NextRequest) => { try { await syncAnalysisResults(); - console.info("Successfully synced analysis results"); - return NextResponse.json({ - message: 'Successfully synced analysis results', - }, { status: 200 }); + console.info('Successfully synced analysis results'); + return NextResponse.json( + { + message: 'Successfully synced analysis results', + }, + { status: 200 }, + ); } catch (e) { - console.error("Error syncing analysis results", e); - return NextResponse.json({ - message: 'Failed to sync analysis results', - }, { status: 500 }); + console.error('Error syncing analysis results', e); + return NextResponse.json( + { + message: 'Failed to sync analysis results', + }, + { status: 500 }, + ); } }; diff --git a/app/api/job/sync-connected-online/route.ts b/app/api/job/sync-connected-online/route.ts index 04e90d9..065c8ec 100644 --- a/app/api/job/sync-connected-online/route.ts +++ b/app/api/job/sync-connected-online/route.ts @@ -1,7 +1,8 @@ -import { NextRequest, NextResponse } from "next/server"; -import loadEnv from "../handler/load-env"; -import validateApiKey from "../handler/validate-api-key"; -import syncConnectedOnline from "../handler/sync-connected-online"; +import { NextRequest, NextResponse } from 'next/server'; + +import loadEnv from '../handler/load-env'; +import syncConnectedOnline from '../handler/sync-connected-online'; +import validateApiKey from '../handler/validate-api-key'; export const POST = async (request: NextRequest) => { loadEnv(); @@ -14,14 +15,20 @@ export const POST = async (request: NextRequest) => { try { await syncConnectedOnline(); - console.info("Successfully synced connected-online"); - return NextResponse.json({ - message: 'Successfully synced connected-online', - }, { status: 200 }); + console.info('Successfully synced connected-online'); + return NextResponse.json( + { + message: 'Successfully synced connected-online', + }, + { status: 200 }, + ); } catch (e) { - console.error("Error syncing connected-online", e); - return NextResponse.json({ - message: 'Failed to sync connected-online', - }, { status: 500 }); + console.error('Error syncing connected-online', e); + return NextResponse.json( + { + message: 'Failed to sync connected-online', + }, + { status: 500 }, + ); } }; diff --git a/app/api/job/test-medipost-responses/route.ts b/app/api/job/test-medipost-responses/route.ts index 619756f..fc1f2e1 100644 --- a/app/api/job/test-medipost-responses/route.ts +++ b/app/api/job/test-medipost-responses/route.ts @@ -1,11 +1,17 @@ -import { NextRequest, NextResponse } from "next/server"; -import { getAnalysisOrdersAdmin } from "~/lib/services/order.service"; -import { composeOrderTestResponseXML, sendPrivateMessageTestResponse } from "~/lib/services/medipost/medipostTest.service"; -import { retrieveOrder } from "@lib/data"; -import { getAccountAdmin } from "~/lib/services/account.service"; -import { getOrderedAnalysisIds } from "~/lib/services/medusaOrder.service"; -import loadEnv from "../handler/load-env"; -import validateApiKey from "../handler/validate-api-key"; +import { NextRequest, NextResponse } from 'next/server'; + +import { retrieveOrder } from '@lib/data'; + +import { getAccountAdmin } from '~/lib/services/account.service'; +import { + composeOrderTestResponseXML, + sendPrivateMessageTestResponse, +} from '~/lib/services/medipost/medipostTest.service'; +import { getOrderedAnalysisIds } from '~/lib/services/medusaOrder.service'; +import { getAnalysisOrdersAdmin } from '~/lib/services/order.service'; + +import loadEnv from '../handler/load-env'; +import validateApiKey from '../handler/validate-api-key'; export async function POST(request: NextRequest) { loadEnv(); @@ -16,17 +22,27 @@ export async function POST(request: NextRequest) { return NextResponse.json({}, { status: 401, statusText: 'Unauthorized' }); } - const analysisOrders = await getAnalysisOrdersAdmin({ orderStatus: 'PROCESSING' }); + const analysisOrders = await getAnalysisOrdersAdmin({ + orderStatus: 'PROCESSING', + }); - console.error(`Sending test responses for ${analysisOrders.length} analysis orders`); + console.error( + `Sending test responses for ${analysisOrders.length} analysis orders`, + ); for (const medreportOrder of analysisOrders) { const medusaOrderId = medreportOrder.medusa_order_id; - const medusaOrder = await retrieveOrder(medusaOrderId) + const medusaOrder = await retrieveOrder(medusaOrderId); - const account = await getAccountAdmin({ primaryOwnerUserId: medreportOrder.user_id }); - const orderedAnalysisElementsIds = await getOrderedAnalysisIds({ medusaOrder }); + const account = await getAccountAdmin({ + primaryOwnerUserId: medreportOrder.user_id, + }); + const orderedAnalysisElementsIds = await getOrderedAnalysisIds({ + medusaOrder, + }); - console.info(`Sending test response for order=${medusaOrderId} with ${orderedAnalysisElementsIds.length} ordered analysis elements`); + console.info( + `Sending test response for order=${medusaOrderId} with ${orderedAnalysisElementsIds.length} ordered analysis elements`, + ); const idsToSend = orderedAnalysisElementsIds; const messageXml = await composeOrderTestResponseXML({ person: { @@ -35,8 +51,12 @@ export async function POST(request: NextRequest) { lastName: account.last_name ?? '', phone: account.phone ?? '', }, - orderedAnalysisElementsIds: idsToSend.map(({ analysisElementId }) => analysisElementId).filter(Boolean) as number[], - orderedAnalysesIds: idsToSend.map(({ analysisId }) => analysisId).filter(Boolean) as number[], + orderedAnalysisElementsIds: idsToSend + .map(({ analysisElementId }) => analysisElementId) + .filter(Boolean) as number[], + orderedAnalysesIds: idsToSend + .map(({ analysisId }) => analysisId) + .filter(Boolean) as number[], orderId: medreportOrder.id, orderCreatedAt: new Date(medreportOrder.created_at), }); @@ -44,7 +64,7 @@ export async function POST(request: NextRequest) { try { await sendPrivateMessageTestResponse({ messageXml }); } catch (error) { - console.error("Error sending private message test response: ", error); + console.error('Error sending private message test response: ', error); } } diff --git a/app/api/montonio/verify-token/route.ts b/app/api/montonio/verify-token/route.ts index 6898ac6..541b486 100644 --- a/app/api/montonio/verify-token/route.ts +++ b/app/api/montonio/verify-token/route.ts @@ -1,4 +1,5 @@ import { NextResponse } from 'next/server'; + import jwt from 'jsonwebtoken'; import { z } from 'zod'; @@ -94,4 +95,4 @@ export const POST = enhanceRouteHandler( { auth: false, }, -); \ No newline at end of file +); diff --git a/app/api/order/medipost-test-response/route.ts b/app/api/order/medipost-test-response/route.ts index 5b7ac9a..2cca87e 100644 --- a/app/api/order/medipost-test-response/route.ts +++ b/app/api/order/medipost-test-response/route.ts @@ -1,10 +1,15 @@ -import { NextResponse } from "next/server"; -import { getAnalysisOrder } from "~/lib/services/order.service"; -import { composeOrderTestResponseXML, sendPrivateMessageTestResponse } from "~/lib/services/medipost/medipostTest.service"; -import { retrieveOrder } from "@lib/data"; -import { getAccountAdmin } from "~/lib/services/account.service"; -import { upsertMedipostActionLog } from "~/lib/services/medipost/medipostMessageBase.service"; -import { getOrderedAnalysisIds } from "~/lib/services/medusaOrder.service"; +import { NextResponse } from 'next/server'; + +import { retrieveOrder } from '@lib/data'; + +import { getAccountAdmin } from '~/lib/services/account.service'; +import { upsertMedipostActionLog } from '~/lib/services/medipost/medipostMessageBase.service'; +import { + composeOrderTestResponseXML, + sendPrivateMessageTestResponse, +} from '~/lib/services/medipost/medipostTest.service'; +import { getOrderedAnalysisIds } from '~/lib/services/medusaOrder.service'; +import { getAnalysisOrder } from '~/lib/services/order.service'; export async function POST(request: Request) { // const isDev = process.env.NODE_ENV === 'development'; @@ -14,13 +19,19 @@ export async function POST(request: Request) { const { medusaOrderId } = await request.json(); - const medusaOrder = await retrieveOrder(medusaOrderId) + const medusaOrder = await retrieveOrder(medusaOrderId); const analysisOrder = await getAnalysisOrder({ medusaOrderId }); - const account = await getAccountAdmin({ primaryOwnerUserId: analysisOrder.user_id }); - const orderedAnalysisElementsIds = await getOrderedAnalysisIds({ medusaOrder }); + const account = await getAccountAdmin({ + primaryOwnerUserId: analysisOrder.user_id, + }); + const orderedAnalysisElementsIds = await getOrderedAnalysisIds({ + medusaOrder, + }); - console.info(`Sending test response for order=${medusaOrderId} with ${orderedAnalysisElementsIds.length} ordered analysis elements`); + console.info( + `Sending test response for order=${medusaOrderId} with ${orderedAnalysisElementsIds.length} ordered analysis elements`, + ); const messageXml = await composeOrderTestResponseXML({ person: { idCode: account.personal_code!, @@ -28,8 +39,12 @@ export async function POST(request: Request) { lastName: account.last_name ?? '', phone: account.phone ?? '', }, - orderedAnalysisElementsIds: orderedAnalysisElementsIds.map(({ analysisElementId }) => analysisElementId).filter(Boolean) as number[], - orderedAnalysesIds: orderedAnalysisElementsIds.map(({ analysisId }) => analysisId).filter(Boolean) as number[], + orderedAnalysisElementsIds: orderedAnalysisElementsIds + .map(({ analysisElementId }) => analysisElementId) + .filter(Boolean) as number[], + orderedAnalysesIds: orderedAnalysisElementsIds + .map(({ analysisId }) => analysisId) + .filter(Boolean) as number[], orderId: analysisOrder.id, orderCreatedAt: new Date(analysisOrder.created_at), }); @@ -42,7 +57,7 @@ export async function POST(request: Request) { }); await sendPrivateMessageTestResponse({ messageXml }); } catch (error) { - console.error("Error sending private message test response: ", error); + console.error('Error sending private message test response: ', error); } return NextResponse.json({ success: true }); diff --git a/app/auth/callback/error/page.tsx b/app/auth/callback/error/page.tsx index 1d10580..bf6d608 100644 --- a/app/auth/callback/error/page.tsx +++ b/app/auth/callback/error/page.tsx @@ -3,15 +3,13 @@ import Link from 'next/link'; import type { AuthError } from '@supabase/supabase-js'; import { ResendAuthLinkForm } from '@kit/auth/resend-email-link'; +import { pathsConfig } from '@kit/shared/config'; import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert'; import { Button } from '@kit/ui/button'; import { Trans } from '@kit/ui/trans'; -import { pathsConfig } from '@kit/shared/config'; - import { withI18n } from '~/lib/i18n/with-i18n'; - interface AuthCallbackErrorPageProps { searchParams: Promise<{ error: string; diff --git a/app/auth/callback/layout.tsx b/app/auth/callback/layout.tsx index 1efc0a4..62c719c 100644 --- a/app/auth/callback/layout.tsx +++ b/app/auth/callback/layout.tsx @@ -1,5 +1,4 @@ import { AuthLayoutShell } from '@kit/auth/shared'; - import { AppLogo } from '@kit/shared/components/app-logo'; function AuthLayout({ children }: React.PropsWithChildren) { diff --git a/app/auth/callback/route.ts b/app/auth/callback/route.ts index b5ce0c0..a16e023 100644 --- a/app/auth/callback/route.ts +++ b/app/auth/callback/route.ts @@ -1,17 +1,20 @@ import { redirect } from 'next/navigation'; import type { NextRequest } from 'next/server'; -import { createAuthCallbackService, getErrorURLParameters } from '@kit/supabase/auth'; -import { getSupabaseServerClient } from '@kit/supabase/server-client'; +import { createAccountsApi } from '@/packages/features/accounts/src/server/api'; import { pathsConfig } from '@kit/shared/config'; -import { createAccountsApi } from '@/packages/features/accounts/src/server/api'; +import { + createAuthCallbackService, + getErrorURLParameters, +} from '@kit/supabase/auth'; +import { getSupabaseServerClient } from '@kit/supabase/server-client'; const ERROR_PATH = '/auth/callback/error'; const redirectOnError = (searchParams?: string) => { return redirect(`${ERROR_PATH}${searchParams ? `?${searchParams}` : ''}`); -} +}; export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url); @@ -44,19 +47,17 @@ export async function GET(request: NextRequest) { const service = createAuthCallbackService(getSupabaseServerClient()); const oauthResult = await service.exchangeCodeForSession(authCode); - if (!("isSuccess" in oauthResult)) { + if (!('isSuccess' in oauthResult)) { return redirectOnError(oauthResult.searchParams); } const api = createAccountsApi(getSupabaseServerClient()); - const account = await api.getPersonalAccountByUserId( - oauthResult.user.id, - ); + const account = await api.getPersonalAccountByUserId(oauthResult.user.id); if (!account.email || !account.name || !account.last_name) { return redirect(pathsConfig.auth.updateAccount); } - + return redirect(redirectPath); } diff --git a/app/auth/confirm/layout.tsx b/app/auth/confirm/layout.tsx index 1efc0a4..62c719c 100644 --- a/app/auth/confirm/layout.tsx +++ b/app/auth/confirm/layout.tsx @@ -1,5 +1,4 @@ import { AuthLayoutShell } from '@kit/auth/shared'; - import { AppLogo } from '@kit/shared/components/app-logo'; function AuthLayout({ children }: React.PropsWithChildren) { diff --git a/app/auth/confirm/route.ts b/app/auth/confirm/route.ts index 5586c79..73f72da 100644 --- a/app/auth/confirm/route.ts +++ b/app/auth/confirm/route.ts @@ -1,10 +1,9 @@ import { NextRequest, NextResponse } from 'next/server'; +import { pathsConfig } from '@kit/shared/config'; import { createAuthCallbackService } from '@kit/supabase/auth'; import { getSupabaseServerClient } from '@kit/supabase/server-client'; -import { pathsConfig } from '@kit/shared/config'; - export async function GET(request: NextRequest) { const service = createAuthCallbackService(getSupabaseServerClient()); diff --git a/app/auth/membership-confirmation/_components/membership-confirmation-notification.tsx b/app/auth/membership-confirmation/_components/membership-confirmation-notification.tsx index 4229e32..86b8079 100644 --- a/app/auth/membership-confirmation/_components/membership-confirmation-notification.tsx +++ b/app/auth/membership-confirmation/_components/membership-confirmation-notification.tsx @@ -2,11 +2,11 @@ import React from 'react'; -import { pathsConfig } from '@kit/shared/config'; import { useTranslation } from 'react-i18next'; import { usePersonalAccountData } from '@kit/accounts/hooks/use-personal-account-data'; import { SuccessNotification } from '@kit/notifications/components'; +import { pathsConfig } from '@kit/shared/config'; const MembershipConfirmationNotification: React.FC<{ userId: string; diff --git a/app/auth/membership-confirmation/layout.tsx b/app/auth/membership-confirmation/layout.tsx index c024555..e3d32c7 100644 --- a/app/auth/membership-confirmation/layout.tsx +++ b/app/auth/membership-confirmation/layout.tsx @@ -1,6 +1,5 @@ import { withI18n } from '~/lib/i18n/with-i18n'; - async function SiteLayout(props: React.PropsWithChildren) { return (
diff --git a/app/auth/password-reset/layout.tsx b/app/auth/password-reset/layout.tsx index 1efc0a4..62c719c 100644 --- a/app/auth/password-reset/layout.tsx +++ b/app/auth/password-reset/layout.tsx @@ -1,5 +1,4 @@ import { AuthLayoutShell } from '@kit/auth/shared'; - import { AppLogo } from '@kit/shared/components/app-logo'; function AuthLayout({ children }: React.PropsWithChildren) { diff --git a/app/auth/password-reset/page.tsx b/app/auth/password-reset/page.tsx index aaa1a5f..f025a94 100644 --- a/app/auth/password-reset/page.tsx +++ b/app/auth/password-reset/page.tsx @@ -1,16 +1,14 @@ import Link from 'next/link'; import { PasswordResetRequestContainer } from '@kit/auth/password-reset'; +import { pathsConfig } from '@kit/shared/config'; import { Button } from '@kit/ui/button'; import { Heading } from '@kit/ui/heading'; import { Trans } from '@kit/ui/trans'; -import { pathsConfig } from '@kit/shared/config'; - import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { withI18n } from '~/lib/i18n/with-i18n'; - export const generateMetadata = async () => { const { t } = await createI18nServerInstance(); diff --git a/app/auth/sign-in/components/SignInPageClientRedirect.tsx b/app/auth/sign-in/components/SignInPageClientRedirect.tsx index 2e79df4..60661f9 100644 --- a/app/auth/sign-in/components/SignInPageClientRedirect.tsx +++ b/app/auth/sign-in/components/SignInPageClientRedirect.tsx @@ -1,25 +1,26 @@ 'use client'; -import Loading from '@/app/home/loading'; import { useEffect } from 'react'; -import { getSupabaseBrowserClient } from '@/packages/supabase/src/clients/browser-client'; + import { useRouter } from 'next/navigation'; +import Loading from '@/app/home/loading'; +import { getSupabaseBrowserClient } from '@/packages/supabase/src/clients/browser-client'; + export function SignInPageClientRedirect() { const router = useRouter(); useEffect(() => { async function signIn() { - const { data, error } = await getSupabaseBrowserClient() - .auth - .signInWithOAuth({ + const { data, error } = + await getSupabaseBrowserClient().auth.signInWithOAuth({ provider: 'keycloak', options: { redirectTo: `${window.location.origin}/auth/callback`, queryParams: { prompt: 'login', }, - } + }, }); if (error) { diff --git a/app/auth/sign-in/layout.tsx b/app/auth/sign-in/layout.tsx index 1efc0a4..62c719c 100644 --- a/app/auth/sign-in/layout.tsx +++ b/app/auth/sign-in/layout.tsx @@ -1,5 +1,4 @@ import { AuthLayoutShell } from '@kit/auth/shared'; - import { AppLogo } from '@kit/shared/components/app-logo'; function AuthLayout({ children }: React.PropsWithChildren) { diff --git a/app/auth/sign-in/page.tsx b/app/auth/sign-in/page.tsx index 4799f7d..d0fcfd7 100644 --- a/app/auth/sign-in/page.tsx +++ b/app/auth/sign-in/page.tsx @@ -2,8 +2,9 @@ import { getServerAuthConfig, pathsConfig } from '@kit/shared/config'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { withI18n } from '~/lib/i18n/with-i18n'; -import { SignInPageClientRedirect } from './components/SignInPageClientRedirect'; + import PasswordOption from './components/PasswordOption'; +import { SignInPageClientRedirect } from './components/SignInPageClientRedirect'; interface SignInPageProps { searchParams: Promise<{ diff --git a/app/auth/sign-up/layout.tsx b/app/auth/sign-up/layout.tsx index 1efc0a4..62c719c 100644 --- a/app/auth/sign-up/layout.tsx +++ b/app/auth/sign-up/layout.tsx @@ -1,5 +1,4 @@ import { AuthLayoutShell } from '@kit/auth/shared'; - import { AppLogo } from '@kit/shared/components/app-logo'; function AuthLayout({ children }: React.PropsWithChildren) { diff --git a/app/auth/sign-up/page.tsx b/app/auth/sign-up/page.tsx index cdee3a5..0611b78 100644 --- a/app/auth/sign-up/page.tsx +++ b/app/auth/sign-up/page.tsx @@ -8,7 +8,6 @@ import { Heading } from '@kit/ui/heading'; import { Trans } from '@kit/ui/trans'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; - import { withI18n } from '~/lib/i18n/with-i18n'; export const generateMetadata = async () => { diff --git a/app/auth/update-account/_lib/schemas/update-account.schema.ts b/app/auth/update-account/_lib/schemas/update-account.schema.ts index bba388c..8123ec4 100644 --- a/app/auth/update-account/_lib/schemas/update-account.schema.ts +++ b/app/auth/update-account/_lib/schemas/update-account.schema.ts @@ -1,6 +1,6 @@ -import { z } from 'zod'; import Isikukood from 'isikukood'; import parsePhoneNumber from 'libphonenumber-js/min'; +import { z } from 'zod'; const updateAccountSchema = { firstName: z @@ -39,14 +39,18 @@ const updateAccountSchema = { (phone) => { try { const phoneNumber = parsePhoneNumber(phone); - return !!phoneNumber && phoneNumber.isValid() && phoneNumber.country === 'EE'; + return ( + !!phoneNumber && + phoneNumber.isValid() && + phoneNumber.country === 'EE' + ); } catch { return false; } }, { message: 'common:formFieldError.invalidPhoneNumber', - } + }, ), city: z.string().optional(), weight: z @@ -81,22 +85,27 @@ export const UpdateAccountSchemaServer = z.object({ height: updateAccountSchema.height.nullable(), userConsent: updateAccountSchema.userConsent, }); -export const UpdateAccountSchemaClient = ({ isEmailUser }: { isEmailUser: boolean }) => z.object({ - firstName: updateAccountSchema.firstName, - lastName: updateAccountSchema.lastName, - personalCode: updateAccountSchema.personalCode, - email: updateAccountSchema.email, - phone: updateAccountSchema.phone, - ...(isEmailUser - ? { - city: z.string().optional(), - weight: z.number().optional(), - height: z.number().optional(), - } - : { - city: updateAccountSchema.city, - weight: updateAccountSchema.weight, - height: updateAccountSchema.height, - }), - userConsent: updateAccountSchema.userConsent, -}); +export const UpdateAccountSchemaClient = ({ + isEmailUser, +}: { + isEmailUser: boolean; +}) => + z.object({ + firstName: updateAccountSchema.firstName, + lastName: updateAccountSchema.lastName, + personalCode: updateAccountSchema.personalCode, + email: updateAccountSchema.email, + phone: updateAccountSchema.phone, + ...(isEmailUser + ? { + city: z.string().optional(), + weight: z.number().optional(), + height: z.number().optional(), + } + : { + city: updateAccountSchema.city, + weight: updateAccountSchema.weight, + height: updateAccountSchema.height, + }), + userConsent: updateAccountSchema.userConsent, + }); diff --git a/app/auth/update-account/_lib/server/update-account.ts b/app/auth/update-account/_lib/server/update-account.ts index 07e415b..8bca7bb 100644 --- a/app/auth/update-account/_lib/server/update-account.ts +++ b/app/auth/update-account/_lib/server/update-account.ts @@ -4,9 +4,8 @@ import { updateCustomer } from '@lib/data/customer'; import { AccountSubmitData, createAuthApi } from '@kit/auth/api'; import { enhanceAction } from '@kit/next/actions'; -import { getSupabaseServerClient } from '@kit/supabase/server-client'; - import { pathsConfig } from '@kit/shared/config'; +import { getSupabaseServerClient } from '@kit/supabase/server-client'; import { UpdateAccountSchemaServer } from '../schemas/update-account.schema'; @@ -32,14 +31,14 @@ export const onUpdateAccount = enhanceAction( phone: params.phone, }); } catch (e) { - console.error("Failed to update Medusa customer", e); + console.error('Failed to update Medusa customer', e); } const hasUnseenMembershipConfirmation = await api.hasUnseenMembershipConfirmation(); return { hasUnseenMembershipConfirmation, - } + }; }, { schema: UpdateAccountSchemaServer, diff --git a/app/auth/update-account/layout.tsx b/app/auth/update-account/layout.tsx index d9687a8..8212f3c 100644 --- a/app/auth/update-account/layout.tsx +++ b/app/auth/update-account/layout.tsx @@ -1,6 +1,5 @@ import { withI18n } from '~/lib/i18n/with-i18n'; - async function SiteLayout(props: React.PropsWithChildren) { return (
diff --git a/app/auth/verify/layout.tsx b/app/auth/verify/layout.tsx index 1efc0a4..62c719c 100644 --- a/app/auth/verify/layout.tsx +++ b/app/auth/verify/layout.tsx @@ -1,5 +1,4 @@ import { AuthLayoutShell } from '@kit/auth/shared'; - import { AppLogo } from '@kit/shared/components/app-logo'; function AuthLayout({ children }: React.PropsWithChildren) { diff --git a/app/auth/verify/page.tsx b/app/auth/verify/page.tsx index abc9203..677c020 100644 --- a/app/auth/verify/page.tsx +++ b/app/auth/verify/page.tsx @@ -1,11 +1,10 @@ import { redirect } from 'next/navigation'; import { MultiFactorChallengeContainer } from '@kit/auth/mfa'; +import { pathsConfig } from '@kit/shared/config'; import { checkRequiresMultiFactorAuthentication } from '@kit/supabase/check-requires-mfa'; import { getSupabaseServerClient } from '@kit/supabase/server-client'; -import { pathsConfig } from '@kit/shared/config'; - import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { withI18n } from '~/lib/i18n/with-i18n'; @@ -41,7 +40,8 @@ async function VerifyPage(props: Props) { } const nextPath = (await props.searchParams).next; - const redirectPath = !!nextPath && nextPath.length > 0 ? nextPath : pathsConfig.app.home; + const redirectPath = + !!nextPath && nextPath.length > 0 ? nextPath : pathsConfig.app.home; return ( {endIcon ||
} - ) : (isCancelled ? null : ( + ) : isCancelled ? null : ( <>
@@ -140,7 +140,7 @@ const AnalysisDoctor = ({
- ))} + )}
); diff --git a/app/doctor/_components/analysis-level-bar.tsx b/app/doctor/_components/analysis-level-bar.tsx index e9080db..ace79d1 100644 --- a/app/doctor/_components/analysis-level-bar.tsx +++ b/app/doctor/_components/analysis-level-bar.tsx @@ -3,6 +3,7 @@ import { useMemo } from 'react'; import { ArrowDown } from 'lucide-react'; import { cn } from '@kit/ui/utils'; + import { AnalysisResultForDisplay } from './analysis-doctor'; export enum AnalysisResultLevel { @@ -48,7 +49,7 @@ const Level = ({ export const AnalysisLevelBarSkeleton = () => { return ( -
+
); @@ -65,44 +66,46 @@ const AnalysisLevelBar = ({ level: AnalysisResultLevel; results: AnalysisResultForDisplay; }) => { - - const { norm_lower: lower, norm_upper: upper, response_value: value } = results; + const { + norm_lower: lower, + norm_upper: upper, + response_value: value, + } = results; const arrowLocation = useMemo(() => { if (value < lower!) { return 0; } - + if (normLowerIncluded || normUpperIncluded) { return 50; } const calculated = ((value - lower!) / (upper! - lower!)) * 100; - + if (calculated > 100) { return 100; } - + return calculated; }, [value, upper, lower]); - const [isVeryLow, isLow, isHigh, isVeryHigh] = useMemo(() => [ - level === AnalysisResultLevel.VERY_LOW, - level === AnalysisResultLevel.LOW, - level === AnalysisResultLevel.HIGH, - level === AnalysisResultLevel.VERY_HIGH, - ], [level, value, upper, lower]); + const [isVeryLow, isLow, isHigh, isVeryHigh] = useMemo( + () => [ + level === AnalysisResultLevel.VERY_LOW, + level === AnalysisResultLevel.LOW, + level === AnalysisResultLevel.HIGH, + level === AnalysisResultLevel.VERY_HIGH, + ], + [level, value, upper, lower], + ); const hasAbnormalLevel = isVeryLow || isLow || isHigh || isVeryHigh; return ( -
+
{normLowerIncluded && ( <> - + )} @@ -110,21 +113,16 @@ const AnalysisLevelBar = ({ {normUpperIncluded && ( <> - - + + )}
diff --git a/app/doctor/_components/analysis-view.tsx b/app/doctor/_components/analysis-view.tsx index b22f8d4..cfb8ecb 100644 --- a/app/doctor/_components/analysis-view.tsx +++ b/app/doctor/_components/analysis-view.tsx @@ -23,9 +23,7 @@ import { doctorAnalysisFeedbackFormSchema, } from '@kit/doctor/schema/doctor-analysis.schema'; import ConfirmationModal from '@kit/shared/components/confirmation-modal'; -import { - useCurrentLocaleLanguageNames -} from '@kit/shared/hooks'; +import { useCurrentLocaleLanguageNames } from '@kit/shared/hooks'; import { getFullName } from '@kit/shared/utils'; import { useUser } from '@kit/supabase/hooks/use-user'; import { Button } from '@kit/ui/button'; diff --git a/app/doctor/_components/doctor-dashboard.tsx b/app/doctor/_components/doctor-dashboard.tsx index 0ff9df2..4f265c2 100644 --- a/app/doctor/_components/doctor-dashboard.tsx +++ b/app/doctor/_components/doctor-dashboard.tsx @@ -6,6 +6,7 @@ import { getUserDoneResponsesAction, getUserInProgressResponsesAction, } from '@kit/doctor/actions/table-data-fetching-actions'; + import ResultsTableWrapper from './results-table-wrapper'; export default function Dashboard() { diff --git a/app/doctor/_components/doctor-guard.tsx b/app/doctor/_components/doctor-guard.tsx index c52a139..e764bc0 100644 --- a/app/doctor/_components/doctor-guard.tsx +++ b/app/doctor/_components/doctor-guard.tsx @@ -1,8 +1,7 @@ import { notFound } from 'next/navigation'; -import { getSupabaseServerClient } from '@kit/supabase/server-client'; import { isDoctor } from '@kit/doctor/lib/server/utils/is-doctor'; - +import { getSupabaseServerClient } from '@kit/supabase/server-client'; type LayoutOrPageComponent = React.ComponentType; diff --git a/app/doctor/_components/results-table.tsx b/app/doctor/_components/results-table.tsx index cc253c1..c9b5505 100644 --- a/app/doctor/_components/results-table.tsx +++ b/app/doctor/_components/results-table.tsx @@ -5,6 +5,7 @@ import { useTransition } from 'react'; import Link from 'next/link'; import { format } from 'date-fns'; +import { capitalize } from 'lodash'; import { Eye } from 'lucide-react'; import { getResultSetName } from '@kit/doctor/lib/helpers'; @@ -26,7 +27,6 @@ import { import { Trans } from '@kit/ui/trans'; import DoctorJobSelect from './doctor-job-select'; -import { capitalize } from 'lodash'; export default function ResultsTable({ results = [], @@ -189,7 +189,9 @@ export default function ResultsTable({ {capitalize( - languageNames.of(result?.patient?.preferred_locale ?? 'et'), + languageNames.of( + result?.patient?.preferred_locale ?? 'et', + ), )} diff --git a/app/doctor/analysis/[id]/page.tsx b/app/doctor/analysis/[id]/page.tsx index b6b55f7..ad7b311 100644 --- a/app/doctor/analysis/[id]/page.tsx +++ b/app/doctor/analysis/[id]/page.tsx @@ -50,5 +50,3 @@ async function AnalysisPage({ export default DoctorGuard(AnalysisPage); const loadResult = cache(getAnalysisResultsForDoctor); - - diff --git a/app/doctor/layout.tsx b/app/doctor/layout.tsx index 5210ec3..c946d0c 100644 --- a/app/doctor/layout.tsx +++ b/app/doctor/layout.tsx @@ -5,7 +5,6 @@ import { cookies } from 'next/headers'; import { Page, PageMobileNavigation, PageNavigation } from '@kit/ui/page'; import { SidebarProvider } from '@kit/ui/shadcn-sidebar'; - import { loadUserWorkspace } from '../home/(user)/_lib/server/load-user-workspace'; import { DoctorSidebar } from './_components/doctor-sidebar'; import { DoctorMobileNavigation } from './_components/mobile-navigation'; diff --git a/app/global-error.tsx b/app/global-error.tsx index 97e601e..5c1d747 100644 --- a/app/global-error.tsx +++ b/app/global-error.tsx @@ -5,12 +5,12 @@ import Link from 'next/link'; import { ArrowLeft, MessageCircle } from 'lucide-react'; import { useCaptureException } from '@kit/monitoring/hooks'; +import { RootProviders } from '@kit/shared/components/root-providers'; import { Button } from '@kit/ui/button'; import { Heading } from '@kit/ui/heading'; import { Trans } from '@kit/ui/trans'; import { SiteHeader } from '~/(marketing)/_components/site-header'; -import { RootProviders } from '@kit/shared/components/root-providers'; const GlobalErrorPage = ({ error, diff --git a/app/home/(user)/(dashboard)/analysis-results/[id]/page.tsx b/app/home/(user)/(dashboard)/analysis-results/[id]/page.tsx index fa70adf..b18a4da 100644 --- a/app/home/(user)/(dashboard)/analysis-results/[id]/page.tsx +++ b/app/home/(user)/(dashboard)/analysis-results/[id]/page.tsx @@ -1,4 +1,5 @@ import React from 'react'; + import Link from 'next/link'; import { redirect } from 'next/navigation'; @@ -32,7 +33,7 @@ export default async function AnalysisResultsPage({ ]); if (!account?.id) { - return redirect("/"); + return redirect('/'); } await createPageViewLog({ @@ -47,27 +48,31 @@ export default async function AnalysisResultsPage({ title={} description={} /> - - + ); } const orderedAnalysisElements = analysisResponse.orderedAnalysisElements; const hasOrderedAnalysisElements = orderedAnalysisElements.length > 0; - const isPartialStatus = analysisResponse.order.status === 'PARTIAL_ANALYSIS_RESPONSE'; + const isPartialStatus = + analysisResponse.order.status === 'PARTIAL_ANALYSIS_RESPONSE'; return ( <> } - description={hasOrderedAnalysisElements ? ( - isPartialStatus - ? - : - ) : ( - - )} + description={ + hasOrderedAnalysisElements ? ( + isPartialStatus ? ( + + ) : ( + + ) + ) : ( + + ) + } >
{promotions.length > 0 && ( -
-
+
+

@@ -111,32 +118,32 @@ export default function DiscountCode({ cart }: { return (
- + {promotion.code} - {" "} + {' '} ( {promotion.application_method?.value !== undefined && promotion.application_method.currency_code !== - undefined && ( + undefined && ( <> - {promotion.application_method.type === - "percentage" + {promotion.application_method.type === 'percentage' ? `${promotion.application_method.value}%` : convertToLocale({ - amount: Number(promotion.application_method.value), - currency_code: - promotion.application_method - .currency_code, - })} + amount: Number( + promotion.application_method.value, + ), + currency_code: + promotion.application_method.currency_code, + })} )} ) @@ -152,10 +159,10 @@ export default function DiscountCode({ cart }: { className="flex items-center" onClick={() => { if (!promotion.code) { - return + return; } - removePromotionCode(promotion.code) + removePromotionCode(promotion.code); }} data-testid="remove-discount-button" > @@ -166,11 +173,11 @@ export default function DiscountCode({ cart }: { )}
- ) + ); })}
)}
- ) + ); } diff --git a/app/home/(user)/_components/cart/index.tsx b/app/home/(user)/_components/cart/index.tsx index 09064bd..7887040 100644 --- a/app/home/(user)/_components/cart/index.tsx +++ b/app/home/(user)/_components/cart/index.tsx @@ -1,22 +1,21 @@ -"use client"; +'use client'; + +import { useState } from 'react'; + +import { handleNavigateToPayment } from '@/lib/services/medusaCart.service'; +import { formatCurrency } from '@/packages/shared/src/utils'; +import { initiatePaymentSession } from '@lib/data/cart'; +import { StoreCart, StoreCartLineItem } from '@medusajs/types'; +import { Loader2 } from 'lucide-react'; +import { useTranslation } from 'react-i18next'; -import { useState } from "react"; -import { Loader2 } from "lucide-react"; -import { StoreCart, StoreCartLineItem } from "@medusajs/types" -import CartItems from "./cart-items" -import { Trans } from '@kit/ui/trans'; import { Button } from '@kit/ui/button'; -import { - Card, - CardContent, - CardHeader, -} from '@kit/ui/card'; -import DiscountCode from "./discount-code"; -import { initiatePaymentSession } from "@lib/data/cart"; -import { formatCurrency } from "@/packages/shared/src/utils"; -import { useTranslation } from "react-i18next"; -import { handleNavigateToPayment } from "@/lib/services/medusaCart.service"; -import AnalysisLocation from "./analysis-location"; +import { Card, CardContent, CardHeader } from '@kit/ui/card'; +import { Trans } from '@kit/ui/trans'; + +import AnalysisLocation from './analysis-location'; +import CartItems from './cart-items'; +import DiscountCode from './discount-code'; const IS_DISCOUNT_SHOWN = true as boolean; @@ -25,11 +24,13 @@ export default function Cart({ synlabAnalyses, ttoServiceItems, }: { - cart: StoreCart | null + cart: StoreCart | null; synlabAnalyses: StoreCartLineItem[]; ttoServiceItems: StoreCartLineItem[]; }) { - const { i18n: { language } } = useTranslation(); + const { + i18n: { language }, + } = useTranslation(); const [isInitiatingSession, setIsInitiatingSession] = useState(false); @@ -39,7 +40,10 @@ export default function Cart({ return (
-
+

@@ -71,21 +75,29 @@ export default function Cart({ const isLocationsShown = synlabAnalyses.length > 0; return ( -
-
- - +
+
+ +
{hasCartItems && ( <> -
-
-

+

+
+

-

+

{formatCurrency({ value: cart.subtotal, currencyCode: cart.currency_code, @@ -94,14 +106,14 @@ export default function Cart({

-
-
-

+

+
+

-

+

{formatCurrency({ value: cart.discount_total, currencyCode: cart.currency_code, @@ -110,14 +122,14 @@ export default function Cart({

-
-
-

+

+
+

-

+

{formatCurrency({ value: cart.total, currencyCode: cart.currency_code, @@ -129,11 +141,9 @@ export default function Cart({ )} -

+
{IS_DISCOUNT_SHOWN && ( - +
@@ -146,24 +156,31 @@ export default function Cart({ )} {isLocationsShown && ( - +
- +
)}
-
diff --git a/app/home/(user)/_components/cart/partner-locations.json b/app/home/(user)/_components/cart/partner-locations.json index 1266f0c..147059b 100644 --- a/app/home/(user)/_components/cart/partner-locations.json +++ b/app/home/(user)/_components/cart/partner-locations.json @@ -119,4 +119,4 @@ "hours": "Verevõtt tööpäeviti 8.00-12.00", "city": "Otepää" } -] \ No newline at end of file +] diff --git a/app/home/(user)/_components/cart/types.ts b/app/home/(user)/_components/cart/types.ts index 22385ce..9150557 100644 --- a/app/home/(user)/_components/cart/types.ts +++ b/app/home/(user)/_components/cart/types.ts @@ -4,12 +4,12 @@ export interface MontonioOrderToken { merchantReference: string; merchantReferenceDisplay: string; paymentStatus: - | 'PAID' - | 'FAILED' - | 'CANCELLED' - | 'PENDING' - | 'EXPIRED' - | 'REFUNDED'; + | 'PAID' + | 'FAILED' + | 'CANCELLED' + | 'PENDING' + | 'EXPIRED' + | 'REFUNDED'; paymentMethod: string; grandTotal: number; currency: string; @@ -19,4 +19,4 @@ export interface MontonioOrderToken { paymentLinkUuid: string; iat: number; exp: number; -} \ No newline at end of file +} diff --git a/app/home/(user)/_components/compare-packages-modal.tsx b/app/home/(user)/_components/compare-packages-modal.tsx index eadfd88..06797b4 100644 --- a/app/home/(user)/_components/compare-packages-modal.tsx +++ b/app/home/(user)/_components/compare-packages-modal.tsx @@ -1,9 +1,13 @@ import { JSX } from 'react'; +import { StoreProduct } from '@medusajs/types'; import { QuestionMarkCircledIcon } from '@radix-ui/react-icons'; import { VisuallyHidden } from '@radix-ui/react-visually-hidden'; import { Check, X } from 'lucide-react'; +import { PackageHeader } from '@kit/shared/components/package-header'; +import { AnalysisPackageWithVariant } from '@kit/shared/components/select-analysis-package'; +import { InfoTooltip } from '@kit/shared/components/ui/info-tooltip'; import { Dialog, DialogContent, @@ -18,14 +22,14 @@ import { TableHeader, TableRow, } from '@kit/ui/table'; + import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; -import { PackageHeader } from '@kit/shared/components/package-header'; -import { InfoTooltip } from '@kit/shared/components/ui/info-tooltip'; -import { StoreProduct } from '@medusajs/types'; -import { AnalysisPackageWithVariant } from '@kit/shared/components/select-analysis-package'; import { withI18n } from '~/lib/i18n/with-i18n'; -export type AnalysisPackageElement = Pick & { +export type AnalysisPackageElement = Pick< + StoreProduct, + 'title' | 'id' | 'description' +> & { isIncludedInStandard: boolean; isIncludedInStandardPlus: boolean; isIncludedInPremium: boolean; @@ -39,7 +43,11 @@ const CheckWithBackground = () => { ); }; -const PackageTableHead = async ({ product }: { product: AnalysisPackageWithVariant }) => { +const PackageTableHead = async ({ + product, +}: { + product: AnalysisPackageWithVariant; +}) => { const { t, language } = await createI18nServerInstance(); const { title, price, nrOfAnalyses } = product; @@ -48,14 +56,14 @@ const PackageTableHead = async ({ product }: { product: AnalysisPackageWithVaria - ) -} + ); +}; const ComparePackagesModal = async ({ analysisPackages, @@ -69,7 +77,9 @@ const ComparePackagesModal = async ({ const { t } = await createI18nServerInstance(); const standardPackage = analysisPackages.find(({ isStandard }) => isStandard); - const standardPlusPackage = analysisPackages.find(({ isStandardPlus }) => isStandardPlus); + const standardPlusPackage = analysisPackages.find( + ({ isStandardPlus }) => isStandardPlus, + ); const premiumPackage = analysisPackages.find(({ isPremium }) => isPremium); if (!standardPackage || !standardPlusPackage || !premiumPackage) { @@ -100,7 +110,7 @@ const ComparePackagesModal = async ({

{t('product:healthPackageComparison.description')}

-
+
@@ -112,16 +122,14 @@ const ComparePackagesModal = async ({ {analysisPackageElements.map( - ( - { - title, - id, - description, - isIncludedInStandard, - isIncludedInStandardPlus, - isIncludedInPremium, - }, - ) => { + ({ + title, + id, + description, + isIncludedInStandard, + isIncludedInStandardPlus, + isIncludedInPremium, + }) => { if (!title) { return null; } @@ -130,20 +138,28 @@ const ComparePackagesModal = async ({ {title}{' '} - {description && (} />)} + {description && ( + } + /> + )} {isIncludedInStandard && } - {isIncludedInStandardPlus && } + {isIncludedInStandardPlus && ( + + )} {isIncludedInPremium && } ); - })} + }, + )}
diff --git a/app/home/(user)/_components/dashboard-cards.tsx b/app/home/(user)/_components/dashboard-cards.tsx index 3127331..686afe9 100644 --- a/app/home/(user)/_components/dashboard-cards.tsx +++ b/app/home/(user)/_components/dashboard-cards.tsx @@ -11,7 +11,7 @@ export default function DashboardCards() {
{ @@ -57,80 +58,78 @@ const cards = ({ bmiStatus: BmiCategory | null; smoking?: boolean | null; }) => [ - { - title: 'dashboard:gender', - description: gender ?? '-', - icon: , - iconBg: 'bg-success', - }, - { - title: 'dashboard:age', - description: age ? `${age}` : '-', - icon: , - iconBg: 'bg-success', - }, - { - title: 'dashboard:height', - description: height ? `${height}cm` : '-', - icon: , - iconBg: 'bg-success', - }, - { - title: 'dashboard:weight', - description: weight ? `${weight}kg` : '-', - icon: , - iconBg: 'bg-success', - }, - { - title: 'dashboard:bmi', - description: bmiFromMetric(weight || 0, height || 0)?.toString() ?? '-', - icon: , - iconBg: getBmiBackgroundColor(bmiStatus), - }, - { - title: 'dashboard:bloodPressure', - description: '-', - icon: , - iconBg: 'bg-warning', - }, - { - title: 'dashboard:cholesterol', - description: '-', - icon: , - iconBg: 'bg-destructive', - }, - { - title: 'dashboard:ldlCholesterol', - description: '-', - icon: , - iconBg: 'bg-warning', - }, - // { - // title: 'Score 2', - // description: 'Normis', - // icon: , - // iconBg: 'bg-success', - // }, - { - title: 'dashboard:smoking', - description: - isNil(smoking) - ? 'dashboard:respondToQuestion' - : !!smoking - ? 'common:yes' - : 'common:no', - descriptionColor: 'text-primary', - icon: - isNil(smoking) ? ( - - - - ) : null, - cardVariant: getCardVariant(isNil(smoking) ? null : !smoking), - }, - ]; + { + title: 'dashboard:gender', + description: gender ?? '-', + icon: , + iconBg: 'bg-success', + }, + { + title: 'dashboard:age', + description: age ? `${age}` : '-', + icon: , + iconBg: 'bg-success', + }, + { + title: 'dashboard:height', + description: height ? `${height}cm` : '-', + icon: , + iconBg: 'bg-success', + }, + { + title: 'dashboard:weight', + description: weight ? `${weight}kg` : '-', + icon: , + iconBg: 'bg-success', + }, + { + title: 'dashboard:bmi', + description: bmiFromMetric(weight || 0, height || 0)?.toString() ?? '-', + icon: , + iconBg: getBmiBackgroundColor(bmiStatus), + }, + { + title: 'dashboard:bloodPressure', + description: '-', + icon: , + iconBg: 'bg-warning', + }, + { + title: 'dashboard:cholesterol', + description: '-', + icon: , + iconBg: 'bg-destructive', + }, + { + title: 'dashboard:ldlCholesterol', + description: '-', + icon: , + iconBg: 'bg-warning', + }, + // { + // title: 'Score 2', + // description: 'Normis', + // icon: , + // iconBg: 'bg-success', + // }, + { + title: 'dashboard:smoking', + description: isNil(smoking) + ? 'dashboard:respondToQuestion' + : smoking + ? 'common:yes' + : 'common:no', + descriptionColor: 'text-primary', + icon: isNil(smoking) ? ( + + + + ) : null, + cardVariant: getCardVariant(isNil(smoking) ? null : !smoking), + }, +]; const IS_SHOWN_RECOMMENDATIONS = false as boolean; @@ -146,13 +145,15 @@ export default function Dashboard({ }) { const height = account.accountParams?.height || 0; const weight = account.accountParams?.weight || 0; - + let age: number = 0; let gender: { label: string; value: string } | null = null; try { - ({ age = 0, gender } = PersonalCode.parsePersonalCode(account.personal_code!)); + ({ age = 0, gender } = PersonalCode.parsePersonalCode( + account.personal_code!, + )); } catch (e) { - console.error("Failed to parse personal code", e); + console.error('Failed to parse personal code', e); } const bmiStatus = getBmiStatus(bmiThresholds, { age, height, weight }); diff --git a/app/home/(user)/_components/home-account-selector.tsx b/app/home/(user)/_components/home-account-selector.tsx index 5ea17c6..813e45c 100644 --- a/app/home/(user)/_components/home-account-selector.tsx +++ b/app/home/(user)/_components/home-account-selector.tsx @@ -5,11 +5,9 @@ import { useContext } from 'react'; import { useRouter } from 'next/navigation'; import { AccountSelector } from '@kit/accounts/account-selector'; +import { featureFlagsConfig, pathsConfig } from '@kit/shared/config'; import { SidebarContext } from '@kit/ui/shadcn-sidebar'; -import { pathsConfig, featureFlagsConfig } from '@kit/shared/config'; - - const features = { enableTeamCreation: featureFlagsConfig.enableTeamCreation, }; diff --git a/app/home/(user)/_components/home-page-header.tsx b/app/home/(user)/_components/home-page-header.tsx index da64f7f..8beb78f 100644 --- a/app/home/(user)/_components/home-page-header.tsx +++ b/app/home/(user)/_components/home-page-header.tsx @@ -7,6 +7,8 @@ export function HomeLayoutPageHeader( }>, ) { return ( - {props.children} + + {props.children} + ); } diff --git a/app/home/(user)/_components/order-analyses-cards.tsx b/app/home/(user)/_components/order-analyses-cards.tsx index bd7f8a7..8d6a04d 100644 --- a/app/home/(user)/_components/order-analyses-cards.tsx +++ b/app/home/(user)/_components/order-analyses-cards.tsx @@ -1,25 +1,23 @@ -"use client"; +'use client'; +import { useState } from 'react'; + +import { formatCurrency } from '@/packages/shared/src/utils'; +import { StoreProduct } from '@medusajs/types'; import { HeartPulse, Loader2, ShoppingCart } from 'lucide-react'; import { useTranslation } from 'react-i18next'; -import { Button } from '@kit/ui/button'; -import { - Card, - CardHeader, - CardFooter, - CardDescription, -} from '@kit/ui/card'; -import { StoreProduct } from '@medusajs/types'; -import { useState } from 'react'; -import { handleAddToCart } from '~/lib/services/medusaCart.service'; import { InfoTooltip } from '@kit/shared/components/ui/info-tooltip'; -import { Trans } from '@kit/ui/trans'; +import { Button } from '@kit/ui/button'; +import { Card, CardDescription, CardFooter, CardHeader } from '@kit/ui/card'; import { toast } from '@kit/ui/sonner'; -import { formatCurrency } from '@/packages/shared/src/utils'; +import { Trans } from '@kit/ui/trans'; + +import { handleAddToCart } from '~/lib/services/medusaCart.service'; export type OrderAnalysisCard = Pick< - StoreProduct, 'title' | 'description' | 'subtitle' + StoreProduct, + 'title' | 'description' | 'subtitle' > & { variant: { id: string }; price: number | null; @@ -32,10 +30,13 @@ export default function OrderAnalysesCards({ analyses: OrderAnalysisCard[]; countryCode: string; }) { + const { + i18n: { language }, + } = useTranslation(); - const { i18n: { language } } = useTranslation() - - const [variantAddingToCart, setVariantAddingToCart] = useState(null); + const [variantAddingToCart, setVariantAddingToCart] = useState( + null, + ); const handleSelect = async (variantId: string) => { if (variantAddingToCart) { return null; @@ -54,24 +55,19 @@ export default function OrderAnalysesCards({ setVariantAddingToCart(null); console.error(e); } - } + }; return ( -
- {analyses.map(({ - title, - variant, - description, - subtitle, - price, - }) => { - const formattedPrice = typeof price === 'number' - ? formatCurrency({ - currencyCode: 'eur', - locale: language, - value: price, - }) - : null; +
+ {analyses.map(({ title, variant, description, subtitle, price }) => { + const formattedPrice = + typeof price === 'number' + ? formatCurrency({ + currencyCode: 'eur', + locale: language, + value: price, + }) + : null; return (
-
+
-
+
{title} {description && ( @@ -104,7 +106,7 @@ export default function OrderAnalysesCards({ {' '} +
{formattedPrice} {description}
@@ -113,11 +115,7 @@ export default function OrderAnalysesCards({ )}
- {subtitle && ( - - {subtitle} - - )} + {subtitle && {subtitle}}
{formattedPrice} diff --git a/app/home/(user)/_components/order/cart-totals.tsx b/app/home/(user)/_components/order/cart-totals.tsx index fb7b030..bc59e8f 100644 --- a/app/home/(user)/_components/order/cart-totals.tsx +++ b/app/home/(user)/_components/order/cart-totals.tsx @@ -1,15 +1,21 @@ -"use client" +'use client'; + +import React from 'react'; + +import { formatCurrency } from '@/packages/shared/src/utils'; +import { StoreOrder } from '@medusajs/types'; +import { useTranslation } from 'react-i18next'; -import { formatCurrency } from "@/packages/shared/src/utils" -import { StoreOrder } from "@medusajs/types" -import React from "react" -import { useTranslation } from "react-i18next" import { Trans } from '@kit/ui/trans'; -export default function CartTotals({ medusaOrder }: { - medusaOrder: StoreOrder +export default function CartTotals({ + medusaOrder, +}: { + medusaOrder: StoreOrder; }) { - const { i18n: { language } } = useTranslation() + const { + i18n: { language }, + } = useTranslation(); const { currency_code, total, @@ -17,29 +23,39 @@ export default function CartTotals({ medusaOrder }: { tax_total, discount_total, gift_card_total, - } = medusaOrder + } = medusaOrder; return (
-
+
- + - {formatCurrency({ value: subtotal ?? 0, currencyCode: currency_code, locale: language })} + {formatCurrency({ + value: subtotal ?? 0, + currencyCode: currency_code, + locale: language, + })}
{!!discount_total && (
- + + + - -{" "} - {formatCurrency({ value: discount_total ?? 0, currencyCode: currency_code, locale: language })} + -{' '} + {formatCurrency({ + value: discount_total ?? 0, + currencyCode: currency_code, + locale: language, + })}
)} @@ -53,30 +69,42 @@ export default function CartTotals({ medusaOrder }: {
*/} {!!gift_card_total && (
- + + + - -{" "} - {formatCurrency({ value: gift_card_total ?? 0, currencyCode: currency_code, locale: language })} + -{' '} + {formatCurrency({ + value: gift_card_total ?? 0, + currencyCode: currency_code, + locale: language, + })}
)}
-
-
- +
+
+ + + - {formatCurrency({ value: total ?? 0, currencyCode: currency_code, locale: language })} + {formatCurrency({ + value: total ?? 0, + currencyCode: currency_code, + locale: language, + })}
-
+
- ) + ); } diff --git a/app/home/(user)/_components/order/order-details.tsx b/app/home/(user)/_components/order/order-details.tsx index e10f3bc..1cda501 100644 --- a/app/home/(user)/_components/order/order-details.tsx +++ b/app/home/(user)/_components/order/order-details.tsx @@ -1,29 +1,25 @@ -import { Trans } from '@kit/ui/trans'; import { formatDate } from 'date-fns'; -import type { AnalysisOrder } from "~/lib/types/analysis-order"; -export default function OrderDetails({ order }: { - order: AnalysisOrder -}) { +import { Trans } from '@kit/ui/trans'; + +import type { AnalysisOrder } from '~/lib/types/analysis-order'; + +export default function OrderDetails({ order }: { order: AnalysisOrder }) { return (
- :{" "} - - - {order.medusa_order_id} + :{' '} + {order.medusa_order_id}
- :{" "} - - - {formatDate(order.created_at, 'dd.MM.yyyy HH:mm')} + :{' '} + {formatDate(order.created_at, 'dd.MM.yyyy HH:mm')}
- ) + ); } diff --git a/app/home/(user)/_components/order/order-item.tsx b/app/home/(user)/_components/order/order-item.tsx index cad98e6..ed9ee37 100644 --- a/app/home/(user)/_components/order/order-item.tsx +++ b/app/home/(user)/_components/order/order-item.tsx @@ -1,13 +1,16 @@ -import { StoreCartLineItem, StoreOrderLineItem } from "@medusajs/types" -import { TableCell, TableRow } from "@kit/ui/table" - +import { StoreCartLineItem, StoreOrderLineItem } from '@medusajs/types'; // import LineItemOptions from "@modules/common/components/line-item-options" -import LineItemPrice from "@modules/common/components/line-item-price" -import LineItemUnitPrice from "@modules/common/components/line-item-unit-price" +import LineItemPrice from '@modules/common/components/line-item-price'; +import LineItemUnitPrice from '@modules/common/components/line-item-unit-price'; -export default function OrderItem({ item, currencyCode }: { - item: StoreCartLineItem | StoreOrderLineItem - currencyCode: string +import { TableCell, TableRow } from '@kit/ui/table'; + +export default function OrderItem({ + item, + currencyCode, +}: { + item: StoreCartLineItem | StoreOrderLineItem; + currencyCode: string; }) { const partnerLocationName = item.metadata?.partner_location_name; return ( @@ -18,22 +21,21 @@ export default function OrderItem({ item, currencyCode }: {
*/} - + - {item.product_title}{` ${partnerLocationName ? `(${partnerLocationName})` : ''}`} + {item.product_title} + {` ${partnerLocationName ? `(${partnerLocationName})` : ''}`} {/* */} - - - - {item.quantity}x{" "} - + + + {item.quantity}x - ) + ); } diff --git a/app/home/(user)/_components/order/order-items.tsx b/app/home/(user)/_components/order/order-items.tsx index 5375314..98b18d1 100644 --- a/app/home/(user)/_components/order/order-items.tsx +++ b/app/home/(user)/_components/order/order-items.tsx @@ -1,39 +1,44 @@ -import repeat from "@lib/util/repeat" -import { StoreOrder } from "@medusajs/types" -import { Table, TableBody } from "@kit/ui/table" +import repeat from '@lib/util/repeat'; +import { StoreOrder } from '@medusajs/types'; +import SkeletonLineItem from '@modules/skeletons/components/skeleton-line-item'; -import SkeletonLineItem from "@modules/skeletons/components/skeleton-line-item" -import OrderItem from "./order-item" -import { Heading } from "@kit/ui/heading" +import { Heading } from '@kit/ui/heading'; +import { Table, TableBody } from '@kit/ui/table'; import { Trans } from '@kit/ui/trans'; -export default function OrderItems({ medusaOrder }: { - medusaOrder: StoreOrder +import OrderItem from './order-item'; + +export default function OrderItems({ + medusaOrder, +}: { + medusaOrder: StoreOrder; }) { - const items = medusaOrder.items + const items = medusaOrder.items; return (
- +
- +
{items?.length ? items - .sort((a, b) => (a.created_at ?? "") > (b.created_at ?? "") ? -1 : 1) - .map((item) => ( - - )) + .sort((a, b) => + (a.created_at ?? '') > (b.created_at ?? '') ? -1 : 1, + ) + .map((item) => ( + + )) : repeat(5).map((i) => )}
- ) + ); } diff --git a/app/home/(user)/_components/orders/actions.ts b/app/home/(user)/_components/orders/actions.ts index 07bdfbc..91fb129 100644 --- a/app/home/(user)/_components/orders/actions.ts +++ b/app/home/(user)/_components/orders/actions.ts @@ -1,9 +1,15 @@ 'use server'; -import { createPageViewLog, PageViewAction } from "~/lib/services/audit/pageView.service"; -import { loadCurrentUserAccount } from "../../_lib/server/load-user-account"; +import { + PageViewAction, + createPageViewLog, +} from '~/lib/services/audit/pageView.service'; -export async function logAnalysisResultsNavigateAction(analysisOrderId: string) { +import { loadCurrentUserAccount } from '../../_lib/server/load-user-account'; + +export async function logAnalysisResultsNavigateAction( + analysisOrderId: string, +) { const { account } = await loadCurrentUserAccount(); if (!account) { throw new Error('Account not found'); diff --git a/app/home/(user)/_components/orders/order-block.tsx b/app/home/(user)/_components/orders/order-block.tsx index ccffd9e..03f0447 100644 --- a/app/home/(user)/_components/orders/order-block.tsx +++ b/app/home/(user)/_components/orders/order-block.tsx @@ -1,37 +1,57 @@ -import type { AnalysisOrder } from "~/lib/types/analysis-order"; -import { Trans } from '@kit/ui/makerkit/trans'; -import { StoreOrderLineItem } from "@medusajs/types"; -import OrderItemsTable from "./order-items-table"; -import Link from "next/link"; -import { Eye } from "lucide-react"; +import Link from 'next/link'; -export default function OrderBlock({ analysisOrder, itemsAnalysisPackage, itemsOther }: { - analysisOrder: AnalysisOrder, - itemsAnalysisPackage: StoreOrderLineItem[], - itemsOther: StoreOrderLineItem[], +import { StoreOrderLineItem } from '@medusajs/types'; +import { Eye } from 'lucide-react'; + +import { Trans } from '@kit/ui/makerkit/trans'; + +import type { AnalysisOrder } from '~/lib/types/analysis-order'; + +import OrderItemsTable from './order-items-table'; + +export default function OrderBlock({ + analysisOrder, + itemsAnalysisPackage, + itemsOther, +}: { + analysisOrder: AnalysisOrder; + itemsAnalysisPackage: StoreOrderLineItem[]; + itemsOther: StoreOrderLineItem[]; }) { return (

- + {` (${analysisOrder.id})`}

- -
- - + +
- ) + ); } diff --git a/app/home/(user)/_components/orders/order-items-table.tsx b/app/home/(user)/_components/orders/order-items-table.tsx index fc27d81..8511c08 100644 --- a/app/home/(user)/_components/orders/order-items-table.tsx +++ b/app/home/(user)/_components/orders/order-items-table.tsx @@ -65,7 +65,7 @@ export default function OrderItemsTable({ ) .map((orderItem) => ( - +

{orderItem.product_title}

diff --git a/app/home/(user)/_lib/server/load-accounts.ts b/app/home/(user)/_lib/server/load-accounts.ts index 77e7e42..e48e831 100644 --- a/app/home/(user)/_lib/server/load-accounts.ts +++ b/app/home/(user)/_lib/server/load-accounts.ts @@ -1,6 +1,5 @@ import { cache } from 'react'; - import { createAccountsApi } from '@kit/accounts/api'; import { getSupabaseServerClient } from '@kit/supabase/server-client'; diff --git a/app/home/(user)/_lib/server/load-analyses.ts b/app/home/(user)/_lib/server/load-analyses.ts index cd16e61..411d68a 100644 --- a/app/home/(user)/_lib/server/load-analyses.ts +++ b/app/home/(user)/_lib/server/load-analyses.ts @@ -1,7 +1,7 @@ import { cache } from 'react'; import { getProductCategories } from '@lib/data/categories'; -import { listProducts, listProductTypes } from '@lib/data/products'; +import { listProductTypes, listProducts } from '@lib/data/products'; import { listRegions } from '@lib/data/regions'; import { OrderAnalysisCard } from '../../_components/order-analyses-cards'; @@ -40,9 +40,9 @@ async function analysesLoader() { ); const categoryProducts = category ? await listProducts({ - countryCode, - queryParams: { limit: 100, category_id: category.id, order: 'title' }, - }) + countryCode, + queryParams: { limit: 100, category_id: category.id, order: 'title' }, + }) : null; const serviceCategories = productCategories.filter( @@ -52,21 +52,24 @@ async function analysesLoader() { return { analyses: categoryProducts?.response.products - .filter(({ status, metadata }) => status === 'published' && !!metadata?.analysisIdOriginal) - .map( - ({ title, description, subtitle, variants }) => { - const variant = variants![0]!; - return { - title, - description, - subtitle, - variant: { - id: variant.id, - }, - price: variant.calculated_price?.calculated_amount ?? null, - }; - }, - ) ?? [], + .filter( + ({ status, metadata }) => + status === 'published' && !!metadata?.analysisIdOriginal, + ) + .map( + ({ title, description, subtitle, variants }) => { + const variant = variants![0]!; + return { + title, + description, + subtitle, + variant: { + id: variant.id, + }, + price: variant.calculated_price?.calculated_amount ?? null, + }; + }, + ) ?? [], countryCode, }; } diff --git a/app/home/(user)/_lib/server/load-analysis-packages.ts b/app/home/(user)/_lib/server/load-analysis-packages.ts index 596a041..f564e08 100644 --- a/app/home/(user)/_lib/server/load-analysis-packages.ts +++ b/app/home/(user)/_lib/server/load-analysis-packages.ts @@ -1,14 +1,17 @@ import { cache } from 'react'; -import { listProductTypes, listProducts } from "@lib/data/products"; -import { listRegions } from '@lib/data/regions'; import { getAnalysisElementMedusaProductIds } from '@/utils/medusa-product'; +import { listProductTypes, listProducts } from '@lib/data/products'; +import { listRegions } from '@lib/data/regions'; import type { StoreProduct } from '@medusajs/types'; -import { loadCurrentUserAccount } from './load-user-account'; + import type { AccountWithParams } from '@kit/accounts/types/accounts'; import type { AnalysisPackageWithVariant } from '@kit/shared/components/select-analysis-package'; + import PersonalCode from '~/lib/utils'; +import { loadCurrentUserAccount } from './load-user-account'; + async function countryCodesLoader() { const countryCodes = await listRegions().then((regions) => regions?.map((r) => r.countries?.map((c) => c.iso_2)).flat(), @@ -33,24 +36,25 @@ function userSpecificVariantLoader({ throw new Error('Personal code not found'); } - const { ageRange, gender: { value: gender } } = PersonalCode.parsePersonalCode(personalCode); + const { + ageRange, + gender: { value: gender }, + } = PersonalCode.parsePersonalCode(personalCode); - return ({ - product, - }: { - product: StoreProduct; - }) => { + return ({ product }: { product: StoreProduct }) => { const variants = product.variants; if (!variants) { return null; } - const variant = variants.find((v) => v.options?.every((o) => [ageRange, gender].includes(o.value))); + const variant = variants.find((v) => + v.options?.every((o) => [ageRange, gender].includes(o.value)), + ); if (!variant) { return null; } return variant; - } + }; } async function analysisPackageElementsLoader({ @@ -60,30 +64,46 @@ async function analysisPackageElementsLoader({ analysisPackagesWithVariant: AnalysisPackageWithVariant[]; countryCode: string; }) { - const analysisElementMedusaProductIds = getAnalysisElementMedusaProductIds(analysisPackagesWithVariant); + const analysisElementMedusaProductIds = getAnalysisElementMedusaProductIds( + analysisPackagesWithVariant, + ); if (analysisElementMedusaProductIds.length === 0) { return []; } - const { response: { products } } = await listProducts({ + const { + response: { products }, + } = await listProducts({ countryCode, queryParams: { id: analysisElementMedusaProductIds, limit: 100, - order: "title", + order: 'title', }, }); - const standardPackage = analysisPackagesWithVariant.find(({ isStandard }) => isStandard); - const standardPlusPackage = analysisPackagesWithVariant.find(({ isStandardPlus }) => isStandardPlus); - const premiumPackage = analysisPackagesWithVariant.find(({ isPremium }) => isPremium); + const standardPackage = analysisPackagesWithVariant.find( + ({ isStandard }) => isStandard, + ); + const standardPlusPackage = analysisPackagesWithVariant.find( + ({ isStandardPlus }) => isStandardPlus, + ); + const premiumPackage = analysisPackagesWithVariant.find( + ({ isPremium }) => isPremium, + ); if (!standardPackage || !standardPlusPackage || !premiumPackage) { return []; } - const standardPackageAnalyses = getAnalysisElementMedusaProductIds([standardPackage]); - const standardPlusPackageAnalyses = getAnalysisElementMedusaProductIds([standardPlusPackage]); - const premiumPackageAnalyses = getAnalysisElementMedusaProductIds([premiumPackage]); + const standardPackageAnalyses = getAnalysisElementMedusaProductIds([ + standardPackage, + ]); + const standardPlusPackageAnalyses = getAnalysisElementMedusaProductIds([ + standardPlusPackage, + ]); + const premiumPackageAnalyses = getAnalysisElementMedusaProductIds([ + premiumPackage, + ]); return products.map(({ id, title, description }) => ({ id, @@ -103,18 +123,20 @@ async function analysisPackagesWithVariantLoader({ countryCode: string; }) { const productTypes = await loadProductTypes(); - const productType = productTypes.find(({ metadata }) => metadata?.handle === 'analysis-packages'); + const productType = productTypes.find( + ({ metadata }) => metadata?.handle === 'analysis-packages', + ); if (!productType) { return null; } const analysisPackagesResponse = await listProducts({ countryCode, - queryParams: { limit: 100, "type_id[0]": productType.id }, + queryParams: { limit: 100, 'type_id[0]': productType.id }, }); const getVariant = userSpecificVariantLoader({ account }); - const analysisPackagesWithVariant = analysisPackagesResponse.response.products - .reduce((acc, product) => { + const analysisPackagesWithVariant = + analysisPackagesResponse.response.products.reduce((acc, product) => { const variant = getVariant({ product }); if (!variant) { return acc; @@ -124,14 +146,17 @@ async function analysisPackagesWithVariantLoader({ { variant, variantId: variant.id, - nrOfAnalyses: getAnalysisElementMedusaProductIds([{ ...product, variant }]).length, + nrOfAnalyses: getAnalysisElementMedusaProductIds([ + { ...product, variant }, + ]).length, price: variant.calculated_price?.calculated_amount ?? 0, title: product.title, subtitle: product.subtitle, description: product.description, metadata: product.metadata, isStandard: product.metadata?.analysisPackageTier === 'standard', - isStandardPlus: product.metadata?.analysisPackageTier === 'standard-plus', + isStandardPlus: + product.metadata?.analysisPackageTier === 'standard-plus', isPremium: product.metadata?.analysisPackageTier === 'premium', }, ]; @@ -149,13 +174,23 @@ async function analysisPackagesLoader() { const countryCodes = await loadCountryCodes(); const countryCode = countryCodes[0]!; - const analysisPackagesWithVariant = await analysisPackagesWithVariantLoader({ account, countryCode }); + const analysisPackagesWithVariant = await analysisPackagesWithVariantLoader({ + account, + countryCode, + }); if (!analysisPackagesWithVariant) { return { analysisPackageElements: [], analysisPackages: [], countryCode }; } - const analysisPackageElements = await analysisPackageElementsLoader({ analysisPackagesWithVariant, countryCode }); + const analysisPackageElements = await analysisPackageElementsLoader({ + analysisPackagesWithVariant, + countryCode, + }); - return { analysisPackageElements, analysisPackages: analysisPackagesWithVariant, countryCode }; + return { + analysisPackageElements, + analysisPackages: analysisPackagesWithVariant, + countryCode, + }; } export const loadAnalysisPackages = cache(analysisPackagesLoader); diff --git a/app/home/(user)/_lib/server/load-user-account.ts b/app/home/(user)/_lib/server/load-user-account.ts index a16108a..c40e254 100644 --- a/app/home/(user)/_lib/server/load-user-account.ts +++ b/app/home/(user)/_lib/server/load-user-account.ts @@ -1,8 +1,9 @@ import { cache } from 'react'; +import { requireUserInServerComponent } from '@/lib/server/require-user-in-server-component'; + import { createAccountsApi } from '@kit/accounts/api'; import { getSupabaseServerClient } from '@kit/supabase/server-client'; -import { requireUserInServerComponent } from '@/lib/server/require-user-in-server-component'; export type UserAccount = Awaited>; diff --git a/app/home/(user)/_lib/server/load-user-analysis.ts b/app/home/(user)/_lib/server/load-user-analysis.ts index 5e70c3f..022bee1 100644 --- a/app/home/(user)/_lib/server/load-user-analysis.ts +++ b/app/home/(user)/_lib/server/load-user-analysis.ts @@ -1,8 +1,9 @@ import { cache } from 'react'; -import type { AnalysisResultDetailsMapped } from '@/packages/features/user-analyses/src/types/analysis-results'; -import { getSupabaseServerClient } from '@kit/supabase/server-client'; import { createUserAnalysesApi } from '@/packages/features/user-analyses/src/server/api'; +import type { AnalysisResultDetailsMapped } from '@/packages/features/user-analyses/src/types/analysis-results'; + +import { getSupabaseServerClient } from '@kit/supabase/server-client'; export type UserAnalyses = Awaited>; diff --git a/app/home/(user)/_lib/server/update-cart-partner-location.ts b/app/home/(user)/_lib/server/update-cart-partner-location.ts index 0ad1c6f..3a02b14 100644 --- a/app/home/(user)/_lib/server/update-cart-partner-location.ts +++ b/app/home/(user)/_lib/server/update-cart-partner-location.ts @@ -1,6 +1,6 @@ -"use server"; +'use server'; -import { retrieveCart, updateCart, updateLineItem } from "@lib/data/cart"; +import { retrieveCart, updateCart, updateLineItem } from '@lib/data/cart'; export const updateCartPartnerLocation = async ({ cartId, @@ -15,7 +15,7 @@ export const updateCartPartnerLocation = async ({ }) => { const cart = await retrieveCart(cartId); if (!cart) { - throw new Error("Cart not found"); + throw new Error('Cart not found'); } for (const lineItemId of lineIds) { @@ -35,4 +35,4 @@ export const updateCartPartnerLocation = async ({ partner_location_id: partnerLocationId, }, }); -} +}; diff --git a/app/home/(user)/billing/_components/personal-account-checkout-form.tsx b/app/home/(user)/billing/_components/personal-account-checkout-form.tsx index aacc8e5..bcece00 100644 --- a/app/home/(user)/billing/_components/personal-account-checkout-form.tsx +++ b/app/home/(user)/billing/_components/personal-account-checkout-form.tsx @@ -7,6 +7,7 @@ import dynamic from 'next/dynamic'; import { ExclamationTriangleIcon } from '@radix-ui/react-icons'; import { PlanPicker } from '@kit/billing-gateway/components'; +import { billingConfig } from '@kit/shared/config'; import { useAppEvents } from '@kit/shared/events'; import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert'; import { @@ -19,8 +20,6 @@ import { import { If } from '@kit/ui/if'; import { Trans } from '@kit/ui/trans'; -import { billingConfig } from '@kit/shared/config'; - import { createPersonalAccountCheckoutSession } from '../_lib/server/server-actions'; const EmbeddedCheckout = dynamic( diff --git a/app/home/(user)/billing/_lib/server/server-actions.ts b/app/home/(user)/billing/_lib/server/server-actions.ts index 8bec904..cbcbb70 100644 --- a/app/home/(user)/billing/_lib/server/server-actions.ts +++ b/app/home/(user)/billing/_lib/server/server-actions.ts @@ -3,11 +3,11 @@ import { redirect } from 'next/navigation'; import { enhanceAction } from '@kit/next/actions'; +import { featureFlagsConfig } from '@kit/shared/config'; import { getSupabaseServerClient } from '@kit/supabase/server-client'; import { PersonalAccountCheckoutSchema } from '../schema/personal-account-checkout.schema'; import { createUserBillingService } from './user-billing.service'; -import { featureFlagsConfig } from '@kit/shared/config'; /** * @name enabled diff --git a/app/home/(user)/billing/_lib/server/user-billing.service.ts b/app/home/(user)/billing/_lib/server/user-billing.service.ts index dd1f00b..afe34dc 100644 --- a/app/home/(user)/billing/_lib/server/user-billing.service.ts +++ b/app/home/(user)/billing/_lib/server/user-billing.service.ts @@ -8,12 +8,10 @@ import { z } from 'zod'; import { createAccountsApi } from '@kit/accounts/api'; import { getProductPlanPair } from '@kit/billing'; import { getBillingGatewayProvider } from '@kit/billing-gateway'; -import { getLogger } from '@kit/shared/logger'; -import { requireUser } from '@kit/supabase/require-user'; - import { appConfig, billingConfig } from '@kit/shared/config'; import { pathsConfig } from '@kit/shared/config'; - +import { getLogger } from '@kit/shared/logger'; +import { requireUser } from '@kit/supabase/require-user'; import { PersonalAccountCheckoutSchema } from '../schema/personal-account-checkout.schema'; diff --git a/app/home/(user)/billing/layout.tsx b/app/home/(user)/billing/layout.tsx index 7b3c5cb..540ba43 100644 --- a/app/home/(user)/billing/layout.tsx +++ b/app/home/(user)/billing/layout.tsx @@ -1,6 +1,6 @@ -import { featureFlagsConfig } from '@kit/shared/config'; import { notFound } from 'next/navigation'; +import { featureFlagsConfig } from '@kit/shared/config'; function UserBillingLayout(props: React.PropsWithChildren) { const isEnabled = featureFlagsConfig.enablePersonalAccountBilling; diff --git a/app/home/(user)/billing/page.tsx b/app/home/(user)/billing/page.tsx index 62484b4..461e053 100644 --- a/app/home/(user)/billing/page.tsx +++ b/app/home/(user)/billing/page.tsx @@ -3,17 +3,17 @@ import { CurrentLifetimeOrderCard, CurrentSubscriptionCard, } from '@kit/billing-gateway/components'; +import { billingConfig } from '@kit/shared/config'; import { AppBreadcrumbs } from '@kit/ui/app-breadcrumbs'; import { If } from '@kit/ui/if'; import { PageBody } from '@kit/ui/page'; import { Trans } from '@kit/ui/trans'; -import { billingConfig } from '@kit/shared/config'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; -import { requireUserInServerComponent } from '~/lib/server/require-user-in-server-component'; - // local imports import { withI18n } from '~/lib/i18n/with-i18n'; +import { requireUserInServerComponent } from '~/lib/server/require-user-in-server-component'; + import { HomeLayoutPageHeader } from '../_components/home-page-header'; import { createPersonalAccountBillingPortalSession } from '../billing/_lib/server/server-actions'; import { PersonalAccountCheckoutForm } from './_components/personal-account-checkout-form'; diff --git a/app/home/(user)/settings/_components/account-preferences-form.tsx b/app/home/(user)/settings/_components/account-preferences-form.tsx index f36adb3..54aa472 100644 --- a/app/home/(user)/settings/_components/account-preferences-form.tsx +++ b/app/home/(user)/settings/_components/account-preferences-form.tsx @@ -4,11 +4,12 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; import { Trans } from 'react-i18next'; -import type { AccountWithParams } from '@kit/accounts/types/accounts'; import { useRevalidatePersonalAccountDataQuery } from '@kit/accounts/hooks/use-personal-account-data'; +import type { AccountWithParams } from '@kit/accounts/types/accounts'; import { Button } from '@kit/ui/button'; import { Card, CardDescription, CardTitle } from '@kit/ui/card'; import { Form } from '@kit/ui/form'; +import { LanguageSelector } from '@kit/ui/language-selector'; import { toast } from '@kit/ui/sonner'; import { Switch } from '@kit/ui/switch'; @@ -17,7 +18,6 @@ import { accountPreferencesSchema, } from '../_lib/account-preferences.schema'; import { updatePersonalAccountPreferencesAction } from '../_lib/server/actions'; -import { LanguageSelector } from '@kit/ui/language-selector'; export default function AccountPreferencesForm({ account, diff --git a/app/home/(user)/settings/_components/account-settings-form.tsx b/app/home/(user)/settings/_components/account-settings-form.tsx index 5aba272..2aaa91e 100644 --- a/app/home/(user)/settings/_components/account-settings-form.tsx +++ b/app/home/(user)/settings/_components/account-settings-form.tsx @@ -4,8 +4,8 @@ import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; import { Trans } from 'react-i18next'; -import type { AccountWithParams } from '@kit/accounts/types/accounts'; import { useRevalidatePersonalAccountDataQuery } from '@kit/accounts/hooks/use-personal-account-data'; +import type { AccountWithParams } from '@kit/accounts/types/accounts'; import { Button } from '@kit/ui/button'; import { Form, @@ -129,11 +129,7 @@ export default function AccountSettingsForm({ - + @@ -152,11 +148,7 @@ export default function AccountSettingsForm({ - + diff --git a/app/home/(user)/settings/_components/settings-navigation.tsx b/app/home/(user)/settings/_components/settings-navigation.tsx index 4812349..157a477 100644 --- a/app/home/(user)/settings/_components/settings-navigation.tsx +++ b/app/home/(user)/settings/_components/settings-navigation.tsx @@ -9,6 +9,8 @@ import { Cross, Menu, Shield, ShoppingCart } from 'lucide-react'; import { usePersonalAccountData } from '@kit/accounts/hooks/use-personal-account-data'; import { ApplicationRoleEnum } from '@kit/accounts/types/accounts'; +import SignOutDropdownItem from '@kit/shared/components/sign-out-dropdown-item'; +import DropdownLink from '@kit/shared/components/ui/dropdown-link'; import { pathsConfig } from '@kit/shared/config'; import { useSignOut } from '@kit/supabase/hooks/use-sign-out'; import { @@ -22,8 +24,6 @@ import { import { If } from '@kit/ui/if'; import { Trans } from '@kit/ui/trans'; -import SignOutDropdownItem from '@kit/shared/components/sign-out-dropdown-item'; -import DropdownLink from '@kit/shared/components/ui/dropdown-link'; import { UserWorkspace } from '../../_lib/server/load-user-workspace'; import { routes } from './settings-sidebar'; @@ -148,5 +148,3 @@ export function SettingsMobileNavigation(props: { ); } - - diff --git a/app/home/(user)/settings/_components/settings-section-header.tsx b/app/home/(user)/settings/_components/settings-section-header.tsx index 36eaa0a..3381e2e 100644 --- a/app/home/(user)/settings/_components/settings-section-header.tsx +++ b/app/home/(user)/settings/_components/settings-section-header.tsx @@ -1,5 +1,5 @@ -import { Separator } from "@kit/ui/separator"; -import { Trans } from "@kit/ui/trans"; +import { Separator } from '@kit/ui/separator'; +import { Trans } from '@kit/ui/trans'; export default function SettingsSectionHeader({ titleKey, diff --git a/app/home/(user)/settings/layout.tsx b/app/home/(user)/settings/layout.tsx index d93b963..ffdde34 100644 --- a/app/home/(user)/settings/layout.tsx +++ b/app/home/(user)/settings/layout.tsx @@ -11,11 +11,11 @@ import { SidebarProvider } from '@kit/ui/shadcn-sidebar'; import { withI18n } from '~/lib/i18n/with-i18n'; -import { SettingsSidebar } from './_components/settings-sidebar'; // home imports import { HomeMenuNavigation } from '../_components/home-menu-navigation'; import { loadUserWorkspace } from '../_lib/server/load-user-workspace'; import { SettingsMobileNavigation } from './_components/settings-navigation'; +import { SettingsSidebar } from './_components/settings-sidebar'; function UserSettingsLayout({ children }: React.PropsWithChildren) { return {children}; @@ -27,7 +27,6 @@ function HeaderLayout({ children }: React.PropsWithChildren) { const workspace = use(loadUserWorkspace()); const cart = use(retrieveCart()); - return ( @@ -44,7 +43,7 @@ function HeaderLayout({ children }: React.PropsWithChildren) { -
{children}
+
{children}
diff --git a/app/home/[account]/_components/team-account-accounts-selector.tsx b/app/home/[account]/_components/team-account-accounts-selector.tsx index 4b6fc7b..12cbcc0 100644 --- a/app/home/[account]/_components/team-account-accounts-selector.tsx +++ b/app/home/[account]/_components/team-account-accounts-selector.tsx @@ -5,11 +5,9 @@ import { useContext } from 'react'; import { useRouter } from 'next/navigation'; import { AccountSelector } from '@kit/accounts/account-selector'; +import { featureFlagsConfig, pathsConfig } from '@kit/shared/config'; import { SidebarContext } from '@kit/ui/shadcn-sidebar'; -import { pathsConfig, featureFlagsConfig } from '@kit/shared/config'; - - const features = { enableTeamCreation: featureFlagsConfig.enableTeamCreation, }; diff --git a/app/home/[account]/_components/team-account-layout-mobile-navigation.tsx b/app/home/[account]/_components/team-account-layout-mobile-navigation.tsx index 70fb207..356e309 100644 --- a/app/home/[account]/_components/team-account-layout-mobile-navigation.tsx +++ b/app/home/[account]/_components/team-account-layout-mobile-navigation.tsx @@ -1,12 +1,12 @@ 'use client'; -import DropdownLink from '@kit/shared/components/ui/dropdown-link'; import { useRouter } from 'next/navigation'; -import SignOutDropdownItem from '@kit/shared/components/sign-out-dropdown-item'; import { Home, Menu } from 'lucide-react'; import { AccountSelector } from '@kit/accounts/account-selector'; +import SignOutDropdownItem from '@kit/shared/components/sign-out-dropdown-item'; +import DropdownLink from '@kit/shared/components/ui/dropdown-link'; import { featureFlagsConfig, getTeamAccountSidebarConfig, @@ -93,8 +93,6 @@ export const TeamAccountLayoutMobileNavigation = ( ); }; - - function TeamAccountsModal(props: { accounts: Accounts; userId: string; diff --git a/app/home/[account]/_components/team-account-notifications.tsx b/app/home/[account]/_components/team-account-notifications.tsx index 5344490..eec9503 100644 --- a/app/home/[account]/_components/team-account-notifications.tsx +++ b/app/home/[account]/_components/team-account-notifications.tsx @@ -1,8 +1,6 @@ import { NotificationsPopover } from '@kit/notifications/components'; - import { featureFlagsConfig } from '@kit/shared/config'; - export function TeamAccountNotifications(params: { userId: string; accountId: string; diff --git a/app/home/[account]/_lib/server/team-account-workspace.loader.ts b/app/home/[account]/_lib/server/team-account-workspace.loader.ts index 3ecaaee..49a5c9f 100644 --- a/app/home/[account]/_lib/server/team-account-workspace.loader.ts +++ b/app/home/[account]/_lib/server/team-account-workspace.loader.ts @@ -4,11 +4,10 @@ import { cache } from 'react'; import { redirect } from 'next/navigation'; +import { pathsConfig } from '@kit/shared/config'; import { getSupabaseServerClient } from '@kit/supabase/server-client'; import { createTeamAccountsApi } from '@kit/team-accounts/api'; -import { pathsConfig } from '@kit/shared/config'; - import { requireUserInServerComponent } from '~/lib/server/require-user-in-server-component'; export type TeamAccountWorkspace = Awaited< @@ -29,7 +28,7 @@ export const loadTeamWorkspace = cache(workspaceLoader); async function workspaceLoader(accountSlug: string) { const client = getSupabaseServerClient(); const api = createTeamAccountsApi(client); - const user = await requireUserInServerComponent(); + const user = await requireUserInServerComponent(); const workspace = await api.getAccountWorkspace(accountSlug, user.id); // we cannot find any record for the selected account // so we redirect the user to the home page @@ -39,7 +38,9 @@ async function workspaceLoader(accountSlug: string) { return { ...workspace.data, - accounts: workspace.data.accounts.map(({ user_accounts }) => ({...user_accounts})), + accounts: workspace.data.accounts.map(({ user_accounts }) => ({ + ...user_accounts, + })), user, }; } diff --git a/app/home/[account]/billing/_components/team-account-checkout-form.tsx b/app/home/[account]/billing/_components/team-account-checkout-form.tsx index ae0e711..c2ac569 100644 --- a/app/home/[account]/billing/_components/team-account-checkout-form.tsx +++ b/app/home/[account]/billing/_components/team-account-checkout-form.tsx @@ -6,6 +6,7 @@ import dynamic from 'next/dynamic'; import { useParams } from 'next/navigation'; import { PlanPicker } from '@kit/billing-gateway/components'; +import { billingConfig } from '@kit/shared/config'; import { useAppEvents } from '@kit/shared/events'; import { Card, @@ -16,8 +17,6 @@ import { } from '@kit/ui/card'; import { Trans } from '@kit/ui/trans'; -import { billingConfig } from '@kit/shared/config'; - import { createTeamAccountCheckoutSession } from '../_lib/server/server-actions'; const EmbeddedCheckout = dynamic( diff --git a/app/home/[account]/billing/page.tsx b/app/home/[account]/billing/page.tsx index 9291324..bc8288b 100644 --- a/app/home/[account]/billing/page.tsx +++ b/app/home/[account]/billing/page.tsx @@ -6,7 +6,6 @@ import { PageBody } from '@kit/ui/page'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { withI18n } from '~/lib/i18n/with-i18n'; - import HealthBenefitForm from './_components/health-benefit-form'; interface TeamAccountBillingPageProps { diff --git a/app/home/[account]/billing/return/page.tsx b/app/home/[account]/billing/return/page.tsx index 08274e3..52c92f0 100644 --- a/app/home/[account]/billing/return/page.tsx +++ b/app/home/[account]/billing/return/page.tsx @@ -5,10 +5,10 @@ import { BillingSessionStatus } from '@kit/billing-gateway/components'; import { billingConfig } from '@kit/shared/config'; import { getSupabaseServerClient } from '@kit/supabase/server-client'; +import { withI18n } from '~/lib/i18n/with-i18n'; import { requireUserInServerComponent } from '~/lib/server/require-user-in-server-component'; import { EmbeddedCheckoutForm } from '../_components/embedded-checkout-form'; -import { withI18n } from '~/lib/i18n/with-i18n'; interface SessionPageProps { searchParams: Promise<{ diff --git a/app/home/[account]/members/page.tsx b/app/home/[account]/members/page.tsx index 4eddcef..bb471bf 100644 --- a/app/home/[account]/members/page.tsx +++ b/app/home/[account]/members/page.tsx @@ -22,7 +22,6 @@ import { Trans } from '@kit/ui/trans'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { withI18n } from '~/lib/i18n/with-i18n'; - // local imports import { TeamAccountLayoutPageHeader } from '../_components/team-account-layout-page-header'; import { loadMembersPageData } from './_lib/server/members-page.loader'; diff --git a/app/home/[account]/page.tsx b/app/home/[account]/page.tsx index 8279c92..7283798 100644 --- a/app/home/[account]/page.tsx +++ b/app/home/[account]/page.tsx @@ -5,9 +5,9 @@ import { use } from 'react'; import { CompanyGuard } from '@/packages/features/team-accounts/src/components'; import { createTeamAccountsApi } from '@/packages/features/team-accounts/src/server/api'; import { getSupabaseServerClient } from '@/packages/supabase/src/clients/server-client'; -import { createUserAnalysesApi } from '@kit/user-analyses/api'; import { PageBody } from '@kit/ui/page'; +import { createUserAnalysesApi } from '@kit/user-analyses/api'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { withI18n } from '~/lib/i18n/with-i18n'; diff --git a/app/join/page.tsx b/app/join/page.tsx index 82a0db4..ec32148 100644 --- a/app/join/page.tsx +++ b/app/join/page.tsx @@ -4,6 +4,8 @@ import { notFound, redirect } from 'next/navigation'; import { ArrowLeft } from 'lucide-react'; import { AuthLayoutShell } from '@kit/auth/shared'; +import { AppLogo } from '@kit/shared/components/app-logo'; +import { pathsConfig } from '@kit/shared/config'; import { requireUser } from '@kit/supabase/require-user'; import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; import { getSupabaseServerClient } from '@kit/supabase/server-client'; @@ -13,13 +15,9 @@ import { Button } from '@kit/ui/button'; import { Heading } from '@kit/ui/heading'; import { Trans } from '@kit/ui/trans'; -import { AppLogo } from '@kit/shared/components/app-logo'; -import { pathsConfig } from '@kit/shared/config'; - import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { withI18n } from '~/lib/i18n/with-i18n'; - interface JoinTeamAccountPageProps { searchParams: Promise<{ invite_token?: string; diff --git a/app/layout.tsx b/app/layout.tsx index 4ea28c2..c2990ab 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -4,10 +4,10 @@ import { RootProviders } from '@kit/shared/components/root-providers'; import { Toaster } from '@kit/ui/sonner'; import { getFontsClassName } from '~/lib/fonts'; +import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import { generateRootMetadata } from '~/lib/root-metdata'; import { getRootTheme } from '~/lib/root-theme'; -import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; import '../styles/globals.css'; export const generateMetadata = () => { diff --git a/app/not-found.tsx b/app/not-found.tsx index 5b6bd81..5422bc1 100644 --- a/app/not-found.tsx +++ b/app/not-found.tsx @@ -7,8 +7,8 @@ import { Heading } from '@kit/ui/heading'; import { Trans } from '@kit/ui/trans'; import { SiteHeader } from '~/(marketing)/_components/site-header'; -import { withI18n } from '~/lib/i18n/with-i18n'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; +import { withI18n } from '~/lib/i18n/with-i18n'; export const generateMetadata = async () => { const i18n = await createI18nServerInstance(); diff --git a/app/update-password/page.tsx b/app/update-password/page.tsx index 293e42f..c72fb45 100644 --- a/app/update-password/page.tsx +++ b/app/update-password/page.tsx @@ -4,8 +4,8 @@ import { AppLogo } from '@kit/shared/components/app-logo'; import { pathsConfig } from '@kit/shared/config'; import { createI18nServerInstance } from '~/lib/i18n/i18n.server'; -import { requireUserInServerComponent } from '~/lib/server/require-user-in-server-component'; import { withI18n } from '~/lib/i18n/with-i18n'; +import { requireUserInServerComponent } from '~/lib/server/require-user-in-server-component'; export const generateMetadata = async () => { const { t } = await createI18nServerInstance(); diff --git a/app_unused_medusa_routes/store/[countryCode]/(checkout)/checkout/page.tsx b/app_unused_medusa_routes/store/[countryCode]/(checkout)/checkout/page.tsx index 6244a1d..5f0b85a 100644 --- a/app_unused_medusa_routes/store/[countryCode]/(checkout)/checkout/page.tsx +++ b/app_unused_medusa_routes/store/[countryCode]/(checkout)/checkout/page.tsx @@ -1,30 +1,32 @@ -import { retrieveCart } from "@lib/data/cart" -import { retrieveCustomer } from "@lib/data/customer" -import PaymentWrapper from "@modules/checkout/components/payment-wrapper" -import CheckoutForm from "@modules/checkout/templates/checkout-form" -import CheckoutSummary from "@modules/checkout/templates/checkout-summary" -import { Metadata } from "next" -import { notFound } from "next/navigation" +import { Metadata } from 'next'; + +import { notFound } from 'next/navigation'; + +import { retrieveCart } from '@lib/data/cart'; +import { retrieveCustomer } from '@lib/data/customer'; +import PaymentWrapper from '@modules/checkout/components/payment-wrapper'; +import CheckoutForm from '@modules/checkout/templates/checkout-form'; +import CheckoutSummary from '@modules/checkout/templates/checkout-summary'; export const metadata: Metadata = { - title: "Checkout", -} + title: 'Checkout', +}; export default async function Checkout() { - const cart = await retrieveCart() + const cart = await retrieveCart(); if (!cart) { - return notFound() + return notFound(); } - const customer = await retrieveCustomer() + const customer = await retrieveCustomer(); return ( -
+
- ) + ); } diff --git a/app_unused_medusa_routes/store/[countryCode]/(main)/layout.tsx b/app_unused_medusa_routes/store/[countryCode]/(main)/layout.tsx index 26c8da1..14e9413 100644 --- a/app_unused_medusa_routes/store/[countryCode]/(main)/layout.tsx +++ b/app_unused_medusa_routes/store/[countryCode]/(main)/layout.tsx @@ -1,10 +1,10 @@ import { Metadata } from 'next'; -import { StoreCartShippingOption } from '@medusajs/types'; - import { listCartOptions, retrieveCart } from '@lib/data/cart'; import { retrieveCustomer } from '@lib/data/customer'; import { getBaseURL } from '@lib/util/env'; +import { StoreCartShippingOption } from '@medusajs/types'; + import CartMismatchBanner from '~/medusa/modules/layout/components/cart-mismatch-banner'; import Footer from '~/medusa/modules/layout/templates/footer'; import Nav from '~/medusa/modules/layout/templates/nav'; diff --git a/jest.config.js b/jest.config.js index eac3110..5595cea 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,5 @@ -import { pathsToModuleNameMapper } from 'ts-jest'; import { readFileSync } from 'fs'; +import { pathsToModuleNameMapper } from 'ts-jest'; const tsconfig = JSON.parse(readFileSync('./tsconfig.json', 'utf8')); @@ -7,7 +7,7 @@ const tsconfig = JSON.parse(readFileSync('./tsconfig.json', 'utf8')); export default { preset: 'ts-jest', testEnvironment: 'node', - + // Handle module resolution for TypeScript paths moduleNameMapper: { ...pathsToModuleNameMapper(tsconfig.compilerOptions.paths, { @@ -17,16 +17,13 @@ export default { '^isikukood$': '/__mocks__/isikukood.ts', '^server-only$': '/__mocks__/server-only.ts', }, - + // Test file patterns - testMatch: [ - '**/__tests__/**/*.(ts|tsx|js)', - '**/*.(test|spec).(ts|tsx|js)' - ], - + testMatch: ['**/__tests__/**/*.(ts|tsx|js)', '**/*.(test|spec).(ts|tsx|js)'], + // Setup files setupFilesAfterEnv: ['/jest.setup.js'], - + // Coverage configuration collectCoverageFrom: [ 'lib/**/*.{ts,tsx}', @@ -34,33 +31,31 @@ export default { 'components/**/*.{ts,tsx}', '!**/*.d.ts', '!**/node_modules/**', - '!**/.next/**' + '!**/.next/**', ], - + // Transform configuration transform: { - '^.+\\.(ts|tsx)$': ['ts-jest', { - useESM: true, - tsconfig: { - jsx: 'react-jsx', + '^.+\\.(ts|tsx)$': [ + 'ts-jest', + { + useESM: true, + tsconfig: { + jsx: 'react-jsx', + }, }, - }], + ], }, - + // Module file extensions moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'], - + // Ignore patterns - testPathIgnorePatterns: [ - '/.next/', - '/node_modules/', - ], - + testPathIgnorePatterns: ['/.next/', '/node_modules/'], + // Transform ignore patterns for node_modules - transformIgnorePatterns: [ - 'node_modules/(?!(.*\\.mjs$))', - ], - + transformIgnorePatterns: ['node_modules/(?!(.*\\.mjs$))'], + // ESM support extensionsToTreatAsEsm: ['.ts'], }; diff --git a/lib/constants.ts b/lib/constants.ts index 93f3bca..a40a1fb 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -1,2 +1,2 @@ -export const DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss"; -export const DATE_FORMAT = "yyyy-MM-dd"; +export const DATE_TIME_FORMAT = 'yyyy-MM-dd HH:mm:ss'; +export const DATE_FORMAT = 'yyyy-MM-dd'; diff --git a/lib/fonts.ts b/lib/fonts.ts index a98d6bb..e29672c 100644 --- a/lib/fonts.ts +++ b/lib/fonts.ts @@ -1,4 +1,4 @@ -import { Geist as HeadingFont } from 'next/font/google'; +import { Geist as HeadingFont } from 'next/font/google'; import SansFont from 'next/font/local'; import { cn } from '@kit/ui/utils'; @@ -22,7 +22,6 @@ const sans = SansFont({ style: 'medium', }, ], - }); /** diff --git a/lib/services/analyses.service.ts b/lib/services/analyses.service.ts index 7eabeac..0a47cf1 100644 --- a/lib/services/analyses.service.ts +++ b/lib/services/analyses.service.ts @@ -1,6 +1,8 @@ import type { Tables } from '@/packages/supabase/src/database.types'; + import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; -import type { IUuringElement } from "./medipost/medipost.types"; + +import type { IUuringElement } from './medipost/medipost.types'; export type AnalysesWithGroupsAndElements = ({ analysis_elements: Tables<{ schema: 'medreport' }, 'analysis_elements'> & { @@ -37,7 +39,7 @@ export const createAnalysis = async ( } return insertedAnalysisId; -} +}; const createSyncEntry = async ({ operation, @@ -49,14 +51,15 @@ const createSyncEntry = async ({ comment?: string; }) => { await getSupabaseServerAdminClient() - .schema('audit').from('sync_entries') + .schema('audit') + .from('sync_entries') .insert({ operation, status, changed_by_role: 'service_role', comment, }); -} +}; export const createNoNewDataReceivedEntry = async () => { await createSyncEntry({ @@ -64,7 +67,7 @@ export const createNoNewDataReceivedEntry = async () => { status: 'SUCCESS', comment: 'No new data received', }); -} +}; export const createNoDataReceivedEntry = async () => { await createSyncEntry({ @@ -72,7 +75,7 @@ export const createNoDataReceivedEntry = async () => { status: 'SUCCESS', comment: 'No data received', }); -} +}; export const createSyncFailEntry = async (error: string) => { await createSyncEntry({ @@ -80,14 +83,14 @@ export const createSyncFailEntry = async (error: string) => { status: 'FAIL', comment: error, }); -} +}; export const createSyncSuccessEntry = async () => { await createSyncEntry({ operation: 'ANALYSES_SYNC', status: 'SUCCESS', }); -} +}; export const createMedusaSyncFailEntry = async (error: string) => { await createSyncEntry({ @@ -95,15 +98,14 @@ export const createMedusaSyncFailEntry = async (error: string) => { status: 'FAIL', comment: error, }); -} - +}; export const createMedusaSyncSuccessEntry = async () => { await createSyncEntry({ operation: 'ANALYSES_MEDUSA_SYNC', status: 'SUCCESS', }); -} +}; export async function getAnalyses({ ids, diff --git a/lib/services/analysis-element.service.ts b/lib/services/analysis-element.service.ts index e4f3aff..d1e61a8 100644 --- a/lib/services/analysis-element.service.ts +++ b/lib/services/analysis-element.service.ts @@ -1,8 +1,12 @@ import { Json, Tables } from '@kit/supabase/database'; import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; + import type { IMaterialGroup, IUuringElement } from './medipost/medipost.types'; -export type AnalysisElement = Tables<{ schema: 'medreport' }, 'analysis_elements'> & { +export type AnalysisElement = Tables< + { schema: 'medreport' }, + 'analysis_elements' +> & { analysis_groups: Tables<{ schema: 'medreport' }, 'analysis_groups'>; }; @@ -27,8 +31,15 @@ export async function getAnalysisElements({ const hasIdsFilter = Array.isArray(ids); const hasAnalysisGroupIdFilter = typeof analysisGroupId === 'number'; - if (!hasOriginalIdsFilter && !hasIdsFilter && !hasAnalysisGroupIdFilter && getAll !== true) { - throw new Error('Either originalIds, ids, or analysisGroupId must be provided'); + if ( + !hasOriginalIdsFilter && + !hasIdsFilter && + !hasAnalysisGroupIdFilter && + getAll !== true + ) { + throw new Error( + 'Either originalIds, ids, or analysisGroupId must be provided', + ); } if (hasOriginalIdsFilter) { @@ -85,23 +96,24 @@ export async function createAnalysisElement({ analysisGroupId: number; materialGroups: IMaterialGroup[]; }) { - const { data: insertedAnalysisElement, error } = await getSupabaseServerAdminClient() - .schema('medreport') - .from('analysis_elements') - .upsert( - { - analysis_id_oid: analysisElement.UuringIdOID, - analysis_id_original: analysisElement.UuringId, - tehik_short_loinc: analysisElement.TLyhend, - tehik_loinc_name: analysisElement.KNimetus, - analysis_name_lab: analysisElement.UuringNimi, - order: analysisElement.Jarjekord, - parent_analysis_group_id: analysisGroupId, - material_groups: materialGroups as unknown as Json[], - }, - { onConflict: 'analysis_id_original', ignoreDuplicates: false }, - ) - .select('id'); + const { data: insertedAnalysisElement, error } = + await getSupabaseServerAdminClient() + .schema('medreport') + .from('analysis_elements') + .upsert( + { + analysis_id_oid: analysisElement.UuringIdOID, + analysis_id_original: analysisElement.UuringId, + tehik_short_loinc: analysisElement.TLyhend, + tehik_loinc_name: analysisElement.KNimetus, + analysis_name_lab: analysisElement.UuringNimi, + order: analysisElement.Jarjekord, + parent_analysis_group_id: analysisGroupId, + material_groups: materialGroups as unknown as Json[], + }, + { onConflict: 'analysis_id_original', ignoreDuplicates: false }, + ) + .select('id'); const id = insertedAnalysisElement?.[0]?.id; if (error || !id) { diff --git a/lib/services/analysis-group.service.ts b/lib/services/analysis-group.service.ts index 17e323c..54c0a6a 100644 --- a/lib/services/analysis-group.service.ts +++ b/lib/services/analysis-group.service.ts @@ -1,24 +1,23 @@ -import { getSupabaseServerAdminClient } from "@kit/supabase/server-admin-client"; +import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; -export const createAnalysisGroup = async ( - analysisGroup: { - id: string; - name: string; - order: number; - } -) => { - const { data: insertedAnalysisGroup, error } = await getSupabaseServerAdminClient() - .schema('medreport') - .from('analysis_groups') - .upsert( - { - original_id: analysisGroup.id, - name: analysisGroup.name, - order: analysisGroup.order, - }, - { onConflict: 'original_id', ignoreDuplicates: false }, - ) - .select('id'); +export const createAnalysisGroup = async (analysisGroup: { + id: string; + name: string; + order: number; +}) => { + const { data: insertedAnalysisGroup, error } = + await getSupabaseServerAdminClient() + .schema('medreport') + .from('analysis_groups') + .upsert( + { + original_id: analysisGroup.id, + name: analysisGroup.name, + order: analysisGroup.order, + }, + { onConflict: 'original_id', ignoreDuplicates: false }, + ) + .select('id'); const analysisGroupId = insertedAnalysisGroup?.[0]?.id as number; if (error || !analysisGroupId) { @@ -28,7 +27,7 @@ export const createAnalysisGroup = async ( } return analysisGroupId; -} +}; export const getAnalysisGroups = async () => { const { data: analysisGroups } = await getSupabaseServerAdminClient() @@ -37,4 +36,4 @@ export const getAnalysisGroups = async () => { .select('*'); return analysisGroups; -} +}; diff --git a/lib/services/analysis-order.service.ts b/lib/services/analysis-order.service.ts index 5fa5ed5..03c34cb 100644 --- a/lib/services/analysis-order.service.ts +++ b/lib/services/analysis-order.service.ts @@ -1,7 +1,7 @@ -import { getSupabaseServerAdminClient } from "@/packages/supabase/src/clients/server-admin-client"; import { AnalysisOrderStatus } from '@/packages/shared/src/types/medipost-analysis'; +import { getSupabaseServerAdminClient } from '@/packages/supabase/src/clients/server-admin-client'; -import type { AnalysisResponseElement } from "../types/analysis-response-element"; +import type { AnalysisResponseElement } from '../types/analysis-response-element'; export async function getExistingAnalysisResponseElements({ analysisResponseId, @@ -26,20 +26,17 @@ export async function upsertAnalysisResponseElement({ const { data } = await getSupabaseServerAdminClient() .schema('medreport') .from('analysis_response_elements') - .upsert( - element, - { - onConflict: 'analysis_response_id,analysis_element_original_id', - ignoreDuplicates: false - } - ) + .upsert(element, { + onConflict: 'analysis_response_id,analysis_element_original_id', + ignoreDuplicates: false, + }) .select('id') .throwOnError(); const analysisResponseElementId = data?.[0]?.id; if (!analysisResponseElementId) { throw new Error( - `Failed to insert or update analysis response element (response id: ${element.analysis_response_id}, element id: ${element.analysis_element_original_id})` + `Failed to insert or update analysis response element (response id: ${element.analysis_response_id}, element id: ${element.analysis_element_original_id})`, ); } @@ -54,7 +51,7 @@ export async function upsertAnalysisResponse({ }: { analysisOrderId: number; orderNumber: string; - orderStatus: typeof AnalysisOrderStatus[keyof typeof AnalysisOrderStatus]; + orderStatus: (typeof AnalysisOrderStatus)[keyof typeof AnalysisOrderStatus]; userId: string; }) { const { data: analysisResponse } = await getSupabaseServerAdminClient() @@ -72,7 +69,6 @@ export async function upsertAnalysisResponse({ .select('id') .throwOnError(); - const analysisResponseId = analysisResponse?.[0]?.id; if (!analysisResponseId) { throw new Error( diff --git a/lib/services/audit.service.ts b/lib/services/audit.service.ts index 880c037..c68a01b 100644 --- a/lib/services/audit.service.ts +++ b/lib/services/audit.service.ts @@ -1,5 +1,5 @@ - 'use server' - +'use server'; + import { RequestStatus } from '@/lib/types/audit'; import { ConnectedOnlineMethodName } from '@/lib/types/connected-online'; import { ExternalApi } from '@/lib/types/external'; diff --git a/lib/services/codes.service.ts b/lib/services/codes.service.ts index f3b19d3..32ab7d7 100644 --- a/lib/services/codes.service.ts +++ b/lib/services/codes.service.ts @@ -1,8 +1,10 @@ -import { getSupabaseServerAdminClient } from "@kit/supabase/server-admin-client"; -import type { ICode } from "~/lib/types/code"; +import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; + +import type { ICode } from '~/lib/types/code'; export const createCodes = async (codes: ICode[]) => { await getSupabaseServerAdminClient() - .schema('medreport').from('codes') + .schema('medreport') + .from('codes') .upsert(codes); -} +}; diff --git a/lib/services/medipost/medipostMessageBase.service.ts b/lib/services/medipost/medipostMessageBase.service.ts index d3194e8..5174320 100644 --- a/lib/services/medipost/medipostMessageBase.service.ts +++ b/lib/services/medipost/medipostMessageBase.service.ts @@ -1,7 +1,6 @@ 'use server'; import type { Message } from '@/lib/types/medipost'; - import { getSupabaseServerAdminClient } from '@/packages/supabase/src/clients/server-admin-client'; export async function getLatestMessage({ @@ -15,14 +14,17 @@ export async function getLatestMessage({ return null; } - const filtered = messages.filter(({ messageId }) => !excludedMessageIds?.includes(messageId)); + const filtered = messages.filter( + ({ messageId }) => !excludedMessageIds?.includes(messageId), + ); if (!filtered.length) { return null; } - return filtered.reduce((prev, current) => - Number(prev.messageId) > Number(current.messageId) ? prev : current, + return filtered.reduce( + (prev, current) => + Number(prev.messageId) > Number(current.messageId) ? prev : current, { messageId: '' } as Message, ); } @@ -38,9 +40,9 @@ export async function upsertMedipostActionLog({ medipostPrivateMessageId, }: { action: - | 'send_order_to_medipost' - | 'sync_analysis_results_from_medipost' - | 'send_fake_analysis_results_to_medipost'; + | 'send_order_to_medipost' + | 'sync_analysis_results_from_medipost' + | 'send_fake_analysis_results_to_medipost'; xml: string; hasAnalysisResults?: boolean; medusaOrderId?: string | null; @@ -63,10 +65,10 @@ export async function upsertMedipostActionLog({ medipost_external_order_id: medipostExternalOrderId, medipost_private_message_id: medipostPrivateMessageId, }, - { - onConflict: 'medipost_private_message_id', - ignoreDuplicates: false - } + { + onConflict: 'medipost_private_message_id', + ignoreDuplicates: false, + }, ) .select('id') .throwOnError(); @@ -74,7 +76,7 @@ export async function upsertMedipostActionLog({ const medipostActionId = data?.[0]?.id; if (!medipostActionId) { throw new Error( - `Failed to insert or update medipost action (private message id: ${medipostPrivateMessageId})` + `Failed to insert or update medipost action (private message id: ${medipostPrivateMessageId})`, ); } diff --git a/lib/services/medipost/medipostPrivateMessage.service.test.ts b/lib/services/medipost/medipostPrivateMessage.service.test.ts index aeb16f1..0b94d15 100644 --- a/lib/services/medipost/medipostPrivateMessage.service.test.ts +++ b/lib/services/medipost/medipostPrivateMessage.service.test.ts @@ -1,8 +1,16 @@ -import { AnalysisResponseElement } from "~/lib/types/analysis-response-element"; -import { canCreateAnalysisResponseElement, getAnalysisResponseElementsForGroup } from "./medipostPrivateMessage.service"; -import { ResponseUuring } from "@/packages/shared/src/types/medipost-analysis"; +import { ResponseUuring } from '@/packages/shared/src/types/medipost-analysis'; -type TestExistingElement = Pick; +import { AnalysisResponseElement } from '~/lib/types/analysis-response-element'; + +import { + canCreateAnalysisResponseElement, + getAnalysisResponseElementsForGroup, +} from './medipostPrivateMessage.service'; + +type TestExistingElement = Pick< + AnalysisResponseElement, + 'analysis_element_original_id' | 'status' | 'response_value' +>; describe('medipostPrivateMessage.service', () => { describe('canCreateAnalysisResponseElement', () => { @@ -16,11 +24,20 @@ describe('medipostPrivateMessage.service', () => { } as const; const responseValue = 1; const log = jest.fn(); - expect(await canCreateAnalysisResponseElement({ existingElements, groupUuring, responseValue, log })).toBe(true); + expect( + await canCreateAnalysisResponseElement({ + existingElements, + groupUuring, + responseValue, + log, + }), + ).toBe(true); }); it('should return false if the analysis response element exists and the status is higher', async () => { - const existingElements = [{ analysis_element_original_id: '1', status: '2', response_value: 1 }] as TestExistingElement[]; + const existingElements = [ + { analysis_element_original_id: '1', status: '2', response_value: 1 }, + ] as TestExistingElement[]; const groupUuring = { UuringuElement: { UuringOlek: 1, @@ -29,7 +46,14 @@ describe('medipostPrivateMessage.service', () => { } as const; const responseValue = 1; const log = jest.fn(); - expect(await canCreateAnalysisResponseElement({ existingElements, groupUuring, responseValue, log })).toBe(false); + expect( + await canCreateAnalysisResponseElement({ + existingElements, + groupUuring, + responseValue, + log, + }), + ).toBe(false); }); }); @@ -49,8 +73,14 @@ describe('medipostPrivateMessage.service', () => { } as const; const existingElements = [] as TestExistingElement[]; const log = jest.fn(); - expect(await getAnalysisResponseElementsForGroup({ analysisGroup, existingElements, log })) - .toEqual([{ + expect( + await getAnalysisResponseElementsForGroup({ + analysisGroup, + existingElements, + log, + }), + ).toEqual([ + { analysis_element_original_id: '1', analysis_name: undefined, comment: null, @@ -68,7 +98,8 @@ describe('medipostPrivateMessage.service', () => { UuringuVastus: [{ VastuseVaartus: '1' }], }, status: '1', - }]); + }, + ]); }); it('should return no new element if element already exists in higher status', async () => { @@ -84,10 +115,17 @@ describe('medipostPrivateMessage.service', () => { }, ] as unknown as ResponseUuring[], } as const; - const existingElements = [{ analysis_element_original_id: '1', status: '2', response_value: 1 }] as TestExistingElement[]; + const existingElements = [ + { analysis_element_original_id: '1', status: '2', response_value: 1 }, + ] as TestExistingElement[]; const log = jest.fn(); - expect(await getAnalysisResponseElementsForGroup({ analysisGroup, existingElements, log })) - .toEqual([]); + expect( + await getAnalysisResponseElementsForGroup({ + analysisGroup, + existingElements, + log, + }), + ).toEqual([]); }); it('should return no new element if element already exists with response value', async () => { @@ -103,10 +141,17 @@ describe('medipostPrivateMessage.service', () => { }, ] as unknown as ResponseUuring[], } as const; - const existingElements = [{ analysis_element_original_id: '1', status: '1', response_value: 1 }] as TestExistingElement[]; + const existingElements = [ + { analysis_element_original_id: '1', status: '1', response_value: 1 }, + ] as TestExistingElement[]; const log = jest.fn(); - expect(await getAnalysisResponseElementsForGroup({ analysisGroup, existingElements, log })) - .toEqual([]); + expect( + await getAnalysisResponseElementsForGroup({ + analysisGroup, + existingElements, + log, + }), + ).toEqual([]); }); }); }); diff --git a/lib/services/medipost/medipostPrivateMessage.service.ts b/lib/services/medipost/medipostPrivateMessage.service.ts index ef3e9ac..cf790ea 100644 --- a/lib/services/medipost/medipostPrivateMessage.service.ts +++ b/lib/services/medipost/medipostPrivateMessage.service.ts @@ -1,36 +1,42 @@ 'use server'; import type { PostgrestError } from '@supabase/supabase-js'; -import axios from 'axios'; -import { - GetMessageListResponse, - MedipostAction, -} from '@/lib/types/medipost'; +import { GetMessageListResponse, MedipostAction } from '@/lib/types/medipost'; +import { createUserAnalysesApi } from '@/packages/features/user-analyses/src/server/api'; import { AnalysisOrderStatus } from '@/packages/shared/src/types/medipost-analysis'; import type { - ResponseUuringuGrupp, MedipostOrderResponse, + ResponseUuringuGrupp, UuringElement, } from '@/packages/shared/src/types/medipost-analysis'; +import { getSupabaseServerAdminClient } from '@/packages/supabase/src/clients/server-admin-client'; +import axios from 'axios'; + import { toArray } from '@kit/shared/utils'; +import { Tables } from '@kit/supabase/database'; + import type { AnalysisOrder } from '~/lib/types/analysis-order'; import type { AnalysisResponseElement } from '~/lib/types/analysis-response-element'; -import { createUserAnalysesApi } from '@/packages/features/user-analyses/src/server/api'; -import { Tables } from '@kit/supabase/database'; -import { getSupabaseServerAdminClient } from '@/packages/supabase/src/clients/server-admin-client'; -import { getAnalysisElementsAdmin } from '../analysis-element.service'; +import { getAccountAdmin } from '../account.service'; import { getAnalyses } from '../analyses.service'; -import { upsertMedipostActionLog, getLatestMessage } from './medipostMessageBase.service'; -import { validateMedipostResponse } from './medipostValidate.service'; +import { getAnalysisElementsAdmin } from '../analysis-element.service'; +import { + getExistingAnalysisResponseElements, + upsertAnalysisResponse, + upsertAnalysisResponseElement, +} from '../analysis-order.service'; +import { logMedipostDispatch } from '../audit.service'; import { getAnalysisOrder, updateAnalysisOrderStatus } from '../order.service'; import { parseXML } from '../util/xml.service'; -import { composeOrderXML, OrderedAnalysisElement } from './medipostXML.service'; -import { getAccountAdmin } from '../account.service'; -import { logMedipostDispatch } from '../audit.service'; import { MedipostValidationError } from './MedipostValidationError'; -import { upsertAnalysisResponseElement, getExistingAnalysisResponseElements, upsertAnalysisResponse } from '../analysis-order.service'; +import { + getLatestMessage, + upsertMedipostActionLog, +} from './medipostMessageBase.service'; +import { validateMedipostResponse } from './medipostValidate.service'; +import { OrderedAnalysisElement, composeOrderXML } from './medipostXML.service'; const BASE_URL = process.env.MEDIPOST_URL!; const USER = process.env.MEDIPOST_USER!; @@ -56,73 +62,102 @@ export async function getLatestPrivateMessageListItem({ throw new Error('Failed to get private message list'); } - return await getLatestMessage({ messages: data?.messages, excludedMessageIds }); + return await getLatestMessage({ + messages: data?.messages, + excludedMessageIds, + }); } -const logger = (analysisOrder: AnalysisOrder, externalId: string, analysisResponseId: string) => (message: string, error?: PostgrestError | null) => { - const messageFormatted = `[${analysisOrder.id}] [${externalId}] [${analysisResponseId}] ${message}`; - if (error) { - console.info(messageFormatted, error); - } else { - console.info(messageFormatted); - } -}; +const logger = + ( + analysisOrder: AnalysisOrder, + externalId: string, + analysisResponseId: string, + ) => + (message: string, error?: PostgrestError | null) => { + const messageFormatted = `[${analysisOrder.id}] [${externalId}] [${analysisResponseId}] ${message}`; + if (error) { + console.info(messageFormatted, error); + } else { + console.info(messageFormatted); + } + }; export async function canCreateAnalysisResponseElement({ existingElements, groupUuring: { - UuringuElement: { - UuringOlek: status, - UuringId: analysisElementOriginalId, - }, + UuringuElement: { UuringOlek: status, UuringId: analysisElementOriginalId }, }, responseValue, log, }: { - existingElements: Pick[]; - groupUuring: { UuringuElement: Pick }; + existingElements: Pick< + AnalysisResponseElement, + 'analysis_element_original_id' | 'status' | 'response_value' + >[]; + groupUuring: { + UuringuElement: Pick; + }; responseValue: number | null; log: ReturnType; }) { - const existingAnalysisResponseElement = existingElements.find(({ analysis_element_original_id }) => analysis_element_original_id === analysisElementOriginalId); + const existingAnalysisResponseElement = existingElements.find( + ({ analysis_element_original_id }) => + analysis_element_original_id === analysisElementOriginalId, + ); if (!existingAnalysisResponseElement) { return true; } if (Number(existingAnalysisResponseElement.status) > status) { - log(`Analysis response element id=${analysisElementOriginalId} already exists for order in higher status ${existingAnalysisResponseElement.status} than ${status}`); + log( + `Analysis response element id=${analysisElementOriginalId} already exists for order in higher status ${existingAnalysisResponseElement.status} than ${status}`, + ); return false; } if (existingAnalysisResponseElement.response_value && !responseValue) { - log(`Analysis response element id=${analysisElementOriginalId} already exists for order with response value ${existingAnalysisResponseElement.response_value} but new response has no value`); + log( + `Analysis response element id=${analysisElementOriginalId} already exists for order with response value ${existingAnalysisResponseElement.response_value} but new response has no value`, + ); return false; } return true; } - export async function getAnalysisResponseElementsForGroup({ analysisGroup, existingElements, log, }: { analysisGroup: Pick; - existingElements: Pick[]; + existingElements: Pick< + AnalysisResponseElement, + 'analysis_element_original_id' | 'status' | 'response_value' + >[]; log: ReturnType; }) { - const groupUuringItems = toArray(analysisGroup.Uuring as ResponseUuringuGrupp['Uuring']); - log(`Order has results in group '${analysisGroup.UuringuGruppNimi}' for ${groupUuringItems.length} analysis elements`); + const groupUuringItems = toArray( + analysisGroup.Uuring as ResponseUuringuGrupp['Uuring'], + ); + log( + `Order has results in group '${analysisGroup.UuringuGruppNimi}' for ${groupUuringItems.length} analysis elements`, + ); - const results: Omit[] = []; + const results: Omit< + AnalysisResponseElement, + 'created_at' | 'updated_at' | 'id' | 'analysis_response_id' + >[] = []; for (const groupUuring of groupUuringItems) { const groupUuringElement = groupUuring.UuringuElement; const elementAnalysisResponses = toArray(groupUuringElement.UuringuVastus); const status = groupUuringElement.UuringOlek; - log(`Group uuring '${analysisGroup.UuringuGruppNimi}' has status ${status}`); + log( + `Group uuring '${analysisGroup.UuringuGruppNimi}' has status ${status}`, + ); for (const response of elementAnalysisResponses) { const analysisElementOriginalId = groupUuringElement.UuringId; @@ -135,12 +170,20 @@ export async function getAnalysisResponseElementsForGroup({ return valueAsNumber; })(); - if (!await canCreateAnalysisResponseElement({ existingElements, groupUuring, responseValue, log })) { + if ( + !(await canCreateAnalysisResponseElement({ + existingElements, + groupUuring, + responseValue, + log, + })) + ) { continue; } - const mappedResponse = createUserAnalysesApi(getSupabaseServerAdminClient()) - .mapUuringVastus({ uuringVastus: response }); + const mappedResponse = createUserAnalysesApi( + getSupabaseServerAdminClient(), + ).mapUuringVastus({ uuringVastus: response }); results.push({ analysis_element_original_id: analysisElementOriginalId, @@ -153,7 +196,8 @@ export async function getAnalysisResponseElementsForGroup({ response_value: mappedResponse.responseValue, unit: groupUuringElement.Mootyhik ?? null, original_response_element: groupUuringElement, - analysis_name: groupUuringElement.UuringNimi || groupUuringElement.KNimetus, + analysis_name: + groupUuringElement.UuringNimi || groupUuringElement.KNimetus, comment: groupUuringElement.UuringuKommentaar ?? null, status: status.toString(), response_value_is_within_norm: mappedResponse.responseValueIsWithinNorm, @@ -174,9 +218,14 @@ async function getNewAnalysisResponseElements({ existingElements: AnalysisResponseElement[]; log: ReturnType; }) { - const newElements: Omit[] = []; + const newElements: Omit< + AnalysisResponseElement, + 'created_at' | 'updated_at' | 'id' | 'analysis_response_id' + >[] = []; for (const analysisGroup of analysisGroups) { - log(`[${analysisGroups.indexOf(analysisGroup) + 1}/${analysisGroups.length}] Syncing analysis group '${analysisGroup.UuringuGruppNimi}'`); + log( + `[${analysisGroups.indexOf(analysisGroup) + 1}/${analysisGroups.length}] Syncing analysis group '${analysisGroup.UuringuGruppNimi}'`, + ); const elements = await getAnalysisResponseElementsForGroup({ analysisGroup, existingElements, @@ -194,7 +243,9 @@ async function hasAllAnalysisResponseElements({ analysisResponseId: number; order: Pick; }) { - const allOrderResponseElements = await getExistingAnalysisResponseElements({ analysisResponseId }); + const allOrderResponseElements = await getExistingAnalysisResponseElements({ + analysisResponseId, + }); const expectedOrderResponseElements = order.analysis_element_ids?.length ?? 0; return allOrderResponseElements.length >= expectedOrderResponseElements; } @@ -208,7 +259,10 @@ export async function syncPrivateMessage({ }, order, }: { - messageResponse: Pick, 'ValisTellimuseId' | 'TellimuseNumber' | 'TellimuseOlek' | 'UuringuGrupp'>; + messageResponse: Pick< + NonNullable, + 'ValisTellimuseId' | 'TellimuseNumber' | 'TellimuseOlek' | 'UuringuGrupp' + >; order: Tables<{ schema: 'medreport' }, 'analysis_orders'>; }) { const supabase = getSupabaseServerAdminClient(); @@ -232,11 +286,17 @@ export async function syncPrivateMessage({ userId: analysisOrder.user_id, }); - const existingElements = await getExistingAnalysisResponseElements({ analysisResponseId }); + const existingElements = await getExistingAnalysisResponseElements({ + analysisResponseId, + }); const analysisGroups = toArray(UuringuGrupp); log(`Order has results for ${analysisGroups.length} analysis groups`); - const newElements = await getNewAnalysisResponseElements({ analysisGroups, existingElements, log }); + const newElements = await getNewAnalysisResponseElements({ + analysisGroups, + existingElements, + log, + }); for (const element of newElements) { try { @@ -247,11 +307,14 @@ export async function syncPrivateMessage({ }, }); } catch (e) { - log(`Failed to create order response element for response id ${analysisResponseId}, element id '${element.analysis_element_original_id}' (order id: ${order.id})`, e as PostgrestError); + log( + `Failed to create order response element for response id ${analysisResponseId}, element id '${element.analysis_element_original_id}' (order id: ${order.id})`, + e as PostgrestError, + ); } } - return await hasAllAnalysisResponseElements({ analysisResponseId, order }) + return (await hasAllAnalysisResponseElements({ analysisResponseId, order })) ? { isCompleted: orderStatus === 'COMPLETED' } : { isPartial: true }; } @@ -276,7 +339,9 @@ export async function readPrivateMessageResponse({ let analysisOrderId: number | undefined = undefined; try { - const privateMessage = await getLatestPrivateMessageListItem({ excludedMessageIds }); + const privateMessage = await getLatestPrivateMessageListItem({ + excludedMessageIds, + }); messageId = privateMessage?.messageId ?? null; if (!privateMessage || !messageId) { @@ -286,17 +351,18 @@ export async function readPrivateMessageResponse({ hasPartialAnalysisResponse: false, hasFullAnalysisResponse: false, medusaOrderId: undefined, - analysisOrderId: undefined + analysisOrderId: undefined, }; } const { messageId: privateMessageId } = privateMessage; - const { message: privateMessageContent, xml: privateMessageXml } = await getPrivateMessage( - privateMessageId, - ); + const { message: privateMessageContent, xml: privateMessageXml } = + await getPrivateMessage(privateMessageId); const messageResponse = privateMessageContent?.Saadetis?.Vastus; - const medipostExternalOrderId = privateMessageContent?.Saadetis?.Tellimus?.ValisTellimuseId || messageResponse?.ValisTellimuseId; + const medipostExternalOrderId = + privateMessageContent?.Saadetis?.Tellimus?.ValisTellimuseId || + messageResponse?.ValisTellimuseId; const patientPersonalCode = messageResponse?.Patsient.Isikukood?.toString(); analysisOrderId = Number(medipostExternalOrderId); @@ -318,27 +384,36 @@ export async function readPrivateMessageResponse({ hasPartialAnalysisResponse: false, hasFullAnalysisResponse: false, medusaOrderId: hasInvalidOrderId ? undefined : medusaOrderId, - analysisOrderId: hasInvalidOrderId ? undefined : analysisOrderId + analysisOrderId: hasInvalidOrderId ? undefined : analysisOrderId, }; } let analysisOrder: AnalysisOrder; try { - analysisOrder = await getAnalysisOrder({ analysisOrderId }) + analysisOrder = await getAnalysisOrder({ analysisOrderId }); medusaOrderId = analysisOrder.medusa_order_id; } catch (e) { if (IS_ENABLED_DELETE_PRIVATE_MESSAGE) { await deletePrivateMessage(privateMessageId); } - throw new Error(`No analysis order found for Medipost message ValisTellimuseId=${medipostExternalOrderId}`); + throw new Error( + `No analysis order found for Medipost message ValisTellimuseId=${medipostExternalOrderId}`, + ); } - const orderPerson = await getAccountAdmin({ primaryOwnerUserId: analysisOrder.user_id }); + const orderPerson = await getAccountAdmin({ + primaryOwnerUserId: analysisOrder.user_id, + }); if (orderPerson.personal_code !== patientPersonalCode) { - throw new Error(`Order person personal code does not match Medipost message Patsient.Isikukood=${patientPersonalCode}, orderPerson.personal_code=${orderPerson.personal_code}`); + throw new Error( + `Order person personal code does not match Medipost message Patsient.Isikukood=${patientPersonalCode}, orderPerson.personal_code=${orderPerson.personal_code}`, + ); } - const status = await syncPrivateMessage({ messageResponse, order: analysisOrder }); + const status = await syncPrivateMessage({ + messageResponse, + order: analysisOrder, + }); await upsertMedipostActionLog({ action: 'sync_analysis_results_from_medipost', @@ -349,11 +424,17 @@ export async function readPrivateMessageResponse({ medipostExternalOrderId, }); if (status.isPartial) { - await updateAnalysisOrderStatus({ medusaOrderId, orderStatus: 'PARTIAL_ANALYSIS_RESPONSE' }); + await updateAnalysisOrderStatus({ + medusaOrderId, + orderStatus: 'PARTIAL_ANALYSIS_RESPONSE', + }); hasAnalysisResponse = true; hasPartialAnalysisResponse = true; } else if (status.isCompleted) { - await updateAnalysisOrderStatus({ medusaOrderId, orderStatus: 'FULL_ANALYSIS_RESPONSE' }); + await updateAnalysisOrderStatus({ + medusaOrderId, + orderStatus: 'FULL_ANALYSIS_RESPONSE', + }); if (IS_ENABLED_DELETE_PRIVATE_MESSAGE) { await deletePrivateMessage(privateMessageId); } @@ -361,10 +442,19 @@ export async function readPrivateMessageResponse({ hasFullAnalysisResponse = true; } } catch (e) { - console.warn(`Failed to process private message id=${messageId}, message=${(e as Error).message}`); + console.warn( + `Failed to process private message id=${messageId}, message=${(e as Error).message}`, + ); } - return { messageId, hasAnalysisResponse, hasPartialAnalysisResponse, hasFullAnalysisResponse, medusaOrderId, analysisOrderId }; + return { + messageId, + hasAnalysisResponse, + hasPartialAnalysisResponse, + hasFullAnalysisResponse, + medusaOrderId, + analysisOrderId, + }; } export async function deletePrivateMessage(messageId: string) { @@ -430,7 +520,9 @@ export async function sendOrderToMedipost({ orderedAnalysisElements: OrderedAnalysisElement[]; }) { const medreportOrder = await getAnalysisOrder({ medusaOrderId }); - const account = await getAccountAdmin({ primaryOwnerUserId: medreportOrder.user_id }); + const account = await getAccountAdmin({ + primaryOwnerUserId: medreportOrder.user_id, + }); const orderedAnalysesIds = orderedAnalysisElements .map(({ analysisId }) => analysisId) @@ -441,11 +533,17 @@ export async function sendOrderToMedipost({ const analyses = await getAnalyses({ ids: orderedAnalysesIds }); if (analyses.length !== orderedAnalysesIds.length) { - throw new Error(`Got ${analyses.length} analyses, expected ${orderedAnalysesIds.length}`); + throw new Error( + `Got ${analyses.length} analyses, expected ${orderedAnalysesIds.length}`, + ); } - const analysisElements = await getAnalysisElementsAdmin({ ids: orderedAnalysisElementsIds }); + const analysisElements = await getAnalysisElementsAdmin({ + ids: orderedAnalysisElementsIds, + }); if (analysisElements.length !== orderedAnalysisElementsIds.length) { - throw new Error(`Got ${analysisElements.length} analysis elements, expected ${orderedAnalysisElementsIds.length}`); + throw new Error( + `Got ${analysisElements.length} analysis elements, expected ${orderedAnalysisElementsIds.length}`, + ); } const orderXml = await composeOrderXML({ diff --git a/lib/services/medipost/medipostPublicMessage.service.ts b/lib/services/medipost/medipostPublicMessage.service.ts index c6c823e..a8aac96 100644 --- a/lib/services/medipost/medipostPublicMessage.service.ts +++ b/lib/services/medipost/medipostPublicMessage.service.ts @@ -1,9 +1,6 @@ 'use server'; -import { - GetMessageListResponse, - MedipostAction, -} from '@/lib/types/medipost'; +import { GetMessageListResponse, MedipostAction } from '@/lib/types/medipost'; import axios from 'axios'; import { getLatestMessage } from './medipostMessageBase.service'; diff --git a/lib/services/medipost/medipostTest.service.ts b/lib/services/medipost/medipostTest.service.ts index a7ce270..fdb0bfe 100644 --- a/lib/services/medipost/medipostTest.service.ts +++ b/lib/services/medipost/medipostTest.service.ts @@ -8,14 +8,13 @@ import { getPatient, getProviderInstitution, } from '@/lib/templates/medipost-order'; -import { - MedipostAction, -} from '@/lib/types/medipost'; +import { MedipostAction } from '@/lib/types/medipost'; import axios from 'axios'; +import { formatDate } from 'date-fns'; import { uniqBy } from 'lodash'; import { Tables } from '@kit/supabase/database'; -import { formatDate } from 'date-fns'; + import { getAnalyses } from '../analyses.service'; import { getAnalysisElementsAdmin } from '../analysis-element.service'; import { validateMedipostResponse } from './medipostValidate.service'; @@ -71,7 +70,9 @@ export async function composeOrderTestResponseXML({ orderId: number; orderCreatedAt: Date; }) { - const analysisElements = await getAnalysisElementsAdmin({ ids: orderedAnalysisElementsIds }); + const analysisElements = await getAnalysisElementsAdmin({ + ids: orderedAnalysisElementsIds, + }); const analyses = await getAnalyses({ ids: orderedAnalysesIds }); const analysisGroups: Tables<{ schema: 'medreport' }, 'analysis_groups'>[] = @@ -94,13 +95,15 @@ export async function composeOrderTestResponseXML({ const orderNumber = orderId; const allAnalysisElementsForGroups = analysisElements?.filter((element) => { - return analysisGroups.some((group) => group.id === element.analysis_groups.id); + return analysisGroups.some( + (group) => group.id === element.analysis_groups.id, + ); }); const addedIds = new Set(); return ` - ${getPais(USER, RECIPIENT, orderId, "AL")} + ${getPais(USER, RECIPIENT, orderId, 'AL')} ${orderId} ${getClientInstitution({ index: 1 })} @@ -126,38 +129,54 @@ export async function composeOrderTestResponseXML({ ${orderNumber} ${orderStatus} - ${allAnalysisElementsForGroups.map((analysisElement) => { - const group = analysisGroups.find((group) => group.id === analysisElement.analysis_groups.id); - if (!group) { - throw new Error(`Failed to find group for analysis element ${analysisElement.id}`); - } + ${allAnalysisElementsForGroups + .map((analysisElement) => { + const group = analysisGroups.find( + (group) => group.id === analysisElement.analysis_groups.id, + ); + if (!group) { + throw new Error( + `Failed to find group for analysis element ${analysisElement.id}`, + ); + } - let relatedAnalysisElement = analysisElements?.find( - (element) => element.analysis_groups.id === group.id && !addedIds.has(element.id), - ); - const relatedAnalyses = analyses?.filter((analysis) => { - return analysis.analysis_elements.analysis_groups.id === group.id && !addedIds.has(analysis.analysis_elements.id); - }); + let relatedAnalysisElement = analysisElements?.find( + (element) => + element.analysis_groups.id === group.id && + !addedIds.has(element.id), + ); + const relatedAnalyses = analyses?.filter((analysis) => { + return ( + analysis.analysis_elements.analysis_groups.id === group.id && + !addedIds.has(analysis.analysis_elements.id) + ); + }); - if (!relatedAnalysisElement) { - relatedAnalysisElement = relatedAnalyses?.find( - (relatedAnalysis) => - relatedAnalysis.analysis_elements.analysis_groups.id === - group.id, - )?.analysis_elements; - } + if (!relatedAnalysisElement) { + relatedAnalysisElement = relatedAnalyses?.find( + (relatedAnalysis) => + relatedAnalysis.analysis_elements.analysis_groups.id === + group.id, + )?.analysis_elements; + } - if (!relatedAnalysisElement || !relatedAnalysisElement.material_groups) { - throw new Error( - `Failed to find related analysis element for group ${group.name} (id: ${group.id})`, - ); - } + if ( + !relatedAnalysisElement || + !relatedAnalysisElement.material_groups + ) { + throw new Error( + `Failed to find related analysis element for group ${group.name} (id: ${group.id})`, + ); + } - const lower = getRandomInt(0, 100); - const upper = getRandomInt(lower + 1, 500); - const result = getRandomInt(lower - Math.floor(lower * 0.1), upper + Math.floor(upper * 0.1)); - addedIds.add(relatedAnalysisElement.id); - return (` + const lower = getRandomInt(0, 100); + const upper = getRandomInt(lower + 1, 500); + const result = getRandomInt( + lower - Math.floor(lower * 0.1), + upper + Math.floor(upper * 0.1), + ); + addedIds.add(relatedAnalysisElement.id); + return ` ${group.original_id} ${group.name} @@ -177,15 +196,16 @@ export async function composeOrderTestResponseXML({ ${formatDate(new Date(), 'yyyy-MM-dd HH:mm:ss')} ${upper} ${lower} - ${result < lower ? 1 : (result > upper ? 1 : 0)} + ${result < lower ? 1 : result > upper ? 1 : 0} 1 2 - `); - }).join('')} + `; + }) + .join('')} `; } diff --git a/lib/services/medipost/medipostValidate.service.ts b/lib/services/medipost/medipostValidate.service.ts index aa85192..54a7bc4 100644 --- a/lib/services/medipost/medipostValidate.service.ts +++ b/lib/services/medipost/medipostValidate.service.ts @@ -1,25 +1,26 @@ 'use server'; -import type { - IMedipostResponseXMLBase, -} from '@/packages/shared/src/types/medipost-analysis'; +import type { IMedipostResponseXMLBase } from '@/packages/shared/src/types/medipost-analysis'; -import { MedipostValidationError } from './MedipostValidationError'; import { parseXML } from '../util/xml.service'; +import { MedipostValidationError } from './MedipostValidationError'; -export async function validateMedipostResponse(response: string, { canHaveEmptyCode = false }: { canHaveEmptyCode?: boolean } = {}) { +export async function validateMedipostResponse( + response: string, + { canHaveEmptyCode = false }: { canHaveEmptyCode?: boolean } = {}, +) { const parsed: IMedipostResponseXMLBase = await parseXML(response); const code = parsed.ANSWER?.CODE; if (canHaveEmptyCode) { if (code && code !== 0) { - console.error("Bad response", response); + console.error('Bad response', response); throw new MedipostValidationError(response); } return; } if (typeof code !== 'number' || (code !== 0 && !canHaveEmptyCode)) { - console.error("Bad response", response); + console.error('Bad response', response); throw new MedipostValidationError(response); } } diff --git a/lib/services/medipost/medipostXML.service.ts b/lib/services/medipost/medipostXML.service.ts index 1b1f7d3..b3541bc 100644 --- a/lib/services/medipost/medipostXML.service.ts +++ b/lib/services/medipost/medipostXML.service.ts @@ -11,15 +11,14 @@ import { getProviderInstitution, getSpecimen, } from '@/lib/templates/medipost-order'; -import { - MaterjalideGrupp, -} from '@/lib/types/medipost'; -import { toArray } from '@kit/shared/utils'; +import { MaterjalideGrupp } from '@/lib/types/medipost'; import { uniqBy } from 'lodash'; +import { toArray } from '@kit/shared/utils'; import { Tables } from '@kit/supabase/database'; -import { AnalysisElement } from '../analysis-element.service'; + import { AnalysesWithGroupsAndElements } from '../analyses.service'; +import { AnalysisElement } from '../analysis-element.service'; const USER = process.env.MEDIPOST_USER!; const RECIPIENT = process.env.MEDIPOST_RECIPIENT!; @@ -27,7 +26,7 @@ const RECIPIENT = process.env.MEDIPOST_RECIPIENT!; export type OrderedAnalysisElement = { analysisElementId?: number; analysisId?: number; -} +}; export async function composeOrderXML({ analyses, @@ -63,24 +62,32 @@ export async function composeOrderXML({ ); // First, collect all unique materials across all analysis groups - const uniqueMaterials = new Map(); + const uniqueMaterials = new Map< + string, + { + MaterjaliTyypOID: string; + MaterjaliTyyp: string; + MaterjaliNimi: string; + ProovinouKoodOID?: string; + ProovinouKood?: string; + order: number; + } + >(); let specimenOrder = 1; // Collect all materials from all analysis groups for (const currentGroup of analysisGroups) { - let relatedAnalysisElements = analysisElements?.filter(({ analysis_groups }) => analysis_groups.id === currentGroup.id); + let relatedAnalysisElements = analysisElements?.filter( + ({ analysis_groups }) => analysis_groups.id === currentGroup.id, + ); if (!relatedAnalysisElements || relatedAnalysisElements.length === 0) { relatedAnalysisElements = analyses - .filter(({ analysis_elements }) => analysis_elements.analysis_groups.id === currentGroup.id) + .filter( + ({ analysis_elements }) => + analysis_elements.analysis_groups.id === currentGroup.id, + ) .flatMap(({ analysis_elements }) => analysis_elements); } @@ -91,7 +98,9 @@ export async function composeOrderXML({ } for (const analysisElement of relatedAnalysisElements) { - for (const { Materjal } of analysisElement.material_groups as MaterjalideGrupp[]) { + for (const { + Materjal, + } of analysisElement.material_groups as MaterjalideGrupp[]) { for (const material of toArray(Materjal)) { const { MaterjaliTyyp } = material; @@ -115,7 +124,7 @@ export async function composeOrderXML({ } // Generate specimen section from unique materials - const specimenSection = Array.from(uniqueMaterials.values()).map(material => + const specimenSection = Array.from(uniqueMaterials.values()).map((material) => getSpecimen( material.MaterjaliTyypOID, material.MaterjaliTyyp, @@ -123,7 +132,7 @@ export async function composeOrderXML({ material.order, material.ProovinouKoodOID, material.ProovinouKood, - ) + ), ); // Generate analysis section with correct specimen references @@ -135,7 +144,10 @@ export async function composeOrderXML({ if (!relatedAnalysisElements) { relatedAnalysisElements = analyses - .filter(({ analysis_elements }) => analysis_elements.analysis_groups.id === currentGroup.id) + .filter( + ({ analysis_elements }) => + analysis_elements.analysis_groups.id === currentGroup.id, + ) .flatMap(({ analysis_elements }) => analysis_elements); } @@ -146,8 +158,8 @@ export async function composeOrderXML({ } const uuringElementInputs: { - analysisElement: Tables<{ schema: 'medreport' }, 'analysis_elements'>, - specimenOrderNr: number, + analysisElement: Tables<{ schema: 'medreport' }, 'analysis_elements'>; + specimenOrderNr: number; }[] = []; for (const analysisElement of relatedAnalysisElements) { for (const group of analysisElement.material_groups as MaterjalideGrupp[]) { @@ -155,7 +167,9 @@ export async function composeOrderXML({ for (const material of materials) { const uniqueMaterial = uniqueMaterials.get(material.MaterjaliTyyp); if (!uniqueMaterial) { - console.info(`Unique material not found for material: ${material.MaterjaliTyyp}, analysis element: ${analysisElement.id} ${analysisElement.analysis_id_original} ${analysisElement.analysis_name_lab}`); + console.info( + `Unique material not found for material: ${material.MaterjaliTyyp}, analysis element: ${analysisElement.id} ${analysisElement.analysis_id_original} ${analysisElement.analysis_name_lab}`, + ); continue; } uuringElementInputs.push({ @@ -177,7 +191,7 @@ export async function composeOrderXML({ return ` - ${getPais(USER, RECIPIENT, orderId, "OL")} + ${getPais(USER, RECIPIENT, orderId, 'OL')} ${orderId} ${getClientInstitution()} diff --git a/lib/services/medusaOrder.service.ts b/lib/services/medusaOrder.service.ts index 5b3396f..7bf5ff4 100644 --- a/lib/services/medusaOrder.service.ts +++ b/lib/services/medusaOrder.service.ts @@ -1,11 +1,12 @@ 'use server'; -import { getAnalysisElements } from './analysis-element.service'; -import { getAnalyses } from './analyses.service'; -import { StoreOrder } from '@medusajs/types'; +import { getAnalysisElementMedusaProductIds } from '@/utils/medusa-product'; import { listProducts } from '@lib/data/products'; import { listRegions } from '@lib/data/regions'; -import { getAnalysisElementMedusaProductIds } from '@/utils/medusa-product'; +import { StoreOrder } from '@medusajs/types'; + +import { getAnalyses } from './analyses.service'; +import { getAnalysisElements } from './analysis-element.service'; const ANALYSIS_PACKAGE_HANDLE_PREFIX = 'analysis-package-'; @@ -13,10 +14,12 @@ export async function getOrderedAnalysisIds({ medusaOrder, }: { medusaOrder: StoreOrder; -}): Promise<{ - analysisElementId?: number; - analysisId?: number; -}[]> { +}): Promise< + { + analysisElementId?: number; + analysisId?: number; + }[] +> { const countryCodes = await listRegions(); const countryCode = countryCodes[0]!.countries![0]!.iso_2!; @@ -37,54 +40,76 @@ export async function getOrderedAnalysisIds({ } async function getOrderedAnalysisPackages(medusaOrder: StoreOrder) { - const orderedPackages = (medusaOrder?.items ?? []).filter(({ product }) => product?.handle.startsWith(ANALYSIS_PACKAGE_HANDLE_PREFIX)); - const orderedPackageIds = orderedPackages.map(({ product }) => product?.id).filter(Boolean) as string[]; + const orderedPackages = (medusaOrder?.items ?? []).filter(({ product }) => + product?.handle.startsWith(ANALYSIS_PACKAGE_HANDLE_PREFIX), + ); + const orderedPackageIds = orderedPackages + .map(({ product }) => product?.id) + .filter(Boolean) as string[]; if (orderedPackageIds.length === 0) { return []; } console.info(`Order has ${orderedPackageIds.length} packages`); - const { response: { products: orderedPackagesProducts } } = await listProducts({ + const { + response: { products: orderedPackagesProducts }, + } = await listProducts({ countryCode, queryParams: { limit: 100, id: orderedPackageIds }, }); - console.info(`Order has ${orderedPackagesProducts.length} packages = ${JSON.stringify(orderedPackageIds, null, 2)}`); + console.info( + `Order has ${orderedPackagesProducts.length} packages = ${JSON.stringify(orderedPackageIds, null, 2)}`, + ); if (orderedPackagesProducts.length !== orderedPackageIds.length) { - throw new Error(`Got ${orderedPackagesProducts.length} ordered packages products, expected ${orderedPackageIds.length}`); + throw new Error( + `Got ${orderedPackagesProducts.length} ordered packages products, expected ${orderedPackageIds.length}`, + ); } const ids = getAnalysisElementMedusaProductIds( orderedPackagesProducts.map(({ id, metadata }) => ({ metadata, - variant: orderedPackages.find(({ product }) => product?.id === id)?.variant, + variant: orderedPackages.find(({ product }) => product?.id === id) + ?.variant, })), ); if (ids.length === 0) { return []; } - const { response: { products: analysisPackagesProducts } } = await listProducts({ + const { + response: { products: analysisPackagesProducts }, + } = await listProducts({ countryCode, queryParams: { limit: 100, id: ids }, }); if (analysisPackagesProducts.length !== ids.length) { - throw new Error(`Got ${analysisPackagesProducts.length} analysis packages products, expected ${ids.length}`); + throw new Error( + `Got ${analysisPackagesProducts.length} analysis packages products, expected ${ids.length}`, + ); } const originalIds = analysisPackagesProducts .map(({ metadata }) => metadata?.analysisIdOriginal) .filter((id) => typeof id === 'string'); if (originalIds.length !== ids.length) { - throw new Error(`Got ${originalIds.length} analysis packages products with analysisIdOriginal, expected ${ids.length}`); + throw new Error( + `Got ${originalIds.length} analysis packages products with analysisIdOriginal, expected ${ids.length}`, + ); } const analysisElements = await getAnalysisElements({ originalIds }); return analysisElements.map(({ id }) => ({ analysisElementId: id })); } - const [analysisPackageElements, orderedAnalysisElements, orderedAnalyses] = await Promise.all([ - getOrderedAnalysisPackages(medusaOrder), - getOrderedAnalysisElements(medusaOrder), - getOrderedAnalyses(medusaOrder), - ]); + const [analysisPackageElements, orderedAnalysisElements, orderedAnalyses] = + await Promise.all([ + getOrderedAnalysisPackages(medusaOrder), + getOrderedAnalysisElements(medusaOrder), + getOrderedAnalyses(medusaOrder), + ]); - return [...analysisPackageElements, ...orderedAnalysisElements, ...orderedAnalyses]; + return [ + ...analysisPackageElements, + ...orderedAnalysisElements, + ...orderedAnalyses, + ]; } diff --git a/lib/services/order.service.ts b/lib/services/order.service.ts index 4e934fd..7edb7f7 100644 --- a/lib/services/order.service.ts +++ b/lib/services/order.service.ts @@ -1,7 +1,9 @@ -import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; -import type { Tables } from '@kit/supabase/database'; -import { getSupabaseServerClient } from '@kit/supabase/server-client'; import type { StoreOrder } from '@medusajs/types'; + +import type { Tables } from '@kit/supabase/database'; +import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; +import { getSupabaseServerClient } from '@kit/supabase/server-client'; + import type { AnalysisOrder } from '../types/analysis-order'; export async function createAnalysisOrder({ @@ -9,19 +11,29 @@ export async function createAnalysisOrder({ orderedAnalysisElements, }: { medusaOrder: StoreOrder; - orderedAnalysisElements: { analysisElementId?: number; analysisId?: number }[]; + orderedAnalysisElements: { + analysisElementId?: number; + analysisId?: number; + }[]; }) { const supabase = getSupabaseServerClient(); - const { data: { user } } = await supabase.auth.getUser(); + const { + data: { user }, + } = await supabase.auth.getUser(); if (!user) { throw new Error('User not found'); } - const orderResult = await supabase.schema('medreport') + const orderResult = await supabase + .schema('medreport') .from('analysis_orders') .insert({ - analysis_element_ids: orderedAnalysisElements.map(({ analysisElementId }) => analysisElementId).filter(Boolean) as number[], - analysis_ids: orderedAnalysisElements.map(({ analysisId }) => analysisId).filter(Boolean) as number[], + analysis_element_ids: orderedAnalysisElements + .map(({ analysisElementId }) => analysisElementId) + .filter(Boolean) as number[], + analysis_ids: orderedAnalysisElements + .map(({ analysisId }) => analysisId) + .filter(Boolean) as number[], status: 'QUEUED', user_id: user.id, medusa_order_id: medusaOrder.id, @@ -31,7 +43,9 @@ export async function createAnalysisOrder({ .throwOnError(); if (orderResult.error || !orderResult.data?.id) { - throw new Error(`Failed to create order, message=${orderResult.error}, data=${JSON.stringify(orderResult)}`); + throw new Error( + `Failed to create order, message=${orderResult.error}, data=${JSON.stringify(orderResult)}`, + ); } return orderResult.data.id; @@ -89,7 +103,7 @@ export async function getAnalysisOrder({ const query = getSupabaseServerAdminClient() .schema('medreport') .from('analysis_orders') - .select('*') + .select('*'); if (medusaOrderId) { query.eq('medusa_order_id', medusaOrderId); } else if (analysisOrderId) { @@ -100,7 +114,9 @@ export async function getAnalysisOrder({ const { data: order, error } = await query.single(); if (error) { - throw new Error(`Failed to get order by medusaOrderId=${medusaOrderId} or analysisOrderId=${analysisOrderId}, message=${error.message}, data=${JSON.stringify(order)}`); + throw new Error( + `Failed to get order by medusaOrderId=${medusaOrderId} or analysisOrderId=${analysisOrderId}, message=${error.message}, data=${JSON.stringify(order)}`, + ); } return order as AnalysisOrder; } @@ -111,7 +127,7 @@ export async function getAnalysisOrders({ orderStatus?: Tables<{ schema: 'medreport' }, 'analysis_orders'>['status']; } = {}) { const client = getSupabaseServerClient(); - + const { data: { user }, } = await client.auth.getUser(); @@ -123,11 +139,13 @@ export async function getAnalysisOrders({ .schema('medreport') .from('analysis_orders') .select('*') - .eq("user_id", user.id) + .eq('user_id', user.id); if (orderStatus) { query.eq('status', orderStatus); } - const orders = await query.order('created_at', { ascending: false }).throwOnError(); + const orders = await query + .order('created_at', { ascending: false }) + .throwOnError(); return orders.data; } @@ -141,13 +159,15 @@ export async function getAnalysisOrdersAdmin({ const query = getSupabaseServerAdminClient() .schema('medreport') .from('analysis_orders') - .select('*') + .select('*'); if (orderStatus) { query.eq('status', orderStatus); } if (medusaOrderId) { query.eq('medusa_order_id', medusaOrderId); } - const orders = await query.order('created_at', { ascending: false }).throwOnError(); + const orders = await query + .order('created_at', { ascending: false }) + .throwOnError(); return orders.data; } diff --git a/lib/services/sync-entries.service.ts b/lib/services/sync-entries.service.ts index 01ca7bb..e3e5f48 100644 --- a/lib/services/sync-entries.service.ts +++ b/lib/services/sync-entries.service.ts @@ -1,4 +1,5 @@ import { format } from 'date-fns'; + import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; export const getLastCheckedDate = async () => { @@ -15,4 +16,4 @@ export const getLastCheckedDate = async () => { : null; return lastCheckedDate; -} +}; diff --git a/lib/templates/medipost-order.ts b/lib/templates/medipost-order.ts index 46a9e8a..21e53c6 100644 --- a/lib/templates/medipost-order.ts +++ b/lib/templates/medipost-order.ts @@ -1,6 +1,7 @@ -import { format } from 'date-fns'; -import { Tables } from '@/packages/supabase/src/database.types'; import { DATE_FORMAT, DATE_TIME_FORMAT } from '@/lib/constants'; +import { Tables } from '@/packages/supabase/src/database.types'; +import { format } from 'date-fns'; + import PersonalCode from '../utils'; const isProd = process.env.NODE_ENV === 'production'; @@ -65,9 +66,9 @@ export const getPatient = ({ lastName, firstName, }: { - idCode: string, - lastName: string, - firstName: string, + idCode: string; + lastName: string; + firstName: string; }) => { const { dob, gender } = PersonalCode.parsePersonalCode(idCode); return ` @@ -149,16 +150,19 @@ export const getAnalysisGroup = ( analysisGroupOriginalId: string, analysisGroupName: string, uuringElementInputs: { - analysisElement: Tables<{ schema: 'medreport' }, 'analysis_elements'>, - specimenOrderNr: number, + analysisElement: Tables<{ schema: 'medreport' }, 'analysis_elements'>; + specimenOrderNr: number; }[], ) => { - const uuringElements = uuringElementInputs.map(({ analysisElement, specimenOrderNr }) => - ` + const uuringElements = uuringElementInputs + .map( + ({ analysisElement, specimenOrderNr }) => + ` ${getAnalysisElement(analysisElement.analysis_id_oid, analysisElement.analysis_id_original, analysisElement.tehik_short_loinc, analysisElement.tehik_loinc_name, analysisElement.id, analysisElement.analysis_name_lab)} ${specimenOrderNr} - ` - ).join(''); + `, + ) + .join(''); return ` ${analysisGroupOriginalId} diff --git a/lib/types/analysis-response-element.ts b/lib/types/analysis-response-element.ts index db5b20f..7928ce7 100644 --- a/lib/types/analysis-response-element.ts +++ b/lib/types/analysis-response-element.ts @@ -1,3 +1,4 @@ -import type { Database } from "@/packages/supabase/src/database.types"; +import type { Database } from '@/packages/supabase/src/database.types'; -export type AnalysisResponseElement = Database['medreport']['Tables']['analysis_response_elements']['Row']; +export type AnalysisResponseElement = + Database['medreport']['Tables']['analysis_response_elements']['Row']; diff --git a/lib/types/audit.ts b/lib/types/audit.ts index a4985ab..8737ec3 100644 --- a/lib/types/audit.ts +++ b/lib/types/audit.ts @@ -1,9 +1,9 @@ export enum SyncStatus { - Success = "SUCCESS", - Fail = "FAIL", + Success = 'SUCCESS', + Fail = 'FAIL', } export enum RequestStatus { - Success = "SUCCESS", - Fail = "FAIL", + Success = 'SUCCESS', + Fail = 'FAIL', } diff --git a/lib/types/medipost.ts b/lib/types/medipost.ts index b8228fb..645c262 100644 --- a/lib/types/medipost.ts +++ b/lib/types/medipost.ts @@ -1,4 +1,4 @@ -import type { IMedipostResponseXMLBase } from "@/packages/shared/src/types/medipost-analysis"; +import type { IMedipostResponseXMLBase } from '@/packages/shared/src/types/medipost-analysis'; export type Message = { messageId: string; diff --git a/lib/utils.ts b/lib/utils.ts index 70a6054..d9d0f96 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -15,7 +15,7 @@ export function toTitleCase(str?: string) { ?.toLowerCase() .replace(/[^-'’\s]+/g, (match) => match.replace(/^./, (first) => first.toUpperCase()), - ) ?? "" + ) ?? '' ); } @@ -140,6 +140,6 @@ export default class PersonalCode { gender, dob: parsed.getBirthday(), age: parsed.getAge(), - } + }; } } diff --git a/lib/validations/company-offer.schema.ts b/lib/validations/company-offer.schema.ts index a8ab60e..4d519f2 100644 --- a/lib/validations/company-offer.schema.ts +++ b/lib/validations/company-offer.schema.ts @@ -7,9 +7,8 @@ export const companyOfferSchema = z.object({ contactPerson: z.string({ error: 'Contact person is required', }), - email: z - .email({ - error: 'Invalid email', - }), + email: z.email({ + error: 'Invalid email', + }), phone: z.string().optional(), }); diff --git a/packages/analytics/README.md b/packages/analytics/README.md index cd57b92..134c982 100644 --- a/packages/analytics/README.md +++ b/packages/analytics/README.md @@ -2,4 +2,4 @@ @kit/analytics Package provides a simple and consistent API for tracking analytics events in web applications. -Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/analytics/analytics-and-events). \ No newline at end of file +Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/analytics/analytics-and-events). diff --git a/packages/billing/core/README.md b/packages/billing/core/README.md index 2bea63b..fca1a9f 100644 --- a/packages/billing/core/README.md +++ b/packages/billing/core/README.md @@ -6,9 +6,9 @@ Make sure the app installs the `@kit/billing` package before using it. ```json { - "name": "my-app", - "dependencies": { - "@kit/billing": "*" - } + "name": "my-app", + "dependencies": { + "@kit/billing": "*" + } } -``` \ No newline at end of file +``` diff --git a/packages/billing/core/src/create-billing-schema.ts b/packages/billing/core/src/create-billing-schema.ts index 4f26cbb..925026c 100644 --- a/packages/billing/core/src/create-billing-schema.ts +++ b/packages/billing/core/src/create-billing-schema.ts @@ -25,21 +25,32 @@ export const LineItemSchema = z .describe('Unique identifier for the line item. Defined by the Provider.') .min(1), name: z - .string().describe('Name of the line item. Displayed to the user.') + .string() + .describe('Name of the line item. Displayed to the user.') .min(1), description: z - .string().describe('Description of the line item. Displayed to the user and will replace the auto-generated description inferred' + - ' from the line item. This is useful if you want to provide a more detailed description to the user.') + .string() + .describe( + 'Description of the line item. Displayed to the user and will replace the auto-generated description inferred' + + ' from the line item. This is useful if you want to provide a more detailed description to the user.', + ) .optional(), cost: z - .number().describe('Cost of the line item. Displayed to the user.') + .number() + .describe('Cost of the line item. Displayed to the user.') .min(0), type: LineItemTypeSchema, unit: z - .string().describe('Unit of the line item. Displayed to the user. Example "seat" or "GB"') + .string() + .describe( + 'Unit of the line item. Displayed to the user. Example "seat" or "GB"', + ) .optional(), setupFee: z - .number().describe(`Lemon Squeezy only: If true, in addition to the cost, a setup fee will be charged.`) + .number() + .describe( + `Lemon Squeezy only: If true, in addition to the cost, a setup fee will be charged.`, + ) .positive() .optional(), tiers: z @@ -78,10 +89,12 @@ export const LineItemSchema = z export const PlanSchema = z .object({ id: z - .string().describe('Unique identifier for the plan. Defined by yourself.') + .string() + .describe('Unique identifier for the plan. Defined by yourself.') .min(1), name: z - .string().describe('Name of the plan. Displayed to the user.') + .string() + .describe('Name of the plan. Displayed to the user.') .min(1), interval: BillingIntervalSchema.optional(), custom: z.boolean().default(false).optional(), @@ -106,7 +119,10 @@ export const PlanSchema = z }, ), trialDays: z - .number().describe('Number of days for the trial period. Leave empty for no trial.') + .number() + .describe( + 'Number of days for the trial period. Leave empty for no trial.', + ) .positive() .optional(), paymentType: PaymentTypeSchema, @@ -188,34 +204,43 @@ export const PlanSchema = z const ProductSchema = z .object({ id: z - .string().describe('Unique identifier for the product. Defined by th Provider.') + .string() + .describe('Unique identifier for the product. Defined by th Provider.') .min(1), name: z - .string().describe('Name of the product. Displayed to the user.') + .string() + .describe('Name of the product. Displayed to the user.') .min(1), description: z - .string().describe('Description of the product. Displayed to the user.') + .string() + .describe('Description of the product. Displayed to the user.') .min(1), currency: z - .string().describe('Currency code for the product. Displayed to the user.') + .string() + .describe('Currency code for the product. Displayed to the user.') .min(3) .max(3), badge: z - .string().describe('Badge for the product. Displayed to the user. Example: "Popular"') + .string() + .describe( + 'Badge for the product. Displayed to the user. Example: "Popular"', + ) .optional(), features: z - .array( - z.string(), - ).describe('Features of the product. Displayed to the user.') + .array(z.string()) + .describe('Features of the product. Displayed to the user.') .nonempty(), enableDiscountField: z - .boolean().describe('Enable discount field for the product in the checkout.') + .boolean() + .describe('Enable discount field for the product in the checkout.') .optional(), highlighted: z - .boolean().describe('Highlight this product. Displayed to the user.') + .boolean() + .describe('Highlight this product. Displayed to the user.') .optional(), hidden: z - .boolean().describe('Hide this product from being displayed to users.') + .boolean() + .describe('Hide this product from being displayed to users.') .optional(), plans: z.array(PlanSchema), }) diff --git a/packages/billing/core/src/schema/report-billing-usage.schema.ts b/packages/billing/core/src/schema/report-billing-usage.schema.ts index 874b922..d213b42 100644 --- a/packages/billing/core/src/schema/report-billing-usage.schema.ts +++ b/packages/billing/core/src/schema/report-billing-usage.schema.ts @@ -1,7 +1,11 @@ import { z } from 'zod'; export const ReportBillingUsageSchema = z.object({ - id: z.string().describe('The id of the usage record. For Stripe a customer ID, for LS a subscription item ID.'), + id: z + .string() + .describe( + 'The id of the usage record. For Stripe a customer ID, for LS a subscription item ID.', + ), eventName: z .string() .describe('The name of the event that triggered the usage') diff --git a/packages/billing/core/src/services/billing-webhook-handler.service.ts b/packages/billing/core/src/services/billing-webhook-handler.service.ts index 0a047b9..e9982d2 100644 --- a/packages/billing/core/src/services/billing-webhook-handler.service.ts +++ b/packages/billing/core/src/services/billing-webhook-handler.service.ts @@ -24,9 +24,7 @@ export interface IHandleWebhookEventParams { // this method is called when an invoice is paid. We don't have a specific use case for this // but it's extremely common for credit-based systems - onInvoicePaid: ( - subscription: UpsertSubscriptionParams, - ) => Promise; + onInvoicePaid: (subscription: UpsertSubscriptionParams) => Promise; // generic handler for any event onEvent?: (data: unknown) => Promise; diff --git a/packages/billing/gateway/README.md b/packages/billing/gateway/README.md index 0cd1e8a..2f27c58 100644 --- a/packages/billing/gateway/README.md +++ b/packages/billing/gateway/README.md @@ -1,3 +1,3 @@ # Billing - @kit/billing-gateway -This package is responsible for handling all billing related operations. It is a gateway to the billing service. \ No newline at end of file +This package is responsible for handling all billing related operations. It is a gateway to the billing service. diff --git a/packages/billing/gateway/src/components/embedded-checkout.tsx b/packages/billing/gateway/src/components/embedded-checkout.tsx index 9b25408..47eae27 100644 --- a/packages/billing/gateway/src/components/embedded-checkout.tsx +++ b/packages/billing/gateway/src/components/embedded-checkout.tsx @@ -107,7 +107,7 @@ function BlurryBackdrop() { return (
diff --git a/packages/billing/gateway/src/components/plan-picker.tsx b/packages/billing/gateway/src/components/plan-picker.tsx index bd593eb..fa7fdd1 100644 --- a/packages/billing/gateway/src/components/plan-picker.tsx +++ b/packages/billing/gateway/src/components/plan-picker.tsx @@ -317,7 +317,7 @@ export function PlanPicker(
diff --git a/packages/billing/lemon-squeezy/README.md b/packages/billing/lemon-squeezy/README.md index 044c05a..dd77626 100644 --- a/packages/billing/lemon-squeezy/README.md +++ b/packages/billing/lemon-squeezy/README.md @@ -2,4 +2,4 @@ This package is responsible for handling all billing related operations using Lemon Squeezy. -Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/billing/lemon-squeezy). \ No newline at end of file +Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/billing/lemon-squeezy). diff --git a/packages/billing/montonio/README.md b/packages/billing/montonio/README.md index 608cb7b..b6f276e 100644 --- a/packages/billing/montonio/README.md +++ b/packages/billing/montonio/README.md @@ -1,4 +1,3 @@ # Billing / Montonio - @kit/montonio This package is responsible for handling all billing related operations using Montonio. - diff --git a/packages/billing/montonio/src/schema/montonio-client-env.schema.ts b/packages/billing/montonio/src/schema/montonio-client-env.schema.ts index eadb056..4806f98 100644 --- a/packages/billing/montonio/src/schema/montonio-client-env.schema.ts +++ b/packages/billing/montonio/src/schema/montonio-client-env.schema.ts @@ -1,6 +1,5 @@ import { z } from 'zod'; -export const MontonioClientEnvSchema = z - .object({ - accessKey: z.string().min(1), - }); +export const MontonioClientEnvSchema = z.object({ + accessKey: z.string().min(1), +}); diff --git a/packages/billing/montonio/src/schema/montonio-server-env.schema.ts b/packages/billing/montonio/src/schema/montonio-server-env.schema.ts index ccef446..09f38f5 100644 --- a/packages/billing/montonio/src/schema/montonio-server-env.schema.ts +++ b/packages/billing/montonio/src/schema/montonio-server-env.schema.ts @@ -1,15 +1,14 @@ import { z } from 'zod'; -export const MontonioServerEnvSchema = z - .object({ - secretKey: z - .string({ - error: `Please provide the variable MONTONIO_SECRET_KEY`, - }) - .min(1), - apiUrl: z - .string({ - error: `Please provide the variable MONTONIO_API_URL`, - }) - .min(1), - }); +export const MontonioServerEnvSchema = z.object({ + secretKey: z + .string({ + error: `Please provide the variable MONTONIO_SECRET_KEY`, + }) + .min(1), + apiUrl: z + .string({ + error: `Please provide the variable MONTONIO_API_URL`, + }) + .min(1), +}); diff --git a/packages/billing/montonio/src/services/montonio-order-handler.service.ts b/packages/billing/montonio/src/services/montonio-order-handler.service.ts index 7b23ae4..adaa71c 100644 --- a/packages/billing/montonio/src/services/montonio-order-handler.service.ts +++ b/packages/billing/montonio/src/services/montonio-order-handler.service.ts @@ -1,16 +1,19 @@ -import jwt from 'jsonwebtoken'; import axios, { AxiosError } from 'axios'; +import jwt from 'jsonwebtoken'; + import { MontonioClientEnvSchema } from '../schema/montonio-client-env.schema'; import { MontonioServerEnvSchema } from '../schema/montonio-server-env.schema'; -const clientEnv = () => MontonioClientEnvSchema.parse({ - accessKey: process.env.NEXT_PUBLIC_MONTONIO_ACCESS_KEY, -}); +const clientEnv = () => + MontonioClientEnvSchema.parse({ + accessKey: process.env.NEXT_PUBLIC_MONTONIO_ACCESS_KEY, + }); -const serverEnv = () => MontonioServerEnvSchema.parse({ - apiUrl: process.env.MONTONIO_API_URL, - secretKey: process.env.MONTONIO_SECRET_KEY, -}); +const serverEnv = () => + MontonioServerEnvSchema.parse({ + apiUrl: process.env.MONTONIO_API_URL, + secretKey: process.env.MONTONIO_SECRET_KEY, + }); export class MontonioOrderHandlerService { public async getMontonioPaymentLink({ @@ -45,23 +48,27 @@ export class MontonioOrderHandlerService { returnUrl, askAdditionalInfo: false, merchantReference, - type: "one_time", + type: 'one_time', }; const token = jwt.sign(params, secretKey, { - algorithm: "HS256", - expiresIn: "10m", + algorithm: 'HS256', + expiresIn: '10m', }); try { - const { data } = await axios.post(`${apiUrl}/api/payment-links`, { data: token }); + const { data } = await axios.post(`${apiUrl}/api/payment-links`, { + data: token, + }); return data.url; } catch (error) { if (error instanceof AxiosError) { console.error(error.response?.data); } - console.error(`Failed to create payment link, params=${JSON.stringify(params)}`, error); - throw new Error("Failed to create payment link"); + console.error( + `Failed to create payment link, params=${JSON.stringify(params)}`, + error, + ); + throw new Error('Failed to create payment link'); } } - } diff --git a/packages/billing/montonio/src/services/montonio-webhook-handler.service.ts b/packages/billing/montonio/src/services/montonio-webhook-handler.service.ts index 792d103..97a2fd0 100644 --- a/packages/billing/montonio/src/services/montonio-webhook-handler.service.ts +++ b/packages/billing/montonio/src/services/montonio-webhook-handler.service.ts @@ -1,7 +1,12 @@ -import type { BillingWebhookHandlerService, IHandleWebhookEventParams } from '@kit/billing'; +import jwt from 'jsonwebtoken'; + +import type { + BillingWebhookHandlerService, + IHandleWebhookEventParams, +} from '@kit/billing'; import { getLogger } from '@kit/shared/logger'; import { Database, Enums } from '@kit/supabase/database'; -import jwt from 'jsonwebtoken'; + import { MontonioServerEnvSchema } from '../schema/montonio-server-env.schema'; type UpsertOrderParams = @@ -10,20 +15,26 @@ type UpsertOrderParams = type BillingProvider = Enums<{ schema: 'medreport' }, 'billing_provider'>; interface MontonioOrderToken { - uuid: string; - accessKey: string; - merchantReference: string; - merchantReferenceDisplay: string; - paymentStatus: 'PAID' | 'FAILED' | 'CANCELLED' | 'PENDING' | 'EXPIRED' | 'REFUNDED'; - paymentMethod: string; - grandTotal: number; - currency: string; - senderIban?: string; - senderName?: string; - paymentProviderName?: string; - paymentLinkUuid: string; - iat: number; - exp: number; + uuid: string; + accessKey: string; + merchantReference: string; + merchantReferenceDisplay: string; + paymentStatus: + | 'PAID' + | 'FAILED' + | 'CANCELLED' + | 'PENDING' + | 'EXPIRED' + | 'REFUNDED'; + paymentMethod: string; + grandTotal: number; + currency: string; + senderIban?: string; + senderName?: string; + paymentProviderName?: string; + paymentLinkUuid: string; + iat: number; + exp: number; } const { secretKey } = MontonioServerEnvSchema.parse({ @@ -39,22 +50,25 @@ export class MontonioWebhookHandlerService async verifyWebhookSignature(request: Request) { const logger = await getLogger(); - + let token: string; try { const url = new URL(request.url); const searchParams = url.searchParams; - console.info("searchParams", searchParams, url); + console.info('searchParams', searchParams, url); const tokenParam = searchParams.get('order-token') as string | null; if (!tokenParam) { throw new Error('Missing order-token'); } token = tokenParam; } catch (error) { - logger.error({ - error, - name: this.namespace, - }, `Failed to parse Montonio webhook request`); + logger.error( + { + error, + name: this.namespace, + }, + `Failed to parse Montonio webhook request`, + ); throw new Error('Invalid request'); } @@ -64,24 +78,30 @@ export class MontonioWebhookHandlerService }); return decoded as MontonioOrderToken; } catch (error) { - logger.error({ - error, - name: this.namespace, - }, `Failed to verify Montonio webhook signature`); + logger.error( + { + error, + name: this.namespace, + }, + `Failed to verify Montonio webhook signature`, + ); throw new Error('Invalid signature'); } } async handleWebhookEvent( event: MontonioOrderToken, - params: IHandleWebhookEventParams + params: IHandleWebhookEventParams, ) { const logger = await getLogger(); - logger.info({ - name: this.namespace, - event, - }, `Received Montonio webhook event`); + logger.info( + { + name: this.namespace, + event, + }, + `Received Montonio webhook event`, + ); if (event.paymentStatus === 'PAID') { const [accountId] = event.merchantReferenceDisplay.split(':'); @@ -101,11 +121,13 @@ export class MontonioWebhookHandlerService return params.onCheckoutSessionCompleted(order); } - if (event.paymentStatus === 'FAILED' || event.paymentStatus === 'CANCELLED') { + if ( + event.paymentStatus === 'FAILED' || + event.paymentStatus === 'CANCELLED' + ) { return params.onPaymentFailed(event.uuid); } return; } } - \ No newline at end of file diff --git a/packages/billing/stripe/README.md b/packages/billing/stripe/README.md index 04bf47c..7f4b0ba 100644 --- a/packages/billing/stripe/README.md +++ b/packages/billing/stripe/README.md @@ -2,4 +2,4 @@ This package is responsible for handling all billing related operations using Stripe. -Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/billing/stripe). \ No newline at end of file +Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/billing/stripe). diff --git a/packages/cms/core/README.md b/packages/cms/core/README.md index 9f552a4..7574491 100644 --- a/packages/cms/core/README.md +++ b/packages/cms/core/README.md @@ -1,3 +1,3 @@ # CMS - @kit/cms -CMS abstraction layer for the Makerkit framework. \ No newline at end of file +CMS abstraction layer for the Makerkit framework. diff --git a/packages/cms/keystatic/README.md b/packages/cms/keystatic/README.md index e3f1945..dc98963 100644 --- a/packages/cms/keystatic/README.md +++ b/packages/cms/keystatic/README.md @@ -2,4 +2,4 @@ Implementation of the CMS layer using the Keystatic library. -Please refer to the [Documentation](https://makerkit.dev/docs/next-supabase-turbo/content/keystatic). \ No newline at end of file +Please refer to the [Documentation](https://makerkit.dev/docs/next-supabase-turbo/content/keystatic). diff --git a/packages/cms/wordpress/README.md b/packages/cms/wordpress/README.md index 5b6ced3..15986b7 100644 --- a/packages/cms/wordpress/README.md +++ b/packages/cms/wordpress/README.md @@ -1,3 +1,3 @@ # CMS/Wordpress - @kit/wordpress -Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/content/wordpress). \ No newline at end of file +Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/content/wordpress). diff --git a/packages/cms/wordpress/docker-compose.yml b/packages/cms/wordpress/docker-compose.yml index ebfbe68..15bf0d9 100644 --- a/packages/cms/wordpress/docker-compose.yml +++ b/packages/cms/wordpress/docker-compose.yml @@ -31,18 +31,18 @@ services: - WORDPRESS_DB_NAME=wordpress - WORDPRESS_DEBUG=1 - WORDPRESS_CONFIG_EXTRA = | - define('FS_METHOD', 'direct'); - /** disable wp core auto update */ - define('WP_AUTO_UPDATE_CORE', false); - - /** local environment settings */ - define('WP_CACHE', false); - define('ENVIRONMENT', 'local'); - - /** force site home url */ - if(!defined('WP_HOME')) { - define('WP_HOME', 'http://localhost'); - define('WP_SITEURL', WP_HOME); - } + define('FS_METHOD', 'direct'); + /** disable wp core auto update */ + define('WP_AUTO_UPDATE_CORE', false); + + /** local environment settings */ + define('WP_CACHE', false); + define('ENVIRONMENT', 'local'); + + /** force site home url */ + if(!defined('WP_HOME')) { + define('WP_HOME', 'http://localhost'); + define('WP_SITEURL', WP_HOME); + } volumes: - db_data: \ No newline at end of file + db_data: diff --git a/packages/database-webhooks/README.md b/packages/database-webhooks/README.md index 44e8011..558b25b 100644 --- a/packages/database-webhooks/README.md +++ b/packages/database-webhooks/README.md @@ -3,6 +3,7 @@ This package is responsible for handling webhooks from database changes. For example: + 1. when an account is deleted, we handle the cleanup of all related data in the third-party services. 2. when a user is invited, we send an email to the user. 3. when an account member is added, we update the subscription in the third-party services @@ -21,4 +22,4 @@ WEBHOOK_SENDER_PROVIDER=svix For example, you can add [https://docs.svix.com/quickstart]](Swix) as a webhook sender provider that receives webhooks from the database changes and forwards them to your application. -Svix is not implemented yet. \ No newline at end of file +Svix is not implemented yet. diff --git a/packages/database-webhooks/src/server/services/verifier/postgres-database-webhook-verifier.service.ts b/packages/database-webhooks/src/server/services/verifier/postgres-database-webhook-verifier.service.ts index d11c37d..1f61a27 100644 --- a/packages/database-webhooks/src/server/services/verifier/postgres-database-webhook-verifier.service.ts +++ b/packages/database-webhooks/src/server/services/verifier/postgres-database-webhook-verifier.service.ts @@ -6,7 +6,7 @@ const webhooksSecret = z .string({ error: `Provide the variable SUPABASE_DB_WEBHOOK_SECRET. This is used to authenticate the webhook event from Supabase.`, }) - .describe(`The secret used to verify the webhook signature`,) + .describe(`The secret used to verify the webhook signature`) .min(1) .parse(process.env.SUPABASE_DB_WEBHOOK_SECRET); diff --git a/packages/email-templates/src/components/common-footer.tsx b/packages/email-templates/src/components/common-footer.tsx index 846ddc4..32480ee 100644 --- a/packages/email-templates/src/components/common-footer.tsx +++ b/packages/email-templates/src/components/common-footer.tsx @@ -1,6 +1,7 @@ -import { TFunction } from "i18next"; -import { Text } from "@react-email/components"; -import { EmailFooter } from "./footer"; +import { Text } from '@react-email/components'; +import { TFunction } from 'i18next'; + +import { EmailFooter } from './footer'; export default function CommonFooter({ t }: { t: TFunction }) { const namespace = 'common'; @@ -15,8 +16,12 @@ export default function CommonFooter({ t }: { t: TFunction }) { return ( {lines.map((line, index) => ( - + ))} - ) + ); } diff --git a/packages/email-templates/src/emails/patient-first-results-received.email.tsx b/packages/email-templates/src/emails/patient-first-results-received.email.tsx index adeac31..831b662 100644 --- a/packages/email-templates/src/emails/patient-first-results-received.email.tsx +++ b/packages/email-templates/src/emails/patient-first-results-received.email.tsx @@ -65,7 +65,7 @@ export async function renderPatientFirstResultsReceivedEmail({ {t(`${namespace}:p2`)} {t(`${namespace}:p3`)} - {t(`${namespace}:p4`)} + {t(`${namespace}:p4`)} diff --git a/packages/email-templates/src/locales/en/account-delete-email.json b/packages/email-templates/src/locales/en/account-delete-email.json index 1b71932..df33b1a 100644 --- a/packages/email-templates/src/locales/en/account-delete-email.json +++ b/packages/email-templates/src/locales/en/account-delete-email.json @@ -6,4 +6,4 @@ "paragraph2": "We're sorry to see you go. Please note that this action is irreversible, and we'll make sure to delete all of your data from our systems.", "paragraph3": "We thank you again for using {{productName}}.", "paragraph4": "The {{productName}} Team" -} \ No newline at end of file +} diff --git a/packages/email-templates/src/locales/en/all-results-received-email.json b/packages/email-templates/src/locales/en/all-results-received-email.json index c8e7c4b..986c214 100644 --- a/packages/email-templates/src/locales/en/all-results-received-email.json +++ b/packages/email-templates/src/locales/en/all-results-received-email.json @@ -1,8 +1,8 @@ { - "previewText": "All analysis results have been received", - "subject": "All patient analysis results have been received", - "openOrdersHeading": "Review the results and prepare a summary:", - "linkText": "See results", - "ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.", - "hello": "Hello" -} \ No newline at end of file + "previewText": "All analysis results have been received", + "subject": "All patient analysis results have been received", + "openOrdersHeading": "Review the results and prepare a summary:", + "linkText": "See results", + "ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.", + "hello": "Hello" +} diff --git a/packages/email-templates/src/locales/en/common.json b/packages/email-templates/src/locales/en/common.json index 4474694..de91363 100644 --- a/packages/email-templates/src/locales/en/common.json +++ b/packages/email-templates/src/locales/en/common.json @@ -5,4 +5,4 @@ "lines3": "Customer service: +372 5887 1517", "lines4": "www.medreport.ee" } -} \ No newline at end of file +} diff --git a/packages/email-templates/src/locales/en/company-offer-email.json b/packages/email-templates/src/locales/en/company-offer-email.json index b0cd165..d9577e0 100644 --- a/packages/email-templates/src/locales/en/company-offer-email.json +++ b/packages/email-templates/src/locales/en/company-offer-email.json @@ -5,4 +5,4 @@ "contactPerson": "Contact Person:", "email": "Email:", "phone": "Phone:" -} \ No newline at end of file +} diff --git a/packages/email-templates/src/locales/en/doctor-summary-received-email.json b/packages/email-templates/src/locales/en/doctor-summary-received-email.json index ed17242..bb497da 100644 --- a/packages/email-templates/src/locales/en/doctor-summary-received-email.json +++ b/packages/email-templates/src/locales/en/doctor-summary-received-email.json @@ -1,8 +1,8 @@ { - "subject": "Doctor's summary has arrived", - "previewText": "The doctor has prepared a summary of the test results.", - "p1": "The doctor's summary has arrived:", - "p2": "It is recommended to have a comprehensive health check-up regularly, at least once a year, if you wish to maintain an active and fulfilling lifestyle.", - "p3": "MedReport makes it easy, convenient, and fast to view health data in one place and order health check-ups.", - "p4": "SYNLAB customer support phone: 17123" + "subject": "Doctor's summary has arrived", + "previewText": "The doctor has prepared a summary of the test results.", + "p1": "The doctor's summary has arrived:", + "p2": "It is recommended to have a comprehensive health check-up regularly, at least once a year, if you wish to maintain an active and fulfilling lifestyle.", + "p3": "MedReport makes it easy, convenient, and fast to view health data in one place and order health check-ups.", + "p4": "SYNLAB customer support phone: 17123" } diff --git a/packages/email-templates/src/locales/en/first-results-received-email.json b/packages/email-templates/src/locales/en/first-results-received-email.json index 03693ff..d3da27a 100644 --- a/packages/email-templates/src/locales/en/first-results-received-email.json +++ b/packages/email-templates/src/locales/en/first-results-received-email.json @@ -1,9 +1,9 @@ { - "previewText": "First analysis responses received", - "subject": "New job - first analysis responses received", - "resultsReceivedForOrders": "New job available to claim", - "openOrdersHeading": "See here:", - "linkText": "See results", - "ifLinksDisabled": "If the link does not work, you can see available jobs by copying this link into your browser.", - "hello": "Hello," -} \ No newline at end of file + "previewText": "First analysis responses received", + "subject": "New job - first analysis responses received", + "resultsReceivedForOrders": "New job available to claim", + "openOrdersHeading": "See here:", + "linkText": "See results", + "ifLinksDisabled": "If the link does not work, you can see available jobs by copying this link into your browser.", + "hello": "Hello," +} diff --git a/packages/email-templates/src/locales/en/invite-email.json b/packages/email-templates/src/locales/en/invite-email.json index da06d64..4bb83ff 100644 --- a/packages/email-templates/src/locales/en/invite-email.json +++ b/packages/email-templates/src/locales/en/invite-email.json @@ -6,4 +6,4 @@ "joinTeam": "Join {{teamName}}", "copyPasteLink": "or copy and paste this URL into your browser:", "invitationIntendedFor": "This invitation is intended for {{invitedUserEmail}}." -} \ No newline at end of file +} diff --git a/packages/email-templates/src/locales/en/new-jobs-available-email.json b/packages/email-templates/src/locales/en/new-jobs-available-email.json index e187b3c..ddf2d67 100644 --- a/packages/email-templates/src/locales/en/new-jobs-available-email.json +++ b/packages/email-templates/src/locales/en/new-jobs-available-email.json @@ -1,9 +1,9 @@ { - "previewText": "New jobs available", - "subject": "Please write a summary", - "resultsReceivedForOrders": "Please review the results and write a summary.", - "openOrdersHeading": "See here:", - "linkText": "Open job {{nr}}", - "ifLinksDisabled": "If the links do not work, you can see available jobs by copying this link into your browser.", - "hello": "Hello," -} \ No newline at end of file + "previewText": "New jobs available", + "subject": "Please write a summary", + "resultsReceivedForOrders": "Please review the results and write a summary.", + "openOrdersHeading": "See here:", + "linkText": "Open job {{nr}}", + "ifLinksDisabled": "If the links do not work, you can see available jobs by copying this link into your browser.", + "hello": "Hello," +} diff --git a/packages/email-templates/src/locales/en/order-processing-email.json b/packages/email-templates/src/locales/en/order-processing-email.json index b3472f0..b56d4de 100644 --- a/packages/email-templates/src/locales/en/order-processing-email.json +++ b/packages/email-templates/src/locales/en/order-processing-email.json @@ -1,13 +1,13 @@ { - "subject": "The referral has been sent to the laboratory. Please go to give samples.", - "heading": "Thank you for your order!", - "previewText": "The referral for tests has been sent to the laboratory.", - "p1": "The referral for tests has been sent to the laboratory digitally. Please go to give samples: {{partnerLocation}}.", - "p2": "If you are unable to go to the selected location to give samples, you may visit any other sampling point convenient for you - see locations and opening hours.", - "p3": "It is recommended to give samples preferably in the morning (before 12:00) and on an empty stomach without drinking or eating (you may drink water).", - "p4": "At the sampling point, please choose in the queue system: under referrals select specialist referral.", - "p5": "If you have any additional questions, please do not hesitate to contact us.", - "p6": "SYNLAB customer support phone: 17123", - "p1Urine": "The tests include a urine test. For the urine test, please collect the first morning urine.", - "p2Urine": "You can buy a sample container at the pharmacy and bring the sample with you (procedure performed at home), or ask for one at the sampling point (procedure performed in the point’s restroom)." + "subject": "The referral has been sent to the laboratory. Please go to give samples.", + "heading": "Thank you for your order!", + "previewText": "The referral for tests has been sent to the laboratory.", + "p1": "The referral for tests has been sent to the laboratory digitally. Please go to give samples: {{partnerLocation}}.", + "p2": "If you are unable to go to the selected location to give samples, you may visit any other sampling point convenient for you - see locations and opening hours.", + "p3": "It is recommended to give samples preferably in the morning (before 12:00) and on an empty stomach without drinking or eating (you may drink water).", + "p4": "At the sampling point, please choose in the queue system: under referrals select specialist referral.", + "p5": "If you have any additional questions, please do not hesitate to contact us.", + "p6": "SYNLAB customer support phone: 17123", + "p1Urine": "The tests include a urine test. For the urine test, please collect the first morning urine.", + "p2Urine": "You can buy a sample container at the pharmacy and bring the sample with you (procedure performed at home), or ask for one at the sampling point (procedure performed in the point’s restroom)." } diff --git a/packages/email-templates/src/locales/en/patient-first-results-received-email.json b/packages/email-templates/src/locales/en/patient-first-results-received-email.json index 1a77006..c458aaf 100644 --- a/packages/email-templates/src/locales/en/patient-first-results-received-email.json +++ b/packages/email-templates/src/locales/en/patient-first-results-received-email.json @@ -1,8 +1,8 @@ { - "subject": "The first ordered test results have arrived", - "previewText": "The first test results have arrived.", - "p1": "The first test results have arrived:", - "p2": "We will send the next notification once all test results have been received in the system.", - "p3": "If you have any additional questions, please feel free to contact us.", - "p4": "SYNLAB customer support phone: 17123" + "subject": "The first ordered test results have arrived", + "previewText": "The first test results have arrived.", + "p1": "The first test results have arrived:", + "p2": "We will send the next notification once all test results have been received in the system.", + "p3": "If you have any additional questions, please feel free to contact us.", + "p4": "SYNLAB customer support phone: 17123" } diff --git a/packages/email-templates/src/locales/en/patient-full-results-received-email.json b/packages/email-templates/src/locales/en/patient-full-results-received-email.json index 8fd6ed2..6ba6ccb 100644 --- a/packages/email-templates/src/locales/en/patient-full-results-received-email.json +++ b/packages/email-templates/src/locales/en/patient-full-results-received-email.json @@ -1,7 +1,7 @@ { - "subject": "All ordered test results have arrived. Awaiting doctor's summary.", - "previewText": "All test results have arrived.", - "p1": "All test results have arrived:", - "p2": "We will send the next notification once the doctor's summary has been prepared.", - "p3": "SYNLAB customer support phone: 17123" + "subject": "All ordered test results have arrived. Awaiting doctor's summary.", + "previewText": "All test results have arrived.", + "p1": "All test results have arrived:", + "p2": "We will send the next notification once the doctor's summary has been prepared.", + "p3": "SYNLAB customer support phone: 17123" } diff --git a/packages/email-templates/src/locales/en/synlab-email.json b/packages/email-templates/src/locales/en/synlab-email.json index cde6548..c26e1c5 100644 --- a/packages/email-templates/src/locales/en/synlab-email.json +++ b/packages/email-templates/src/locales/en/synlab-email.json @@ -1,12 +1,12 @@ { - "subject": "Your Medreport order has been placed - {{analysisPackageName}}", - "previewText": "Your Medreport order has been placed - {{analysisPackageName}}", - "heading": "Your Medreport order has been placed - {{analysisPackageName}}", - "hello": "Hello {{personName}},", - "lines1": "The order for {{analysisPackageName}} analysis package has been sent to the lab. Please go to the lab to collect the sample: Synlab - {{partnerLocationName}}", - "lines2": "If you are unable to go to the lab to collect the sample, you can go to any other suitable collection point - view locations and opening hours.", - "lines3": "It is recommended to collect the sample in the morning (before 12:00) and not to eat or drink (water can be drunk).", - "lines4": "At the collection point, select the order from the queue: the order from the doctor.", - "lines5": "If you have any questions, please contact us.", - "lines6": "SYNLAB customer service phone: 17123" -} \ No newline at end of file + "subject": "Your Medreport order has been placed - {{analysisPackageName}}", + "previewText": "Your Medreport order has been placed - {{analysisPackageName}}", + "heading": "Your Medreport order has been placed - {{analysisPackageName}}", + "hello": "Hello {{personName}},", + "lines1": "The order for {{analysisPackageName}} analysis package has been sent to the lab. Please go to the lab to collect the sample: Synlab - {{partnerLocationName}}", + "lines2": "If you are unable to go to the lab to collect the sample, you can go to any other suitable collection point - view locations and opening hours.", + "lines3": "It is recommended to collect the sample in the morning (before 12:00) and not to eat or drink (water can be drunk).", + "lines4": "At the collection point, select the order from the queue: the order from the doctor.", + "lines5": "If you have any questions, please contact us.", + "lines6": "SYNLAB customer service phone: 17123" +} diff --git a/packages/email-templates/src/locales/et/all-results-received-email.json b/packages/email-templates/src/locales/et/all-results-received-email.json index a96c137..fce8614 100644 --- a/packages/email-templates/src/locales/et/all-results-received-email.json +++ b/packages/email-templates/src/locales/et/all-results-received-email.json @@ -1,8 +1,8 @@ { - "previewText": "Kõik analüüside vastused on saabunud", - "subject": "Patsiendi kõikide analüüside vastused on saabunud", - "openOrdersHeading": "Vaata tulemusi ja kirjuta kokkuvõte:", - "linkText": "Vaata tulemusi", - "ifLinksDisabled": "Kui link ei tööta, näed analüüsitulemusi sellelt aadressilt:", - "hello": "Tere" -} \ No newline at end of file + "previewText": "Kõik analüüside vastused on saabunud", + "subject": "Patsiendi kõikide analüüside vastused on saabunud", + "openOrdersHeading": "Vaata tulemusi ja kirjuta kokkuvõte:", + "linkText": "Vaata tulemusi", + "ifLinksDisabled": "Kui link ei tööta, näed analüüsitulemusi sellelt aadressilt:", + "hello": "Tere" +} diff --git a/packages/email-templates/src/locales/et/common.json b/packages/email-templates/src/locales/et/common.json index 8b41d33..c663ccf 100644 --- a/packages/email-templates/src/locales/et/common.json +++ b/packages/email-templates/src/locales/et/common.json @@ -7,4 +7,4 @@ }, "helloName": "Tere, {{name}}", "hello": "Tere" -} \ No newline at end of file +} diff --git a/packages/email-templates/src/locales/et/doctor-summary-received-email.json b/packages/email-templates/src/locales/et/doctor-summary-received-email.json index 9e81ab5..79ee247 100644 --- a/packages/email-templates/src/locales/et/doctor-summary-received-email.json +++ b/packages/email-templates/src/locales/et/doctor-summary-received-email.json @@ -1,8 +1,8 @@ { - "subject": "Arsti kokkuvõte on saabunud", - "previewText": "Arst on koostanud kokkuvõte analüüsitulemustele.", - "p1": "Arsti kokkuvõte on saabunud:", - "p2": "Põhjalikul terviseuuringul on soovituslik käia regulaarselt, aga vähemalt üks kord aastas, kui soovite säilitada aktiivset ja täisväärtuslikku elustiili.", - "p3": "MedReport aitab lihtsalt, mugavalt ja kiirelt terviseandmeid ühest kohast vaadata ning tellida terviseuuringuid.", - "p4": "SYNLAB klienditoe telefon: 17123" -} \ No newline at end of file + "subject": "Arsti kokkuvõte on saabunud", + "previewText": "Arst on koostanud kokkuvõte analüüsitulemustele.", + "p1": "Arsti kokkuvõte on saabunud:", + "p2": "Põhjalikul terviseuuringul on soovituslik käia regulaarselt, aga vähemalt üks kord aastas, kui soovite säilitada aktiivset ja täisväärtuslikku elustiili.", + "p3": "MedReport aitab lihtsalt, mugavalt ja kiirelt terviseandmeid ühest kohast vaadata ning tellida terviseuuringuid.", + "p4": "SYNLAB klienditoe telefon: 17123" +} diff --git a/packages/email-templates/src/locales/et/first-results-received-email.json b/packages/email-templates/src/locales/et/first-results-received-email.json index d82aa7d..3aa6e43 100644 --- a/packages/email-templates/src/locales/et/first-results-received-email.json +++ b/packages/email-templates/src/locales/et/first-results-received-email.json @@ -1,9 +1,9 @@ { - "previewText": "Saabusid esimesed analüüside vastused", - "subject": "Uus töö - saabusid esimesed analüüside vastused", - "resultsReceivedForOrders": "Patsiendile saabusid esimesed analüüside vastused.", - "openOrdersHeading": "Vaata siit:", - "linkText": "Vaata tulemusi", - "ifLinksDisabled": "Kui link ei tööta, näed analüüsitulemusi sellelt aadressilt:", - "hello": "Tere" -} \ No newline at end of file + "previewText": "Saabusid esimesed analüüside vastused", + "subject": "Uus töö - saabusid esimesed analüüside vastused", + "resultsReceivedForOrders": "Patsiendile saabusid esimesed analüüside vastused.", + "openOrdersHeading": "Vaata siit:", + "linkText": "Vaata tulemusi", + "ifLinksDisabled": "Kui link ei tööta, näed analüüsitulemusi sellelt aadressilt:", + "hello": "Tere" +} diff --git a/packages/email-templates/src/locales/et/new-jobs-available-email.json b/packages/email-templates/src/locales/et/new-jobs-available-email.json index eae44b8..b532f8e 100644 --- a/packages/email-templates/src/locales/et/new-jobs-available-email.json +++ b/packages/email-templates/src/locales/et/new-jobs-available-email.json @@ -1,9 +1,9 @@ { - "previewText": "Palun koosta kokkuvõte", - "subject": "Palun koosta kokkuvõte", - "resultsReceivedForOrders": "Palun vaata tulemused üle ja kirjuta kokkuvõte.", - "openOrdersHeading": "Vaata siit:", - "linkText": "Töö {{nr}}", - "ifLinksDisabled": "Kui lingid ei tööta, näed vabasid töid sellelt aadressilt:", - "hello": "Tere" -} \ No newline at end of file + "previewText": "Palun koosta kokkuvõte", + "subject": "Palun koosta kokkuvõte", + "resultsReceivedForOrders": "Palun vaata tulemused üle ja kirjuta kokkuvõte.", + "openOrdersHeading": "Vaata siit:", + "linkText": "Töö {{nr}}", + "ifLinksDisabled": "Kui lingid ei tööta, näed vabasid töid sellelt aadressilt:", + "hello": "Tere" +} diff --git a/packages/email-templates/src/locales/et/order-processing-email.json b/packages/email-templates/src/locales/et/order-processing-email.json index a9e57c0..05a064b 100644 --- a/packages/email-templates/src/locales/et/order-processing-email.json +++ b/packages/email-templates/src/locales/et/order-processing-email.json @@ -1,13 +1,13 @@ { - "subject": "Saatekiri on saadetud laborisse. Palun mine proove andma.", - "heading": "Täname tellimuse eest!", - "previewText": "Saatekiri uuringute tegemiseks on saadetud laborisse.", - "p1": "Saatekiri uuringute tegemiseks on saadetud laborisse digitaalselt. Palun mine proove andma: {{partnerLocation}}.", - "p2": "Kui Teil ei ole võimalik valitud asukohta minna proove andma, siis võite minna endale sobivasse proovivõtupunkti - vaata asukohti ja lahtiolekuaegasid.", - "p3": "Soovituslik on proove anda pigem hommikul (enne 12:00) ning söömata ja joomata (vett võib juua).", - "p4": "Proovivõtupunktis valige järjekorrasüsteemis: saatekirjad alt eriarsti saatekiri", - "p5": "Juhul kui tekkis lisaküsimusi, siis võtke julgelt ühendust.", - "p6": "SYNLAB klienditoe telefon: 17123", - "p1Urine": "Analüüsides on ette nähtud uriinianalüüs. Uriinianalüüsiks võta hommikune esmane uriin.", - "p2Urine": "Proovitopsi võib soetada apteegist ja analüüsi kaasa võtta (teostada protseduur kodus) või küsida proovivõtupunktist (teostada protseduur proovipunkti wc-s)." -} \ No newline at end of file + "subject": "Saatekiri on saadetud laborisse. Palun mine proove andma.", + "heading": "Täname tellimuse eest!", + "previewText": "Saatekiri uuringute tegemiseks on saadetud laborisse.", + "p1": "Saatekiri uuringute tegemiseks on saadetud laborisse digitaalselt. Palun mine proove andma: {{partnerLocation}}.", + "p2": "Kui Teil ei ole võimalik valitud asukohta minna proove andma, siis võite minna endale sobivasse proovivõtupunkti - vaata asukohti ja lahtiolekuaegasid.", + "p3": "Soovituslik on proove anda pigem hommikul (enne 12:00) ning söömata ja joomata (vett võib juua).", + "p4": "Proovivõtupunktis valige järjekorrasüsteemis: saatekirjad alt eriarsti saatekiri", + "p5": "Juhul kui tekkis lisaküsimusi, siis võtke julgelt ühendust.", + "p6": "SYNLAB klienditoe telefon: 17123", + "p1Urine": "Analüüsides on ette nähtud uriinianalüüs. Uriinianalüüsiks võta hommikune esmane uriin.", + "p2Urine": "Proovitopsi võib soetada apteegist ja analüüsi kaasa võtta (teostada protseduur kodus) või küsida proovivõtupunktist (teostada protseduur proovipunkti wc-s)." +} diff --git a/packages/email-templates/src/locales/et/patient-first-results-received-email.json b/packages/email-templates/src/locales/et/patient-first-results-received-email.json index 7d87e78..c1d078e 100644 --- a/packages/email-templates/src/locales/et/patient-first-results-received-email.json +++ b/packages/email-templates/src/locales/et/patient-first-results-received-email.json @@ -1,8 +1,8 @@ { - "subject": "Saabusid tellitud uuringute esimesed tulemused", - "previewText": "Esimesed uuringute tulemused on saabunud.", - "p1": "Esimesed uuringute tulemused on saabunud:", - "p2": "Saadame järgmise teavituse, kui kõik uuringute vastused on saabunud süsteemi.", - "p3": "Juhul kui tekkis lisaküsimusi, siis võtke julgelt ühendust.", - "p4": "SYNLAB klienditoe telefon: 17123" -} \ No newline at end of file + "subject": "Saabusid tellitud uuringute esimesed tulemused", + "previewText": "Esimesed uuringute tulemused on saabunud.", + "p1": "Esimesed uuringute tulemused on saabunud:", + "p2": "Saadame järgmise teavituse, kui kõik uuringute vastused on saabunud süsteemi.", + "p3": "Juhul kui tekkis lisaküsimusi, siis võtke julgelt ühendust.", + "p4": "SYNLAB klienditoe telefon: 17123" +} diff --git a/packages/email-templates/src/locales/et/patient-full-results-received-email.json b/packages/email-templates/src/locales/et/patient-full-results-received-email.json index 4a1de1a..c8ddc69 100644 --- a/packages/email-templates/src/locales/et/patient-full-results-received-email.json +++ b/packages/email-templates/src/locales/et/patient-full-results-received-email.json @@ -1,7 +1,7 @@ { - "subject": "Kõikide tellitud uuringute tulemused on saabunud. Ootab arsti kokkuvõtet.", - "previewText": "Kõikide uuringute tulemused on saabunud.", - "p1": "Kõikide uuringute tulemused on saabunud:", - "p2": "Saadame järgmise teavituse kui arsti kokkuvõte on koostatud.", - "p3": "SYNLAB klienditoe telefon: 17123" -} \ No newline at end of file + "subject": "Kõikide tellitud uuringute tulemused on saabunud. Ootab arsti kokkuvõtet.", + "previewText": "Kõikide uuringute tulemused on saabunud.", + "p1": "Kõikide uuringute tulemused on saabunud:", + "p2": "Saadame järgmise teavituse kui arsti kokkuvõte on koostatud.", + "p3": "SYNLAB klienditoe telefon: 17123" +} diff --git a/packages/email-templates/src/locales/et/synlab-email.json b/packages/email-templates/src/locales/et/synlab-email.json index fa16c20..4917866 100644 --- a/packages/email-templates/src/locales/et/synlab-email.json +++ b/packages/email-templates/src/locales/et/synlab-email.json @@ -1,12 +1,12 @@ { - "subject": "Teie Medreport tellimus on kinnitatud - {{analysisPackageName}}", - "previewText": "Teie Medreport tellimus on kinnitatud - {{analysisPackageName}}", - "heading": "Teie Medreport tellimus on kinnitatud - {{analysisPackageName}}", - "hello": "Tere {{personName}},", - "lines1": "Saatekiri {{analysisPackageName}} analüüsi uuringuteks on saadetud laborisse digitaalselt. Palun mine proove andma: Synlab - {{partnerLocationName}}", - "lines2": "Kui Teil ei ole võimalik valitud asukohta minna proove andma, siis võite minna endale sobivasse proovivõtupunkti - vaata asukohti ja lahtiolekuaegasid.", - "lines3": "Soovituslik on proove anda pigem hommikul (enne 12:00) ning söömata ja joomata (vett võib juua).", - "lines4": "Proovivõtupunktis valige järjekorrasüsteemis: saatekirjad alt eriarsti saatekiri.", - "lines5": "Juhul kui tekkis lisaküsimusi, siis võtke julgelt ühendust.", - "lines6": "SYNLAB klienditoe telefon: 17123" -} \ No newline at end of file + "subject": "Teie Medreport tellimus on kinnitatud - {{analysisPackageName}}", + "previewText": "Teie Medreport tellimus on kinnitatud - {{analysisPackageName}}", + "heading": "Teie Medreport tellimus on kinnitatud - {{analysisPackageName}}", + "hello": "Tere {{personName}},", + "lines1": "Saatekiri {{analysisPackageName}} analüüsi uuringuteks on saadetud laborisse digitaalselt. Palun mine proove andma: Synlab - {{partnerLocationName}}", + "lines2": "Kui Teil ei ole võimalik valitud asukohta minna proove andma, siis võite minna endale sobivasse proovivõtupunkti - vaata asukohti ja lahtiolekuaegasid.", + "lines3": "Soovituslik on proove anda pigem hommikul (enne 12:00) ning söömata ja joomata (vett võib juua).", + "lines4": "Proovivõtupunktis valige järjekorrasüsteemis: saatekirjad alt eriarsti saatekiri.", + "lines5": "Juhul kui tekkis lisaküsimusi, siis võtke julgelt ühendust.", + "lines6": "SYNLAB klienditoe telefon: 17123" +} diff --git a/packages/email-templates/src/locales/ru/all-results-received-email.json b/packages/email-templates/src/locales/ru/all-results-received-email.json index c8e7c4b..986c214 100644 --- a/packages/email-templates/src/locales/ru/all-results-received-email.json +++ b/packages/email-templates/src/locales/ru/all-results-received-email.json @@ -1,8 +1,8 @@ { - "previewText": "All analysis results have been received", - "subject": "All patient analysis results have been received", - "openOrdersHeading": "Review the results and prepare a summary:", - "linkText": "See results", - "ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.", - "hello": "Hello" -} \ No newline at end of file + "previewText": "All analysis results have been received", + "subject": "All patient analysis results have been received", + "openOrdersHeading": "Review the results and prepare a summary:", + "linkText": "See results", + "ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.", + "hello": "Hello" +} diff --git a/packages/email-templates/src/locales/ru/common.json b/packages/email-templates/src/locales/ru/common.json index 5e1ae9a..6ec123a 100644 --- a/packages/email-templates/src/locales/ru/common.json +++ b/packages/email-templates/src/locales/ru/common.json @@ -5,4 +5,4 @@ "lines3": "Служба поддержки: +372 5887 1517", "lines4": "www.medreport.ee" } -} \ No newline at end of file +} diff --git a/packages/email-templates/src/locales/ru/company-offer-email.json b/packages/email-templates/src/locales/ru/company-offer-email.json index 2678bdb..3143f5f 100644 --- a/packages/email-templates/src/locales/ru/company-offer-email.json +++ b/packages/email-templates/src/locales/ru/company-offer-email.json @@ -5,4 +5,4 @@ "contactPerson": "Контактное лицо:", "email": "Электронная почта:", "phone": "Телефон:" -} \ No newline at end of file +} diff --git a/packages/email-templates/src/locales/ru/doctor-summary-received-email.json b/packages/email-templates/src/locales/ru/doctor-summary-received-email.json index e233f55..9939608 100644 --- a/packages/email-templates/src/locales/ru/doctor-summary-received-email.json +++ b/packages/email-templates/src/locales/ru/doctor-summary-received-email.json @@ -1,8 +1,8 @@ { - "subject": "Заключение врача готово", - "previewText": "Врач подготовил заключение по результатам анализов.", - "p1": "Заключение врача готово:", - "p2": "Рекомендуется проходить комплексное обследование регулярно, но как минимум один раз в год, если вы хотите сохранить активный и полноценный образ жизни.", - "p3": "MedReport позволяет легко, удобно и быстро просматривать медицинские данные в одном месте и заказывать обследования.", - "p4": "Телефон службы поддержки SYNLAB: 17123" -} \ No newline at end of file + "subject": "Заключение врача готово", + "previewText": "Врач подготовил заключение по результатам анализов.", + "p1": "Заключение врача готово:", + "p2": "Рекомендуется проходить комплексное обследование регулярно, но как минимум один раз в год, если вы хотите сохранить активный и полноценный образ жизни.", + "p3": "MedReport позволяет легко, удобно и быстро просматривать медицинские данные в одном месте и заказывать обследования.", + "p4": "Телефон службы поддержки SYNLAB: 17123" +} diff --git a/packages/email-templates/src/locales/ru/first-results-received-email.json b/packages/email-templates/src/locales/ru/first-results-received-email.json index 6aff2c7..56b5e54 100644 --- a/packages/email-templates/src/locales/ru/first-results-received-email.json +++ b/packages/email-templates/src/locales/ru/first-results-received-email.json @@ -1,9 +1,9 @@ { - "previewText": "First analysis responses received", - "subject": "New job - first analysis responses received", - "resultsReceivedForOrders": "New job available to claim", - "openOrdersHeading": "See here:", - "linkText": "See results", - "ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.", - "hello": "Hello," -} \ No newline at end of file + "previewText": "First analysis responses received", + "subject": "New job - first analysis responses received", + "resultsReceivedForOrders": "New job available to claim", + "openOrdersHeading": "See here:", + "linkText": "See results", + "ifLinksDisabled": "If the link does not work, you can see the results by copying this link into your browser.", + "hello": "Hello," +} diff --git a/packages/email-templates/src/locales/ru/new-jobs-available-email.json b/packages/email-templates/src/locales/ru/new-jobs-available-email.json index e187b3c..ddf2d67 100644 --- a/packages/email-templates/src/locales/ru/new-jobs-available-email.json +++ b/packages/email-templates/src/locales/ru/new-jobs-available-email.json @@ -1,9 +1,9 @@ { - "previewText": "New jobs available", - "subject": "Please write a summary", - "resultsReceivedForOrders": "Please review the results and write a summary.", - "openOrdersHeading": "See here:", - "linkText": "Open job {{nr}}", - "ifLinksDisabled": "If the links do not work, you can see available jobs by copying this link into your browser.", - "hello": "Hello," -} \ No newline at end of file + "previewText": "New jobs available", + "subject": "Please write a summary", + "resultsReceivedForOrders": "Please review the results and write a summary.", + "openOrdersHeading": "See here:", + "linkText": "Open job {{nr}}", + "ifLinksDisabled": "If the links do not work, you can see available jobs by copying this link into your browser.", + "hello": "Hello," +} diff --git a/packages/email-templates/src/locales/ru/order-processing-email.json b/packages/email-templates/src/locales/ru/order-processing-email.json index 3a5d6ac..8cd96a9 100644 --- a/packages/email-templates/src/locales/ru/order-processing-email.json +++ b/packages/email-templates/src/locales/ru/order-processing-email.json @@ -1,13 +1,13 @@ { - "subject": "Направление отправлено в лабораторию. Пожалуйста, сдайте анализы.", - "heading": "Спасибо за заказ!", - "previewText": "Направление на обследование отправлено в лабораторию.", - "p1": "Направление на обследование было отправлено в лабораторию в цифровом виде. Пожалуйста, сдайте анализы: {{partnerLocation}}.", - "p2": "Если у вас нет возможности прийти в выбранный пункт сдачи анализов, вы можете обратиться в любой удобный для вас пункт – посмотреть адреса и часы работы.", - "p3": "Рекомендуется сдавать анализы утром (до 12:00) натощак, без еды и напитков (разрешается пить воду).", - "p4": "В пункте сдачи анализов выберите в системе очереди: в разделе направлениянаправление от специалиста.", - "p5": "Если у вас возникли дополнительные вопросы, пожалуйста, свяжитесь с нами.", - "p6": "Телефон службы поддержки SYNLAB: 17123", - "p1Urine": "В обследование входит анализ мочи. Для анализа необходимо собрать первую утреннюю мочу.", - "p2Urine": "Контейнер можно приобрести в аптеке и принести образец с собой (процедура проводится дома) или взять контейнер в пункте сдачи (процедура проводится в туалете пункта)." + "subject": "Направление отправлено в лабораторию. Пожалуйста, сдайте анализы.", + "heading": "Спасибо за заказ!", + "previewText": "Направление на обследование отправлено в лабораторию.", + "p1": "Направление на обследование было отправлено в лабораторию в цифровом виде. Пожалуйста, сдайте анализы: {{partnerLocation}}.", + "p2": "Если у вас нет возможности прийти в выбранный пункт сдачи анализов, вы можете обратиться в любой удобный для вас пункт – посмотреть адреса и часы работы.", + "p3": "Рекомендуется сдавать анализы утром (до 12:00) натощак, без еды и напитков (разрешается пить воду).", + "p4": "В пункте сдачи анализов выберите в системе очереди: в разделе направлениянаправление от специалиста.", + "p5": "Если у вас возникли дополнительные вопросы, пожалуйста, свяжитесь с нами.", + "p6": "Телефон службы поддержки SYNLAB: 17123", + "p1Urine": "В обследование входит анализ мочи. Для анализа необходимо собрать первую утреннюю мочу.", + "p2Urine": "Контейнер можно приобрести в аптеке и принести образец с собой (процедура проводится дома) или взять контейнер в пункте сдачи (процедура проводится в туалете пункта)." } diff --git a/packages/email-templates/src/locales/ru/patient-first-results-received-email.json b/packages/email-templates/src/locales/ru/patient-first-results-received-email.json index 975934f..e1158b4 100644 --- a/packages/email-templates/src/locales/ru/patient-first-results-received-email.json +++ b/packages/email-templates/src/locales/ru/patient-first-results-received-email.json @@ -1,8 +1,8 @@ { - "subject": "Поступили первые результаты заказанных исследований", - "previewText": "Первые результаты исследований поступили.", - "p1": "Первые результаты исследований поступили:", - "p2": "Мы отправим следующее уведомление, когда все результаты исследований будут получены в системе.", - "p3": "Если у вас возникнут дополнительные вопросы, пожалуйста, свяжитесь с нами.", - "p4": "Телефон службы поддержки SYNLAB: 17123" + "subject": "Поступили первые результаты заказанных исследований", + "previewText": "Первые результаты исследований поступили.", + "p1": "Первые результаты исследований поступили:", + "p2": "Мы отправим следующее уведомление, когда все результаты исследований будут получены в системе.", + "p3": "Если у вас возникнут дополнительные вопросы, пожалуйста, свяжитесь с нами.", + "p4": "Телефон службы поддержки SYNLAB: 17123" } diff --git a/packages/email-templates/src/locales/ru/patient-full-results-received-email.json b/packages/email-templates/src/locales/ru/patient-full-results-received-email.json index e47f161..80f6ab5 100644 --- a/packages/email-templates/src/locales/ru/patient-full-results-received-email.json +++ b/packages/email-templates/src/locales/ru/patient-full-results-received-email.json @@ -1,7 +1,7 @@ { - "subject": "Все заказанные результаты исследований поступили. Ожидается заключение врача.", - "previewText": "Все результаты исследований поступили.", - "p1": "Все результаты исследований поступили:", - "p2": "Мы отправим следующее уведомление, когда заключение врача будет подготовлено.", - "p3": "Телефон службы поддержки SYNLAB: 17123" -} \ No newline at end of file + "subject": "Все заказанные результаты исследований поступили. Ожидается заключение врача.", + "previewText": "Все результаты исследований поступили.", + "p1": "Все результаты исследований поступили:", + "p2": "Мы отправим следующее уведомление, когда заключение врача будет подготовлено.", + "p3": "Телефон службы поддержки SYNLAB: 17123" +} diff --git a/packages/email-templates/src/locales/ru/synlab-email.json b/packages/email-templates/src/locales/ru/synlab-email.json index 6373b90..d5a78dc 100644 --- a/packages/email-templates/src/locales/ru/synlab-email.json +++ b/packages/email-templates/src/locales/ru/synlab-email.json @@ -1,12 +1,12 @@ { - "subject": "Ваш заказ Medreport подтвержден - {{analysisPackageName}}", - "previewText": "Ваш заказ Medreport подтвержден - {{analysisPackageName}}", - "heading": "Ваш заказ Medreport подтвержден - {{analysisPackageName}}", - "hello": "Здравствуйте, {{personName}},", - "lines1": "Направление на исследование {{analysisPackageName}} было отправлено в лабораторию в цифровом виде. Пожалуйста, сдайте анализы: Synlab - {{partnerLocationName}}", - "lines2": "Если вы не можете посетить выбранный пункт сдачи анализов, вы можете обратиться в удобный для вас пункт - посмотреть адреса и часы работы.", - "lines3": "Рекомендуется сдавать анализы утром (до 12:00) натощак (можно пить воду).", - "lines4": "В пункте сдачи анализов выберите в системе очереди: направления -> направление от специалиста.", - "lines5": "Если у вас возникнут дополнительные вопросы, смело свяжитесь с нами.", - "lines6": "Телефон службы поддержки SYNLAB: 17123" -} \ No newline at end of file + "subject": "Ваш заказ Medreport подтвержден - {{analysisPackageName}}", + "previewText": "Ваш заказ Medreport подтвержден - {{analysisPackageName}}", + "heading": "Ваш заказ Medreport подтвержден - {{analysisPackageName}}", + "hello": "Здравствуйте, {{personName}},", + "lines1": "Направление на исследование {{analysisPackageName}} было отправлено в лабораторию в цифровом виде. Пожалуйста, сдайте анализы: Synlab - {{partnerLocationName}}", + "lines2": "Если вы не можете посетить выбранный пункт сдачи анализов, вы можете обратиться в удобный для вас пункт - посмотреть адреса и часы работы.", + "lines3": "Рекомендуется сдавать анализы утром (до 12:00) натощак (можно пить воду).", + "lines4": "В пункте сдачи анализов выберите в системе очереди: направления -> направление от специалиста.", + "lines5": "Если у вас возникнут дополнительные вопросы, смело свяжитесь с нами.", + "lines6": "Телефон службы поддержки SYNLAB: 17123" +} diff --git a/packages/features/accounts/src/components/account-selector.tsx b/packages/features/accounts/src/components/account-selector.tsx index f9cee97..9fac23a 100644 --- a/packages/features/accounts/src/components/account-selector.tsx +++ b/packages/features/accounts/src/components/account-selector.tsx @@ -112,7 +112,7 @@ export function AccountSelector({ role="combobox" aria-expanded={open} className={cn( - 'dark:shadow-primary/10 group w-full min-w-0 px-4 py-2 h-10 border-1 lg:w-auto lg:max-w-fit', + 'dark:shadow-primary/10 group h-10 w-full min-w-0 border-1 px-4 py-2 lg:w-auto lg:max-w-fit', { 'justify-start': !collapsed, 'm-auto justify-center px-4 lg:w-full': collapsed, @@ -124,7 +124,7 @@ export function AccountSelector({ condition={selected} fallback={ - +
- + + ); diff --git a/packages/features/accounts/src/components/index.ts b/packages/features/accounts/src/components/index.ts index 1e4dabd..3e4c5c6 100644 --- a/packages/features/accounts/src/components/index.ts +++ b/packages/features/accounts/src/components/index.ts @@ -1,3 +1,3 @@ export * from './user-workspace-context'; -export * from './personal-account-settings/mfa/multi-factor-auth-list' -export * from './personal-account-settings/mfa/multi-factor-auth-setup-dialog' +export * from './personal-account-settings/mfa/multi-factor-auth-list'; +export * from './personal-account-settings/mfa/multi-factor-auth-setup-dialog'; diff --git a/packages/features/accounts/src/components/personal-account-dropdown.tsx b/packages/features/accounts/src/components/personal-account-dropdown.tsx index b88eea9..8e2cd40 100644 --- a/packages/features/accounts/src/components/personal-account-dropdown.tsx +++ b/packages/features/accounts/src/components/personal-account-dropdown.tsx @@ -81,7 +81,8 @@ export function PersonalAccountDropdown({ const { name, last_name } = personalAccountData ?? {}; const firstNameLabel = toTitleCase(name) ?? '-'; - const fullNameLabel = name && last_name ? toTitleCase(`${name} ${last_name}`) : '-'; + const fullNameLabel = + name && last_name ? toTitleCase(`${name} ${last_name}`) : '-'; const hasTotpFactor = useMemo(() => { const factors = user?.factors ?? []; diff --git a/packages/features/accounts/src/components/personal-account-settings/mfa/multi-factor-auth-setup-dialog.tsx b/packages/features/accounts/src/components/personal-account-settings/mfa/multi-factor-auth-setup-dialog.tsx index b485d95..2647efb 100644 --- a/packages/features/accounts/src/components/personal-account-settings/mfa/multi-factor-auth-setup-dialog.tsx +++ b/packages/features/accounts/src/components/personal-account-settings/mfa/multi-factor-auth-setup-dialog.tsx @@ -347,9 +347,7 @@ function FactorQrCode({
-

- {form.getValues('totpSecret')} -

+

{form.getValues('totpSecret')}

); } diff --git a/packages/features/accounts/src/server/api.ts b/packages/features/accounts/src/server/api.ts index 015e0f4..b934e39 100644 --- a/packages/features/accounts/src/server/api.ts +++ b/packages/features/accounts/src/server/api.ts @@ -1,6 +1,7 @@ import { SupabaseClient } from '@supabase/supabase-js'; import { Database } from '@kit/supabase/database'; + import PersonalCode from '~/lib/utils'; import { AccountWithParams } from '../types/accounts'; @@ -11,7 +12,7 @@ import { AccountWithParams } from '../types/accounts'; * @param {SupabaseClient} client - The Supabase client instance. */ class AccountsApi { - constructor(private readonly client: SupabaseClient) { } + constructor(private readonly client: SupabaseClient) {} /** * @name getAccount diff --git a/packages/features/accounts/src/types/accounts.ts b/packages/features/accounts/src/types/accounts.ts index 7259cfb..bc305c0 100644 --- a/packages/features/accounts/src/types/accounts.ts +++ b/packages/features/accounts/src/types/accounts.ts @@ -11,13 +11,13 @@ export enum ApplicationRoleEnum { export type AccountWithParams = Database['medreport']['Tables']['accounts']['Row'] & { accountParams: - | (Pick< - Database['medreport']['Tables']['account_params']['Row'], - 'weight' | 'height' - > & { - isSmoker: - | Database['medreport']['Tables']['account_params']['Row']['is_smoker'] + | (Pick< + Database['medreport']['Tables']['account_params']['Row'], + 'weight' | 'height' + > & { + isSmoker: + | Database['medreport']['Tables']['account_params']['Row']['is_smoker'] + | null; + }) | null; - }) - | null; }; diff --git a/packages/features/admin/src/components/admin-create-user-dialog.tsx b/packages/features/admin/src/components/admin-create-user-dialog.tsx index 5b4bffc..b2f849d 100644 --- a/packages/features/admin/src/components/admin-create-user-dialog.tsx +++ b/packages/features/admin/src/components/admin-create-user-dialog.tsx @@ -48,7 +48,7 @@ export function AdminCreateUserDialog(props: React.PropsWithChildren) { email: '', password: '', emailConfirm: false, - personalCode: '' + personalCode: '', }, mode: 'onBlur', }); @@ -163,7 +163,7 @@ export function AdminCreateUserDialog(props: React.PropsWithChildren) { ( - + name === customerGroupName); + const customerGroup = customer_groups.find( + ({ name }) => name === customerGroupName, + ); if (customerGroup) { try { await medusa.admin.customerGroup.delete(customerGroup.id); } catch (e) { - logger.error({ accountId }, `Error deleting Medusa customer group for company ${customerGroupName}`); + logger.error( + { accountId }, + `Error deleting Medusa customer group for company ${customerGroupName}`, + ); throw e; } } @@ -288,22 +293,29 @@ export const createCompanyAccountAction = enhanceAction( logger.info(ctx, `Creating Medusa customer group`); const medusa = getAdminSdk(); - const { customer_groups: existingCustomerGroups } = await medusa.admin.customerGroup.list(); - const isExisting = existingCustomerGroups.find((group) => group.name === name); + const { customer_groups: existingCustomerGroups } = + await medusa.admin.customerGroup.list(); + const isExisting = existingCustomerGroups.find( + (group) => group.name === name, + ); if (isExisting) { logger.info(ctx, `Customer group already exists`); } else { logger.info(ctx, `Creating Medusa customer group`); const { data: account } = await client - .schema('medreport').from('accounts') + .schema('medreport') + .from('accounts') .select('medusa_account_id') .eq('personal_code', ownerPersonalCode) - .single().throwOnError(); + .single() + .throwOnError(); const medusaAccountId = account.medusa_account_id; if (!medusaAccountId) { logger.error(ctx, `User has no Medusa account ID`); } else { - const { customer_group: { id: customerGroupId } } = await medusa.admin.customerGroup.create({ name }); + const { + customer_group: { id: customerGroupId }, + } = await medusa.admin.customerGroup.create({ name }); const { customers } = await medusa.admin.customer.list({ id: medusaAccountId, }); @@ -316,7 +328,6 @@ export const createCompanyAccountAction = enhanceAction( }); } } - } redirect(`/admin/accounts/${data.id}`); diff --git a/packages/features/admin/src/lib/server/schema/create-user-profile.schema.ts b/packages/features/admin/src/lib/server/schema/create-user-profile.schema.ts index 03e971d..6a466b5 100644 --- a/packages/features/admin/src/lib/server/schema/create-user-profile.schema.ts +++ b/packages/features/admin/src/lib/server/schema/create-user-profile.schema.ts @@ -1,10 +1,13 @@ import { z } from 'zod'; export const CreateUserProfileSchema = z.object({ - personalCode: z.string().regex(/^[1-6]\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}\d$/, { - message: 'Invalid Estonian personal code format', - }), + personalCode: z + .string() + .regex(/^[1-6]\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}\d$/, { + message: 'Invalid Estonian personal code format', + }), }); -export type CreateUserProfileSchemaType = z.infer; - +export type CreateUserProfileSchemaType = z.infer< + typeof CreateUserProfileSchema +>; diff --git a/packages/features/admin/src/lib/server/schema/create-user.schema.ts b/packages/features/admin/src/lib/server/schema/create-user.schema.ts index 9b05b4e..5d9e84d 100644 --- a/packages/features/admin/src/lib/server/schema/create-user.schema.ts +++ b/packages/features/admin/src/lib/server/schema/create-user.schema.ts @@ -1,9 +1,11 @@ import { z } from 'zod'; export const CreateUserSchema = z.object({ - personalCode: z.string().regex(/^[1-6]\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}\d$/, { - message: 'Invalid Estonian personal code format', - }), + personalCode: z + .string() + .regex(/^[1-6]\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}\d$/, { + message: 'Invalid Estonian personal code format', + }), email: z.string().email({ message: 'Please enter a valid email address' }), password: z .string() diff --git a/packages/features/admin/src/lib/server/services/admin-accounts.service.ts b/packages/features/admin/src/lib/server/services/admin-accounts.service.ts index 87e72e9..c46bc03 100644 --- a/packages/features/admin/src/lib/server/services/admin-accounts.service.ts +++ b/packages/features/admin/src/lib/server/services/admin-accounts.service.ts @@ -44,7 +44,8 @@ class AdminAccountsService { .from('accounts') .select('*') .eq('id', accountId) - .single().throwOnError(); + .single() + .throwOnError(); return data; } diff --git a/packages/features/admin/src/lib/server/utils/medusa-sdk.ts b/packages/features/admin/src/lib/server/utils/medusa-sdk.ts index 997ab55..89606d9 100644 --- a/packages/features/admin/src/lib/server/utils/medusa-sdk.ts +++ b/packages/features/admin/src/lib/server/utils/medusa-sdk.ts @@ -1,8 +1,9 @@ -import Medusa from "@medusajs/js-sdk" +import Medusa from '@medusajs/js-sdk'; export const getAdminSdk = () => { const medusaBackendUrl = process.env.MEDUSA_BACKEND_PUBLIC_URL!; - const medusaPublishableApiKey = process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY!; + const medusaPublishableApiKey = + process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY!; const key = process.env.MEDUSA_SECRET_API_KEY!; if (!medusaBackendUrl || !medusaPublishableApiKey) { @@ -13,4 +14,4 @@ export const getAdminSdk = () => { debug: process.env.NODE_ENV === 'development', apiKey: key, }); -} +}; diff --git a/packages/features/admin/tsconfig.json b/packages/features/admin/tsconfig.json index 7383acd..c4697e9 100644 --- a/packages/features/admin/tsconfig.json +++ b/packages/features/admin/tsconfig.json @@ -4,7 +4,5 @@ "tsBuildInfoFile": "node_modules/.cache/tsbuildinfo.json" }, "include": ["*.ts", "src"], - "exclude": [ - "node_modules" - ] + "exclude": ["node_modules"] } diff --git a/packages/features/auth/src/components/auth-layout.tsx b/packages/features/auth/src/components/auth-layout.tsx index 003da16..4ba38e8 100644 --- a/packages/features/auth/src/components/auth-layout.tsx +++ b/packages/features/auth/src/components/auth-layout.tsx @@ -7,7 +7,7 @@ export function AuthLayoutShell({ return (
diff --git a/packages/features/auth/src/components/password-sign-up-container.tsx b/packages/features/auth/src/components/password-sign-up-container.tsx index 631c7a5..6387c47 100644 --- a/packages/features/auth/src/components/password-sign-up-container.tsx +++ b/packages/features/auth/src/components/password-sign-up-container.tsx @@ -4,13 +4,13 @@ import { CheckCircledIcon } from '@radix-ui/react-icons'; import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert'; import { If } from '@kit/ui/if'; +import { Spinner } from '@kit/ui/makerkit/spinner'; import { Trans } from '@kit/ui/trans'; import { useCaptchaToken } from '../captcha/client'; import { usePasswordSignUpFlow } from '../hooks/use-sign-up-flow'; import { AuthErrorAlert } from './auth-error-alert'; import { PasswordSignUpForm } from './password-sign-up-form'; -import { Spinner } from '@kit/ui/makerkit/spinner'; interface EmailPasswordSignUpContainerProps { authConfig: { @@ -56,8 +56,9 @@ export function EmailPasswordSignUpContainer({
- ) : - } + ) : ( + + )} diff --git a/packages/features/auth/src/components/sign-up-methods-container.tsx b/packages/features/auth/src/components/sign-up-methods-container.tsx index 00782bd..a480fb2 100644 --- a/packages/features/auth/src/components/sign-up-methods-container.tsx +++ b/packages/features/auth/src/components/sign-up-methods-container.tsx @@ -1,8 +1,9 @@ 'use client'; -import type { Provider } from '@supabase/supabase-js'; import { useRouter } from 'next/navigation'; +import type { Provider } from '@supabase/supabase-js'; + import { isBrowser } from '@kit/shared/utils'; import { Alert, AlertDescription, AlertTitle } from '@kit/ui/alert'; import { If } from '@kit/ui/if'; @@ -53,7 +54,7 @@ export function SignUpMethodsContainer(props: { return; } setTimeout(() => { - router.replace(props.paths.updateAccount) + router.replace(props.paths.updateAccount); }, 2_500); }} /> diff --git a/packages/features/doctor/package.json b/packages/features/doctor/package.json index 9fab3a4..2f3da81 100644 --- a/packages/features/doctor/package.json +++ b/packages/features/doctor/package.json @@ -43,4 +43,4 @@ ] } } -} \ No newline at end of file +} diff --git a/packages/features/doctor/src/lib/server/actions/table-data-fetching-actions.ts b/packages/features/doctor/src/lib/server/actions/table-data-fetching-actions.ts index 577e82b..8802874 100644 --- a/packages/features/doctor/src/lib/server/actions/table-data-fetching-actions.ts +++ b/packages/features/doctor/src/lib/server/actions/table-data-fetching-actions.ts @@ -1,13 +1,13 @@ 'use server'; -import { getLogger } from '@kit/shared/logger'; - import { getOpenResponses, getOtherResponses, getUserDoneResponses, getUserInProgressResponses, } from '@kit/doctor/services/doctor-analysis.service'; +import { getLogger } from '@kit/shared/logger'; + import { doctorAction } from '../utils/doctor-action'; export const getUserDoneResponsesAction = doctorAction( diff --git a/packages/features/doctor/src/lib/server/schema/doctor-analysis.schema.ts b/packages/features/doctor/src/lib/server/schema/doctor-analysis.schema.ts index db8e2be..efda780 100644 --- a/packages/features/doctor/src/lib/server/schema/doctor-analysis.schema.ts +++ b/packages/features/doctor/src/lib/server/schema/doctor-analysis.schema.ts @@ -1,6 +1,6 @@ +import z from 'zod'; import { Database } from '@kit/supabase/database'; -import z from 'zod'; export const doctorJobSelectSchema = z.object({ userId: z.uuid(), diff --git a/packages/features/doctor/src/lib/server/utils/is-doctor.ts b/packages/features/doctor/src/lib/server/utils/is-doctor.ts index 905ee0d..9f89ec6 100644 --- a/packages/features/doctor/src/lib/server/utils/is-doctor.ts +++ b/packages/features/doctor/src/lib/server/utils/is-doctor.ts @@ -9,9 +9,7 @@ import { Database } from '@kit/supabase/database'; */ export async function isDoctor(client: SupabaseClient) { try { - const { data, error } = await client - .schema('medreport') - .rpc('is_doctor'); + const { data, error } = await client.schema('medreport').rpc('is_doctor'); if (error) { throw error; diff --git a/packages/features/doctor/tsconfig.json b/packages/features/doctor/tsconfig.json index 254ef1f..d05f5e7 100644 --- a/packages/features/doctor/tsconfig.json +++ b/packages/features/doctor/tsconfig.json @@ -9,17 +9,9 @@ "./services/*": "./src/lib/server/services/*.ts", "./actions/*": "./src/lib/server/actions/*.ts" }, - "include": [ - "*.ts", - "src", - "app" - ], - "exclude": [ - "node_modules" - ], + "include": ["*.ts", "src", "app"], + "exclude": ["node_modules"], "paths": { - "@components/*": [ - "./src/lib/*" - ], + "@components/*": ["./src/lib/*"] } -} \ No newline at end of file +} diff --git a/packages/features/medusa-storefront/check-env-variables.js b/packages/features/medusa-storefront/check-env-variables.js index 417a00c..2ecdc9e 100644 --- a/packages/features/medusa-storefront/check-env-variables.js +++ b/packages/features/medusa-storefront/check-env-variables.js @@ -1,39 +1,39 @@ -const c = require("ansi-colors") +const c = require('ansi-colors'); const requiredEnvs = [ { - key: "NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY", + key: 'NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY', // TODO: we need a good doc to point this to description: - "Learn how to create a publishable key: https://docs.medusajs.com/v2/resources/storefront-development/publishable-api-keys", + 'Learn how to create a publishable key: https://docs.medusajs.com/v2/resources/storefront-development/publishable-api-keys', }, -] +]; function checkEnvVariables() { const missingEnvs = requiredEnvs.filter(function (env) { - return !process.env[env.key] - }) + return !process.env[env.key]; + }); if (missingEnvs.length > 0) { console.error( - c.red.bold("\n🚫 Error: Missing required environment variables\n") - ) + c.red.bold('\n🚫 Error: Missing required environment variables\n'), + ); missingEnvs.forEach(function (env) { - console.error(c.yellow(` ${c.bold(env.key)}`)) + console.error(c.yellow(` ${c.bold(env.key)}`)); if (env.description) { - console.error(c.dim(` ${env.description}\n`)) + console.error(c.dim(` ${env.description}\n`)); } - }) + }); console.error( c.yellow( - "\nPlease set these variables in your .env file or environment before starting the application.\n" - ) - ) + '\nPlease set these variables in your .env file or environment before starting the application.\n', + ), + ); - process.exit(1) + process.exit(1); } } -module.exports = checkEnvVariables +module.exports = checkEnvVariables; diff --git a/packages/features/medusa-storefront/src/lib/config.ts b/packages/features/medusa-storefront/src/lib/config.ts index f48be4b..83f264b 100644 --- a/packages/features/medusa-storefront/src/lib/config.ts +++ b/packages/features/medusa-storefront/src/lib/config.ts @@ -1,7 +1,7 @@ -import Medusa from "@medusajs/js-sdk"; +import Medusa from '@medusajs/js-sdk'; // Defaults to standard port for Medusa server -let MEDUSA_BACKEND_URL = "http://localhost:9000"; +let MEDUSA_BACKEND_URL = 'http://localhost:9000'; if (process.env.MEDUSA_BACKEND_URL) { MEDUSA_BACKEND_URL = process.env.MEDUSA_BACKEND_URL; @@ -9,7 +9,7 @@ if (process.env.MEDUSA_BACKEND_URL) { export const SDK_CONFIG = { baseUrl: MEDUSA_BACKEND_URL, - debug: process.env.NODE_ENV === "development", + debug: process.env.NODE_ENV === 'development', publishableKey: process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY, }; diff --git a/packages/features/medusa-storefront/src/lib/constants.tsx b/packages/features/medusa-storefront/src/lib/constants.tsx index 1a39a62..624b139 100644 --- a/packages/features/medusa-storefront/src/lib/constants.tsx +++ b/packages/features/medusa-storefront/src/lib/constants.tsx @@ -1,9 +1,9 @@ -import React from "react" -import { CreditCard } from "@medusajs/icons" +import React from 'react'; -import Ideal from "@modules/common/icons/ideal" -import Bancontact from "@modules/common/icons/bancontact" -import PayPal from "@modules/common/icons/paypal" +import { CreditCard } from '@medusajs/icons'; +import Bancontact from '@modules/common/icons/bancontact'; +import Ideal from '@modules/common/icons/ideal'; +import PayPal from '@modules/common/icons/paypal'; /* Map of payment provider_id to their title and icon. Add in any payment providers you want to use. */ export const paymentInfoMap: Record< @@ -11,58 +11,58 @@ export const paymentInfoMap: Record< { title: string; icon: React.JSX.Element } > = { pp_stripe_stripe: { - title: "Credit card", + title: 'Credit card', icon: , }, - "pp_stripe-ideal_stripe": { - title: "iDeal", + 'pp_stripe-ideal_stripe': { + title: 'iDeal', icon: , }, - "pp_stripe-bancontact_stripe": { - title: "Bancontact", + 'pp_stripe-bancontact_stripe': { + title: 'Bancontact', icon: , }, pp_paypal_paypal: { - title: "PayPal", + title: 'PayPal', icon: , }, pp_system_default: { - title: "Manual Payment", + title: 'Manual Payment', icon: , }, // Add more payment providers here -} +}; // This only checks if it is native stripe for card payments, it ignores the other stripe-based providers export const isStripe = (providerId?: string) => { - return providerId?.startsWith("pp_stripe_") -} + return providerId?.startsWith('pp_stripe_'); +}; export const isPaypal = (providerId?: string) => { - return providerId?.startsWith("pp_paypal") -} + return providerId?.startsWith('pp_paypal'); +}; export const isManual = (providerId?: string) => { - return providerId?.startsWith("pp_system_default") -} + return providerId?.startsWith('pp_system_default'); +}; // Add currencies that don't need to be divided by 100 export const noDivisionCurrencies = [ - "krw", - "jpy", - "vnd", - "clp", - "pyg", - "xaf", - "xof", - "bif", - "djf", - "gnf", - "kmf", - "mga", - "rwf", - "xpf", - "htg", - "vuv", - "xag", - "xdr", - "xau", -] + 'krw', + 'jpy', + 'vnd', + 'clp', + 'pyg', + 'xaf', + 'xof', + 'bif', + 'djf', + 'gnf', + 'kmf', + 'mga', + 'rwf', + 'xpf', + 'htg', + 'vuv', + 'xag', + 'xdr', + 'xau', +]; diff --git a/packages/features/medusa-storefront/src/lib/context/modal-context.tsx b/packages/features/medusa-storefront/src/lib/context/modal-context.tsx index 6ebccf2..7687c10 100644 --- a/packages/features/medusa-storefront/src/lib/context/modal-context.tsx +++ b/packages/features/medusa-storefront/src/lib/context/modal-context.tsx @@ -1,16 +1,16 @@ -"use client" +'use client'; -import React, { createContext, useContext } from "react" +import React, { createContext, useContext } from 'react'; interface ModalContext { - close: () => void + close: () => void; } -const ModalContext = createContext(null) +const ModalContext = createContext(null); interface ModalProviderProps { - children?: React.ReactNode - close: () => void + children?: React.ReactNode; + close: () => void; } export const ModalProvider = ({ children, close }: ModalProviderProps) => { @@ -22,13 +22,13 @@ export const ModalProvider = ({ children, close }: ModalProviderProps) => { > {children} - ) -} + ); +}; export const useModal = () => { - const context = useContext(ModalContext) + const context = useContext(ModalContext); if (context === null) { - throw new Error("useModal must be used within a ModalProvider") + throw new Error('useModal must be used within a ModalProvider'); } - return context -} + return context; +}; diff --git a/packages/features/medusa-storefront/src/lib/data/cart.ts b/packages/features/medusa-storefront/src/lib/data/cart.ts index 0bb1cfd..411edc5 100644 --- a/packages/features/medusa-storefront/src/lib/data/cart.ts +++ b/packages/features/medusa-storefront/src/lib/data/cart.ts @@ -1,9 +1,12 @@ -"use server"; +'use server'; + +import { revalidateTag } from 'next/cache'; +import { redirect } from 'next/navigation'; + +import { sdk } from '@lib/config'; +import medusaError from '@lib/util/medusa-error'; +import { HttpTypes } from '@medusajs/types'; -import medusaError from "@lib/util/medusa-error"; -import { HttpTypes } from "@medusajs/types"; -import { revalidateTag } from "next/cache"; -import { redirect } from "next/navigation"; import { getAuthHeaders, getCacheOptions, @@ -11,10 +14,9 @@ import { getCartId, removeCartId, setCartId, -} from "./cookies"; -import { getRegion } from "./regions"; -import { sdk } from "@lib/config"; -import { retrieveOrder } from "./orders"; +} from './cookies'; +import { retrieveOrder } from './orders'; +import { getRegion } from './regions'; /** * Retrieves a cart by its ID. If no ID is provided, it will use the cart ID from the cookies. @@ -33,15 +35,15 @@ export async function retrieveCart(cartId?: string) { }; const next = { - ...(await getCacheOptions("carts")), + ...(await getCacheOptions('carts')), }; return await sdk.client .fetch(`/store/carts/${id}`, { - method: "GET", + method: 'GET', query: { fields: - "*items, *region, *items.product, *items.variant, *items.thumbnail, *items.metadata, +items.total, *promotions, +shipping_methods.name", + '*items, *region, *items.product, *items.variant, *items.thumbnail, *items.metadata, +items.total, *promotions, +shipping_methods.name', }, headers, next, @@ -68,19 +70,19 @@ export async function getOrSetCart(countryCode: string) { const cartResp = await sdk.store.cart.create( { region_id: region.id }, {}, - headers + headers, ); cart = cartResp.cart; await setCartId(cart.id); - const cartCacheTag = await getCacheTag("carts"); + const cartCacheTag = await getCacheTag('carts'); revalidateTag(cartCacheTag); } if (cart && cart?.region_id !== region.id) { await sdk.store.cart.update(cart.id, { region_id: region.id }, {}, headers); - const cartCacheTag = await getCacheTag("carts"); + const cartCacheTag = await getCacheTag('carts'); revalidateTag(cartCacheTag); } @@ -89,13 +91,16 @@ export async function getOrSetCart(countryCode: string) { export async function updateCart( { id, ...data }: HttpTypes.StoreUpdateCart & { id?: string }, - { onSuccess, onError }: { onSuccess: () => void, onError: () => void } = { onSuccess: () => {}, onError: () => {} }, + { onSuccess, onError }: { onSuccess: () => void; onError: () => void } = { + onSuccess: () => {}, + onError: () => {}, + }, ) { const cartId = id || (await getCartId()); if (!cartId) { throw new Error( - "No existing cart found, please create one before updating" + 'No existing cart found, please create one before updating', ); } @@ -106,10 +111,10 @@ export async function updateCart( return sdk.store.cart .update(cartId, data, {}, headers) .then(async ({ cart }) => { - const cartCacheTag = await getCacheTag("carts"); + const cartCacheTag = await getCacheTag('carts'); revalidateTag(cartCacheTag); - const fulfillmentCacheTag = await getCacheTag("fulfillment"); + const fulfillmentCacheTag = await getCacheTag('fulfillment'); revalidateTag(fulfillmentCacheTag); onSuccess(); @@ -131,13 +136,13 @@ export async function addToCart({ countryCode: string; }) { if (!variantId) { - throw new Error("Missing variant ID when adding to cart"); + throw new Error('Missing variant ID when adding to cart'); } const cart = await getOrSetCart(countryCode); if (!cart) { - throw new Error("Error retrieving or creating cart"); + throw new Error('Error retrieving or creating cart'); } const headers = { @@ -152,13 +157,13 @@ export async function addToCart({ quantity, }, {}, - headers + headers, ) .then(async () => { - const cartCacheTag = await getCacheTag("carts"); + const cartCacheTag = await getCacheTag('carts'); revalidateTag(cartCacheTag); - const fulfillmentCacheTag = await getCacheTag("fulfillment"); + const fulfillmentCacheTag = await getCacheTag('fulfillment'); revalidateTag(fulfillmentCacheTag); }) .catch(medusaError); @@ -176,13 +181,13 @@ export async function updateLineItem({ metadata?: Record; }) { if (!lineId) { - throw new Error("Missing lineItem ID when updating line item"); + throw new Error('Missing lineItem ID when updating line item'); } const cartId = await getCartId(); if (!cartId) { - throw new Error("Missing cart ID when updating line item"); + throw new Error('Missing cart ID when updating line item'); } const headers = { @@ -192,10 +197,10 @@ export async function updateLineItem({ await sdk.store.cart .updateLineItem(cartId, lineId, { quantity, metadata }, {}, headers) .then(async () => { - const cartCacheTag = await getCacheTag("carts"); + const cartCacheTag = await getCacheTag('carts'); revalidateTag(cartCacheTag); - const fulfillmentCacheTag = await getCacheTag("fulfillment"); + const fulfillmentCacheTag = await getCacheTag('fulfillment'); revalidateTag(fulfillmentCacheTag); }) .catch(medusaError); @@ -203,13 +208,13 @@ export async function updateLineItem({ export async function deleteLineItem(lineId: string) { if (!lineId) { - throw new Error("Missing lineItem ID when deleting line item"); + throw new Error('Missing lineItem ID when deleting line item'); } const cartId = await getCartId(); if (!cartId) { - throw new Error("Missing cart ID when deleting line item"); + throw new Error('Missing cart ID when deleting line item'); } const headers = { @@ -219,10 +224,10 @@ export async function deleteLineItem(lineId: string) { await sdk.store.cart .deleteLineItem(cartId, lineId, headers) .then(async () => { - const cartCacheTag = await getCacheTag("carts"); + const cartCacheTag = await getCacheTag('carts'); revalidateTag(cartCacheTag); - const fulfillmentCacheTag = await getCacheTag("fulfillment"); + const fulfillmentCacheTag = await getCacheTag('fulfillment'); revalidateTag(fulfillmentCacheTag); }) .catch(medusaError); @@ -242,7 +247,7 @@ export async function setShippingMethod({ return sdk.store.cart .addShippingMethod(cartId, { option_id: shippingMethodId }, {}, headers) .then(async () => { - const cartCacheTag = await getCacheTag("carts"); + const cartCacheTag = await getCacheTag('carts'); revalidateTag(cartCacheTag); }) .catch(medusaError); @@ -250,7 +255,7 @@ export async function setShippingMethod({ export async function initiatePaymentSession( cart: HttpTypes.StoreCart, - data: HttpTypes.StoreInitializePaymentSession + data: HttpTypes.StoreInitializePaymentSession, ) { const headers = { ...(await getAuthHeaders()), @@ -259,7 +264,7 @@ export async function initiatePaymentSession( return sdk.store.payment .initiatePaymentSession(cart, data, {}, headers) .then(async (resp) => { - const cartCacheTag = await getCacheTag("carts"); + const cartCacheTag = await getCacheTag('carts'); revalidateTag(cartCacheTag); return resp; }) @@ -268,12 +273,15 @@ export async function initiatePaymentSession( export async function applyPromotions( codes: string[], - { onSuccess, onError }: { onSuccess: () => void, onError: () => void } = { onSuccess: () => {}, onError: () => {} }, + { onSuccess, onError }: { onSuccess: () => void; onError: () => void } = { + onSuccess: () => {}, + onError: () => {}, + }, ) { const cartId = await getCartId(); if (!cartId) { - throw new Error("No existing cart found"); + throw new Error('No existing cart found'); } const headers = { @@ -283,10 +291,10 @@ export async function applyPromotions( return sdk.store.cart .update(cartId, { promo_codes: codes }, {}, headers) .then(async () => { - const cartCacheTag = await getCacheTag("carts"); + const cartCacheTag = await getCacheTag('carts'); revalidateTag(cartCacheTag); - const fulfillmentCacheTag = await getCacheTag("fulfillment"); + const fulfillmentCacheTag = await getCacheTag('fulfillment'); revalidateTag(fulfillmentCacheTag); onSuccess(); @@ -322,7 +330,7 @@ export async function removeDiscount(code: string) { export async function removeGiftCard( codeToRemove: string, - giftCards: any[] + giftCards: any[], // giftCards: GiftCard[] ) { // const cartId = getCartId() @@ -342,9 +350,9 @@ export async function removeGiftCard( export async function submitPromotionForm( currentState: unknown, - formData: FormData + formData: FormData, ) { - const code = formData.get("code") as string; + const code = formData.get('code') as string; try { await applyPromotions([code]); } catch (e: any) { @@ -356,44 +364,44 @@ export async function submitPromotionForm( export async function setAddresses(currentState: unknown, formData: FormData) { try { if (!formData) { - throw new Error("No form data found when setting addresses"); + throw new Error('No form data found when setting addresses'); } const cartId = getCartId(); if (!cartId) { - throw new Error("No existing cart found when setting addresses"); + throw new Error('No existing cart found when setting addresses'); } const data = { shipping_address: { - first_name: formData.get("shipping_address.first_name"), - last_name: formData.get("shipping_address.last_name"), - address_1: formData.get("shipping_address.address_1"), - address_2: "", - company: formData.get("shipping_address.company"), - postal_code: formData.get("shipping_address.postal_code"), - city: formData.get("shipping_address.city"), - country_code: formData.get("shipping_address.country_code"), - province: formData.get("shipping_address.province"), - phone: formData.get("shipping_address.phone"), + first_name: formData.get('shipping_address.first_name'), + last_name: formData.get('shipping_address.last_name'), + address_1: formData.get('shipping_address.address_1'), + address_2: '', + company: formData.get('shipping_address.company'), + postal_code: formData.get('shipping_address.postal_code'), + city: formData.get('shipping_address.city'), + country_code: formData.get('shipping_address.country_code'), + province: formData.get('shipping_address.province'), + phone: formData.get('shipping_address.phone'), }, - email: formData.get("email"), + email: formData.get('email'), } as any; - const sameAsBilling = formData.get("same_as_billing"); - if (sameAsBilling === "on") data.billing_address = data.shipping_address; + const sameAsBilling = formData.get('same_as_billing'); + if (sameAsBilling === 'on') data.billing_address = data.shipping_address; - if (sameAsBilling !== "on") + if (sameAsBilling !== 'on') data.billing_address = { - first_name: formData.get("billing_address.first_name"), - last_name: formData.get("billing_address.last_name"), - address_1: formData.get("billing_address.address_1"), - address_2: "", - company: formData.get("billing_address.company"), - postal_code: formData.get("billing_address.postal_code"), - city: formData.get("billing_address.city"), - country_code: formData.get("billing_address.country_code"), - province: formData.get("billing_address.province"), - phone: formData.get("billing_address.phone"), + first_name: formData.get('billing_address.first_name'), + last_name: formData.get('billing_address.last_name'), + address_1: formData.get('billing_address.address_1'), + address_2: '', + company: formData.get('billing_address.company'), + postal_code: formData.get('billing_address.postal_code'), + city: formData.get('billing_address.city'), + country_code: formData.get('billing_address.country_code'), + province: formData.get('billing_address.province'), + phone: formData.get('billing_address.phone'), }; await updateCart(data); } catch (e: any) { @@ -401,7 +409,7 @@ export async function setAddresses(currentState: unknown, formData: FormData) { } redirect( - `/${formData.get("shipping_address.country_code")}/checkout?step=delivery` + `/${formData.get('shipping_address.country_code')}/checkout?step=delivery`, ); } @@ -410,11 +418,14 @@ export async function setAddresses(currentState: unknown, formData: FormData) { * @param cartId - optional - The ID of the cart to place an order for. * @returns The cart object if the order was successful, or null if not. */ -export async function placeOrder(cartId?: string, options: { revalidateCacheTags: boolean } = { revalidateCacheTags: true }) { +export async function placeOrder( + cartId?: string, + options: { revalidateCacheTags: boolean } = { revalidateCacheTags: true }, +) { const id = cartId || (await getCartId()); if (!id) { - throw new Error("No existing cart found when placing an order"); + throw new Error('No existing cart found when placing an order'); } const headers = { @@ -425,22 +436,22 @@ export async function placeOrder(cartId?: string, options: { revalidateCacheTags .complete(id, {}, headers) .then(async (cartRes) => { if (options?.revalidateCacheTags) { - const cartCacheTag = await getCacheTag("carts"); + const cartCacheTag = await getCacheTag('carts'); revalidateTag(cartCacheTag); } return cartRes; }) .catch(medusaError); - if (cartRes?.type === "order") { + if (cartRes?.type === 'order') { if (options?.revalidateCacheTags) { - const orderCacheTag = await getCacheTag("orders"); + const orderCacheTag = await getCacheTag('orders'); revalidateTag(orderCacheTag); } removeCartId(); } else { - throw new Error("Cart is not an order"); + throw new Error('Cart is not an order'); } return retrieveOrder(cartRes.order.id); @@ -461,14 +472,14 @@ export async function updateRegion(countryCode: string, currentPath: string) { if (cartId) { await updateCart({ region_id: region.id }); - const cartCacheTag = await getCacheTag("carts"); + const cartCacheTag = await getCacheTag('carts'); revalidateTag(cartCacheTag); } - const regionCacheTag = await getCacheTag("regions"); + const regionCacheTag = await getCacheTag('regions'); revalidateTag(regionCacheTag); - const productsCacheTag = await getCacheTag("products"); + const productsCacheTag = await getCacheTag('products'); revalidateTag(productsCacheTag); redirect(`/${countryCode}${currentPath}`); @@ -480,15 +491,15 @@ export async function listCartOptions() { ...(await getAuthHeaders()), }; const next = { - ...(await getCacheOptions("shippingOptions")), + ...(await getCacheOptions('shippingOptions')), }; return await sdk.client.fetch<{ shipping_options: HttpTypes.StoreCartShippingOption[]; - }>("/store/shipping-options", { + }>('/store/shipping-options', { query: { cart_id: cartId }, next, headers, - cache: "force-cache", + cache: 'force-cache', }); } diff --git a/packages/features/medusa-storefront/src/lib/data/categories.ts b/packages/features/medusa-storefront/src/lib/data/categories.ts index b4db69d..a2ef202 100644 --- a/packages/features/medusa-storefront/src/lib/data/categories.ts +++ b/packages/features/medusa-storefront/src/lib/data/categories.ts @@ -1,34 +1,35 @@ -import { sdk } from "@lib/config"; -import { HttpTypes } from "@medusajs/types"; -import { getCacheOptions } from "./cookies"; +import { sdk } from '@lib/config'; +import { HttpTypes } from '@medusajs/types'; + +import { getCacheOptions } from './cookies'; export const listCategories = async (query?: Record) => { const next = { - ...(await getCacheOptions("categories")), + ...(await getCacheOptions('categories')), }; const limit = query?.limit || 100; return sdk.client .fetch<{ product_categories: HttpTypes.StoreProductCategory[] }>( - "/store/product-categories", + '/store/product-categories', { query: { fields: - "*category_children, *products, *parent_category, *parent_category.parent_category", + '*category_children, *products, *parent_category, *parent_category.parent_category', limit, ...query, }, next, - cache: "force-cache", - } + cache: 'force-cache', + }, ) .then(({ product_categories }) => product_categories); }; export const getCategoryByHandle = async (categoryHandle: string[]) => { const { product_categories } = await getProductCategories({ - handle: `${categoryHandle.join("/")}`, + handle: `${categoryHandle.join('/')}`, limit: 1, }); return product_categories[0]; @@ -37,14 +38,14 @@ export const getCategoryByHandle = async (categoryHandle: string[]) => { export const getProductCategories = async ({ handle, limit, - fields = "*category_children, *products", + fields = '*category_children, *products', }: { handle?: string; limit?: number; fields?: string; } = {}) => { const next = { - ...(await getCacheOptions("categories")), + ...(await getCacheOptions('categories')), }; return sdk.client.fetch( @@ -57,6 +58,6 @@ export const getProductCategories = async ({ }, next, //cache: "force-cache", - } + }, ); }; diff --git a/packages/features/medusa-storefront/src/lib/data/collections.ts b/packages/features/medusa-storefront/src/lib/data/collections.ts index ce3b4d6..540e2f5 100644 --- a/packages/features/medusa-storefront/src/lib/data/collections.ts +++ b/packages/features/medusa-storefront/src/lib/data/collections.ts @@ -1,12 +1,13 @@ -"use server"; +'use server'; -import { sdk, SDK_CONFIG } from "@lib/config"; -import { HttpTypes } from "@medusajs/types"; -import { getCacheOptions } from "./cookies"; +import { SDK_CONFIG, sdk } from '@lib/config'; +import { HttpTypes } from '@medusajs/types'; + +import { getCacheOptions } from './cookies'; export const retrieveCollection = async (id: string) => { const next = { - ...(await getCacheOptions("collections")), + ...(await getCacheOptions('collections')), }; return sdk.client @@ -14,46 +15,46 @@ export const retrieveCollection = async (id: string) => { `/store/collections/${id}`, { next, - cache: "force-cache", - } + cache: 'force-cache', + }, ) .then(({ collection }) => collection); }; export const listCollections = async ( - queryParams: Record = {} + queryParams: Record = {}, ): Promise<{ collections: HttpTypes.StoreCollection[]; count: number }> => { const next = { - ...(await getCacheOptions("collections")), + ...(await getCacheOptions('collections')), }; - queryParams.limit = queryParams.limit || "100"; - queryParams.offset = queryParams.offset || "0"; - console.log("SDK_CONFIG: ", SDK_CONFIG.baseUrl); + queryParams.limit = queryParams.limit || '100'; + queryParams.offset = queryParams.offset || '0'; + console.log('SDK_CONFIG: ', SDK_CONFIG.baseUrl); return sdk.client .fetch<{ collections: HttpTypes.StoreCollection[]; count: number }>( - "/store/collections", + '/store/collections', { query: queryParams, next, - cache: "force-cache", - } + cache: 'force-cache', + }, ) .then(({ collections }) => ({ collections, count: collections.length })); }; export const getCollectionByHandle = async ( - handle: string + handle: string, ): Promise => { const next = { - ...(await getCacheOptions("collections")), + ...(await getCacheOptions('collections')), }; return sdk.client .fetch(`/store/collections`, { - query: { handle, fields: "*products" }, + query: { handle, fields: '*products' }, next, - cache: "force-cache", + cache: 'force-cache', }) .then(({ collections }) => collections[0]); }; diff --git a/packages/features/medusa-storefront/src/lib/data/cookies.ts b/packages/features/medusa-storefront/src/lib/data/cookies.ts index ede7537..50c973a 100644 --- a/packages/features/medusa-storefront/src/lib/data/cookies.ts +++ b/packages/features/medusa-storefront/src/lib/data/cookies.ts @@ -1,124 +1,124 @@ -import "server-only" +import 'server-only'; -import { cookies as nextCookies } from "next/headers" +import { cookies as nextCookies } from 'next/headers'; const CookieName = { - MEDUSA_CUSTOMER_ID: "_medusa_customer_id", - MEDUSA_JWT: "_medusa_jwt", - MEDUSA_CART_ID: "_medusa_cart_id", - MEDUSA_CACHE_ID: "_medusa_cache_id", -} + MEDUSA_CUSTOMER_ID: '_medusa_customer_id', + MEDUSA_JWT: '_medusa_jwt', + MEDUSA_CART_ID: '_medusa_cart_id', + MEDUSA_CACHE_ID: '_medusa_cache_id', +}; export const getAuthHeaders = async (): Promise< { authorization: string } | {} > => { try { - const cookies = await nextCookies() - const token = cookies.get(CookieName.MEDUSA_JWT)?.value + const cookies = await nextCookies(); + const token = cookies.get(CookieName.MEDUSA_JWT)?.value; if (!token) { - return {} + return {}; } - return { authorization: `Bearer ${token}` } + return { authorization: `Bearer ${token}` }; } catch { - return {} + return {}; } -} +}; -export const getMedusaCustomerId = async (): Promise< - { customerId: string | null } -> => { +export const getMedusaCustomerId = async (): Promise<{ + customerId: string | null; +}> => { try { - const cookies = await nextCookies() - const customerId = cookies.get(CookieName.MEDUSA_CUSTOMER_ID)?.value + const cookies = await nextCookies(); + const customerId = cookies.get(CookieName.MEDUSA_CUSTOMER_ID)?.value; if (!customerId) { - return { customerId: null } + return { customerId: null }; } - return { customerId } + return { customerId }; } catch { - return { customerId: null } + return { customerId: null }; } -} +}; export const getCacheTag = async (tag: string): Promise => { try { - const cookies = await nextCookies() - const cacheId = cookies.get(CookieName.MEDUSA_CACHE_ID)?.value + const cookies = await nextCookies(); + const cacheId = cookies.get(CookieName.MEDUSA_CACHE_ID)?.value; if (!cacheId) { - return "" + return ''; } - return `${tag}-${cacheId}` + return `${tag}-${cacheId}`; } catch (error) { - return "" + return ''; } -} +}; export const getCacheOptions = async ( - tag: string + tag: string, ): Promise<{ tags: string[] } | {}> => { - if (typeof window !== "undefined") { - return {} + if (typeof window !== 'undefined') { + return {}; } - const cacheTag = await getCacheTag(tag) + const cacheTag = await getCacheTag(tag); if (!cacheTag) { - return {} + return {}; } - return { tags: [`${cacheTag}`] } -} + return { tags: [`${cacheTag}`] }; +}; const getCookieSharedOptions = () => ({ maxAge: 60 * 60 * 24 * 7, httpOnly: false, - secure: process.env.NODE_ENV === "production", + secure: process.env.NODE_ENV === 'production', }); const getCookieResetOptions = () => ({ maxAge: -1, }); export const setAuthToken = async (token: string) => { - const cookies = await nextCookies() + const cookies = await nextCookies(); cookies.set(CookieName.MEDUSA_JWT, token, { ...getCookieSharedOptions(), - }) -} + }); +}; export const setMedusaCustomerId = async (customerId: string) => { - const cookies = await nextCookies() + const cookies = await nextCookies(); cookies.set(CookieName.MEDUSA_CUSTOMER_ID, customerId, { ...getCookieSharedOptions(), - }) -} + }); +}; export const removeAuthToken = async () => { - const cookies = await nextCookies() - cookies.set(CookieName.MEDUSA_JWT, "", { + const cookies = await nextCookies(); + cookies.set(CookieName.MEDUSA_JWT, '', { ...getCookieResetOptions(), - }) -} + }); +}; export const getCartId = async () => { - const cookies = await nextCookies() - return cookies.get(CookieName.MEDUSA_CART_ID)?.value -} + const cookies = await nextCookies(); + return cookies.get(CookieName.MEDUSA_CART_ID)?.value; +}; export const setCartId = async (cartId: string) => { - const cookies = await nextCookies() + const cookies = await nextCookies(); cookies.set(CookieName.MEDUSA_CART_ID, cartId, { ...getCookieSharedOptions(), - }) -} + }); +}; export const removeCartId = async () => { - const cookies = await nextCookies() - cookies.set(CookieName.MEDUSA_CART_ID, "", { + const cookies = await nextCookies(); + cookies.set(CookieName.MEDUSA_CART_ID, '', { ...getCookieResetOptions(), - }) -} + }); +}; diff --git a/packages/features/medusa-storefront/src/lib/data/customer.ts b/packages/features/medusa-storefront/src/lib/data/customer.ts index 3c05921..405edf1 100644 --- a/packages/features/medusa-storefront/src/lib/data/customer.ts +++ b/packages/features/medusa-storefront/src/lib/data/customer.ts @@ -1,9 +1,11 @@ -"use server" +'use server'; + +import { revalidateTag } from 'next/cache'; + +import { sdk } from '@lib/config'; +import medusaError from '@lib/util/medusa-error'; +import { HttpTypes } from '@medusajs/types'; -import { sdk } from "@lib/config" -import medusaError from "@lib/util/medusa-error" -import { HttpTypes } from "@medusajs/types" -import { revalidateTag } from "next/cache" import { getAuthHeaders, getCacheOptions, @@ -12,268 +14,275 @@ import { removeAuthToken, removeCartId, setAuthToken, -} from "./cookies" +} from './cookies'; export const retrieveCustomer = async (): Promise => { - const authHeaders = await getAuthHeaders() + const authHeaders = await getAuthHeaders(); - if (!authHeaders) return null + if (!authHeaders) return null; const headers = { ...authHeaders, - } + }; const next = { - ...(await getCacheOptions("customers")), - } + ...(await getCacheOptions('customers')), + }; return await sdk.client .fetch<{ customer: HttpTypes.StoreCustomer }>(`/store/customers/me`, { - method: "GET", + method: 'GET', query: { - fields: "*orders", + fields: '*orders', }, headers, next, - cache: "force-cache", + cache: 'force-cache', }) .then(({ customer }) => customer) - .catch(() => null) - } + .catch(() => null); + }; export const updateCustomer = async (body: HttpTypes.StoreUpdateCustomer) => { const headers = { ...(await getAuthHeaders()), - } + }; const updateRes = await sdk.store.customer .update(body, {}, headers) .then(({ customer }) => customer) - .catch(medusaError) + .catch(medusaError); - const cacheTag = await getCacheTag("customers") - revalidateTag(cacheTag) + const cacheTag = await getCacheTag('customers'); + revalidateTag(cacheTag); - return updateRes -} + return updateRes; +}; export async function signup(_currentState: unknown, formData: FormData) { - const password = formData.get("password") as string + const password = formData.get('password') as string; const customerForm = { - email: formData.get("email") as string, - first_name: formData.get("first_name") as string, - last_name: formData.get("last_name") as string, - phone: formData.get("phone") as string, - } + email: formData.get('email') as string, + first_name: formData.get('first_name') as string, + last_name: formData.get('last_name') as string, + phone: formData.get('phone') as string, + }; try { - const token = await sdk.auth.register("customer", "emailpass", { + const token = await sdk.auth.register('customer', 'emailpass', { email: customerForm.email, password: password, - }) + }); - await setAuthToken(token as string) + await setAuthToken(token as string); const headers = { ...(await getAuthHeaders()), - } + }; const { customer: createdCustomer } = await sdk.store.customer.create( customerForm, {}, - headers - ) + headers, + ); - const loginToken = await sdk.auth.login("customer", "emailpass", { + const loginToken = await sdk.auth.login('customer', 'emailpass', { email: customerForm.email, password, - }) + }); - await setAuthToken(loginToken as string) + await setAuthToken(loginToken as string); - const customerCacheTag = await getCacheTag("customers") - revalidateTag(customerCacheTag) + const customerCacheTag = await getCacheTag('customers'); + revalidateTag(customerCacheTag); - await transferCart() + await transferCart(); - return createdCustomer + return createdCustomer; } catch (error: any) { - return error.toString() + return error.toString(); } } export async function login(_currentState: unknown, formData: FormData) { - const email = formData.get("email") as string - const password = formData.get("password") as string + const email = formData.get('email') as string; + const password = formData.get('password') as string; try { await sdk.auth - .login("customer", "emailpass", { email, password }) + .login('customer', 'emailpass', { email, password }) .then(async (token) => { - await setAuthToken(token as string) - const customerCacheTag = await getCacheTag("customers") - revalidateTag(customerCacheTag) - }) + await setAuthToken(token as string); + const customerCacheTag = await getCacheTag('customers'); + revalidateTag(customerCacheTag); + }); } catch (error: any) { - return error.toString() + return error.toString(); } try { - await transferCart() + await transferCart(); } catch (error: any) { - return error.toString() + return error.toString(); } } -export async function medusaLogout(countryCode = 'ee', canRevalidateTags = true) { - await sdk.auth.logout() +export async function medusaLogout( + countryCode = 'ee', + canRevalidateTags = true, +) { + await sdk.auth.logout(); - await removeAuthToken() + await removeAuthToken(); if (canRevalidateTags) { - const customerCacheTag = await getCacheTag("customers") - revalidateTag(customerCacheTag) + const customerCacheTag = await getCacheTag('customers'); + revalidateTag(customerCacheTag); } - await removeCartId() + await removeCartId(); if (canRevalidateTags) { - const cartCacheTag = await getCacheTag("carts") - revalidateTag(cartCacheTag) + const cartCacheTag = await getCacheTag('carts'); + revalidateTag(cartCacheTag); } } export async function transferCart() { - const cartId = await getCartId() + const cartId = await getCartId(); if (!cartId) { - return + return; } - const headers = await getAuthHeaders() + const headers = await getAuthHeaders(); - await sdk.store.cart.transferCart(cartId, {}, headers) + await sdk.store.cart.transferCart(cartId, {}, headers); - const cartCacheTag = await getCacheTag("carts") - revalidateTag(cartCacheTag) + const cartCacheTag = await getCacheTag('carts'); + revalidateTag(cartCacheTag); } export const addCustomerAddress = async ( currentState: Record, - formData: FormData + formData: FormData, ): Promise => { - const isDefaultBilling = (currentState.isDefaultBilling as boolean) || false - const isDefaultShipping = (currentState.isDefaultShipping as boolean) || false + const isDefaultBilling = (currentState.isDefaultBilling as boolean) || false; + const isDefaultShipping = + (currentState.isDefaultShipping as boolean) || false; const address = { - first_name: formData.get("first_name") as string, - last_name: formData.get("last_name") as string, - company: formData.get("company") as string, - address_1: formData.get("address_1") as string, - address_2: formData.get("address_2") as string, - city: formData.get("city") as string, - postal_code: formData.get("postal_code") as string, - province: formData.get("province") as string, - country_code: formData.get("country_code") as string, - phone: formData.get("phone") as string, + first_name: formData.get('first_name') as string, + last_name: formData.get('last_name') as string, + company: formData.get('company') as string, + address_1: formData.get('address_1') as string, + address_2: formData.get('address_2') as string, + city: formData.get('city') as string, + postal_code: formData.get('postal_code') as string, + province: formData.get('province') as string, + country_code: formData.get('country_code') as string, + phone: formData.get('phone') as string, is_default_billing: isDefaultBilling, is_default_shipping: isDefaultShipping, - } + }; const headers = { ...(await getAuthHeaders()), - } + }; return sdk.store.customer .createAddress(address, {}, headers) .then(async ({ customer }) => { - const customerCacheTag = await getCacheTag("customers") - revalidateTag(customerCacheTag) - return { success: true, error: null } + const customerCacheTag = await getCacheTag('customers'); + revalidateTag(customerCacheTag); + return { success: true, error: null }; }) .catch((err) => { - return { success: false, error: err.toString() } - }) -} + return { success: false, error: err.toString() }; + }); +}; export const deleteCustomerAddress = async ( - addressId: string + addressId: string, ): Promise => { const headers = { ...(await getAuthHeaders()), - } + }; await sdk.store.customer .deleteAddress(addressId, headers) .then(async () => { - const customerCacheTag = await getCacheTag("customers") - revalidateTag(customerCacheTag) - return { success: true, error: null } + const customerCacheTag = await getCacheTag('customers'); + revalidateTag(customerCacheTag); + return { success: true, error: null }; }) .catch((err) => { - return { success: false, error: err.toString() } - }) -} + return { success: false, error: err.toString() }; + }); +}; export const updateCustomerAddress = async ( currentState: Record, - formData: FormData + formData: FormData, ): Promise => { const addressId = - (currentState.addressId as string) || (formData.get("addressId") as string) + (currentState.addressId as string) || (formData.get('addressId') as string); if (!addressId) { - return { success: false, error: "Address ID is required" } + return { success: false, error: 'Address ID is required' }; } const address = { - first_name: formData.get("first_name") as string, - last_name: formData.get("last_name") as string, - company: formData.get("company") as string, - address_1: formData.get("address_1") as string, - address_2: formData.get("address_2") as string, - city: formData.get("city") as string, - postal_code: formData.get("postal_code") as string, - province: formData.get("province") as string, - country_code: formData.get("country_code") as string, - } as HttpTypes.StoreUpdateCustomerAddress + first_name: formData.get('first_name') as string, + last_name: formData.get('last_name') as string, + company: formData.get('company') as string, + address_1: formData.get('address_1') as string, + address_2: formData.get('address_2') as string, + city: formData.get('city') as string, + postal_code: formData.get('postal_code') as string, + province: formData.get('province') as string, + country_code: formData.get('country_code') as string, + } as HttpTypes.StoreUpdateCustomerAddress; - const phone = formData.get("phone") as string + const phone = formData.get('phone') as string; if (phone) { - address.phone = phone + address.phone = phone; } const headers = { ...(await getAuthHeaders()), - } + }; return sdk.store.customer .updateAddress(addressId, address, {}, headers) .then(async () => { - const customerCacheTag = await getCacheTag("customers") - revalidateTag(customerCacheTag) - return { success: true, error: null } + const customerCacheTag = await getCacheTag('customers'); + revalidateTag(customerCacheTag); + return { success: true, error: null }; }) .catch((err) => { - return { success: false, error: err.toString() } - }) -} + return { success: false, error: err.toString() }; + }); +}; async function medusaLogin(email: string, password: string) { - const token = await sdk.auth.login("customer", "emailpass", { email, password }); + const token = await sdk.auth.login('customer', 'emailpass', { + email, + password, + }); await setAuthToken(token as string); try { await transferCart(); } catch (e) { - console.error("Failed to transfer cart", e); + console.error('Failed to transfer cart', e); } const customer = await retrieveCustomer(); if (!customer) { - throw new Error("Customer not found for active session"); + throw new Error('Customer not found for active session'); } return customer.id; @@ -290,29 +299,41 @@ async function medusaRegister({ name: string | undefined; lastName: string | undefined; }) { - console.info(`Creating new Medusa account for Keycloak user with email=${email}`); - - const registerToken = await sdk.auth.register("customer", "emailpass", { email, password }); + console.info( + `Creating new Medusa account for Keycloak user with email=${email}`, + ); + + const registerToken = await sdk.auth.register('customer', 'emailpass', { + email, + password, + }); await setAuthToken(registerToken); - console.info(`Creating new Medusa customer profile for Keycloak user with email=${email} and name=${name} and lastName=${lastName}`); + console.info( + `Creating new Medusa customer profile for Keycloak user with email=${email} and name=${name} and lastName=${lastName}`, + ); await sdk.store.customer.create( { email, first_name: name, last_name: lastName }, {}, { ...(await getAuthHeaders()), - }); + }, + ); } -export async function medusaLoginOrRegister(credentials: { - email: string - supabaseUserId?: string - name?: string, - lastName?: string, -} & ({ isDevPasswordLogin: true; password: string } | { isDevPasswordLogin?: false; password?: undefined })) { +export async function medusaLoginOrRegister( + credentials: { + email: string; + supabaseUserId?: string; + name?: string; + lastName?: string; + } & ( + | { isDevPasswordLogin: true; password: string } + | { isDevPasswordLogin?: false; password?: undefined } + ), +) { const { email, supabaseUserId, name, lastName } = credentials; - const password = await (async () => { if (credentials.isDevPasswordLogin) { return credentials.password; @@ -324,13 +345,19 @@ export async function medusaLoginOrRegister(credentials: { try { return await medusaLogin(email, password); } catch (loginError) { - console.error("Failed to login customer, attempting to register", loginError); + console.error( + 'Failed to login customer, attempting to register', + loginError, + ); try { await medusaRegister({ email, password, name, lastName }); return await medusaLogin(email, password); } catch (registerError) { - console.error("Failed to create Medusa account for user with email=${email}", registerError); + console.error( + 'Failed to create Medusa account for user with email=${email}', + registerError, + ); throw medusaError(registerError); } } @@ -340,7 +367,10 @@ export async function medusaLoginOrRegister(credentials: { * Generate a deterministic password based on user identifier * This ensures the same user always gets the same password for Medusa */ -async function generateDeterministicPassword(email: string, userId?: string): Promise { +async function generateDeterministicPassword( + email: string, + userId?: string, +): Promise { // Use the user ID or email as the base for deterministic generation const baseString = userId || email; const secret = process.env.MEDUSA_PASSWORD_SECRET!; @@ -356,13 +386,15 @@ async function generateDeterministicPassword(email: string, userId?: string): Pr keyData, { name: 'HMAC', hash: 'SHA-256' }, false, - ['sign'] + ['sign'], ); // Generate HMAC const signature = await crypto.subtle.sign('HMAC', key, messageData); // Convert to base64 and make it a valid password const hashArray = Array.from(new Uint8Array(signature)); - const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); + const hashHex = hashArray + .map((b) => b.toString(16).padStart(2, '0')) + .join(''); // Take first 24 characters and add some complexity const basePassword = hashHex.substring(0, 24); // Add some required complexity for Medusa (uppercase, lowercase, numbers, symbols) diff --git a/packages/features/medusa-storefront/src/lib/data/fulfillment.ts b/packages/features/medusa-storefront/src/lib/data/fulfillment.ts index 1aa28a7..abf9e01 100644 --- a/packages/features/medusa-storefront/src/lib/data/fulfillment.ts +++ b/packages/features/medusa-storefront/src/lib/data/fulfillment.ts @@ -1,70 +1,71 @@ -"use server" +'use server'; -import { sdk } from "@lib/config" -import { HttpTypes } from "@medusajs/types" -import { getAuthHeaders, getCacheOptions } from "./cookies" +import { sdk } from '@lib/config'; +import { HttpTypes } from '@medusajs/types'; + +import { getAuthHeaders, getCacheOptions } from './cookies'; export const listCartShippingMethods = async (cartId: string) => { const headers = { ...(await getAuthHeaders()), - } + }; const next = { - ...(await getCacheOptions("fulfillment")), - } + ...(await getCacheOptions('fulfillment')), + }; return sdk.client .fetch( `/store/shipping-options`, { - method: "GET", + method: 'GET', query: { cart_id: cartId, fields: - "+service_zone.fulfllment_set.type,*service_zone.fulfillment_set.location.address", + '+service_zone.fulfllment_set.type,*service_zone.fulfillment_set.location.address', }, headers, next, - cache: "force-cache", - } + cache: 'force-cache', + }, ) .then(({ shipping_options }) => shipping_options) .catch(() => { - return null - }) -} + return null; + }); +}; export const calculatePriceForShippingOption = async ( optionId: string, cartId: string, - data?: Record + data?: Record, ) => { const headers = { ...(await getAuthHeaders()), - } + }; const next = { - ...(await getCacheOptions("fulfillment")), - } + ...(await getCacheOptions('fulfillment')), + }; - const body = { cart_id: cartId, data } + const body = { cart_id: cartId, data }; if (data) { - body.data = data + body.data = data; } return sdk.client .fetch<{ shipping_option: HttpTypes.StoreCartShippingOption }>( `/store/shipping-options/${optionId}/calculate`, { - method: "POST", + method: 'POST', body, headers, next, - } + }, ) .then(({ shipping_option }) => shipping_option) .catch((e) => { - return null - }) -} + return null; + }); +}; diff --git a/packages/features/medusa-storefront/src/lib/data/index.ts b/packages/features/medusa-storefront/src/lib/data/index.ts index 45ff164..adc886c 100644 --- a/packages/features/medusa-storefront/src/lib/data/index.ts +++ b/packages/features/medusa-storefront/src/lib/data/index.ts @@ -1,11 +1,11 @@ -export * from "./cart"; -export * from "./categories"; -export * from "./collections"; -export * from "./cookies"; -export * from "./customer"; -export * from "./fulfillment"; -export * from "./onboarding"; -export * from "./orders"; -export * from "./payment"; -export * from "./products"; -export * from "./regions"; +export * from './cart'; +export * from './categories'; +export * from './collections'; +export * from './cookies'; +export * from './customer'; +export * from './fulfillment'; +export * from './onboarding'; +export * from './orders'; +export * from './payment'; +export * from './products'; +export * from './regions'; diff --git a/packages/features/medusa-storefront/src/lib/data/onboarding.ts b/packages/features/medusa-storefront/src/lib/data/onboarding.ts index 913ca22..227a277 100644 --- a/packages/features/medusa-storefront/src/lib/data/onboarding.ts +++ b/packages/features/medusa-storefront/src/lib/data/onboarding.ts @@ -1,9 +1,10 @@ -"use server" -import { cookies as nextCookies } from "next/headers" -import { redirect } from "next/navigation" +'use server'; + +import { cookies as nextCookies } from 'next/headers'; +import { redirect } from 'next/navigation'; export async function resetOnboardingState(orderId: string) { - const cookies = await nextCookies() - cookies.set("_medusa_onboarding", "false", { maxAge: -1 }) - redirect(`http://localhost:7001/a/orders/${orderId}`) + const cookies = await nextCookies(); + cookies.set('_medusa_onboarding', 'false', { maxAge: -1 }); + redirect(`http://localhost:7001/a/orders/${orderId}`); } diff --git a/packages/features/medusa-storefront/src/lib/data/orders.ts b/packages/features/medusa-storefront/src/lib/data/orders.ts index cf0231c..c79c579 100644 --- a/packages/features/medusa-storefront/src/lib/data/orders.ts +++ b/packages/features/medusa-storefront/src/lib/data/orders.ts @@ -1,111 +1,112 @@ -"use server" +'use server'; -import { sdk } from "@lib/config" -import medusaError from "@lib/util/medusa-error" -import { getAuthHeaders, getCacheOptions } from "./cookies" -import { HttpTypes } from "@medusajs/types" +import { sdk } from '@lib/config'; +import medusaError from '@lib/util/medusa-error'; +import { HttpTypes } from '@medusajs/types'; + +import { getAuthHeaders, getCacheOptions } from './cookies'; export const retrieveOrder = async (id: string) => { const headers = { ...(await getAuthHeaders()), - } + }; const next = { - ...(await getCacheOptions("orders")), - } + ...(await getCacheOptions('orders')), + }; return sdk.client .fetch(`/store/orders/${id}`, { - method: "GET", + method: 'GET', query: { fields: - "*payment_collections.payments,*items,*items.metadata,*items.variant,*items.product", + '*payment_collections.payments,*items,*items.metadata,*items.variant,*items.product', }, headers, next, - cache: "force-cache", + cache: 'force-cache', }) .then(({ order }) => order) - .catch((err) => medusaError(err)) -} + .catch((err) => medusaError(err)); +}; export const listOrders = async ( limit: number = 10, offset: number = 0, - filters?: Record + filters?: Record, ) => { const headers = { ...(await getAuthHeaders()), - } + }; const next = { - ...(await getCacheOptions("orders")), - } + ...(await getCacheOptions('orders')), + }; return sdk.client .fetch(`/store/orders`, { - method: "GET", + method: 'GET', query: { limit, offset, - order: "-created_at", - fields: "*items,+items.metadata,*items.variant,*items.product", + order: '-created_at', + fields: '*items,+items.metadata,*items.variant,*items.product', ...filters, }, headers, next, }) .then(({ orders }) => orders) - .catch((err) => medusaError(err)) -} + .catch((err) => medusaError(err)); +}; export const createTransferRequest = async ( state: { - success: boolean - error: string | null - order: HttpTypes.StoreOrder | null + success: boolean; + error: string | null; + order: HttpTypes.StoreOrder | null; }, - formData: FormData + formData: FormData, ): Promise<{ - success: boolean - error: string | null - order: HttpTypes.StoreOrder | null + success: boolean; + error: string | null; + order: HttpTypes.StoreOrder | null; }> => { - const id = formData.get("order_id") as string + const id = formData.get('order_id') as string; if (!id) { - return { success: false, error: "Order ID is required", order: null } + return { success: false, error: 'Order ID is required', order: null }; } - const headers = await getAuthHeaders() + const headers = await getAuthHeaders(); return await sdk.store.order .requestTransfer( id, {}, { - fields: "id, email", + fields: 'id, email', }, - headers + headers, ) .then(({ order }) => ({ success: true, error: null, order })) - .catch((err) => ({ success: false, error: err.message, order: null })) -} + .catch((err) => ({ success: false, error: err.message, order: null })); +}; export const acceptTransferRequest = async (id: string, token: string) => { - const headers = await getAuthHeaders() + const headers = await getAuthHeaders(); return await sdk.store.order .acceptTransfer(id, { token }, {}, headers) .then(({ order }) => ({ success: true, error: null, order })) - .catch((err) => ({ success: false, error: err.message, order: null })) -} + .catch((err) => ({ success: false, error: err.message, order: null })); +}; export const declineTransferRequest = async (id: string, token: string) => { - const headers = await getAuthHeaders() + const headers = await getAuthHeaders(); return await sdk.store.order .declineTransfer(id, { token }, {}, headers) .then(({ order }) => ({ success: true, error: null, order })) - .catch((err) => ({ success: false, error: err.message, order: null })) -} + .catch((err) => ({ success: false, error: err.message, order: null })); +}; diff --git a/packages/features/medusa-storefront/src/lib/data/payment.ts b/packages/features/medusa-storefront/src/lib/data/payment.ts index b1366ab..ea1eab2 100644 --- a/packages/features/medusa-storefront/src/lib/data/payment.ts +++ b/packages/features/medusa-storefront/src/lib/data/payment.ts @@ -1,35 +1,36 @@ -"use server" +'use server'; -import { sdk } from "@lib/config" -import { getAuthHeaders, getCacheOptions } from "./cookies" -import { HttpTypes } from "@medusajs/types" +import { sdk } from '@lib/config'; +import { HttpTypes } from '@medusajs/types'; + +import { getAuthHeaders, getCacheOptions } from './cookies'; export const listCartPaymentMethods = async (regionId: string) => { const headers = { ...(await getAuthHeaders()), - } + }; const next = { - ...(await getCacheOptions("payment_providers")), - } + ...(await getCacheOptions('payment_providers')), + }; return sdk.client .fetch( `/store/payment-providers`, { - method: "GET", + method: 'GET', query: { region_id: regionId }, headers, next, - cache: "force-cache", - } + cache: 'force-cache', + }, ) .then(({ payment_providers }) => payment_providers.sort((a, b) => { - return a.id > b.id ? 1 : -1 - }) + return a.id > b.id ? 1 : -1; + }), ) .catch(() => { - return null - }) -} + return null; + }); +}; diff --git a/packages/features/medusa-storefront/src/lib/data/products.ts b/packages/features/medusa-storefront/src/lib/data/products.ts index b65efe9..0b24825 100644 --- a/packages/features/medusa-storefront/src/lib/data/products.ts +++ b/packages/features/medusa-storefront/src/lib/data/products.ts @@ -1,11 +1,12 @@ -"use server" +'use server'; -import { sdk } from "@lib/config" -import { sortProducts } from "@lib/util/sort-products" -import { HttpTypes } from "@medusajs/types" -import { SortOptions } from "@modules/store/components/refinement-list/sort-products" -import { getAuthHeaders, getCacheOptions } from "./cookies" -import { getRegion, retrieveRegion } from "./regions" +import { sdk } from '@lib/config'; +import { sortProducts } from '@lib/util/sort-products'; +import { HttpTypes } from '@medusajs/types'; +import { SortOptions } from '@modules/store/components/refinement-list/sort-products'; + +import { getAuthHeaders, getCacheOptions } from './cookies'; +import { getRegion, retrieveRegion } from './regions'; export const listProducts = async ({ pageParam = 1, @@ -13,70 +14,71 @@ export const listProducts = async ({ countryCode, regionId, }: { - pageParam?: number - queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams & { - "type_id[0]"?: string; - id?: string[], - category_id?: string; - order?: 'title'; - } - countryCode?: string - regionId?: string + pageParam?: number; + queryParams?: HttpTypes.FindParams & + HttpTypes.StoreProductParams & { + 'type_id[0]'?: string; + id?: string[]; + category_id?: string; + order?: 'title'; + }; + countryCode?: string; + regionId?: string; }): Promise<{ - response: { products: HttpTypes.StoreProduct[]; count: number } - nextPage: number | null - queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams + response: { products: HttpTypes.StoreProduct[]; count: number }; + nextPage: number | null; + queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams; }> => { if (!countryCode && !regionId) { - throw new Error("Country code or region ID is required") + throw new Error('Country code or region ID is required'); } - const limit = queryParams?.limit || 12 - const _pageParam = Math.max(pageParam, 1) - const offset = (_pageParam === 1) ? 0 : (_pageParam - 1) * limit; + const limit = queryParams?.limit || 12; + const _pageParam = Math.max(pageParam, 1); + const offset = _pageParam === 1 ? 0 : (_pageParam - 1) * limit; - let region: HttpTypes.StoreRegion | undefined | null + let region: HttpTypes.StoreRegion | undefined | null; if (countryCode) { - region = await getRegion(countryCode) + region = await getRegion(countryCode); } else { - region = await retrieveRegion(regionId!) + region = await retrieveRegion(regionId!); } if (!region) { return { response: { products: [], count: 0 }, nextPage: null, - } + }; } const headers = { ...(await getAuthHeaders()), - } + }; const next = { - ...(await getCacheOptions("products")), - } + ...(await getCacheOptions('products')), + }; return sdk.client .fetch<{ products: HttpTypes.StoreProduct[]; count: number }>( `/store/products`, { - method: "GET", + method: 'GET', query: { limit, offset, region_id: region?.id, fields: - "*variants.calculated_price,+variants.inventory_quantity,+metadata,+tags,+status", + '*variants.calculated_price,+variants.inventory_quantity,+metadata,+tags,+status', ...queryParams, }, headers, next, - } + }, ) .then(({ products, count }) => { - const nextPage = count > offset + limit ? pageParam + 1 : null + const nextPage = count > offset + limit ? pageParam + 1 : null; return { response: { @@ -85,9 +87,9 @@ export const listProducts = async ({ }, nextPage: nextPage, queryParams, - } - }) -} + }; + }); +}; /** * This will fetch 100 products to the Next.js cache and sort them based on the sortBy parameter. @@ -96,19 +98,19 @@ export const listProducts = async ({ export const listProductsWithSort = async ({ page = 0, queryParams, - sortBy = "created_at", + sortBy = 'created_at', countryCode, }: { - page?: number - queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams - sortBy?: SortOptions - countryCode: string + page?: number; + queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams; + sortBy?: SortOptions; + countryCode: string; }): Promise<{ - response: { products: HttpTypes.StoreProduct[]; count: number } - nextPage: number | null - queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams + response: { products: HttpTypes.StoreProduct[]; count: number }; + nextPage: number | null; + queryParams?: HttpTypes.FindParams & HttpTypes.StoreProductParams; }> => { - const limit = queryParams?.limit || 12 + const limit = queryParams?.limit || 12; const { response: { products, count }, @@ -119,15 +121,15 @@ export const listProductsWithSort = async ({ limit: 100, }, countryCode, - }) + }); - const sortedProducts = sortProducts(products, sortBy) + const sortedProducts = sortProducts(products, sortBy); - const pageParam = (page - 1) * limit + const pageParam = (page - 1) * limit; - const nextPage = count > pageParam + limit ? pageParam + limit : null + const nextPage = count > pageParam + limit ? pageParam + limit : null; - const paginatedProducts = sortedProducts.slice(pageParam, pageParam + limit) + const paginatedProducts = sortedProducts.slice(pageParam, pageParam + limit); return { response: { @@ -136,24 +138,27 @@ export const listProductsWithSort = async ({ }, nextPage, queryParams, - } -} + }; +}; -export const listProductTypes = async (): Promise<{ productTypes: HttpTypes.StoreProductType[]; count: number }> => { +export const listProductTypes = async (): Promise<{ + productTypes: HttpTypes.StoreProductType[]; + count: number; +}> => { const next = { - ...(await getCacheOptions("productTypes")), + ...(await getCacheOptions('productTypes')), }; return sdk.client .fetch<{ product_types: HttpTypes.StoreProductType[]; count: number }>( - "/store/product-types", + '/store/product-types', { next, //cache: "force-cache", query: { - fields: "id,value,metadata", + fields: 'id,value,metadata', }, - } + }, ) .then(({ product_types, count }) => { return { productTypes: product_types, count }; diff --git a/packages/features/medusa-storefront/src/lib/data/regions.ts b/packages/features/medusa-storefront/src/lib/data/regions.ts index d724328..8214058 100644 --- a/packages/features/medusa-storefront/src/lib/data/regions.ts +++ b/packages/features/medusa-storefront/src/lib/data/regions.ts @@ -1,66 +1,67 @@ -"use server" +'use server'; -import { sdk } from "@lib/config" -import medusaError from "@lib/util/medusa-error" -import { HttpTypes } from "@medusajs/types" -import { getCacheOptions } from "./cookies" +import { sdk } from '@lib/config'; +import medusaError from '@lib/util/medusa-error'; +import { HttpTypes } from '@medusajs/types'; + +import { getCacheOptions } from './cookies'; export const listRegions = async () => { const next = { - ...(await getCacheOptions("regions")), - } + ...(await getCacheOptions('regions')), + }; return sdk.client .fetch<{ regions: HttpTypes.StoreRegion[] }>(`/store/regions`, { - method: "GET", + method: 'GET', next, - cache: "force-cache", + cache: 'force-cache', }) .then(({ regions }) => regions) - .catch(medusaError) -} + .catch(medusaError); +}; export const retrieveRegion = async (id: string) => { const next = { - ...(await getCacheOptions(["regions", id].join("-"))), - } + ...(await getCacheOptions(['regions', id].join('-'))), + }; return sdk.client .fetch<{ region: HttpTypes.StoreRegion }>(`/store/regions/${id}`, { - method: "GET", + method: 'GET', next, - cache: "force-cache", + cache: 'force-cache', }) .then(({ region }) => region) - .catch(medusaError) -} + .catch(medusaError); +}; -const regionMap = new Map() +const regionMap = new Map(); export const getRegion = async (countryCode: string) => { try { if (regionMap.has(countryCode)) { - return regionMap.get(countryCode) + return regionMap.get(countryCode); } - const regions = await listRegions() + const regions = await listRegions(); if (!regions) { - return null + return null; } regions.forEach((region) => { region.countries?.forEach((c) => { - regionMap.set(c?.iso_2 ?? "", region) - }) - }) + regionMap.set(c?.iso_2 ?? '', region); + }); + }); const region = countryCode ? regionMap.get(countryCode) - : regionMap.get("et") + : regionMap.get('et'); - return region + return region; } catch (e: any) { - return null + return null; } -} +}; diff --git a/packages/features/medusa-storefront/src/lib/hooks/use-in-view.tsx b/packages/features/medusa-storefront/src/lib/hooks/use-in-view.tsx index 50b0c53..11dd56d 100644 --- a/packages/features/medusa-storefront/src/lib/hooks/use-in-view.tsx +++ b/packages/features/medusa-storefront/src/lib/hooks/use-in-view.tsx @@ -1,29 +1,29 @@ -import { RefObject, useEffect, useState } from "react" +import { RefObject, useEffect, useState } from 'react'; export const useIntersection = ( element: RefObject, - rootMargin: string + rootMargin: string, ) => { - const [isVisible, setState] = useState(false) + const [isVisible, setState] = useState(false); useEffect(() => { if (!element.current) { - return + return; } - const el = element.current + const el = element.current; const observer = new IntersectionObserver( ([entry]) => { - setState(entry.isIntersecting) + setState(entry.isIntersecting); }, - { rootMargin } - ) + { rootMargin }, + ); - observer.observe(el) + observer.observe(el); - return () => observer.unobserve(el) - }, [element, rootMargin]) + return () => observer.unobserve(el); + }, [element, rootMargin]); - return isVisible -} + return isVisible; +}; diff --git a/packages/features/medusa-storefront/src/lib/hooks/use-toggle-state.tsx b/packages/features/medusa-storefront/src/lib/hooks/use-toggle-state.tsx index 58180ca..94f6f84 100644 --- a/packages/features/medusa-storefront/src/lib/hooks/use-toggle-state.tsx +++ b/packages/features/medusa-storefront/src/lib/hooks/use-toggle-state.tsx @@ -1,11 +1,11 @@ -import { useState } from "react" +import { useState } from 'react'; export type StateType = [boolean, () => void, () => void, () => void] & { - state: boolean - open: () => void - close: () => void - toggle: () => void -} + state: boolean; + open: () => void; + close: () => void; + toggle: () => void; +}; /** * @@ -21,26 +21,26 @@ export type StateType = [boolean, () => void, () => void, () => void] & { */ const useToggleState = (initialState = false) => { - const [state, setState] = useState(initialState) + const [state, setState] = useState(initialState); const close = () => { - setState(false) - } + setState(false); + }; const open = () => { - setState(true) - } + setState(true); + }; const toggle = () => { - setState((state) => !state) - } + setState((state) => !state); + }; - const hookData = [state, open, close, toggle] as StateType - hookData.state = state - hookData.open = open - hookData.close = close - hookData.toggle = toggle - return hookData -} + const hookData = [state, open, close, toggle] as StateType; + hookData.state = state; + hookData.open = open; + hookData.close = close; + hookData.toggle = toggle; + return hookData; +}; -export default useToggleState +export default useToggleState; diff --git a/packages/features/medusa-storefront/src/lib/util/compare-addresses.ts b/packages/features/medusa-storefront/src/lib/util/compare-addresses.ts index c0eb78e..6e0cc59 100644 --- a/packages/features/medusa-storefront/src/lib/util/compare-addresses.ts +++ b/packages/features/medusa-storefront/src/lib/util/compare-addresses.ts @@ -1,28 +1,28 @@ -import { isEqual, pick } from "lodash" +import { isEqual, pick } from 'lodash'; export default function compareAddresses(address1: any, address2: any) { return isEqual( pick(address1, [ - "first_name", - "last_name", - "address_1", - "company", - "postal_code", - "city", - "country_code", - "province", - "phone", + 'first_name', + 'last_name', + 'address_1', + 'company', + 'postal_code', + 'city', + 'country_code', + 'province', + 'phone', ]), pick(address2, [ - "first_name", - "last_name", - "address_1", - "company", - "postal_code", - "city", - "country_code", - "province", - "phone", - ]) - ) + 'first_name', + 'last_name', + 'address_1', + 'company', + 'postal_code', + 'city', + 'country_code', + 'province', + 'phone', + ]), + ); } diff --git a/packages/features/medusa-storefront/src/lib/util/env.ts b/packages/features/medusa-storefront/src/lib/util/env.ts index 6010249..5f51b91 100644 --- a/packages/features/medusa-storefront/src/lib/util/env.ts +++ b/packages/features/medusa-storefront/src/lib/util/env.ts @@ -1,3 +1,3 @@ export const getBaseURL = () => { - return process.env.NEXT_PUBLIC_BASE_URL || "https://localhost:8000" -} + return process.env.NEXT_PUBLIC_BASE_URL || 'https://localhost:8000'; +}; diff --git a/packages/features/medusa-storefront/src/lib/util/get-precentage-diff.ts b/packages/features/medusa-storefront/src/lib/util/get-precentage-diff.ts index 274b7f5..ccfda2c 100644 --- a/packages/features/medusa-storefront/src/lib/util/get-precentage-diff.ts +++ b/packages/features/medusa-storefront/src/lib/util/get-precentage-diff.ts @@ -1,6 +1,6 @@ export const getPercentageDiff = (original: number, calculated: number) => { - const diff = original - calculated - const decrease = (diff / original) * 100 + const diff = original - calculated; + const decrease = (diff / original) * 100; - return decrease.toFixed() -} + return decrease.toFixed(); +}; diff --git a/packages/features/medusa-storefront/src/lib/util/get-product-price.ts b/packages/features/medusa-storefront/src/lib/util/get-product-price.ts index 1bb4ee1..b91d40b 100644 --- a/packages/features/medusa-storefront/src/lib/util/get-product-price.ts +++ b/packages/features/medusa-storefront/src/lib/util/get-product-price.ts @@ -1,10 +1,11 @@ -import { HttpTypes } from "@medusajs/types" -import { getPercentageDiff } from "./get-precentage-diff" -import { convertToLocale } from "./money" +import { HttpTypes } from '@medusajs/types'; + +import { getPercentageDiff } from './get-precentage-diff'; +import { convertToLocale } from './money'; export const getPricesForVariant = (variant: any) => { if (!variant?.calculated_price?.calculated_amount) { - return null + return null; } return { @@ -22,25 +23,25 @@ export const getPricesForVariant = (variant: any) => { price_type: variant.calculated_price.calculated_price.price_list_type, percentage_diff: getPercentageDiff( variant.calculated_price.original_amount, - variant.calculated_price.calculated_amount + variant.calculated_price.calculated_amount, ), - } -} + }; +}; export function getProductPrice({ product, variantId, }: { - product: HttpTypes.StoreProduct - variantId?: string + product: HttpTypes.StoreProduct; + variantId?: string; }) { if (!product || !product.id) { - throw new Error("No product provided") + throw new Error('No product provided'); } const cheapestPrice = () => { if (!product || !product.variants?.length) { - return null + return null; } const cheapestVariant: any = product.variants @@ -49,31 +50,31 @@ export function getProductPrice({ return ( a.calculated_price.calculated_amount - b.calculated_price.calculated_amount - ) - })[0] + ); + })[0]; - return getPricesForVariant(cheapestVariant) - } + return getPricesForVariant(cheapestVariant); + }; const variantPrice = () => { if (!product || !variantId) { - return null + return null; } const variant: any = product.variants?.find( - (v) => v.id === variantId || v.sku === variantId - ) + (v) => v.id === variantId || v.sku === variantId, + ); if (!variant) { - return null + return null; } - return getPricesForVariant(variant) - } + return getPricesForVariant(variant); + }; return { product, cheapestPrice: cheapestPrice(), variantPrice: variantPrice(), - } + }; } diff --git a/packages/features/medusa-storefront/src/lib/util/index.ts b/packages/features/medusa-storefront/src/lib/util/index.ts index 96efccd..5c5ec86 100644 --- a/packages/features/medusa-storefront/src/lib/util/index.ts +++ b/packages/features/medusa-storefront/src/lib/util/index.ts @@ -1,10 +1,10 @@ -export * from "./compare-addresses"; -export * from "./env"; -export * from "./get-precentage-diff"; -export * from "./get-product-price"; -export * from "./isEmpty"; -export * from "./medusa-error"; -export * from "./money"; -export * from "./product"; -export * from "./repeat"; -export * from "./sort-products"; +export * from './compare-addresses'; +export * from './env'; +export * from './get-precentage-diff'; +export * from './get-product-price'; +export * from './isEmpty'; +export * from './medusa-error'; +export * from './money'; +export * from './product'; +export * from './repeat'; +export * from './sort-products'; diff --git a/packages/features/medusa-storefront/src/lib/util/isEmpty.ts b/packages/features/medusa-storefront/src/lib/util/isEmpty.ts index afcbe0b..30df332 100644 --- a/packages/features/medusa-storefront/src/lib/util/isEmpty.ts +++ b/packages/features/medusa-storefront/src/lib/util/isEmpty.ts @@ -1,11 +1,11 @@ -export const isObject = (input: any) => input instanceof Object -export const isArray = (input: any) => Array.isArray(input) +export const isObject = (input: any) => input instanceof Object; +export const isArray = (input: any) => Array.isArray(input); export const isEmpty = (input: any) => { return ( input === null || input === undefined || (isObject(input) && Object.keys(input).length === 0) || (isArray(input) && (input as any[]).length === 0) || - (typeof input === "string" && input.trim().length === 0) - ) -} + (typeof input === 'string' && input.trim().length === 0) + ); +}; diff --git a/packages/features/medusa-storefront/src/lib/util/medusa-error.ts b/packages/features/medusa-storefront/src/lib/util/medusa-error.ts index 81311f3..6162617 100644 --- a/packages/features/medusa-storefront/src/lib/util/medusa-error.ts +++ b/packages/features/medusa-storefront/src/lib/util/medusa-error.ts @@ -2,21 +2,21 @@ export default function medusaError(error: any): never { if (error.response) { // The request was made and the server responded with a status code // that falls out of the range of 2xx - const u = new URL(error.config.url, error.config.baseURL) - console.error("Resource:", u.toString()) - console.error("Response data:", error.response.data) - console.error("Status code:", error.response.status) - console.error("Headers:", error.response.headers) + const u = new URL(error.config.url, error.config.baseURL); + console.error('Resource:', u.toString()); + console.error('Response data:', error.response.data); + console.error('Status code:', error.response.status); + console.error('Headers:', error.response.headers); // Extracting the error message from the response data - const message = error.response.data.message || error.response.data + const message = error.response.data.message || error.response.data; - throw new Error(message.charAt(0).toUpperCase() + message.slice(1) + ".") + throw new Error(message.charAt(0).toUpperCase() + message.slice(1) + '.'); } else if (error.request) { // The request was made but no response was received - throw new Error("No response received: " + error.request) + throw new Error('No response received: ' + error.request); } else { // Something happened in setting up the request that triggered an Error - throw new Error("Error setting up the request: " + error.message) + throw new Error('Error setting up the request: ' + error.message); } } diff --git a/packages/features/medusa-storefront/src/lib/util/money.ts b/packages/features/medusa-storefront/src/lib/util/money.ts index 23e955e..f38a413 100644 --- a/packages/features/medusa-storefront/src/lib/util/money.ts +++ b/packages/features/medusa-storefront/src/lib/util/money.ts @@ -1,26 +1,26 @@ -import { isEmpty } from "./isEmpty" +import { isEmpty } from './isEmpty'; type ConvertToLocaleParams = { - amount: number - currency_code: string - minimumFractionDigits?: number - maximumFractionDigits?: number - locale?: string -} + amount: number; + currency_code: string; + minimumFractionDigits?: number; + maximumFractionDigits?: number; + locale?: string; +}; export const convertToLocale = ({ amount, currency_code, minimumFractionDigits, maximumFractionDigits, - locale = "en-US", + locale = 'en-US', }: ConvertToLocaleParams) => { return currency_code && !isEmpty(currency_code) ? new Intl.NumberFormat(locale, { - style: "currency", + style: 'currency', currency: currency_code, minimumFractionDigits, maximumFractionDigits, }).format(amount) - : amount.toString() -} + : amount.toString(); +}; diff --git a/packages/features/medusa-storefront/src/lib/util/product.ts b/packages/features/medusa-storefront/src/lib/util/product.ts index 1c129bc..ac59acf 100644 --- a/packages/features/medusa-storefront/src/lib/util/product.ts +++ b/packages/features/medusa-storefront/src/lib/util/product.ts @@ -1,5 +1,7 @@ -import { HttpTypes } from "@medusajs/types"; +import { HttpTypes } from '@medusajs/types'; export const isSimpleProduct = (product: HttpTypes.StoreProduct): boolean => { - return product.options?.length === 1 && product.options[0].values?.length === 1; -} \ No newline at end of file + return ( + product.options?.length === 1 && product.options[0].values?.length === 1 + ); +}; diff --git a/packages/features/medusa-storefront/src/lib/util/repeat.ts b/packages/features/medusa-storefront/src/lib/util/repeat.ts index 1b5c24f..b807a6a 100644 --- a/packages/features/medusa-storefront/src/lib/util/repeat.ts +++ b/packages/features/medusa-storefront/src/lib/util/repeat.ts @@ -1,5 +1,5 @@ const repeat = (times: number) => { - return Array.from(Array(times).keys()) -} + return Array.from(Array(times).keys()); +}; -export default repeat +export default repeat; diff --git a/packages/features/medusa-storefront/src/lib/util/sort-products.ts b/packages/features/medusa-storefront/src/lib/util/sort-products.ts index 87c2811..f923cdb 100644 --- a/packages/features/medusa-storefront/src/lib/util/sort-products.ts +++ b/packages/features/medusa-storefront/src/lib/util/sort-products.ts @@ -1,8 +1,8 @@ -import { HttpTypes } from "@medusajs/types" -import { SortOptions } from "@modules/store/components/refinement-list/sort-products" +import { HttpTypes } from '@medusajs/types'; +import { SortOptions } from '@modules/store/components/refinement-list/sort-products'; interface MinPricedProduct extends HttpTypes.StoreProduct { - _minPrice?: number + _minPrice?: number; } /** @@ -13,38 +13,38 @@ interface MinPricedProduct extends HttpTypes.StoreProduct { */ export function sortProducts( products: HttpTypes.StoreProduct[], - sortBy: SortOptions + sortBy: SortOptions, ): HttpTypes.StoreProduct[] { - let sortedProducts = products as MinPricedProduct[] + let sortedProducts = products as MinPricedProduct[]; - if (["price_asc", "price_desc"].includes(sortBy)) { + if (['price_asc', 'price_desc'].includes(sortBy)) { // Precompute the minimum price for each product sortedProducts.forEach((product) => { if (product.variants && product.variants.length > 0) { product._minPrice = Math.min( ...product.variants.map( - (variant) => variant?.calculated_price?.calculated_amount || 0 - ) - ) + (variant) => variant?.calculated_price?.calculated_amount || 0, + ), + ); } else { - product._minPrice = Infinity + product._minPrice = Infinity; } - }) + }); // Sort products based on the precomputed minimum prices sortedProducts.sort((a, b) => { - const diff = a._minPrice! - b._minPrice! - return sortBy === "price_asc" ? diff : -diff - }) + const diff = a._minPrice! - b._minPrice!; + return sortBy === 'price_asc' ? diff : -diff; + }); } - if (sortBy === "created_at") { + if (sortBy === 'created_at') { sortedProducts.sort((a, b) => { return ( new Date(b.created_at!).getTime() - new Date(a.created_at!).getTime() - ) - }) + ); + }); } - return sortedProducts + return sortedProducts; } diff --git a/packages/features/medusa-storefront/src/middleware.ts b/packages/features/medusa-storefront/src/middleware.ts index aa2df6c..693b46a 100644 --- a/packages/features/medusa-storefront/src/middleware.ts +++ b/packages/features/medusa-storefront/src/middleware.ts @@ -1,9 +1,10 @@ -import { HttpTypes } from "@medusajs/types"; -import { NextRequest, NextResponse } from "next/server"; +import { NextRequest, NextResponse } from 'next/server'; + +import { HttpTypes } from '@medusajs/types'; const BACKEND_URL = process.env.MEDUSA_BACKEND_URL; const PUBLISHABLE_API_KEY = process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY; -const DEFAULT_REGION = process.env.NEXT_PUBLIC_DEFAULT_REGION || "ee"; +const DEFAULT_REGION = process.env.NEXT_PUBLIC_DEFAULT_REGION || 'ee'; const regionMapCache = { regionMap: new Map(), @@ -15,7 +16,7 @@ async function getRegionMap(cacheId: string) { if (!BACKEND_URL) { throw new Error( - "Middleware.ts: Error fetching regions. Did you set up regions in your Medusa Admin and define a MEDUSA_BACKEND_URL environment variable? Note that the variable is no longer named NEXT_PUBLIC_MEDUSA_BACKEND_URL." + 'Middleware.ts: Error fetching regions. Did you set up regions in your Medusa Admin and define a MEDUSA_BACKEND_URL environment variable? Note that the variable is no longer named NEXT_PUBLIC_MEDUSA_BACKEND_URL.', ); } @@ -26,13 +27,13 @@ async function getRegionMap(cacheId: string) { // Fetch regions from Medusa. We can't use the JS client here because middleware is running on Edge and the client needs a Node environment. const { regions } = await fetch(`${BACKEND_URL}/store/regions`, { headers: { - "x-publishable-api-key": PUBLISHABLE_API_KEY!, + 'x-publishable-api-key': PUBLISHABLE_API_KEY!, }, next: { revalidate: 3600, tags: [`regions-${cacheId}`], }, - cache: "force-cache", + cache: 'force-cache', }).then(async (response) => { const json = await response.json(); @@ -45,14 +46,14 @@ async function getRegionMap(cacheId: string) { if (!regions?.length) { throw new Error( - "No regions found. Please set up regions in your Medusa Admin." + 'No regions found. Please set up regions in your Medusa Admin.', ); } // Create a map of country codes to regions. regions.forEach((region: HttpTypes.StoreRegion) => { region.countries?.forEach((c) => { - regionMapCache.regionMap.set(c.iso_2 ?? "", region); + regionMapCache.regionMap.set(c.iso_2 ?? '', region); }); }); @@ -69,17 +70,17 @@ async function getRegionMap(cacheId: string) { */ async function getCountryCode( request: NextRequest, - regionMap: Map + regionMap: Map, ) { try { let countryCode; const vercelCountryCode = request.headers - .get("x-vercel-ip-country") + .get('x-vercel-ip-country') ?.toLowerCase(); const urlCountryCode = request.nextUrl.pathname - .split("/")[1] + .split('/')[1] ?.toLowerCase(); if (urlCountryCode && regionMap.has(urlCountryCode)) { @@ -94,9 +95,9 @@ async function getCountryCode( return countryCode; } catch (error) { - if (process.env.NODE_ENV === "development") { + if (process.env.NODE_ENV === 'development') { console.error( - "Middleware.ts: Error getting the country code. Did you set up regions in your Medusa Admin and define a MEDUSA_BACKEND_URL environment variable? Note that the variable is no longer named NEXT_PUBLIC_MEDUSA_BACKEND_URL." + 'Middleware.ts: Error getting the country code. Did you set up regions in your Medusa Admin and define a MEDUSA_BACKEND_URL environment variable? Note that the variable is no longer named NEXT_PUBLIC_MEDUSA_BACKEND_URL.', ); } } @@ -110,7 +111,7 @@ export async function middleware(request: NextRequest) { let response = NextResponse.redirect(redirectUrl, 307); - let cacheIdCookie = request.cookies.get("_medusa_cache_id"); + let cacheIdCookie = request.cookies.get('_medusa_cache_id'); let cacheId = cacheIdCookie?.value || crypto.randomUUID(); @@ -118,7 +119,7 @@ export async function middleware(request: NextRequest) { try { regionMap = await getRegionMap(cacheId); } catch (error) { - console.error("Error fetching regions", error); + console.error('Error fetching regions', error); return { redirect: { destination: '/auth/sign-in', @@ -130,7 +131,8 @@ export async function middleware(request: NextRequest) { const countryCode = regionMap && (await getCountryCode(request, regionMap)); const urlHasCountryCode = - countryCode && request.nextUrl.pathname.split("/")[1]?.includes(countryCode); + countryCode && + request.nextUrl.pathname.split('/')[1]?.includes(countryCode); // if one of the country codes is in the url and the cache id is set, return next if (urlHasCountryCode && cacheIdCookie) { @@ -139,7 +141,7 @@ export async function middleware(request: NextRequest) { // if one of the country codes is in the url and the cache id is not set, set the cache id and redirect if (urlHasCountryCode && !cacheIdCookie) { - response.cookies.set("_medusa_cache_id", cacheId, { + response.cookies.set('_medusa_cache_id', cacheId, { maxAge: 60 * 60 * 24, }); @@ -147,14 +149,14 @@ export async function middleware(request: NextRequest) { } // check if the url is a static asset - if (request.nextUrl.pathname.includes(".")) { + if (request.nextUrl.pathname.includes('.')) { return NextResponse.next(); } const redirectPath = - request.nextUrl.pathname === "/" ? "" : request.nextUrl.pathname; + request.nextUrl.pathname === '/' ? '' : request.nextUrl.pathname; - const queryString = request.nextUrl.search ? request.nextUrl.search : ""; + const queryString = request.nextUrl.search ? request.nextUrl.search : ''; // If no country code is set, we redirect to the relevant region. if (!urlHasCountryCode && countryCode) { @@ -167,6 +169,6 @@ export async function middleware(request: NextRequest) { export const config = { matcher: [ - "/((?!api|_next/static|_next/image|favicon.ico|images|assets|png|svg|jpg|jpeg|gif|webp).*)", + '/((?!api|_next/static|_next/image|favicon.ico|images|assets|png|svg|jpg|jpeg|gif|webp).*)', ], }; diff --git a/packages/features/medusa-storefront/src/modules/account/components/account-info/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/account-info/index.tsx index f0c4937..6e54fbc 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/account-info/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/account-info/index.tsx @@ -1,20 +1,21 @@ -import { Disclosure } from "@headlessui/react" -import { Badge, Button, clx } from "@medusajs/ui" -import { useEffect } from "react" +import { useEffect } from 'react'; -import useToggleState from "@lib/hooks/use-toggle-state" -import { useFormStatus } from "react-dom" +import { useFormStatus } from 'react-dom'; + +import { Disclosure } from '@headlessui/react'; +import useToggleState from '@lib/hooks/use-toggle-state'; +import { Badge, Button, clx } from '@medusajs/ui'; type AccountInfoProps = { - label: string - currentInfo: string | React.ReactNode - isSuccess?: boolean - isError?: boolean - errorMessage?: string - clearState: () => void - children?: React.ReactNode - 'data-testid'?: string -} + label: string; + currentInfo: string | React.ReactNode; + isSuccess?: boolean; + isError?: boolean; + errorMessage?: string; + clearState: () => void; + children?: React.ReactNode; + 'data-testid'?: string; +}; const AccountInfo = ({ label, @@ -22,33 +23,35 @@ const AccountInfo = ({ isSuccess, isError, clearState, - errorMessage = "An error occurred, please try again", + errorMessage = 'An error occurred, please try again', children, - 'data-testid': dataTestid + 'data-testid': dataTestid, }: AccountInfoProps) => { - const { state, close, toggle } = useToggleState() + const { state, close, toggle } = useToggleState(); - const { pending } = useFormStatus() + const { pending } = useFormStatus(); const handleToggle = () => { - clearState() - setTimeout(() => toggle(), 100) - } + clearState(); + setTimeout(() => toggle(), 100); + }; useEffect(() => { if (isSuccess) { - close() + close(); } - }, [isSuccess, close]) + }, [isSuccess, close]); return (
- {label} -
- {typeof currentInfo === "string" ? ( - {currentInfo} + {label} +
+ {typeof currentInfo === 'string' ? ( + + {currentInfo} + ) : ( currentInfo )} @@ -57,13 +60,13 @@ const AccountInfo = ({
@@ -73,15 +76,15 @@ const AccountInfo = ({ - + {label} updated succesfully @@ -92,15 +95,15 @@ const AccountInfo = ({ - + {errorMessage} @@ -110,19 +113,19 @@ const AccountInfo = ({
{children}
-
+
- ) -} + ); +}; -export default AccountInfo +export default AccountInfo; diff --git a/packages/features/medusa-storefront/src/modules/account/components/account-nav/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/account-nav/index.tsx index 338dd22..39baeb7 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/account-nav/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/account-nav/index.tsx @@ -1,28 +1,28 @@ -"use client" +'use client'; -import { clx } from "@medusajs/ui" -import { ArrowRightOnRectangle } from "@medusajs/icons" -import { useParams, usePathname } from "next/navigation" +import { useParams, usePathname } from 'next/navigation'; -import ChevronDown from "@modules/common/icons/chevron-down" -import User from "@modules/common/icons/user" -import MapPin from "@modules/common/icons/map-pin" -import Package from "@modules/common/icons/package" -import LocalizedClientLink from "@modules/common/components/localized-client-link" -import { HttpTypes } from "@medusajs/types" -import { medusaLogout } from "@lib/data/customer" +import { medusaLogout } from '@lib/data/customer'; +import { ArrowRightOnRectangle } from '@medusajs/icons'; +import { HttpTypes } from '@medusajs/types'; +import { clx } from '@medusajs/ui'; +import LocalizedClientLink from '@modules/common/components/localized-client-link'; +import ChevronDown from '@modules/common/icons/chevron-down'; +import MapPin from '@modules/common/icons/map-pin'; +import Package from '@modules/common/icons/package'; +import User from '@modules/common/icons/user'; const AccountNav = ({ customer, }: { - customer: HttpTypes.StoreCustomer | null + customer: HttpTypes.StoreCustomer | null; }) => { - const route = usePathname() - const { countryCode } = useParams() as { countryCode: string } + const route = usePathname(); + const { countryCode } = useParams() as { countryCode: string }; const handleLogout = async () => { - await medusaLogout(countryCode) - } + await medusaLogout(countryCode); + }; return (
@@ -30,11 +30,11 @@ const AccountNav = ({ {route !== `/${countryCode}/account` ? ( <> - + Account @@ -48,7 +48,7 @@ const AccountNav = ({
  • <> @@ -56,14 +56,14 @@ const AccountNav = ({ Profile
  • - +
  • <> @@ -71,27 +71,27 @@ const AccountNav = ({ Addresses
  • - +
  • Orders
    - +
  • - + @@ -107,13 +107,13 @@ const AccountNav = ({ )}
    -
    +

    Account

    -
      +
    - ) -} + ); +}; type AccountNavLinkProps = { - href: string - route: string - children: React.ReactNode - "data-testid"?: string -} + href: string; + route: string; + children: React.ReactNode; + 'data-testid'?: string; +}; const AccountNavLink = ({ href, route, children, - "data-testid": dataTestId, + 'data-testid': dataTestId, }: AccountNavLinkProps) => { - const { countryCode }: { countryCode: string } = useParams() + const { countryCode }: { countryCode: string } = useParams(); - const active = route.split(countryCode)[1] === href + const active = route.split(countryCode)[1] === href; return ( {children} - ) -} + ); +}; -export default AccountNav +export default AccountNav; diff --git a/packages/features/medusa-storefront/src/modules/account/components/address-book/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/address-book/index.tsx index edd8ac8..5b69a4a 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/address-book/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/address-book/index.tsx @@ -1,28 +1,29 @@ -import React from "react" +import React from 'react'; -import AddAddress from "../address-card/add-address" -import EditAddress from "../address-card/edit-address-modal" -import { HttpTypes } from "@medusajs/types" +import { HttpTypes } from '@medusajs/types'; + +import AddAddress from '../address-card/add-address'; +import EditAddress from '../address-card/edit-address-modal'; type AddressBookProps = { - customer: HttpTypes.StoreCustomer - region: HttpTypes.StoreRegion -} + customer: HttpTypes.StoreCustomer; + region: HttpTypes.StoreRegion; +}; const AddressBook: React.FC = ({ customer, region }) => { - const { addresses } = customer + const { addresses } = customer; return (
    -
    +
    {addresses.map((address) => { return ( - ) + ); })}
    - ) -} + ); +}; -export default AddressBook +export default AddressBook; diff --git a/packages/features/medusa-storefront/src/modules/account/components/address-card/add-address.tsx b/packages/features/medusa-storefront/src/modules/account/components/address-card/add-address.tsx index 14ad95e..dfcf2e3 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/address-card/add-address.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/address-card/add-address.tsx @@ -1,55 +1,55 @@ -"use client" +'use client'; -import { Plus } from "@medusajs/icons" -import { Button, Heading } from "@medusajs/ui" -import { useEffect, useState, useActionState } from "react" +import { useActionState, useEffect, useState } from 'react'; -import useToggleState from "@lib/hooks/use-toggle-state" -import CountrySelect from "@modules/checkout/components/country-select" -import Input from "@modules/common/components/input" -import Modal from "@modules/common/components/modal" -import { SubmitButton } from "@modules/checkout/components/submit-button" -import { HttpTypes } from "@medusajs/types" -import { addCustomerAddress } from "@lib/data/customer" +import { addCustomerAddress } from '@lib/data/customer'; +import useToggleState from '@lib/hooks/use-toggle-state'; +import { Plus } from '@medusajs/icons'; +import { HttpTypes } from '@medusajs/types'; +import { Button, Heading } from '@medusajs/ui'; +import CountrySelect from '@modules/checkout/components/country-select'; +import { SubmitButton } from '@modules/checkout/components/submit-button'; +import Input from '@modules/common/components/input'; +import Modal from '@modules/common/components/modal'; const AddAddress = ({ region, addresses, }: { - region: HttpTypes.StoreRegion - addresses: HttpTypes.StoreCustomerAddress[] + region: HttpTypes.StoreRegion; + addresses: HttpTypes.StoreCustomerAddress[]; }) => { - const [successState, setSuccessState] = useState(false) - const { state, open, close: closeModal } = useToggleState(false) + const [successState, setSuccessState] = useState(false); + const { state, open, close: closeModal } = useToggleState(false); const [formState, formAction] = useActionState(addCustomerAddress, { isDefaultShipping: addresses.length === 0, success: false, error: null, - }) + }); const close = () => { - setSuccessState(false) - closeModal() - } + setSuccessState(false); + closeModal(); + }; useEffect(() => { if (successState) { - close() + close(); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [successState]) + }, [successState]); useEffect(() => { if (formState.success) { - setSuccessState(true) + setSuccessState(true); } - }, [formState]) + }, [formState]); return ( <>
    {formState.error && (
    {formState.error} @@ -145,7 +145,7 @@ const AddAddress = ({ )} -
    +
    - ) -} + ); +}; -export default Login +export default Login; diff --git a/packages/features/medusa-storefront/src/modules/account/components/order-card/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/order-card/index.tsx index d877231..a6ea23d 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/order-card/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/order-card/index.tsx @@ -1,34 +1,34 @@ -import { Button } from "@medusajs/ui" -import { useMemo } from "react" +import { useMemo } from 'react'; -import Thumbnail from "@modules/products/components/thumbnail" -import LocalizedClientLink from "@modules/common/components/localized-client-link" -import { convertToLocale } from "@lib/util/money" -import { HttpTypes } from "@medusajs/types" +import { convertToLocale } from '@lib/util/money'; +import { HttpTypes } from '@medusajs/types'; +import { Button } from '@medusajs/ui'; +import LocalizedClientLink from '@modules/common/components/localized-client-link'; +import Thumbnail from '@modules/products/components/thumbnail'; type OrderCardProps = { - order: HttpTypes.StoreOrder -} + order: HttpTypes.StoreOrder; +}; const OrderCard = ({ order }: OrderCardProps) => { const numberOfLines = useMemo(() => { return ( order.items?.reduce((acc, item) => { - return acc + item.quantity + return acc + item.quantity; }, 0) ?? 0 - ) - }, [order]) + ); + }, [order]); const numberOfProducts = useMemo(() => { - return order.items?.length ?? 0 - }, [order]) + return order.items?.length ?? 0; + }, [order]); return ( -
    -
    +
    +
    #{order.display_id}
    -
    +
    {new Date(order.created_at).toDateString()} @@ -39,10 +39,10 @@ const OrderCard = ({ order }: OrderCardProps) => { })} {`${numberOfLines} ${ - numberOfLines > 1 ? "items" : "item" + numberOfLines > 1 ? 'items' : 'item' }`}
    -
    +
    {order.items?.slice(0, 3).map((i) => { return (
    { data-testid="order-item" > -
    +
    { {i.quantity}
    - ) + ); })} {numberOfProducts > 4 && ( -
    +
    + {numberOfLines - 4} @@ -81,7 +81,7 @@ const OrderCard = ({ order }: OrderCardProps) => {
    - ) -} + ); +}; -export default OrderCard +export default OrderCard; diff --git a/packages/features/medusa-storefront/src/modules/account/components/order-overview/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/order-overview/index.tsx index 35ffe0b..7d8e4a6 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/order-overview/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/order-overview/index.tsx @@ -1,35 +1,35 @@ -"use client" +'use client'; -import { Button } from "@medusajs/ui" +import { HttpTypes } from '@medusajs/types'; +import { Button } from '@medusajs/ui'; +import LocalizedClientLink from '@modules/common/components/localized-client-link'; -import OrderCard from "../order-card" -import LocalizedClientLink from "@modules/common/components/localized-client-link" -import { HttpTypes } from "@medusajs/types" +import OrderCard from '../order-card'; const OrderOverview = ({ orders }: { orders: HttpTypes.StoreOrder[] }) => { if (orders?.length) { return ( -
    +
    {orders.map((o) => (
    ))}
    - ) + ); } return (

    Nothing to see here

    - You don't have any orders yet, let us change that {":)"} + You don't have any orders yet, let us change that {':)'}

    @@ -39,7 +39,7 @@ const OrderOverview = ({ orders }: { orders: HttpTypes.StoreOrder[] }) => {
    - ) -} + ); +}; -export default OrderOverview +export default OrderOverview; diff --git a/packages/features/medusa-storefront/src/modules/account/components/overview/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/overview/index.tsx index d807e97..7476170 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/overview/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/overview/index.tsx @@ -1,25 +1,24 @@ -import { Container } from "@medusajs/ui" - -import ChevronDown from "@modules/common/icons/chevron-down" -import LocalizedClientLink from "@modules/common/components/localized-client-link" -import { convertToLocale } from "@lib/util/money" -import { HttpTypes } from "@medusajs/types" +import { convertToLocale } from '@lib/util/money'; +import { HttpTypes } from '@medusajs/types'; +import { Container } from '@medusajs/ui'; +import LocalizedClientLink from '@modules/common/components/localized-client-link'; +import ChevronDown from '@modules/common/icons/chevron-down'; type OverviewProps = { - customer: HttpTypes.StoreCustomer | null - orders: HttpTypes.StoreOrder[] | null -} + customer: HttpTypes.StoreCustomer | null; + orders: HttpTypes.StoreOrder[] | null; +}; const Overview = ({ customer, orders }: OverviewProps) => { return (
    -
    -
    +
    +
    Hello {customer?.first_name} - Signed in as:{" "} + Signed in as:{' '} {
    -
    -
    -
    +
    +
    +

    Profile

    @@ -42,7 +41,7 @@ const Overview = ({ customer, orders }: OverviewProps) => { > {getProfileCompletion(customer)}% - + Completed
    @@ -58,7 +57,7 @@ const Overview = ({ customer, orders }: OverviewProps) => { > {customer?.addresses?.length || 0} - + Saved
    @@ -84,8 +83,8 @@ const Overview = ({ customer, orders }: OverviewProps) => { - -
    + +
    Date placed Order number @@ -121,7 +120,7 @@ const Overview = ({ customer, orders }: OverviewProps) => { - ) + ); }) ) : ( No recent orders @@ -132,37 +131,37 @@ const Overview = ({ customer, orders }: OverviewProps) => {
    - ) -} + ); +}; const getProfileCompletion = (customer: HttpTypes.StoreCustomer | null) => { - let count = 0 + let count = 0; if (!customer) { - return 0 + return 0; } if (customer.email) { - count++ + count++; } if (customer.first_name && customer.last_name) { - count++ + count++; } if (customer.phone) { - count++ + count++; } const billingAddress = customer.addresses?.find( - (addr) => addr.is_default_billing - ) + (addr) => addr.is_default_billing, + ); if (billingAddress) { - count++ + count++; } - return (count / 4) * 100 -} + return (count / 4) * 100; +}; -export default Overview +export default Overview; diff --git a/packages/features/medusa-storefront/src/modules/account/components/profile-billing-address/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/profile-billing-address/index.tsx index 95ce947..5ed5621 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/profile-billing-address/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/profile-billing-address/index.tsx @@ -1,18 +1,18 @@ -"use client" +'use client'; -import React, { useEffect, useMemo, useActionState } from "react" +import React, { useActionState, useEffect, useMemo } from 'react'; -import Input from "@modules/common/components/input" -import NativeSelect from "@modules/common/components/native-select" +import { addCustomerAddress, updateCustomerAddress } from '@lib/data/customer'; +import { HttpTypes } from '@medusajs/types'; +import Input from '@modules/common/components/input'; +import NativeSelect from '@modules/common/components/native-select'; -import AccountInfo from "../account-info" -import { HttpTypes } from "@medusajs/types" -import { addCustomerAddress, updateCustomerAddress } from "@lib/data/customer" +import AccountInfo from '../account-info'; type MyInformationProps = { - customer: HttpTypes.StoreCustomer - regions: HttpTypes.StoreRegion[] -} + customer: HttpTypes.StoreCustomer; + regions: HttpTypes.StoreRegion[]; +}; const ProfileBillingAddress: React.FC = ({ customer, @@ -25,51 +25,51 @@ const ProfileBillingAddress: React.FC = ({ return region.countries?.map((country) => ({ value: country.iso_2, label: country.display_name, - })) + })); }) .flat() || [] - ) - }, [regions]) + ); + }, [regions]); - const [successState, setSuccessState] = React.useState(false) + const [successState, setSuccessState] = React.useState(false); const billingAddress = customer.addresses?.find( - (addr) => addr.is_default_billing - ) + (addr) => addr.is_default_billing, + ); const initialState: Record = { isDefaultBilling: true, isDefaultShipping: false, error: false, success: false, - } + }; if (billingAddress) { - initialState.addressId = billingAddress.id + initialState.addressId = billingAddress.id; } const [state, formAction] = useActionState( billingAddress ? updateCustomerAddress : addCustomerAddress, - initialState - ) + initialState, + ); const clearState = () => { - setSuccessState(false) - } + setSuccessState(false); + }; useEffect(() => { - setSuccessState(state.success) - }, [state]) + setSuccessState(state.success); + }, [state]); const currentInfo = useMemo(() => { if (!billingAddress) { - return "No billing address" + return 'No billing address'; } const country = regionOptions?.find( - (country) => country?.value === billingAddress.country_code - )?.label || billingAddress.country_code?.toUpperCase() + (country) => country?.value === billingAddress.country_code, + )?.label || billingAddress.country_code?.toUpperCase(); return (
    @@ -79,15 +79,15 @@ const ProfileBillingAddress: React.FC = ({ {billingAddress.company} {billingAddress.address_1} - {billingAddress.address_2 ? `, ${billingAddress.address_2}` : ""} + {billingAddress.address_2 ? `, ${billingAddress.address_2}` : ''} {billingAddress.postal_code}, {billingAddress.city} {country}
    - ) - }, [billingAddress, regionOptions]) + ); + }, [billingAddress, regionOptions]); return (
    clearState()} className="w-full"> @@ -170,13 +170,13 @@ const ProfileBillingAddress: React.FC = ({ - ) + ); })}
    - ) -} + ); +}; -export default ProfileBillingAddress +export default ProfileBillingAddress; diff --git a/packages/features/medusa-storefront/src/modules/account/components/profile-email/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/profile-email/index.tsx index 48b0bf0..99fd92e 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/profile-email/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/profile-email/index.tsx @@ -1,49 +1,50 @@ -"use client" +'use client'; -import React, { useEffect, useActionState } from "react"; +import React, { useActionState, useEffect } from 'react'; -import Input from "@modules/common/components/input" +import { HttpTypes } from '@medusajs/types'; +import Input from '@modules/common/components/input'; + +import AccountInfo from '../account-info'; -import AccountInfo from "../account-info" -import { HttpTypes } from "@medusajs/types" // import { updateCustomer } from "@lib/data/customer" type MyInformationProps = { - customer: HttpTypes.StoreCustomer -} + customer: HttpTypes.StoreCustomer; +}; const ProfileEmail: React.FC = ({ customer }) => { - const [successState, setSuccessState] = React.useState(false) + const [successState, setSuccessState] = React.useState(false); // TODO: It seems we don't support updating emails now? const updateCustomerEmail = ( _currentState: Record, - formData: FormData + formData: FormData, ) => { const customer = { - email: formData.get("email") as string, - } + email: formData.get('email') as string, + }; try { // await updateCustomer(customer) - return { success: true, error: null } + return { success: true, error: null }; } catch (error: any) { - return { success: false, error: error.toString() } + return { success: false, error: error.toString() }; } - } + }; const [state, formAction] = useActionState(updateCustomerEmail, { error: false, success: false, - }) + }); const clearState = () => { - setSuccessState(false) - } + setSuccessState(false); + }; useEffect(() => { - setSuccessState(state.success) - }, [state]) + setSuccessState(state.success); + }, [state]); return (
    @@ -69,7 +70,7 @@ const ProfileEmail: React.FC = ({ customer }) => {
    - ) -} + ); +}; -export default ProfileEmail +export default ProfileEmail; diff --git a/packages/features/medusa-storefront/src/modules/account/components/profile-name/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/profile-name/index.tsx index be9c258..a30bdce 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/profile-name/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/profile-name/index.tsx @@ -1,49 +1,49 @@ -"use client" +'use client'; -import React, { useEffect, useActionState } from "react"; +import React, { useActionState, useEffect } from 'react'; -import Input from "@modules/common/components/input" +import { updateCustomer } from '@lib/data/customer'; +import { HttpTypes } from '@medusajs/types'; +import Input from '@modules/common/components/input'; -import AccountInfo from "../account-info" -import { HttpTypes } from "@medusajs/types" -import { updateCustomer } from "@lib/data/customer" +import AccountInfo from '../account-info'; type MyInformationProps = { - customer: HttpTypes.StoreCustomer -} + customer: HttpTypes.StoreCustomer; +}; const ProfileName: React.FC = ({ customer }) => { - const [successState, setSuccessState] = React.useState(false) + const [successState, setSuccessState] = React.useState(false); const updateCustomerName = async ( _currentState: Record, - formData: FormData + formData: FormData, ) => { const customer = { - first_name: formData.get("first_name") as string, - last_name: formData.get("last_name") as string, - } + first_name: formData.get('first_name') as string, + last_name: formData.get('last_name') as string, + }; try { - await updateCustomer(customer) - return { success: true, error: null } + await updateCustomer(customer); + return { success: true, error: null }; } catch (error: any) { - return { success: false, error: error.toString() } + return { success: false, error: error.toString() }; } - } + }; const [state, formAction] = useActionState(updateCustomerName, { error: false, success: false, - }) + }); const clearState = () => { - setSuccessState(false) - } + setSuccessState(false); + }; useEffect(() => { - setSuccessState(state.success) - }, [state]) + setSuccessState(state.success); + }, [state]); return (
    @@ -60,20 +60,20 @@ const ProfileName: React.FC = ({ customer }) => { label="First name" name="first_name" required - defaultValue={customer.first_name ?? ""} + defaultValue={customer.first_name ?? ''} data-testid="first-name-input" />
    - ) -} + ); +}; -export default ProfileName +export default ProfileName; diff --git a/packages/features/medusa-storefront/src/modules/account/components/profile-password/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/profile-password/index.tsx index 63e8d90..a6abaa1 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/profile-password/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/profile-password/index.tsx @@ -1,26 +1,28 @@ -"use client" +'use client'; -import React, { useEffect, useActionState } from "react" -import Input from "@modules/common/components/input" -import AccountInfo from "../account-info" -import { HttpTypes } from "@medusajs/types" -import { toast } from "@medusajs/ui" +import React, { useActionState, useEffect } from 'react'; + +import { HttpTypes } from '@medusajs/types'; +import { toast } from '@medusajs/ui'; +import Input from '@modules/common/components/input'; + +import AccountInfo from '../account-info'; type MyInformationProps = { - customer: HttpTypes.StoreCustomer -} + customer: HttpTypes.StoreCustomer; +}; const ProfilePassword: React.FC = ({ customer }) => { - const [successState, setSuccessState] = React.useState(false) + const [successState, setSuccessState] = React.useState(false); // TODO: Add support for password updates const updatePassword = async () => { - toast.info("Password update is not implemented") - } + toast.info('Password update is not implemented'); + }; const clearState = () => { - setSuccessState(false) - } + setSuccessState(false); + }; return (
    = ({ customer }) => {
    - ) -} + ); +}; -export default ProfilePassword +export default ProfilePassword; diff --git a/packages/features/medusa-storefront/src/modules/account/components/profile-phone/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/profile-phone/index.tsx index d1a8b6b..f99cf62 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/profile-phone/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/profile-phone/index.tsx @@ -1,48 +1,48 @@ -"use client" +'use client'; -import React, { useEffect, useActionState } from "react"; +import React, { useActionState, useEffect } from 'react'; -import Input from "@modules/common/components/input" +import { updateCustomer } from '@lib/data/customer'; +import { HttpTypes } from '@medusajs/types'; +import Input from '@modules/common/components/input'; -import AccountInfo from "../account-info" -import { HttpTypes } from "@medusajs/types" -import { updateCustomer } from "@lib/data/customer" +import AccountInfo from '../account-info'; type MyInformationProps = { - customer: HttpTypes.StoreCustomer -} + customer: HttpTypes.StoreCustomer; +}; const ProfileEmail: React.FC = ({ customer }) => { - const [successState, setSuccessState] = React.useState(false) + const [successState, setSuccessState] = React.useState(false); const updateCustomerPhone = async ( _currentState: Record, - formData: FormData + formData: FormData, ) => { const customer = { - phone: formData.get("phone") as string, - } + phone: formData.get('phone') as string, + }; try { - await updateCustomer(customer) - return { success: true, error: null } + await updateCustomer(customer); + return { success: true, error: null }; } catch (error: any) { - return { success: false, error: error.toString() } + return { success: false, error: error.toString() }; } - } + }; const [state, formAction] = useActionState(updateCustomerPhone, { error: false, success: false, - }) + }); const clearState = () => { - setSuccessState(false) - } + setSuccessState(false); + }; useEffect(() => { - setSuccessState(state.success) - }, [state]) + setSuccessState(state.success); + }, [state]); return (
    @@ -62,13 +62,13 @@ const ProfileEmail: React.FC = ({ customer }) => { type="phone" autoComplete="phone" required - defaultValue={customer.phone ?? ""} + defaultValue={customer.phone ?? ''} data-testid="phone-input" />
    - ) -} + ); +}; -export default ProfileEmail +export default ProfileEmail; diff --git a/packages/features/medusa-storefront/src/modules/account/components/register/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/register/index.tsx index 197d7fc..584ee2c 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/register/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/register/index.tsx @@ -1,34 +1,35 @@ -"use client" +'use client'; -import { useActionState } from "react" -import Input from "@modules/common/components/input" -import { LOGIN_VIEW } from "@modules/account/templates/login-template" -import ErrorMessage from "@modules/checkout/components/error-message" -import { SubmitButton } from "@modules/checkout/components/submit-button" -import LocalizedClientLink from "@modules/common/components/localized-client-link" -import { signup } from "@lib/data/customer" +import { useActionState } from 'react'; + +import { signup } from '@lib/data/customer'; +import { LOGIN_VIEW } from '@modules/account/templates/login-template'; +import ErrorMessage from '@modules/checkout/components/error-message'; +import { SubmitButton } from '@modules/checkout/components/submit-button'; +import Input from '@modules/common/components/input'; +import LocalizedClientLink from '@modules/common/components/localized-client-link'; type Props = { - setCurrentView: (view: LOGIN_VIEW) => void -} + setCurrentView: (view: LOGIN_VIEW) => void; +}; const Register = ({ setCurrentView }: Props) => { - const [message, formAction] = useActionState(signup, null) + const [message, formAction] = useActionState(signup, null); return (
    -

    +

    Become a Medusa Store Member

    -

    +

    Create your Medusa Store Member profile, and get access to an enhanced shopping experience.

    -
    -
    + +
    { />
    - - By creating an account, you agree to Medusa Store's{" "} + + By creating an account, you agree to Medusa Store's{' '} Privacy Policy - {" "} - and{" "} + {' '} + and{' '} { . - + Join - - Already a member?{" "} + + Already a member?{' '}
    - ) -} + ); +}; -export default Register +export default Register; diff --git a/packages/features/medusa-storefront/src/modules/account/components/transfer-request-form/index.tsx b/packages/features/medusa-storefront/src/modules/account/components/transfer-request-form/index.tsx index c859f32..50fe520 100644 --- a/packages/features/medusa-storefront/src/modules/account/components/transfer-request-form/index.tsx +++ b/packages/features/medusa-storefront/src/modules/account/components/transfer-request-form/index.tsx @@ -1,30 +1,38 @@ -"use client" +'use client'; -import { useActionState } from "react" -import { createTransferRequest } from "@lib/data/orders" -import { Text, Heading, Input, Button, IconButton, Toaster } from "@medusajs/ui" -import { SubmitButton } from "@modules/checkout/components/submit-button" -import { CheckCircleMiniSolid, XCircleSolid } from "@medusajs/icons" -import { useEffect, useState } from "react" +import { useActionState } from 'react'; +import { useEffect, useState } from 'react'; + +import { createTransferRequest } from '@lib/data/orders'; +import { CheckCircleMiniSolid, XCircleSolid } from '@medusajs/icons'; +import { + Button, + Heading, + IconButton, + Input, + Text, + Toaster, +} from '@medusajs/ui'; +import { SubmitButton } from '@modules/checkout/components/submit-button'; export default function TransferRequestForm() { - const [showSuccess, setShowSuccess] = useState(false) + const [showSuccess, setShowSuccess] = useState(false); const [state, formAction] = useActionState(createTransferRequest, { success: false, error: null, order: null, - }) + }); useEffect(() => { if (state.success && state.order) { - setShowSuccess(true) + setShowSuccess(true); } - }, [state.success, state.order]) + }, [state.success, state.order]); return ( -
    -
    +
    +
    Order transfers @@ -38,11 +46,11 @@ export default function TransferRequestForm() { action={formAction} className="flex flex-col gap-y-1 sm:items-end" > -
    +
    Request transfer @@ -50,14 +58,14 @@ export default function TransferRequestForm() {
    {!state.success && state.error && ( - + {state.error} )} {showSuccess && ( -
    -
    - +
    +
    +
    Transfer for order {state.order?.id} requested @@ -72,10 +80,10 @@ export default function TransferRequestForm() { className="h-fit" onClick={() => setShowSuccess(false)} > - +
    )}
    - ) + ); } diff --git a/packages/features/medusa-storefront/src/modules/account/templates/account-layout.tsx b/packages/features/medusa-storefront/src/modules/account/templates/account-layout.tsx index 2d29490..799635b 100644 --- a/packages/features/medusa-storefront/src/modules/account/templates/account-layout.tsx +++ b/packages/features/medusa-storefront/src/modules/account/templates/account-layout.tsx @@ -1,13 +1,13 @@ -import React from "react" +import React from 'react'; -import UnderlineLink from "@modules/common/components/interactive-link" +import { HttpTypes } from '@medusajs/types'; +import UnderlineLink from '@modules/common/components/interactive-link'; -import AccountNav from "../components/account-nav" -import { HttpTypes } from "@medusajs/types" +import AccountNav from '../components/account-nav'; interface AccountLayoutProps { - customer: HttpTypes.StoreCustomer | null - children: React.ReactNode + customer: HttpTypes.StoreCustomer | null; + children: React.ReactNode; } const AccountLayout: React.FC = ({ @@ -15,13 +15,13 @@ const AccountLayout: React.FC = ({ children, }) => { return ( -
    -
    -
    +
    +
    +
    {customer && }
    {children}
    -
    +

    Got questions?

    @@ -37,7 +37,7 @@ const AccountLayout: React.FC = ({
    - ) -} + ); +}; -export default AccountLayout +export default AccountLayout; diff --git a/packages/features/medusa-storefront/src/modules/account/templates/index.ts b/packages/features/medusa-storefront/src/modules/account/templates/index.ts index 3507a36..8b34a7a 100644 --- a/packages/features/medusa-storefront/src/modules/account/templates/index.ts +++ b/packages/features/medusa-storefront/src/modules/account/templates/index.ts @@ -1,7 +1,7 @@ // account-info -export { default as AccountLayout } from "./account-layout"; -export * from "./account-layout"; +export { default as AccountLayout } from './account-layout'; +export * from './account-layout'; // account-nav -export { default as LoginTemplate } from "./login-template"; -export * from "./login-template"; +export { default as LoginTemplate } from './login-template'; +export * from './login-template'; diff --git a/packages/features/medusa-storefront/src/modules/account/templates/login-template.tsx b/packages/features/medusa-storefront/src/modules/account/templates/login-template.tsx index bbca313..afe8308 100644 --- a/packages/features/medusa-storefront/src/modules/account/templates/login-template.tsx +++ b/packages/features/medusa-storefront/src/modules/account/templates/login-template.tsx @@ -1,19 +1,20 @@ -"use client"; +'use client'; -import { useState } from "react"; -import { Login, Register } from "../components"; +import { useState } from 'react'; + +import { Login, Register } from '../components'; export enum LOGIN_VIEW { - SIGN_IN = "sign-in", - REGISTER = "register", + SIGN_IN = 'sign-in', + REGISTER = 'register', } const LoginTemplate = () => { - const [currentView, setCurrentView] = useState("sign-in"); + const [currentView, setCurrentView] = useState('sign-in'); return ( -
    - {currentView === "sign-in" ? ( +
    + {currentView === 'sign-in' ? ( ) : ( diff --git a/packages/features/medusa-storefront/src/modules/cart/components/cart-item-select/index.tsx b/packages/features/medusa-storefront/src/modules/cart/components/cart-item-select/index.tsx index 0073df0..a9733f8 100644 --- a/packages/features/medusa-storefront/src/modules/cart/components/cart-item-select/index.tsx +++ b/packages/features/medusa-storefront/src/modules/cart/components/cart-item-select/index.tsx @@ -1,6 +1,5 @@ -"use client" +'use client'; -import { IconBadge, clx } from "@medusajs/ui" import { SelectHTMLAttributes, forwardRef, @@ -8,33 +7,34 @@ import { useImperativeHandle, useRef, useState, -} from "react" +} from 'react'; -import ChevronDown from "@modules/common/icons/chevron-down" +import { IconBadge, clx } from '@medusajs/ui'; +import ChevronDown from '@modules/common/icons/chevron-down'; type NativeSelectProps = { - placeholder?: string - errors?: Record - touched?: Record -} & Omit, "size"> + placeholder?: string; + errors?: Record; + touched?: Record; +} & Omit, 'size'>; const CartItemSelect = forwardRef( - ({ placeholder = "Select...", className, children, ...props }, ref) => { - const innerRef = useRef(null) - const [isPlaceholder, setIsPlaceholder] = useState(false) + ({ placeholder = 'Select...', className, children, ...props }, ref) => { + const innerRef = useRef(null); + const [isPlaceholder, setIsPlaceholder] = useState(false); useImperativeHandle( ref, - () => innerRef.current - ) + () => innerRef.current, + ); useEffect(() => { - if (innerRef.current && innerRef.current.value === "") { - setIsPlaceholder(true) + if (innerRef.current && innerRef.current.value === '') { + setIsPlaceholder(true); } else { - setIsPlaceholder(false) + setIsPlaceholder(false); } - }, [innerRef.current?.value]) + }, [innerRef.current?.value]); return (
    @@ -42,32 +42,32 @@ const CartItemSelect = forwardRef( onFocus={() => innerRef.current?.focus()} onBlur={() => innerRef.current?.blur()} className={clx( - "relative flex items-center txt-compact-small border text-ui-fg-base group", + 'txt-compact-small text-ui-fg-base group relative flex items-center border', className, { - "text-ui-fg-subtle": isPlaceholder, - } + 'text-ui-fg-subtle': isPlaceholder, + }, )} > - +
    - ) - } -) + ); + }, +); -CartItemSelect.displayName = "CartItemSelect" +CartItemSelect.displayName = 'CartItemSelect'; -export default CartItemSelect +export default CartItemSelect; diff --git a/packages/features/medusa-storefront/src/modules/cart/components/empty-cart-message/index.tsx b/packages/features/medusa-storefront/src/modules/cart/components/empty-cart-message/index.tsx index e04a1f8..5bee4bd 100644 --- a/packages/features/medusa-storefront/src/modules/cart/components/empty-cart-message/index.tsx +++ b/packages/features/medusa-storefront/src/modules/cart/components/empty-cart-message/index.tsx @@ -1,13 +1,15 @@ -import { Heading, Text } from "@medusajs/ui" - -import InteractiveLink from "@modules/common/components/interactive-link" +import { Heading, Text } from '@medusajs/ui'; +import InteractiveLink from '@modules/common/components/interactive-link'; const EmptyCartMessage = () => { return ( -
    +
    Cart @@ -19,7 +21,7 @@ const EmptyCartMessage = () => { Explore products
    - ) -} + ); +}; -export default EmptyCartMessage +export default EmptyCartMessage; diff --git a/packages/features/medusa-storefront/src/modules/cart/components/item/index.tsx b/packages/features/medusa-storefront/src/modules/cart/components/item/index.tsx index b35f1c4..df8abd3 100644 --- a/packages/features/medusa-storefront/src/modules/cart/components/item/index.tsx +++ b/packages/features/medusa-storefront/src/modules/cart/components/item/index.tsx @@ -1,57 +1,58 @@ -"use client" +'use client'; -import { Table, Text, clx } from "@medusajs/ui" -import { updateLineItem } from "@lib/data/cart" -import { HttpTypes } from "@medusajs/types" -import CartItemSelect from "@modules/cart/components/cart-item-select" -import ErrorMessage from "@modules/checkout/components/error-message" -import DeleteButton from "@modules/common/components/delete-button" -import LineItemOptions from "@modules/common/components/line-item-options" -import LineItemPrice from "@modules/common/components/line-item-price" -import LineItemUnitPrice from "@modules/common/components/line-item-unit-price" -import LocalizedClientLink from "@modules/common/components/localized-client-link" -import Spinner from "@modules/common/icons/spinner" -import Thumbnail from "@modules/products/components/thumbnail" -import { useState } from "react" +import { useState } from 'react'; + +import { updateLineItem } from '@lib/data/cart'; +import { HttpTypes } from '@medusajs/types'; +import { Table, Text, clx } from '@medusajs/ui'; +import CartItemSelect from '@modules/cart/components/cart-item-select'; +import ErrorMessage from '@modules/checkout/components/error-message'; +import DeleteButton from '@modules/common/components/delete-button'; +import LineItemOptions from '@modules/common/components/line-item-options'; +import LineItemPrice from '@modules/common/components/line-item-price'; +import LineItemUnitPrice from '@modules/common/components/line-item-unit-price'; +import LocalizedClientLink from '@modules/common/components/localized-client-link'; +import Spinner from '@modules/common/icons/spinner'; +import Thumbnail from '@modules/products/components/thumbnail'; type ItemProps = { - item: HttpTypes.StoreCartLineItem - type?: "full" | "preview" - currencyCode: string -} + item: HttpTypes.StoreCartLineItem; + type?: 'full' | 'preview'; + currencyCode: string; +}; -const Item = ({ item, type = "full", currencyCode }: ItemProps) => { - const [updating, setUpdating] = useState(false) - const [error, setError] = useState(null) +const Item = ({ item, type = 'full', currencyCode }: ItemProps) => { + const [updating, setUpdating] = useState(false); + const [error, setError] = useState(null); const changeQuantity = async (quantity: number) => { - setError(null) - setUpdating(true) + setError(null); + setUpdating(true); await updateLineItem({ lineId: item.id, quantity, }) .catch((err) => { - setError(err.message) + setError(err.message); }) .finally(() => { - setUpdating(false) - }) - } + setUpdating(false); + }); + }; // TODO: Update this to grab the actual max inventory - const maxQtyFromInventory = 10 - const maxQuantity = item.variant?.manage_inventory ? 10 : maxQtyFromInventory + const maxQtyFromInventory = 10; + const maxQuantity = item.variant?.manage_inventory ? 10 : maxQtyFromInventory; return ( - + { - {type === "full" && ( + {type === 'full' && ( -
    +
    changeQuantity(parseInt(value.target.value))} - className="w-14 h-10 p-4" + className="h-10 w-14 p-4" data-testid="product-select-button" > {/* TODO: Update this with the v2 way of managing inventory */} @@ -91,7 +92,7 @@ const Item = ({ item, type = "full", currencyCode }: ItemProps) => { - ) + ), )}