From 78f97320de98bc156974c6ada9e0010cede76c32 Mon Sep 17 00:00:00 2001 From: Guillem Arias Date: Mon, 18 May 2026 22:29:20 +0200 Subject: [PATCH] feat(goals): footer 'N pending' on cards + drop warning tone from top callout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Pending pledges surface in the card footer as '· N pending' tacked on after the existing footer line (text-subdued). Quiet, semantic, doesn't compete with the status pill or the avatar. - The top-of-page 'You have pending pledges' callout was using the amber DS::Alert warning variant. Pending isn't a warning — it's a passive 'we're waiting on a sync' state. Switch to the info variant so the visual weight matches the meaning. --- app/components/goals/card_component.html.erb | 12 +++--------- app/components/goals/card_component.rb | 6 +++++- app/views/goals/index.html.erb | 2 +- config/locales/views/goals/en.yml | 3 +++ 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/app/components/goals/card_component.html.erb b/app/components/goals/card_component.html.erb index 64be14b7f..b54c9d24f 100644 --- a/app/components/goals/card_component.html.erb +++ b/app/components/goals/card_component.html.erb @@ -13,14 +13,6 @@ <%= goal.name %>

- <% if has_pending_pledge? %> - " - title="<%= t("goals.goal_card.pending_pledge") %>"> - <%= helpers.icon("clock", size: "xs") %> - - <% end %> <%= render Goals::StatusPillComponent.new(goal: goal) %>

<%= secondary_line %>

@@ -66,6 +58,8 @@ <%= render Goals::AccountStackComponent.new(accounts: linked_accounts, color_map: goal.account_color_map) %> <%= linked_accounts_count_label %> - <%= footer_line %> + + <%= footer_line %><% if has_pending_pledge? %> · <%= t("goals.goal_card.pending_count", count: pending_pledges_count) %><% end %> + diff --git a/app/components/goals/card_component.rb b/app/components/goals/card_component.rb index ac49079a0..4d2a22742 100644 --- a/app/components/goals/card_component.rb +++ b/app/components/goals/card_component.rb @@ -30,7 +30,11 @@ class Goals::CardComponent < ApplicationComponent # `.includes(:open_pledges, ...)` chain in GoalsController#index, so # this is a hit on the in-memory association — no N+1. def has_pending_pledge? - goal.open_pledges.any? + pending_pledges_count.positive? + end + + def pending_pledges_count + @pending_pledges_count ||= goal.open_pledges.size end def linked_accounts_count_label diff --git a/app/views/goals/index.html.erb b/app/views/goals/index.html.erb index b5b6873d1..fe7d9bb34 100644 --- a/app/views/goals/index.html.erb +++ b/app/views/goals/index.html.erb @@ -85,7 +85,7 @@ <% if @any_pending_pledge %> - <%= render DS::Alert.new(variant: "warning", message: t(".pending_pledges_callout"), live: :polite) %> + <%= render DS::Alert.new(variant: "info", message: t(".pending_pledges_callout"), live: :polite) %> <% end %> <%# Goals section %> diff --git a/config/locales/views/goals/en.yml b/config/locales/views/goals/en.yml index fa6e9698f..46ee5e1c9 100644 --- a/config/locales/views/goals/en.yml +++ b/config/locales/views/goals/en.yml @@ -234,6 +234,9 @@ en: footer_catch_up: "Save %{amount}/mo to catch up" footer_no_deadline: Open pending_pledge: Pending pledge + pending_count: + one: 1 pending + other: "%{count} pending" footer_no_pledges: No matched pledges yet footer_last_today: Last pledge matched today footer_last_days: