Skip to content

Commit 71df7c5

Browse files
committed
Add AppPatientSessionProgrammeComponent
Shows the programme status (heading with colour, contextual detail text, vaccination outcomes table, and action link) for a patient on the session patient show page. This card links to the respective programme tab in the child’s record. Eventually this will be the only card on the page with a coloured heading so various statuses (consent, triage, etc) do not compete for attention and the programme status for the child is reflected right at the top. MAV-4846
1 parent f2dff38 commit 71df7c5

7 files changed

Lines changed: 240 additions & 102 deletions

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# frozen_string_literal: true
2+
3+
class AppPatientSessionProgrammeComponent < ViewComponent::Base
4+
erb_template <<-ERB
5+
<%= render AppCardComponent.new(feature: true) do |card| %>
6+
<% card.with_heading(level: 4, colour:) { heading } %>
7+
<% if details.present? %>
8+
<p><%= details %></p>
9+
<% end %>
10+
<% if programme_status.vaccinated? || programme_status.cannot_vaccinate? %>
11+
<%= render AppPatientVaccinationTableComponent.new(
12+
patient,
13+
programme:,
14+
academic_year:,
15+
show_caption: true,
16+
show_details: false
17+
) %>
18+
<% end %>
19+
<%= render AppActionLinkComponent.new(
20+
text: action_link_text,
21+
href: patient_programme_path(patient, programme.type)
22+
) %>
23+
<% end %>
24+
ERB
25+
26+
def initialize(patient:, session:, programme:)
27+
@patient = patient
28+
@session = session
29+
@programme = programme
30+
end
31+
32+
private
33+
34+
attr_reader :patient, :session, :programme
35+
36+
delegate :academic_year, to: :session
37+
38+
def heading
39+
"#{resolver[:prefix]}: #{resolver[:text]}"
40+
end
41+
42+
def colour
43+
resolver[:colour]
44+
end
45+
46+
def details
47+
if programme_status.due?
48+
criteria_label =
49+
I18n.t(
50+
programme_status.vaccine_criteria.to_param,
51+
scope: :vaccine_criteria
52+
)
53+
if criteria_label.present?
54+
"#{patient.given_name} is ready to vaccinate (#{criteria_label.downcase})."
55+
else
56+
"#{patient.given_name} is ready to vaccinate."
57+
end
58+
elsif programme_status.vaccinated?
59+
record =
60+
patient
61+
.vaccination_records
62+
.for_programme(programme)
63+
.order_by_performed_at
64+
.first
65+
nurse = [
66+
record&.performed_by_given_name,
67+
record&.performed_by_family_name
68+
].compact_blank.join(" ")
69+
if nurse.present?
70+
"#{patient.given_name} was vaccinated by #{nurse} on #{record&.performed_at&.to_fs(:long)}."
71+
else
72+
"#{patient.given_name} was vaccinated on #{record&.performed_at&.to_fs(:long)}."
73+
end
74+
elsif programme_status.needs_triage?
75+
"You need to decide if it’s safe to vaccinate."
76+
else
77+
resolver[:details_text]
78+
end
79+
end
80+
81+
def programme_status
82+
@programme_status ||= patient.programme_status(programme, academic_year:)
83+
end
84+
85+
def action_link_text
86+
"View child’s #{programme.name} record"
87+
end
88+
89+
def resolver
90+
@resolver ||=
91+
PatientProgrammeStatusResolver.call(
92+
patient,
93+
programme_type: programme.type,
94+
academic_year:
95+
)
96+
end
97+
end

app/components/app_patient_session_vaccination_component.rb

Lines changed: 0 additions & 51 deletions
This file was deleted.

app/models/patient/programme_status.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,10 @@ def has_refusal? = status.in?(HAS_REFUSAL_STATUSES.keys)
154154

155155
def cannot_vaccinate? = status.in?(CANNOT_VACCINATE_STATUSES.keys)
156156

157+
def needs_triage? = status.in?(NEEDS_TRIAGE_STATUSES.keys)
158+
159+
def due? = status.in?(DUE_STATUSES.keys)
160+
157161
def vaccinated? = status.in?(VACCINATED_STATUSES.keys)
158162

159163
def group = GROUPS.find { status.starts_with?(it) }

app/views/patient_sessions/programmes/show.html.erb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
</div>
77

88
<div class="app-grid-column-patient-session">
9+
<%= render AppPatientSessionProgrammeComponent.new(patient: @patient, session: @session, programme: @programme) %>
10+
911
<%= render AppPatientSessionConsentComponent.new(patient: @patient, session: @session, programme: @programme) %>
1012

1113
<%= render AppPatientSessionTriageComponent.new(patient: @patient, session: @session, programme: @programme, current_user:, triage_form: @triage_form) %>
1214

