1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-05 05:25:24 +02:00

Account Activity View + Account Forms (#1406)
Some checks are pending
Publish Docker image / ci (push) Waiting to run
Publish Docker image / Build docker image (push) Blocked by required conditions

* Remove balance mode, sketch out refactor

* Activity view checkpoint

* Entry partials, checkpoint

* Finish txn partial

* Give entries context when editing for different turbo responses

* Calculate change of balance for each entry

* Account tabs consolidation

* Translations, linting, brakeman updates

* Account actions concern

* Finalize forms, get account system tests passing

* Get tests passing

* Lint, rubocop, schema updates

* Improve routing and stream responses

* Fix broken routes

* Add import option for adding accounts

* Fix system test

* Fix test specificity

* Fix sparklines

* Improve account redirects
This commit is contained in:
Zach Gollwitzer 2024-11-04 20:27:31 -05:00 committed by GitHub
parent 12e4f1067d
commit 65db49273c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
216 changed files with 2043 additions and 1620 deletions

View file

@ -1,3 +1,5 @@
<%# locals: (account:, return_to: nil) %>
<%= turbo_frame_tag dom_id(account) do %>
<div class="p-4 flex items-center justify-between gap-3 group/account">
<div class="flex items-center gap-3">
@ -16,7 +18,7 @@
<% end %>
</div>
<%= link_to edit_account_path(account), data: { turbo_frame: :modal }, class: "group-hover/account:flex hidden hover:opacity-80 items-center justify-center" do %>
<%= link_to edit_account_path(account, return_to: return_to), data: { turbo_frame: :modal }, class: "group-hover/account:flex hidden hover:opacity-80 items-center justify-center" do %>
<%= lucide_icon "pencil-line", class: "w-4 h-4 text-gray-500" %>
<% end %>
</div>

View file

@ -1,35 +1,37 @@
<%# locals: (group:) -%>
<% type = Accountable.from_type(group.name) %>
<% if group && group.children.any? %>
<details class="mb-1 text-sm group" data-controller="account-collapse" data-account-collapse-type-value="<%= type %>">
<summary class="flex gap-4 px-3 py-2 items-center w-full rounded-[10px] font-medium hover:bg-gray-100 cursor-pointer">
<%= lucide_icon("chevron-down", class: "hidden group-open:block text-gray-500 w-5 h-5") %>
<%= lucide_icon("chevron-right", class: "group-open:hidden text-gray-500 w-5 h-5") %>
<% group_trend = group.series.trend %>
<details
class="mb-1 text-sm group"
data-controller="account-collapse"
data-account-collapse-type-value="<%= type %>">
<summary class="flex gap-4 px-3 py-2 items-center w-full rounded-[10px] font-medium
hover:bg-gray-100 cursor-pointer">
<%= lucide_icon("chevron-down",
class: "hidden group-open:block text-gray-500 w-5 h-5") %>
<%= lucide_icon("chevron-right",
class: "group-open:hidden text-gray-500 w-5 h-5") %>
<div class="text-left"><%= type.model_name.human %></div>
<div class="ml-auto flex flex-col items-end">
<p class="text-right"><%= format_money group.sum %></p>
<div class="flex items-center gap-1">
<%=
tag.div(
id: "#{group.name}_sparkline",
class: "h-3 w-8 ml-auto",
data: {
controller: "time-series-chart",
"time-series-chart-data-value": group.series.to_json,
"time-series-chart-stroke-width-value": 1,
"time-series-chart-use-labels-value": false,
"time-series-chart-use-tooltip-value": false
}
)
%>
<% styles = trend_styles(group.series.trend) %>
<span class="text-xs <%= styles[:text_class] %>"><%= sprintf("%+.2f", group.series.trend.percent) %>%</span>
<div class="h-3 w-8">
<%= render "shared/sparkline", series: group.series, id: "#{group.name}_sparkline" %>
</div>
<span class="text-xs" style="color: <%= group_trend.color %>"><%= group_trend.value.positive? ? "+" : "" %><%= group_trend.percent.infinite? ? "∞" : number_to_percentage(group_trend.percent, precision: 0) %></span>
</div>
</div>
</summary>
<% group.children.sort_by(&:name).each do |account_value_node| %>
<% account = account_value_node.original %>
<%= link_to account_path(account), class: "flex items-center w-full gap-3 px-3 py-2 mb-1 hover:bg-gray-100 rounded-[10px]" do %>
<% account_trend = account_value_node.series.trend %>
<%= link_to account, class: "flex items-center w-full gap-3 px-3 py-2 mb-1 hover:bg-gray-100 rounded-[10px]" do %>
<%= render "accounts/logo", account: account, size: "sm" %>
<div>
<p class="font-medium"><%= account_value_node.name %></p>
@ -37,31 +39,21 @@
<p class="text-xs text-gray-500"><%= account.subtype&.humanize %></p>
<% end %>
</div>
<div class="flex flex-col ml-auto font-medium text-right">
<div class="flex flex-col items-end font-medium text-right ml-auto">
<p><%= format_money account.balance_money %></p>
<% unless account_value_node.series.trend.direction.flat? %>
<div class="flex items-center gap-1">
<%=
tag.div(
id: dom_id(account, :list_sparkline),
class: "h-3 w-8 ml-auto",
data: {
controller: "time-series-chart",
"time-series-chart-data-value": account_value_node.series.to_json,
"time-series-chart-stroke-width-value": 1,
"time-series-chart-use-labels-value": false,
"time-series-chart-use-tooltip-value": false
}
)
%>
<% styles = trend_styles(account_value_node.series.trend) %>
<span class="text-xs <%= styles[:text_class] %>"><%= sprintf("%+.2f", account_value_node.series.trend.percent) %>%</span>
<div class="flex items-center gap-1">
<div class="h-3 w-8">
<%= render "shared/sparkline", series: account_value_node.series, id: dom_id(account, :list_sparkline) %>
</div>
<% end %>
<span class="text-xs" style="color: <%= account_trend.color %>">
<%= account_trend.value.positive? ? "+" : "" %><%= account_trend.percent.infinite? ? "∞" : number_to_percentage(account_trend.percent, precision: 0) %>
</span>
</div>
</div>
<% end %>
<% end %>
<%= link_to new_account_path(step: "method", type: type.name.demodulize), class: "flex items-center min-h-10 gap-4 px-3 py-2 mb-1 text-gray-500 text-sm font-medium rounded-[10px] hover:bg-gray-100", data: { turbo_frame: "modal" } do %>
<%= link_to new_polymorphic_path(type, step: "method_select"), class: "flex items-center min-h-10 gap-4 px-3 py-2 mb-1 text-gray-500 text-sm font-medium rounded-[10px] hover:bg-gray-100", data: { turbo_frame: "modal" } do %>
<%= lucide_icon("plus", class: "w-5 h-5") %>
<%= t(".new_account", type: type.model_name.human.downcase) %>
<% end %>

View file

@ -1,10 +1,9 @@
<%= link_to new_account_path(
type: type.class.name.demodulize,
institution_id: params[:institution_id]
),
<%# locals: (accountable:) %>
<%= link_to new_polymorphic_path(accountable, institution_id: params[:institution_id], step: "method_select", return_to: params[:return_to]),
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 style="background-color: color-mix(in srgb, <%= accountable.color %> 10%, white);" class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg border border-alpha-black-25">
<%= lucide_icon(accountable.icon, style: "color: #{accountable.color}", class: "w-5 h-5") %>
</span>
<%= type.model_name.human %>
<%= accountable.model_name.human %>
<% end %>

View file

@ -3,7 +3,7 @@
<%= tag.p t(".no_accounts"), class: "text-gray-900 mb-1 font-medium" %>
<%= tag.p t(".empty_message"), class: "text-gray-500 mb-4" %>
<%= link_to new_account_path(step: "method"), 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 %>
<%= 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 %>

View file

@ -1,17 +0,0 @@
<%# locals: (text:, icon:, disabled: false) %>
<% if disabled %>
<span class="flex items-center w-full gap-4 p-2 px-2 text-center border border-transparent rounded-lg cursor-not-allowed focus:outline-none focus:bg-gray-50 focus:border focus:border-gray-200 text-gray-400">
<span class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg bg-alpha-black-50 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.02)]">
<%= lucide_icon(icon, class: "text-gray-500 w-5 h-5") %>
</span>
<%= text %>
</span>
<% else %>
<%= link_to new_account_path(institution_id: params[:institution_id]), class: "flex items-center gap-4 w-full text-center focus:outline-none focus:bg-gray-50 border border-transparent focus:border focus:border-gray-200 px-2 hover:bg-gray-50 rounded-lg p-2" do %>
<span class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg bg-alpha-black-50 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.02)]">
<%= lucide_icon(icon, class: "text-gray-500 w-5 h-5") %>
</span>
<%= text %>
<% end %>
<% end %>

