Skip to content

Commit 7b3db09

Browse files
committed
Show health questions for chosen vaccines for all appointments in clinic booking
Prior to this, the health questions presented were: - a hard-coded set of questions - shown for only one appointment - not attributed to a specific child
1 parent a32ea08 commit 7b3db09

7 files changed

Lines changed: 97 additions & 76 deletions

File tree

app/controllers/book-into-a-clinic.js

Lines changed: 17 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@ import _ from 'lodash'
44

55
import { ParentalRelationship, SessionPresets } from '../enums.js'
66
import { ClinicAppointment, ClinicBooking } from '../models.js'
7-
import { getAllAppointmentPaths } from '../utils/clinic-appointment.js'
7+
import {
8+
getAllAppointmentPaths,
9+
getHealthQuestionPaths
10+
} from '../utils/clinic-appointment.js'
811
import { kebabToCamelCase } from '../utils/string.js'
912

1013
export const bookIntoClinicController = {
@@ -167,28 +170,15 @@ export const bookIntoClinicController = {
167170
value: 'false'
168171
}
169172
},
170-
// TODO: Currently, `appointment` in this call to getHealthQuestionPaths is null because offer-health-questions is outside the appointment journey
171-
// Should I put the offer into the journey too, and offer per-child, or should I just pass the first appointment on the booking?
172-
//...getHealthQuestionPaths(`/${session_preset_slug}/${booking_uuid}/new/${appointment_uuid}/`, appointment),
173-
// TODO: logic to loop back if more than one appointment
174-
175-
// REMOVE: hard-coded health questions, and update showForm to reset to using generic health-question.njk view
176-
[`/${session_preset_slug}/${booking_uuid}/new/health-question-immune-system-hpv`]:
177-
{},
178-
[`/${session_preset_slug}/${booking_uuid}/new/health-question-allergy`]:
179-
{},
180-
[`/${session_preset_slug}/${booking_uuid}/new/health-question-bleeding`]:
181-
{},
182-
[`/${session_preset_slug}/${booking_uuid}/new/health-question-blood-thinning`]:
183-
{},
184-
[`/${session_preset_slug}/${booking_uuid}/new/health-question-previous-reaction`]:
185-
{},
186-
[`/${session_preset_slug}/${booking_uuid}/new/health-question-recent-men-acwy-vaccination`]:
187-
{},
188-
[`/${session_preset_slug}/${booking_uuid}/new/health-question-recent-td-ipv-vaccination`]:
189-
{},
190-
[`/${session_preset_slug}/${booking_uuid}/new/impairments`]: {},
191-
[`/${session_preset_slug}/${booking_uuid}/new/adjustments`]: {},
173+
174+
// For each child being booked in, and their selected vaccinations, ask the
175+
// relevant health questions and impairments/adjustments questions
176+
...getHealthQuestionPaths(
177+
`/${session_preset_slug}/${booking_uuid}/new/`,
178+
booking_uuid,
179+
data.wizard,
180+
data
181+
),
192182

193183
// Check answers
194184
[`/${session_preset_slug}/${booking_uuid}/new/check-answers`]: {},
@@ -233,7 +223,9 @@ export const bookIntoClinicController = {
233223

234224
// Only ask for details if question does not have sub-questions
235225
const hasSubQuestions =
236-
appointment?.healthQuestionsForSelectedProgrammes[key]?.conditional
226+
appointment?.getHealthQuestionsForSelectedProgrammes(
227+
request.session.data
228+
)[key]?.conditional
237229

238230
response.render(`book-into-a-clinic/form/${view}`, { key, hasSubQuestions })
239231
},
@@ -261,13 +253,11 @@ export const bookIntoClinicController = {
261253
)
262254
}
263255
if (request.body.transaction) {
264-
// MAL: need to key this on the booking_uuid, not just have one transaction object shared by all users
265256
data.wizard.transaction = data.wizard.transaction ?? {}
266257
_.merge(data.wizard.transaction, request.body.transaction)
267258
}
268259

269-
// If we've just set the child count, create the appointments to start the sub-journey and
270-
// put the first uuid into the routes from this point on
260+
// If we've just set the child count, create the appointments we'll need
271261
if (request.originalUrl.endsWith('/new/child-count')) {
272262
const booking = ClinicBooking.findOne(booking_uuid, data.wizard)
273263

app/locales/en.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ export const en = {
282282
hint: 'For example, if you have twins needing vaccination, enter 2'
283283
}
284284
},
285+
nextChildButtonText: 'Continue to next child',
285286
appointment: {
286287
caption: 'Appointment for %s'
287288
},
@@ -448,6 +449,7 @@ export const en = {
448449
},
449450
healthAnswers: {
450451
label: 'Answers to health questions',
452+
caption: 'Health questions for %s',
451453
yes: 'Yes',
452454
no: 'No',
453455
details: 'Give details'

app/models/clinic-appointment.js

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { fakerEN_GB as faker } from '@faker-js/faker'
22
import _ from 'lodash'
33

4-
import vaccines from '../datasets/vaccines.js'
54
import {
65
ClinicBooking,
76
Parent,
@@ -200,12 +199,13 @@ export class ClinicAppointment {
200199
/**
201200
* Get the programmes selected for this appointment
202201
*
202+
* @param {object} programmeContext - the context in which we'll find the programmes
203203
* @returns {Array<Programme>} Programmes selected for this appointment
204204
*/
205-
get selectedProgrammes() {
205+
#getSelectedProgrammes(programmeContext) {
206206
return ClinicAppointment.#getProgrammesFromIDs(
207207
this.selected_programme_ids,
208-
this.context
208+
programmeContext ?? this.context
209209
)
210210
}
211211

@@ -258,19 +258,24 @@ export class ClinicAppointment {
258258
*
259259
* Note: this method requires this instance to have a full context
260260
*
261+
* @param {object} programmeContext - the context in which we'll find the programmes
261262
* @returns {Array} Health questions
262263
*/
263-
get healthQuestionsForSelectedProgrammes() {
264-
// Work out which vaccines the child could receive
264+
getHealthQuestionsForSelectedProgrammes(programmeContext) {
265+
// Logic is: programme -> vaccine (matched on programme type) -> health questions
266+
265267
// NB: given we don't have information about consent for nasal vs. injection, or for
266268
// gelatine, we can end up asking more questions here than we might need to. :/
267269
const vaccinesForSelectedProgrammes = []
268-
for (const programme of this.selectedProgrammes) {
270+
for (const programme of this.#getSelectedProgrammes(programmeContext)) {
269271
vaccinesForSelectedProgrammes.push(
270-
...Object.values(vaccines).filter((v) => v.type === programme.type)
272+
...Object.values(programmeContext.vaccines).filter(
273+
(v) => v.type === programme.type
274+
)
271275
)
272276
}
273277

278+
// Collate the questions from the vaccines, making sure we don't duplicate them
274279
const questions = new Map()
275280
for (const vaccine of vaccinesForSelectedProgrammes) {
276281
for (const [key, value] of Object.entries(vaccine.healthQuestions)) {
@@ -313,7 +318,7 @@ export class ClinicAppointment {
313318
date: session?.formatted.date ?? '',
314319
dateAndTime: `${session?.formatted.date} at ${formattedStartTime}`,
315320
timeSlot: `${formattedStartTime} to ${formattedEndTime}`,
316-
vaccinations: this.selectedProgrammes
321+
vaccinations: this.#getSelectedProgrammes(this.context)
317322
.map((programme) => programme.name)
318323
.join(', ')
319324
}

app/utils/clinic-appointment.js

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { ClinicBooking } from '../models.js'
2+
13
import { camelToKebabCase } from './string.js'
24

35
/**
@@ -70,62 +72,79 @@ export const getAllAppointmentPaths = (booking) => {
7072
* Get the path for a single health question
7173
*
7274
* @param {string} key
75+
* @param {ClinicAppointment} appointment
7376
* @param {string} pathPrefix
7477
* @returns
7578
*/
76-
const getHealthQuestionPath = (key, pathPrefix) => {
77-
return `${pathPrefix}health-question-${camelToKebabCase(key)}`
79+
const getHealthQuestionPath = (key, appointment, pathPrefix) => {
80+
return `${pathPrefix}${appointment.uuid}/health-question-${camelToKebabCase(key)}`
7881
}
7982

8083
/**
8184
* Get health question paths for given vaccines
8285
*
8386
* @param {string} pathPrefix - Path prefix
84-
* @param {import('../models.js').ClinicAppointment} appointment - clinic appointment
87+
* @param {string} booking_uuid - clinic booking identifier, for access to all appointments
88+
* @param {object} bookingContext - the data context holding the booking and appointments
89+
* @param {object} programmeContext - the data context holding the programme and vaccine info
8590
* @returns {object} Health question paths
8691
*/
87-
export const getHealthQuestionPaths = (pathPrefix, appointment) => {
88-
// Don't worry about it till we've actually made our first appointment
89-
if (!appointment) {
90-
console.log('getHealthQuestionPaths: no appointment')
92+
export const getHealthQuestionPaths = (
93+
pathPrefix,
94+
booking_uuid,
95+
bookingContext,
96+
programmeContext
97+
) => {
98+
const paths = {}
9199

92-
return {}
100+
const booking = ClinicBooking.findOne(booking_uuid, bookingContext)
101+
if (!booking) {
102+
return paths
93103
}
94104

95-
const paths = {}
96-
const healthQuestions = Object.entries(
97-
appointment.healthQuestionsForSelectedProgrammes
98-
)
105+
for (const appointment of booking.appointments) {
106+
const healthQuestions = Object.entries(
107+
appointment.getHealthQuestionsForSelectedProgrammes(programmeContext)
108+
)
99109

100-
healthQuestions.forEach(([key, question], index) => {
101-
const questionPath = getHealthQuestionPath(key, pathPrefix)
110+
healthQuestions.forEach(([key, question], index) => {
111+
const questionPath = getHealthQuestionPath(key, appointment, pathPrefix)
102112

103-
if (question.conditional) {
104-
const nextQuestion = healthQuestions[index + 1]
105-
if (nextQuestion) {
106-
const forkPath = getHealthQuestionPath(nextQuestion[0], pathPrefix)
113+
if (question.conditional) {
114+
const nextQuestion = healthQuestions[index + 1]
115+
if (nextQuestion) {
116+
const forkPath = getHealthQuestionPath(
117+
nextQuestion[0],
118+
appointment,
119+
pathPrefix
120+
)
107121

108-
paths[questionPath] = {
109-
[forkPath]: {
110-
data: `appointment.healthAnswers.${key}.answer`,
111-
value: 'No'
122+
paths[questionPath] = {
123+
[forkPath]: {
124+
data: `appointment.healthAnswers.${key}.answer`,
125+
value: 'No'
126+
}
112127
}
128+
} else {
129+
paths[questionPath] = {}
130+
}
131+
132+
// Add paths for conditional sub-questions
133+
for (const subKey of Object.keys(question.conditional)) {
134+
const subQuestionPath = getHealthQuestionPath(
135+
subKey,
136+
appointment,
137+
pathPrefix
138+
)
139+
paths[subQuestionPath] = {}
113140
}
114141
} else {
115142
paths[questionPath] = {}
116143
}
117-
118-
// Add paths for conditional sub-questions
119-
for (const subKey of Object.keys(question.conditional)) {
120-
const subQuestionPath = getHealthQuestionPath(subKey, pathPrefix)
121-
paths[subQuestionPath] = {}
122-
}
123-
} else {
124-
paths[questionPath] = {}
125-
}
126-
})
127-
128-
console.log(`getHealthQuestionPaths: ${paths.length} questions`)
144+
})
145+
paths[`${pathPrefix}${appointment.uuid}/impairments`] = {}
146+
paths[`${pathPrefix}${appointment.uuid}/adjustments`] = {}
147+
}
129148

130149
return paths
131150
}

app/views/book-into-a-clinic/form/adjustments.njk

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
{{ checkboxes({
77
fieldset: {
88
legend: {
9-
isPageHeading: true,
10-
text: title,
11-
size: "l"
9+
html: appHeading({
10+
classes: "nhsuk-fieldset__legend--l",
11+
title: title,
12+
caption: __("clinicBooking.healthAnswers.caption", fullName) if childCount > 1
13+
})
1214
}
1315
},
1416
items: [{

app/views/book-into-a-clinic/form/health-question.njk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
legend: {
1111
html: appHeading({
1212
classes: "nhsuk-fieldset__legend--l",
13-
title: title | replace('the child', 'your child')
13+
title: title | replace('the child', 'your child'),
14+
caption: __("clinicBooking.healthAnswers.caption", fullName) if childCount > 1
1415
})
1516
}
1617
}) %}

app/views/book-into-a-clinic/form/impairments.njk

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
{{ checkboxes({
77
fieldset: {
88
legend: {
9-
isPageHeading: true,
10-
text: title,
11-
size: "l"
9+
html: appHeading({
10+
classes: "nhsuk-fieldset__legend--l",
11+
title: title,
12+
caption: __("clinicBooking.healthAnswers.caption", fullName) if childCount > 1
13+
})
1214
}
1315
},
1416
items: [{

0 commit comments

Comments
 (0)