Files
sitemente/components/site-mente/PricingTable.tsx
T
Haitham Khalifa 11252e6520 Initial commit
2026-02-16 12:02:45 +01:00

349 lines
11 KiB
TypeScript

"use client";
import { useMemo, useState } from "react";
type PricingTableProps = {
lang: "es" | "en";
onContact: () => void;
};
type Plan = {
id: string;
name: string;
setup: string;
monthly: number | null;
term: string;
features: string[];
optional: string[];
cta: string;
popular?: boolean;
subtext?: string;
};
const formatMonthly = (
value: number,
yearly: boolean,
lang: PricingTableProps["lang"]
) => {
const discounted = yearly ? Math.round(value * 0.85) : value;
return `${discounted} €/${lang === "es" ? "mes" : "mo"}`;
};
export default function PricingTable({ lang, onContact }: PricingTableProps) {
const [yearly, setYearly] = useState(false);
const [showFairUse, setShowFairUse] = useState(false);
const pricingContent = useMemo(
() => ({
es: {
labels: {
popular: "Más popular",
setup: "Instalación",
billedAnnually: "(facturado anualmente)",
},
plans: [
{
id: "starter",
name: "Smart Starter",
setup: "900 €",
monthly: 299,
term: "6-12 meses",
features: [
"Chat IA en la web (1 idioma)",
"Reservas y captación de leads",
"Bandeja ligera de leads",
"Analíticas básicas",
],
optional: ["+WhatsApp (+100€/mes)", "+Idioma extra (+80€/mes)"],
cta: "Empezar",
},
{
id: "site",
name: "Smart Site",
setup: "3.500 €",
monthly: 749,
term: "6-12 meses",
features: [
"Todo lo incluido en Starter",
"Nuevo sitio web Next.js",
"WhatsApp incluido",
"2 idiomas (ES+EN)",
"Sugerencias de contenido con IA",
"Analíticas avanzadas",
],
optional: [
"+Llamadas de voz (+150€/mes)",
"+Ubicación extra (+120€/mes)",
],
cta: "Empezar",
popular: true,
},
{
id: "growth",
name: "AI Growth Partner",
setup: "5.000 €",
monthly: 1950,
term: "12 meses",
features: [
"Todo lo incluido en Smart Site",
"Llamadas de voz incluidas",
"Soporte multiubicación",
"Integraciones CRM",
"Automatizaciones personalizadas",
"Llamada estratégica mensual",
"Soporte prioritario",
],
optional: ["+Pack de contenido IA (+200€/mes)"],
cta: "Empezar",
},
{
id: "enterprise",
name: "Enterprise / A medida",
setup: "Personalizado",
monthly: null,
term: "Definimos el alcance contigo",
features: [
"Todo a medida",
"Multimarca y white-label",
"Account manager dedicado",
"SLA de rendimiento",
],
optional: [],
cta: "Contactar",
subtext: "Hablemos",
},
] satisfies Plan[],
},
en: {
labels: {
popular: "Most popular",
setup: "Setup",
billedAnnually: "(billed annually)",
},
plans: [
{
id: "starter",
name: "Smart Starter",
setup: "900 €",
monthly: 299,
term: "6-12 months",
features: [
"AI website chat (1 language)",
"Booking & lead capture",
"Light lead inbox",
"Basic analytics",
],
optional: ["+WhatsApp (+100€/mo)", "+Extra language (+80€/mo)"],
cta: "Get started",
},
{
id: "site",
name: "Smart Site",
setup: "3,500 €",
monthly: 749,
term: "6-12 months",
features: [
"Everything in Starter",
"New Next.js website",
"WhatsApp included",
"2 languages (ES+EN)",
"AI content suggestions",
"Advanced analytics",
],
optional: ["+Voice calls (+150€/mo)", "+Extra location (+120€/mo)"],
cta: "Get started",
popular: true,
},
{
id: "growth",
name: "AI Growth Partner",
setup: "5,000 €",
monthly: 1950,
term: "12 months",
features: [
"Everything in Smart Site",
"Voice calls included",
"Multi-location support",
"CRM integrations",
"Custom automations",
"Monthly strategy call",
"Priority support",
],
optional: ["+AI content pack (+200€/mo)"],
cta: "Get started",
},
{
id: "enterprise",
name: "Enterprise / Custom",
setup: "Custom",
monthly: null,
term: "Let us scope it",
features: [
"Everything tailored",
"Multi-brand & white-label",
"Dedicated account manager",
"Performance SLAs",
],
optional: [],
cta: "Contact us",
subtext: "Let us talk",
},
] satisfies Plan[],
},
}),
[]
);
const pricing = pricingContent[lang];
const plans = pricing.plans;
return (
<div className="mt-10">
<div className="flex flex-col items-center justify-between gap-4 rounded-2xl border border-white/15 bg-white/10 p-5 text-center backdrop-blur md:flex-row md:text-left">
<div>
<p className="text-sm font-semibold uppercase tracking-[0.2em] text-white/70">
{lang === "es" ? "Pago anual" : "Pay yearly"}
</p>
<p className="mt-2 text-base text-white/90">
{lang === "es"
? "Paga anual y ahorra 15%"
: "Pay yearly - Save 15%"}
</p>
</div>
<label className="flex items-center gap-3 rounded-full border border-white/25 bg-white/10 px-4 py-2 text-sm font-semibold text-white">
<span>{lang === "es" ? "Descuento 15%" : "Save 15%"}</span>
<button
type="button"
onClick={() => setYearly((prev) => !prev)}
className={`relative h-6 w-12 rounded-full transition ${
yearly ? "bg-brand-pink" : "bg-white/20"
}`}
>
<span
className={`absolute left-1 top-1 h-4 w-4 rounded-full bg-white transition ${
yearly ? "translate-x-6" : ""
}`}
/>
</button>
</label>
</div>
<div className="mt-10 grid gap-6 lg:grid-cols-4 items-stretch">
{plans.map((plan) => (
<div
key={plan.id}
className={`flex h-full flex-col rounded-2xl border p-6 backdrop-blur transition duration-300 hover:-translate-y-2 hover:shadow-[0_25px_50px_-20px_rgba(118,75,162,0.65)] ${
plan.popular
? "border-brand-pink bg-white/12"
: "border-white/15 bg-white/8"
}`}
>
{plan.popular && (
<span className="inline-flex rounded-full bg-brand-pink/20 px-3 py-1 text-xs font-semibold text-white">
{pricing.labels.popular}
</span>
)}
<h3 className="mt-4 text-xl font-semibold">{plan.name}</h3>
<p className="mt-2 text-sm text-white/70">
{pricing.labels.setup}: {plan.setup}
</p>
<p className="mt-6 text-3xl font-bold">
{plan.monthly === null
? plan.subtext
: formatMonthly(plan.monthly, yearly, lang)}
</p>
<p className="mt-2 text-sm text-white/70">
{plan.term}
{plan.monthly !== null && yearly && (
<span className="block text-xs text-white/60">
{pricing.labels.billedAnnually}
</span>
)}
</p>
<ul className="mt-6 space-y-2 text-sm text-white/90">
{plan.features.map((feature) => (
<li key={feature}> {feature}</li>
))}
</ul>
{plan.optional.length > 0 && (
<div className="mt-4 text-xs text-white/60">
{plan.optional.map((option) => (
<p key={option}>{option}</p>
))}
</div>
)}
<button
onClick={onContact}
className="mt-auto w-full rounded-lg bg-brand-pink px-4 py-2 text-sm font-semibold text-white transition hover:-translate-y-1 hover:bg-[#ff7bc0]"
>
{plan.cta}
</button>
</div>
))}
</div>
<p className="mt-6 text-center text-xs text-white/70">
Todos los planes incluyen un uso generoso de IA para un negocio típico.
Se aplica una{" "}
<button
type="button"
onClick={() => setShowFairUse(true)}
className="font-semibold text-white underline decoration-white/60 underline-offset-4"
>
política de uso justo
</button>
, sin cargos sorpresa.
</p>
{showFairUse && (
<div className="fixed inset-0 z-50 flex items-center justify-center px-4">
<div
className="absolute inset-0 bg-black/60 backdrop-blur-sm"
onClick={() => setShowFairUse(false)}
/>
<div className="relative z-10 w-full max-w-2xl rounded-2xl border border-white/20 bg-white/10 p-8 text-white shadow-purple-soft backdrop-blur">
<div className="flex items-start justify-between gap-4">
<div>
<p className="text-sm uppercase tracking-[0.3em] text-white/70">
Uso justo
</p>
<h3 className="mt-3 text-2xl font-bold">
Qué significa "uso justo"?
</h3>
</div>
<button
onClick={() => setShowFairUse(false)}
className="rounded-full border border-white/40 px-3 py-1 text-xs font-semibold text-white/80 transition hover:bg-white/10 hover:text-white"
>
Cerrar
</button>
</div>
<div className="mt-6 space-y-4 text-sm text-white/85">
<p>
Cada plan incluye suficientes mensajes de IA, llamadas y
conversaciones de WhatsApp para un negocio típico de tu tamaño.
</p>
<p>
Si tu uso se mantiene muy por encima de lo normal (por ejemplo,
porque añades nuevas marcas, locales o campañas), haremos lo
siguiente:
</p>
<ol className="list-decimal space-y-2 pl-5">
<li>Te avisaremos primero.</li>
<li>Te enviaremos un informe sencillo de uso.</li>
<li>
Te propondremos opciones (seguir igual con algunos límites o
subir de plan / añadir más capacidad).
</li>
</ol>
<p>
Nunca aplicamos cargos extra sin hablar contigo antes.
</p>
</div>
</div>
</div>
)}
</div>
);
}