1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-19 05:09:38 +02:00

Add breadcrumbs support across application (#1897)
Some checks are pending
Publish Docker image / ci (push) Waiting to run
Publish Docker image / Build docker image (push) Blocked by required conditions

* Add breadcrumbs support across application

Fixes #1896

* Potential fix for tests

* Simplify breadcrumbs implementation

Remove complex breadcrumbs logic from controllers and concern, replacing with a simpler default approach that sets a basic breadcrumb based on the current controller name

* Refactor page header and breadcrumbs rendering

Remove complex breadcrumbs helper method and update layout to use more flexible content_for approach for page headers and breadcrumbs

* Add fallback breadcrumbs rendering to settings layout
This commit is contained in:
Josh Pigford 2025-02-25 10:14:07 -06:00 committed by GitHub
parent 763e222cdd
commit a4874815a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 75 additions and 21 deletions

View file

@ -1,5 +1,5 @@
class ApplicationController < ActionController::Base
include Onboardable, Localize, AutoSync, Authentication, Invitable, SelfHostable, StoreLocation, Impersonatable
include Onboardable, Localize, AutoSync, Authentication, Invitable, SelfHostable, StoreLocation, Impersonatable, Breadcrumbable
include Pagy::Backend
helper_method :require_upgrade?, :subscription_pending?

View file

@ -25,6 +25,7 @@ class BudgetsController < ApplicationController
end
private
def budget_create_params
params.require(:budget).permit(:start_date)
end

View file

@ -0,0 +1,13 @@
module Breadcrumbable
extend ActiveSupport::Concern
included do
before_action :set_breadcrumbs
end
private
# The default, unless specific controller or action explicitly overrides
def set_breadcrumbs
@breadcrumbs = [ [ "Home", root_path ], [ controller_name.titleize, nil ] ]
end
end

View file

@ -5,6 +5,8 @@ class PagesController < ApplicationController
@period = Period.from_key(params[:period], fallback: true)
@balance_sheet = Current.family.balance_sheet
@accounts = Current.family.accounts.active.with_attached_logo
@breadcrumbs = [ [ "Home", root_path ], [ "Dashboard", nil ] ]
end
def changelog

View file

@ -49,6 +49,7 @@ class TransactionsController < ApplicationController
end
private
def search_params
cleaned_params = params.fetch(:q, {})
.permit(

View file

@ -44,6 +44,17 @@
<% end %>
<%= tag.div class: class_names("mx-auto w-full h-full", Current.user.show_sidebar? ? "max-w-4xl" : "max-w-5xl"), data: { sidebar_target: "content" } do %>
<% unless controller_path.start_with?('settings/') %>
<% if content_for?(:breadcrumbs) %>
<%= yield :breadcrumbs %>
<% else %>
<%= render "layouts/shared/breadcrumbs", breadcrumbs: @breadcrumbs %>
<% end %>
<% if content_for?(:page_header) %>
<%= yield :page_header %>
<% end %>
<% end %>
<%= yield %>
<% end %>
<% end %>

View file

@ -7,6 +7,12 @@
<main class="py-4 px-10 grow flex h-full overflow-y-auto">
<div class="relative max-w-4xl mx-auto flex flex-col w-full h-full">
<div class="grow space-y-4 overflow-y-auto -mx-1 px-1 pb-12">
<% if content_for?(:breadcrumbs) %>
<%= yield :breadcrumbs %>
<% else %>
<%= render "layouts/shared/breadcrumbs", breadcrumbs: @breadcrumbs %>
<% end %>
<% if content_for?(:page_title) %>
<h1 class="text-primary text-xl font-medium">
<%= content_for :page_title %>

View file

@ -0,0 +1,21 @@
<%# locals: (breadcrumbs:) %>
<nav class="flex items-center gap-2 mb-6">
<button data-action="sidebar#toggle" class="w-9 h-9 inline-flex rounded-lg items-center justify-center hover:bg-gray-100 cursor-pointer">
<%= icon("panel-left", color: "gray") %>
</button>
<% breadcrumbs.each_with_index do |(name, path), index| %>
<% if index > 0 %>
<%= icon("chevron-right", color: "gray", size: "sm") %>
<% end %>
<% if path.present? && index < breadcrumbs.size - 1 %>
<%= link_to name, path, class: "text-sm text-gray-500 font-medium" %>
<% elsif index == breadcrumbs.size - 1 %>
<span class="text-gray-900 font-medium text-sm"><%= name %></span>
<% else %>
<span class="text-sm text-gray-500 font-medium"><%= name %></span>
<% end %>
<% end %>
</nav>

View file

@ -0,0 +1,11 @@
<%# This partial renders the page header with title and optional subtitle %>
<header class="space-y-6">
<% if local_assigns[:title].present? %>
<div class="space-y-1">
<h1 class="text-3xl font-medium text-gray-900"><%= title %></h1>
<% if local_assigns[:subtitle].present? %>
<p class="text-gray-500"><%= subtitle %></p>
<% end %>
</div>
<% end %>
</header>

View file

@ -1,23 +1,11 @@
<% content_for :page_header do %>
<div class="space-y-1 mb-6">
<h1 class="text-3xl font-medium text-gray-900">Welcome back, <%= Current.user.first_name %></h1>
<p class="text-gray-500">Here's what's happening with your money this week</p>
</div>
<% end %>
<div class="w-full space-y-6 pb-24">
<header class="space-y-6">
<nav class="flex items-center gap-2">
<button data-action="sidebar#toggle" class="w-9 h-9 inline-flex rounded-lg items-center justify-center hover:bg-gray-100 cursor-pointer">
<%= icon("panel-left", color: "gray") %>
</button>
<span class="text-sm text-gray-500 font-medium">Home</span>
<%= icon("chevron-right", color: "gray", size: "sm") %>
<span class="text-gray-900 font-medium text-sm">Dashboard</span>
</nav>
<div class="space-y-1">
<h1 class="text-3xl font-medium text-gray-900">Welcome back, <%= Current.user.first_name %></h1>
<p class="text-gray-500">Here's what's happening with your money this week</p>
</div>
</header>
<section class="bg-white py-4 rounded-xl shadow-border-xs">
<%= render partial: "pages/dashboard/net_worth_chart", locals: { series: @balance_sheet.net_worth_series(period: @period), period: @period } %>
</section>

View file

@ -103,7 +103,7 @@ class AccountsTest < ApplicationSystemTestCase
visit account_url(created_account)
within "header" do
within "header:has(button[data-menu-target='button'])" do
find('button[data-menu-target="button"]').click
click_on "Edit"
end