Files
sure/app/views/goals/_pending_pledge_banner.html.erb
Guillem Arias 314113e582 ux(goals): redesign show page — one CTA, calm banners
Header collapses to title + kebab. The status pill and the `Record pledge`
button leave the title row. Status moves into a one-line callout below the
subtitle that doubles as the catch-up demand when behind, the
reach-date when on track, or a prompt for a target date when missing.

`Record pledge` is now the only pledge entry point on the page and lives
under the ring. Behind goals pre-fill it with the catch-up delta.

The standalone catch-up alert card is gone — its title is the callout, its
pace breakdown moves into the projection chart's subtitle, and its CTA
is the ring-adjacent button. The "Adjust target instead" link is
absorbed into the kebab's existing Edit item.

Pending-pledge banner switches from a warning Alert to a neutral
container chip. It is informational state, not a warning. Title carries
the relative pledged-at meta inline; verbose auto-confirms body stays
but in subdued size.

Projection chart drops the today-line pending stub (vertical line +
dashed marker + "+ pending $X" text). That data already lives in the
pending banner above the chart; the duplicate annotation clutters the
today line, the small dashed circle reads as misaligned at small pending
amounts, and the label overlaps the projection trajectory. Shortfall
label gets a paint-order halo so it stays legible across the dashed
projection line.
2026-05-15 14:11:23 +02:00

42 lines
1.8 KiB
Plaintext

<%
account = pledge.account
amount_money = pledge.amount_money
days_left = pledge.days_left
body_key = pledge.kind_transfer? ? "goals.show.pending_pledge.body_transfer" : "goals.show.pending_pledge.body_manual"
title = t("goals.show.pending_pledge.title", amount: amount_money.format(precision: 0), account: account.name, count: days_left)
%>
<div class="rounded-lg bg-surface-inset px-3 py-2.5 text-sm" role="status" aria-live="polite">
<div class="flex items-start gap-2.5">
<span class="text-secondary shrink-0 mt-0.5"><%= icon("info", size: "sm") %></span>
<div class="flex-1 min-w-0">
<p class="text-primary">
<span class="font-medium"><%= title %></span>
<span class="text-secondary">· <%= t("goals.show.pending_pledge.pledged_at", time_ago: time_ago_in_words(pledge.created_at)) %></span>
</p>
<p class="text-xs text-subdued mt-0.5"><%= t(body_key) %></p>
<div class="mt-2 flex items-center gap-2 flex-wrap">
<%= render DS::Button.new(
text: t("goals.show.pending_pledge.extend"),
href: renew_goal_pledge_path(pledge.goal, pledge),
method: :patch,
variant: "outline",
size: "sm"
) %>
<%= render DS::Button.new(
text: t("goals.show.pending_pledge.cancel"),
href: goal_pledge_path(pledge.goal, pledge),
method: :delete,
variant: "ghost",
size: "sm",
confirm: CustomConfirm.new(
destructive: true,
title: t("goals.show.pending_pledge.confirm_cancel_title"),
body: t("goals.show.pending_pledge.confirm_cancel_body", amount: amount_money.format(precision: 0)),
btn_text: t("goals.show.pending_pledge.confirm_cancel_cta")
)
) %>
</div>
</div>
</div>
</div>