add avatar from gravatar or create avatar based on initials

This commit is contained in:
Guillaume Dorce 2022-09-16 16:45:00 +02:00
parent 05c65f172a
commit 871ffe8462
6 changed files with 227 additions and 11 deletions

View File

@ -10,6 +10,7 @@
}, },
"dependencies": { "dependencies": {
"@tanstack/react-query": "^4.2.3", "@tanstack/react-query": "^4.2.3",
"gravatar": "^1.8.2",
"ms": "^2.1.3", "ms": "^2.1.3",
"react": "^18.2.0", "react": "^18.2.0",
"react-cookie": "^4.1.1", "react-cookie": "^4.1.1",
@ -18,6 +19,7 @@
"react-router-dom": "^6.3.0" "react-router-dom": "^6.3.0"
}, },
"devDependencies": { "devDependencies": {
"@types/gravatar": "^1.8.3",
"@types/react": "^18.0.17", "@types/react": "^18.0.17",
"@types/react-dom": "^18.0.6", "@types/react-dom": "^18.0.6",
"@vitejs/plugin-react": "^2.0.1", "@vitejs/plugin-react": "^2.0.1",

View File

@ -2,10 +2,12 @@ lockfileVersion: 5.4
specifiers: specifiers:
'@tanstack/react-query': ^4.2.3 '@tanstack/react-query': ^4.2.3
'@types/gravatar': ^1.8.3
'@types/react': ^18.0.17 '@types/react': ^18.0.17
'@types/react-dom': ^18.0.6 '@types/react-dom': ^18.0.6
'@vitejs/plugin-react': ^2.0.1 '@vitejs/plugin-react': ^2.0.1
autoprefixer: ^10.4.8 autoprefixer: ^10.4.8
gravatar: ^1.8.2
ms: ^2.1.3 ms: ^2.1.3
postcss: ^8.4.16 postcss: ^8.4.16
react: ^18.2.0 react: ^18.2.0
@ -20,6 +22,7 @@ specifiers:
dependencies: dependencies:
'@tanstack/react-query': 4.2.3_biqbaboplfbrettd7655fr4n2y '@tanstack/react-query': 4.2.3_biqbaboplfbrettd7655fr4n2y
gravatar: 1.8.2
ms: 2.1.3 ms: 2.1.3
react: 18.2.0 react: 18.2.0
react-cookie: 4.1.1_react@18.2.0 react-cookie: 4.1.1_react@18.2.0
@ -28,6 +31,7 @@ dependencies:
react-router-dom: 6.3.0_biqbaboplfbrettd7655fr4n2y react-router-dom: 6.3.0_biqbaboplfbrettd7655fr4n2y
devDependencies: devDependencies:
'@types/gravatar': 1.8.3
'@types/react': 18.0.17 '@types/react': 18.0.17
'@types/react-dom': 18.0.6 '@types/react-dom': 18.0.6
'@vitejs/plugin-react': 2.0.1_vite@3.0.7 '@vitejs/plugin-react': 2.0.1_vite@3.0.7
@ -409,6 +413,10 @@ packages:
resolution: {integrity: sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==} resolution: {integrity: sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==}
dev: false dev: false
/@types/gravatar/1.8.3:
resolution: {integrity: sha512-F4Ij02yEI2+hr7aMCrM8syaU9pN16cSJIxnFf/ccVNQ+HrKzgVz8Kn0ZJhWzCJM+UnELHO/OGKTW0O646vk/HA==}
dev: true
/@types/hoist-non-react-statics/3.3.1: /@types/hoist-non-react-statics/3.3.1:
resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==} resolution: {integrity: sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==}
dependencies: dependencies:
@ -476,6 +484,11 @@ packages:
hasBin: true hasBin: true
dev: true dev: true
/ansi-regex/5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
dev: false
/ansi-styles/3.2.1: /ansi-styles/3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -483,6 +496,13 @@ packages:
color-convert: 1.9.3 color-convert: 1.9.3
dev: true dev: true
/ansi-styles/4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
dependencies:
color-convert: 2.0.1
dev: false
/anymatch/3.1.2: /anymatch/3.1.2:
resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@ -516,6 +536,10 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true dev: true
/blueimp-md5/2.19.0:
resolution: {integrity: sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==}
dev: false
/braces/3.0.2: /braces/3.0.2:
resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -539,6 +563,11 @@ packages:
engines: {node: '>= 6'} engines: {node: '>= 6'}
dev: true dev: true
/camelcase/5.3.1:
resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
engines: {node: '>=6'}
dev: false
/caniuse-lite/1.0.30001376: /caniuse-lite/1.0.30001376:
resolution: {integrity: sha512-I27WhtOQ3X3v3it9gNs/oTpoE5KpwmqKR5oKPA8M0G7uMXh9Ty81Q904HpKUrM30ei7zfcL5jE7AXefgbOfMig==} resolution: {integrity: sha512-I27WhtOQ3X3v3it9gNs/oTpoE5KpwmqKR5oKPA8M0G7uMXh9Ty81Q904HpKUrM30ei7zfcL5jE7AXefgbOfMig==}
dev: true dev: true
@ -567,19 +596,33 @@ packages:
fsevents: 2.3.2 fsevents: 2.3.2
dev: true dev: true
/cliui/6.0.0:
resolution: {integrity: sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==}
dependencies:
string-width: 4.2.3
strip-ansi: 6.0.1
wrap-ansi: 6.2.0
dev: false
/color-convert/1.9.3: /color-convert/1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies: dependencies:
color-name: 1.1.3 color-name: 1.1.3
dev: true dev: true
/color-convert/2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
dependencies:
color-name: 1.1.4
dev: false
/color-name/1.1.3: /color-name/1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
dev: true dev: true
/color-name/1.1.4: /color-name/1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
dev: true
/convert-source-map/1.8.0: /convert-source-map/1.8.0:
resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==}
@ -613,6 +656,11 @@ packages:
ms: 2.1.2 ms: 2.1.2
dev: true dev: true
/decamelize/1.2.0:
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
engines: {node: '>=0.10.0'}
dev: false
/defined/1.0.0: /defined/1.0.0:
resolution: {integrity: sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==} resolution: {integrity: sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==}
dev: true dev: true
@ -639,6 +687,15 @@ packages:
resolution: {integrity: sha512-zoQJsXOUw0ZA0YxbjkmzBumAJRtr6je5JySuL/bAoFs0DuLiLJ+5FzRF7/ZayihxR2QcewlRZVm5QZdUhwjOgA==} resolution: {integrity: sha512-zoQJsXOUw0ZA0YxbjkmzBumAJRtr6je5JySuL/bAoFs0DuLiLJ+5FzRF7/ZayihxR2QcewlRZVm5QZdUhwjOgA==}
dev: true dev: true
/email-validator/2.0.4:
resolution: {integrity: sha512-gYCwo7kh5S3IDyZPLZf6hSS0MnZT8QmJFqYvbqlDZSbwdZlY6QZWxJ4i/6UhITOJ4XzyI647Bm2MXKCLqnJ4nQ==}
engines: {node: '>4.0'}
dev: false
/emoji-regex/8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
dev: false
/esbuild-android-64/0.14.54: /esbuild-android-64/0.14.54:
resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==} resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@ -882,6 +939,14 @@ packages:
to-regex-range: 5.0.1 to-regex-range: 5.0.1
dev: true dev: true
/find-up/4.1.0:
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
engines: {node: '>=8'}
dependencies:
locate-path: 5.0.0
path-exists: 4.0.0
dev: false
/fraction.js/4.2.0: /fraction.js/4.2.0:
resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==} resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==}
dev: true dev: true
@ -903,6 +968,11 @@ packages:
engines: {node: '>=6.9.0'} engines: {node: '>=6.9.0'}
dev: true dev: true
/get-caller-file/2.0.5:
resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
engines: {node: 6.* || 8.* || >= 10.*}
dev: false
/glob-parent/5.1.2: /glob-parent/5.1.2:
resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
@ -922,6 +992,17 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
dev: true dev: true
/gravatar/1.8.2:
resolution: {integrity: sha512-GdRwLM3oYpFQKy47MKuluw9hZ2gaCtiKPbDGdcDEuYDKlc8eNnW27KYL9LVbIDzEsx88WtDWQm2ClBcsgBnj6w==}
engines: {node: '>=10'}
hasBin: true
dependencies:
blueimp-md5: 2.19.0
email-validator: 2.0.4
querystring: 0.2.0
yargs: 15.4.1
dev: false
/has-flag/3.0.0: /has-flag/3.0.0:
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -968,6 +1049,11 @@ packages:
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: true dev: true
/is-fullwidth-code-point/3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
dev: false
/is-glob/4.0.3: /is-glob/4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -1000,6 +1086,13 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dev: true dev: true
/locate-path/5.0.0:
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
engines: {node: '>=8'}
dependencies:
p-locate: 4.1.0
dev: false
/loose-envify/1.4.0: /loose-envify/1.4.0:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true hasBin: true
@ -1064,6 +1157,30 @@ packages:
engines: {node: '>= 6'} engines: {node: '>= 6'}
dev: true dev: true
/p-limit/2.3.0:
resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
engines: {node: '>=6'}
dependencies:
p-try: 2.2.0
dev: false
/p-locate/4.1.0:
resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
engines: {node: '>=8'}
dependencies:
p-limit: 2.3.0
dev: false
/p-try/2.2.0:
resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
engines: {node: '>=6'}
dev: false
/path-exists/4.0.0:
resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
engines: {node: '>=8'}
dev: false
/path-parse/1.0.7: /path-parse/1.0.7:
resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
dev: true dev: true
@ -1152,6 +1269,12 @@ packages:
source-map-js: 1.0.2 source-map-js: 1.0.2
dev: true dev: true
/querystring/0.2.0:
resolution: {integrity: sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==}
engines: {node: '>=0.4.x'}
deprecated: The querystring API is considered Legacy. new code should use the URLSearchParams API instead.
dev: false
/queue-microtask/1.2.3: /queue-microtask/1.2.3:
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
dev: true dev: true
@ -1244,6 +1367,15 @@ packages:
resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==} resolution: {integrity: sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==}
dev: false dev: false
/require-directory/2.1.1:
resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
engines: {node: '>=0.10.0'}
dev: false
/require-main-filename/2.0.0:
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
dev: false
/resolve/1.22.1: /resolve/1.22.1:
resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==} resolution: {integrity: sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==}
hasBin: true hasBin: true
@ -1297,6 +1429,10 @@ packages:
hasBin: true hasBin: true
dev: true dev: true
/set-blocking/2.0.0:
resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==}
dev: false
/source-map-js/1.0.2: /source-map-js/1.0.2:
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -1306,6 +1442,22 @@ packages:
resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==}
dev: true dev: true
/string-width/4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
dependencies:
emoji-regex: 8.0.0
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
dev: false
/strip-ansi/6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
dependencies:
ansi-regex: 5.0.1
dev: false
/supports-color/5.5.0: /supports-color/5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'} engines: {node: '>=4'}
@ -1427,12 +1579,54 @@ packages:
fsevents: 2.3.2 fsevents: 2.3.2
dev: true dev: true
/which-module/2.0.0:
resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==}
dev: false
/wrap-ansi/6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
engines: {node: '>=8'}
dependencies:
ansi-styles: 4.3.0
string-width: 4.2.3
strip-ansi: 6.0.1
dev: false
/xtend/4.0.2: /xtend/4.0.2:
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
engines: {node: '>=0.4'} engines: {node: '>=0.4'}
dev: true dev: true
/y18n/4.0.3:
resolution: {integrity: sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==}
dev: false
/yaml/1.10.2: /yaml/1.10.2:
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
dev: true dev: true
/yargs-parser/18.1.3:
resolution: {integrity: sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==}
engines: {node: '>=6'}
dependencies:
camelcase: 5.3.1
decamelize: 1.2.0
dev: false
/yargs/15.4.1:
resolution: {integrity: sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==}
engines: {node: '>=8'}
dependencies:
cliui: 6.0.0
decamelize: 1.2.0
find-up: 4.1.0
get-caller-file: 2.0.5
require-directory: 2.1.1
require-main-filename: 2.0.0
set-blocking: 2.0.0
string-width: 4.2.3
which-module: 2.0.0
y18n: 4.0.3
yargs-parser: 18.1.3
dev: false

