Skip to content
Draft
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
23 changes: 22 additions & 1 deletion app/assets/javascript/close-clinic.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ document.addEventListener('DOMContentLoaded', () => {

const clinicId = container.dataset.clinicId
const fetchOptions = { headers: { 'X-Requested-With': 'XMLHttpRequest' } }
let detailsToOpen = null

// Counts in the card headings and inset text aren't updated in place -
// this link invites a refresh instead
Expand All @@ -21,7 +22,22 @@ document.addEventListener('DOMContentLoaded', () => {
}

// Any swapped row means the page counts may be stale
container.addEventListener('fragment:swapped', showRefreshLink)
container.addEventListener('fragment:swapped', (event) => {
showRefreshLink()

if (detailsToOpen !== event.detail.fragment.dataset.fragmentId) return

const appointmentId = detailsToOpen
detailsToOpen = null
window.openModal('app-form-modal', {
loadUrl: `/clinics/${clinicId}/close/reason/${appointmentId}`,
onSuccess: () => {
const row = rowFor(appointmentId)
if (!row) return window.location.reload()
refreshRow(row).catch(() => window.location.reload())
}
})
})

const rowFor = (appointmentId) =>
container.querySelector(`tr[data-fragment-id="${appointmentId}"]`)
Expand Down Expand Up @@ -64,6 +80,11 @@ document.addEventListener('DOMContentLoaded', () => {
}

container.addEventListener('click', (event) => {
const actionLink = event.target.closest('a[data-open-details-after-action]')
if (actionLink) {
detailsToOpen = actionLink.closest('[data-fragment-id]')?.dataset.fragmentId
}

const bulkLink = event.target.closest('.js-bulk-action')
if (bulkLink) {
event.preventDefault()
Expand Down
2 changes: 1 addition & 1 deletion app/assets/javascript/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,7 @@ class AppModal {
// Flow complete — close and refresh. Capture the callback before
// close(), which resets it.
const onSuccess = this._onSuccessCallback
this.close()
this.close({ notifyClose: false })
if (onSuccess) {
onSuccess()
} else {
Expand Down
10 changes: 7 additions & 3 deletions app/routes/clinics.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,9 @@ const CLOSE_STATUS_ACTIONS = {
attended_not_screened: { from: 'checked_in', resolves: true },
did_not_attend: { from: 'scheduled', resolves: true },
checked_in: { from: 'attended_not_screened', resolves: false },
scheduled: { from: 'did_not_attend', resolves: false }
scheduled: { from: 'did_not_attend', resolves: false },
checked_in_from_scheduled: { from: 'scheduled', to: 'checked_in', resolves: false },
scheduled_from_checked_in: { from: 'checked_in', to: 'scheduled', resolves: false }
}

/**
Expand Down Expand Up @@ -261,7 +263,7 @@ module.exports = (router) => {
}

const data = req.session.data
updateAppointmentStatus(data, appointmentId, status)
updateAppointmentStatus(data, appointmentId, action.to || status)
trackCloseResolvedIds(data, clinicId, [appointmentId], action.resolves)

if (req.xhr) {
Expand Down Expand Up @@ -454,7 +456,9 @@ module.exports = (router) => {

const updatedClinic = updateClinic(data, clinicId, { status: 'closed' })
if (updatedClinic) {
req.flash('success', `Clinic ${updatedClinic.clinicCode} closed`)
req.flash('success', {
html: `Clinic ${updatedClinic.clinicCode} closed. <a href="/reports/${clinicId}">View report</a>`
})
}

// This clinic's close flow is finished - drop its resolved tracking
Expand Down
28 changes: 23 additions & 5 deletions app/views/_includes/close-clinic-appointment-row.njk
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,53 @@

{% macro closeClinicAppointmentRow(appointment, participant, clinicId, showActions) %}
{% set detailsLink = {
text: "Manage details" if appointment | hasStoppedDetails else "Add details",
text: "Change details" if appointment | hasStoppedDetails else "Add details",
href: "/clinics/" + clinicId + "/close/reason/" + appointment.id
} %}
<tr data-fragment-id="{{ appointment.id }}">
<td class="nhsuk-table__cell">{{ appointment.statusHistory[0].timestamp | formatTimeString }}</td>
<td class="nhsuk-table__cell">
<p class="nhsuk-u-margin-bottom-1 nhsuk-u-font-weight-bold">{{ participant | getFullName }}</p>
<p class="nhsuk-u-margin-bottom-1 nhsuk-u-font-weight-bold">{{ participant | getFullNameReversed }}</p>
<p class="nhsuk-u-secondary-text-colour nhsuk-u-margin-bottom-1">NHS: {{ participant.medicalInformation.nhsNumber | formatNhsNumber }}</p>
<p class="nhsuk-u-margin-bottom-0"><a href="/clinics/{{ clinicId }}/appointments/{{ appointment.id }}">View appointment</a></p>
</td>
<td class="nhsuk-table__cell">
{{ appointment.status | toTag({ vocabulary: "appointment" }) }}
{% if appointment.status == "in_progress" and appointment.sessionDetails.startedBy %}
<span class="nhsuk-u-secondary-text-colour nhsuk-body-s nhsuk-u-margin-bottom-0">with {{ appointment.sessionDetails.startedBy | getUsername({
format: 'short',
identifyCurrentUser: true
}) }}</span>
{% endif %}
{% if appointment.status == "rescheduled" and appointment | hasStoppedDetails %}
{{ "attended_not_screened" | toTag({ vocabulary: "appointment" }) }}
{% endif %}
{% if appointment | hasStoppedDetails %}
<p class="nhsuk-u-margin-top-2 nhsuk-u-margin-bottom-0">{{ appointment.appointmentStopped.stoppedReason | join(", ") }}</p>
{% endif %}
{% if showActions and appointment.status == "checked_in" %}
<p class="nhsuk-u-margin-top-2 nhsuk-u-margin-bottom-0">
<a href="/clinics/{{ clinicId }}/close/set-status/{{ appointment.id }}/scheduled_from_checked_in" data-fragment-action>Change to scheduled</a>
</p>
{% elseif showActions and appointment.status == "scheduled" %}
<p class="nhsuk-u-margin-top-2 nhsuk-u-margin-bottom-0">
<a href="/clinics/{{ clinicId }}/close/set-status/{{ appointment.id }}/checked_in_from_scheduled" data-fragment-action>Change to checked in</a>
</p>
{% endif %}
</td>
<td class="nhsuk-table__cell">
{% if showActions %}
{% if appointment.status == "in_progress" or appointment.status == "paused" %}
<a href="/clinics/{{ clinicId }}/appointments/{{ appointment.id }}">Go to appointment</a>
{% elseif appointment.status == "checked_in" %}
<a href="/clinics/{{ clinicId }}/close/set-status/{{ appointment.id }}/attended_not_screened" data-fragment-action>Mark as attended not screened</a>
<a href="/clinics/{{ clinicId }}/close/set-status/{{ appointment.id }}/attended_not_screened" data-fragment-action data-open-details-after-action>Mark as attended not screened</a>
{% elseif appointment.status == "scheduled" %}
<a href="/clinics/{{ clinicId }}/close/set-status/{{ appointment.id }}/did_not_attend" data-fragment-action>Mark as did not attend</a>
{% elseif appointment.status == "attended_not_screened" %}
<a href="/clinics/{{ clinicId }}/close/set-status/{{ appointment.id }}/checked_in" data-fragment-action>Undo</a>
<a href="/clinics/{{ clinicId }}/close/set-status/{{ appointment.id }}/checked_in" data-fragment-action>Undo status</a>
<br>{{ appLink(detailsLink | openInModal) }}
{% elseif appointment.status == "did_not_attend" %}
<a href="/clinics/{{ clinicId }}/close/set-status/{{ appointment.id }}/scheduled" data-fragment-action>Undo</a>
<a href="/clinics/{{ clinicId }}/close/set-status/{{ appointment.id }}/scheduled" data-fragment-action>Undo status</a>
{% elseif appointment.status == "rescheduled" and appointment | hasStoppedDetails %}
{{ appLink(detailsLink | openInModal) }}
{% endif %}
Expand Down
23 changes: 12 additions & 11 deletions app/views/clinics/close.html
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ <h1 class="nhsuk-heading-l">
<div id="js-close-clinic-content" data-clinic-id="{{ clinicId }}">

{% set introHtml %}
<p>Record an appointment outcome for every participant to close this clinic.</p>
<p>There were {{ appointmentCount }} total participants in this clinic, and {{ needsOutcomeCount }} still need a final outcome assigned.</p>
<p>{{ needsOutcomeCount }} appointments need a completed status before this clinic can be closed.</p>
{% endset %}

{{ insetText({
Expand All @@ -63,41 +62,43 @@ <h1 class="nhsuk-heading-l">
{% set needsOutcomeHtml %}
{% if inProgressAppointments | length %}
<h3 class="nhsuk-heading-s">In progress</h3>
<p>Complete or end these appointments to close the clinic.</p>
{% if inProgressAppointments | length == 1 %}
<p>This appointment needs to be completed or ended by the mammographer it is assigned to.</p>
{% else %}
<p>These appointments need to be completed or ended by the mammographers they are assigned to.</p>
{% endif %}
{{ statusGroupTable(inProgressAppointments, clinicId, true) }}
{% endif %}

{# Checked in, not screened - includes attended not screened appointments still needing details #}
{# Checked in, not started - includes attended not screened appointments still needing details #}
{% if checkedInAppointments | length %}
<h3 class="nhsuk-heading-s nhsuk-u-margin-top-4">Checked in, not screened</h3>
{{ bulkActionControl(clinicId, "attended_not_screened", "checked_in", "Mark all as attended not screened", "attended not screened") }}
<h3 class="nhsuk-heading-s nhsuk-u-margin-top-4">Checked in, not started</h3>
{{ statusGroupTable(checkedInAppointments, clinicId, true) }}
{% endif %}

{% if scheduledAppointments | length %}
<h3 class="nhsuk-heading-s nhsuk-u-margin-top-4">Did not check in</h3>
{{ bulkActionControl(clinicId, "did_not_attend", "scheduled", "Mark all as did not attend", "did not attend") }}
<h3 class="nhsuk-heading-s nhsuk-u-margin-top-4">Not checked in</h3>
{{ statusGroupTable(scheduledAppointments, clinicId, true) }}
{% endif %}
{% endset %}

{{ card({
heading: "Needs an outcome (" + needsOutcomeCount + ")",
heading: "To be completed (" + needsOutcomeCount + ")",
headingLevel: "2",
feature: true,
descriptionHtml: needsOutcomeHtml
}) }}
{% endif %}

{% set outcomeRecordedHtml %}
<p><a href="" class="js-refresh-link" hidden>Refresh to update the list</a></p>
{% if outcomeRecordedAppointments | length %}
{{ statusGroupTable(outcomeRecordedAppointments, clinicId, false) }}
{% endif %}
<p>Some appointment statuses have been updated. <a href="" class="js-refresh-link" hidden>Refresh list</a></p>
{% endset %}

{{ card({
heading: "Outcome recorded (" + outcomeRecordedAppointments | length + ")",
heading: "Completed appointments (" + outcomeRecordedAppointments | length + ")",
headingLevel: "2",
feature: true,
classes: "app-card--feature-green",
Expand Down
Loading