mirror of
https://github.com/we-promise/sure.git
synced 2026-04-19 20:14:08 +00:00
Add privacy mode with blur toggle for financial data
- Stimulus controller on global layout (persists across all pages) - CSS blur effect on .privacy-sensitive elements (8px active, 4px on hover) - localStorage persistence survives page navigations - Toggle button on dashboard with aria-pressed for accessibility - Applied to 28+ views: accounts, budgets, transactions, reports, etc. Fixes: UTF-8 encoding, global controller mount, aria-pressed attribute
This commit is contained in:
@@ -13,6 +13,7 @@
|
|||||||
@import "./google-sign-in.css";
|
@import "./google-sign-in.css";
|
||||||
@import "./date-picker-dark-mode.css";
|
@import "./date-picker-dark-mode.css";
|
||||||
@import "./print-report.css";
|
@import "./print-report.css";
|
||||||
|
@import "./privacy-mode.css";
|
||||||
|
|
||||||
@layer components {
|
@layer components {
|
||||||
.pcr-app{
|
.pcr-app{
|
||||||
|
|||||||
14
app/assets/tailwind/privacy-mode.css
Normal file
14
app/assets/tailwind/privacy-mode.css
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/* Privacy Mode - blurs financial numbers when activated */
|
||||||
|
html.privacy-mode .privacy-sensitive {
|
||||||
|
filter: blur(8px);
|
||||||
|
user-select: none;
|
||||||
|
transition: filter 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
html.privacy-mode .privacy-sensitive:hover {
|
||||||
|
filter: blur(4px);
|
||||||
|
}
|
||||||
|
|
||||||
|
html:not(.privacy-mode) .privacy-sensitive {
|
||||||
|
transition: filter 0.2s ease;
|
||||||
|
}
|
||||||
32
app/javascript/controllers/privacy_mode_controller.js
Normal file
32
app/javascript/controllers/privacy_mode_controller.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { Controller } from "@hotwired/stimulus"
|
||||||
|
|
||||||
|
// Privacy Mode Controller
|
||||||
|
// Toggles visibility of financial numbers across the page.
|
||||||
|
// Elements with class "privacy-sensitive" will be blurred when active.
|
||||||
|
// State persists in localStorage so it survives page navigations.
|
||||||
|
export default class extends Controller {
|
||||||
|
static targets = ["toggle"]
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
this.active = localStorage.getItem("privacyMode") === "true"
|
||||||
|
this._apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
toggle() {
|
||||||
|
this.active = !this.active
|
||||||
|
localStorage.setItem("privacyMode", this.active.toString())
|
||||||
|
this._apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
_apply() {
|
||||||
|
if (this.active) {
|
||||||
|
document.documentElement.classList.add("privacy-mode")
|
||||||
|
} else {
|
||||||
|
document.documentElement.classList.remove("privacy-mode")
|
||||||
|
}
|
||||||
|
|
||||||
|
this.toggleTargets.forEach((el) => {
|
||||||
|
el.setAttribute("aria-pressed", this.active.toString())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
<% elsif account.syncing? %>
|
<% elsif account.syncing? %>
|
||||||
<div class="w-16 h-6 bg-loader rounded-full animate-pulse"></div>
|
<div class="w-16 h-6 bg-loader rounded-full animate-pulse"></div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<p class="text-sm font-medium <%= account.active? ? "text-primary" : "text-subdued" %>">
|
<p class="text-sm font-medium privacy-sensitive <%= account.active? ? "text-primary" : "text-subdued" %>">
|
||||||
<%= format_money account.balance_money %>
|
<%= format_money account.balance_money %>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ml-auto text-right grow">
|
<div class="ml-auto text-right grow">
|
||||||
<%= tag.p format_money(account_group.total_money), class: "text-sm font-medium text-primary" %>
|
<%= tag.p format_money(account_group.total_money), class: "text-sm font-medium text-primary privacy-sensitive" %>
|
||||||
<%= turbo_frame_tag "#{account_group.key}_sparkline", src: accountable_sparkline_path(account_group.key), loading: "lazy", data: { controller: "turbo-frame-timeout", turbo_frame_timeout_timeout_value: 10000 } do %>
|
<%= turbo_frame_tag "#{account_group.key}_sparkline", src: accountable_sparkline_path(account_group.key), loading: "lazy", data: { controller: "turbo-frame-timeout", turbo_frame_timeout_timeout_value: 10000 } do %>
|
||||||
<div class="flex items-center w-8 h-4 ml-auto">
|
<div class="flex items-center w-8 h-4 ml-auto">
|
||||||
<div class="w-6 h-px bg-loader"></div>
|
<div class="w-6 h-px bg-loader"></div>
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ml-auto text-right grow h-10">
|
<div class="ml-auto text-right grow h-10">
|
||||||
<%= tag.p format_money(account.balance_money), class: "text-sm font-medium text-primary whitespace-nowrap" %>
|
<%= tag.p format_money(account.balance_money), class: "text-sm font-medium text-primary whitespace-nowrap privacy-sensitive" %>
|
||||||
<%= turbo_frame_tag dom_id(account, :sparkline), src: sparkline_account_path(account), loading: "lazy", data: { controller: "turbo-frame-timeout", turbo_frame_timeout_timeout_value: 10000 } do %>
|
<%= turbo_frame_tag dom_id(account, :sparkline), src: sparkline_account_path(account), loading: "lazy", data: { controller: "turbo-frame-timeout", turbo_frame_timeout_timeout_value: 10000 } do %>
|
||||||
<div class="flex items-center w-8 h-4 ml-auto">
|
<div class="flex items-center w-8 h-4 ml-auto">
|
||||||
<div class="w-6 h-px bg-loader"></div>
|
<div class="w-6 h-px bg-loader"></div>
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<p class="ml-auto text-sm space-x-1">
|
<p class="ml-auto text-sm space-x-1">
|
||||||
<span class="<%= budget.available_to_allocate.negative? ? "text-red-500" : "text-primary" %>"><%= format_money(budget.allocated_spending_money) %></span>
|
<span class="privacy-sensitive <%= budget.available_to_allocate.negative? ? "text-red-500" : "text-primary" %>"><%= format_money(budget.allocated_spending_money) %></span>
|
||||||
<span class="text-secondary"> / </span>
|
<span class="text-secondary"> / </span>
|
||||||
<span class="text-secondary"><%= format_money(budget.budgeted_spending_money) %></span>
|
<span class="text-secondary privacy-sensitive"><%= format_money(budget.budgeted_spending_money) %></span>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -34,10 +34,10 @@
|
|||||||
<div class="text-sm">
|
<div class="text-sm">
|
||||||
<% if budget.available_to_allocate.negative? %>
|
<% if budget.available_to_allocate.negative? %>
|
||||||
<p class="text-secondary">
|
<p class="text-secondary">
|
||||||
Budget exceeded by <span class="text-red-500"><%= format_money(budget.available_to_allocate_money.abs) %></span>
|
Budget exceeded by <span class="text-red-500 privacy-sensitive"><%= format_money(budget.available_to_allocate_money.abs) %></span>
|
||||||
</p>
|
</p>
|
||||||
<% else %>
|
<% else %>
|
||||||
<span class="text-primary"><%= format_money(budget.available_to_allocate_money) %></span>
|
<span class="text-primary privacy-sensitive"><%= format_money(budget.available_to_allocate_money) %></span>
|
||||||
<span class="text-secondary">left to allocate</span>
|
<span class="text-secondary">left to allocate</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -57,13 +57,13 @@
|
|||||||
<div class="flex flex-wrap items-center gap-x-4 gap-y-2 text-sm">
|
<div class="flex flex-wrap items-center gap-x-4 gap-y-2 text-sm">
|
||||||
<div class="whitespace-nowrap w-full sm:w-auto">
|
<div class="whitespace-nowrap w-full sm:w-auto">
|
||||||
<span class="text-sm text-secondary"><%= t("reports.budget_performance.spent") %>:</span>
|
<span class="text-sm text-secondary"><%= t("reports.budget_performance.spent") %>:</span>
|
||||||
<span class="font-medium text-primary">
|
<span class="font-medium text-primary privacy-sensitive">
|
||||||
<%= format_money(budget_category.actual_spending_money) %>
|
<%= format_money(budget_category.actual_spending_money) %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="whitespace-nowrap w-full sm:w-auto inline-flex items-center gap-1">
|
<div class="whitespace-nowrap w-full sm:w-auto inline-flex items-center gap-1">
|
||||||
<span class="text-sm text-secondary"><%= t("reports.budget_performance.budgeted") %>:</span>
|
<span class="text-sm text-secondary"><%= t("reports.budget_performance.budgeted") %>:</span>
|
||||||
<span class="font-medium text-primary">
|
<span class="font-medium text-primary privacy-sensitive">
|
||||||
<%= format_money(budget_category.budgeted_spending_money) %>
|
<%= format_money(budget_category.budgeted_spending_money) %>
|
||||||
</span>
|
</span>
|
||||||
<% if budget_category.inherits_parent_budget? %>
|
<% if budget_category.inherits_parent_budget? %>
|
||||||
@@ -73,12 +73,12 @@
|
|||||||
<div class="whitespace-nowrap w-full sm:w-auto lg:ml-auto">
|
<div class="whitespace-nowrap w-full sm:w-auto lg:ml-auto">
|
||||||
<% if budget_category.available_to_spend >= 0 %>
|
<% if budget_category.available_to_spend >= 0 %>
|
||||||
<span class="text-sm text-secondary"><%= t("reports.budget_performance.remaining") %>:</span>
|
<span class="text-sm text-secondary"><%= t("reports.budget_performance.remaining") %>:</span>
|
||||||
<span class="font-medium <%= (budget_category.near_limit? ? "text-yellow-500" : "text-green-500") %>">
|
<span class="font-medium <%= (budget_category.near_limit? ? "text-yellow-500" : "text-green-500") %> privacy-sensitive">
|
||||||
<%= format_money(budget_category.available_to_spend_money) %>
|
<%= format_money(budget_category.available_to_spend_money) %>
|
||||||
</span>
|
</span>
|
||||||
<% else %>
|
<% else %>
|
||||||
<span class="text-sm text-secondary"><%= t("reports.budget_performance.over_by") %>:</span>
|
<span class="text-sm text-secondary"><%= t("reports.budget_performance.over_by") %>:</span>
|
||||||
<span class="font-medium text-red-500">
|
<span class="font-medium text-red-500 privacy-sensitive">
|
||||||
<%= format_money(budget_category.available_to_spend_money.abs) %>
|
<%= format_money(budget_category.available_to_spend_money.abs) %>
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -116,13 +116,13 @@
|
|||||||
|
|
||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<p class="text-sm font-medium text-primary truncate"><%= budget_category.category.name %></p>
|
<p class="text-sm font-medium text-primary truncate"><%= budget_category.category.name %></p>
|
||||||
<p class="text-sm text-secondary font-medium">
|
<p class="text-sm text-secondary font-medium privacy-sensitive">
|
||||||
<%= budget_category.median_monthly_expense_money.format %> avg
|
<%= budget_category.median_monthly_expense_money.format %> avg
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ml-auto text-right flex-shrink-0">
|
<div class="ml-auto text-right flex-shrink-0">
|
||||||
<p class="text-sm font-medium text-primary whitespace-nowrap"><%= format_money(budget_category.actual_spending_money) %></p>
|
<p class="text-sm font-medium text-primary whitespace-nowrap privacy-sensitive"><%= format_money(budget_category.actual_spending_money) %></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -8,11 +8,11 @@
|
|||||||
|
|
||||||
<% if @budget_category.budget.initialized? %>
|
<% if @budget_category.budget.initialized? %>
|
||||||
<p class="text-sm text-secondary">
|
<p class="text-sm text-secondary">
|
||||||
<span class="text-primary">
|
<span class="text-primary privacy-sensitive">
|
||||||
<%= format_money(@budget_category.actual_spending_money) %>
|
<%= format_money(@budget_category.actual_spending_money) %>
|
||||||
</span>
|
</span>
|
||||||
<span>/</span>
|
<span>/</span>
|
||||||
<span><%= format_money(@budget_category.budgeted_spending_money) %></span>
|
<span class="privacy-sensitive"><%= format_money(@budget_category.budgeted_spending_money) %></span>
|
||||||
</p>
|
</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
<dt class="text-secondary">
|
<dt class="text-secondary">
|
||||||
<%= @budget_category.budget.start_date.strftime("%b %Y") %> spending
|
<%= @budget_category.budget.start_date.strftime("%b %Y") %> spending
|
||||||
</dt>
|
</dt>
|
||||||
<dd class="text-primary font-medium">
|
<dd class="text-primary font-medium privacy-sensitive">
|
||||||
<%= format_money @budget_category.actual_spending_money %>
|
<%= format_money @budget_category.actual_spending_money %>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
@@ -42,19 +42,19 @@
|
|||||||
<div class="flex items-center justify-between text-sm">
|
<div class="flex items-center justify-between text-sm">
|
||||||
<dt class="text-secondary">Status</dt>
|
<dt class="text-secondary">Status</dt>
|
||||||
<% if @budget_category.available_to_spend.negative? %>
|
<% if @budget_category.available_to_spend.negative? %>
|
||||||
<dd class="flex items-center gap-1 text-red-500 font-medium">
|
<dd class="flex items-center gap-1 text-red-500 font-medium privacy-sensitive">
|
||||||
<%= icon "alert-circle", size: "sm", color: "destructive" %>
|
<%= icon "alert-circle", size: "sm", color: "destructive" %>
|
||||||
<%= format_money @budget_category.available_to_spend_money.abs %>
|
<%= format_money @budget_category.available_to_spend_money.abs %>
|
||||||
<span>overspent</span>
|
<span>overspent</span>
|
||||||
</dd>
|
</dd>
|
||||||
<% elsif @budget_category.available_to_spend.zero? %>
|
<% elsif @budget_category.available_to_spend.zero? %>
|
||||||
<dd class="flex items-center gap-1 text-orange-500 font-medium">
|
<dd class="flex items-center gap-1 text-orange-500 font-medium privacy-sensitive">
|
||||||
<%= icon "x-circle", size: "sm", color: "warning" %>
|
<%= icon "x-circle", size: "sm", color: "warning" %>
|
||||||
<%= format_money @budget_category.available_to_spend_money %>
|
<%= format_money @budget_category.available_to_spend_money %>
|
||||||
<span>left</span>
|
<span>left</span>
|
||||||
</dd>
|
</dd>
|
||||||
<% else %>
|
<% else %>
|
||||||
<dd class="text-primary flex items-center gap-1 text-green-500 font-medium">
|
<dd class="text-primary flex items-center gap-1 text-green-500 font-medium privacy-sensitive">
|
||||||
<%= icon "check-circle", size: "sm", color: "success" %>
|
<%= icon "check-circle", size: "sm", color: "success" %>
|
||||||
<%= format_money @budget_category.available_to_spend_money %>
|
<%= format_money @budget_category.available_to_spend_money %>
|
||||||
<span>left</span>
|
<span>left</span>
|
||||||
@@ -64,7 +64,7 @@
|
|||||||
|
|
||||||
<div class="flex items-center justify-between text-sm">
|
<div class="flex items-center justify-between text-sm">
|
||||||
<dt class="text-secondary">Budgeted</dt>
|
<dt class="text-secondary">Budgeted</dt>
|
||||||
<dd class="text-primary font-medium">
|
<dd class="text-primary font-medium privacy-sensitive">
|
||||||
<%= format_money @budget_category.budgeted_spending_money %>
|
<%= format_money @budget_category.budgeted_spending_money %>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
@@ -72,14 +72,14 @@
|
|||||||
|
|
||||||
<div class="flex items-center justify-between text-sm">
|
<div class="flex items-center justify-between text-sm">
|
||||||
<dt class="text-secondary">Monthly average spending</dt>
|
<dt class="text-secondary">Monthly average spending</dt>
|
||||||
<dd class="text-primary font-medium">
|
<dd class="text-primary font-medium privacy-sensitive">
|
||||||
<%= @budget_category.avg_monthly_expense_money.format %>
|
<%= @budget_category.avg_monthly_expense_money.format %>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center justify-between text-sm">
|
<div class="flex items-center justify-between text-sm">
|
||||||
<dt class="text-secondary">Monthly median spending</dt>
|
<dt class="text-secondary">Monthly median spending</dt>
|
||||||
<dd class="text-primary font-medium">
|
<dd class="text-primary font-medium privacy-sensitive">
|
||||||
<%= @budget_category.median_monthly_expense_money.format %>
|
<%= @budget_category.median_monthly_expense_money.format %>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
@@ -111,7 +111,7 @@
|
|||||||
class: "text-primary hover:underline",
|
class: "text-primary hover:underline",
|
||||||
data: { turbo_frame: :_top } %>
|
data: { turbo_frame: :_top } %>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-primary font-medium">
|
<p class="text-primary font-medium privacy-sensitive">
|
||||||
<%= format_money transaction.entry.amount_money %>
|
<%= format_money transaction.entry.amount_money %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<div class="p-4 border-b border-secondary">
|
<div class="p-4 border-b border-secondary">
|
||||||
<h3 class="text-sm text-secondary mb-2">Income</h3>
|
<h3 class="text-sm text-secondary mb-2">Income</h3>
|
||||||
|
|
||||||
<span class="inline-block mb-2 text-xl font-medium text-primary">
|
<span class="inline-block mb-2 text-xl font-medium text-primary privacy-sensitive">
|
||||||
<%= budget.actual_income_money.format %>
|
<%= budget.actual_income_money.format %>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<h3 class="text-sm text-secondary mb-2">Expenses</h3>
|
<h3 class="text-sm text-secondary mb-2">Expenses</h3>
|
||||||
|
|
||||||
<span class="inline-block mb-2 text-xl font-medium text-primary"><%= budget.actual_spending_money.format %></span>
|
<span class="inline-block mb-2 text-xl font-medium text-primary privacy-sensitive"><%= budget.actual_spending_money.format %></span>
|
||||||
|
|
||||||
<% if budget.expense_category_totals.any? %>
|
<% if budget.expense_category_totals.any? %>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<span>Spent</span>
|
<span>Spent</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-2 text-3xl font-medium <%= budget.available_to_spend.negative? ? "text-red-500" : "text-primary" %>">
|
<div class="mb-2 text-3xl font-medium privacy-sensitive <%= budget.available_to_spend.negative? ? "text-red-500" : "text-primary" %>">
|
||||||
<%= format_money(budget.actual_spending_money) %>
|
<%= format_money(budget.actual_spending_money) %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
href: edit_budget_path(budget)
|
href: edit_budget_path(budget)
|
||||||
) %>
|
) %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="text-subdued text-3xl mb-2">
|
<div class="text-subdued text-3xl mb-2 privacy-sensitive">
|
||||||
<span><%= format_money Money.new(0, budget.currency || budget.family.currency) %></span>
|
<span><%= format_money Money.new(0, budget.currency || budget.family.currency) %></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<p class="text-sm text-secondary"><%= bc.category.name %></p>
|
<p class="text-sm text-secondary"><%= bc.category.name %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="text-3xl font-medium <%= bc.available_to_spend.negative? ? "text-red-500" : "text-primary" %>">
|
<p class="text-3xl font-medium privacy-sensitive <%= bc.available_to_spend.negative? ? "text-red-500" : "text-primary" %>">
|
||||||
<%= format_money(bc.actual_spending_money) %>
|
<%= format_money(bc.actual_spending_money) %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
<div id="segment_unused" class="hidden">
|
<div id="segment_unused" class="hidden">
|
||||||
<p class="text-sm text-secondary text-center mb-2">Unused</p>
|
<p class="text-sm text-secondary text-center mb-2">Unused</p>
|
||||||
|
|
||||||
<p class="text-3xl font-medium text-primary">
|
<p class="text-3xl font-medium text-primary privacy-sensitive">
|
||||||
<%= format_money(budget.available_to_spend_money) %>
|
<%= format_money(budget.available_to_spend_money) %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<div class="p-4 border-b border-secondary">
|
<div class="p-4 border-b border-secondary">
|
||||||
<h3 class="text-sm text-secondary mb-2">Expected income</h3>
|
<h3 class="text-sm text-secondary mb-2">Expected income</h3>
|
||||||
|
|
||||||
<span class="inline-block mb-2 text-xl font-medium text-primary">
|
<span class="inline-block mb-2 text-xl font-medium text-primary privacy-sensitive">
|
||||||
<%= format_money(budget.expected_income_money) %>
|
<%= format_money(budget.expected_income_money) %>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<div class="rounded-md h-1.5 bg-surface-inset" style="width: <%= 100 - budget.actual_income_percent %>%"></div>
|
<div class="rounded-md h-1.5 bg-surface-inset" style="width: <%= 100 - budget.actual_income_percent %>%"></div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between text-sm">
|
<div class="flex justify-between text-sm privacy-sensitive">
|
||||||
<p class="text-secondary"><%= format_money(budget.actual_income_money) %> earned</p>
|
<p class="text-secondary"><%= format_money(budget.actual_income_money) %> earned</p>
|
||||||
<p class="font-medium">
|
<p class="font-medium">
|
||||||
<% if budget.remaining_expected_income.negative? %>
|
<% if budget.remaining_expected_income.negative? %>
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<h3 class="text-sm text-secondary mb-2">Budgeted</h3>
|
<h3 class="text-sm text-secondary mb-2">Budgeted</h3>
|
||||||
|
|
||||||
<span class="inline-block mb-2 text-xl font-medium text-primary">
|
<span class="inline-block mb-2 text-xl font-medium text-primary privacy-sensitive">
|
||||||
<%= format_money(budget.budgeted_spending_money) %>
|
<%= format_money(budget.budgeted_spending_money) %>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
<div class="rounded-md h-1.5 bg-surface-inset" style="width: <%= 100 - budget.percent_of_budget_spent %>%"></div>
|
<div class="rounded-md h-1.5 bg-surface-inset" style="width: <%= 100 - budget.percent_of_budget_spent %>%"></div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between text-sm">
|
<div class="flex justify-between text-sm privacy-sensitive">
|
||||||
<p class="text-secondary"><%= format_money(budget.actual_spending_money) %> spent</p>
|
<p class="text-secondary"><%= format_money(budget.actual_spending_money) %> spent</p>
|
||||||
<p class="font-medium">
|
<p class="font-medium">
|
||||||
<% if budget.available_to_spend.negative? %>
|
<% if budget.available_to_spend.negative? %>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ end %>
|
|||||||
<%= render "layouts/shared/htmldoc" do %>
|
<%= render "layouts/shared/htmldoc" do %>
|
||||||
<div
|
<div
|
||||||
class="flex flex-col lg:flex-row h-full bg-surface"
|
class="flex flex-col lg:flex-row h-full bg-surface"
|
||||||
data-controller="app-layout"
|
data-controller="app-layout privacy-mode"
|
||||||
data-app-layout-expanded-sidebar-class="<%= expanded_sidebar_class %>"
|
data-app-layout-expanded-sidebar-class="<%= expanded_sidebar_class %>"
|
||||||
data-app-layout-collapsed-sidebar-class="<%= collapsed_sidebar_class %>"
|
data-app-layout-collapsed-sidebar-class="<%= collapsed_sidebar_class %>"
|
||||||
data-app-layout-user-id-value="<%= Current.user.id %>">
|
data-app-layout-user-id-value="<%= Current.user.id %>">
|
||||||
|
|||||||
@@ -9,21 +9,33 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= render DS::Link.new(
|
<div class="flex items-center gap-2">
|
||||||
icon: "plus",
|
<button type="button"
|
||||||
text: t("pages.dashboard.new"),
|
class="inline-flex items-center justify-center w-9 h-9 rounded-lg text-secondary hover:text-primary hover:bg-surface-hover transition-colors"
|
||||||
href: new_account_path,
|
data-action="click->privacy-mode#toggle"
|
||||||
frame: :modal,
|
data-privacy-mode-target="toggle"
|
||||||
class: "hidden lg:inline-flex"
|
title="<%= t("pages.dashboard.privacy_mode") %>"
|
||||||
) %>
|
aria-label="<%= t("pages.dashboard.privacy_mode") %>"
|
||||||
|
aria-pressed="false">
|
||||||
|
<%= icon("eye-off", size: "sm") %>
|
||||||
|
</button>
|
||||||
|
|
||||||
<%= render DS::Link.new(
|
<%= render DS::Link.new(
|
||||||
variant: "icon-inverse",
|
|
||||||
icon: "plus",
|
icon: "plus",
|
||||||
|
text: t("pages.dashboard.new"),
|
||||||
href: new_account_path,
|
href: new_account_path,
|
||||||
frame: :modal,
|
frame: :modal,
|
||||||
class: "rounded-full lg:hidden"
|
class: "hidden lg:inline-flex"
|
||||||
) %>
|
) %>
|
||||||
|
|
||||||
|
<%= render DS::Link.new(
|
||||||
|
variant: "icon-inverse",
|
||||||
|
icon: "plus",
|
||||||
|
href: new_account_path,
|
||||||
|
frame: :modal,
|
||||||
|
class: "rounded-full lg:hidden"
|
||||||
|
) %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<% if classification_group.account_groups.any? %>
|
<% if classification_group.account_groups.any? %>
|
||||||
<span class="text-secondary">·</span>
|
<span class="text-secondary">·</span>
|
||||||
<span class="text-secondary font-medium text-lg"><%= classification_group.total_money.format(precision: 0) %></span>
|
<span class="text-secondary font-medium text-lg privacy-sensitive"><%= classification_group.total_money.format(precision: 0) %></span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</h2>
|
</h2>
|
||||||
</div>
|
</div>
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
<div class="flex items-center gap-2 text-sm">
|
<div class="flex items-center gap-2 text-sm">
|
||||||
<div class="h-2.5 w-2.5 rounded-full" style="background-color: <%= account_group.color %>;"></div>
|
<div class="h-2.5 w-2.5 rounded-full" style="background-color: <%= account_group.color %>;"></div>
|
||||||
<p class="text-secondary"><%= account_group.name %></p>
|
<p class="text-secondary"><%= account_group.name %></p>
|
||||||
<p class="text-primary font-mono"><%= number_to_percentage(account_group.weight, precision: 0) %></p>
|
<p class="text-primary font-mono privacy-sensitive"><%= number_to_percentage(account_group.weight, precision: 0) %></p>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-40 shrink-0">
|
<div class="w-40 shrink-0">
|
||||||
<p><%= format_money(account_group.total_money) %></p>
|
<p class="privacy-sensitive"><%= format_money(account_group.total_money) %></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</summary>
|
</summary>
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-40 shrink-0">
|
<div class="w-40 shrink-0">
|
||||||
<p><%= format_money(account.balance_money) %></p>
|
<p class="privacy-sensitive"><%= format_money(account.balance_money) %></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,5 +8,5 @@
|
|||||||
<div class="w-0.5 h-2.5 rounded-lg <%= i < (effective_weight / 10.0).ceil ? "" : "opacity-20" %>" style="background-color: <%= color %>;"></div>
|
<div class="w-0.5 h-2.5 rounded-lg <%= i < (effective_weight / 10.0).ceil ? "" : "opacity-20" %>" style="background-color: <%= color %>;"></div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-sm"><%= number_to_percentage(effective_weight, precision: 2) %></p>
|
<p class="text-sm privacy-sensitive"><%= number_to_percentage(effective_weight, precision: 2) %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<h2 class="text-lg font-medium"><%= t(".title") %></h2>
|
<h2 class="text-lg font-medium"><%= t(".title") %></h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p class="text-primary text-3xl font-medium">
|
<p class="text-primary text-3xl font-medium privacy-sensitive">
|
||||||
<%= format_money(investment_statement.portfolio_value_money) %>
|
<%= format_money(investment_statement.portfolio_value_money) %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<% if trend %>
|
<% if trend %>
|
||||||
<div class="flex items-center gap-2 text-sm">
|
<div class="flex items-center gap-2 text-sm">
|
||||||
<span class="text-secondary"><%= t(".total_return") %>:</span>
|
<span class="text-secondary"><%= t(".total_return") %>:</span>
|
||||||
<span class="font-medium" style="color: <%= trend.color %>">
|
<span class="font-medium privacy-sensitive" style="color: <%= trend.color %>">
|
||||||
<%= format_money(Money.new(trend.value, Current.family.currency)) %>
|
<%= format_money(Money.new(trend.value, Current.family.currency)) %>
|
||||||
(<%= trend.percent_formatted %>)
|
(<%= trend.percent_formatted %>)
|
||||||
</span>
|
</span>
|
||||||
@@ -52,17 +52,17 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-20 text-right text-secondary">
|
<div class="w-20 text-right text-secondary privacy-sensitive">
|
||||||
<%= number_to_percentage(holding.weight || 0, precision: 1) %>
|
<%= number_to_percentage(holding.weight || 0, precision: 1) %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-28 text-right">
|
<div class="w-28 text-right privacy-sensitive">
|
||||||
<%= format_money(holding.amount_money) %>
|
<%= format_money(holding.amount_money) %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-24 text-right">
|
<div class="w-24 text-right">
|
||||||
<% if holding.trend %>
|
<% if holding.trend %>
|
||||||
<span style="color: <%= holding.trend.color %>">
|
<span class="privacy-sensitive" style="color: <%= holding.trend.color %>">
|
||||||
<%= holding.trend.percent_formatted %>
|
<%= holding.trend.percent_formatted %>
|
||||||
</span>
|
</span>
|
||||||
<% else %>
|
<% else %>
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p class="text-xs text-secondary"><%= t(".contributions") %></p>
|
<p class="text-xs text-secondary"><%= t(".contributions") %></p>
|
||||||
<p class="font-medium text-green-600"><%= format_money(totals.contributions) %></p>
|
<p class="font-medium text-green-600 privacy-sensitive"><%= format_money(totals.contributions) %></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p class="text-xs text-secondary"><%= t(".withdrawals") %></p>
|
<p class="text-xs text-secondary"><%= t(".withdrawals") %></p>
|
||||||
<p class="font-medium text-orange-600"><%= format_money(totals.withdrawals) %></p>
|
<p class="font-medium text-orange-600 privacy-sensitive"><%= format_money(totals.withdrawals) %></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<div class="flex justify-between gap-4 px-4">
|
<div class="flex justify-between gap-4 px-4">
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<% if series.trend.present? %>
|
<% if series.trend.present? %>
|
||||||
<p class="text-primary -space-x-0.5 text-3xl font-medium <%= "animate-pulse" if balance_sheet.syncing? %>">
|
<p class="text-primary -space-x-0.5 text-3xl font-medium privacy-sensitive <%= "animate-pulse" if balance_sheet.syncing? %>">
|
||||||
<%= series.trend.current.format %>
|
<%= series.trend.current.format %>
|
||||||
</p>
|
</p>
|
||||||
<%= render partial: "shared/trend_change", locals: { trend: series.trend, comparison_label: period.comparison_label } %>
|
<%= render partial: "shared/trend_change", locals: { trend: series.trend, comparison_label: period.comparison_label } %>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<span><%= t("pages.dashboard.outflows_donut.total_outflows") %></span>
|
<span><%= t("pages.dashboard.outflows_donut.total_outflows") %></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-3xl font-medium text-primary">
|
<div class="text-3xl font-medium text-primary privacy-sensitive">
|
||||||
<%= format_money Money.new(outflows_data[:total], outflows_data[:currency]) %>
|
<%= format_money Money.new(outflows_data[:total], outflows_data[:currency]) %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -41,11 +41,11 @@
|
|||||||
<div class="flex flex-col gap-2 items-center">
|
<div class="flex flex-col gap-2 items-center">
|
||||||
<p class="text-sm text-secondary"><%= category[:name] %></p>
|
<p class="text-sm text-secondary"><%= category[:name] %></p>
|
||||||
|
|
||||||
<p class="text-3xl font-medium text-primary">
|
<p class="text-3xl font-medium text-primary privacy-sensitive">
|
||||||
<%= outflows_data[:currency_symbol] %><%= number_with_delimiter(category[:amount], delimiter: ",") %>
|
<%= outflows_data[:currency_symbol] %><%= number_with_delimiter(category[:amount], delimiter: ",") %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p class="text-sm text-secondary"><%= category[:percentage] %>%</p>
|
<p class="text-sm text-secondary privacy-sensitive"><%= category[:percentage] %>%</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
@@ -94,8 +94,8 @@
|
|||||||
<span class="text-sm font-medium text-primary truncate"><%= category[:name] %></span>
|
<span class="text-sm font-medium text-primary truncate"><%= category[:name] %></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-4 flex-shrink-0 text-right">
|
<div class="flex items-center gap-4 flex-shrink-0 text-right">
|
||||||
<span class="text-sm font-medium text-primary whitespace-nowrap"><%= format_money Money.new(category[:amount], category[:currency]) %></span>
|
<span class="text-sm font-medium text-primary whitespace-nowrap privacy-sensitive"><%= format_money Money.new(category[:amount], category[:currency]) %></span>
|
||||||
<span class="text-sm text-secondary whitespace-nowrap w-10 lg:w-15"><%= category[:percentage] %>%</span>
|
<span class="text-sm text-secondary whitespace-nowrap w-10 lg:w-15 privacy-sensitive"><%= category[:percentage] %>%</span>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,6 @@
|
|||||||
|
|
||||||
<div class="col-span-2 ml-auto text-right shrink-0">
|
<div class="col-span-2 ml-auto text-right shrink-0">
|
||||||
<% display_amount = recurring_transaction.manual? && recurring_transaction.expected_amount_avg.present? ? recurring_transaction.expected_amount_avg : recurring_transaction.amount %>
|
<% display_amount = recurring_transaction.manual? && recurring_transaction.expected_amount_avg.present? ? recurring_transaction.expected_amount_avg : recurring_transaction.amount %>
|
||||||
<%= content_tag :p, format_money(-Money.new(display_amount, recurring_transaction.currency)), class: ["font-medium", display_amount.negative? ? "text-success" : "text-subdued"] %>
|
<%= content_tag :p, format_money(-Money.new(display_amount, recurring_transaction.currency)), class: ["font-medium", "privacy-sensitive", display_amount.negative? ? "text-success" : "text-subdued"] %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -128,11 +128,11 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="py-3 px-2 text-sm font-medium <%= recurring_transaction.amount.negative? ? "text-success" : "text-primary" %>">
|
<td class="py-3 px-2 text-sm font-medium privacy-sensitive <%= recurring_transaction.amount.negative? ? "text-success" : "text-primary" %>">
|
||||||
<% if recurring_transaction.manual? && recurring_transaction.has_amount_variance? %>
|
<% if recurring_transaction.manual? && recurring_transaction.has_amount_variance? %>
|
||||||
<div class="inline-flex items-center gap-1 cursor-help group" title="<%= t("recurring_transactions.amount_range", min: format_money(-recurring_transaction.expected_amount_min_money), max: format_money(-recurring_transaction.expected_amount_max_money)) %>">
|
<div class="inline-flex items-center gap-1 cursor-help group" title="<%= t("recurring_transactions.amount_range", min: format_money(-recurring_transaction.expected_amount_min_money), max: format_money(-recurring_transaction.expected_amount_max_money)) %>">
|
||||||
<span class="text-xs text-secondary group-hover:text-primary transition-colors">~</span>
|
<span class="text-xs text-secondary group-hover:text-primary transition-colors">~</span>
|
||||||
<span class="border-b border-dashed border-subdued group-hover:border-primary transition-colors"><%= format_money(-recurring_transaction.expected_amount_avg_money) %></span>
|
<span class="border-b border-dashed border-subdued group-hover:border-primary transition-colors privacy-sensitive"><%= format_money(-recurring_transaction.expected_amount_avg_money) %></span>
|
||||||
</div>
|
</div>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= format_money(-recurring_transaction.amount_money) %>
|
<%= format_money(-recurring_transaction.amount_money) %>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<div class="text-large mb-4 flex items-center gap-2 text-lg">
|
<div class="text-large mb-4 flex items-center gap-2 text-lg">
|
||||||
<%= icon(icon_name, class: "w-5 h-5") %>
|
<%= icon(icon_name, class: "w-5 h-5") %>
|
||||||
<span><%= t(title_key) %>:</span>
|
<span><%= t(title_key) %>:</span>
|
||||||
<span class="font-medium text-secondary <%= color_class %>"> <%= Money.new(total, Current.family.currency).format %></span>
|
<span class="font-medium text-secondary <%= color_class %> privacy-sensitive"> <%= Money.new(total, Current.family.currency).format %></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-container-inset rounded-xl p-1 overflow-x-auto">
|
<div class="bg-container-inset rounded-xl p-1 overflow-x-auto">
|
||||||
|
|||||||
@@ -63,13 +63,13 @@
|
|||||||
<div class="flex items-center gap-4">
|
<div class="flex items-center gap-4">
|
||||||
<div>
|
<div>
|
||||||
<span class="text-subdued"><%= t("reports.budget_performance.spent") %>:</span>
|
<span class="text-subdued"><%= t("reports.budget_performance.spent") %>:</span>
|
||||||
<span class="font-medium text-primary">
|
<span class="font-medium text-primary privacy-sensitive">
|
||||||
<%= Money.new(budget_item[:actual], Current.family.currency).format %>
|
<%= Money.new(budget_item[:actual], Current.family.currency).format %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="text-subdued"><%= t("reports.budget_performance.budgeted") %>:</span>
|
<span class="text-subdued"><%= t("reports.budget_performance.budgeted") %>:</span>
|
||||||
<span class="font-medium text-secondary">
|
<span class="font-medium text-secondary privacy-sensitive">
|
||||||
<%= Money.new(budget_item[:budgeted], Current.family.currency).format %>
|
<%= Money.new(budget_item[:budgeted], Current.family.currency).format %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -78,12 +78,12 @@
|
|||||||
<div>
|
<div>
|
||||||
<% if budget_item[:remaining] >= 0 %>
|
<% if budget_item[:remaining] >= 0 %>
|
||||||
<span class="text-subdued"><%= t("reports.budget_performance.remaining") %>:</span>
|
<span class="text-subdued"><%= t("reports.budget_performance.remaining") %>:</span>
|
||||||
<span class="font-medium text-success">
|
<span class="font-medium text-success privacy-sensitive">
|
||||||
<%= Money.new(budget_item[:remaining], Current.family.currency).format %>
|
<%= Money.new(budget_item[:remaining], Current.family.currency).format %>
|
||||||
</span>
|
</span>
|
||||||
<% else %>
|
<% else %>
|
||||||
<span class="text-subdued"><%= t("reports.budget_performance.over_by") %>:</span>
|
<span class="text-subdued"><%= t("reports.budget_performance.over_by") %>:</span>
|
||||||
<span class="font-medium text-destructive">
|
<span class="font-medium text-destructive privacy-sensitive">
|
||||||
<%= Money.new(budget_item[:remaining].abs, Current.family.currency).format %>
|
<%= Money.new(budget_item[:remaining].abs, Current.family.currency).format %>
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-span-1 text-right">
|
<div class="col-span-1 text-right">
|
||||||
<span class="text-sm <%= color_class %>">
|
<span class="text-sm <%= color_class %> privacy-sensitive">
|
||||||
<%= Money.new(item[:total], Current.family.currency).format %>
|
<%= Money.new(item[:total], Current.family.currency).format %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<%= icon("trending-up", size: "sm", class: "text-green-600") %>
|
<%= icon("trending-up", size: "sm", class: "text-green-600") %>
|
||||||
<h3 class="text-sm font-medium text-secondary">Contributions</h3>
|
<h3 class="text-sm font-medium text-secondary">Contributions</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-2xl font-semibold" style="color: rgb(34 197 94);">
|
<div class="text-2xl font-semibold privacy-sensitive" style="color: rgb(34 197 94);">
|
||||||
<%= format_money(investment_flows.contributions) %>
|
<%= format_money(investment_flows.contributions) %>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-xs text-secondary mt-1">Money added to investments</p>
|
<p class="text-xs text-secondary mt-1">Money added to investments</p>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
<%= icon("trending-down", size: "sm", class: "text-orange-600") %>
|
<%= icon("trending-down", size: "sm", class: "text-orange-600") %>
|
||||||
<h3 class="text-sm font-medium text-secondary">Withdrawals</h3>
|
<h3 class="text-sm font-medium text-secondary">Withdrawals</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-2xl font-semibold" style="color: rgb(249 115 22);">
|
<div class="text-2xl font-semibold privacy-sensitive" style="color: rgb(249 115 22);">
|
||||||
<%= format_money(investment_flows.withdrawals) %>
|
<%= format_money(investment_flows.withdrawals) %>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-xs text-secondary mt-1">Money withdrawn from investments</p>
|
<p class="text-xs text-secondary mt-1">Money withdrawn from investments</p>
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
<%= icon("arrow-right-left", size: "sm", class: "text-primary") %>
|
<%= icon("arrow-right-left", size: "sm", class: "text-primary") %>
|
||||||
<h3 class="text-sm font-medium text-secondary">Net Flow</h3>
|
<h3 class="text-sm font-medium text-secondary">Net Flow</h3>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-2xl font-semibold text-primary">
|
<div class="text-2xl font-semibold text-primary privacy-sensitive">
|
||||||
<%= format_money(investment_flows.net_flow) %>
|
<%= format_money(investment_flows.net_flow) %>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-xs text-secondary mt-1">Total net change</p>
|
<p class="text-xs text-secondary mt-1">Total net change</p>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<%= icon("briefcase", size: "sm") %>
|
<%= icon("briefcase", size: "sm") %>
|
||||||
<span class="text-sm text-secondary"><%= t("reports.investment_performance.portfolio_value") %></span>
|
<span class="text-sm text-secondary"><%= t("reports.investment_performance.portfolio_value") %></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-xl font-semibold text-primary">
|
<p class="text-xl font-semibold text-primary privacy-sensitive">
|
||||||
<%= format_money(investment_metrics[:portfolio_value]) %>
|
<%= format_money(investment_metrics[:portfolio_value]) %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
<span class="text-sm text-secondary"><%= t("reports.investment_performance.total_return") %></span>
|
<span class="text-sm text-secondary"><%= t("reports.investment_performance.total_return") %></span>
|
||||||
</div>
|
</div>
|
||||||
<% if investment_metrics[:unrealized_trend] %>
|
<% if investment_metrics[:unrealized_trend] %>
|
||||||
<p class="text-xl font-semibold" style="color: <%= investment_metrics[:unrealized_trend].color %>">
|
<p class="text-xl font-semibold privacy-sensitive" style="color: <%= investment_metrics[:unrealized_trend].color %>">
|
||||||
<%= format_money(Money.new(investment_metrics[:unrealized_trend].value, Current.family.currency)) %>
|
<%= format_money(Money.new(investment_metrics[:unrealized_trend].value, Current.family.currency)) %>
|
||||||
(<%= investment_metrics[:unrealized_trend].percent_formatted %>)
|
(<%= investment_metrics[:unrealized_trend].percent_formatted %>)
|
||||||
</p>
|
</p>
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
<%= icon("arrow-down-to-line", size: "sm") %>
|
<%= icon("arrow-down-to-line", size: "sm") %>
|
||||||
<span class="text-sm text-secondary"><%= t("reports.investment_performance.contributions") %></span>
|
<span class="text-sm text-secondary"><%= t("reports.investment_performance.contributions") %></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-xl font-semibold text-primary">
|
<p class="text-xl font-semibold text-primary privacy-sensitive">
|
||||||
<%= format_money(investment_metrics[:period_contributions]) %>
|
<%= format_money(investment_metrics[:period_contributions]) %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
<%= icon("arrow-up-from-line", size: "sm") %>
|
<%= icon("arrow-up-from-line", size: "sm") %>
|
||||||
<span class="text-sm text-secondary"><%= t("reports.investment_performance.withdrawals") %></span>
|
<span class="text-sm text-secondary"><%= t("reports.investment_performance.withdrawals") %></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="text-xl font-semibold text-primary">
|
<p class="text-xl font-semibold text-primary privacy-sensitive">
|
||||||
<%= format_money(investment_metrics[:period_withdrawals]) %>
|
<%= format_money(investment_metrics[:period_withdrawals]) %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right text-secondary"><%= number_to_percentage(holding.weight || 0, precision: 1) %></div>
|
<div class="text-right text-secondary"><%= number_to_percentage(holding.weight || 0, precision: 1) %></div>
|
||||||
<div class="text-right font-medium text-primary"><%= format_money(holding.amount_money) %></div>
|
<div class="text-right font-medium text-primary privacy-sensitive"><%= format_money(holding.amount_money) %></div>
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<% if holding.trend %>
|
<% if holding.trend %>
|
||||||
<span style="color: <%= holding.trend.color %>">
|
<span style="color: <%= holding.trend.color %>">
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
<span class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium <%= tax_treatment_badge_classes(treatment) %>" title="<%= t("accounts.tax_treatment_descriptions.#{treatment}") %>">
|
<span class="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium <%= tax_treatment_badge_classes(treatment) %>" title="<%= t("accounts.tax_treatment_descriptions.#{treatment}") %>">
|
||||||
<%= t("accounts.tax_treatments.#{treatment}") %>
|
<%= t("accounts.tax_treatments.#{treatment}") %>
|
||||||
</span>
|
</span>
|
||||||
<span class="text-sm font-semibold text-primary">
|
<span class="text-sm font-semibold text-primary privacy-sensitive">
|
||||||
<%= format_money(data[:total_gain]) %>
|
<%= format_money(data[:total_gain]) %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -125,11 +125,11 @@
|
|||||||
<div class="space-y-2 text-sm">
|
<div class="space-y-2 text-sm">
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<span class="text-secondary"><%= t("reports.investment_performance.unrealized_gains") %></span>
|
<span class="text-secondary"><%= t("reports.investment_performance.unrealized_gains") %></span>
|
||||||
<span class="text-primary"><%= format_money(data[:unrealized_gain]) %></span>
|
<span class="text-primary privacy-sensitive"><%= format_money(data[:unrealized_gain]) %></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex justify-between">
|
<div class="flex justify-between">
|
||||||
<span class="text-secondary"><%= t("reports.investment_performance.realized_gains") %></span>
|
<span class="text-secondary"><%= t("reports.investment_performance.realized_gains") %></span>
|
||||||
<span class="text-primary"><%= format_money(data[:realized_gain]) %></span>
|
<span class="text-primary privacy-sensitive"><%= format_money(data[:realized_gain]) %></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -205,7 +205,7 @@
|
|||||||
<p class="text-xs text-secondary"><%= account.short_subtype_label %></p>
|
<p class="text-xs text-secondary"><%= account.short_subtype_label %></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="font-medium text-primary"><%= format_money(account.balance_money) %></p>
|
<p class="font-medium text-primary privacy-sensitive"><%= format_money(account.balance_money) %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<%# Current Net Worth %>
|
<%# Current Net Worth %>
|
||||||
<div class="p-4 bg-surface-inset rounded-lg">
|
<div class="p-4 bg-surface-inset rounded-lg">
|
||||||
<p class="text-sm text-secondary mb-2"><%= t("reports.net_worth.current_net_worth") %></p>
|
<p class="text-sm text-secondary mb-2"><%= t("reports.net_worth.current_net_worth") %></p>
|
||||||
<p class="text-2xl font-semibold <%= net_worth_metrics[:current_net_worth] >= 0 ? "text-success" : "text-destructive" %>">
|
<p class="text-2xl font-semibold privacy-sensitive <%= net_worth_metrics[:current_net_worth] >= 0 ? "text-success" : "text-destructive" %>">
|
||||||
<%= net_worth_metrics[:current_net_worth].format %>
|
<%= net_worth_metrics[:current_net_worth].format %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
<p class="text-sm text-secondary mb-2"><%= t("reports.net_worth.period_change") %></p>
|
<p class="text-sm text-secondary mb-2"><%= t("reports.net_worth.period_change") %></p>
|
||||||
<% if net_worth_metrics[:trend] %>
|
<% if net_worth_metrics[:trend] %>
|
||||||
<% trend = net_worth_metrics[:trend] %>
|
<% trend = net_worth_metrics[:trend] %>
|
||||||
<p class="text-2xl font-semibold mb-1" style="color: <%= trend.color %>">
|
<p class="text-2xl font-semibold mb-1 privacy-sensitive" style="color: <%= trend.color %>">
|
||||||
<%= trend.value.format(signify_positive: true) %>
|
<%= trend.value.format(signify_positive: true) %>
|
||||||
</p>
|
</p>
|
||||||
<p class="text-xs" style="color: <%= trend.color %>">
|
<p class="text-xs" style="color: <%= trend.color %>">
|
||||||
@@ -29,9 +29,9 @@
|
|||||||
<div class="p-4 bg-surface-inset rounded-lg">
|
<div class="p-4 bg-surface-inset rounded-lg">
|
||||||
<p class="text-sm text-secondary mb-2"><%= t("reports.net_worth.assets_vs_liabilities") %></p>
|
<p class="text-sm text-secondary mb-2"><%= t("reports.net_worth.assets_vs_liabilities") %></p>
|
||||||
<div class="flex items-baseline gap-2 flex-wrap">
|
<div class="flex items-baseline gap-2 flex-wrap">
|
||||||
<span class="text-lg font-semibold text-success break-words"><%= net_worth_metrics[:total_assets].format %></span>
|
<span class="text-lg font-semibold text-success break-words privacy-sensitive"><%= net_worth_metrics[:total_assets].format %></span>
|
||||||
<span class="text-xs text-subdued shrink-0">-</span>
|
<span class="text-xs text-subdued shrink-0">-</span>
|
||||||
<span class="text-lg font-semibold text-destructive break-words"><%= net_worth_metrics[:total_liabilities].format %></span>
|
<span class="text-lg font-semibold text-destructive break-words privacy-sensitive"><%= net_worth_metrics[:total_liabilities].format %></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
<% net_worth_metrics[:asset_groups].each_with_index do |group, idx| %>
|
<% net_worth_metrics[:asset_groups].each_with_index do |group, idx| %>
|
||||||
<div class="grid grid-cols-2 items-center text-secondary text-sm py-3 px-4 lg:px-6">
|
<div class="grid grid-cols-2 items-center text-secondary text-sm py-3 px-4 lg:px-6">
|
||||||
<div class="col-span-1 font-medium text-secondary"><%= group[:name] %></div>
|
<div class="col-span-1 font-medium text-secondary"><%= group[:name] %></div>
|
||||||
<div class="col-span-1 font-medium text-secondary justify-self-end text-success"><%= group[:total].format %></div>
|
<div class="col-span-1 font-medium text-secondary justify-self-end text-success privacy-sensitive"><%= group[:total].format %></div>
|
||||||
</div>
|
</div>
|
||||||
<% if idx < net_worth_metrics[:asset_groups].size - 1 %>
|
<% if idx < net_worth_metrics[:asset_groups].size - 1 %>
|
||||||
<%= render "shared/ruler", classes: "mx-3 lg:mx-4" %>
|
<%= render "shared/ruler", classes: "mx-3 lg:mx-4" %>
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
<% net_worth_metrics[:liability_groups].each_with_index do |group, idx| %>
|
<% net_worth_metrics[:liability_groups].each_with_index do |group, idx| %>
|
||||||
<div class="grid grid-cols-2 items-center text-secondary text-sm py-3 px-4 lg:px-6">
|
<div class="grid grid-cols-2 items-center text-secondary text-sm py-3 px-4 lg:px-6">
|
||||||
<div class="col-span-1 font-medium text-secondary"><%= group[:name] %></div>
|
<div class="col-span-1 font-medium text-secondary"><%= group[:name] %></div>
|
||||||
<div class="col-span-1 font-medium text-secondary justify-self-end text-destructive"><%= group[:total].format %></div>
|
<div class="col-span-1 font-medium text-secondary justify-self-end text-destructive privacy-sensitive"><%= group[:total].format %></div>
|
||||||
</div>
|
</div>
|
||||||
<% if idx < net_worth_metrics[:liability_groups].size - 1 %>
|
<% if idx < net_worth_metrics[:liability_groups].size - 1 %>
|
||||||
<%= render "shared/ruler", classes: "mx-3 lg:mx-4" %>
|
<%= render "shared/ruler", classes: "mx-3 lg:mx-4" %>
|
||||||
|
|||||||
@@ -11,12 +11,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<p class="text-2xl font-semibold text-primary">
|
<p class="text-2xl font-semibold text-primary privacy-sensitive">
|
||||||
<%= metrics[:current_income].format %>
|
<%= metrics[:current_income].format %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<% if metrics[:income_change] %>
|
<% if metrics[:income_change] %>
|
||||||
<div class="flex items-center gap-1.5">
|
<div class="flex items-center gap-1.5 privacy-sensitive">
|
||||||
<% if metrics[:income_change] >= 0 %>
|
<% if metrics[:income_change] >= 0 %>
|
||||||
<%= icon("arrow-up", size: "sm") %>
|
<%= icon("arrow-up", size: "sm") %>
|
||||||
<span class="text-sm font-medium text-success">
|
<span class="text-sm font-medium text-success">
|
||||||
@@ -48,12 +48,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<p class="text-2xl font-semibold text-primary">
|
<p class="text-2xl font-semibold text-primary privacy-sensitive">
|
||||||
<%= metrics[:current_expenses].format %>
|
<%= metrics[:current_expenses].format %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<% if metrics[:expense_change] %>
|
<% if metrics[:expense_change] %>
|
||||||
<div class="flex items-center gap-1.5">
|
<div class="flex items-center gap-1.5 privacy-sensitive">
|
||||||
<% if metrics[:expense_change] >= 0 %>
|
<% if metrics[:expense_change] >= 0 %>
|
||||||
<%= icon("arrow-up", class: "w-4 h-4 text-destructive") %>
|
<%= icon("arrow-up", class: "w-4 h-4 text-destructive") %>
|
||||||
<span class="text-sm font-medium text-destructive">
|
<span class="text-sm font-medium text-destructive">
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<p class="text-2xl font-semibold <%= metrics[:net_savings] >= 0 ? "text-success" : "text-destructive" %>">
|
<p class="text-2xl font-semibold privacy-sensitive <%= metrics[:net_savings] >= 0 ? "text-success" : "text-destructive" %>">
|
||||||
<%= metrics[:net_savings].format %>
|
<%= metrics[:net_savings].format %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
|
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<% if metrics[:budget_percent] %>
|
<% if metrics[:budget_percent] %>
|
||||||
<p class="text-2xl font-semibold text-primary">
|
<p class="text-2xl font-semibold text-primary privacy-sensitive">
|
||||||
<%= metrics[:budget_percent] %>%
|
<%= metrics[:budget_percent] %>%
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|||||||
@@ -24,13 +24,13 @@
|
|||||||
<span class="text-xs text-subdued">(<%= t("reports.trends.current") %>)</span>
|
<span class="text-xs text-subdued">(<%= t("reports.trends.current") %>)</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right">
|
<div class="text-right privacy-sensitive">
|
||||||
<%= Money.new(trend[:income], Current.family.currency).format %>
|
<%= Money.new(trend[:income], Current.family.currency).format %>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right">
|
<div class="text-right privacy-sensitive">
|
||||||
<%= Money.new(trend[:expenses], Current.family.currency).format %>
|
<%= Money.new(trend[:expenses], Current.family.currency).format %>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right <%= trend[:net] >= 0 ? "text-success" : "text-destructive" %>">
|
<div class="text-right privacy-sensitive <%= trend[:net] >= 0 ? "text-success" : "text-destructive" %>">
|
||||||
<%= Money.new(trend[:net], Current.family.currency).format %>
|
<%= Money.new(trend[:net], Current.family.currency).format %>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right <%= trend[:net] >= 0 ? "text-success" : "text-destructive" %>">
|
<div class="text-right <%= trend[:net] >= 0 ? "text-success" : "text-destructive" %>">
|
||||||
@@ -54,21 +54,21 @@
|
|||||||
|
|
||||||
<div class="p-4 bg-surface-inset rounded-lg">
|
<div class="p-4 bg-surface-inset rounded-lg">
|
||||||
<p class="text-sm text-secondary mb-1"><%= t("reports.trends.avg_monthly_income") %></p>
|
<p class="text-sm text-secondary mb-1"><%= t("reports.trends.avg_monthly_income") %></p>
|
||||||
<p class="text-lg font-semibold text-success">
|
<p class="text-lg font-semibold text-success privacy-sensitive">
|
||||||
<%= Money.new(avg_income, Current.family.currency).format %>
|
<%= Money.new(avg_income, Current.family.currency).format %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-4 bg-surface-inset rounded-lg">
|
<div class="p-4 bg-surface-inset rounded-lg">
|
||||||
<p class="text-sm text-secondary mb-1"><%= t("reports.trends.avg_monthly_expenses") %></p>
|
<p class="text-sm text-secondary mb-1"><%= t("reports.trends.avg_monthly_expenses") %></p>
|
||||||
<p class="text-lg font-semibold text-destructive">
|
<p class="text-lg font-semibold text-destructive privacy-sensitive">
|
||||||
<%= Money.new(avg_expenses, Current.family.currency).format %>
|
<%= Money.new(avg_expenses, Current.family.currency).format %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-4 bg-surface-inset rounded-lg">
|
<div class="p-4 bg-surface-inset rounded-lg">
|
||||||
<p class="text-sm text-secondary mb-1"><%= t("reports.trends.avg_monthly_savings") %></p>
|
<p class="text-sm text-secondary mb-1"><%= t("reports.trends.avg_monthly_savings") %></p>
|
||||||
<p class="text-lg font-semibold <%= avg_net >= 0 ? "text-success" : "text-destructive" %>">
|
<p class="text-lg font-semibold privacy-sensitive <%= avg_net >= 0 ? "text-success" : "text-destructive" %>">
|
||||||
<%= Money.new(avg_net, Current.family.currency).format %>
|
<%= Money.new(avg_net, Current.family.currency).format %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<%# locals: { trend:, comparison_label: nil } %>
|
<%# locals: { trend:, comparison_label: nil } %>
|
||||||
|
|
||||||
<p class="text-sm" style="color: <%= trend.color %>">
|
<p class="text-sm privacy-sensitive" style="color: <%= trend.color %>">
|
||||||
<% if trend.direction.flat? %>
|
<% if trend.direction.flat? %>
|
||||||
<%= t(".no_change") %><%= " #{comparison_label}" if defined?(comparison_label) && comparison_label.present? %>
|
<%= t(".no_change") %><%= " #{comparison_label}" if defined?(comparison_label) && comparison_label.present? %>
|
||||||
<% else %>
|
<% else %>
|
||||||
|
|||||||
@@ -2,17 +2,17 @@
|
|||||||
<div class="grid grid-cols-1 md:grid-cols-3 bg-container rounded-xl shadow-border-xs md:divide-x divide-y md:divide-y-0 divide-alpha-black-100 theme-dark:divide-alpha-white-200">
|
<div class="grid grid-cols-1 md:grid-cols-3 bg-container rounded-xl shadow-border-xs md:divide-x divide-y md:divide-y-0 divide-alpha-black-100 theme-dark:divide-alpha-white-200">
|
||||||
<div class="p-4 space-y-2">
|
<div class="p-4 space-y-2">
|
||||||
<p class="text-sm text-secondary">Total transactions</p>
|
<p class="text-sm text-secondary">Total transactions</p>
|
||||||
<p class="text-primary font-medium text-xl" id="total-transactions"><%= totals.count.round(0) %></p>
|
<p class="text-primary font-medium text-xl privacy-sensitive" id="total-transactions"><%= totals.count.round(0) %></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-4 space-y-2">
|
<div class="p-4 space-y-2">
|
||||||
<p class="text-sm text-secondary">Income</p>
|
<p class="text-sm text-secondary">Income</p>
|
||||||
<p class="text-primary font-medium text-xl" id="total-income">
|
<p class="text-primary font-medium text-xl privacy-sensitive" id="total-income">
|
||||||
<%= totals.income_money.format %>
|
<%= totals.income_money.format %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-4 space-y-2">
|
<div class="p-4 space-y-2">
|
||||||
<p class="text-sm text-secondary">Expenses</p>
|
<p class="text-sm text-secondary">Expenses</p>
|
||||||
<p class="text-primary font-medium text-xl" id="total-expense">
|
<p class="text-primary font-medium text-xl privacy-sensitive" id="total-expense">
|
||||||
<%= totals.expense_money.format %>
|
<%= totals.expense_money.format %>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ de:
|
|||||||
welcome: "Willkommen zurück, %{name}"
|
welcome: "Willkommen zurück, %{name}"
|
||||||
subtitle: "Hier siehst du, was in deinen Finanzen passiert."
|
subtitle: "Hier siehst du, was in deinen Finanzen passiert."
|
||||||
new: "Neu"
|
new: "Neu"
|
||||||
|
privacy_mode: "Datenschutzmodus umschalten"
|
||||||
net_worth_chart:
|
net_worth_chart:
|
||||||
data_not_available: Für den ausgewählten Zeitraum sind keine Daten verfügbar.
|
data_not_available: Für den ausgewählten Zeitraum sind keine Daten verfügbar.
|
||||||
title: Nettovermögen
|
title: Nettovermögen
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ en:
|
|||||||
welcome: "Welcome back, %{name}"
|
welcome: "Welcome back, %{name}"
|
||||||
subtitle: "Here's what's happening with your finances"
|
subtitle: "Here's what's happening with your finances"
|
||||||
new: "New"
|
new: "New"
|
||||||
|
privacy_mode: "Toggle privacy mode"
|
||||||
drag_to_reorder: "Drag to reorder section"
|
drag_to_reorder: "Drag to reorder section"
|
||||||
toggle_section: "Toggle section visibility"
|
toggle_section: "Toggle section visibility"
|
||||||
net_worth_chart:
|
net_worth_chart:
|
||||||
|
|||||||
Reference in New Issue
Block a user