diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 184654111e..502eb6861c 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -1171,7 +1171,8 @@ "newChat": "New Chat", "newGroupChat": "New Group Chat", "groupInfo": "Group Info", - "members": "Members" + "members": "Members", + "addMembers": "Add Members" }, "userChatRoom": { "selectContact": "Select a contact to start conversation", diff --git a/public/locales/fr/translation.json b/public/locales/fr/translation.json index a5e7f627d6..820f50fd10 100644 --- a/public/locales/fr/translation.json +++ b/public/locales/fr/translation.json @@ -1171,7 +1171,8 @@ "newChat": "nouvelle discussion", "newGroupChat": "Nouvelle discussion de groupe", "groupInfo": "Informations sur le groupe", - "members": "Membres" + "members": "Membres", + "addMembers": "Add Members" }, "userChatRoom": { "selectContact": "Sélectionnez un contact pour démarrer la conversation", diff --git a/public/locales/hi/translation.json b/public/locales/hi/translation.json index babc732c22..1a48a371f2 100644 --- a/public/locales/hi/translation.json +++ b/public/locales/hi/translation.json @@ -1171,7 +1171,8 @@ "newChat": "नई चैट", "newGroupChat": "नया समूह चैट", "groupInfo": "समूह जानकारी", - "members": "सदस्यों" + "members": "सदस्यों", + "addMembers": "Add Members" }, "userChatRoom": { "selectContact": "बातचीत शुरू करने के लिए एक संपर्क चुनें", diff --git a/public/locales/sp/translation.json b/public/locales/sp/translation.json index e2aeb8742f..187db37829 100644 --- a/public/locales/sp/translation.json +++ b/public/locales/sp/translation.json @@ -1172,7 +1172,8 @@ "newChat": "nueva charla", "newGroupChat": "Nuevo chat grupal", "groupInfo": "Información del grupo", - "members": "Miembros" + "members": "Miembros", + "addMembers": "Add Members" }, "userChatRoom": { "selectContact": "Seleccione un contacto para iniciar una conversación", diff --git a/public/locales/zh/translation.json b/public/locales/zh/translation.json index 2dda2d57b4..6bdd65348d 100644 --- a/public/locales/zh/translation.json +++ b/public/locales/zh/translation.json @@ -1171,7 +1171,8 @@ "newChat": "新聊天", "newGroupChat": "新群聊", "groupInfo": "集团信息", - "members": "会员" + "members": "会员", + "addMembers": "Add Members" }, "userChatRoom": { "selectContact": "选择联系人开始对话", diff --git a/src/GraphQl/Queries/PlugInQueries.ts b/src/GraphQl/Queries/PlugInQueries.ts index 4ca3a38be8..e2e831bd34 100644 --- a/src/GraphQl/Queries/PlugInQueries.ts +++ b/src/GraphQl/Queries/PlugInQueries.ts @@ -150,6 +150,13 @@ export const CHAT_BY_ID = gql` email image } + admins { + _id + firstName + lastName + email + image + } unseenMessagesByUsers } } @@ -172,12 +179,6 @@ export const GROUP_CHAT_LIST = gql` createdAt messageContent media - receiver { - _id - firstName - lastName - email - } sender { _id firstName @@ -196,6 +197,13 @@ export const GROUP_CHAT_LIST = gql` email image } + admins { + _id + firstName + lastName + email + image + } unseenMessagesByUsers } } @@ -236,6 +244,13 @@ export const UNREAD_CHAT_LIST = gql` email image } + admins { + _id + firstName + lastName + email + image + } unseenMessagesByUsers } } @@ -285,6 +300,13 @@ export const CHATS_LIST = gql` email image } + admins { + _id + firstName + lastName + email + image + } unseenMessagesByUsers } } diff --git a/src/components/GroupChatDetails/GroupChatDetails.module.css b/src/components/GroupChatDetails/GroupChatDetails.module.css index 319c77d6cf..6bf80fdcee 100644 --- a/src/components/GroupChatDetails/GroupChatDetails.module.css +++ b/src/components/GroupChatDetails/GroupChatDetails.module.css @@ -20,6 +20,17 @@ gap: 10px; } +.groupMembersList { + display: flex; + align-items: center; + justify-content: space-between; +} + +.groupMembersList p { + margin: 0; + color: #959595; +} + .membersImage { width: 40px !important; } @@ -75,3 +86,9 @@ color: rgb(42, 197, 42); cursor: pointer; } + +.chatUserDetails { + display: flex; + gap: 10px; + align-items: center; +} \ No newline at end of file diff --git a/src/components/GroupChatDetails/GroupChatDetails.test.tsx b/src/components/GroupChatDetails/GroupChatDetails.test.tsx new file mode 100644 index 0000000000..5820a0fd33 --- /dev/null +++ b/src/components/GroupChatDetails/GroupChatDetails.test.tsx @@ -0,0 +1,168 @@ +import React from 'react'; +import { render, screen, fireEvent, waitFor } from '@testing-library/react'; +import GroupChatDetails from './GroupChatDetails'; +import { MockedProvider } from '@apollo/client/testing'; +import { + ADD_USER_TO_GROUP_CHAT, + UPDATE_CHAT, +} from 'GraphQl/Mutations/OrganizationMutations'; +import { USERS_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; + +const mockChat = { + _id: '1', + isGroup: true, + name: 'Test Group', + image: '', + messages: [], + admins: [ + { + _id: '1', + firstName: 'Admin', + lastName: 'User', + email: 'admin@example.com', + }, + ], + users: [ + { + _id: '2', + firstName: 'Test', + lastName: 'User', + email: 'test@example.com', + }, + ], + unseenMessagesByUsers: JSON.parse('{"1": 0, "2": 0}'), + description: 'Test Description', +}; + +const mocks = [ + { + request: { + query: USERS_CONNECTION_LIST, + variables: { firstName_contains: '', lastName_contains: '' }, + }, + result: { + data: { + users: [ + { + user: { + _id: '3', + firstName: 'New', + lastName: 'User', + email: 'newuser@example.com', + }, + }, + ], + }, + }, + }, + { + request: { + query: ADD_USER_TO_GROUP_CHAT, + variables: { userId: '3', chatId: '1' }, + }, + result: { + data: { + addUserToGroupChat: { success: true }, + }, + }, + }, + { + request: { + query: UPDATE_CHAT, + variables: { input: { _id: '1', image: '', name: 'Updated Group' } }, + }, + result: { + data: { + updateChat: { success: true }, + }, + }, + }, +]; + +describe('GroupChatDetails', () => { + it('renders correctly', () => { + render( + + + , + ); + + expect(screen.getByText('Test Group')).toBeInTheDocument(); + expect(screen.getByText('Test Description')).toBeInTheDocument(); + }); + + it('opens and closes modals correctly', () => { + const toggleGroupChatDetailsModal = jest.fn(); + render( + + + , + ); + + fireEvent.click(screen.getByTestId('createDirectChat')); + expect(toggleGroupChatDetailsModal).toHaveBeenCalled(); + }); + + it('edits chat title', async () => { + render( + + + , + ); + + fireEvent.click(screen.getByText('Test Group')); + fireEvent.change(screen.getByDisplayValue('Test Group'), { + target: { value: 'Updated Group' }, + }); + fireEvent.click(screen.getByText('✔')); + + await waitFor(() => { + expect(screen.getByText('Updated Group')).toBeInTheDocument(); + }); + }); + + it('opens add user modal and adds user', async () => { + render( + + + , + ); + + fireEvent.click(screen.getByText('Add Members')); + expect(screen.getByTestId('addExistingUserModal')).toBeInTheDocument(); + + fireEvent.change(screen.getByPlaceholderText('searchFullName'), { + target: { value: 'New User' }, + }); + fireEvent.click(screen.getByTestId('submitBtn')); + + await waitFor(() => { + expect(screen.getByText('New User')).toBeInTheDocument(); + }); + + fireEvent.click(screen.getByText('Add')); + await waitFor(() => { + expect(screen.queryByText('New User')).not.toBeInTheDocument(); + }); + }); +}); diff --git a/src/components/GroupChatDetails/GroupChatDetails.tsx b/src/components/GroupChatDetails/GroupChatDetails.tsx index 0bd9008755..762385aa8e 100644 --- a/src/components/GroupChatDetails/GroupChatDetails.tsx +++ b/src/components/GroupChatDetails/GroupChatDetails.tsx @@ -17,13 +17,13 @@ import { styled } from '@mui/material/styles'; import type { InterfaceQueryUserListItem } from 'utils/interfaces'; import { USERS_CONNECTION_LIST } from 'GraphQl/Queries/Queries'; import Loader from 'components/Loader/Loader'; -import { Search } from '@mui/icons-material'; +import { Search, Add } from '@mui/icons-material'; import { useTranslation } from 'react-i18next'; import Avatar from 'components/Avatar/Avatar'; -import AddIcon from 'assets/svgs/add.svg'; import { FiEdit } from 'react-icons/fi'; import { FaCheck, FaX } from 'react-icons/fa6'; import convertToBase64 from 'utils/convertToBase64'; +import useLocalStorage from 'utils/useLocalstorage'; type DirectMessage = { _id: string; @@ -62,6 +62,12 @@ type Chat = { name?: string; image?: string; messages: DirectMessage[]; + admins: { + _id: string; + firstName: string; + lastName: string; + email: string; + }[]; users: { _id: string; firstName: string; @@ -122,6 +128,9 @@ export default function groupChatDetails({ }); const [userName, setUserName] = useState(''); + const { getItem } = useLocalStorage(); + + const userId = getItem('userId'); const [editChatTitle, setEditChatTitle] = useState(false); const [chatName, setChatName] = useState(chat?.name || ''); @@ -280,27 +289,42 @@ export default function groupChatDetails({ {chat.users.length} {t('members')} - { - openAddUserModal(); - }} - > - {t('addMember')} - + {chat.admins.map((admin) => admin._id).includes(userId) && ( + { + openAddUserModal(); + }} + > + {t('addMembers')} + + )} {chat.users.map( (user: { _id: string; firstName: string; lastName: string; }) => ( - - - {user.firstName} {user.lastName} - + <> + +
+ + {user.firstName} {user.lastName} +
+ +
+ {chat.admins + .map((admin) => admin._id) + .includes(user._id) &&

Admin

} +
+
+ ), )}
diff --git a/src/components/UserPortal/ChatRoom/ChatRoom.tsx b/src/components/UserPortal/ChatRoom/ChatRoom.tsx index 9699b6aac5..8c05f69daa 100644 --- a/src/components/UserPortal/ChatRoom/ChatRoom.tsx +++ b/src/components/UserPortal/ChatRoom/ChatRoom.tsx @@ -81,6 +81,12 @@ type Chat = { name?: string; image?: string; messages: DirectMessage[]; + admins: { + _id: string; + firstName: string; + lastName: string; + email: string; + }[]; users: { _id: string; firstName: string; diff --git a/src/screens/UserPortal/Events/Events.test.tsx b/src/screens/UserPortal/Events/Events.test.tsx index 3e7fef23ed..00363d2e2e 100644 --- a/src/screens/UserPortal/Events/Events.test.tsx +++ b/src/screens/UserPortal/Events/Events.test.tsx @@ -19,9 +19,8 @@ import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs'; import { ThemeProvider } from 'react-bootstrap'; import { createTheme } from '@mui/material'; import useLocalStorage from 'utils/useLocalstorage'; -import { create } from 'domain'; -const { setItem, getItem } = useLocalStorage(); +const { setItem } = useLocalStorage(); jest.mock('react-toastify', () => ({ toast: {