diff --git a/app/components/settings/health_summary.html.erb b/app/components/settings/health_summary.html.erb deleted file mode 100644 index 646c89521..000000000 --- a/app/components/settings/health_summary.html.erb +++ /dev/null @@ -1,8 +0,0 @@ -
- <% tiles.each do |tile| %> -
-
<%= tile[:count] %>
-
<%= tile[:label] %>
-
- <% end %> -
diff --git a/app/components/settings/health_summary.rb b/app/components/settings/health_summary.rb deleted file mode 100644 index 0fa4d96ad..000000000 --- a/app/components/settings/health_summary.rb +++ /dev/null @@ -1,38 +0,0 @@ -class Settings::HealthSummary < ApplicationComponent - def initialize(counts:) - @counts = counts - end - - private - attr_reader :counts - - def connected_count = counts[:connected] - def needs_attention_count = counts[:needs_attention] - def errors_count = counts[:errors] - def accounts_synced_count = counts[:accounts_synced] - - def tiles - [ - { - count: connected_count, - label: t("settings.providers.health.connected"), - color_class: connected_count > 0 ? "text-success" : "text-subdued" - }, - { - count: needs_attention_count, - label: t("settings.providers.health.needs_attention"), - color_class: needs_attention_count > 0 ? "text-warning" : "text-subdued" - }, - { - count: errors_count, - label: t("settings.providers.health.errors"), - color_class: errors_count > 0 ? "text-destructive" : "text-subdued" - }, - { - count: accounts_synced_count, - label: t("settings.providers.health.accounts_synced"), - color_class: "text-primary" - } - ] - end -end diff --git a/app/components/settings/provider_card.html.erb b/app/components/settings/provider_card.html.erb index 2a286a8bc..d607dd1ca 100644 --- a/app/components/settings/provider_card.html.erb +++ b/app/components/settings/provider_card.html.erb @@ -1,7 +1,9 @@ -
+<%= link_to connect_path, + class: "bg-container shadow-border-xs rounded-xl p-4 flex flex-col gap-3 text-primary hover:bg-container-hover transition-colors", + data: { turbo_frame: "drawer", turbo_prefetch: "false" } do %>
- <%= logo_text %> + <%= logo_text %>
@@ -18,12 +20,8 @@ <% if tagline.present? %>

<%= tagline %>

