diff --git a/libs/application/templates/university/src/fields/EducationDetails/DetailsRepeaterItem.tsx b/libs/application/templates/university/src/fields/EducationDetails/DetailsRepeaterItem.tsx index a6ee43b897c7..7dd44f67c341 100644 --- a/libs/application/templates/university/src/fields/EducationDetails/DetailsRepeaterItem.tsx +++ b/libs/application/templates/university/src/fields/EducationDetails/DetailsRepeaterItem.tsx @@ -23,6 +23,7 @@ import { getAllCountryCodes } from '@island.is/shared/utils' import { FileUploadController } from '@island.is/application/ui-components' import { useFormContext } from 'react-hook-form' import { EducationDetailsItem } from '../../shared/types' +import { degreeLevelOptions } from '../../lib/constants' interface DetailsRepeaterItemProps extends FieldBaseProps { index: number @@ -38,8 +39,6 @@ interface DetailsRepeaterItemProps extends FieldBaseProps { export const DetailsRepeaterItem: FC = ({ id, application, - field, - goToScreen, index, repeaterField, itemNumber, @@ -122,7 +121,7 @@ export const DetailsRepeaterItem: FC = ({ return ( ) diff --git a/libs/application/templates/university/src/fields/HiddenTextInput/index.tsx b/libs/application/templates/university/src/fields/HiddenTextInput/index.tsx deleted file mode 100644 index 82b15987a288..000000000000 --- a/libs/application/templates/university/src/fields/HiddenTextInput/index.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { FieldBaseProps } from '@island.is/application/types' -import { Box } from '@island.is/island-ui/core' -import { FC } from 'react' -import { InputController } from '@island.is/shared/form-fields' - -export const HiddenTextInput: FC = ({ field }) => { - return ( - - ) -} diff --git a/libs/application/templates/university/src/fields/HiddenValidation/index.tsx b/libs/application/templates/university/src/fields/HiddenValidation/index.tsx new file mode 100644 index 000000000000..0ded62aba49e --- /dev/null +++ b/libs/application/templates/university/src/fields/HiddenValidation/index.tsx @@ -0,0 +1,26 @@ +import { FieldBaseProps } from '@island.is/application/types' +import { Box } from '@island.is/island-ui/core' +import { FC } from 'react' +import { EMPTY_MODE_OF_DELIVERY, Routes } from '../../lib/constants' +import { useFormContext } from 'react-hook-form' + +// Special validation to make sure chosenMode is not empty, +// since we sometimes need to set the value to dummy EMPTY_MODE_OF_DELIVERY +// when trying to clear the field in the programSelection step +export const HiddenValidation: FC = ({ + setBeforeSubmitCallback, +}) => { + const { getValues } = useFormContext() + + setBeforeSubmitCallback?.(async () => { + const modeOfDeliveryAnswer = getValues( + `${Routes.MODEOFDELIVERYINFORMATION}.chosenMode`, + ) + + if (modeOfDeliveryAnswer === EMPTY_MODE_OF_DELIVERY) return [false, ''] + + return [true, null] + }) + + return +} diff --git a/libs/application/templates/university/src/fields/Overview/index.tsx b/libs/application/templates/university/src/fields/Overview/index.tsx index b38097950f71..b96e2becf739 100644 --- a/libs/application/templates/university/src/fields/Overview/index.tsx +++ b/libs/application/templates/university/src/fields/Overview/index.tsx @@ -16,6 +16,7 @@ import { EducationDetailsItemNotFinished, } from '../../shared/types' import { ApplicationTypes } from '@island.is/university-gateway' +import { getChosenProgram } from '../../utils' export const Overview: FC = ({ application, @@ -47,12 +48,19 @@ export const Overview: FC = ({ setAcceptModalVisibility(true) } + const chosenProgram = getChosenProgram(application.externalData, answers) + const showOtherDocuments = + !!chosenProgram && + chosenProgram.extraApplicationFields && + chosenProgram.extraApplicationFields.length > 0 + return ( - + + {educationOptionChosen && educationOptionChosen === ApplicationTypes.EXEMPTION && ( @@ -89,13 +97,18 @@ export const Overview: FC = ({ route={Routes.EDUCATIONDETAILSFINISHED} /> )} - - + + {showOtherDocuments && } + {showOtherDocuments && ( + + )} + diff --git a/libs/application/templates/university/src/fields/ProgramSelection/index.tsx b/libs/application/templates/university/src/fields/ProgramSelection/index.tsx index 8d8578cd320a..e3f8f22d2dd2 100644 --- a/libs/application/templates/university/src/fields/ProgramSelection/index.tsx +++ b/libs/application/templates/university/src/fields/ProgramSelection/index.tsx @@ -1,8 +1,8 @@ import { FieldBaseProps } from '@island.is/application/types' import { FC, useCallback, useEffect, useState } from 'react' -import { Box, LoadingDots } from '@island.is/island-ui/core' +import { AlertMessage, Box, LoadingDots } from '@island.is/island-ui/core' import { UniversityApplication } from '../../lib/dataSchema' -import { Routes } from '../../lib/constants' +import { EMPTY_MODE_OF_DELIVERY, Routes } from '../../lib/constants' import { SelectController } from '@island.is/shared/form-fields' import { UniversityExternalData } from '../../types' import { Program } from '@island.is/clients/university-gateway-api' @@ -12,13 +12,8 @@ import { getValueViaPath } from '@island.is/application/core' import { useLazyUniversityQuery } from '../../hooks/useGetUniversityInformation' import { UniversityGatewayUniversity } from '@island.is/api/schema' import { useFormContext } from 'react-hook-form' -import { ModeOfDelivery } from '@island.is/university-gateway' -export const ProgramSelection: FC = ({ - application, - field, - goToScreen, -}) => { +export const ProgramSelection: FC = ({ application }) => { const answers = application.answers as UniversityApplication const externalData = application.externalData const universities = externalData.universities @@ -31,7 +26,7 @@ export const ProgramSelection: FC = ({ const { formatMessage, lang } = useLocale() const { setValue } = useFormContext() - const preChosenProgram = getValueViaPath(answers, `initialQuery`, '') + const preSelectedProgram = getValueViaPath(answers, `initialQuery`, '') const programAnswer = getValueViaPath( answers, `${Routes.PROGRAMINFORMATION}.program`, @@ -42,85 +37,181 @@ export const ProgramSelection: FC = ({ `${Routes.PROGRAMINFORMATION}.university`, '', ) + const modeOfDeliveryAnswer = getValueViaPath( + answers, + `${Routes.MODEOFDELIVERYINFORMATION}.chosenMode`, + ) as string | undefined - const [chosenProgram, setChosenProgram] = useState() - const [chosenUniversity, setChosenUniversity] = useState() + const [selectedUniversity, setSelectedUniversity] = useState() + const [selectedProgram, setSelectedProgram] = useState() + const [filteredPrograms, setFilteredPrograms] = useState>([]) const [loadingUniversities, setLoadingUniversities] = useState(true) const [loadingPreAnswer, setLoadingPreAnswer] = useState(true) const [contentfulUniversities, setContentfulUniversities] = useState< Array >([]) + const getUniversities = useLazyUniversityQuery() + const getUniversityInformationCallback = useCallback(async () => { + const { data } = await getUniversities({}) + return data + }, [getUniversities]) + useEffect(() => { //Get university information from contentful getUniversityInformationCallback().then((response) => { - setContentfulUniversities(response.universityGatewayUniversities) + const responseUniversities = response.universityGatewayUniversities + setContentfulUniversities(responseUniversities) setLoadingUniversities(false) - }) - //We have a predetermined choice and no answer already in application - if (preChosenProgram && programAnswer === '' && universityAnswer === '') { - setChosenProgram(preChosenProgram) - const programUniversityId = programs.find( - (x) => x.id === preChosenProgram, - )?.universityId - setChosenUniversity( - universities.find((x) => x.id === programUniversityId)?.id || '', + let universityId: string | undefined + + // We have a predetermined the program selection and there is no value yet in application answers + if ( + preSelectedProgram && + universityAnswer === '' && + programAnswer === '' + ) { + const programInfo = programs.find((x) => x.id === preSelectedProgram) + + const universityInfo = responseUniversities.find( + (x) => x.id === programInfo?.universityId, + ) + + // set selected university + if (universityInfo) { + setSelectedUniversity(universityInfo.id) + setValue( + `${Routes.PROGRAMINFORMATION}.universityName`, + universityInfo.contentfulTitle, + ) + } + + // set selected program + if (programInfo) { + setSelectedProgram(programInfo.id) + setValue( + `${Routes.PROGRAMINFORMATION}.programName`, + getProgramNameAndExtra(programInfo), + ) + + updateDefaultModeOfDelivery(programInfo) + } + + // set universityId to filter programs + universityId = universityInfo?.id + } else { + // Otherwise apply the answers we already have + if (universityAnswer) setSelectedUniversity(universityAnswer) + if (programAnswer) setSelectedProgram(programAnswer) + + // set universityId to filter programs + universityId = universityAnswer + } + + // filter program list by selected university + setFilteredPrograms( + universityId + ? sortedProgramsDeepCopy.filter( + (program) => program.universityId === universityId, + ) + : [], ) - } else { - // Otherwise apply the answers we already have - setChosenProgram(programAnswer) - setChosenUniversity(universityAnswer) - } - setLoadingPreAnswer(false) + + setLoadingPreAnswer(false) + }) }, []) - const getUniversities = useLazyUniversityQuery() - const getUniversityInformationCallback = useCallback(async () => { - const { data } = await getUniversities({}) - return data - }, [getUniversities]) + // to make sure chosenMode value is not cleared when going back and forth + useEffect(() => { + setValue( + `${Routes.MODEOFDELIVERYINFORMATION}.chosenMode`, + modeOfDeliveryAnswer, + ) + }, [modeOfDeliveryAnswer, setValue]) + + const selectUniversity = (universityId: string) => { + const universityInfo = contentfulUniversities.find( + (x) => x.id === universityId, + ) - const ChooseUniversity = (value: string) => { - setChosenUniversity(value) + // set selected university + setSelectedUniversity(universityId) setValue( `${Routes.PROGRAMINFORMATION}.universityName`, - contentfulUniversities.filter((x) => x.id === value)[0].contentfulTitle || - '', + universityInfo?.contentfulTitle, + ) + + // clear program selection + setSelectedProgram(undefined) + setValue(`${Routes.PROGRAMINFORMATION}.program`, '') // set as empty string to make dropdown look empty + setValue(`${Routes.PROGRAMINFORMATION}.programName`, undefined) // set as undefined to make zod validation stop user from continuing to next step + + // filter program list by selected university + setFilteredPrograms( + universityId + ? sortedProgramsDeepCopy.filter( + (program) => program.universityId === universityId, + ) + : [], ) } - const ChooseProgram = (value: string) => { - const chosenProgram = programs.find( + const selectProgram = (programId: string) => { + const programInfo = programs.find( (program) => - program.universityId === chosenUniversity && program.id === value, + program.universityId === selectedUniversity && program.id === programId, + ) + + // set selected program + setSelectedProgram(programId) + setValue( + `${Routes.PROGRAMINFORMATION}.programName`, + programInfo && getProgramNameAndExtra(programInfo), ) + // set default mode of delivery (or clear selection) + updateDefaultModeOfDelivery(programInfo) + + // clear testing site selection + clearModeOfDeliveryTestingSite() + } + + const updateDefaultModeOfDelivery = (program: Program | undefined) => { + if (program?.modeOfDelivery.length === 1) { + setValue( + `${Routes.MODEOFDELIVERYINFORMATION}.chosenMode`, + program.modeOfDelivery[0].modeOfDelivery, + ) + } else { + setValue( + `${Routes.MODEOFDELIVERYINFORMATION}.chosenMode`, + EMPTY_MODE_OF_DELIVERY, + ) + } + } + + const clearModeOfDeliveryTestingSite = () => { + setValue(`${Routes.MODEOFDELIVERYINFORMATION}.location`, '') + } + + const getProgramNameAndExtra = (program: Program) => { const extra = - lang === 'is' && chosenProgram - ? chosenProgram.specializationNameIs + lang === 'is' && program + ? program.specializationNameIs ? ` - ${formatMessage( information.labels.programSelection.specializationLabel, - )}: ${chosenProgram.specializationNameIs}` + )}: ${program.specializationNameIs}` : '' - : chosenProgram && chosenProgram.specializationNameEn + : program && program.specializationNameEn ? ` - ${formatMessage( information.labels.programSelection.specializationLabel, - )}: ${chosenProgram.specializationNameEn}` + )}: ${program.specializationNameEn}` : '' - const programName = `${ - lang === 'is' && chosenProgram - ? chosenProgram.nameIs - : chosenProgram && chosenProgram.nameEn - }${extra}` - setChosenProgram(value) - if ( - chosenProgram?.modeOfDelivery && - chosenProgram?.modeOfDelivery.length <= 1 - ) { - setValue(`modeOfDeliveryInformation.chosenMode`, ModeOfDelivery.ON_SITE) - } - setValue(`${Routes.PROGRAMINFORMATION}.programName`, programName) + + return ( + program && `${lang === 'is' ? program.nameIs : program.nameEn}${extra}` + ) } return !loadingUniversities && !loadingPreAnswer ? ( @@ -128,12 +219,12 @@ export const ProgramSelection: FC = ({ ChooseUniversity(value.value as string)} + onSelect={(value) => selectUniversity(value.value as string)} options={universities.map((uni) => { return { label: @@ -145,46 +236,46 @@ export const ProgramSelection: FC = ({ })} /> - - {!!chosenUniversity && ( - ChooseProgram(value.value as string)} - options={sortedProgramsDeepCopy - .sort((x, y) => { - if (lang === 'is' && x.nameIs > y.nameIs) return 1 - else if (lang === 'en' && x.nameEn > y.nameEn) return 1 - else return -1 - }) - .filter((program) => program.universityId === chosenUniversity) - .map((program) => { - const extra = - lang === 'is' - ? program.specializationNameIs - ? ` - ${formatMessage( - information.labels.programSelection - .specializationLabel, - )}: ${program.specializationNameIs}` - : '' - : program.specializationNameEn - ? ` - ${formatMessage( - information.labels.programSelection.specializationLabel, - )}: ${program.specializationNameEn}` - : '' - return { - label: `${ - lang === 'is' ? program.nameIs : program.nameEn - }${extra}`, - value: program.id, - } - })} - /> - )} - + {!!selectedUniversity && ( + + {!!filteredPrograms.length && ( + selectProgram(value.value as string)} + options={filteredPrograms + .sort((x, y) => { + if (lang === 'is' && x.nameIs > y.nameIs) return 1 + else if (lang === 'en' && x.nameEn > y.nameEn) return 1 + else return -1 + }) + .map((program) => { + return { + label: getProgramNameAndExtra(program), + value: program.id, + } + })} + /> + )} + {!filteredPrograms.length && ( + + )} + + )} ) : ( diff --git a/libs/application/templates/university/src/fields/Review/OtherDocumentsReview.tsx b/libs/application/templates/university/src/fields/Review/OtherDocumentsReview.tsx index 6d8e4cc03881..f71d177c20bb 100644 --- a/libs/application/templates/university/src/fields/Review/OtherDocumentsReview.tsx +++ b/libs/application/templates/university/src/fields/Review/OtherDocumentsReview.tsx @@ -3,27 +3,76 @@ import { FC } from 'react' import { review } from '../../lib/messages' import { useLocale } from '@island.is/localization' import { Routes } from '../../lib/constants' -import { GenericReview } from '../../components/GenericReview' +import SummaryBlock from '../../components/SummaryBlock' +import { Box, GridColumn, GridRow, Icon, Text } from '@island.is/island-ui/core' +import { UniversityApplication } from '../../lib/dataSchema' +import { + OtherDocumentsDetailsItem, + ProgramExtraApplicationField, +} from '../../shared/types' interface Props extends FieldBaseProps { goToScreen?: (id: string) => void - route?: Routes + route: Routes + extraApplicationFields: Array } export const OtherDocumentsReview: FC = ({ application, goToScreen, route, + extraApplicationFields, }) => { const { formatMessage } = useLocale() + const answers = application.answers as UniversityApplication + const otherDocuments = + answers.otherDocuments as Array return ( - + goToScreen?.(route)}> + + + + + {formatMessage(review.labels.otherDocuments)} + + + {extraApplicationFields.map((field, index) => { + const item = otherDocuments[index] + if (item.attachments && item.attachments.length > 0) { + return ( + + {field.externalKey}: + {item.attachments.map((file) => { + return ( + + + + + {file.name} + + ) + })} + + ) + } + })} + + + + ) } diff --git a/libs/application/templates/university/src/fields/Review/SchoolCareerReview.tsx b/libs/application/templates/university/src/fields/Review/SchoolCareerReview.tsx index f3841e40de19..9069dd7df641 100644 --- a/libs/application/templates/university/src/fields/Review/SchoolCareerReview.tsx +++ b/libs/application/templates/university/src/fields/Review/SchoolCareerReview.tsx @@ -3,7 +3,6 @@ import { FC } from 'react' import { review } from '../../lib/messages' import { useLocale } from '@island.is/localization' import { Routes } from '../../lib/constants' -import { GenericReview } from '../../components/GenericReview' import { EducationDetailsItem, EducationDetailsItemExemption, @@ -12,7 +11,8 @@ import { import { formerEducation } from '../../lib/messages/formerEducation' import { coreMessages } from '@island.is/application/core' import SummaryBlock from '../../components/SummaryBlock' -import { Box, GridColumn, GridRow, Text } from '@island.is/island-ui/core' +import { Box, GridColumn, GridRow, Icon, Text } from '@island.is/island-ui/core' +import { formatDateStr, getCountryName, getDegreeLevelLabel } from '../../utils' interface Props extends FieldBaseProps { goToScreen?: (id: string) => void @@ -45,9 +45,32 @@ export const SchoolCareerReview: FC = ({ {`${formatMessage( formerEducation.labels.educationDetails.moreDetailsLabel, )}: ${educationItemExemption.moreDetails}`} - {`${formatMessage(review.labels.documents)}: TODO`} + {educationItemExemption.degreeAttachments && ( + {`${formatMessage(review.labels.documents)}:`} + )} + {educationItemExemption.degreeAttachments?.map((file) => { + return ( + + + + + {file.name} + + ) + })} )} + {educationItemThirdLevel && ( @@ -56,10 +79,11 @@ export const SchoolCareerReview: FC = ({ {`${formatMessage( formerEducation.labels.educationDetails.schoolLabel, )}: ${educationItemThirdLevel.school}`} - {`${formatMessage( formerEducation.labels.educationDetails.degreeLevelLabel, - )}: ${educationItemThirdLevel.degreeLevel}`} + )}: ${formatMessage( + getDegreeLevelLabel(educationItemThirdLevel.degreeLevel), + )}`} {educationItemThirdLevel.degreeAttachments && ( {`${formatMessage( formerEducation.labels.educationDetails.degreeMajorLabel, @@ -77,15 +101,19 @@ export const SchoolCareerReview: FC = ({ )} {`${formatMessage( formerEducation.labels.educationDetails.degreeCountryLabel, - )}: ${educationItemThirdLevel.degreeCountry}`} + )}: ${getCountryName( + educationItemThirdLevel.degreeCountry, + )}`} {educationItemThirdLevel.beginningDate && ( {`${formatMessage( formerEducation.labels.educationDetails.beginningDateLabel, - )}: ${educationItemThirdLevel.beginningDate}`} + )}: ${formatDateStr( + educationItemThirdLevel.beginningDate, + )}`} )} {`${formatMessage( formerEducation.labels.educationDetails.endDateLabel, - )}: ${educationItemThirdLevel.endDate}`} + )}: ${formatDateStr(educationItemThirdLevel.endDate)}`} {educationItemThirdLevel.degreeFinished && ( {`${formatMessage( formerEducation.labels.educationDetails @@ -101,8 +129,31 @@ export const SchoolCareerReview: FC = ({ formerEducation.labels.educationDetails.moreDetailsLabel, )}: ${educationItemThirdLevel.moreDetails}`} )} + {educationItemThirdLevel.degreeAttachments && ( + {`${formatMessage(review.labels.documents)}:`} + )} + {educationItemThirdLevel.degreeAttachments?.map((file) => { + return ( + + + + + {file.name} + + ) + })} )} + {educationItemNotFinished && ( @@ -119,6 +170,7 @@ export const SchoolCareerReview: FC = ({ )}: ${educationItemNotFinished.moreDetails}`} )} + {educationItemsFinished && educationItemsFinished.map((educationItem, index) => { return ( @@ -129,14 +181,14 @@ export const SchoolCareerReview: FC = ({ { index: index + 1 }, )} - {`${formatMessage( formerEducation.labels.educationDetails.schoolLabel, )}: ${educationItem.school}`} - {`${formatMessage( formerEducation.labels.educationDetails.degreeLevelLabel, - )}: ${educationItem.degreeLevel}`} + )}: ${formatMessage( + getDegreeLevelLabel(educationItem.degreeLevel), + )}`} {educationItem.degreeAttachments && ( {`${formatMessage( formerEducation.labels.educationDetails.degreeMajorLabel, @@ -155,16 +207,16 @@ export const SchoolCareerReview: FC = ({ )} {`${formatMessage( formerEducation.labels.educationDetails.degreeCountryLabel, - )}: ${educationItem.degreeCountry}`} + )}: ${getCountryName(educationItem.degreeCountry)}`} {educationItem.beginningDate && ( {`${formatMessage( formerEducation.labels.educationDetails .beginningDateLabel, - )}: ${educationItem.beginningDate}`} + )}: ${formatDateStr(educationItem.beginningDate)}`} )} {`${formatMessage( formerEducation.labels.educationDetails.endDateLabel, - )}: ${educationItem.endDate}`} + )}: ${formatDateStr(educationItem.endDate)}`} {educationItem.degreeFinished && ( {`${formatMessage( formerEducation.labels.educationDetails @@ -180,6 +232,28 @@ export const SchoolCareerReview: FC = ({ formerEducation.labels.educationDetails.moreDetailsLabel, )}: ${educationItem.moreDetails}`} )} + {educationItem.degreeAttachments && ( + {`${formatMessage(review.labels.documents)}:`} + )} + {educationItem.degreeAttachments?.map((file) => { + return ( + + + + + {file.name} + + ) + })} ) })} diff --git a/libs/application/templates/university/src/fields/Review/index.tsx b/libs/application/templates/university/src/fields/Review/index.tsx index b2823af6c698..cc0e9079ddeb 100644 --- a/libs/application/templates/university/src/fields/Review/index.tsx +++ b/libs/application/templates/university/src/fields/Review/index.tsx @@ -12,6 +12,8 @@ import { EducationDetailsItemNotFinished, } from '../../shared/types' import { ApplicationTypes } from '@island.is/university-gateway' +import { OtherDocumentsReview } from './OtherDocumentsReview' +import { getChosenProgram } from '../../utils' export const Review: FC = ({ application, @@ -31,15 +33,21 @@ export const Review: FC = ({ const educationNotFinished = answers.educationDetails .notFinishedDetails as EducationDetailsItemNotFinished + const chosenProgram = getChosenProgram(application.externalData, answers) + const showOtherDocuments = + !!chosenProgram && + chosenProgram.extraApplicationFields && + chosenProgram.extraApplicationFields.length > 0 + return ( - + = ({ route={Routes.USERINFORMATION} goToScreen={goToScreen} /> + {educationOptionChosen && educationOptionChosen === ApplicationTypes.EXEMPTION && ( @@ -87,7 +96,17 @@ export const Review: FC = ({ goToScreen={goToScreen} /> )} - + + {showOtherDocuments && } + {showOtherDocuments && ( + + )} ) } diff --git a/libs/application/templates/university/src/fields/index.ts b/libs/application/templates/university/src/fields/index.ts index 43708a45331b..715a42126e8e 100644 --- a/libs/application/templates/university/src/fields/index.ts +++ b/libs/application/templates/university/src/fields/index.ts @@ -1,6 +1,6 @@ export * from './Review' export * from './ProgramSelection' export * from './EducationDetails' -export * from './HiddenTextInput' +export * from './HiddenValidation' export * from './Overview' export * from './OtherDocuments' diff --git a/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/Exemption.ts b/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/Exemption.ts index f556a1557dcd..7412673e9b1b 100644 --- a/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/Exemption.ts +++ b/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/Exemption.ts @@ -15,7 +15,7 @@ import { ApplicationTypes } from '@island.is/university-gateway' export const ExemptionSubSection = buildSubSection({ id: `${Routes.EDUCATIONDETAILS}.exemptionDetails`, title: formerEducation.labels.educationDetails.pageTitle, - condition: (answers: FormValue, externalData) => { + condition: (answers: FormValue) => { const optionAnswers = getValueViaPath(answers, 'educationOptions') return optionAnswers === ApplicationTypes.EXEMPTION }, diff --git a/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/NotFinishedEducation.ts b/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/NotFinishedEducation.ts index 7b86bfd80424..a4b3e8a37790 100644 --- a/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/NotFinishedEducation.ts +++ b/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/NotFinishedEducation.ts @@ -8,15 +8,14 @@ import { getValueViaPath, } from '@island.is/application/core' import { formerEducation } from '../../../../lib/messages/formerEducation' -import { Routes } from '../../../../lib/constants' -import { degreeLevelOptions } from './degreeLevelOptions' +import { degreeLevelOptions, Routes } from '../../../../lib/constants' import { FormValue } from '@island.is/application/types' import { ApplicationTypes } from '@island.is/university-gateway' export const NotFinishedEducationSubSection = buildSubSection({ id: `${Routes.EDUCATIONDETAILS}.notFinishedDetails`, title: formerEducation.labels.educationDetails.pageTitle, - condition: (answers: FormValue, externalData) => { + condition: (answers: FormValue) => { const optionAnswers = getValueViaPath(answers, 'educationOptions') return optionAnswers === ApplicationTypes.NOTFINISHED }, diff --git a/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/ThirdLevelEducation.ts b/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/ThirdLevelEducation.ts index efc126c5e57a..d43d09500db0 100644 --- a/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/ThirdLevelEducation.ts +++ b/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/ThirdLevelEducation.ts @@ -10,17 +10,16 @@ import { getValueViaPath, } from '@island.is/application/core' import { formerEducation } from '../../../../lib/messages/formerEducation' -import { Routes } from '../../../../lib/constants' +import { degreeLevelOptions, Routes } from '../../../../lib/constants' import { FILE_SIZE_LIMIT } from '../../../../shared' import { getAllCountryCodes } from '@island.is/shared/utils' -import { degreeLevelOptions } from './degreeLevelOptions' import { FormValue } from '@island.is/application/types' import { ApplicationTypes } from '@island.is/university-gateway' export const ThirdLevelEducationSubSection = buildSubSection({ id: `${Routes.EDUCATIONDETAILS}.thirdLevelDetails`, title: formerEducation.labels.educationDetails.pageTitle, - condition: (answers: FormValue, externalData) => { + condition: (answers: FormValue) => { const optionAnswers = getValueViaPath(answers, 'educationOptions') return optionAnswers === ApplicationTypes.THIRDLEVEL }, diff --git a/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/degreeLevelOptions.ts b/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/degreeLevelOptions.ts deleted file mode 100644 index cdf0c5a25776..000000000000 --- a/libs/application/templates/university/src/forms/UniversityForm/FormerEducation/EducationDetails/degreeLevelOptions.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { formerEducation } from '../../../../lib/messages/formerEducation' - -export const degreeLevelOptions = [ - { - label: formerEducation.labels.educationDetails.framhaldsskoliSelectionLabel, - value: 'framhaldsskoli', - }, - { - label: formerEducation.labels.educationDetails.bachelorsSelectionLabel, - value: 'bachelors', - }, - { - label: formerEducation.labels.educationDetails.mastersSelectionLabel, - value: 'masters', - }, - { - label: formerEducation.labels.educationDetails.doctorsSelectionLabel, - value: 'doctors', - }, -] diff --git a/libs/application/templates/university/src/forms/UniversityForm/InformationSection/ModeOfDeliverySubSection.ts b/libs/application/templates/university/src/forms/UniversityForm/InformationSection/ModeOfDeliverySubSection.ts index 0073abea3ab0..66dc846ad4cc 100644 --- a/libs/application/templates/university/src/forms/UniversityForm/InformationSection/ModeOfDeliverySubSection.ts +++ b/libs/application/templates/university/src/forms/UniversityForm/InformationSection/ModeOfDeliverySubSection.ts @@ -4,6 +4,7 @@ import { buildRadioField, getValueViaPath, buildSelectField, + buildCustomField, } from '@island.is/application/core' import { information } from '../../../lib/messages' import { Routes } from '../../../lib/constants' @@ -119,6 +120,11 @@ export const ModeOfDeliverySubSection = buildSubSection({ }) }, }), + buildCustomField({ + id: `${Routes.MODEOFDELIVERYINFORMATION}.chosenModeHiddenValidation`, + title: '', + component: 'HiddenValidation', + }), buildSelectField({ id: `${Routes.MODEOFDELIVERYINFORMATION}.location`, title: '', diff --git a/libs/application/templates/university/src/forms/UniversityForm/InformationSection/ProgramSubSection.ts b/libs/application/templates/university/src/forms/UniversityForm/InformationSection/ProgramSubSection.ts index 4ec570bf2eab..de5c0740956b 100644 --- a/libs/application/templates/university/src/forms/UniversityForm/InformationSection/ProgramSubSection.ts +++ b/libs/application/templates/university/src/forms/UniversityForm/InformationSection/ProgramSubSection.ts @@ -3,6 +3,7 @@ import { buildSubSection, buildDescriptionField, buildCustomField, + buildHiddenInput, } from '@island.is/application/core' import { information } from '../../../lib/messages' import { Routes } from '../../../lib/constants' @@ -21,6 +22,10 @@ export const ProgramSubSection = buildSubSection({ title: information.labels.programSelection.selectProgramTitle, titleVariant: 'h5', }), + buildHiddenInput({ + id: `${Routes.MODEOFDELIVERYINFORMATION}.chosenMode`, + doesNotRequireAnswer: true, + }), buildCustomField({ id: `${Routes.PROGRAMINFORMATION}`, title: '', diff --git a/libs/application/templates/university/src/forms/UniversityForm/InformationSection/UserInformationSubSection.ts b/libs/application/templates/university/src/forms/UniversityForm/InformationSection/UserInformationSubSection.ts index dc96aa7bb19b..9f8d489caeb3 100644 --- a/libs/application/templates/university/src/forms/UniversityForm/InformationSection/UserInformationSubSection.ts +++ b/libs/application/templates/university/src/forms/UniversityForm/InformationSection/UserInformationSubSection.ts @@ -93,6 +93,7 @@ export const UserInformationSubSection = buildSubSection({ id: 'userInformation.alert', title: '', alertType: 'info', + doesNotRequireAnswer: true, message: personal.labels.userInformation.alertMessage, links: [ { diff --git a/libs/application/templates/university/src/lib/constants.ts b/libs/application/templates/university/src/lib/constants.ts index a40a0a1c3569..5889a6474acc 100644 --- a/libs/application/templates/university/src/lib/constants.ts +++ b/libs/application/templates/university/src/lib/constants.ts @@ -1,4 +1,5 @@ import { DefaultEvents } from '@island.is/application/types' +import { formerEducation } from './messages/formerEducation' export type Events = { type: @@ -36,3 +37,24 @@ export enum Routes { EDUCATIONOPTIONS = 'educationOptions', OTHERDOCUMENTS = 'otherDocuments', } + +export const EMPTY_MODE_OF_DELIVERY = 'EMPTY_MODE_OF_DELIVERY' + +export const degreeLevelOptions = [ + { + label: formerEducation.labels.educationDetails.framhaldsskoliSelectionLabel, + value: 'framhaldsskoli', + }, + { + label: formerEducation.labels.educationDetails.bachelorsSelectionLabel, + value: 'bachelors', + }, + { + label: formerEducation.labels.educationDetails.mastersSelectionLabel, + value: 'masters', + }, + { + label: formerEducation.labels.educationDetails.doctorsSelectionLabel, + value: 'doctors', + }, +] diff --git a/libs/application/templates/university/src/lib/dataSchema.ts b/libs/application/templates/university/src/lib/dataSchema.ts index e2fef34146af..7156d4a93a3b 100644 --- a/libs/application/templates/university/src/lib/dataSchema.ts +++ b/libs/application/templates/university/src/lib/dataSchema.ts @@ -2,6 +2,7 @@ import { z } from 'zod' import * as kennitala from 'kennitala' import { NO, YES } from '@island.is/application/core' import { ApplicationTypes, ModeOfDelivery } from '@island.is/university-gateway' +import { EMPTY_MODE_OF_DELIVERY } from './constants' const UserSchemaBase = z.object({ nationalId: z @@ -119,16 +120,17 @@ const EducationDetailsSchema = z.object({ thirdLevelDetails: RepeateableEducationDetailsSchema.optional(), }) -const otherDocumentsSchema = z.object({ +export const OtherDocumentsSchema = z.object({ attachments: z.array(FileDocumentSchema).optional(), }) -const modeOfDeliverInformationSchema = z.object({ +const ModeOfDeliverInformationSchema = z.object({ chosenMode: z.enum([ ModeOfDelivery.ONLINE, ModeOfDelivery.ON_SITE, ModeOfDelivery.MIXED, ModeOfDelivery.REMOTE, + EMPTY_MODE_OF_DELIVERY, ]), location: z.string().optional(), }) @@ -137,7 +139,7 @@ export const UniversitySchema = z.object({ approveExternalData: z.boolean().refine((v) => v), userInformation: UserInformationSchema, programInformation: ProgramSchema, - modeOfDeliveryInformation: modeOfDeliverInformationSchema, + modeOfDeliveryInformation: ModeOfDeliverInformationSchema, educationOptions: z .enum([ ApplicationTypes.DIPLOMA, @@ -147,7 +149,7 @@ export const UniversitySchema = z.object({ ]) .optional(), educationDetails: EducationDetailsSchema, - otherDocuments: z.array(otherDocumentsSchema).optional(), + otherDocuments: z.array(OtherDocumentsSchema).optional(), }) export type UniversityApplication = z.TypeOf diff --git a/libs/application/templates/university/src/lib/messages/information.ts b/libs/application/templates/university/src/lib/messages/information.ts index c45ca2cf0d48..b140a631d2b3 100644 --- a/libs/application/templates/university/src/lib/messages/information.ts +++ b/libs/application/templates/university/src/lib/messages/information.ts @@ -81,6 +81,17 @@ export const information = { defaultMessage: 'Kjörsvið', description: 'Specialization label label', }, + warningEmptyProgramListTitle: { + id: 'uni.application:information.labels.programSelection.warningEmptyProgramListTitle', + defaultMessage: 'Athugið', + description: 'Warning empty program list title', + }, + warningEmptyProgramListMessage: { + id: 'uni.application:information.labels.programSelection.warningEmptyProgramListMessage', + defaultMessage: + 'Ekki er hægt að sækja um nám fyrir þennan skóla að svo stöddu', + description: 'Warning empty program list message', + }, }), modeOfDeliverySection: defineMessages({ sectionTitle: { diff --git a/libs/application/templates/university/src/lib/messages/review.ts b/libs/application/templates/university/src/lib/messages/review.ts index 39539c858a95..530a75e2f375 100644 --- a/libs/application/templates/university/src/lib/messages/review.ts +++ b/libs/application/templates/university/src/lib/messages/review.ts @@ -42,7 +42,7 @@ export const review = { }, documents: { id: 'uni.application:review.labels.documents#markdown', - defaultMessage: '**Önnur fylgigögn**', + defaultMessage: '**Fylgigögn**', description: 'documents review label', }, otherDocuments: { diff --git a/libs/application/templates/university/src/shared/types.ts b/libs/application/templates/university/src/shared/types.ts index 5f626f360ae1..cb7f3d392b6a 100644 --- a/libs/application/templates/university/src/shared/types.ts +++ b/libs/application/templates/university/src/shared/types.ts @@ -3,6 +3,7 @@ import { EducationNotFinishedSchema, ExemptionEducationSchema, RepeateableEducationDetailsSchema, + OtherDocumentsSchema, } from '../lib/dataSchema' import { ProgramExtraApplicationFieldFieldTypeEnum } from '@island.is/clients/university-gateway-api' @@ -17,6 +18,8 @@ export type EducationDetailsItemNotFinished = z.TypeOf< typeof EducationNotFinishedSchema > +export type OtherDocumentsDetailsItem = z.TypeOf + export type CurrentApplication = { id: string nationalId: string @@ -59,7 +62,7 @@ type ModeOfDelivery = { modeOfDelivery: string } -type ProgramExtraApplicationField = { +export type ProgramExtraApplicationField = { externalKey: string fieldType: ProgramExtraApplicationFieldFieldTypeEnum } diff --git a/libs/application/templates/university/src/utils/formatDate.ts b/libs/application/templates/university/src/utils/formatDate.ts index b491a85d357f..a3f9457061b3 100644 --- a/libs/application/templates/university/src/utils/formatDate.ts +++ b/libs/application/templates/university/src/utils/formatDate.ts @@ -2,3 +2,6 @@ import format from 'date-fns/format' export const formatDate = (date: Date): string => date ? format(new Date(date), 'dd.MM.yyyy') : '' + +export const formatDateStr = (dateStr: string | undefined): string => + dateStr ? formatDate(new Date(dateStr)) : '' diff --git a/libs/application/templates/university/src/utils/getCountryName.ts b/libs/application/templates/university/src/utils/getCountryName.ts new file mode 100644 index 000000000000..7d7897d5faf7 --- /dev/null +++ b/libs/application/templates/university/src/utils/getCountryName.ts @@ -0,0 +1,7 @@ +import { getAllCountryCodes } from '@island.is/shared/utils' + +export const getCountryName = (code: string | undefined) => { + const countries = getAllCountryCodes() + const country = countries.find((x) => x.code === code) + return country?.name_is || country?.name || '' +} diff --git a/libs/application/templates/university/src/utils/getDegreeLevelLabel.ts b/libs/application/templates/university/src/utils/getDegreeLevelLabel.ts new file mode 100644 index 000000000000..7fba46a04690 --- /dev/null +++ b/libs/application/templates/university/src/utils/getDegreeLevelLabel.ts @@ -0,0 +1,5 @@ +import { degreeLevelOptions } from '../lib/constants' + +export const getDegreeLevelLabel = (value: string | undefined) => { + return degreeLevelOptions.find((x) => x.value === value)?.label || '' +} diff --git a/libs/application/templates/university/src/utils/index.ts b/libs/application/templates/university/src/utils/index.ts index 439de6ba404d..379e2b99dcf6 100644 --- a/libs/application/templates/university/src/utils/index.ts +++ b/libs/application/templates/university/src/utils/index.ts @@ -1,2 +1,5 @@ export * from './formatPhoneNumber' export * from './formatDate' +export * from './getChosenProgram' +export * from './getDegreeLevelLabel' +export * from './getCountryName'