mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-07-19 13:19:39 +02:00
Dashboard empty view (#707)
* Added i18n for the Dashboard page. * Add a check for blank. Empty returned an error since @accounts was nil. * Remove subtitle when accounts are empty.. * Increased the padding-right value for the buttons. The sapce occupied by the icon made the button elements unbalanced. * Add refactor as suggested by Zach (https://github.com/maybe-finance/maybe/pull/707#discussion_r1588506443) * Extract empty state into a partial. * Render new partial if no accounts exist. * Moved translation text to shared directory. * Fix padding-right on New account button. * Lint fix * i18n tasks * Get tests passing with :test queue adapter --------- Co-authored-by: Zach Gollwitzer <zach.gollwitzer@gmail.com>
This commit is contained in:
parent
75cdddc6ca
commit
9563ac6334
9 changed files with 101 additions and 71 deletions
|
@ -11,7 +11,8 @@ class AccountsController < ApplicationController
|
|||
@net_worth_series = snapshot[:net_worth_series]
|
||||
@asset_series = snapshot[:asset_series]
|
||||
@liability_series = snapshot[:liability_series]
|
||||
@account_groups = Current.family.accounts.by_group(period: @period, currency: Current.family.currency)
|
||||
@accounts = Current.family.accounts
|
||||
@account_groups = @accounts.by_group(period: @period, currency: Current.family.currency)
|
||||
end
|
||||
|
||||
def list
|
||||
|
|
|
@ -17,7 +17,8 @@ class PagesController < ApplicationController
|
|||
@top_earners = snapshot_account_transactions[:top_earners]
|
||||
@top_savers = snapshot_account_transactions[:top_savers]
|
||||
|
||||
@account_groups = Current.family.accounts.by_group(period: @period, currency: Current.family.currency)
|
||||
@accounts = Current.family.accounts
|
||||
@account_groups = @accounts.by_group(period: @period, currency: Current.family.currency)
|
||||
@transactions = Current.family.transactions.limit(5).order(date: :desc)
|
||||
|
||||
# TODO: Placeholders for trendlines
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h1 class="text-xl font-medium text-gray-900">Accounts</h1>
|
||||
<%= link_to new_account_path, class: "flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2", data: { turbo_frame: "modal" } do %>
|
||||
<%= link_to new_account_path, class: "flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2 pr-3", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<span><%= t(".new_account") %></span>
|
||||
<% end %>
|
||||
|
@ -14,7 +14,7 @@
|
|||
<div class="text-center flex flex-col items-center max-w-[300px]">
|
||||
<p class="text-gray-900 mb-1 font-medium">No accounts yet</p>
|
||||
<p class="text-gray-500 mb-4">Add an account either via connection, importing or entering manually.</p>
|
||||
<%= link_to new_account_path, class: "w-fit flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2", data: { turbo_frame: "modal" } do %>
|
||||
<%= link_to new_account_path, class: "w-fit flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2 pr-3", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<span><%= t(".new_account") %></span>
|
||||
<% end %>
|
||||
|
|
|
@ -1,76 +1,81 @@
|
|||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h1 class="text-xl font-medium text-gray-900">Accounts</h1>
|
||||
<%= link_to new_account_path, class: "flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2", data: { turbo_frame: "modal" } do %>
|
||||
<%= link_to new_account_path, class: "flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2 pr-3", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<span><%= t(".new") %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
<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
|
||||
} %>
|
||||
|
||||
<% 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: {
|
||||
label: "Assets",
|
||||
period: @period,
|
||||
value: Current.family.assets,
|
||||
trend: @asset_series.trend
|
||||
} %>
|
||||
</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
|
||||
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: {
|
||||
label: "Liabilities",
|
||||
period: @period,
|
||||
size: "md",
|
||||
value: Current.family.liabilities,
|
||||
trend: @liability_series.trend
|
||||
} %>
|
||||
</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: "flex items-center gap-1 p-2 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, class: "flex items-center gap-4", data: { controller: "auto-submit-form" } do %>
|
||||
<%= render partial: "shared/period_select", locals: { value: @period.name } %>
|
||||
<% end %>
|
||||
<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
|
||||
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>
|
||||
<%= 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 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, class: "flex items-center gap-4", data: { controller: "auto-submit-form" } do %>
|
||||
<%= render partial: "shared/period_select", locals: { value: @period.name } %>
|
||||
<% end %>
|
||||
<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, class: "flex items-center gap-4", data: { controller: "auto-submit-form" } do %>
|
||||
<%= render partial: "shared/period_select", locals: { value: @period.name } %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<%= 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>
|
||||
<%= 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>
|
||||
<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, class: "flex items-center gap-4", data: { controller: "auto-submit-form" } do %>
|
||||
<%= render partial: "shared/period_select", locals: { value: @period.name } %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<%= 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 %>
|
||||
</div>
|
||||
|
|
|
@ -3,13 +3,18 @@
|
|||
<div>
|
||||
<h1 class="sr-only">Dashboard</h1>
|
||||
<p class="text-xl font-medium text-gray-900 mb-1"><%= t(".greeting", name: Current.user.first_name ) %></p>
|
||||
<p class="text-gray-500 text-sm"><%= t(".subtitle") %></p>
|
||||
<% if !@accounts.blank? %>
|
||||
<p class="text-gray-500 text-sm"><%= t(".subtitle") %></p>
|
||||
<% end %>
|
||||
</div>
|
||||
<%= link_to new_account_path, class: "flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2", data: { turbo_frame: "modal" } do %>
|
||||
<%= link_to new_account_path, class: "flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2 pr-3", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<span><%= t(".new") %></span>
|
||||
<% end %>
|
||||
</header>
|
||||
<% if @accounts.empty? %>
|
||||
<%= render "shared/no_account_empty_state" %>
|
||||
<% else %>
|
||||
<section class="flex gap-4">
|
||||
<div class="bg-white border border-alpha-black-25 shadow-xs rounded-xl w-3/4 min-h-48 flex flex-col">
|
||||
<div class="flex justify-between p-4">
|
||||
|
@ -177,4 +182,5 @@
|
|||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
10
app/views/shared/_no_account_empty_state.html.erb
Normal file
10
app/views/shared/_no_account_empty_state.html.erb
Normal file
|
@ -0,0 +1,10 @@
|
|||
<div class="flex justify-center items-center h-[800px] text-sm">
|
||||
<div class="text-center flex flex-col items-center max-w-[300px]">
|
||||
<p class="text-gray-900 mb-1 font-medium"><%= t(".no_account_title") %></p>
|
||||
<p class="text-gray-500 mb-4"><%= t(".no_account_subtitle") %></p>
|
||||
<%= link_to new_account_path, class: "w-fit flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2 pr-3", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<span><%= t(".new_account") %></span>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
|
@ -4,7 +4,7 @@
|
|||
<div class="space-y-4">
|
||||
<div class="flex items-center justify-between">
|
||||
<h1 class="text-xl font-medium text-gray-900"><%= t(".title") %></h1>
|
||||
<%= link_to new_transaction_merchant_path, class: "flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2", data: { turbo_frame: "modal" } do %>
|
||||
<%= link_to new_transaction_merchant_path, class: "flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2 pr-3", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<span><%= t(".new_short") %></span>
|
||||
<% end %>
|
||||
|
@ -14,7 +14,7 @@
|
|||
<div class="flex justify-center items-center py-20">
|
||||
<div class="text-center flex flex-col items-center max-w-[300px]">
|
||||
<p class="text-gray-900 mb-1 font-medium text-sm"><%= t(".empty") %></p>
|
||||
<%= link_to new_transaction_merchant_path, class: "w-fit flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2", data: { turbo_frame: "modal" } do %>
|
||||
<%= link_to new_transaction_merchant_path, class: "w-fit flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2 pr-3", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<span><%= t(".new_long") %></span>
|
||||
<% end %>
|
||||
|
|
|
@ -52,6 +52,8 @@ Rails.application.configure do
|
|||
# Tell Active Support which deprecation messages to disallow.
|
||||
config.active_support.disallowed_deprecation_warnings = []
|
||||
|
||||
config.active_job.queue_adapter = :test
|
||||
|
||||
# Raises error for missing translations.
|
||||
# config.i18n.raise_on_missing_translations = true
|
||||
|
||||
|
|
|
@ -6,6 +6,11 @@ en:
|
|||
body_html: "<p>You will not be able to undo this decision</p>"
|
||||
cancel: Cancel
|
||||
title: Are you sure?
|
||||
no_account_empty_state:
|
||||
new_account: New account
|
||||
no_account_subtitle: Since no accounts have been added, there's no data to display.
|
||||
Add your first accounts to start viewing dashboard data.
|
||||
no_account_title: No accounts yet
|
||||
notification:
|
||||
dismiss: Dismiss
|
||||
upgrade_notification:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue