diff --git a/public/locales/en.json b/public/locales/en.json index 72ad23c5cb..9ed31628f0 100644 --- a/public/locales/en.json +++ b/public/locales/en.json @@ -163,6 +163,8 @@ "noRequestFound": "No Request Found", "sort": "Sort", "filter": "Filter", + "Oldest": "Oldest First", + "Latest": "Latest First", "noOrgError": "Organizations not found, please create an organization through dashboard", "userApproved": "User Approved", "userRejected": "User Rejected", diff --git a/public/locales/fr.json b/public/locales/fr.json index 07cd92e71d..df32a6230c 100644 --- a/public/locales/fr.json +++ b/public/locales/fr.json @@ -153,6 +153,8 @@ "noRequestFound": "Aucune demande trouvée", "sort": "Trier", "filter": "Filtre", + "Oldest": "Les plus anciennes d'abord", + "Latest": "Les plus récentes d'abord", "userApproved": "Approuvé par l'utilisateur", "userRejected": "Utilisateur rejeté", "noResultsFoundFor": "Aucun résultat trouvé pour ", diff --git a/public/locales/hi.json b/public/locales/hi.json index 48d5fa1287..70bb05ec2e 100644 --- a/public/locales/hi.json +++ b/public/locales/hi.json @@ -152,6 +152,8 @@ "noRequestFound": "कोई अनुरोध नहीं मिला।", "sort": "छांटें", "filter": "फ़िल्टर", + "Oldest": "सबसे पुराना पहले", + "Latest": "सबसे नवीनतम पहले", "userApproved": "उपयोगकर्ता स्वीकृत", "userRejected": "उपयोगकर्ता अस्वीकृत", "noResultsFoundFor": "के लिए कोई परिणाम नहीं मिला ", diff --git a/public/locales/sp.json b/public/locales/sp.json index fb4f5d265d..020f46937f 100644 --- a/public/locales/sp.json +++ b/public/locales/sp.json @@ -152,6 +152,8 @@ "noRequestFound": "No se encontró ninguna solicitud.", "sort": "Ordenar", "filter": "Filtrar", + "Oldest": "Más Antiguas Primero", + "Latest": "Más Recientes Primero", "userApproved": "Aprobado por el usuario", "userRejected": "Usuario rechazado", "noResultsFoundFor": "No se encontraron resultados para ", diff --git a/public/locales/zh.json b/public/locales/zh.json index 71f7f59fc0..3d3b1826f5 100644 --- a/public/locales/zh.json +++ b/public/locales/zh.json @@ -152,6 +152,8 @@ "noRequestFound": "找不到請求。", "sort": "排序", "filter": "過濾", + "Oldest": "最旧的优先", + "Latest": "最新的优先", "userApproved": "用戶批准", "userRejected": "用戶被拒絕", "noResultsFoundFor": "未找到结果 ", diff --git a/src/screens/Requests/Requests.test.tsx b/src/screens/Requests/Requests.test.tsx index 4ec0c83069..60e6a5f5ec 100644 --- a/src/screens/Requests/Requests.test.tsx +++ b/src/screens/Requests/Requests.test.tsx @@ -1,6 +1,6 @@ import React from 'react'; import { MockedProvider } from '@apollo/react-testing'; -import { act, render, screen } from '@testing-library/react'; +import { act, fireEvent, render, screen } from '@testing-library/react'; import 'jest-localstorage-mock'; import 'jest-location-mock'; import { I18nextProvider } from 'react-i18next'; @@ -110,14 +110,46 @@ describe('Testing Request screen', () => { ); + await wait(); + const searchInput = screen.getByTestId('searchByName'); userEvent.type(searchInput, 'l'); - const notFoundDiv = await screen.findByTestId('searchAndNotFound'); - - expect(notFoundDiv).toBeInTheDocument(); + await screen.findByTestId('searchAndNotFound'); + }); - await wait(); + test('Testing search latest and oldest toggle', async () => { + await act(async () => { + render( + + + + + + + + + + ); + + await wait(); + + const searchInput = screen.getByTestId('sort'); + expect(searchInput).toBeInTheDocument(); + + const inputText = screen.getByTestId('sortDropdown'); + + fireEvent.click(inputText); + const toggleText = screen.getByTestId('latest'); + + fireEvent.click(toggleText); + + expect(searchInput).toBeInTheDocument(); + fireEvent.click(inputText); + const toggleTite = screen.getByTestId('oldest'); + fireEvent.click(toggleTite); + expect(searchInput).toBeInTheDocument(); + }); }); test('Testing accept user functionality', async () => { diff --git a/src/screens/Requests/Requests.tsx b/src/screens/Requests/Requests.tsx index edb21aaf5b..2755d4f637 100644 --- a/src/screens/Requests/Requests.tsx +++ b/src/screens/Requests/Requests.tsx @@ -29,6 +29,10 @@ import type { InterfaceQueryRequestListItem, InterfaceUserType, } from 'utils/interfaces'; + +import dayjs from 'dayjs'; +import relativeTime from 'dayjs/plugin/relativeTime'; +dayjs.extend(relativeTime); import styles from './Requests.module.css'; const Requests = (): JSX.Element => { @@ -41,7 +45,10 @@ const Requests = (): JSX.Element => { const [hasMore, sethasMore] = useState(true); const [isLoadingMore, setIsLoadingMore] = useState(false); const [searchByName, setSearchByName] = useState(''); - + const [sortingOption, setSortingOption] = useState(''); + const [displayedUsers, setDisplayedUsers] = useState< + InterfaceQueryRequestListItem[] + >([]); const [acceptAdminFunc] = useMutation(ACCEPT_ADMIN_MUTATION); const [rejectAdminFunc] = useMutation(REJECT_ADMIN_MUTATION); const { @@ -91,13 +98,29 @@ const Requests = (): JSX.Element => { }, []); // To manage loading states - useEffect(() => { - if (!usersData) { - return; + const updateDisplayedUsers = (data: any): InterfaceQueryRequestListItem[] => { + if (!data) { + return []; } - if (usersData.users.length < perPageResult) { - sethasMore(false); + + const newDisplayedUsers = sortRequests(data.users, sortingOption); + return newDisplayedUsers; + }; + + const setHasMoreBasedOnUsers = (data: any): boolean => { + if (!data) { + return false; } + + return data.users.length >= perPageResult; + }; + + useEffect(() => { + const newDisplayedUsers = updateDisplayedUsers(usersData); + setDisplayedUsers(newDisplayedUsers); + + const hasMoreValue = setHasMoreBasedOnUsers(usersData); + sethasMore(hasMoreValue); }, [usersData]); // If the user is not Superadmin, redirect to Organizations screen @@ -127,6 +150,13 @@ const Requests = (): JSX.Element => { } }, [loading]); + useEffect(() => { + if (usersData && usersData?.users.length > 0) { + const newDisplayedUsers = sortRequests(usersData?.users, sortingOption); + setDisplayedUsers(newDisplayedUsers); + } + }, [usersData, sortingOption]); + /* istanbul ignore next */ const resetAndRefetch = (): void => { refetchUsers({ @@ -233,8 +263,34 @@ const Requests = (): JSX.Element => { t('email'), t('accept'), t('reject'), + '', ]; + const handleSorting = (option: string): void => { + setSortingOption(option); + }; + + const sortRequests = ( + users: InterfaceQueryRequestListItem[], + sortingOption: string + ): InterfaceQueryRequestListItem[] => { + const sortedRequest = [...users]; + + if (sortingOption === 'latest') { + sortedRequest.sort( + (a, b) => + new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime() + ); + } else if (sortingOption === 'oldest') { + sortedRequest.sort( + (a, b) => + new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime() + ); + } + + return sortedRequest; + }; + return ( <> @@ -270,15 +326,35 @@ const Requests = (): JSX.Element => { - - + + - {t('sort')} + {sortingOption === '' + ? t('sort') + : sortingOption === 'latest' + ? t('Latest') + : t('Oldest')} - Action 1 - Action 2 - Action 3 + handleSorting('latest')} + data-testid="latest" + > + {t('Latest')} + + handleSorting('oldest')} + data-testid="oldest" + > + {t('Oldest')} + @@ -313,7 +389,12 @@ const Requests = (): JSX.Element => { } + loader={ + + } hasMore={hasMore} className={styles.listBox} data-testid="organizations-list" @@ -336,8 +417,9 @@ const Requests = (): JSX.Element => { - {usersData?.users && - usersData.users.map((user, index) => { + {displayedUsers && + displayedUsers.length > 0 && + displayedUsers.map((user, index) => { return ( {index + 1} @@ -365,6 +447,7 @@ const Requests = (): JSX.Element => { {t('reject')} + {dayjs(user.createdAt).fromNow()} ); })}