1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-09 15:35:22 +02:00

Checkpoint: fix tests, all buttons and menus converted

This commit is contained in:
Zach Gollwitzer 2025-04-25 20:30:52 -04:00
parent 2bfd00f611
commit cbd05ae3da
21 changed files with 111 additions and 92 deletions

View file

@ -1,4 +1,4 @@
<div data-controller="menu" data-menu-placement-value="<%= @placement %>" data-menu-offset-value="<%= @offset %>">
<%= tag.div data: merged_data do %>
<% if @variant == :icon %>
<%= render ButtonComponent.new(variant: "icon", icon: @icon_vertical ? "more-vertical" : "more-horizontal", data: { menu_target: "button" }) %>
<% elsif @variant == :button %>
@ -22,4 +22,4 @@
<%= custom_content %>
</div>
</div>
</div>
<% end %>

View file

@ -25,11 +25,20 @@ class MenuComponent < ViewComponent::Base
avatar: {}
}
def initialize(variant: "icon", avatar_url: nil, placement: "bottom-end", offset: 12, icon_vertical: false)
def initialize(variant: "icon", avatar_url: nil, placement: "bottom-end", offset: 12, icon_vertical: false, data: {})
@variant = variant.to_sym
@avatar_url = avatar_url
@placement = placement
@offset = offset
@icon_vertical = icon_vertical
@data = data
end
def merged_data
{
controller: "menu",
menu_placement_value: @placement,
menu_offset_value: @offset
}.merge(@data)
end
end

View file

@ -3,18 +3,18 @@
<div class="flex items-center gap-5">
<div class="flex items-center gap-2">
<%= render ButtonComponent.new(
text: "Sync all",
href: sync_all_accounts_path,
text: "Sync all",
href: sync_all_accounts_path,
method: :post,
variant: "outline",
variant: "outline",
disabled: Current.family.syncing?,
leading_icon: "refresh-cw"
) %>
<%= render ButtonComponent.new(
text: "New account",
href: new_account_path(return_to: accounts_path),
variant: "primary",
text: "New account",
href: new_account_path(return_to: accounts_path),
variant: "primary",
leading_icon: "plus",
data: { turbo_frame: "modal" }
) %>

View file

@ -5,20 +5,20 @@
<div class="flex items-center justify-between mb-4">
<%= tag.h2 t(".title"), class: "font-medium text-lg" %>
<% unless @account.plaid_account_id.present? %>
<%= render MenuComponent.new(variant: "button") do |menu| %>
<%= render MenuComponent.new(variant: "button", data: { testid: "activity-menu" }) do |menu| %>
<% menu.with_button(text: "New", variant: "secondary", leading_icon: "plus") %>
<% menu.with_item(
text: "New balance",
icon: "circle-dollar-sign",
text: "New balance",
icon: "circle-dollar-sign",
href: new_valuation_path(account_id: @account.id), data: { turbo_frame: :modal }) %>
<% unless @account.crypto? %>
<% href = @account.investment? ? new_trade_path(account_id: @account.id) : new_transaction_path(account_id: @account.id) %>
<% menu.with_item(
text: "New transaction",
icon: "credit-card",
href: href,
text: "New transaction",
icon: "credit-card",
href: href,
data: { turbo_frame: :modal }) %>
<% end %>
<% end %>

View file

@ -1,26 +1,26 @@
<%# locals: (account:) %>
<%= render MenuComponent.new do |menu| %>
<% menu.with_item(text: "Edit", href: edit_account_path(account), icon: "pencil-line", data: { turbo_frame: :modal })%>
<% menu.with_item(text: "Edit", href: edit_account_path(account), icon: "pencil-line", data: { turbo_frame: :modal }) %>
<% unless account.crypto? %>
<% menu.with_item(
text: "Import transactions",
href: imports_path({ import: { type: account.investment? ? "TradeImport" : "TransactionImport", account_id: account.id } }),
text: "Import transactions",
href: imports_path({ import: { type: account.investment? ? "TradeImport" : "TransactionImport", account_id: account.id } }),
icon: "download",
data: { turbo_frame: :_top }
) %>
<% end %>
<% menu.with_item(
text: "Delete account",
href: account_path(account),
method: :delete,
icon: "trash-2",
text: "Delete account",
href: account_path(account),
method: :delete,
icon: "trash-2",
data: { turbo_frame: :_top, turbo_confirm: {
title: t(".confirm_title"),
body: t(".confirm_body_html"),
accept: t(".confirm_accept", name: account.name)
}}
)%>
) %>
<% end %>

