mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-05 13:35:21 +02:00
Pre-launch design sync with Figma spec (#2154)
* Add lookbook + viewcomponent, organize design system file * Build menu component * Button updates * More button fixes * Replace all menus with new ViewComponent * Checkpoint: fix tests, all buttons and menus converted * Split into Link and Button components for clarity * Button cleanup * Simplify custom confirmation configuration in views * Finalize button, link component API * Add toggle field to custom form builder + Component * Basic tabs component * Custom tabs, convert all menu / tab instances in app * Gem updates * Centralized icon helper * Update all icon usage to central helper * Lint fixes * Centralize all disclosure instances * Dialog replacements * Consolidation of all dialog styles * Test fixes * Fix app layout issues, move to component with slots * Layout simplification * Flakey test fix * Fix dashboard mobile issues * Finalize homepage * Lint fixes * Fix shadows and borders in dark mode * Fix tests * Remove stale class * Fix filled icon logic * Move transparent? to public interface
This commit is contained in:
parent
1aafed5f8b
commit
90a9546f32
291 changed files with 4143 additions and 3104 deletions
|
@ -25,7 +25,7 @@
|
|||
|
||||
<% unless account.scheduled_for_deletion? %>
|
||||
<%= link_to edit_account_path(account, return_to: return_to), data: { turbo_frame: :modal }, class: "group-hover/account:flex hidden hover:opacity-80 items-center justify-center" do %>
|
||||
<%= lucide_icon "pencil-line", class: "w-4 h-4 text-secondary" %>
|
||||
<%= icon("pencil-line", size: "sm") %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
@ -35,7 +35,9 @@
|
|||
</p>
|
||||
|
||||
<% unless account.scheduled_for_deletion? %>
|
||||
<%= render "shared/toggle_form", model: account, attribute: :is_active, turbo_frame: "_top" %>
|
||||
<%= styled_form_with model: account, data: { turbo_frame: "_top", controller: "auto-submit-form" } do |f| %>
|
||||
<%= f.toggle :is_active, { data: { auto_submit_form_target: "auto" } } %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,88 +1,91 @@
|
|||
<%# locals: (family:) %>
|
||||
<%# locals: (family:, active_account_group_tab:) %>
|
||||
|
||||
<% if family.requires_data_provider? && Provider::Registry.get_provider(:synth).nil? %>
|
||||
<details class="group bg-yellow-tint-10 rounded-lg p-2 text-yellow-600 mb-3 text-xs">
|
||||
<summary class="flex items-center justify-between gap-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<%= icon "triangle-alert", size: "sm" %>
|
||||
<p class="font-medium">Missing historical data</p>
|
||||
<div>
|
||||
<% if family.missing_data_provider? %>
|
||||
<details class="group bg-yellow-tint-10 rounded-lg p-2 text-yellow-600 mb-3 text-xs">
|
||||
<summary class="flex items-center justify-between gap-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<%= icon "triangle-alert", size: "sm", color: "warning" %>
|
||||
<p class="font-medium">Missing historical data</p>
|
||||
</div>
|
||||
|
||||
<%= icon("chevron-down", color: "warning", class: "group-open:transform group-open:rotate-180") %>
|
||||
</summary>
|
||||
<div class="text-xs py-2 space-y-2">
|
||||
<p>Maybe uses Synth API to fetch historical exchange rates, security prices, and more. This data is required to calculate accurate historical account balances.</p>
|
||||
|
||||
<p>
|
||||
<%= link_to "Add your Synth API key here.", settings_hosting_path, class: "text-yellow-600 underline" %>
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
<% end %>
|
||||
|
||||
<%= lucide_icon "chevron-down", class: "text-yellow-600 group-open:transform group-open:rotate-180 w-5" %>
|
||||
</summary>
|
||||
<div class="text-xs py-2 space-y-2">
|
||||
<p>Maybe uses Synth API to fetch historical exchange rates, security prices, and more. This data is required to calculate accurate historical account balances.</p>
|
||||
|
||||
<p>
|
||||
<%= link_to "Add your Synth API key here.", settings_hosting_path, class: "text-yellow-600 underline" %>
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
<% end %>
|
||||
|
||||
<div
|
||||
class="space-y-3"
|
||||
data-controller="tabs"
|
||||
data-tabs-local-storage-key-value="account-sidebar-tabs"
|
||||
data-tabs-active-class="bg-surface shadow-sm text-primary"
|
||||
data-tabs-inactive-class="text-secondary"
|
||||
data-tabs-default-tab-value="assets-tab">
|
||||
<div class="bg-surface-inset rounded-lg p-1 flex">
|
||||
<button type="button" data-id="assets-tab" class="w-1/3 px-2 py-1 rounded-md text-sm text-secondary font-medium" data-tabs-target="btn" data-action="click->tabs#select">
|
||||
Assets
|
||||
</button>
|
||||
|
||||
<button type="button" data-id="debts-tab" class="w-1/3 px-2 py-1 rounded-md text-secondary text-sm font-medium" data-tabs-target="btn" data-action="click->tabs#select">
|
||||
Debts
|
||||
</button>
|
||||
|
||||
<button type="button" data-id="all-tab" class="w-1/3 px-2 py-1 rounded-md text-secondary text-sm font-medium" data-tabs-target="btn" data-action="click->tabs#select">
|
||||
All
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div data-tabs-target="tab" id="assets-tab">
|
||||
<%= link_to new_account_path(step: "method_select", classification: "asset"),
|
||||
class: "flex items-center gap-3 btn btn--ghost text-secondary mb-1",
|
||||
data: { turbo_frame: "modal" } do %>
|
||||
<%= icon("plus") %>
|
||||
<span>New asset</span>
|
||||
<%= render TabsComponent.new(active_tab: active_account_group_tab, url_param_key: "account_group_tab", testid: "account-sidebar-tabs") do |tabs| %>
|
||||
<% tabs.with_nav do |nav| %>
|
||||
<% nav.with_btn(id: "assets", label: "Assets") %>
|
||||
<% nav.with_btn(id: "debts", label: "Debts") %>
|
||||
<% nav.with_btn(id: "all", label: "All") %>
|
||||
<% end %>
|
||||
|
||||
<div class="space-y-2">
|
||||
<% family.balance_sheet.account_groups("asset").each do |group| %>
|
||||
<%= render "accounts/accountable_group", account_group: group %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% tabs.with_panel(tab_id: "assets") do %>
|
||||
<div class="space-y-2">
|
||||
<%= render LinkComponent.new(
|
||||
text: "New asset",
|
||||
variant: "ghost",
|
||||
href: new_account_path(step: "method_select", classification: "asset"),
|
||||
icon: "plus",
|
||||
frame: :modal,
|
||||
full_width: true,
|
||||
class: "justify-start"
|
||||
) %>
|
||||
|
||||
<div data-tabs-target="tab" id="debts-tab" class="hidden">
|
||||
<%= link_to new_account_path(step: "method_select", classification: "liability"),
|
||||
class: "flex items-center gap-3 btn btn--ghost text-secondary mb-1",
|
||||
data: { turbo_frame: "modal" } do %>
|
||||
<%= icon("plus") %>
|
||||
<span>New debt</span>
|
||||
<div>
|
||||
<% family.balance_sheet.account_groups("asset").each do |group| %>
|
||||
<%= render "accounts/accountable_group", account_group: group %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="space-y-2">
|
||||
<% family.balance_sheet.account_groups("liability").each do |group| %>
|
||||
<%= render "accounts/accountable_group", account_group: group %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% tabs.with_panel(tab_id: "debts") do %>
|
||||
<div class="space-y-2">
|
||||
<%= render LinkComponent.new(
|
||||
text: "New debt",
|
||||
variant: "ghost",
|
||||
href: new_account_path(step: "method_select", classification: "liability"),
|
||||
icon: "plus",
|
||||
frame: :modal,
|
||||
full_width: true,
|
||||
class: "justify-start"
|
||||
) %>
|
||||
|
||||
<div data-tabs-target="tab" id="all-tab" class="hidden">
|
||||
<%= link_to new_account_path(step: "method_select"),
|
||||
class: "flex items-center gap-3 btn btn--ghost text-secondary mb-1",
|
||||
data: { turbo_frame: "modal" } do %>
|
||||
<%= icon("plus") %>
|
||||
<span>New account</span>
|
||||
<div>
|
||||
<% family.balance_sheet.account_groups("liability").each do |group| %>
|
||||
<%= render "accounts/accountable_group", account_group: group %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="space-y-2">
|
||||
<% family.balance_sheet.account_groups.each do |group| %>
|
||||
<%= render "accounts/accountable_group", account_group: group %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% tabs.with_panel(tab_id: "all") do %>
|
||||
<div class="space-y-2">
|
||||
<%= render LinkComponent.new(
|
||||
text: "New account",
|
||||
variant: "ghost",
|
||||
full_width: true,
|
||||
href: new_account_path(step: "method_select"),
|
||||
icon: "plus",
|
||||
frame: :modal,
|
||||
class: "justify-start"
|
||||
) %>
|
||||
|
||||
<div>
|
||||
<% family.balance_sheet.account_groups.each do |group| %>
|
||||
<%= render "accounts/accountable_group", account_group: group %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
<%# locals: (accountable:) %>
|
||||
|
||||
<%= link_to new_polymorphic_path(accountable, step: "method_select", return_to: params[:return_to]),
|
||||
class: "flex items-center gap-4 w-full text-center focus:outline-hidden hover:bg-surface-hover focus:bg-surface-hover fg-contrast hover:fg-primary focus:fg-primary border border-transparent block px-2 rounded-lg p-2" do %>
|
||||
<span style="background-color: color-mix(in srgb, <%= accountable.color %> 10%, white);" class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg border border-alpha-black-25">
|
||||
<%= lucide_icon(accountable.icon, style: "color: #{accountable.color}", class: "w-5 h-5") %>
|
||||
</span>
|
||||
class: "flex items-center gap-4 w-full text-center focus:outline-hidden hover:bg-surface-hover focus:bg-surface-hover fg-primary border border-transparent block px-2 rounded-lg p-2" do %>
|
||||
<%= render FilledIconComponent.new(
|
||||
icon: accountable.icon,
|
||||
hex_color: accountable.color,
|
||||
) %>
|
||||
|
||||
<%= accountable.display_name.singularize %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
<%# locals: (account_group:) %>
|
||||
|
||||
<details class="group" data-controller="account-collapse" data-account-collapse-type-value="<%= account_group.key %>">
|
||||
<summary class="px-3 py-2 flex items-center gap-3 cursor-pointer h-10 mb-1">
|
||||
<%= lucide_icon("chevron-right", class: "group-open:rotate-90 text-secondary w-5 h-5") %>
|
||||
|
||||
<%= tag.p account_group.name, class: "text-sm font-medium" %>
|
||||
|
||||
<%= render DisclosureComponent.new(title: account_group.name, align: :left) do |disclosure| %>
|
||||
<% disclosure.with_summary_content do %>
|
||||
<div class="ml-auto text-right grow">
|
||||
<%= tag.p format_money(account_group.total_money), class: "text-sm font-medium text-primary" %>
|
||||
|
||||
|
@ -15,11 +11,11 @@
|
|||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</summary>
|
||||
<% end %>
|
||||
|
||||
<div class="space-y-1">
|
||||
<% account_group.accounts.each do |account| %>
|
||||
<%= link_to account_path(account), class: "block flex items-center gap-2 btn btn--ghost", title: account.name do %>
|
||||
<%= link_to account_path(account), class: "block flex items-center gap-2 px-3 py-2 hover:bg-surface-hover", title: account.name do %>
|
||||
<%= render "accounts/logo", account: account, size: "sm", color: account_group.color %>
|
||||
|
||||
<div class="min-w-0 grow">
|
||||
|
@ -40,10 +36,13 @@
|
|||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= link_to new_polymorphic_path(account_group.key, step: "method_select"),
|
||||
class: "flex items-center gap-3 btn btn--ghost text-secondary",
|
||||
data: { turbo_frame: "modal" } do %>
|
||||
<%= icon("plus") %>
|
||||
<span>New <%= account_group.name.downcase.singularize %></span>
|
||||
<% end %>
|
||||
</details>
|
||||
<%= render LinkComponent.new(
|
||||
href: new_polymorphic_path(account_group.key, step: "method_select"),
|
||||
text: "New #{account_group.name.downcase.singularize}",
|
||||
icon: "plus",
|
||||
full_width: true,
|
||||
variant: "ghost",
|
||||
frame: :modal,
|
||||
class: "justify-start"
|
||||
) %>
|
||||
<% end %>
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
<%= tag.p t(".no_accounts"), class: "text-primary mb-1 font-medium" %>
|
||||
<%= tag.p t(".empty_message"), class: "text-secondary mb-4" %>
|
||||
|
||||
<%= link_to new_account_path, class: "w-fit flex text-white text-sm font-medium items-center gap-1 bg-gray-900 rounded-lg p-2 pr-3", data: { turbo_frame: "modal" } do %>
|
||||
<%= lucide_icon("plus", class: "w-5 h-5") %>
|
||||
<span><%= t(".new_account") %></span>
|
||||
<% end %>
|
||||
<%= render LinkComponent.new(
|
||||
text: t(".new_account"),
|
||||
href: new_account_path,
|
||||
frame: :modal
|
||||
) %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -12,5 +12,5 @@
|
|||
<% elsif account.logo.attached? %>
|
||||
<%= image_tag account.logo, class: "shrink-0 rounded-full #{size_classes[size]}" %>
|
||||
<% else %>
|
||||
<%= circle_logo(account.name, hex: color || account.accountable.color, size: size) %>
|
||||
<%= render FilledIconComponent.new(variant: :text, hex_color: color || account.accountable.color, text: account.name, size: size, rounded: true) %>
|
||||
<% end %>
|
||||
|
|
|
@ -2,23 +2,23 @@
|
|||
<h1 class="text-xl"><%= t(".accounts") %></h1>
|
||||
<div class="flex items-center gap-5">
|
||||
<div class="flex items-center gap-2">
|
||||
<%= button_to sync_all_accounts_path,
|
||||
disabled: Current.family.syncing?,
|
||||
class: "md:btn md:btn--outline flex items-center justify-center gap-2 w-9 h-9 md:w-auto md:h-auto rounded-full md:rounded-lg",
|
||||
title: t(".sync") do %>
|
||||
<%= lucide_icon "refresh-cw", class: "w-5 h-5" %>
|
||||
<span class="hidden md:inline"><%= t(".sync") %></span>
|
||||
<% end %>
|
||||
<%= render ButtonComponent.new(
|
||||
text: "Sync all",
|
||||
href: sync_all_accounts_path,
|
||||
method: :post,
|
||||
variant: "outline",
|
||||
disabled: Current.family.syncing?,
|
||||
icon: "refresh-cw",
|
||||
class: ""
|
||||
) %>
|
||||
|
||||
<%= link_to new_account_path(return_to: accounts_path),
|
||||
data: { turbo_frame: "modal" },
|
||||
class: "btn btn--primary flex items-center justify-center gap-1 w-9 h-9 md:w-auto md:h-auto rounded-full md:rounded-lg" do %>
|
||||
<div class="flex items-center justify-center w-5 h-5">
|
||||
|
||||
<%= lucide_icon("plus") %>
|
||||
</div>
|
||||
<p class="hidden md:block text-sm font-medium"><%= t(".new_account") %></p>
|
||||
<% end %>
|
||||
<%= render LinkComponent.new(
|
||||
text: "New account",
|
||||
href: new_account_path(return_to: accounts_path),
|
||||
variant: "primary",
|
||||
icon: "plus",
|
||||
frame: :modal
|
||||
) %>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
|
||||
<details open class="group bg-container p-4 shadow-border-xs rounded-xl">
|
||||
<summary class="flex items-center gap-2 focus-visible:outline-hidden">
|
||||
<%= lucide_icon "chevron-right", class: "group-open:transform group-open:rotate-90 text-secondary w-5" %>
|
||||
<%= icon("chevron-right", class: "group-open:transform group-open:rotate-90") %>
|
||||
|
||||
<div class="flex items-center justify-center h-8 w-8 rounded-full bg-black/5">
|
||||
<%= lucide_icon("folder-pen", class: "w-5 h-5 text-secondary") %>
|
||||
<%= icon("folder-pen") %>
|
||||
</div>
|
||||
|
||||
<span class="mr-auto text-sm font-medium text-primary"><%= t(".other_accounts") %></span>
|
||||
|
|
|
@ -24,10 +24,12 @@
|
|||
<% unless params[:return_to].present? %>
|
||||
<%= button_to imports_path(import: { type: "AccountImport" }),
|
||||
data: { turbo_frame: :_top },
|
||||
class: "flex items-center gap-4 w-full text-center focus:outline-hidden hover:bg-surface-hover focus:bg-surface-hover fg-contrast hover:fg-primary focus:fg-primary border border-transparent block px-2 rounded-lg p-2" do %>
|
||||
<span style="background-color: color-mix(in srgb, #F79009 10%, white);" class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg border border-alpha-black-25">
|
||||
<%= lucide_icon("download", style: "color: #F79009", class: "w-5 h-5") %>
|
||||
</span>
|
||||
class: "flex items-center gap-4 w-full text-center focus:outline-hidden hover:bg-surface-hover focus:bg-surface-hover fg-primary border border-transparent block px-2 rounded-lg p-2" do %>
|
||||
<%= render FilledIconComponent.new(
|
||||
icon: "download",
|
||||
hex_color: "#F79009",
|
||||
) %>
|
||||
|
||||
<%= t("accounts.new.import_accounts") %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
<%# locals: (title:, back_path: nil) %>
|
||||
|
||||
<%= modal do %>
|
||||
<div class="flex flex-col w-screen max-w-xl relative" data-controller="list-keyboard-navigation">
|
||||
<div class="border-b border-tertiary md:border-alpha-black-25 p-4 text-gray-800 flex items-center space-x-3">
|
||||
<% if back_path %>
|
||||
<%= link_to back_path, class: "flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg bg-alpha-black-50 focus:outline-gray-300 focus:outline" do %>
|
||||
<%= lucide_icon("arrow-left", class: "text-secondary w-5 h-5") %>
|
||||
<%= render DialogComponent.new do |dialog| %>
|
||||
<div class="flex flex-col relative" data-controller="list-keyboard-navigation">
|
||||
<div class="border-b border-tertiary md:border-alpha-black-25 px-4 pb-4 text-gray-800 flex items-center justify-between gap-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<% if back_path %>
|
||||
<%= render LinkComponent.new(
|
||||
variant: "icon",
|
||||
icon: "arrow-left",
|
||||
href: back_path,
|
||||
size: "lg"
|
||||
) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<span class="text-primary"><%= title %></span>
|
||||
<button class="absolute top-1/2 -translate-y-1/2 right-4 flex w-8 h-8 items-center justify-center rounded-lg md:hidden outline-0" data-action="click->modal#close">
|
||||
<%= lucide_icon("x", class: "text-secondary w-6 h-6") %>
|
||||
</button>
|
||||
<span class="text-primary"><%= title %></span>
|
||||
</div>
|
||||
|
||||
<%= icon("x", as_button: true, size: "lg", data: { action: "dialog#close" }) %>
|
||||
</div>
|
||||
|
||||
<div class="p-2 text-subdued">
|
||||
|
@ -22,20 +26,26 @@
|
|||
<%= yield %>
|
||||
</div>
|
||||
|
||||
<div class="border-t border-alpha-black-25 p-4 text-secondary text-sm justify-between hidden md:flex">
|
||||
<div class="border-t border-alpha-black-25 px-4 pt-4 text-secondary text-sm justify-between hidden md:flex">
|
||||
<div class="flex space-x-5">
|
||||
<div class="flex items-center space-x-2">
|
||||
<span>Select</span>
|
||||
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-5 h-5 shrink-0 grow-0 items-center justify-center"><%= lucide_icon("corner-down-left", class: "inline w-3 h-3") %></kbd>
|
||||
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-5 h-5 shrink-0 grow-0 items-center justify-center">
|
||||
<%= icon("corner-down-left", size: "xs") %>
|
||||
</kbd>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<span>Navigate</span>
|
||||
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-5 h-5 shrink-0 grow-0 items-center justify-center"><%= lucide_icon("arrow-up", class: "inline w-3 h-3") %></kbd>
|
||||
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-5 h-5 shrink-0 grow-0 items-center justify-center"><%= lucide_icon("arrow-down", class: "inline w-3 h-3") %></kbd>
|
||||
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-5 h-5 shrink-0 grow-0 items-center justify-center">
|
||||
<%= icon("arrow-up", size: "xs") %>
|
||||
</kbd>
|
||||
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-5 h-5 shrink-0 grow-0 items-center justify-center">
|
||||
<%= icon("arrow-down", size: "xs") %>
|
||||
</kbd>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<button data-action="modal#close">Close</button>
|
||||
<button data-action="dialog#close">Close</button>
|
||||
<kbd class="bg-alpha-black-50 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.1)] p-1 rounded-md flex w-8 h-5 shrink-0 grow-0 items-center justify-center text-xs">ESC</kbd>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
|
||||
<%= render layout: "accounts/new/container", locals: { title: t(".title"), back_path: new_account_path } do %>
|
||||
<div class="text-sm">
|
||||
<%= link_to path, class: "flex items-center gap-4 w-full text-center focus:outline-hidden focus:bg-surface border border-transparent focus:border focus:border-gray-200 px-2 hover:bg-surface rounded-lg p-2" do %>
|
||||
<%= link_to path, class: "flex items-center gap-4 w-full text-center text-primary focus:outline-hidden focus:bg-surface border border-transparent focus:border focus:border-gray-200 px-2 hover:bg-surface rounded-lg p-2" do %>
|
||||
<span class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg bg-alpha-black-50 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.02)]">
|
||||
<%= lucide_icon("keyboard", class: "text-secondary w-5 h-5") %>
|
||||
<%= icon("keyboard") %>
|
||||
</span>
|
||||
<%= t("accounts.new.method_selector.manual_entry") %>
|
||||
<% end %>
|
||||
|
||||
<% if us_link_token %>
|
||||
<%# Default US-only Link %>
|
||||
<button data-controller="plaid" data-action="plaid#open modal#close" data-plaid-region-value="us" data-plaid-link-token-value="<%= us_link_token %>" class="flex items-center gap-4 w-full text-center focus:outline-hidden focus:bg-gray-50 border border-transparent focus:border focus:border-gray-200 px-2 hover:bg-gray-50 rounded-lg p-2">
|
||||
<button data-controller="plaid" data-action="plaid#open dialog#close" data-plaid-region-value="us" data-plaid-link-token-value="<%= us_link_token %>" class="text-primary flex items-center gap-4 w-full text-center focus:outline-hidden focus:bg-gray-50 border border-transparent focus:border focus:border-gray-200 px-2 hover:bg-gray-50 rounded-lg p-2">
|
||||
<span class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg bg-alpha-black-50 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.02)]">
|
||||
<%= lucide_icon("link-2", class: "text-secondary w-5 h-5") %>
|
||||
<%= icon("link-2") %>
|
||||
</span>
|
||||
<%= t("accounts.new.method_selector.connected_entry") %>
|
||||
</button>
|
||||
|
@ -21,9 +21,9 @@
|
|||
|
||||
<%# EU Link %>
|
||||
<% if eu_link_token %>
|
||||
<button data-controller="plaid" data-action="plaid#open modal#close" data-plaid-region-value="eu" data-plaid-link-token-value="<%= eu_link_token %>" class="flex items-center gap-4 w-full text-center focus:outline-hidden focus:bg-gray-50 border border-transparent focus:border focus:border-gray-200 px-2 hover:bg-gray-50 rounded-lg p-2">
|
||||
<button data-controller="plaid" data-action="plaid#open dialog#close" data-plaid-region-value="eu" data-plaid-link-token-value="<%= eu_link_token %>" class="text-primary flex items-center gap-4 w-full text-center focus:outline-hidden focus:bg-gray-50 border border-transparent focus:border focus:border-gray-200 px-2 hover:bg-gray-50 rounded-lg p-2">
|
||||
<span class="flex w-8 h-8 shrink-0 grow-0 items-center justify-center rounded-lg bg-alpha-black-50 shadow-[inset_0_0_0_1px_rgba(0,0,0,0.02)]">
|
||||
<%= lucide_icon("link-2", class: "text-secondary w-5 h-5") %>
|
||||
<%= icon("link-2") %>
|
||||
</span>
|
||||
<%= t("accounts.new.method_selector.connected_entry_eu") %>
|
||||
</button>
|
||||
|
|
|
@ -2,30 +2,29 @@
|
|||
|
||||
<%= turbo_frame_tag dom_id(account, "entries") do %>
|
||||
<div class="bg-container p-5 shadow-border-xs rounded-xl" data-controller="focus-record" data-focus-record-id-value="<%= @focused_record ? dom_id(@focused_record) : nil %>">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<div class="flex items-center justify-between mb-4" data-testid="activity-menu">
|
||||
<%= tag.h2 t(".title"), class: "font-medium text-lg" %>
|
||||
<% unless @account.plaid_account_id.present? %>
|
||||
<div data-controller="menu" data-testid="activity-menu">
|
||||
<button class="btn btn--secondary flex items-center gap-2" data-menu-target="button">
|
||||
<%= lucide_icon("plus", class: "w-4 h-4") %>
|
||||
<%= tag.span t(".new") %>
|
||||
</button>
|
||||
<div data-menu-target="content" class="z-10 hidden bg-container rounded-lg border border-alpha-black-25 shadow-xs p-1">
|
||||
<%= link_to new_valuation_path(account_id: @account.id), data: { turbo_frame: :modal }, class: "block p-2 rounded-lg hover:bg-gray-50 flex items-center gap-2" do %>
|
||||
<%= lucide_icon("circle-dollar-sign", class: "text-secondary w-5 h-5") %>
|
||||
<%= tag.span t(".new_balance"), class: "text-sm" %>
|
||||
<% end %>
|
||||
<%= render MenuComponent.new(variant: "button") do |menu| %>
|
||||
<% menu.with_button(text: "New", variant: "secondary", icon: "plus") %>
|
||||
|
||||
<% unless @account.crypto? %>
|
||||
<%= link_to @account.investment? ? new_trade_path(account_id: @account.id) : new_transaction_path(account_id: @account.id), data: { turbo_frame: :modal }, class: "btn btn--primary flex items-center justify-center gap-2 rounded-full md:rounded-lg w-9 h-9 md:w-auto md:h-auto" do %>
|
||||
<span class="flex items-center justify-center">
|
||||
<%= lucide_icon("credit-card", class: "text-secondary w-5 h-5") %>
|
||||
</span>
|
||||
<%= tag.span t(".new_transaction"), class: "text-sm md:block" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% menu.with_item(
|
||||
variant: "link",
|
||||
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(
|
||||
variant: "link",
|
||||
text: "New transaction",
|
||||
icon: "credit-card",
|
||||
href: href,
|
||||
data: { turbo_frame: :modal }) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
|
@ -38,7 +37,7 @@
|
|||
<div class="flex gap-2 mb-4">
|
||||
<div class="grow">
|
||||
<div class="flex items-center px-3 py-2 gap-2 border border-secondary rounded-lg focus-within:ring-gray-100 focus-within:border-gray-900">
|
||||
<%= lucide_icon("search", class: "w-5 h-5 text-secondary") %>
|
||||
<%= icon("search") %>
|
||||
<%= hidden_field_tag :account_id, @account.id %>
|
||||
<%= form.search_field :search,
|
||||
placeholder: "Search entries by name",
|
||||
|
|
|
@ -24,7 +24,11 @@
|
|||
data: { "auto-submit-form-target": "auto" } %>
|
||||
<% end %>
|
||||
|
||||
<%= period_select form: form, selected: period %>
|
||||
<%= form.select :period,
|
||||
Period.as_options,
|
||||
{ selected: period.key },
|
||||
data: { "auto-submit-form-target": "auto" },
|
||||
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" %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -19,17 +19,27 @@
|
|||
</div>
|
||||
<% end %>
|
||||
|
||||
<div class="flex items-center gap-3 ml-auto">
|
||||
<div class="flex items-center gap-1 ml-auto">
|
||||
<% if account.plaid_account_id.present? %>
|
||||
<% if Rails.env.development? %>
|
||||
<%= button_to sync_plaid_item_path(account.plaid_account.plaid_item), disabled: account.syncing?, data: { turbo: false }, class: "flex items-center gap-2", title: "Sync Account" do %>
|
||||
<%= lucide_icon "refresh-cw", class: "w-4 h-4 text-secondary hover:text-subdued" %>
|
||||
<% end %>
|
||||
<%= icon(
|
||||
"refresh-cw",
|
||||
as_button: true,
|
||||
size: "sm",
|
||||
href: sync_plaid_item_path(account.plaid_account.plaid_item),
|
||||
disabled: account.syncing?,
|
||||
frame: :_top
|
||||
) %>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= button_to sync_account_path(account), disabled: account.syncing?, data: { turbo: false }, class: "flex items-center gap-2", title: "Sync Account" do %>
|
||||
<%= lucide_icon "refresh-cw", class: "w-4 h-4 text-secondary hover:text-subdued" %>
|
||||
<% end %>
|
||||
<%= icon(
|
||||
"refresh-cw",
|
||||
as_button: true,
|
||||
size: "sm",
|
||||
href: sync_account_path(account),
|
||||
disabled: account.syncing?,
|
||||
frame: :_top
|
||||
) %>
|
||||
<% end %>
|
||||
|
||||
<%= render "accounts/show/menu", account: account %>
|
||||
|
|
|
@ -1,47 +1,25 @@
|
|||
<%# locals: (account:) %>
|
||||
|
||||
<%= contextual_menu do %>
|
||||
<div class="w-48 p-1 text-sm leading-6 text-primary bg-container shadow-lg shrink rounded-xl ring-1 ring-gray-900/5">
|
||||
<% if account.plaid_account_id.present? %>
|
||||
<%= link_to accounts_path,
|
||||
data: { turbo_frame: :_top },
|
||||
class: "block w-full py-2 px-3 space-x-2 text-primary hover:bg-gray-50 flex items-center rounded-lg" do %>
|
||||
<%= lucide_icon "pencil-line", class: "w-5 h-5 text-secondary" %>
|
||||
<%= render MenuComponent.new(testid: "account-menu") do |menu| %>
|
||||
<% menu.with_item(variant: "link", text: "Edit", href: edit_account_path(account), icon: "pencil-line", data: { turbo_frame: :modal }) %>
|
||||
|
||||
<span><%= t(".manage") %></span>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<%= link_to edit_account_path(account),
|
||||
data: { turbo_frame: :modal },
|
||||
class: "block w-full py-2 px-3 space-x-2 text-primary hover:bg-gray-50 flex items-center rounded-lg" do %>
|
||||
<%= lucide_icon "pencil-line", class: "w-5 h-5 text-secondary" %>
|
||||
<% unless account.crypto? %>
|
||||
<% menu.with_item(
|
||||
variant: "link",
|
||||
text: "Import transactions",
|
||||
href: imports_path({ import: { type: account.investment? ? "TradeImport" : "TransactionImport", account_id: account.id } }),
|
||||
icon: "download",
|
||||
data: { turbo_frame: :_top }
|
||||
) %>
|
||||
<% end %>
|
||||
|
||||
<span><%= t(".edit") %></span>
|
||||
<% end %>
|
||||
|
||||
<% unless account.crypto? %>
|
||||
<%= button_to imports_path({ import: { type: account.investment? ? "TradeImport" : "TransactionImport", account_id: account.id } }),
|
||||
data: { turbo_frame: :_top },
|
||||
class: "block w-full py-2 px-3 space-x-2 text-primary hover:bg-gray-50 flex items-center rounded-lg" do %>
|
||||
<%= lucide_icon "download", class: "w-5 h-5 text-secondary" %>
|
||||
|
||||
<span><%= t(".import") %></span>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= button_to account_path(account),
|
||||
method: :delete,
|
||||
class: "block w-full py-2 px-3 space-x-2 text-red-600 hover:bg-red-50 flex items-center rounded-lg",
|
||||
data: {
|
||||
turbo_frame: :_top,
|
||||
turbo_confirm: {
|
||||
title: t(".confirm_title"),
|
||||
body: t(".confirm_body_html"),
|
||||
accept: t(".confirm_accept", name: account.name)
|
||||
}
|
||||
} do %>
|
||||
<%= lucide_icon("trash-2", class: "w-5 h-5 mr-2") %> Delete account
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% menu.with_item(
|
||||
variant: "button",
|
||||
text: "Delete account",
|
||||
href: account_path(account),
|
||||
method: :delete,
|
||||
icon: "trash-2",
|
||||
confirm: CustomConfirm.for_resource_deletion("Account", high_severity: true),
|
||||
data: { turbo_frame: :_top }
|
||||
) %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
<%# locals: (account:, tabs:) %>
|
||||
|
||||
<% selected_tab = tabs.find { |tab| tab[:key] == params[:tab] } || tabs.first %>
|
||||
<% active_tab = tabs.find { |tab| tab[:key] == params[:tab] } || tabs.first %>
|
||||
|
||||
<div class="flex gap-2 text-sm text-primary font-medium mb-4">
|
||||
<% tabs.each do |tab| %>
|
||||
<%= render "accounts/show/tab", account: account, key: tab[:key], is_selected: selected_tab[:key] == tab[:key] %>
|
||||
<%= render TabsComponent.new(active_tab: active_tab[:key], url_param_key: "tab") do |tabs_container| %>
|
||||
<% tabs_container.with_nav(classes: "max-w-fit") do |nav| %>
|
||||
<% tabs.each do |tab| %>
|
||||
<% nav.with_btn(id: tab[:key], label: tab[:key].humanize, classes: "px-6") %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= selected_tab[:contents] %>
|
||||
<% tabs.each do |tab| %>
|
||||
<% tabs_container.with_panel(tab_id: tab[:key]) do %>
|
||||
<%= tab[:contents] %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<%= render "accounts/show/chart", account: account %>
|
||||
<% end %>
|
||||
|
||||
<div class="min-h-[800px]">
|
||||
<div class="min-h-[800px]" data-testid="account-details>
|
||||
<% if tabs.present? %>
|
||||
<%= tabs %>
|
||||
<% else %>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue