Skip to content

Commit b19e780

Browse files
authored
Merge pull request #6167 from NHSDigital/child-record-redesign-vaccinations-per-programme
Child record redesign - vaccination records per programme
2 parents 73429ea + 633fff2 commit b19e780

10 files changed

Lines changed: 263 additions & 32 deletions

app/components/app_patient_card_component.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
class AppPatientCardComponent < ViewComponent::Base
44
erb_template <<-ERB
55
<%= render AppCardComponent.new(section: true) do |card| %>
6-
<% card.with_heading(level: heading_level) { "Child record" } %>
6+
<% card.with_heading(level: heading_level, actions:) { "Child record" } %>
77
88
<% important_notices.each do |notice| %>
99
<%= render AppStatusComponent.new(text: notice) %>
@@ -30,7 +30,8 @@ def initialize(
3030
show_add_parent: false,
3131
change_links: {},
3232
remove_links: {},
33-
heading_level: 3
33+
heading_level: 3,
34+
actions: []
3435
)
3536
@patient = patient
3637
@current_team = current_team
@@ -39,6 +40,7 @@ def initialize(
3940
@change_links = change_links
4041
@remove_links = remove_links
4142
@heading_level = heading_level
43+
@actions = actions
4244
end
4345

4446
private
@@ -49,7 +51,8 @@ def initialize(
4951
:show_add_parent,
5052
:change_links,
5153
:remove_links,
52-
:heading_level
54+
:heading_level,
55+
:actions
5356

5457
def show_school_and_year_group = patient.show_year_group?(team: current_team)
5558

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<%= render AppCardComponent.new(section: true) do |card| %>
2+
<% card.with_heading { vaccination_records.present? ? "Vaccination record" : "No vaccination record" } %>
3+
4+
<%= render programme_status_tag %>
5+
6+
<% if vaccination_records.present? %>
7+
<%= govuk_table(html_attributes: { class: "nhsuk-table-responsive" }) do |table| %>
8+
<% table.with_caption(text: "Vaccination records", size: "s") if show_caption %>
9+
10+
<% table.with_head do |head| %>
11+
<% head.with_row do |row| %>
12+
<% row.with_cell(text: "Vaccination date") %>
13+
<% row.with_cell(text: "Age") %>
14+
<% row.with_cell(text: "Programme") %>
15+
<% row.with_cell(text: "Source") %>
16+
<% end %>
17+
<% end %>
18+
19+
<% table.with_body do |body| %>
20+
<% vaccination_records.each do |vaccination_record| %>
21+
<% body.with_row do |row| %>
22+
<% row.with_cell do %>
23+
<span class="nhsuk-table-responsive__heading">Vaccination date</span>
24+
<%= link_to vaccination_record.performed_at.to_date.to_fs(:long),
25+
vaccination_record_path(vaccination_record) %>
26+
<% end %>
27+
28+
<% row.with_cell do %>
29+
<span class="nhsuk-table-responsive__heading">Age</span>
30+
<%= formatted_age_when(vaccination_record) %>
31+
<% end %>
32+
33+
<% row.with_cell do %>
34+
<span class="nhsuk-table-responsive__heading">Programme</span>
35+
<%= render AppProgrammeTagsComponent.new([vaccination_record.programme]) %>
36+
<% end %>
37+
38+
<% row.with_cell do %>
39+
<span class="nhsuk-table-responsive__heading">Source</span>
40+
<%= vaccination_record_source(vaccination_record) %>
41+
<% end %>
42+
<% end %>
43+
<% end %>
44+
<% end %>
45+
<% end %>
46+
<% end %>
47+
<% end %>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# frozen_string_literal: true
2+
3+
class AppPatientProgrammeVaccinationCardComponent < ViewComponent::Base
4+
def initialize(patient, academic_year:, programme: nil, show_caption: false)
5+
@patient = patient
6+
@academic_year = academic_year
7+
@programme = programme
8+
@show_caption = show_caption
9+
end
10+
11+
private
12+
13+
delegate :govuk_table, :vaccination_record_source, to: :helpers
14+
15+
attr_reader :patient, :academic_year, :programme, :show_caption
16+
17+
def vaccination_records
18+
patient
19+
.vaccination_records
20+
.for_programme(programme)
21+
.includes(:location)
22+
.order_by_performed_at
23+
.select { it.show_in_academic_year?(academic_year) }
24+
end
25+
26+
def formatted_age_when(vaccination_record)
27+
age = patient.age_years(now: vaccination_record.performed_at)
28+
pluralize(age, "year")
29+
end
30+
31+
def programme_status_tag
32+
resolved_status =
33+
PatientProgrammeStatusResolver.call(
34+
patient,
35+
programme_type: programme.type,
36+
academic_year: AcademicYear.current
37+
)
38+
39+
AppAttachedTagsComponent.new(
40+
resolved_status.fetch(:prefix) => resolved_status
41+
)
42+
end
43+
end

app/components/app_patient_programmes_table_component.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def call
1212
caption: CAPTION,
1313
head: HEADERS,
1414
rows:,
15-
first_cell_is_header: true
15+
first_cell_is_header: false
1616
)
1717
end
1818

@@ -23,7 +23,7 @@ def call
2323
delegate :govuk_table, to: :helpers
2424

2525
CAPTION = "Vaccination programmes"
26-
HEADERS = ["Programme name", "Status", "Notes"].freeze
26+
HEADERS = %w[Programme Status Notes].freeze
2727

2828
def rows
2929
programmes.flat_map { |programme| rows_for_programme(programme:) }
@@ -52,7 +52,10 @@ def build_row(programme:, academic_year:)
5252
programme_type = programme.type
5353

5454
[
55-
name_for_programme(programme:, academic_year:),
55+
helpers.govuk_link_to(
56+
name_for_programme(programme:, academic_year:),
57+
patient_programme_path(patient, programme_type)
58+
),
5659
status_for_programme(programme_type:, academic_year:),
5760
notes_for_programme(programme_type:, academic_year:)
5861
]

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99

1010
<%= render AppPatientNavigationComponent.new(@patient, current_user.programmes, active: @programme.type.to_sym) %>
1111

12-
<%= render AppCardComponent.new(section: true) do |card| %>
13-
<% card.with_heading { "Vaccinations" } %>
14-
<%= render AppPatientVaccinationTableComponent.new(
15-
@patient, academic_year: AcademicYear.current, show_caption: false, programme: @programme,
16-
) %>
17-
<% end %>
12+
<%= render AppPatientProgrammeVaccinationCardComponent.new(
13+
@patient,
14+
academic_year: AcademicYear.current,
15+
show_caption: false,
16+
programme: @programme,
17+
) %>
1818

1919
<%= render AppCardComponent.new(section: true) do |card| %>
2020
<% card.with_heading { "Sessions" } %>

app/views/patients/show.html.erb

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,11 @@
2626
@patient,
2727
current_team:,
2828
show_parents: !current_team.has_national_reporting_access?,
29+
actions: [
30+
({ text: "Edit child record", href: edit_patient_path(@patient) } if @patient.not_archived?(team: current_team) || current_team.has_national_reporting_access?),
31+
({ text: "Archive child record", href: new_patient_archive_path(@patient) } if @patient.not_archived?(team: current_team)),
32+
].compact,
2933
) do %>
30-
<% if @patient.not_archived?(team: current_team) %>
31-
<div class="nhsuk-button-group">
32-
<%= govuk_button_link_to "Edit child record", edit_patient_path(@patient), secondary: true %>
33-
<%= govuk_button_link_to "Archive child record", new_patient_archive_path(@patient), class: "app-button--secondary-warning" %>
34-
</div>
35-
<% elsif current_team.has_national_reporting_access? %>
36-
<div class="nhsuk-button-group">
37-
<%= govuk_button_link_to "Edit child record", edit_patient_path(@patient), secondary: true %>
38-
</div>
39-
<% end %>
4034
<% end %>
4135

