mirror of
https://github.com/we-promise/sure.git
synced 2026-04-07 14:31:25 +00:00
* feat: Add responsive dialog behavior for transaction modals Add responsive option to DS::Dialog component that switches between: - Mobile (< 1024px): Modal style (centered) with inline close button - Desktop (≥ 1024px): Drawer style (right side panel) with header close button Update transaction, transfer, holding, trade, and valuation views to use responsive behavior, maintaining mobile experience while reverting desktop to drawer style like budget categories. Changes: - app/components/DS/dialog.rb: Add responsive parameter and helper methods - app/components/DS/dialog.html.erb: Apply responsive styling - app/views/*/show.html.erb: Add responsive: true and hide close icons on mobile * fix: Enhance close button accessibility in dialog components * fix: Refactor dialog component to improve close button handling and accessibility
This commit is contained in:
@@ -1,16 +1,14 @@
|
|||||||
<%= wrapper_element do %>
|
<%= wrapper_element do %>
|
||||||
<%= tag.dialog class: "w-full h-full bg-transparent theme-dark:backdrop:bg-alpha-black-900 backdrop:bg-overlay pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)] #{drawer? ? "lg:p-3" : "lg:p-1"}", **merged_opts do %>
|
<%= tag.dialog class: "w-full h-full bg-transparent theme-dark:backdrop:bg-alpha-black-900 backdrop:bg-overlay pt-[env(safe-area-inset-top)] pb-[env(safe-area-inset-bottom)] #{(drawer? || responsive?) ? "lg:p-3" : "lg:p-1"}", **merged_opts do %>
|
||||||
<%= tag.div class: dialog_outer_classes do %>
|
<%= tag.div class: dialog_outer_classes do %>
|
||||||
<%= tag.div class: dialog_inner_classes, data: { DS__dialog_target: "content" } do %>
|
<%= tag.div class: dialog_inner_classes, data: { DS__dialog_target: "content" } do %>
|
||||||
<div class="grow overflow-y-auto py-4 space-y-4 flex flex-col">
|
<div class="grow overflow-y-auto py-4 space-y-4 flex flex-col">
|
||||||
<% if header? %>
|
<% if header? %>
|
||||||
<%= header %>
|
<%= header %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if body? %>
|
<% if body? %>
|
||||||
<div class="px-4 grow">
|
<div class="px-4 grow">
|
||||||
<%= body %>
|
<%= body %>
|
||||||
|
|
||||||
<% if sections.any? %>
|
<% if sections.any? %>
|
||||||
<div class="space-y-4">
|
<div class="space-y-4">
|
||||||
<% sections.each do |section| %>
|
<% sections.each do |section| %>
|
||||||
@@ -20,11 +18,9 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%# Optional, for customizing dialogs %>
|
<%# Optional, for customizing dialogs %>
|
||||||
<%= content %>
|
<%= content %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<% if actions? %>
|
<% if actions? %>
|
||||||
<div class="flex items-center gap-2 justify-end p-4">
|
<div class="flex items-center gap-2 justify-end p-4">
|
||||||
<% actions.each do |action| %>
|
<% actions.each do |action| %>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
class DS::Dialog < DesignSystemComponent
|
class DS::Dialog < DesignSystemComponent
|
||||||
renders_one :header, ->(title: nil, subtitle: nil, hide_close_icon: false, **opts, &block) do
|
renders_one :header, ->(title: nil, subtitle: nil, custom_header: false, **opts, &block) do
|
||||||
content_tag(:header, class: "px-4 flex flex-col gap-2", **opts) do
|
content_tag(:header, class: "px-4 flex flex-col gap-2", **opts) do
|
||||||
title_div = content_tag(:div, class: "flex items-center justify-between gap-2") do
|
title_div = content_tag(:div, class: "flex items-center justify-between gap-2") do
|
||||||
title = content_tag(:h2, title, class: class_names("font-medium text-primary", drawer? ? "text-lg" : "")) if title
|
title = content_tag(:h2, title, class: class_names("font-medium text-primary", drawer? ? "text-lg" : "")) if title
|
||||||
close_icon = render DS::Button.new(variant: "icon", class: "ml-auto", icon: "x", tabindex: "-1", data: { action: "DS--dialog#close" }) unless hide_close_icon
|
close_icon = close_button unless custom_header
|
||||||
safe_join([ title, close_icon ].compact)
|
safe_join([ title, close_icon ].compact)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ class DS::Dialog < DesignSystemComponent
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
attr_reader :variant, :auto_open, :reload_on_close, :width, :disable_frame, :content_class, :disable_click_outside, :opts
|
attr_reader :variant, :auto_open, :reload_on_close, :width, :disable_frame, :content_class, :disable_click_outside, :opts, :responsive
|
||||||
|
|
||||||
VARIANTS = %w[modal drawer].freeze
|
VARIANTS = %w[modal drawer].freeze
|
||||||
WIDTHS = {
|
WIDTHS = {
|
||||||
@@ -43,7 +43,7 @@ class DS::Dialog < DesignSystemComponent
|
|||||||
full: "lg:max-w-full"
|
full: "lg:max-w-full"
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
def initialize(variant: "modal", auto_open: true, reload_on_close: false, width: "md", frame: nil, disable_frame: false, content_class: nil, disable_click_outside: false, **opts)
|
def initialize(variant: "modal", auto_open: true, reload_on_close: false, width: "md", frame: nil, disable_frame: false, content_class: nil, disable_click_outside: false, responsive: false, **opts)
|
||||||
@variant = variant.to_sym
|
@variant = variant.to_sym
|
||||||
@auto_open = auto_open
|
@auto_open = auto_open
|
||||||
@reload_on_close = reload_on_close
|
@reload_on_close = reload_on_close
|
||||||
@@ -52,6 +52,7 @@ class DS::Dialog < DesignSystemComponent
|
|||||||
@disable_frame = disable_frame
|
@disable_frame = disable_frame
|
||||||
@content_class = content_class
|
@content_class = content_class
|
||||||
@disable_click_outside = disable_click_outside
|
@disable_click_outside = disable_click_outside
|
||||||
|
@responsive = responsive
|
||||||
@opts = opts
|
@opts = opts
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -69,7 +70,9 @@ class DS::Dialog < DesignSystemComponent
|
|||||||
end
|
end
|
||||||
|
|
||||||
def dialog_outer_classes
|
def dialog_outer_classes
|
||||||
variant_classes = if drawer?
|
variant_classes = if responsive?
|
||||||
|
"items-center justify-center lg:items-end lg:justify-end"
|
||||||
|
elsif drawer?
|
||||||
"items-end justify-end"
|
"items-end justify-end"
|
||||||
else
|
else
|
||||||
"items-center justify-center"
|
"items-center justify-center"
|
||||||
@@ -82,7 +85,9 @@ class DS::Dialog < DesignSystemComponent
|
|||||||
end
|
end
|
||||||
|
|
||||||
def dialog_inner_classes
|
def dialog_inner_classes
|
||||||
variant_classes = if drawer?
|
variant_classes = if responsive?
|
||||||
|
"max-h-full lg:h-full lg:w-[550px]"
|
||||||
|
elsif drawer?
|
||||||
"lg:w-[550px] h-full"
|
"lg:w-[550px] h-full"
|
||||||
else
|
else
|
||||||
class_names(
|
class_names(
|
||||||
@@ -116,4 +121,20 @@ class DS::Dialog < DesignSystemComponent
|
|||||||
def drawer?
|
def drawer?
|
||||||
variant == :drawer
|
variant == :drawer
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def responsive?
|
||||||
|
@responsive
|
||||||
|
end
|
||||||
|
|
||||||
|
def close_button
|
||||||
|
classes = responsive? ? "ml-auto hidden lg:flex" : "ml-auto"
|
||||||
|
render DS::Button.new(
|
||||||
|
variant: "icon",
|
||||||
|
class: classes,
|
||||||
|
icon: "x",
|
||||||
|
title: I18n.t("common.close"),
|
||||||
|
aria_label: I18n.t("common.close"),
|
||||||
|
data: { action: "DS--dialog#close" }
|
||||||
|
)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,21 +1,22 @@
|
|||||||
<%= render DS::Dialog.new(frame: "drawer") do |dialog| %>
|
<%= render DS::Dialog.new(frame: "drawer", responsive: true) do |dialog| %>
|
||||||
<% dialog.with_header(hide_close_icon: true) do %>
|
<% dialog.with_header(custom_header: true) do %>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<%= tag.h3 @holding.name, class: "text-2xl font-medium text-primary" %>
|
<%= tag.h3 @holding.name, class: "text-2xl font-medium text-primary" %>
|
||||||
<%= tag.p @holding.ticker, class: "text-sm text-secondary" %>
|
<%= tag.p @holding.ticker, class: "text-sm text-secondary" %>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
<% if @holding.security.brandfetch_icon_url.present? %>
|
<% if @holding.security.brandfetch_icon_url.present? %>
|
||||||
<%= image_tag @holding.security.brandfetch_icon_url, loading: "lazy", class: "w-9 h-9 rounded-full" %>
|
<%= image_tag @holding.security.brandfetch_icon_url, loading: "lazy", class: "w-9 h-9 rounded-full" %>
|
||||||
<% elsif @holding.security.logo_url.present? %>
|
<% elsif @holding.security.logo_url.present? %>
|
||||||
<%= image_tag @holding.security.logo_url, loading: "lazy", class: "w-9 h-9 rounded-full" %>
|
<%= image_tag @holding.security.logo_url, loading: "lazy", class: "w-9 h-9 rounded-full" %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<%= render DS::FilledIcon.new(variant: :text, text: @holding.name, size: "md", rounded: true) %>
|
<%= render DS::FilledIcon.new(variant: :text, text: @holding.name, size: "md", rounded: true) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
<%= dialog.close_button %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_body do %>
|
<% dialog.with_body do %>
|
||||||
<% dialog.with_section(title: t(".overview"), open: true) do %>
|
<% dialog.with_section(title: t(".overview"), open: true) do %>
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
@@ -33,13 +34,12 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
<button type="button"
|
<button type="button"
|
||||||
data-action="click->holding-security-remap#toggle"
|
data-action="click->holding-security-remap#toggle"
|
||||||
class="text-secondary hover:text-primary"
|
class="text-secondary hover:text-primary"
|
||||||
aria-label="<%= t('.edit_security') %>">
|
aria-label="<%= t('.edit_security') %>">
|
||||||
<%= icon "pencil", size: "xs" %>
|
<%= icon "pencil", size: "xs" %>
|
||||||
</button>
|
</button>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div data-holding-security-remap-target="form" class="hidden mt-3 space-y-3">
|
<div data-holding-security-remap-target="form" class="hidden mt-3 space-y-3">
|
||||||
<% if Security.provider.present? %>
|
<% if Security.provider.present? %>
|
||||||
<%= form_with url: remap_security_holding_path(@holding), method: :patch, class: "space-y-3" do |f| %>
|
<%= form_with url: remap_security_holding_path(@holding), method: :patch, class: "space-y-3" do |f| %>
|
||||||
@@ -64,23 +64,24 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center justify-between text-sm">
|
<div class="flex items-center justify-between text-sm">
|
||||||
<dt class="text-secondary"><%= t(".current_market_price_label") %></dt>
|
<dt class="text-secondary"><%= t(".current_market_price_label") %></dt>
|
||||||
<dd class="text-primary">
|
<dd class="text-primary">
|
||||||
<% begin %>
|
<% begin %>
|
||||||
<%= @holding.security.current_price ? format_money(@holding.security.current_price) : t(".unknown") %>
|
<%= @holding.security.current_price ? format_money(@holding.security.current_price) : t(".unknown") %>
|
||||||
<% rescue ActiveRecord::RecordInvalid, StandardError %>
|
<% rescue ActiveRecord::RecordInvalid %>
|
||||||
|
<%= t(".unknown") %>
|
||||||
|
<% rescue StandardError => e %>
|
||||||
|
<% logger.error "Error fetching current price for security #{@holding.security.id}: #{e.message}" %>
|
||||||
|
<% logger.error e.backtrace.first(5).join("\n") %>
|
||||||
<%= t(".unknown") %>
|
<%= t(".unknown") %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center justify-between text-sm">
|
<div class="flex items-center justify-between text-sm">
|
||||||
<dt class="text-secondary"><%= t(".portfolio_weight_label") %></dt>
|
<dt class="text-secondary"><%= t(".portfolio_weight_label") %></dt>
|
||||||
<dd class="text-primary"><%= @holding.weight ? number_to_percentage(@holding.weight, precision: 2) : t(".unknown") %></dd>
|
<dd class="text-primary"><%= @holding.weight ? number_to_percentage(@holding.weight, precision: 2) : t(".unknown") %></dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%# Average Cost with inline editor %>
|
<%# Average Cost with inline editor %>
|
||||||
<%
|
<%
|
||||||
currency = Money::Currency.new(@holding.currency)
|
currency = Money::Currency.new(@holding.currency)
|
||||||
@@ -103,7 +104,6 @@
|
|||||||
</button>
|
</button>
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%# Inline cost basis editor (hidden by default) %>
|
<%# Inline cost basis editor (hidden by default) %>
|
||||||
<div class="hidden mt-3 space-y-3" data-drawer-cost-basis-target="form">
|
<div class="hidden mt-3 space-y-3" data-drawer-cost-basis-target="form">
|
||||||
<%
|
<%
|
||||||
@@ -136,7 +136,7 @@
|
|||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
value="<%= number_with_precision(current_total, precision: 2) if current_total %>"
|
value="<%= number_with_precision(current_total, precision: 2) if current_total %>"
|
||||||
data-action="input->drawer-cost-basis#updatePerShare"
|
data-action="input->drawer-cost-basis#updatePerShare"
|
||||||
data-drawer-cost-basis-target="total">
|
data-drawer-cost-basis-target="total">
|
||||||
<span class="text-secondary text-sm"><%= currency.iso_code %></span>
|
<span class="text-secondary text-sm"><%= currency.iso_code %></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -144,7 +144,6 @@
|
|||||||
<p class="text-xs text-secondary -mt-2">
|
<p class="text-xs text-secondary -mt-2">
|
||||||
= <%= currency.symbol %><span data-drawer-cost-basis-target="perShareValue"><%= number_with_precision(current_per_share, precision: 2) || "0.00" %></span> <%= t("holdings.cost_basis_cell.per_share") %>
|
= <%= currency.symbol %><span data-drawer-cost-basis-target="perShareValue"><%= number_with_precision(current_per_share, precision: 2) || "0.00" %></span> <%= t("holdings.cost_basis_cell.per_share") %>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<!-- Per-share input -->
|
<!-- Per-share input -->
|
||||||
<div class="pt-2 border-t border-tertiary">
|
<div class="pt-2 border-t border-tertiary">
|
||||||
<label class="text-xs text-secondary block mb-1"><%= t("holdings.cost_basis_cell.or_per_share_label") %></label>
|
<label class="text-xs text-secondary block mb-1"><%= t("holdings.cost_basis_cell.or_per_share_label") %></label>
|
||||||
@@ -156,11 +155,10 @@
|
|||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
value="<%= number_with_precision(current_per_share, precision: 2) if current_per_share %>"
|
value="<%= number_with_precision(current_per_share, precision: 2) if current_per_share %>"
|
||||||
data-action="input->drawer-cost-basis#updateTotal"
|
data-action="input->drawer-cost-basis#updateTotal"
|
||||||
data-drawer-cost-basis-target="perShare">
|
data-drawer-cost-basis-target="perShare">
|
||||||
<span class="text-secondary text-sm"><%= currency.iso_code %></span>
|
<span class="text-secondary text-sm"><%= currency.iso_code %></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-end gap-2 pt-2">
|
<div class="flex justify-end gap-2 pt-2">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="inline-flex items-center gap-1 px-3 py-2 rounded-lg text-sm font-medium text-primary bg-gray-200 hover:bg-gray-300 theme-dark:bg-gray-700 theme-dark:hover:bg-gray-600"
|
class="inline-flex items-center gap-1 px-3 py-2 rounded-lg text-sm font-medium text-primary bg-gray-200 hover:bg-gray-300 theme-dark:bg-gray-700 theme-dark:hover:bg-gray-600"
|
||||||
@@ -172,7 +170,6 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center justify-between text-sm">
|
<div class="flex items-center justify-between text-sm">
|
||||||
<dt class="text-secondary"><%= t(".total_return_label") %></dt>
|
<dt class="text-secondary"><%= t(".total_return_label") %></dt>
|
||||||
<% if @holding.trend %>
|
<% if @holding.trend %>
|
||||||
@@ -186,7 +183,6 @@
|
|||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_section(title: t(".history"), open: true) do %>
|
<% dialog.with_section(title: t(".history"), open: true) do %>
|
||||||
<div class="space-y-2">
|
<div class="space-y-2">
|
||||||
<div class="px-3 py-4">
|
<div class="px-3 py-4">
|
||||||
@@ -200,10 +196,8 @@
|
|||||||
<div class="h-12 w-px bg-alpha-black-200"></div>
|
<div class="h-12 w-px bg-alpha-black-200"></div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<p class="text-secondary text-xs uppercase"><%= l(trade_entry.date, format: :long) %></p>
|
<p class="text-secondary text-xs uppercase"><%= l(trade_entry.date, format: :long) %></p>
|
||||||
|
|
||||||
<p class="text-primary"><%= t(
|
<p class="text-primary"><%= t(
|
||||||
".trade_history_entry",
|
".trade_history_entry",
|
||||||
qty: trade_entry.trade.qty,
|
qty: trade_entry.trade.qty,
|
||||||
@@ -214,14 +208,12 @@
|
|||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<% else %>
|
<% else %>
|
||||||
<p class="text-secondary"><%= t(".no_trade_history") %></p>
|
<p class="text-secondary"><%= t(".no_trade_history") %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @holding.cost_basis_locked? || @holding.security_remapped? || @holding.account.can_delete_holdings? %>
|
<% if @holding.cost_basis_locked? || @holding.security_remapped? || @holding.account.can_delete_holdings? %>
|
||||||
<% dialog.with_section(title: t(".settings"), open: true) do %>
|
<% dialog.with_section(title: t(".settings"), open: true) do %>
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
@@ -231,7 +223,6 @@
|
|||||||
<h4 class="text-primary"><%= t(".security_remapped_label") %></h4>
|
<h4 class="text-primary"><%= t(".security_remapped_label") %></h4>
|
||||||
<p class="text-secondary"><%= t(".provider_sent", ticker: @holding.provider_security.ticker) %></p>
|
<p class="text-secondary"><%= t(".provider_sent", ticker: @holding.provider_security.ticker) %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= button_to t(".reset_to_provider"),
|
<%= button_to t(".reset_to_provider"),
|
||||||
reset_security_holding_path(@holding),
|
reset_security_holding_path(@holding),
|
||||||
method: :post,
|
method: :post,
|
||||||
@@ -243,14 +234,12 @@
|
|||||||
} } %>
|
} } %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @holding.cost_basis_locked? %>
|
<% if @holding.cost_basis_locked? %>
|
||||||
<div class="flex items-center justify-between gap-2 p-3 border-b border-tertiary">
|
<div class="flex items-center justify-between gap-2 p-3 border-b border-tertiary">
|
||||||
<div class="text-sm space-y-1">
|
<div class="text-sm space-y-1">
|
||||||
<h4 class="text-primary"><%= t(".cost_basis_locked_label") %></h4>
|
<h4 class="text-primary"><%= t(".cost_basis_locked_label") %></h4>
|
||||||
<p class="text-secondary"><%= t(".cost_basis_locked_description") %></p>
|
<p class="text-secondary"><%= t(".cost_basis_locked_description") %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= button_to t(".unlock_cost_basis"),
|
<%= button_to t(".unlock_cost_basis"),
|
||||||
unlock_cost_basis_holding_path(@holding),
|
unlock_cost_basis_holding_path(@holding),
|
||||||
method: :post,
|
method: :post,
|
||||||
@@ -259,14 +248,12 @@
|
|||||||
data: { turbo_confirm: { title: t(".unlock_confirm_title"), body: t(".unlock_confirm_body") } } %>
|
data: { turbo_confirm: { title: t(".unlock_confirm_title"), body: t(".unlock_confirm_body") } } %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if @holding.account.can_delete_holdings? %>
|
<% if @holding.account.can_delete_holdings? %>
|
||||||
<div class="flex items-center justify-between gap-2 p-3">
|
<div class="flex items-center justify-between gap-2 p-3">
|
||||||
<div class="text-sm space-y-1">
|
<div class="text-sm space-y-1">
|
||||||
<h4 class="text-primary"><%= t(".delete_title") %></h4>
|
<h4 class="text-primary"><%= t(".delete_title") %></h4>
|
||||||
<p class="text-secondary"><%= t(".delete_subtitle") %></p>
|
<p class="text-secondary"><%= t(".delete_subtitle") %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= button_to t(".delete"),
|
<%= button_to t(".delete"),
|
||||||
holding_path(@holding),
|
holding_path(@holding),
|
||||||
method: :delete,
|
method: :delete,
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
class: "bg-container border border-secondary font-medium rounded-lg px-3 py-2 text-sm pr-7 cursor-pointer text-primary focus:outline-hidden focus:ring-0" %>
|
class: "bg-container border border-secondary font-medium rounded-lg px-3 py-2 text-sm pr-7 cursor-pointer text-primary focus:outline-hidden focus:ring-0" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<% if sankey_data[:links].present? %>
|
<% if sankey_data[:links].present? %>
|
||||||
<div class="w-full h-96">
|
<div class="w-full h-96">
|
||||||
<div
|
<div
|
||||||
@@ -18,9 +17,8 @@
|
|||||||
data-sankey-chart-currency-symbol-value="<%= sankey_data[:currency_symbol] %>"
|
data-sankey-chart-currency-symbol-value="<%= sankey_data[:currency_symbol] %>"
|
||||||
class="w-full h-full"></div>
|
class="w-full h-full"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= render DS::Dialog.new(id: "cashflow-expanded-dialog", auto_open: false, width: "custom", disable_frame: true, content_class: "!w-[96vw] max-w-[1650px]", data: { action: "close->cashflow-expand#restore" }) do |dialog| %>
|
<%= render DS::Dialog.new(id: "cashflow-expanded-dialog", auto_open: false, width: "custom", disable_frame: true, content_class: "!w-[96vw] max-w-[1650px]", data: { action: "close->cashflow-expand#restore" }) do |dialog| %>
|
||||||
<% dialog.with_header(title: t("pages.dashboard.cashflow_sankey.title"), hide_close_icon: false) %>
|
<% dialog.with_header(title: t("pages.dashboard.cashflow_sankey.title")) %>
|
||||||
<% dialog.with_body do %>
|
<% dialog.with_body do %>
|
||||||
<div class="w-full h-[85dvh] max-h-[90dvh] overflow-y-auto overscroll-contain">
|
<div class="w-full h-[85dvh] max-h-[90dvh] overflow-y-auto overscroll-contain">
|
||||||
<div
|
<div
|
||||||
@@ -38,7 +36,6 @@
|
|||||||
variant: :container,
|
variant: :container,
|
||||||
icon: "activity" # cashflow placeholder icon
|
icon: "activity" # cashflow placeholder icon
|
||||||
) %>
|
) %>
|
||||||
|
|
||||||
<p class="text-sm font-medium text-primary"><%= t("pages.dashboard.cashflow_sankey.no_data_title") %></p>
|
<p class="text-sm font-medium text-primary"><%= t("pages.dashboard.cashflow_sankey.no_data_title") %></p>
|
||||||
<p class="text-secondary text-sm"><%= t("pages.dashboard.cashflow_sankey.no_data_description") %></p>
|
<p class="text-secondary text-sm"><%= t("pages.dashboard.cashflow_sankey.no_data_description") %></p>
|
||||||
<%= render DS::Link.new(
|
<%= render DS::Link.new(
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<%= render DS::Dialog.new(frame: "drawer") do |dialog| %>
|
<%= render DS::Dialog.new(frame: "drawer", responsive: true) do |dialog| %>
|
||||||
<% dialog.with_header(hide_close_icon: true) do %>
|
<% dialog.with_header(custom_header: true) do %>
|
||||||
<%= render "trades/header", entry: @entry %>
|
<div class="flex items-start justify-between gap-4">
|
||||||
|
<%= render "trades/header", entry: @entry %>
|
||||||
|
<%= dialog.close_button %>
|
||||||
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% trade = @entry.trade %>
|
<% trade = @entry.trade %>
|
||||||
|
|
||||||
<% dialog.with_body do %>
|
<% dialog.with_body do %>
|
||||||
<%= render "entries/protection_indicator", entry: @entry, unlock_path: unlock_trade_path(trade) %>
|
<%= render "entries/protection_indicator", entry: @entry, unlock_path: unlock_trade_path(trade) %>
|
||||||
|
|
||||||
<% dialog.with_section(title: t(".details"), open: true) do %>
|
<% dialog.with_section(title: t(".details"), open: true) do %>
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
<%= styled_form_with model: @entry,
|
<%= styled_form_with model: @entry,
|
||||||
@@ -19,13 +19,11 @@
|
|||||||
max: Date.current,
|
max: Date.current,
|
||||||
disabled: @entry.linked?,
|
disabled: @entry.linked?,
|
||||||
"data-auto-submit-form-target": "auto" %>
|
"data-auto-submit-form-target": "auto" %>
|
||||||
|
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<%= f.select :nature,
|
<%= f.select :nature,
|
||||||
[[t(".buy"), "outflow"], [t(".sell"), "inflow"]],
|
[[t(".buy"), "outflow"], [t(".sell"), "inflow"]],
|
||||||
{ container_class: "w-1/3", label: t(".type_label"), selected: @entry.amount.negative? ? "outflow" : "inflow" },
|
{ container_class: "w-1/3", label: t(".type_label"), selected: @entry.amount.negative? ? "outflow" : "inflow" },
|
||||||
{ data: { "auto-submit-form-target": "auto" }, disabled: @entry.linked? } %>
|
{ data: { "auto-submit-form-target": "auto" }, disabled: @entry.linked? } %>
|
||||||
|
|
||||||
<%= f.fields_for :entryable do |ef| %>
|
<%= f.fields_for :entryable do |ef| %>
|
||||||
<%= ef.number_field :qty,
|
<%= ef.number_field :qty,
|
||||||
label: t(".quantity_label"),
|
label: t(".quantity_label"),
|
||||||
@@ -35,7 +33,6 @@
|
|||||||
disabled: @entry.linked? %>
|
disabled: @entry.linked? %>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= f.fields_for :entryable do |ef| %>
|
<%= f.fields_for :entryable do |ef| %>
|
||||||
<%= ef.money_field :price,
|
<%= ef.money_field :price,
|
||||||
label: t(".cost_per_share_label"),
|
label: t(".cost_per_share_label"),
|
||||||
@@ -49,7 +46,6 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_section(title: t(".additional")) do %>
|
<% dialog.with_section(title: t(".additional")) do %>
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
<%= styled_form_with model: @entry,
|
<%= styled_form_with model: @entry,
|
||||||
@@ -64,7 +60,6 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_section(title: t(".settings")) do %>
|
<% dialog.with_section(title: t(".settings")) do %>
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
<!-- Exclude Trade Form -->
|
<!-- Exclude Trade Form -->
|
||||||
@@ -77,18 +72,15 @@
|
|||||||
<h4 class="text-primary"><%= t(".exclude_title") %></h4>
|
<h4 class="text-primary"><%= t(".exclude_title") %></h4>
|
||||||
<p class="text-secondary"><%= t(".exclude_subtitle") %></p>
|
<p class="text-secondary"><%= t(".exclude_subtitle") %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= f.toggle :excluded, { data: { auto_submit_form_target: "auto" } } %>
|
<%= f.toggle :excluded, { data: { auto_submit_form_target: "auto" } } %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Delete Trade Form -->
|
<!-- Delete Trade Form -->
|
||||||
<div class="flex items-center justify-between gap-2 p-3">
|
<div class="flex items-center justify-between gap-2 p-3">
|
||||||
<div class="text-sm space-y-1">
|
<div class="text-sm space-y-1">
|
||||||
<h4 class="text-primary"><%= t(".delete_title") %></h4>
|
<h4 class="text-primary"><%= t(".delete_title") %></h4>
|
||||||
<p class="text-secondary"><%= t(".delete_subtitle") %></p>
|
<p class="text-secondary"><%= t(".delete_subtitle") %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= button_to t(".delete"),
|
<%= button_to t(".delete"),
|
||||||
entry_path(@entry),
|
entry_path(@entry),
|
||||||
method: :delete,
|
method: :delete,
|
||||||
|
|||||||
@@ -1,32 +1,26 @@
|
|||||||
<%# locals: (entry:) %>
|
<%# locals: (entry:) %>
|
||||||
|
|
||||||
<div class="flex items-start justify-between gap-4" id="<%= dom_id(entry, :header) %>">
|
<div class="flex items-start justify-between gap-4" id="<%= dom_id(entry, :header) %>">
|
||||||
<div>
|
<div>
|
||||||
<h3 class="font-medium flex items-center gap-2">
|
<h3 class="font-medium flex items-center gap-2">
|
||||||
<span class="text-2xl text-primary">
|
<span class="text-2xl text-primary">
|
||||||
<%= format_money -entry.amount_money %>
|
<%= format_money -entry.amount_money %>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="text-lg text-secondary">
|
<span class="text-lg text-secondary">
|
||||||
<%= entry.currency %>
|
<%= entry.currency %>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<% if entry.transaction.transfer? %>
|
<% if entry.transaction.transfer? %>
|
||||||
<%= icon "arrow-left-right", size: "sm", class: "text-secondary" %>
|
<%= icon "arrow-left-right", size: "sm", class: "text-secondary" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if entry.linked? %>
|
<% if entry.linked? %>
|
||||||
<span title="<%= t('transactions.transaction.linked_with_plaid') %>" class="text-secondary">
|
<span title="<%= t('transactions.transaction.linked_with_plaid') %>" class="text-secondary">
|
||||||
<%= icon("refresh-ccw", size: "sm") %>
|
<%= icon("refresh-ccw", size: "sm") %>
|
||||||
</span>
|
</span>
|
||||||
<% end %>
|
<% end %>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<span class="text-sm text-secondary">
|
<span class="text-sm text-secondary">
|
||||||
<%= I18n.l(entry.date, format: :long) %>
|
<%= I18n.l(entry.date, format: :long) %>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<% if entry.transaction.pending? %>
|
<% if entry.transaction.pending? %>
|
||||||
<span class="inline-flex items-center gap-1 text-xs font-medium rounded-full px-1.5 py-0.5 border border-secondary text-secondary" title="<%= t("transactions.transaction.pending_tooltip") %>">
|
<span class="inline-flex items-center gap-1 text-xs font-medium rounded-full px-1.5 py-0.5 border border-secondary text-secondary" title="<%= t("transactions.transaction.pending_tooltip") %>">
|
||||||
<%= icon "clock", size: "sm", color: "current" %>
|
<%= icon "clock", size: "sm", color: "current" %>
|
||||||
@@ -35,6 +29,4 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= render DS::Button.new(variant: "icon", icon: "x", data: { action: "DS--dialog#close" }) %>
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
<%= render DS::Dialog.new(frame: "drawer") do |dialog| %>
|
<%= render DS::Dialog.new(frame: "drawer", responsive: true) do |dialog| %>
|
||||||
<% dialog.with_header(hide_close_icon: true) do %>
|
<% dialog.with_header(custom_header: true) do %>
|
||||||
<%= render "transactions/header", entry: @entry %>
|
<div class="flex items-start justify-between gap-4">
|
||||||
|
<%= render "transactions/header", entry: @entry %>
|
||||||
|
<%= dialog.close_button %>
|
||||||
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_body do %>
|
<% dialog.with_body do %>
|
||||||
<%# Potential duplicate alert %>
|
<%# Potential duplicate alert %>
|
||||||
<% if @entry.transaction.has_potential_duplicate? %>
|
<% if @entry.transaction.has_potential_duplicate? %>
|
||||||
@@ -14,7 +16,6 @@
|
|||||||
<div class="flex-1 space-y-2">
|
<div class="flex-1 space-y-2">
|
||||||
<h4 class="text-sm font-medium text-primary"><%= t("transactions.show.potential_duplicate_title") %></h4>
|
<h4 class="text-sm font-medium text-primary"><%= t("transactions.show.potential_duplicate_title") %></h4>
|
||||||
<p class="text-sm text-secondary"><%= t("transactions.show.potential_duplicate_description") %></p>
|
<p class="text-sm text-secondary"><%= t("transactions.show.potential_duplicate_description") %></p>
|
||||||
|
|
||||||
<div class="mt-3 p-3 rounded bg-container border border-primary">
|
<div class="mt-3 p-3 rounded bg-container border border-primary">
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
@@ -26,7 +27,6 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center gap-2 mt-3">
|
<div class="flex items-center gap-2 mt-3">
|
||||||
<%= button_to t("transactions.show.merge_duplicate"),
|
<%= button_to t("transactions.show.merge_duplicate"),
|
||||||
merge_duplicate_transaction_path(@entry.transaction),
|
merge_duplicate_transaction_path(@entry.transaction),
|
||||||
@@ -44,33 +44,27 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= render "entries/protection_indicator", entry: @entry, unlock_path: unlock_transaction_path(@entry.transaction) %>
|
<%= render "entries/protection_indicator", entry: @entry, unlock_path: unlock_transaction_path(@entry.transaction) %>
|
||||||
|
|
||||||
<% dialog.with_section(title: t(".overview"), open: true) do %>
|
<% dialog.with_section(title: t(".overview"), open: true) do %>
|
||||||
<div>
|
<div>
|
||||||
<%= styled_form_with model: @entry,
|
<%= styled_form_with model: @entry,
|
||||||
url: transaction_path(@entry),
|
url: transaction_path(@entry),
|
||||||
class: "space-y-2",
|
class: "space-y-2",
|
||||||
data: { controller: "auto-submit-form" } do |f| %>
|
data: { controller: "auto-submit-form" } do |f| %>
|
||||||
|
|
||||||
<%= f.text_field :name,
|
<%= f.text_field :name,
|
||||||
label: t(".name_label"),
|
label: t(".name_label"),
|
||||||
"data-auto-submit-form-target": "auto" %>
|
"data-auto-submit-form-target": "auto" %>
|
||||||
|
|
||||||
<%= f.date_field :date,
|
<%= f.date_field :date,
|
||||||
label: t(".date_label"),
|
label: t(".date_label"),
|
||||||
max: Date.current,
|
max: Date.current,
|
||||||
disabled: @entry.linked?,
|
disabled: @entry.linked?,
|
||||||
"data-auto-submit-form-target": "auto" %>
|
"data-auto-submit-form-target": "auto" %>
|
||||||
|
|
||||||
<% unless @entry.transaction.transfer? %>
|
<% unless @entry.transaction.transfer? %>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<%= f.select :nature,
|
<%= f.select :nature,
|
||||||
[["Expense", "outflow"], ["Income", "inflow"]],
|
[["Expense", "outflow"], ["Income", "inflow"]],
|
||||||
{ container_class: "w-1/3", label: t(".nature"), selected: @entry.amount.negative? ? "inflow" : "outflow" },
|
{ container_class: "w-1/3", label: t(".nature"), selected: @entry.amount.negative? ? "inflow" : "outflow" },
|
||||||
{ data: { "auto-submit-form-target": "auto" }, disabled: @entry.linked? } %>
|
{ data: { "auto-submit-form-target": "auto" }, disabled: @entry.linked? } %>
|
||||||
|
|
||||||
<%= f.money_field :amount, label: t(".amount"),
|
<%= f.money_field :amount, label: t(".amount"),
|
||||||
container_class: "w-2/3",
|
container_class: "w-2/3",
|
||||||
auto_submit: true,
|
auto_submit: true,
|
||||||
@@ -79,7 +73,6 @@
|
|||||||
disabled: @entry.linked?,
|
disabled: @entry.linked?,
|
||||||
disable_currency: @entry.linked? %>
|
disable_currency: @entry.linked? %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= f.fields_for :entryable do |ef| %>
|
<%= f.fields_for :entryable do |ef| %>
|
||||||
<%= ef.collection_select :category_id,
|
<%= ef.collection_select :category_id,
|
||||||
Current.family.categories.alphabetically,
|
Current.family.categories.alphabetically,
|
||||||
@@ -89,11 +82,9 @@
|
|||||||
"data-auto-submit-form-target": "auto" %>
|
"data-auto-submit-form-target": "auto" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_section(title: t(".details")) do %>
|
<% dialog.with_section(title: t(".details")) do %>
|
||||||
<%= styled_form_with model: @entry,
|
<%= styled_form_with model: @entry,
|
||||||
url: transaction_path(@entry),
|
url: transaction_path(@entry),
|
||||||
@@ -107,9 +98,7 @@
|
|||||||
),
|
),
|
||||||
{ label: t(".account_label") },
|
{ label: t(".account_label") },
|
||||||
{ disabled: true } %>
|
{ disabled: true } %>
|
||||||
|
|
||||||
<%= f.fields_for :entryable do |ef| %>
|
<%= f.fields_for :entryable do |ef| %>
|
||||||
|
|
||||||
<%= ef.collection_select :merchant_id,
|
<%= ef.collection_select :merchant_id,
|
||||||
Current.family.available_merchants.alphabetically,
|
Current.family.available_merchants.alphabetically,
|
||||||
:id, :name,
|
:id, :name,
|
||||||
@@ -117,7 +106,6 @@
|
|||||||
label: t(".merchant_label"),
|
label: t(".merchant_label"),
|
||||||
class: "text-subdued" },
|
class: "text-subdued" },
|
||||||
"data-auto-submit-form-target": "auto" %>
|
"data-auto-submit-form-target": "auto" %>
|
||||||
|
|
||||||
<%= ef.select :tag_ids,
|
<%= ef.select :tag_ids,
|
||||||
Current.family.tags.alphabetically.pluck(:name, :id),
|
Current.family.tags.alphabetically.pluck(:name, :id),
|
||||||
{
|
{
|
||||||
@@ -128,16 +116,13 @@
|
|||||||
{ "data-controller": "multi-select", "data-auto-submit-form-target": "auto" } %>
|
{ "data-controller": "multi-select", "data-auto-submit-form-target": "auto" } %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= f.text_area :notes,
|
<%= f.text_area :notes,
|
||||||
label: t(".note_label"),
|
label: t(".note_label"),
|
||||||
placeholder: t(".note_placeholder"),
|
placeholder: t(".note_placeholder"),
|
||||||
rows: 5,
|
rows: 5,
|
||||||
"data-auto-submit-form-target": "auto" %>
|
"data-auto-submit-form-target": "auto" %>
|
||||||
|
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if (details = build_transaction_extra_details(@entry)) %>
|
<% if (details = build_transaction_extra_details(@entry)) %>
|
||||||
<% dialog.with_section(title: "Additional details", open: false) do %>
|
<% dialog.with_section(title: "Additional details", open: false) do %>
|
||||||
<div class="px-3 py-2 space-y-3">
|
<div class="px-3 py-2 space-y-3">
|
||||||
@@ -165,7 +150,6 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</dl>
|
</dl>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if details[:provider_extras].present? %>
|
<% if details[:provider_extras].present? %>
|
||||||
<div class="pt-2">
|
<div class="pt-2">
|
||||||
<h4 class="text-sm text-secondary mb-1">Provider extras</h4>
|
<h4 class="text-sm text-secondary mb-1">Provider extras</h4>
|
||||||
@@ -185,7 +169,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_section(title: t(".settings")) do %>
|
<% dialog.with_section(title: t(".settings")) do %>
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
<%= styled_form_with model: @entry,
|
<%= styled_form_with model: @entry,
|
||||||
@@ -197,12 +180,10 @@
|
|||||||
<h4 class="text-primary"><%= t(".exclude") %></h4>
|
<h4 class="text-primary"><%= t(".exclude") %></h4>
|
||||||
<p class="text-secondary"><%= t(".exclude_description") %></p>
|
<p class="text-secondary"><%= t(".exclude_description") %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= f.toggle :excluded, { data: { auto_submit_form_target: "auto" } } %>
|
<%= f.toggle :excluded, { data: { auto_submit_form_target: "auto" } } %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<% if @entry.account.investment? || @entry.account.crypto? %>
|
<% if @entry.account.investment? || @entry.account.crypto? %>
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
<%= styled_form_with model: @entry,
|
<%= styled_form_with model: @entry,
|
||||||
@@ -215,7 +196,6 @@
|
|||||||
<h4 class="text-primary"><%= t(".activity_type") %></h4>
|
<h4 class="text-primary"><%= t(".activity_type") %></h4>
|
||||||
<p class="text-secondary"><%= t(".activity_type_description") %></p>
|
<p class="text-secondary"><%= t(".activity_type_description") %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= ef.select :investment_activity_label,
|
<%= ef.select :investment_activity_label,
|
||||||
options_for_select(
|
options_for_select(
|
||||||
[["—", nil]] + Transaction::ACTIVITY_LABELS.map { |l| [t("transactions.activity_labels.#{l.parameterize(separator: '_')}"), l] },
|
[["—", nil]] + Transaction::ACTIVITY_LABELS.map { |l| [t("transactions.activity_labels.#{l.parameterize(separator: '_')}"), l] },
|
||||||
@@ -229,7 +209,6 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
<%= styled_form_with model: @entry,
|
<%= styled_form_with model: @entry,
|
||||||
url: transaction_path(@entry),
|
url: transaction_path(@entry),
|
||||||
@@ -241,7 +220,6 @@
|
|||||||
<h4 class="text-primary"><%= t(".one_time_title", type: @entry.amount.negative? ? t("transactions.form.income") : t("transactions.form.expense")) %></h4>
|
<h4 class="text-primary"><%= t(".one_time_title", type: @entry.amount.negative? ? t("transactions.form.income") : t("transactions.form.expense")) %></h4>
|
||||||
<p class="text-secondary"><%= t(".one_time_description") %></p>
|
<p class="text-secondary"><%= t(".one_time_description") %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= ef.toggle :kind, {
|
<%= ef.toggle :kind, {
|
||||||
checked: @entry.transaction.one_time?,
|
checked: @entry.transaction.one_time?,
|
||||||
data: { auto_submit_form_target: "auto" }
|
data: { auto_submit_form_target: "auto" }
|
||||||
@@ -249,13 +227,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<div class="flex items-center justify-between gap-4 p-3">
|
<div class="flex items-center justify-between gap-4 p-3">
|
||||||
<div class="text-sm space-y-1">
|
<div class="text-sm space-y-1">
|
||||||
<h4 class="text-primary">Transfer or Debt Payment?</h4>
|
<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>
|
<p class="text-secondary">Transfers and payments are special types of transactions that indicate money movement between 2 accounts.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= render DS::Link.new(
|
<%= render DS::Link.new(
|
||||||
text: "Open matcher",
|
text: "Open matcher",
|
||||||
icon: "arrow-left-right",
|
icon: "arrow-left-right",
|
||||||
@@ -264,7 +240,6 @@
|
|||||||
frame: :modal
|
frame: :modal
|
||||||
) %>
|
) %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Convert to Trade (Investment Accounts Only, not already converted) -->
|
<!-- Convert to Trade (Investment Accounts Only, not already converted) -->
|
||||||
<% if @entry.account.investment? && @entry.entryable.is_a?(Transaction) && !@entry.excluded? %>
|
<% if @entry.account.investment? && @entry.entryable.is_a?(Transaction) && !@entry.excluded? %>
|
||||||
<div class="flex items-center justify-between gap-2 p-3">
|
<div class="flex items-center justify-between gap-2 p-3">
|
||||||
@@ -272,7 +247,6 @@
|
|||||||
<h4 class="text-primary">Convert to Security Trade</h4>
|
<h4 class="text-primary">Convert to Security Trade</h4>
|
||||||
<p class="text-secondary">Convert this transaction into a security trade (buy/sell) by providing ticker, shares, and price.</p>
|
<p class="text-secondary">Convert this transaction into a security trade (buy/sell) by providing ticker, shares, and price.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= render DS::Button.new(
|
<%= render DS::Button.new(
|
||||||
text: "Convert",
|
text: "Convert",
|
||||||
variant: "outline",
|
variant: "outline",
|
||||||
@@ -283,14 +257,12 @@
|
|||||||
) %>
|
) %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Mark as Recurring Form -->
|
<!-- Mark as Recurring Form -->
|
||||||
<div class="flex items-center justify-between gap-2 p-3">
|
<div class="flex items-center justify-between gap-2 p-3">
|
||||||
<div class="text-sm space-y-1">
|
<div class="text-sm space-y-1">
|
||||||
<h4 class="text-primary"><%= t(".mark_recurring_title") %></h4>
|
<h4 class="text-primary"><%= t(".mark_recurring_title") %></h4>
|
||||||
<p class="text-secondary"><%= t(".mark_recurring_subtitle") %></p>
|
<p class="text-secondary"><%= t(".mark_recurring_subtitle") %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= render DS::Button.new(
|
<%= render DS::Button.new(
|
||||||
text: t(".mark_recurring"),
|
text: t(".mark_recurring"),
|
||||||
variant: "outline",
|
variant: "outline",
|
||||||
@@ -300,14 +272,12 @@
|
|||||||
frame: "_top"
|
frame: "_top"
|
||||||
) %>
|
) %>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Delete Transaction Form -->
|
<!-- Delete Transaction Form -->
|
||||||
<div class="flex items-center justify-between gap-2 p-3">
|
<div class="flex items-center justify-between gap-2 p-3">
|
||||||
<div class="text-sm space-y-1">
|
<div class="text-sm space-y-1">
|
||||||
<h4 class="text-primary"><%= t(".delete_title") %></h4>
|
<h4 class="text-primary"><%= t(".delete_title") %></h4>
|
||||||
<p class="text-secondary"><%= t(".delete_subtitle") %></p>
|
<p class="text-secondary"><%= t(".delete_subtitle") %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= render DS::Button.new(
|
<%= render DS::Button.new(
|
||||||
text: t(".delete"),
|
text: t(".delete"),
|
||||||
variant: "outline-destructive",
|
variant: "outline-destructive",
|
||||||
|
|||||||
@@ -1,28 +1,23 @@
|
|||||||
<%= render DS::Dialog.new(frame: "drawer") do |dialog| %>
|
<%= render DS::Dialog.new(frame: "drawer", responsive: true) do |dialog| %>
|
||||||
<% dialog.with_header(hide_close_icon: true) do %>
|
<% dialog.with_header(custom_header: true) do %>
|
||||||
<div class="flex items-start justify-between gap-4">
|
<div class="flex items-start justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h3 class="font-medium flex items-center gap-2">
|
<h3 class="font-medium flex items-center gap-2">
|
||||||
<span class="text-2xl text-primary">
|
<span class="text-2xl text-primary">
|
||||||
<%= format_money @transfer.amount_abs %>
|
<%= format_money @transfer.amount_abs %>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span class="text-lg text-secondary">
|
<span class="text-lg text-secondary">
|
||||||
<%= @transfer.amount_abs.currency.iso_code %>
|
<%= @transfer.amount_abs.currency.iso_code %>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<%= icon "arrow-left-right", size: "sm", class: "text-secondary" %>
|
<%= icon "arrow-left-right", size: "sm", class: "text-secondary" %>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<span class="text-sm text-secondary">
|
<span class="text-sm text-secondary">
|
||||||
<%= @transfer.name %>
|
<%= @transfer.name %>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<%= dialog.close_button %>
|
||||||
<%= render DS::Button.new(variant: "icon", icon: "x", data: { action: "DS--dialog#close" }) %>
|
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_body do %>
|
<% dialog.with_body do %>
|
||||||
<% dialog.with_section(title: t(".overview"), open: true) do %>
|
<% dialog.with_section(title: t(".overview"), open: true) do %>
|
||||||
<div class="pb-4 px-3 pt-2 text-sm space-y-3 text-primary">
|
<div class="pb-4 px-3 pt-2 text-sm space-y-3 text-primary">
|
||||||
@@ -34,20 +29,16 @@
|
|||||||
<%= link_to @transfer.from_account.name, account_path(@transfer.from_account), data: { turbo_frame: "_top" } %>
|
<%= link_to @transfer.from_account.name, account_path(@transfer.from_account), data: { turbo_frame: "_top" } %>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl class="flex items-center gap-2 justify-between">
|
<dl class="flex items-center gap-2 justify-between">
|
||||||
<dt class="text-secondary">Date</dt>
|
<dt class="text-secondary">Date</dt>
|
||||||
<dd class="font-medium"><%= l(@transfer.outflow_transaction.entry.date, format: :long) %></dd>
|
<dd class="font-medium"><%= l(@transfer.outflow_transaction.entry.date, format: :long) %></dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl class="flex items-center gap-2 justify-between">
|
<dl class="flex items-center gap-2 justify-between">
|
||||||
<dt class="text-secondary">Amount</dt>
|
<dt class="text-secondary">Amount</dt>
|
||||||
<dd class="font-medium text-red-500"><%= format_money @transfer.outflow_transaction.entry.amount_money * -1 %></dd>
|
<dd class="font-medium text-red-500"><%= format_money @transfer.outflow_transaction.entry.amount_money * -1 %></dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= render "shared/ruler", classes: "my-2" %>
|
<%= render "shared/ruler", classes: "my-2" %>
|
||||||
|
|
||||||
<div class="space-y-3">
|
<div class="space-y-3">
|
||||||
<dl class="flex items-center gap-2 justify-between">
|
<dl class="flex items-center gap-2 justify-between">
|
||||||
<dt class="text-secondary">To</dt>
|
<dt class="text-secondary">To</dt>
|
||||||
@@ -56,12 +47,10 @@
|
|||||||
<%= link_to @transfer.to_account.name, account_path(@transfer.to_account), data: { turbo_frame: "_top" } %>
|
<%= link_to @transfer.to_account.name, account_path(@transfer.to_account), data: { turbo_frame: "_top" } %>
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl class="flex items-center gap-2 justify-between">
|
<dl class="flex items-center gap-2 justify-between">
|
||||||
<dt class="text-secondary">Date</dt>
|
<dt class="text-secondary">Date</dt>
|
||||||
<dd class="font-medium"><%= l(@transfer.inflow_transaction.entry.date, format: :long) %></dd>
|
<dd class="font-medium"><%= l(@transfer.inflow_transaction.entry.date, format: :long) %></dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
<dl class="flex items-center gap-2 justify-between">
|
<dl class="flex items-center gap-2 justify-between">
|
||||||
<dt class="text-secondary">Amount</dt>
|
<dt class="text-secondary">Amount</dt>
|
||||||
<dd class="font-medium text-green-500">+<%= format_money @transfer.inflow_transaction.entry.amount_money * -1 %></dd>
|
<dd class="font-medium text-green-500">+<%= format_money @transfer.inflow_transaction.entry.amount_money * -1 %></dd>
|
||||||
@@ -69,14 +58,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_section(title: t(".details")) do %>
|
<% dialog.with_section(title: t(".details")) do %>
|
||||||
<%= styled_form_with model: @transfer,
|
<%= styled_form_with model: @transfer,
|
||||||
data: { controller: "auto-submit-form" }, class: "space-y-2" do |f| %>
|
data: { controller: "auto-submit-form" }, class: "space-y-2" do |f| %>
|
||||||
<% if @transfer.categorizable? %>
|
<% if @transfer.categorizable? %>
|
||||||
<%= f.collection_select :category_id, @categories.alphabetically, :id, :name, { label: "Category", include_blank: "Uncategorized", selected: @transfer.outflow_transaction.category&.id }, "data-auto-submit-form-target": "auto" %>
|
<%= f.collection_select :category_id, @categories.alphabetically, :id, :name, { label: "Category", include_blank: "Uncategorized", selected: @transfer.outflow_transaction.category&.id }, "data-auto-submit-form-target": "auto" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= f.text_area :notes,
|
<%= f.text_area :notes,
|
||||||
label: t(".note_label"),
|
label: t(".note_label"),
|
||||||
placeholder: t(".note_placeholder"),
|
placeholder: t(".note_placeholder"),
|
||||||
@@ -84,7 +71,6 @@
|
|||||||
"data-auto-submit-form-target": "auto" %>
|
"data-auto-submit-form-target": "auto" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_section(title: t(".settings")) do %>
|
<% dialog.with_section(title: t(".settings")) do %>
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
<div class="flex items-center justify-between gap-2 p-3">
|
<div class="flex items-center justify-between gap-2 p-3">
|
||||||
@@ -92,7 +78,6 @@
|
|||||||
<h4 class="text-primary"><%= t(".delete_title") %></h4>
|
<h4 class="text-primary"><%= t(".delete_title") %></h4>
|
||||||
<p class="text-secondary"><%= t(".delete_subtitle") %></p>
|
<p class="text-secondary"><%= t(".delete_subtitle") %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= button_to t(".delete"),
|
<%= button_to t(".delete"),
|
||||||
transfer_path(@transfer),
|
transfer_path(@transfer),
|
||||||
method: :delete,
|
method: :delete,
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
<% entry, account = @entry, @entry.account %>
|
<% entry, account = @entry, @entry.account %>
|
||||||
|
<%= render DS::Dialog.new(frame: "drawer", responsive: true) do |dialog| %>
|
||||||
<%= render DS::Dialog.new(frame: "drawer") do |dialog| %>
|
<% dialog.with_header(custom_header: true) do %>
|
||||||
<% dialog.with_header(hide_close_icon: true) do %>
|
<div class="flex items-start justify-between gap-4">
|
||||||
<%= render "valuations/header", entry: @entry %>
|
<%= render "valuations/header", entry: @entry %>
|
||||||
|
<%= dialog.close_button %>
|
||||||
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_body do %>
|
<% dialog.with_body do %>
|
||||||
<% if @error_message.present? %>
|
<% if @error_message.present? %>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<%= render DS::Alert.new(message: @error_message, variant: :error) %>
|
<%= render DS::Alert.new(message: @error_message, variant: :error) %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_section(title: t(".overview"), open: true) do %>
|
<% dialog.with_section(title: t(".overview"), open: true) do %>
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
<%= styled_form_with model: entry,
|
<%= styled_form_with model: entry,
|
||||||
@@ -22,11 +22,9 @@
|
|||||||
<%= f.date_field :date,
|
<%= f.date_field :date,
|
||||||
label: t(".date_label"),
|
label: t(".date_label"),
|
||||||
max: Date.current %>
|
max: Date.current %>
|
||||||
|
|
||||||
<%= f.money_field :amount,
|
<%= f.money_field :amount,
|
||||||
label: "Account value on date",
|
label: "Account value on date",
|
||||||
disable_currency: true %>
|
disable_currency: true %>
|
||||||
|
|
||||||
<div class="flex justify-end">
|
<div class="flex justify-end">
|
||||||
<%= render DS::Button.new(
|
<%= render DS::Button.new(
|
||||||
text: "Update value",
|
text: "Update value",
|
||||||
@@ -37,7 +35,6 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_section(title: t(".details")) do %>
|
<% dialog.with_section(title: t(".details")) do %>
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
<%= styled_form_with model: entry,
|
<%= styled_form_with model: entry,
|
||||||
@@ -53,7 +50,6 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% dialog.with_section(title: t(".settings")) do %>
|
<% dialog.with_section(title: t(".settings")) do %>
|
||||||
<div class="pb-4">
|
<div class="pb-4">
|
||||||
<!-- Delete Valuation Form -->
|
<!-- Delete Valuation Form -->
|
||||||
@@ -62,7 +58,6 @@
|
|||||||
<h4 class="text-primary"><%= t(".delete_title") %></h4>
|
<h4 class="text-primary"><%= t(".delete_title") %></h4>
|
||||||
<p class="text-secondary"><%= t(".delete_subtitle") %></p>
|
<p class="text-secondary"><%= t(".delete_subtitle") %></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= button_to t(".delete"),
|
<%= button_to t(".delete"),
|
||||||
entry_path(entry),
|
entry_path(entry),
|
||||||
method: :delete,
|
method: :delete,
|
||||||
|
|||||||
Reference in New Issue
Block a user