View File

@ -1,8 +1,7 @@
import logo from '@assets/images/logo.svg'; import logo from '@assets/images/logo.svg';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { useState } from 'react';
import { Cookies, withCookies, useCookies } from 'react-cookie'; import { Cookies, withCookies, useCookies } from 'react-cookie';
import { Navigate } from 'react-router-dom'; import Avatar from '@components/Avatar';
const getMeInfo = async () => { const getMeInfo = async () => {
const token = new Cookies().get('token'); const token = new Cookies().get('token');
@ -43,7 +42,7 @@ const AppHeader = () => {
<div className="right"> <div className="right">
<div className="flex items-center space-x-6"> <div className="flex items-center space-x-6">
<div className="rounded-full w-24 overflow-hidden"> <div className="rounded-full w-24 overflow-hidden">
<img src="https://randomuser.me/api/portraits/women/72.jpg" alt="avatar" /> {meInfo.data && <Avatar user={meInfo.data} />}
</div> </div>
<div className="app-header__user__name"> <div className="app-header__user__name">
<span className="text-white"> <span className="text-white">

View File

@ -0,0 +1,19 @@
import gravatar from 'gravatar';
import { useState } from 'react';
const Avatar = ({ user }: any) => {
const initials = user.firstName[0] + user.lastName[0];
const gravatarUrl = gravatar.url(user.email, { s: '64', r: 'x', d: '404' }, true);
const avatarUi = `https://ui-avatars.com/api/?name=${initials}&background=0D8ABC&color=fff&size=64`;
const [avatar, setAvatar] = useState(avatarUi);
fetch(gravatarUrl).then((response) => {
if (response.status === 200) {
setAvatar(gravatarUrl);
}
});
return <img src={avatar} alt="avatar" className={'rounded-full w-16 h-16'} />;
};
export default Avatar;

View File

@ -1,19 +1,20 @@
import { FaEllipsisH } from 'react-icons/fa'; import { FaEllipsisH } from 'react-icons/fa';
import Avatar from '@components/Avatar';
const Message = ({ text, user, date }: any) => { const Message = ({ text, user, date }: any) => {
const initials = user.firstName[0] + user.lastName[0];
return ( return (
<> <>
<div className="flex bg-grey-dark rounded-xl max-w-3xl p-5 gap-5"> <div className="flex bg-grey-dark rounded-xl max-w-3xl p-5 gap-5">
<div className="avatar rounded-full bg-red-light w-20 p-3 aspect-square h-fit"> {user && <Avatar user={user} />}
<span className="text-grey-dark text-xl">{initials}</span>
</div>
<div className="flex flex-col gap-2"> <div className="flex flex-col gap-2">
<div className="flex justify-between"> <div className="flex justify-between">
<div className="text-red-light text-xl username"> <div className="text-red-light text-xl username">
{user.firstName} {user.lastName} {user.firstName} {user.lastName}
</div> </div>
<div className="text-grey-light popup-btn text-2xl"><FaEllipsisH/></div> <div className="text-grey-light popup-btn text-2xl">
<FaEllipsisH />
</div>
</div> </div>
<div className="text-white message">{text}</div> <div className="text-white message">{text}</div>
<div className="text-grey-light date">{date}</div> <div className="text-grey-light date">{date}</div>
@ -21,6 +22,6 @@ const Message = ({ text, user, date }: any) => {
</div> </div>
</> </>
); );
} };
export default Message; export default Message;

View File

@ -5,6 +5,7 @@ const Home = () => {
const user = { const user = {
firstName: "Guillaume", firstName: "Guillaume",
lastName: "Dorce", lastName: "Dorce",
email: "guillaume.dorce@bm-services.com",
}; };
return ( return (