feat: redesign secure access flows
This commit is contained in:
@@ -14,6 +14,8 @@
|
||||
"api:generate": "node scripts/generate-api.mjs"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/funnel-sans": "^5.3.0",
|
||||
"@fontsource/geist-mono": "^5.3.0",
|
||||
"@hookform/resolvers": "^5.1.0",
|
||||
"@tanstack/react-query": "^5.80.0",
|
||||
"i18next": "^25.2.0",
|
||||
|
||||
Generated
+85
-69
@@ -8,6 +8,12 @@ importers:
|
||||
|
||||
.:
|
||||
dependencies:
|
||||
'@fontsource/funnel-sans':
|
||||
specifier: ^5.3.0
|
||||
version: 5.3.0
|
||||
'@fontsource/geist-mono':
|
||||
specifier: ^5.3.0
|
||||
version: 5.3.0
|
||||
'@hookform/resolvers':
|
||||
specifier: ^5.1.0
|
||||
version: 5.9.1(react-hook-form@7.87.0(react@19.3.0))(zod@3.25.76)
|
||||
@@ -59,22 +65,22 @@ importers:
|
||||
version: 19.3.0(@types/react@19.3.0)
|
||||
'@vitejs/plugin-react':
|
||||
specifier: ^4.5.0
|
||||
version: 4.7.0(vite@6.4.3)
|
||||
version: 4.7.0(supports-color@10.2.2)(vite@6.4.3)
|
||||
eslint:
|
||||
specifier: ^9.28.0
|
||||
version: 9.39.5
|
||||
version: 9.39.5(supports-color@10.2.2)
|
||||
eslint-plugin-jsx-a11y:
|
||||
specifier: ^6.10.2
|
||||
version: 6.10.2(eslint@9.39.5)
|
||||
version: 6.10.2(eslint@9.39.5(supports-color@10.2.2))
|
||||
eslint-plugin-react-hooks:
|
||||
specifier: ^5.2.0
|
||||
version: 5.2.0(eslint@9.39.5)
|
||||
version: 5.2.0(eslint@9.39.5(supports-color@10.2.2))
|
||||
globals:
|
||||
specifier: ^16.2.0
|
||||
version: 16.5.0
|
||||
jsdom:
|
||||
specifier: ^26.1.0
|
||||
version: 26.1.0
|
||||
version: 26.1.0(supports-color@10.2.2)
|
||||
openapi-typescript:
|
||||
specifier: ^7.8.0
|
||||
version: 7.13.0(typescript@5.8.3)
|
||||
@@ -83,13 +89,13 @@ importers:
|
||||
version: 5.8.3
|
||||
typescript-eslint:
|
||||
specifier: ^8.33.0
|
||||
version: 8.70.0(eslint@9.39.5)(typescript@5.8.3)
|
||||
version: 8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3)
|
||||
vite:
|
||||
specifier: ^6.3.5
|
||||
version: 6.4.3
|
||||
vitest:
|
||||
specifier: ^3.2.0
|
||||
version: 3.2.7(jsdom@26.1.0)
|
||||
version: 3.2.7(jsdom@26.1.0(supports-color@10.2.2))(supports-color@10.2.2)
|
||||
|
||||
packages:
|
||||
|
||||
@@ -408,6 +414,12 @@ packages:
|
||||
resolution: {integrity: sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==}
|
||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||
|
||||
'@fontsource/funnel-sans@5.3.0':
|
||||
resolution: {integrity: sha512-LmINq/6qfoYW1LOkOwaiZw7YVEpi3QACa36V7jxgBlO8MPGPbeSxFrPjk4lF6uP1ZbCp2VsBWmneo+1b59GbbA==}
|
||||
|
||||
'@fontsource/geist-mono@5.3.0':
|
||||
resolution: {integrity: sha512-UtJ1BBBCVpMYdIcW7nEB45UAoAw5M53ZXs2t0ciPW+IokuAAIc56M8+kW5tXbRJCTpDw4XTtU7proT6NdQAHTg==}
|
||||
|
||||
'@hookform/resolvers@5.9.1':
|
||||
resolution: {integrity: sha512-7b7vsbraJxKgjVSA1Nur9tLwj539WGJUBLA7QNvXnFoT2pM5Z7G+6rlukk4B2/QrTZy6huRtH6wKeESPKuIr6w==}
|
||||
peerDependencies:
|
||||
@@ -2195,16 +2207,16 @@ snapshots:
|
||||
|
||||
'@babel/compat-data@7.29.7': {}
|
||||
|
||||
'@babel/core@7.29.7':
|
||||
'@babel/core@7.29.7(supports-color@10.2.2)':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.29.7
|
||||
'@babel/generator': 7.29.8
|
||||
'@babel/helper-compilation-targets': 7.29.7
|
||||
'@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
|
||||
'@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
|
||||
'@babel/helpers': 7.29.7
|
||||
'@babel/parser': 7.29.8
|
||||
'@babel/template': 7.29.7
|
||||
'@babel/traverse': 7.29.8
|
||||
'@babel/traverse': 7.29.8(supports-color@10.2.2)
|
||||
'@babel/types': 7.29.8
|
||||
'@jridgewell/remapping': 2.3.5
|
||||
convert-source-map: 2.0.0
|
||||
@@ -2233,19 +2245,19 @@ snapshots:
|
||||
|
||||
'@babel/helper-globals@7.29.7': {}
|
||||
|
||||
'@babel/helper-module-imports@7.29.7':
|
||||
'@babel/helper-module-imports@7.29.7(supports-color@10.2.2)':
|
||||
dependencies:
|
||||
'@babel/traverse': 7.29.8
|
||||
'@babel/traverse': 7.29.8(supports-color@10.2.2)
|
||||
'@babel/types': 7.29.8
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)':
|
||||
'@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.7
|
||||
'@babel/helper-module-imports': 7.29.7
|
||||
'@babel/core': 7.29.7(supports-color@10.2.2)
|
||||
'@babel/helper-module-imports': 7.29.7(supports-color@10.2.2)
|
||||
'@babel/helper-validator-identifier': 7.29.7
|
||||
'@babel/traverse': 7.29.8
|
||||
'@babel/traverse': 7.29.8(supports-color@10.2.2)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@@ -2266,14 +2278,14 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/types': 7.29.8
|
||||
|
||||
'@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7)':
|
||||
'@babel/plugin-transform-react-jsx-self@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.7
|
||||
'@babel/core': 7.29.7(supports-color@10.2.2)
|
||||
'@babel/helper-plugin-utils': 7.29.7
|
||||
|
||||
'@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7)':
|
||||
'@babel/plugin-transform-react-jsx-source@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.7
|
||||
'@babel/core': 7.29.7(supports-color@10.2.2)
|
||||
'@babel/helper-plugin-utils': 7.29.7
|
||||
|
||||
'@babel/runtime@7.29.7': {}
|
||||
@@ -2284,7 +2296,7 @@ snapshots:
|
||||
'@babel/parser': 7.29.8
|
||||
'@babel/types': 7.29.8
|
||||
|
||||
'@babel/traverse@7.29.8':
|
||||
'@babel/traverse@7.29.8(supports-color@10.2.2)':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.29.7
|
||||
'@babel/generator': 7.29.8
|
||||
@@ -2399,14 +2411,14 @@ snapshots:
|
||||
'@esbuild/win32-x64@0.25.12':
|
||||
optional: true
|
||||
|
||||
'@eslint-community/eslint-utils@4.10.1(eslint@9.39.5)':
|
||||
'@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(supports-color@10.2.2))':
|
||||
dependencies:
|
||||
eslint: 9.39.5
|
||||
eslint: 9.39.5(supports-color@10.2.2)
|
||||
eslint-visitor-keys: 3.4.3
|
||||
|
||||
'@eslint-community/regexpp@4.12.2': {}
|
||||
|
||||
'@eslint/config-array@0.21.2':
|
||||
'@eslint/config-array@0.21.2(supports-color@10.2.2)':
|
||||
dependencies:
|
||||
'@eslint/object-schema': 2.1.7
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
@@ -2422,7 +2434,7 @@ snapshots:
|
||||
dependencies:
|
||||
'@types/json-schema': 7.0.15
|
||||
|
||||
'@eslint/eslintrc@3.3.7':
|
||||
'@eslint/eslintrc@3.3.7(supports-color@10.2.2)':
|
||||
dependencies:
|
||||
ajv: 6.15.0
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
@@ -2445,6 +2457,10 @@ snapshots:
|
||||
'@eslint/core': 0.17.0
|
||||
levn: 0.4.1
|
||||
|
||||
'@fontsource/funnel-sans@5.3.0': {}
|
||||
|
||||
'@fontsource/geist-mono@5.3.0': {}
|
||||
|
||||
'@hookform/resolvers@5.9.1(react-hook-form@7.87.0(react@19.3.0))(zod@3.25.76)':
|
||||
dependencies:
|
||||
'@standard-schema/utils': 0.3.0
|
||||
@@ -2676,15 +2692,15 @@ snapshots:
|
||||
dependencies:
|
||||
csstype: 3.2.3
|
||||
|
||||
'@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5)(typescript@5.8.3))(eslint@9.39.5)(typescript@5.8.3)':
|
||||
'@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3))(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
'@typescript-eslint/parser': 8.70.0(eslint@9.39.5)(typescript@5.8.3)
|
||||
'@typescript-eslint/parser': 8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3)
|
||||
'@typescript-eslint/scope-manager': 8.70.0
|
||||
'@typescript-eslint/type-utils': 8.70.0(eslint@9.39.5)(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.70.0(eslint@9.39.5)(typescript@5.8.3)
|
||||
'@typescript-eslint/type-utils': 8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3)
|
||||
'@typescript-eslint/visitor-keys': 8.70.0
|
||||
eslint: 9.39.5
|
||||
eslint: 9.39.5(supports-color@10.2.2)
|
||||
ignore: 7.0.9
|
||||
natural-compare: 1.4.0
|
||||
ts-api-utils: 2.5.0(typescript@5.8.3)
|
||||
@@ -2692,19 +2708,19 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/parser@8.70.0(eslint@9.39.5)(typescript@5.8.3)':
|
||||
'@typescript-eslint/parser@8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/scope-manager': 8.70.0
|
||||
'@typescript-eslint/types': 8.70.0
|
||||
'@typescript-eslint/typescript-estree': 8.70.0(typescript@5.8.3)
|
||||
'@typescript-eslint/typescript-estree': 8.70.0(supports-color@10.2.2)(typescript@5.8.3)
|
||||
'@typescript-eslint/visitor-keys': 8.70.0
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
eslint: 9.39.5
|
||||
eslint: 9.39.5(supports-color@10.2.2)
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/project-service@8.70.0(typescript@5.8.3)':
|
||||
'@typescript-eslint/project-service@8.70.0(supports-color@10.2.2)(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/tsconfig-utils': 8.70.0(typescript@5.8.3)
|
||||
'@typescript-eslint/types': 8.70.0
|
||||
@@ -2722,13 +2738,13 @@ snapshots:
|
||||
dependencies:
|
||||
typescript: 5.8.3
|
||||
|
||||
'@typescript-eslint/type-utils@8.70.0(eslint@9.39.5)(typescript@5.8.3)':
|
||||
'@typescript-eslint/type-utils@8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/types': 8.70.0
|
||||
'@typescript-eslint/typescript-estree': 8.70.0(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.70.0(eslint@9.39.5)(typescript@5.8.3)
|
||||
'@typescript-eslint/typescript-estree': 8.70.0(supports-color@10.2.2)(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3)
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
eslint: 9.39.5
|
||||
eslint: 9.39.5(supports-color@10.2.2)
|
||||
ts-api-utils: 2.5.0(typescript@5.8.3)
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
@@ -2736,9 +2752,9 @@ snapshots:
|
||||
|
||||
'@typescript-eslint/types@8.70.0': {}
|
||||
|
||||
'@typescript-eslint/typescript-estree@8.70.0(typescript@5.8.3)':
|
||||
'@typescript-eslint/typescript-estree@8.70.0(supports-color@10.2.2)(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@typescript-eslint/project-service': 8.70.0(typescript@5.8.3)
|
||||
'@typescript-eslint/project-service': 8.70.0(supports-color@10.2.2)(typescript@5.8.3)
|
||||
'@typescript-eslint/tsconfig-utils': 8.70.0(typescript@5.8.3)
|
||||
'@typescript-eslint/types': 8.70.0
|
||||
'@typescript-eslint/visitor-keys': 8.70.0
|
||||
@@ -2751,13 +2767,13 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@typescript-eslint/utils@8.70.0(eslint@9.39.5)(typescript@5.8.3)':
|
||||
'@typescript-eslint/utils@8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3)':
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5)
|
||||
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@10.2.2))
|
||||
'@typescript-eslint/scope-manager': 8.70.0
|
||||
'@typescript-eslint/types': 8.70.0
|
||||
'@typescript-eslint/typescript-estree': 8.70.0(typescript@5.8.3)
|
||||
eslint: 9.39.5
|
||||
'@typescript-eslint/typescript-estree': 8.70.0(supports-color@10.2.2)(typescript@5.8.3)
|
||||
eslint: 9.39.5(supports-color@10.2.2)
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -2767,11 +2783,11 @@ snapshots:
|
||||
'@typescript-eslint/types': 8.70.0
|
||||
eslint-visitor-keys: 5.0.1
|
||||
|
||||
'@vitejs/plugin-react@4.7.0(vite@6.4.3)':
|
||||
'@vitejs/plugin-react@4.7.0(supports-color@10.2.2)(vite@6.4.3)':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.7
|
||||
'@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7)
|
||||
'@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7)
|
||||
'@babel/core': 7.29.7(supports-color@10.2.2)
|
||||
'@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))
|
||||
'@babel/plugin-transform-react-jsx-source': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))
|
||||
'@rolldown/pluginutils': 1.0.0-beta.27
|
||||
'@types/babel__core': 7.20.5
|
||||
react-refresh: 0.17.0
|
||||
@@ -3198,7 +3214,7 @@ snapshots:
|
||||
|
||||
escape-string-regexp@4.0.0: {}
|
||||
|
||||
eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5):
|
||||
eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5(supports-color@10.2.2)):
|
||||
dependencies:
|
||||
aria-query: 5.3.2
|
||||
array-includes: 3.2.0
|
||||
@@ -3208,7 +3224,7 @@ snapshots:
|
||||
axobject-query: 4.1.0
|
||||
damerau-levenshtein: 1.0.8
|
||||
emoji-regex: 9.2.2
|
||||
eslint: 9.39.5
|
||||
eslint: 9.39.5(supports-color@10.2.2)
|
||||
hasown: 2.0.4
|
||||
jsx-ast-utils: 3.3.5
|
||||
language-tags: 1.0.9
|
||||
@@ -3217,9 +3233,9 @@ snapshots:
|
||||
safe-regex-test: 1.1.0
|
||||
string.prototype.includes: 2.0.1
|
||||
|
||||
eslint-plugin-react-hooks@5.2.0(eslint@9.39.5):
|
||||
eslint-plugin-react-hooks@5.2.0(eslint@9.39.5(supports-color@10.2.2)):
|
||||
dependencies:
|
||||
eslint: 9.39.5
|
||||
eslint: 9.39.5(supports-color@10.2.2)
|
||||
|
||||
eslint-scope@8.4.0:
|
||||
dependencies:
|
||||
@@ -3232,14 +3248,14 @@ snapshots:
|
||||
|
||||
eslint-visitor-keys@5.0.1: {}
|
||||
|
||||
eslint@9.39.5:
|
||||
eslint@9.39.5(supports-color@10.2.2):
|
||||
dependencies:
|
||||
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5)
|
||||
'@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(supports-color@10.2.2))
|
||||
'@eslint-community/regexpp': 4.12.2
|
||||
'@eslint/config-array': 0.21.2
|
||||
'@eslint/config-array': 0.21.2(supports-color@10.2.2)
|
||||
'@eslint/config-helpers': 0.4.2
|
||||
'@eslint/core': 0.17.0
|
||||
'@eslint/eslintrc': 3.3.7
|
||||
'@eslint/eslintrc': 3.3.7(supports-color@10.2.2)
|
||||
'@eslint/js': 9.39.5
|
||||
'@eslint/plugin-kit': 0.4.1
|
||||
'@humanfs/node': 0.16.8
|
||||
@@ -3417,7 +3433,7 @@ snapshots:
|
||||
dependencies:
|
||||
void-elements: 3.1.0
|
||||
|
||||
http-proxy-agent@7.0.2:
|
||||
http-proxy-agent@7.0.2(supports-color@10.2.2):
|
||||
dependencies:
|
||||
agent-base: 7.1.4
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
@@ -3584,13 +3600,13 @@ snapshots:
|
||||
dependencies:
|
||||
argparse: 2.0.1
|
||||
|
||||
jsdom@26.1.0:
|
||||
jsdom@26.1.0(supports-color@10.2.2):
|
||||
dependencies:
|
||||
cssstyle: 4.6.0
|
||||
data-urls: 5.0.0
|
||||
decimal.js: 10.6.0
|
||||
html-encoding-sniffer: 4.0.0
|
||||
http-proxy-agent: 7.0.2
|
||||
http-proxy-agent: 7.0.2(supports-color@10.2.2)
|
||||
https-proxy-agent: 7.0.6(supports-color@10.2.2)
|
||||
is-potential-custom-element-name: 1.0.1
|
||||
nwsapi: 2.2.27
|
||||
@@ -4122,13 +4138,13 @@ snapshots:
|
||||
possible-typed-array-names: 1.1.0
|
||||
reflect.getprototypeof: 1.0.10
|
||||
|
||||
typescript-eslint@8.70.0(eslint@9.39.5)(typescript@5.8.3):
|
||||
typescript-eslint@8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3):
|
||||
dependencies:
|
||||
'@typescript-eslint/eslint-plugin': 8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5)(typescript@5.8.3))(eslint@9.39.5)(typescript@5.8.3)
|
||||
'@typescript-eslint/parser': 8.70.0(eslint@9.39.5)(typescript@5.8.3)
|
||||
'@typescript-eslint/typescript-estree': 8.70.0(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.70.0(eslint@9.39.5)(typescript@5.8.3)
|
||||
eslint: 9.39.5
|
||||
'@typescript-eslint/eslint-plugin': 8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3))(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3)
|
||||
'@typescript-eslint/parser': 8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3)
|
||||
'@typescript-eslint/typescript-estree': 8.70.0(supports-color@10.2.2)(typescript@5.8.3)
|
||||
'@typescript-eslint/utils': 8.70.0(eslint@9.39.5(supports-color@10.2.2))(supports-color@10.2.2)(typescript@5.8.3)
|
||||
eslint: 9.39.5(supports-color@10.2.2)
|
||||
typescript: 5.8.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@@ -4154,7 +4170,7 @@ snapshots:
|
||||
dependencies:
|
||||
punycode: 2.3.1
|
||||
|
||||
vite-node@3.2.4:
|
||||
vite-node@3.2.4(supports-color@10.2.2):
|
||||
dependencies:
|
||||
cac: 6.7.14
|
||||
debug: 4.4.3(supports-color@10.2.2)
|
||||
@@ -4186,7 +4202,7 @@ snapshots:
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
vitest@3.2.7(jsdom@26.1.0):
|
||||
vitest@3.2.7(jsdom@26.1.0(supports-color@10.2.2))(supports-color@10.2.2):
|
||||
dependencies:
|
||||
'@types/chai': 5.2.3
|
||||
'@vitest/expect': 3.2.7
|
||||
@@ -4209,10 +4225,10 @@ snapshots:
|
||||
tinypool: 1.1.1
|
||||
tinyrainbow: 2.0.0
|
||||
vite: 6.4.3
|
||||
vite-node: 3.2.4
|
||||
vite-node: 3.2.4(supports-color@10.2.2)
|
||||
why-is-node-running: 2.3.0
|
||||
optionalDependencies:
|
||||
jsdom: 26.1.0
|
||||
jsdom: 26.1.0(supports-color@10.2.2)
|
||||
transitivePeerDependencies:
|
||||
- jiti
|
||||
- less
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import type { ReactNode } from 'react'
|
||||
import { Link } from 'react-router-dom'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { LangSwitcher } from '@/components/layout/LangSwitcher'
|
||||
|
||||
interface AuthLayoutProps {
|
||||
title: string
|
||||
subtitle: string
|
||||
context: string
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export function AuthLayout({ title, subtitle, context, children }: AuthLayoutProps) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className="auth-page">
|
||||
<aside className="auth-identity">
|
||||
<Link to="/login" className="brand">
|
||||
<span className="brand-mark" aria-hidden="true">FS</span>
|
||||
<span>FINSPACE</span>
|
||||
</Link>
|
||||
<div className="auth-manifest">
|
||||
<h2>{t('authShell.statement')}</h2>
|
||||
<p>{t('authShell.explanation')}</p>
|
||||
</div>
|
||||
<ol className="security-facts">
|
||||
<li>{t('authShell.session')}</li>
|
||||
<li>{t('authShell.encryption')}</li>
|
||||
<li>{t('authShell.isolation')}</li>
|
||||
</ol>
|
||||
</aside>
|
||||
<main className="auth-workspace">
|
||||
<header className="auth-top">
|
||||
<span>{context}</span>
|
||||
<LangSwitcher />
|
||||
</header>
|
||||
<section className="auth-card">
|
||||
<h1 className="page-title">{title}</h1>
|
||||
<p className="page-subtitle">{subtitle}</p>
|
||||
{children}
|
||||
</section>
|
||||
<footer className="auth-contract">
|
||||
<span>{t('authShell.private')}</span>
|
||||
<span>{t('authShell.singleUse')}</span>
|
||||
<span>{t('authShell.rub')}</span>
|
||||
</footer>
|
||||
</main>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -42,7 +42,7 @@ export function Modal({ open, onClose, title, children }: ModalProps) {
|
||||
onClick={onClose}
|
||||
aria-label={t('common.close')}
|
||||
>
|
||||
✕
|
||||
<span className="close-glyph" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="modal-body">{children}</div>
|
||||
|
||||
@@ -39,6 +39,19 @@
|
||||
"reviewBlockers": "Review blockers",
|
||||
"categoryPulse": "Category pulse"
|
||||
},
|
||||
"authShell": {
|
||||
"statement": "Your household ledger, sealed by design.",
|
||||
"explanation": "Invite-only access. Every account, operation and statement stays inside one encrypted financial space.",
|
||||
"session": "14-day secure session",
|
||||
"encryption": "AES-GCM statement encryption",
|
||||
"isolation": "Space-isolated financial data",
|
||||
"private": "Private workspace",
|
||||
"singleUse": "Single-use invitations",
|
||||
"rub": "RUB accounting",
|
||||
"signIn": "Access / sign in",
|
||||
"invitation": "Access / invitation",
|
||||
"reset": "Access / reset password"
|
||||
},
|
||||
"lang": {
|
||||
"label": "Language"
|
||||
},
|
||||
|
||||
@@ -39,6 +39,19 @@
|
||||
"reviewBlockers": "Разобрать блокировки",
|
||||
"categoryPulse": "Состояние категорий"
|
||||
},
|
||||
"authShell": {
|
||||
"statement": "Семейный гроссбух, закрытый по замыслу.",
|
||||
"explanation": "Доступ только по приглашению. Счета, операции и выписки остаются внутри одного зашифрованного пространства.",
|
||||
"session": "Защищённая сессия на 14 дней",
|
||||
"encryption": "Шифрование выписок AES-GCM",
|
||||
"isolation": "Изоляция данных пространства",
|
||||
"private": "Приватное пространство",
|
||||
"singleUse": "Одноразовые приглашения",
|
||||
"rub": "Учёт в рублях",
|
||||
"signIn": "Доступ / вход",
|
||||
"invitation": "Доступ / приглашение",
|
||||
"reset": "Доступ / сброс пароля"
|
||||
},
|
||||
"lang": {
|
||||
"label": "Язык"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import '@fontsource/funnel-sans/400.css'
|
||||
import '@fontsource/funnel-sans/500.css'
|
||||
import '@fontsource/funnel-sans/600.css'
|
||||
import '@fontsource/funnel-sans/700.css'
|
||||
import '@fontsource/geist-mono/400.css'
|
||||
import '@fontsource/geist-mono/500.css'
|
||||
import '@fontsource/geist-mono/600.css'
|
||||
import '@fontsource/geist-mono/700.css'
|
||||
import App from './App'
|
||||
import './i18n'
|
||||
import './styles/global.css'
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Link, Navigate, useNavigate, useSearchParams } from 'react-router-dom'
|
||||
import { z } from 'zod'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { TextField } from '@/components/ui/fields'
|
||||
import { LangSwitcher } from '@/components/layout/LangSwitcher'
|
||||
import { AuthLayout } from '@/components/layout/AuthLayout'
|
||||
import { useAcceptInvite, useMe } from '@/hooks/useAuth'
|
||||
import { describeApiError } from '@/lib/apiErrors'
|
||||
|
||||
@@ -63,17 +63,11 @@ export function AcceptInvitePage() {
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="auth-page">
|
||||
<div className="auth-card card">
|
||||
<div className="auth-top">
|
||||
<span className="brand">
|
||||
<span className="brand-mark" aria-hidden="true" />
|
||||
{t('app.brand')}
|
||||
</span>
|
||||
<LangSwitcher />
|
||||
</div>
|
||||
<h1 className="page-title">{t('auth.inviteTitle')}</h1>
|
||||
<p className="page-subtitle">{t('auth.inviteSubtitle')}</p>
|
||||
<AuthLayout
|
||||
title={t('auth.inviteTitle')}
|
||||
subtitle={t('auth.inviteSubtitle')}
|
||||
context={t('authShell.invitation')}
|
||||
>
|
||||
{apiError ? (
|
||||
<div className="banner banner-danger" role="alert">
|
||||
{apiError}
|
||||
@@ -114,7 +108,6 @@ export function AcceptInvitePage() {
|
||||
<p className="auth-alt">
|
||||
<Link to="/login">{t('auth.backToLogin')}</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</AuthLayout>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Link, Navigate, useLocation, useNavigate } from 'react-router-dom'
|
||||
import { z } from 'zod'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { TextField } from '@/components/ui/fields'
|
||||
import { LangSwitcher } from '@/components/layout/LangSwitcher'
|
||||
import { AuthLayout } from '@/components/layout/AuthLayout'
|
||||
import { useLogin, useMe } from '@/hooks/useAuth'
|
||||
import { describeApiError } from '@/lib/apiErrors'
|
||||
|
||||
@@ -54,17 +54,11 @@ export function LoginPage() {
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="auth-page">
|
||||
<div className="auth-card card">
|
||||
<div className="auth-top">
|
||||
<span className="brand">
|
||||
<span className="brand-mark" aria-hidden="true" />
|
||||
{t('app.brand')}
|
||||
</span>
|
||||
<LangSwitcher />
|
||||
</div>
|
||||
<h1 className="page-title">{t('auth.loginTitle')}</h1>
|
||||
<p className="page-subtitle">{t('auth.loginSubtitle')}</p>
|
||||
<AuthLayout
|
||||
title={t('auth.loginTitle')}
|
||||
subtitle={t('auth.loginSubtitle')}
|
||||
context={t('authShell.signIn')}
|
||||
>
|
||||
{apiError ? (
|
||||
<div className="banner banner-danger" role="alert">
|
||||
{apiError}
|
||||
@@ -95,7 +89,6 @@ export function LoginPage() {
|
||||
<p className="auth-alt">
|
||||
<Link to="/invite/accept">{t('auth.haveInvite')}</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</AuthLayout>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useForm } from 'react-hook-form'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Link, useNavigate, useSearchParams } from 'react-router-dom'
|
||||
import { z } from 'zod'
|
||||
import { LangSwitcher } from '@/components/layout/LangSwitcher'
|
||||
import { AuthLayout } from '@/components/layout/AuthLayout'
|
||||
import { Button } from '@/components/ui/Button'
|
||||
import { TextField } from '@/components/ui/fields'
|
||||
import { useConfirmPasswordReset, useRequestPasswordReset } from '@/hooks/useAuth'
|
||||
@@ -73,17 +73,11 @@ export function ResetPasswordPage() {
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="auth-page">
|
||||
<div className="auth-card card">
|
||||
<div className="auth-top">
|
||||
<span className="brand">
|
||||
<span className="brand-mark" aria-hidden="true" />
|
||||
{t('app.brand')}
|
||||
</span>
|
||||
<LangSwitcher />
|
||||
</div>
|
||||
<h1 className="page-title">{t('auth.resetTitle')}</h1>
|
||||
<p className="page-subtitle">{t('auth.resetSubtitle')}</p>
|
||||
<AuthLayout
|
||||
title={t('auth.resetTitle')}
|
||||
subtitle={t('auth.resetSubtitle')}
|
||||
context={t('authShell.reset')}
|
||||
>
|
||||
{apiError ? (
|
||||
<div className="banner banner-danger" role="alert">
|
||||
{apiError}
|
||||
@@ -130,7 +124,6 @@ export function ResetPasswordPage() {
|
||||
<p className="auth-alt">
|
||||
<Link to="/login">{t('auth.backToLogin')}</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</AuthLayout>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
@import url('https://fonts.googleapis.com/css2?family=Funnel+Sans:wght@400;500;600;700&family=Geist+Mono:wght@400;500;600;700&display=swap');
|
||||
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--paper: #f7f5ef;
|
||||
@@ -384,6 +382,11 @@ a {
|
||||
.btn-danger:hover:not(:disabled) { background: #8e241d; }
|
||||
.btn-small { min-height: 28px; padding: 5px 8px; font-family: var(--font-data); font-size: 9px; }
|
||||
.btn-icon { width: 36px; min-height: 36px; padding: 0; }
|
||||
.close-glyph { position: relative; width: 14px; height: 14px; display: block; }
|
||||
.close-glyph::before,
|
||||
.close-glyph::after { content: ''; position: absolute; left: 6px; top: 0; width: 1px; height: 14px; background: currentColor; }
|
||||
.close-glyph::before { transform: rotate(45deg); }
|
||||
.close-glyph::after { transform: rotate(-45deg); }
|
||||
|
||||
.lang-switch { display: inline-flex; }
|
||||
.lang-switch .btn { color: #81817d; }
|
||||
@@ -672,55 +675,26 @@ input[type='file']::file-selector-button { min-height: 30px; margin-right: 10px;
|
||||
.pulse-track span { display: block; height: 100%; background: var(--blue); }
|
||||
.mobile-primary-action { display: none; }
|
||||
|
||||
.auth-page {
|
||||
min-height: 100vh;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 34px;
|
||||
background: linear-gradient(90deg, var(--ink) 0 39%, var(--paper) 39% 100%);
|
||||
}
|
||||
|
||||
.auth-card {
|
||||
width: min(560px, calc(61vw - 96px));
|
||||
margin-left: 39vw;
|
||||
padding: 34px 0;
|
||||
}
|
||||
|
||||
.auth-card::before {
|
||||
content: 'FS';
|
||||
position: fixed;
|
||||
left: 56px;
|
||||
top: 54px;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
color: var(--white);
|
||||
background: var(--blue);
|
||||
font: 700 11px var(--font-data);
|
||||
}
|
||||
|
||||
.auth-card::after {
|
||||
content: 'Your household ledger, sealed by design.';
|
||||
position: fixed;
|
||||
left: 56px;
|
||||
top: 150px;
|
||||
width: min(31vw, 410px);
|
||||
color: var(--white);
|
||||
font-size: clamp(34px, 4vw, 52px);
|
||||
font-weight: 600;
|
||||
line-height: 0.98;
|
||||
letter-spacing: -0.035em;
|
||||
}
|
||||
|
||||
.auth-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 44px; }
|
||||
.auth-top .brand { color: var(--blue); }
|
||||
.auth-top .brand-mark { display: none; }
|
||||
.auth-page { min-height: 100vh; display: grid; grid-template-columns: minmax(360px, 39%) minmax(0, 1fr); background: var(--paper); }
|
||||
.auth-identity { min-height: 100vh; display: grid; grid-template-rows: auto 1fr auto; gap: 64px; padding: 54px 56px; color: var(--white); background: var(--ink); }
|
||||
.auth-manifest { align-self: start; max-width: 460px; padding-top: 56px; }
|
||||
.auth-manifest h2 { max-width: 9ch; margin: 0; font-size: clamp(40px, 4.2vw, 58px); font-weight: 600; line-height: 0.96; letter-spacing: -0.035em; }
|
||||
.auth-manifest p { max-width: 48ch; margin: 24px 0 0; color: #aaa9a5; font-size: 15px; line-height: 1.55; }
|
||||
.security-facts { margin: 0; padding: 0; list-style: none; counter-reset: facts; border-top: 1px solid #ffffff33; }
|
||||
.security-facts li { counter-increment: facts; display: grid; grid-template-columns: 28px 1fr; gap: 14px; padding: 14px 0; color: #d5d5d1; border-bottom: 1px solid #ffffff22; font-size: 13px; }
|
||||
.security-facts li::before { content: counter(facts, decimal-leading-zero); color: #6f8bc6; font-family: var(--font-data); font-size: 9px; }
|
||||
.auth-workspace { min-width: 0; min-height: 100vh; display: grid; grid-template-rows: auto 1fr auto; gap: 28px; padding: 48px clamp(42px, 6vw, 90px) 34px; }
|
||||
.auth-top { display: flex; align-items: center; justify-content: space-between; gap: 16px; color: var(--blue); font-family: var(--font-data); font-size: 9px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }
|
||||
.auth-top .lang-switch .btn { color: var(--muted); }
|
||||
.auth-top .lang-switch .is-active { color: var(--white); }
|
||||
.auth-card { align-self: center; width: min(550px, 100%); padding: 28px 0 42px; }
|
||||
.auth-card .page-title { font-size: 38px; }
|
||||
.auth-card .page-subtitle { margin-bottom: 28px; }
|
||||
.auth-card .form-grid { margin-top: 22px; }
|
||||
.auth-card .btn-primary { width: 100%; min-height: 48px; }
|
||||
.auth-alt { margin: 16px 0 0; color: var(--muted); font-size: 13px; }
|
||||
.auth-contract { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
|
||||
.auth-contract span { color: var(--muted); font-family: var(--font-data); font-size: 8px; line-height: 1.4; text-transform: uppercase; }
|
||||
|
||||
@media (max-width: 1120px) {
|
||||
:root { --sidebar: 214px; }
|
||||
@@ -781,6 +755,7 @@ input[type='file']::file-selector-button { min-height: 30px; margin-right: 10px;
|
||||
.mobile-pool small { color: #a9a9a4; font-family: var(--font-data); font-size: 8px; text-transform: uppercase; }
|
||||
.mobile-pool strong { margin: 4px 0; font-size: 28px; }
|
||||
.overview-stats .stat:first-child { display: none; }
|
||||
.overview-stats .stat:nth-child(4) { display: block; }
|
||||
.overview-workbench { display: block; margin-top: 20px; }
|
||||
.month-story { display: none; }
|
||||
.decision-panel { margin-bottom: 24px; padding: 14px; color: var(--ink); background: var(--amber-soft); }
|
||||
@@ -793,8 +768,8 @@ input[type='file']::file-selector-button { min-height: 30px; margin-right: 10px;
|
||||
.pulse-grid { display: block; border: 0; }
|
||||
.pulse-item { padding: 13px 0; border-width: 0 0 1px; background: transparent; }
|
||||
.mobile-primary-action { position: fixed; right: 12px; bottom: 72px; z-index: 45; display: block; }
|
||||
.mobile-primary-action .btn { width: 48px; height: 48px; padding: 0; overflow: hidden; color: transparent; }
|
||||
.mobile-primary-action .btn::after { content: '+'; color: var(--white); font: 500 25px var(--font-ui); }
|
||||
.mobile-primary-action .btn { position: relative; width: 48px; height: 48px; padding: 0; overflow: hidden; color: transparent; }
|
||||
.mobile-primary-action .btn::after { content: '+'; position: absolute; inset: 0; display: grid; place-items: center; color: var(--white); font: 500 25px var(--font-ui); }
|
||||
.filters { grid-template-columns: 1fr 1fr; }
|
||||
.filters .field:first-child { grid-column: 1 / -1; }
|
||||
.filters .checkbox-field { grid-column: 1 / -1; }
|
||||
@@ -825,12 +800,18 @@ input[type='file']::file-selector-button { min-height: 30px; margin-right: 10px;
|
||||
.modal { width: 100vw; }
|
||||
.modal-head { padding: 18px 16px; }
|
||||
.modal-body { padding: 18px 16px 90px; }
|
||||
.auth-page { display: block; padding: 0; background: var(--paper); }
|
||||
.auth-card { width: 100%; min-height: 100vh; margin: 0; padding: 96px 20px 40px; }
|
||||
.auth-card::before { position: absolute; left: 20px; top: 24px; }
|
||||
.auth-card::after { display: none; }
|
||||
.auth-top { margin-bottom: 34px; }
|
||||
.auth-page { display: block; background: var(--paper); }
|
||||
.auth-identity { min-height: 180px; display: block; padding: 20px; }
|
||||
.auth-identity .brand { margin-bottom: 34px; }
|
||||
.auth-manifest { padding: 0; }
|
||||
.auth-manifest h2 { max-width: 12ch; font-size: 31px; }
|
||||
.auth-manifest p,
|
||||
.security-facts { display: none; }
|
||||
.auth-workspace { min-height: calc(100vh - 180px); display: block; padding: 20px 20px 36px; }
|
||||
.auth-top { margin-bottom: 42px; }
|
||||
.auth-card { width: 100%; padding: 0; }
|
||||
.auth-card .page-title { font-size: 32px; }
|
||||
.auth-contract { margin-top: 42px; }
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
|
||||
Reference in New Issue
Block a user