mirror of
https://github.com/we-promise/sure.git
synced 2026-06-01 08:49:01 +00:00
fix(savings): DS conformance pass on stepper, ring, card, status pill
- StatusPill: use functional `text-success` / `text-warning` tokens with matching icon colors and `px-2 py-1`, mirroring `app/views/budget_categories/_budget_category.html.erb:29-43`. - ProgressRing: rework center text to match `_budget_donut.html.erb` (small "Saved" label, `text-3xl font-medium` headline, "of $X" underline). Stroke color now derives from goal.status (yellow when behind, blue on track, green reached, gray for no-date). - GoalCard bar: track height + transition match budget category bar (`h-1.5`, `transition-all duration-500`, `inline-size`). - Index/show layouts: render page header inline (`<h1>` + actions). The default application layout doesn't yield `:page_actions`, so the CTA + kebab menu wouldn't appear when emitted via `content_for`. - Stepper review summary: target the actual form inputs by `name` rather than relying on the `data-target` Stimulus attribute, since `money_field` puts the attribute on the wrapper. Step 1 validation scoped to the step 1 panel. - Demo generator: filter Depository accounts via `where(accountable_type: "Depository")` — Rails delegated_type generates the `depository?` predicate, not a `.depository` scope.
This commit is contained in:
@@ -15,8 +15,8 @@
|
||||
<span class="text-secondary"><%= goal.current_balance_money.format %></span>
|
||||
<span class="text-secondary">/ <%= goal.target_amount_money.format %></span>
|
||||
</div>
|
||||
<div class="mt-2 h-2 w-full rounded-full bg-container-inset overflow-hidden">
|
||||
<div class="h-full <%= bar_color_class %>" style="width: <%= progress_percent %>%"></div>
|
||||
<div class="mt-2 h-1.5 w-full rounded-full bg-container-inset overflow-hidden">
|
||||
<div class="h-full <%= bar_color_class %> rounded-full transition-all duration-500" style="inline-size: <%= progress_percent %>%"></div>
|
||||
</div>
|
||||
<div class="mt-1 flex items-center justify-between text-xs text-secondary tabular-nums">
|
||||
<span><%= progress_percent %>%</span>
|
||||
|
||||
@@ -21,10 +21,11 @@ class Savings::GoalCardComponent < ApplicationComponent
|
||||
end
|
||||
|
||||
def bar_color_class
|
||||
case progress_percent
|
||||
when 0...25 then "bg-gray-400"
|
||||
when 25...75 then "bg-blue-500"
|
||||
else "bg-green-600"
|
||||
case goal.status
|
||||
when :reached then "bg-green-500"
|
||||
when :behind then "bg-yellow-500"
|
||||
when :on_track then "bg-blue-500"
|
||||
else "bg-gray-400"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
transform="rotate(-90 <%= Savings::ProgressRingComponent::SIZE / 2.0 %> <%= Savings::ProgressRingComponent::SIZE / 2.0 %>)" />
|
||||
</svg>
|
||||
<div class="absolute inset-0 flex flex-col items-center justify-center text-center">
|
||||
<span class="text-2xl font-semibold text-primary tabular-nums"><%= percent %>%</span>
|
||||
<span class="text-xs text-secondary tabular-nums mt-1"><%= current_label %></span>
|
||||
<span class="text-xs text-secondary tabular-nums">of <%= target_label %></span>
|
||||
<span class="text-secondary text-sm mb-1"><%= t("savings_goals.show.ring.saved") %></span>
|
||||
<span class="text-3xl font-medium text-primary tabular-nums privacy-sensitive"><%= current_label %></span>
|
||||
<span class="text-secondary text-sm mt-1 tabular-nums">of <%= target_label %></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class Savings::ProgressRingComponent < ApplicationComponent
|
||||
SIZE = 180
|
||||
SIZE = 220
|
||||
STROKE = 14
|
||||
RADIUS = (SIZE - STROKE) / 2.0
|
||||
CIRCUMFERENCE = 2 * Math::PI * RADIUS
|
||||
@@ -19,10 +19,11 @@ class Savings::ProgressRingComponent < ApplicationComponent
|
||||
end
|
||||
|
||||
def stroke_color
|
||||
case percent
|
||||
when 0...25 then "var(--color-gray-400)"
|
||||
when 25...75 then "var(--color-blue-500)"
|
||||
else "var(--color-green-600)"
|
||||
case goal.status
|
||||
when :reached then "var(--color-green-500)"
|
||||
when :behind then "var(--color-yellow-500)"
|
||||
when :on_track then "var(--color-blue-500)"
|
||||
else "var(--color-gray-400)"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-xs font-medium <%= classes %>">
|
||||
<%= helpers.icon(icon_name, size: "xs", color: "current") %>
|
||||
<span class="inline-flex items-center gap-1 px-2 py-1 rounded-full text-xs font-medium whitespace-nowrap <%= classes %>">
|
||||
<%= helpers.icon(icon_name, size: "sm", color: icon_color) %>
|
||||
<%= label %>
|
||||
</span>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
class Savings::StatusPillComponent < ApplicationComponent
|
||||
VARIANTS = {
|
||||
on_track: { classes: "bg-green-600/10 text-green-700", icon: "check" },
|
||||
behind: { classes: "bg-yellow-500/10 text-yellow-700", icon: "alert-triangle" },
|
||||
reached: { classes: "bg-green-600/10 text-green-700", icon: "circle-check-big" },
|
||||
no_target_date: { classes: "bg-container-inset text-secondary", icon: "calendar-off" }
|
||||
on_track: { classes: "bg-green-500/10 text-success", icon: "check-circle", icon_color: "green" },
|
||||
behind: { classes: "bg-yellow-500/10 text-warning", icon: "alert-triangle", icon_color: "yellow" },
|
||||
reached: { classes: "bg-green-500/10 text-success", icon: "circle-check-big", icon_color: "green" },
|
||||
no_target_date: { classes: "bg-surface-inset text-secondary", icon: "calendar-off", icon_color: "default" }
|
||||
}.freeze
|
||||
|
||||
def initialize(goal:)
|
||||
@@ -26,6 +26,10 @@ class Savings::StatusPillComponent < ApplicationComponent
|
||||
variant[:icon]
|
||||
end
|
||||
|
||||
def icon_color
|
||||
variant[:icon_color]
|
||||
end
|
||||
|
||||
def classes
|
||||
variant[:classes]
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user