From 249617001e1415396f3de06e861e4314d45c4e98 Mon Sep 17 00:00:00 2001 From: Sampo Tawast Date: Tue, 27 Jun 2023 14:19:09 +0300 Subject: [PATCH] refactor: application lists get data from prop --- .../applicationList/ApplicationList.tsx | 23 +++--- .../__tests__/ApplicationList.test.tsx | 1 + .../applicationList/useApplicationList.ts | 68 +--------------- .../applicationList/useApplicationListData.ts | 77 +++++++++++++++++++ frontend/benefit/handler/src/constants.ts | 9 +++ frontend/benefit/handler/src/pages/index.tsx | 54 +++++++++---- 6 files changed, 136 insertions(+), 96 deletions(-) create mode 100644 frontend/benefit/handler/src/components/applicationList/useApplicationListData.ts diff --git a/frontend/benefit/handler/src/components/applicationList/ApplicationList.tsx b/frontend/benefit/handler/src/components/applicationList/ApplicationList.tsx index 3c8afae5e3..5e49aacda7 100644 --- a/frontend/benefit/handler/src/components/applicationList/ApplicationList.tsx +++ b/frontend/benefit/handler/src/components/applicationList/ApplicationList.tsx @@ -1,10 +1,10 @@ -import { ROUTES } from 'benefit/handler/constants'; -import { allApplicationStatuses } from 'benefit/handler/pages'; +import { ALL_APPLICATION_STATUSES, ROUTES } from 'benefit/handler/constants'; import { ApplicationListTableColumns, ApplicationListTableTransforms, } from 'benefit/handler/types/applicationList'; import { APPLICATION_STATUSES } from 'benefit-shared/constants'; +import { ApplicationListItemData } from 'benefit-shared/types/application'; import { IconSpeechbubbleText, LoadingSpinner, @@ -26,6 +26,8 @@ import { useApplicationList } from './useApplicationList'; export interface ApplicationListProps { heading: string; status: APPLICATION_STATUSES[]; + list?: ApplicationListItemData[]; + isLoading: boolean; } const buildApplicationUrl = ( @@ -41,19 +43,14 @@ const buildApplicationUrl = ( const ApplicationList: React.FC = ({ heading, status, + list = [], + isLoading = true, }) => { - const { - t, - list, - shouldShowSkeleton, - shouldHideList, - translationsBase, - getHeader, - } = useApplicationList(status); + const { t, translationsBase, getHeader } = useApplicationList(); const theme = useTheme(); - const isAllStatuses: boolean = status === allApplicationStatuses; + const isAllStatuses: boolean = status === ALL_APPLICATION_STATUSES; const columns = React.useMemo(() => { const cols: ApplicationListTableColumns[] = [ @@ -186,7 +183,7 @@ const ApplicationList: React.FC = ({ return cols.filter(Boolean); }, [t, getHeader, status, theme, isAllStatuses]); - if (shouldShowSkeleton) { + if (isLoading) { return ( <> {heading && <$Heading>{`${heading}`}} @@ -198,7 +195,7 @@ const ApplicationList: React.FC = ({ const statusAsString = isAllStatuses ? 'all' : status.join(','); return (
- {!shouldHideList ? ( + {list.length > 0 ? ( { const initialProps: ApplicationListProps = { heading: 'Application List', status: [APPLICATION_STATUSES.RECEIVED], + isLoading: true, }; const getComponent = ( diff --git a/frontend/benefit/handler/src/components/applicationList/useApplicationList.ts b/frontend/benefit/handler/src/components/applicationList/useApplicationList.ts index 558c771423..82fb84ffd5 100644 --- a/frontend/benefit/handler/src/components/applicationList/useApplicationList.ts +++ b/frontend/benefit/handler/src/components/applicationList/useApplicationList.ts @@ -1,87 +1,21 @@ -import useApplicationsQuery from 'benefit/handler/hooks/useApplicationsQuery'; -import { APPLICATION_STATUSES } from 'benefit-shared/constants'; -import { - ApplicationData, - ApplicationListItemData, -} from 'benefit-shared/types/application'; import { TFunction, useTranslation } from 'next-i18next'; -import { getFullName } from 'shared/utils/application.utils'; -import { convertToUIDateFormat } from 'shared/utils/date.utils'; interface ApplicationListProps { t: TFunction; - list: ApplicationListItemData[]; - shouldShowSkeleton: boolean; - shouldHideList: boolean; getHeader: (id: string) => string; translationsBase: string; } const translationsBase = 'common:applications.list'; -const useApplicationList = ( - status: APPLICATION_STATUSES[], - excludeBatched?: boolean -): ApplicationListProps => { +const useApplicationList = (): ApplicationListProps => { const { t } = useTranslation(); - const query = useApplicationsQuery(status, '-submitted_at', excludeBatched); - - const list = query.data?.map( - (application: ApplicationData): ApplicationListItemData => { - const { - id = '', - employee, - company, - submitted_at, - application_number: applicationNum, - calculation, - additional_information_needed_by, - status: applicationStatus, - unread_messages_count, - batch, - application_origin: applicationOrigin, - } = application; - - return { - id, - status: applicationStatus, - companyName: company ? company.name : '-', - companyId: company ? company.business_id : '-', - employeeName: - getFullName(employee?.first_name, employee?.last_name) || '-', - submittedAt: convertToUIDateFormat(submitted_at) || '-', - additionalInformationNeededBy: - convertToUIDateFormat(additional_information_needed_by) || '-', - applicationNum, - // refactor when we have handler data - handlerName: - getFullName( - calculation?.handler_details?.first_name, - calculation?.handler_details?.last_name - ) || '-', - unreadMessagesCount: unread_messages_count ?? 0, - batch: batch ?? null, - applicationOrigin, - }; - } - ); - - const shouldShowSkeleton = query.isLoading; - - const shouldHideList = - Boolean(query.error) || - (!shouldShowSkeleton && - Array.isArray(query.data) && - query.data.length === 0); const getHeader = (id: string): string => t(`${translationsBase}.columns.${id}`); return { t, - list: list || [], - shouldShowSkeleton, - shouldHideList, getHeader, translationsBase, }; diff --git a/frontend/benefit/handler/src/components/applicationList/useApplicationListData.ts b/frontend/benefit/handler/src/components/applicationList/useApplicationListData.ts new file mode 100644 index 0000000000..09d56db6ea --- /dev/null +++ b/frontend/benefit/handler/src/components/applicationList/useApplicationListData.ts @@ -0,0 +1,77 @@ +import useApplicationsQuery from 'benefit/handler/hooks/useApplicationsQuery'; +import { APPLICATION_STATUSES } from 'benefit-shared/constants'; +import { + ApplicationData, + ApplicationListItemData, +} from 'benefit-shared/types/application'; +import { getFullName } from 'shared/utils/application.utils'; +import { convertToUIDateFormat } from 'shared/utils/date.utils'; + +interface ApplicationListProps { + list: ApplicationListItemData[]; + shouldShowSkeleton: boolean; + shouldHideList: boolean; +} + +const useApplicationListData = ( + status: APPLICATION_STATUSES[], + excludeBatched?: boolean +): ApplicationListProps => { + const query = useApplicationsQuery(status, '-submitted_at', excludeBatched); + + const list = query.data?.map( + (application: ApplicationData): ApplicationListItemData => { + const { + id = '', + employee, + company, + submitted_at, + application_number: applicationNum, + calculation, + additional_information_needed_by, + status: applicationStatus, + unread_messages_count, + batch, + application_origin: applicationOrigin, + } = application; + + return { + id, + status: applicationStatus, + companyName: company ? company.name : '-', + companyId: company ? company.business_id : '-', + employeeName: + getFullName(employee?.first_name, employee?.last_name) || '-', + submittedAt: convertToUIDateFormat(submitted_at) || '-', + additionalInformationNeededBy: + convertToUIDateFormat(additional_information_needed_by) || '-', + applicationNum, + // refactor when we have handler data + handlerName: + getFullName( + calculation?.handler_details?.first_name, + calculation?.handler_details?.last_name + ) || '-', + unreadMessagesCount: unread_messages_count ?? 0, + batch: batch ?? null, + applicationOrigin, + }; + } + ); + + const shouldShowSkeleton = query.isLoading; + + const shouldHideList = + Boolean(query.error) || + (!shouldShowSkeleton && + Array.isArray(query.data) && + query.data.length === 0); + + return { + list: list || [], + shouldShowSkeleton, + shouldHideList, + }; +}; + +export { useApplicationListData }; diff --git a/frontend/benefit/handler/src/constants.ts b/frontend/benefit/handler/src/constants.ts index 70bf15a8f8..2829a1cdf5 100644 --- a/frontend/benefit/handler/src/constants.ts +++ b/frontend/benefit/handler/src/constants.ts @@ -182,3 +182,12 @@ export const APPLICATION_INITIAL_VALUES = { applicationStep: DEFAULT_APPLICATION_STEP, [APPLICATION_FIELD_KEYS.APPLICATION_ORIGIN]: APPLICATION_ORIGINS.HANDLER, }; + +export const ALL_APPLICATION_STATUSES: APPLICATION_STATUSES[] = [ + APPLICATION_STATUSES.RECEIVED, + APPLICATION_STATUSES.HANDLING, + APPLICATION_STATUSES.INFO_REQUIRED, + APPLICATION_STATUSES.ACCEPTED, + APPLICATION_STATUSES.DRAFT, + APPLICATION_STATUSES.REJECTED, +]; diff --git a/frontend/benefit/handler/src/pages/index.tsx b/frontend/benefit/handler/src/pages/index.tsx index 90eba7b55d..fc0d368d0a 100644 --- a/frontend/benefit/handler/src/pages/index.tsx +++ b/frontend/benefit/handler/src/pages/index.tsx @@ -4,6 +4,7 @@ import MainIngress from 'benefit/handler/components/mainIngress/MainIngress'; import AppContext from 'benefit/handler/context/AppContext'; import FrontPageProvider from 'benefit/handler/context/FrontPageProvider'; import { APPLICATION_STATUSES } from 'benefit-shared/constants'; +import { ApplicationListItemData } from 'benefit-shared/types/application'; import { Tabs } from 'hds-react'; import { GetStaticProps, NextPage } from 'next'; import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; @@ -13,16 +14,9 @@ import Container from 'shared/components/container/Container'; import theme from 'shared/styles/theme'; import { useApplicationList } from '../components/applicationList/useApplicationList'; +import { useApplicationListData } from '../components/applicationList/useApplicationListData'; import { $BackgroundWrapper } from '../components/layout/Layout'; - -export const allApplicationStatuses: APPLICATION_STATUSES[] = [ - APPLICATION_STATUSES.RECEIVED, - APPLICATION_STATUSES.HANDLING, - APPLICATION_STATUSES.INFO_REQUIRED, - APPLICATION_STATUSES.ACCEPTED, - APPLICATION_STATUSES.DRAFT, - APPLICATION_STATUSES.REJECTED, -]; +import { ALL_APPLICATION_STATUSES } from '../constants'; const ApplicantIndex: NextPage = () => { const { @@ -45,17 +39,27 @@ const ApplicantIndex: NextPage = () => { const translationBase = 'common:applications.list.headings'; - const { t, list } = useApplicationList(allApplicationStatuses, true); + const { list, shouldShowSkeleton } = useApplicationListData( + ALL_APPLICATION_STATUSES, + true + ); + const { t } = useApplicationList(); + + const getHeadingTranslation = ( + headingStatus: APPLICATION_STATUSES | 'all' + ): string => t(`${translationBase}.${headingStatus}`); + + const getTabCount = (statuses: APPLICATION_STATUSES[]): number => + list.filter((app: ApplicationListItemData) => statuses.includes(app.status)) + .length; const getListHeadingByStatus = ( headingStatus: APPLICATION_STATUSES | 'all', statuses: APPLICATION_STATUSES[] ): string => list && list?.length > 0 - ? `${t(`${translationBase}.${headingStatus}`)} (${ - list.filter((app) => statuses.includes(app.status)).length - })` - : `${t(`${translationBase}.${headingStatus}`)}`; + ? `${getHeadingTranslation(headingStatus)} (${getTabCount(statuses)})` + : getHeadingTranslation(headingStatus); return ( @@ -65,7 +69,7 @@ const ApplicantIndex: NextPage = () => { - {getListHeadingByStatus('all', allApplicationStatuses)} + {getListHeadingByStatus('all', ALL_APPLICATION_STATUSES)} {getListHeadingByStatus(APPLICATION_STATUSES.DRAFT, [ @@ -97,13 +101,19 @@ const ApplicantIndex: NextPage = () => { + [APPLICATION_STATUSES.DRAFT].includes(app.status) + )} heading={t(`${translationBase}.draft`)} status={[APPLICATION_STATUSES.DRAFT]} /> @@ -111,6 +121,10 @@ const ApplicantIndex: NextPage = () => { + [APPLICATION_STATUSES.RECEIVED].includes(app.status) + )} heading={t(`${translationBase}.received`)} status={[APPLICATION_STATUSES.RECEIVED]} /> @@ -118,10 +132,18 @@ const ApplicantIndex: NextPage = () => { + [APPLICATION_STATUSES.HANDLING].includes(app.status) + )} heading={t(`${translationBase}.handling`)} status={[APPLICATION_STATUSES.HANDLING]} /> + [APPLICATION_STATUSES.INFO_REQUIRED].includes(app.status) + )} heading={t(`${translationBase}.infoRequired`)} status={[APPLICATION_STATUSES.INFO_REQUIRED]} />