View file

@ -1,28 +1,21 @@
<%# locals: (account:, url:) %>
<%= styled_form_with model: account, url: url, scope: :account, class: "flex flex-col gap-4 justify-between grow", data: { turbo: false } do |f| %>
<%= styled_form_with model: account, url: url, scope: :account, data: { turbo: false }, class: "flex flex-col gap-4 justify-between grow" do |form| %>
<div class="grow space-y-2">
<% unless account.new_record? %>
<% if account.accountable.mode_required? %>
<%= f.select :mode, Account::VALUE_MODES.map { |mode| [mode.titleize, mode] }, { label: t(".mode"), prompt: t(".mode_prompt") }, required: true %>
<% end %>
<% end %>
<%= f.select :accountable_type, Accountable::TYPES.map { |type| [type.titleize, type] }, { label: t(".accountable_type"), prompt: t(".type_prompt") }, required: true, autofocus: true %>
<%= f.text_field :name, placeholder: t(".name_placeholder"), required: "required", label: t(".name_label") %>
<%= form.hidden_field :accountable_type %>
<%= form.hidden_field :return_to, value: params[:return_to] %>
<% if account.new_record? %>
<%= f.hidden_field :institution_id %>
<%= form.hidden_field :institution_id %>
<% else %>
<%= f.collection_select :institution_id, Current.family.institutions.alphabetically, :id, :name, { include_blank: t(".ungrouped"), label: t(".institution") } %>
<%= form.collection_select :institution_id, Current.family.institutions.alphabetically, :id, :name, { include_blank: t(".ungrouped"), label: t(".institution") } %>
<% end %>
<%= f.money_field :balance, label: t(".balance"), required: true, default_currency: Current.family.currency %>
<%= form.text_field :name, placeholder: t(".name_placeholder"), required: "required", label: t(".name_label") %>
<%= form.money_field :balance, label: t(".balance"), required: true, default_currency: Current.family.currency %>
<% if account.accountable %>
<%= render permitted_accountable_partial(account, "form"), f: f %>
<% end %>
<%= yield form %>
</div>
<%= f.submit %>
<%= form.submit %>
<% end %>

View file

@ -1,3 +0,0 @@
<%# locals: (account:) %>
<%= render partial: "accounts/accountables/#{account.accountable_type.underscore}/overview", locals: { account: account } %>

View file

@ -1,7 +0,0 @@
<div class="flex items-center gap-3">
<%= render "accounts/logo", account: account %>
<div>
<h2 class="font-medium text-xl"><%= account.name %></h2>
</div>
</div>

View file

@ -1,13 +0,0 @@
<%# locals: (account:, selected_tab:) %>
<% if account.mode.nil? %>
<%= render "accounts/accountables/value_onboarding", account: account %>
<% else %>
<div class="min-h-[800px]">
<% if account.mode == "transactions" %>
<%= render "accounts/accountables/transactions", account: account %>
<% else %>
<%= render "accounts/accountables/valuations", account: account %>
<% end %>
</div>
<% end %>

View file

@ -1,5 +0,0 @@
<%# locals: (account:) %>
<%= turbo_frame_tag dom_id(account, :transactions), src: account_transactions_path(account) do %>
<%= render "account/entries/loading" %>
<% end %>