4236
<% unless current_team.has_national_reporting_access? %>
@@ -60,5 +54,7 @@
6054
<% end %>
6155
<% end %>
6256

63-
<%= vaccinations_card %>
57+
<% unless Flipper.enabled?(:child_record_redesign) %>
58+
<%= vaccinations_card %>
59+
<% end %>
6460
<% end %>
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# frozen_string_literal: true
2+
3+
describe AppPatientProgrammeVaccinationCardComponent do
4+
subject(:rendered) { render_inline(component) }
5+
6+
let(:component) do
7+
described_class.new(patient, academic_year:, programme:, show_caption:)
8+
end
9+
10+
let(:patient) { create(:patient) }
11+
let(:academic_year) { 2023 }
12+
let(:programme) { Programme.hpv }
13+
let(:show_caption) { false }
14+
15+
it { should have_css(".nhsuk-card__heading", text: "No vaccination record") }
16+
it { should_not have_css(".nhsuk-table") }
17+
18+
context "with a vaccination record" do
19+
let(:location) do
20+
create(
21+
:school,
22+
name: "Test School",
23+
address_line_1: "Waterloo Road",
24+
address_town: "London",
25+
address_postcode: "SE1 8TY"
26+
)
27+
end
28+
29+
let(:vaccination_record_programme) { Programme.hpv }
30+
let(:performed_at) { Time.zone.local(2024, 1, 1) }
31+
32+
before do
33+
create(
34+
:vaccination_record,
35+
patient:,
36+
session:
37+
create(
38+
:session,
39+
location:,
40+
programmes: [vaccination_record_programme]
41+
),
42+
programme: vaccination_record_programme,
43+
performed_at:
44+
)
45+
end
46+
47+
it { should have_css(".nhsuk-card__heading", text: "Vaccination record") }
48+
49+
it { should have_css(".nhsuk-tag", text: "Not eligible") }
50+
it { should have_css(".nhsuk-table__header", text: "Vaccination date") }
51+
it { should have_css(".nhsuk-table__header", text: "Age") }
52+
it { should have_css(".nhsuk-table__header", text: "Programme") }
53+
it { should have_css(".nhsuk-table__header", text: "Source") }
54+
55+
it { should have_link("1 January 2024") }
56+
57+
it do
58+
expect(rendered).to have_css(
59+
".nhsuk-table",
60+
text: "#{patient.age_years(now: performed_at)} years"
61+
)
62+
end
63+
64+
it { should have_css(".nhsuk-table", text: "HPV") }
65+
it { should have_css(".nhsuk-table", text: "Recorded in Mavis") }
66+
67+
context "with a vaccination record from a different programme" do
68+
let(:programme) { Programme.hpv }
69+
let(:vaccination_record_programme) { Programme.flu }
70+
71+
it { should_not have_link("1 January 2024") }
72+
73+
it do
74+
expect(rendered).not_to have_css(
75+
".nhsuk-table",
76+
text: "#{patient.age_years(now: performed_at)} years"
77+
)
78+
end
79+
80+
it { should_not have_css(".nhsuk-table", text: "HPV") }
81+
it { should_not have_css(".nhsuk-table", text: "Recorded in Mavis") }
82+
end
83+
84+
context "with a Flu vaccination record from a previous year" do
85+
let(:vaccination_record_programme) { Programme.flu }
86+
let(:programme) { vaccination_record_programme }
87+
let(:performed_at) { Time.zone.local(2022, 1, 1) }
88+
89+
it { should_not have_link("1 January 2022") }
90+
91+
it do
92+
expect(rendered).not_to have_css(
93+
".nhsuk-table",
94+
text: "#{patient.age_years(now: performed_at)} years"
95+
)
96+
end
97+
98+
it { should_not have_css(".nhsuk-table", text: "Flu") }
99+
it { should_not have_css(".nhsuk-table", text: "Recorded in Mavis") }
100+
end
101+
end
102+
end

