diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index 131de698..3c800760 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -14,6 +14,9 @@ class AccountsController < ApplicationController @account_groups = Current.family.accounts.by_group(period: @period, currency: Current.family.currency) end + def list + end + def new @account = Account.new( balance: nil, diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 56be0a49..19e60b2d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -27,8 +27,8 @@ module ApplicationHelper render partial: "shared/modal", locals: { content: content } end - def account_groups - assets, liabilities = Current.family.accounts.by_group(currency: Current.family.currency, period: Period.last_30_days).values_at(:assets, :liabilities) + def account_groups(period: nil) + assets, liabilities = Current.family.accounts.by_group(currency: Current.family.currency, period: period || Period.last_30_days).values_at(:assets, :liabilities) [ assets.children, liabilities.children ].flatten end diff --git a/app/javascript/controllers/time_series_chart_controller.js b/app/javascript/controllers/time_series_chart_controller.js index 1c518306..85dd3e79 100644 --- a/app/javascript/controllers/time_series_chart_controller.js +++ b/app/javascript/controllers/time_series_chart_controller.js @@ -5,6 +5,7 @@ import * as d3 from "d3" export default class extends Controller { static values = { data: Object, + strokeWidth: { type: Number, default: 2 }, useLabels: { type: Boolean, default: true }, useTooltip: { type: Boolean, default: true }, usePercentSign: Boolean @@ -128,7 +129,7 @@ export default class extends Controller { .attr("d", this.#d3Line) .attr("stroke-linejoin", "round") .attr("stroke-linecap", "round") - .attr("stroke-width", 2) + .attr("stroke-width", this.strokeWidthValue) } #installTrendlineSplit() { diff --git a/app/models/time_series/trend.rb b/app/models/time_series/trend.rb index 70f9077e..f62090fb 100644 --- a/app/models/time_series/trend.rb +++ b/app/models/time_series/trend.rb @@ -39,8 +39,8 @@ class TimeSeries::Trend elsif previous.zero? Float::INFINITY else - change = (current_amount - previous_amount).abs - base = previous_amount.abs.to_f + change = (current_amount - previous_amount) + base = previous_amount.to_f (change / base * 100).round(1).to_f end diff --git a/app/views/accounts/_account_list.html.erb b/app/views/accounts/_account_list.html.erb index 23f71a8c..e70849ff 100644 --- a/app/views/accounts/_account_list.html.erb +++ b/app/views/accounts/_account_list.html.erb @@ -8,20 +8,58 @@
<%= type.model_name.human %>

<%= format_money group.sum %>

+
+ <%= + 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) %> + <%= sprintf("%+.2f", group.series.trend.percent) %>% +
<% group.children.each do |account_value_node| %> - <%= link_to account_path(account_value_node.original), class: "flex items-center w-full gap-3 px-2 py-3 mb-1 hover:bg-gray-100 rounded-[10px]" do %> + <% 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 %> + <%= image_tag account_logo_url(account), class: "w-6 h-6" %>

<%= account_value_node.name %>

- <% if account_value_node.original.subtype %> -

<%= account_value_node.original.subtype&.humanize %>

+ <% if account.subtype %> +

<%= account.subtype&.humanize %>

<% end %>
-

<%= format_money account_value_node.original.balance_money %>

+
+

<%= format_money account.balance_money %>

+
+ <%= + 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) %> + <%= sprintf("%+.2f", account_value_node.series.trend.percent) %>% +
+
<% end %> <% end %> - <%= link_to new_account_path(step: "method", type: type.name.demodulize), class: "flex items-center gap-4 px-2 py-3 mb-1 text-gray-500 text-sm font-medium rounded-[10px] hover:bg-gray-100", data: { turbo_frame: "modal" } do %> + <%= 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 %> <%= lucide_icon("plus", class: "w-5 h-5") %>

New <%= type.model_name.human.downcase %>

<% end %> diff --git a/app/views/accounts/list.html.erb b/app/views/accounts/list.html.erb new file mode 100644 index 00000000..fe2a7d33 --- /dev/null +++ b/app/views/accounts/list.html.erb @@ -0,0 +1,5 @@ + + <% account_groups(period: @period).each do |group| %> + <%= render "accounts/account_list", group: group %> + <% end %> + diff --git a/app/views/layouts/_sidebar.html.erb b/app/views/layouts/_sidebar.html.erb index 9f92537a..43b0c342 100644 --- a/app/views/layouts/_sidebar.html.erb +++ b/app/views/layouts/_sidebar.html.erb @@ -72,19 +72,23 @@
-
- <%= link_to accounts_path, class: "text-xs uppercase text-gray-500 font-bold tracking-wide" do %> - <%= t(".accounts") %> - <% end %> +
+
+ <%= link_to accounts_path, class: "text-xs uppercase text-gray-500 font-bold tracking-wide" do %> + <%= t(".portfolio") %> + <% end %> + + <%= form_with url: list_accounts_path, method: :get, class: "flex items-center gap-4", data: { controller: "auto-submit-form", turbo_frame: "account-list" } do %> + <%= render partial: "shared/period_select", locals: { button_class: "flex items-center gap-1 w-full cursor-pointer font-bold tracking-wide" } %> + <% end %> +
<%= link_to new_account_path, class: "block hover:bg-gray-100 p-2 text-sm font-semibold text-gray-900 flex items-center rounded", title: t(".new_account"), data: { turbo_frame: "modal" } do %> <%= lucide_icon("plus", class: "w-5 h-5 text-gray-500") %> <% end %>
- <%= link_to new_account_path, class: "flex items-center gap-4 px-2 py-3 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") %>

- <% end %> - <% account_groups.each do |group| %> - <%= render "accounts/account_list", group: group %> - <% end %> + + <% account_groups.each do |group| %> + <%= render "accounts/account_list", group: group %> + <% end %> +
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 30f5c32c..e279c9e9 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -26,7 +26,7 @@
<%= safe_join(flash.map { |type, message| notification(message, type: type) }) %>
-
+
<% if content_for?(:sidebar) %> <%= yield :sidebar %> <% else %> diff --git a/app/views/shared/_period_select.html.erb b/app/views/shared/_period_select.html.erb index b5b38f88..8b935a72 100644 --- a/app/views/shared/_period_select.html.erb +++ b/app/views/shared/_period_select.html.erb @@ -1,12 +1,18 @@ -<%# locals: (value: 'last_30_days') -%> +<%# locals: (value: 'last_30_days', button_class: '') -%> <% options = [["7D", "last_7_days"], ["1M", "last_30_days"], ["1Y", "last_365_days"], ["All", "all"]] %>
- + <% end %> -