Skip to content

Commit

Permalink
chore(financial-aid): refactor student and employment screens (#17553)
Browse files Browse the repository at this point in the history
jonnigs authored Jan 21, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent 50217b7 commit 328b65d
Showing 11 changed files with 253 additions and 328 deletions.

This file was deleted.

This file was deleted.

2 changes: 0 additions & 2 deletions libs/application/templates/financial-aid/src/fields/index.ts
Original file line number Diff line number Diff line change
@@ -2,9 +2,7 @@ export { default as AboutForm } from './AboutForm/AboutForm'
export { default as ChildrenForm } from './ChildrenForm/ChildrenForm'
export { default as ChildrenFilesForm } from './ChildrenFilesForm/ChildrenFilesForm'
export { default as DescriptionText } from './DescriptionText/DescriptionText'
export { default as StudentForm } from './StudentForm/StudentForm'
export { default as IncomeForm } from './IncomeForm/IncomeForm'
export { default as EmploymentForm } from './EmploymentForm/EmploymentForm'
export { default as BankInfoForm } from './BankInfoForm/BankInfoForm'
export { default as PersonalTaxCreditForm } from './PersonalTaxCreditForm/PersonalTaxCreditForm'
export { default as ApplicantConfirmation } from './Confirmation/ApplicantConfirmation'
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { buildCustomField } from '@island.is/application/core'
import { buildSubSection } from '@island.is/application/core'
import { Routes } from '../../../lib/constants'
import { hasChildren } from '../../../utils/conditions'
import * as m from '../../../lib/messages'

export const childrenFilesSubsection = buildSubSection({
condition: hasChildren,
id: Routes.CHILDRENFILES,
title: m.childrenFilesForm.general.sectionTitle,
children: [
buildCustomField({
id: Routes.CHILDRENFILES,
title: m.childrenFilesForm.general.pageTitle,
component: 'ChildrenFilesForm',
}),
],
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { buildCustomField } from '@island.is/application/core'
import { buildSubSection } from '@island.is/application/core'
import { Routes } from '../../../lib/constants'
import { hasChildren } from '../../../utils/conditions'
import * as m from '../../../lib/messages'

export const childrenSchoolInfoSubsection = buildSubSection({
condition: hasChildren,
id: Routes.CHILDRENSCHOOLINFO,
title: m.childrenForm.general.sectionTitle,
children: [
buildCustomField({
id: Routes.CHILDRENSCHOOLINFO,
title: m.childrenForm.general.pageTitle,
component: 'ChildrenForm',
}),
],
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import {
buildMultiField,
buildRadioField,
buildSubSection,
buildTextField,
} from '@island.is/application/core'
import { Routes } from '../../../lib/constants'
import * as m from '../../../lib/messages'
import { employmentOptions } from '../../../utils/options'
import { otherEmployment } from '../../../utils/conditions'

export const employmentSubsection = buildSubSection({
id: Routes.EMPLOYMENT,
title: m.employmentForm.general.sectionTitle,
children: [
buildMultiField({
id: 'employmentMultiField',
title: m.employmentForm.general.pageTitle,
children: [
buildRadioField({
id: 'employment.type',
title: '',
options: employmentOptions,
marginBottom: 2,
}),
buildTextField({
condition: otherEmployment,
id: 'employment.custom',
title: m.input.label,
required: true,
variant: 'textarea',
rows: 8,
}),
],
}),
],
})
Original file line number Diff line number Diff line change
@@ -1,84 +1,23 @@
import {
buildCustomField,
buildSection,
buildSubSection,
getValueViaPath,
} from '@island.is/application/core'
import * as m from '../../../lib/messages'
import { Routes } from '../../../lib/constants'
import { ApplicantChildCustodyInformation } from '@island.is/application/types'
import { buildSection } from '@island.is/application/core'
import { inRelationshipSubsection } from './inRelationshipSubsection'
import { unknownRelationshipSubsection } from './unknownRelationshipSubsection'
import { homeCircumstancesSubsection } from './homeCircumstancesSubsection'
import { employmentSubsection } from './employmentSubsection'
import { studentSubsection } from './studentSubsection'
import { childrenSchoolInfoSubsection } from './childrenSchoolInfoSubsection'
import { childrenFilesSubsection } from './childrenFilesSubsection'
import * as m from '../../../lib/messages'

export const personalInterestSection = buildSection({
id: 'personalInterest',
title: m.section.personalInterest,
children: [
inRelationshipSubsection,
unknownRelationshipSubsection,
buildSubSection({
condition: (_, externalData) => {
const childWithInfo = getValueViaPath(
externalData,
'childrenCustodyInformation.data',
[],
) as ApplicantChildCustodyInformation[]

return Boolean(childWithInfo?.length)
},
id: Routes.CHILDRENSCHOOLINFO,
title: m.childrenForm.general.sectionTitle,
children: [
buildCustomField({
id: Routes.CHILDRENSCHOOLINFO,
title: m.childrenForm.general.pageTitle,
component: 'ChildrenForm',
}),
],
}),
buildSubSection({
condition: (_, externalData) => {
const childWithInfo = getValueViaPath(
externalData,
'childrenCustodyInformation.data',
[],
) as ApplicantChildCustodyInformation[]

return Boolean(childWithInfo?.length)
},
id: Routes.CHILDRENFILES,
title: m.childrenFilesForm.general.sectionTitle,
children: [
buildCustomField({
id: Routes.CHILDRENFILES,
title: m.childrenFilesForm.general.pageTitle,
component: 'ChildrenFilesForm',
}),
],
}),
childrenSchoolInfoSubsection,
childrenFilesSubsection,
homeCircumstancesSubsection,
buildSubSection({
id: Routes.STUDENT,
title: m.studentForm.general.sectionTitle,
children: [
buildCustomField({
id: Routes.STUDENT,
title: m.studentForm.general.pageTitle,
component: 'StudentForm',
}),
],
}),
buildSubSection({
id: Routes.EMPLOYMENT,
title: m.employmentForm.general.sectionTitle,
children: [
buildCustomField({
id: Routes.EMPLOYMENT,
title: m.employmentForm.general.pageTitle,
component: 'EmploymentForm',
}),
],
}),
studentSubsection,
employmentSubsection,
],
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {
buildMultiField,
buildRadioField,
buildSubSection,
buildTextField,
} from '@island.is/application/core'
import { Routes } from '../../../lib/constants'
import * as m from '../../../lib/messages'
import { studentOptions } from '../../../utils/options'
import { isStudent } from '../../../utils/conditions'

export const studentSubsection = buildSubSection({
id: Routes.STUDENT,
title: m.studentForm.general.sectionTitle,
children: [
buildMultiField({
id: 'studentMultiField',
title: m.studentForm.general.pageTitle,
children: [
buildRadioField({
id: 'student.isStudent',
title: '',
options: studentOptions,
marginBottom: 2,
}),
buildTextField({
condition: isStudent,
id: 'student.custom',
title: m.studentForm.input.label,
placeholder: m.studentForm.input.example,
required: true,
}),
],
}),
],
})
161 changes: 76 additions & 85 deletions libs/application/templates/financial-aid/src/lib/dataSchema.ts
Original file line number Diff line number Diff line change
@@ -7,6 +7,77 @@ import {
import { isValidEmail, isValidNationalId, isValidPhone } from './utils'
import { ApproveOptions } from './types'

const relationshipStatusSchema = z
.object({
unregisteredCohabitation: z.nativeEnum(ApproveOptions).refine((v) => v, {
params: error.validation.radioErrorMessage,
}),
spouseEmail: z.string().optional(),
spouseNationalId: z.string().optional(),
spouseApproveTerms: z.array(z.string()).optional(),
})
.refine(
(v) =>
v.unregisteredCohabitation === ApproveOptions.Yes
? v.spouseEmail &&
isValidEmail(v.spouseEmail) &&
v.spouseNationalId &&
isValidNationalId(v.spouseNationalId) &&
v.spouseApproveTerms &&
v.spouseApproveTerms.length === 1
: true,
{
//More detailed error messages are in the UnknownRelationshipForm component
params: error.validation.email,
},
)

const childrenSchoolInfoSchema = z.array(
z.object({
fullName: z.string(),
nationalId: z.string(),
school: z.string(),
livesWithApplicant: z.boolean(),
livesWithBothParents: z.boolean(),
}),
)

const homeCircumstancesSchema = z
.object({
type: z.nativeEnum(HomeCircumstances).refine((v) => v, {
params: error.validation.radioErrorMessage,
}),
custom: z.string().optional(),
})
.refine((v) => (v.type === HomeCircumstances.OTHER ? v.custom : true), {
params: error.validation.inputErrorMessage,
path: ['custom'],
})

const studentSchema = z
.object({
isStudent: z.nativeEnum(ApproveOptions).refine((v) => v, {
params: error.validation.radioErrorMessage,
}),
custom: z.string().optional(),
})
.refine((v) => (v.isStudent === ApproveOptions.Yes ? v.custom : true), {
params: error.validation.inputErrorMessage,
path: ['custom'],
})

const employmentSchema = z
.object({
type: z.nativeEnum(Employment).refine((v) => v, {
params: error.validation.radioErrorMessage,
}),
custom: z.string().optional(),
})
.refine((v) => (v.type === Employment.OTHER ? v.custom : true), {
params: error.validation.inputErrorMessage,
path: ['custom'],
})

export const dataSchema = z.object({
approveExternalData: z.boolean().refine((v) => v, {
params: error.validation.dataGathering,
@@ -22,95 +93,15 @@ export const dataSchema = z.object({
params: error.validation.approveSpouse,
}),
}),
childrenSchoolInfo: z.array(
z.object({
fullName: z.string(),
nationalId: z.string(),
school: z.string(),
livesWithApplicant: z.boolean(),
livesWithBothParents: z.boolean(),
}),
),
relationshipStatus: relationshipStatusSchema,
childrenSchoolInfo: childrenSchoolInfoSchema,
childrenComment: z.string().optional(),
relationshipStatus: z
.object({
unregisteredCohabitation: z
.enum([ApproveOptions.Yes, ApproveOptions.No])
.refine((v) => v, {
params: error.validation.radioErrorMessage,
}),
spouseEmail: z.string().optional(),
spouseNationalId: z.string().optional(),
spouseApproveTerms: z.array(z.string()).optional(),
})
.refine(
(v) =>
v.unregisteredCohabitation === ApproveOptions.Yes
? v.spouseEmail &&
isValidEmail(v.spouseEmail) &&
v.spouseNationalId &&
isValidNationalId(v.spouseNationalId) &&
v.spouseApproveTerms &&
v.spouseApproveTerms.length === 1
: true,
{
//More detailed error messages are in the UnknownRelationshipForm component
params: error.validation.email,
},
),
student: z
.object({
isStudent: z
.enum([ApproveOptions.Yes, ApproveOptions.No])
.refine((v) => v, {
params: error.validation.radioErrorMessage,
}),
custom: z.string().optional(),
})
.refine((v) => (v.isStudent === ApproveOptions.Yes ? v.custom : true), {
params: error.validation.inputErrorMessage,
}),
homeCircumstances: z
.object({
type: z
.enum([
HomeCircumstances.WITHPARENTS,
HomeCircumstances.WITHOTHERS,
HomeCircumstances.OWNPLACE,
HomeCircumstances.REGISTEREDLEASE,
HomeCircumstances.UNREGISTEREDLEASE,
HomeCircumstances.OTHER,
])
.refine((v) => v, {
params: error.validation.radioErrorMessage,
}),
custom: z.string().optional(),
})
.refine((v) => (v.type === HomeCircumstances.OTHER ? v.custom : true), {
params: error.validation.inputErrorMessage,
path: ['custom'],
}),
homeCircumstances: homeCircumstancesSchema,
student: studentSchema,
employment: employmentSchema,
income: z.enum([ApproveOptions.Yes, ApproveOptions.No]).refine((v) => v, {
params: error.validation.radioErrorMessage,
}),
employment: z
.object({
type: z
.enum([
Employment.WORKING,
Employment.UNEMPLOYED,
Employment.CANNOTWORK,
Employment.OTHER,
])
.refine((v) => v, {
params: error.validation.radioErrorMessage,
}),
custom: z.string().optional(),
})
.refine((v) => (v.type === Employment.OTHER ? v.custom : true), {
params: error.validation.inputErrorMessage,
path: ['custom'],
}),
bankInfo: z.object({
bankNumber: z.string().optional(),
ledger: z.string().optional(),
25 changes: 24 additions & 1 deletion libs/application/templates/financial-aid/src/utils/conditions.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import {
ApplicantChildCustodyInformation,
ExternalData,
FormValue,
NationalRegistrySpouse,
} from '@island.is/application/types'
import { ApproveOptions } from '..'
import { getValueViaPath } from '@island.is/application/core'
import { HomeCircumstances } from '@island.is/financial-aid/shared/lib'
import {
Employment,
HomeCircumstances,
} from '@island.is/financial-aid/shared/lib'

export const hasSpouse = (_answers: FormValue, externalData: ExternalData) =>
getValueViaPath<NationalRegistrySpouse>(
@@ -25,6 +29,25 @@ export const isInRelationship = (answers: FormValue) =>
'relationshipStatus.unregisteredCohabitation',
) === ApproveOptions.Yes

export const hasChildren = (
_answers: FormValue,
externalData: ExternalData,
) => {
const childWithInfo = getValueViaPath<ApplicantChildCustodyInformation[]>(
externalData,
'childrenCustodyInformation.data',
[],
)
return Boolean(childWithInfo?.length)
}

export const hasOtherHomeCircumstances = (answers: FormValue) =>
getValueViaPath<HomeCircumstances>(answers, 'homeCircumstances.type') ===
HomeCircumstances.OTHER

export const isStudent = (answers: FormValue) =>
getValueViaPath<ApproveOptions>(answers, 'student.isStudent') ===
ApproveOptions.Yes

export const otherEmployment = (answers: FormValue) =>
getValueViaPath<Employment>(answers, 'employment.type') === Employment.OTHER
35 changes: 34 additions & 1 deletion libs/application/templates/financial-aid/src/utils/options.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { HomeCircumstances } from '@island.is/financial-aid/shared/lib'
import {
Employment,
HomeCircumstances,
} from '@island.is/financial-aid/shared/lib'
import * as m from '../lib/messages'
import { ApproveOptions } from '..'

@@ -54,3 +57,33 @@ export const homeCircumstancesOptions = [
label: m.homeCircumstancesForm.circumstances.other,
},
]

export const studentOptions = [
{
value: ApproveOptions.No,
label: m.approveOptions.no,
},
{
value: ApproveOptions.Yes,
label: m.approveOptions.yes,
},
]

export const employmentOptions = [
{
value: Employment.WORKING,
label: m.employmentForm.employment.working,
},
{
value: Employment.UNEMPLOYED,
label: m.employmentForm.employment.unemployed,
},
{
value: Employment.CANNOTWORK,
label: m.employmentForm.employment.cannotWork,
},
{
value: Employment.OTHER,
label: m.employmentForm.employment.other,
},
]

0 comments on commit 328b65d

Please sign in to comment.