diff --git a/app/controllers/locations_controller.rb b/app/controllers/locations_controller.rb index e55ee10d6..f89325b41 100644 --- a/app/controllers/locations_controller.rb +++ b/app/controllers/locations_controller.rb @@ -6,15 +6,18 @@ class LocationsController < ApplicationController before_action :find_location, except: %i[create index] before_action :find_scheme before_action :scheme_and_location_present, except: %i[create index] + before_action :session_filters, if: :current_user, only: %i[index] + before_action -> { filter_manager.serialize_filters_to_session }, if: :current_user, only: %i[index] before_action :authorize_user, except: %i[index create] def index authorize @scheme - @pagy, @locations = pagy(filtered_collection(@scheme.locations, search_term)) + @pagy, @locations = pagy(filter_manager.filtered_locations(@scheme.locations, search_term, session_filters)) @total_count = @scheme.locations.size @searched = search_term.presence + @filter_type = "scheme_locations" end def create @@ -297,4 +300,12 @@ private params[:referrer] == "check_answers" end helper_method :return_to_check_your_answers? + + def filter_manager + FilterManager.new(current_user:, session:, params:, filter_type: "scheme_locations") + end + + def session_filters + filter_manager.session_filters + end end diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index cdcd05c9f..225f05f8b 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -1,8 +1,9 @@ class SessionsController < ApplicationController def clear_filters session[session_name_for(params[:filter_type])] = "{}" + path_params = params[:path_params].presence || {} - redirect_to send("#{params[:filter_type]}_path") + redirect_to send("#{params[:filter_type]}_path", scheme_id: path_params[:scheme_id]) end private diff --git a/app/helpers/filters_helper.rb b/app/helpers/filters_helper.rb index 33e109565..e2da5b0ed 100644 --- a/app/helpers/filters_helper.rb +++ b/app/helpers/filters_helper.rb @@ -56,6 +56,17 @@ module FiltersHelper }.freeze end + def location_status_filters + { + "incomplete" => "Incomplete", + "active" => "Active", + "deactivating_soon" => "Deactivating soon", + "activating_soon" => "Activating soon", + "reactivating_soon" => "Reactivating soon", + "deactivated" => "Deactivated", + }.freeze + end + def selected_option(filter, filter_type) return false unless session[session_name_for(filter_type)] @@ -80,9 +91,9 @@ module FiltersHelper applied_filters_count(filter_type).zero? ? "No filters applied" : "#{pluralize(applied_filters_count(filter_type), 'filter')} applied" end - def reset_filters_link(filter_type) + def reset_filters_link(filter_type, path_params = {}) if applied_filters_count(filter_type).positive? - govuk_link_to "Clear", clear_filters_path(filter_type:) + govuk_link_to "Clear", clear_filters_path(filter_type:, path_params:) end end @@ -104,6 +115,8 @@ private end def applied_filters(filter_type) + return {} unless session[session_name_for(filter_type)] + JSON.parse(session[session_name_for(filter_type)]) end diff --git a/app/models/location.rb b/app/models/location.rb index 0dd6ba522..f25fd7d5d 100644 --- a/app/models/location.rb +++ b/app/models/location.rb @@ -27,6 +27,56 @@ class Location < ApplicationRecord scope :active_in_2_weeks, -> { where(confirmed: true).and(started_in_2_weeks) } scope :confirmed, -> { where(confirmed: true) } scope :unconfirmed, -> { where.not(confirmed: true) } + scope :filter_by_status, lambda { |statuses, _user = nil| + filtered_records = all + scopes = [] + + statuses.each do |status| + if respond_to?(status, true) + scopes << (status == "active" ? send("active_status") : send(status)) + end + end + + if scopes.any? + filtered_records = filtered_records + .left_outer_joins(:location_deactivation_periods) + .order("location_deactivation_periods.created_at DESC") + .merge(scopes.reduce(&:or)) + end + + filtered_records + } + + scope :incomplete, lambda { + where.not(confirmed: true) + } + + scope :deactivated, lambda { + merge(LocationDeactivationPeriod.deactivations_without_reactivation) + .where("location_deactivation_periods.deactivation_date <= ?", Time.zone.now) + } + + scope :deactivating_soon, lambda { + merge(LocationDeactivationPeriod.deactivations_without_reactivation) + .where("location_deactivation_periods.deactivation_date > ?", Time.zone.now) + } + + scope :reactivating_soon, lambda { + where.not("location_deactivation_periods.reactivation_date IS NULL") + .where("location_deactivation_periods.reactivation_date > ?", Time.zone.now) + } + + scope :activating_soon, lambda { + where("startdate > ?", Time.zone.now) + } + + scope :active_status, lambda { + where.not(id: joins(:location_deactivation_periods).reactivating_soon.pluck(:id)) + .where.not(id: joins(:location_deactivation_periods).deactivated.pluck(:id)) + .where.not(id: incomplete.pluck(:id)) + .where.not(id: joins(:location_deactivation_periods).deactivating_soon.pluck(:id)) + .where.not(id: activating_soon.pluck(:id)) + } LOCAL_AUTHORITIES = LocalAuthority.all.map { |la| [la.name, la.code] }.to_h diff --git a/app/services/filter_manager.rb b/app/services/filter_manager.rb index 63b13ecdc..c8665752d 100644 --- a/app/services/filter_manager.rb +++ b/app/services/filter_manager.rb @@ -62,6 +62,17 @@ class FilterManager schemes end + def self.filter_locations(locations, search_term, filters, user) + locations = filter_by_search(locations, search_term) + + filters.each do |category, values| + next if Array(values).reject(&:empty?).blank? + + locations = locations.public_send("filter_by_#{category}", values, user) + end + locations.order(created_at: :desc) + end + def serialize_filters_to_session(specific_org: false) session[session_name_for(filter_type)] = session_filters(specific_org:).to_json end @@ -86,7 +97,7 @@ class FilterManager new_filters["user"] = current_user.id.to_s if params["assigned_to"] == "you" end - if (filter_type.include?("schemes") || filter_type.include?("users")) && params["status"].present? + if (filter_type.include?("schemes") || filter_type.include?("users") || filter_type.include?("scheme_locations")) && params["status"].present? new_filters["status"] = params["status"] end @@ -117,6 +128,10 @@ class FilterManager FilterManager.filter_schemes(schemes, search_term, filters, current_user, all_orgs) end + def filtered_locations(locations, search_term, filters) + FilterManager.filter_locations(locations, search_term, filters, current_user) + end + def bulk_upload id = (logs_filters["bulk_upload_id"] || []).reject(&:blank?)[0] @bulk_upload ||= current_user.bulk_uploads.find_by(id:) diff --git a/app/views/locations/_location_filters.html.erb b/app/views/locations/_location_filters.html.erb new file mode 100644 index 000000000..d5bdeb156 --- /dev/null +++ b/app/views/locations/_location_filters.html.erb @@ -0,0 +1,30 @@ +
+ <%= filters_applied_text(@filter_type) %> +
++ <%= reset_filters_link(@filter_type, { scheme_id: @scheme.id }) %> +
+