View file

@ -1,5 +0,0 @@
<%# locals: (account:) %>
<%= turbo_frame_tag dom_id(account, :valuations), src: account_valuations_path(account) do %>
<%= render "account/entries/loading" %>
<% end %>

View file

@ -1,16 +0,0 @@
<%# locals: (account:) %>
<div data-test-id="value-onboarding" class="py-12 flex flex-col justify-center items-center bg-white rounded-lg border border-alpha-black-25 shadow-xs">
<h3 class="font-medium text-lg mb-2">How would you like to track value for this account?</h3>
<p class="text-sm text-gray-500 mb-8">We will use this to determine what data to show for this account.</p>
<div class="flex items-center gap-4">
<%= button_to account_path(account, { account: { mode: "balance" } }), method: :put, class: "btn btn--outline", data: { controller: "tooltip", turbo: false } do %>
<%= render partial: "shared/text_tooltip", locals: { tooltip_text: "Choose this if you only need to track the historical value of this account over time and do not plan on importing any transactions." } %>
<span>Balance only</span>
<% end %>
<%= button_to account_path(account, { account: { mode: "transactions" } }), method: :put, class: "btn btn--primary", data: { controller: "tooltip", turbo: false } do %>
<%= render partial: "shared/text_tooltip", locals: { tooltip_text: "Choose this if you plan on importing transactions into this account for budgeting and other analytics." } %>
<span>Transactions</span>
<% end %>
</div>
</div>

View file

@ -1,21 +0,0 @@
<div>
<hr class="my-4">
<div class="space-y-2">
<%= f.fields_for :accountable do |credit_card_form| %>
<div class="flex items-center gap-2">
<%= credit_card_form.number_field :available_credit, label: t(".available_credit"), placeholder: t(".available_credit_placeholder"), min: 0 %>
</div>
<div class="flex items-center gap-2">
<%= credit_card_form.number_field :minimum_payment, label: t(".minimum_payment"), placeholder: t(".minimum_payment_placeholder"), min: 0 %>
<%= credit_card_form.number_field :apr, label: t(".apr"), placeholder: t(".apr_placeholder"), min: 0, step: 0.01 %>
</div>
<div class="flex items-center gap-2">
<%= credit_card_form.date_field :expiration_date, label: t(".expiration_date") %>
<%= credit_card_form.number_field :annual_fee, label: t(".annual_fee"), placeholder: t(".annual_fee_placeholder"), min: 0 %>
</div>
<% end %>
</div>
</div>

View file

@ -1 +0,0 @@
<%= render "accounts/accountables/default_header", account: account %>

View file

@ -1,31 +0,0 @@
<%# locals: (account:) %>
<div class="grid grid-cols-3 gap-2">
<%= summary_card title: t(".amount_owed") do %>
<%= format_money(account.balance_money) %>
<% end %>
<%= summary_card title: t(".available_credit") do %>
<%= format_money(account.credit_card.available_credit_money) || t(".unknown") %>
<% end %>
<%= summary_card title: t(".minimum_payment") do %>
<%= format_money(account.credit_card.minimum_payment_money || Money.new(0, account.currency)) %>
<% end %>
<%= summary_card title: t(".apr") do %>
<%= account.credit_card.apr ? number_to_percentage(account.credit_card.apr, precision: 2) : t(".unknown") %>
<% end %>
<%= summary_card title: t(".expiration_date") do %>
<%= account.credit_card.expiration_date ? l(account.credit_card.expiration_date, format: :long) : t(".unknown") %>
<% end %>
<%= summary_card title: t(".annual_fee") do %>
<%= format_money(account.credit_card.annual_fee_money || Money.new(0, account.currency)) %>
<% end %>
</div>
<div class="flex justify-center py-8">
<%= link_to "Edit account details", edit_account_path(account), class: "btn btn--ghost", data: { turbo_frame: :modal } %>
</div>

View file

@ -1,26 +0,0 @@
<%# locals: (account:, selected_tab:) %>
<% if account.mode.nil? %>
<%= render "accounts/accountables/value_onboarding", account: account %>
<% else %>
<div class="flex gap-2 text-sm text-gray-900 font-medium mb-4">
<%= render "accounts/accountables/tab", account: account, key: "overview", is_selected: selected_tab.in?([nil, "overview"]) %>
<% if account.mode == "transactions" %>
<%= render "accounts/accountables/tab", account: account, key: "transactions", is_selected: selected_tab == "transactions" %>
<% else %>
<%= render "accounts/accountables/tab", account: account, key: "value", is_selected: selected_tab == "value" %>
<% end %>
</div>
<div class="min-h-[800px]">
<% case selected_tab %>
<% when nil, "overview" %>
<%= render "accounts/accountables/credit_card/overview", account: account %>
<% when "transactions" %>
<%= render "accounts/accountables/transactions", account: account %>
<% when "value" %>
<%= render "accounts/accountables/valuations", account: account %>
<% end %>
</div>
<% end %>

View file

@ -1 +0,0 @@
<%= render "accounts/accountables/default_header", account: account %>

View file

@ -1 +0,0 @@
<%= render "accounts/accountables/default_tabs", account: account, selected_tab: selected_tab %>

View file

@ -1 +0,0 @@
<%= f.select :subtype, [["Checking", "checking"], ["Savings", "savings"]], { label: true, prompt: t(".prompt"), include_blank: t(".none") } %>

View file

@ -1 +0,0 @@
<%= render "accounts/accountables/default_header", account: account %>

View file

@ -1 +0,0 @@
<%= render "accounts/accountables/default_tabs", account: account, selected_tab: selected_tab %>

View file

@ -1 +0,0 @@
<%= f.select :subtype, Investment::SUBTYPES, { label: true, prompt: t(".prompt"), include_blank: t(".none") } %>

View file

@ -1 +0,0 @@
<%= render "accounts/accountables/default_header", account: account %>

View file

