mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-09 15:35:22 +02:00
Account:: namespace simplifications and cleanup (#2110)
* Flatten Holding model * Flatten balance model * Entries domain renames * Fix valuations reference * Fix trades stream * Fix brakeman warnings * Fix tests * Replace existing entryable type references in DB
This commit is contained in:
parent
f181ba941f
commit
e657c40d19
172 changed files with 1297 additions and 1258 deletions
57
app/views/transactions/_form.html.erb
Normal file
57
app/views/transactions/_form.html.erb
Normal file
|
@ -0,0 +1,57 @@
|
|||
<%= styled_form_with model: @entry, url: transactions_path, class: "space-y-4" do |f| %>
|
||||
|
||||
<% if entry.errors.any? %>
|
||||
<%= render "shared/form_errors", model: entry %>
|
||||
<% end %>
|
||||
|
||||
<section>
|
||||
<fieldset class="bg-gray-50 rounded-lg p-1 grid grid-flow-col justify-stretch gap-x-2">
|
||||
<%= radio_tab_tag form: f, name: :nature, value: :outflow, label: t(".expense"), icon: "minus-circle", checked: params[:nature] == "outflow" || params[:nature].nil? %>
|
||||
<%= radio_tab_tag form: f, name: :nature, value: :inflow, label: t(".income"), icon: "plus-circle", checked: params[:nature] == "inflow" %>
|
||||
<%= link_to new_transfer_path, data: { turbo_frame: :modal }, class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-subdued group-has-checked:bg-container group-has-checked:text-gray-800 group-has-checked:shadow-sm" do %>
|
||||
<%= lucide_icon "arrow-right-left", class: "w-5 h-5" %>
|
||||
<%= tag.span t(".transfer") %>
|
||||
<% end %>
|
||||
</fieldset>
|
||||
</section>
|
||||
|
||||
<section class="space-y-2 overflow-hidden">
|
||||
<%= f.text_field :name, label: t(".description"), placeholder: t(".description_placeholder"), required: true %>
|
||||
|
||||
<%= f.hidden_field :entryable_type, value: "Transaction" %>
|
||||
|
||||
<% if @entry.account_id %>
|
||||
<%= f.hidden_field :account_id %>
|
||||
<% else %>
|
||||
<%= f.collection_select :account_id, Current.family.accounts.manual.alphabetically, :id, :name, { prompt: t(".account_prompt"), label: t(".account") }, required: true, class: "form-field__input text-ellipsis" %>
|
||||
<% end %>
|
||||
|
||||
<%= f.money_field :amount, label: t(".amount"), required: true %>
|
||||
<%= f.fields_for :entryable do |ef| %>
|
||||
<%= ef.collection_select :category_id, Current.family.categories.alphabetically, :id, :name, { prompt: t(".category_prompt"), label: t(".category") } %>
|
||||
<% end %>
|
||||
<%= f.date_field :date, label: t(".date"), required: true, min: Entry.min_supported_date, max: Date.current, value: Date.current %>
|
||||
</section>
|
||||
|
||||
<%= disclosure t(".details"), default_open: false do %>
|
||||
<%= f.fields_for :entryable do |ef| %>
|
||||
<%= ef.select :tag_ids,
|
||||
Current.family.tags.alphabetically.pluck(:name, :id),
|
||||
{
|
||||
include_blank: t(".none"),
|
||||
multiple: true,
|
||||
label: t(".tags_label"),
|
||||
container_class: "h-40"
|
||||
}%>
|
||||
<% end %>
|
||||
<%= f.text_area :notes,
|
||||
label: t(".note_label"),
|
||||
placeholder: t(".note_placeholder"),
|
||||
rows: 5,
|
||||
"data-auto-submit-form-target": "auto" %>
|
||||
<% end %>
|
||||
|
||||
<section>
|
||||
<%= f.submit t(".submit") %>
|
||||
</section>
|
||||
<% end %>
|
|
@ -1,23 +1,23 @@
|
|||
<header class="flex justify-between items-center text-primary font-medium">
|
||||
<h1 class="text-xl">Transactions</h1>
|
||||
<div class="flex items-center gap-5">
|
||||
<div class="flex items-center gap-2">
|
||||
<%= contextual_menu do %>
|
||||
<%= contextual_menu_modal_action_item t(".edit_categories"), categories_path, icon: "shapes", turbo_frame: :_top %>
|
||||
<%= contextual_menu_modal_action_item t(".edit_tags"), tags_path, icon: "tags", turbo_frame: :_top %>
|
||||
<%= contextual_menu_modal_action_item t(".edit_merchants"), merchants_path, icon: "store", turbo_frame: :_top %>
|
||||
<%= contextual_menu_modal_action_item t(".edit_imports"), imports_path, icon: "hard-drive-upload", turbo_frame: :_top %>
|
||||
<% end %>
|
||||
<%# locals: (entry:) %>
|
||||
|
||||
<%= link_to new_import_path, class: "btn btn--outline flex items-center gap-2", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("download", class: "text-secondary w-4 h-4") %>
|
||||
<p class="text-sm font-medium text-primary"><%= t(".import") %></p>
|
||||
<% end %>
|
||||
<%= tag.header class: "mb-4 space-y-1", id: dom_id(entry, :header) do %>
|
||||
<div class="flex items-center gap-4">
|
||||
<h3 class="font-medium">
|
||||
<span class="text-2xl">
|
||||
<%= format_money -entry.amount_money %>
|
||||
</span>
|
||||
|
||||
<%= link_to new_account_transaction_path, class: "btn btn--primary flex items-center gap-2", data: { turbo_frame: :modal } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<p class="text-sm font-medium">New transaction</p>
|
||||
<% end %>
|
||||
</div>
|
||||
<span class="text-lg text-secondary">
|
||||
<%= entry.currency %>
|
||||
</span>
|
||||
</h3>
|
||||
|
||||
<% if entry.transaction.transfer? %>
|
||||
<%= lucide_icon "arrow-left-right", class: "text-secondary mt-1 w-5 h-5" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<span class="text-sm text-secondary">
|
||||
<%= I18n.l(entry.date, format: :long) %>
|
||||
</span>
|
||||
<% end %>
|
||||
|
|
23
app/views/transactions/_selection_bar.html.erb
Normal file
23
app/views/transactions/_selection_bar.html.erb
Normal file
|
@ -0,0 +1,23 @@
|
|||
<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: "checkbox checkbox--dark", data: { action: "bulk-select#deselectAll" } %>
|
||||
|
||||
<p data-bulk-select-target="selectionBarText"></p>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-1 text-secondary">
|
||||
<%= turbo_frame_tag "bulk_transaction_edit_drawer" %>
|
||||
<%= link_to new_transactions_bulk_update_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: transactions_bulk_deletion_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>
|
98
app/views/transactions/_transaction.html.erb
Normal file
98
app/views/transactions/_transaction.html.erb
Normal file
|
@ -0,0 +1,98 @@
|
|||
<%# locals: (entry:, balance_trend: nil, view_ctx: "global") %>
|
||||
|
||||
<% transaction = entry.entryable %>
|
||||
|
||||
<%= turbo_frame_tag dom_id(entry) do %>
|
||||
<%= turbo_frame_tag dom_id(transaction) do %>
|
||||
<div class="grid grid-cols-12 items-center text-primary text-sm font-medium p-4
|
||||
<%= @focused_record == entry || @focused_record == transaction ?
|
||||
"border border-gray-900 rounded-lg" : "" %>">
|
||||
|
||||
<div class="pr-10 flex items-center gap-4
|
||||
<%= balance_trend ? "col-span-6" : "col-span-8" %>">
|
||||
<%= check_box_tag dom_id(entry, "selection"),
|
||||
disabled: transaction.transfer?,
|
||||
class: "checkbox checkbox--light",
|
||||
data: {
|
||||
id: entry.id,
|
||||
"bulk-select-target": "row",
|
||||
action: "bulk-select#toggleRowSelection"
|
||||
} %>
|
||||
|
||||
<div class="max-w-full">
|
||||
<%= content_tag :div, class: ["flex items-center gap-2"] do %>
|
||||
<% if transaction.merchant&.icon_url %>
|
||||
<%= image_tag transaction.merchant.icon_url,
|
||||
class: "w-6 h-6 rounded-full",
|
||||
loading: "lazy" %>
|
||||
<% else %>
|
||||
<%= render "shared/circle_logo",
|
||||
name: entry.display_name,
|
||||
size: "sm" %>
|
||||
<% end %>
|
||||
|
||||
<div class="truncate">
|
||||
<div class="space-y-0.5">
|
||||
<div class="flex items-center gap-1">
|
||||
<%= link_to(
|
||||
transaction.transfer? ? transaction.transfer.name : entry.display_name,
|
||||
transaction.transfer? ? transfer_path(transaction.transfer) : entry_path(entry),
|
||||
data: {
|
||||
turbo_frame: "drawer",
|
||||
turbo_prefetch: false
|
||||
},
|
||||
class: "hover:underline hover:text-gray-800"
|
||||
) %>
|
||||
|
||||
<% if entry.excluded %>
|
||||
<span title="One-time <%= entry.amount.negative? ? "income" : "expense" %> (excluded from averages)">
|
||||
<%= lucide_icon "asterisk", class: "w-4 h-4 shrink-0 text-orange-500" %>
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
<% if transaction.transfer? %>
|
||||
<%= render "transactions/transfer_match", transaction: transaction %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="text-secondary text-xs font-normal">
|
||||
<% if transaction.transfer? %>
|
||||
<%= render "transfers/account_links",
|
||||
transfer: transaction.transfer,
|
||||
is_inflow: transaction.transfer_as_inflow.present? %>
|
||||
<% else %>
|
||||
<%= link_to entry.account.name,
|
||||
account_path(entry.account, tab: "transactions", focused_record_id: entry.id),
|
||||
data: { turbo_frame: "_top" },
|
||||
class: "hover:underline" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center gap-1 col-span-2">
|
||||
<%= render "transactions/transaction_category", transaction: transaction %>
|
||||
</div>
|
||||
|
||||
<div class="col-span-2 ml-auto">
|
||||
<%= content_tag :p,
|
||||
transaction.transfer? && view_ctx == "global" ? "+/- #{format_money(entry.amount_money.abs)}" : format_money(-entry.amount_money),
|
||||
class: ["text-green-600": entry.amount.negative?] %>
|
||||
</div>
|
||||
|
||||
<% if balance_trend %>
|
||||
<div class="col-span-2 justify-self-end">
|
||||
<% if balance_trend.trend %>
|
||||
<%= tag.p format_money(balance_trend.trend.current),
|
||||
class: "font-medium text-sm text-primary" %>
|
||||
<% else %>
|
||||
<%= tag.p "--", class: "font-medium text-sm text-gray-400" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
9
app/views/transactions/_transaction_category.html.erb
Normal file
9
app/views/transactions/_transaction_category.html.erb
Normal file
|
@ -0,0 +1,9 @@
|
|||
<%# locals: (transaction:) %>
|
||||
|
||||
<div id="<%= dom_id(transaction, "category_menu") %>">
|
||||
<% if transaction.transfer&.categorizable? || transaction.transfer.nil? %>
|
||||
<%= render "categories/menu", transaction: transaction %>
|
||||
<% else %>
|
||||
<%= render "categories/badge", category: transaction.transfer&.payment? ? payment_category : transfer_category %>
|
||||
<% end %>
|
||||
</div>
|
28
app/views/transactions/_transfer_match.html.erb
Normal file
28
app/views/transactions/_transfer_match.html.erb
Normal file
|
@ -0,0 +1,28 @@
|
|||
<%# locals: (transaction:) %>
|
||||
|
||||
<div id="<%= dom_id(transaction, "transfer_match") %>" class="flex items-center gap-1">
|
||||
<% if transaction.transfer.confirmed? %>
|
||||
<span title="<%= transaction.transfer.payment? ? "Payment" : "Transfer" %> is confirmed">
|
||||
<%= lucide_icon "link-2", class: "w-4 h-4 text-indigo-600" %>
|
||||
</span>
|
||||
<% elsif transaction.transfer.pending? %>
|
||||
<span class="inline-flex items-center rounded-full bg-indigo-50 px-2 py-0.5 text-xs font-medium text-indigo-700">
|
||||
Auto-matched
|
||||
</span>
|
||||
|
||||
<%= button_to transfer_path(transaction.transfer, transfer: { status: "confirmed" }),
|
||||
method: :patch,
|
||||
class: "text-secondary hover:text-gray-800 flex items-center justify-center cursor-pointer",
|
||||
title: "Confirm match" do %>
|
||||
<%= lucide_icon "check", class: "w-4 h-4 text-indigo-400 hover:text-indigo-600" %>
|
||||
<% end %>
|
||||
|
||||
<%= button_to transfer_path(transaction.transfer, transfer: { status: "rejected" }),
|
||||
method: :patch,
|
||||
data: { turbo: false },
|
||||
class: "text-secondary hover:text-gray-800 flex items-center justify-center cursor-pointer",
|
||||
title: "Reject match" do %>
|
||||
<%= lucide_icon "x", class: "w-4 h-4 text-subdued hover:text-gray-600" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
63
app/views/transactions/bulk_updates/new.html.erb
Normal file
63
app/views/transactions/bulk_updates/new.html.erb
Normal file
|
@ -0,0 +1,63 @@
|
|||
<%= turbo_frame_tag "bulk_transaction_edit_drawer" do %>
|
||||
<dialog data-controller="modal"
|
||||
data-action="mousedown->modal#clickOutside"
|
||||
class="bg-container shadow-border-xs rounded-2xl max-h-[calc(100vh-32px)] h-full max-w-[480px] w-full mt-4 mr-4 ml-auto">
|
||||
<%= styled_form_with url: transactions_bulk_update_path, scope: "bulk_update", class: "h-full", data: { turbo_frame: "_top" } do |form| %>
|
||||
<div class="flex h-full flex-col justify-between p-4 gap-4">
|
||||
<div>
|
||||
<div class="flex h-9 items-center justify-end">
|
||||
<div data-action="mousedown->modal#close" class="cursor-pointer">
|
||||
<%= lucide_icon("x", class: "w-5 h-5 shrink-0") %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col overflow-scroll">
|
||||
<div>
|
||||
<header class="mb-4 space-y-1">
|
||||
<h3 class="text-2xl font-medium" data-bulk-select-target="bulkEditDrawerTitle">
|
||||
Edit transactions
|
||||
</h3>
|
||||
</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-secondary bg-gray-25 focus-visible:outline-hidden">
|
||||
<h4>Overview</h4>
|
||||
<%= lucide_icon "chevron-down", class: "group-open:transform group-open:rotate-180 text-secondary w-5" %>
|
||||
</summary>
|
||||
|
||||
<div class="pb-6 space-y-2">
|
||||
<%= form.date_field :date, label: "Date", max: Date.current %>
|
||||
</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-secondary bg-gray-25 focus-visible:outline-hidden">
|
||||
<h4>Details</h4>
|
||||
<%= lucide_icon "chevron-down", class: "group-open:transform group-open:rotate-180 text-secondary w-5" %>
|
||||
</summary>
|
||||
|
||||
<div class="space-y-2">
|
||||
<%= form.collection_select :category_id, Current.family.categories.alphabetically, :id, :name, { prompt: "Select a category", label: "Category", class: "text-subdued" } %>
|
||||
<%= form.collection_select :merchant_id, Current.family.merchants.alphabetically, :id, :name, { prompt: "Select a merchant", label: "Merchant", class: "text-subdued" } %>
|
||||
<%= form.select :tag_ids, Current.family.tags.alphabetically.pluck(:name, :id), { include_blank: "None", multiple: true, label: "Tags", container_class: "h-40" } %>
|
||||
<%= form.text_area :notes, label: "Notes", placeholder: "Enter a note that will be applied to selected transactions", rows: 5 %>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-end items-center gap-2">
|
||||
<%= link_to "Cancel", transactions_path, class: "btn btn--ghost" %>
|
||||
|
||||
<%= tag.button "Save",
|
||||
type: "button",
|
||||
data: { "bulk-select-scope-param": "bulk_update", action: "bulk-select#submitBulkRequest" },
|
||||
class: "btn btn--primary" %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</dialog>
|
||||
<% end %>
|
|
@ -1,5 +1,27 @@
|
|||
<div class="space-y-4 pb-20 flex flex-col" data-controller="focus-record" data-focus-record-id-value="<%= @focused_record ? dom_id(@focused_record) : nil %>">
|
||||
<%= render "header" %>
|
||||
<header class="flex justify-between items-center text-primary font-medium">
|
||||
<h1 class="text-xl">Transactions</h1>
|
||||
<div class="flex items-center gap-5">
|
||||
<div class="flex items-center gap-2">
|
||||
<%= contextual_menu do %>
|
||||
<%= contextual_menu_modal_action_item t(".edit_categories"), categories_path, icon: "shapes", turbo_frame: :_top %>
|
||||
<%= contextual_menu_modal_action_item t(".edit_tags"), tags_path, icon: "tags", turbo_frame: :_top %>
|
||||
<%= contextual_menu_modal_action_item t(".edit_merchants"), merchants_path, icon: "store", turbo_frame: :_top %>
|
||||
<%= contextual_menu_modal_action_item t(".edit_imports"), imports_path, icon: "hard-drive-upload", turbo_frame: :_top %>
|
||||
<% end %>
|
||||
|
||||
<%= link_to new_import_path, class: "btn btn--outline flex items-center gap-2", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("download", class: "text-secondary w-4 h-4") %>
|
||||
<p class="text-sm font-medium text-primary"><%= t(".import") %></p>
|
||||
<% end %>
|
||||
|
||||
<%= link_to new_transaction_path, class: "btn btn--primary flex items-center gap-2", data: { turbo_frame: :modal } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<p class="text-sm font-medium">New transaction</p>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<%= render "summary", totals: @totals %>
|
||||
|
||||
|
@ -11,7 +33,7 @@
|
|||
<%= render "transactions/searches/search" %>
|
||||
|
||||
<div id="entry-selection-bar" data-bulk-select-target="selectionBar" class="flex justify-center hidden">
|
||||
<%= render "account/transactions/selection_bar" %>
|
||||
<%= render "transactions/selection_bar" %>
|
||||
</div>
|
||||
|
||||
<% if @pagy.count > 0 %>
|
||||
|
@ -34,7 +56,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= render "account/entries/empty" %>
|
||||
<%= render "entries/empty" %>
|
||||
<% end %>
|
||||
|
||||
<div class="pt-4">
|
||||
|
|
3
app/views/transactions/new.html.erb
Normal file
3
app/views/transactions/new.html.erb
Normal file
|
@ -0,0 +1,3 @@
|
|||
<%= modal_form_wrapper title: "New transaction" do %>
|
||||
<%= render "form", entry: @entry %>
|
||||
<% end %>
|
151
app/views/transactions/show.html.erb
Normal file
151
app/views/transactions/show.html.erb
Normal file
|
@ -0,0 +1,151 @@
|
|||
<%= drawer(reload_on_close: true) do %>
|
||||
<%= render "transactions/header", entry: @entry %>
|
||||
|
||||
<div class="space-y-2">
|
||||
<!-- Overview Section -->
|
||||
<%= disclosure t(".overview") do %>
|
||||
<div class="pb-4">
|
||||
<%= styled_form_with model: @entry,
|
||||
url: transaction_path(@entry),
|
||||
class: "space-y-2",
|
||||
data: { controller: "auto-submit-form" } do |f| %>
|
||||
|
||||
<%= f.text_field @entry.enriched_at.present? ? :enriched_name : :name,
|
||||
label: t(".name_label"),
|
||||
"data-auto-submit-form-target": "auto" %>
|
||||
|
||||
<%= f.date_field :date,
|
||||
label: t(".date_label"),
|
||||
max: Date.current,
|
||||
"data-auto-submit-form-target": "auto" %>
|
||||
|
||||
<% unless @entry.transaction.transfer? %>
|
||||
<div class="flex items-center gap-2">
|
||||
<%= f.select :nature,
|
||||
[["Expense", "outflow"], ["Income", "inflow"]],
|
||||
{ container_class: "w-1/3", label: t(".nature"), selected: @entry.amount.negative? ? "inflow" : "outflow" },
|
||||
{ data: { "auto-submit-form-target": "auto" } } %>
|
||||
|
||||
<%= f.money_field :amount, label: t(".amount"),
|
||||
container_class: "w-2/3",
|
||||
auto_submit: true,
|
||||
min: 0,
|
||||
value: @entry.amount.abs %>
|
||||
</div>
|
||||
|
||||
<%= f.fields_for :entryable do |ef| %>
|
||||
<%= ef.collection_select :category_id,
|
||||
Current.family.categories.alphabetically,
|
||||
:id, :name,
|
||||
{ label: t(".category_label"),
|
||||
class: "text-subdued", include_blank: t(".uncategorized") },
|
||||
"data-auto-submit-form-target": "auto" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- Details Section -->
|
||||
<%= disclosure t(".details"), default_open: false do %>
|
||||
<div class="pb-4">
|
||||
<%= styled_form_with model: @entry,
|
||||
url: transaction_path(@entry),
|
||||
class: "space-y-2",
|
||||
data: { controller: "auto-submit-form" } do |f| %>
|
||||
<% unless @entry.transaction.transfer? %>
|
||||
<%= f.select :account,
|
||||
options_for_select(
|
||||
Current.family.accounts.alphabetically.pluck(:name, :id),
|
||||
@entry.account_id
|
||||
),
|
||||
{ label: t(".account_label") },
|
||||
{ disabled: true } %>
|
||||
|
||||
<%= f.fields_for :entryable do |ef| %>
|
||||
|
||||
<%= ef.collection_select :merchant_id,
|
||||
Current.family.merchants.alphabetically,
|
||||
:id, :name,
|
||||
{ include_blank: t(".none"),
|
||||
label: t(".merchant_label"),
|
||||
class: "text-subdued" },
|
||||
"data-auto-submit-form-target": "auto" %>
|
||||
|
||||
<%= ef.select :tag_ids,
|
||||
Current.family.tags.alphabetically.pluck(:name, :id),
|
||||
{
|
||||
include_blank: t(".none"),
|
||||
multiple: true,
|
||||
label: t(".tags_label"),
|
||||
container_class: "h-40"
|
||||
},
|
||||
{ "data-auto-submit-form-target": "auto" } %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= f.text_area :notes,
|
||||
label: t(".note_label"),
|
||||
placeholder: t(".note_placeholder"),
|
||||
rows: 5,
|
||||
"data-auto-submit-form-target": "auto" %>
|
||||
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<!-- Settings Section -->
|
||||
<%= disclosure t(".settings") do %>
|
||||
<div class="pb-4">
|
||||
|
||||
<%= styled_form_with model: @entry,
|
||||
url: transaction_path(@entry),
|
||||
class: "p-3",
|
||||
data: { controller: "auto-submit-form" } do |f| %>
|
||||
<div class="flex cursor-pointer items-center gap-4 justify-between">
|
||||
<div class="text-sm space-y-1">
|
||||
<h4 class="text-primary">One-time <%= @entry.amount.negative? ? "Income" : "Expense" %></h4>
|
||||
<p class="text-secondary">One-time transactions will be excluded from certain budgeting calculations and reports to help you see what's really important.</p>
|
||||
</div>
|
||||
|
||||
<div class="relative inline-block select-none">
|
||||
<%= f.check_box :excluded,
|
||||
class: "sr-only peer",
|
||||
"data-auto-submit-form-target": "auto" %>
|
||||
<label for="entry_excluded"
|
||||
class="switch"></label>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="flex items-center justify-between gap-4 p-3">
|
||||
<div class="text-sm space-y-1">
|
||||
<h4 class="text-primary">Transfer or Debt Payment?</h4>
|
||||
<p class="text-secondary">Transfers and payments are special types of transactions that indicate money movement between 2 accounts.</p>
|
||||
</div>
|
||||
|
||||
<%= link_to new_transaction_transfer_match_path(@entry), class: "btn btn--outline flex items-center gap-2", data: { turbo_frame: :modal } do %>
|
||||
<%= lucide_icon "arrow-left-right", class: "w-4 h-4 shrink-0" %>
|
||||
<span class="whitespace-nowrap">Open matcher</span>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<!-- Delete Transaction Form -->
|
||||
<div class="flex items-center justify-between gap-2 p-3">
|
||||
<div class="text-sm space-y-1">
|
||||
<h4 class="text-primary"><%= t(".delete_title") %></h4>
|
||||
<p class="text-secondary"><%= t(".delete_subtitle") %></p>
|
||||
</div>
|
||||
|
||||
<%= button_to t(".delete"),
|
||||
entry_path(@entry),
|
||||
method: :delete,
|
||||
class: "rounded-lg px-3 py-2 text-red-500 text-sm
|
||||
font-medium border border-secondary",
|
||||
data: { turbo_confirm: true, turbo_frame: "_top" } %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
Loading…
Add table
Add a link
Reference in a new issue