Files
sure/app/javascript/controllers/retirement_what_if_controller.js
Guillem Arias 01118b858f feat(retirement): PR4d what-if slider rail
Each lever (retire age / target spend / save per mo / real return) now
pairs a numeric input with a range slider; retirement_what_if_controller
mirrors the value across the pair (data-lever) and debounces the live
forecast preview. Birth year stays a plain numeric input.

(Skinned delete confirmations already render via Sure's global
Turbo.config.forms.confirm → DS::Dialog override, so the PR2 turbo_confirm
buttons are already styled — no change needed.)
2026-05-29 12:38:24 +02:00

46 lines
1.3 KiB
JavaScript

import { Controller } from "@hotwired/stimulus"
// Live "what-if": debounce input changes and POST the current plan inputs
// to the forecast endpoint, which streams back the recomputed KPI cards
// without persisting. Saving is a separate form submit (#update).
export default class extends Controller {
static targets = ["form"]
static values = { url: String, debounce: { type: Number, default: 300 } }
// Mirror a lever's value across its paired number + range inputs (matched
// by data-lever), then debounce a preview.
sync(event) {
const lever = event.target.dataset.lever
if (lever) {
this.element.querySelectorAll(`[data-lever="${lever}"]`).forEach((el) => {
if (el !== event.target) el.value = event.target.value
})
}
this.preview()
}
preview() {
clearTimeout(this.timer)
this.timer = setTimeout(() => this.fetchPreview(), this.debounceValue)
}
async fetchPreview() {
const response = await fetch(this.urlValue, {
method: "PATCH",
body: new FormData(this.formTarget),
headers: {
Accept: "text/vnd.turbo-stream.html",
"X-CSRF-Token": document.querySelector("meta[name='csrf-token']")?.content
}
})
if (response.ok) {
window.Turbo.renderStreamMessage(await response.text())
}
}
disconnect() {
clearTimeout(this.timer)
}
}