Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(new-primary-school): Implement school meal page #17513

Merged
merged 5 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { getApplicationAnswers } from '../../lib/newPrimarySchoolUtils'

import { AllergiesAndIntolerances } from './review-groups/AllergiesAndIntolerances'
import { Child } from './review-groups/Child'
import { FreeSchoolMeal } from './review-groups/FreeSchoolMeal'
import { Languages } from './review-groups/Languages'
import { Parents } from './review-groups/Parents'
import { ReasonForApplication } from './review-groups/ReasonForApplication'
Expand Down Expand Up @@ -166,6 +167,7 @@ export const Review: FC<ReviewScreenProps> = ({
)}
<School {...childProps} />
<Languages {...childProps} />
<FreeSchoolMeal {...childProps} />
<AllergiesAndIntolerances {...childProps} />
<Support {...childProps} />
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { coreErrorMessages } from '@island.is/application/core'
import { YES } from '@island.is/application/types'
import {
DataValue,
RadioValue,
ReviewGroup,
} from '@island.is/application/ui-components'
import {
GridColumn,
GridRow,
SkeletonLoader,
Stack,
} from '@island.is/island-ui/core'
import { useLocale } from '@island.is/localization'
import { useFriggOptions } from '../../../hooks/useFriggOptions'
import { OptionsType } from '../../../lib/constants'
import { newPrimarySchoolMessages } from '../../../lib/messages'
import {
getApplicationAnswers,
getSelectedOptionLabel,
} from '../../../lib/newPrimarySchoolUtils'
import { ReviewGroupProps } from './props'

export const FreeSchoolMeal = ({
application,
editable,
goToScreen,
}: ReviewGroupProps) => {
const { formatMessage } = useLocale()
const { acceptFreeSchoolLunch, hasSpecialNeeds, specialNeedsType } =
getApplicationAnswers(application.answers)

const {
options: specialNeedsTypeOptions,
loading,
error,
} = useFriggOptions(OptionsType.ALLERGY) // TODO: Update when Júní has updated key-options

return (
<ReviewGroup
isEditable={editable}
editAction={() => goToScreen?.('freeSchoolMeal')}
>
<Stack space={2}>
{acceptFreeSchoolLunch === YES && hasSpecialNeeds === YES && loading ? (
<SkeletonLoader height={40} width="80%" borderRadius="large" />
) : (
<>
<GridRow>
<GridColumn span="10/12">
<RadioValue
label={formatMessage(
newPrimarySchoolMessages.differentNeeds
.acceptFreeSchoolLunch,
)}
value={acceptFreeSchoolLunch}
/>
</GridColumn>
</GridRow>
{acceptFreeSchoolLunch === YES && (
<GridRow>
<GridColumn span="12/12">
<RadioValue
label={formatMessage(
newPrimarySchoolMessages.differentNeeds.hasSpecialNeeds,
)}
value={hasSpecialNeeds}
/>
</GridColumn>
</GridRow>
)}
{acceptFreeSchoolLunch === YES && hasSpecialNeeds === YES && (
<GridRow>
<GridColumn span="12/12">
<DataValue
label={formatMessage(
newPrimarySchoolMessages.differentNeeds.specialNeedsType,
)}
value={getSelectedOptionLabel(
specialNeedsTypeOptions,
specialNeedsType,
)}
error={
error
? formatMessage(coreErrorMessages.failedDataProvider)
: undefined
}
/>
</GridColumn>
</GridRow>
)}
</>
)}
</Stack>
</ReviewGroup>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import {
buildAlertMessageField,
buildCustomField,
buildMultiField,
buildRadioField,
buildSubSection,
} from '@island.is/application/core'
import { NO, YES } from '@island.is/application/types'
import { OptionsType } from '../../../lib/constants'
import { newPrimarySchoolMessages } from '../../../lib/messages'
import { getApplicationAnswers } from '../../../lib/newPrimarySchoolUtils'

export const freeSchoolMealSubSection = buildSubSection({
id: 'freeSchoolMealSubSection',
title: newPrimarySchoolMessages.differentNeeds.freeSchoolMealSubSectionTitle,
children: [
buildMultiField({
id: 'freeSchoolMeal',
title:
newPrimarySchoolMessages.differentNeeds.freeSchoolMealSubSectionTitle,
description:
newPrimarySchoolMessages.differentNeeds.freeSchoolMealDescription,
children: [
buildRadioField({
id: 'freeSchoolMeal.acceptFreeSchoolLunch',
title: newPrimarySchoolMessages.differentNeeds.acceptFreeSchoolLunch,
width: 'half',
required: true,
options: [
{
label: newPrimarySchoolMessages.shared.yes,
value: YES,
},
{
label: newPrimarySchoolMessages.shared.no,
value: NO,
},
],
}),
buildRadioField({
id: 'freeSchoolMeal.hasSpecialNeeds',
title: newPrimarySchoolMessages.differentNeeds.hasSpecialNeeds,
width: 'half',
required: true,
space: 4,
options: [
{
label: newPrimarySchoolMessages.shared.yes,
value: YES,
},
{
label: newPrimarySchoolMessages.shared.no,
value: NO,
},
],
condition: (answers) => {
const { acceptFreeSchoolLunch } = getApplicationAnswers(answers)

return acceptFreeSchoolLunch === YES
},
}),
buildCustomField(
{
id: 'freeSchoolMeal.specialNeedsType',
title: newPrimarySchoolMessages.differentNeeds.specialNeedsType,
component: 'FriggOptionsAsyncSelectField',
condition: (answers) => {
const { acceptFreeSchoolLunch, hasSpecialNeeds } =
getApplicationAnswers(answers)

return acceptFreeSchoolLunch === YES && hasSpecialNeeds === YES
},
},
{
optionsType: OptionsType.ALLERGY, // TODO: Update when Júní has updated key-options
placeholder:
newPrimarySchoolMessages.differentNeeds
.specialNeedsTypePlaceholder,
},
),
buildAlertMessageField({
id: 'freeSchoolMeal.foodAlergiesAlertMessage',
title: newPrimarySchoolMessages.shared.alertTitle,
message:
newPrimarySchoolMessages.differentNeeds.foodAlergiesAlertMessage,
doesNotRequireAnswer: true,
alertType: 'info',
condition: (answers) => {
const { acceptFreeSchoolLunch, hasSpecialNeeds } =
getApplicationAnswers(answers)

return acceptFreeSchoolLunch === YES && hasSpecialNeeds === YES
},
}),
],
}),
],
})
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ReasonForApplicationOptions } from '../../../lib/constants'
import { newPrimarySchoolMessages } from '../../../lib/messages'
import { getApplicationAnswers } from '../../../lib/newPrimarySchoolUtils'
import { allergiesAndIntolerancesSubSection } from './allergiesAndIntolerancesSubSection'
import { freeSchoolMealSubSection } from './freeSchoolMealSubSection'
import { languageSubSection } from './languageSubSection'
import { supportSubSection } from './supportSubSection'

Expand All @@ -16,6 +17,7 @@ export const differentNeedsSection = buildSection({
},
children: [
languageSubSection,
freeSchoolMealSubSection,
allergiesAndIntolerancesSubSection,
supportSubSection,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ const NewPrimarySchoolTemplate: ApplicationTemplate<
'clearPlaceOfResidence',
'clearLanguages',
'clearAllergiesAndIntolerances',
'clearFreeSchoolMeal',
],
meta: {
name: States.DRAFT,
Expand Down Expand Up @@ -247,6 +248,20 @@ const NewPrimarySchoolTemplate: ApplicationTemplate<
}
return context
}),
clearFreeSchoolMeal: assign((context) => {
const { application } = context
const { acceptFreeSchoolLunch, hasSpecialNeeds } =
getApplicationAnswers(application.answers)

if (acceptFreeSchoolLunch !== YES) {
unset(application.answers, 'freeSchoolMeal.hasSpecialNeeds')
unset(application.answers, 'freeSchoolMeal.specialNeedsType')
}
if (hasSpecialNeeds !== YES) {
unset(application.answers, 'freeSchoolMeal.specialNeedsType')
}
return context
}),
},
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,30 @@ export const dataSchema = z.object({
params: errorMessages.languagesRequired,
},
),
freeSchoolMeal: z
.object({
acceptFreeSchoolLunch: z.enum([YES, NO]),
veronikasif marked this conversation as resolved.
Show resolved Hide resolved
hasSpecialNeeds: z.string().optional(),
specialNeedsType: z.string().optional(),
veronikasif marked this conversation as resolved.
Show resolved Hide resolved
})
.refine(
({ acceptFreeSchoolLunch, hasSpecialNeeds }) =>
acceptFreeSchoolLunch === YES
? !!hasSpecialNeeds && hasSpecialNeeds.length > 0
: true,
{
path: ['hasSpecialNeeds'],
},
)
.refine(
({ acceptFreeSchoolLunch, hasSpecialNeeds, specialNeedsType }) =>
acceptFreeSchoolLunch === YES && hasSpecialNeeds === YES
? !!specialNeedsType && specialNeedsType.length > 0
: true,
{
path: ['specialNeedsType'],
},
),
allergiesAndIntolerances: z
.object({
hasFoodAllergiesOrIntolerances: z.array(z.string()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,50 @@ export const newPrimarySchoolMessages: MessageDir = {
"Icelandic is not spoken in the child's immediate environment",
},

// Free school meal
freeSchoolMealSubSectionTitle: {
id: 'nps.application:different.needs.free.school.meal.sub.section.title',
defaultMessage: 'Gjaldfrjáls skólamáltíð',
description: 'Free school meal ',
},
freeSchoolMealDescription: {
id: 'nps.application:different.needs.free.school.meal.description',
defaultMessage:
'Barninu stendur til boða gjaldfrjáls skólamáltíð. Til þess að skólinn geti mætt fæðuþörfum barnsins á sama tíma og spornað er við matarsóun þurfum við upplýsingar er varða matarumhverfi barnsins.',
description:
"The child is entitled to a free school meal. In order for the school to be able to meet the child's nutritional needs while at the same time preventing food waste, we need information about the child's food environment.",
},
acceptFreeSchoolLunch: {
id: 'nps.application:different.needs.free.school.meal.accept.fre.school.lunch',
defaultMessage:
'Viltu þiggja gjaldfrjálsa máltíð í hádeginu fyrir barnið þitt?',
description:
'Would you like to accept a free school lunch for your child?',
},
hasSpecialNeeds: {
id: 'nps.application:different.needs.free.school.meal.has.special.needs',
defaultMessage:
'Er barnið með sérþarfir sem óskað er eftir að tekið sé tillit til?',
description:
'Does the child have special needs that you wish to be taken into account?',
},
specialNeedsType: {
id: 'nps.application:different.needs.free.school.meal.special.needs.type',
defaultMessage: 'Tegund',
description: 'Type',
},
specialNeedsTypePlaceholder: {
id: 'nps.application:different.needs.free.school.meal.special.needs.type.placeholder',
defaultMessage: 'Veldu tegund',
description: 'Select type',
},
foodAlergiesAlertMessage: {
id: 'nps.application:different.needs.free.school.meal.food.alergies.alert.message',
veronikasif marked this conversation as resolved.
Show resolved Hide resolved
defaultMessage: 'Spurt er um matarofnæmi undir ofnæmi og óþól',
description:
'Food allergies are addressed in the allergies and intolerances section',
},

veronikasif marked this conversation as resolved.
Show resolved Hide resolved
// Allergies and intolerances
allergiesAndIntolerancesSubSectionTitle: {
id: 'nps.application:different.needs.allergies.and.intolerances.sub.section.title',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ export const getApplicationAnswers = (answers: Application['answers']) => {
'languages.icelandicNotSpokenAroundChild',
) as string[]

const acceptFreeSchoolLunch = getValueViaPath(
answers,
'freeSchoolMeal.acceptFreeSchoolLunch',
) as YesOrNo

const hasSpecialNeeds = getValueViaPath(
answers,
'freeSchoolMeal.hasSpecialNeeds',
) as YesOrNo

const specialNeedsType = getValueViaPath(
answers,
'freeSchoolMeal.specialNeedsType',
) as string

const hasFoodAllergiesOrIntolerances = getValueViaPath(
answers,
'allergiesAndIntolerances.hasFoodAllergiesOrIntolerances',
Expand Down Expand Up @@ -162,6 +177,9 @@ export const getApplicationAnswers = (answers: Application['answers']) => {
otherLanguagesSpokenDaily,
otherLanguages,
icelandicNotSpokenAroundChild,
acceptFreeSchoolLunch,
hasSpecialNeeds,
specialNeedsType,
hasFoodAllergiesOrIntolerances,
foodAllergiesOrIntolerances,
hasOtherAllergies,
Expand Down
Loading