Skip to content

Commit cc4ccff

Browse files
Check-in inline and no visited links (#32)
* Check-in inline and no visited links * Support clearing data from same page
1 parent 2037e1b commit cc4ccff

File tree

17 files changed

+183
-80
lines changed

17 files changed

+183
-80
lines changed

app/assets/javascript/main.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,78 @@
11
// ES6 or Vanilla JavaScript
2+
3+
4+
document.addEventListener('DOMContentLoaded', () => {
5+
6+
7+
// Inline check in without requiring page reload
8+
const checkInLinks = document.querySelectorAll('.js-check-in-link')
9+
10+
checkInLinks.forEach(link => {
11+
link.addEventListener('click', async (e) => {
12+
e.preventDefault()
13+
const link = e.currentTarget
14+
const clinicId = link.dataset.clinicId
15+
const eventId = link.dataset.eventId
16+
17+
try {
18+
const response = await fetch(
19+
`/clinics/${clinicId}/check-in/${eventId}`,
20+
{
21+
method: 'GET',
22+
headers: {
23+
'Accept': 'application/json'
24+
}
25+
}
26+
)
27+
28+
if (!response.ok) {
29+
throw new Error('Failed to check in participant')
30+
}
31+
32+
// Find the containing element by data attribute
33+
const container = document.querySelector(`[data-event-status-container="${eventId}"]`)
34+
if (container) {
35+
container.innerHTML = `
36+
<strong class="nhsuk-tag">
37+
Checked in
38+
</strong>
39+
`
40+
}
41+
} catch (error) {
42+
console.error('Error checking in participant:', error)
43+
window.location.href = link.href
44+
}
45+
})
46+
})
47+
48+
// Handle clear data link with AJAX
49+
const clearDataLinks = document.querySelectorAll('a[href="/clear-data"]')
50+
clearDataLinks.forEach(link => {
51+
link.addEventListener('click', async (e) => {
52+
e.preventDefault()
53+
try {
54+
const response = await fetch('/clear-data', {
55+
method: 'GET',
56+
headers: {
57+
'Accept': 'application/json'
58+
}
59+
})
60+
61+
if (!response.ok) {
62+
throw new Error('Failed to clear data')
63+
}
64+
65+
const result = await response.json()
66+
if (result.success) {
67+
// Refresh the page to reflect the cleared data
68+
window.location.reload()
69+
} else {
70+
throw new Error('Failed to clear data')
71+
}
72+
} catch (error) {
73+
console.error('Error clearing data:', error)
74+
window.location.href = link.href
75+
}
76+
})
77+
})
78+
})

app/routes/clinics.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ module.exports = router => {
216216
const eventIndex = data.events.findIndex(e => e.id === eventId && e.clinicId === clinicId)
217217

218218
if (eventIndex === -1) {
219+
if (req.headers.accept?.includes('application/json')) {
220+
return res.status(404).json({ error: 'Event not found' })
221+
}
219222
return res.redirect(`/clinics/${clinicId}/${currentFilter}`)
220223
}
221224

@@ -224,6 +227,9 @@ module.exports = router => {
224227

225228
// Only allow check-in if currently scheduled
226229
if (event.status !== 'event_scheduled') {
230+
if (req.headers.accept?.includes('application/json')) {
231+
return res.status(400).json({ error: 'Event cannot be checked in' })
232+
}
227233
return res.redirect(`/clinics/${clinicId}/${currentFilter}`)
228234
}
229235

@@ -243,10 +249,18 @@ module.exports = router => {
243249
// Save back to session
244250
req.session.data = data
245251

252+
// If this was an AJAX request, send JSON response
253+
if (req.headers.accept?.includes('application/json')) {
254+
return res.json({
255+
status: 'success',
256+
event: data.events[eventIndex]
257+
})
258+
}
259+
246260
// If there's a returnTo path, use that, otherwise go back to the filter view
247-
const returnTo = req.query.returnTo
248-
if (returnTo) {
249-
res.redirect(returnTo)
261+
const referrer = req.query.referrer
262+
if (referrer) {
263+
res.redirect(referrer)
250264
} else {
251265
res.redirect(`/clinics/${clinicId}/${currentFilter}`)
252266
}

app/routes/events.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,10 @@ module.exports = router => {
9898
if (!canBeginScreening) {
9999
res.redirect(`/clinics/${clinicId}/events/${eventId}`)
100100
} else if (canBeginScreening === 'yes') {
101-
if (req.session.data.events[eventIndex].status !== 'checked_in') {
101+
if (req.session.data.events[eventIndex].status !== 'event_checked_in') {
102102
req.session.data.events[eventIndex] = updateEventStatus(
103103
req.session.data.events[eventIndex],
104-
'checked_in'
104+
'event_checked_in'
105105
)
106106
}
107107
res.redirect(`/clinics/${clinicId}/events/${eventId}/medical-background`)

app/routes/settings.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,16 @@ module.exports = router => {
1515
res.redirect('/settings')
1616
})
1717

18-
// Handle regenerate data action
18+
// Handle clear data action
1919
router.get('/clear-data', async (req, res) => {
2020
console.log('Clearing session data')
2121
req.session.data = {}
2222
req.flash('success', 'Session data cleared')
23+
24+
if (req.headers['accept'] === 'application/json') {
25+
return res.json({ success: true })
26+
}
27+
2328
res.redirect('/settings')
2429
})
2530
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{% macro eventStatus(params) %}
2+
{%- include './template.njk' -%}
3+
{% endmacro %}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{% from 'tag/macro.njk' import tag %}
2+
3+
{% set tagClasses %}
4+
{% if params.event.status | getStatusTagColour %}
5+
nhsuk-tag--{{ params.event.status | getStatusTagColour}}
6+
{% endif %}
7+
{% endset %}
8+
9+
<div data-event-status-container="{{ params.event.id }}">
10+
{{ tag({
11+
text: params.event.status | getStatusText,
12+
classes: tagClasses | trim
13+
})}}
14+
15+
{# Build href with optional referrer #}
16+
{% set href -%}
17+
/clinics/{{ params.clinicId }}/check-in/{{ params.event.id }}
18+
{%- if params.referrer %}?referrer={{ params.referrer }}{% endif %}
19+
{%- endset %}
20+
21+
{% if params.event.status === 'event_scheduled' %}
22+
<p class="nhsuk-u-margin-top-2">
23+
<a href="{{ href | trim }}" class="nhsuk-link nhsuk-link--no-visited-state js-check-in-link" data-clinic-id="{{ params.clinicId }}"
24+
data-event-id="{{ params.event.id }}">
25+
Check in participant
26+
</a>
27+
</p>
28+
{% endif %}
29+
</div>

app/views/_includes/event-header.njk

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,18 @@
11
{% set unit = data.breastScreeningUnits | findById(clinic.breastScreeningUnitId) %}
22

33
{% set statusHtml %}
4-
{{ tag({
5-
text: event.status | getStatusText,
6-
classes: "nhsuk-tag--" + event.status | getStatusTagColour
7-
}) }}
8-
{% if event.status === 'event_scheduled' %}
9-
{% set href -%}
10-
/clinics/{{ clinicId }}/check-in/{{ event.id }}?returnTo=/clinics/{{ clinicId }}/events/{{ eventId }}
11-
{%- endset %}
12-
<p class="nhsuk-u-margin-top-2"><a href="{{href | trim}}">Check in participant</a></p>
13-
14-
{% endif %}
15-
{% if event.status === "event_attended_not_screened" %}
16-
<p class="nhsuk-u-margin-top-2">[Reason for not screened here]</p>
17-
{% endif %}
4+
{# Status tag with check-in link #}
5+
{{ eventStatus({
6+
clinicId: clinicId,
7+
event: event,
8+
referrer: currentUrl
9+
})}}
1810
{% endset %}
1911

20-
2112
<div class="app-event-header">
2213
<h1 class="nhsuk-heading-l">
2314
<span class="nhsuk-caption-l">
24-
{{ clinic.clinicType | sentenceCase }} appointment
15+
{{ clinic.clinicType | sentenceCase }} appointment
2516

2617
</span>
2718
{{ pageHeading }}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<p class="nhsuk-u-margin-top-x9"><a class="nhsuk-link nhsuk-link--no-visited-state" href="./attended-not-screened-reason">Screening cannot proceed</a></p>

app/views/_templates/layout.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<!--
1+
<!--
22
This is the main layout where you can:
3-
- change the header and footer
3+
- change the header and footer
44
- add custom CSS and JavaScript
55
-->
66

@@ -9,6 +9,7 @@
99

1010
{%- from '_components/header/macro.njk' import headerNew %}
1111
{%- from '_components/count/macro.njk' import appCount %}
12+
{%- from '_components/event-status/macro.njk' import eventStatus %}
1213
{%- from '_components/secondary-navigation/macro.njk' import appSecondaryNavigation %}
1314

1415
<!-- Add your custom CSS or Sass in /app/assets/sass/main.scss -->

app/views/clinics/show.html

Lines changed: 15 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ <h1 class="nhsuk-heading-l">
7474
{% for event in filteredEvents %}
7575
{% set participant = data.participants | findById(event.participantId) %}
7676

77-
<tr>
77+
<tr id="event-row-{{event.id}}">
7878

7979
{# Appointment time #}
8080
<td class="nhsuk-table__cell">{{ event.statusHistory[0].timestamp | formatTime }}</td>
@@ -113,40 +113,23 @@ <h1 class="nhsuk-heading-l">
113113
{# NHS Number #}
114114
{# <td class="nhsuk-table__cell">{{ participant.medicalInformation.nhsNumber | formatNhsNumber | noWrap }}</td> #}
115115

116-
{# Appointment status #}
116+
{# Appointment status and check-in #}
117117
<td class="nhsuk-table__cell">
118-
{{ tag({
119-
text: event.status | getStatusText,
120-
classes: "nhsuk-tag--" + event.status | getStatusTagColour
118+
{# Status tag with check-in link #}
119+
{{ eventStatus({
120+
clinicId: clinicId,
121+
event: event,
122+
referrer: currentUrl + "#event-row-" + event.id
121123
})}}
122-
123-
{% if event.status === 'event_scheduled' %}
124-
<div class="nhsuk-u-margin-top-2">
125-
{# <br> #}
126-
<a href="/clinics/{{ clinicId }}/check-in/{{ event.id }}?currentFilter={{ currentFilter }}" class="nhsuk-link">
127-
{{ "Check in participant" | noWrap }}
128-
</a>
129-
</div>
130-
131-
{% endif %}
132124
</td>
133-
134-
{# Check-in action #}
135-
{# <td class="nhsuk-table__cell">
136-
{% if event.status === 'event_scheduled' %}
137-
<a href="/clinics/{{ clinicId }}/check-in/{{ event.id }}?currentFilter={{ currentFilter }}" class="nhsuk-link">
138-
{{ "Check in" | noWrap }}
139-
</a>
140-
{% endif %}
141-
</td> #}
142125
</tr>
143126
{% endfor %}
144127
</tbody>
145128
</table>
146129
{% endif %}
147130

148131
<h2 class="nhsuk-heading-m">Details</h2>
149-
132+
150133
<dl class="nhsuk-summary-list">
151134
<div class="nhsuk-summary-list__row">
152135
<dt class="nhsuk-summary-list__key">Location</dt>
@@ -157,17 +140,17 @@ <h2 class="nhsuk-heading-m">Details</h2>
157140
{% endfor %}
158141
</dd>
159142
</div>
160-
143+
161144
<div class="nhsuk-summary-list__row">
162145
<dt class="nhsuk-summary-list__key">Phone</dt>
163146
<dd class="nhsuk-summary-list__value">{{ unit.phoneNumber }}</dd>
164147
</div>
165-
148+
166149
<div class="nhsuk-summary-list__row">
167150
<dt class="nhsuk-summary-list__key">Date</dt>
168151
<dd class="nhsuk-summary-list__value">{{ clinic.date | formatDate }}</dd>
169152
</div>
170-
153+
171154
<div class="nhsuk-summary-list__row">
172155
<dt class="nhsuk-summary-list__key">Location</dt>
173156
<dd class="nhsuk-summary-list__value">{{ clinic.locationType | formatWords | sentenceCase }}</dd>
@@ -180,3 +163,7 @@ <h2 class="nhsuk-heading-m">Details</h2>
180163
</dl>
181164

182165
{% endblock %}
166+
167+
{% block pageScripts %}
168+
169+
{% endblock %}

0 commit comments

Comments
 (0)