diff --git a/src/containers/List/List.module.css b/src/containers/List/List.module.css index 36d76cad8..18c6fada2 100644 --- a/src/containers/List/List.module.css +++ b/src/containers/List/List.module.css @@ -270,10 +270,13 @@ } .ListContainer { - height: 100vh; background-color: #f8faf5; } +.FullHeight { + height: 100vh; +} + .Checkbox { min-width: 50px; padding: 1rem; diff --git a/src/containers/List/List.tsx b/src/containers/List/List.tsx index 57b5926ab..54742b58e 100644 --- a/src/containers/List/List.tsx +++ b/src/containers/List/List.tsx @@ -227,9 +227,7 @@ export const List = ({ // check if the user has access to manage collections const userRolePermissions = getUserRolePermissions(); - const capitalListItemName = listItemName - ? listItemName[0].toUpperCase() + listItemName.slice(1) - : ''; + const capitalListItemName = listItemName ? listItemName[0].toUpperCase() + listItemName.slice(1) : ''; // function to get the default sorting set for columns const getDefaultSortColumn = (columnsFields: any) => { @@ -333,12 +331,9 @@ export const List = ({ let l; if (countQuery) { - [, { data: countData, error: e, loading: l, refetch: refetchCount }] = useLazyQuery( - countQuery, - { - variables: { filter }, - } - ); + [, { data: countData, error: e, loading: l, refetch: refetchCount }] = useLazyQuery(countQuery, { + variables: { filter }, + }); } // Get item data here @@ -348,8 +343,7 @@ export const List = ({ }); // Get item data here - const [fetchUserCollections, { loading: loadingCollections, data: userCollections }] = - useLazyQuery(GET_CURRENT_USER); + const [fetchUserCollections, { loading: loadingCollections, data: userCollections }] = useLazyQuery(GET_CURRENT_USER); const checkUserRole = () => { userRole = getUserRole(); @@ -460,9 +454,7 @@ export const List = ({ const { component, props } = useDelete(dialogMessage); dialogBox = ( allowedAction.delete ? ( -
showDialogHandler(Id, text)} - > +
showDialogHandler(Id, text)}>
Delete
@@ -592,9 +580,7 @@ export const List = ({
{actionListMap(item, actionsInsideMore, true)} - - {deleteButton(id, labelValue)} - + {deleteButton(id, labelValue)}
@@ -619,9 +605,7 @@ export const List = ({ if (event.target.checked) { checkbox?.setSelectedItems([...checkbox?.selectedItems, listItem]); } else { - checkbox?.setSelectedItems( - checkbox?.selectedItems.filter((item: any) => item.id !== listItem.id) - ); + checkbox?.setSelectedItems(checkbox?.selectedItems.filter((item: any) => item.id !== listItem.id)); } }} /> @@ -696,8 +680,7 @@ export const List = ({
{t('Sorry, no results found! Please try a different search.')}
) : (
- There are no {noItemText || listItemName}s right now.{' '} - {button.show && t('Please create one.')} + There are no {noItemText || listItemName}s right now. {button.show && t('Please create one.')}
)}
@@ -709,10 +692,7 @@ export const List = ({ { label: ( { if (event.target.checked) { checkbox?.setSelectedItems(data[listItem]); @@ -774,12 +754,7 @@ export const List = ({ ); } else if (!button.link) { buttonContent = ( - ); @@ -815,18 +790,14 @@ export const List = ({ ) : null; return ( -
+
{showHeader && ( <>
{backLink && ( - navigate(backLink)} - className={styles.BackLink} - data-testid="back-button" - /> + navigate(backLink)} className={styles.BackLink} data-testid="back-button" /> )}
{title}
{helpData && } diff --git a/src/containers/Profile/Contact/ContactDescription/ContactDescription.tsx b/src/containers/Profile/Contact/ContactDescription/ContactDescription.tsx index a2ff34aa7..29e798c29 100644 --- a/src/containers/Profile/Contact/ContactDescription/ContactDescription.tsx +++ b/src/containers/Profile/Contact/ContactDescription/ContactDescription.tsx @@ -9,12 +9,14 @@ import styles from './ContactDescription.module.css'; export interface ContactDescriptionProps { fields: any; - settings: any; - phone: string; - maskedPhone: string; + settings?: any; + phone?: string; + maskedPhone?: string; collections: any; - lastMessage: string; - statusMessage: string; + lastMessage?: string; + statusMessage?: string; + groups?: boolean; + customStyles?: string; } export const ContactDescription = ({ @@ -25,17 +27,15 @@ export const ContactDescription = ({ statusMessage, fields, settings, + groups = false, + customStyles, }: ContactDescriptionProps) => { const [showPlainPhone, setShowPlainPhone] = useState(false); const { t } = useTranslation(); // list of collections that the contact is assigned let assignedToCollection: any = Array.from( - new Set( - [].concat( - ...collections.map((collection: any) => collection.users.map((user: any) => user.name)) - ) - ) + new Set([].concat(...collections.map((collection: any) => collection.users.map((user: any) => user.name)))) ); if (assignedToCollection.length > 2) { @@ -49,16 +49,19 @@ export const ContactDescription = ({ // list of collections that the contact belongs const collectionList = collections.map((collection: any) => collection.label).join(', '); - const collectionDetails = [ - { label: t('Collections'), value: collectionList || t('None') }, - { - label: t('Assigned to'), - value: assignedToCollection || t('None'), - }, - ]; + let collectionDetails = [{ label: t('Collections'), value: collectionList || t('None') }]; + if (!groups) { + collectionDetails = [ + ...collectionDetails, + { + label: t('Assigned to'), + value: assignedToCollection || t('None'), + }, + ]; + } let settingsValue: any = ''; - if (typeof settings === 'string') { + if (settings && typeof settings === 'string') { settingsValue = JSON.parse(settings); } @@ -110,23 +113,30 @@ export const ContactDescription = ({ ); } - return ( -
-
- - Number - -
- {phoneDisplay} -
- {t('Session Timer')} - + const numberBlock = ( + <> + {!groups && ( + <> +
+ + Number + +
+ {phoneDisplay} +
+ {t('Session Timer')} + +
+
-
-
- -
+
+ + )} + + ); + const collectionBlock = ( + <>
{collectionDetails.map((collectionItem: any) => (
@@ -139,38 +149,65 @@ export const ContactDescription = ({
+ + ); -
-
-
Status
-
{statusMessage}
-
-
- {settingsValue && - typeof settingsValue === 'object' && - Object.keys(settingsValue).map((key) => ( -
-
{key}
-
- {Object.keys(settingsValue[key]) - .filter((settingKey) => settingsValue[key][settingKey] === true) - .join(', ')} -
-
+ const settingsBlock = ( + <> + {settingsValue && + !groups && + typeof settingsValue === 'object' && + Object.keys(settingsValue).map((key) => ( +
+
{key}
+
+ {Object.keys(settingsValue[key]) + .filter((settingKey) => settingsValue[key][settingKey] === true) + .join(', ')}
- ))} - {fieldsValue && - typeof fieldsValue === 'object' && - Object.keys(fieldsValue).map((key) => ( -
-
- {fieldsValue[key].label ? fieldsValue[key].label : key.replace('_', ' ')} -
-
{fieldsValue[key].value}
-
+
+
+ ))} + + ); + + const statusBlock = ( + <> + {!groups && ( +
+
+
Status
+
{statusMessage}
+
+
+
+ )} + + ); + + const fieldsBlock = ( +
+ {fieldsValue && + typeof fieldsValue === 'object' && + Object.keys(fieldsValue).map((key) => ( +
+
+ {fieldsValue[key].label ? fieldsValue[key].label : key.replace('_', ' ')}
- ))} -
+
{fieldsValue[key].value}
+
+
+ ))} +
+ ); + + return ( +
+ {numberBlock} + {collectionBlock} + {settingsBlock} + {statusBlock} + {fieldsBlock}
); }; diff --git a/src/containers/WaGroups/GroupDetails.tsx/GroupDetails.module.css b/src/containers/WaGroups/GroupDetails.tsx/GroupDetails.module.css index f1cf10b2f..a39403fd6 100644 --- a/src/containers/WaGroups/GroupDetails.tsx/GroupDetails.module.css +++ b/src/containers/WaGroups/GroupDetails.tsx/GroupDetails.module.css @@ -65,3 +65,78 @@ padding: 2px 8px; border-radius: 8px; } + +.Container { + width: 100%; + height: 100%; + display: flex; + background-color: #f8faf5; +} + +.RightContainer { + height: 100%; + width: 100%; +} + +.Drawer { + width: fit-content; + border-right: 1px solid #efefef; + height: calc(100vh - 110px) !important; +} + +.Tab { + border-radius: 10px; + width: 200px; + height: 34px; + display: flex; + align-items: center; + margin: 2px 0; + padding: 0px !important; + font-weight: 400; + font-size: 14px; + color: #717971; + padding-left: 16px !important; +} + +.Tab:hover { + background-color: #71797123; + cursor: pointer !important; +} + +.ActiveTab { + font-weight: 700 !important; + color: #073f24 !important; + background-color: #cce6d0 !important; +} + +.GroupHeader { + display: flex; + box-shadow: 0px 1px 1px 0px #00000029; + padding: 15px; + align-items: center; + gap: 1rem; +} + +.GroupHeaderTitle { + font-size: 16px; + font-weight: 500; + color: #717971; + display: flex; + align-items: center; + gap: 10px; +} + +.GroupHeaderElements { + padding: 0.5rem 1rem; +} + +.Table { + display: flex; +} + +.BackGround { + background-color: #f8faf5 !important; + width: 100%; + height: 100%; + +} \ No newline at end of file diff --git a/src/containers/WaGroups/GroupDetails.tsx/GroupDetails.tsx b/src/containers/WaGroups/GroupDetails.tsx/GroupDetails.tsx index b0f0596dd..e73cc46f1 100644 --- a/src/containers/WaGroups/GroupDetails.tsx/GroupDetails.tsx +++ b/src/containers/WaGroups/GroupDetails.tsx/GroupDetails.tsx @@ -1,20 +1,20 @@ +import { useMutation, useQuery } from '@apollo/client'; +import { useState } from 'react'; import { useParams } from 'react-router-dom'; -import { List } from 'containers/List/List'; import { useTranslation } from 'react-i18next'; + import CollectionIcon from 'assets/images/icons/Collection/Dark.svg?react'; -import styles from './GroupDetails.module.css'; -import { UPDATE_GROUP_CONTACT } from 'graphql/mutations/Group'; -import { - COUNT_COUNTACTS_WA_GROUPS, - GET_WA_GROUP, - LIST_CONTACTS_WA_GROUPS, -} from 'graphql/queries/WaGroups'; import DeleteIcon from 'assets/images/icons/Delete/Red.svg?react'; -import { useState } from 'react'; -import { useMutation, useQuery } from '@apollo/client'; import { setNotification } from 'common/notification'; import { DialogBox } from 'components/UI/DialogBox/DialogBox'; +import { Heading } from 'components/UI/Heading/Heading'; import { Loading } from 'components/UI/Layout/Loading/Loading'; +import { AvatarDisplay } from 'components/UI/AvatarDisplay/AvatarDisplay'; +import { List } from 'containers/List/List'; +import { ContactDescription } from 'containers/Profile/Contact/ContactDescription/ContactDescription'; +import { UPDATE_GROUP_CONTACT } from 'graphql/mutations/Group'; +import { COUNT_COUNTACTS_WA_GROUPS, GET_WA_GROUP, LIST_CONTACTS_WA_GROUPS } from 'graphql/queries/WaGroups'; +import styles from './GroupDetails.module.css'; export const GroupDetails = () => { const params = useParams(); @@ -22,20 +22,22 @@ export const GroupDetails = () => { const [showDeleteDialog, setShowDeleteDialog] = useState(false); const [deleteVariables, setDeleteVariables] = useState(); - - const { loading: groupDataLoading, data: groupData } = useQuery(GET_WA_GROUP, { - variables: { - waGroupId: params.id, - }, - }); + const [contentToShow, setContentToShow] = useState('members'); const dialogTitle = 'Are you sure you want to remove this contact from the group?'; const dialogMessage = 'The contact will no longer receive messages sent to this group'; - const columnNames = [ - { label: t('Contact') }, - { label: 'All WhatsApp Groups' }, - { label: t('Actions') }, + const columnNames = [{ label: t('Contact') }, { label: 'All WhatsApp Groups' }, { label: t('Actions') }]; + + const list = [ + { + name: t('Members'), + section: 'members', + }, + { + name: t('Details'), + section: 'details', + }, ]; const [removeContact, { loading }] = useMutation(UPDATE_GROUP_CONTACT, { @@ -45,6 +47,14 @@ export const GroupDetails = () => { }, }); + const { loading: groupDataLoading, data } = useQuery(GET_WA_GROUP, { + variables: { + waGroupId: params.id, + }, + }); + + const groupData = data?.waGroup?.waGroup; + const queries = { countQuery: COUNT_COUNTACTS_WA_GROUPS, filterItemsQuery: LIST_CONTACTS_WA_GROUPS, @@ -141,24 +151,19 @@ export const GroupDetails = () => { alignButtons="center" buttonOkLoading={loading} > -
- The contact will no longer receive messages sent to this group -
+
The contact will no longer receive messages sent to this group
); } - if (groupDataLoading) { - return ; - } - - return ( - <> + let contentBody; + if (contentToShow === 'members') { + contentBody = ( { {...queries} {...columnAttributes} showSearch={false} + showHeader={false} + customStyles={styles.Table} /> + ); + } else { + contentBody = ( + + ); + } + + const drawer = ( +
+
+ + +
{groupData?.label}
+
+
+ {list.map((data: any, index: number) => { + return ( +
setContentToShow(data.section)} + className={`${styles.Tab} ${contentToShow === data.section ? styles.ActiveTab : ''}`} + > + {data.name} +
+ ); + })} +
+
+ ); + + if (groupDataLoading) { + return ; + } + + return ( + <> + + +
+ {drawer} +
{contentBody}
+
{dialog} ); diff --git a/src/graphql/queries/WaGroups.ts b/src/graphql/queries/WaGroups.ts index bce6e7051..11727ffca 100644 --- a/src/graphql/queries/WaGroups.ts +++ b/src/graphql/queries/WaGroups.ts @@ -56,11 +56,7 @@ export const GROUP_SEARCH_QUERY = gql` export const GROUP_SEARCH_MULTI_QUERY = gql` query WaSearchMulti($filter: WaSearchFilter!, $waGroupOpts: Opts!, $waMessageOpts: Opts!) { - searchMulti: waSearchMulti( - filter: $filter - waGroupOpts: $waGroupOpts - waMessageOpts: $waMessageOpts - ) { + searchMulti: waSearchMulti(filter: $filter, waGroupOpts: $waGroupOpts, waMessageOpts: $waMessageOpts) { groups: waGroups { bspId id @@ -173,10 +169,18 @@ export const GET_WA_GROUP = gql` id lastCommunicationAt bspId + fields waManagedPhone { phone id } + groups { + id + label + users { + name + } + } } } } diff --git a/src/i18n/en/en.json b/src/i18n/en/en.json index 6d041df3c..99e5e250c 100644 --- a/src/i18n/en/en.json +++ b/src/i18n/en/en.json @@ -531,5 +531,6 @@ "Add files to file search": "Add files to file search", "First name is required.": "First Name is required.", "Last name is required.": "Last name is required.", - "Failed": "Failed" + "Failed": "Failed", + "Members": "Members" }