mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-03 04:25:21 +02:00
Account namespace updates: part 5 (valuations) (#901)
* Move Valuation to Account namespace * Move account history to controller * Clean up valuation controller and views * Translations and cleanup * Remove unused scopes and methods * Pass brakeman
This commit is contained in:
parent
0bc0d87768
commit
12380dc8ad
45 changed files with 478 additions and 346 deletions
23
app/views/account/valuations/_form.html.erb
Normal file
23
app/views/account/valuations/_form.html.erb
Normal file
|
@ -0,0 +1,23 @@
|
|||
<%# locals: (valuation:) %>
|
||||
<%= form_with model: valuation,
|
||||
data: { turbo_frame: "_top" },
|
||||
url: valuation.new_record? ? account_valuations_path(valuation.account) : account_valuation_path(valuation.account, valuation),
|
||||
builder: ActionView::Helpers::FormBuilder do |f| %>
|
||||
<div class="grid grid-cols-10 p-4 items-center">
|
||||
<div class="col-span-7 flex items-center gap-4">
|
||||
<div class="w-8 h-8 rounded-full p-1.5 flex items-center justify-center bg-gray-500/5">
|
||||
<%= lucide_icon("pencil-line", class: "w-4 h-4 text-gray-500") %>
|
||||
</div>
|
||||
<div class="w-full flex items-center justify-between gap-2">
|
||||
<%= f.date_field :date, required: "required", max: Date.today, class: "border border-alpha-black-200 bg-white rounded-lg shadow-xs min-w-[200px] px-3 py-1.5 text-gray-900 text-sm" %>
|
||||
<%= f.number_field :value, required: "required", placeholder: "0.00", step: "0.01", class: "bg-white border border-alpha-black-200 rounded-lg shadow-xs text-gray-900 text-sm px-3 py-1.5 text-right" %>
|
||||
<%= f.hidden_field :currency, value: valuation.account.currency %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-3 flex gap-2 justify-end items-center">
|
||||
<%= link_to t(".cancel"), account_valuations_path(valuation.account), class: "text-sm text-gray-900 hover:text-gray-800 font-medium px-3 py-1.5" %>
|
||||
<%= f.submit class: "bg-gray-50 rounded-lg font-medium px-3 py-1.5 cursor-pointer hover:bg-gray-100 text-sm" %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
50
app/views/account/valuations/_valuation.html.erb
Normal file
50
app/views/account/valuations/_valuation.html.erb
Normal file
|
@ -0,0 +1,50 @@
|
|||
<%# locals: (valuation:) %>
|
||||
|
||||
<%= turbo_frame_tag dom_id(valuation) do %>
|
||||
<div class="p-4 grid grid-cols-10 items-center">
|
||||
<div class="col-span-5 flex items-center gap-4">
|
||||
<%= tag.div class: "w-8 h-8 rounded-full p-1.5 flex items-center justify-center", style: valuation_style(valuation).html_safe do %>
|
||||
<%= lucide_icon valuation_icon(valuation), class: "w-4 h-4" %>
|
||||
<% end %>
|
||||
|
||||
<div class="text-sm">
|
||||
<%= tag.p valuation.date, class: "text-gray-900 font-medium" %>
|
||||
<%= tag.p valuation.first_of_series? ? t(".start_balance") : t(".value_update"), class: "text-gray-500" %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-span-2 justify-self-end">
|
||||
<%= tag.p format_money(valuation.value_money), class: "font-medium text-sm text-gray-900" %>
|
||||
</div>
|
||||
|
||||
<div class="col-span-2 justify-self-end font-medium text-sm" style="color: <%= valuation.trend.color %>">
|
||||
<% if valuation.trend.direction.flat? %>
|
||||
<%= tag.span t(".no_change"), class: "text-gray-500" %>
|
||||
<% else %>
|
||||
<%= tag.span format_money(valuation.trend.value) %>
|
||||
<%= tag.span "(#{valuation.trend.percent}%)" %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="col-span-1 justify-self-end">
|
||||
<%= contextual_menu do %>
|
||||
<div class="w-48 p-1 text-sm leading-6 text-gray-900 bg-white shadow-lg shrink rounded-xl ring-1 ring-gray-900/5">
|
||||
<%= contextual_menu_modal_action_item t(".edit_entry"), edit_account_valuation_path(valuation.account, valuation) %>
|
||||
|
||||
<%= contextual_menu_destructive_item t(".delete_entry"),
|
||||
account_valuation_path(valuation.account, valuation),
|
||||
turbo_frame: "_top",
|
||||
turbo_confirm: {
|
||||
title: t(".confirm_title"),
|
||||
body: t(".confirm_body_html"),
|
||||
accept: t(".confirm_accept")
|
||||
} %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<% unless valuation.last_of_series? %>
|
||||
<div class="h-px bg-alpha-black-50 ml-16 mr-4"></div>
|
||||
<% end %>
|
||||
<% end %>
|
3
app/views/account/valuations/edit.html.erb
Normal file
3
app/views/account/valuations/edit.html.erb
Normal file
|
@ -0,0 +1,3 @@
|
|||
<%= turbo_frame_tag dom_id(@valuation) do %>
|
||||
<%= render "form", valuation: @valuation %>
|
||||
<% end %>
|
15
app/views/account/valuations/index.html.erb
Normal file
15
app/views/account/valuations/index.html.erb
Normal file
|
@ -0,0 +1,15 @@
|
|||
<%= turbo_frame_tag dom_id(@account, "valuations") do %>
|
||||
<div class="grid grid-cols-10 items-center uppercase text-xs font-medium text-gray-500 px-4 py-2">
|
||||
<%= tag.p t(".date"), class: "col-span-5" %>
|
||||
<%= tag.p t(".value"), class: "col-span-2 justify-self-end" %>
|
||||
<%= tag.p t(".change"), class: "col-span-2 justify-self-end" %>
|
||||
<%= tag.div class: "col-span-1" %>
|
||||
</div>
|
||||
|
||||
<div class="rounded-lg bg-white border-alpha-black-25 shadow-xs">
|
||||
<%= turbo_frame_tag dom_id(Account::Valuation.new) %>
|
||||
<% @account.valuations.reverse_chronological.each do |valuation| %>
|
||||
<%= render valuation %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
4
app/views/account/valuations/new.html.erb
Normal file
4
app/views/account/valuations/new.html.erb
Normal file
|
@ -0,0 +1,4 @@
|
|||
<%= turbo_frame_tag dom_id(@valuation) do %>
|
||||
<%= render "form", valuation: @valuation %>
|
||||
<div class="h-px bg-alpha-black-50 ml-20 mr-4"></div>
|
||||
<% end %>
|
1
app/views/account/valuations/show.html.erb
Normal file
1
app/views/account/valuations/show.html.erb
Normal file
|
@ -0,0 +1 @@
|
|||
<%= render "valuation", valuation: @valuation %>
|
|
@ -1,29 +0,0 @@
|
|||
<%# locals: (account:, valuations:) %>
|
||||
<div class="bg-white space-y-4 p-5 border border-alpha-black-25 rounded-xl shadow-xs">
|
||||
<div class="flex justify-between items-center">
|
||||
<h3 class="font-medium text-lg">History</h3>
|
||||
<%= link_to new_account_valuation_path(account), data: { turbo_frame: dom_id(Valuation.new) }, class: "flex gap-1 font-medium items-center bg-gray-50 text-gray-900 p-2 rounded-lg" do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-900") %>
|
||||
<span class="text-sm">New entry</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="rounded-xl bg-gray-25 p-1">
|
||||
<div class="flex flex-col rounded-lg space-y-1">
|
||||
<div class="text-xs font-medium text-gray-500 uppercase flex items-center px-4 py-2">
|
||||
<div class="w-16">date</div>
|
||||
<div class="flex items-center justify-between grow">
|
||||
<div></div>
|
||||
<div>value</div>
|
||||
</div>
|
||||
<div class="w-56 text-right">change</div>
|
||||
<div class="w-[72px]"></div>
|
||||
</div>
|
||||
<div class="rounded-lg bg-white border-alpha-black-25 shadow-xs">
|
||||
<%= turbo_frame_tag dom_id(Valuation.new) %>
|
||||
<%= turbo_frame_tag "valuations_list" do %>
|
||||
<%= render partial: "accounts/account_valuation_list", locals: { valuation_series: valuations } %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,57 +0,0 @@
|
|||
<%# locals: (valuation_series:) %>
|
||||
<% valuation_series.values.reverse_each.with_index do |valuation, index| %>
|
||||
<% valuation_styles = trend_styles(valuation.trend) %>
|
||||
<%= turbo_frame_tag dom_id(valuation.original) do %>
|
||||
<div class="p-4 flex items-center">
|
||||
<div class="w-16">
|
||||
<div class="w-8 h-8 rounded-full p-1.5 flex items-center justify-center <%= valuation_styles[:bg_class] %>">
|
||||
<%= lucide_icon(valuation_styles[:icon], class: "w-4 h-4 #{valuation_styles[:text_class]}") %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between grow">
|
||||
<div class="text-sm">
|
||||
<p><%= valuation.date %></p>
|
||||
<%# TODO: Add descriptive name of valuation %>
|
||||
<p class="text-gray-500">Manually entered</p>
|
||||
</div>
|
||||
<div class="flex text-sm font-medium text-right"><%= format_money valuation.value %></div>
|
||||
</div>
|
||||
<div class="flex w-56 justify-end text-right text-sm font-medium">
|
||||
<% if valuation.trend.value == 0 %>
|
||||
<span class="text-gray-500">No change</span>
|
||||
<% else %>
|
||||
<span class="<%= valuation_styles[:text_class] %>"><%= valuation_styles[:symbol] %><%= format_money valuation.trend.value.abs %></span>
|
||||
<span class="<%= valuation_styles[:text_class] %>">(<%= lucide_icon(valuation_styles[:icon], class: "w-4 h-4 align-text-bottom inline") %> <%= valuation.trend.percent %>%)</span>
|
||||
<% end %>
|
||||
</div>
|
||||
<div class="relative w-[72px]" data-controller="menu">
|
||||
<button
|
||||
data-menu-target="button"
|
||||
class="ml-auto flex items-center justify-center hover:bg-gray-50 w-8 h-8 rounded-lg">
|
||||
<%= lucide_icon("more-horizontal", class: "w-5 h-5 text-gray-500") %>
|
||||
</button>
|
||||
<div
|
||||
data-menu-target="content"
|
||||
class="absolute hidden min-w-[200px] z-10 top-10 right-0 bg-white p-1 rounded-sm shadow-xs border border-alpha-black-25 w-fit">
|
||||
<%= link_to edit_valuation_path(valuation.original),
|
||||
class: "flex gap-1 items-center hover:bg-gray-50 rounded-md p-2" do %>
|
||||
<%= lucide_icon("pencil-line", class: "w-5 h-5 text-gray-500 shrink-0") %>
|
||||
<span class="text-gray-900 text-sm">Edit entry</span>
|
||||
<% end %>
|
||||
<%= link_to valuation_path(valuation.original),
|
||||
data: { turbo_method: :delete,
|
||||
turbo_confirm: { title: t(".confirm_title"),
|
||||
body: t(".confirm_body_html"),
|
||||
accept: t(".confirm_accept") } },
|
||||
class: "text-red-600 flex gap-1 items-center hover:bg-gray-50 rounded-md p-2" do %>
|
||||
<%= lucide_icon("trash-2", class: "w-5 h-5 shrink-0") %>
|
||||
<span class="text-sm">Delete entry</span>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% unless index == valuation_series.values.size - 1 %>
|
||||
<div class="h-px bg-alpha-black-50 ml-20 mr-4"></div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
|
@ -56,11 +56,11 @@
|
|||
<div class="p-4 flex justify-between">
|
||||
<div class="space-y-2">
|
||||
<%= render partial: "shared/value_heading", locals: {
|
||||
label: "Total Value",
|
||||
period: @period,
|
||||
value: @account.balance_money,
|
||||
trend: @balance_series.trend
|
||||
} %>
|
||||
label: "Total Value",
|
||||
period: @period,
|
||||
value: @account.balance_money,
|
||||
trend: @balance_series.trend
|
||||
} %>
|
||||
</div>
|
||||
<%= form_with url: account_path(@account), method: :get, class: "flex items-center gap-4", data: { controller: "auto-submit-form" } do %>
|
||||
<%= render partial: "shared/period_select", locals: { value: @period.name } %>
|
||||
|
@ -77,7 +77,23 @@
|
|||
</div>
|
||||
<div class="min-h-[800px]">
|
||||
<div data-tabs-target="tab" id="account-history-tab">
|
||||
<%= render partial: "accounts/account_history", locals: { account: @account, valuations: @valuation_series } %>
|
||||
<div class="bg-white space-y-4 p-5 border border-alpha-black-25 rounded-xl shadow-xs">
|
||||
<div class="flex items-center justify-between">
|
||||
<%= tag.h2 t(".valuations"), class: "font-medium text-lg" %>
|
||||
<%= link_to new_account_valuation_path(@account), data: { turbo_frame: dom_id(Account::Valuation.new) }, class: "flex gap-1 font-medium items-center bg-gray-50 text-gray-900 p-2 rounded-lg" do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-900") %>
|
||||
<%= tag.span t(".new_entry"), class: "text-sm" %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl bg-gray-25 p-1">
|
||||
<%= turbo_frame_tag dom_id(@account, "valuations"), src: account_valuations_path(@account) do %>
|
||||
<div class="p-5 flex justify-center items-center">
|
||||
<%= tag.p t(".loading_history"), class: "text-gray-500 animate-pulse text-sm" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-tabs-target="tab" id="account-transactions-tab" class="hidden">
|
||||
<%= render partial: "accounts/transactions", locals: { account: @account, transactions: @account.transactions.order(date: :desc) } %>
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
<%# locals (f:, form_icon:, submit_button_text:)%>
|
||||
<div class="h-[72px] p-4 flex items-center">
|
||||
<div class="w-16">
|
||||
<div class="w-8 h-8 rounded-full p-1.5 flex items-center justify-center bg-gray-500/5">
|
||||
<%= lucide_icon(form_icon, class: "w-4 h-4 text-gray-500") %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center justify-between grow">
|
||||
<%= f.date_field :date, required: "required", max: Date.today, class: "border border-alpha-black-200 bg-white rounded-lg shadow-xs min-w-[200px] px-3 py-1.5 text-gray-900 text-sm" %>
|
||||
<%= f.number_field :value, required: "required", placeholder: "0.00", step: "0.01", class: "bg-white border border-alpha-black-200 rounded-lg shadow-xs text-gray-900 text-sm px-3 py-1.5 text-right" %>
|
||||
</div>
|
||||
<div class="w-[296px] flex gap-2 justify-end items-center">
|
||||
<%= link_to "Cancel", account_path(@valuation.account), class: "text-sm text-gray-900 hover:text-gray-800 font-medium px-3 py-1.5" %>
|
||||
<%= f.submit submit_button_text, class: "bg-gray-50 rounded-lg font-medium px-3 py-1.5 cursor-pointer hover:bg-gray-100 text-sm" %>
|
||||
</div>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<div>
|
||||
<h1 class="font-bold text-4xl">Valuations#create</h1>
|
||||
<p>Find me in app/views/valuations/create.html.erb</p>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<%= turbo_stream.replace Valuation.new, body: turbo_frame_tag(dom_id(Valuation.new)) %>
|
||||
<%= turbo_stream.append "notification-tray", partial: "shared/notification", locals: { type: "success", content: { body: "Valuation created" } } %>
|
||||
<%= turbo_stream.replace "valuations_list", partial: "accounts/account_valuation_list", locals: { valuation_series: @account.valuations.to_series } %>
|
||||
<%= turbo_stream.replace "sync_message", partial: "accounts/sync_message", locals: { is_syncing: true } %>
|
|
@ -1,4 +0,0 @@
|
|||
<div>
|
||||
<h1 class="font-bold text-4xl">Valuations#destroy</h1>
|
||||
<p>Find me in app/views/valuations/destroy.html.erb</p>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<%= turbo_stream.remove @valuation %>
|
||||
<%= turbo_stream.append "notification-tray", partial: "shared/notification", locals: { type: "success", content: { body: "Valuation deleted" } } %>
|
||||
<%= turbo_stream.replace "valuations_list", partial: "accounts/account_valuation_list", locals: { valuation_series: @account.valuations.to_series } %>
|
||||
<%= turbo_stream.replace "sync_message", partial: "accounts/sync_message", locals: { is_syncing: true } %>
|
|
@ -1,8 +0,0 @@
|
|||
<div>
|
||||
<h1 class="font-bold text-4xl">Edit Valuation</h1>
|
||||
<%= turbo_frame_tag dom_id(@valuation) do %>
|
||||
<%= form_with model: @valuation, url: valuation_path(@valuation), html: { class: "" } do |f| %>
|
||||
<%= render "form_row", f: f, form_icon: "pencil-line", submit_button_text: "Update" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
|
@ -1,9 +0,0 @@
|
|||
<div>
|
||||
<h1 class="font-bold text-4xl">Add Valuation: <%= @account.name %></h1>
|
||||
<%= turbo_frame_tag dom_id(Valuation.new) do %>
|
||||
<%= form_with model: [@account, @valuation], url: account_valuations_path(@account), html: { class: "" } do |f| %>
|
||||
<%= render "form_row", f: f, form_icon: "plus", submit_button_text: "Add" %>
|
||||
<% end %>
|
||||
<div class="h-px bg-alpha-black-50 ml-20 mr-4"></div>
|
||||
<% end %>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<div>
|
||||
<h1 class="font-bold text-4xl">Valuation: <%= @valuation.type %></h1>
|
||||
<p>Find me in app/views/valuations/show.html.erb</p>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<div>
|
||||
<h1 class="font-bold text-4xl">Valuations#update</h1>
|
||||
<p>Find me in app/views/valuations/update.html.erb</p>
|
||||
</div>
|
Loading…
Add table
Add a link
Reference in a new issue