diff --git a/jest.config.js b/jest.config.js index 955d567..9f34ee4 100644 --- a/jest.config.js +++ b/jest.config.js @@ -14,4 +14,11 @@ module.exports = { '^@app/(.*)$': '/src/app/$1', '^@env/(.*)$': '/src/environments/$1', }, + // Ajouter cette section pour gérer les warnings Node.js + testEnvironmentOptions: { + customExportConditions: ['node', 'node-addons'], + }, + + // Supprimer les warnings de dépréciation + setupFiles: ['/suppress-deprecation-warnings.js'], }; diff --git a/package-lock.json b/package-lock.json index fd18812..91f4d73 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,6 @@ "@fortawesome/free-regular-svg-icons": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.2", "@ngneat/until-destroy": "^10.0.0", - "angularx-qrcode": "^17.0.1", "express": "^4.18.2", "ng2-pdf-viewer": "^10.3.3", "ngx-toastr": "^17.0.2", @@ -8033,19 +8032,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/angularx-qrcode": { - "version": "17.0.1", - "resolved": "https://registry.npmjs.org/angularx-qrcode/-/angularx-qrcode-17.0.1.tgz", - "integrity": "sha512-23ZkkaMVtQU2DvyNDj7kTaZRRwYP6R3Vkoa6NmlfkdO/JACv5ppPKYceq2mG3mxP+7N7FCcIO5gpM67Lspm1hQ==", - "license": "MIT", - "dependencies": { - "qrcode": "1.5.3", - "tslib": "^2.3.0" - }, - "peerDependencies": { - "@angular/core": "^17.0.0" - } - }, "node_modules/ansi-colors": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", @@ -8089,6 +8075,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -8803,6 +8790,7 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -9608,15 +9596,6 @@ } } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/decimal.js": { "version": "10.6.0", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", @@ -9813,12 +9792,6 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/dijkstrajs": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", - "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", - "license": "MIT" - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -9972,6 +9945,7 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, "license": "MIT" }, "node_modules/emojis-list": { @@ -9984,12 +9958,6 @@ "node": ">= 4" } }, - "node_modules/encode-utf8": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", - "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", - "license": "MIT" - }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -11001,6 +10969,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "license": "MIT", "dependencies": { "locate-path": "^5.0.0", @@ -11235,6 +11204,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -12137,6 +12107,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -14649,6 +14620,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "license": "MIT", "dependencies": { "p-locate": "^4.1.0" @@ -15990,6 +15962,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "license": "MIT", "dependencies": { "p-limit": "^2.2.0" @@ -16002,6 +15975,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -16057,6 +16031,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -16218,6 +16193,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -16481,15 +16457,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pngjs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", - "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, "node_modules/pocketbase": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/pocketbase/-/pocketbase-0.21.5.tgz", @@ -17087,76 +17054,6 @@ ], "license": "MIT" }, - "node_modules/qrcode": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", - "integrity": "sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg==", - "license": "MIT", - "dependencies": { - "dijkstrajs": "^1.0.1", - "encode-utf8": "^1.0.3", - "pngjs": "^5.0.0", - "yargs": "^15.3.1" - }, - "bin": { - "qrcode": "bin/qrcode" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/qrcode/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/qrcode/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "license": "ISC" - }, - "node_modules/qrcode/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "license": "MIT", - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/qs": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", @@ -17460,6 +17357,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -17475,12 +17373,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "license": "ISC" - }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -18064,6 +17956,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true, "license": "ISC" }, "node_modules/set-function-length": { @@ -18577,6 +18470,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -18607,6 +18501,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -20794,12 +20689,6 @@ "node": ">= 8" } }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "license": "ISC" - }, "node_modules/wide-align": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", @@ -20838,6 +20727,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", diff --git a/package.json b/package.json index 29e3f0a..03aaa09 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "watch": "ng build --watch --configuration development", "tsc": "tsc --noEmit", "tsc:watch": "tsc --noEmit --watch", - "format": "prettier --write \"src/**/*.{ts,html,scss,css,md,json}\"", + "prettier": "prettier --write \"src/**/*.{ts,html,scss,css,md,json}\"", "check:all": "npm run format && npm run tsc && npm run lint && npm run test", "test": "jest", "test:watch": "jest --watch", @@ -36,7 +36,6 @@ "@fortawesome/free-regular-svg-icons": "^6.4.2", "@fortawesome/free-solid-svg-icons": "^6.4.2", "@ngneat/until-destroy": "^10.0.0", - "angularx-qrcode": "^17.0.1", "express": "^4.18.2", "ng2-pdf-viewer": "^10.3.3", "ngx-toastr": "^17.0.2", diff --git a/src/app/routes/authentification/auth/auth.component.html b/src/app/routes/authentification/auth/auth.component.html index 3c9e231..e411a39 100644 --- a/src/app/routes/authentification/auth/auth.component.html +++ b/src/app/routes/authentification/auth/auth.component.html @@ -1,34 +1,48 @@ -
-
-
-
- -
-
- +
+
+
+ + -
+ + +
+ Politiques + + Conditions + + Aide +
+
+
+ + +
+
+ +
+

Identifiez-vous

+

Accédez à votre espace

+
+ + + +
+
diff --git a/src/app/routes/authentification/auth/auth.component.scss b/src/app/routes/authentification/auth/auth.component.scss index e69de29..552292d 100644 --- a/src/app/routes/authentification/auth/auth.component.scss +++ b/src/app/routes/authentification/auth/auth.component.scss @@ -0,0 +1,49 @@ +/* Animations simples et subtiles */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fade-in { + animation: fadeIn 0.6s ease-out; +} + +.animate-slide-up { + animation: slideUp 0.7s ease-out; +} + +.animate-slide-up-delay { + animation: slideUp 0.7s ease-out 0.1s both; +} + +.animate-fade-in-delay { + animation: fadeIn 0.8s ease-out 0.3s both; +} + +/* Amélioration de l'accessibilité */ +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/src/app/routes/home/home.component.html b/src/app/routes/home/home.component.html index 92fb773..77f1df7 100644 --- a/src/app/routes/home/home.component.html +++ b/src/app/routes/home/home.component.html @@ -1,23 +1,204 @@ -
-
-
-

- Dans quel secteur se cache votre prochaine -
- pépites? +
+ +
+
+
+
+
-
- Les finances - La Santé - Les Etudes + +
+
+
+ +
+ +
+ +
+
+ + + + + + Plateforme de mise en relation professionnelle +
-

-
+
-
- + +
+

+ Dans quel secteur se cache + + votre prochaine +
+ + + pépite? + + +

+ + +
+
+
+
+ Les finances + La Santé + Les Études + La Tech +
+
+
+
+
+
+ + +
+

+ Connectez-vous avec des professionnels talentueux dans tous les secteurs d'activité +

+
+ + +
+
+ +
+
+ + +
+
+
+
+ + + +
+
+

+ 250+ +

+

Profils actifs

+
+
+
+ +
+
+
+ + + + +
+
+

12+

+

Secteurs

+
+
+
+ +
+
+
+ + + +
+
+

500+

+

Projets

