From 1ad52cfb09f8145944e930fcac0e1bbdf1203256 Mon Sep 17 00:00:00 2001 From: Sampo Tawast <5328394+sirtawast@users.noreply.github.com> Date: Tue, 30 Apr 2024 09:45:31 +0300 Subject: [PATCH] feat: prepare handler application index for new ahjo integration (hl-1278) (#2958) * chore: move experimental ahjo button to main header * chore: expose talpa status to application list, filter out ahjo case id * chore: update translations * feat: add index component for new ahjo integration --- .../applications/api/v1/application_views.py | 4 + .../api/v1/serializers/application.py | 1 + .../applications/api/v1/serializers/batch.py | 4 +- .../handler/public/locales/en/common.json | 5 +- .../handler/public/locales/fi/common.json | 5 +- .../handler/public/locales/sv/common.json | 5 +- .../applicationHeader/ApplicationHeader.tsx | 30 --- .../applicationList/ApplicationList.sc.ts | 14 ++ .../applicationList/ApplicationList.tsx | 80 ++++++- .../applicationList/HandlerIndex.tsx | 222 ++++++++++++++++++ .../applicationList/useApplicationListData.ts | 4 + .../batchProcessing/useApplicationsHandled.ts | 2 + .../handler/src/components/header/Header.tsx | 9 + .../header/TemporaryAhjoModeSwitch.tsx | 46 ++++ .../src/components/header/useHeader.ts | 23 +- .../handler/src/hooks/useApplicationsQuery.ts | 5 +- frontend/benefit/handler/src/pages/index.tsx | 11 +- .../benefit/shared/src/types/application.d.ts | 4 + 18 files changed, 428 insertions(+), 46 deletions(-) create mode 100644 frontend/benefit/handler/src/components/applicationList/HandlerIndex.tsx create mode 100644 frontend/benefit/handler/src/components/header/TemporaryAhjoModeSwitch.tsx diff --git a/backend/benefit/applications/api/v1/application_views.py b/backend/benefit/applications/api/v1/application_views.py index 1f2689507d..9cfe0e5c8c 100755 --- a/backend/benefit/applications/api/v1/application_views.py +++ b/backend/benefit/applications/api/v1/application_views.py @@ -287,6 +287,10 @@ def _get_simplified_queryset(self, request, context) -> QuerySet: should_filter_archived = request.query_params.get("filter_archived") == "1" qs = qs.filter(archived=should_filter_archived) + ahjo_cases = request.query_params.get("ahjo_case") == "1" + if ahjo_cases: + qs = qs.filter(ahjo_case_id__isnull=False, ahjo_case_id__gt="") + return qs def _get_attachment(self, attachment_pk): diff --git a/backend/benefit/applications/api/v1/serializers/application.py b/backend/benefit/applications/api/v1/serializers/application.py index ecf8ee333f..34a68241e4 100755 --- a/backend/benefit/applications/api/v1/serializers/application.py +++ b/backend/benefit/applications/api/v1/serializers/application.py @@ -1608,6 +1608,7 @@ class Meta(BaseApplicationSerializer.Meta): "pay_subsidies", "training_compensations", "batch", + "talpa_status", "create_application_for_company", "latest_decision_comment", "handled_at", diff --git a/backend/benefit/applications/api/v1/serializers/batch.py b/backend/benefit/applications/api/v1/serializers/batch.py index 39b377a616..f65372ff39 100755 --- a/backend/benefit/applications/api/v1/serializers/batch.py +++ b/backend/benefit/applications/api/v1/serializers/batch.py @@ -143,8 +143,10 @@ def _update_applications(self, application_batch, applications): class ApplicationBatchListSerializer(ApplicationBatchSerializer): def to_representation(self, instance): representation = super().to_representation(instance) + + # Do not include applications that have been sent to Ahjo applications = BatchApplicationSerializer( - Application.objects.filter(batch=instance), + Application.objects.filter(batch=instance, ahjo_case_id__isnull=True), many=True, ).data representation["applications"] = applications diff --git a/frontend/benefit/handler/public/locales/en/common.json b/frontend/benefit/handler/public/locales/en/common.json index 40003dd564..2f5517cf68 100644 --- a/frontend/benefit/handler/public/locales/en/common.json +++ b/frontend/benefit/handler/public/locales/en/common.json @@ -188,6 +188,7 @@ "rejected": "Ei yhtään käsiteltyä kielteistä hakemusta.", "received": "Ei yhtään saapunutta hakemusta.", "archived": "Ei yhtään arkistoitua hakemusta.", + "accepted,rejected": "Ei yhtään päätettävänä olevaa hakemusta.", "additional_information_needed": "Ei yhtään lisätietoja odottavaa hakemusta.", "all": "Ei yhtään hakemusta.", "draft": "Ei yhtään luonnosta." @@ -201,7 +202,9 @@ "accepted": "Myönteiset", "rejected": "Kielteiset", "infoRequired": "Odottaa lisätietoja", - "decisions": "päätökset" + "decisions": "päätökset", + "pending": "Päätettävänä", + "inPayment": "Maksussa" }, "errors": { "fetch": { diff --git a/frontend/benefit/handler/public/locales/fi/common.json b/frontend/benefit/handler/public/locales/fi/common.json index df1fb1a9d1..5961b83510 100644 --- a/frontend/benefit/handler/public/locales/fi/common.json +++ b/frontend/benefit/handler/public/locales/fi/common.json @@ -188,6 +188,7 @@ "rejected": "Ei yhtään käsiteltyä kielteistä hakemusta.", "received": "Ei yhtään saapunutta hakemusta.", "archived": "Ei yhtään arkistoitua hakemusta.", + "accepted,rejected": "Ei yhtään päätettävänä olevaa hakemusta.", "additional_information_needed": "Ei yhtään lisätietoja odottavaa hakemusta.", "all": "Ei yhtään hakemusta.", "draft": "Ei yhtään luonnosta." @@ -201,7 +202,9 @@ "accepted": "Myönteiset", "rejected": "Kielteiset", "infoRequired": "Odottaa lisätietoja", - "decisions": "päätökset" + "decisions": "päätökset", + "pending": "Päätettävänä", + "inPayment": "Maksussa" }, "errors": { "fetch": { diff --git a/frontend/benefit/handler/public/locales/sv/common.json b/frontend/benefit/handler/public/locales/sv/common.json index 40003dd564..2f5517cf68 100644 --- a/frontend/benefit/handler/public/locales/sv/common.json +++ b/frontend/benefit/handler/public/locales/sv/common.json @@ -188,6 +188,7 @@ "rejected": "Ei yhtään käsiteltyä kielteistä hakemusta.", "received": "Ei yhtään saapunutta hakemusta.", "archived": "Ei yhtään arkistoitua hakemusta.", + "accepted,rejected": "Ei yhtään päätettävänä olevaa hakemusta.", "additional_information_needed": "Ei yhtään lisätietoja odottavaa hakemusta.", "all": "Ei yhtään hakemusta.", "draft": "Ei yhtään luonnosta." @@ -201,7 +202,9 @@ "accepted": "Myönteiset", "rejected": "Kielteiset", "infoRequired": "Odottaa lisätietoja", - "decisions": "päätökset" + "decisions": "päätökset", + "pending": "Päätettävänä", + "inPayment": "Maksussa" }, "errors": { "fetch": { diff --git a/frontend/benefit/handler/src/components/applicationHeader/ApplicationHeader.tsx b/frontend/benefit/handler/src/components/applicationHeader/ApplicationHeader.tsx index 14b1565006..c63c237197 100644 --- a/frontend/benefit/handler/src/components/applicationHeader/ApplicationHeader.tsx +++ b/frontend/benefit/handler/src/components/applicationHeader/ApplicationHeader.tsx @@ -8,11 +8,6 @@ import * as React from 'react'; import Container from 'shared/components/container/Container'; import { getFullName } from 'shared/utils/application.utils'; import { convertToUIDateFormat, formatDate } from 'shared/utils/date.utils'; -import { - getLocalStorageItem, - removeLocalStorageItem, - setLocalStorageItem, -} from 'shared/utils/localstorage.utils'; import { $NoticeBar } from '../applicationReview/ApplicationReview.sc'; import { @@ -30,20 +25,6 @@ type ApplicationReviewProps = { isApplicationReadOnly: boolean; }; -const toggleNewAhjoMode = (): void => { - // eslint-disable-next-line no-alert - const confirm = window.confirm( - 'Kokeile Ahjo-integraation käyttöliittymää? Vain testiympäristöihin, älä käytä tuotannossa!' - ); - if (!confirm) return; - if (getLocalStorageItem('newAhjoMode') !== '1') { - setLocalStorageItem('newAhjoMode', '1'); - } else { - removeLocalStorageItem('newAhjoMode'); - } - window.location.reload(); -}; - const ApplicationHeader: React.FC = ({ data, isApplicationReadOnly, @@ -110,17 +91,6 @@ const ApplicationHeader: React.FC = ({ {data.submittedAt && formatDate(new Date(data.submittedAt))} - <$ItemWrapper> - - <$Col> diff --git a/frontend/benefit/handler/src/components/applicationList/ApplicationList.sc.ts b/frontend/benefit/handler/src/components/applicationList/ApplicationList.sc.ts index a62089154a..e6dd18a386 100644 --- a/frontend/benefit/handler/src/components/applicationList/ApplicationList.sc.ts +++ b/frontend/benefit/handler/src/components/applicationList/ApplicationList.sc.ts @@ -20,3 +20,17 @@ export const $CellContent = styled.div` align-items: center; background-color: ${(props) => props.theme.colors.white}; `; + +type TagWrapperProps = { + $colors: { + background: string; + text: string; + }; +}; + +export const $TagWrapper = styled.div` + #hds-tag { + background: ${(props) => props.$colors.background}; + color: ${(props) => props.$colors.text}; + } +`; diff --git a/frontend/benefit/handler/src/components/applicationList/ApplicationList.tsx b/frontend/benefit/handler/src/components/applicationList/ApplicationList.tsx index 5cb62c6fb1..14a92973e2 100644 --- a/frontend/benefit/handler/src/components/applicationList/ApplicationList.tsx +++ b/frontend/benefit/handler/src/components/applicationList/ApplicationList.tsx @@ -1,5 +1,3 @@ -import 'react-loading-skeleton/dist/skeleton.css'; - import { ALL_APPLICATION_STATUSES, ROUTES } from 'benefit/handler/constants'; import { ApplicationListTableColumns, @@ -18,7 +16,12 @@ import { } from 'shared/utils/date.utils'; import { useTheme } from 'styled-components'; -import { $CellContent, $EmptyHeading, $Heading } from './ApplicationList.sc'; +import { + $CellContent, + $EmptyHeading, + $Heading, + $TagWrapper, +} from './ApplicationList.sc'; import { useApplicationList } from './useApplicationList'; export interface ApplicationListProps { @@ -64,10 +67,60 @@ const ApplicationList: React.FC = ({ status.includes(APPLICATION_STATUSES.HANDLING) && !isAllStatuses, infoRequired: status.includes(APPLICATION_STATUSES.INFO_REQUIRED) && !isAllStatuses, + accepted: + status.includes(APPLICATION_STATUSES.ACCEPTED) && !isAllStatuses, + rejected: + status.includes(APPLICATION_STATUSES.REJECTED) && !isAllStatuses, }), [isAllStatuses, status] ); + const getTagStyleForStatus = React.useMemo( + () => + ( + appStatus: APPLICATION_STATUSES + ): { background: string; text: string } => { + let background: string; + let text: string = theme.colors.black; + switch (appStatus) { + case APPLICATION_STATUSES.DRAFT: + background = theme.colors.black50; + text = theme.colors.white; + break; + + case APPLICATION_STATUSES.INFO_REQUIRED: + background = theme.colors.alertLight; + break; + + case APPLICATION_STATUSES.RECEIVED: + background = theme.colors.black20; + break; + + case APPLICATION_STATUSES.ACCEPTED: + background = theme.colors.tramLight; + break; + + case APPLICATION_STATUSES.REJECTED: + background = theme.colors.brickMediumLight; + break; + + case APPLICATION_STATUSES.CANCELLED: + background = theme.colors.alertDark; + break; + + case APPLICATION_STATUSES.HANDLING: + background = theme.colors.infoLight; + break; + + default: + background = theme.colors.black40; + break; + } + return { background, text }; + }, + [theme.colors] + ); + const columns = React.useMemo(() => { const cols: ApplicationListTableColumns[] = [ { @@ -134,12 +187,16 @@ const ApplicationList: React.FC = ({ }); } - if (isAllStatuses) { + if ( + isVisibleOnlyForStatus.accepted || + isVisibleOnlyForStatus.rejected || + isAllStatuses + ) { cols.push({ transform: ({ status: applicationStatus, }: ApplicationListTableTransforms) => ( -
+ <$TagWrapper $colors={getTagStyleForStatus(applicationStatus)}> {t( `common:applications.list.columns.applicationStatuses.${String( @@ -147,7 +204,7 @@ const ApplicationList: React.FC = ({ )}` )} -
+ ), headerName: getHeader('applicationStatus'), key: 'status', @@ -219,7 +276,15 @@ const ApplicationList: React.FC = ({ }); return cols.filter(Boolean); - }, [t, getHeader, status, theme, isAllStatuses, isVisibleOnlyForStatus]); + }, [ + t, + getHeader, + status, + theme, + isAllStatuses, + isVisibleOnlyForStatus, + getTagStyleForStatus, + ]); if (isLoading) { return ( @@ -240,6 +305,7 @@ const ApplicationList: React.FC = ({ } const statusAsString = isAllStatuses ? 'all' : status.join(','); + return (
{list.length > 0 ? ( diff --git a/frontend/benefit/handler/src/components/applicationList/HandlerIndex.tsx b/frontend/benefit/handler/src/components/applicationList/HandlerIndex.tsx new file mode 100644 index 0000000000..acf7baab9c --- /dev/null +++ b/frontend/benefit/handler/src/components/applicationList/HandlerIndex.tsx @@ -0,0 +1,222 @@ +import { ALL_APPLICATION_STATUSES } from 'benefit/handler/constants'; +import FrontPageProvider from 'benefit/handler/context/FrontPageProvider'; +import { APPLICATION_STATUSES } from 'benefit-shared/constants'; +import { ApplicationListItemData } from 'benefit-shared/types/application'; +import { LoadingSpinner, Tabs } from 'hds-react'; +import { useRouter } from 'next/router'; +import * as React from 'react'; +import Container from 'shared/components/container/Container'; +import { useTheme } from 'styled-components'; + +import { $BackgroundWrapper } from '../layout/Layout'; +import MainIngress from '../mainIngress/MainIngress'; +import ApplicationList from './ApplicationList'; +import { useApplicationList } from './useApplicationList'; + +export interface ApplicationListProps { + layoutBackgroundColor: string; + list?: ApplicationListItemData[]; + isLoading: boolean; +} +const translationBase = 'common:applications.list.headings'; + +const HandlerIndex: React.FC = ({ + // heading, + // status, + layoutBackgroundColor, + list = [], + isLoading = true, +}) => { + const { t } = useApplicationList(); + + const theme = useTheme(); + + const getHeadingTranslation = ( + headingStatus: APPLICATION_STATUSES | 'all' | 'pending' | 'inPayment' + ): string => t(`${translationBase}.${headingStatus}`); + + const getTabCountPending = (): number => + list.filter( + (app: ApplicationListItemData) => + app.talpaStatus === 'not_sent_to_talpa' && + app.ahjoCaseId && + [APPLICATION_STATUSES.ACCEPTED, APPLICATION_STATUSES.REJECTED].includes( + app.status + ) + ).length; + + const getTabCountInPayment = (): number => + list.filter( + (app: ApplicationListItemData) => + app.talpaStatus !== 'not_sent_to_talpa' && + [APPLICATION_STATUSES.ACCEPTED].includes(app.status) + ).length; + + const getTabCount = ( + statuses: APPLICATION_STATUSES[], + handled?: 'inPayment' | 'pending' + ): number => { + if (handled === 'pending') return getTabCountPending(); + if (handled === 'inPayment') return getTabCountInPayment(); + return list.filter((app: ApplicationListItemData) => + statuses.includes(app.status) + ).length; + }; + + const getListHeadingByStatus = ( + headingStatus: APPLICATION_STATUSES | 'all' | 'pending' | 'inPayment', + statuses: APPLICATION_STATUSES[] + ): string => + list && list?.length > 0 + ? `${getHeadingTranslation(headingStatus)} (${getTabCount( + statuses, + headingStatus as 'inPayment' | 'pending' + )})` + : getHeadingTranslation(headingStatus); + + const router = useRouter(); + const { tab } = router.query; + const [activeTab, setActiveTab] = React.useState(null); + + React.useEffect(() => { + if (!router.isReady) return; + setActiveTab(parseInt(tab as string, 10) || 0); + }, [router.isReady, tab]); + + if (activeTab === null) { + return ( +
+ +
+ ); + } + + return ( + + <$BackgroundWrapper backgroundColor={layoutBackgroundColor}> + + + + + + {getListHeadingByStatus('all', ALL_APPLICATION_STATUSES)} + + + {getListHeadingByStatus(APPLICATION_STATUSES.DRAFT, [ + APPLICATION_STATUSES.DRAFT, + ])} + + + {getListHeadingByStatus(APPLICATION_STATUSES.RECEIVED, [ + APPLICATION_STATUSES.RECEIVED, + ])} + + + {getListHeadingByStatus(APPLICATION_STATUSES.HANDLING, [ + APPLICATION_STATUSES.HANDLING, + APPLICATION_STATUSES.INFO_REQUIRED, + ])} + + + {getListHeadingByStatus('pending', [ + APPLICATION_STATUSES.ACCEPTED, + APPLICATION_STATUSES.REJECTED, + ])} + + + {getListHeadingByStatus('inPayment', [ + APPLICATION_STATUSES.ACCEPTED, + ])} + + + + + + + + + + [APPLICATION_STATUSES.DRAFT].includes(app.status) + )} + heading={t(`${translationBase}.draft`)} + status={[APPLICATION_STATUSES.DRAFT]} + /> + + + + + [APPLICATION_STATUSES.RECEIVED].includes(app.status) + )} + heading={t(`${translationBase}.received`)} + status={[APPLICATION_STATUSES.RECEIVED]} + /> + + + + + [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]} + /> + + + + + [ + APPLICATION_STATUSES.ACCEPTED, + APPLICATION_STATUSES.REJECTED, + ].includes(app.status) && + app.talpaStatus === 'not_sent_to_talpa' && + app.ahjoCaseId + )} + heading={t(`${translationBase}.pending`)} + status={[ + APPLICATION_STATUSES.ACCEPTED, + APPLICATION_STATUSES.REJECTED, + ]} + /> + + + + + [APPLICATION_STATUSES.ACCEPTED].includes(app.status) && + app.talpaStatus !== 'not_sent_to_talpa' + )} + heading={t(`${translationBase}.inPayment`)} + status={[APPLICATION_STATUSES.ACCEPTED]} + /> + + + + + + ); +}; + +export default HandlerIndex; diff --git a/frontend/benefit/handler/src/components/applicationList/useApplicationListData.ts b/frontend/benefit/handler/src/components/applicationList/useApplicationListData.ts index a658fd0699..4203a3bddc 100644 --- a/frontend/benefit/handler/src/components/applicationList/useApplicationListData.ts +++ b/frontend/benefit/handler/src/components/applicationList/useApplicationListData.ts @@ -36,6 +36,8 @@ const useApplicationListData = ( status: applicationStatus, unread_messages_count, batch, + talpa_status, + ahjo_case_id, application_origin: applicationOrigin, } = application; @@ -60,6 +62,8 @@ const useApplicationListData = ( unreadMessagesCount: unread_messages_count ?? 0, batch: batch ?? null, applicationOrigin, + talpaStatus: talpa_status, + ahjoCaseId: ahjo_case_id, }; } ); diff --git a/frontend/benefit/handler/src/components/batchProcessing/useApplicationsHandled.ts b/frontend/benefit/handler/src/components/batchProcessing/useApplicationsHandled.ts index b915e381c9..f2aac70091 100644 --- a/frontend/benefit/handler/src/components/batchProcessing/useApplicationsHandled.ts +++ b/frontend/benefit/handler/src/components/batchProcessing/useApplicationsHandled.ts @@ -41,6 +41,7 @@ const useApplicationsHandled = ( application_number: applicationNum, status: appStatus, batch, + talpa_status, } = application; return { @@ -54,6 +55,7 @@ const useApplicationsHandled = ( handledAt: convertToUIDateFormat(handled_at) || '-', dataReceived: getBatchDataReceived(status, batch?.created_at), applicationNum, + talpaStatus: talpa_status, }; }); diff --git a/frontend/benefit/handler/src/components/header/Header.tsx b/frontend/benefit/handler/src/components/header/Header.tsx index 44a815e481..a2fcb61314 100644 --- a/frontend/benefit/handler/src/components/header/Header.tsx +++ b/frontend/benefit/handler/src/components/header/Header.tsx @@ -3,6 +3,7 @@ import useLogin from 'benefit/handler/hooks/useLogin'; import useLogout from 'benefit/handler/hooks/useLogout'; import useUserQuery from 'benefit/handler/hooks/useUserQuery'; import noop from 'lodash/noop'; +import dynamic from 'next/dynamic'; import { useRouter } from 'next/router'; import * as React from 'react'; import BaseHeader from 'shared/components/header/Header'; @@ -24,9 +25,17 @@ const Header: React.FC = () => { const { asPath } = router; const isLoginPage = asPath?.startsWith(ROUTES.LOGIN); + const TemporaryAhjoModeSwitch = dynamic( + () => import('benefit/handler/components/header/TemporaryAhjoModeSwitch'), + { + ssr: false, + } + ); + return ( ]} titleUrl={ROUTES.HOME} skipToContentLabel={t('common:header.linkSkipToContent')} menuToggleAriaLabel={t('common:header.menuToggleAriaLabel')} diff --git a/frontend/benefit/handler/src/components/header/TemporaryAhjoModeSwitch.tsx b/frontend/benefit/handler/src/components/header/TemporaryAhjoModeSwitch.tsx new file mode 100644 index 0000000000..3f6cab116c --- /dev/null +++ b/frontend/benefit/handler/src/components/header/TemporaryAhjoModeSwitch.tsx @@ -0,0 +1,46 @@ +import { useDetermineAhjoMode } from 'benefit/handler/hooks/useDetermineAhjoMode'; +import { Button } from 'hds-react'; +import React from 'react'; +import { + removeLocalStorageItem, + setLocalStorageItem, +} from 'shared/utils/localstorage.utils'; + +const toggleNewAhjoMode = (isNewMode: boolean): void => { + // eslint-disable-next-line no-alert + const confirm = isNewMode + ? // eslint-disable-next-line no-alert + window.confirm( + 'Haluatko palata vanhaan koontipohjaiseen käyttöliittymään?' + ) + : // eslint-disable-next-line no-alert + window.confirm( + 'Haluatko kokeilla uutta Ahjo-integraation käyttöliittymää? Vain testiympäristöihin, älä käytä tuotannossa!' + ); + if (!confirm) return; + if (!isNewMode) { + setLocalStorageItem('newAhjoMode', '1'); + } else { + removeLocalStorageItem('newAhjoMode'); + } + window.location.reload(); +}; + +const TemporaryAhjoModeSwitch: React.FC = () => { + const isNewAhjoMode = useDetermineAhjoMode(); + return ( + + ); +}; + +export default TemporaryAhjoModeSwitch; diff --git a/frontend/benefit/handler/src/components/header/useHeader.ts b/frontend/benefit/handler/src/components/header/useHeader.ts index 22183fc91d..77a3dfc3c1 100644 --- a/frontend/benefit/handler/src/components/header/useHeader.ts +++ b/frontend/benefit/handler/src/components/header/useHeader.ts @@ -1,5 +1,6 @@ import { ROUTES } from 'benefit/handler/constants'; import AppContext from 'benefit/handler/context/AppContext'; +import { useDetermineAhjoMode } from 'benefit/handler/hooks/useDetermineAhjoMode'; import { useRouter } from 'next/router'; import { TFunction, useTranslation } from 'next-i18next'; import React from 'react'; @@ -23,14 +24,15 @@ const useHeader = (): ExtendedComponentProps => { const { t } = useTranslation(); const router = useRouter(); const { isNavigationVisible } = React.useContext(AppContext); + const isNewAhjoMode = useDetermineAhjoMode(); const languageOptions = React.useMemo( (): OptionType[] => getLanguageOptions(t, 'supportedLanguages'), [t] ); - const navigationItems = React.useMemo( - (): NavigationItem[] => [ + const items = { + default: [ { label: t('common:header.navigation.applications'), url: ROUTES.HOME }, { label: t('common:header.navigation.batches'), @@ -45,7 +47,22 @@ const useHeader = (): ExtendedComponentProps => { url: ROUTES.APPLICATIONS_REPORTS, }, ], - [t] + newAhjo: [ + { label: t('common:header.navigation.applications'), url: ROUTES.HOME }, + { + label: t('common:header.navigation.archive'), + url: ROUTES.APPLICATIONS_ARCHIVE, + }, + { + label: t('common:header.navigation.reports'), + url: ROUTES.APPLICATIONS_REPORTS, + }, + ], + }; + + const navigationItems = React.useMemo( + (): NavigationItem[] => (isNewAhjoMode ? items.newAhjo : items.default), + [items.default, items.newAhjo, isNewAhjoMode] ); const handleLanguageChange = ( diff --git a/frontend/benefit/handler/src/hooks/useApplicationsQuery.ts b/frontend/benefit/handler/src/hooks/useApplicationsQuery.ts index 8397922039..9601fe6c28 100644 --- a/frontend/benefit/handler/src/hooks/useApplicationsQuery.ts +++ b/frontend/benefit/handler/src/hooks/useApplicationsQuery.ts @@ -9,7 +9,8 @@ const useApplicationsQuery = ( status: string[], orderBy = 'id', excludeBatched = false, - filterArchived = false + filterArchived = false, + filterAhjoCaseId = false ): UseQueryResult => { const { axios, handleResponse } = useBackendAPI(); const { t } = useTranslation(); @@ -28,9 +29,11 @@ const useApplicationsQuery = ( order_by: string; exclude_batched?: '1'; filter_archived?: '1'; + ahjo_case?: '0' | '1'; } = { status: status.join(','), order_by: orderBy, + ahjo_case: filterAhjoCaseId ? '1' : '0', }; if (excludeBatched) { diff --git a/frontend/benefit/handler/src/pages/index.tsx b/frontend/benefit/handler/src/pages/index.tsx index ca283e825b..0e2d5c05c3 100644 --- a/frontend/benefit/handler/src/pages/index.tsx +++ b/frontend/benefit/handler/src/pages/index.tsx @@ -3,6 +3,7 @@ import ApplicationsHandled from 'benefit/handler/components/batchProcessing/Appl import MainIngress from 'benefit/handler/components/mainIngress/MainIngress'; import AppContext from 'benefit/handler/context/AppContext'; import FrontPageProvider from 'benefit/handler/context/FrontPageProvider'; +import { useDetermineAhjoMode } from 'benefit/handler/hooks/useDetermineAhjoMode'; import { APPLICATION_STATUSES } from 'benefit-shared/constants'; import { ApplicationListItemData } from 'benefit-shared/types/application'; import { LoadingSpinner, Tabs } from 'hds-react'; @@ -14,6 +15,7 @@ import { useEffect } from 'react'; import Container from 'shared/components/container/Container'; import theme from 'shared/styles/theme'; +import HandlerIndex from '../components/applicationList/HandlerIndex'; import { useApplicationList } from '../components/applicationList/useApplicationList'; import { useApplicationListData } from '../components/applicationList/useApplicationListData'; import { $BackgroundWrapper } from '../components/layout/Layout'; @@ -45,6 +47,7 @@ const ApplicantIndex: NextPage = () => { true ); const { t } = useApplicationList(); + const isNewAhjoMode = useDetermineAhjoMode(); const getHeadingTranslation = ( headingStatus: APPLICATION_STATUSES | 'all' @@ -81,7 +84,13 @@ const ApplicantIndex: NextPage = () => { ); } - return ( + return isNewAhjoMode ? ( + + ) : ( <$BackgroundWrapper backgroundColor={layoutBackgroundColor}> diff --git a/frontend/benefit/shared/src/types/application.d.ts b/frontend/benefit/shared/src/types/application.d.ts index c3c11accb6..b732c5b5b3 100644 --- a/frontend/benefit/shared/src/types/application.d.ts +++ b/frontend/benefit/shared/src/types/application.d.ts @@ -446,6 +446,8 @@ export type ApplicationData = { action?: APPLICATION_ACTIONS; company_contact_person_first_name: string; company_contact_person_last_name: string; + talpa_status: TALPA_STATUSES; + ahjo_case_id: string; }; export type EmployeeData = { @@ -538,6 +540,8 @@ export type ApplicationListItemData = { applicationOrigin?: APPLICATION_ORIGINS; validUntil?: string; contactPersonName?: string; + talpaStatus?: string; + ahjoCaseId?: string; }; export type TextProp = 'textFi' | 'textEn' | 'textSv';