fusion_ok
This commit is contained in:
parent
6f21551956
commit
42c6bb6897
137
package-lock.json
generated
137
package-lock.json
generated
@ -14,10 +14,9 @@
|
|||||||
"@vitejs/plugin-vue": "^5.0.5",
|
"@vitejs/plugin-vue": "^5.0.5",
|
||||||
"html5-qrcode": "^2.3.8",
|
"html5-qrcode": "^2.3.8",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"vite": "^5.4.9",
|
"sweetalert2": "^11.14.5",
|
||||||
"vite-plugin-copy": "^0.1.6",
|
"vite-plugin-copy": "^0.1.6",
|
||||||
"vite-plugin-html": "^3.2.2",
|
"vite-plugin-html": "^3.2.2",
|
||||||
"vite-plugin-terminal": "^1.2.0",
|
|
||||||
"vite-plugin-wasm": "^3.3.0"
|
"vite-plugin-wasm": "^3.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -26,6 +25,7 @@
|
|||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"ts-loader": "^9.5.1",
|
"ts-loader": "^9.5.1",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
|
"vite": "^5.4.11",
|
||||||
"vite-plugin-static-copy": "^1.0.6",
|
"vite-plugin-static-copy": "^1.0.6",
|
||||||
"webpack": "^5.90.3",
|
"webpack": "^5.90.3",
|
||||||
"webpack-cli": "^5.1.4",
|
"webpack-cli": "^5.1.4",
|
||||||
@ -904,56 +904,6 @@
|
|||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@polka/url": {
|
|
||||||
"version": "1.0.0-next.28",
|
|
||||||
"resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz",
|
|
||||||
"integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/plugin-strip": {
|
|
||||||
"version": "3.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/plugin-strip/-/plugin-strip-3.0.4.tgz",
|
|
||||||
"integrity": "sha512-LDRV49ZaavxUo2YoKKMQjCxzCxugu1rCPQa0lDYBOWLj6vtzBMr8DcoJjsmg+s450RbKbe3qI9ZLaSO+O1oNbg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@rollup/pluginutils": "^5.0.1",
|
|
||||||
"estree-walker": "^2.0.2",
|
|
||||||
"magic-string": "^0.30.3"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.0.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"rollup": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/plugin-strip/node_modules/@rollup/pluginutils": {
|
|
||||||
"version": "5.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.2.tgz",
|
|
||||||
"integrity": "sha512-/FIdS3PyZ39bjZlwqFnWqCOVnW7o963LtKMwQOD0NhQqw22gSr2YY1afu3FxRip4ZCZNsD5jq6Aaz6QV3D/Njw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@types/estree": "^1.0.0",
|
|
||||||
"estree-walker": "^2.0.2",
|
|
||||||
"picomatch": "^2.3.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.0.0"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"rollup": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@rollup/pluginutils": {
|
"node_modules/@rollup/pluginutils": {
|
||||||
"version": "4.2.1",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz",
|
||||||
@ -4188,12 +4138,6 @@
|
|||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/kolorist": {
|
|
||||||
"version": "1.8.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz",
|
|
||||||
"integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/launch-editor": {
|
"node_modules/launch-editor": {
|
||||||
"version": "2.8.0",
|
"version": "2.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.8.0.tgz",
|
||||||
@ -4250,6 +4194,7 @@
|
|||||||
"version": "0.30.10",
|
"version": "0.30.10",
|
||||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
|
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
|
||||||
"integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
|
"integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
|
||||||
|
"peer": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||||
}
|
}
|
||||||
@ -4391,15 +4336,6 @@
|
|||||||
"node": ">=16 || 14 >=14.17"
|
"node": ">=16 || 14 >=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mrmime": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
@ -5512,20 +5448,6 @@
|
|||||||
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/sirv": {
|
|
||||||
"version": "2.0.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz",
|
|
||||||
"integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@polka/url": "^1.0.0-next.24",
|
|
||||||
"mrmime": "^2.0.0",
|
|
||||||
"totalist": "^3.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 10"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/slash": {
|
"node_modules/slash": {
|
||||||
"version": "5.1.0",
|
"version": "5.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz",
|
||||||
@ -5744,6 +5666,15 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/sweetalert2": {
|
||||||
|
"version": "11.14.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.14.5.tgz",
|
||||||
|
"integrity": "sha512-8MWk5uc/r6bWhiJWkUXyEuApfXAhSCZT8FFX7pZXL7YwaPxq+9Ynhi2dUzWkOFn9jvLjKj22CXuccZ+IHcnjvQ==",
|
||||||
|
"funding": {
|
||||||
|
"type": "individual",
|
||||||
|
"url": "https://github.com/sponsors/limonte"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tapable": {
|
"node_modules/tapable": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||||
@ -5904,15 +5835,6 @@
|
|||||||
"node": ">=0.6"
|
"node": ">=0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/totalist": {
|
|
||||||
"version": "3.0.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
|
|
||||||
"integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/tree-dump": {
|
"node_modules/tree-dump": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz",
|
||||||
@ -6071,12 +5993,6 @@
|
|||||||
"node": ">=14.17"
|
"node": ">=14.17"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ufo": {
|
|
||||||
"version": "1.5.4",
|
|
||||||
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
|
|
||||||
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/undici-types": {
|
"node_modules/undici-types": {
|
||||||
"version": "5.26.5",
|
"version": "5.26.5",
|
||||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
|
||||||
@ -6189,10 +6105,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "5.4.9",
|
"version": "5.4.11",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.9.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz",
|
||||||
"integrity": "sha512-20OVpJHh0PAM0oSOELa5GaZNWeDjcAvQjGXy2Uyr+Tp+/D2/Hdz6NLgpJLsarPTA2QJ6v8mX2P1ZfbsSKvdMkg==",
|
"integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.21.3",
|
"esbuild": "^0.21.3",
|
||||||
"postcss": "^8.4.43",
|
"postcss": "^8.4.43",
|
||||||
@ -6312,28 +6227,6 @@
|
|||||||
"node": ">=14.14"
|
"node": ">=14.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite-plugin-terminal": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/vite-plugin-terminal/-/vite-plugin-terminal-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-IIw1V+IySth8xlrGmH4U7YmfTp681vTzYpa7b8A3KNCJ2oW1BGPPwW8tSz6BQTvSgbRmrP/9NsBLsfXkN4e8sA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@rollup/plugin-strip": "^3.0.2",
|
|
||||||
"debug": "^4.3.4",
|
|
||||||
"kolorist": "^1.7.0",
|
|
||||||
"sirv": "^2.0.2",
|
|
||||||
"ufo": "^1.1.1"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14"
|
|
||||||
},
|
|
||||||
"funding": {
|
|
||||||
"url": "https://github.com/sponsors/patak-dev"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"vite": "^2.0.0||^3.0.0||^4.0.0||^5.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/vite-plugin-wasm": {
|
"node_modules/vite-plugin-wasm": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/vite-plugin-wasm/-/vite-plugin-wasm-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/vite-plugin-wasm/-/vite-plugin-wasm-3.3.0.tgz",
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"prettier": "^3.3.3",
|
"prettier": "^3.3.3",
|
||||||
"ts-loader": "^9.5.1",
|
"ts-loader": "^9.5.1",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
|
"vite": "^5.4.11",
|
||||||
"vite-plugin-static-copy": "^1.0.6",
|
"vite-plugin-static-copy": "^1.0.6",
|
||||||
"webpack": "^5.90.3",
|
"webpack": "^5.90.3",
|
||||||
"webpack-cli": "^5.1.4",
|
"webpack-cli": "^5.1.4",
|
||||||
@ -31,7 +32,7 @@
|
|||||||
"@vitejs/plugin-vue": "^5.0.5",
|
"@vitejs/plugin-vue": "^5.0.5",
|
||||||
"html5-qrcode": "^2.3.8",
|
"html5-qrcode": "^2.3.8",
|
||||||
"qrcode": "^1.5.3",
|
"qrcode": "^1.5.3",
|
||||||
"vite": "^5.4.9",
|
"sweetalert2": "^11.14.5",
|
||||||
"vite-plugin-copy": "^0.1.6",
|
"vite-plugin-copy": "^0.1.6",
|
||||||
"vite-plugin-html": "^3.2.2",
|
"vite-plugin-html": "^3.2.2",
|
||||||
"vite-plugin-wasm": "^3.3.0"
|
"vite-plugin-wasm": "^3.3.0"
|
||||||
|
1319
public/style/account.css
Normal file
1319
public/style/account.css
Normal file
File diff suppressed because it is too large
Load Diff
337
public/style/chat.css
Normal file
337
public/style/chat.css
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
/* Styles de base */
|
||||||
|
:root {
|
||||||
|
--primary-color: #3A506B;
|
||||||
|
/* Bleu métallique */
|
||||||
|
--secondary-color: #B0BEC5;
|
||||||
|
/* Gris acier */
|
||||||
|
--accent-color: #D68C45;
|
||||||
|
/* Cuivre */
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #e9edf1;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 4NK NAVBAR */
|
||||||
|
|
||||||
|
.brand-logo {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-wrapper {
|
||||||
|
position: fixed;
|
||||||
|
background: radial-gradient(circle, white, var(--primary-color));
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
color: #37474F;
|
||||||
|
height: 9vh;
|
||||||
|
width: 100vw;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
box-shadow: 0px 8px 10px -5px rgba(0, 0, 0, .2), 0px 16px 24px 2px rgba(0, 0, 0, .14), 0px 6px 30px 5px rgba(0, 0, 0, .12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Icônes de la barre de navigation */
|
||||||
|
.nav-right-icons {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-bell,
|
||||||
|
.burger-menu {
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
margin-right: 1rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-container {
|
||||||
|
position: relative;
|
||||||
|
/* Conserve la position pour le notification-board */
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-board {
|
||||||
|
position: absolute;
|
||||||
|
/* Position absolue pour le placer par rapport au container */
|
||||||
|
top: 40px;
|
||||||
|
right: 0;
|
||||||
|
background-color: white;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 10px;
|
||||||
|
width: 200px;
|
||||||
|
max-height: 300px;
|
||||||
|
overflow-y: auto;
|
||||||
|
/* Scroll si les notifications dépassent la taille */
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
z-index: 10;
|
||||||
|
/* Définit la priorité d'affichage au-dessus des autres éléments */
|
||||||
|
display: none;
|
||||||
|
/* Par défaut, la notification est masquée */
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-item{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notification-badge {
|
||||||
|
position: absolute;
|
||||||
|
top: -18px;
|
||||||
|
right: 35px;
|
||||||
|
background-color: red;
|
||||||
|
color: white;
|
||||||
|
border-radius: 50%;
|
||||||
|
padding: 4px 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
display: none;
|
||||||
|
/* S'affiche seulement lorsqu'il y a des notifications */
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Par défaut, le menu est masqué */
|
||||||
|
#menu {
|
||||||
|
display: none;
|
||||||
|
/* Menu caché par défaut */
|
||||||
|
transition: display 0.3s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.burger-menu {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Icône burger */
|
||||||
|
#burger-icon {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-content {
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 3.4rem;
|
||||||
|
right: 1rem;
|
||||||
|
background-color: white;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 5px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-content a {
|
||||||
|
display: block;
|
||||||
|
padding: 10px 20px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: #333;
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(26, 28, 24, .08);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-content a:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ajustement pour la barre de navigation fixe */
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
height: calc(100% - 4vh);
|
||||||
|
margin-top: 4vh;
|
||||||
|
margin-left: -1%;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Liste des groupes */
|
||||||
|
|
||||||
|
.group-list {
|
||||||
|
width: 25%;
|
||||||
|
background-color: #1f2c3d;
|
||||||
|
color: white;
|
||||||
|
padding: 20px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow-y: auto;
|
||||||
|
border-right: 2px solid #2c3e50;
|
||||||
|
flex-shrink: 0;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-list ul {
|
||||||
|
cursor: pointer;
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
padding-right: 10px;
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-list li {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #273646;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s, box-shadow 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.group-list li:hover {
|
||||||
|
background-color: #34495e;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Zone de chat */
|
||||||
|
.chat-area {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
||||||
|
margin: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-left: 0%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* En-tête du chat */
|
||||||
|
.chat-header {
|
||||||
|
background-color: #34495e;
|
||||||
|
color: white;
|
||||||
|
padding: 15px;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
border-radius: 10px 10px 0 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Messages */
|
||||||
|
.messages {
|
||||||
|
flex: 1;
|
||||||
|
padding: 20px;
|
||||||
|
overflow-y: auto;
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-container {
|
||||||
|
max-width: 100%;
|
||||||
|
border-radius: 5px;
|
||||||
|
overflow-wrap: break-word;
|
||||||
|
word-wrap: break-word;
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-container .message {
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-container .message.user {
|
||||||
|
align-self: flex-end;
|
||||||
|
margin-left: auto;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
padding: 12px 18px;
|
||||||
|
background-color: #e1e1e1;
|
||||||
|
border-radius: 15px;
|
||||||
|
max-width: 70%;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.4;
|
||||||
|
margin-bottom: 0%;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Messages de l'utilisateur */
|
||||||
|
.message.user {
|
||||||
|
background-color: #3498db;
|
||||||
|
color: white;
|
||||||
|
align-self: flex-end;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Amélioration de l'esthétique des messages */
|
||||||
|
/* .message.user:before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: -10px;
|
||||||
|
border: 10px solid transparent;
|
||||||
|
border-left-color: #3498db;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/* Zone de saisie */
|
||||||
|
.input-area {
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #bdc3c7;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
/* Alignement vertical */
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-area input[type="text"] {
|
||||||
|
flex: 1;
|
||||||
|
/* Prend l'espace restant */
|
||||||
|
padding: 10px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-area .attachment-icon {
|
||||||
|
margin: 0 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-area button {
|
||||||
|
padding: 10px;
|
||||||
|
margin-left: 10px;
|
||||||
|
background-color: #2980b9;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-area button:hover {
|
||||||
|
background-color: #1f608d;
|
||||||
|
}
|
||||||
|
|
||||||
|
#message-input {
|
||||||
|
width: 100%;
|
||||||
|
height: 50px;
|
||||||
|
resize: none;
|
||||||
|
padding: 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: auto;
|
||||||
|
max-width: 100%;
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsive */
|
||||||
|
@media screen and (max-width: 768px) {
|
||||||
|
.group-list {
|
||||||
|
display: none;
|
||||||
|
/* Masquer la liste des groupes sur les petits écrans */
|
||||||
|
}
|
||||||
|
|
||||||
|
.chat-area {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
1485
public/style/signature.css
Normal file
1485
public/style/signature.css
Normal file
File diff suppressed because it is too large
Load Diff
12
src/components/profile-header/profile-header.html
Normal file
12
src/components/profile-header/profile-header.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<div class="avatar-section">
|
||||||
|
<img src="https://via.placeholder.com/800x200" alt="Banner" class="banner-image">
|
||||||
|
<div class="banner-content">
|
||||||
|
<div class="avatar-container">
|
||||||
|
<img src="https://via.placeholder.com/150" alt="Avatar" class="avatar" onclick="window.openAvatarPopup()">
|
||||||
|
</div>
|
||||||
|
<div class="user-info">
|
||||||
|
<span class="user-name">John</span>
|
||||||
|
<span class="user-lastname">Doe</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
40
src/mocks/mock-chat/groupsMock.js
Normal file
40
src/mocks/mock-chat/groupsMock.js
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
export const groupsMock = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Group 🚀 ",
|
||||||
|
roles: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Role 1",
|
||||||
|
members: [{ id: 1, name: "Member 1" }, { id: 2, name: "Member 2" }]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Role 2",
|
||||||
|
members: [{ id: 3, name: "Member 3" }, { id: 4, name: "Member 4" }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Group ₿",
|
||||||
|
roles: [
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Role 1",
|
||||||
|
members: [{ id: 5, name: "Member 5" }, { id: 6, name: "Member 6" }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Group 🪙",
|
||||||
|
roles: [
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "Role 1",
|
||||||
|
members: [{ id: 7, name: "Member 7" }, { id: 8, name: "Member 8" }]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
65
src/mocks/mock-chat/messagesMock.js
Normal file
65
src/mocks/mock-chat/messagesMock.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
export const messagesMock = [
|
||||||
|
{
|
||||||
|
memberId: 1, // Conversations avec Mmber 1
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 1", text: "Salut !", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Bonjour ! Comment ça va ?", time: "10:31 AM" },
|
||||||
|
{ id: 3, sender: "4NK", text: "Tout va bien, merci !", time: "10:32 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 2, // Conversations avec Member 2
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 2", text: "Salut, on se voit ce soir ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Oui, à quelle heure ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 3, // Conversations avec Member 3
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 3", text: "Hey, ça va ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 4, // Conversations avec Member 4
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 4", text: "Hey, ça va ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" },
|
||||||
|
{ id: 3, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 5, // Conversations avec Member 5
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 5", text: "Hey, ça va ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" },
|
||||||
|
{ id: 3, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 6, // Conversations avec Member 6
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 6", text: "Hey, ça va ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" },
|
||||||
|
{ id: 3, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 7, // Conversations avec Member 7
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 7", text: "Hey, ça va ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" },
|
||||||
|
{ id: 3, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 8, // Conversations avec Member 8
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 8", text: "Hey, ça va ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" },
|
||||||
|
{ id: 3, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
];
|
264
src/mocks/mock-signature/groupsMock.js
Normal file
264
src/mocks/mock-signature/groupsMock.js
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
// Définir les rôles autorisés
|
||||||
|
const VALID_ROLES = [
|
||||||
|
"User",
|
||||||
|
"Process",
|
||||||
|
"Member",
|
||||||
|
"Peer",
|
||||||
|
"Payment",
|
||||||
|
"Deposit",
|
||||||
|
"Artefact",
|
||||||
|
"Resolve",
|
||||||
|
"Backup"
|
||||||
|
];
|
||||||
|
|
||||||
|
const VISIBILITY_LEVELS = {
|
||||||
|
PUBLIC: "public",
|
||||||
|
CONFIDENTIAL: "confidential",
|
||||||
|
PRIVATE: "private",
|
||||||
|
};
|
||||||
|
|
||||||
|
const DOCUMENT_STATUS = {
|
||||||
|
DRAFT: "draft",
|
||||||
|
PENDING: "pending",
|
||||||
|
IN_REVIEW: "in_review",
|
||||||
|
APPROVED: "approved",
|
||||||
|
REJECTED: "rejected",
|
||||||
|
EXPIRED: "expired"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Fonction pour créer un rôle
|
||||||
|
function createRole(name, members) {
|
||||||
|
if (!VALID_ROLES.includes(name)) {
|
||||||
|
throw new Error(`Role "${name}" is not valid.`);
|
||||||
|
}
|
||||||
|
return { name, members };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const groupsMock = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Processus 1",
|
||||||
|
description: "Description du processus 1",
|
||||||
|
roles: [
|
||||||
|
{
|
||||||
|
name: "User",
|
||||||
|
members: [{ id: 1, name: "Alice" }, { id: 2, name: "Bob" }],
|
||||||
|
documents: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "Document User A",
|
||||||
|
description: "Description du document User A.",
|
||||||
|
visibility: "public",
|
||||||
|
createdAt: "2024-01-01",
|
||||||
|
deadline: "2024-02-01",
|
||||||
|
signatures: [
|
||||||
|
{
|
||||||
|
member: { id: 1, name: "Alice" },
|
||||||
|
signed: true,
|
||||||
|
signedAt: "2024-01-15"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
member: { id: 2, name: "Bob" },
|
||||||
|
signed: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Document User B",
|
||||||
|
description: "Document vierge pour le rôle User",
|
||||||
|
visibility: "confidential",
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
name: "Document User C",
|
||||||
|
description: "Document vierge pour validation utilisateur",
|
||||||
|
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||||
|
status: DOCUMENT_STATUS.DRAFT,
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 8,
|
||||||
|
name: "Document User D",
|
||||||
|
description: "Document vierge pour approbation utilisateur",
|
||||||
|
visibility: VISIBILITY_LEVELS.PUBLIC,
|
||||||
|
status: DOCUMENT_STATUS.DRAFT,
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Process",
|
||||||
|
members: [{ id: 3, name: "Charlie" }, { id: 4, name: "David" }],
|
||||||
|
documents: [
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Document Process A",
|
||||||
|
description: "Description du document Process A.",
|
||||||
|
visibility: "confidential",
|
||||||
|
createdAt: "2024-01-10",
|
||||||
|
deadline: "2024-03-01",
|
||||||
|
signatures: [
|
||||||
|
{
|
||||||
|
member: { id: 3, name: "Charlie" },
|
||||||
|
signed: true,
|
||||||
|
signedAt: "2024-01-12"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 9,
|
||||||
|
name: "Document Process B",
|
||||||
|
description: "Document vierge pour processus interne",
|
||||||
|
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||||
|
status: DOCUMENT_STATUS.DRAFT,
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 10,
|
||||||
|
name: "Document Process C",
|
||||||
|
description: "Document vierge pour validation processus",
|
||||||
|
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||||
|
status: DOCUMENT_STATUS.DRAFT,
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Backup",
|
||||||
|
members: [{ id: 15, name: "Oscar" }, { id: 16, name: "Patricia" }],
|
||||||
|
documents: [
|
||||||
|
{
|
||||||
|
id: 11,
|
||||||
|
name: "Document Backup A",
|
||||||
|
description: "Document vierge pour sauvegarde",
|
||||||
|
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||||
|
status: DOCUMENT_STATUS.DRAFT,
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "Processus 2",
|
||||||
|
description: "Description du processus 2",
|
||||||
|
roles: [
|
||||||
|
{
|
||||||
|
name: "Artefact",
|
||||||
|
members: [{ id: 17, name: "Quinn" }, { id: 18, name: "Rachel" }],
|
||||||
|
documents: [
|
||||||
|
{
|
||||||
|
id: 12,
|
||||||
|
name: "Document Artefact A",
|
||||||
|
description: "Document vierge pour artefact",
|
||||||
|
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||||
|
status: DOCUMENT_STATUS.DRAFT,
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 13,
|
||||||
|
name: "Document Artefact B",
|
||||||
|
description: "Document vierge pour validation artefact",
|
||||||
|
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||||
|
status: DOCUMENT_STATUS.DRAFT,
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Resolve",
|
||||||
|
members: [{ id: 19, name: "Sam" }, { id: 20, name: "Tom" }],
|
||||||
|
documents: [
|
||||||
|
{
|
||||||
|
id: 14,
|
||||||
|
name: "Document Resolve A",
|
||||||
|
description: "Document vierge pour résolution",
|
||||||
|
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||||
|
status: DOCUMENT_STATUS.DRAFT,
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "Processus 3",
|
||||||
|
description: "Description du processus 3",
|
||||||
|
roles: [
|
||||||
|
{
|
||||||
|
name: "Deposit",
|
||||||
|
members: [{ id: 21, name: "Uma" }, { id: 22, name: "Victor" }],
|
||||||
|
documents: [
|
||||||
|
{
|
||||||
|
id: 15,
|
||||||
|
name: "Document Deposit A",
|
||||||
|
description: "Document vierge pour dépôt",
|
||||||
|
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||||
|
status: DOCUMENT_STATUS.DRAFT,
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 16,
|
||||||
|
name: "Document Deposit B",
|
||||||
|
description: "Document vierge pour validation dépôt",
|
||||||
|
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||||
|
status: DOCUMENT_STATUS.DRAFT,
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Payment",
|
||||||
|
members: [{ id: 23, name: "Walter" }, { id: 24, name: "Xena" }],
|
||||||
|
documents: [
|
||||||
|
{
|
||||||
|
id: 17,
|
||||||
|
name: "Document Payment B",
|
||||||
|
description: "Document vierge pour paiement",
|
||||||
|
visibility: VISIBILITY_LEVELS.PRIVATE,
|
||||||
|
status: DOCUMENT_STATUS.DRAFT,
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 18,
|
||||||
|
name: "Document Payment C",
|
||||||
|
description: "Document vierge pour validation paiement",
|
||||||
|
visibility: VISIBILITY_LEVELS.CONFIDENTIAL,
|
||||||
|
status: DOCUMENT_STATUS.DRAFT,
|
||||||
|
createdAt: null,
|
||||||
|
deadline: null,
|
||||||
|
signatures: []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
186
src/mocks/mock-signature/membersMocks.js
Normal file
186
src/mocks/mock-signature/membersMocks.js
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
// Définir les rôles autorisés
|
||||||
|
const VALID_ROLES = [
|
||||||
|
"User",
|
||||||
|
"Process",
|
||||||
|
"Member",
|
||||||
|
"Peer",
|
||||||
|
"Payment",
|
||||||
|
"Deposit",
|
||||||
|
"Artefact",
|
||||||
|
"Resolve",
|
||||||
|
"Backup"
|
||||||
|
];
|
||||||
|
|
||||||
|
function createProcessRole(processId, roleName) {
|
||||||
|
if (!VALID_ROLES.includes(roleName)) {
|
||||||
|
throw new Error(`Role "${roleName}" is not valid.`);
|
||||||
|
}
|
||||||
|
return { processId, role: roleName };
|
||||||
|
}
|
||||||
|
|
||||||
|
export const membersMock = [
|
||||||
|
{
|
||||||
|
id: "USR-001",
|
||||||
|
name: "Alice Johnson",
|
||||||
|
avatar: "AJ",
|
||||||
|
email: "alice.j@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-001", "User"),
|
||||||
|
createProcessRole("PROC-002", "Process"),
|
||||||
|
createProcessRole("PROC-003", "Member")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-002",
|
||||||
|
name: "Bob Smith",
|
||||||
|
avatar: "BS",
|
||||||
|
email: "bob.s@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-001", "Process"),
|
||||||
|
createProcessRole("PROC-004", "Payment")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-003",
|
||||||
|
name: "Charlie Davis",
|
||||||
|
avatar: "CD",
|
||||||
|
email: "charlie.d@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-002", "Peer"),
|
||||||
|
createProcessRole("PROC-003", "Deposit"),
|
||||||
|
createProcessRole("PROC-005", "User")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-004",
|
||||||
|
name: "David Wilson",
|
||||||
|
avatar: "DW",
|
||||||
|
email: "david.w@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-001", "Artefact"),
|
||||||
|
createProcessRole("PROC-004", "Resolve"),
|
||||||
|
createProcessRole("PROC-006", "Process")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-005",
|
||||||
|
name: "Eve Brown",
|
||||||
|
avatar: "EB",
|
||||||
|
email: "eve.b@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-002", "Backup"),
|
||||||
|
createProcessRole("PROC-003", "User"),
|
||||||
|
createProcessRole("PROC-007", "Payment")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-006",
|
||||||
|
name: "Frank Miller",
|
||||||
|
avatar: "FM",
|
||||||
|
email: "frank.m@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-001", "Member"),
|
||||||
|
createProcessRole("PROC-004", "Process"),
|
||||||
|
createProcessRole("PROC-008", "Peer")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-007",
|
||||||
|
name: "Grace Taylor",
|
||||||
|
avatar: "GT",
|
||||||
|
email: "grace.t@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-005", "Deposit"),
|
||||||
|
createProcessRole("PROC-006", "Artefact"),
|
||||||
|
createProcessRole("PROC-007", "Resolve")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-008",
|
||||||
|
name: "Henry Clark",
|
||||||
|
avatar: "HC",
|
||||||
|
email: "henry.c@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-002", "User"),
|
||||||
|
createProcessRole("PROC-005", "Backup"),
|
||||||
|
createProcessRole("PROC-008", "Member")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-009",
|
||||||
|
name: "Ivy Chen",
|
||||||
|
avatar: "IC",
|
||||||
|
email: "ivy.c@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-003", "Process"),
|
||||||
|
createProcessRole("PROC-006", "Payment"),
|
||||||
|
createProcessRole("PROC-009", "Peer")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-010",
|
||||||
|
name: "Jack White",
|
||||||
|
avatar: "JW",
|
||||||
|
email: "jack.w@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-004", "Deposit"),
|
||||||
|
createProcessRole("PROC-007", "Artefact"),
|
||||||
|
createProcessRole("PROC-010", "Resolve")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-011",
|
||||||
|
name: "Kelly Brown",
|
||||||
|
avatar: "KB",
|
||||||
|
email: "kelly.b@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-001", "Backup"),
|
||||||
|
createProcessRole("PROC-008", "User"),
|
||||||
|
createProcessRole("PROC-009", "Process")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-012",
|
||||||
|
name: "Liam Jones",
|
||||||
|
avatar: "LJ",
|
||||||
|
email: "liam.j@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-002", "Member"),
|
||||||
|
createProcessRole("PROC-009", "Payment"),
|
||||||
|
createProcessRole("PROC-010", "Deposit")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-013",
|
||||||
|
name: "Mia Wilson",
|
||||||
|
avatar: "MW",
|
||||||
|
email: "mia.w@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-003", "Peer"),
|
||||||
|
createProcessRole("PROC-005", "Artefact"),
|
||||||
|
createProcessRole("PROC-010", "Backup")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-014",
|
||||||
|
name: "Noah Martin",
|
||||||
|
avatar: "NM",
|
||||||
|
email: "noah.m@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-004", "Resolve"),
|
||||||
|
createProcessRole("PROC-006", "User"),
|
||||||
|
createProcessRole("PROC-008", "Process")
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "USR-015",
|
||||||
|
name: "Olivia Moore",
|
||||||
|
avatar: "OM",
|
||||||
|
email: "olivia.m@company.com",
|
||||||
|
processRoles: [
|
||||||
|
createProcessRole("PROC-005", "Member"),
|
||||||
|
createProcessRole("PROC-007", "Peer"),
|
||||||
|
createProcessRole("PROC-009", "Deposit")
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
65
src/mocks/mock-signature/messagesMock.ts
Normal file
65
src/mocks/mock-signature/messagesMock.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
export const messagesMock = [
|
||||||
|
{
|
||||||
|
memberId: 1, // Conversations avec Mmber 1
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Mmeber 1", text: "Salut !", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Bonjour ! Comment ça va ?", time: "10:31 AM" },
|
||||||
|
{ id: 3, sender: "4NK", text: "Tout va bien, merci !", time: "10:32 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 2, // Conversations avec Member 2
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 2", text: "Salut, on se voit ce soir ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Oui, à quelle heure ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 3, // Conversations avec Member 3
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 3", text: "Hey, ça va ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 4, // Conversations avec Member 4
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 4", text: "Hey, ça va ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" },
|
||||||
|
{ id: 3, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 5, // Conversations avec Member 5
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 5", text: "Hey, ça va ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" },
|
||||||
|
{ id: 3, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 6, // Conversations avec Member 6
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 6", text: "Hey, ça va ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" },
|
||||||
|
{ id: 3, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 7, // Conversations avec Member 7
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 7", text: "Hey, ça va ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" },
|
||||||
|
{ id: 3, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
memberId: 8, // Conversations avec Member 8
|
||||||
|
messages: [
|
||||||
|
{ id: 1, sender: "Member 8", text: "Hey, ça va ?", time: "10:30 AM" },
|
||||||
|
{ id: 2, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" },
|
||||||
|
{ id: 3, sender: "4NK", text: "Ça va et toi ?", time: "10:31 AM" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
];
|
58
src/models/signature.models.ts
Normal file
58
src/models/signature.models.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
export interface Group {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
roles: {
|
||||||
|
id?: number;
|
||||||
|
name: string;
|
||||||
|
members: { id: string | number; name: string; }[];
|
||||||
|
documents?: {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
description?: string;
|
||||||
|
visibility: string;
|
||||||
|
createdAt: string | null;
|
||||||
|
deadline: string | null;
|
||||||
|
signatures: DocumentSignature[];
|
||||||
|
status?: string;
|
||||||
|
}[];
|
||||||
|
}[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Message {
|
||||||
|
id: number;
|
||||||
|
sender: string;
|
||||||
|
text?: string;
|
||||||
|
time: string;
|
||||||
|
type: 'text' | 'file';
|
||||||
|
fileName?: string;
|
||||||
|
fileData?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MemberMessages {
|
||||||
|
memberId: string;
|
||||||
|
messages: Message[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DocumentSignature {
|
||||||
|
signed: boolean;
|
||||||
|
member: {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
signedAt?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RequestParams {
|
||||||
|
processId: number;
|
||||||
|
processName: string;
|
||||||
|
roleId: number;
|
||||||
|
roleName: string;
|
||||||
|
documentId: number;
|
||||||
|
documentName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Notification {
|
||||||
|
memberId: string;
|
||||||
|
text: string;
|
||||||
|
time: string;
|
||||||
|
}
|
91
src/pages/account/account.html
Normal file
91
src/pages/account/account.html
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Account</title>
|
||||||
|
<link rel="stylesheet" href="../../public/style/account.css">
|
||||||
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<!-- Header Container -->
|
||||||
|
<div id="header-container"></div>
|
||||||
|
|
||||||
|
<!-- Profile Popup -->
|
||||||
|
<div id="avatar-popup" class="popup">
|
||||||
|
<div class="popup-content">
|
||||||
|
<span class="close-popup">×</span>
|
||||||
|
<h2>Profile</h2>
|
||||||
|
|
||||||
|
<!-- Banner Preview Section -->
|
||||||
|
<div class="banner-preview">
|
||||||
|
<div class="banner-image-container">
|
||||||
|
<img src="https://via.placeholder.com/800x200" alt="Banner" class="banner-image" id="popup-banner-img">
|
||||||
|
<div class="banner-content">
|
||||||
|
<div class="avatar-container">
|
||||||
|
<img src="https://via.placeholder.com/150" alt="Avatar" class="avatar" id="popup-avatar-img">
|
||||||
|
</div>
|
||||||
|
<div class="user-info">
|
||||||
|
<span class="editable" id="popup-name"></span>
|
||||||
|
<span class="editable" id="popup-lastname"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="banner-controls">
|
||||||
|
<label for="banner-upload" class="banner-upload-label button-style">
|
||||||
|
Change Banner Image
|
||||||
|
<input type="file" id="banner-upload" accept="image/*" style="display: none;">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Avatar Upload Section -->
|
||||||
|
<div class="popup-avatar">
|
||||||
|
<label for="avatar-upload" class="avatar-upload-label">
|
||||||
|
<img src="https://via.placeholder.com/150" alt="Avatar" class="avatar" id="popup-avatar-img">
|
||||||
|
<div class="avatar-overlay">
|
||||||
|
<span>Change Avatar</span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<input type="file" id="avatar-upload" accept="image/*" style="display: none;">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- User Info Section -->
|
||||||
|
<div class="popup-info">
|
||||||
|
<p><strong>Name:</strong> <span class="editable" id="popup-name"></span></p>
|
||||||
|
<p><strong>Last Name:</strong> <span class="editable" id="popup-lastname"></span></p>
|
||||||
|
<p><strong>Address:</strong> 🏠 🌍 🗽🎊😩-🎊😑🎄😩</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Buttons Container -->
|
||||||
|
<div class="popup-buttons">
|
||||||
|
<button class="delete-account-btn" onclick="confirmDeleteAccount()">Delete Account</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Main Content -->
|
||||||
|
<div class="container">
|
||||||
|
<!-- Parameter List -->
|
||||||
|
<div class="parameter-list">
|
||||||
|
<ul class="parameter-list-ul" onclick="window.showPairing()">Pairing 🔗</ul>
|
||||||
|
<ul class="parameter-list-ul" onclick="window.showWallet()">Wallet 👛</ul>
|
||||||
|
<ul class="parameter-list-ul" onclick="window.showProcess()">Process ⚙️</ul>
|
||||||
|
<ul class="parameter-list-ul" onclick="window.showData()">Data 💾</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Parameter Area -->
|
||||||
|
<div class="parameter-area">
|
||||||
|
<div class="content-container">
|
||||||
|
<div id="pairing-content"></div>
|
||||||
|
<div id="wallet-content"></div>
|
||||||
|
<div id="process-content"></div>
|
||||||
|
<div id="data-content"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Scripts -->
|
||||||
|
<script type="module" src="./account.ts?ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
1893
src/pages/account/account.ts
Normal file
1893
src/pages/account/account.ts
Normal file
File diff suppressed because it is too large
Load Diff
53
src/pages/chat/chat.html
Normal file
53
src/pages/chat/chat.html
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Messagerie</title>
|
||||||
|
<link rel="stylesheet" href="../../public/style/chat.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- Main content-->
|
||||||
|
<div class="container">
|
||||||
|
<!-- List of groups -->
|
||||||
|
<div class="group-list">
|
||||||
|
<ul id="group-list">
|
||||||
|
<!-- Groups will be added here dynamically -->
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Chat area -->
|
||||||
|
<div class="chat-area">
|
||||||
|
<div class="chat-header" id="chat-header">
|
||||||
|
<!-- Chat title -->
|
||||||
|
</div>
|
||||||
|
<div class="messages" id="messages">
|
||||||
|
<!-- Messages -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Input area -->
|
||||||
|
<div class="input-area">
|
||||||
|
<label for="file-input" class="attachment-icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
d="M13.514 2.444l-10.815 10.785c-.449.449-.678 1.074-.625 1.707l.393 4.696c.041.479.422.86.9.9l4.697.394c.633.053 1.258-.177 1.707-.626l11.875-11.844c.196-.196.195-.512 0-.707l-3.536-3.536c-.195-.195-.511-.196-.707 0l-8.878 8.848c-.162.162-.253.382-.253.611v.725c0 .184.148.332.332.332h.725c.229 0 .448-.092.61-.254l7.11-7.08 1.415 1.415-7.386 7.354c-.375.375-.885.586-1.414.586h-2.414c-.555 0-1-.448-1-1v-2.414c0-.53.211-1.039.586-1.414l9.506-9.477c.781-.781 2.049-.781 2.829-.001l4.243 4.243c.391.391.586.902.586 1.414 0 .512-.196 1.025-.587 1.416l-12.35 12.319c-.748.747-1.76 1.164-2.81 1.164-.257 0-6.243-.467-6.499-.487-.664-.052-1.212-.574-1.268-1.267-.019-.242-.486-6.246-.486-6.499 0-1.05.416-2.062 1.164-2.811l10.936-10.936 1.414 1.444z" />
|
||||||
|
</svg>
|
||||||
|
</label>
|
||||||
|
<input type="file" id="file-input" style="display: none;" />
|
||||||
|
|
||||||
|
<textarea id="message-input" rows="3" placeholder="Type your message..."></textarea>
|
||||||
|
|
||||||
|
|
||||||
|
<button id="send-button">Send</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<script type="module" src="./chat.ts?ts"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
373
src/pages/chat/chat.ts
Normal file
373
src/pages/chat/chat.ts
Normal file
@ -0,0 +1,373 @@
|
|||||||
|
import { groupsMock } from '../../mocks/mock-signature/groupsMock.js';
|
||||||
|
import { messageStore } from '../../utils/messageMock.js';
|
||||||
|
|
||||||
|
let messagesMock = messageStore.getMessages();
|
||||||
|
|
||||||
|
let selectedMemberId: number | null = null;
|
||||||
|
|
||||||
|
// Load the list of groups
|
||||||
|
function loadGroupList() {
|
||||||
|
const groupList = document.getElementById('group-list');
|
||||||
|
if (!groupList) return;
|
||||||
|
|
||||||
|
groupsMock.forEach(group => {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.textContent = group.name;
|
||||||
|
li.onclick = (event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
toggleRoles(group, li);
|
||||||
|
};
|
||||||
|
groupList.appendChild(li);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle the list of Roles
|
||||||
|
function toggleRoles(group: { roles: { name: string; members: any[] }[] }, groupElement: HTMLElement) {
|
||||||
|
let roleList = groupElement.querySelector('.role-list') as HTMLElement;
|
||||||
|
if (roleList) {
|
||||||
|
roleList.style.display = roleList.style.display === 'none' ? 'block' : 'none';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
roleList = document.createElement('ul');
|
||||||
|
roleList.className = 'role-list';
|
||||||
|
|
||||||
|
group.roles.forEach(role => {
|
||||||
|
const roleItem = document.createElement('li');
|
||||||
|
roleItem.textContent = role.name;
|
||||||
|
|
||||||
|
roleItem.onclick = (event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
toggleMembers(role, roleItem);
|
||||||
|
};
|
||||||
|
|
||||||
|
roleList.appendChild(roleItem);
|
||||||
|
});
|
||||||
|
|
||||||
|
groupElement.appendChild(roleList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle the list of membres
|
||||||
|
function toggleMembers(role: { members: { id: number; name: string; }[] }, roleElement: HTMLElement) {
|
||||||
|
let memberList = roleElement.querySelector('.member-list') as HTMLElement;
|
||||||
|
if (memberList) {
|
||||||
|
memberList.style.display = memberList.style.display === 'none' ? 'block' : 'none';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memberList = document.createElement('ul');
|
||||||
|
memberList.className = 'member-list';
|
||||||
|
|
||||||
|
role.members.forEach(member => {
|
||||||
|
const memberItem = document.createElement('li');
|
||||||
|
memberItem.textContent = member.name;
|
||||||
|
|
||||||
|
memberItem.onclick = (event) => {
|
||||||
|
event.stopPropagation();
|
||||||
|
loadMemberChat(member.id);
|
||||||
|
};
|
||||||
|
|
||||||
|
memberList.appendChild(memberItem);
|
||||||
|
});
|
||||||
|
|
||||||
|
roleElement.appendChild(memberList);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load the list of members
|
||||||
|
function loadMemberChat(memberId: string | number) {
|
||||||
|
selectedMemberId = Number(memberId);
|
||||||
|
const memberMessages = messagesMock.find(m => String(m.memberId) === String(memberId));
|
||||||
|
|
||||||
|
// Trouver le processus et le rôle du membre
|
||||||
|
let memberInfo = { processName: '', roleName: '', memberName: '' };
|
||||||
|
groupsMock.forEach(process => {
|
||||||
|
process.roles.forEach(role => {
|
||||||
|
const member = role.members.find(m => String(m.id) === String(memberId));
|
||||||
|
if (member) {
|
||||||
|
memberInfo = {
|
||||||
|
processName: process.name,
|
||||||
|
roleName: role.name,
|
||||||
|
memberName: member.name
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const chatHeader = document.getElementById('chat-header');
|
||||||
|
const messagesContainer = document.getElementById('messages');
|
||||||
|
|
||||||
|
if (!chatHeader || !messagesContainer) return;
|
||||||
|
|
||||||
|
chatHeader.textContent = `Chat with ${memberInfo.roleName} ${memberInfo.memberName} from ${memberInfo.processName}`;
|
||||||
|
messagesContainer.innerHTML = '';
|
||||||
|
|
||||||
|
if (memberMessages) {
|
||||||
|
memberMessages.messages.forEach((message: {
|
||||||
|
type: string;
|
||||||
|
fileData?: string;
|
||||||
|
fileName?: string;
|
||||||
|
sender: string;
|
||||||
|
text?: string;
|
||||||
|
time: string;
|
||||||
|
}) => {
|
||||||
|
const messageElement = document.createElement('div');
|
||||||
|
messageElement.className = 'message-container';
|
||||||
|
|
||||||
|
const messageContent = document.createElement('div');
|
||||||
|
messageContent.className = 'message';
|
||||||
|
if (message.type === 'file') {
|
||||||
|
messageContent.innerHTML = `<a href="${message.fileData}" download="${message.fileName}" target="_blank">${message.fileName}</a>`;
|
||||||
|
messageContent.classList.add('user');
|
||||||
|
} else {
|
||||||
|
messageContent.innerHTML = `<strong>${message.sender}</strong>: ${message.text} <span style="float: right;">${message.time}</span>`;
|
||||||
|
if (message.sender === "4NK") {
|
||||||
|
messageContent.classList.add('user');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
messageElement.appendChild(messageContent);
|
||||||
|
messagesContainer.appendChild(messageElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
scrollToBottom(messagesContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scroll down the conversation after loading messages
|
||||||
|
function scrollToBottom(container: HTMLElement) {
|
||||||
|
container.scrollTop = container.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate an automatic response
|
||||||
|
function generateAutoReply(senderName: string) {
|
||||||
|
return {
|
||||||
|
id: Date.now(),
|
||||||
|
sender: senderName,
|
||||||
|
text: "OK...",
|
||||||
|
time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
|
||||||
|
type: 'text'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a messsage
|
||||||
|
function sendMessage() {
|
||||||
|
const messageInput = document.getElementById('message-input') as HTMLInputElement;
|
||||||
|
if (!messageInput) return;
|
||||||
|
const messageText = messageInput.value.trim();
|
||||||
|
|
||||||
|
if (messageText === '' || selectedMemberId === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newMessage = {
|
||||||
|
id: Date.now(),
|
||||||
|
sender: "4NK",
|
||||||
|
text: messageText,
|
||||||
|
time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
|
||||||
|
type: 'text'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Ajouter et afficher le message immédiatement
|
||||||
|
messageStore.addMessage(selectedMemberId, newMessage);
|
||||||
|
messagesMock = messageStore.getMessages();
|
||||||
|
loadMemberChat(selectedMemberId);
|
||||||
|
|
||||||
|
// Réinitialiser l'input
|
||||||
|
messageInput.value = '';
|
||||||
|
|
||||||
|
// Réponse automatique après 2 secondes
|
||||||
|
setTimeout(() => {
|
||||||
|
if (selectedMemberId === null) return;
|
||||||
|
|
||||||
|
const autoReply = generateAutoReply(`Member ${selectedMemberId}`);
|
||||||
|
messageStore.addMessage(selectedMemberId, autoReply);
|
||||||
|
messagesMock = messageStore.getMessages();
|
||||||
|
loadMemberChat(selectedMemberId);
|
||||||
|
addNotification(selectedMemberId, autoReply);
|
||||||
|
}, 2000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an event for the submit button
|
||||||
|
const sendBtn = document.getElementById('send-button');
|
||||||
|
const messageInput = document.getElementById('message-input');
|
||||||
|
|
||||||
|
if (sendBtn) sendBtn.onclick = sendMessage;
|
||||||
|
if (messageInput) {
|
||||||
|
messageInput.addEventListener('keydown', function (event) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
sendMessage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send a file
|
||||||
|
function sendFile(file: File) {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onloadend = function () {
|
||||||
|
const fileData = reader.result;
|
||||||
|
const fileName = file.name;
|
||||||
|
|
||||||
|
const newFileMessage = {
|
||||||
|
id: Date.now(),
|
||||||
|
sender: "4NK",
|
||||||
|
fileName: fileName,
|
||||||
|
fileData: fileData,
|
||||||
|
time: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
|
||||||
|
type: 'file'
|
||||||
|
};
|
||||||
|
|
||||||
|
if (selectedMemberId === null) return;
|
||||||
|
messageStore.addMessage(selectedMemberId, newFileMessage);
|
||||||
|
|
||||||
|
messagesMock = messageStore.getMessages();
|
||||||
|
|
||||||
|
if (selectedMemberId !== null) {
|
||||||
|
loadMemberChat(selectedMemberId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Managing the sent file
|
||||||
|
document.getElementById('file-input')?.addEventListener('change', function (event: Event) {
|
||||||
|
const file = (event.target as HTMLInputElement).files?.[0];
|
||||||
|
if (file) {
|
||||||
|
sendFile(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////// Notification module /////////////////////
|
||||||
|
const notificationBadge = document.querySelector('.notification-badge') as HTMLElement;
|
||||||
|
const notificationBoard = document.getElementById('notification-board');
|
||||||
|
const notificationBell = document.getElementById('notification-bell');
|
||||||
|
|
||||||
|
interface Notification {
|
||||||
|
memberId: number;
|
||||||
|
text: string;
|
||||||
|
time: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let notifications: Notification[] = [];
|
||||||
|
let unreadCount = 0;
|
||||||
|
// Update notification badge
|
||||||
|
function updateNotificationBadge() {
|
||||||
|
if (!notificationBadge) return;
|
||||||
|
const count = notifications.length;
|
||||||
|
notificationBadge.textContent = count > 99 ? '+99' : count.toString();
|
||||||
|
notificationBadge.style.display = count > 0 ? 'block' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add notification
|
||||||
|
function addNotification(memberId: number, message: { text: string; time: string }) {
|
||||||
|
// Creating a new notification
|
||||||
|
const notification = {
|
||||||
|
memberId,
|
||||||
|
text: `New message from Member ${memberId}: ${message.text}`,
|
||||||
|
time: message.time
|
||||||
|
};
|
||||||
|
|
||||||
|
// Added notification to list and interface
|
||||||
|
notifications.push(notification);
|
||||||
|
renderNotifications();
|
||||||
|
updateNotificationBadge();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show notifications
|
||||||
|
function renderNotifications() {
|
||||||
|
if (!notificationBoard) return;
|
||||||
|
|
||||||
|
// Reset the interface
|
||||||
|
notificationBoard.innerHTML = '';
|
||||||
|
|
||||||
|
// Displays "No notifications available" if there are no notifications
|
||||||
|
if (notifications.length === 0) {
|
||||||
|
notificationBoard.innerHTML = '<div class="no-notification">No notifications available</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add each notification to the list
|
||||||
|
notifications.forEach((notif, index) => {
|
||||||
|
const notifElement = document.createElement('div');
|
||||||
|
notifElement.className = 'notification-item';
|
||||||
|
notifElement.textContent = `${notif.text} at ${notif.time}`;
|
||||||
|
notifElement.onclick = () => {
|
||||||
|
loadMemberChat(notif.memberId);
|
||||||
|
removeNotification(index);
|
||||||
|
};
|
||||||
|
notificationBoard.appendChild(notifElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete a notification
|
||||||
|
function removeNotification(index: number) {
|
||||||
|
notifications.splice(index, 1);
|
||||||
|
renderNotifications();
|
||||||
|
updateNotificationBadge();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds an event for deploying the notification list
|
||||||
|
if (notificationBell && notificationBoard) {
|
||||||
|
notificationBell.onclick = () => {
|
||||||
|
notificationBoard.style.display = notificationBoard.style.display === 'block' ? 'none' : 'block';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the notification board when clicking outside of it
|
||||||
|
document.addEventListener('click', (event) => {
|
||||||
|
if (notificationBoard && notificationBell &&
|
||||||
|
notificationBoard.style.display === 'block' &&
|
||||||
|
!notificationBoard.contains(event.target as Node) &&
|
||||||
|
!notificationBell.contains(event.target as Node)) {
|
||||||
|
notificationBoard.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Loads group list at startup
|
||||||
|
//loadGroupList();
|
||||||
|
|
||||||
|
export function initChat(): void {
|
||||||
|
loadGroupList();
|
||||||
|
|
||||||
|
// Re-initialize event listeners
|
||||||
|
const sendBtn = document.getElementById('send-button');
|
||||||
|
const messageInput = document.getElementById('message-input');
|
||||||
|
const fileInput = document.getElementById('file-input');
|
||||||
|
|
||||||
|
if (sendBtn) sendBtn.onclick = sendMessage;
|
||||||
|
if (messageInput) {
|
||||||
|
messageInput.addEventListener('keydown', function (event) {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
event.preventDefault();
|
||||||
|
sendMessage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileInput) {
|
||||||
|
fileInput.addEventListener('change', function (event: Event) {
|
||||||
|
const file = (event.target as HTMLInputElement).files?.[0];
|
||||||
|
if (file) {
|
||||||
|
sendFile(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize notification listeners
|
||||||
|
const notificationBell = document.getElementById('notification-bell');
|
||||||
|
const notificationBoard = document.getElementById('notification-board');
|
||||||
|
|
||||||
|
if (notificationBell && notificationBoard) {
|
||||||
|
notificationBell.onclick = () => {
|
||||||
|
notificationBoard.style.display = notificationBoard.style.display === 'block' ? 'none' : 'block';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveMessagesToLocalStorage(messages: any[]) {
|
||||||
|
messageStore.setMessages(messages);
|
||||||
|
messagesMock = messageStore.getMessages();
|
||||||
|
}
|
53
src/pages/signature/signature.html
Normal file
53
src/pages/signature/signature.html
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Signatures</title>
|
||||||
|
<link rel="stylesheet" href="../../../public/style/signature.css">
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!-- Main content-->
|
||||||
|
<div class="container">
|
||||||
|
<!-- List of groups -->
|
||||||
|
<div class="group-list">
|
||||||
|
<ul id="group-list">
|
||||||
|
<!-- Groups will be added here dynamically -->
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Chat area -->
|
||||||
|
<div class="chat-area">
|
||||||
|
<div class="chat-header" id="chat-header">
|
||||||
|
<!-- Chat title -->
|
||||||
|
</div>
|
||||||
|
<div class="messages" id="messages">
|
||||||
|
<!-- Messages -->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Input area -->
|
||||||
|
<div class="input-area">
|
||||||
|
<label for="file-input" class="attachment-icon">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
d="M13.514 2.444l-10.815 10.785c-.449.449-.678 1.074-.625 1.707l.393 4.696c.041.479.422.86.9.9l4.697.394c.633.053 1.258-.177 1.707-.626l11.875-11.844c.196-.196.195-.512 0-.707l-3.536-3.536c-.195-.195-.511-.196-.707 0l-8.878 8.848c-.162.162-.253.382-.253.611v.725c0 .184.148.332.332.332h.725c.229 0 .448-.092.61-.254l7.11-7.08 1.415 1.415-7.386 7.354c-.375.375-.885.586-1.414.586h-2.414c-.555 0-1-.448-1-1v-2.414c0-.53.211-1.039.586-1.414l9.506-9.477c.781-.781 2.049-.781 2.829-.001l4.243 4.243c.391.391.586.902.586 1.414 0 .512-.196 1.025-.587 1.416l-12.35 12.319c-.748.747-1.76 1.164-2.81 1.164-.257 0-6.243-.467-6.499-.487-.664-.052-1.212-.574-1.268-1.267-.019-.242-.486-6.246-.486-6.499 0-1.05.416-2.062 1.164-2.811l10.936-10.936 1.414 1.444z" />
|
||||||
|
</svg>
|
||||||
|
</label>
|
||||||
|
<input type="file" id="file-input" style="display: none;" />
|
||||||
|
|
||||||
|
<textarea id="message-input" rows="3" placeholder="Type your message..."></textarea>
|
||||||
|
|
||||||
|
|
||||||
|
<button id="send-button">Send</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<script type="module" src="./signature.ts?ts"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
1209
src/pages/signature/signature.ts
Normal file
1209
src/pages/signature/signature.ts
Normal file
File diff suppressed because it is too large
Load Diff
53
src/utils/messageMock.ts
Normal file
53
src/utils/messageMock.ts
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import { messagesMock as initialMessagesMock } from '../mocks/mock-signature/messagesMock.js';
|
||||||
|
|
||||||
|
// Store singleton for messages
|
||||||
|
class MessageStore {
|
||||||
|
private readonly STORAGE_KEY = 'chat_messages';
|
||||||
|
private messages: any[] = [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.messages = this.loadFromLocalStorage() || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadFromLocalStorage() {
|
||||||
|
try {
|
||||||
|
const stored = localStorage.getItem(this.STORAGE_KEY);
|
||||||
|
return stored ? JSON.parse(stored) : null;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading messages:', error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getMessages() {
|
||||||
|
return this.messages;
|
||||||
|
}
|
||||||
|
|
||||||
|
setMessages(messages: any[]) {
|
||||||
|
this.messages = messages;
|
||||||
|
this.saveToLocalStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
private saveToLocalStorage() {
|
||||||
|
try {
|
||||||
|
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(this.messages));
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error saving messages:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addMessage(memberId: string | number, message: any) {
|
||||||
|
const memberMessages = this.messages.find(m => String(m.memberId) === String(memberId));
|
||||||
|
if (memberMessages) {
|
||||||
|
memberMessages.messages.push(message);
|
||||||
|
} else {
|
||||||
|
this.messages.push({
|
||||||
|
memberId: String(memberId),
|
||||||
|
messages: [message]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.saveToLocalStorage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const messageStore = new MessageStore();
|
96
src/utils/notification.store.ts
Normal file
96
src/utils/notification.store.ts
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
interface INotification {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
time?: string;
|
||||||
|
memberId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotificationStore {
|
||||||
|
private static instance: NotificationStore;
|
||||||
|
private notifications: INotification[] = [];
|
||||||
|
|
||||||
|
private constructor() {
|
||||||
|
this.loadFromLocalStorage();
|
||||||
|
}
|
||||||
|
|
||||||
|
static getInstance(): NotificationStore {
|
||||||
|
if (!NotificationStore.instance) {
|
||||||
|
NotificationStore.instance = new NotificationStore();
|
||||||
|
}
|
||||||
|
return NotificationStore.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
addNotification(notification: INotification) {
|
||||||
|
this.notifications.push(notification);
|
||||||
|
this.saveToLocalStorage();
|
||||||
|
this.updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeNotification(index: number) {
|
||||||
|
this.notifications.splice(index, 1);
|
||||||
|
this.saveToLocalStorage();
|
||||||
|
this.updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
getNotifications(): INotification[] {
|
||||||
|
return this.notifications;
|
||||||
|
}
|
||||||
|
|
||||||
|
private saveToLocalStorage() {
|
||||||
|
localStorage.setItem('notifications', JSON.stringify(this.notifications));
|
||||||
|
}
|
||||||
|
|
||||||
|
private loadFromLocalStorage() {
|
||||||
|
const stored = localStorage.getItem('notifications');
|
||||||
|
if (stored) {
|
||||||
|
this.notifications = JSON.parse(stored);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateUI() {
|
||||||
|
const badge = document.querySelector('.notification-badge') as HTMLElement;
|
||||||
|
const board = document.querySelector('.notification-board') as HTMLElement;
|
||||||
|
|
||||||
|
if (badge) {
|
||||||
|
badge.textContent = this.notifications.length.toString();
|
||||||
|
badge.style.display = this.notifications.length > 0 ? 'block' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (board) {
|
||||||
|
this.renderNotificationBoard(board);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderNotificationBoard(board: HTMLElement) {
|
||||||
|
board.innerHTML = '';
|
||||||
|
|
||||||
|
if (this.notifications.length === 0) {
|
||||||
|
board.innerHTML = '<div class="no-notification">No notifications available</div>';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.notifications.forEach((notif, index) => {
|
||||||
|
const notifElement = document.createElement('div');
|
||||||
|
notifElement.className = 'notification-item';
|
||||||
|
notifElement.innerHTML = `
|
||||||
|
<div>${notif.title}</div>
|
||||||
|
<div>${notif.description}</div>
|
||||||
|
${notif.time ? `<div>${notif.time}</div>` : ''}
|
||||||
|
`;
|
||||||
|
notifElement.onclick = () => {
|
||||||
|
if (notif.memberId) {
|
||||||
|
window.loadMemberChat(notif.memberId);
|
||||||
|
}
|
||||||
|
this.removeNotification(index);
|
||||||
|
};
|
||||||
|
board.appendChild(notifElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public refreshNotifications() {
|
||||||
|
this.updateUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const notificationStore = NotificationStore.getInstance();
|
Loading…
x
Reference in New Issue
Block a user