<% end %> -
- <%= link_to connect_path, - class: "inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:text-primary/70 transition-colors", - data: { turbo_frame: "drawer", turbo_prefetch: "false" } do %> - <%= t("settings.providers.connect") %> - <%= helpers.icon "arrow-right", class: "w-4 h-4" %> - <% end %> +
+ <%= t("settings.providers.connect") %> + <%= helpers.icon "arrow-right", class: "w-4 h-4" %>
-
+<% end %> diff --git a/app/components/settings/provider_card.rb b/app/components/settings/provider_card.rb index 2f9e2bc5e..f92ab9d02 100644 --- a/app/components/settings/provider_card.rb +++ b/app/components/settings/provider_card.rb @@ -1,5 +1,12 @@ class Settings::ProviderCard < ApplicationComponent - MATURITY_LABELS = { beta: "Beta", alpha: "Alpha" }.freeze + def self.maturity_label(maturity) + return nil if maturity.blank? + + key = maturity.to_sym + return nil if key == :stable + + I18n.t("settings.providers.maturity.#{key}", default: nil) + end def initialize(provider_key:, name:, tagline: nil, region: nil, kind: nil, tier: nil, maturity: :stable, logo_bg: "bg-gray-500", logo_text: nil) @@ -15,7 +22,7 @@ def initialize(provider_key:, name:, tagline: nil, region: nil, kind: nil, tier: end def maturity_label - MATURITY_LABELS[@maturity] + self.class.maturity_label(@maturity) end def meta_line diff --git a/app/controllers/settings/providers_controller.rb b/app/controllers/settings/providers_controller.rb index 3549f6321..a3cbb08bb 100644 --- a/app/controllers/settings/providers_controller.rb +++ b/app/controllers/settings/providers_controller.rb @@ -254,13 +254,6 @@ def prepare_show_context @connected = entries.select { |e| e[:summary][:status] == :ok } @needs_attention = entries.select { |e| [ :warn, :err ].include?(e[:summary][:status]) } @available = entries.select { |e| e[:summary][:status] == :off } - - @health_counts = { - connected: @connected.size + @needs_attention.size, - needs_attention: @needs_attention.size, - errors: @needs_attention.count { |e| e[:summary][:status] == :err }, - accounts_synced: Current.family.accounts.joins(:account_providers).distinct.count - } end # Returns a hash mapping provider key → { error:, last_synced_at:, stale: } diff --git a/app/helpers/settings_helper.rb b/app/helpers/settings_helper.rb index 3e73933b9..f03c9b117 100644 --- a/app/helpers/settings_helper.rb +++ b/app/helpers/settings_helper.rb @@ -44,9 +44,9 @@ def adjacent_setting(current_path, offset) } end - def settings_section(title:, subtitle: nil, collapsible: false, open: true, auto_open_param: nil, status: nil, meta: nil, actions: nil, badge: nil, &block) + def settings_section(title:, subtitle: nil, collapsible: false, open: true, auto_open_param: nil, status_pill: nil, meta: nil, actions: nil, badge: nil, &block) content = capture(&block) - render partial: "settings/section", locals: { title: title, subtitle: subtitle, content: content, collapsible: collapsible, open: open, auto_open_param: auto_open_param, status: status, meta: meta, actions: actions, badge: badge } + render partial: "settings/section", locals: { title: title, subtitle: subtitle, content: content, collapsible: collapsible, open: open, auto_open_param: auto_open_param, status_pill: status_pill, meta: meta, actions: actions, badge: badge } end def provider_summary(provider_key) diff --git a/app/models/provider/metadata.rb b/app/models/provider/metadata.rb index 378e133ed..e2326990d 100644 --- a/app/models/provider/metadata.rb +++ b/app/models/provider/metadata.rb @@ -4,7 +4,6 @@ module Metadata simplefin: { region: "US", kind: "Bank", - tier: "Free", maturity: :stable, logo_bg: "bg-blue-600", logo_text: "SF" @@ -12,7 +11,6 @@ module Metadata lunchflow: { region: "US", kind: "Lunch", - tier: "Free", maturity: :stable, logo_bg: "bg-orange-500", logo_text: "LF" @@ -20,7 +18,6 @@ module Metadata enable_banking: { region: "EU", kind: "Bank", - tier: "Free", maturity: :beta, logo_bg: "bg-purple-600", logo_text: "EB" @@ -28,7 +25,6 @@ module Metadata coinstats: { region: "Global", kind: "Crypto", - tier: "Free", maturity: :beta, logo_bg: "bg-yellow-500", logo_text: "CS" @@ -36,7 +32,6 @@ module Metadata mercury: { region: "US", kind: "Bank", - tier: "Free", maturity: :beta, logo_bg: "bg-cyan-600", logo_text: "ME" @@ -44,7 +39,6 @@ module Metadata coinbase: { region: "Global", kind: "Crypto", - tier: "Free", maturity: :beta, logo_bg: "bg-blue-500", logo_text: "CB" @@ -52,7 +46,6 @@ module Metadata binance: { region: "Global", kind: "Crypto", - tier: "Free", maturity: :beta, logo_bg: "bg-yellow-400", logo_text: "BI" @@ -60,7 +53,6 @@ module Metadata snaptrade: { region: "US / CA", kind: "Investment", - tier: "Free", maturity: :beta, logo_bg: "bg-green-600", logo_text: "ST" @@ -68,7 +60,6 @@ module Metadata indexa_capital: { region: "ES", kind: "Investment", - tier: "Free", maturity: :alpha, logo_bg: "bg-red-600", logo_text: "IC" @@ -76,7 +67,6 @@ module Metadata sophtron: { region: "US", kind: "Bank", - tier: "Free", maturity: :alpha, logo_bg: "bg-teal-600", logo_text: "SO" diff --git a/app/views/settings/_section.html.erb b/app/views/settings/_section.html.erb index fcbe77f00..7d93c59e3 100644 --- a/app/views/settings/_section.html.erb +++ b/app/views/settings/_section.html.erb @@ -1,4 +1,4 @@ -<%# locals: (title:, subtitle: nil, content:, collapsible: false, open: true, auto_open_param: nil, status: nil, meta: nil, actions: nil, badge: nil) %> +<%# locals: (title:, subtitle: nil, content:, collapsible: false, open: true, auto_open_param: nil, status_pill: nil, meta: nil, actions: nil, badge: nil) %> <% if collapsible %>
class="group bg-container shadow-border-xs rounded-xl p-4" @@ -16,12 +16,12 @@ <% end %>
- <% if status.present? %> + <% if status_pill.present? %>
<% if meta.present? %> <%= meta %> <% end %> - <%= render "settings/providers/status_pill", status: status %> + <%= status_pill %> <%= actions if actions.present? %>
<% end %> diff --git a/app/views/settings/providers/show.html.erb b/app/views/settings/providers/show.html.erb index b0a2e06e4..df188a167 100644 --- a/app/views/settings/providers/show.html.erb +++ b/app/views/settings/providers/show.html.erb @@ -1,4 +1,4 @@ -<%= content_for :page_title, "Bank Sync" %> +<%= content_for :page_title, t("settings.providers.show.page_title") %>
<% if @encryption_error %> @@ -13,9 +13,7 @@
<% else %>
-

- Connect external accounts so transactions, balances and holdings flow into Sure automatically. -

+

<%= t("settings.providers.show.lede") %>

<% if @connected.any? || @needs_attention.any? %> <% sync_all_disabled = Current.family.last_sync_all_attempted_at.present? && Current.family.last_sync_all_attempted_at > 30.seconds.ago %> <%= button_to sync_all_settings_providers_path, @@ -29,28 +27,25 @@ <% end %>
- <%= render Settings::HealthSummary.new(counts: @health_counts) %> - <% all_connections = @needs_attention + @connected %> - <%= render "settings/providers/group_heading", - title: t("settings.providers.groups.your_connections"), - count: all_connections.size %> - - <% if all_connections.empty? %> -

<%= t("settings.providers.groups.empty_connected") %>

+ <% if all_connections.any? %> + <%= render "settings/providers/group_heading", + title: t("settings.providers.groups.your_connections"), + count: all_connections.size %> <% end %> <% all_connections.each do |entry| %> <% auto_open = [ :warn, :err ].include?(entry[:summary][:status]) || all_connections.size == 1 %> <% sync_action = entry[:partial].present? ? render("settings/providers/sync_button", provider_key: entry[:provider_key], last_synced_at: entry[:summary][:last_synced_at]) : nil %> - <% maturity_label = Settings::ProviderCard::MATURITY_LABELS[entry[:maturity]] %> + <% maturity_label = Settings::ProviderCard.maturity_label(entry[:maturity]) %> <% maturity_badge = maturity_label ? content_tag(:span, maturity_label, class: "text-xs font-medium px-1.5 py-0.5 rounded-full bg-alpha-black-50 text-secondary") : nil %> + <% status_pill = render("settings/providers/status_pill", status: entry[:summary][:status]) %> <%= settings_section title: entry[:title], collapsible: true, open: auto_open, auto_open_param: entry[:auto_open_param], - status: entry[:summary][:status], + status_pill: status_pill, meta: entry[:summary][:meta], actions: sync_action, badge: maturity_badge do %> diff --git a/config/locales/views/settings/en.yml b/config/locales/views/settings/en.yml index c47fd2444..e141c8c7e 100644 --- a/config/locales/views/settings/en.yml +++ b/config/locales/views/settings/en.yml @@ -176,7 +176,7 @@ en: whats_new_label: What's new api_keys_label: API Key appearance_label: Appearance - bank_sync_label: Bank Sync + bank_sync_label: Bank sync settings_nav_link_large: next: Next previous: Back @@ -197,13 +197,7 @@ en: connected: Connected needs_attention: Action needed available: Available - empty_connected: Nothing connected yet — pick a provider below to get started. empty_available: All available providers are connected. - health: - connected: Connected - needs_attention: Action needed - errors: Errors - accounts_synced: Accounts synced meta: sync_error: Sync error no_recent_sync: Sync overdue @@ -235,7 +229,12 @@ en: title: Add another provider body: Connect a new bank or data source to start syncing accounts. cta: Browse providers + maturity: + beta: Beta + alpha: Alpha show: + page_title: Bank sync + lede: Connect external accounts so transactions, balances and holdings flow into Sure automatically. coinbase_title: Coinbase encryption_error: title: Encryption Configuration Required diff --git a/test/system/settings/providers_test.rb b/test/system/settings/providers_test.rb index 2de951c31..fd5870e6b 100644 --- a/test/system/settings/providers_test.rb +++ b/test/system/settings/providers_test.rb @@ -81,17 +81,6 @@ class Settings::ProvidersTest < ApplicationSystemTestCase assert_operator available_y, :<, available_grid_top, "Available heading should appear above the card grid" end - test "health strip shows four tiles with correct counts" do - SimplefinItem.create!(family: @family, name: "Test SimpleFIN", access_url: "https://bridge.simplefin.org/simplefin/access") - - visit settings_providers_path - - assert_text "Connected" - assert_text "Action needed" - assert_text "Errors" - assert_text "Accounts synced" - end - test "action needed group is absent when no providers have issues" do SimplefinItem.create!(family: @family, name: "Test SimpleFIN", access_url: "https://bridge.simplefin.org/simplefin/access") @@ -149,14 +138,11 @@ class Settings::ProvidersTest < ApplicationSystemTestCase end end - test "clicking a provider card connect link opens the connect drawer" do + test "clicking a provider card opens the connect drawer" do visit settings_providers_path within available_provider_cards_container do - card = find(:xpath, ".//div[contains(concat(' ', normalize-space(@class), ' '), ' bg-container ')][.//span[normalize-space()='SimpleFIN']]") - within(card) do - find("a[data-turbo-frame='drawer']", text: "Connect").click - end + find("a[data-turbo-frame='drawer']", text: "SimpleFIN").click end assert_selector "dialog[open]" diff --git a/test/system/settings_test.rb b/test/system/settings_test.rb index 941d1bd02..fa04fb42d 100644 --- a/test/system/settings_test.rb +++ b/test/system/settings_test.rb @@ -7,7 +7,7 @@ class SettingsTest < ApplicationSystemTestCase # Base settings available to all users @settings_links = [ [ "Accounts", accounts_path ], - [ "Bank Sync", settings_providers_path ], + [ "Bank sync", settings_providers_path ], [ "Preferences", settings_preferences_path ], [ "Profile Info", settings_profile_path ], [ "Security", settings_security_path ],