1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-24 15:49:39 +02:00

Preserve transaction filters and transaction focus across page visits (#1733)

* Preserve transaction filters across page visits

* Preserve params when per_page is updated

* Autofocus selected transactions

* Lint fixes

* Fix syntax error

* Fix filter clearing

* Update e2e tests for new UI

* Consolidate focus behavior into concern

* Lint fixes
This commit is contained in:
Zach Gollwitzer 2025-01-30 14:12:01 -05:00 committed by GitHub
parent 0b17976256
commit 282c05345d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 310 additions and 243 deletions

View file

@ -1,26 +0,0 @@
class Account::EntriesController < ApplicationController
layout :with_sidebar
before_action :set_account
def index
@q = search_params
@pagy, @entries = pagy(entries_scope.search(@q).reverse_chronological, limit: params[:per_page] || "10")
end
private
def set_account
@account = Current.family.accounts.find(params[:account_id])
end
def entries_scope
scope = Current.family.entries
scope = scope.where(account: @account) if @account
scope
end
def search_params
params.fetch(:q, {})
.permit(:search)
end
end

View file

@ -2,6 +2,8 @@ module AccountableResource
extend ActiveSupport::Concern
included do
include ScrollFocusable
layout :with_sidebar
before_action :set_account, only: [ :show, :edit, :update, :destroy ]
before_action :set_link_token, only: :new
@ -22,6 +24,12 @@ module AccountableResource
end
def show
@q = params.fetch(:q, {}).permit(:search)
entries = @account.entries.search(@q).reverse_chronological
set_focused_record(entries, params[:focused_record_id])
@pagy, @entries = pagy(entries, limit: params[:per_page] || "10", params: ->(params) { params.except(:focused_record_id) })
end
def edit

View file

@ -0,0 +1,21 @@
module ScrollFocusable
extend ActiveSupport::Concern
def set_focused_record(record_scope, record_id, default_per_page: 10)
return unless record_id.present?
@focused_record = record_scope.find_by(id: record_id)
record_index = record_scope.pluck(:id).index(record_id)
return unless record_index
page_of_focused_record = (record_index / (params[:per_page]&.to_i || default_per_page)) + 1
if params[:page]&.to_i != page_of_focused_record
(
redirect_to(url_for(page: page_of_focused_record, focused_record_id: record_id))
)
end
end
end

View file

@ -1,10 +1,21 @@
class TransactionsController < ApplicationController
include ScrollFocusable
layout :with_sidebar
before_action :store_params!, only: :index
def index
@q = search_params
search_query = Current.family.transactions.search(@q).reverse_chronological
@pagy, @transaction_entries = pagy(search_query, limit: params[:per_page] || "50")
set_focused_record(search_query, params[:focused_record_id], default_per_page: 50)
@pagy, @transaction_entries = pagy(
search_query,
limit: params[:per_page].presence || default_params[:per_page],
params: ->(params) { params.except(:focused_record_id) }
)
totals_query = search_query.incomes_and_expenses
family_currency = Current.family.currency
@ -18,13 +29,76 @@ class TransactionsController < ApplicationController
}
end
def clear_filter
updated_params = stored_params.deep_dup
q_params = updated_params["q"] || {}
param_key = params[:param_key]
param_value = params[:param_value]
if q_params[param_key].is_a?(Array)
q_params[param_key].delete(param_value)
q_params.delete(param_key) if q_params[param_key].empty?
else
q_params.delete(param_key)
end
updated_params["q"] = q_params.presence
Current.session.update!(prev_transaction_page_params: updated_params)
redirect_to transactions_path(updated_params)
end
private
def search_params
params.fetch(:q, {})
cleaned_params = params.fetch(:q, {})
.permit(
:start_date, :end_date, :search, :amount,
:amount_operator, accounts: [], account_ids: [],
categories: [], merchants: [], types: [], tags: []
)
.to_h
.compact_blank
cleaned_params.delete(:amount_operator) unless cleaned_params[:amount].present?
cleaned_params
end
def store_params!
if should_restore_params?
params_to_restore = {}
params_to_restore[:q] = stored_params["q"].presence || default_params[:q]
params_to_restore[:page] = stored_params["page"].presence || default_params[:page]
params_to_restore[:per_page] = stored_params["per_page"].presence || default_params[:per_page]
redirect_to transactions_path(params_to_restore)
else
Current.session.update!(
prev_transaction_page_params: {
q: search_params,
page: params[:page],
per_page: params[:per_page]
}
)
end
end
def should_restore_params?
request.query_parameters.blank? && (stored_params["q"].present? || stored_params["page"].present? || stored_params["per_page"].present?)
end
def stored_params
Current.session.prev_transaction_page_params
end
def default_params
{
q: {},
page: 1,
per_page: 50
}
end
end