feat: sitio comercial FSPM con micro CRM interno
Sitio público orientado a venta consultiva e implementación de las recomendaciones de la auditoría de marca y mercado: - Inicio con tres rutas (industria, riesgo, cumplimiento) y clasificador de riesgo en el héroe, contra el hallazgo de que el visitante tenía que inferir qué solución le correspondía. - Cinco páginas por segmento prioritario y catálogo comparable por clase de fuego, capacidad y agente. - Los claims sin evidencia por modelo quedan aislados y se presentan como compromiso de documentación, nunca como característica del producto. - SEO técnico completo: metadatos por página, sitemap derivado de los datos, JSON-LD, iconos y tarjeta social generadas. Micro CRM: - Captura por formulario embebido y por widget de WhatsApp que registra antes de abrir la conversación. - Atribución de primer toque que sobrevive a la navegación. - Deduplicación de contacto; un mismo contacto acumula oportunidades. - Motor de asignación por reglas con reparto por turno de respaldo. - Panel con dos roles de alcance distinto, tablero analítico, bitácora, pedidos y reglas. No enlazado desde el sitio público y con noindex. Empaquetado en Docker multietapa con la base de demostración horneada en la imagen y el volumen de datos separado, para que los leads capturados sobrevivan a los redespliegues. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
122e06a4bb
commit
01b817d098
@@ -0,0 +1,248 @@
|
||||
import type { Metadata } from "next";
|
||||
import Link from "next/link";
|
||||
import { FormularioContacto } from "@/components/formulario/FormularioContacto";
|
||||
import { Revelar } from "@/components/site/Revelar";
|
||||
import { EMPRESA, SITIO_URL, WHATSAPP } from "@/data/empresa";
|
||||
|
||||
/**
|
||||
* /contacto
|
||||
*
|
||||
* Solo datos verificados: teléfono, correo, ciudad y colonia. No hay horario de
|
||||
* atención, ni domicilio con número, ni mapa: nada de eso está confirmado, y
|
||||
* una dirección equivocada en un sitio de protección contra incendios es un
|
||||
* problema real, no un detalle.
|
||||
*/
|
||||
|
||||
const TITULO = "Contacto";
|
||||
const DESCRIPCION = `Habla con ${EMPRESA.nombre}. Teléfono, correo y solicitud de diagnóstico para operaciones que necesitan protección contra incendios documentada.`;
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: TITULO,
|
||||
description: DESCRIPCION,
|
||||
alternates: { canonical: `${SITIO_URL}/contacto` },
|
||||
openGraph: {
|
||||
title: `${TITULO} | ${EMPRESA.nombreCorto}`,
|
||||
description: DESCRIPCION,
|
||||
url: `${SITIO_URL}/contacto`,
|
||||
},
|
||||
};
|
||||
|
||||
const MENSAJE_WHATSAPP = encodeURIComponent(
|
||||
"Hola, me gustaría información sobre protección contra incendios.",
|
||||
);
|
||||
|
||||
export default function PaginaContacto() {
|
||||
return (
|
||||
<>
|
||||
{/* ---------- encabezado ---------- */}
|
||||
<section className="grid-bg bg-ink pt-12 pb-14 sm:pt-16 sm:pb-16">
|
||||
<div className="shell">
|
||||
<nav aria-label="Ruta de navegación" className="mb-8">
|
||||
<ol className="flex flex-wrap items-center gap-2 font-mono text-[0.625rem] uppercase tracking-[0.14em] text-faint">
|
||||
<li>
|
||||
<Link href="/" className="hover:text-bright">
|
||||
Inicio
|
||||
</Link>
|
||||
</li>
|
||||
<li aria-hidden="true">/</li>
|
||||
<li className="text-bright">Contacto</li>
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
<div className="max-w-3xl anim-rise">
|
||||
<p className="eyebrow mb-5">Contacto</p>
|
||||
<h1 className="font-display text-[2rem] font-black uppercase leading-[1.03] tracking-tight sm:text-[2.75rem] lg:text-5xl">
|
||||
Si tu situación no puede esperar, marca
|
||||
</h1>
|
||||
<p className="mt-6 text-base leading-relaxed text-muted sm:text-lg">
|
||||
Para todo lo demás, el formulario sirve mejor: llega con la clase de fuego, la
|
||||
superficie y el tipo de operación, así que la primera respuesta puede ser técnica en
|
||||
lugar de una pregunta de vuelta.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ---------- datos verificados ---------- */}
|
||||
<section className="border-t border-rule bg-ink-2 py-12 sm:py-14" aria-labelledby="datos-titulo">
|
||||
<div className="shell">
|
||||
<h2 id="datos-titulo" className="sr-only">
|
||||
Datos de contacto
|
||||
</h2>
|
||||
|
||||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<a
|
||||
href={`tel:${EMPRESA.telefonoTel}`}
|
||||
className="group flex flex-col rounded-[6px] border border-rule bg-ink p-5 transition-colors duration-200 hover:border-signal [-webkit-tap-highlight-color:transparent]"
|
||||
>
|
||||
<span className="font-mono text-[0.625rem] uppercase tracking-[0.14em] text-faint">
|
||||
Teléfono
|
||||
</span>
|
||||
<span className="mt-2.5 font-mono text-lg font-semibold text-bright transition-colors group-hover:text-signal-hi">
|
||||
{EMPRESA.telefono}
|
||||
</span>
|
||||
<span className="mt-2 text-xs leading-relaxed text-muted">
|
||||
Marca directo desde el móvil.
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href={`mailto:${EMPRESA.correo}`}
|
||||
className="group flex flex-col rounded-[6px] border border-rule bg-ink p-5 transition-colors duration-200 hover:border-signal [-webkit-tap-highlight-color:transparent]"
|
||||
>
|
||||
<span className="font-mono text-[0.625rem] uppercase tracking-[0.14em] text-faint">
|
||||
Correo
|
||||
</span>
|
||||
<span className="mt-2.5 break-all font-mono text-sm font-semibold text-bright transition-colors group-hover:text-signal-hi">
|
||||
{EMPRESA.correo}
|
||||
</span>
|
||||
<span className="mt-2 text-xs leading-relaxed text-muted">
|
||||
Útil si necesitas adjuntar planos o el requerimiento de tu auditoría.
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href={`https://api.whatsapp.com/send?phone=${WHATSAPP}&text=${MENSAJE_WHATSAPP}`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group flex flex-col rounded-[6px] border border-rule bg-ink p-5 transition-colors duration-200 hover:border-signal [-webkit-tap-highlight-color:transparent]"
|
||||
>
|
||||
<span className="font-mono text-[0.625rem] uppercase tracking-[0.14em] text-faint">
|
||||
WhatsApp
|
||||
</span>
|
||||
<span className="mt-2.5 font-mono text-sm font-semibold text-bright transition-colors group-hover:text-signal-hi">
|
||||
Abrir conversación
|
||||
</span>
|
||||
<span className="mt-2 text-xs leading-relaxed text-muted">
|
||||
El mismo número, si prefieres escribir antes de llamar.
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<div className="flex flex-col rounded-[6px] border border-rule bg-ink p-5">
|
||||
<span className="font-mono text-[0.625rem] uppercase tracking-[0.14em] text-faint">
|
||||
Ubicación
|
||||
</span>
|
||||
<span className="mt-2.5 font-mono text-sm font-semibold text-bright">
|
||||
{EMPRESA.colonia}
|
||||
</span>
|
||||
<span className="mt-1 font-mono text-sm text-muted">
|
||||
{EMPRESA.ciudad}, {EMPRESA.pais}
|
||||
</span>
|
||||
<span className="mt-2 text-xs leading-relaxed text-muted">
|
||||
Dinos en el formulario dónde está la instalación y te confirmamos cómo podemos
|
||||
atenderla.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="mt-6 max-w-3xl text-xs leading-relaxed text-faint">
|
||||
Publicamos únicamente los datos que pudimos verificar en la información pública de la
|
||||
empresa. Si necesitas domicilio fiscal, horario de atención o una visita presencial,
|
||||
pídelos por cualquiera de estos medios y te los confirmamos por escrito.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* ---------- formulario completo ---------- */}
|
||||
<section id="formulario" className="grid-bg-lite border-t border-rule bg-paper py-14 sm:py-20">
|
||||
<div className="shell">
|
||||
<div className="grid gap-10 lg:grid-cols-[1fr_1.1fr] lg:items-start lg:gap-16">
|
||||
<div>
|
||||
<Revelar>
|
||||
<p className="eyebrow mb-4">Solicitud</p>
|
||||
<h2 className="font-display text-2xl font-extrabold text-deep sm:text-3xl">
|
||||
Qué pasa cuando envías el formulario
|
||||
</h2>
|
||||
</Revelar>
|
||||
|
||||
<ol className="mt-8 space-y-6">
|
||||
{[
|
||||
{
|
||||
n: "01",
|
||||
t: "Se registra con folio",
|
||||
d: "Recibes un folio en pantalla. Tu solicitud queda asignada a una persona, no a un buzón compartido.",
|
||||
},
|
||||
{
|
||||
n: "02",
|
||||
t: "Se interpreta el escenario",
|
||||
d: "Con la clase de fuego, la superficie y el tipo de operación que declaraste, alguien revisa qué configuración aplica y qué habría que descartar.",
|
||||
},
|
||||
{
|
||||
n: "03",
|
||||
t: "Respondemos con documentación, no con folleto",
|
||||
d: "La respuesta incluye la selección propuesta y el índice de documentos que debería acompañarla. Si algo no podemos sostener por escrito, va dicho ahí.",
|
||||
},
|
||||
].map((paso) => (
|
||||
<li key={paso.n} className="flex gap-4">
|
||||
<span className="font-mono text-[0.625rem] font-semibold tracking-[0.08em] text-signal">
|
||||
{paso.n}
|
||||
</span>
|
||||
<div>
|
||||
<h3 className="font-display text-sm font-bold uppercase tracking-wide text-deep">
|
||||
{paso.t}
|
||||
</h3>
|
||||
<p className="mt-1.5 text-sm leading-relaxed text-deep-muted">{paso.d}</p>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
|
||||
<hr className="hair-lite my-8" />
|
||||
|
||||
<h3 className="font-mono text-[0.6875rem] uppercase tracking-[0.16em] text-deep-muted">
|
||||
Antes de escribir, quizá ya está respondido
|
||||
</h3>
|
||||
<ul className="mt-4 flex flex-wrap gap-2">
|
||||
{[
|
||||
{ href: "/preguntas-frecuentes", label: "Preguntas frecuentes" },
|
||||
{ href: "/cumplimiento-nom-002", label: "Cumplimiento NOM-002" },
|
||||
{ href: "/evidencia", label: "Centro de evidencia" },
|
||||
{ href: "/catalogo", label: "Catálogo" },
|
||||
].map((enlace) => (
|
||||
<li key={enlace.href}>
|
||||
<Link
|
||||
href={enlace.href}
|
||||
className="badge !border-rule-lite !text-deep-muted hover:!border-signal hover:!text-deep [-webkit-tap-highlight-color:transparent]"
|
||||
>
|
||||
{enlace.label}
|
||||
</Link>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<h3 className="mt-8 font-mono text-[0.6875rem] uppercase tracking-[0.16em] text-deep-muted">
|
||||
Redes
|
||||
</h3>
|
||||
<ul className="mt-4 flex flex-wrap gap-4">
|
||||
{[
|
||||
{ url: EMPRESA.redes.linkedin, label: "LinkedIn" },
|
||||
{ url: EMPRESA.redes.facebook, label: "Facebook" },
|
||||
{ url: EMPRESA.redes.youtube, label: "YouTube" },
|
||||
].map((red) => (
|
||||
<li key={red.label}>
|
||||
<a
|
||||
href={red.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="font-mono text-[0.6875rem] uppercase tracking-[0.12em] text-deep underline decoration-rule-lite underline-offset-4 hover:decoration-signal"
|
||||
>
|
||||
{red.label}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<FormularioContacto
|
||||
canal="contacto"
|
||||
variante="claro"
|
||||
compacto={false}
|
||||
titulo="Solicitar diagnóstico"
|
||||
descripcion="Cuéntanos qué operación hay que proteger. Te respondemos con el escenario, el equipo que aplica y qué documentación te corresponde."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user