From 9645463f1e4e70a3ddc42dc450043a0c5bf4fb11 Mon Sep 17 00:00:00 2001 From: Pyry Koivisto Date: Mon, 18 Nov 2024 12:35:09 +0200 Subject: [PATCH] VKT(Frontend): ClerkExaminerListing language filters [deploy] --- .../vkt/public/i18n/fi-FI/examiner.json | 8 ++ .../clerkExaminer/ClerkExaminerListing.tsx | 74 ++++++++++++++----- .../vkt/src/interfaces/clerkListExaminer.ts | 6 ++ .../ClerkGoodAndSatisfactoryLevelPage.tsx | 4 +- .../src/redux/reducers/clerkListExaminer.ts | 32 ++++++-- .../vkt/src/redux/sagas/clerkListExaminer.ts | 12 +-- .../src/redux/selectors/clerkListExaminer.ts | 28 ++++++- 7 files changed, 131 insertions(+), 33 deletions(-) diff --git a/frontend/packages/vkt/public/i18n/fi-FI/examiner.json b/frontend/packages/vkt/public/i18n/fi-FI/examiner.json index 460c54f41..5006a15de 100644 --- a/frontend/packages/vkt/public/i18n/fi-FI/examiner.json +++ b/frontend/packages/vkt/public/i18n/fi-FI/examiner.json @@ -92,6 +92,14 @@ "upcoming": "Tulevat" } }, + "examinerFilter": { + "label": "Näytä seuraavien kielten tutkintosuoritusten vastaanottajat", + "options": { + "ALL": "Molemmat kielet", + "FI": "Suomi", + "SV": "Ruotsi" + } + }, "examinerHomepage": { "heading": "Hyvän ja tyydyttävän taidon kielitutkinnot" }, diff --git a/frontend/packages/vkt/src/components/clerkExaminer/ClerkExaminerListing.tsx b/frontend/packages/vkt/src/components/clerkExaminer/ClerkExaminerListing.tsx index ac2149e88..153cce21a 100644 --- a/frontend/packages/vkt/src/components/clerkExaminer/ClerkExaminerListing.tsx +++ b/frontend/packages/vkt/src/components/clerkExaminer/ClerkExaminerListing.tsx @@ -1,6 +1,10 @@ import { Divider, - SelectChangeEvent, + FormControl, + FormControlLabel, + FormLabel, + Radio, + RadioGroup, TableCell, TableHead, TableRow, @@ -9,18 +13,20 @@ import { Link } from 'react-router-dom'; import { CustomButtonLink, CustomTable, H2, Text } from 'shared/components'; import { Color, Variant } from 'shared/enums'; -import { LanguageFilter } from 'components/common/LanguageFilter'; import { useClerkTranslation, useCommonTranslation, + useExaminerTranslation, useKoodistoMunicipalitiesTranslation, } from 'configs/i18n'; import { useAppDispatch, useAppSelector } from 'configs/redux'; import { AppRoutes, ExamLanguage } from 'enums/app'; import { ExaminerDetails } from 'interfaces/examinerDetails'; -import { setExamEventLanguageFilter } from 'redux/reducers/clerkListExamEvent'; -import { clerkListExamEventsSelector } from 'redux/selectors/clerkListExamEvent'; -import { clerkListExaminerSelector } from 'redux/selectors/clerkListExaminer'; +import { setClerkListExaminerFilters } from 'redux/reducers/clerkListExaminer'; +import { + clerkListExaminerSelector, + selectFilteredExaminers, +} from 'redux/selectors/clerkListExaminer'; import { ExaminerUtils } from 'utils/examiner'; const ClerkExaminerListingHeader = () => { @@ -49,7 +55,7 @@ const ExaminerListingRow = ({ examiner }: { examiner: ExaminerDetails }) => { const translateCommon = useCommonTranslation(); const translateMunicipality = useKoodistoMunicipalitiesTranslation(); - const examinerUrl = AppRoutes.ExaminerDetailsPage.replace( + const examinerUrl = AppRoutes.ExaminerHomePage.replace( /:oid/, `${examiner.oid}`, ); @@ -99,19 +105,54 @@ const getRowDetails = (examiner: ExaminerDetails) => { return ; }; -export const ClerkExaminerListing = () => { - const { t } = useClerkTranslation({ - keyPrefix: 'vkt.component.clerkExaminerListing', +const ExaminerFilter = () => { + const { t } = useExaminerTranslation({ + keyPrefix: 'vkt.component.examinerFilter', }); + const { examLanguage } = useAppSelector(clerkListExaminerSelector).filters; const dispatch = useAppDispatch(); - const { languageFilter } = useAppSelector(clerkListExamEventsSelector); + return ( + + + {t('label')}: + + { + dispatch( + setClerkListExaminerFilters({ + examLanguage: e.target.value as ExamLanguage, + }), + ); + }} + > +
+ {Object.entries(ExamLanguage).map(([key, language]) => { + return ( + } + /> + ); + })} +
+
+
+ ); +}; - const handleLanguageFilterChange = (event: SelectChangeEvent) => { - dispatch(setExamEventLanguageFilter(event.target.value as ExamLanguage)); - }; +export const ClerkExaminerListing = () => { + const { t } = useClerkTranslation({ + keyPrefix: 'vkt.component.clerkExaminerListing', + }); - const { examiners } = useAppSelector(clerkListExaminerSelector); + const examiners = useAppSelector(selectFilteredExaminers); return ( <> @@ -119,10 +160,7 @@ export const ClerkExaminerListing = () => {

{t('title')}

- + ; + filters: ClerkListExaminerFilters; } diff --git a/frontend/packages/vkt/src/pages/ClerkGoodAndSatisfactoryLevelPage.tsx b/frontend/packages/vkt/src/pages/ClerkGoodAndSatisfactoryLevelPage.tsx index 74f0b6e92..174bdb0fd 100644 --- a/frontend/packages/vkt/src/pages/ClerkGoodAndSatisfactoryLevelPage.tsx +++ b/frontend/packages/vkt/src/pages/ClerkGoodAndSatisfactoryLevelPage.tsx @@ -10,7 +10,7 @@ import { useClerkTranslation } from 'configs/i18n'; import { useAppDispatch, useAppSelector } from 'configs/redux'; import { resetClerkExamEventOverview } from 'redux/reducers/clerkExamEventOverview'; import { loadExamEvents } from 'redux/reducers/clerkListExamEvent'; -import { loadExaminers } from 'redux/reducers/clerkListExaminer'; +import { loadClerkListExaminers } from 'redux/reducers/clerkListExaminer'; import { clerkListExamEventsSelector } from 'redux/selectors/clerkListExamEvent'; import { clerkListExaminerSelector } from 'redux/selectors/clerkListExaminer'; @@ -38,7 +38,7 @@ export const ClerkGoodAndSatisfactoryLevelPage: FC = () => { }, [dispatch, examEventsStatus]); useEffect(() => { if (examinerListStatus === APIResponseStatus.NotStarted) { - dispatch(loadExaminers()); + dispatch(loadClerkListExaminers()); } }, [dispatch, examinerListStatus]); diff --git a/frontend/packages/vkt/src/redux/reducers/clerkListExaminer.ts b/frontend/packages/vkt/src/redux/reducers/clerkListExaminer.ts index 15b5da1e1..de04637d6 100644 --- a/frontend/packages/vkt/src/redux/reducers/clerkListExaminer.ts +++ b/frontend/packages/vkt/src/redux/reducers/clerkListExaminer.ts @@ -1,31 +1,51 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit'; import { APIResponseStatus } from 'shared/enums'; -import { ClerkListExaminerState } from 'interfaces/clerkListExaminer'; +import { ExamLanguage } from 'enums/app'; +import { + ClerkListExaminerFilters, + ClerkListExaminerState, +} from 'interfaces/clerkListExaminer'; import { ExaminerDetails } from 'interfaces/examinerDetails'; const initialState: ClerkListExaminerState = { status: APIResponseStatus.NotStarted, examiners: [], + filters: { + examLanguage: ExamLanguage.ALL, + }, }; const clerkListExaminerSlice = createSlice({ name: 'clerkListExaminer', initialState, reducers: { - acceptExaminers(state, action: PayloadAction>) { + acceptClerkListExaminers( + state, + action: PayloadAction>, + ) { state.status = APIResponseStatus.Success; state.examiners = action.payload; }, - loadExaminers(state) { + loadClerkListExaminers(state) { state.status = APIResponseStatus.InProgress; }, - rejectExaminers(state) { + rejectClerkListExaminers(state) { state.status = APIResponseStatus.Error; }, + setClerkListExaminerFilters( + state, + action: PayloadAction, + ) { + state.filters = action.payload; + }, }, }); -export const { acceptExaminers, loadExaminers, rejectExaminers } = - clerkListExaminerSlice.actions; +export const { + acceptClerkListExaminers, + loadClerkListExaminers, + rejectClerkListExaminers, + setClerkListExaminerFilters, +} = clerkListExaminerSlice.actions; export const clerkListExaminerReducer = clerkListExaminerSlice.reducer; diff --git a/frontend/packages/vkt/src/redux/sagas/clerkListExaminer.ts b/frontend/packages/vkt/src/redux/sagas/clerkListExaminer.ts index c2803fb7e..4e9873745 100644 --- a/frontend/packages/vkt/src/redux/sagas/clerkListExaminer.ts +++ b/frontend/packages/vkt/src/redux/sagas/clerkListExaminer.ts @@ -6,9 +6,9 @@ import { APIEndpoints } from 'enums/api'; import { ExaminerDetails } from 'interfaces/examinerDetails'; import { setAPIError } from 'redux/reducers/APIError'; import { - acceptExaminers, - loadExaminers, - rejectExaminers, + acceptClerkListExaminers, + loadClerkListExaminers, + rejectClerkListExaminers, } from 'redux/reducers/clerkListExaminer'; import { NotifierUtils } from 'utils/notifier'; @@ -18,14 +18,14 @@ function* loadExaminersSaga() { axiosInstance.get, APIEndpoints.ClerkExaminer, ); - yield put(acceptExaminers(response.data)); + yield put(acceptClerkListExaminers(response.data)); } catch (error) { const errorMessage = NotifierUtils.getAPIErrorMessage(error as AxiosError); yield put(setAPIError(errorMessage)); - yield put(rejectExaminers()); + yield put(rejectClerkListExaminers()); } } export function* watchListExaminers() { - yield takeLatest(loadExaminers.type, loadExaminersSaga); + yield takeLatest(loadClerkListExaminers.type, loadExaminersSaga); } diff --git a/frontend/packages/vkt/src/redux/selectors/clerkListExaminer.ts b/frontend/packages/vkt/src/redux/selectors/clerkListExaminer.ts index c151d239f..d08e69884 100644 --- a/frontend/packages/vkt/src/redux/selectors/clerkListExaminer.ts +++ b/frontend/packages/vkt/src/redux/selectors/clerkListExaminer.ts @@ -1,6 +1,32 @@ +import { createSelector } from '@reduxjs/toolkit'; + import { RootState } from 'configs/redux'; -import { ClerkListExaminerState } from 'interfaces/clerkListExaminer'; +import { ExamLanguage } from 'enums/app'; +import { + ClerkListExaminerFilters, + ClerkListExaminerState, +} from 'interfaces/clerkListExaminer'; +import { ExaminerDetails } from 'interfaces/examinerDetails'; export const clerkListExaminerSelector = ( state: RootState, ): ClerkListExaminerState => state.clerkListExaminer; + +export const selectFilteredExaminers = createSelector( + (state: RootState) => state.clerkListExaminer.examiners, + (state: RootState) => state.clerkListExaminer.filters, + ( + examiners: Array, + filters: ClerkListExaminerFilters, + ): Array => { + const { examLanguage } = filters; + + if (examLanguage === ExamLanguage.FI) { + return examiners.filter((e) => e.examLanguageFinnish); + } else if (examLanguage === ExamLanguage.SV) { + return examiners.filter((e) => e.examLanguageSwedish); + } else { + return examiners; + } + }, +);