diff --git a/app/assets/javascript/main.js b/app/assets/javascript/main.js index bdc7aa2e..9fc8505b 100644 --- a/app/assets/javascript/main.js +++ b/app/assets/javascript/main.js @@ -201,13 +201,13 @@ function setupBreastDensityFactorsAutosave() { return } - const factorsName = 'breastDensityFactors' const hrtName = 'breastDensityFactorsHrt' + const hrtYearStartedName = 'breastDensityFactorsHrtYearStarted' + const hrtYearStoppedName = 'breastDensityFactorsHrtYearStopped' - const checkboxes = container.querySelectorAll(`input[name="${factorsName}"]`) const hrtRadios = container.querySelectorAll(`input[name="${hrtName}"]`) - if (checkboxes.length === 0 && hrtRadios.length === 0) { + if (hrtRadios.length === 0) { return } @@ -223,13 +223,8 @@ function setupBreastDensityFactorsAutosave() { return } - // "No" to HRT is an answer, not a factor - match the count in - // getBreastDensityFactors so the two never disagree - const checkedFactors = container.querySelectorAll( - `input[name="${factorsName}"]:checked` - ).length const hrtYes = container.querySelector(`input[name="${hrtName}"]:checked`)?.value === 'yes' - const count = checkedFactors + (hrtYes ? 1 : 0) + const count = hrtYes ? 1 : 0 if (count === 0) { summary.textContent = 'No breast density factors added' @@ -244,18 +239,24 @@ function setupBreastDensityFactorsAutosave() { // queue - otherwise an earlier response could be the last one to arrive let pendingSave = Promise.resolve() - const saveFactors = () => { + const saveHrt = () => { const formData = new URLSearchParams() - container - .querySelectorAll(`input[name="${factorsName}"]:checked`) - .forEach((checkbox) => formData.append(factorsName, checkbox.value)) - const selectedHrt = container.querySelector(`input[name="${hrtName}"]:checked`) if (selectedHrt) { formData.append(hrtName, selectedHrt.value) } + const yearStartedInput = container.querySelector(`input[name="${hrtYearStartedName}"]`) + if (yearStartedInput) { + formData.append(hrtYearStartedName, yearStartedInput.value) + } + + const yearStoppedInput = container.querySelector(`input[name="${hrtYearStoppedName}"]`) + if (yearStoppedInput) { + formData.append(hrtYearStoppedName, yearStoppedInput.value) + } + updateContentsSummary() pendingSave = pendingSave @@ -279,8 +280,12 @@ function setupBreastDensityFactorsAutosave() { } container - .querySelectorAll(`input[name="${factorsName}"], input[name="${hrtName}"]`) - .forEach((input) => input.addEventListener('change', saveFactors)) + .querySelectorAll(`input[name="${hrtName}"]`) + .forEach((input) => input.addEventListener('change', saveHrt)) + + container + .querySelectorAll(`input[name="${hrtYearStartedName}"], input[name="${hrtYearStoppedName}"]`) + .forEach((input) => input.addEventListener('change', saveHrt)) } // Quick settings modal — press backtick (`) to open settings in a modal overlay. diff --git a/app/lib/utils/medical-information.js b/app/lib/utils/medical-information.js index c7cfead3..5a0c1e30 100644 --- a/app/lib/utils/medical-information.js +++ b/app/lib/utils/medical-information.js @@ -464,26 +464,32 @@ const summariseBreastFeatures = (features) => { */ const getBreastDensityFactors = (medicalInformation) => { const rawFactors = medicalInformation?.breastDensityFactors - const factors = Array.isArray(rawFactors) - ? rawFactors.filter(Boolean) + const factors = (Array.isArray(rawFactors) + ? rawFactors : rawFactors ? [rawFactors] : [] + ).filter((f) => f && f !== '_unchecked') const hrt = medicalInformation?.breastDensityFactorsHrt + const hrtYearStarted = medicalInformation?.breastDensityFactorsHrtYearStarted + const hrtYearStopped = medicalInformation?.breastDensityFactorsHrtYearStopped // "Not started HRT" is an answer, but it isn't a density factor - only // count the things that actually affect density const count = (hrt === 'yes' ? 1 : 0) + (factors.includes('pregnant') ? 1 : 0) + - (factors.includes('breastfeeding') ? 1 : 0) + (factors.includes('breastfeeding') ? 1 : 0) + + (factors.includes('stopped-less-than-3-months') ? 1 : 0) const summaries = summariseBreastDensityFactors(medicalInformation) return { factors, hrt, + hrtYearStarted, + hrtYearStopped, count, // Everything worth showing, including a recorded "no" to HRT question - use this // to decide whether to show the row at all, and count for "n added" @@ -507,21 +513,27 @@ const summariseBreastDensityFactors = (medicalInformation) => { : [] const hrt = medicalInformation?.breastDensityFactorsHrt + const hrtYearStarted = medicalInformation?.breastDensityFactorsHrtYearStarted + const hrtYearStopped = medicalInformation?.breastDensityFactorsHrtYearStopped const summaries = [] if (hrt === 'yes') { - summaries.push('Started a course of HRT since last screening appointment') + summaries.push('Currently taking HRT' + (hrtYearStarted ? ` (Approximate year started: ${hrtYearStarted})` : '')) } else if (hrt === 'no') { - summaries.push('Not started a course of HRT since last screening appointment') + summaries.push('Not currently taking HRT' + (hrtYearStopped ? ` (stopped: ${hrtYearStopped})` : '')) } if (factors.includes('pregnant')) { - summaries.push('Pregnant') + summaries.push('Currently pregnant') } if (factors.includes('breastfeeding')) { - summaries.push('Breastfeeding') + summaries.push('Currently breastfeeding') + } + + if (factors.includes('stopped-less-than-3-months')) { + summaries.push('Pregnancy or breastfeeding stopped less than 3 months ago') } return summaries diff --git a/app/routes/appointments/medical-information.js b/app/routes/appointments/medical-information.js index 11dd646d..44370294 100644 --- a/app/routes/appointments/medical-information.js +++ b/app/routes/appointments/medical-information.js @@ -29,44 +29,68 @@ module.exports = (router) => { const { appointmentId } = req.params const data = req.session.data - // An unticked checkbox group posts nothing at all, so a missing value - // means "none selected" rather than "unchanged" - const postedFactors = req.body?.breastDensityFactors - const factors = ( - Array.isArray(postedFactors) - ? postedFactors - : postedFactors - ? [postedFactors] - : [] - ).filter((factor) => factor && factor !== '_unchecked') - const postedHrt = req.body?.breastDensityFactorsHrt + const postedHrtYearStarted = req.body?.breastDensityFactorsHrtYearStarted + const postedHrtYearStopped = req.body?.breastDensityFactorsHrtYearStopped - // The appointment context middleware has already made the temp copy, - // so this is only defensive if (data.appointment?.id !== appointmentId) { res.status(409).send() return } const medicalInformation = data.appointment.medicalInformation || {} - medicalInformation.breastDensityFactors = factors if (postedHrt) { medicalInformation.breastDensityFactorsHrt = postedHrt } + if (postedHrtYearStarted !== undefined) { + medicalInformation.breastDensityFactorsHrtYearStarted = postedHrtYearStarted + } + + if (postedHrtYearStopped !== undefined) { + medicalInformation.breastDensityFactorsHrtYearStopped = postedHrtYearStopped + } + data.appointment.medicalInformation = medicalInformation - // These aren't form fields for any other page - don't leave them in - // session data where auto-store-data has put them - delete data.breastDensityFactors delete data.breastDensityFactorsHrt + delete data.breastDensityFactorsHrtYearStarted + delete data.breastDensityFactorsHrtYearStopped res.status(204).send() } ) + // Pregnancy/breastfeeding modal form — data is auto-saved by the kit + // via the field name; we just need the modalBreakout redirect. + // Pregnancy/breastfeeding modal — auto-store-data saves the field + // directly to appointment.medicalInformation.breastDensityFactors; + // route only handles the modalBreakout redirect. + router.post( + '/clinics/:clinicId/appointments/:appointmentId/medical-information/pregnancy-and-breastfeeding-save', + (req, res) => { + const { clinicId, appointmentId } = req.params + res.redirect(modalBreakout(`/clinics/${clinicId}/appointments/${appointmentId}/review-medical-information`)) + } + ) + + // Delete pregnancy/breastfeeding + router.get( + '/clinics/:clinicId/appointments/:appointmentId/medical-information/pregnancy-and-breastfeeding-delete', + (req, res) => { + const { clinicId, appointmentId } = req.params + const data = req.session.data + + if (data.appointment?.medicalInformation) { + delete data.appointment.medicalInformation.breastDensityFactors + } + + req.flash('success', 'Pregnancy and breastfeeding deleted') + res.redirect(modalBreakout(`/clinics/${clinicId}/appointments/${appointmentId}/review-medical-information`)) + } + ) + // Save breast features (includes converting JSON string to structured data) router.post( '/clinics/:clinicId/appointments/:appointmentId/medical-information/record-breast-features/save', diff --git a/app/views/_includes/forms/breast-density-factors.njk b/app/views/_includes/forms/breast-density-factors.njk index a8a211e2..51be6fab 100644 --- a/app/views/_includes/forms/breast-density-factors.njk +++ b/app/views/_includes/forms/breast-density-factors.njk @@ -19,28 +19,55 @@ {% set participantName = participant | getFullName %} -{% set hrtQuestion = "Has " + participant.demographicInformation.firstName + " started a course of HRT since their last screening appointment?" %} +{% set hrtQuestion = "Is " + participant.demographicInformation.firstName + " currently taking HRT?" %} {% set pregnantOrBreastfeedingQuestion = "Is " + participant.demographicInformation.firstName + " pregnant or breastfeeding?" %} +{% set hrtYesConditionalHtml %} +
Started a course of HRT since last screening appointment
+Currently taking HRT{% if breastDensityFactors.hrtYearStarted %} (started: {{ breastDensityFactors.hrtYearStarted }}){% endif %}
{% elseif breastDensityFactors.hrt == "no" %} -Not started a course of HRT since last screening appointment
+Not currently taking HRT{% if breastDensityFactors.hrtYearStopped %} (stopped: {{ breastDensityFactors.hrtYearStopped }}){% endif %}
{% else %}Not answered
{% endif %} @@ -84,10 +111,13 @@ {% if breastDensityFactors.factors | length %}+ {{ button({ + text: "Add pregnancy and breastfeeding", + href: contextUrl + "/medical-information/pregnancy-and-breastfeeding", + variant: "secondary", + small: true + } | openInModal) }} +
+ {% endif %}