@ -1,34 +0,0 @@
<%# locals: (account:, selected_tab:) %>
<% if account.mode.nil? %>
<%= render "accounts/accountables/value_onboarding", account: account %>
<% else %>
<div class="flex gap-2 text-sm text-gray-900 font-medium mb-4">
<% if account.mode == "transactions" %>
<%= render "accounts/accountables/tab", account: account, key: "holdings", is_selected: selected_tab.in?([nil, "holdings"]) %>
<%= render "accounts/accountables/tab", account: account, key: "cash", is_selected: selected_tab == "cash" %>
<%= render "accounts/accountables/tab", account: account, key: "transactions", is_selected: selected_tab == "transactions" %>
<% end %>
</div>
<div class="min-h-[800px]">
<% if account.mode == "transactions" %>
<% case selected_tab %>
<% when nil, "holdings" %>
<%= turbo_frame_tag dom_id(account, :holdings), src: account_holdings_path(account) do %>
<%= render "account/entries/loading" %>
<% end %>
<% when "cash" %>
<%= turbo_frame_tag dom_id(account, :cash), src: account_cashes_path(account) do %>
<%= render "account/entries/loading" %>
<% end %>
<% when "transactions" %>
<%= turbo_frame_tag dom_id(account, :trades), src: account_trades_path(account) do %>
<%= render "account/entries/loading" %>
<% end %>
<% end %>
<% else %>
<%= render "accounts/accountables/valuations", account: account %>
<% end %>
</div>
<% end %>

View file

@ -1,26 +0,0 @@
<%# locals: (account:) -%>
<div data-controller="tooltip" data-tooltip-placement-value="right" data-tooltip-offset-value=10 data-tooltip-cross-axis-value=50>
<%= lucide_icon("info", class: "w-4 h-4 shrink-0 text-gray-500") %>
<div role="tooltip" data-tooltip-target="tooltip" class="tooltip bg-gray-700 text-sm p-2 rounded w-64">
<div class="text-white">
<%= t(".total_value_tooltip") %>
</div>
<div class="flex pt-3">
<div class="text-gray-300">
<%= t(".holdings") %>
</div>
<div class="text-white ml-auto">
<%= tag.p format_money(account.investment.holdings_value, precision: 0) %>
</div>
</div>
<div class="flex">
<div class="text-gray-300">
<%= t(".cash") %>
</div>
<div class="text-white ml-auto">
<%= tag.p format_money(account.balance_money, precision: 0) %>
</div>
</div>
</div>
</div>

View file

@ -1,16 +0,0 @@
<div>
<hr class="my-4">
<div class="space-y-2">
<%= f.fields_for :accountable do |loan_form| %>
<div class="flex items-center gap-2">
<%= loan_form.number_field :interest_rate, label: t(".interest_rate"), placeholder: t(".interest_rate_placeholder"), min: 0, step: 0.01 %>
<%= loan_form.select :rate_type, options_for_select([["Fixed", "fixed"], ["Variable", "variable"], ["Adjustable", "adjustable"]]), { label: t(".rate_type") } %>
</div>
<div class="flex items-center gap-2">
<%= loan_form.number_field :term_months, label: t(".term_months"), placeholder: t(".term_months_placeholder") %>
</div>
<% end %>
</div>
</div>

View file

@ -1 +0,0 @@
<%= render "accounts/accountables/default_header", account: account %>

View file

@ -1,49 +0,0 @@
<%# locals: (account:) %>
<div class="grid grid-cols-3 gap-2">
<%= summary_card title: t(".original_principal") do %>
<%= format_money account.original_balance %>
<% end %>
<%= summary_card title: t(".remaining_principal") do %>
<%= format_money account.balance_money %>
<% end %>
<%= summary_card title: t(".interest_rate") do %>
<% if account.loan.interest_rate.present? %>
<%= number_to_percentage(account.loan.interest_rate, precision: 2) %>
<% else %>
<%= t(".unknown") %>
<% end %>
<% end %>
<%= summary_card title: t(".monthly_payment") do %>
<% if account.loan.rate_type.present? && account.loan.rate_type != 'fixed' %>
<%= t(".not_applicable") %>
<% elsif account.loan.rate_type == 'fixed' && account.loan.monthly_payment.present? %>
<%= format_money(account.loan.monthly_payment) %>
<% else %>
<%= t(".unknown") %>
<% end %>
<% end %>
<%= summary_card title: t(".term") do %>
<% if account.loan.term_months.present? %>
<% if account.loan.term_months < 12 %>
<%= pluralize(account.loan.term_months, "month") %>
<% else %>
<%= pluralize(account.loan.term_months / 12, "year") %>
<% end %>
<% else %>
<%= t(".unknown") %>
<% end %>
<% end %>
<%= summary_card title: t(".type") do %>
<%= account.loan.rate_type&.titleize || t(".unknown") %>
<% end %>
</div>
<div class="flex justify-center py-8">
<%= link_to "Edit account details", edit_account_path(account), class: "btn btn--ghost", data: { turbo_frame: :modal } %>
</div>

View file

@ -1,25 +0,0 @@
<%# locals: (account:, selected_tab:) %>
<% if account.mode.nil? %>
<%= render "accounts/accountables/value_onboarding", account: account %>
<% else %>
<div class="flex gap-2 text-sm text-gray-900 font-medium mb-4">
<%= render "accounts/accountables/tab", account: account, key: "overview", is_selected: selected_tab.in?([nil, "overview"]) %>
<% if account.mode == "transactions" %>
<%= render "accounts/accountables/tab", account: account, key: "transactions", is_selected: selected_tab == "transactions" %>
<% else %>
<%= render "accounts/accountables/tab", account: account, key: "value", is_selected: selected_tab == "value" %>
<% end %>
</div>
<div class="min-h-[800px]">
<% case selected_tab %>
<% when nil, "overview" %>
<%= render "accounts/accountables/loan/overview", account: account %>
<% when "transactions" %>
<%= render "accounts/accountables/transactions", account: account %>
<% when "value" %>
<%= render "accounts/accountables/valuations", account: account %>
<% end %>
</div>
<% end %>

