Skip to content

Commit 04222d6

Browse files
Add errors and warnings based on estimated due date (#163)
This adds some error messages if the estimated due date is highly likely to be an error, and some warnings if the estimated due date is outside the recommended period, but still possible. ## Errors ### Blank <img width="812" alt="Screenshot 2025-01-14 at 15 02 12" src="https://github.com/user-attachments/assets/9afe8356-536a-4713-96fe-052e8d2f271c" /> ### Due date is more than 37 weeks after vaccination date This is an error as also highly unlikely to know they are pregnant at this point ![Screenshot 2025-01-16 at 14 18 36](https://github.com/user-attachments/assets/558dc3f2-ed70-4301-a66c-ef8dadb570d8) ### Due date is more than 4 weeks before vaccination date This is an error as almost no pregnancies will go beyond 44 weeks <img width="908" alt="Screenshot 2025-01-14 at 14 58 25" src="https://github.com/user-attachments/assets/868d0ffd-f4d1-4315-a589-aec5c3aca4c8" /> ## Warnings These are shown on a subsequent page, and users can choose to either continue, go back (eg to fix a mistake) or cancel the vaccination (by navigating away). ### RSV This is only shown if the patient is not yet 28 weeks pregnant ![Screenshot 2025-01-16 at 14 22 29](https://github.com/user-attachments/assets/02398ba6-611b-4e73-bbd2-be5b9f585094) ### Pertussis This is only shown if the patient is not yet 16 weeks pregnant ![Screenshot 2025-01-16 at 14 21 30](https://github.com/user-attachments/assets/38445572-e68b-409f-ac1a-a11e114f90b5) --------- Co-authored-by: Anna-Sutton <[email protected]>
1 parent 6037c38 commit 04222d6

File tree

4 files changed

+241
-5
lines changed

4 files changed

+241
-5
lines changed

app/routes/vaccinate.js

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,33 @@
1+
// Returns a date object from a valid year, month, and day.
2+
// Note: inputs can be strings, and month is based on 1 = Jan
3+
// rather than 0 = Jan
4+
// Time is set to midday
5+
function dateFromYearMonthDay(year, month, day) {
6+
const yearInt = parseInt(year)
7+
const monthInt = parseInt(month)
8+
const dayInt = parseInt(day)
9+
10+
if (yearInt > 0 && monthInt > 0 && dayInt > 0) {
11+
return new Date(yearInt, (monthInt - 1), dayInt, 12)
12+
} else {
13+
return null
14+
}
15+
}
16+
17+
// If date2 is after date1 return positive number of days,
18+
// if it’s before then negative, if it’s the same then 0.
19+
function daysBetweenDates(date1, date2) {
20+
if (!date1 || !date2) {
21+
return null
22+
}
23+
const millisecondsInADay = (24 * 3600 * 1000)
24+
const differenceInMilliseconds = date2.getTime() - date1.getTime()
25+
const differenceInDays = differenceInMilliseconds / millisecondsInADay
26+
27+
return Math.floor(differenceInDays)
28+
}
29+
30+
131
module.exports = router => {
232

333
router.post('/vaccinate/answer-patient-nhs-number-known', (req, res) => {
@@ -16,7 +46,6 @@ module.exports = router => {
1646
} else {
1747
res.redirect('/vaccinate/patient?showError=yes')
1848
}
19-
2049
})
2150

2251

@@ -80,6 +109,124 @@ module.exports = router => {
80109

81110
})
82111

112+
router.get('/vaccinate/patient-estimated-due-date', (req, res) => {
113+
114+
const showError = req.query.showError
115+
const data = req.session.data
116+
const pregnancyDueDate = dateFromYearMonthDay(data.pregnancyDueDate?.year, data.pregnancyDueDate?.month, data.pregnancyDueDate?.day);
117+
118+
let dateErrorMessage = false
119+
120+
if (showError === 'yes') {
121+
122+
if (!pregnancyDueDate) {
123+
dateErrorMessage = "Enter estimated due date"
124+
} else if (data.vaccinationToday === "yes") {
125+
126+
const vaccinationDate = new Date()
127+
128+
// Estimated due date is based on 40 weeks (280 days) since last period
129+
const numberOfDaysPregnant = 280 - daysBetweenDates(vaccinationDate, pregnancyDueDate)
130+
131+
if (numberOfDaysPregnant < 21) {
132+
dateErrorMessage = "Estimated due date is too far in the future. Patient must be at least 21 days pregnant."
133+
} else if (numberOfDaysPregnant > 308) {
134+
dateErrorMessage = "Patient cannot be more than 44 weeks pregnant"
135+
}
136+
137+
}
138+
}
139+
140+
res.render('vaccinate/patient-estimated-due-date', {
141+
dateErrorMessage
142+
})
143+
})
144+
145+
146+
// Routing page after setting pregnancy estimated due date
147+
router.post('/vaccinate/save-estimated-due-date', (req, res) => {
148+
149+
const data = req.session.data
150+
const pregnancyDueDate = dateFromYearMonthDay(data.pregnancyDueDate?.year, data.pregnancyDueDate?.month, data.pregnancyDueDate?.day)
151+
152+
// Re-render with error if date is not set
153+
if (!pregnancyDueDate) {
154+
return res.redirect('/vaccinate/patient-estimated-due-date?showError=yes')
155+
}
156+
157+
// Skip to consent page if the vaccination happened in the past
158+
// as it’s then too late for any warnings
159+
if (data.vaccinationToday != "yes") {
160+
return res.redirect('/vaccinate/consent')
161+
}
162+
163+
// Vaccination date is today
164+
const vaccinationDate = new Date()
165+
166+
// Estimated due date is based on 40 weeks (280 days) since last period
167+
const numberOfDaysPregnant = 280 - daysBetweenDates(vaccinationDate, pregnancyDueDate)
168+
169+
// Being less than 3 weeks or more than 44 weeks (308 days) pregnant
170+
// results in an error
171+
if (numberOfDaysPregnant < 21 || numberOfDaysPregnant > 308) {
172+
return res.redirect('/vaccinate/patient-estimated-due-date?showError=yes')
173+
}
174+
175+
// RSV is recommended from 28+ weeks (196 days)
176+
if (data.vaccinationToday == 'yes' && data.vaccine === "RSV" && numberOfDaysPregnant < 196) {
177+
res.redirect('/vaccinate/patient-estimated-due-date-rsv-warning')
178+
179+
// Pertussis is recommended between 16 weeks (112 days) and 32 weeks
180+
} else if (data.vaccinationToday == 'yes' && data.vaccine === "Pertussis" && numberOfDaysPregnant < 112) {
181+
res.redirect('/vaccinate/patient-estimated-due-date-pertussis-warning')
182+
} else {
183+
res.redirect('/vaccinate/consent')
184+
}
185+
186+
});
187+
188+
router.get('/vaccinate/patient-estimated-due-date-rsv-warning', (req, res) => {
189+
190+
const data = req.session.data
191+
const pregnancyDueDate = dateFromYearMonthDay(data.pregnancyDueDate?.year, data.pregnancyDueDate?.month, data.pregnancyDueDate?.day)
192+
193+
// Vaccination date is today
194+
const vaccinationDate = new Date()
195+
196+
// Estimated due date is based on 40 weeks (280 days) since last period
197+
const numberOfDaysPregnant = 280 - daysBetweenDates(vaccinationDate, pregnancyDueDate)
198+
199+
const fullWeeksPregnant = Math.floor(numberOfDaysPregnant / 7)
200+
const remainderDaysPregnant = (numberOfDaysPregnant % 7)
201+
202+
res.render('vaccinate/patient-estimated-due-date-rsv-warning', {
203+
fullWeeksPregnant,
204+
remainderDaysPregnant
205+
})
206+
207+
})
208+
209+
router.get('/vaccinate/patient-estimated-due-date-pertussis-warning', (req, res) => {
210+
211+
const data = req.session.data
212+
const pregnancyDueDate = dateFromYearMonthDay(data.pregnancyDueDate?.year, data.pregnancyDueDate?.month, data.pregnancyDueDate?.day)
213+
214+
// Vaccination date is today
215+
const vaccinationDate = new Date()
216+
217+
// Estimated due date is based on 40 weeks (280 days) since last period
218+
const numberOfDaysPregnant = 280 - daysBetweenDates(vaccinationDate, pregnancyDueDate)
219+
220+
const fullWeeksPregnant = Math.floor(numberOfDaysPregnant / 7)
221+
const remainderDaysPregnant = (numberOfDaysPregnant % 7)
222+
223+
res.render('vaccinate/patient-estimated-due-date-pertussis-warning', {
224+
fullWeeksPregnant,
225+
remainderDaysPregnant
226+
})
227+
228+
})
229+
83230
// Routing page after DONE
84231
router.post('/vaccinate/what-next', (req, res) => {
85232

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{% extends 'layout.html' %}
2+
3+
{% block pageTitle %}
4+
Vaccines
5+
{% endblock %}
6+
7+
{% set currentSection = "vaccinate" %}
8+
9+
{% block beforeContent %}
10+
{{ backLink({ href: "/vaccinate/patient-estimated-due-date" }) }}
11+
{% endblock %}
12+
13+
{% block content %}
14+
<div class="nhsuk-grid-row">
15+
<div class="nhsuk-grid-column-two-thirds">
16+
17+
<h1 class="nhsuk-heading-l">Are you sure you want to continue?</h1>
18+
19+
<p>{{ data.patientName }} is {{ fullWeeksPregnant | plural("week") }}{% if remainderDaysPregnant > 0 %} and {{ remainderDaysPregnant | plural("day") }}{% endif %} pregnant.
20+
</p>
21+
22+
<p>The pertussis vaccine is recommended between 16 and 32 weeks of pregnancy.</p>
23+
24+
<p><a href="https://www.gov.uk/government/publications/vaccination-against-pertussis-whooping-cough-for-pregnant-women/pertussis-whooping-cough-vaccination-programme-for-pregnant-women" target="_blank">UKHSA guidance on pertussis vaccination of pregnant women (opens in new tab)</a>.
25+
26+
27+
</div>
28+
</div>
29+
30+
{{ button({
31+
"text": "Continue",
32+
"href": "/vaccinate/consent"
33+
}) }}
34+
35+
{% endblock %}
36+
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{% extends 'layout.html' %}
2+
3+
{% block pageTitle %}
4+
Vaccines
5+
{% endblock %}
6+
7+
{% set currentSection = "vaccinate" %}
8+
9+
{% block beforeContent %}
10+
{{ backLink({ href: "/vaccinate/patient-estimated-due-date" }) }}
11+
{% endblock %}
12+
13+
{% block content %}
14+
<div class="nhsuk-grid-row">
15+
<div class="nhsuk-grid-column-two-thirds">
16+
17+
<h1 class="nhsuk-heading-l">Are you sure you want to continue?</h1>
18+
19+
20+
<p>{{ data.patientName }} is {{ fullWeeksPregnant | plural("week") }}{% if remainderDaysPregnant > 0 %} and {{ remainderDaysPregnant | plural("day") }}{% endif %} pregnant.
21+
</p>
22+
23+
<p>The {{ data.vaccine }} vaccine is not routinely recommended before 28 weeks of pregnancy.</p>
24+
25+
<p><a href="https://www.gov.uk/government/publications/respiratory-syncytial-virus-rsv-programme-information-for-healthcare-professionals/rsv-vaccination-of-pregnant-women-for-infant-protection-information-for-healthcare-practitioners" target="_blank">UKHSA guidance on RSV vaccination of pregnant women (opens in new tab)</a>.
26+
27+
28+
</div>
29+
</div>
30+
31+
{{ button({
32+
"text": "Continue",
33+
"href": "/vaccinate/consent"
34+
}) }}
35+
36+
{% endblock %}
37+

app/views/vaccinate/patient-estimated-due-date.html

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,20 @@
1414
<div class="nhsuk-grid-row">
1515
<div class="nhsuk-grid-column-two-thirds">
1616

17-
<form action="/vaccinate/consent" method="post" novalidate>
17+
{% if dateErrorMessage %}
18+
{{ errorSummary({
19+
titleText: "There is a problem",
20+
errorList: [{
21+
text: dateErrorMessage,
22+
href: "#pregnancyDueDate-day"
23+
}]
24+
}) }}
25+
{% endif %}
26+
27+
28+
<form action="/vaccinate/save-estimated-due-date" method="post" novalidate>
29+
<!-- reset showError to false -->
30+
<input type="hidden" name="showError" value="">
1831

1932
{{ dateInput({
2033
id: "pregnancyDueDate",
@@ -26,22 +39,25 @@
2639
isPageHeading: true
2740
}
2841
},
42+
errorMessage: {
43+
text: dateErrorMessage
44+
} if dateErrorMessage,
2945
values: data.pregnancyDueDate,
3046
hint: {
3147
text: "For example, 15 6 2025"
3248
},
3349
items: [
3450
{
3551
name: "day",
36-
classes: "nhsuk-input--width-2"
52+
classes: "nhsuk-input--width-2 " + ("nhsuk-input--error" if dateErrorMessage else "")
3753
},
3854
{
3955
name: "month",
40-
classes: "nhsuk-input--width-2"
56+
classes: "nhsuk-input--width-2 " + ("nhsuk-input--error" if dateErrorMessage else "")
4157
},
4258
{
4359
name: "year",
44-
classes: "nhsuk-input--width-4"
60+
classes: "nhsuk-input--width-4 " + ("nhsuk-input--error" if dateErrorMessage else "")
4561
}
4662
]
4763
}) }}

0 commit comments

Comments
 (0)