- 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>
213 lines
8.9 KiB
TypeScript
213 lines
8.9 KiB
TypeScript
import { headers } from 'next/headers';
|
|
import { getTenantPerfil } from '@/db/tenant-queries';
|
|
import { actualizarEmpresa } from './actions';
|
|
import LogoUploader from '@/components/panel/LogoUploader';
|
|
import AboutFotoUploader from '@/components/panel/AboutFotoUploader';
|
|
import ThemePicker from '@/components/panel/ThemePicker';
|
|
|
|
export const dynamic = 'force-dynamic';
|
|
|
|
export default async function EmpresaPage() {
|
|
const perfil = await getTenantPerfil();
|
|
|
|
const h = await headers();
|
|
const host = h.get('x-forwarded-host') ?? h.get('host') ?? 'reformix.dv3.com.es';
|
|
const proto = h.get('x-forwarded-proto') ?? 'https';
|
|
const funnelUrl = `${proto}://${host}/${perfil.slug}`;
|
|
|
|
return (
|
|
<div className="space-y-10 max-w-2xl">
|
|
<div>
|
|
<h1 className="text-2xl font-black tracking-tight text-black">Datos de empresa</h1>
|
|
<p className="text-sm text-gray-500 mt-1">
|
|
Estos datos y el logo aparecen en la cabecera de los presupuestos en PDF que recibe el
|
|
cliente. Manténlos al día.
|
|
</p>
|
|
</div>
|
|
|
|
<section className="bg-white rounded-xl border border-gray-200 p-6">
|
|
<h2 className="font-bold text-black mb-4">Logo</h2>
|
|
<LogoUploader logoUrl={perfil.logoUrl} />
|
|
</section>
|
|
|
|
<section className="bg-white rounded-xl border border-gray-200 p-6">
|
|
<h2 className="font-bold text-black mb-4">Identidad</h2>
|
|
<form action={actualizarEmpresa} className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<label className="text-sm md:col-span-2">
|
|
<span className="block text-gray-500 mb-1">Nombre de la empresa *</span>
|
|
<input
|
|
name="nombreEmpresa"
|
|
required
|
|
defaultValue={perfil.nombreEmpresa}
|
|
className="w-full border border-gray-300 rounded-lg px-3 py-2"
|
|
/>
|
|
</label>
|
|
<label className="text-sm md:col-span-2">
|
|
<span className="block text-gray-500 mb-1">Enlace de tu funnel *</span>
|
|
<div className="flex items-center border border-gray-300 rounded-lg overflow-hidden">
|
|
<span className="px-3 py-2 text-gray-400 bg-gray-50 border-r border-gray-200 select-none whitespace-nowrap">
|
|
{host}/
|
|
</span>
|
|
<input
|
|
name="slug"
|
|
required
|
|
defaultValue={perfil.slug}
|
|
pattern="[a-z0-9-]+"
|
|
className="flex-1 px-3 py-2 outline-none min-w-0"
|
|
/>
|
|
</div>
|
|
<span className="block text-gray-400 mt-1.5 text-xs">
|
|
Esta es la dirección que compartes con tus clientes:{' '}
|
|
<a
|
|
href={funnelUrl}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-black underline underline-offset-2 break-all"
|
|
>
|
|
{funnelUrl}
|
|
</a>
|
|
</span>
|
|
</label>
|
|
<label className="text-sm">
|
|
<span className="block text-gray-500 mb-1">CIF / NIF</span>
|
|
<input
|
|
name="cif"
|
|
defaultValue={perfil.cif ?? ''}
|
|
className="w-full border border-gray-300 rounded-lg px-3 py-2"
|
|
/>
|
|
</label>
|
|
<label className="text-sm">
|
|
<span className="block text-gray-500 mb-1">Provincia</span>
|
|
<input
|
|
name="provincia"
|
|
defaultValue={perfil.provincia ?? ''}
|
|
className="w-full border border-gray-300 rounded-lg px-3 py-2"
|
|
/>
|
|
</label>
|
|
<label className="text-sm md:col-span-2">
|
|
<span className="block text-gray-500 mb-1">Dirección</span>
|
|
<input
|
|
name="direccion"
|
|
defaultValue={perfil.direccion ?? ''}
|
|
className="w-full border border-gray-300 rounded-lg px-3 py-2"
|
|
/>
|
|
</label>
|
|
<label className="text-sm">
|
|
<span className="block text-gray-500 mb-1">Teléfono</span>
|
|
<input
|
|
name="telefono"
|
|
defaultValue={perfil.telefono ?? ''}
|
|
className="w-full border border-gray-300 rounded-lg px-3 py-2"
|
|
/>
|
|
</label>
|
|
<label className="text-sm">
|
|
<span className="block text-gray-500 mb-1">Email</span>
|
|
<input
|
|
name="email"
|
|
type="email"
|
|
defaultValue={perfil.email ?? ''}
|
|
className="w-full border border-gray-300 rounded-lg px-3 py-2"
|
|
/>
|
|
</label>
|
|
<label className="text-sm md:col-span-2">
|
|
<span className="block text-gray-500 mb-1">Web</span>
|
|
<input
|
|
name="web"
|
|
defaultValue={perfil.web ?? ''}
|
|
className="w-full border border-gray-300 rounded-lg px-3 py-2"
|
|
/>
|
|
</label>
|
|
|
|
<div className="md:col-span-2 border-t border-gray-100 pt-5 mt-1">
|
|
<h3 className="font-bold text-black">SEO de tu funnel</h3>
|
|
<p className="text-xs text-gray-400 mt-1">
|
|
Personaliza cómo aparece tu página en Google y al compartirla. Si lo dejas vacío,
|
|
usamos un texto por defecto con el nombre de tu empresa.
|
|
</p>
|
|
</div>
|
|
<label className="text-sm md:col-span-2">
|
|
<span className="block text-gray-500 mb-1">Título (title)</span>
|
|
<input
|
|
name="seoTitle"
|
|
defaultValue={perfil.seoTitle ?? ''}
|
|
maxLength={70}
|
|
placeholder={`${perfil.nombreEmpresa} · Presupuesto de reforma`}
|
|
className="w-full border border-gray-300 rounded-lg px-3 py-2"
|
|
/>
|
|
</label>
|
|
<label className="text-sm md:col-span-2">
|
|
<span className="block text-gray-500 mb-1">Descripción (meta description)</span>
|
|
<textarea
|
|
name="seoDescription"
|
|
defaultValue={perfil.seoDescription ?? ''}
|
|
maxLength={160}
|
|
rows={2}
|
|
placeholder="Pide tu presupuesto de reforma con render IA en minutos."
|
|
className="w-full border border-gray-300 rounded-lg px-3 py-2"
|
|
/>
|
|
</label>
|
|
|
|
<div className="md:col-span-2 border-t border-gray-100 pt-5 mt-1">
|
|
<h3 className="font-bold text-black">Bloque “Quiénes somos”</h3>
|
|
<p className="text-xs text-gray-400 mt-1">
|
|
Si lo activas, en tu funnel aparece un bloque con tu foto, tu historia y tus años de
|
|
experiencia.
|
|
</p>
|
|
</div>
|
|
<label className="text-sm md:col-span-2 flex items-center gap-2">
|
|
<input
|
|
type="checkbox"
|
|
name="aboutEnabled"
|
|
defaultChecked={perfil.aboutEnabled}
|
|
className="w-4 h-4 accent-black"
|
|
/>
|
|
<span className="text-gray-700">Mostrar el bloque “Quiénes somos” en mi funnel</span>
|
|
</label>
|
|
<label className="text-sm">
|
|
<span className="block text-gray-500 mb-1">Años de experiencia</span>
|
|
<input
|
|
name="aniosExperiencia"
|
|
type="number"
|
|
min="1"
|
|
max="100"
|
|
defaultValue={perfil.aniosExperiencia ?? ''}
|
|
className="w-full border border-gray-300 rounded-lg px-3 py-2"
|
|
/>
|
|
</label>
|
|
<label className="text-sm md:col-span-2">
|
|
<span className="block text-gray-500 mb-1">Texto de presentación</span>
|
|
<textarea
|
|
name="aboutTexto"
|
|
defaultValue={perfil.aboutTexto ?? ''}
|
|
rows={5}
|
|
placeholder="Cuéntale al cliente quién eres, tu trayectoria y por qué confiar en ti."
|
|
className="w-full border border-gray-300 rounded-lg px-3 py-2"
|
|
/>
|
|
</label>
|
|
|
|
<button className="md:col-span-2 justify-self-start inline-flex items-center justify-center rounded-lg bg-black px-4 py-2 text-sm font-semibold text-white transition hover:bg-gray-900">
|
|
Guardar datos
|
|
</button>
|
|
</form>
|
|
</section>
|
|
|
|
<section className="bg-white rounded-xl border border-gray-200 p-6">
|
|
<h2 className="font-bold text-black mb-1">Foto de “Quiénes somos”</h2>
|
|
<p className="text-sm text-gray-500 mb-4">
|
|
Tu foto o la de tu equipo. Aparece en el bloque “Quiénes somos” de tu funnel.
|
|
</p>
|
|
<AboutFotoUploader fotoUrl={perfil.aboutFotoUrl} />
|
|
</section>
|
|
|
|
<section className="bg-white rounded-xl border border-gray-200 p-6">
|
|
<h2 className="font-bold text-black mb-1">Tema de tu funnel</h2>
|
|
<p className="text-sm text-gray-500 mb-4">
|
|
Elige los colores y la tipografía con los que tus clientes ven tu landing. Puedes partir
|
|
de un preset y, si quieres, fijar tu propio color de marca.
|
|
</p>
|
|
<ThemePicker themePreset={perfil.themePreset} themeColor={perfil.themeColor} />
|
|
</section>
|
|
</div>
|
|
);
|
|
}
|