View file

@ -1 +0,0 @@
<%= render "accounts/accountables/default_header", account: account %>

View file

@ -1 +0,0 @@
<%= render "accounts/accountables/valuations", account: account %>

View file

@ -1 +0,0 @@
<%= render "accounts/accountables/default_header", account: account %>

View file

@ -1 +0,0 @@
<%= render "accounts/accountables/valuations", account: account %>

View file

@ -1,36 +0,0 @@
<%# locals: (f:) %>
<div>
<hr class="my-4">
<h3 class="my-4 font-medium"><%= t(".additional_info") %> (<%= t(".optional") %>)</h3>
<div class="space-y-2">
<%= f.fields_for :accountable do |af| %>
<div class="flex gap-2">
<%= af.number_field :year_built, label: t(".year_built"), placeholder: 2005, min: 1700, max: Time.current.year %>
<%= af.number_field :area_value, label: t(".area_value"), placeholder: 2000, min: 1 %>
<%= af.select :area_unit,
[["Square feet", "sqft"], ["Square meters", "sqm"]],
{ label: t(".area_unit") } %>
</div>
<%= af.fields_for :address do |address_form| %>
<div class="flex gap-2">
<%= address_form.text_field :line1, label: t(".line1"), placeholder: "123 Main St" %>
<%= address_form.text_field :line2, label: t(".line2"), placeholder: "Apt 1" %>
</div>
<div class="flex gap-2">
<%= address_form.text_field :locality, label: t(".city"), placeholder: "Sacramento" %>
<%= address_form.text_field :region, label: t(".state"), placeholder: "CA" %>
</div>
<div class="flex gap-2">
<%= address_form.text_field :postal_code, label: t(".postal_code"), placeholder: "95814" %>
<%= address_form.text_field :country, label: t(".country"), placeholder: "USA" %>
</div>
<% end %>
<% end %>
</div>
</div>

View file

@ -1,11 +0,0 @@
<div class="flex items-center gap-3">
<%= render "accounts/logo", account: account %>
<div>
<h2 class="font-medium text-xl"><%= account.name %></h2>
<% if account.property.address&.line1.present? %>
<p class="text-gray-500"><%= account.property.address %></p>
<% end %>
</div>
</div>

View file

@ -1,33 +0,0 @@
<%# locals: (account:) %>
<div class="grid grid-cols-3 gap-2">
<%= summary_card title: t(".market_value") do %>
<%= format_money(account.balance_money) %>
<% end %>
<%= summary_card title: t(".purchase_price") do %>
<%= account.property.purchase_price ? format_money(account.property.purchase_price) : t(".unknown") %>
<% end %>
<%= summary_card title: t(".trend") do %>
<div class="flex items-center gap-1" style="color: <%= account.property.trend.color %>">
<p class="text-xl font-medium">
<%= account.property.trend.value %>
</p>
<p>(<%= account.property.trend.percent %>%)</p>
</div>
<% end %>
<%= summary_card title: t(".year_built") do %>
<%= account.property.year_built || t(".unknown") %>
<% end %>
<%= summary_card title: t(".living_area") do %>
<%= account.property.area || t(".unknown") %>
<% end %>
</div>
<div class="flex justify-center py-8">
<%= link_to "Edit account details", edit_account_path(account), class: "btn btn--ghost", data: { turbo_frame: :modal } %>
</div>

View file

@ -1,15 +0,0 @@
<%# locals: (account:, selected_tab:) %>
<div class="flex gap-2 text-sm text-gray-900 font-medium mb-4">
<%= render "accounts/accountables/tab", account: account, key: "overview", is_selected: selected_tab.in?([nil, "overview"]) %>
<%= render "accounts/accountables/tab", account: account, key: "value", is_selected: selected_tab == "value" %>
</div>
<div class="min-h-[800px]">
<% case selected_tab %>
<% when nil, "overview" %>
<%= render "accounts/accountables/property/overview", account: account %>
<% when "value" %>
<%= render "accounts/accountables/valuations", account: account %>
<% end %>
</div>

View file

@ -1,23 +0,0 @@
<%# locals: (f:) %>
<div>
<hr class="my-4">
<div class="space-y-2">
<%= f.fields_for :accountable do |vehicle_form| %>
<div class="flex items-center gap-2">
<%= vehicle_form.text_field :make, label: t(".make"), placeholder: t(".make_placeholder") %>
<%= vehicle_form.text_field :model, label: t(".model"), placeholder: t(".model_placeholder") %>
</div>
<div class="flex items-center gap-2">
<%= vehicle_form.number_field :year, label: t(".year"), placeholder: t(".year_placeholder"), min: 1900, max: Time.current.year %>
<%= vehicle_form.number_field :mileage_value, label: t(".mileage"), placeholder: t(".mileage_placeholder"), min: 0 %>
<%= vehicle_form.select :mileage_unit,
[["Miles", "mi"], ["Kilometers", "km"]],
{ label: t(".mileage_unit") } %>
</div>
<% end %>
</div>
</div>

View file

@ -1 +0,0 @@
<%= render "accounts/accountables/default_header", account: account %>

View file

@ -1,37 +0,0 @@
<%# locals: (account:) %>
<div class="grid grid-cols-3 gap-2">
<%= summary_card title: t(".make_model") do %>
<%= [account.vehicle.make, account.vehicle.model].compact.join(" ").presence || t(".unknown") %>
<% end %>
<%= summary_card title: t(".year") do %>
<%= account.vehicle.year || t(".unknown") %>
<% end %>
<%= summary_card title: t(".mileage") do %>
<%= account.vehicle.mileage || t(".unknown") %>
<% end %>
<%= summary_card title: t(".purchase_price") do %>
<%= format_money account.vehicle.purchase_price %>
<% end %>
<%= summary_card title: t(".current_price") do %>
<%= format_money account.balance_money %>
<% end %>
<%= summary_card title: t(".trend") do %>
<div class="flex items-center gap-1" style="color: <%= account.vehicle.trend.color %>">
<p class="text-xl font-medium">
<%= account.vehicle.trend.value %>
</p>
<p>(<%= account.vehicle.trend.percent %>%)</p>
</div>
<% end %>
</div>
<div class="flex justify-center py-8">
<%= link_to "Edit account details", edit_account_path(account), class: "btn btn--ghost", data: { turbo_frame: :modal } %>
</div>

