1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-21 22:29:38 +02:00

Improve dashboard/account charts and tooltips (#2157)

* Improve net worth hover

* Improve graph tooltip

* Use locales files for some text on net worth and account charts

* Consolidate and simplify trend change between net worth and account charts

* Fix test and self-review stuff

* Clean up some stuff on the holding sidebar
This commit is contained in:
Alex Hatzenbuhler 2025-04-28 13:57:32 -05:00 committed by GitHub
parent e6b69c1f5c
commit 341a800b65
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 37 additions and 45 deletions

View file

@ -322,7 +322,7 @@ export default class extends Controller {
.attr("class", "data-point-circle")
.attr("cx", this._d3XScale(d.date))
.attr("cy", this._d3YScale(this._getDatumValue(d)))
.attr("r", 8)
.attr("r", 10)
.attr("fill", this._trendColor)
.attr("fill-opacity", "0.1")
.attr("pointer-events", "none");
@ -333,7 +333,7 @@ export default class extends Controller {
.attr("class", "data-point-circle")
.attr("cx", this._d3XScale(d.date))
.attr("cy", this._d3YScale(this._getDatumValue(d)))
.attr("r", 3)
.attr("r", 5)
.attr("fill", this._trendColor)
.attr("pointer-events", "none");
@ -364,19 +364,17 @@ export default class extends Controller {
<div style="margin-bottom: 4px; color: var(--color-gray-500);">
${datum.date_formatted}
</div>
<div style="display: flex; align-items: center; gap: 16px;">
<div style="display: flex; align-items: center; gap: 8px;">
<svg width="10" height="10">
<circle
cx="5"
cy="5"
r="4"
stroke="${datum.trend.color}"
fill="transparent"
stroke-width="1"></circle>
</svg>
<div style="display: flex; align-items: center; gap: 16px; margin-bottom: 0px;">
<div style="display: flex; align-items: center; gap: 8px; color: var(--color-black);">
<div style="display: flex; align-items: center; justify-content: center; height: 16px; width: 16px;">
${datum.trend.previous.amount === datum.trend.current.amount ? `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="${datum.trend.color}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-minus-icon lucide-minus"><path d="M5 12h14"/></svg>
` : Number(datum.trend.previous.amount) < Number(datum.trend.current.amount) ? `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="${datum.trend.color}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-arrow-up-right-icon lucide-arrow-up-right"><path d="M7 7h10v10"/><path d="M7 17 17 7"/></svg>
` : `
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="${datum.trend.color}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-arrow-down-right-icon lucide-arrow-down-right"><path d="m7 7 10 10"/><path d="M17 7v10H7"/></svg>
`}
</div>
${this._extractFormattedValue(datum.trend.current)}
</div>

View file

@ -3,16 +3,7 @@
<%= turbo_frame_tag dom_id(@account, :chart_details) do %>
<div class="px-4">
<% if trend.direction.flat? %>
<%= tag.span t(".no_change"), class: "text-secondary" %>
<% 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.comparison_label, class: "text-secondary" %>
<%= render partial: "shared/trend_change", locals: { trend: trend, comparison_label: @period.comparison_label } %>
</div>
<div class="h-64 pb-4">
@ -24,7 +15,7 @@
data-time-series-chart-data-value="<%= series.to_json %>"></div>
<% else %>
<div class="w-full h-full flex items-center justify-center">
<p class="text-secondary text-sm">No data available for the selected period.</p>
<p class="text-secondary text-sm"><%= t(".data_not_available") %></p>
</div>
<% end %>
</div>

View file

@ -15,7 +15,7 @@
<div class="grid grid-cols-12 items-center uppercase text-xs font-medium text-secondary px-4 py-2">
<%= tag.p t(".name"), class: "col-span-4" %>
<%= tag.p t(".weight"), class: "col-span-2 justify-self-end" %>
<%= tag.p t(".cost"), class: "col-span-2 justify-self-end" %>
<%= tag.p t(".average_cost"), class: "col-span-2 justify-self-end" %>
<%= tag.p t(".holdings"), class: "col-span-2 justify-self-end" %>
<%= tag.p t(".return"), class: "col-span-2 justify-self-end" %>
</div>

View file

@ -38,7 +38,7 @@
</div>
<div class="flex items-center justify-between text-sm">
<dt class="text-secondary"><%= t(".trend_label") %></dt>
<dt class="text-secondary"><%= t(".total_return_label") %></dt>
<dd style="color: <%= @holding.trend&.color %>;">
<%= @holding.trend ? render("shared/trend_change", trend: @holding.trend) : t(".unknown") %>
</dd>

View file

@ -3,19 +3,14 @@
<div class="flex justify-between gap-4 px-4">
<div class="space-y-2">
<div class="space-y-2">
<p class="text-sm text-secondary font-medium">Net Worth</p>
<p class="text-sm text-secondary font-medium"><%= t(".title") %></p>
<p class="text-primary -space-x-0.5 text-3xl font-medium">
<%= series.current.format %>
</p>
<% if series.trend.nil? %>
<p class="text-sm text-secondary">Data not available for the selected period</p>
<% elsif series.trend.direction.flat? %>
<p class="text-sm text-secondary">No change vs. prior period</p>
<p class="text-sm text-secondary"><%= t(".data_not_available") %></p>
<% else %>
<div class="flex items-center gap-2">
<%= render partial: "shared/trend_change", locals: { trend: series.trend } %>
<span class="text-sm text-secondary"><%= period.comparison_label %></span>
</div>
<%= render partial: "shared/trend_change", locals: { trend: series.trend, comparison_label: period.comparison_label } %>
<% end %>
</div>
</div>
@ -32,6 +27,6 @@
data-time-series-chart-data-value="<%= series.to_json %>"></div>
<% else %>
<div class="w-full h-full flex items-center justify-center">
<p class="text-secondary text-sm">No data available for the selected period.</p>
<p class="text-secondary text-sm"><%= t(".data_not_available") %></p>
</div>
<% end %>

View file

@ -1,8 +1,8 @@
<%# locals: { trend: } %>
<%# locals: { trend:, comparison_label: nil } %>
<p class="text-sm" style="color: <%= trend.color %>">
<% if trend.direction.flat? %>
<span>No change</span>
<%= t(".no_change") %><%= " #{comparison_label}" if defined?(comparison_label) && comparison_label.present? %>
<% else %>
<span class="font-mono">
<%= trend.value.is_a?(Money) ? format_money(trend.value) : trend.value.round(2) %>
@ -10,5 +10,8 @@
<% unless trend.percent.infinite? %>
<span class="font-mono">(<%= lucide_icon(trend.icon, class: "w-4 h-4 align-text-bottom inline") %><%= trend.percent_formatted %>)</span>
<% end %>
<span class="text-secondary">
<%= " #{comparison_label}" if defined?(comparison_label) && comparison_label.present? %>
</span>
<% end %>
</p>

View file

@ -4,7 +4,7 @@ en:
account:
troubleshoot: Troubleshoot
chart:
no_change: no change
data_not_available: Data not available for the selected period
create:
success: "%{type} account created"
destroy:

View file

@ -9,13 +9,13 @@ en:
per_share: per share
shares: "%{qty} shares"
index:
cost: cost
average_cost: Average cost
holdings: Holdings
name: name
name: Name
new_holding: New transaction
no_holdings: No holdings to show.
return: total return
weight: weight
return: Total return
weight: Weight
missing_price_tooltip:
description: This investment has missing values and we could not calculate
its returns or value.
@ -33,5 +33,5 @@ en:
settings: Settings
ticker_label: Ticker
trade_history_entry: "%{qty} shares of %{security} at %{price}"
trend_label: Trend
total_return_label: Total Return
unknown: Unknown

View file

@ -4,6 +4,9 @@ en:
changelog:
title: What's new
dashboard:
net_worth_chart:
data_not_available: Data not available for the selected period
title: Net Worth
no_account_empty_state:
new_account: New account
no_account_subtitle: Since no accounts have been added, there's no data to

View file

@ -10,3 +10,5 @@ en:
label: Amount
syncing_notice:
syncing: Syncing accounts data...
trend_change:
no_change: "no change"