Skip to content

Commit

Permalink
VKT(Backend&Frontend): Get (mocked, fixed) list of examiners to displ…
Browse files Browse the repository at this point in the history
…ay on frontend from backend API [deploy]
  • Loading branch information
pkoivisto committed Oct 3, 2024
1 parent cafb2e5 commit 6a95274
Show file tree
Hide file tree
Showing 12 changed files with 234 additions and 67 deletions.
10 changes: 10 additions & 0 deletions backend/vkt/src/main/java/fi/oph/vkt/api/PublicController.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import fi.oph.vkt.api.dto.PublicEnrollmentDTO;
import fi.oph.vkt.api.dto.PublicEnrollmentInitialisationDTO;
import fi.oph.vkt.api.dto.PublicExamEventDTO;
import fi.oph.vkt.api.dto.PublicExaminerDTO;
import fi.oph.vkt.api.dto.PublicPersonDTO;
import fi.oph.vkt.api.dto.PublicReservationDTO;
import fi.oph.vkt.model.Enrollment;
Expand All @@ -20,6 +21,7 @@
import fi.oph.vkt.service.PublicAuthService;
import fi.oph.vkt.service.PublicEnrollmentService;
import fi.oph.vkt.service.PublicExamEventService;
import fi.oph.vkt.service.PublicExaminerService;
import fi.oph.vkt.service.PublicPersonService;
import fi.oph.vkt.service.PublicReservationService;
import fi.oph.vkt.service.koski.KoskiService;
Expand Down Expand Up @@ -87,11 +89,19 @@ public class PublicController {
@Resource
private FeatureFlagService featureFlagService;

@Resource
private PublicExaminerService publicExaminerService;

@GetMapping(path = "/examEvent")
public List<PublicExamEventDTO> list() {
return publicExamEventService.listExamEvents(ExamLevel.EXCELLENT);
}

@GetMapping(path = "/examiner")
public List<PublicExaminerDTO> listExaminers() {
return publicExaminerService.listExaminers();
}

@PostMapping(path = "/enrollment/reservation/{reservationId:\\d+}")
@ResponseStatus(HttpStatus.CREATED)
public PublicEnrollmentDTO createEnrollment(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package fi.oph.vkt.api.dto;

import fi.oph.vkt.model.type.ExamLanguage;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;
import java.util.List;
import lombok.Builder;
import lombok.NonNull;

@Builder
public record PublicExaminerDTO(
@NonNull @NotNull Long id,
@NonNull @NotNull String lastName,
@NonNull @NotNull String firstName,
@NonNull @NotNull List<ExamLanguage> languages,
@NonNull @NotNull List<PublicMunicipalityDTO> municipalities,
@NonNull @NotNull List<LocalDate> examDates
) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package fi.oph.vkt.api.dto;

import jakarta.validation.constraints.NotNull;
import lombok.Builder;
import lombok.NonNull;

@Builder
public record PublicMunicipalityDTO(@NonNull @NotNull String fi, @NonNull @NotNull String sv) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package fi.oph.vkt.service;

import fi.oph.vkt.api.dto.PublicExaminerDTO;
import fi.oph.vkt.api.dto.PublicMunicipalityDTO;
import fi.oph.vkt.model.type.ExamLanguage;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class PublicExaminerService {

public List<PublicExaminerDTO> listExaminers() {
final PublicMunicipalityDTO helsinki = PublicMunicipalityDTO.builder().fi("Helsinki").sv("Helsingfors").build();
final PublicMunicipalityDTO espoo = PublicMunicipalityDTO.builder().fi("Espoo").sv("Esbo").build();
final PublicMunicipalityDTO vantaa = PublicMunicipalityDTO.builder().fi("Vantaa").sv("Vanda").build();
final PublicMunicipalityDTO kauniainen = PublicMunicipalityDTO.builder().fi("Kauniainen").sv("Grankulla").build();
final List<PublicExaminerDTO> examiners = new ArrayList<>();
examiners.add(
PublicExaminerDTO
.builder()
.id(1L)
.lastName("Laine")
.firstName("Eemeli")
.languages(List.of(ExamLanguage.FI))
.municipalities(List.of(helsinki, espoo, vantaa, kauniainen))
.examDates(List.of())
.build()
);

return examiners;
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
import {
Box,
Paper,
SelectChangeEvent,
TableCell,
TableHead,
TableRow,
} from '@mui/material';
import { Fragment } from 'react';
import { CustomButtonLink, CustomTable, H2, Text } from 'shared/components';
import { Color, Variant } from 'shared/enums';
import {
CustomButtonLink,
CustomCircularProgress,
CustomTable,
H2,
Text,
} from 'shared/components';
import { APIResponseStatus, AppLanguage, Color, Variant } from 'shared/enums';
import { useWindowProperties } from 'shared/hooks';
import { DateUtils } from 'shared/utils';

import { LanguageFilter } from 'components/common/LanguageFilter';
import { usePublicTranslation } from 'configs/i18n';
import {
getCurrentLang,
useCommonTranslation,
usePublicTranslation,
} from 'configs/i18n';
import { useAppDispatch, useAppSelector } from 'configs/redux';
import { ExamLanguage } from 'enums/app';
import { PublicExaminer } from 'interfaces/publicExaminer';
Expand Down Expand Up @@ -50,6 +61,7 @@ const DesktopExaminerRow = ({
const { t } = usePublicTranslation({
keyPrefix: 'vkt.component.publicExaminerListing',
});
const appLanguage = getCurrentLang();

return (
<TableRow sx={{ verticalAlign: 'text-top' }}>
Expand All @@ -61,7 +73,13 @@ const DesktopExaminerRow = ({
</TableCell>
<TableCell>
<Text>
{municipalities.length > 0 ? municipalities.join(', ') : ''}
{municipalities.length > 0
? municipalities
.map(({ fi, sv }) =>
appLanguage === AppLanguage.Swedish ? sv : fi,
)
.join(', ')
: ''}
</Text>
</TableCell>
<TableCell>
Expand Down Expand Up @@ -106,8 +124,7 @@ const getRowDetails = ({
};

export const PublicExaminerListing = () => {
// TODO Kick off API request & display content based on request status
const { languageFilter } = useAppSelector(publicExaminerSelector);
const { languageFilter, status } = useAppSelector(publicExaminerSelector);
const filteredExaminers = useAppSelector(selectFilteredPublicExaminers);
const dispatch = useAppDispatch();

Expand All @@ -117,23 +134,43 @@ export const PublicExaminerListing = () => {
);
};

return (
<Paper elevation={3} className="public-examiner-listing">
<div className="columns">
<div className="grow">
<H2>Ota yhteyttä tutkinnon vastaanottajiin</H2>
</div>
</div>
<LanguageFilter
value={languageFilter}
onChange={handleLanguageFilterChange}
/>
<CustomTable
className="table-layout-auto"
data={filteredExaminers}
getRowDetails={getRowDetails}
header={<PublicExaminerListingHeader />}
/>
</Paper>
);
const translateCommon = useCommonTranslation();

switch (status) {
case APIResponseStatus.NotStarted:
case APIResponseStatus.InProgress:
return <CustomCircularProgress color={Color.Secondary} />;
case APIResponseStatus.Cancelled:
case APIResponseStatus.Error:
return (
<Box
minHeight="10vh"
display="flex"
justifyContent="center"
alignItems="center"
>
<H2>{translateCommon('errors.loadingFailed')}</H2>
</Box>
);
case APIResponseStatus.Success:
return (
<Paper elevation={3} className="public-examiner-listing">
<div className="columns">
<div className="grow">
<H2>Ota yhteyttä tutkinnon vastaanottajiin</H2>
</div>
</div>
<LanguageFilter
value={languageFilter}
onChange={handleLanguageFilterChange}
/>
<CustomTable
className="table-layout-auto"
data={filteredExaminers}
getRowDetails={getRowDetails}
header={<PublicExaminerListingHeader />}
/>
</Paper>
);
}
};
1 change: 1 addition & 0 deletions frontend/packages/vkt/src/enums/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export enum APIEndpoints {
PublicAuthLogin = '/vkt/api/v1/auth/login/:examEventId/:type?locale=:locale',
PublicAuthLogout = '/vkt/api/v1/auth/logout',
PublicExamEvent = '/vkt/api/v1/examEvent',
PublicExaminer = '/vkt/api/v1/examiner',
PublicEnrollment = '/vkt/api/v1/enrollment',
PublicReservation = '/vkt/api/v1/reservation',
PublicEducation = '/vkt/api/v1/education',
Expand Down
16 changes: 14 additions & 2 deletions frontend/packages/vkt/src/interfaces/publicExaminer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,26 @@ import { WithId } from 'shared/interfaces';
import { ExamLanguage } from 'enums/app';
import { APIResponseStatus } from 'shared/enums';

interface PublicMunicipality {
fi: string;
sv: string;
}

export interface PublicExaminer extends WithId {
name: string;
language: ExamLanguage;
// TODO Municipality could instead be something like { fi: 'Helsinki', sv: 'Helsingfors' } ?
municipalities: Array<string>;
municipalities: Array<PublicMunicipality>;
examDates: Array<Dayjs>;
}

export interface PublicExaminerResponse extends WithId {
lastName: string;
firstName: string;
languages: Array<ExamLanguage>;
municipalities: Array<PublicMunicipality>;
examDates: Array<string>;
}

export interface PublicExaminerState {
status: APIResponseStatus;
examiners: Array<PublicExaminer>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { Box, Grid } from '@mui/material';
import { FC } from 'react';
import { FC, useEffect } from 'react';
import { H1, HeaderSeparator, Text } from 'shared/components';

import { PublicExaminerListing } from 'components/publicExaminerListing/PublicExaminerListing';
import { usePublicTranslation } from 'configs/i18n';
import { useAppDispatch } from 'configs/redux';
import { loadPublicExaminers } from 'redux/reducers/publicExaminer';

export const PublicGoodAndSatisfactoryLevelLandingPage: FC = () => {
const { t } = usePublicTranslation({
keyPrefix: 'vkt.component.goodAndSatisfactoryLevel',
});
const dispatch = useAppDispatch();
useEffect(() => {
dispatch(loadPublicExaminers());
}, [dispatch]);

return (
<Box className="public-homepage">
Expand Down
58 changes: 19 additions & 39 deletions frontend/packages/vkt/src/redux/reducers/publicExaminer.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,29 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import dayjs from 'dayjs';
import { APIResponseStatus } from 'shared/enums';

import { ExamLanguage } from 'enums/app';
import { PublicExaminerState } from 'interfaces/publicExaminer';
import { PublicExaminer, PublicExaminerState } from 'interfaces/publicExaminer';

const initialState: PublicExaminerState = {
status: APIResponseStatus.Success,
examiners: [
{
id: 1,
name: 'Eemeli Laine',
language: ExamLanguage.FI,
municipalities: ['Helsinki', 'Espoo', 'Vantaa', 'Kauniainen'],
examDates: [],
},
{
id: 2,
name: 'Kerttu Virtanen',
language: ExamLanguage.SV,
municipalities: ['Vaasa'],
examDates: [],
},
{
id: 3,
name: 'Aapo Mäkinen',
language: ExamLanguage.ALL,
municipalities: ['Tampere'],
examDates: [dayjs('2024-10-17')],
},
{
id: 4,
name: 'Veera Salminen',
language: ExamLanguage.FI,
municipalities: ['Kajaani'],
examDates: [
dayjs('2024-09-12'),
dayjs('2024-09-13'),
dayjs('2024-09-19'),
dayjs('2024-09-20'),
],
},
],
status: APIResponseStatus.NotStarted,
examiners: [],
languageFilter: ExamLanguage.ALL,
};

const publicExaminerSlice = createSlice({
name: 'publicExaminer',
initialState,
reducers: {
loadPublicExaminers(state) {
state.status = APIResponseStatus.InProgress;
},
rejectPublicExaminers(state) {
state.status = APIResponseStatus.Error;
},
storePublicExaminers(state, action: PayloadAction<Array<PublicExaminer>>) {
state.status = APIResponseStatus.Success;
state.examiners = action.payload;
},
setPublicExaminerLanguageFilter(
state,
action: PayloadAction<ExamLanguage>,
Expand All @@ -59,4 +34,9 @@ const publicExaminerSlice = createSlice({
});

export const publicExaminerReducer = publicExaminerSlice.reducer;
export const { setPublicExaminerLanguageFilter } = publicExaminerSlice.actions;
export const {
loadPublicExaminers,
rejectPublicExaminers,
storePublicExaminers,
setPublicExaminerLanguageFilter,
} = publicExaminerSlice.actions;
2 changes: 2 additions & 0 deletions frontend/packages/vkt/src/redux/sagas/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { watchFeatureFlags } from 'redux/sagas/featureFlags';
import { watchPublicEducation } from 'redux/sagas/publicEducation';
import { watchPublicEnrollments } from 'redux/sagas/publicEnrollment';
import { watchPublicExamEvents } from 'redux/sagas/publicExamEvent';
import { watchPublicExaminers } from 'redux/sagas/publicExaminer';
import { watchFileUpload } from 'redux/sagas/publicFileUpload';
import { watchPublicUser } from 'redux/sagas/publicUser';

Expand All @@ -25,5 +26,6 @@ export default function* rootSaga() {
watchFeatureFlags(),
watchFileUpload(),
watchPublicEducation(),
watchPublicExaminers(),
]);
}
Loading

0 comments on commit 6a95274

Please sign in to comment.