View file

@ -1,15 +0,0 @@
<%# locals: (account:, selected_tab:) %>
<div class="flex gap-2 text-sm text-gray-900 font-medium mb-4">
<%= render "accounts/accountables/tab", account: account, key: "overview", is_selected: selected_tab.in?([nil, "overview"]) %>
<%= render "accounts/accountables/tab", account: account, key: "value", is_selected: selected_tab == "value" %>
</div>
<div class="min-h-[800px]">
<% case selected_tab %>
<% when nil, "overview" %>
<%= render "accounts/accountables/vehicle/overview", account: account %>
<% when "value" %>
<%= render "accounts/accountables/valuations", account: account %>
<% end %>
</div>

View file

@ -1,3 +0,0 @@
<%= modal_form_wrapper title: t(".edit", account: @account.name) do %>
<%= render "form", account: @account, url: edit_account_form_url(@account) %>
<% end %>

View file

@ -20,7 +20,7 @@
<%= render "sync_all_button" %>
<%= link_to new_account_path(step: "method"),
<%= link_to new_account_path(return_to: accounts_path),
data: { turbo_frame: "modal" },
class: "btn btn--primary flex items-center gap-1" do %>
<%= lucide_icon("plus", class: "w-5 h-5") %>
@ -35,11 +35,11 @@
<% else %>
<div class="space-y-2">
<% @institutions.each do |institution| %>
<%= render "institution_accounts", institution: %>
<%= render "accounts/index/institution_accounts", institution: %>
<% end %>
<% if @accounts.any? %>
<%= render "institutionless_accounts", accounts: @accounts %>
<%= render "accounts/index/institutionless_accounts", accounts: @accounts %>
<% end %>
</div>
<% end %>

View file

@ -40,7 +40,7 @@
<%= contextual_menu do %>
<div class="w-48 p-1 text-sm leading-6 text-gray-900 bg-white shadow-lg shrink rounded-xl ring-1 ring-gray-900/5">
<%= link_to new_account_path(institution_id: institution.id),
<%= link_to new_account_path(institution_id: institution.id, return_to: accounts_path),
class: "block w-full py-2 px-3 space-x-2 text-gray-900 hover:bg-gray-50 flex items-center rounded-lg",
data: { turbo_frame: :modal } do %>
<%= lucide_icon "plus", class: "w-5 h-5 text-gray-500" %>
@ -81,7 +81,7 @@
<% else %>
<div class="p-4 flex flex-col gap-3 items-center justify-center">
<p class="text-gray-500 text-sm">There are no accounts in this financial institution</p>
<%= link_to new_account_path(institution_id: institution.id), class: "w-fit flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-1.5 pr-2", data: { turbo_frame: "modal" } do %>
<%= link_to new_account_path(institution_id: institution.id, return_to: accounts_path), class: "w-fit flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-1.5 pr-2", data: { turbo_frame: "modal" } do %>
<%= lucide_icon("plus", class: "w-4 h-4") %>
<span><%= t(".new_account") %></span>
<% end %>

View file

@ -1,53 +1,24 @@
<h1 class="text-3xl font-semibold font-display"><%= t(".title") %></h1>
<%= modal do %>
<div class="flex flex-col w-screen max-w-xl" data-controller="list-keyboard-navigation">
<% if params[:step] == 'method' %>
<div class="border-b border-alpha-black-25 p-4 text-gray-400 flex items-center space-x-3">
<span>How would you like to add it?</span>
</div>
<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 layout: "accounts/new/container", locals: { title: t(".title") } do %>
<div class="text-sm">
<%= render "account_type", accountable: Depository.new %>
<%= render "account_type", accountable: Investment.new %>
<%= render "account_type", accountable: Crypto.new %>
<%= render "account_type", accountable: Property.new %>
<%= render "account_type", accountable: Vehicle.new %>
<%= render "account_type", accountable: CreditCard.new %>
<%= render "account_type", accountable: Loan.new %>
<%= render "account_type", accountable: OtherAsset.new %>
<%= render "account_type", accountable: OtherLiability.new %>
<%= render "entry_method", text: t(".manual_entry"), icon: "keyboard" %>
<%= link_to new_import_path(import: { type: "AccountImport" }), class: "flex items-center gap-4 w-full text-center focus:outline-none focus:bg-gray-50 border border-transparent focus:border focus:border-gray-200 px-2 hover:bg-gray-50 rounded-lg p-2" do %>
<span class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg bg-alpha-black-50 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.02)]">
<%= lucide_icon("sheet", class: "text-gray-500 w-5 h-5") %>
</span>
<%= t(".csv_entry") %>
<% end %>
<%= render "entry_method", text: t(".connected_entry"), icon: "link-2", disabled: true %>
</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">
<div class="flex items-center space-x-2">
<span>Select</span>
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-5 h-5 shrink-0 grow-0 items-center justify-center"><%= lucide_icon("corner-down-left", class: "inline w-3 h-3") %></kbd>
</div>
<div class="flex items-center space-x-2">
<span>Navigate</span>
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-5 h-5 shrink-0 grow-0 items-center justify-center"><%= lucide_icon("arrow-up", class: "inline w-3 h-3") %></kbd>
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-5 h-5 shrink-0 grow-0 items-center justify-center"><%= lucide_icon("arrow-down", class: "inline w-3 h-3") %></kbd>
</div>
</div>
<div class="flex items-center space-x-2">
<button data-action="modal#close">Close</button>
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-8 h-5 shrink-0 grow-0 items-center justify-center text-xs">ESC</kbd>
</div>
</div>
<% else %>
<div class="border-b border-alpha-black-25 p-4 text-gray-800 flex items-center space-x-3">
<%= link_to new_account_path(step: "method"), class: "flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg bg-alpha-black-50 focus:outline-gray-300 focus:outline" do %>
<%= lucide_icon("arrow-left", class: "text-gray-500 w-5 h-5") %>
<% end %>
<span>Add account</span>
</div>
<div class="p-4">
<%= render "form", account: @account, url: new_account_form_url(@account) %>
</div>
<% unless params[:return_to].present? %>
<%= button_to imports_path(import: { type: "AccountImport" }),
data: { turbo_frame: :_top },
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 style="background-color: color-mix(in srgb, #F79009 10%, white);" class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg border border-alpha-black-25">
<%= lucide_icon("download", style: "color: #F79009", class: "w-5 h-5") %>
</span>
<%= t("accounts.new.import_accounts") %>
<% end %>
<% end %>
</div>
<% end %>

