Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
37 changes: 21 additions & 16 deletions app/assets/javascript/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand All @@ -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'
Expand All @@ -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
Expand All @@ -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.
Expand Down
26 changes: 19 additions & 7 deletions app/lib/utils/medical-information.js
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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
Expand Down
58 changes: 41 additions & 17 deletions app/routes/appointments/medical-information.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
Loading