Skip to content

Commit

Permalink
VKT(Frontend & Backend): Enrollment appointment clerk interface
Browse files Browse the repository at this point in the history
  • Loading branch information
jrkkp committed Nov 5, 2024
1 parent 7cf0e92 commit b3327b4
Show file tree
Hide file tree
Showing 15 changed files with 102 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import fi.oph.vkt.api.dto.EnrollmentDTOSkillFields;
import fi.oph.vkt.model.type.EnrollmentAppointmentStatus;
import fi.oph.vkt.model.type.EnrollmentStatus;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
Expand Down Expand Up @@ -32,6 +31,7 @@ public record ClerkEnrollmentAppointmentDTO(
String country,
@NonNull @NotBlank String firstName,
@NonNull @NotBlank String lastName,
@NonNull @NotBlank String authLink,
@NonNull @NotNull List<ClerkPaymentDTO> payments
)
implements EnrollmentDTOSkillFields {}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
public record ClerkEnrollmentAppointmentUpdateDTO(
@NonNull @NotNull Long id,
@NonNull @NotNull Integer version,
@NonNull @NotNull LocalDateTime enrollmentTime,
@NonNull @NotNull Boolean oralSkill,
@NonNull @NotNull Boolean textualSkill,
@NonNull @NotNull Boolean understandingSkill,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ protected void copyDtoFieldsToEnrollment(
) {
copyDtoSkillFieldsToEnrollment(enrollment, dto);
enrollment.setEmail(dto.email());
enrollment.setPhoneNumber(dto.phoneNumber());
enrollment.setStreet(dto.street());
enrollment.setPostalCode(dto.postalCode());
enrollment.setTown(dto.town());
enrollment.setCountry(dto.country());
}

protected void copyDtoFieldsToEnrollment(
Expand All @@ -38,6 +43,8 @@ protected void copyDtoFieldsToEnrollment(
) {
copyDtoSkillFieldsToEnrollment(enrollment, dto);
enrollment.setEmail(dto.email());
enrollment.setFirstName(dto.firstName());
enrollment.setLastName(dto.lastName());
}

protected void copyDtoFieldsToEnrollment(final Enrollment enrollment, final EnrollmentDTOCommonFields dto) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -241,31 +241,39 @@ public ClerkEnrollmentAppointmentDTO convertToAppointment(final long enrollmentC
final EnrollmentAppointment enrollmentAppointment = enrollmentAppointmentRepository.getReferenceById(
enrollmentContactId
);
final String baseUrlAPI = environment.getRequiredProperty("app.base-url.api");

enrollmentAppointment.setStatus(EnrollmentAppointmentStatus.WAITING_AUTHENTICATION);

if (enrollmentAppointment.getAuthHash() == null) {
enrollmentAppointment.setAuthHash(uuidSource.getRandomNonce());
}

enrollmentAppointmentRepository.flush();

return ClerkEnrollmentUtil.createClerkEnrollmentAppointmentDTO(enrollmentAppointment);
return ClerkEnrollmentUtil.createClerkEnrollmentAppointmentDTO(enrollmentAppointment, baseUrlAPI);
}

@Transactional(readOnly = true)
public ClerkEnrollmentAppointmentDTO getEnrollmentAppointment(final long enrollmentAppointmentId) {
final EnrollmentAppointment enrollmentAppointment = enrollmentAppointmentRepository.getReferenceById(
enrollmentAppointmentId
);
final String baseUrlAPI = environment.getRequiredProperty("app.base-url.api");

return ClerkEnrollmentUtil.createClerkEnrollmentAppointmentDTO(enrollmentAppointment);
return ClerkEnrollmentUtil.createClerkEnrollmentAppointmentDTO(enrollmentAppointment, baseUrlAPI);
}

@Transactional
public ClerkEnrollmentAppointmentDTO updateAppointment(final ClerkEnrollmentAppointmentUpdateDTO dto) {
final EnrollmentAppointment enrollmentAppointment = enrollmentAppointmentRepository.getReferenceById(dto.id());
final String baseUrlAPI = environment.getRequiredProperty("app.base-url.api");

enrollmentAppointment.assertVersion(dto.version());

copyDtoFieldsToEnrollment(enrollmentAppointment, dto);
enrollmentAppointmentRepository.flush();

return ClerkEnrollmentUtil.createClerkEnrollmentAppointmentDTO(enrollmentAppointment);
return ClerkEnrollmentUtil.createClerkEnrollmentAppointmentDTO(enrollmentAppointment, baseUrlAPI);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -683,9 +683,6 @@ public void createEnrollmentContact(final PublicEnrollmentContactCreateDTO dto)
enrollmentAppointment.setStatus(EnrollmentAppointmentStatus.CONTACT_CREATED);
copyDtoFieldsToEnrollment(enrollmentAppointment, dto);

// TODO: remove
enrollmentAppointment.setAuthHash("asd");

enrollmentAppointmentRepository.saveAndFlush(enrollmentAppointment);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ public static KoskiEducationsDTO createKoskiEducationsDTO(final KoskiEducations
}

public static ClerkEnrollmentAppointmentDTO createClerkEnrollmentAppointmentDTO(
final EnrollmentAppointment enrollmentAppointment
final EnrollmentAppointment enrollmentAppointment,
final String baseUrlAPI
) {
final List<ClerkPaymentDTO> paymentDTOs = enrollmentAppointment
.getPayments()
Expand All @@ -170,10 +171,23 @@ public static ClerkEnrollmentAppointmentDTO createClerkEnrollmentAppointmentDTO(
.speechComprehensionPartialExam(enrollmentAppointment.isSpeechComprehensionPartialExam())
.writingPartialExam(enrollmentAppointment.isWritingPartialExam())
.readingComprehensionPartialExam(enrollmentAppointment.isReadingComprehensionPartialExam())
.street(enrollmentAppointment.getStreet())
.postalCode(enrollmentAppointment.getPostalCode())
.town(enrollmentAppointment.getTown())
.country(enrollmentAppointment.getCountry())
.status(enrollmentAppointment.getStatus())
.email(enrollmentAppointment.getEmail())
.phoneNumber(enrollmentAppointment.getPhoneNumber())
.firstName(enrollmentAppointment.getFirstName())
.lastName(enrollmentAppointment.getLastName())
.authLink(
String.format(
"%s/enrollment/appointment/%d/redirect/%s",
baseUrlAPI,
enrollmentAppointment.getId(),
enrollmentAppointment.getAuthHash()
)
)
.payments(paymentDTOs)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ import { EnrollmentUtils } from 'utils/enrollment';

export const ClerkEnrollmentAppointmentDetails = ({
enrollment,
editMode,
}: {
enrollment: ClerkEnrollmentAppointment;
editMode: boolean;
}) => {
// Redux
const dispatch = useAppDispatch();
Expand All @@ -47,7 +49,9 @@ export const ClerkEnrollmentAppointmentDetails = ({
ClerkEnrollmentAppointment | undefined
>(enrollment);
const [hasLocalChanges, setHasLocalChanges] = useState(false);
const [currentUIMode, setCurrentUIMode] = useState(UIMode.View);
const [currentUIMode, setCurrentUIMode] = useState(
editMode ? UIMode.Edit : UIMode.View,
);
const isViewMode = currentUIMode === UIMode.View;

const resetLocalEnrollmentDetails = useCallback(() => {
Expand All @@ -59,6 +63,7 @@ export const ClerkEnrollmentAppointmentDetails = ({
keyPrefix: 'vkt.component.clerkEnrollmentDetails',
});
const translateCommon = useCommonTranslation();
const isLoading = status === APIResponseStatus.InProgress;

const resetToInitialState = useCallback(() => {
dispatch(resetClerkEnrollmentDetailsUpdate());
Expand Down Expand Up @@ -233,6 +238,7 @@ export const ClerkEnrollmentAppointmentDetails = ({
onMove={handleMoveButtonClick}
isViewMode={isViewMode}
hasRequiredDetails={hasRequiredDetails}
isLoading={isLoading}
/>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,9 @@ export const ClerkEnrollmentAppointmentDetailsFields = ({
)}
</div>
)}
<div className="rows flex-start">
<Text>Ilmoittautumislinkki: {enrollment.authLink}</Text>
</div>
</div>
<CustomModal
open={paymentLinkModalOpen}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const ClerkEnrollmentDetails = () => {
const [hasLocalChanges, setHasLocalChanges] = useState(false);
const [currentUIMode, setCurrentUIMode] = useState(UIMode.View);
const isViewMode = currentUIMode === UIMode.View;
const isLoading = status === APIResponseStatus.InProgress;

const handleMoveButtonCLick = () => setIsOpenModalOpen(true);
const closeMoveModal = () => setIsOpenModalOpen(false);
Expand Down Expand Up @@ -281,6 +282,7 @@ export const ClerkEnrollmentDetails = () => {
onMove={handleMoveButtonCLick}
isViewMode={isViewMode}
hasRequiredDetails={hasRequiredDetails}
isLoading={isLoading}
/>
}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import EditIcon from '@mui/icons-material/Edit';
import { FC } from 'react';
import { CustomButton, LoadingProgressIndicator } from 'shared/components';
import { APIResponseStatus, Color, Variant } from 'shared/enums';
import { Color, Variant } from 'shared/enums';

import { useClerkTranslation, useCommonTranslation } from 'configs/i18n';
import { useAppSelector } from 'configs/redux';
import { clerkEnrollmentDetailsSelector } from 'redux/selectors/clerkEnrollmentDetails';

interface ControlButtonsProps {
onCancel: () => void;
Expand All @@ -14,6 +12,7 @@ interface ControlButtonsProps {
onMove: () => void;
isViewMode: boolean;
hasRequiredDetails: boolean;
isLoading: boolean;
}

export const ControlButtons: FC<ControlButtonsProps> = ({
Expand All @@ -23,16 +22,13 @@ export const ControlButtons: FC<ControlButtonsProps> = ({
onMove,
isViewMode,
hasRequiredDetails,
isLoading,
}) => {
const { t } = useClerkTranslation({
keyPrefix: 'vkt.component.clerkEnrollmentDetails.controlButtons',
});
const translateCommon = useCommonTranslation();

const { status } = useAppSelector(clerkEnrollmentDetailsSelector);

const isLoading = status === APIResponseStatus.InProgress;

if (isViewMode) {
return (
<div className="columns gapped">
Expand Down
1 change: 1 addition & 0 deletions frontend/packages/vkt/src/interfaces/clerkEnrollment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export interface ClerkEnrollmentContactResponse
export interface ClerkEnrollmentAppointment extends ClerkEnrollmentContact {
payments: Array<ClerkPayment>;
person?: ClerkPerson;
authLink: string;
}

export interface ClerkEnrollmentAppointmentResponse
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ export const ClerkEnrollmentAppointmentOverviewPage: FC = () => {
className="clerk-enrollment-overview-page__content-container rows"
>
{enrollment && (
<ClerkEnrollmentAppointmentDetails enrollment={enrollment} />
<ClerkEnrollmentAppointmentDetails
editMode={true}
enrollment={enrollment}
/>
)}
</Paper>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ import { APIResponseStatus, Color, Variant } from 'shared/enums';
import { useCommonTranslation } from 'configs/i18n';
import { useAppDispatch, useAppSelector } from 'configs/redux';
import { AppRoutes } from 'enums/app';
import { PartialExamsAndSkills } from 'interfaces/common/enrollment';
import {
createClerkEnrollmentAppointment,
loadClerkEnrollmentContactRequest,
} from 'redux/reducers/clerkEnrollmentContactRequest';
import { clerkEnrollmentContactRequestSelector } from 'redux/selectors/clerkEnrollmentContactRequest';
import { EnrollmentUtils } from 'utils/enrollment';

const BackButton = () => {
const translateCommon = useCommonTranslation();
Expand Down Expand Up @@ -80,6 +82,31 @@ export const ClerkEnrollmentContactRequestPage: FC = () => {
return <></>;
}

const partialExamsToText = (skills: PartialExamsAndSkills) => {
return [
skills.writingPartialExam
? translateCommon('enrollment.partialExamsAndSkills.writingPartialExam')
: false,
skills.readingComprehensionPartialExam
? translateCommon(
'enrollment.partialExamsAndSkills.readingComprehensionPartialExam',
)
: false,
skills.speakingPartialExam
? translateCommon(
'enrollment.partialExamsAndSkills.speakingPartialExam',
)
: false,
skills.speechComprehensionPartialExam
? translateCommon(
'enrollment.partialExamsAndSkills.speechComprehensionPartialExam',
)
: false,
]
.filter((skill) => skill)
.join(', ');
};

const onSubmit = () => {
dispatch(createClerkEnrollmentAppointment(enrollment.id));
};
Expand Down Expand Up @@ -122,15 +149,23 @@ export const ClerkEnrollmentContactRequestPage: FC = () => {
<H2>Yhteydenoton tiedot</H2>
<div className="rows gapped">
<H3>Haluan suorittaa koko tutkinnon?</H3>
<Text>Ei</Text>
<Text>
{EnrollmentUtils.isFullExam(enrollment)
? translateCommon('yes')
: translateCommon('no')}
</Text>
</div>
<div className="rows gapped">
<H3>Osakokeet, jotka haluan suorittaa</H3>
<Text>Ei</Text>
<Text>{partialExamsToText(enrollment)}</Text>
</div>
<div className="rows gapped">
<H3>Osallistunut aiempiin tutkintoihin?</H3>
<Text>Ei</Text>
<Text>
{enrollment.previousEnrollment
? translateCommon('yes')
: translateCommon('no')}
</Text>
</div>
<div className="rows gapped">
<H3>Viesti</H3>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function* updateClerkEnrollmentAppointmentSaga(
const apiResponse: AxiosResponse<ClerkEnrollmentAppointmentResponse> =
yield call(
axiosInstance.put,
APIEndpoints.ClerkEnrollment,
`${APIEndpoints.ClerkEnrollmentAppointment}/${enrollment.id}`,
SerializationUtils.serializeClerkEnrollmentAppointment(enrollment),
);
const updatedEnrollment =
Expand Down
9 changes: 9 additions & 0 deletions frontend/packages/vkt/src/utils/enrollment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ import {
import { PublicEnrollment } from 'interfaces/publicEnrollment';

export class EnrollmentUtils {
static isFullExam(skills: PartialExamsAndSkills) {
return (
skills.writingPartialExam &&
skills.readingComprehensionPartialExam &&
skills.speakingPartialExam &&
skills.speechComprehensionPartialExam
);
}

static isValidTextualSkillAndPartialExams(skills: PartialExamsAndSkills) {
return skills.textualSkill
? skills.writingPartialExam || skills.readingComprehensionPartialExam
Expand Down

0 comments on commit b3327b4

Please sign in to comment.