View file

@ -24,9 +24,9 @@
<p class="text-sm text-secondary font-normal mb-4"><%= t(".empty") %></p>
<%= render ButtonComponent.new(
text: t(".bootstrap"),
variant: "outline",
href: bootstrap_categories_path,
text: t(".bootstrap"),
variant: "outline",
href: bootstrap_categories_path,
method: :post,
data: { turbo_frame: :_top }) %>
</div>

View file

@ -12,14 +12,14 @@
<%= render MenuComponent.new(icon_vertical: true) do |menu| %>
<% menu.with_item(text: "Edit chat", href: edit_chat_path(chat), icon: "pencil", data: { turbo_frame: dom_id(chat, "title") }) %>
<% menu.with_item(
text: "Delete chat",
href: chat_path(chat),
icon: "trash-2",
method: :delete,
data: {
turbo_confirm: {
title: "Are you sure you want to delete this chat?",
variant: "outline-destructive"
text: "Delete chat",
href: chat_path(chat),
icon: "trash-2",
method: :delete,
data: {
turbo_confirm: {
title: "Are you sure you want to delete this chat?",
variant: "outline-destructive"
}
}) %>
<% end %>

View file

@ -19,14 +19,14 @@
<% unless chat.new_record? %>
<% menu.with_item(text: "Edit chat title", href: edit_chat_path(chat, ctx: "chat"), icon: "pencil", data: { turbo_frame: dom_id(chat, "title") }) %>
<% menu.with_item(
text: "Delete chat",
href: chat_path(chat),
icon: "trash-2",
method: :delete,
data: {
turbo_confirm: {
title: "Are you sure you want to delete this chat?",
variant: "outline-destructive"
text: "Delete chat",
href: chat_path(chat),
icon: "trash-2",
method: :delete,
data: {
turbo_confirm: {
title: "Are you sure you want to delete this chat?",
variant: "outline-destructive"
}
}) %>
<% end %>

View file

@ -17,10 +17,10 @@
<div class="justify-self-end">
<%= render MenuComponent.new do |menu| %>
<% menu.with_item(text: "Edit", href: edit_family_merchant_path(family_merchant), icon: "pencil", data: { turbo_frame: "modal" }) %>
<% menu.with_item(text: "Delete", href: family_merchant_path(family_merchant), icon: "trash-2", method: :delete, data: { turbo_confirm: {
title: "Delete #{family_merchant.name}?",
<% menu.with_item(text: "Delete", href: family_merchant_path(family_merchant), icon: "trash-2", method: :delete, data: { turbo_confirm: {
title: "Delete #{family_merchant.name}?",
body: "This will remove this merchant from all transactions it has been assigned to.",
variant: "outline-destructive"
variant: "outline-destructive"
} }) %>
<% end %>
</div>

View file

@ -18,8 +18,8 @@
<p class="text-sm text-secondary">We found a configuration from a previous import for this account. Would you like to apply it to this import?</p>
<div class="mt-4 flex gap-2 items-center">
<%= ButtonComponent.new(text: "Manually configure", href: import_configuration_path(@import), variant: "outline") %>
<%= ButtonComponent.new(text: "Apply template", href: apply_template_import_path(@import), method: :put, data: { turbo_frame: :_top }) %>
<%= render ButtonComponent.new(text: "Manually configure", href: import_configuration_path(@import), variant: "outline") %>
<%= render ButtonComponent.new(text: "Apply template", href: apply_template_import_path(@import), method: :put, data: { turbo_frame: :_top }) %>
</div>
</div>
</div>

View file

@ -41,11 +41,11 @@
<% if import.complete? || import.revert_failed? %>
<% menu.with_item(
text: t(".revert"),
href: revert_import_path(import),
icon: "rotate-ccw",
method: :put,
data: {
text: t(".revert"),
href: revert_import_path(import),
icon: "rotate-ccw",
method: :put,
data: {
turbo_confirm: {
title: "Revert import?",
body: "This will delete transactions that were imported, but you will still be able to review and re-import your data at any time.",
@ -55,16 +55,16 @@
<% else %>
<% menu.with_item(
text: t(".delete"),
href: import_path(import),
icon: "trash-2",
method: :delete,
data: {
turbo_confirm: {
title: "Delete import?",
body: "This will delete the import and is not reversible.",
variant: "outline-destructive"
}
text: t(".delete"),
href: import_path(import),
icon: "trash-2",
method: :delete,
data: {
turbo_confirm: {
title: "Delete import?",
body: "This will delete the import and is not reversible.",
variant: "outline-destructive"
}
}) %>
<% end %>
<% end %>

View file

@ -35,5 +35,5 @@
</div>
</div>
<%= ButtonComponent.new(text: "Publish import", href: publish_import_path(import), method: :post) %>
<%= render ButtonComponent.new(text: "Publish import", href: publish_import_path(import), method: :post) %>
</div>

View file

@ -5,8 +5,8 @@
<h3 class="font-medium text-primary" data-confirm-dialog-target="title">Are you sure?</h3>
<%= render ButtonComponent.new(
variant: "icon",
icon: "x",
variant: "icon",
icon: "x",
value: "cancel",
type: "submit"
) %>

View file

@ -18,10 +18,10 @@
<%= render MenuComponent.new do |menu| %>
<% menu.with_item(text: t(".edit"), href: edit_merchant_path(merchant), icon: "pencil", data: { turbo_frame: "modal" }) %>
<% menu.with_item(
text: t(".delete"),
href: merchant_path(merchant),
icon: "trash-2",
method: :delete,
text: t(".delete"),
href: merchant_path(merchant),
icon: "trash-2",
method: :delete,
data: { turbo_confirm: {
title: t(".confirm_title"),
body: t(".confirm_body"),

View file

@ -17,9 +17,9 @@
</div>
<%= render ButtonComponent.new(
text: "Confirm changes",
href: apply_rule_path(@rule),
method: :post,
text: "Confirm changes",
href: apply_rule_path(@rule),
method: :post,
full_width: true,
data: { turbo_frame: "_top" }) %>
</div>

View file

@ -5,17 +5,17 @@
<% if @rules.any? %>
<%= render MenuComponent.new do |menu| %>
<% menu.with_item(
text: "Delete all rules",
href: destroy_all_rules_path,
icon: "trash-2",
method: :delete,
data: {
text: "Delete all rules",
href: destroy_all_rules_path,
icon: "trash-2",
method: :delete,
data: {
turbo_confirm: {
title: "Delete all rules",
body: "Are you sure you want to delete all rules? This action cannot be undone.",
confirmText: "Delete all rules",
variant: "destructive"
}
}
}) %>
<% end %>
<% end %>

View file

@ -46,9 +46,9 @@
<%= form_with model: @user, class: "flex flex-col md:flex-row justify-between items-center gap-4", id: "theme_form",
data: { controller: "auto-submit-form", auto_submit_form_trigger_event_value: "change" } do |form| %>
<%= form.hidden_field :redirect_to, value: "preferences" %>
<% theme_option_class = "text-center transition-all duration-200 p-3 rounded-lg hover:bg-surface-hover cursor-pointer [&:has(input:checked)]:bg-surface-hover [&:has(input:checked)]:border [&:has(input:checked)]:border-primary [&:has(input:checked)]:shadow-xs" %>
<% [
{ value: "light", image: "light-mode-preview.png" },
{ value: "dark", image: "dark-mode-preview.png" },
@ -57,8 +57,8 @@
<%= form.label :"theme_#{theme[:value]}", class: "group" do %>
<div class="<%= theme_option_class %>">
<%= image_tag(theme[:image], alt: "#{theme[:value].titleize} Theme Preview", class: "h-44 mb-2") %>
<div class="<%= theme[:value] == 'system' ? 'flex items-center gap-2 justify-center' : 'text-sm font-medium text-primary' %>">
<%= form.radio_button :theme, theme[:value], checked: @user.theme == theme[:value], class: "sr-only",
<div class="<%= theme[:value] == "system" ? "flex items-center gap-2 justify-center" : "text-sm font-medium text-primary" %>">
<%= form.radio_button :theme, theme[:value], checked: @user.theme == theme[:value], class: "sr-only",
data: { auto_submit_form_target: "auto", autosubmit_trigger_event: "change", action: "theme#updateTheme" } %>
<%= t(".theme_#{theme[:value]}") %>
</div>

View file

@ -1,14 +1,14 @@
<fieldset class="bg-gray-50 rounded-lg p-1 grid grid-flow-col justify-stretch gap-x-2">
<% active_tab = local_assigns[:active_tab] || 'expense' %>
<% active_tab = local_assigns[:active_tab] || "expense" %>
<%= link_to new_transaction_path(nature: 'outflow'),
<%= link_to new_transaction_path(nature: "outflow"),
data: { turbo_frame: :modal },
class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-sm md:text-normal text-subdued #{active_tab == 'expense' ? 'bg-container text-gray-800 shadow-sm' : 'hover:bg-container hover:text-gray-800 hover:shadow-sm'}" do %>
<%= lucide_icon "minus-circle", class: "w-4 h-4 md:w-5 md:h-5" %>
<%= tag.span t("shared.transaction_tabs.expense") %>
<% end %>
<%= link_to new_transaction_path(nature: 'inflow'),
<%= link_to new_transaction_path(nature: "inflow"),
data: { turbo_frame: :modal },
class: "flex px-4 py-1 rounded-lg items-center space-x-2 justify-center text-sm md:text-normal text-subdued #{active_tab == 'income' ? 'bg-container text-gray-800 shadow-sm' : 'hover:bg-container hover:text-gray-800 hover:shadow-sm'}" do %>
<%= lucide_icon "plus-circle", class: "w-4 h-4 md:w-5 md:h-5" %>

View file

@ -1,6 +1,6 @@
<%# locals: (user:, placement: "right-start", offset: 16) %>
<%= render MenuComponent.new(variant: "avatar", avatar_url: user.profile_image&.variant(:small)&.url, placement: placement, offset: offset) do |menu| %>
<%= render MenuComponent.new(variant: "avatar", avatar_url: user.profile_image&.variant(:small)&.url, placement: placement, offset: offset, data: { testid: "user-menu" }) do |menu| %>
<%= menu.with_header do %>
<div class="px-4 py-3 flex items-center gap-3">
<div class="w-9 h-9 shrink-0">
@ -42,4 +42,4 @@
<% menu.with_item(variant: "divider") %>
<% menu.with_item(text: "Log out", icon: "log-out", href: session_path(Current.session), method: :delete) %>
<% end %>
<% end %>

View file

@ -19,7 +19,9 @@ class ImportsTest < ApplicationSystemTestCase
fill_in "import[raw_file_str]", with: file_fixture("imports/transactions.csv").read
find('input[type="submit"][value="Upload CSV"]').click
within "form" do
click_on "Upload CSV"
end
select "Date", from: "import[date_col_label]"
select "YYYY-MM-DD", from: "import[date_format]"
@ -65,7 +67,9 @@ class ImportsTest < ApplicationSystemTestCase
fill_in "import[raw_file_str]", with: file_fixture("imports/trades.csv").read
find('input[type="submit"][value="Upload CSV"]').click
within "form" do
click_on "Upload CSV"
end
select "date", from: "import[date_col_label]"
select "YYYY-MM-DD", from: "import[date_format]"
@ -103,7 +107,9 @@ class ImportsTest < ApplicationSystemTestCase
fill_in "import[raw_file_str]", with: file_fixture("imports/accounts.csv").read
find('input[type="submit"][value="Upload CSV"]').click
within "form" do
click_on "Upload CSV"
end
select "type", from: "import[entity_type_col_label]"
select "name", from: "import[name_col_label]"
@ -147,7 +153,9 @@ class ImportsTest < ApplicationSystemTestCase
fill_in "import[raw_file_str]", with: file_fixture("imports/mint.csv").read
find('input[type="submit"][value="Upload CSV"]').click
within "form" do
click_on "Upload CSV"
end
click_on "Apply configuration"

View file

@ -56,7 +56,9 @@ class SettingsTest < ApplicationSystemTestCase
private
def open_settings_from_sidebar
find("#user-menu").click
within "div[data-testid=user-menu]" do
find("button").click
end
click_link "Settings"
end
end