From f610d26c5d92c804e8229cd9fb7d80ef1ada2608 Mon Sep 17 00:00:00 2001 From: Pyry Koivisto Date: Wed, 18 Dec 2024 21:57:23 +0200 Subject: [PATCH] VKT(Frontend): PublicEnrollmentContactStepper show error dialog if user tries to proceed with invalid fields --- .../vkt/public/i18n/fi-FI/public.json | 18 ++++ .../PublicEnrollmentContactControlButtons.tsx | 89 +++++++++++++++++-- .../steps/FillContactDetails.tsx | 14 +-- 3 files changed, 110 insertions(+), 11 deletions(-) diff --git a/frontend/packages/vkt/public/i18n/fi-FI/public.json b/frontend/packages/vkt/public/i18n/fi-FI/public.json index cacf89cd3..623e9b66d 100644 --- a/frontend/packages/vkt/public/i18n/fi-FI/public.json +++ b/frontend/packages/vkt/public/i18n/fi-FI/public.json @@ -320,6 +320,24 @@ } }, "publicEnrollmentContact": { + "controlButtons": { + "submit": "Lähetä" + }, + "errors": { + "fields": { + "email": "Sähköpostiosoite", + "emailConfirmation": "Sähköpostiosoitteen vahvistus", + "firstName": "Etunimi", + "hasPreviousEnrollment": "Oletko osallistunut aiemmin hyvän ja tyydyttävän taidon tutkintoon?", + "isFullExam": "Haluatko suorittaa sekä suullisen että kirjallisen taidon tutkinnon?", + "message": "Viesti", + "lastName": "Sukunimi", + "partialExamSelection": "Kerro, minkä osakokeen / mitkä osakokeet haluat suorittaa", + "phoneNumber": "Puhelinnumero" + }, + "fixErrors": "Korjaa puuttuvat tai virheelliset tiedot:", + "title": "Tiedoissa on korjattavaa!" + }, "examinerDetails": { "byRequest": "Sovittavissa", "examDate": "Tutkintopäivä", diff --git a/frontend/packages/vkt/src/components/publicEnrollmentContact/PublicEnrollmentContactControlButtons.tsx b/frontend/packages/vkt/src/components/publicEnrollmentContact/PublicEnrollmentContactControlButtons.tsx index 5a8ca69fa..6338411ec 100644 --- a/frontend/packages/vkt/src/components/publicEnrollmentContact/PublicEnrollmentContactControlButtons.tsx +++ b/frontend/packages/vkt/src/components/publicEnrollmentContact/PublicEnrollmentContactControlButtons.tsx @@ -4,14 +4,27 @@ import { } from '@mui/icons-material'; import { useEffect, useState } from 'react'; import { useNavigate } from 'react-router'; -import { CustomButton, LoadingProgressIndicator } from 'shared/components'; -import { APIResponseStatus, Color, Variant } from 'shared/enums'; +import { + CustomButton, + LoadingProgressIndicator, + Text, +} from 'shared/components'; +import { APIResponseStatus, Color, Severity, Variant } from 'shared/enums'; +import { useDialog } from 'shared/hooks'; +import { getErrors, StringUtils } from 'shared/utils'; +import { + contactDetailsStepEmailsMatch, + contactDetailsStepFields, +} from 'components/publicEnrollmentContact/steps/FillContactDetails'; import { useCommonTranslation, usePublicTranslation } from 'configs/i18n'; import { useAppDispatch, useAppSelector } from 'configs/redux'; import { AppRoutes } from 'enums/app'; import { PublicEnrollmentContactFormStep } from 'enums/publicEnrollment'; -import { PublicEnrollmentContact } from 'interfaces/publicEnrollment'; +import { + PublicEnrollmentContact, + PublicEnrollmentContactRequestDetails, +} from 'interfaces/publicEnrollment'; import { loadPublicEnrollmentSave, resetPublicEnrollmentContact, @@ -35,7 +48,7 @@ export const PublicEnrollmentContactControlButtons = ({ examinerId: number; }) => { const { t } = usePublicTranslation({ - keyPrefix: 'vkt.component.publicEnrollment.controlButtons', + keyPrefix: 'vkt.component.publicEnrollmentContact', }); const translateCommon = useCommonTranslation(); const [isSubmitLoading, setIsSubmitLoading] = useState(false); @@ -50,6 +63,8 @@ export const PublicEnrollmentContactControlButtons = ({ navigate(AppRoutes.PublicGoodAndSatisfactoryLevelLanding); }; + const { showDialog } = useDialog(); + useEffect(() => { if (submitStatus === APIResponseStatus.Success) { navigate( @@ -73,6 +88,37 @@ export const PublicEnrollmentContactControlButtons = ({ navigate(RouteUtils.contactStepToRoute(nextStep, examinerId)); } else { setShowValidation(true); + const errors = getErrors({ + fields: contactDetailsStepFields, + values: enrollment, + t, + extraValidation: (errors, values, dirtyFields) => + contactDetailsStepEmailsMatch(t, errors, values, dirtyFields), + }); + + const dialogContent = ( +
+ {t('errors.fixErrors')} +
    + {Object.entries(errors) + .filter(([_, val]) => val) + .map(([field, _]) => ( + +
  • {t(`errors.fields.${field}`)}
  • +
    + ))} +
+
+ ); + + showDialog({ + title: t('errors.title'), + severity: Severity.Error, + content: dialogContent, + actions: [ + { title: translateCommon('back'), variant: Variant.Contained }, + ], + }); } }; @@ -83,6 +129,39 @@ export const PublicEnrollmentContactControlButtons = ({ dispatch(loadPublicEnrollmentSave({ enrollment, examinerId })); } else { setShowValidation(true); + const errors = { + isFullExam: enrollment.isFullExam === undefined, + partialExamSelection: + enrollment.isFullExam === false && + (enrollment.partialExamSelection === undefined || + StringUtils.isBlankString(enrollment.partialExamSelection)), + hasPreviousEnrollment: enrollment.hasPreviousEnrollment === undefined, + message: StringUtils.isBlankString(enrollment.message), + }; + + const dialogContent = ( +
+ {t('errors.fixErrors')} +
    + {Object.entries(errors) + .filter(([_, val]) => val) + .map(([field, _]) => ( + +
  • {t(`errors.fields.${field}`)}
  • +
    + ))} +
+
+ ); + + showDialog({ + title: t('errors.title'), + severity: Severity.Error, + content: dialogContent, + actions: [ + { title: translateCommon('back'), variant: Variant.Contained }, + ], + }); } }; @@ -141,7 +220,7 @@ export const PublicEnrollmentContactControlButtons = ({ data-testid="public-enrollment__controlButtons__submit" disabled={isSubmitLoading} > - {t('submit')} + {t('controlButtons.submit')} ); diff --git a/frontend/packages/vkt/src/components/publicEnrollmentContact/steps/FillContactDetails.tsx b/frontend/packages/vkt/src/components/publicEnrollmentContact/steps/FillContactDetails.tsx index 0d617c9b3..f2ffe189f 100644 --- a/frontend/packages/vkt/src/components/publicEnrollmentContact/steps/FillContactDetails.tsx +++ b/frontend/packages/vkt/src/components/publicEnrollmentContact/steps/FillContactDetails.tsx @@ -13,7 +13,9 @@ import { PublicEnrollmentContactRequestDetails, } from 'interfaces/publicEnrollment'; -const fields: Array> = [ +export const contactDetailsStepFields: Array< + TextField +> = [ { name: 'firstName', required: true, @@ -46,7 +48,7 @@ const fields: Array> = [ }, ]; -const emailsMatch = ( +export const contactDetailsStepEmailsMatch = ( t: (key: string) => string, errors: FieldErrors, values: PublicEnrollmentContactRequestDetails, @@ -92,11 +94,11 @@ export const FillContactDetails = ({ const dirty = showValidation ? undefined : dirtyFields; const errors = getErrors({ - fields, + fields: contactDetailsStepFields, values: enrollment, t: translateCommon, dirtyFields: dirty, - extraValidation: emailsMatch.bind(this, t), + extraValidation: contactDetailsStepEmailsMatch.bind(this, t), }); const dispatch = useAppDispatch(); @@ -104,10 +106,10 @@ export const FillContactDetails = ({ useEffect(() => { setIsStepValid( !hasErrors({ - fields, + fields: contactDetailsStepFields, values: enrollment, t: translateCommon, - extraValidation: emailsMatch.bind(this, t), + extraValidation: contactDetailsStepEmailsMatch.bind(this, t), }), ); }, [setIsStepValid, enrollment, t, translateCommon]);