View file

@ -0,0 +1,40 @@
<%# locals: (title:, back_path: nil) %>
<%= modal do %>
<div class="flex flex-col w-screen max-w-xl" data-controller="list-keyboard-navigation">
<div class="border-b border-alpha-black-25 p-4 text-gray-800 flex items-center space-x-3">
<% if back_path %>
<%= link_to back_path, class: "flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg bg-alpha-black-50 focus:outline-gray-300 focus:outline" do %>
<%= lucide_icon("arrow-left", class: "text-gray-500 w-5 h-5") %>
<% end %>
<% end %>
<span class="text-gray-400"><%= title %></span>
</div>
<div class="p-2">
<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>
<%= yield %>
</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">
<div class="flex items-center space-x-2">
<span>Select</span>
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-5 h-5 shrink-0 grow-0 items-center justify-center"><%= lucide_icon("corner-down-left", class: "inline w-3 h-3") %></kbd>
</div>
<div class="flex items-center space-x-2">
<span>Navigate</span>
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-5 h-5 shrink-0 grow-0 items-center justify-center"><%= lucide_icon("arrow-up", class: "inline w-3 h-3") %></kbd>
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-5 h-5 shrink-0 grow-0 items-center justify-center"><%= lucide_icon("arrow-down", class: "inline w-3 h-3") %></kbd>
</div>
</div>
<div class="flex items-center space-x-2">
<button data-action="modal#close">Close</button>
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-8 h-5 shrink-0 grow-0 items-center justify-center text-xs">ESC</kbd>
</div>
</div>
</div>
<% end %>

View file

@ -0,0 +1,19 @@
<%# locals: (path:) %>
<%= render layout: "accounts/new/container", locals: { title: t(".title"), back_path: new_account_path } do %>
<div class="text-sm">
<%= link_to path, class: "flex items-center gap-4 w-full text-center focus:outline-none focus:bg-gray-50 border border-transparent focus:border focus:border-gray-200 px-2 hover:bg-gray-50 rounded-lg p-2" do %>
<span class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg bg-alpha-black-50 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.02)]">
<%= lucide_icon("keyboard", class: "text-gray-500 w-5 h-5") %>
</span>
<%= t("accounts.new.method_selector.manual_entry") %>
<% end %>
<span class="flex items-center w-full gap-4 p-2 px-2 text-center border border-transparent rounded-lg cursor-not-allowed focus:outline-none focus:bg-gray-50 focus:border focus:border-gray-200 text-gray-400">
<span class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg bg-alpha-black-50 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.02)]">
<%= lucide_icon("link-2", class: "text-gray-500 w-5 h-5") %>
</span>
<%= t("accounts.new.method_selector.connected_entry") %>
</span>
</div>
<% end %>

View file

@ -1,65 +0,0 @@
<%= turbo_stream_from @account %>
<% series = @account.series(period: @period) %>
<% trend = series.trend %>
<%= tag.div id: dom_id(@account), class: "space-y-4" do %>
<header class="flex items-center gap-4">
<%= render permitted_accountable_partial(@account, "header"), account: @account %>
<div class="flex items-center gap-3 ml-auto">
<%= button_to sync_account_path(@account), method: :post, class: "flex items-center gap-2", title: "Sync Account" do %>
<%= lucide_icon "refresh-cw", class: "w-4 h-4 text-gray-500 hover:text-gray-400" %>
<% end %>
<%= render "menu", account: @account %>
</div>
</header>
<% if @account.highest_priority_issue %>
<%= render partial: "issues/issue", locals: { issue: @account.highest_priority_issue } %>
<% end %>
<div class="bg-white shadow-xs rounded-xl border border-alpha-black-25 rounded-lg">
<div class="p-4 flex justify-between">
<div class="space-y-2">
<div class="flex items-center gap-1">
<div>
<% if @account.asset? %>
<%= tag.p t(".total_value"), class: "text-sm font-medium text-gray-500" %>
<% else %>
<%= tag.p t(".total_owed"), class: "text-sm font-medium text-gray-500" %>
<% end %>
</div>
<%= render permitted_accountable_partial(@account, "tooltip"), account: @account if @account.investment? %>
</div>
<%= tag.p format_money(@account.value), class: "text-gray-900 text-3xl font-medium" %>
<div>
<% if trend.direction.flat? %>
<%= tag.span t(".no_change"), class: "text-gray-500" %>
<% else %>
<%= tag.span format_money(trend.value), style: "color: #{trend.color}" %>
<%= tag.span "(#{trend.percent}%)", style: "color: #{trend.color}" %>
<% end %>
<%= tag.span period_label(@period), class: "text-gray-500" %>
</div>
</div>
<%= form_with url: account_path(@account), method: :get, data: { controller: "auto-submit-form" } do |form| %>
<%= period_select form: form, selected: @period.name %>
<% end %>
</div>
<div class="h-96 flex items-center justify-center text-2xl font-bold">
<%= render "shared/line_chart", series: @account.series(period: @period) %>
</div>
</div>
<div class="min-h-[800px]">
<%= render permitted_accountable_partial(@account, "tabs"), account: @account, selected_tab: params[:tab] %>
</div>
<% end %>

View file

