mirror of
https://github.com/we-promise/sure.git
synced 2026-06-01 00:39:01 +00:00
- SavingsGoal#display_status returns :archived / :paused before falling
through to the visualization status. Memoized like #status. The plain
#status method keeps its meaning (visualization vs. target/pace) so
callers that genuinely want "is this on track" — KPI sort, goal-card
ring color, projection_payload — keep working unchanged.
- Savings::StatusPillComponent: status_key uses display_status; new
:archived variant (bg-surface-inset / text-gray-700 / archive icon).
Previously an archived goal showed "Behind" on the detail page while
the archived banner said the goal was archived — conflicting signal.
- show.html.erb: paused/archived goals render a static recap card
(current saved vs target) instead of the projection chart. Pace stat
(avg vs required monthly) is also hidden — extrapolating "Behind by
$X/mo" against a goal that isn't accepting contributions is misleading.
- New locale keys: savings_goals.status.archived,
savings_goals.show.inactive.{heading_paused, heading_archived, body}.
- Tests cover display_status for archived / paused / active goals.
40 lines
1.2 KiB
Ruby
40 lines
1.2 KiB
Ruby
class Savings::StatusPillComponent < ApplicationComponent
|
|
# Text colors here intentionally use palette steps (green-700 / yellow-700 /
|
|
# gray-700) rather than `text-success` / `text-warning` / `text-secondary`
|
|
# tokens because the functional tokens drop below WCAG 1.4.3 4.5:1 on tinted
|
|
# surfaces in light mode (~2.88:1 / 3.0:1 / 4.16:1). Local override only;
|
|
# revert once we-promise/sure#1736 lands token-level fixes.
|
|
VARIANTS = {
|
|
on_track: { classes: "bg-green-500/10 text-green-700", icon: "circle-check" },
|
|
behind: { classes: "bg-yellow-500/10 text-yellow-700", icon: "triangle-alert" },
|
|
reached: { classes: "bg-green-500/10 text-green-700", icon: "star" },
|
|
no_target_date: { classes: "bg-surface-inset text-gray-700", icon: "infinity" },
|
|
paused: { classes: "bg-surface-inset text-gray-700", icon: "pause" },
|
|
archived: { classes: "bg-surface-inset text-gray-700", icon: "archive" }
|
|
}.freeze
|
|
|
|
def initialize(goal:)
|
|
@goal = goal
|
|
end
|
|
|
|
def status_key
|
|
@goal.display_status
|
|
end
|
|
|
|
def variant
|
|
VARIANTS.fetch(status_key, VARIANTS[:no_target_date])
|
|
end
|
|
|
|
def label
|
|
I18n.t("savings_goals.status.#{status_key}")
|
|
end
|
|
|
|
def classes
|
|
variant[:classes]
|
|
end
|
|
|
|
def icon_name
|
|
variant[:icon]
|
|
end
|
|
end
|