chore(goals): drop dead V1 hooks + surface chart errors

Loose ends from the V1 → V2 refactor that the architecture commit
didn't sweep.

- Demo generator (B14): the `goal_spec[:contributions]` arrays
  + the `wedding_contribs` / `house_contribs` builders still
  shipped in the file, but the seeding loop that consumed them
  was deleted alongside `GoalContribution`. Dead data. Strip both
  the per-goal arrays and the two locals. Goal balance/pace in
  the demo family now derives from the linked depository
  accounts' own seeded entries elsewhere in the generator.

- Goal stepper controller (B16): the `static targets` declaration
  still listed `initialContributionAmount` and
  `initialContributionAccountSelect`, and `refreshAccountSelect`
  + its two callsites still ran every time a linked-account
  checkbox flipped. The HTML targets disappeared with the V2
  stepper rebuild, so `has*Target` guards short-circuited and the
  method was a no-op — but it was still dispatched on every
  change. Drop the targets, the method, and the two callsites.

- Chart series rescue (B25): `Goal#balance_series_values` and
  `FundingAccountsBreakdownComponent#sparkline_map` both swallowed
  `StandardError` with a `Rails.logger.warn(…)`. The chart then
  degraded to "target line only" silently. Promote the log to
  `error` level and forward to Sentry when present (matching the
  pattern in `Account::Syncer`, `Sync`, `PlaidItem`). Fallback to
  empty result still preserved so the surface degrades instead of
  500-ing.
This commit is contained in:
Guillem Arias
2026-05-14 19:48:32 +02:00
parent 4a46a90a88
commit 5530ff5f06
4 changed files with 20 additions and 85 deletions

View File

@@ -3,8 +3,8 @@ import { Controller } from "@hotwired/stimulus";
// 2-step modal stepper for creating a goal.
//
// Single <form> with two panels. Step 1 collects identity (name, amount,
// date, color, notes, linked accounts). Step 2 reviews + optional initial
// contribution. All state lives in the DOM — no half-records, single POST.
// date, color, notes, linked accounts). Step 2 reviews and submits. All
// state lives in the DOM — no half-records, single POST.
export default class extends Controller {
static targets = [
"step1Panel",
@@ -22,8 +22,6 @@ export default class extends Controller {
"amountError",
"accountsError",
"linkedAccountCheckbox",
"initialContributionAmount",
"initialContributionAccountSelect",
"reviewName",
"reviewSummary",
"reviewSuggested",
@@ -85,7 +83,6 @@ export default class extends Controller {
this.step1PanelTarget.classList.add("hidden");
this.step2PanelTarget.classList.remove("hidden");
this.updateStepperState();
this.refreshAccountSelect();
this.updateReview();
this.updateFooter();
}
@@ -99,7 +96,6 @@ export default class extends Controller {
}
linkedAccountChanged() {
this.refreshAccountSelect();
this.refreshSubmitState();
this.updateReview();
if (this.linkedAccountCheckboxTargets.some((cb) => cb.checked) && this.hasAccountsErrorTarget) {
@@ -169,26 +165,6 @@ export default class extends Controller {
this.footerRightButtonTarget.classList.toggle("opacity-50", !anyChecked && this.currentStep === 1);
}
refreshAccountSelect() {
if (!this.hasInitialContributionAccountSelectTarget) return;
const select = this.initialContributionAccountSelectTarget;
const previous = select.value;
while (select.options.length > 1) select.remove(1);
this.linkedAccountCheckboxTargets
.filter((cb) => cb.checked)
.forEach((cb) => {
const opt = document.createElement("option");
opt.value = cb.value;
opt.textContent = cb.dataset.accountName || cb.value;
select.appendChild(opt);
});
if ([...select.options].some((o) => o.value === previous)) {
select.value = previous;
}
}
updateStepperState() {
if (this.hasStep1CircleTarget) {
this.step1CircleTarget.classList.toggle("bg-inverse", this.currentStep === 1);