Skip to content

Commit

Permalink
New header and primary navigation for candidate support and provider
Browse files Browse the repository at this point in the history
With the introduction of one login and the fact that we need a new
header and primary navigation for the candidate path, to allow the
candidate to manage their one login account.

We decided to implement the header and primary navigation for our other users.
providers and support as well as candidates.

I have not changed these components for our api users. The content
that's already there needs a bit more work before, I think.

This should show the GOV.UK One Login account link for candidates if the
one login feature is enabled.
  • Loading branch information
CatalinVoineag committed Jan 15, 2025
1 parent 75213a8 commit b3b2dbb
Show file tree
Hide file tree
Showing 14 changed files with 268 additions and 75 deletions.
2 changes: 1 addition & 1 deletion app/components/utility/header_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class HeaderComponent < ViewComponent::Base
attr_reader :classes, :product_name, :service_name, :service_link, :phase_tag, :navigation_items, :navigation_classes

def initialize(service_link:, classes: '', product_name: nil, homepage_url: nil, service_name: nil, phase_tag: false, navigation_items: [], navigation_classes: '')
def initialize(service_link: nil, classes: '', product_name: nil, homepage_url: nil, service_name: nil, phase_tag: false, navigation_items: [], navigation_classes: '')
@classes = classes
@product_name = product_name
@homepage_url = homepage_url
Expand Down
2 changes: 1 addition & 1 deletion app/components/utility/phase_banner_component.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div class="app-phase-banner<%= @no_border ? ' app-phase-banner--no-border' : '' %> govuk-!-display-none-print">
<div class="app-phase-banner govuk-!-display-none-print">
<div class="govuk-width-container">
<%= govuk_phase_banner(
tag: {
Expand Down
32 changes: 32 additions & 0 deletions app/frontend/styles/_header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,35 @@
}
}
}

.govuk-header {
&__navigation {
display: flex;

@include govuk-media-query($from: tablet) {
justify-content: flex-end;
}
}

&__navigation-list {
@include govuk-media-query($from: tablet) {
display: flex;
}
}

&__navigation-item {
@include govuk-media-query($from: tablet) {
padding-inline: govuk-spacing(3);
margin: 0;

border-left: 1px solid $govuk-border-colour;
}
}
}

.one-login-svg {
position: relative;
top: 2px;

margin-left: 7px;
}
10 changes: 10 additions & 0 deletions app/frontend/styles/_primary-navigation.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
.govuk-service-navigation {
&__container {
justify-content: space-between;
}

&__link {
font-weight: bold;
}
}

.app-primary-navigation {
background-color: govuk-colour("light-grey");
}
Expand Down
154 changes: 125 additions & 29 deletions app/helpers/navigation_items.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,72 @@ def candidate_primary_navigation(current_candidate:, current_controller:)

if current_candidate.current_application.any_offer_accepted?
[
NavigationItem.new(
t('page_titles.offer_dashboard'),
candidate_interface_application_offer_dashboard_path,
true,
),
{
text: t('page_titles.offer_dashboard'),
href: candidate_interface_application_offer_dashboard_path,
active: true,
},
]
elsif current_candidate.current_application.carry_over?
[
NavigationItem.new(
t('page_titles.your_applications'),
candidate_interface_application_choices_path,
true,
),
{
text: t('page_titles.your_applications'),
href: candidate_interface_application_choices_path,
active: true,
},
]
else
[
NavigationItem.new(
t('page_titles.your_details'),
candidate_interface_details_path,
current_controller.respond_to?(:choices_controller?) ? !current_controller.choices_controller? : false,
),
NavigationItem.new(
t('page_titles.your_applications'),
candidate_interface_application_choices_path,
current_controller.respond_to?(:choices_controller?) ? current_controller.choices_controller? : false,
),
{
text: t('page_titles.your_details'),
href: candidate_interface_details_path,
active: current_controller.respond_to?(:choices_controller?) ? !current_controller.choices_controller? : false,
},
{
text: t('page_titles.your_applications'),
href: candidate_interface_application_choices_path,
active: current_controller.respond_to?(:choices_controller?) ? current_controller.choices_controller? : false,
},
]
end
end

def candidate(current_candidate:)
if current_candidate.nil?
[]
else
sign_in_items(current_candidate)
end
end