@ -0,0 +1,5 @@
<%# locals: (account:) %>
<%= turbo_frame_tag dom_id(account, :entries), src: account_entries_path(account) do %>
<%= render "account/entries/loading" %>
<% end %>

View file

@ -0,0 +1,40 @@
<%# locals: (account:, title: nil, tooltip: nil) %>
<% period = Period.from_param(params[:period]) %>
<% series = account.series(period: period) %>
<% trend = series.trend %>
<% default_value_title = account.asset? ? t(".balance") : t(".owed") %>
<div class="bg-white shadow-xs rounded-xl border border-alpha-black-25 rounded-lg">
<div class="p-4 flex justify-between">
<div class="space-y-2">
<div class="flex items-center gap-1">
<%= tag.p title || default_value_title, class: "text-sm font-medium text-gray-500" %>
<%= tooltip %>
</div>
<%= tag.p format_money(account.value), class: "text-gray-900 text-3xl font-medium" %>
<div>
<% if trend.direction.flat? %>
<%= tag.span t(".no_change"), class: "text-gray-500" %>
<% else %>
<%= tag.span "#{trend.value.positive? ? "+" : ""}#{format_money(trend.value)}", style: "color: #{trend.color}" %>
<% unless trend.percent.infinite? %>
<%= tag.span "(#{trend.percent}%)", style: "color: #{trend.color}" %>
<% end %>
<% end %>
<%= tag.span period_label(period), class: "text-gray-500" %>
</div>
</div>
<%= form_with url: request.path, method: :get, data: { controller: "auto-submit-form" } do |form| %>
<%= period_select form: form, selected: period.name %>
<% end %>
</div>
<div class="h-64 flex items-center justify-center text-2xl font-bold">
<%= render "shared/line_chart", series: series %>
</div>
</div>

View file

@ -0,0 +1,34 @@
<%# locals: (account:, title: nil, subtitle: nil) %>
<header class="space-y-4">
<div class="flex items-center gap-4">
<% content = yield %>
<% if content.present? %>
<%= content %>
<% else %>
<div class="flex items-center gap-3">
<%= render "accounts/logo", account: account %>
<div>
<h2 class="font-medium text-xl"><%= title || account.name %></h2>
<% if subtitle.present? %>
<p class="text-sm text-gray-500"><%= subtitle %></p>
<% end %>
</div>
</div>
<% end %>
<div class="flex items-center gap-3 ml-auto">
<%= button_to sync_account_path(account), method: :post, class: "flex items-center gap-2", title: "Sync Account" do %>
<%= lucide_icon "refresh-cw", class: "w-4 h-4 text-gray-500 hover:text-gray-400" %>
<% end %>
<%= render "accounts/show/menu", account: account %>
</div>
</div>
<% if account.highest_priority_issue %>
<%= render partial: "issues/issue", locals: { issue: account.highest_priority_issue } %>
<% end %>
</header>

View file

@ -0,0 +1,3 @@
<div class="p-5">
<p class="text-gray-500 animate-pulse">Loading account...</p>
</div>

View file

@ -11,6 +11,7 @@
<% end %>
<%= link_to new_import_path,
data: { turbo_frame: :modal },
class: "block w-full py-2 px-3 space-x-2 text-gray-900 hover:bg-gray-50 flex items-center rounded-lg" do %>
<%= lucide_icon "download", class: "w-5 h-5 text-gray-500" %>
@ -21,6 +22,7 @@
method: :delete,
class: "block w-full py-2 px-3 space-x-2 text-red-600 hover:bg-red-50 flex items-center rounded-lg",
data: {
turbo_frame: :_top,
turbo_confirm: {
title: t(".confirm_title"),
body: t(".confirm_body_html"),

View file

@ -0,0 +1,11 @@
<%# locals: (account:, tabs:) %>
<% selected_tab = tabs.find { |tab| tab[:key] == params[:tab] } || tabs.first %>
<div class="flex gap-2 text-sm text-gray-900 font-medium mb-4">
<% tabs.each do |tab| %>
<%= render "accounts/show/tab", account: account, key: tab[:key], is_selected: selected_tab[:key] == tab[:key] %>
<% end %>
</div>
<%= selected_tab[:contents] %>

View file

@ -0,0 +1,27 @@
<%# locals: (account:, header: nil, chart: nil, tabs: nil) %>
<%= turbo_stream_from account %>
<%= turbo_frame_tag dom_id(account) do %>
<%= tag.div class: "space-y-4" do %>
<% if header.present? %>
<%= header %>
<% else %>
<%= render "accounts/show/header", account: account %>
<% end %>
<% if chart.present? %>
<%= chart %>
<% else %>
<%= render "accounts/show/chart", account: account %>
<% end %>
<div class="min-h-[800px]">
<% if tabs.present? %>
<%= tabs %>
<% else %>
<%= render "accounts/show/activity", account: account %>
<% end %>
</div>
<% end %>
<% end %>

View file

@ -1,13 +1,15 @@
<% period = Period.from_param(params[:period]) %>
<div class="space-y-4">
<%= render "header" %>
<%= render "accounts/summary/header" %>
<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,
period: period,
value: Current.family.assets,
trend: @asset_series.trend
} %>
@ -23,7 +25,7 @@
<div class="space-y-2 grow">
<%= render partial: "shared/value_heading", locals: {
label: "Liabilities",
period: @period,
period: period,
size: "md",
value: Current.family.liabilities,
trend: @liability_series.trend
@ -41,12 +43,12 @@
<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(step: "method"), class: "btn btn--secondary flex items-center gap-1", data: { turbo_frame: "modal" } do %>
<%= 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 %>
<%= period_select form: form, selected: period.name %>
<% end %>
</div>
</div>
@ -66,12 +68,12 @@
<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(step: "method"), class: "btn btn--secondary flex items-center gap-1", data: { turbo_frame: "modal" } do %>
<%= 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 %>
<%= period_select form: form, selected: period.name %>
<% end %>
</div>
</div>

View file

@ -13,7 +13,7 @@
<% end %>
<%= link_to new_account_path(step: "method"), 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 %>
<%= 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>
<% end %>