From 57b7848eec14bd671ac06124715c2b42bbcf5206 Mon Sep 17 00:00:00 2001 From: Guillem Arias Date: Mon, 11 May 2026 21:11:42 +0200 Subject: [PATCH] ux(goals/show): catch-up CTA pre-fills + secondary "Adjust your target" link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "Add $1,531.25" CTA used to open the contribution modal with an empty amount field — label was a hint, not a default. Now passes the catch-up amount via ?amount= and the contributions controller seeds @contribution.amount from params. One click brings the user to the modal already populated. Adds a secondary text link below the primary CTA: "Or adjust your target" → opens the edit modal (Turbo frame). Behavioural-econ choice architecture: gives the rebaseline path explicitly so users who can't realistically catch up don't feel forced into the contribution. Trade-off: lets the alert respect autonomy — commit or recalibrate, both fine. Action paralysis kept low by visual hierarchy (primary button vs muted text link). --- app/controllers/goal_contributions_controller.rb | 3 ++- app/views/goals/show.html.erb | 8 ++++++-- config/locales/views/goals/en.yml | 1 + 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/controllers/goal_contributions_controller.rb b/app/controllers/goal_contributions_controller.rb index da3a0353d..17cdeedca 100644 --- a/app/controllers/goal_contributions_controller.rb +++ b/app/controllers/goal_contributions_controller.rb @@ -7,7 +7,8 @@ class GoalContributionsController < ApplicationController @contribution = @goal.goal_contributions.new( contributed_at: Date.current, currency: @goal.currency, - source: "manual" + source: "manual", + amount: params[:amount].presence ) end diff --git a/app/views/goals/show.html.erb b/app/views/goals/show.html.erb index 9acee2f83..9640d0d2f 100644 --- a/app/views/goals/show.html.erb +++ b/app/views/goals/show.html.erb @@ -146,15 +146,19 @@ <%= t("goals.show.catch_up.body", avg: catch_up_avg_money.format, delta: catch_up_delta_money.format) %> <% end %>

-
+
<%= render DS::Link.new( text: t("goals.show.catch_up.cta", amount: catch_up_money.format), variant: "primary", size: "sm", - href: new_goal_contribution_path(@goal), + href: new_goal_contribution_path(@goal, amount: @goal.monthly_target_amount.to_f), icon: "plus", frame: :modal ) %> + <%= link_to t("goals.show.catch_up.adjust_target_cta"), + edit_goal_path(@goal), + data: { turbo_frame: :modal }, + class: "text-xs text-secondary hover:text-primary underline-offset-2 hover:underline" %>
<% end %> <% end %> diff --git a/config/locales/views/goals/en.yml b/config/locales/views/goals/en.yml index db513601e..0eea272ff 100644 --- a/config/locales/views/goals/en.yml +++ b/config/locales/views/goals/en.yml @@ -127,6 +127,7 @@ en: body_with_date: "Your current pace is %{avg}/mo. You need an extra %{delta}/mo to finish by %{date}." body: "Your current pace is %{avg}/mo. You need an extra %{delta}/mo to hit the required rate." cta: "Add %{amount}" + adjust_target_cta: Or adjust your target confirm_complete_title: Mark this goal complete? confirm_complete_body: It leaves the Ongoing list. You can still archive or restore it later. confirm_complete_cta: Mark complete