def for_support_primary_nav(current_support_user, current_controller)
if current_support_user
[
NavigationItem.new('Candidates', support_interface_applications_path, active?(current_controller, %w[candidates import_references application_forms]), []),
NavigationItem.new('Providers', support_interface_providers_path, active?(current_controller, %w[providers course provider_users api_tokens]), []),
NavigationItem.new('Performance', support_interface_performance_path, active?(current_controller, %w[performance data_exports validation_errors email_log vendor_api_requests performance_dashboard]), []),
NavigationItem.new('Settings', support_interface_settings_path, active?(current_controller, %w[settings tasks support_users]), []),
NavigationItem.new('Documentation', support_interface_docs_path, active?(current_controller, %w[docs]), []),
{
text: 'Candidates',
href: support_interface_applications_path,
active: active?(current_controller, %w[candidates import_references application_forms]),
},
{
text: 'Providers',
href: support_interface_providers_path,
active: active?(current_controller, %w[providers course provider_users api_tokens]),
},
{
text: 'Performance',
href: support_interface_performance_path,
active: active?(current_controller, %w[performance data_exports validation_errors email_log vendor_api_requests performance_dashboard]),
},
{
text: 'Settings',
href: support_interface_settings_path,
active: active?(current_controller, %w[settings tasks support_users]),
},
{
text: 'Documentation',
href: support_interface_docs_path,
active: active?(current_controller, %w[docs]),
},
]
else
[]
Expand Down Expand Up @@ -75,10 +103,54 @@ def for_provider_primary_nav(current_provider_user, current_controller, performi
items = []

if current_provider_user && !performing_setup
items << NavigationItem.new('Applications', provider_interface_applications_path, active?(current_controller, %w[application_choices decisions offer_changes notes interviews offers feedback conditions reconfirm_deferred_offers]), [])
items << NavigationItem.new('Interview schedule', provider_interface_interview_schedule_path, active?(current_controller, %w[interview_schedules]), [])
items << NavigationItem.new('Reports', provider_interface_reports_path, active?(current_controller, %w[reports application_data_export hesa_exports recruitment_performance_reports withdrawal_reports withdrawal_reasons_reports status_of_active_applications diversity_reports]))
items << NavigationItem.new('Activity log', provider_interface_activity_log_path, active?(current_controller, %w[activity_log]), [])
items << {
text: 'Applications',
href: provider_interface_applications_path,
active: active?(
current_controller,
%w[
application_choices
decisions
offer_changes
notes
interviews
offers
feedback
conditions
reconfirm_deferred_offers
references
courses
study_modes
],
),
}
items << {
text: 'Interview schedule',
href: provider_interface_interview_schedule_path,
active: active?(current_controller, %w[interview_schedules]),
}
items << {
text: 'Reports',
href: provider_interface_reports_path,
active: active?(
current_controller,
%w[
reports
application_data_export
hesa_exports
recruitment_performance_reports
withdrawal_reports
withdrawal_reasons_reports
status_of_active_applications
diversity_reports
],
),
}
items << {
text: 'Activity log',
href: provider_interface_activity_log_path,
active: active?(current_controller, %w[activity_log]),
}
end

items
Expand Down Expand Up @@ -140,5 +212,29 @@ def active?(current_controller, active_controllers)
def active_action?(current_controller, active_action)
current_controller.action_name == active_action
end

def sign_in_items(current_candidate)
items = []

if FeatureFlag.active?(:one_login_candidate_sign_in) && !OneLogin.bypass?
items << NavigationItem.new("GOV.UK One Login #{one_login_svg}".html_safe, ENV['GOVUK_ONE_LOGIN_ACCOUNT_URL'], false)
end

if current_candidate.present?
sign_out_path = FeatureFlag.active?(:one_login_candidate_sign_in) ? auth_one_login_sign_out_path : candidate_interface_sign_out_path
items << NavigationItem.new('Sign out', sign_out_path)
end
end

def one_login_svg
"<span aria-hidden=\"true\" class=\"one-login-svg\">
<svg width=\"15\" height=\"15\" viewBox=\"0 0 22 22\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" focusable=\"false\" aria-hidden=\"true\">
<circle cx=\"11\" cy=\"11\" r=\"11\" fill=\"white\" data-darkreader-inline-fill=\"\" style=\"--darkreader-inline-fill: #e8e6e3;\"></circle>
<path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M3.29297 18.8487C4.23255 15.4753 7.32741 13 11.0004 13C14.6731 13 17.7678 15.4749 18.7076 18.848C17.8058 19.7338 16.752 20.4654 15.5889 21H11.0004H6.41097C5.24819 20.4655 4.19463 19.7342 3.29297 18.8487Z\" fill=\"#1D70B8\" data-darkreader-inline-fill=\"\" style=\"--darkreader-inline-fill: #65aee7;\"></path>
<circle cx=\"11\" cy=\"7.75\" r=\"3.75\" fill=\"#1D70B8\" data-darkreader-inline-fill=\"\" style=\"--darkreader-inline-fill: #65aee7;\"></circle>
<circle cx=\"11\" cy=\"11\" r=\"10\" stroke=\"white\" stroke-width=\"2\" data-darkreader-inline-stroke=\"\" style=\"--darkreader-inline-stroke: #e8e6e3;\"></circle>
</svg>
</span><span class=\"govuk-visually-hidden\">Currently impersonating:</span>"
end
end
end
55 changes: 29 additions & 26 deletions app/views/layouts/_header.html.erb
Original file line number Diff line number Diff line change
@@ -1,41 +1,47 @@
<% case try(:current_namespace) %>
<% when 'candidate_interface' %>
<%= render(HeaderComponent.new(
classes: "app-header--#{HostingEnvironment.environment_name} app-header--full-border",
service_name: service_name,
service_link: service_link,
)) %>
<%= render PhaseBannerComponent.new(no_border: current_candidate.present?) %>
<% if current_candidate %>
<% sign_out_path = FeatureFlag.active?(:one_login_candidate_sign_in) ? auth_one_login_sign_out_path : candidate_interface_sign_out_path %>
<%= render(PrimaryNavigationComponent.new(
items: NavigationItems.candidate_primary_navigation(current_candidate:, current_controller: controller),
items_right: [NavigationItems::NavigationItem.new('Sign out', sign_out_path)],
)) %>
<% end %>
<%= render(
HeaderComponent.new(
homepage_url: service_link,
classes: "app-header--#{HostingEnvironment.environment_name} app-header--full-border",
navigation_items: NavigationItems.candidate(current_candidate:),
),
) %>

<%= govuk_service_navigation(
service_name: t('service_name.apply'),
current_path: request.path,
navigation_items: NavigationItems.candidate_primary_navigation(
current_candidate:,
current_controller: controller,
),
) %>
<%= render PhaseBannerComponent.new(no_border: current_candidate.present?) %>
<% when 'support_interface' %>
<%= render(HeaderComponent.new(
classes: "app-header--#{HostingEnvironment.environment_name} app-header--full-border app-header--wide-logo",
product_name: service_name,
homepage_url: service_link,
service_link: service_link,
phase_tag: true,
navigation_items: NavigationItems.for_support_account_nav(try(:current_support_user)),
navigation_classes: 'govuk-header__navigation--end',
)) %>
<%= render(PrimaryNavigationComponent.new(
items: NavigationItems.for_support_primary_nav(try(:current_support_user), controller),
)) %>
<%= govuk_service_navigation(
service_name: t('service_name.apply'),
current_path: request.path,
navigation_items: NavigationItems.for_support_primary_nav(try(:current_support_user), controller),
) %>
<%= yield(:navigation) if content_for?(:navigation) %>
<% when 'provider_interface' %>
<%= render(HeaderComponent.new(
classes: "app-header--#{HostingEnvironment.environment_name} app-header--full-border app-header--wide-logo",
product_name: service_name,
homepage_url: service_link,
service_link: service_link,
navigation_items: NavigationItems.for_provider_account_nav(try(:current_provider_user), controller, performing_setup: @provider_setup&.pending?),
navigation_classes: 'govuk-header__navigation--end',
)) %>

<%= govuk_service_navigation(
service_name: t('service_name.apply'),
current_path: request.path,
navigation_items: NavigationItems.for_provider_primary_nav(try(:current_provider_user), controller, performing_setup: @provider_setup&.pending?),
) %>

<% if controller.controller_name == 'start_page' %>
<%= render(PhaseBannerComponent.new(
feedback_link: ProviderInterface::FEEDBACK_LINK,
Expand All @@ -49,9 +55,6 @@
no_border: true,
feedback_link: ProviderInterface::FEEDBACK_LINK,
)) %>
<%= render(PrimaryNavigationComponent.new(
items: NavigationItems.for_provider_primary_nav(try(:current_provider_user), controller, performing_setup: @provider_setup&.pending?),
)) %>
<% end %>
<% when 'vendor_api_docs' %>
<%= render(HeaderComponent.new(
Expand Down
Loading

0 comments on commit b3b2dbb

Please sign in to comment.