Initial commit

This commit is contained in:
Haitham Khalifa
2026-02-16 12:02:45 +01:00
commit 11252e6520
37 changed files with 8118 additions and 0 deletions
@@ -0,0 +1,570 @@
"use client";
import { useMemo, useState } from "react";
import { motion } from "framer-motion";
type ServicesAndPricingProps = {
lang: "es" | "en";
onContact: () => void;
};
type ServiceCard = {
id: string;
icon: string;
title: string;
for: string;
description: string[];
sections?: { title: string; items: string[] }[];
setup: string;
monthly: number | null;
term: string;
features: string[];
optional: string[];
cta: string;
popular?: boolean;
subtext?: string;
};
const fadeUp = {
hidden: { opacity: 0, y: 24 },
visible: { opacity: 1, y: 0 },
};
const content = {
es: {
sectionTitle: "Servicios y Precios",
sectionEyebrow: "Servicios y Precios",
headline: "Convertimos tu web en un vendedor inteligente que trabaja 24/7",
subheadline:
"En 2026, los clientes esperan respuestas instantáneas, reservas sin fricción y experiencias personalizadas. Si tu web no puede hacerlo, están yendo a tu competencia.",
yearlyLabel: "Pago anual",
yearlyDesc: "Paga anual y ahorra 15%",
saveLabel: "Descuento 15%",
setupLabel: "Instalación",
fromLabel: "Desde",
perMonth: "/mes",
billedAnnually: "(facturado anualmente)",
examplesTitle: "Casos de uso reales en Costa del Sol",
examplesCta: "Descubre tu plan ideal",
fairUseNote: "Todos los planes incluyen un uso generoso de IA para un negocio típico. Se aplica una",
fairUseLink: "política de uso justo",
fairUseEnd: ", sin cargos sorpresa.",
fairUseTitle: "Uso justo",
fairUseQuestion: 'Qué significa "uso justo"?',
close: "Cerrar",
fairUseBody: [
"Cada plan incluye suficientes mensajes de IA, llamadas y conversaciones de WhatsApp para un negocio típico de tu tamaño.",
"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:",
],
fairUseList: [
"Te avisaremos primero.",
"Te enviaremos un informe sencillo de uso.",
"Te propondremos opciones (seguir igual con algunos límites o subir de plan / añadir más capacidad).",
],
fairUseEndBody: "Nunca aplicamos cargos extra sin hablar contigo antes.",
popular: "Más popular",
},
en: {
sectionTitle: "Services & Pricing",
sectionEyebrow: "Services & Pricing",
headline: "Turn your website into a 24/7 intelligent salesperson",
subheadline:
"In 2026, customers expect instant answers, frictionless bookings, and personalized experiences. If your site can't deliver, they're going to your competitors.",
yearlyLabel: "Pay yearly",
yearlyDesc: "Pay yearly - Save 15%",
saveLabel: "Save 15%",
setupLabel: "Setup",
fromLabel: "From",
perMonth: "/month",
billedAnnually: "(billed annually)",
examplesTitle: "Real use cases on the Costa del Sol",
examplesCta: "Find your ideal plan",
fairUseNote: "All plans include generous AI usage for a typical business. A",
fairUseLink: "fair use policy",
fairUseEnd: " applies, no surprise charges.",
fairUseTitle: "Fair use",
fairUseQuestion: 'What does "fair use" mean?',
close: "Close",
fairUseBody: [
"Each plan includes enough AI messages, calls and WhatsApp conversations for a typical business of your size.",
"If your usage stays well above normal (e.g. you add new brands, locations or campaigns), we will:",
],
fairUseList: [
"Notify you first.",
"Send you a simple usage report.",
"Propose options (continue as-is with some limits, or upgrade / add capacity).",
],
fairUseEndBody: "We never apply extra charges without speaking to you first.",
popular: "Most popular",
},
} as const;
const serviceCards: Record<"es" | "en", ServiceCard[]> = {
es: [
{
id: "starter",
icon: "💬",
title: "AI Chat + Reservas Automatizadas",
for: "Restaurantes, clínicas, negocios locales con web existente",
description: [
"¿Tu web pierde clientes fuera de horario? Tu sitio responde preguntas, toma reservas y captura leads mientras duermes.",
],
sections: [
{
title: "Resultados típicos:",
items: [
"24/7 reservas sin intervención humana",
"Reduce llamadas repetitivas en un 70%",
"ROI positivo en el primer mes",
],
},
],
setup: "900 €",
monthly: 299,
term: "6-12 meses",
features: [
"Chat IA en la web (1 idioma)",
"Reservas y captación de leads",
"Analíticas básicas",
],
optional: ["+WhatsApp (+100€/mes)", "+Idioma extra (+80€/mes)"],
cta: "Empezar",
},
{
id: "site",
icon: "🌐",
title: "Web Inteligente Completa",
for: "Negocios listos para una web moderna + cerebro IA",
description: [
"Construimos tu nuevo sitio web Next.js (rápido, seguro, SEO) e integramos IA que vende, reserva y da soporte en español e inglés.",
],
sections: [
{
title: "Incluye:",
items: [
"Sitio que convierte visitas en ventas",
"Chat + WhatsApp incluidos",
"2 idiomas desde el día uno",
"Analíticas avanzadas",
],
},
],
setup: "3.500 €",
monthly: 749,
term: "6-12 meses",
features: [
"Todo lo de Starter",
"Nuevo sitio web Next.js",
"WhatsApp incluido",
"2 idiomas (ES+EN)",
],
optional: ["+Llamadas de voz (+150€/mes)", "+Ubicación extra (+120€/mes)"],
cta: "Empezar",
popular: true,
},
{
id: "growth",
icon: "🚀",
title: "Partner Estratégico de IA",
for: "Grupos de restaurantes, inmobiliarias, cadenas de alquiler",
description: [
"Socio estratégico: IA multicanal (web, WhatsApp, llamadas), integraciones CRM y consultoría mensual.",
],
sections: [
{
title: "Incluye:",
items: [
"Todo lo de Smart Site",
"Llamadas de voz incluidas",
"Soporte multiubicación",
"Integraciones CRM",
"Llamada estratégica mensual",
],
},
],
setup: "5.000 €",
monthly: 1950,
term: "12 meses",
features: [
"Todo lo de Smart Site",
"Llamadas de voz incluidas",
"Integraciones CRM",
"Soporte prioritario",
],
optional: ["+Pack contenido IA (+200€/mes)"],
cta: "Hablemos",
},
{
id: "enterprise",
icon: "🎯",
title: "Enterprise / A medida",
for: "Operaciones a escala con necesidades custom",
description: [
"Todo adaptado a tu operación: multimarca, white-label, account manager dedicado y SLA de rendimiento.",
],
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",
},
],
en: [
{
id: "starter",
icon: "💬",
title: "AI Chat + Automated Bookings",
for: "Restaurants, clinics, local businesses with existing websites",
description: [
"Is your website losing customers after hours? Your site answers questions, takes bookings, and captures leads while you sleep.",
],
sections: [
{
title: "Typical results:",
items: [
"24/7 bookings without human intervention",
"Reduce repetitive calls by 70%",
"Positive ROI in the first month",
],
},
],
setup: "900 €",
monthly: 299,
term: "6-12 months",
features: [
"AI website chat (1 language)",
"Booking & lead capture",
"Basic analytics",
],
optional: ["+WhatsApp (+100€/mo)", "+Extra language (+80€/mo)"],
cta: "Get started",
},
{
id: "site",
icon: "🌐",
title: "Full Smart Website",
for: "Businesses ready for a modern site + AI brain",
description: [
"We build your new Next.js website (fast, secure, SEO) and integrate AI that sells, books, and supports in Spanish and English.",
],
sections: [
{
title: "Includes:",
items: [
"Site that converts visits into sales",
"Chat + WhatsApp included",
"2 languages from day one",
"Advanced analytics",
],
},
],
setup: "3,500 €",
monthly: 749,
term: "6-12 months",
features: [
"Everything in Starter",
"New Next.js website",
"WhatsApp included",
"2 languages (ES+EN)",
],
optional: ["+Voice calls (+150€/mo)", "+Extra location (+120€/mo)"],
cta: "Get started",
popular: true,
},
{
id: "growth",
icon: "🚀",
title: "AI Strategy Partner",
for: "Restaurant groups, real estate teams, rental chains",
description: [
"Strategic partner: multichannel AI (web, WhatsApp, calls), CRM integrations, monthly consulting.",
],
sections: [
{
title: "Includes:",
items: [
"Everything in Smart Site",
"Voice calls included",
"Multi-location support",
"CRM integrations",
"Monthly strategy call",
],
},
],
setup: "5,000 €",
monthly: 1950,
term: "12 months",
features: [
"Everything in Smart Site",
"Voice calls included",
"CRM integrations",
"Priority support",
],
optional: ["+AI content pack (+200€/mo)"],
cta: "Let's talk",
},
{
id: "enterprise",
icon: "🎯",
title: "Enterprise / Custom",
for: "Large-scale operations with custom needs",
description: [
"Everything tailored: multi-brand, white-label, dedicated account manager, performance SLA.",
],
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's talk",
},
],
};
const examples = {
es: [
{ title: "🍽️ Restaurantes", text: "Reservas a las 3 AM, respuestas sobre alérgenos, sugerencias de platos." },
{ title: "🏠 Inmobiliarias", text: "IA responde dudas, agenda visitas, cualifica leads." },
{ title: "🚗 Rent a Car", text: "Cotiza y reserva en 3 idiomas sin intervención humana." },
],
en: [
{ title: "🍽️ Restaurants", text: "Reservations at 3 AM, allergy answers, dish suggestions." },
{ title: "🏠 Real Estate", text: "AI answers questions, books viewings, qualifies leads." },
{ title: "🚗 Rent a Car", text: "Quote and book in 3 languages with no human intervention." },
],
};
export default function ServicesAndPricing({
lang,
onContact,
}: ServicesAndPricingProps) {
const [yearly, setYearly] = useState(false);
const [showFairUse, setShowFairUse] = useState(false);
const t = content[lang];
const cards = serviceCards[lang];
const formatMonthly = (value: number) => {
const price = yearly ? Math.round(value * 0.85) : value;
return `${price}${t.perMonth}`;
};
return (
<section
id="services"
className="mx-auto w-full max-w-6xl px-6 py-20"
>
<motion.div
variants={fadeUp}
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.3 }}
transition={{ duration: 0.7 }}
>
<p className="text-sm font-semibold uppercase tracking-[0.2em] text-white/70">
{t.sectionEyebrow}
</p>
<h2 className="mt-4 text-3xl font-bold sm:text-4xl">
{t.sectionTitle}
</h2>
<p className="mt-4 max-w-3xl text-base text-white/85">
{t.subheadline}
</p>
</motion.div>
<div className="mt-6 flex flex-col items-center justify-between gap-4 rounded-2xl border border-white/15 bg-white/10 p-5 text-center backdrop-blur sm:flex-row">
<div>
<p className="text-sm font-semibold text-white/90">{t.yearlyLabel}</p>
<p className="mt-1 text-sm text-white/75">{t.yearlyDesc}</p>
</div>
<button
type="button"
onClick={() => setYearly((prev) => !prev)}
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>{t.saveLabel}</span>
<span
className={`relative block h-6 w-11 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-5" : ""
}`}
/>
</span>
</button>
</div>
<div className="mt-10 grid gap-6 lg:grid-cols-2 xl:grid-cols-4">
{cards.map((card, index) => (
<motion.div
key={card.id}
variants={fadeUp}
initial="hidden"
whileInView="visible"
viewport={{ once: true, amount: 0.2 }}
transition={{ duration: 0.5, delay: index * 0.08 }}
className={`flex flex-col rounded-2xl border p-6 backdrop-blur transition hover:border-white/30 ${
card.popular
? "border-brand-pink bg-white/12 shadow-purple-soft"
: "border-white/15 bg-white/8"
}`}
>
{card.popular && (
<span className="mb-3 inline-flex w-fit rounded-full bg-brand-pink/25 px-3 py-0.5 text-xs font-semibold text-white">
{t.popular}
</span>
)}
<div className="flex items-center gap-3">
<span className="text-2xl">{card.icon}</span>
<h3 className="text-lg font-semibold">{card.title}</h3>
</div>
<p className="mt-2 text-sm text-white/70">{card.for}</p>
<div className="mt-4 space-y-2 text-sm text-white/90">
{card.description.map((p, i) => (
<p key={i}>{p}</p>
))}
</div>
{card.sections?.map((section) => (
<div key={section.title} className="mt-4">
<p className="text-xs font-semibold text-white/85">
{section.title}
</p>
<ul className="mt-2 space-y-1 text-xs text-white/80">
{section.items.map((item) => (
<li key={item}> {item}</li>
))}
</ul>
</div>
))}
<div className="mt-6 rounded-xl border border-white/15 bg-white/5 px-4 py-3">
<p className="text-xs text-white/70">
{t.setupLabel}: <span className="font-semibold text-white">{card.setup}</span>
</p>
<p className="mt-1 text-xl font-bold text-brand-pink">
{card.monthly === null
? card.subtext
: card.monthly !== null
? `${t.fromLabel} ${formatMonthly(card.monthly)}`
: null}
</p>
<p className="mt-1 text-xs text-white/60">
{card.term}
{card.monthly !== null && yearly && (
<span className="block">{t.billedAnnually}</span>
)}
</p>
</div>
<ul className="mt-4 space-y-1.5 text-sm text-white/85">
{card.features.map((f) => (
<li key={f}> {f}</li>
))}
</ul>
{card.optional.length > 0 && (
<p className="mt-3 text-xs text-white/60">
{card.optional.join(" · ")}
</p>
)}
<button
onClick={onContact}
className="mt-auto mt-6 w-full rounded-lg bg-brand-pink py-2.5 text-sm font-semibold text-white transition hover:bg-[#ff7bc0]"
>
{card.cta}
</button>
</motion.div>
))}
</div>
<div className="mt-16 rounded-2xl border border-white/15 bg-white/10 p-8 backdrop-blur">
<h3 className="text-xl font-semibold">{t.examplesTitle}</h3>
<div className="mt-6 grid gap-4 md:grid-cols-3">
{examples[lang].map((ex) => (
<div
key={ex.title}
className="rounded-xl border border-white/10 bg-white/5 p-4"
>
<p className="text-lg">{ex.title}</p>
<p className="mt-2 text-sm text-white/80">"{ex.text}"</p>
</div>
))}
</div>
<div className="mt-6 flex justify-center">
<button
onClick={onContact}
className="rounded-lg bg-brand-pink px-6 py-3 text-sm font-semibold text-white transition hover:bg-[#ff7bc0]"
>
{t.examplesCta}
</button>
</div>
</div>
<p className="mt-6 text-center text-xs text-white/70">
{t.fairUseNote}{" "}
<button
type="button"
onClick={() => setShowFairUse(true)}
className="font-semibold text-white underline decoration-white/60 underline-offset-2"
>
{t.fairUseLink}
</button>
{t.fairUseEnd}
</p>
{showFairUse && (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
<div
className="absolute inset-0 bg-black/60"
onClick={() => setShowFairUse(false)}
/>
<div className="relative z-10 w-full max-w-lg rounded-2xl border border-white/20 bg-[#4a3572] p-8 text-white shadow-xl">
<div className="flex items-start justify-between gap-4">
<div>
<p className="text-xs uppercase tracking-widest text-white/70">
{t.fairUseTitle}
</p>
<h3 className="mt-2 text-xl font-bold">{t.fairUseQuestion}</h3>
</div>
<button
onClick={() => setShowFairUse(false)}
className="rounded-full border border-white/40 px-3 py-1 text-xs font-semibold text-white/80 hover:bg-white/10"
>
{t.close}
</button>
</div>
<div className="mt-6 space-y-3 text-sm text-white/85">
{t.fairUseBody.map((p) => (
<p key={p}>{p}</p>
))}
<ol className="list-decimal space-y-2 pl-5">
{t.fairUseList.map((item) => (
<li key={item}>{item}</li>
))}
</ol>
<p className="font-medium">{t.fairUseEndBody}</p>
</div>
</div>
</div>
)}
</section>
);
}