From bb20fb46e4858c6efb5837775babc0b3fbb45c7e Mon Sep 17 00:00:00 2001
From: Jarkko Pesonen <435495+jrkkp@users.noreply.github.com>
Date: Tue, 29 Oct 2024 23:25:28 +0200
Subject: [PATCH] VKT(Frontend & Backend): Enrollment appointment clerk
interface
---
.../api/clerk/ClerkEnrollmentController.java | 6 ++
.../ClerkEnrollmentAppointmentDetails.tsx | 53 +++--------
...lerkEnrollmentAppointmentDetailsFields.tsx | 94 +++++++------------
.../vkt/src/interfaces/clerkEnrollment.ts | 3 +-
...ClerkEnrollmentAppointmentOverviewPage.tsx | 1 -
.../reducers/clerkEnrollmentAppointment.ts | 23 +++++
.../redux/sagas/clerkEnrollmentAppointment.ts | 43 ++++++++-
.../packages/vkt/src/utils/serialization.ts | 10 ++
8 files changed, 128 insertions(+), 105 deletions(-)
diff --git a/backend/vkt/src/main/java/fi/oph/vkt/api/clerk/ClerkEnrollmentController.java b/backend/vkt/src/main/java/fi/oph/vkt/api/clerk/ClerkEnrollmentController.java
index ea8e7f30b..c0d99fe88 100644
--- a/backend/vkt/src/main/java/fi/oph/vkt/api/clerk/ClerkEnrollmentController.java
+++ b/backend/vkt/src/main/java/fi/oph/vkt/api/clerk/ClerkEnrollmentController.java
@@ -95,6 +95,12 @@ public ClerkEnrollmentAppointmentDTO getEnrollmentAppointment(@PathVariable fina
return clerkEnrollmentService.getEnrollmentAppointment(enrollmentAppointmentId);
}
+ @PutMapping(path = "/appointment/{enrollmentAppointmentId:\\d+}")
+ @Operation(tags = TAG_ENROLLMENT, summary = "Update enrollment appointment")
+ public ClerkEnrollmentDTO updateEnrollmentAppointment(@RequestBody @Valid final ClerkEnrollmentUpdateDTO dto) {
+ return clerkEnrollmentService.update(dto);
+ }
+
@GetMapping(path = "/attachment", consumes = ALL_VALUE)
@Operation(tags = TAG_ENROLLMENT, summary = "Download enrollment attachment")
public void attachmentRedirect(final HttpServletResponse response, @RequestParam final String key)
diff --git a/frontend/packages/vkt/src/components/clerkEnrollment/appointment/ClerkEnrollmentAppointmentDetails.tsx b/frontend/packages/vkt/src/components/clerkEnrollment/appointment/ClerkEnrollmentAppointmentDetails.tsx
index 3d68b56df..1437f2a1b 100644
--- a/frontend/packages/vkt/src/components/clerkEnrollment/appointment/ClerkEnrollmentAppointmentDetails.tsx
+++ b/frontend/packages/vkt/src/components/clerkEnrollment/appointment/ClerkEnrollmentAppointmentDetails.tsx
@@ -1,12 +1,11 @@
import { ChangeEvent, useCallback, useEffect, useState } from 'react';
-import { CustomButton, CustomModal } from 'shared/components';
+import { CustomButton } from 'shared/components';
import { APIResponseStatus, Color, Severity, Variant } from 'shared/enums';
import { useDialog, useToast } from 'shared/hooks';
import { StringUtils } from 'shared/utils';
import { ClerkEnrollmentAppointmentDetailsFields } from 'components/clerkEnrollment/appointment/ClerkEnrollmentAppointmentDetailsFields';
import { ControlButtons } from 'components/clerkEnrollment/overview/ControlButtons';
-import { MoveModal } from 'components/clerkEnrollment/overview/MoveModal';
import { useClerkTranslation, useCommonTranslation } from 'configs/i18n';
import { useAppDispatch, useAppSelector } from 'configs/redux';
import { EnrollmentStatus, UIMode } from 'enums/app';
@@ -16,8 +15,8 @@ import { ClerkEnrollmentAppointment } from 'interfaces/clerkEnrollment';
import { PartialExamsAndSkills } from 'interfaces/common/enrollment';
import {
resetClerkEnrollmentDetailsUpdate,
- updateClerkEnrollmentDetails,
-} from 'redux/reducers/clerkEnrollmentDetails';
+ updateClerkEnrollmentAppointment,
+} from 'redux/reducers/clerkEnrollmentAppointment';
import {
changeClerkEnrollmentStatus,
resetClerkEnrollmentStatusChange,
@@ -47,14 +46,10 @@ export const ClerkEnrollmentAppointmentDetails = ({
const [enrollmentDetails, setEnrollmentDetails] = useState<
ClerkEnrollmentAppointment | undefined
>(enrollment);
- const [isMoveModalOpen, setIsOpenModalOpen] = useState(false);
const [hasLocalChanges, setHasLocalChanges] = useState(false);
const [currentUIMode, setCurrentUIMode] = useState(UIMode.View);
const isViewMode = currentUIMode === UIMode.View;
- const handleMoveButtonCLick = () => setIsOpenModalOpen(true);
- const closeMoveModal = () => setIsOpenModalOpen(false);
-
const resetLocalEnrollmentDetails = useCallback(() => {
setEnrollmentDetails(enrollment);
}, [enrollment]);
@@ -140,43 +135,30 @@ export const ClerkEnrollmentAppointmentDetails = ({
return undefined;
}
- let updatedEnrollmentDetails;
- if (
- field === ClerkEnrollmentTextFieldEnum.FirstName ||
- field === ClerkEnrollmentTextFieldEnum.LastName
- ) {
- updatedEnrollmentDetails = {
- ...prevState,
- person: {
- ...prevState.person,
- [field]: fieldValue,
- },
- };
- } else {
- updatedEnrollmentDetails = {
- ...prevState,
- [field]: fieldValue,
- };
- }
-
- return updatedEnrollmentDetails;
+ return {
+ ...prevState,
+ [field]: fieldValue,
+ };
});
};
const handleSaveButtonClick = () => {
dispatch(
- updateClerkEnrollmentDetails({
+ updateClerkEnrollmentAppointment({
enrollment: {
...enrollmentDetails,
understandingSkill:
enrollmentDetails.speechComprehensionPartialExam &&
enrollmentDetails.readingComprehensionPartialExam,
},
- examEvent,
}),
);
};
+ const handleMoveButtonClick = () => {
+ // TODO
+ };
+
const handleEditButtonClick = () => {
resetLocalEnrollmentDetails();
setCurrentUIMode(UIMode.Edit);
@@ -237,15 +219,6 @@ export const ClerkEnrollmentAppointmentDetails = ({
return (
<>
-
-
-
diff --git a/frontend/packages/vkt/src/components/clerkEnrollment/appointment/ClerkEnrollmentAppointmentDetailsFields.tsx b/frontend/packages/vkt/src/components/clerkEnrollment/appointment/ClerkEnrollmentAppointmentDetailsFields.tsx
index 8e5c25a06..c5dcd7483 100644
--- a/frontend/packages/vkt/src/components/clerkEnrollment/appointment/ClerkEnrollmentAppointmentDetailsFields.tsx
+++ b/frontend/packages/vkt/src/components/clerkEnrollment/appointment/ClerkEnrollmentAppointmentDetailsFields.tsx
@@ -19,7 +19,6 @@ import {
import { useDialog } from 'shared/hooks';
import { InputFieldUtils } from 'shared/utils';
-import { ExamEventDetails } from 'components/publicEnrollment/steps/ExamEventDetails';
import {
translateOutsideComponent,
useClerkTranslation,
@@ -330,8 +329,6 @@ export const ClerkEnrollmentAppointmentDetailsFields = ({
const displayPaymentHistory = enrollment.payments.length > 1;
// TODO Remove this flag once digital certificates are available
- const isDigitalCertificateAvailable = false;
-
return (
@@ -375,6 +372,39 @@ export const ClerkEnrollmentAppointmentDetailsFields = ({
)}
/>
+ {!enrollment.digitalCertificateConsent && (
+
+
+ {translateCommon('enrollment.certificateShipping.addressTitle')}
+
+
+
+
+
+
+
+
+ )}
{t('header.previousEnrollment')}
@@ -461,7 +491,6 @@ export const ClerkEnrollmentAppointmentDetailsFields = ({
)}
-
{t('status')}
{t(`enrollmentStatus.${enrollment.status}`)}
@@ -501,63 +530,6 @@ export const ClerkEnrollmentAppointmentDetailsFields = ({
)}
)}
- {isDigitalCertificateAvailable && (
-
-
{t('header.digitalCertificateConsent')}
-
- onCheckboxFieldChange(
- 'digitalCertificateConsent',
- !enrollment.digitalCertificateConsent,
- )
- }
- color={Color.Secondary}
- checked={enrollment.digitalCertificateConsent}
- disabled={editDisabled}
- />
- }
- label={translateCommon('enrollment.certificateShipping.consent')}
- />
-
- )}
-
- {!enrollment.digitalCertificateConsent && (
-
-
- {translateCommon('enrollment.certificateShipping.addressTitle')}
-
-
-
-
-
-
-
-
- )}
{
+ extends Omit {
enrollmentTime: string;
+ payments: Array;
}
diff --git a/frontend/packages/vkt/src/pages/ClerkEnrollmentAppointmentOverviewPage.tsx b/frontend/packages/vkt/src/pages/ClerkEnrollmentAppointmentOverviewPage.tsx
index de5445756..afcfdf762 100644
--- a/frontend/packages/vkt/src/pages/ClerkEnrollmentAppointmentOverviewPage.tsx
+++ b/frontend/packages/vkt/src/pages/ClerkEnrollmentAppointmentOverviewPage.tsx
@@ -27,7 +27,6 @@ export const ClerkEnrollmentAppointmentOverviewPage: FC = () => {
}
}, [dispatch, status, params.enrollmentAppointmentId]);
- console.log('enrollment', enrollment);
return (
diff --git a/frontend/packages/vkt/src/redux/reducers/clerkEnrollmentAppointment.ts b/frontend/packages/vkt/src/redux/reducers/clerkEnrollmentAppointment.ts
index 4d5136c78..d95348a96 100644
--- a/frontend/packages/vkt/src/redux/reducers/clerkEnrollmentAppointment.ts
+++ b/frontend/packages/vkt/src/redux/reducers/clerkEnrollmentAppointment.ts
@@ -2,6 +2,7 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import { APIResponseStatus } from 'shared/enums';
import { ClerkEnrollmentAppointment } from 'interfaces/clerkEnrollment';
+import { ClerkExamEvent } from 'interfaces/clerkExamEvent';
interface ClerkEnrollmentAppointmentState {
status: APIResponseStatus;
@@ -28,16 +29,38 @@ const clerkEnrollmentAppointmentSlice = createSlice({
state.enrollment = action.payload;
state.status = APIResponseStatus.Success;
},
+ storeClerkEnrollmentAppointmentUpdate(
+ state,
+ action: PayloadAction,
+ ) {
+ state.status = APIResponseStatus.Success;
+ state.enrollment = action.payload;
+ },
rejectClerkEnrollmentAppointment(state) {
state.status = APIResponseStatus.Error;
},
+ updateClerkEnrollmentAppointment(
+ state,
+ _action: PayloadAction<{
+ enrollment: ClerkEnrollmentAppointment;
+ examEvent?: ClerkExamEvent;
+ }>,
+ ) {
+ state.status = APIResponseStatus.InProgress;
+ },
+ resetClerkEnrollmentDetailsUpdate(state) {
+ state.status = initialState.status;
+ },
},
});
export const clerkEnrollmentAppointmentReducer =
clerkEnrollmentAppointmentSlice.reducer;
export const {
+ storeClerkEnrollmentAppointmentUpdate,
rejectClerkEnrollmentAppointment,
storeClerkEnrollmentAppointment,
loadClerkEnrollmentAppointment,
+ updateClerkEnrollmentAppointment,
+ resetClerkEnrollmentDetailsUpdate,
} = clerkEnrollmentAppointmentSlice.actions;
diff --git a/frontend/packages/vkt/src/redux/sagas/clerkEnrollmentAppointment.ts b/frontend/packages/vkt/src/redux/sagas/clerkEnrollmentAppointment.ts
index 55406e6be..9a9243e0f 100644
--- a/frontend/packages/vkt/src/redux/sagas/clerkEnrollmentAppointment.ts
+++ b/frontend/packages/vkt/src/redux/sagas/clerkEnrollmentAppointment.ts
@@ -1,17 +1,52 @@
import { PayloadAction } from '@reduxjs/toolkit';
-import { AxiosResponse } from 'axios';
+import { AxiosError, AxiosResponse } from 'axios';
import { call, put, takeLatest } from 'redux-saga/effects';
import axiosInstance from 'configs/axios';
import { APIEndpoints } from 'enums/api';
-import { ClerkEnrollmentAppointmentResponse } from 'interfaces/clerkEnrollment';
+import {
+ ClerkEnrollmentAppointment,
+ ClerkEnrollmentAppointmentResponse,
+} from 'interfaces/clerkEnrollment';
+import { setAPIError } from 'redux/reducers/APIError';
import {
loadClerkEnrollmentAppointment,
rejectClerkEnrollmentAppointment,
storeClerkEnrollmentAppointment,
+ storeClerkEnrollmentAppointmentUpdate,
+ updateClerkEnrollmentAppointment,
} from 'redux/reducers/clerkEnrollmentAppointment';
+import { NotifierUtils } from 'utils/notifier';
import { SerializationUtils } from 'utils/serialization';
+function* updateClerkEnrollmentAppointmentSaga(
+ action: PayloadAction<{
+ enrollment: ClerkEnrollmentAppointment;
+ }>,
+) {
+ const { enrollment } = action.payload;
+
+ try {
+ const apiResponse: AxiosResponse =
+ yield call(
+ axiosInstance.put,
+ APIEndpoints.ClerkEnrollment,
+ SerializationUtils.serializeClerkEnrollmentAppointment(enrollment),
+ );
+ const updatedEnrollment =
+ SerializationUtils.deserializeClerkEnrollmentAppointment(
+ apiResponse.data,
+ );
+
+ yield put(storeClerkEnrollmentAppointmentUpdate(updatedEnrollment));
+ //yield put(storeClerkExamEventOverview(updatedExamEvent));
+ } catch (error) {
+ const errorMessage = NotifierUtils.getAPIErrorMessage(error as AxiosError);
+ yield put(setAPIError(errorMessage));
+ //yield put(rejectClerkEnrollmentDetailsUpdate());
+ }
+}
+
function* loadClerkEnrollmentAppointmentSaga(action: PayloadAction) {
try {
const appointmentId = action.payload;
@@ -30,6 +65,10 @@ function* loadClerkEnrollmentAppointmentSaga(action: PayloadAction) {
}
export function* watchClerkEnrollmentAppointment() {
+ yield takeLatest(
+ updateClerkEnrollmentAppointment.type,
+ updateClerkEnrollmentAppointmentSaga,
+ );
yield takeLatest(
loadClerkEnrollmentAppointment.type,
loadClerkEnrollmentAppointmentSaga,
diff --git a/frontend/packages/vkt/src/utils/serialization.ts b/frontend/packages/vkt/src/utils/serialization.ts
index 467ddb4be..53fee0121 100644
--- a/frontend/packages/vkt/src/utils/serialization.ts
+++ b/frontend/packages/vkt/src/utils/serialization.ts
@@ -4,6 +4,7 @@ import { DateUtils } from 'shared/utils';
import { ExamLanguage } from 'enums/app';
import {
ClerkEnrollment,
+ ClerkEnrollmentAppointment,
ClerkEnrollmentAppointmentResponse,
ClerkEnrollmentContactResponse,
ClerkEnrollmentResponse,
@@ -103,6 +104,15 @@ export class SerializationUtils {
};
}
+ static serializeClerkEnrollmentAppointment(
+ enrollment: ClerkEnrollmentAppointment,
+ ) {
+ return {
+ ...enrollment,
+ enrollmentTime: DateUtils.serializeDate(enrollment.enrollmentTime),
+ };
+ }
+
static deserializeClerkEnrollmentAppointment(
enrollment: ClerkEnrollmentAppointmentResponse,
) {