/* ===================== Plans page ===================== */
const { useState: useStatePl, useEffect: useEffectPl } = React;
const Cpl = window.CONTENT;
const tpl = window.t;
function PlanesPage({ lang, setRoute, setPrefilledPlan }) {
const [selected, setSelected] = useStatePl(Cpl.plans[2].id); // premium default
const [billing, setBilling] = useStatePl("monthly");
const [openFaq, setOpenFaq] = useStatePl(0);
const goContact = (planName) => (e) => {
e.preventDefault();
setPrefilledPlan(planName);
setRoute("contacto");
window.scrollTo({ top: 0, behavior: "smooth" });
};
const discount = (price) => {
const n = parseFloat(price.replace("$", ""));
return "$" + Math.round(n * 0.9);
};
return (
{/* Header section */}
{tpl(lang, Cpl.plansPage.eyebrow)}
{tpl(lang, Cpl.plansPage.title)}
{tpl(lang, Cpl.plansPage.sub)}
{/* Billing toggle */}
{[
["monthly", tpl(lang, Cpl.plansPage.monthly)],
["quarterly", tpl(lang, Cpl.plansPage.quarterly)]].
map(([id, label]) =>
)}
{/* Plan cards */}
{Cpl.plans.map((plan) =>
setSelected(plan.id)}
onReserve={goContact(tpl(lang, plan.name))} />
)}
{/* Compare table */}
|
{Cpl.plans.map((p) =>
{tpl(lang, p.name)}
{p.price}{tpl(lang, p.cadence)}
|
)}
{Cpl.plansPage.compareRows.map((row, i) =>
| {tpl(lang, row.k)} |
{row.v.map((v, j) =>
{v ? : }
|
)}
)}
{/* FAQ */}
FAQ
{tpl(lang, Cpl.plansPage.faqTitle)}
{tpl(lang, {
es: "¿No encuentras la respuesta? Escríbeme directamente.",
en: "Can't find your answer? Message me directly."
})}
WhatsApp
{Cpl.plansPage.faq.map((item, i) =>
)}
);
}
const cellHead = {
padding: "20px 16px",
textAlign: "left",
fontWeight: 400,
fontSize: 13,
color: "var(--ab-fg-muted)"
};
const cell = {
padding: "16px",
fontSize: 14,
color: "var(--ab-fg)"
};
function PlanCardLarge({ plan, lang, billing, discount, selected, onSelect, onReserve }) {
const price = billing === "quarterly" ? discount(plan.price) : plan.price;
return (
{plan.best &&
{tpl(lang, Cpl.plansPage.bestBadge)}
}
{tpl(lang, plan.name)}
{tpl(lang, plan.blurb)}
{price}
{tpl(lang, plan.cadence)}
{billing === "quarterly" &&
{plan.price}
}
{tpl(lang, plan.features).map((f, i) =>
-
{f}
)}
);
}
window.PlanesPage = PlanesPage;
/* ===================== About page ===================== */
function SobreMiPage({ lang, setRoute }) {
const go = (id) => (e) => {e.preventDefault();setRoute(id);window.scrollTo({ top: 0, behavior: "smooth" });};
return (
{/* Hero */}
{tpl(lang, Cpl.about.eyebrow)}
{tpl(lang, Cpl.about.title)}
{tpl(lang, Cpl.about.intro)}
{/* Long body + values */}
{tpl(lang, Cpl.about.paragraphs).map((p, i) =>
{p}
)}
{tpl(lang, Cpl.about.valuesTitle)}
{tpl(lang, Cpl.about.values).map((v, i) =>
)}
{/* Image strip */}
{/* Credentials */}
{tpl(lang, Cpl.about.credsTitle)}
{tpl(lang, {
es: "Formación, certificación, experiencia.",
en: "Training, certification, experience."
})}
{tpl(lang, Cpl.about.creds).map((c, i) =>
{c.y}
{c.t}
)}
{/* CTA */}
);
}
window.SobreMiPage = SobreMiPage;
/* ===================== Contact page ===================== */
function ContactoPage({ lang, prefilledPlan }) {
const f = Cpl.contactPage.form;
const [state, setState] = useStatePl({
name: "", email: "", phone: "", plan: prefilledPlan || "", goal: "", message: ""
});
const [errors, setErrors] = useStatePl({});
const [status, setStatus] = useStatePl("idle"); // idle | sending | sent
useEffectPl(() => {
if (prefilledPlan) setState((s) => ({ ...s, plan: prefilledPlan }));
}, [prefilledPlan]);
const update = (k) => (e) => {
setState((s) => ({ ...s, [k]: e.target.value }));
setErrors((err) => ({ ...err, [k]: undefined }));
};
const submit = (e) => {
e.preventDefault();
const next = {};
if (!state.name.trim()) next.name = tpl(lang, f.required);
if (!state.email.trim()) next.email = tpl(lang, f.required);else
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(state.email)) next.email = tpl(lang, f.invalidEmail);
if (!state.message.trim()) next.message = tpl(lang, f.required);
if (Object.keys(next).length) {setErrors(next);return;}
setStatus("sending");
setTimeout(() => setStatus("sent"), 1100);
};
return (
{tpl(lang, Cpl.contactPage.eyebrow)}
{tpl(lang, Cpl.contactPage.title)}
{tpl(lang, Cpl.contactPage.sub)}
{/* Form */}
{status === "sent" ?
{tpl(lang, f.success)}
{tpl(lang, { es: "Mientras tanto, sígueme en Instagram para más contenido.", en: "Meanwhile, follow me on Instagram for more content." })}
{Cpl.contact.instagramHandle}
:
}
{/* Direct contact */}
{tpl(lang, Cpl.contactPage.directTitle)}
{tpl(lang, { es: "O escríbeme directamente.", en: "Or message me directly." })}
} label="WhatsApp" value={Cpl.contact.phone} href={Cpl.contact.whatsapp} />
} label="Email" value={Cpl.contact.email} href={Cpl.contact.emailHref} />
} label={tpl(lang, { es: "Teléfono", en: "Phone" })} value={Cpl.contact.phone} href={Cpl.contact.phoneHref} />
} label="Instagram" value={Cpl.contact.instagramHandle} href={Cpl.contact.instagram} />
{tpl(lang, { es: "Horario", en: "Hours" })}
{tpl(lang, Cpl.contactPage.hours)}
{tpl(lang, { es: "Respuesta en menos de 24 horas", en: "Reply within 24 hours" })}
);
}
function Field({ label, children, error }) {
return (
{children}
{error && {error}}
);
}
function DirectLink({ icon, label, value, href }) {
return (
e.currentTarget.style.color = "var(--ab-accent-deep)"}
onMouseLeave={(e) => e.currentTarget.style.color = ""}>
{icon}
);
}
window.ContactoPage = ContactoPage;