+
+
+
+
+ + +
+ + + +
diff --git a/src/app/routes/home/home.component.scss b/src/app/routes/home/home.component.scss index 1808d1a..b70d4db 100644 --- a/src/app/routes/home/home.component.scss +++ b/src/app/routes/home/home.component.scss @@ -1,66 +1,226 @@ -h1 { - .word-animation { - overflow: hidden; +// Variables +$animation-duration: 12s; +$blob-duration: 7s; +$gradient-duration: 3s; - span { - color: #4ec7f3; - display: block; - text-transform: capitalize; - animation: rotateSpin 10s infinite; +// Mixins pour les animations +@mixin animation-delay($delay) { + animation-delay: $delay; + opacity: 0; + animation-fill-mode: forwards; +} - &.red { - color: red; - } +// Animation du gradient de fond +@keyframes gradient { + 0%, + 100% { + background-position: 0% 50%; + } + 50% { + background-position: 100% 50%; + } +} - &.orange { - color: orange; - } +// Animation des blobs de fond +@keyframes blob { + 0%, + 100% { + transform: translate(0, 0) scale(1); + } + 25% { + transform: translate(20px, -50px) scale(1.1); + } + 50% { + transform: translate(-20px, 20px) scale(0.9); + } + 75% { + transform: translate(50px, 50px) scale(1.05); + } +} - &.blue { - color: blue; - } +// Animations d'entrée +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +// Animation des mots qui défilent +@keyframes wordSlide { + 0%, + 20% { + transform: translateY(0); + } + 25%, + 45% { + transform: translateY(-100%); + } + 50%, + 70% { + transform: translateY(-200%); + } + 75%, + 95% { + transform: translateY(-300%); + } + 100% { + transform: translateY(-400%); + } +} + +// Classes d'animation +.animate-gradient { + background-size: 200% 200%; + animation: gradient $gradient-duration ease infinite; +} + +.animate-blob { + animation: blob $blob-duration infinite; +} + +.animate-fade-in { + animation: fadeIn 0.8s ease-out; +} + +.animate-slide-up { + animation: slideUp 0.8s ease-out; +} + +// Délais d'animation +.animation-delay-200 { + @include animation-delay(0.2s); +} + +.animation-delay-300 { + @include animation-delay(0.3s); +} + +.animation-delay-400 { + @include animation-delay(0.4s); +} + +.animation-delay-500 { + @include animation-delay(0.5s); +} + +.animation-delay-600 { + @include animation-delay(0.6s); +} + +.animation-delay-2000 { + animation-delay: 2s; +} + +.animation-delay-4000 { + animation-delay: 4s; +} + +// Section des mots animés +.word-animation { + position: relative; + overflow: hidden; + + .word-container { + display: flex; + flex-direction: column; + animation: wordSlide $animation-duration infinite; + } + + .word { + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + text-transform: capitalize; + + // Tailles responsive + font-size: 2.5rem; + height: 3rem; + + @media (min-width: 640px) { + font-size: 3rem; + height: 3.5rem; + } + + @media (min-width: 768px) { + font-size: 3.5rem; + height: 4rem; + } + + @media (min-width: 1024px) { + font-size: 4rem; + height: 5rem; + } + + // Variantes de couleur (avec support dark mode) + &.red { + @apply text-red-500 dark:text-red-400; + } + + &.orange { + @apply text-orange-500 dark:text-orange-400; + } + + &.blue { + @apply text-blue-500 dark:text-blue-400; + } + + &.green { + @apply text-green-500 dark:text-green-400; } } } -@keyframes rotateSpin { - 10% { - -webkit-transform-style: translateY(-102%); - transform: translateY(-102%); - } +// Shadow custom +.shadow-3xl { + box-shadow: 0 35px 60px -15px rgba(0, 0, 0, 0.3); +} - 25% { - -webkit-transform-style: translateY(-100%); - transform: translateY(-100%); - } +// Effet de hover sur les cards de statistiques +.stat-card { + @apply bg-white dark:bg-gray-800 rounded-2xl px-6 py-4 shadow-lg; + @apply transition-all duration-300 transform; - 35% { - -webkit-transform-style: translateY(-202%); - transform: translateY(-202%); - } + &:hover { + @apply shadow-xl -translate-y-1; - 50% { - -webkit-transform-style: translateY(-200%); - transform: translateY(-200%); - } - - 60% { - -webkit-transform-style: translateY(-302%); - transform: translateY(-302%); - } - - 75% { - -webkit-transform-style: translateY(-300%); - transform: translateY(-300%); - } - - 85% { - -webkit-transform-style: translateY(-402%); - transform: translateY(-402%); - } - - 100% { - -webkit-transform-style: translateY(-400%); - transform: translateY(-400%); + .icon-container { + @apply scale-110; + } + } +} + +// Amélioration de l'accessibilité +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} + +// Support pour les écrans très larges +@media (min-width: 1536px) { + .word { + font-size: 4.5rem !important; + height: 5.5rem !important; } } diff --git a/src/app/routes/my-profile/my-profile.component.html b/src/app/routes/my-profile/my-profile.component.html index 355200c..c8c663e 100644 --- a/src/app/routes/my-profile/my-profile.component.html +++ b/src/app/routes/my-profile/my-profile.component.html @@ -1,266 +1,344 @@ @if (profile != undefined) { -
-
-
-
- - - Retour - - - +
+
+
+ +
+
+ +
- @if (profile().estVerifier) { - - Profile verifier - - - } -
-
- -
-
- @if (!isEditMode()) { -
- +
+ +
- } + + Retour + + + - @if (!isEditMode()) { + + @if (profile().estVerifier) { +
+ + Profil vérifié + + + +
+ } +
+
+ + +
+
+ +
+
+
+ @if (user().avatar) { + {{ user().username }} + } @else { + {{ user().username }} + } +
+
+
+ + +
+ @if (user().name) { +

+ {{ user().name }} +

+ } @else if (user().username) { +

+ {{ user().username }} +

+ } @else { +

+ {{ user().email }} +

+ } + +

+ {{ profile().profession | uppercase }} +

+
+
+
+
+ + +
+ +
+ + @if (profile().secteur) { +
+

+ + + + Secteur +

+ +
+ } -
-
-
    -
  • + @if (profile().reseaux) { +
    - - - - Mon profile -
  • -
  • - - - - Mes projets -
  • -
  • - - - - Mes informations -
  • -
  • - - - + + + + + Réseaux + + +
+ } + - Lecteur de PDF - - + +
+ +
+ +
+ + +
@switch (menu().toLowerCase()) { - @case ('home'.toLowerCase()) { - + @case ('home') { + } - @case ('projects'.toLowerCase()) { + @case ('projects') { } - @case ('update'.toLowerCase()) { + @case ('update') { } - @case ('cv'.toLowerCase()) { + @case ('cv') { } @default { - + } }
-
+
diff --git a/src/app/routes/my-profile/my-profile.component.scss b/src/app/routes/my-profile/my-profile.component.scss index e69de29..9917d7a 100644 --- a/src/app/routes/my-profile/my-profile.component.scss +++ b/src/app/routes/my-profile/my-profile.component.scss @@ -0,0 +1,345 @@ +// ============================================ +// ANIMATIONS +// ============================================ + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes pulseSlow { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.8; + } +} + +.animate-fade-in { + animation: fadeIn 0.6s ease-out; +} + +.animate-slide-up { + animation: slideUp 0.6s ease-out; +} + +.animate-pulse-slow { + animation: pulseSlow 3s ease-in-out infinite; +} + +.animation-delay-100 { + animation-delay: 0.1s; + opacity: 0; + animation-fill-mode: forwards; +} + +.animation-delay-200 { + animation-delay: 0.2s; + opacity: 0; + animation-fill-mode: forwards; +} + +.animation-delay-300 { + animation-delay: 0.3s; + opacity: 0; + animation-fill-mode: forwards; +} + +// ============================================ +// NAVIGATION PAR ONGLETS +// ============================================ + +.tab-button { + @apply bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300; + @apply hover:bg-indigo-50 dark:hover:bg-gray-600 hover:text-indigo-600 dark:hover:text-indigo-400; + + &.active-tab { + @apply bg-gradient-to-r from-indigo-600 to-purple-600 text-white; + @apply shadow-lg; + + svg { + @apply text-white; + } + } + + // Animation au hover + &:hover:not(.active-tab) { + transform: translateY(-2px); + box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + } + + // Effet au clic + &:active { + transform: scale(0.98); + } +} + +// ============================================ +// CARDS +// ============================================ + +.card { + @apply bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6; + @apply transition-shadow duration-300; + + &:hover { + @apply shadow-xl; + } +} + +// ============================================ +// RESPONSIVE BREAKPOINTS +// ============================================ + +// Mobile (par défaut) +@media (max-width: 640px) { + .tab-button { + min-width: auto; + padding: 0.625rem; + + span { + display: none; + } + } +} + +// Tablet +@media (min-width: 768px) and (max-width: 1023px) { + .tab-button { + font-size: 0.875rem; + } +} + +// Desktop +@media (min-width: 1024px) { + // Grille sidebar + contenu + .sidebar-layout { + display: grid; + grid-template-columns: 300px 1fr; + gap: 1.5rem; + } +} + +// ============================================ +// BOUTON D'ÉDITION SUR L'AVATAR +// ============================================ + +.edit-button { + @apply absolute -top-2 -right-2 z-10; + @apply w-8 h-8 bg-indigo-600 hover:bg-indigo-700; + @apply rounded-full flex items-center justify-center; + @apply shadow-lg transition-all duration-300; + + &:hover { + transform: scale(1.1); + } + + svg { + @apply w-4 h-4 text-white; + } +} + +// ============================================ +// AVATAR +// ============================================ + +.avatar-wrapper { + position: relative; + + .avatar-ring { + @apply w-28 h-28 md:w-36 md:h-36; + @apply rounded-full bg-gradient-to-br from-indigo-500 to-purple-600; + @apply p-1 shadow-2xl; + @apply transition-transform duration-300; + + &:hover { + transform: scale(1.05); + } + } + + .avatar-image { + @apply w-full h-full rounded-full overflow-hidden bg-white; + + img { + @apply object-cover w-full h-full; + } + } +} + +// ============================================ +// BANNIÈRE +// ============================================ + +.banner { + @apply relative rounded-2xl overflow-hidden shadow-xl; + + .banner-image { + @apply h-48 md:h-64 bg-cover bg-center; + } + + .banner-overlay { + @apply absolute inset-0 bg-gradient-to-b from-transparent to-black/30; + } + + .banner-content { + @apply relative z-10 p-4 flex justify-between items-start; + } +} + +// ============================================ +// BACK BUTTON +// ============================================ + +.back-button { + @apply flex items-center justify-center; + @apply w-10 h-10 md:w-12 md:h-12; + @apply bg-white/20 backdrop-blur-md rounded-full; + @apply hover:bg-white/30 transition-all duration-300; + + &:hover { + transform: scale(1.1); + + svg { + transform: translateX(-4px); + } + } + + svg { + @apply w-6 h-6 text-white transition-transform; + } +} + +// ============================================ +// BADGE VÉRIFIÉ +// ============================================ + +.verified-badge { + @apply flex items-center gap-2; + @apply bg-purple-500/20 backdrop-blur-md; + @apply px-3 py-2 rounded-full; + + svg { + @apply w-5 h-5 md:w-6 md:h-6 text-purple-300; + } + + span { + @apply text-white text-sm font-medium; + } +} + +// ============================================ +// SECTIONS AVEC ICÔNES +// ============================================ + +.section-title { + @apply text-lg font-bold text-gray-900 dark:text-white mb-3; + @apply flex items-center gap-2; + + svg { + @apply h-5 w-5 text-indigo-500; + } +} + +// ============================================ +// AMÉLIORATION DE L'ACCESSIBILITÉ +// ============================================ + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} + +// Focus visible pour l'accessibilité +*:focus-visible { + outline: 2px solid #4f46e5; + outline-offset: 2px; + border-radius: 0.25rem; +} + +// ============================================ +// MODE SOMBRE +// ============================================ + +@media (prefers-color-scheme: dark) { + .card { + background-color: rgba(31, 41, 55, 0.8); + border: 1px solid rgba(55, 65, 81, 0.3); + } + + .tab-button { + &:not(.active-tab) { + background-color: rgba(55, 65, 81, 0.5); + color: rgba(209, 213, 219, 1); + } + } +} + +// ============================================ +// UTILITAIRES PERSONNALISÉS +// ============================================ + +// Divider avec gradient +.divider-gradient { + height: 4px; + background: linear-gradient(90deg, transparent, #4f46e5, transparent); + border-radius: 9999px; +} + +// Card avec hover effect +.hover-lift { + transition: all 0.3s ease; + + &:hover { + transform: translateY(-4px); + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1); + } +} + +// Glassmorphism effect +.glass { + background: rgba(255, 255, 255, 0.1); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +// ============================================ +// PRINT STYLES (optionnel) +// ============================================ + +@media print { + .banner, + .back-button, + .edit-button, + .tab-button { + display: none; + } + + .card { + box-shadow: none; + border: 1px solid #e5e7eb; + } +} diff --git a/src/app/routes/my-profile/my-profile.component.spec.ts b/src/app/routes/my-profile/my-profile.component.spec.ts index 4b8888c..59f5295 100644 --- a/src/app/routes/my-profile/my-profile.component.spec.ts +++ b/src/app/routes/my-profile/my-profile.component.spec.ts @@ -6,12 +6,14 @@ import { ProfileRepository } from '@app/domain/profiles/profile.repository'; import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token'; import { of } from 'rxjs'; import { Profile } from '@app/domain/profiles/profile.model'; +import { ToastrService } from 'ngx-toastr'; describe('MyProfileComponent', () => { let component: MyProfileComponent; let fixture: ComponentFixture; let mockProfileRepo: ProfileRepository; + let mockToastrService: Partial; beforeEach(async () => { mockProfileRepo = { @@ -20,11 +22,18 @@ describe('MyProfileComponent', () => { update: jest.fn(), getByUserId: jest.fn().mockReturnValue(of({} as Profile)), }; + mockToastrService = { + warning: jest.fn(), + success: jest.fn(), + info: jest.fn(), + error: jest.fn(), + }; await TestBed.configureTestingModule({ imports: [MyProfileComponent], providers: [ provideRouter([]), { provide: PROFILE_REPOSITORY_TOKEN, useValue: mockProfileRepo }, + { provide: ToastrService, useValue: mockToastrService }, ], }).compileComponents(); diff --git a/src/app/routes/my-profile/my-profile.component.ts b/src/app/routes/my-profile/my-profile.component.ts index 0527084..6a7166c 100644 --- a/src/app/routes/my-profile/my-profile.component.ts +++ b/src/app/routes/my-profile/my-profile.component.ts @@ -1,16 +1,13 @@ import { Component, computed, inject, OnInit, signal } from '@angular/core'; -import { ActivatedRoute, RouterLink, RouterOutlet } from '@angular/router'; +import { ActivatedRoute, RouterOutlet } from '@angular/router'; import { User } from '@app/shared/models/user'; -import { Location, NgClass } from '@angular/common'; +import { Location, UpperCasePipe } from '@angular/common'; import { UntilDestroy } from '@ngneat/until-destroy'; -import { SafeUrl } from '@angular/platform-browser'; -import { QRCodeModule } from 'angularx-qrcode'; import { environment } from '@env/environment'; import { ChipsComponent } from '@app/shared/components/chips/chips.component'; import { ReseauxComponent } from '@app/shared/components/reseaux/reseaux.component'; import { UpdateUserComponent } from '@app/shared/features/update-user/update-user.component'; import { MyProfileProjectListComponent } from '@app/shared/components/my-profile-project-list/my-profile-project-list.component'; -import { MyHomeProfileComponent } from '@app/shared/components/my-home-profile/my-home-profile.component'; import { MyProfileUpdateFormComponent } from '@app/shared/components/my-profile-update-form/my-profile-update-form.component'; import { PdfViewerComponent } from '@app/shared/features/pdf-viewer/pdf-viewer.component'; import { ProfileFacade } from '@app/ui/profiles/profile.facade'; @@ -19,17 +16,14 @@ import { ProfileFacade } from '@app/ui/profiles/profile.facade'; selector: 'app-my-profile', standalone: true, imports: [ - RouterLink, - QRCodeModule, ChipsComponent, ReseauxComponent, UpdateUserComponent, MyProfileProjectListComponent, RouterOutlet, - MyHomeProfileComponent, MyProfileUpdateFormComponent, - NgClass, PdfViewerComponent, + UpperCasePipe, ], templateUrl: './my-profile.component.html', styleUrl: './my-profile.component.scss', @@ -40,7 +34,6 @@ export class MyProfileComponent implements OnInit { protected menu = signal('home'); protected myProfileQrCode = `${environment.production}`; - protected qrCodeDownloadLink: SafeUrl = `${environment.production}`; protected location = inject(Location); protected readonly route = inject(ActivatedRoute); @@ -52,16 +45,6 @@ export class MyProfileComponent implements OnInit { return {} as User; }); - protected isEditMode = signal(false); - - onChangeURL(url: SafeUrl) { - this.qrCodeDownloadLink = url; - } - - onCancelEditMode($event: boolean) { - this.isEditMode.set(!$event); - } - private readonly profileFacade = new ProfileFacade(); protected profile = this.profileFacade.profile; protected readonly loading = this.profileFacade.loading; diff --git a/src/app/routes/profile/profile-detail/profile-detail.component.html b/src/app/routes/profile/profile-detail/profile-detail.component.html index e259620..cf76607 100644 --- a/src/app/routes/profile/profile-detail/profile-detail.component.html +++ b/src/app/routes/profile/profile-detail/profile-detail.component.html @@ -1,114 +1,267 @@ -
-
-
-
-
- - - Retour - - - +
+
+
+ +
+
+ +
- @if (profile().estVerifier) { - +
+ - Profile verifier - - + + Retour + + + + + + @if (profile().estVerifier) { +
+ + Profil vérifié + + + +
+ } +
+
+ + +
+
+ +
+
+
+ @if (user().avatar) { + {{ user().username }} + } @else { + {{ user().username }} + } +
+
+ +
+
+ + +
+ @if (user().name) { +

+ {{ user().name }} +

+ } @else if (user().username) { +

+ {{ user().username }} +

+ } @else { +

+ {{ user().email }} +

+ } + +

+ {{ profile().profession | uppercase }} +

+
+
+
+
+ + +
+ +
+ +
+

+ + + + Biographie +

+ @if (profile().bio) { +

+ {{ profile().bio }} +

+ } @else { +

+ Je suis sur la plateforme Trouve Ton Profile pour partager mon expertise et mes + compétences. N'hésitez pas à me contacter pour en savoir plus sur mon parcours et + mes domaines d'intervention. +

+ } +
+ + + @if (profile().secteur) { +
+

+ + + + Secteur +

+ +
+ } + + + @if (profile().reseaux) { +
+

+ + + + + Réseaux +

+ +
}
- -
-
-
+ +
+
- @if (user().avatar) { - {{ user().username }} - } @else { - {{ user().username }} - } +

+ + + + À propos +

+

+ {{ profile().apropos }} +

-
- @if (user().name) { -

- {{ user().name }} -

- } @else if (user().username) { -

- {{ user().username }} -

- } @else { -

- {{ user().email }} -

- } -
- @if (profile().bio) { -

{{ profile().bio }}

- } @else { -

- Je suis sur la plateforme Trouve Ton Profile pour partager mon expertise et mes - compétences. N’hésitez pas à me contacter pour en savoir plus sur mon parcours et - mes domaines d’intervention. -

- } - @if (profile().secteur) { -
-

Secteur

- + +
+ +
+
+ + +
- } - - @if (profile().reseaux) { -
-

Réseaux

- +
+

+ Explorer les projets +

+

+ Découvrez les réalisations de la communauté +

- } +
+
-
-

- {{ profile().profession | uppercase }} -

-

{{ profile().apropos }}

- - -
diff --git a/src/app/routes/profile/profile-detail/profile-detail.component.scss b/src/app/routes/profile/profile-detail/profile-detail.component.scss index e69de29..4e30ba7 100644 --- a/src/app/routes/profile/profile-detail/profile-detail.component.scss +++ b/src/app/routes/profile/profile-detail/profile-detail.component.scss @@ -0,0 +1,62 @@ +/* Animations personnalisées */ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes pulseSlow { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.8; + } +} + +.animate-fade-in { + animation: fadeIn 0.6s ease-out; +} + +.animate-slide-up { + animation: slideUp 0.6s ease-out; +} + +.animation-delay-100 { + animation-delay: 0.1s; + opacity: 0; + animation-fill-mode: forwards; +} + +.animation-delay-200 { + animation-delay: 0.2s; + opacity: 0; + animation-fill-mode: forwards; +} + +.animation-delay-300 { + animation-delay: 0.3s; + opacity: 0; + animation-fill-mode: forwards; +} + +.animate-pulse-slow { + animation: pulseSlow 3s ease-in-out infinite; +} diff --git a/src/app/routes/profile/profile-detail/profile-detail.component.ts b/src/app/routes/profile/profile-detail/profile-detail.component.ts index 1dc8caf..e23e6fb 100644 --- a/src/app/routes/profile/profile-detail/profile-detail.component.ts +++ b/src/app/routes/profile/profile-detail/profile-detail.component.ts @@ -1,6 +1,5 @@ import { Component, computed, inject } from '@angular/core'; import { ActivatedRoute, RouterLink } from '@angular/router'; -import { QRCodeModule } from 'angularx-qrcode'; import { UpperCasePipe } from '@angular/common'; import { User } from '@app/shared/models/user'; import { ChipsComponent } from '@app/shared/components/chips/chips.component'; @@ -13,14 +12,7 @@ import { Profile } from '@app/domain/profiles/profile.model'; @Component({ selector: 'app-profile-detail', standalone: true, - imports: [ - QRCodeModule, - ChipsComponent, - ReseauxComponent, - RouterLink, - UpperCasePipe, - ProjectListComponent, - ], + imports: [ChipsComponent, ReseauxComponent, RouterLink, UpperCasePipe, ProjectListComponent], templateUrl: './profile-detail.component.html', styleUrl: './profile-detail.component.scss', }) diff --git a/src/app/routes/profile/profile-list/profile-list.component.html b/src/app/routes/profile/profile-list/profile-list.component.html index 547ea42..381257a 100644 --- a/src/app/routes/profile/profile-list/profile-list.component.html +++ b/src/app/routes/profile/profile-list/profile-list.component.html @@ -1,19 +1,77 @@ -
-
-
- +
+ +
+ +
+
+
+
+
+ +
+ +
+

+ Découvrez les + + meilleurs profils + +

+

+ Explorez notre communauté de talents et trouvez le profil parfait pour votre projet +

+
+ + +
+
+ +
+
-
+ +
@if (loading().isLoading) { -
-

Chargement...

-
+ } @else { - + +
+

Tous les profils

+
+ + + + {{ profiles().length }} profil(s) +
+
+ + +
+ +
}
diff --git a/src/app/routes/profile/profile-list/profile-list.component.scss b/src/app/routes/profile/profile-list/profile-list.component.scss index e69de29..39603ae 100644 --- a/src/app/routes/profile/profile-list/profile-list.component.scss +++ b/src/app/routes/profile/profile-list/profile-list.component.scss @@ -0,0 +1,86 @@ +/* Animations blob pour le fond */ +@keyframes blob { + 0%, + 100% { + transform: translate(0, 0) scale(1); + } + 25% { + transform: translate(20px, -50px) scale(1.1); + } + 50% { + transform: translate(-20px, 20px) scale(0.9); + } + 75% { + transform: translate(50px, 50px) scale(1.05); + } +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(30px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes spinSlow { + to { + transform: rotate(360deg); + } +} + +.animate-blob { + animation: blob 7s infinite; +} + +.animate-fade-in { + animation: fadeIn 0.6s ease-out; +} + +.animate-slide-up { + animation: slideUp 0.6s ease-out; +} + +.animate-spin-slow { + animation: spinSlow 3s linear infinite; +} + +.animation-delay-100 { + animation-delay: 0.1s; + opacity: 0; + animation-fill-mode: forwards; +} + +.animation-delay-200 { + animation-delay: 0.2s; + opacity: 0; + animation-fill-mode: forwards; +} + +.animation-delay-300 { + animation-delay: 0.3s; + opacity: 0; + animation-fill-mode: forwards; +} + +.animation-delay-2000 { + animation-delay: 2s; +} + +.animation-delay-4000 { + animation-delay: 4s; +} diff --git a/src/app/routes/profile/profile-list/profile-list.component.ts b/src/app/routes/profile/profile-list/profile-list.component.ts index 4194f7a..e203e01 100644 --- a/src/app/routes/profile/profile-list/profile-list.component.ts +++ b/src/app/routes/profile/profile-list/profile-list.component.ts @@ -3,17 +3,21 @@ import { SearchComponent } from '@app/shared/features/search/search.component'; import { VerticalProfileListComponent } from '@app/shared/components/vertical-profile-list/vertical-profile-list.component'; import { UntilDestroy } from '@ngneat/until-destroy'; import { ProfileFacade } from '@app/ui/profiles/profile.facade'; +import { LoadingComponent } from '@app/shared/components/loading/loading.component'; +import { Router } from '@angular/router'; @Component({ selector: 'app-profile-list', standalone: true, - imports: [SearchComponent, VerticalProfileListComponent], + imports: [SearchComponent, VerticalProfileListComponent, LoadingComponent], templateUrl: './profile-list.component.html', styleUrl: './profile-list.component.scss', }) @UntilDestroy() export class ProfileListComponent implements OnInit { private readonly facade = inject(ProfileFacade); + private readonly router = inject(Router); + protected readonly profiles = this.facade.profiles; protected readonly loading = this.facade.loading; protected readonly error = this.facade.error; @@ -21,4 +25,8 @@ export class ProfileListComponent implements OnInit { ngOnInit() { this.facade.load(); } + + showNewQuery(newQuery: string) { + this.router.navigate(['/profiles'], { queryParams: { search: newQuery } }); + } } diff --git a/src/app/shared/components/loading/loading.component.html b/src/app/shared/components/loading/loading.component.html new file mode 100644 index 0000000..4700596 --- /dev/null +++ b/src/app/shared/components/loading/loading.component.html @@ -0,0 +1,14 @@ + +
+
+
+
+
+

+ {{ message }} +

+
diff --git a/src/app/shared/components/my-home-profile/my-home-profile.component.scss b/src/app/shared/components/loading/loading.component.scss similarity index 100% rename from src/app/shared/components/my-home-profile/my-home-profile.component.scss rename to src/app/shared/components/loading/loading.component.scss diff --git a/src/app/shared/components/loading/loading.component.spec.ts b/src/app/shared/components/loading/loading.component.spec.ts new file mode 100644 index 0000000..3660663 --- /dev/null +++ b/src/app/shared/components/loading/loading.component.spec.ts @@ -0,0 +1,22 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { LoadingComponent } from './loading.component'; + +describe('LoadingComponent', () => { + let component: LoadingComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [LoadingComponent], + }).compileComponents(); + + fixture = TestBed.createComponent(LoadingComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/shared/components/loading/loading.component.ts b/src/app/shared/components/loading/loading.component.ts new file mode 100644 index 0000000..c29ae25 --- /dev/null +++ b/src/app/shared/components/loading/loading.component.ts @@ -0,0 +1,12 @@ +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'app-loading', + standalone: true, + imports: [], + templateUrl: './loading.component.html', + styleUrl: './loading.component.scss', +}) +export class LoadingComponent { + @Input() message: string = 'Chargement...'; +} diff --git a/src/app/shared/components/my-home-profile/my-home-profile.component.html b/src/app/shared/components/my-home-profile/my-home-profile.component.html deleted file mode 100644 index 2c111c0..0000000 --- a/src/app/shared/components/my-home-profile/my-home-profile.component.html +++ /dev/null @@ -1,6 +0,0 @@ -@if (profile != undefined) { -

- {{ profile.profession | uppercase }} -

-

{{ profile.apropos }}

-} diff --git a/src/app/shared/components/my-home-profile/my-home-profile.component.spec.ts b/src/app/shared/components/my-home-profile/my-home-profile.component.spec.ts deleted file mode 100644 index db1dce1..0000000 --- a/src/app/shared/components/my-home-profile/my-home-profile.component.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { MyHomeProfileComponent } from './my-home-profile.component'; - -describe('MyHomeProfileComponent', () => { - let component: MyHomeProfileComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - imports: [MyHomeProfileComponent], - }).compileComponents(); - - fixture = TestBed.createComponent(MyHomeProfileComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - - await fixture.whenStable(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/shared/components/my-home-profile/my-home-profile.component.ts b/src/app/shared/components/my-home-profile/my-home-profile.component.ts deleted file mode 100644 index 3829260..0000000 --- a/src/app/shared/components/my-home-profile/my-home-profile.component.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Component, Input } from '@angular/core'; -import { UpperCasePipe } from '@angular/common'; -import { UntilDestroy } from '@ngneat/until-destroy'; -import { ProfileViewModel } from '@app/ui/profiles/profile.presenter.model'; - -@Component({ - selector: 'app-my-home-profile', - standalone: true, - imports: [UpperCasePipe], - templateUrl: './my-home-profile.component.html', - styleUrl: './my-home-profile.component.scss', -}) -@UntilDestroy() -export class MyHomeProfileComponent { - @Input({ required: true }) profile: ProfileViewModel | undefined = undefined; -} diff --git a/src/app/shared/components/my-profile-project-list/my-profile-project-list.component.html b/src/app/shared/components/my-profile-project-list/my-profile-project-list.component.html index 90bfd62..c5b4952 100644 --- a/src/app/shared/components/my-profile-project-list/my-profile-project-list.component.html +++ b/src/app/shared/components/my-profile-project-list/my-profile-project-list.component.html @@ -1,33 +1,124 @@ -
-
-

Mes projets

- - @if (projects()) { -
- + + + + - } - -
- } -
- @if (projectIdSelected() != null) { + @for (project of projects(); track project.id) { + + } + + + +
+ + + +
+
+ + +

+ + + + Vous avez {{ projects().length }} projet(s) enregistré(s) +

+
+
+ + + @if (projectIdSelected() != null) { +
- } -
-
+
+ } @else { + +
+
+ + + +
+

+ Aucun projet sélectionné +

+

+ Sélectionnez un projet existant ou créez-en un nouveau pour commencer +

+
+ } + }
diff --git a/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.html b/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.html index 7261496..b2b6855 100644 --- a/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.html +++ b/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.html @@ -1,283 +1,450 @@ -
-

- Mon curriculum vitae (CV) -

- - -

- Ce qu'il faut savoir de moi -

-
-
- -
- -
-
- -
- -
- -
-
-
- -

Mon domaine de competence

- -
-
- -
- - -
- - - - -
-
-
- -
- - -
- + +
+

Mon curriculum vitae (CV)

+
-

Mes réseaux

-
-
- -
- - -
- - Facebook - - -
-
-
-
- -
- - -
- - GitHub - - -
-
-
-
- -
- - -
- - Instagram - - -
-
-
-
- -
- - -
- - LinkedIn - - -
-
-
-
- -
- - -
- - world-globe-outline - - -
-
-
-
- -
- - -
- - X - - -
-
-
-
- -
- - -
- - YouTube - - -
-
-
-
- - +
+
+ + + +
+

Ce qu'il faut savoir de moi

+
+ +
+ +
+ + +
+ + +
+ + +
+
+
+ + +
+
+
+ + + + +
+

Mon domaine de compétence

+
+ +
+ +
+ +
+
+ + + + +
+ +
+
+ + +
+ +
+
+ + + +
+ +
+ + + +
+
+
+
+
+ + +
+
+
+ + + + +
+

Mes réseaux sociaux

+
+ +
+ +
+ +
+
+ + + +
+ +
+
+ +
+ +
+
+ + + +
+ +
+
+ +
+ +
+
+ + + +
+ +
+
+ +
+ +
+
+ + + +
+ +
+
+ +
+ +
+
+ + + +
+ +
+
+ +
+ +
+
+ + + +
+ +
+
+ +
+ +
+
+ + YouTube + + +
+ +
+
+
+
+ +
+ +
diff --git a/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.scss b/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.scss index e69de29..cb08411 100644 --- a/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.scss +++ b/src/app/shared/components/my-profile-update-form/my-profile-update-form.component.scss @@ -0,0 +1,48 @@ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fade-in { + animation: fadeIn 0.6s ease-out; +} + +.animation-delay-100 { + animation-delay: 0.1s; + opacity: 0; + animation-fill-mode: forwards; +} + +.animation-delay-200 { + animation-delay: 0.2s; + opacity: 0; + animation-fill-mode: forwards; +} + +.animation-delay-300 { + animation-delay: 0.3s; + opacity: 0; + animation-fill-mode: forwards; +} + +.animation-delay-400 { + animation-delay: 0.4s; + opacity: 0; + animation-fill-mode: forwards; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/src/app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component.html b/src/app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component.html index 080bdcf..2fdd243 100644 --- a/src/app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component.html +++ b/src/app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component.html @@ -1,98 +1,189 @@ @if (projectId) { - @if (projectId == 'add'.toLowerCase()) { - - } @else { - - } +
+ +
+
+
+ + + +
+

Image du projet

+
-

- Information du projet -

- - @if (loading().isLoading) { - @switch (loading().action) { - @case (ActionType.NONE || ActionType.CREATE || ActionType.DELETE) {} - @default { -

Chargement...

+ @if (projectId == 'add'.toLowerCase()) { + + } @else { + } - } - } @else { -
- -
- +
-
+ +
+
+
+ + fill-rule="evenodd" + d="M4 5a2 2 0 012-2 3 3 0 003 3h2a3 3 0 003-3 2 2 0 012 2v11a2 2 0 01-2 2H6a2 2 0 01-2-2V5zm3 4a1 1 0 000 2h.01a1 1 0 100-2H7zm3 0a1 1 0 000 2h3a1 1 0 100-2h-3zm-3 4a1 1 0 100 2h.01a1 1 0 100-2H7zm3 0a1 1 0 100 2h3a1 1 0 100-2h-3z" + clip-rule="evenodd" + />
+

Informations du projet

- -
- + @if (loading().isLoading) { + @switch (loading().action) { + @case (ActionType.NONE || ActionType.CREATE || ActionType.DELETE) {} + @default { + + + } + } + } @else { + + + +
+ +
+
+ + + +
+ +
+
-
- - - -
-
+ +
+ +
+
+ + + +
+ +
+
- -
- -
+ +
+ + +
- + +
+ - - - } + +
+ + } +
+
} diff --git a/src/app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component.scss b/src/app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component.scss index e69de29..fc1cc26 100644 --- a/src/app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component.scss +++ b/src/app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component.scss @@ -0,0 +1,30 @@ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fade-in { + animation: fadeIn 0.6s ease-out; +} + +.animation-delay-100 { + animation-delay: 0.1s; + opacity: 0; + animation-fill-mode: forwards; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/src/app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component.ts b/src/app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component.ts index 4acb6da..9a814c7 100644 --- a/src/app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component.ts +++ b/src/app/shared/components/my-profile-update-project-form/my-profile-update-project-form.component.ts @@ -17,11 +17,18 @@ import { AuthService } from '@app/core/services/authentication/auth.service'; import { ProjectFacade } from '@app/ui/projects/project.facade'; import { CreateProjectDto } from '@app/domain/projects/dto/create-project.dto'; import { ActionType } from '@app/domain/action-type.util'; +import { LoadingComponent } from '@app/shared/components/loading/loading.component'; @Component({ selector: 'app-my-profile-update-project-form', standalone: true, - imports: [PaginatorModule, ReactiveFormsModule, NgClass, ProjectPictureFormComponent], + imports: [ + PaginatorModule, + ReactiveFormsModule, + NgClass, + ProjectPictureFormComponent, + LoadingComponent, + ], templateUrl: './my-profile-update-project-form.component.html', styleUrl: './my-profile-update-project-form.component.scss', }) diff --git a/src/app/shared/components/project-item/project-item.component.html b/src/app/shared/components/project-item/project-item.component.html index 5f4f89e..fba895c 100644 --- a/src/app/shared/components/project-item/project-item.component.html +++ b/src/app/shared/components/project-item/project-item.component.html @@ -1,32 +1,56 @@ @if (project) { -
- @if (project.fichier) { - {{ project.nom }} - } @else { - nouveau-projet - } +
+ +
+ @if (project.fichier) { + {{ project.nom }} + } @else { + {{ project.nom }} + } -
-

{{ project.nom }}

-

{{ project.description }}

-
+ +
+
+ + + + }
+ + +
} diff --git a/src/app/shared/components/project-item/project-item.component.scss b/src/app/shared/components/project-item/project-item.component.scss index e69de29..1922bd8 100644 --- a/src/app/shared/components/project-item/project-item.component.scss +++ b/src/app/shared/components/project-item/project-item.component.scss @@ -0,0 +1,39 @@ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fade-in { + animation: fadeIn 0.6s ease-out; +} + +/* Line clamp pour limiter le texte */ +.line-clamp-2 { + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.line-clamp-3 { + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/src/app/shared/components/project-list/project-list.component.html b/src/app/shared/components/project-list/project-list.component.html index 9a0b0a3..000848a 100644 --- a/src/app/shared/components/project-list/project-list.component.html +++ b/src/app/shared/components/project-list/project-list.component.html @@ -1,12 +1,41 @@ -
-
-

Explorer les projets

-
- @for (project of projects(); track project) { - - } @empty { -

Aucun projet

- } -
+
+ +
+ @for (project of projects(); track project.id) { + + } @empty { + +
+
+
+ + + +
+

+ Aucun projet disponible +

+

+ Il n'y a pas encore de projets à explorer. Revenez plus tard pour découvrir de nouvelles + réalisations ! +

+
+
+ }
diff --git a/src/app/shared/components/project-list/project-list.component.scss b/src/app/shared/components/project-list/project-list.component.scss index e69de29..597967c 100644 --- a/src/app/shared/components/project-list/project-list.component.scss +++ b/src/app/shared/components/project-list/project-list.component.scss @@ -0,0 +1,24 @@ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fade-in { + animation: fadeIn 0.6s ease-out; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/src/app/shared/components/user-form/user-form.component.html b/src/app/shared/components/user-form/user-form.component.html index 05b75a3..37c4b80 100644 --- a/src/app/shared/components/user-form/user-form.component.html +++ b/src/app/shared/components/user-form/user-form.component.html @@ -1,35 +1,107 @@
-

Mon Identité

- -
- - + +
+
+ + + +
+

Mon identité

-
- - + +
+ +
+
+ + + +
+ +
+ +
+ +
+
+ + + +
+ +
+
+ + diff --git a/src/app/shared/components/user-form/user-form.component.scss b/src/app/shared/components/user-form/user-form.component.scss index e69de29..597967c 100644 --- a/src/app/shared/components/user-form/user-form.component.scss +++ b/src/app/shared/components/user-form/user-form.component.scss @@ -0,0 +1,24 @@ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fade-in { + animation: fadeIn 0.6s ease-out; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/src/app/shared/components/user-form/user-form.component.ts b/src/app/shared/components/user-form/user-form.component.ts index 5439538..55da06f 100644 --- a/src/app/shared/components/user-form/user-form.component.ts +++ b/src/app/shared/components/user-form/user-form.component.ts @@ -35,10 +35,10 @@ export class UserFormComponent implements OnInit { ngOnInit(): void { this.userForm = this.fb.group({ - firstname: new FormControl(this.user?.name!.split(' ').slice(0, -1).join(' ') ?? '', [ + firstname: new FormControl(this.user?.name?.split(' ').slice(0, -1).join(' ') ?? '', [ Validators.required, ]), - name: new FormControl(this.user?.name!.split(' ').slice(-1)[0] ?? '', [Validators.required]), + name: new FormControl(this.user?.name?.split(' ').slice(-1)[0] ?? '', [Validators.required]), }); } diff --git a/src/app/shared/components/vertical-profile-item/vertical-profile-item.component.html b/src/app/shared/components/vertical-profile-item/vertical-profile-item.component.html index 4f58ba3..60fd723 100644 --- a/src/app/shared/components/vertical-profile-item/vertical-profile-item.component.html +++ b/src/app/shared/components/vertical-profile-item/vertical-profile-item.component.html @@ -2,59 +2,97 @@ -
+ +
+ @if (profile.estVerifier) { - - - - } - @if (user.avatar) { - {{ user.username }} - } @else { - {{ user.username }} +
+
+ + + +
+
} -
+ +
+ +
+
+ @if (user.avatar) { + {{ user.username }} + } @else { + {{ user.username }} + } +
+
+ + @if (user.name) { -

+

{{ user.name }}

} @else if (user.username) { -

+

{{ user.username }}

} @else { -

- Non mentionné -

+

Non mentionné

} -

{{ profile.profession }}

- - + + +

+ {{ profile.profession || 'Profession non renseignée' }} +

+ + +
+ +
+ +
+ + + @if (profile.reseaux) { +
+ +
+ } +
+ + +
} diff --git a/src/app/shared/components/vertical-profile-item/vertical-profile-item.component.scss b/src/app/shared/components/vertical-profile-item/vertical-profile-item.component.scss index e69de29..1ac15f2 100644 --- a/src/app/shared/components/vertical-profile-item/vertical-profile-item.component.scss +++ b/src/app/shared/components/vertical-profile-item/vertical-profile-item.component.scss @@ -0,0 +1,23 @@ +@keyframes pulseSlow { + 0%, + 100% { + opacity: 1; + } + 50% { + opacity: 0.8; + } +} + +.animate-pulse-slow { + animation: pulseSlow 3s ease-in-out infinite; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/src/app/shared/components/vertical-profile-list/vertical-profile-list.component.html b/src/app/shared/components/vertical-profile-list/vertical-profile-list.component.html index edf49a3..30166f4 100644 --- a/src/app/shared/components/vertical-profile-list/vertical-profile-list.component.html +++ b/src/app/shared/components/vertical-profile-list/vertical-profile-list.component.html @@ -1,10 +1,41 @@ -
-
-
+
+
+ +
@for (profile of profiles; track profile.id) { } @empty { -

Aucun profile trouvée

+ +
+
+
+ + + +
+

+ Aucun profil trouvé +

+

+ Aucun profil ne correspond à votre recherche. Essayez de modifier vos critères. +

+
+
}
diff --git a/src/app/shared/components/vertical-profile-list/vertical-profile-list.component.scss b/src/app/shared/components/vertical-profile-list/vertical-profile-list.component.scss index e69de29..597967c 100644 --- a/src/app/shared/components/vertical-profile-list/vertical-profile-list.component.scss +++ b/src/app/shared/components/vertical-profile-list/vertical-profile-list.component.scss @@ -0,0 +1,24 @@ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fade-in { + animation: fadeIn 0.6s ease-out; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/src/app/shared/features/login/login.component.html b/src/app/shared/features/login/login.component.html index a5cdf20..a7d458a 100644 --- a/src/app/shared/features/login/login.component.html +++ b/src/app/shared/features/login/login.component.html @@ -1,107 +1,170 @@ -
-
+ + +
+
- +
- + + - - +
+ @if (loginForm.get('email')?.invalid && loginForm.get('email')?.touched) { +

Veuillez entrer une adresse email valide

+ }
-
-
-
- + +
+ +
+
+ + + +
+ + -
- Mot de passe oublié? + } @else { + + + + + } +
+ @if (loginForm.get('password')?.invalid && loginForm.get('password')?.touched) { +

Le mot de passe est requis

+ }
-
- + + -
-

- Vous n'avez pas de compte? - Créez-en ici + + + + + +

+

+ Vous n'avez pas de compte ? + + Créez-en un ici +

+ @if (isLoading()) { - - - +
+ +
} diff --git a/src/app/shared/features/pdf-viewer/pdf-viewer.component.html b/src/app/shared/features/pdf-viewer/pdf-viewer.component.html index 4d0d452..9f03c21 100644 --- a/src/app/shared/features/pdf-viewer/pdf-viewer.component.html +++ b/src/app/shared/features/pdf-viewer/pdf-viewer.component.html @@ -1,18 +1,101 @@ @if (cv_link()) { - + +
+ +
+
+
+ + + +
+

Mon CV

+
+ + + + + + + + +
+ + +
+ +
+
} @else { -

Aucun curriculum vitae (CV) n'a été rajouté.

+ +
+
+ + + +
+

Aucun CV disponible

+

+ Aucun curriculum vitae n'a été ajouté pour le moment. Veuillez télécharger votre CV pour le + visualiser ici. +

+
} diff --git a/src/app/shared/features/register/register.component.html b/src/app/shared/features/register/register.component.html index 9638cef..b4710c0 100644 --- a/src/app/shared/features/register/register.component.html +++ b/src/app/shared/features/register/register.component.html @@ -1,174 +1,273 @@ -
-
+ + +
+
- +
- + + - - +
+ @if (registerForm.get('email')?.invalid && registerForm.get('email')?.touched) { +

Veuillez entrer une adresse email valide

+ }
-
-
-
- + +
+ +
+
+ + + +
+ + -
-
-
- -
-
-
- + } @else { + - - - - -
+ } +
+ @if (registerForm.get('password')?.invalid && registerForm.get('password')?.touched) { +

Le mot de passe doit contenir au moins 8 caractères

+ }
-
- +
+ @if ( + registerForm.get('passwordConfirm')?.invalid && registerForm.get('passwordConfirm')?.touched + ) { +

Les mots de passe ne correspondent pas

+ } +
+ + + @if (registerForm.get('password')!.value; as pwd) { +
+
+
+
+
+
+

+ @if (pwd.length < 8) { + Mot de passe faible + } @else if (pwd.length < 10) { + Mot de passe moyen + } @else { + Mot de passe fort + } +

+
+ } + + + -
-
-

- Vous avez un compte? - Connectez vous ici + } + + + +

+

+ Vous avez déjà un compte ? + + Connectez-vous ici +

+ + +

+ En créant un compte, vous acceptez nos + Conditions d'utilisation + et notre + Politique de confidentialité +

+ @if (isLoading()) { - - - +
+ +
} diff --git a/src/app/shared/features/update-user/update-user.component.html b/src/app/shared/features/update-user/update-user.component.html index 825ed0c..a4f03e6 100644 --- a/src/app/shared/features/update-user/update-user.component.html +++ b/src/app/shared/features/update-user/update-user.component.html @@ -1,38 +1,34 @@ -
- - - - - - Terminer - - - - - - - - Annuler - -
- @if (user != undefined) { -
- - +
+ +
+
+
+ + + +
+

Photo de profil

+
+ +
+ + +
+ +
} diff --git a/src/app/shared/features/update-user/update-user.component.scss b/src/app/shared/features/update-user/update-user.component.scss index e69de29..fc1cc26 100644 --- a/src/app/shared/features/update-user/update-user.component.scss +++ b/src/app/shared/features/update-user/update-user.component.scss @@ -0,0 +1,30 @@ +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.animate-fade-in { + animation: fadeIn 0.6s ease-out; +} + +.animation-delay-100 { + animation-delay: 0.1s; + opacity: 0; + animation-fill-mode: forwards; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} diff --git a/src/app/shared/features/update-user/update-user.component.ts b/src/app/shared/features/update-user/update-user.component.ts index 28914bf..f6a0e81 100644 --- a/src/app/shared/features/update-user/update-user.component.ts +++ b/src/app/shared/features/update-user/update-user.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, output } from '@angular/core'; +import { Component, Input } from '@angular/core'; import { User } from '@app/shared/models/user'; import { UserFormComponent } from '@app/shared/components/user-form/user-form.component'; import { UserAvatarFormComponent } from '@app/shared/components/user-avatar-form/user-avatar-form.component'; @@ -12,6 +12,4 @@ import { UserAvatarFormComponent } from '@app/shared/components/user-avatar-form }) export class UpdateUserComponent { @Input({ required: true }) user: User | undefined = undefined; - onFormSubmitted = output(); - isCancelEditMode = output(); } diff --git a/src/setup-jest.ts b/src/setup-jest.ts index 6e92006..0f356ca 100644 --- a/src/setup-jest.ts +++ b/src/setup-jest.ts @@ -32,23 +32,47 @@ global.fetch = jest.fn(() => }) ) as jest.Mock; -// 🟡 Ignore le warning pdfjs-dist +// 🟡 Ignore les warnings pdfjs-dist const originalWarn = console.warn; console.warn = (...args) => { - if ( - typeof args[0] === 'string' && - args[0].includes('ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG') - ) { + const message = typeof args[0] === 'string' ? args[0] : ''; + + // Liste des warnings à ignorer + const ignoredWarnings = [ + 'ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG', + 'loadPackages', + 'pdfjs-dist', + ]; + + if (ignoredWarnings.some((warning) => message.includes(warning))) { return; } + originalWarn(...args); }; -// 🔴 Ignore le log angularx-qrcode après les tests -const originalError = console.error; -console.error = (...args) => { - if (typeof args[0] === 'string' && args[0].includes('[angularx-qrcode]')) { +// 🟡 Ignore les logs angularx-qrcode +const originalLog = console.log; +console.log = (...args) => { + const message = typeof args[0] === 'string' ? args[0] : ''; + + const ignoredLogs = ['Warning: loadPackages', 'ERR_VM_DYNAMIC_IMPORT_CALLBACK_MISSING_FLAG']; + + if (ignoredLogs.some((log) => message.includes(log))) { return; } + + originalLog(...args); +}; + +// 🔴 Ignore les errors angularx-qrcode +const originalError = console.error; +console.error = (...args) => { + const message = typeof args[0] === 'string' ? args[0] : ''; + + if (message.includes('[angularx-qrcode]')) { + return; + } + originalError(...args); }; diff --git a/suppress-deprecation-warnings.js b/suppress-deprecation-warnings.js new file mode 100644 index 0000000..66e6da1 --- /dev/null +++ b/suppress-deprecation-warnings.js @@ -0,0 +1,9 @@ +// suppress-deprecation-warnings.js +const originalEmitWarning = process.emitWarning; + +process.emitWarning = (warning, type, code, ...args) => { + if (code === 'DEP0040') { + return; + } + return originalEmitWarning.call(process, warning, type, code, ...args); +};