spec/components/app_patient_programmes_table_component_spec.rb

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# frozen_string_literal: true
22

33
describe AppPatientProgrammesTableComponent do
4+
include Rails.application.routes.url_helpers
5+
46
subject(:rendered) { render_inline(component) }
57

68
let(:component) do
@@ -20,8 +22,21 @@
2022
let(:patient) { create(:patient, session:) }
2123
let(:programmes) { [Programme.flu] }
2224

25+
it "has the correct column headings" do
26+
expect(rendered).to have_css(".nhsuk-table__header", text: "Programme")
27+
expect(rendered).to have_css(".nhsuk-table__header", text: "Status")
28+
expect(rendered).to have_css(".nhsuk-table__header", text: "Notes")
29+
end
30+
2331
it { should have_content("Vaccination programmes") }
24-
it { should have_content("Flu (winter 2025)") }
32+
33+
it "renders a link to the Flu tab" do
34+
expect(rendered).to have_link(
35+
"Flu (winter 2025)",
36+
href: patient_programme_path(patient, "flu")
37+
)
38+
end
39+
2540
it { should_not have_content("Vaccinated") }
2641

2742
context "when vaccinated" do
@@ -135,9 +150,21 @@
135150
let(:programmes) { [Programme.hpv, Programme.menacwy, Programme.td_ipv] }
136151

137152
it { should have_content("Vaccination programmes") }
138-
it { should have_content("HPV") }
139-
it { should have_content("Td/IPV") }
140-
it { should have_content("MenACWY") }
153+
it { should have_link("HPV", href: patient_programme_path(patient, "hpv")) }
154+
155+
it "renders a link to the Td/IPV tab" do
156+
expect(rendered).to have_link(
157+
"Td/IPV",
158+
href: patient_programme_path(patient, "td_ipv")
159+
)
160+
end
161+
162+
it "renders a link to the MenACWY tab" do
163+
expect(rendered).to have_link(
164+
"MenACWY",
165+
href: patient_programme_path(patient, "menacwy")
166+
)
167+
end
141168

142169
context "when vaccinated last year" do
143170
let(:patient) { create(:patient, session:) }

spec/features/national_reporting_team_spec.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
and_i_search_for_a_child(search_term: "Harry")
3636
and_i_click_on_the_childs_card(given_name: "Harry", family_name: "Potter")
3737
then_i_should_see_vaccinations_then_child_details
38-
and_child_cannot_be_archived
38+
and_child_can_be_edited_but_not_be_archived
3939
and_child_does_not_look_archived
4040
end
4141

@@ -190,9 +190,13 @@ def then_i_should_see_vaccinations_then_child_details
190190
expect(app_cards[1]).to have_content("Child record")
191191
end
192192

193-
def and_child_cannot_be_archived
194-
app_card_buttons = page.all(".app-card .nhsuk-button")
193+
def and_child_can_be_edited_but_not_be_archived
194+
app_card_buttons = page.all(".nhsuk-card .nhsuk-card__action")
195195
expect(app_card_buttons.count).to eq(1)
196+
expect(page).to have_css(
197+
".nhsuk-card .nhsuk-card__action",
198+
text: "Edit child record"
199+
)
196200
expect(page).not_to have_content("Archive child record")
197201
end
198202

0 commit comments

Comments
 (0)