feat(whatsapp): schema del bot de reservas + panel de trabajos por jefe (F1+F3)

FASE 1 — schema:
- Cliente.email opcional; nuevo telefonoNorm (E.164, único) para matchear por WhatsApp
- TipoServicio.jefeMecanicoId opcional (trabajos per-jefe; globales legacy quedan null)
- Turno.autoId/kilometros opcionales (reservas por WhatsApp sin auto/km)
- Nuevo modelo ConversacionWhatsapp (estado del bot por teléfono)
- admin/turnos/[id]: no permite COMPLETADO sin auto+km; Sheets tolera email nulo

FASE 3 — panel de trabajos del jefe:
- API jefe/servicios (GET/POST) y jefe/servicios/[id] (PATCH/DELETE), scoped al jefe
- DELETE desactiva si el trabajo ya tiene turnos asociados
- Página /jefe/servicios (alta/listado/activar/editar/eliminar) + nav Turnos|Trabajos
- Dashboard del jefe resiliente a turnos sin auto/km ("a completar")

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Beldor
2026-07-27 19:01:54 -03:00
parent dd7f73453e
commit c53e5bb5aa
7 changed files with 348 additions and 26 deletions
+23
View File
@@ -12,6 +12,11 @@ export default function JefeLayout({ children }: { children: React.ReactNode })
if (pathname === "/jefe") return <>{children}</>;
const tabs = [
{ href: "/jefe/dashboard", label: "Turnos" },
{ href: "/jefe/servicios", label: "Trabajos" },
];
return (
<div className="min-h-screen flex flex-col">
<div className="max-w-5xl mx-auto w-full px-4 flex-1 flex flex-col py-6 gap-4">
@@ -24,6 +29,24 @@ export default function JefeLayout({ children }: { children: React.ReactNode })
Cerrar sesión
</button>
</div>
<nav className="flex gap-1">
{tabs.map((t) => {
const activo = pathname === t.href;
return (
<button
key={t.href}
onClick={() => router.push(t.href)}
className={`text-sm px-4 py-2 rounded-lg transition ${
activo
? "bg-white/15 text-white font-medium"
: "text-gray-300 hover:text-white hover:bg-white/10"
}`}
>
{t.label}
</button>
);
})}
</nav>
<main className="flex-1">{children}</main>
</div>
</div>