Add pricing plans and currency formatting for regional pricing display

This commit is contained in:
Jose Selesan
2026-09-15 17:04:32 -03:00
parent 531a77018f
commit 0d397ca7db
5 changed files with 78 additions and 48 deletions

View File

@@ -39,7 +39,8 @@ Ejemplo: `http://192.168.x.x:8081`
├── package.json # Scripts y dependencias
├── src/
│ ├── _data/
│ │ └── site.json # Datos globales del sitio (nombre, navegación, footer, año)
│ │ ├── site.json # Datos globales del sitio (nombre, navegación, footer, año)
│ │ └── pricing.json # Precios y monedas por plan (parametrizados)
│ ├── _includes/
│ │ ├── layouts/
│ │ │ └── base.njk # Layout principal (head, Tailwind CDN, dark mode, header/footer)
@@ -59,5 +60,6 @@ Ejemplo: `http://192.168.x.x:8081`
## Funcionalidades
- **Tema claro/oscuro**: toggle funcional que persiste en `localStorage` y respeta `prefers-color-scheme`.
- **Precios por región**: si el usuario navega desde Argentina (detectado por zona horaria) ve precios en pesos (ARS); en el resto de LATAM se muestran en dólares (USD). Los valores y monedas se parametrizan en `src/_data/pricing.json`: para cambiar un precio solo se edita ese archivo y se corre `npm run build`.
- **Responsive**: mobile-first, adaptado a móviles, tablets y escritorio.
- **Templates Nunjucks**: header, footer y datos reutilizables vía `_data/site.json`.

View File

@@ -5,6 +5,11 @@ export default function (eleventyConfig) {
host: "0.0.0.0",
});
eleventyConfig.addFilter("formatPrice", (value, currency) => {
const locale = currency === "ars" ? "es-AR" : "en-US";
return new Intl.NumberFormat(locale).format(value);
});
return {
dir: {
input: "src",

37
src/_data/pricing.json Normal file
View File

@@ -0,0 +1,37 @@
{
"currencies": {
"ars": { "label": "ARS", "symbol": "$" },
"usd": { "label": "USD", "symbol": "US$" }
},
"plans": [
{
"name": "Starter",
"tagline": "Para grupos pequeños que están comenzando.",
"price": { "ars": 0, "usd": 0 },
"cta": "Empezar gratis",
"ctaStyle": "outline",
"features": [
"Hasta 50 miembros",
"1 evento al mes",
"Analíticas básicas",
"Soporte por correo"
]
},
{
"name": "Pro",
"tagline": "Para comunidades en crecimiento con funciones avanzadas.",
"price": { "ars": 30000, "usd": 25 },
"cta": "Empezar",
"ctaStyle": "solid",
"highlight": true,
"badge": "Más conveniente",
"features": [
"Miembros ilimitados",
"Eventos ilimitados",
"Automatizaciones ilimitadas",
"Analíticas avanzadas",
"Soporte prioritario"
]
}
]
}

View File

@@ -10,6 +10,18 @@
document.documentElement.classList.add('dark');
}
</script>
<script>
(function () {
var currency = 'usd';
try {
var tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
if (tz && tz.indexOf('America/Argentina') === 0) {
currency = 'ars';
}
} catch (e) {}
document.documentElement.setAttribute('data-currency', currency);
})();
</script>
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
@@ -44,6 +56,9 @@
<style>
[x-cloak] { display: none !important; }
input[type="range"] { accent-color: #3b63f5; }
.price-ars { display: none; }
html[data-currency="ars"] .price-ars { display: inline; }
html[data-currency="ars"] .price-usd { display: none; }
</style>
</head>
<body class="font-sans antialiased bg-white text-slate-900 dark:bg-slate-950 dark:text-slate-100 transition-colors duration-300">

View File

@@ -9,59 +9,30 @@
</div>
<div class="mt-12 grid gap-6 lg:mx-auto lg:max-w-3xl lg:grid-cols-2 lg:items-stretch">
<!-- Starter / Gratis -->
<div class="flex flex-col rounded-2xl border border-slate-200 bg-white p-8 dark:border-slate-800 dark:bg-slate-900">
<h3 class="text-lg font-bold">Starter</h3>
<p class="mt-1 text-sm text-slate-600 dark:text-slate-400">Para grupos pequeños que están comenzando.</p>
{% for plan in pricing.plans %}
<div class="{% if plan.highlight %}relative flex flex-col rounded-2xl border-2 border-brand-500 bg-white p-8 shadow-2xl shadow-brand-500/20 dark:border-brand-400 dark:bg-slate-900{% else %}flex flex-col rounded-2xl border border-slate-200 bg-white p-8 dark:border-slate-800 dark:bg-slate-900{% endif %}">
{% if plan.highlight and plan.badge %}
<span class="absolute -top-4 left-1/2 -translate-x-1/2 rounded-full bg-gradient-to-r from-brand-500 to-brand-700 px-4 py-1.5 text-xs font-bold uppercase tracking-wide text-white shadow-lg shadow-brand-600/30">{{ plan.badge }}</span>
{% endif %}
<h3 class="text-lg font-bold">{{ plan.name }}</h3>
<p class="mt-1 text-sm text-slate-600 dark:text-slate-400">{{ plan.tagline }}</p>
<div class="mt-6 flex items-baseline gap-1">
<span class="text-4xl font-extrabold tracking-tight">$0</span>
<span class="price-usd text-4xl font-extrabold tracking-tight">{{ pricing.currencies.usd.symbol }} {{ plan.price.usd | formatPrice('usd') }}</span>
<span class="price-ars text-4xl font-extrabold tracking-tight">{{ pricing.currencies.ars.symbol }} {{ plan.price.ars | formatPrice('ars') }}</span>
<span class="text-sm font-medium text-slate-500 dark:text-slate-400">/mes</span>
</div>
<a href="#" class="mt-6 inline-flex w-full items-center justify-center rounded-xl border border-slate-300 bg-white px-6 py-3 text-sm font-semibold text-slate-800 transition hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100 dark:hover:bg-slate-800">Empezar gratis</a>
<a href="#" class="mt-6 inline-flex w-full items-center justify-center rounded-xl {% if plan.ctaStyle == 'solid' %}bg-brand-600 px-6 py-3 text-sm font-semibold text-white shadow-lg shadow-brand-600/30 transition hover:bg-brand-700{% else %}border border-slate-300 bg-white px-6 py-3 text-sm font-semibold text-slate-800 transition hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100 dark:hover:bg-slate-800{% endif %}">{{ plan.cta }}</a>
<ul class="mt-8 space-y-3 text-sm text-slate-700 dark:text-slate-300">
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>Hasta 200 miembros</li>
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>3 eventos al mes</li>
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>Analíticas básicas</li>
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>Soporte por correo</li>
{% for feature in plan.features %}
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>{{ feature }}</li>
{% endfor %}
</ul>
</div>
<!-- Pro / Destacado -->
<div class="relative flex flex-col rounded-2xl border-2 border-brand-500 bg-white p-8 shadow-2xl shadow-brand-500/20 dark:border-brand-400 dark:bg-slate-900">
{# <span class="absolute -top-4 left-1/2 -translate-x-1/2 rounded-full bg-gradient-to-r from-brand-500 to-brand-700 px-4 py-1.5 text-xs font-bold uppercase tracking-wide text-white shadow-lg shadow-brand-600/30">Popular</span> #}
<h3 class="text-lg font-bold">Pro</h3>
<p class="mt-1 text-sm text-slate-600 dark:text-slate-400">Para comunidades en crecimiento con funciones avanzadas.</p>
<div class="mt-6 flex items-baseline gap-1">
<span class="text-4xl font-extrabold tracking-tight">$29</span>
<span class="text-sm font-medium text-slate-500 dark:text-slate-400">/mes</span>
</div>
<a href="#" class="mt-6 inline-flex w-full items-center justify-center rounded-xl bg-brand-600 px-6 py-3 text-sm font-semibold text-white shadow-lg shadow-brand-600/30 transition hover:bg-brand-700">Empezar prueba gratis</a>
<ul class="mt-8 space-y-3 text-sm text-slate-700 dark:text-slate-300">
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>Hasta 5,000 miembros</li>
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>Eventos ilimitados</li>
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>Automatizaciones ilimitadas</li>
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>Analíticas avanzadas</li>
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>Soporte prioritario</li>
</ul>
</div>
<!-- Enterprise / Comunidad -->
{# <div class="flex flex-col rounded-2xl border border-slate-200 bg-white p-8 dark:border-slate-800 dark:bg-slate-900">
<h3 class="text-lg font-bold">Enterprise</h3>
<p class="mt-1 text-sm text-slate-600 dark:text-slate-400">Para grandes organizaciones con soporte dedicado.</p>
<div class="mt-6 flex items-baseline gap-1">
<span class="text-4xl font-extrabold tracking-tight">$99</span>
<span class="text-sm font-medium text-slate-500 dark:text-slate-400">/mes</span>
</div>
<a href="#" class="mt-6 inline-flex w-full items-center justify-center rounded-xl border border-slate-300 bg-white px-6 py-3 text-sm font-semibold text-slate-800 transition hover:bg-slate-50 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100 dark:hover:bg-slate-800">Contactar ventas</a>
<ul class="mt-8 space-y-3 text-sm text-slate-700 dark:text-slate-300">
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>Miembros ilimitados</li>
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>Integraciones personalizadas</li>
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>SSO y control de accesos</li>
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>Gerente de cuenta dedicado</li>
<li class="flex items-start gap-3"><svg class="mt-0.5 h-5 w-5 shrink-0 text-emerald-500" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 6 9 17l-5-5" /></svg>SLA y soporte 24/7</li>
</ul>
</div> #}
{% endfor %}
</div>
<p class="mt-8 text-center text-sm text-slate-500 dark:text-slate-400">¿Necesitas algo distinto? <a href="#" class="font-semibold text-brand-600 hover:underline dark:text-brand-400">Habla con nosotros</a></p>