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

Allow user to add buy and sell trade transactions for investment accounts (#1066)

* Consolidate modal form structure into partial + helper

* Scaffold out trade transaction form

* Normalize translations

* Add buy and sell trade form with tests

* Move entryable lists to dedicated controllers

* Delegate entry group contents rendering

* More cleanup

* Extract transaction and valuation update logic from entries controller

* Delegate edit and show actions to entryables

* Trade builder

* Update paths for transaction updates
This commit is contained in:
Zach Gollwitzer 2024-08-09 11:22:57 -04:00 committed by GitHub
parent 6bca35fa22
commit e05f03b314
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
75 changed files with 801 additions and 624 deletions

View file

@ -1,4 +1,5 @@
<%# locals: (entry:, **opts) %>
<%= turbo_frame_tag dom_id(entry) do %>
<%= render permitted_entryable_partial_path(entry, entry.entryable_name_short), entry: entry, **opts %>
<%= render partial: entry.entryable.to_partial_path, locals: { entry: entry, **opts } %>
<% end %>

View file

@ -1,4 +1,4 @@
<%# locals: (date:, entries:, selectable: true, combine_transfers: false, **opts) %>
<%# locals: (date:, entries:, content:, selectable:) %>
<div id="entry-group-<%= date %>" class="bg-gray-25 rounded-xl p-1 w-full" data-bulk-select-target="group">
<div class="py-2 px-4 flex items-center justify-between font-medium text-xs text-gray-500">
<div class="flex pl-0.5 items-center gap-4">
@ -15,11 +15,6 @@
<%= totals_by_currency(collection: entries, money_method: :amount_money, negate: true) %>
</div>
<div class="bg-white shadow-xs rounded-md border border-alpha-black-25 divide-y divide-alpha-black-50">
<% if combine_transfers %>
<%= render entries.reject { |e| e.transfer_id.present? }, selectable:, **opts %>
<%= render transfer_entries(entries), selectable: false, **opts %>
<% else %>
<%= render entries, selectable:, **opts %>
<% end %>
<%= content %>
</div>
</div>

View file

@ -1,3 +0,0 @@
<%= turbo_frame_tag dom_id(@entry) do %>
<%= render permitted_entryable_partial_path(@entry, "edit"), entry: @entry %>
<% end %>

View file

@ -1,15 +0,0 @@
<div class="fixed bottom-6 z-10 flex items-center justify-between rounded-xl bg-gray-900 px-4 text-sm text-white w-[420px] py-1.5">
<div class="flex items-center gap-2">
<%= check_box_tag "entry_selection", 1, true, class: "maybe-checkbox maybe-checkbox--dark", data: { action: "bulk-select#deselectAll" } %>
<p data-bulk-select-target="selectionBarText"></p>
</div>
<div class="flex items-center gap-1 text-gray-500">
<%= form_with url: bulk_delete_transactions_path, data: { turbo_confirm: true, turbo_frame: "_top" } do %>
<button type="button" data-bulk-select-scope-param="bulk_delete" data-action="bulk-select#submitBulkRequest" class="p-1.5 group hover:bg-gray-700 flex items-center justify-center rounded-md" title="Delete">
<%= lucide_icon "trash-2", class: "w-5 group-hover:text-white" %>
</button>
<% end %>
</div>
</div>

View file

@ -1,31 +0,0 @@
<%# locals: (entry:) %>
<% trade, account = entry.account_trade, entry.account %>
<%= drawer do %>
<div>
<header class="mb-4 space-y-1">
<div class="flex items-center gap-4">
<h3 class="font-medium">
<span class="text-2xl"><%= format_money -entry.amount_money %></span>
<span class="text-lg text-gray-500"><%= entry.currency %></span>
</h3>
</div>
<span class="text-sm text-gray-500"><%= entry.date.strftime("%A %d %B") %></span>
</header>
<div class="space-y-2">
<details class="group space-y-2" open>
<summary class="flex list-none items-center justify-between rounded-xl px-3 py-2 text-xs font-medium uppercase text-gray-500 bg-gray-25 focus-visible:outline-none">
<h4><%= t(".overview") %></h4>
<%= lucide_icon "chevron-down", class: "group-open:transform group-open:rotate-180 text-gray-500 w-5" %>
</summary>
<div class="pb-6 pl-4 text-gray-500">
<p>Details coming soon...</p>
</div>
</details>
</div>
</div>
<% end %>

View file

@ -1,41 +0,0 @@
<%# locals: (entry:, selectable: true, **opts) %>
<% trade, account = entry.account_trade, entry.account %>
<div class="grid grid-cols-12 items-center text-gray-900 text-sm font-medium p-4">
<div class="pr-10 flex items-center gap-4 col-span-6">
<% if selectable %>
<%= check_box_tag dom_id(entry, "selection"),
class: "maybe-checkbox maybe-checkbox--light",
data: { id: entry.id, "bulk-select-target": "row", action: "bulk-select#toggleRowSelection" } %>
<% end %>
<div class="max-w-full">
<%= tag.div class: ["flex items-center gap-2"] do %>
<div class="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-gray-600/5 text-gray-600">
<%= entry.name[0].upcase %>
</div>
<div class="truncate text-gray-900">
<% if entry.new_record? %>
<%= content_tag :p, entry.name %>
<% else %>
<%= link_to entry.name,
account_entry_path(account, entry),
data: { turbo_frame: "drawer", turbo_prefetch: false },
class: "hover:underline hover:text-gray-800" %>
<% end %>
</div>
<% end %>
</div>
</div>
<div class="flex items-center justify-end gap-1 col-span-3">
<%= tag.p trade.buy? ? t(".buy") : t(".sell") %>
</div>
<div class="col-span-3 flex items-center justify-end">
<%= tag.p format_money(entry.amount_money * -1), class: { "text-green-500": trade.sell? } %>
</div>
</div>

View file

@ -1,44 +0,0 @@
<div class="fixed bottom-6 z-10 flex items-center justify-between rounded-xl bg-gray-900 px-4 text-sm text-white w-[420px] py-1.5">
<div class="flex items-center gap-2">
<%= check_box_tag "entry_selection", 1, true, class: "maybe-checkbox maybe-checkbox--dark", data: { action: "bulk-select#deselectAll" } %>
<p data-bulk-select-target="selectionBarText"></p>
</div>
<div class="flex items-center gap-1 text-gray-500">
<%= turbo_frame_tag "bulk_transaction_edit_drawer" %>
<%= form_with url: mark_transfers_transactions_path,
scope: "bulk_update",
data: {
turbo_frame: "_top",
turbo_confirm: {
title: t(".mark_transfers"),
body: t(".mark_transfers_message"),
accept: t(".mark_transfers_confirm"),
}
} do |f| %>
<button id="bulk-transfer-btn"
type="button"
data-bulk-select-scope-param="bulk_update"
data-action="bulk-select#submitBulkRequest"
class="p-1.5 group hover:bg-gray-700 flex items-center justify-center rounded-md"
title="Mark as transfer">
<%= lucide_icon "arrow-right-left", class: "w-5 group-hover:text-white" %>
</button>
<% end %>
<%= link_to bulk_edit_transactions_path,
class: "p-1.5 group hover:bg-gray-700 flex items-center justify-center rounded-md",
title: "Edit",
data: { turbo_frame: "bulk_transaction_edit_drawer" } do %>
<%= lucide_icon "pencil-line", class: "w-5 group-hover:text-white" %>
<% end %>
<%= form_with url: bulk_delete_transactions_path, data: { turbo_confirm: true, turbo_frame: "_top" } do %>
<button type="button" data-bulk-select-scope-param="bulk_delete" data-action="bulk-select#submitBulkRequest" class="p-1.5 group hover:bg-gray-700 flex items-center justify-center rounded-md" title="Delete">
<%= lucide_icon "trash-2", class: "w-5 group-hover:text-white" %>
</button>
<% end %>
</div>
</div>

View file

@ -1,121 +0,0 @@
<%# locals: (entry:) %>
<% transaction, account = entry.account_transaction, entry.account %>
<%= drawer do %>
<div>
<header class="mb-4 space-y-1">
<div class="flex items-center gap-4">
<h3 class="font-medium">
<span class="text-2xl"><%= format_money -entry.amount_money %></span>
<span class="text-lg text-gray-500"><%= entry.currency %></span>
</h3>
<% if entry.marked_as_transfer? %>
<%= lucide_icon "arrow-left-right", class: "text-gray-500 mt-1 w-5 h-5" %>
<% end %>
</div>
<span class="text-sm text-gray-500"><%= entry.date.strftime("%A %d %B") %></span>
</header>
<div class="space-y-2">
<details class="group space-y-2" open>
<summary class="flex list-none items-center justify-between rounded-xl px-3 py-2 text-xs font-medium uppercase text-gray-500 bg-gray-25 focus-visible:outline-none">
<h4><%= t(".overview") %></h4>
<%= lucide_icon "chevron-down", class: "group-open:transform group-open:rotate-180 text-gray-500 w-5" %>
</summary>
<div class="pb-6">
<%= styled_form_with model: [account, entry], url: account_entry_path(account, entry), class: "space-y-2", data: { controller: "auto-submit-form" } do |f| %>
<%= f.text_field :name, label: t(".name_label"), "data-auto-submit-form-target": "auto" %>
<% unless entry.marked_as_transfer? %>
<div class="flex space-x-2">
<div>
<%= f.select :nature, [["Expense", "expense"], ["Income", "income"]], { label: t(".nature"), selected: entry.amount.negative? ? "income" : "expense" }, "data-auto-submit-form-target": "auto" %>
</div>
<div class="flex-grow">
<%= f.number_field :amount, value: entry.amount.abs, label: t(".amount"), step: "0.01", "data-auto-submit-form-target": "auto", "data-autosubmit-trigger-event": "change" %>
</div>
</div>
<% end %>
<%= f.date_field :date, label: t(".date_label"), max: Date.current, "data-auto-submit-form-target": "auto" %>
<%= f.fields_for :entryable do |ef| %>
<% unless entry.marked_as_transfer? %>
<%= ef.collection_select :category_id, Current.family.categories.alphabetically, :id, :name, { prompt: t(".category_placeholder"), label: t(".category_label"), class: "text-gray-400" }, "data-auto-submit-form-target": "auto" %>
<%= ef.collection_select :merchant_id, Current.family.merchants.alphabetically, :id, :name, { prompt: t(".merchant_placeholder"), label: t(".merchant_label"), class: "text-gray-400" }, "data-auto-submit-form-target": "auto" %>
<% end %>
<% end %>
<%= f.collection_select :account_id, Current.family.accounts.alphabetically, :id, :name, { prompt: t(".account_placeholder"), label: t(".account_label"), class: "text-gray-500" }, { class: "form-field__input cursor-not-allowed text-gray-400", disabled: "disabled" } %>
<% end %>
</div>
</details>
<details class="group space-y-2" open>
<summary class="flex list-none items-center justify-between rounded-xl px-3 py-2 text-xs font-medium uppercase text-gray-500 bg-gray-25 focus-visible:outline-none">
<h4><%= t(".additional") %></h4>
<%= lucide_icon "chevron-down", class: "group-open:transform group-open:rotate-180 text-gray-500 w-5" %>
</summary>
<div class="pb-6">
<%= styled_form_with model: [account, entry], url: account_entry_path(account, entry), class: "space-y-2", data: { controller: "auto-submit-form" } do |f| %>
<%= f.fields_for :entryable do |ef| %>
<%= ef.select :tag_ids,
options_for_select(Current.family.tags.alphabetically.pluck(:name, :id), transaction.tag_ids),
{
multiple: true,
label: t(".tags_label"),
class: "placeholder:text-gray-500"
},
"data-auto-submit-form-target": "auto" %>
<%= ef.text_area :notes, label: t(".note_label"), placeholder: t(".note_placeholder"), "data-auto-submit-form-target": "auto" %>
<% end %>
<% end %>
</div>
</details>
<details class="group space-y-2" open>
<summary class="flex list-none items-center justify-between rounded-xl px-3 py-2 text-xs font-medium uppercase text-gray-500 bg-gray-25 focus-visible:outline-none">
<h4><%= t(".settings") %></h4>
<%= lucide_icon "chevron-down", class: "group-open:transform group-open:rotate-180 text-gray-500 w-5" %>
</summary>
<div class="pb-6">
<%= styled_form_with model: [account, entry], url: account_entry_path(account, entry), class: "p-3 space-y-3", data: { controller: "auto-submit-form" } do |f| %>
<%= f.fields_for :entryable do |ef| %>
<div class="flex cursor-pointer items-center gap-2 justify-between">
<div class="text-sm space-y-1">
<h4 class="text-gray-900"><%= t(".exclude_title") %></h4>
<p class="text-gray-500"><%= t(".exclude_subtitle") %></p>
</div>
<div class="relative inline-block select-none">
<%= ef.check_box :excluded, class: "sr-only peer", "data-auto-submit-form-target": "auto" %>
<label for="account_entry_entryable_attributes_excluded" class="maybe-switch"></label>
</div>
</div>
<% end %>
<% end %>
<% unless entry.marked_as_transfer? %>
<div class="flex items-center justify-between gap-2 p-3">
<div class="text-sm space-y-1">
<h4 class="text-gray-900"><%= t(".delete_title") %></h4>
<p class="text-gray-500"><%= t(".delete_subtitle") %></p>
</div>
<%= button_to t(".delete"),
account_entry_path(account, entry),
method: :delete,
class: "rounded-lg px-3 py-2 text-red-500 text-sm font-medium border border-alpha-black-200",
data: { turbo_confirm: true, turbo_frame: "_top" } %>
</div>
<% end %>
</div>
</details>
</div>
</div>
<% end %>

View file

@ -1,97 +0,0 @@
<%# locals: (entry:, selectable: true, editable: true, short: false, show_tags: false, **opts) %>
<% transaction, account = entry.account_transaction, entry.account %>
<% is_investment_transfer = entry.account.investment? && entry.transfer.present? %>
<div class="grid grid-cols-12 items-center text-gray-900 text-sm font-medium p-4">
<% name_col_span = unconfirmed_transfer?(entry) ? "col-span-10" : short ? "col-span-6" : "col-span-4" %>
<div class="pr-10 flex items-center gap-4 <%= name_col_span %>">
<% if selectable %>
<%= check_box_tag dom_id(entry, "selection"),
class: "maybe-checkbox maybe-checkbox--light",
data: { id: entry.id, "bulk-select-target": "row", action: "bulk-select#toggleRowSelection" } %>
<% end %>
<div class="max-w-full">
<%= content_tag :div, class: ["flex items-center gap-2"] do %>
<div class="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-gray-600/5 text-gray-600">
<%= entry.name[0].upcase %>
</div>
<div class="truncate text-gray-900">
<% if entry.new_record? %>
<%= content_tag :p, entry.name %>
<% else %>
<%= link_to entry.name,
account_entry_path(account, entry),
data: { turbo_frame: "drawer", turbo_prefetch: false },
class: "hover:underline hover:text-gray-800" %>
<% end %>
</div>
<% end %>
</div>
<% if unconfirmed_transfer?(entry) %>
<% if editable %>
<%= form_with url: unmark_transfers_transactions_path, class: "flex items-center", data: {
turbo_confirm: {
title: t(".remove_transfer"),
body: t(".remove_transfer_body"),
accept: t(".remove_transfer_confirm"),
},
turbo_frame: "_top"
} do |f| %>
<%= f.hidden_field "bulk_update[entry_ids][]", value: entry.id %>
<%= f.button class: "flex items-center justify-center group", title: "Remove transfer" do %>
<%= lucide_icon "arrow-left-right", class: "group-hover:hidden text-gray-500 w-4 h-4" %>
<%= lucide_icon "unlink", class: "hidden group-hover:inline-block text-gray-900 w-4 h-4" %>
<% end %>
<% end %>
<% else %>
<%= lucide_icon "arrow-left-right", class: "text-gray-500 w-4 h-4" %>
<% end %>
<% end %>
</div>
<% if is_investment_transfer %>
<div class="col-span-5 text-right">
<%= tag.p entry.inflow? ? t(".deposit") : t(".withdrawal") %>
</div>
<% end %>
<% unless entry.marked_as_transfer? %>
<% unless short %>
<div class="flex items-center gap-1 <%= show_tags ? "col-span-6" : "col-span-3" %>">
<% if editable %>
<%= render "categories/menu", transaction: transaction %>
<% else %>
<%= render "categories/badge", category: transaction.category %>
<% end %>
<% if show_tags %>
<% transaction.tags.each do |tag| %>
<%= render partial: "tags/badge", locals: { tag: tag } %>
<% end %>
<% end %>
</div>
<% end %>
<% unless show_tags %>
<%= tag.div class: short ? "col-span-4" : "col-span-3" do %>
<% if entry.new_record? %>
<%= tag.p account.name %>
<% else %>
<%= link_to account.name,
account_path(account, tab: "transactions"),
data: { turbo_frame: "_top" },
class: "hover:underline" %>
<% end %>
<% end %>
<% end %>
<% end %>
<div class="<%= is_investment_transfer ? "col-span-3" : "col-span-2" %> ml-auto">
<%= content_tag :p,
format_money(-entry.amount_money),
class: ["text-green-600": entry.inflow?] %>
</div>
</div>

View file

@ -1 +0,0 @@
<%= render permitted_entryable_partial_path(entry, "form"), entry: entry %>

View file

@ -1,23 +0,0 @@
<%# locals: (entry:) %>
<%= form_with model: [entry.account, entry],
data: { turbo_frame: "_top" },
url: entry.new_record? ? account_entries_path(entry.account) : account_entry_path(entry.account, entry) 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", min: Account::Entry.min_supported_date, max: Date.current, 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 :amount, 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: entry.account.currency %>
<%= f.hidden_field :entryable_type, value: entry.entryable_type %>
</div>
</div>
<div class="col-span-3 flex gap-2 justify-end items-center">
<%= link_to t(".cancel"), valuation_account_entries_path(entry.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 %>

View file

@ -1,2 +0,0 @@
<%= render permitted_entryable_partial_path(entry, "form"), entry: entry %>
<div class="h-px bg-alpha-black-50 ml-20 mr-4"></div>

View file

@ -1 +0,0 @@
<%= render permitted_entryable_partial_path(@entry, "valuation"), entry: @entry %>

View file

@ -1,50 +0,0 @@
<%# locals: (entry:, **opts) %>
<% account = entry.account %>
<%= turbo_frame_tag dom_id(entry) do %>
<% is_oldest = entry.first_of_type? %>
<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: entry_style(entry, is_oldest:).html_safe do %>
<%= lucide_icon entry_icon(entry, is_oldest:), class: "w-4 h-4" %>
<% end %>
<div class="text-sm">
<%= tag.p entry.date, class: "text-gray-900 font-medium" %>
<%= tag.p is_oldest ? t(".start_balance") : t(".value_update"), class: "text-gray-500" %>
</div>
</div>
<div class="col-span-2 justify-self-end">
<%= tag.p format_money(entry.amount_money), class: "font-medium text-sm text-gray-900" %>
</div>
<div class="col-span-2 justify-self-end font-medium text-sm" style="color: <%= entry.trend.color %>">
<% if entry.trend.direction.flat? %>
<%= tag.span t(".no_change"), class: "text-gray-500" %>
<% else %>
<%= tag.span format_money(entry.trend.value) %>
<%= tag.span "(#{entry.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_entry_path(account, entry) %>
<%= contextual_menu_destructive_item t(".delete_entry"),
account_entry_path(account, entry),
turbo_frame: "_top",
turbo_confirm: {
title: t(".confirm_title"),
body: t(".confirm_body_html"),
accept: t(".confirm_accept")
} %>
</div>
<% end %>
</div>
</div>
<% end %>

View file

@ -1,3 +0,0 @@
<%= turbo_frame_tag dom_id(@entry) do %>
<%= render permitted_entryable_partial_path(@entry, "new"), entry: @entry %>
<% end %>

View file

@ -1 +0,0 @@
<%= render partial: permitted_entryable_partial_path(@entry, "show"), locals: { entry: @entry } %>

View file

@ -1,42 +0,0 @@
<%= turbo_frame_tag dom_id(@account, "trades") do %>
<div id="trades" data-controller="bulk-select" data-bulk-select-resource-value="<%= t(".trade") %>" 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"><%= t(".trades") %></h3>
<%= link_to new_account_entry_path(@account),
disabled: true,
class: "cursor-not-allowed flex gap-1 font-medium items-center bg-gray-50 text-gray-900 p-2 rounded-lg",
data: { turbo_frame: :modal } do %>
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-900") %>
<span class="text-sm"><%= t(".new") %></span>
<% end %>
</div>
<div class="bg-gray-25 rounded-xl grid grid-cols-12 items-center uppercase text-xs font-medium text-gray-500 px-5 py-3">
<div class="pl-0.5 col-span-6 flex items-center gap-4">
<%= check_box_tag "selection_entry",
class: "maybe-checkbox maybe-checkbox--light",
data: { action: "bulk-select#togglePageSelection" } %>
<%= tag.p t(".trade") %>
</div>
<%= tag.p t(".type"), class: "col-span-3 justify-self-end" %>
<%= tag.p t(".amount"), class: "col-span-3 justify-self-end" %>
</div>
<div>
<div hidden id="transaction-selection-bar" data-bulk-select-target="selectionBar">
<%= render "account/entries/entryables/trade/selection_bar" %>
</div>
<% if @trades.empty? %>
<p class="text-gray-500 py-4"><%= t(".no_trades") %></p>
<% else %>
<div class="space-y-6">
<% @trades.group_by(&:date).each do |date, entries| %>
<%= render "entry_group", date:, entries: entries %>
<% end %>
</div>
<% end %>
</div>
</div>
<% end %>

View file

@ -1,29 +0,0 @@
<%= turbo_frame_tag dom_id(@account, "transactions") do %>
<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"><%= t(".transactions") %></h3>
<%= link_to new_transaction_path(account_id: @account),
class: "flex gap-1 font-medium items-center bg-gray-50 text-gray-900 p-2 rounded-lg",
data: { turbo_frame: :modal } do %>
<%= lucide_icon("plus", class: "w-5 h-5 text-gray-900") %>
<span class="text-sm"><%= t(".new") %></span>
<% end %>
</div>
<div id="transactions" data-controller="bulk-select" data-bulk-select-resource-value="<%= t(".transaction") %>">
<div hidden id="transaction-selection-bar" data-bulk-select-target="selectionBar">
<%= render "account/entries/entryables/transaction/selection_bar" %>
</div>
<% if @transaction_entries.empty? %>
<p class="text-gray-500 py-4"><%= t(".no_transactions") %></p>
<% else %>
<div class="space-y-6">
<% @transaction_entries.group_by(&:date).each do |date, entries| %>
<%= render "entry_group", date:, entries: entries %>
<% end %>
</div>
<% end %>
</div>
</div>
<% end %>

View file

@ -1,35 +0,0 @@
<%= turbo_frame_tag dom_id(@account, "valuations") do %>
<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_entry_path(@account, entryable_type: "Account::Valuation"),
data: { turbo_frame: dom_id(@account.entries.account_valuations.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">
<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.entries.account_valuations.new) %>
<% if @valuation_entries.any? %>
<%= render partial: "account/entries/entryables/valuation/valuation",
collection: @valuation_entries,
as: :entry,
spacer_template: "ruler" %>
<% else %>
<p class="text-gray-500 text-sm p-4"><%= t(".no_valuations") %></p>
<% end %>
</div>
</div>
</div>
<% end %>