diff --git a/app/controllers/accounts_controller.rb b/app/controllers/accounts_controller.rb index e1c4d234..d2a834dc 100644 --- a/app/controllers/accounts_controller.rb +++ b/app/controllers/accounts_controller.rb @@ -10,6 +10,21 @@ class AccountsController < ApplicationController def show @account = Current.family.accounts.find(params[:id]) + + @period = Period.find_by_name(params[:period]) + if @period.nil? + start_date = params[:start_date].presence&.to_date + end_date = params[:end_date].presence&.to_date + if start_date.is_a?(Date) && end_date.is_a?(Date) && start_date <= end_date + @period = Period.new(name: "custom", date_range: start_date..end_date) + else + params[:period] = "last_30_days" + @period = Period.find_by_name(params[:period]) + end + end + + @balance_series = @account.balance_series(@period) + @valuation_series = @account.valuation_series end def create diff --git a/app/controllers/valuations_controller.rb b/app/controllers/valuations_controller.rb index 6e9bc9ef..e73c6287 100644 --- a/app/controllers/valuations_controller.rb +++ b/app/controllers/valuations_controller.rb @@ -4,8 +4,8 @@ class ValuationsController < ApplicationController def create @account = Current.family.accounts.find(params[:account_id]) - # TODO: handle STI once we allow for different types of valuations - @valuation = @account.valuations.new(valuation_params.merge(type: "Appraisal", currency: Current.family.currency)) + # TODO: placeholder logic until we have a better abstraction for trends + @valuation = @account.valuations.new(valuation_params.merge(currency: Current.family.currency)) if @valuation.save respond_to do |format| format.html { redirect_to account_path(@account), notice: "Valuation created" } @@ -41,11 +41,11 @@ class ValuationsController < ApplicationController def destroy @valuation = Valuation.find(params[:id]) - account = @valuation.account + @account = @valuation.account @valuation.destroy respond_to do |format| - format.html { redirect_to account_path(account), notice: "Valuation deleted" } + format.html { redirect_to account_path(@account), notice: "Valuation deleted" } format.turbo_stream end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index e87992e7..15f075de 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -49,8 +49,8 @@ module ApplicationHelper end # Styles to use when displaying a change in value - def trend_styles(trend_direction) - bg_class, text_class, symbol, icon = case trend_direction + def trend_styles(trend) + bg_class, text_class, symbol, icon = case trend.direction when "up" [ "bg-green-500/5", "text-green-500", "+", "arrow-up" ] when "down" @@ -58,14 +58,19 @@ module ApplicationHelper when "flat" [ "bg-gray-500/5", "text-gray-500", "", "minus" ] else - raise ArgumentError, "Invalid trend direction: #{trend_direction}" + raise ArgumentError, "Invalid trend direction: #{trend.direction}" end { bg_class: bg_class, text_class: text_class, symbol: symbol, icon: icon } end - def trend_label(date_range) - start_date, end_date = date_range.values_at(:start, :end) + def trend_label(period) + return "since account creation" if period.date_range.nil? + start_date, end_date = period.date_range.first, period.date_range.last + + return "Starting from #{start_date.strftime('%b %d, %Y')}" if end_date.nil? + return "Ending at #{end_date.strftime('%b %d, %Y')}" if start_date.nil? + days_apart = (end_date - start_date).to_i case days_apart diff --git a/app/javascript/controllers/line_chart_controller.js b/app/javascript/controllers/line_chart_controller.js index e38a43b9..ffd7f099 100644 --- a/app/javascript/controllers/line_chart_controller.js +++ b/app/javascript/controllers/line_chart_controller.js @@ -36,30 +36,20 @@ export default class extends Controller { }[trendDirection]; } - /** - * @param {Array} balances - An array of objects where each object represents a balance entry. Each object should have the following properties: - * - date: {Date} The date of the balance entry. - * - value: {number} The numerical value of the balance. - * - formatted: {string} The formatted string representation of the balance value. - * - trend: {Object} An object containing information about the trend compared to the previous balance entry. It should have: - * - amount: {number} The numerical difference in value from the previous entry. - * - direction: {string} A string indicating the direction of the trend ("up", "down", or "flat"). - * - percent: {number} The percentage change from the previous entry. - */ drawChart(balances) { const data = balances.map((b) => ({ - ...b, - value: +b.value, - date: new Date(b.date), + date: new Date(b.data.date + "T00:00:00"), + value: +b.data.balance, styles: this.trendStyles(b.trend.direction), + trend: b.trend, formatted: { value: Intl.NumberFormat("en-US", { style: "currency", - currency: b.currency || "USD", - }).format(b.value), + currency: b.data.currency || "USD", + }).format(b.data.balance), change: Intl.NumberFormat("en-US", { style: "currency", - currency: b.currency || "USD", + currency: b.data.currency || "USD", signDisplay: "always", }).format(b.trend.amount), }, @@ -87,7 +77,7 @@ export default class extends Controller { ]) .attr("style", "max-width: 100%; height: auto; height: intrinsic;"); - const margin = { top: 20, right: 0, bottom: 30, left: 0 }, + const margin = { top: 20, right: 1, bottom: 30, left: 1 }, width = +svg.attr("width") - margin.left - margin.right, height = +svg.attr("height") - margin.top - margin.bottom, g = svg @@ -216,7 +206,7 @@ export default class extends Controller { .html( `