diff --git a/frontend/package.json b/frontend/package.json index 6607149..073ed49 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -15,7 +15,8 @@ "next": "16.3.4", "react": "^19.3.0", "react-bootstrap": "^2.10.10", - "react-dom": "^19.3.0" + "react-dom": "^19.3.0", + "sileo": "^0.1.6" }, "devDependencies": { "@tailwindcss/postcss": "^4", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index b8d274a..e63560d 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -19,7 +19,7 @@ importers: version: 1.13.1 next: specifier: 16.3.4 - version: 16.3.4(@babel/core@7.29.7)(@types/node@20.19.43)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + version: 16.3.4(@babel/core@7.29.7(supports-color@7.2.0))(@types/node@20.19.43)(react-dom@19.3.0(react@19.3.0))(react@19.3.0) react: specifier: ^19.3.0 version: 19.3.0 @@ -29,6 +29,9 @@ importers: react-dom: specifier: ^19.3.0 version: 19.3.0(react@19.3.0) + sileo: + specifier: ^0.1.6 + version: 0.1.6(react-dom@19.3.0(react@19.3.0))(react@19.3.0) devDependencies: '@tailwindcss/postcss': specifier: ^4 @@ -44,10 +47,10 @@ importers: version: 19.2.7(@types/react@19.2.18) eslint: specifier: ^9 - version: 9.39.5(jiti@2.7.0) + version: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) eslint-config-next: specifier: 16.3.4 - version: 16.3.4(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) + version: 16.3.4(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) tailwindcss: specifier: ^4 version: 4.3.3 @@ -1275,6 +1278,20 @@ packages: resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} engines: {node: '>= 0.4'} + framer-motion@12.43.0: + resolution: {integrity: sha512-1eaL3RvR/kAlbG7UYcpMptEyzPoENO0c6w7ZnB3/hh2vSAz/6uGAFn6fdoqTBguNstf3MsFhJHsD/0DHiclG+g==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} @@ -1673,6 +1690,26 @@ packages: minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + motion-dom@12.43.0: + resolution: {integrity: sha512-azKON4d9S65PEoFUiQTMTgPheEmzf2QngdRc50AKfJp9Q9mmcBVw22c8eMq9k8kxOFHdL7+WZY7N/5F/lwiDag==} + + motion-utils@12.39.0: + resolution: {integrity: sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==} + + motion@12.43.0: + resolution: {integrity: sha512-BQgQbSa9Hn3/mtbib0MK53y6JSANa+YKUKlaYnWzAVDH424RYQ5LVpV3pNiWH00BA2z4ojsSdMzqT7g2FQwjuQ==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -1961,6 +1998,12 @@ packages: resolution: {integrity: sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==} engines: {node: '>= 0.4'} + sileo@0.1.6: + resolution: {integrity: sha512-a1IIJ72BMskiXfbWlO+eTWu1yxz7wQtFIW7SvyaAax0WHqPi/WUsQH9yKvbWo2dDSxel4LdGRLYLzJCIIE6eHA==} + peerDependencies: + react: '>=18' + react-dom: '>=18' + source-map-js@1.2.1: resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} engines: {node: '>=0.10.0'} @@ -2173,20 +2216,20 @@ snapshots: '@babel/compat-data@7.29.7': {} - '@babel/core@7.29.7': + '@babel/core@7.29.7(supports-color@7.2.0)': 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@7.2.0))(supports-color@7.2.0) '@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@7.2.0) '@babel/types': 7.29.8 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@7.2.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -2211,19 +2254,19 @@ snapshots: '@babel/helper-globals@7.29.7': {} - '@babel/helper-module-imports@7.29.7': + '@babel/helper-module-imports@7.29.7(supports-color@7.2.0)': dependencies: - '@babel/traverse': 7.29.8 + '@babel/traverse': 7.29.8(supports-color@7.2.0) '@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@7.2.0))(supports-color@7.2.0)': dependencies: - '@babel/core': 7.29.7 - '@babel/helper-module-imports': 7.29.7 + '@babel/core': 7.29.7(supports-color@7.2.0) + '@babel/helper-module-imports': 7.29.7(supports-color@7.2.0) '@babel/helper-validator-identifier': 7.29.7 - '@babel/traverse': 7.29.8 + '@babel/traverse': 7.29.8(supports-color@7.2.0) transitivePeerDependencies: - supports-color @@ -2250,7 +2293,7 @@ snapshots: '@babel/parser': 7.29.8 '@babel/types': 7.29.8 - '@babel/traverse@7.29.8': + '@babel/traverse@7.29.8(supports-color@7.2.0)': dependencies: '@babel/code-frame': 7.29.7 '@babel/generator': 7.29.8 @@ -2258,7 +2301,7 @@ snapshots: '@babel/parser': 7.29.8 '@babel/template': 7.29.7 '@babel/types': 7.29.8 - debug: 4.4.3 + debug: 4.4.3(supports-color@7.2.0) transitivePeerDependencies: - supports-color @@ -2288,22 +2331,22 @@ snapshots: tslib: 2.8.1 optional: true - '@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(jiti@2.7.0))': + '@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))': dependencies: - eslint: 9.39.5(jiti@2.7.0) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.9.1(eslint@9.39.5(jiti@2.7.0))': + '@eslint-community/eslint-utils@4.9.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))': dependencies: - eslint: 9.39.5(jiti@2.7.0) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) 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@7.2.0)': dependencies: '@eslint/object-schema': 2.1.7 - debug: 4.4.3 + debug: 4.4.3(supports-color@7.2.0) minimatch: 3.1.5 transitivePeerDependencies: - supports-color @@ -2316,10 +2359,10 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.7': + '@eslint/eslintrc@3.3.7(supports-color@7.2.0)': dependencies: ajv: 6.15.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@7.2.0) espree: 10.4.0 globals: 14.0.0 ignore: 5.3.2 @@ -2502,9 +2545,9 @@ snapshots: '@next/env@16.3.4': {} - '@next/eslint-plugin-next@16.3.4(eslint@9.39.5(jiti@2.7.0))': + '@next/eslint-plugin-next@16.3.4(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))': dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.5(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)) fast-glob: 3.3.1 transitivePeerDependencies: - eslint @@ -2698,15 +2741,15 @@ snapshots: '@types/warning@3.0.4': {} - '@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/parser': 8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.70.0 - '@typescript-eslint/type-utils': 8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) - '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/type-utils': 8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.70.0 - eslint: 9.39.5(jiti@2.7.0) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) ignore: 7.0.9 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@5.9.3) @@ -2714,23 +2757,23 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)': + '@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.70.0 '@typescript-eslint/types': 8.70.0 - '@typescript-eslint/typescript-estree': 8.70.0(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.70.0(supports-color@7.2.0)(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.70.0 - debug: 4.4.3 - eslint: 9.39.5(jiti@2.7.0) + debug: 4.4.3(supports-color@7.2.0) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.70.0(typescript@5.9.3)': + '@typescript-eslint/project-service@8.70.0(supports-color@7.2.0)(typescript@5.9.3)': dependencies: '@typescript-eslint/tsconfig-utils': 8.70.0(typescript@5.9.3) '@typescript-eslint/types': 8.70.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@7.2.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -2744,13 +2787,13 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.70.0 - '@typescript-eslint/typescript-estree': 8.70.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) - debug: 4.4.3 - eslint: 9.39.5(jiti@2.7.0) + '@typescript-eslint/typescript-estree': 8.70.0(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + debug: 4.4.3(supports-color@7.2.0) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) ts-api-utils: 2.5.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -2758,13 +2801,13 @@ snapshots: '@typescript-eslint/types@8.70.0': {} - '@typescript-eslint/typescript-estree@8.70.0(typescript@5.9.3)': + '@typescript-eslint/typescript-estree@8.70.0(supports-color@7.2.0)(typescript@5.9.3)': dependencies: - '@typescript-eslint/project-service': 8.70.0(typescript@5.9.3) + '@typescript-eslint/project-service': 8.70.0(supports-color@7.2.0)(typescript@5.9.3) '@typescript-eslint/tsconfig-utils': 8.70.0(typescript@5.9.3) '@typescript-eslint/types': 8.70.0 '@typescript-eslint/visitor-keys': 8.70.0 - debug: 4.4.3 + debug: 4.4.3(supports-color@7.2.0) minimatch: 10.2.6 semver: 7.8.5 tinyglobby: 0.2.17 @@ -2773,13 +2816,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3)': + '@typescript-eslint/utils@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)) '@typescript-eslint/scope-manager': 8.70.0 '@typescript-eslint/types': 8.70.0 - '@typescript-eslint/typescript-estree': 8.70.0(typescript@5.9.3) - eslint: 9.39.5(jiti@2.7.0) + '@typescript-eslint/typescript-estree': 8.70.0(supports-color@7.2.0)(typescript@5.9.3) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -3066,13 +3109,17 @@ snapshots: es-errors: 1.3.0 is-data-view: 1.0.2 - debug@3.2.7: + debug@3.2.7(supports-color@7.2.0): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 7.2.0 - debug@4.4.3: + debug@4.4.3(supports-color@7.2.0): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 7.2.0 deep-is@0.1.4: {} @@ -3231,18 +3278,18 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-config-next@16.3.4(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3): + eslint-config-next@16.3.4(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3): dependencies: - '@next/eslint-plugin-next': 16.3.4(eslint@9.39.5(jiti@2.7.0)) - eslint: 9.39.5(jiti@2.7.0) - eslint-import-resolver-node: 0.3.10 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)) - eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.5(jiti@2.7.0)) - eslint-plugin-react: 7.37.5(eslint@9.39.5(jiti@2.7.0)) - eslint-plugin-react-hooks: 7.1.1(eslint@9.39.5(jiti@2.7.0)) + '@next/eslint-plugin-next': 16.3.4(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + eslint-import-resolver-node: 0.3.10(supports-color@7.2.0) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)) + eslint-plugin-react: 7.37.5(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)) + eslint-plugin-react-hooks: 7.1.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0) globals: 16.4.0 - typescript-eslint: 8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) + typescript-eslint: 8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -3251,52 +3298,52 @@ snapshots: - eslint-plugin-import-x - supports-color - eslint-import-resolver-node@0.3.10: + eslint-import-resolver-node@0.3.10(supports-color@7.2.0): dependencies: - debug: 3.2.7 + debug: 3.2.7(supports-color@7.2.0) is-core-module: 2.16.2 resolve: 2.0.0-next.7 transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0): dependencies: '@nolyfill/is-core-module': 1.0.39 - debug: 4.4.3 - eslint: 9.39.5(jiti@2.7.0) + debug: 4.4.3(supports-color@7.2.0) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) get-tsconfig: 4.14.3 is-bun-module: 2.0.0 stable-hash: 0.0.5 tinyglobby: 0.2.17 unrs-resolver: 1.12.2 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0) transitivePeerDependencies: - supports-color - eslint-module-utils@2.14.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)): + eslint-module-utils@2.14.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10(supports-color@7.2.0))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0): dependencies: - debug: 3.2.7 + debug: 3.2.7(supports-color@7.2.0) optionalDependencies: - '@typescript-eslint/parser': 8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) - eslint: 9.39.5(jiti@2.7.0) - eslint-import-resolver-node: 0.3.10 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)) + '@typescript-eslint/parser': 8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + eslint-import-resolver-node: 0.3.10(supports-color@7.2.0) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0): 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 + debug: 3.2.7(supports-color@7.2.0) doctrine: 2.1.0 - eslint: 9.39.5(jiti@2.7.0) - eslint-import-resolver-node: 0.3.10 - eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) + eslint-import-resolver-node: 0.3.10(supports-color@7.2.0) + eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint-import-resolver-node@0.3.10(supports-color@7.2.0))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0) hasown: 2.0.4 is-core-module: 2.16.2 is-glob: 4.0.3 @@ -3308,13 +3355,13 @@ snapshots: string.prototype.trimend: 1.0.10 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) + '@typescript-eslint/parser': 8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5(jiti@2.7.0)): + eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)): dependencies: aria-query: 5.3.2 array-includes: 3.1.9 @@ -3324,7 +3371,7 @@ snapshots: axobject-query: 4.1.0 damerau-levenshtein: 1.0.8 emoji-regex: 9.2.2 - eslint: 9.39.5(jiti@2.7.0) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) hasown: 2.0.4 jsx-ast-utils: 3.3.5 language-tags: 1.0.9 @@ -3333,18 +3380,18 @@ snapshots: safe-regex-test: 1.1.0 string.prototype.includes: 2.0.1 - eslint-plugin-react-hooks@7.1.1(eslint@9.39.5(jiti@2.7.0)): + eslint-plugin-react-hooks@7.1.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0): dependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@7.2.0) '@babel/parser': 7.29.8 - eslint: 9.39.5(jiti@2.7.0) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) hermes-parser: 0.25.1 zod: 4.5.4 zod-validation-error: 4.0.2(zod@4.5.4) transitivePeerDependencies: - supports-color - eslint-plugin-react@7.37.5(eslint@9.39.5(jiti@2.7.0)): + eslint-plugin-react@7.37.5(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 @@ -3352,7 +3399,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.4.0 - eslint: 9.39.5(jiti@2.7.0) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) estraverse: 5.3.0 hasown: 2.0.4 jsx-ast-utils: 3.3.5 @@ -3377,14 +3424,14 @@ snapshots: eslint-visitor-keys@5.0.1: {} - eslint@9.39.5(jiti@2.7.0): + eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0): dependencies: - '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0)) + '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0)) '@eslint-community/regexpp': 4.12.2 - '@eslint/config-array': 0.21.2 + '@eslint/config-array': 0.21.2(supports-color@7.2.0) '@eslint/config-helpers': 0.4.2 '@eslint/core': 0.17.0 - '@eslint/eslintrc': 3.3.7 + '@eslint/eslintrc': 3.3.7(supports-color@7.2.0) '@eslint/js': 9.39.5 '@eslint/plugin-kit': 0.4.1 '@humanfs/node': 0.16.8 @@ -3394,7 +3441,7 @@ snapshots: ajv: 6.15.0 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.3 + debug: 4.4.3(supports-color@7.2.0) escape-string-regexp: 4.0.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -3482,6 +3529,15 @@ snapshots: dependencies: is-callable: 1.2.7 + framer-motion@12.43.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0): + dependencies: + motion-dom: 12.43.0 + motion-utils: 12.39.0 + tslib: 2.8.1 + optionalDependencies: + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + function-bind@1.1.2: {} function.prototype.name@1.2.0: @@ -3859,6 +3915,20 @@ snapshots: minimist@1.2.8: {} + motion-dom@12.43.0: + dependencies: + motion-utils: 12.39.0 + + motion-utils@12.39.0: {} + + motion@12.43.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0): + dependencies: + framer-motion: 12.43.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + tslib: 2.8.1 + optionalDependencies: + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + ms@2.1.3: {} nanoid@3.3.18: {} @@ -3867,7 +3937,7 @@ snapshots: natural-compare@1.4.0: {} - next@16.3.4(@babel/core@7.29.7)(@types/node@20.19.43)(react-dom@19.3.0(react@19.3.0))(react@19.3.0): + next@16.3.4(@babel/core@7.29.7(supports-color@7.2.0))(@types/node@20.19.43)(react-dom@19.3.0(react@19.3.0))(react@19.3.0): dependencies: '@next/env': 16.3.4 '@swc/helpers': 0.5.23 @@ -3876,7 +3946,7 @@ snapshots: postcss: 8.5.23 react: 19.3.0 react-dom: 19.3.0(react@19.3.0) - styled-jsx: 5.1.6(@babel/core@7.29.7)(react@19.3.0) + styled-jsx: 5.1.6(@babel/core@7.29.7(supports-color@7.2.0))(react@19.3.0) optionalDependencies: '@next/swc-darwin-arm64': 16.3.4 '@next/swc-darwin-x64': 16.3.4 @@ -4233,6 +4303,14 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + sileo@0.1.6(react-dom@19.3.0(react@19.3.0))(react@19.3.0): + dependencies: + motion: 12.43.0(react-dom@19.3.0(react@19.3.0))(react@19.3.0) + react: 19.3.0 + react-dom: 19.3.0(react@19.3.0) + transitivePeerDependencies: + - '@emotion/is-prop-valid' + source-map-js@1.2.1: {} stable-hash@0.0.5: {} @@ -4297,12 +4375,12 @@ snapshots: strip-json-comments@3.1.1: {} - styled-jsx@5.1.6(@babel/core@7.29.7)(react@19.3.0): + styled-jsx@5.1.6(@babel/core@7.29.7(supports-color@7.2.0))(react@19.3.0): dependencies: client-only: 0.0.1 react: 19.3.0 optionalDependencies: - '@babel/core': 7.29.7 + '@babel/core': 7.29.7(supports-color@7.2.0) supports-color@7.2.0: dependencies: @@ -4373,13 +4451,13 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3): + typescript-eslint@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) - '@typescript-eslint/parser': 8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) - '@typescript-eslint/typescript-estree': 8.70.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(jiti@2.7.0))(typescript@5.9.3) - eslint: 9.39.5(jiti@2.7.0) + '@typescript-eslint/eslint-plugin': 8.70.0(@typescript-eslint/parser@8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/parser': 8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/typescript-estree': 8.70.0(supports-color@7.2.0)(typescript@5.9.3) + '@typescript-eslint/utils': 8.70.0(eslint@9.39.5(jiti@2.7.0)(supports-color@7.2.0))(supports-color@7.2.0)(typescript@5.9.3) + eslint: 9.39.5(jiti@2.7.0)(supports-color@7.2.0) typescript: 5.9.3 transitivePeerDependencies: - supports-color diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index 6c03041..6fbb098 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -1,8 +1,10 @@ import type { Metadata } from "next"; import { Inter, Fira_Sans } from "next/font/google"; import "bootstrap/dist/css/bootstrap.min.css"; +import "sileo/styles.css"; import "./globals.css"; import { AuthProvider } from "@/lib/auth"; +import SileoToaster from "@/components/SileoToaster"; const inter = Inter({ variable: "--font-inter", @@ -34,7 +36,10 @@ export default function RootLayout({ /> - {children} + + {children} + + ); diff --git a/frontend/src/components/NotificationBell.tsx b/frontend/src/components/NotificationBell.tsx index faac699..2f7f060 100644 --- a/frontend/src/components/NotificationBell.tsx +++ b/frontend/src/components/NotificationBell.tsx @@ -1,6 +1,6 @@ "use client"; -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useEffect, useRef, useState } from "react"; import { useRouter } from "next/navigation"; import { getNotifications, @@ -9,6 +9,7 @@ import { markAllNotificationsRead, type AppNotification, } from "@/lib/api"; +import { notify } from "@/lib/notify"; import { formatDate } from "@/lib/format"; const POLL_MS = 60000; @@ -49,17 +50,57 @@ export default function NotificationBell() { const [open, setOpen] = useState(false); const [filter, setFilter] = useState(""); const [markingAll, setMarkingAll] = useState(false); + const seenIds = useRef>(new Set()); + const initialized = useRef(false); + + const toastNew = useCallback( + (list: AppNotification[]) => { + const fresh = list.filter((n) => !n.isRead && !seenIds.current.has(n.id)); + // En la primera carga solo registra; evita una ráfaga de toasts históricos. + if (!initialized.current) { + initialized.current = true; + } else if (fresh.length > 0) { + // Un toast por notificación nueva (máx 3) o uno agrupado. + if (fresh.length <= 3) { + for (const n of fresh) { + if (n.ticketId) { + const ticketId = n.ticketId; + notify.action(n.title, "Ver", () => router.push(`/tickets/${ticketId}`), n.body ?? undefined); + } else { + notify.info(n.title, n.body ?? undefined); + } + } + } else { + notify.info( + `${fresh.length} notificaciones nuevas`, + fresh + .slice(0, 3) + .map((n) => n.title) + .join(" · ") + ); + } + } + for (const n of list) seenIds.current.add(n.id); + // Acota memoria del set. + if (seenIds.current.size > 300) { + const keep = new Set(list.map((n) => n.id)); + seenIds.current = keep; + } + }, + [router] + ); const fetchAll = useCallback(() => { Promise.all([getNotifications(50), getUnreadCount()]) .then(([list, { count }]) => { setItems(list); setUnread(count); + toastNew(list); }) .catch(() => { // Sin sesión o backend caído: se reintenta en el próximo ciclo. }); - }, []); + }, [toastNew]); useEffect(() => { fetchAll(); @@ -103,7 +144,9 @@ export default function NotificationBell() { .catch(() => {}); } }) - .catch(() => {}) + .catch(() => { + notify.error("No se pudieron marcar como leídas"); + }) .finally(() => setMarkingAll(false)); }; diff --git a/frontend/src/components/SileoToaster.tsx b/frontend/src/components/SileoToaster.tsx new file mode 100644 index 0000000..202b488 --- /dev/null +++ b/frontend/src/components/SileoToaster.tsx @@ -0,0 +1,7 @@ +"use client"; + +import { Toaster } from "sileo"; + +export default function SileoToaster() { + return ; +} diff --git a/frontend/src/lib/notify.ts b/frontend/src/lib/notify.ts new file mode 100644 index 0000000..8c555b2 --- /dev/null +++ b/frontend/src/lib/notify.ts @@ -0,0 +1,62 @@ +"use client"; + +import { sileo, type SileoOptions } from "sileo"; + +// Wrapper fino sobre sileo para unificar copy en español y defaults. +// Uso: notify.success("Ticket creado"), notify.error("No se pudo guardar", err) +const DEFAULT_DURATION = 5000; + +function base(title: string, description?: string): SileoOptions { + return { title, description, duration: DEFAULT_DURATION }; +} + +export const notify = { + success(title: string, description?: string, opts?: Partial) { + return sileo.success({ ...base(title, description), ...opts }); + }, + error(title: string, description?: string, opts?: Partial) { + return sileo.error({ ...base(title, description), ...opts }); + }, + warning(title: string, description?: string, opts?: Partial) { + return sileo.warning({ ...base(title, description), ...opts }); + }, + info(title: string, description?: string, opts?: Partial) { + return sileo.info({ ...base(title, description), ...opts }); + }, + action( + title: string, + buttonTitle: string, + onClick: () => void, + description?: string, + opts?: Partial + ) { + return sileo.action({ + ...base(title, description), + button: { title: buttonTitle, onClick }, + ...opts, + }); + }, + promise( + promise: Promise | (() => Promise), + messages: { + loading: string; + success: string | ((data: T) => string); + error: string | ((err: unknown) => string); + } + ) { + const { loading, success, error } = messages; + return sileo.promise(promise, { + loading: { title: loading }, + success: + typeof success === "function" + ? (data: T) => ({ title: (success as (d: T) => string)(data) }) + : { title: success }, + error: + typeof error === "function" + ? (err: unknown) => ({ title: (error as (e: unknown) => string)(err) }) + : { title: error }, + }); + }, + dismiss: sileo.dismiss, + clear: sileo.clear, +};