mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-24 15:49:39 +02:00
New Design System + Codebase Refresh (#1823)
Since the very first 0.1.0-alpha.1 release, we've been moving quickly to add new features to the Maybe app. In doing so, some parts of the codebase have become outdated, unnecessary, or overly-complex as a natural result of this feature prioritization. Now that "core" Maybe is complete, we're moving into a second phase of development where we'll be working hard to improve the accuracy of existing features and build additional features on top of "core". This PR is a quick overhaul of the existing codebase aimed to: - Establish the brand new and simplified dashboard view (pictured above) - Establish and move towards the conventions introduced in Cursor rules and project design overview #1788 - Consolidate layouts and improve the performance of layout queries - Organize the core models of the Maybe domain (i.e. Account::Entry, Account::Transaction, etc.) and break out specific traits of each model into dedicated concerns for better readability - Remove stale / dead code from codebase - Remove overly complex code paths in favor of simpler ones
This commit is contained in:
parent
8539ac7dec
commit
d75be2282b
278 changed files with 3428 additions and 4354 deletions
|
@ -1,6 +1,4 @@
|
|||
class Account::HoldingsController < ApplicationController
|
||||
layout :with_sidebar
|
||||
|
||||
before_action :set_holding, only: %i[show destroy]
|
||||
|
||||
def index
|
||||
|
|
25
app/controllers/accountable_sparklines_controller.rb
Normal file
25
app/controllers/accountable_sparklines_controller.rb
Normal file
|
@ -0,0 +1,25 @@
|
|||
class AccountableSparklinesController < ApplicationController
|
||||
def show
|
||||
@accountable = Accountable.from_type(params[:accountable_type]&.classify)
|
||||
|
||||
@series = Rails.cache.fetch(cache_key) do
|
||||
family.accounts.active
|
||||
.where(accountable_type: @accountable.name)
|
||||
.balance_series(
|
||||
currency: family.currency,
|
||||
favorable_direction: @accountable.favorable_direction
|
||||
)
|
||||
end
|
||||
|
||||
render layout: false
|
||||
end
|
||||
|
||||
private
|
||||
def family
|
||||
Current.family
|
||||
end
|
||||
|
||||
def cache_key
|
||||
family.build_cache_key("#{@accountable.name}_sparkline")
|
||||
end
|
||||
end
|
|
@ -1,26 +1,11 @@
|
|||
class AccountsController < ApplicationController
|
||||
layout :with_sidebar
|
||||
|
||||
before_action :set_account, only: %i[sync]
|
||||
before_action :set_account, only: %i[sync chart sparkline]
|
||||
|
||||
def index
|
||||
@manual_accounts = Current.family.accounts.manual.alphabetically
|
||||
@plaid_items = Current.family.plaid_items.ordered
|
||||
end
|
||||
@manual_accounts = family.accounts.manual.alphabetically
|
||||
@plaid_items = family.plaid_items.ordered
|
||||
|
||||
def summary
|
||||
@period = Period.from_param(params[:period])
|
||||
snapshot = Current.family.snapshot(@period)
|
||||
@net_worth_series = snapshot[:net_worth_series]
|
||||
@asset_series = snapshot[:asset_series]
|
||||
@liability_series = snapshot[:liability_series]
|
||||
@accounts = Current.family.accounts.active
|
||||
@account_groups = @accounts.by_group(period: @period, currency: Current.family.currency)
|
||||
end
|
||||
|
||||
def list
|
||||
@period = Period.from_param(params[:period])
|
||||
render layout: false
|
||||
render layout: "settings"
|
||||
end
|
||||
|
||||
def sync
|
||||
|
@ -32,20 +17,27 @@ class AccountsController < ApplicationController
|
|||
end
|
||||
|
||||
def chart
|
||||
@account = Current.family.accounts.find(params[:id])
|
||||
render layout: "application"
|
||||
end
|
||||
|
||||
def sparkline
|
||||
render layout: false
|
||||
end
|
||||
|
||||
def sync_all
|
||||
unless Current.family.syncing?
|
||||
Current.family.sync_later
|
||||
unless family.syncing?
|
||||
family.sync_later
|
||||
end
|
||||
|
||||
redirect_to accounts_path
|
||||
end
|
||||
|
||||
private
|
||||
def family
|
||||
Current.family
|
||||
end
|
||||
|
||||
def set_account
|
||||
@account = Current.family.accounts.find(params[:id])
|
||||
@account = family.accounts.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,12 +22,6 @@ class ApplicationController < ActionController::Base
|
|||
subscribed_at.present? && subscribed_at <= Time.current && subscribed_at > 1.hour.ago
|
||||
end
|
||||
|
||||
def with_sidebar
|
||||
return "turbo_rails/frame" if turbo_frame_request?
|
||||
|
||||
"with_sidebar"
|
||||
end
|
||||
|
||||
def detect_os
|
||||
user_agent = request.user_agent
|
||||
@os = case user_agent
|
||||
|
|
|
@ -7,7 +7,7 @@ class BudgetCategoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
@recent_transactions = @budget.entries
|
||||
@recent_transactions = @budget.transactions
|
||||
|
||||
if params[:id] == BudgetCategory.uncategorized.id
|
||||
@budget_category = @budget.uncategorized_budget_category
|
||||
|
@ -42,6 +42,7 @@ class BudgetCategoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def set_budget
|
||||
@budget = Current.family.budgets.find(params[:budget_id])
|
||||
start_date = Budget.param_to_date(params[:budget_month_year])
|
||||
@budget = Current.family.budgets.find_by(start_date: start_date)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,10 +6,6 @@ class BudgetsController < ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
@next_budget = @budget.next_budget
|
||||
@previous_budget = @budget.previous_budget
|
||||
@latest_budget = Budget.find_or_bootstrap(Current.family)
|
||||
render layout: with_sidebar
|
||||
end
|
||||
|
||||
def edit
|
||||
|
@ -21,12 +17,6 @@ class BudgetsController < ApplicationController
|
|||
redirect_to budget_budget_categories_path(@budget)
|
||||
end
|
||||
|
||||
def create
|
||||
start_date = Date.parse(budget_create_params[:start_date])
|
||||
@budget = Budget.find_or_bootstrap(Current.family, date: start_date)
|
||||
redirect_to budget_path(@budget)
|
||||
end
|
||||
|
||||
def picker
|
||||
render partial: "budgets/picker", locals: {
|
||||
family: Current.family,
|
||||
|
@ -44,12 +34,13 @@ class BudgetsController < ApplicationController
|
|||
end
|
||||
|
||||
def set_budget
|
||||
@budget = Current.family.budgets.find(params[:id])
|
||||
@budget.sync_budget_categories
|
||||
start_date = Budget.param_to_date(params[:month_year])
|
||||
@budget = Budget.find_or_bootstrap(Current.family, start_date: start_date)
|
||||
raise ActiveRecord::RecordNotFound unless @budget
|
||||
end
|
||||
|
||||
def redirect_to_current_month_budget
|
||||
current_budget = Budget.find_or_bootstrap(Current.family)
|
||||
current_budget = Budget.find_or_bootstrap(Current.family, start_date: Date.current)
|
||||
redirect_to budget_path(current_budget)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
class CategoriesController < ApplicationController
|
||||
layout :with_sidebar
|
||||
|
||||
before_action :set_category, only: %i[edit update destroy]
|
||||
before_action :set_categories, only: %i[update edit]
|
||||
before_action :set_transaction, only: :create
|
||||
|
||||
def index
|
||||
@categories = Current.family.categories.alphabetically
|
||||
|
||||
render layout: "settings"
|
||||
end
|
||||
|
||||
def new
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
class Category::DeletionsController < ApplicationController
|
||||
layout :with_sidebar
|
||||
|
||||
before_action :set_category
|
||||
before_action :set_replacement_category, only: :create
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ module AccountableResource
|
|||
included do
|
||||
include ScrollFocusable
|
||||
|
||||
layout :with_sidebar
|
||||
before_action :set_account, only: [ :show, :edit, :update, :destroy ]
|
||||
before_action :set_link_token, only: :new
|
||||
end
|
||||
|
|
|
@ -13,9 +13,7 @@ module AutoSync
|
|||
|
||||
def family_needs_auto_sync?
|
||||
return false unless Current.family.present?
|
||||
return false unless Current.family.accounts.any?
|
||||
|
||||
Current.family.last_synced_at.blank? ||
|
||||
Current.family.last_synced_at.to_date < Date.current
|
||||
(Current.family.last_synced_at&.to_date || 1.day.ago) < Date.current
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,7 +2,6 @@ module EntryableResource
|
|||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
layout :with_sidebar
|
||||
before_action :set_entry, only: %i[show update destroy]
|
||||
end
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
class Help::ArticlesController < ApplicationController
|
||||
layout :with_sidebar
|
||||
|
||||
def show
|
||||
@article = Help::Article.find(params[:id])
|
||||
|
||||
unless @article
|
||||
head :not_found
|
||||
end
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@ class ImportsController < ApplicationController
|
|||
def index
|
||||
@imports = Current.family.imports
|
||||
|
||||
render layout: with_sidebar
|
||||
render layout: "settings"
|
||||
end
|
||||
|
||||
def new
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
class MerchantsController < ApplicationController
|
||||
layout :with_sidebar
|
||||
|
||||
before_action :set_merchant, only: %i[edit update destroy]
|
||||
|
||||
def index
|
||||
@merchants = Current.family.merchants.alphabetically
|
||||
|
||||
render layout: "settings"
|
||||
end
|
||||
|
||||
def new
|
||||
|
|
|
@ -47,7 +47,7 @@ class MfaController < ApplicationController
|
|||
if action_name.in?(%w[verify verify_code])
|
||||
"auth"
|
||||
else
|
||||
"with_sidebar"
|
||||
"settings"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class OnboardingsController < ApplicationController
|
||||
layout "application"
|
||||
before_action :set_user
|
||||
before_action :load_invitation
|
||||
|
||||
|
|
|
@ -1,40 +1,20 @@
|
|||
class PagesController < ApplicationController
|
||||
skip_before_action :authenticate_user!, only: %i[early_access]
|
||||
layout :with_sidebar, except: %i[early_access]
|
||||
|
||||
def dashboard
|
||||
@period = Period.from_param(params[:period])
|
||||
snapshot = Current.family.snapshot(@period)
|
||||
@net_worth_series = snapshot[:net_worth_series]
|
||||
@asset_series = snapshot[:asset_series]
|
||||
@liability_series = snapshot[:liability_series]
|
||||
|
||||
snapshot_transactions = Current.family.snapshot_transactions
|
||||
@income_series = snapshot_transactions[:income_series]
|
||||
@spending_series = snapshot_transactions[:spending_series]
|
||||
@savings_rate_series = snapshot_transactions[:savings_rate_series]
|
||||
|
||||
snapshot_account_transactions = Current.family.snapshot_account_transactions
|
||||
@top_spenders = snapshot_account_transactions[:top_spenders]
|
||||
@top_earners = snapshot_account_transactions[:top_earners]
|
||||
@top_savers = snapshot_account_transactions[:top_savers]
|
||||
|
||||
@accounts = Current.family.accounts.active
|
||||
@account_groups = @accounts.by_group(period: @period, currency: Current.family.currency)
|
||||
@transaction_entries = Current.family.entries.incomes_and_expenses.limit(6).reverse_chronological
|
||||
|
||||
# TODO: Placeholders for trendlines
|
||||
placeholder_series_data = 10.times.map do |i|
|
||||
{ date: Date.current - i.days, value: Money.new(0, Current.family.currency) }
|
||||
end
|
||||
@investing_series = TimeSeries.new(placeholder_series_data)
|
||||
@period = Period.from_key(params[:period], fallback: true)
|
||||
@balance_sheet = Current.family.balance_sheet
|
||||
@accounts = Current.family.accounts.active.with_attached_logo
|
||||
end
|
||||
|
||||
def changelog
|
||||
@release_notes = Provider::Github.new.fetch_latest_release_notes
|
||||
|
||||
render layout: "settings"
|
||||
end
|
||||
|
||||
def feedback
|
||||
render layout: "settings"
|
||||
end
|
||||
|
||||
def early_access
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class Settings::BillingsController < SettingsController
|
||||
class Settings::BillingsController < ApplicationController
|
||||
layout "settings"
|
||||
|
||||
def show
|
||||
@user = Current.user
|
||||
end
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class Settings::HostingsController < SettingsController
|
||||
class Settings::HostingsController < ApplicationController
|
||||
layout "settings"
|
||||
|
||||
before_action :raise_if_not_self_hosted
|
||||
|
||||
def show
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class Settings::PreferencesController < SettingsController
|
||||
class Settings::PreferencesController < ApplicationController
|
||||
layout "settings"
|
||||
|
||||
def show
|
||||
@user = Current.user
|
||||
end
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class Settings::ProfilesController < SettingsController
|
||||
class Settings::ProfilesController < ApplicationController
|
||||
layout "settings"
|
||||
|
||||
def show
|
||||
@user = Current.user
|
||||
@users = Current.family.users.order(:created_at)
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class Settings::SecuritiesController < SettingsController
|
||||
class Settings::SecuritiesController < ApplicationController
|
||||
layout "settings"
|
||||
|
||||
def show
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
class SettingsController < ApplicationController
|
||||
layout :with_sidebar
|
||||
end
|
|
@ -1,6 +1,4 @@
|
|||
class Tag::DeletionsController < ApplicationController
|
||||
layout :with_sidebar
|
||||
|
||||
before_action :set_tag
|
||||
before_action :set_replacement_tag, only: :create
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
class TagsController < ApplicationController
|
||||
layout :with_sidebar
|
||||
|
||||
before_action :set_tag, only: %i[edit update destroy]
|
||||
|
||||
def index
|
||||
@tags = Current.family.tags.alphabetically
|
||||
|
||||
render layout: "settings"
|
||||
end
|
||||
|
||||
def new
|
||||
|
|
|
@ -1,34 +1,26 @@
|
|||
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).active
|
||||
transactions_query = Current.family.transactions.active.search(@q)
|
||||
|
||||
set_focused_record(search_query, params[:focused_record_id], default_per_page: 50)
|
||||
set_focused_record(transactions_query, params[:focused_record_id], default_per_page: 50)
|
||||
|
||||
@pagy, @transaction_entries = pagy(
|
||||
search_query.reverse_chronological.preload(
|
||||
:account,
|
||||
entryable: [
|
||||
:category, :merchant, :tags,
|
||||
:transfer_as_inflow,
|
||||
transfer_as_outflow: {
|
||||
inflow_transaction: { entry: :account },
|
||||
outflow_transaction: { entry: :account }
|
||||
}
|
||||
]
|
||||
),
|
||||
@pagy, @transactions = pagy(
|
||||
transactions_query.includes(
|
||||
{ entry: :account },
|
||||
:category, :merchant, :tags,
|
||||
transfer_as_outflow: { inflow_transaction: { entry: :account } },
|
||||
transfer_as_inflow: { outflow_transaction: { entry: :account } }
|
||||
).reverse_chronological,
|
||||
limit: params[:per_page].presence || default_params[:per_page],
|
||||
params: ->(params) { params.except(:focused_record_id) }
|
||||
)
|
||||
|
||||
@transfers = @transaction_entries.map { |entry| entry.entryable.transfer_as_outflow }.compact
|
||||
@totals = search_query.stats(Current.family.currency)
|
||||
@totals = Current.family.income_statement.totals(transactions_scope: transactions_query)
|
||||
end
|
||||
|
||||
def clear_filter
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
class TransfersController < ApplicationController
|
||||
layout :with_sidebar
|
||||
|
||||
before_action :set_transfer, only: %i[destroy show update]
|
||||
|
||||
def new
|
||||
|
|
|
@ -19,7 +19,10 @@ class UsersController < ApplicationController
|
|||
@user.update!(user_params.except(:redirect_to, :delete_profile_image))
|
||||
@user.profile_image.purge if should_purge_profile_image?
|
||||
|
||||
handle_redirect(t(".success"))
|
||||
respond_to do |format|
|
||||
format.html { handle_redirect(t(".success")) }
|
||||
format.json { head :ok }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -57,7 +60,7 @@ class UsersController < ApplicationController
|
|||
|
||||
def user_params
|
||||
params.require(:user).permit(
|
||||
:first_name, :last_name, :email, :profile_image, :redirect_to, :delete_profile_image, :onboarded_at,
|
||||
:first_name, :last_name, :email, :profile_image, :redirect_to, :delete_profile_image, :onboarded_at, :show_sidebar,
|
||||
family_attributes: [ :name, :currency, :country, :locale, :date_format, :timezone, :id, :data_enrichment_enabled ]
|
||||
)
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue