mirror of
https://github.com/we-promise/sure.git
synced 2026-05-09 21:54:58 +00:00
* feat(splits): add excluded attribute support for split children and improve rendering of split transactions * address coderabbitai suggestions to improve code quality * Fix split excluded coercion, DRY helpers, and clean up view partials Fix boolean coercion bug where string "false" from form params was truthy in Ruby, causing all split children to be marked excluded. Use ActiveModel::Type::Boolean for explicit casting in Entry#split!. Additional changes addressing code review feedback: - Extract duplicated in_split_group logic from TransactionsController and TransactionCategoriesController into TransactionsHelper - Remove redundant local_assigns.fetch calls in partials that already declare defaults via the Rails 7.1 locals: magic comment - Simplify ternary in _transaction.html.erb to pass grouped directly - Guard hidden_field_tag :grouped to only emit when value is "true" - Add model tests for excluded on split children (boolean and string) - Add controller test for excluded param through full HTTP stack - Add test confirming excluded children are dropped from balance queries * fix(splits): simplify excluded attribute boolean check * refactor(splits): extract truthy values constant for excluded check Extract the array of truthy values used for excluded attribute check into a private constant to improve code maintainability and avoid duplication of the magic array. * refactor: simplify split grouping link generation and add test coverage for excluded split parameters
105 lines
4.7 KiB
Plaintext
105 lines
4.7 KiB
Plaintext
<%= turbo_frame_tag "category_dropdown" do %>
|
|
<div class="flex flex-col relative" data-controller="list-filter">
|
|
<div class="grow p-1.5">
|
|
<div class="relative flex items-center bg-container border border-secondary rounded-lg">
|
|
<input
|
|
placeholder="<%= t(".search_placeholder") %>"
|
|
autocomplete="nope"
|
|
type="search"
|
|
role="combobox"
|
|
aria-label="<%= t(".search_placeholder") %>"
|
|
aria-expanded="false"
|
|
aria-autocomplete="list"
|
|
class="bg-container placeholder:text-sm placeholder:text-secondary font-normal h-10 relative pl-10 w-full border-none rounded-lg focus:outline-hidden focus:ring-0"
|
|
data-list-filter-target="input"
|
|
data-action="list-filter#filter keydown->list-filter#handleKeydown">
|
|
<%= icon("search", class: "absolute inset-0 ml-2 transform top-1/2 -translate-y-1/2") %>
|
|
</div>
|
|
</div>
|
|
<div data-list-filter-target="list" role="listbox" class="flex flex-col gap-0.5 p-1.5 mt-0.5 mr-2 max-h-64 overflow-y-scroll scrollbar">
|
|
<div class="pb-2 pl-4 mr-2 text-secondary hidden" data-list-filter-target="emptyMessage">
|
|
<%= t(".no_categories") %>
|
|
</div>
|
|
<% if @categories.any? %>
|
|
<% Category::Group.for(@categories).each do |group| %>
|
|
<%= render "category/dropdowns/row", category: group.category %>
|
|
|
|
<% group.subcategories.each do |category| %>
|
|
<%= render "category/dropdowns/row", category: category %>
|
|
<% end %>
|
|
<% end %>
|
|
<% else %>
|
|
<div class="flex justify-center items-center py-12">
|
|
<div class="text-center flex flex-col items-center max-w-[500px]">
|
|
<p class="text-sm text-secondary font-normal mb-4"><%= t(".empty") %></p>
|
|
|
|
<%= render DS::Button.new(
|
|
text: t(".bootstrap"),
|
|
variant: "outline",
|
|
href: bootstrap_categories_path,
|
|
method: :post,
|
|
data: { turbo_frame: :_top }) %>
|
|
</div>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
|
|
<%= render "shared/ruler", classes: "my-2" %>
|
|
|
|
<div class="relative p-1.5 w-full">
|
|
<% if @transaction.category %>
|
|
<%= button_to transaction_path(@transaction.entry),
|
|
method: :patch,
|
|
data: { turbo_frame: dom_id(@transaction.entry) },
|
|
params: { grouped: params[:grouped], entry: { entryable_type: "Transaction", entryable_attributes: { id: @transaction.id, category_id: nil } } },
|
|
class: "flex text-sm font-medium items-center gap-2 text-secondary w-full rounded-lg p-2 hover:bg-container-inset-hover" do %>
|
|
<%= icon("minus") %>
|
|
|
|
<%= t(".clear") %>
|
|
<% end %>
|
|
<% end %>
|
|
|
|
<% unless @transaction.transfer? %>
|
|
<%= link_to new_transaction_transfer_match_path(@transaction.entry),
|
|
class: "flex text-sm font-medium items-center gap-2 text-secondary w-full rounded-lg p-2 hover:bg-container-inset-hover",
|
|
data: { turbo_frame: "modal" } do %>
|
|
<%= icon("refresh-cw") %>
|
|
|
|
<p>Match transfer/payment</p>
|
|
<% end %>
|
|
<% end %>
|
|
|
|
<% if @transaction.splittable? %>
|
|
<%= link_to new_transaction_split_path(@transaction.entry),
|
|
class: "flex text-sm font-medium items-center gap-2 text-secondary w-full rounded-lg p-2 hover:bg-container-inset-hover",
|
|
data: { turbo_frame: "modal" } do %>
|
|
<%= icon("split") %>
|
|
|
|
<p><%= t("splits.show.button") %></p>
|
|
<% end %>
|
|
<% end %>
|
|
|
|
<div class="flex text-sm font-medium items-center gap-2 text-secondary w-full rounded-lg p-2">
|
|
<div class="flex items-center gap-2">
|
|
<%= form_with url: transaction_path(@transaction.entry),
|
|
method: :patch,
|
|
data: { controller: "auto-submit-form" } do |f| %>
|
|
<%= f.hidden_field "entry[excluded]", value: !@transaction.entry.excluded %>
|
|
<%= hidden_field_tag :grouped, "true" if params[:grouped] == "true" %>
|
|
<%= f.check_box "entry[excluded]",
|
|
checked: @transaction.entry.excluded,
|
|
class: "checkbox checkbox--light",
|
|
data: { auto_submit_form_target: "auto", autosubmit_trigger_event: "change" } %>
|
|
<% end %>
|
|
</div>
|
|
|
|
<p>One-time <%= @transaction.entry.amount.negative? ? "income" : "expense" %></p>
|
|
|
|
<span class="text-orange-500 ml-auto">
|
|
<%= icon("asterisk", color: "current") %>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<% end %>
|