/* SolucionPage — shared component rendering one solution-category page from data. */
const { useEffect: useEffectSP, useRef: useRefSP, useState: useStateSP } = React;
/* ---------- Logo (same as home) ---------- */
const LogoSP = ({ size = 32 }) => (
);
/* ---------- Navbar (mega-menu, sub-page) ---------- */
const NavbarSol = ({ currentKey }) => {
const ctx = window.useMegaMenuMM();
return (
);
};
/* ---------- FadeUp (local copy — BlurText.jsx defines it but we want to be explicit) ---------- */
const FadeUpSP = window.FadeUp || (({ children, delay = 0, className = '' }) => {
const ref = useRefSP(null);
const [visible, setVisible] = useStateSP(false);
useEffectSP(() => {
const el = ref.current;
if (!el) return;
const io = new IntersectionObserver(([e]) => {
if (e.isIntersecting) { setVisible(true); io.disconnect(); }
}, { threshold: 0.1 });
io.observe(el);
return () => io.disconnect();
}, []);
return (
{children}
);
});
/* ---------- Breadcrumb ---------- */
const Breadcrumb = ({ label }) => (
);
/* ---------- Hero ---------- */
const SolHero = ({ d }) => (
{d.eyebrow}
{d.h1}
{d.sub}
{d.stats}
);
/* ---------- Problem ---------- */
const SolProblem = ({ d }) => (
El problema hoy
¿Te suena alguno de estos?
{d.problems.map((it, i) => {
const I = iconFromName(it.icon);
return (
{it.title}
{it.body}
);
})}
);
/* ---------- Workflows ---------- */
const SolWorkflows = ({ d }) => (
Workflows de esta categoría
Tres automatizaciones que resuelven el 80% del trabajo repetitivo.
{d.workflows.map((w, i) => (
))}
);
const WorkflowDetailCard = ({ w }) => (
{w.desc}
{w.bullets.map((b, i) => (
-
{b}
))}
{w.stack.map((s, i) => (
{s}
))}
);
/* ---------- Stack técnico ---------- */
const SolStack = ({ d }) => (
Stack técnico
Las herramientas que operamos en esta categoría.
{d.stack.map((s, i) => {
const Icon = iconFromName(s.icon);
return (
{s.title}
{s.desc}
);
})}
);
/* ---------- Timeline (4 weeks) ---------- */
const SolTimeline = ({ d }) => (
Proceso
De diagnóstico a producción en 4 semanas.
{d.timeline.map((s, i) => (
))}
);
/* ---------- Case study ---------- */
const SolCaseStudy = ({ d }) => (
Caso típico
{d.caseStudy.profile}
{d.caseStudy.disclaimer}
{d.caseStudy.cols.map((c, i) => {
const cls = c.label.toLowerCase()
.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
return (
{c.label}
{c.body}
);
})}
);
/* ---------- Related solutions ---------- */
const SolRelated = ({ d, currentKey }) => {
const all = window.SOLUCIONES_DATA;
const others = (d.related || []).filter(k => k !== currentKey).map(k => all[k]).filter(Boolean);
return (
Otras soluciones
Otras categorías que resolvemos.
);
};
/* ---------- Final CTA ---------- */
const SolCTA = ({ d }) => (
¿Empezamos?
Diagnóstico gratis sobre tu proceso de {d.category}.
30 minutos. Mapeamos lo automatizable, priorizamos por ROI y te decimos qué workflow construir primero.
);
/* ---------- Footer ---------- */
const SolFooter = () => {
const [emailValue, setEmailValue] = useStateSP('');
const [newsletterStatus, setNewsletterStatus] = useStateSP('idle');
const currentYear = new Date().getFullYear();
const prefix = '../';
return (
);
};
/* ---------- WhatsApp Floating Button ---------- */
const WhatsAppFloatSP = () => (
);
/* ---------- Page composition ---------- */
const SolucionPage = ({ data }) => (
<>
>
);
/* ---------- Global parallax (same as home App.jsx) ---------- */
function useGlobalParallaxSP() {
useEffectSP(() => {
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (reduced) return;
let raf = 0;
function onScroll() {
if (raf) return;
raf = requestAnimationFrame(() => {
const items = document.querySelectorAll('[data-parallax]');
const y = window.scrollY;
items.forEach(el => {
const speed = parseFloat(el.dataset.parallax) || 0.3;
const base = el.dataset.parallaxBase || '';
el.style.transform = `${base} translate3d(0, ${y * speed}px, 0)`;
});
raf = 0;
});
}
window.addEventListener('scroll', onScroll, { passive: true });
onScroll();
return () => window.removeEventListener('scroll', onScroll);
}, []);
}
window.SolucionPage = SolucionPage;
window.useGlobalParallaxSP = useGlobalParallaxSP;