From 88ac575d17422d97a9166c41b5cb45de32241245 Mon Sep 17 00:00:00 2001 From: Aime-Patrick Date: Wed, 31 Jul 2024 01:08:28 +0200 Subject: [PATCH] [Delivers #187584880]Users should be able to chat --- package-lock.json | 79 ++++ package.json | 11 +- public/assets/notification.mp3 | Bin 0 -> 17598 bytes src/App.scss | 3 +- src/assets/styles/liveChat.scss | 384 +++++++++++++++++++ src/components/layout/Header.tsx | 2 +- src/components/layout/Layout.tsx | 2 + src/components/live-chat/LiveChat.tsx | 527 ++++++++++++++++++++++++++ src/store/features/auth/authSlice.tsx | 4 +- src/store/features/chat/chatSlice.tsx | 51 +++ src/store/reducers/index.ts | 2 + src/utils/types/custom.d.ts | 5 + src/utils/types/store.d.ts | 8 +- webpack.dev.config.ts | 15 +- webpack.prod.config.ts | 13 + 15 files changed, 1090 insertions(+), 16 deletions(-) create mode 100644 public/assets/notification.mp3 create mode 100644 src/assets/styles/liveChat.scss create mode 100644 src/components/live-chat/LiveChat.tsx create mode 100644 src/store/features/chat/chatSlice.tsx diff --git a/package-lock.json b/package-lock.json index 25b90b64..83b15225 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,11 +20,13 @@ "dotenv": "^16.4.5", "formik": "^2.4.6", "html-webpack-plugin": "^5.6.0", + "jwt-decode": "^4.0.0", "mini-css-extract-plugin": "^2.9.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-helmet": "^6.1.0", "react-icons": "^5.2.1", + "react-input-emoji": "^5.9.0", "react-redux": "^9.1.2", "react-router-dom": "^6.24.0", "react-spinners": "^0.14.1", @@ -2176,6 +2178,22 @@ "node": ">=10.0.0" } }, + "node_modules/@emoji-mart/data": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emoji-mart/data/-/data-1.2.1.tgz", + "integrity": "sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw==", + "license": "MIT" + }, + "node_modules/@emoji-mart/react": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@emoji-mart/react/-/react-1.1.1.tgz", + "integrity": "sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g==", + "license": "MIT", + "peerDependencies": { + "emoji-mart": "^5.2", + "react": "^16.8 || ^17 || ^18" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.12.0", "license": "MIT", @@ -11881,6 +11899,12 @@ "url": "https://github.com/sindresorhus/emittery?sponsor=1" } }, + "node_modules/emoji-mart": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.6.0.tgz", + "integrity": "sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow==", + "license": "MIT" + }, "node_modules/emoji-regex": { "version": "9.2.2", "dev": true, @@ -13502,6 +13526,8 @@ }, "node_modules/file-loader": { "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", "dev": true, "license": "MIT", "dependencies": { @@ -18663,6 +18689,15 @@ "node": ">=8" } }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/keyv": { "version": "4.5.4", "dev": true, @@ -21615,6 +21650,24 @@ "react": "^18.3.1" } }, + "node_modules/react-easy-emoji": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/react-easy-emoji/-/react-easy-emoji-1.8.1.tgz", + "integrity": "sha512-wAf2x+cjwtOlLfXnjc0J3k5B2PDZdoxd1BjtfKr5tq2AL7t2ygvByJQWgFOyN28xg3qe8EKBM6pKxGP+qrGWuQ==", + "license": "MIT", + "dependencies": { + "string-replace-to-array": "^2.1.0" + }, + "peerDependencies": { + "@types/react": ">=0.14.0", + "react": ">=0.14.27" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-element-to-jsx-string": { "version": "15.0.0", "dev": true, @@ -21666,6 +21719,26 @@ "react": "*" } }, + "node_modules/react-input-emoji": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/react-input-emoji/-/react-input-emoji-5.9.0.tgz", + "integrity": "sha512-37Bbg4DEI4UXQ/tNSG3shIA0iFqk3vkhvfTZSQxi/oweeB/870G/6lvp65Ebex2rNM+UlwjMmR80rlJQwl78lQ==", + "license": "MIT", + "dependencies": { + "@emoji-mart/data": "1.2.1", + "@emoji-mart/react": "1.1.1", + "emoji-mart": "5.6.0", + "react-easy-emoji": "^1.8.1" + }, + "engines": { + "node": ">=8", + "npm": ">=5" + }, + "peerDependencies": { + "react": ">=17.0.x", + "react-dom": ">=17.0.x" + } + }, "node_modules/react-is": { "version": "16.13.1", "license": "MIT" @@ -23224,6 +23297,12 @@ "node": ">=10" } }, + "node_modules/string-replace-to-array": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-replace-to-array/-/string-replace-to-array-2.1.1.tgz", + "integrity": "sha512-i31csTEoIrcB8pusAF72Z0WsF04sbdiH4s0egpcmFj30SgHYdYd1swmZ7Zb1qFryJ5DbZR6z4rSjOzoUcrWUWw==", + "license": "MIT" + }, "node_modules/string-width": { "version": "5.1.2", "dev": true, diff --git a/package.json b/package.json index a9fce785..73408151 100644 --- a/package.json +++ b/package.json @@ -22,23 +22,20 @@ "dotenv": "^16.4.5", "formik": "^2.4.6", "html-webpack-plugin": "^5.6.0", + "jwt-decode": "^4.0.0", "mini-css-extract-plugin": "^2.9.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-helmet": "^6.1.0", "react-icons": "^5.2.1", + "react-input-emoji": "^5.9.0", "react-redux": "^9.1.2", "react-router-dom": "^6.24.0", "react-spinners": "^0.14.1", "react-toastify": "^10.0.5", "save-dev": "0.0.1-security", "socket.io-client": "^4.7.5", - "yup": "^1.4.0", - "@emotion/react": "^11.11.4", - "@emotion/styled": "^11.11.5", - "@mui/icons-material": "^5.16.4", - "@mui/material": "^5.16.4", - "antd": "^5.19.2" + "yup": "^1.4.0" }, "devDependencies": { "@babel/core": "^7.24.7", @@ -104,4 +101,4 @@ "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.0.4" } -} \ No newline at end of file +} diff --git a/public/assets/notification.mp3 b/public/assets/notification.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..0cd8d683d0a3d81282e5eaaa2e18719412783f8f GIT binary patch literal 17598 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 literal 0 HcmV?d00001 diff --git a/src/App.scss b/src/App.scss index 7b1f71f6..12147077 100644 --- a/src/App.scss +++ b/src/App.scss @@ -30,4 +30,5 @@ @import "./assets/styles/tables.scss"; @import "./assets/styles/adminDashboard.scss"; @import "./assets/styles/users.scss"; -@import "./assets/styles/tables.scss"; \ No newline at end of file +@import "./assets/styles/tables.scss"; +@import "./assets/styles/liveChat.scss"; \ No newline at end of file diff --git a/src/assets/styles/liveChat.scss b/src/assets/styles/liveChat.scss new file mode 100644 index 00000000..5c95c30d --- /dev/null +++ b/src/assets/styles/liveChat.scss @@ -0,0 +1,384 @@ +.floating-chat-icon { + position: fixed; + bottom: 20px; + right: 20px; + background-color: $primary-color; + border-radius: 50%; + width: 60px; + height: 60px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + animation: bounce 2s infinite; + + .chat-icon { + width: 30px; + height: 30px; + fill: white; + transition: fill 0.3s; + } + + .unreadCount{ + position: absolute; + top: -8px; + right: -8px; + background-color: red; + color: white; + border-radius: 50%; + width: 20px; + height: 20px; + text-align: center; + line-height: 20px; + font-weight: bold; + } +} + +@keyframes bounce { + + 0%, + 100% { + transform: translateY(0); + } + + 50% { + transform: translateY(-10px); + } +} + +.live-chat { + position: fixed; + bottom: 0; + right: 2rem; + width: 50rem; + height: 60rem; + background-color: $secondary-color-light; + border: none; + border-radius: 10px 10px 0 0; + box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5); + display: flex; + flex-direction: column; + max-height: 100vh; + max-width: 100vw; + overflow: hidden; + z-index: 1000; + + + + &.minimized { + height: 5rem; + width: 39rem; + + .chat-messages, + .chat-input { + display: none; + } + .chat-header{ + p { + color: $white-color; + font-weight: bold; + font-size: 1.8rem; + margin: 0; + } + .chat-controls{ + margin: 0; + } + } + } + + .chat-header { + background-color: $primary-color; + padding: 10px; + border-radius: 10px 10px 0 0; + display: flex; + justify-content: space-between; + p { + margin-left: 2rem; + color: $white-color; + font-weight: bold; + font-size: 1.8rem; + display: flex; + align-items: center; + } + .chat-controls{ + gap: 1rem !important; + } + } + + .chat-messages { + flex: 1; + padding: 10px; + overflow-y: auto; + display: flex; + flex-direction: column; + + .system-message { + text-align: center; + color: #999; + font-style: italic; + } + + .unread-badge-container { + text-align: center; + margin-bottom: 10px; + } + + .unread-badge { + display: inline-block; + padding: 5px 0; + background-color: transparent; + color: $primary-color; + font-weight: bold; + font-size: 12px; + text-transform: uppercase; + } + + .unread-badge::before, + .unread-badge::after { + content: ""; + display: inline-block; + width: 15rem; + height: 2px; + background-color: $primary-color; + vertical-align: middle; + margin: 0 20px; + } + + .chat-message { + display: flex; + align-items: center; + margin: 10px; + max-width: 100%; + position: relative; + + .profile-image { + width: 40px; + height: 40px; + border-radius: 50%; + border: 1px solid $primary-color; + overflow: hidden; + margin-right: 10px; + + img { + width: 100%; + height: 100%; + object-fit: cover; + } + } + + &-right { + flex-direction: row-reverse; + + .profile-image { + margin-left: 10px; + margin-right: 0; + } + + .message-content { + background-color: $primary-color-light; + color: $text-color; + border-radius: 5px 5px 5px 5px; + text-align: right; + padding: 5px 15px; + position: relative; + font-size: 2rem; + right: .9rem; + + .images-container{ + display: flex; + img{ + height: 26rem; + width: 25rem; + object-fit: contain; + border: 1px solid $primary-color; + cursor: pointer; + transition: transform 0.2s ease-in-out; + } + .zoomIn{ + position: absolute; + transform: scale(0); + cursor: pointer; + top: 50%; + left: 50%; + z-index: 1; + font-size: 3rem; + color: $primary-color; + } + } + .imageDisplay img:hover { + transform: scale(1.05); + } + .imageDisplay:hover .zoomIn { + transform: scale(1); + transition: transform 0.2s ease-in-out; + } + + &:before { + content: ''; + position: absolute; + top: 50%; + right: -19px; + border-width: 10px; + border-style: solid; + border-color: transparent transparent transparent $primary-color-light; + transform: translateY(-50%); + } + } + } + + &-left { + .message-content { + background-color: $third-color; + color: $text-color; + border-radius: 5px 5px 5px 5px; + padding: 5px 15px; + position: relative; + font-size: 2rem; + left: .9rem; + + .images-container{ + display: flex; + gap: 5px; + img{ + width: 25rem; + height: 26rem; + object-fit: contain; + border: 1px solid $text-color; + cursor: pointer; + transition: transform 0.2s ease-in-out; + } + .zoomIn{ + position: absolute; + transform: scale(0); + cursor: pointer; + top: 50%; + left: 50%; + z-index: 1; + font-size: 3rem; + color: $primary-color; + } + } + .imageDisplay img:hover { + transform: scale(1.05); + } + + .imageDisplay:hover .zoomIn { + transform: scale(1); + transition: transform 0.2s ease-in-out; + } + + &:before { + content: ''; + position: absolute; + top: 50%; + left: -19px; + border-width: 10px; + border-style: solid; + border-color: transparent $third-color transparent transparent; + transform: translateY(-50%); + } + } + } + .username{ + display: block; + font-weight: bold; + color: $text-color; + margin-bottom: 5px; + font-size: 1.2rem; + opacity: .75; + } + .timestamp { + display: block; + font-size: 0.65em; + margin-top: 5px; + opacity: 0.7; + color: $text-color; + } + .unread { + background-color: #f0f0f0; + } + + } + } + + .chat-inputs { + display: flex; + padding: 10px; + border-top: 1px solid #ddd; + flex-direction: column; + + .imageDisplay{ + img{ + width: 10rem; + height: 15rem; + border-radius: .5rem; + } + } + .chat-input{ + display: flex; + padding: 10px; + + .send-btn { + color: $primary-color; + font-size: 5rem; + cursor: pointer; + } + } + + } + +} + +.modal { + position: fixed; + z-index: 1000; + left: 0; + top: 0; + width: 100vw; + height: 100vh; + overflow: auto; + background-color: rgba(0, 0, 0, 0.8); + z-index: 1000; + display: flex; + justify-content: center; + align-items: center; +} + +.modal-content { + position: relative; + max-width: 100%; + max-height: 100%; + align-items: center; + justify-content: center; +} + +.modal-image { + max-width: 100vw; + max-height: 100vh; + display: block; + width: auto; + height: auto; + margin: auto; +} + +.close { + position: absolute; + top: 10px; + right: 20px; + color: white; + font-size: 30px; + font-weight: bold; + cursor: pointer; + background-color: transparent; + border: none; + outline: none; +} + +.close:hover, +.close:focus { + color: $primary-color; + text-decoration: none; + cursor: pointer; + transform: rotate(90deg); + transition: transform 0.2s ease-in-out; +} \ No newline at end of file diff --git a/src/components/layout/Header.tsx b/src/components/layout/Header.tsx index 308ead38..0bd7362e 100644 --- a/src/components/layout/Header.tsx +++ b/src/components/layout/Header.tsx @@ -44,7 +44,7 @@ const Header: React.FC = () => { const categories = Array.from({ length: 5 }, (_, i) => i + 1); useEffect(() => { - if (tokenLogin.trim()) { + if (tokenLogin?.trim()) { setToken(tokenLogin); } else { const token = localStorage.getItem('token') || ''; diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx index 92aa0f32..46b8d4b5 100644 --- a/src/components/layout/Layout.tsx +++ b/src/components/layout/Layout.tsx @@ -3,12 +3,14 @@ import React from "react"; import Header from "./Header"; import { Outlet } from "react-router-dom"; import Footer from "./Footer"; +import LiveChat from "../live-chat/LiveChat"; export default function Layout() { return ( <>
+