From 2e8eb75d4a7e8fdfabb31e52a6afcc34289ea326 Mon Sep 17 00:00:00 2001 From: avinhurry <50492247+avinhurry@users.noreply.github.com> Date: Fri, 20 Sep 2024 12:48:09 +0100 Subject: [PATCH] [2288] Improve Locations (1/6) Add Training Location Information to course Page (#4522) * [2288] Update school placements h1 * [2288] Remove school placements info * [2288] Add intro paragraph below the callout box Different content depending on whether the course is salaried or not * [2288] Update contents * [2288] Add placement schools/study sites description details * [2288] Refactor to use the pluralize method * [2288] Refactor to use govuk component * [2288] Differentiate fee and salary location text * [2288] Add both salaried and fee previews --------- Co-authored-by: Iain McNulty --- .../about_schools_component/view.html.erb | 24 +-- .../courses/contents_component/view.html.erb | 2 +- .../courses/training_locations/view.html.erb | 26 ++++ .../find/courses/training_locations/view.rb | 58 ++++++++ .../en/components/find/training_locations.yml | 2 + config/locales/find.yml | 5 +- .../about_schools_component/view_preview.rb | 23 ++- .../about_schools_component/view_spec.rb | 83 +++-------- .../courses/contents_component/view_spec.rb | 6 +- .../training_locations/view_preview.rb | 79 ++++++++++ .../courses/training_locations/view_spec.rb | 139 ++++++++++++++++++ 11 files changed, 362 insertions(+), 85 deletions(-) create mode 100644 app/components/find/courses/training_locations/view.html.erb create mode 100644 app/components/find/courses/training_locations/view.rb create mode 100644 config/locales/en/components/find/training_locations.yml create mode 100644 spec/components/find/courses/training_locations/view_preview.rb create mode 100644 spec/components/find/courses/training_locations/view_spec.rb diff --git a/app/components/find/courses/about_schools_component/view.html.erb b/app/components/find/courses/about_schools_component/view.html.erb index e4810ef13f..08a4d52a5d 100644 --- a/app/components/find/courses/about_schools_component/view.html.erb +++ b/app/components/find/courses/about_schools_component/view.html.erb @@ -16,6 +16,18 @@ <% end %> <% end %> + <% if course.fee_based? %> +

+ You’ll be placed in schools for most of your course to get classroom experience. You will also spend time at a location where you will study. +

+ <% else %> +

+ You will spend most of your time in one school which will employ you. You will also spend some time in another school and at a location where you will study. +

+ <% end %> + + <%= render Find::Courses::TrainingLocations::View.new(course:, preview: preview?(params)) %> + <% if course.published_how_school_placements_work.present? %> <%= markdown(course.published_how_school_placements_work) %> <% elsif course.how_school_placements_work.present? %> @@ -43,17 +55,5 @@ <% end %> <% end %> - - <% if course.site_statuses.map(&:site).uniq.any? %> -

- <%= course.placements_heading %> -

- -

<%= t(".work_with_schools") %>

- -

- <%= govuk_link_to(t(".view_list_of_school_placements"), placements_url) %> -

- <% end %> diff --git a/app/components/find/courses/contents_component/view.html.erb b/app/components/find/courses/contents_component/view.html.erb index f145c89ede..686e3490da 100644 --- a/app/components/find/courses/contents_component/view.html.erb +++ b/app/components/find/courses/contents_component/view.html.erb @@ -8,7 +8,7 @@ <% end %>
  • <%= govuk_link_to t(".fees_and_financial_support"), "#section-financial-support" %>
  • <% if how_school_placements_work.present? || program_type == "higher_education_programme" || program_type == "scitt_programme" || preview? %> -
  • <%= govuk_link_to t(".how_school_placements_work"), "#training-locations" %>
  • +
  • <%= govuk_link_to t(".where_you_will_train"), "#training-locations" %>
  • <% end %> <% if interview_process.present? %>
  • <%= govuk_link_to t(".interview_process"), "#section-interviews" %>
  • diff --git a/app/components/find/courses/training_locations/view.html.erb b/app/components/find/courses/training_locations/view.html.erb new file mode 100644 index 0000000000..3924865665 --- /dev/null +++ b/app/components/find/courses/training_locations/view.html.erb @@ -0,0 +1,26 @@ +<%= govuk_summary_list(actions: false) do |summary_list| %> + <%= summary_list.with_row do |row| %> + <%= row.with_key { top_heading } %> + <%= row.with_value do %> +

    <%= potential_placements_text %>

    + <%= govuk_link_to(t("view_list_of_school_placements"), placements_url) %> +

    Locations can change and are not guaranteed

    + <% end %> + <% end %> + <%= summary_list.with_row do |row| %> + <%= row.with_key { bottom_heading } %> + <%= row.with_value do %> +

    <%= potential_study_sites_text %>

    + + <% end %> + <% end %> +<% end %> diff --git a/app/components/find/courses/training_locations/view.rb b/app/components/find/courses/training_locations/view.rb new file mode 100644 index 0000000000..d8e997a36b --- /dev/null +++ b/app/components/find/courses/training_locations/view.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module Find + module Courses + module TrainingLocations + class View < ViewComponent::Base + include PublishHelper + include PreviewHelper + + attr_reader :course, :preview + + def initialize(course:, preview: false) + @course = course + @preview = preview + super + end + + def placements_url + if preview + placements_publish_provider_recruitment_cycle_course_path( + course.provider_code, + course.recruitment_cycle_year, + course.course_code + ) + else + find_placements_path(course.provider_code, course.course_code) + end + end + + def potential_placements_text + if course.fee_based? + pluralize(course.sites.size, 'potential placement location') + else + pluralize(course.sites.size, 'potential employing school') + end + end + + def potential_study_sites_text + return 'Not listed yet' if course.study_sites.none? + + if course.study_sites.one? + '1 study site' + else + "#{course.study_sites.size} potential study sites" + end + end + + def top_heading + course.fee_based? ? 'Placement schools' : 'Employing schools' + end + + def bottom_heading + 'Where you will study' + end + end + end + end +end diff --git a/config/locales/en/components/find/training_locations.yml b/config/locales/en/components/find/training_locations.yml new file mode 100644 index 0000000000..499ac3aba1 --- /dev/null +++ b/config/locales/en/components/find/training_locations.yml @@ -0,0 +1,2 @@ +en: + view_list_of_school_placements: View list of school placements \ No newline at end of file diff --git a/config/locales/find.yml b/config/locales/find.yml index db8dbc2bce..cf7fceca23 100644 --- a/config/locales/find.yml +++ b/config/locales/find.yml @@ -108,7 +108,7 @@ en: contents_component: view: course_details: Course details - how_school_placements_work: How school placements work + where_you_will_train: Where you will train training_with_disabilities: Training with disabilities fees_and_financial_support: Fees and financial support salary: Salary @@ -176,8 +176,7 @@ en: contact: Contact %{provider_name} about_schools_component: view: - heading: How school placements work - view_list_of_school_placements: View list of school placements + heading: Where you will train work_with_schools: We work with the following schools to provide your school placements. placements: heading: School placements at %{provider_name} diff --git a/spec/components/find/courses/about_schools_component/view_preview.rb b/spec/components/find/courses/about_schools_component/view_preview.rb index 06a95a3aaf..b085268b2c 100644 --- a/spec/components/find/courses/about_schools_component/view_preview.rb +++ b/spec/components/find/courses/about_schools_component/view_preview.rb @@ -4,11 +4,21 @@ module Find module Courses module AboutSchoolsComponent class ViewPreview < ViewComponent::Preview - def hei_minimum + def hei_minimum_without_salary course = Course.new(course_code: 'FIND', provider: Provider.new(provider_code: 'DFE', recruitment_cycle: RecruitmentCycle.current), program_type: 'higher_education_programme', - level: 'further_education').decorate + level: 'further_education', + funding: 'fee').decorate + render Find::Courses::AboutSchoolsComponent::View.new(course) + end + + def hei_minimum_with_salary + course = Course.new(course_code: 'FIND', + provider: Provider.new(provider_code: 'DFE', recruitment_cycle: RecruitmentCycle.current), + program_type: 'higher_education_programme', + level: 'further_education', + funding: 'salary').decorate render Find::Courses::AboutSchoolsComponent::View.new(course) end @@ -38,6 +48,7 @@ def mock_scitt_course placements_heading: 'How placements work', program_type: 'scitt_programme', study_sites: [fake_study_site], + sites: [fake_study_site], site_statuses: [SiteStatus.new(id: 2_245_455, course_id: 12_983_436, publish: 'published', site_id: 11_228_658, status: 'running', vac_status: 'part_time_vacancies'), SiteStatus.new(id: 22_454_556, course_id: 12_983_436, publish: 'published', site_id: 11_228_659, status: 'running', vac_status: 'part_time_vacancies')]) end @@ -45,10 +56,12 @@ def mock_hei_course FakeCourse.new(provider: Provider.new(provider_code: 'DFE'), provider_code: '1BJ', course_code: 'ZZZZ', + is_fee_based: true, published_how_school_placements_work: 'you will go on placement and learn more', placements_heading: 'How placements work', program_type: 'higher_education_programme', study_sites: [fake_study_site], + sites: [fake_study_site], site_statuses: [SiteStatus.new(id: 2_245_455, course_id: 12_983_436, publish: 'published', site_id: 11_228_658, status: 'running', vac_status: 'part_time_vacancies'), SiteStatus.new(id: 22_454_556, course_id: 12_983_436, publish: 'published', site_id: 11_228_659, status: 'running', vac_status: 'part_time_vacancies')]) end @@ -58,7 +71,7 @@ def fake_study_site class FakeCourse include ActiveModel::Model - attr_accessor(:provider, :provider_code, :course_code, :published_how_school_placements_work, :placements_heading, :program_type, :study_sites, :site_statuses) + attr_accessor(:provider, :provider_code, :course_code, :published_how_school_placements_work, :placements_heading, :program_type, :study_sites, :site_statuses, :is_fee_based, :sites) def higher_education_programme? true @@ -67,6 +80,10 @@ def higher_education_programme? def preview_site_statuses site_statuses.sort_by { |status| status.site.location_name } end + + def fee_based? + is_fee_based + end end end end diff --git a/spec/components/find/courses/about_schools_component/view_spec.rb b/spec/components/find/courses/about_schools_component/view_spec.rb index ba2d69fd34..6371ac8a39 100644 --- a/spec/components/find/courses/about_schools_component/view_spec.rb +++ b/spec/components/find/courses/about_schools_component/view_spec.rb @@ -15,7 +15,7 @@ result = render_inline(described_class.new(course)) - expect(result.text).to include('How school placements work') + expect(result.text).to include('Where you will train') end end end @@ -31,31 +31,36 @@ end end - context 'course with site' do - it 'renders the school placement heading' do - provider = build(:provider) + context 'salaried course' do + it 'renders the correct content' do course = build(:course, - provider:, - site_statuses: [ - build(:site_status, site: build(:site)) - ]).decorate + funding: 'salary').decorate result = render_inline(described_class.new(course)) - expect(result.text).to include(course.placements_heading) + expect(result.text).to include('You will spend most of your time in one school which will employ you. You will also spend some time in another school and at a location where you will study.') end end - context 'course with no site' do - it 'does not render the school placement heading' do - provider = build(:provider) + context 'apprenticeship course' do + it 'renders the correct content' do course = build(:course, - site_statuses: [], - provider:).decorate + funding: 'apprenticeship').decorate result = render_inline(described_class.new(course)) - expect(result.text).not_to include(course.placements_heading) + expect(result.text).to include('You will spend most of your time in one school which will employ you. You will also spend some time in another school and at a location where you will study.') + end + end + + context 'fee paying course' do + it 'renders the correct content' do + course = build(:course, + funding: 'fee').decorate + + result = render_inline(described_class.new(course)) + + expect(result.text).to include('You’ll be placed in schools for most of your course to get classroom experience. You will also spend time at a location where you will study.') end end @@ -174,52 +179,4 @@ end end end - - describe '#placements_url' do - context 'when course is published' do - it 'returns the find url' do - provider = build(:provider) - course = build( - :course, - :published, - provider:, - site_statuses: [ - build(:site_status, :findable, site: build(:site)) - ] - ).decorate - - result = render_inline(described_class.new(course)) - - expect(result).to have_link( - 'View list of school placements', - href: find_placements_path(course.provider_code, course.course_code) - ) - end - end - - context 'when course is not published' do - it 'returns the publish url' do - provider = create(:provider) - course = create( - :course, - provider:, - site_statuses: [ - create(:site_status, :findable, site: create(:site)) - ] - ).decorate - - result = render_inline(described_class.new(course, preview: true)) - url = placements_publish_provider_recruitment_cycle_course_path( - course.provider_code, - course.recruitment_cycle_year, - course.course_code - ) - - expect(result).to have_link( - 'View list of school placements', - href: url - ) - end - end - end end diff --git a/spec/components/find/courses/contents_component/view_spec.rb b/spec/components/find/courses/contents_component/view_spec.rb index 244ee55baf..4deef9e9ba 100644 --- a/spec/components/find/courses/contents_component/view_spec.rb +++ b/spec/components/find/courses/contents_component/view_spec.rb @@ -15,7 +15,7 @@ result = render_inline(described_class.new(course)) - expect(result.text).to include('How school placements work') + expect(result.text).to include('Where you will train') end end @@ -31,7 +31,7 @@ result = render_inline(described_class.new(course)) - expect(result.text).to include('How school placements work') + expect(result.text).to include('Where you will train') end end @@ -46,7 +46,7 @@ result = render_inline(described_class.new(course)) - expect(result.text).not_to include('How school placements work') + expect(result.text).not_to include('Where you will train') end end diff --git a/spec/components/find/courses/training_locations/view_preview.rb b/spec/components/find/courses/training_locations/view_preview.rb new file mode 100644 index 0000000000..55184591db --- /dev/null +++ b/spec/components/find/courses/training_locations/view_preview.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +module Find + module Courses + module TrainingLocations + class ViewPreview < ViewComponent::Preview + def no_study_sites_and_one_placement_fee_paying + course = Course.new(course_code: 'FIND', + sites: [Site.new], + funding: 'fee', + provider: Provider.new(provider_code: 'DFE', recruitment_cycle: RecruitmentCycle.current)).decorate + render Find::Courses::TrainingLocations::View.new(course:) + end + + def one_study_site_and_one_placement_fee_paying + course = Course.new(course_code: 'FIND', + sites: [Site.new], + funding: 'fee', + study_sites: [Site.new], + provider: Provider.new(provider_code: 'DFE', recruitment_cycle: RecruitmentCycle.current)).decorate + render Find::Courses::TrainingLocations::View.new(course:) + end + + def two_study_sites_and_one_placement_fee_paying + course = Course.new(course_code: 'FIND', + sites: [Site.new], + funding: 'fee', + study_sites: [Site.new, Site.new], + provider: Provider.new(provider_code: 'DFE', recruitment_cycle: RecruitmentCycle.current)).decorate + render Find::Courses::TrainingLocations::View.new(course:) + end + + def two_study_sites_and_two_placements_fee_paying + course = Course.new(course_code: 'FIND', + sites: [Site.new, Site.new], + funding: 'fee', + study_sites: [Site.new, Site.new], + provider: Provider.new(provider_code: 'DFE', recruitment_cycle: RecruitmentCycle.current)).decorate + render Find::Courses::TrainingLocations::View.new(course:) + end + + def no_study_sites_and_one_placement_salaried + course = Course.new(course_code: 'FIND', + funding: 'salary', + sites: [Site.new], + provider: Provider.new(provider_code: 'DFE', recruitment_cycle: RecruitmentCycle.current)).decorate + render Find::Courses::TrainingLocations::View.new(course:) + end + + def one_study_site_and_one_placement_salaried + course = Course.new(course_code: 'FIND', + sites: [Site.new], + funding: 'salary', + study_sites: [Site.new], + provider: Provider.new(provider_code: 'DFE', recruitment_cycle: RecruitmentCycle.current)).decorate + render Find::Courses::TrainingLocations::View.new(course:) + end + + def two_study_sites_and_one_placement_salaried + course = Course.new(course_code: 'FIND', + sites: [Site.new], + funding: 'salary', + study_sites: [Site.new, Site.new], + provider: Provider.new(provider_code: 'DFE', recruitment_cycle: RecruitmentCycle.current)).decorate + render Find::Courses::TrainingLocations::View.new(course:) + end + + def two_study_sites_and_two_placements_salaried + course = Course.new(course_code: 'FIND', + sites: [Site.new, Site.new], + funding: 'salary', + study_sites: [Site.new, Site.new], + provider: Provider.new(provider_code: 'DFE', recruitment_cycle: RecruitmentCycle.current)).decorate + render Find::Courses::TrainingLocations::View.new(course:) + end + end + end + end +end diff --git a/spec/components/find/courses/training_locations/view_spec.rb b/spec/components/find/courses/training_locations/view_spec.rb new file mode 100644 index 0000000000..77680c1ef8 --- /dev/null +++ b/spec/components/find/courses/training_locations/view_spec.rb @@ -0,0 +1,139 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe Find::Courses::TrainingLocations::View, type: :component do + include Rails.application.routes.url_helpers + + subject { render_inline(described_class.new(course:, preview:)) } + + let(:preview) { false } + let(:component) { described_class.new(course:, preview:) } + + describe '#render' do + let(:study_site) { course.study_sites.first.decorate } + + context 'for fee-paying courses' do + let(:course) { create(:course, :with_full_time_sites, funding: 'fee', study_sites: [build(:site, :study_site)]) } + + it "renders the 'Placement schools' heading" do + expect(subject).to have_css('.govuk-summary-list__key', text: 'Placement schools') + end + + it 'renders the link to school placements' do + expect(subject).to have_link('View list of school placements') + end + + it 'renders the hint about placements not being guaranteed' do + expect(subject).to have_css('.govuk-hint', text: 'Locations can change and are not guaranteed') + end + end + + context 'for salaried courses' do + let(:course) { create(:course, :with_full_time_sites, funding: 'salary', study_sites: [build(:site, :study_site)]) } + + it "renders the 'Employing schools' heading" do + expect(subject).to have_css('.govuk-summary-list__key', text: 'Employing schools') + end + + it 'renders the link to employing schools' do + expect(subject).to have_link('View list of school placements') + end + + it 'renders the hint about placements not being guaranteed' do + expect(subject).to have_css('.govuk-hint', text: 'Locations can change and are not guaranteed') + end + + it "renders 'Where you will study' for study sites" do + expect(subject).to have_css('.govuk-summary-list__key', text: 'Where you will study') + end + + it 'renders the study site names and addresses' do + expect(subject).to have_css('.govuk-hint strong', text: study_site.location_name) + expect(subject).to have_css('.govuk-hint', text: study_site.full_address) + end + end + end + + describe '#placements_url' do + let(:course) { create(:course) } + + context 'when preview is true' do + let(:preview) { true } + + it 'renders a link to the publish path' do + expect(subject).to have_link( + 'View list of school placements', + href: placements_publish_provider_recruitment_cycle_course_path( + course.provider_code, + course.recruitment_cycle_year, + course.course_code + ) + ) + end + end + + context 'when preview is false' do + let(:preview) { false } + + it 'renders a link to the find path' do + expect(subject).to have_link('View list of school placements', + href: find_placements_path(course.provider_code, course.course_code)) + end + end + end + + describe '#potential_placements_text' do + context 'for fee-paying courses' do + let(:course) { create(:course, :with_full_time_sites, funding: 'fee', study_sites: [build(:site, :study_site)]) } + + it 'returns the correct text for one potential placement location' do + expect(component.potential_placements_text).to eq('1 potential placement location') + end + end + + context 'for salaried courses' do + let(:course) { create(:course, :with_full_time_sites, funding: 'salary', study_sites: [build(:site, :study_site)]) } + + it 'returns the correct text for one potential employing school' do + expect(component.potential_placements_text).to eq('1 potential employing school') + end + end + + context 'with multiple placements' do + let(:course) { create(:course, funding: 'fee', sites: [create(:site), create(:site), create(:site)]) } + + it 'returns the correct text for multiple placements' do + expect(component.potential_placements_text).to eq('3 potential placement locations') + end + end + end + + describe '#potential_study_sites_text' do + let(:course) { create(:course, :with_full_time_sites) } + + context 'when there is one study site' do + let(:course) { create(:course, :with_full_time_sites, study_sites: [build(:site, :study_site)]) } + + it 'returns the correct text for one study site' do + expect(component.potential_study_sites_text).to eq('1 study site') + end + end + + context 'when there are multiple study sites' do + let(:course) { create(:course, :with_full_time_sites, study_sites: [build(:site, :study_site), build(:site, :study_site)]) } + + it 'returns the correct text for multiple study sites' do + expect(component.potential_study_sites_text).to eq('2 potential study sites') + end + end + + context 'when there are no study sites' do + let(:course) { create(:course, :with_full_time_sites, study_sites: []) } + + it 'returns the correct text for no study sites' do + expect(component.potential_study_sites_text).to eq('Not listed yet') + end + end + end +end