1315
<%= render AppPatientSessionRecordComponent.new(patient: @patient, session: @session, programme: @programme, current_user:, vaccinate_form: @vaccinate_form) %>
14-
15-
<%= render AppPatientSessionVaccinationComponent.new(patient: @patient, session: @session, programme: @programme) %>
1616
</div>
1717
</div>
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# frozen_string_literal: true
2+
3+
describe AppPatientSessionProgrammeComponent do
4+
subject(:rendered) { render_inline(component) }
5+
6+
let(:component) { described_class.new(patient:, session:, programme:) }
7+
8+
let(:programme) { Programme.flu }
9+
let(:session) { create(:session, programmes: [programme]) }
10+
let(:patient) { create(:patient, session:) }
11+
12+
it { should have_css("a.nhsuk-action-link", text: "View child’s Flu record") }
13+
14+
context "when due (nasal)" do
15+
before do
16+
create(:patient_programme_status, :due_nasal, patient:, programme:)
17+
end
18+
19+
it { should have_css("h4", text: "Flu:") }
20+
it { should_not have_css("table") }
21+
22+
it "shows ready to vaccinate details" do
23+
expect(rendered).to have_text(
24+
"#{patient.given_name} is ready to vaccinate (nasal spray only)."
25+
)
26+
end
27+
end
28+
29+
context "when due (injection)" do
30+
before do
31+
create(:patient_programme_status, :due_injection, patient:, programme:)
32+
end
33+
34+
it "shows ready to vaccinate details without criteria label for flu injection" do
35+
expect(rendered).to have_text(
36+
"#{patient.given_name} is ready to vaccinate"
37+
)
38+
end
39+
end
40+
41+
context "when vaccinated" do
42+
before do
43+
create(:patient_programme_status, :vaccinated_fully, patient:, programme:)
44+
end
45+
46+
context "with a known nurse" do
47+
let!(:vaccination_record) do
48+
create(
49+
:vaccination_record,
50+
:performed_by_not_user,
51+
patient:,
52+
programme:,
53+
session:
54+
)
55+
end
56+
57+
it { should have_css("table") }
58+
59+
it "shows vaccinated by nurse details" do
60+
nurse = [
61+
vaccination_record.performed_by_given_name,
62+
vaccination_record.performed_by_family_name
63+
].join(" ")
64+
65+
expect(rendered).to have_text(
66+
"#{patient.given_name} was vaccinated by #{nurse} on"
67+
)
68+
end
69+
end
70+
71+
context "without a known nurse" do
72+
before do
73+
create(
74+
:vaccination_record,
75+
patient:,
76+
programme:,
77+
session:,
78+
performed_by_given_name: nil,
79+
performed_by_family_name: nil
80+
)
81+
PatientStatusUpdater.call(patient:)
82+
end
83+
84+
it { should have_css("table") }
85+
86+
it "shows vaccinated without nurse details" do
87+
expect(rendered).to have_text("#{patient.given_name} was vaccinated on")
88+
expect(rendered).not_to have_text("vaccinated by")
89+
end
90+
end
91+
end
92+
93+
context "when the child could not be vaccinated" do
94+
before do
95+
create(
96+
:vaccination_record,
97+
:not_administered,
98+
patient:,
99+
programme:,
100+
session:
101+
)
102+
PatientStatusUpdater.call(patient:)
103+
end
104+
105+
it { should have_css("table") }
106+
107+
it "shows child unwell details" do
108+
expect(rendered).to have_text("Child unwell on")
109+
end
110+
end
111+
112+
context "when needs triage" do
113+
before do
114+
create(:patient_programme_status, :needs_triage, patient:, programme:)
115+
end
116+
117+
it { should have_css("h4", text: "Flu:") }
118+
it { should_not have_css("table") }
119+
120+
it "shows safe to vaccinate decision details" do
121+
expect(rendered).to have_text(
122+
"You need to decide if it’s safe to vaccinate."
123+
)
124+
end
125+
end
126+
end

spec/components/app_patient_session_vaccination_component_spec.rb

Lines changed: 0 additions & 47 deletions
This file was deleted.

spec/features/vaccination_offline_spec.rb

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@
3535
then_i_see_the_successful_import
3636
when_i_navigate_to_the_clinic_page
3737
then_i_see_the_uploaded_vaccination_outcomes_reflected_in_the_session
38-
and_the_clinic_location_is_displayed
38+
when_i_click_on_the_vaccination
39+
then_the_clinic_location_is_displayed
3940

4041
when_vaccination_confirmations_are_sent
4142
then_an_email_is_sent_to_the_parent_confirming_the_vaccination
@@ -577,7 +578,15 @@ def then_i_see_the_uploaded_vaccination_outcomes_reflected_in_the_session
577578
expect(page).to have_content("Vaccinated")
578579
end
579580

580-
def and_the_clinic_location_is_displayed
581+
def when_i_click_on_the_vaccination
582+
click_on VaccinationRecord
583+
.where(patient: @restricted_vaccinated_patient)
584+
.sole
585+
.performed_at
586+
.to_fs(:long)
587+
end
588+
589+
def then_the_clinic_location_is_displayed
581590
expect(page).to have_content("Westfield Shopping Centre")
582591
end
583592

0 commit comments

Comments
 (0)