Integra el agente de voz de Retell (Arquitectura A para la demo): tras la
pre-llamada, el orquestador lanza una llamada saliente real con override de
agente y dynamic variables (empresa + cliente), mientras el render y el
presupuesto se siguen generando con los datos del formulario.
- src/lib/env.ts: esquema zod de RETELL_* (claves opcionales -> sin ellas el
funnel sigue en modo simulado y el build no se rompe)
- src/lib/voice/retell.ts: cliente fino con fetch a create-phone-call
(sin nueva dependencia), normalización E.164 y builder de variables
- orchestrator: dispara la llamada best-effort y guarda el callId
- tests del normalizador de teléfono y del builder de variables
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Añade bajo el título un párrafo orientativo: el precio final se fija tras
la visita gratuita y la estimación se basa en datos estadísticos ajustados
para acercarse lo máximo posible al importe definitivo.
- Añade una sección con el render del resultado y una descripción generada a
partir de los materiales (materialesRender) y el estilo de la llamada, con
fallback elegante cuando faltan datos.
- @react-pdf solo incrusta PNG/JPEG: convierte con sharp los WebP/SVG (render
y logo) que antes se descartaban en silencio dejando el PDF sin imagen. El
render va a JPEG redimensionado (PDF ~360 KB en vez de ~2,7 MB) y el logo a
PNG para conservar transparencia.
- Fija sharp como dependencia directa (ya venía como transitiva de Next).
- Copy nuevo añadido primero a COPY-GUIDE.md (sección entrega del presupuesto).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Los tres uploaders del panel (logo, "quiénes somos" y galería) ahora abren
un recorte interactivo (zoom + encuadre) y reescalan en el navegador antes
de subir: logo y "quiénes somos" a máx. 500 px, galería a máx. 1200 px,
reencodando a WebP (calidad 0.82). El SVG del logo se sube tal cual para no
rasterizar el vector. Esto reduce el peso de los data URIs base64 que se
guardan en Postgres y se inlinean en el funnel.
Nueva dependencia react-easy-crop: librería de recorte ligera, sin estado
global, compatible con React 19; el reescalado y reencodado se hacen con
canvas nativo (lib/image/crop.ts), sin dependencias extra.
Sustituye la paleta negra/azul B2C del panel del reformista por el verde
de marca, neutros cálidos y titulares en Instrument Serif de la landing B2B.
Añade tokens --color-primary-*, --color-stone-50 y --font-display al @theme.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Vista de leads en tarjetas + tabla con toggle (tarjetas por defecto, preferencia persistida)
- Galería de trabajos: gestión en /panel/galeria y bloque público en el funnel
- Selector de tema por reformista (presets + color de marca opcional) aplicado a la landing
- Login y registro rediseñados a pantalla partida 50/50 con foto de reforma
- Enlace "Entrar" funcional en la cabecera del funnel; elimina Navbar muerto
- Unifica tipografía y botones del panel con los tokens de la landing
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Panel/empresa: title y meta description SEO personalizables; foto, texto y
años de experiencia para el bloque "Quiénes somos" (toggle on/off).
- Funnel por slug: metadata SEO desde el tenant, bloque "Quiénes somos" y
testimonios servidos desde DB (sustituye los hardcodeados).
- Flujo de opiniones: el reformista solicita la opinión desde la ficha de un
lead ganado; el cliente la deja en un funnel dedicado /opinion/[id] con
estrellas + texto + fotos; entra como pendiente y el reformista la modera
(publicar/ocultar/eliminar) en /panel/opiniones antes de mostrarla.
- Schema: columnas SEO/about en tenants, testimonioSolicitadoAt en leads,
enum testimonio_estado, tablas testimonios + testimonio_fotos (migración 0006).
- Seed: opiniones demo (2 publicadas, 1 pendiente) y contenido "Quiénes somos".
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- / y /b2b sirven la landing B2B estática (rewrites beforeFiles)
- /{slug} resuelve el funnel del reformista (app/[slug]/page.tsx) con
branding propio (TenantBrand) y atribución de leads por tenant
- crearLead(slug) y páginas /solicitud usan el tenant del lead
- Panel: edición del slug del funnel + URL pública en /panel/empresa
- Helper de slugs reservados para evitar colisiones con rutas reales
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Reemplaza public/b2b.html (bundle estático viejo) por la versión con
reveals al scroll, hover-lift, count-up de stats e imágenes antes/después.
Assets servidos desde /b2b-assets para evitar colisiones. Sirve en el
dominio único reformix.dv3.com.es vía el rewrite /b2b existente.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El formulario de la landing ahora crea un lead real en BD y redirige a
/solicitud/[id]/fotos, donde el cliente sube fotos y datos de la reforma.
El orquestador simula los pasos de IA (pre-llamada, llamada, render) y
calcula el presupuesto DE VERDAD con el catálogo del reformista, dejando
el lead listo en el panel con render y desglose.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
La sección Presupuesto (PDF) usaba lead.pdfUrl, que nunca se rellena en el
MVP, así que siempre mostraba "Aún no generado". Ahora apunta a la ruta
on-demand /panel/[id]/presupuesto cuando existe desglose, con un parámetro
?download=1 que fuerza Content-Disposition: attachment.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Las filas del catálogo, la configuración general y el formulario de alta
no estaban pensados para móvil (input de precio descolgado, etiquetas que
desalineaban la cuadrícula, campos sueltos). Ahora las filas apilan
nombre + metadatos + controles de forma limpia en móvil y mantienen la
fila única en escritorio; la cuadrícula usa etiquetas legibles y alinea
los inputs; el alta es una cuadrícula de 2 columnas en móvil.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Las filas del catálogo y la cabecera CSV se desbordaban horizontalmente
en móvil (botones Guardar/Borrar fuera de pantalla), y ese overflow
horizontal desestabilizaba la barra de navegación fija. Las filas ahora
hacen wrap y el bloque <code> rompe palabra.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
El body usaba overflow-x:hidden, lo que forzaba overflow-y a auto y creaba
un contenedor de scroll ambiguo que rompía position:fixed (la barra
aparecía tarde y no se anclaba abajo, sobre todo en iOS Safari). Se cambia
a overflow-x:clip, que recorta el desbordamiento horizontal sin crear
contenedor de scroll.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sustituye el menú hamburguesa por una barra fija inferior con iconos y
etiquetas (thumb-friendly, siempre visible), manteniendo la nav horizontal
en escritorio.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Extrae un AppNav reutilizable con menú hamburguesa desplegable en móvil
y resaltado del enlace activo. Antes la marca y los enlaces se apretaban
en una sola fila en pantallas pequeñas; ahora el nombre de empresa se
oculta en móvil y los enlaces pasan a un desplegable.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adelanta de F1.5 a F2 la validación pre-envío: el panel permite elegir
modo de envío (automático/revisión), editar los conceptos del
presupuesto y enviar al cliente por WhatsApp (simulado).
Añade datos de empresa y logo configurables en /panel/empresa y genera
el presupuesto como PDF real descargable con esa marca vía
@react-pdf/renderer, sustituyendo la vista HTML imprimible.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Calcula y persiste el desglose de Roberto Salas con computeBudget para
que el detalle muestre un presupuesto generado real al abrir el panel.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>