// Yomee — Question 1 Screen ("Hagamos números")
// Fifth onboarding step. Slider + editable number combo for total debt and monthly payment.
// Uses OnboardingHeader from OnboardingShared.jsx; PrimaryButton from Shared.jsx
/* global React, OnboardingHeader, PrimaryButton */
const { useState: useStateQ1, useEffect: useEffectQ1, useRef: useRefQ1 } = React;
function CurrencySliderField({ value, onChange, min, max, step, disabled }) {
const [draft, setDraft] = useStateQ1(null);
const inputRef = useRefQ1(null);
const fmt = (n) =>
"$" + (Number.isFinite(n) ? n : 0).toLocaleString("en-US");
const clamp = (n) => Math.max(min, Math.min(max, n));
const snap = (n) => Math.round(n / step) * step;
const handleInputChange = (raw) => {
const digits = raw.replace(/[^\d]/g, "").slice(0, 10);
setDraft(digits);
const n = digits === "" ? 0 : parseInt(digits, 10);
onChange(clamp(n));
};
const handleBlur = () => {
setDraft(null);
};
const displayed =
draft !== null
? draft === ""
? ""
: "$" + parseInt(draft, 10).toLocaleString("en-US")
: fmt(value);
const pct = max > min ? ((value - min) / (max - min)) * 100 : 0;
const GREEN = "#2BAE80";
const TRACK_GRAY = "#E0E0E0";
const sliderClassRef = useRefQ1(
"yo-sl-" + Math.random().toString(36).slice(2, 8),
);
const sliderClass = sliderClassRef.current;
return (
!disabled && inputRef.current && inputRef.current.focus()}
style={{
width: "100%",
boxSizing: "border-box",
borderRadius: 14,
background: "#fff",
display: "flex",
alignItems: "center",
justifyContent: "center",
padding: "18px 20px",
cursor: disabled ? "not-allowed" : "text",
}}
>
{
const digits = String(value || "").replace(/[^\d]/g, "");
setDraft(digits === "0" ? "" : digits);
requestAnimationFrame(() => {
try { e.target.select(); } catch (_) {}
});
}}
onBlur={handleBlur}
onChange={(e) => handleInputChange(e.target.value)}
style={{
width: "100%",
border: "none",
outline: "none",
background: "transparent",
textAlign: "center",
fontFamily: "var(--font-mono)",
fontWeight: 700,
fontSize: 28,
letterSpacing: "0.005em",
color: "#1a1a1a",
}}
/>
onChange(snap(clamp(parseInt(e.target.value, 10))))}
disabled={disabled}
className={sliderClass}
style={{
display: "block",
width: "100%",
height: 22,
WebkitAppearance: "none",
appearance: "none",
outline: "none",
background: "transparent",
margin: 0,
padding: 0,
}}
/>
{fmt(min)}
{fmt(max)}
);
}
function Question1Screen({ onBack, onContinue }) {
const TOTAL_MIN = 0;
const TOTAL_MAX = 500000;
const TOTAL_STEP = 5000;
const MONTHLY_MIN = 0;
const MONTHLY_DEFAULT = 3200;
// Reactive bind to the active persona. Switching persona via the Demo
// pill must snap the sliders + checkbox to the new persona's values
// instantly — no remount required.
const yomeeUser = (window.useYomeeUser && window.useYomeeUser()) || {};
const personaTotal =
Number.isFinite(yomeeUser.debt) ? yomeeUser.debt : 65000;
const personaMonthly =
Number.isFinite(yomeeUser.payment) ? yomeeUser.payment : MONTHLY_DEFAULT;
const personaCantPay = yomeeUser.payment === 0;
const [total, setTotal] = useStateQ1(personaTotal);
const [monthly, setMonthly] = useStateQ1(personaMonthly);
const [cantPay, setCantPay] = useStateQ1(personaCantPay);
// When the active persona changes, snap every field back to that
// persona's values — keyed on personaKey so this only fires on switch.
useEffectQ1(() => {
setTotal(personaTotal);
setMonthly(personaMonthly);
setCantPay(personaCantPay);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [yomeeUser.personaKey]);
const monthlyMax = Math.max(0, total);
const monthlyStep =
total <= 50000 ? 500 : total <= 200000 ? 1000 : 5000;
useEffectQ1(() => {
if (monthly > monthlyMax) setMonthly(monthlyMax);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [monthlyMax]);
const submit = () => {
if (allValid) {
onContinue({ total, monthly: cantPay ? 0 : monthly });
}
};
const allValid = total > 0 && (cantPay || monthly > 0);
const handleCantPayToggle = () => {
setCantPay((prev) => {
const next = !prev;
if (next) {
setMonthly(0);
} else {
setMonthly(Math.min(MONTHLY_DEFAULT, Math.max(0, total)));
}
return next;
});
};
return (
Hagamos números
¿Cuánto debes en total hoy?
Incluye tarjetas, préstamos o financiamientos activos.
¿Cuánto pagas cada mes?
Si eres totalero, escribe la misma cantidad que arriba.
Puedes usar montos aproximados
Continuar
);
}
window.Question1Screen = Question1Screen;
window.CurrencySliderField = CurrencySliderField;