/* global React, PrimaryButton, ArchetypeScreen, DiagnosticScreen */
// Yomee — Profile Result Screen (DS-aligned)
// Renders one of four profile screens (totalero, optimizador, escalador,
// reiniciador) based on the user's debt + monthly payment.
//
// Surface = cream var(--yo-bg). Ink = var(--yo-ink) (#333). White is reserved
// for the inner metric card (2px ink stroke, 28px radius, no shadow).
// Typography: Geist Mono for display + numerals + buttons; Onest for body.
// All visual properties go through DS tokens — no inline hex anywhere.
const { useEffect: useEffectP } = React;
// ────────────────────────────────────────────────
// Profile classification — pure function so it can be unit-tested.
// payment_ratio = pago_mensual / deuda_total
// >= 1.0 → totalero
// >= 0.15 → optimizador (was: parcialero)
// >= 0.01 → escalador (was: minimero)
// == 0 → reiniciador
// ────────────────────────────────────────────────
function classifyProfile(deudaTotal, pagoMensual) {
if (!pagoMensual || pagoMensual <= 0) return "reiniciador";
if (!deudaTotal || deudaTotal <= 0) return "reiniciador";
const ratio = pagoMensual / deudaTotal;
if (ratio >= 1.0) return "totalero";
if (ratio >= 0.15) return "optimizador";
if (ratio >= 0.01) return "escalador";
return "reiniciador";
}
// ────────────────────────────────────────────────
// Payoff calculation (per spec)
// tasa_mensual = 0.025
// meses = -ln(1 - tasa_mensual * deuda / pago) / ln(1 + tasa_mensual)
// interes_total = (pago * meses) - deuda
// unpayable when pago <= deuda * tasa_mensual
// ────────────────────────────────────────────────
function calcPayoff(deudaTotal, pagoMensual) {
const r = 0.025;
const D = deudaTotal;
const P = pagoMensual;
if (P <= D * r) return { unpayable: true };
const months = Math.ceil(-Math.log(1 - (r * D) / P) / Math.log(1 + r));
const totalInterest = Math.max(0, Math.round(P * months - D));
return { unpayable: false, months, totalInterest };
}
// Format months → "N meses" if N < 12, else "X años y Y meses".
function formatMonths(months) {
if (months <= 0) return "0 meses";
if (months < 12) return `${months} ${months === 1 ? "mes" : "meses"}`;
const years = Math.floor(months / 12);
const rem = months % 12;
if (rem === 0) return `${years} ${years === 1 ? "año" : "años"}`;
return `${years} ${years === 1 ? "año" : "años"} y ${rem} ${
rem === 1 ? "mes" : "meses"
}`;
}
const fmtCurrency = (n) => "$" + Math.round(n).toLocaleString("es-MX");
// ────────────────────────────────────────────────
// Per-profile config — copy + accent tokens per spec.
// archetypeColor MUST reference a DS token, never a literal hex.
// ────────────────────────────────────────────────
const PROFILES = {
totalero: {
kind: "archetype",
variant: "mascot-on-card",
mascot: "assets/profiles/totalero.png",
subtitle: "¡Excelente!",
archetype: "Eres un Totalero",
archetypeColor: "var(--profile-totalero)",
headline: (
<>
Pagas todo cada mes. Cero interés, cero estrés.
¿Sabes cuánto pagas en anualidades y cargos ocultos?
>
),
cardBody:
"Con tu radiografía podrías encontrar tarjetas con anualidades más bajas o mejores beneficios gratis.",
cta: "CREAR MI RADIOGRAFÍA GRATIS →",
},
optimizador: {
kind: "diagnostic",
mascot: "assets/profiles/optimizador.png",
subtitle: "¡Vas bien!",
archetype: "Eres un Optimizador",
archetypeColor: "var(--profile-optimizador)",
headline: (
<>
Pagas más del mínimo, y eso cuenta.
Pero los intereses siguen trabajando en tu contra cada mes.
>
),
cta: "Armar mi plan →",
},
escalador: {
kind: "diagnostic",
mascot: "assets/profiles/escalador.png",
subtitle: "¡Atención!",
archetype: "Eres un escalador",
archetypeColor: "var(--profile-escalador)",
headline: (
<>
Pagar el mínimo puede costar años y miles en intereses.
La buena noticia: con pequeños ajustes puedes salir mucho antes de lo que crees.
>
),
cta: "Ver cuánto me está costando →",
},
reiniciador: {
kind: "archetype",
variant: "mascot-on-card",
mascot: "assets/profiles/reiniciador.png",
subtitle: "¡Nuevo comienzo!",
archetype: "Eres un reiniciador",
archetypeColor: "var(--profile-reiniciador)",
headline: (
<>
Todos merecemos una segunda vuelta.
Siempre se puede recuperar un buen historial crediticio.
>
),
cardBody:
"Te ayudamos a dar el primer paso para retomar el control de tus finanzas, sin juicios y a tu ritmo.",
cta: "Empezar de nuevo →",
},
};
// Gendered archetype labels — applied when gender === "female".
const PROFILE_LABEL_F = {
totalero: "Eres una Totalera",
optimizador: "Eres una Optimizadora",
escalador: "Eres una escaladora",
reiniciador: "Eres una reiniciadora",
};
function archetypeLabel(profileKey, gender, fallback) {
if (gender === "female" && PROFILE_LABEL_F[profileKey]) {
return PROFILE_LABEL_F[profileKey];
}
return fallback;
}
// ────────────────────────────────────────────────
// Main screen — picks the right primitive (Archetype vs Diagnostic) and
// passes the per-profile config + computed metric.
// ────────────────────────────────────────────────
function ProfileResultScreen({
deudaTotal = 0,
pagoMensual = 0,
gender = null,
forceProfile = null,
onContinue,
onBack,
onClose,
}) {
const classified = classifyProfile(deudaTotal, pagoMensual);
const profile = (forceProfile && PROFILES[forceProfile]) ? forceProfile : classified;
const cfg = PROFILES[profile];
// When forcing a profile, synthesize plausible debt/payment so the
// diagnostic metric still renders something sensible.
const FORCED_NUMBERS = {
optimizador: { d: 65000, p: 12000 },
escalador: { d: 80000, p: 2200 },
};
const useNumbers = forceProfile && FORCED_NUMBERS[forceProfile]
? FORCED_NUMBERS[forceProfile]
: { d: deudaTotal, p: pagoMensual };
const payoff = calcPayoff(useNumbers.d, useNumbers.p);
// Persist for the rest of the session.
useEffectP(() => {
try {
localStorage.setItem("yomee_profile", profile);
} catch (_) {}
}, [profile]);
const archetypeStr = archetypeLabel(profile, gender, cfg.archetype);
const onCta = () => onContinue && onContinue(profile);
if (cfg.kind === "archetype") {
return (
);
}
// Diagnostic (optimizador / escalador)
const metric = !payoff.unpayable ? formatMonths(payoff.months) : "";
const interesTotal = !payoff.unpayable
? fmtCurrency(payoff.totalInterest)
: "";
return (
);
}
Object.assign(window, {
ProfileResultScreen,
classifyProfile,
calcPayoff,
formatMonths,
});