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

Add the ability to "rollup" values in a time series (#554)

* Clean up time series models

* Add value group rollup class for summarizing hierarchical data

* Integrate new classes

* Update UI to use new patterns

* Update D3 charts to expect new data format

* Clean up account model

* More cleanup

* Money improvements

* Use new money fields

* Remove invalid fixture data to avoid orphaned accountables

* Update time series to work better with collections

* Fix tests and UI bugs
This commit is contained in:
Zach Gollwitzer 2024-03-19 09:10:40 -04:00 committed by GitHub
parent 0a8518506c
commit f904d9d062
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 687 additions and 391 deletions

View file

@ -1,48 +1,47 @@
<%# locals: (account_group:) %>
<% accountable_type, account_details = account_group%>
<% text_class = accountable_text_class(accountable_type) %>
<% text_class = accountable_text_class(account_group.name) %>
<details class="open:bg-gray-25 group">
<summary class="flex p-4 items-center w-full rounded-lg font-medium hover:bg-gray-50 text-gray-500 text-sm font-medium cursor-pointer">
<%= lucide_icon("chevron-down", class: "hidden group-open:block w-5 h-5") %>
<%= lucide_icon("chevron-right", class: "group-open:hidden w-5 h-5") %>
<div class="ml-4 h-2.5 w-2.5 rounded-full <%= accountable_bg_class(accountable_type) %>"></div>
<p class="text-gray-900 ml-2"><%= to_accountable_title(Accountable.from_type(accountable_type)) %></p>
<div class="ml-4 h-2.5 w-2.5 rounded-full <%= accountable_bg_class(account_group.name) %>"></div>
<p class="text-gray-900 ml-2"><%= to_accountable_title(Accountable.from_type(account_group.name)) %></p>
<span class="mx-1">&middot;</span>
<div ><%= account_details[:accounts].size %></div>
<div ><%= account_group.children.count %></div>
<div class="ml-auto text-right flex items-center gap-10 text-sm font-medium text-gray-900">
<div class="flex items-center justify-end gap-2 w-24">
<%= render partial: "shared/progress_circle", locals: { progress: account_details[:allocation], text_class: text_class } %>
<p><%= account_details[:allocation] %>%</p>
<%= render partial: "shared/progress_circle", locals: { progress: account_group.percent_of_total, text_class: text_class } %>
<p><%= account_group.percent_of_total.round(1) %>%</p>
</div>
<div class="w-24">
<p><%= format_money account_details[:end_balance] %></p>
<p><%= format_money account_group.sum %></p>
</div>
<div class="w-40">
<%= render partial: "shared/trend_change", locals: { trend: account_details[:trend] } %>
<%= render partial: "shared/trend_change", locals: { trend: account_group.series.trend } %>
</div>
</div>
</summary>
<div class="px-4 py-3 space-y-4">
<% account_details[:accounts].map do |account| %>
<% account_group.children.map do |account| %>
<div class="flex items-center justify-between text-sm font-medium text-gray-900">
<div class="flex items-center gap-4">
<div class="flex items-center justify-center w-8 h-8 rounded-full <%= text_class %> <%= accountable_bg_transparent_class(accountable_type) %>">
<%= account[:name][0].upcase %>
<div class="flex items-center justify-center w-8 h-8 rounded-full <%= text_class %> <%= accountable_bg_transparent_class(account_group.name) %>">
<%= account.name[0].upcase %>
</div>
<div>
<p><%= account[:name] %></p>
<p><%= account.name %></p>
</div>
</div>
<div class="flex gap-10 items-center text-right">
<div class="flex items-center justify-end gap-2 w-24">
<%= render partial: "shared/progress_circle", locals: { progress: account[:allocation], text_class: text_class } %>
<p><%= account[:allocation] %>%</p>
<%= render partial: "shared/progress_circle", locals: { progress: account.percent_of_total, text_class: text_class } %>
<p><%= account.percent_of_total %>%</p>
</div>
<div class="w-24">
<p><%= format_money account[:end_balance] %></p>
<p><%= format_money account.sum %></p>
</div>
<div class="w-40">
<%= render partial: "shared/trend_change", locals: { trend: account[:trend] } %>
<%= render partial: "shared/trend_change", locals: { trend: account.series.trend } %>
</div>
</div>
</div>

View file

@ -1,16 +1,16 @@
<%# locals: (account_groups:) %>
<div class="space-y-4">
<div class="flex gap-1">
<% account_groups.each do |type, value| %>
<div class="h-1.5 rounded-sm w-12 <%= accountable_bg_class(type) %>" style="width: <%= value[:allocation] %>%;"></div>
<% account_groups.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 |type, value| %>
<% account_groups.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(type) %>"></div>
<p class="text-gray-500"><%= to_accountable_title(Accountable.from_type(type)) %></p>
<p class="text-black"><%= value[:allocation] %>%</p>
<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>
<p class="text-black"><%= group.percent_of_total.round(1) %>%</p>
</div>
<% end %>
</div>

View file

@ -34,7 +34,7 @@
data-controller="trendline"
id="assetsTrendline"
class="h-full w-2/5"
data-trendline-series-value="<%= @asset_series.serialize_for_d3_chart %>"
data-trendline-series-value="<%= @asset_series.to_json %>"
data-trendline-classification-value="asset"
></div>
</div>
@ -52,7 +52,7 @@
data-controller="trendline"
id="liabilitiesTrendline"
class="h-full w-2/5"
data-trendline-series-value="<%= @liability_series.serialize_for_d3_chart %>"
data-trendline-series-value="<%= @liability_series.to_json %>"
data-trendline-classification-value="liability"
></div>
</div>
@ -75,12 +75,12 @@
</div>
<div>
<div data-tabs-target="tab" id="asset-summary-tab" class="space-y-6">
<%= render partial: "account_percentages_bar", locals: { account_groups: @account_groups[:asset][:groups] } %>
<%= render partial: "account_percentages_table", locals: { account_groups: @account_groups[:asset][:groups] } %>
<%= render partial: "account_percentages_bar", locals: { account_groups: @account_groups[:assets].children } %>
<%= render partial: "account_percentages_table", locals: { account_groups: @account_groups[:assets].children } %>
</div>
<div data-tabs-target="tab" id="liability-summary-tab" class="space-y-6 hidden">
<%= render partial: "account_percentages_bar", locals: { account_groups: @account_groups[:liability][:groups] } %>
<%= render partial: "account_percentages_table", locals: { account_groups: @account_groups[:liability][:groups] } %>
<%= render partial: "account_percentages_bar", locals: { account_groups: @account_groups[:liabilities].children } %>
<%= render partial: "account_percentages_table", locals: { account_groups: @account_groups[:liabilities].children } %>
</div>
</div>
</div>