mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-24 07:39:39 +02:00
Add empty states to account summary page (#1265)
* Add empty states to account summary page * Liability icon fix * Normalize translations * Clean up modal styles * Account color updates * Lint fixes * Test fix
This commit is contained in:
parent
ffd54e4065
commit
2f6479f058
9 changed files with 93 additions and 69 deletions
|
@ -39,13 +39,16 @@ class Account < ApplicationRecord
|
|||
|
||||
Accountable.by_classification.each do |classification, types|
|
||||
types.each do |type|
|
||||
group = grouped_accounts[classification.to_sym].add_child_group(type, currency)
|
||||
self.where(accountable_type: type).each do |account|
|
||||
group.add_value_node(
|
||||
account,
|
||||
account.balance_money.exchange_to(currency, fallback_rate: 0),
|
||||
account.series(period: period, currency: currency)
|
||||
)
|
||||
accounts = self.where(accountable_type: type)
|
||||
if accounts.any?
|
||||
group = grouped_accounts[classification.to_sym].add_child_group(type, currency)
|
||||
accounts.each do |account|
|
||||
group.add_value_node(
|
||||
account,
|
||||
account.balance_money.exchange_to(currency, fallback_rate: 0),
|
||||
account.series(period: period, currency: currency)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
<%= link_to new_account_path(step: "method", type: type.class.name.demodulize, institution_id: params[:institution_id]), class: "flex items-center gap-4 w-full text-center focus:outline-none focus:bg-gray-25 border border-transparent focus:border focus:border-gray-200 block px-2 hover:bg-gray-25 rounded-lg p-2" do %>
|
||||
<%= link_to new_account_path(
|
||||
step: "method",
|
||||
type: type.class.name.demodulize,
|
||||
institution_id: params[:institution_id]
|
||||
),
|
||||
class: "flex items-center gap-4 w-full text-center focus:outline-none focus:bg-alpha-black-25 hover:bg-alpha-black-25 border border-transparent block px-2 rounded-lg p-2" do %>
|
||||
<span class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg <%= bg_color %> border border-alpha-black-25">
|
||||
<%= lucide_icon(icon, class: "#{text_color} w-5 h-5") %>
|
||||
</span>
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
|
||||
<% end %>
|
||||
|
||||
<%= render "sync_all_button" %>
|
||||
|
||||
<%= link_to new_account_path, class: "rounded-lg bg-gray-900 text-white flex items-center gap-1 justify-center hover:bg-gray-700 px-3 py-2", data: { turbo_frame: :modal } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<p class="text-sm font-medium"><%= t(".new") %></p>
|
||||
|
|
|
@ -8,15 +8,15 @@
|
|||
<div class="flex flex-col p-2 text-sm grow">
|
||||
<button hidden data-controller="hotkey" data-hotkey="k,K,ArrowUp,ArrowLeft" data-action="list-keyboard-navigation#focusPrevious">Previous</button>
|
||||
<button hidden data-controller="hotkey" data-hotkey="j,J,ArrowDown,ArrowRight" data-action="list-keyboard-navigation#focusNext">Next</button>
|
||||
<%= render "account_type", type: Depository.new, bg_color: "bg-blue-50", text_color: "text-blue-500", icon: "landmark" %>
|
||||
<%= render "account_type", type: Investment.new, bg_color: "bg-green-50", text_color: "text-green-500", icon: "line-chart" %>
|
||||
<%= render "account_type", type: Crypto.new, bg_color: "bg-green-50", text_color: "text-green-500", icon: "bitcoin" %>
|
||||
<%= render "account_type", type: Property.new, bg_color: "bg-pink-50", text_color: "text-pink-500", icon: "home" %>
|
||||
<%= render "account_type", type: Vehicle.new, bg_color: "bg-indigo-50", text_color: "text-indigo-500", icon: "car-front" %>
|
||||
<%= render "account_type", type: CreditCard.new, bg_color: "bg-violet-50", text_color: "text-violet-500", icon: "credit-card" %>
|
||||
<%= render "account_type", type: Loan.new, bg_color: "bg-yellow-50", text_color: "text-yellow-500", icon: "hand-coins" %>
|
||||
<%= render "account_type", type: OtherAsset.new, bg_color: "bg-green-50", text_color: "text-green-500", icon: "plus" %>
|
||||
<%= render "account_type", type: OtherLiability.new, bg_color: "bg-red-50", text_color: "text-red-500", icon: "minus" %>
|
||||
<%= render "account_type", type: Depository.new, bg_color: "bg-blue-500/5", text_color: "text-blue-500", icon: "landmark" %>
|
||||
<%= render "account_type", type: Investment.new, bg_color: "bg-green-500/5", text_color: "text-green-500", icon: "line-chart" %>
|
||||
<%= render "account_type", type: Crypto.new, bg_color: "bg-orange-500/5", text_color: "text-orange-500", icon: "bitcoin" %>
|
||||
<%= render "account_type", type: Property.new, bg_color: "bg-pink-500/5", text_color: "text-pink-500", icon: "home" %>
|
||||
<%= render "account_type", type: Vehicle.new, bg_color: "bg-cyan-500/5", text_color: "text-cyan-500", icon: "car-front" %>
|
||||
<%= render "account_type", type: CreditCard.new, bg_color: "bg-violet-500/5", text_color: "text-violet-500", icon: "credit-card" %>
|
||||
<%= render "account_type", type: Loan.new, bg_color: "bg-yellow-500/5", text_color: "text-yellow-500", icon: "hand-coins" %>
|
||||
<%= render "account_type", type: OtherAsset.new, bg_color: "bg-green-500/5", text_color: "text-green-500", icon: "plus" %>
|
||||
<%= render "account_type", type: OtherLiability.new, bg_color: "bg-red-500/5", text_color: "text-red-500", icon: "minus" %>
|
||||
</div>
|
||||
<div class="border-t border-alpha-black-25 p-4 text-gray-500 text-sm flex justify-between">
|
||||
<div class="flex space-x-5">
|
||||
|
|
|
@ -2,75 +2,89 @@
|
|||
|
||||
<%= render "header" %>
|
||||
|
||||
<% if @accounts.empty? %>
|
||||
<%= render "shared/no_account_empty_state" %>
|
||||
<% else %>
|
||||
<div class="bg-white rounded-xl shadow-xs border border-alpha-black-100 flex divide-x divide-gray-200">
|
||||
<div class="w-1/2 p-4 flex items-stretch justify-between">
|
||||
<div class="space-y-2 grow">
|
||||
<%= render partial: "shared/value_heading", locals: {
|
||||
<div class="bg-white rounded-xl shadow-xs border border-alpha-black-100 flex divide-x divide-gray-200">
|
||||
<div class="w-1/2 p-4 flex items-stretch justify-between">
|
||||
<div class="space-y-2 grow">
|
||||
<%= render partial: "shared/value_heading", locals: {
|
||||
label: "Assets",
|
||||
period: @period,
|
||||
value: Current.family.assets,
|
||||
trend: @asset_series.trend
|
||||
} %>
|
||||
</div>
|
||||
<div
|
||||
</div>
|
||||
<div
|
||||
id="assetsChart"
|
||||
class="h-full w-2/5"
|
||||
data-controller="time-series-chart"
|
||||
data-time-series-chart-data-value="<%= @asset_series.to_json %>"
|
||||
data-time-series-chart-use-labels-value="false"></div>
|
||||
</div>
|
||||
<div class="w-1/2 p-4 flex items-stretch justify-between">
|
||||
<div class="space-y-2 grow">
|
||||
<%= render partial: "shared/value_heading", locals: {
|
||||
</div>
|
||||
<div class="w-1/2 p-4 flex items-stretch justify-between">
|
||||
<div class="space-y-2 grow">
|
||||
<%= render partial: "shared/value_heading", locals: {
|
||||
label: "Liabilities",
|
||||
period: @period,
|
||||
size: "md",
|
||||
value: Current.family.liabilities,
|
||||
trend: @liability_series.trend
|
||||
} %>
|
||||
</div>
|
||||
<div
|
||||
</div>
|
||||
<div
|
||||
id="liabilitiesChart"
|
||||
class="h-full w-2/5"
|
||||
data-controller="time-series-chart"
|
||||
data-time-series-chart-data-value="<%= @liability_series.to_json %>"
|
||||
data-time-series-chart-use-labels-value="false"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-4 bg-white rounded-xl shadow-xs border border-alpha-black-25 space-y-4">
|
||||
<div class="flex justify-between items-center mb-5">
|
||||
<h2 class="text-lg font-medium text-gray-900">Assets</h2>
|
||||
<div class="flex items-center gap-2">
|
||||
<%= link_to new_account_path, class: "btn btn--secondary flex items-center gap-1", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-500") %>
|
||||
<p><%= t(".new") %></p>
|
||||
<% end %>
|
||||
<%= form_with url: summary_accounts_path, method: :get, data: { controller: "auto-submit-form" } do |form| %>
|
||||
<%= period_select form: form, selected: @period.name %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-4 bg-white rounded-xl shadow-xs border border-alpha-black-25 space-y-4">
|
||||
<div class="flex justify-between items-center mb-5">
|
||||
<h2 class="text-lg font-medium text-gray-900">Assets</h2>
|
||||
<div class="flex items-center gap-2">
|
||||
<%= link_to new_account_path, class: "flex items-center gap-1 p-2 pr-3 text-gray-900 text-sm font-medium bg-gray-50 rounded-lg hover:bg-gray-100", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-500") %>
|
||||
<p><%= t(".new") %></p>
|
||||
<% end %>
|
||||
<%= form_with url: summary_accounts_path, method: :get, data: { controller: "auto-submit-form" } do |form| %>
|
||||
<%= period_select form: form, selected: @period.name %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if @account_groups[:assets].children.any? %>
|
||||
<%= render partial: "pages/account_percentages_bar", locals: { account_groups: @account_groups[:assets].children } %>
|
||||
<%= render partial: "pages/account_percentages_table", locals: { account_groups: @account_groups[:assets].children } %>
|
||||
</div>
|
||||
<div class="p-4 bg-white rounded-xl shadow-xs border border-alpha-black-25 space-y-4">
|
||||
<div class="flex justify-between items-center mb-5">
|
||||
<h2 class="text-lg font-medium text-gray-900">Liabilities</h2>
|
||||
<div class="flex items-center gap-2">
|
||||
<%= link_to new_account_path, class: "flex items-center gap-1 p-2 pr-3 text-gray-900 text-sm font-medium bg-gray-50 rounded-lg hover:bg-gray-100", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-500") %>
|
||||
<p><%= t(".new") %></p>
|
||||
<% end %>
|
||||
<%= form_with url: summary_accounts_path, method: :get, data: { controller: "auto-submit-form" } do |form| %>
|
||||
<%= period_select form: form, selected: @period.name %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% else %>
|
||||
<div class="py-20 flex flex-col items-center">
|
||||
<%= lucide_icon "blocks", class: "w-6 h-6 shrink-0 text-gray-500" %>
|
||||
<p class="text-gray-900 text-sm font-medium mb-1 mt-4"><%= t(".no_assets") %></p>
|
||||
<p class="text-gray-500 text-sm max-w-xs text-center"><%= t(".no_assets_description") %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="p-4 bg-white rounded-xl shadow-xs border border-alpha-black-25 space-y-4">
|
||||
<div class="flex justify-between items-center mb-5">
|
||||
<h2 class="text-lg font-medium text-gray-900">Liabilities</h2>
|
||||
<div class="flex items-center gap-2">
|
||||
<%= link_to new_account_path, class: "btn btn--secondary flex items-center gap-1", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-500") %>
|
||||
<p><%= t(".new") %></p>
|
||||
<% end %>
|
||||
<%= form_with url: summary_accounts_path, method: :get, data: { controller: "auto-submit-form" } do |form| %>
|
||||
<%= period_select form: form, selected: @period.name %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% if @account_groups[:liabilities].children.any? %>
|
||||
<%= render partial: "pages/account_percentages_bar", locals: { account_groups: @account_groups[:liabilities].children } %>
|
||||
<%= render partial: "pages/account_percentages_table", locals: { account_groups: @account_groups[:liabilities].children } %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<div class="py-20 flex flex-col items-center">
|
||||
<%= lucide_icon "scale", class: "w-6 h-6 shrink-0 text-gray-500" %>
|
||||
<p class="text-gray-900 text-sm font-medium mb-1 mt-4"><%= t(".no_liabilities") %></p>
|
||||
<p class="text-gray-500 text-sm max-w-xs text-center"><%= t(".no_liabilities_description") %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<%# locals: (account_groups:) %>
|
||||
<div class="space-y-4">
|
||||
<div class="flex gap-1">
|
||||
<% account_groups.each do |group| %>
|
||||
<% account_groups.sort_by(&:percent_of_total).reverse.each do |group| %>
|
||||
<div class="h-1.5 rounded-sm w-12 <%= accountable_bg_class(group.name) %>" style="width: <%= group.percent_of_total %>%;"></div>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="flex gap-4">
|
||||
<% account_groups.each do |group| %>
|
||||
<% account_groups.sort_by(&:percent_of_total).reverse.each do |group| %>
|
||||
<div class="flex items-center gap-2 text-sm">
|
||||
<div class="h-2.5 w-2.5 rounded-full <%= accountable_bg_class(group.name) %>"></div>
|
||||
<p class="text-gray-500"><%= to_accountable_title(Accountable.from_type(group.name)) %></p>
|
||||
|
|
|
@ -15,6 +15,6 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="bg-white border border-alpha-black-25 shadow-xs rounded-lg divide-y divide-alpha-black-50">
|
||||
<%= render partial: "pages/account_group_disclosure", collection: account_groups, as: :accountable_group %>
|
||||
<%= render partial: "pages/account_group_disclosure", collection: account_groups.sort_by(&:percent_of_total).reverse, as: :accountable_group %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -107,7 +107,13 @@ en:
|
|||
transactions: Transactions
|
||||
value: Value
|
||||
summary:
|
||||
new: New account
|
||||
new: New
|
||||
no_assets: No assets found
|
||||
no_assets_description: Add an asset either via connection, importing or entering
|
||||
manually.
|
||||
no_liabilities: No liabilities found
|
||||
no_liabilities_description: Add a liability either via connection, importing
|
||||
or entering manually.
|
||||
sync_all:
|
||||
button_text: Sync all
|
||||
success: Successfully queued accounts for syncing.
|
||||
|
|
|
@ -58,11 +58,9 @@ class AccountsTest < ApplicationSystemTestCase
|
|||
assert_account_created("OtherLiability")
|
||||
end
|
||||
|
||||
test "can sync all acounts on accounts page and account summary page" do
|
||||
test "can sync all acounts on accounts page" do
|
||||
visit accounts_url
|
||||
assert_button "Sync all"
|
||||
visit summary_accounts_url
|
||||
assert_button "Sync all"
|
||||
end
|
||||
|
||||
private
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue