Rediseña panel y auth con la identidad de la landing B2C

- 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>
This commit is contained in:
Carlos Narro
2026-06-01 13:51:00 +02:00
parent a91fe5ce2c
commit 1ea5d70675
30 changed files with 2797 additions and 283 deletions

View File

@@ -92,6 +92,10 @@ export const tenants = pgTable('tenants', {
aboutFotoUrl: text('about_foto_url'), // data URI base64 de la foto del reformista
aboutTexto: text('about_texto'),
aniosExperiencia: integer('anios_experiencia'),
// Tema visual de la landing del reformista (personalización del funnel público).
// themePreset = id de THEME_PRESETS; themeColor = override hex opcional del color primario.
themePreset: text('theme_preset').notNull().default('pizarra'),
themeColor: text('theme_color'),
// Datos de empresa para la cabecera del presupuesto (RF-D-07).
cif: text('cif'),
direccion: text('direccion'),
@@ -255,6 +259,22 @@ export const testimonioFotos = pgTable('testimonio_fotos', {
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
});
// Galería de trabajos del reformista (fotos de reformas hechas), visible en su landing.
export const galeriaFotos = pgTable(
'galeria_fotos',
{
id: uuid('id').primaryKey().defaultRandom(),
tenantId: uuid('tenant_id')
.notNull()
.references(() => tenants.id, { onDelete: 'cascade' }),
url: text('url').notNull(), // data URI base64 (no hay storage externo aún)
titulo: text('titulo'),
orden: integer('orden').notNull().default(0),
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
},
(table) => [index('galeria_tenant_idx').on(table.tenantId)]
);
// Histórico de cambios de estado comercial (RF-D-03: persistir y reflejar)
export const leadEstadoHistory = pgTable('lead_estado_history', {
id: uuid('id').primaryKey().defaultRandom(),
@@ -333,6 +353,7 @@ export type LeadFoto = typeof leadFotos.$inferSelect;
export type Testimonio = typeof testimonios.$inferSelect;
export type NewTestimonio = typeof testimonios.$inferInsert;
export type TestimonioFoto = typeof testimonioFotos.$inferSelect;
export type GaleriaFoto = typeof galeriaFotos.$inferSelect;
export type LeadEstadoHistory = typeof leadEstadoHistory.$inferSelect;
export type LeadPipelineEvento = typeof leadPipelineEventos.$inferSelect;
export type PrecisionHistory = typeof precisionHistory.$inferSelect;