From 2f7cbe237e198cd70e385735a7aecb63f0d1191f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Consultor=C3=ADa=20Alcaraz=20Salazar?= Date: Thu, 8 Oct 2026 00:09:00 +0000 Subject: [PATCH] white-label: brand de la clinica por configuracion (fase 1 de instancia sin branding SKEEN) - backend: GET/PUT /skeen/frontend/v1/brand leyendo ir.config_parameter skeen.clinic.brand (JSON: nombre, logo_claro, logo_oscuro, pie) con defaults SKEEN; GET publico (el login lo necesita sin sesion), PUT admin con auditoria. frontend_users.xml: 'Administrador SKEEN' -> 'Administrador' - frontend: ClinicBrand + BRAND_DEFAULT en odoo.ts; brand y setBrand en el contexto de auth (fetch al boot + cache localStorage + document.title) - Login/layouts/mensajes/exports leen el brand en vez de strings SKEEN: Login.tsx, SkeenLayout, HomeNestLayout, Cumpleanos (wa + export), Pacientes/Ventas/Cortes/Reportes/Kpis/Alertas/AgendaPrint (titulos), useClinicaPrint (fallback nombre), Login hace GET publico al montar - Configuracion > Clinica: tarjeta 'Identidad de la clinica' (solo admin) para editar nombre/pie/logos con preview - no renombrado (invisible al usuario): rutas API /skeen/*, claves localStorage, nombres de modulos, parametros skeen.* Verificacion API: 11/11 tests OK (defaults, PUT merge, campo invalido ignorado, restore, admin neutral). Deploy: build + rsync + Odoo reiniciado --- frontend/src/components/AgendaPrint.tsx | 4 +- frontend/src/components/HomeNestLayout.tsx | 8 +- frontend/src/components/SkeenLayout.tsx | 8 +- .../components/inventario/AlertasPanel.tsx | 4 +- .../components/reportes/ExportarReport.tsx | 4 +- .../src/components/reportes/KpisReport.tsx | 4 +- frontend/src/lib/auth.tsx | 38 +++++- frontend/src/lib/ticketConfig.ts | 6 +- frontend/src/pages/Configuracion.tsx | 109 +++++++++++++++++- frontend/src/pages/Cortes.tsx | 6 +- frontend/src/pages/Cumpleanos.tsx | 14 ++- frontend/src/pages/Login.tsx | 25 ++-- frontend/src/pages/Pacientes.tsx | 6 +- frontend/src/pages/Reportes.tsx | 6 +- frontend/src/pages/Ventas.tsx | 6 +- frontend/src/services/odoo.ts | 27 +++++ .../skeen_whatsapp/controllers/frontend.py | 73 ++++++++++++ .../skeen_whatsapp/data/frontend_users.xml | 2 +- 18 files changed, 302 insertions(+), 48 deletions(-) diff --git a/frontend/src/components/AgendaPrint.tsx b/frontend/src/components/AgendaPrint.tsx index d35def0..5cf16b5 100644 --- a/frontend/src/components/AgendaPrint.tsx +++ b/frontend/src/components/AgendaPrint.tsx @@ -1,6 +1,7 @@ import type { FC } from 'react'; import { Printer } from 'lucide-react'; import { Button, Modal } from './ui'; +import { useAuth } from '../lib/auth'; import type { Appointment, Bloqueo } from '../services/odoo'; // Vista de impresión de la agenda del día (patrón print-*): un bloque por @@ -50,6 +51,7 @@ const AgendaPrint: FC = ({ doctors, filterDoctorName, }) => { + const { brand } = useAuth(); const dayApts = appointments.filter((a) => a.date === date); // Bloques: un doctor por bloque (o solo el filtrado). Incluye "Sin asignar" // si hay citas sin doctor. @@ -122,7 +124,7 @@ const AgendaPrint: FC = ({ {/* Encabezado */}
-

SKEEN Derma Experts

+

{brand.nombre}

Agenda del día

diff --git a/frontend/src/components/HomeNestLayout.tsx b/frontend/src/components/HomeNestLayout.tsx index 507f0aa..d9161ff 100644 --- a/frontend/src/components/HomeNestLayout.tsx +++ b/frontend/src/components/HomeNestLayout.tsx @@ -53,8 +53,6 @@ interface LayoutProps { subtitle?: string; } -const LOGO_HOMENEST = '/skeen-brand/logos/Logo%20Completo%20Negro.png'; - const topNavItems = [ { label: 'Dashboard', icon: LayoutDashboard, href: '/' }, { label: 'Agenda', icon: Calendar, href: '/agenda' }, @@ -114,7 +112,7 @@ const menuSections = [ export const HomeNestLayout: FC = ({ children, title: _title, subtitle: _subtitle }) => { const location = useLocation(); const navigate = useNavigate(); - const { user, canSee, hasRole, logout } = useAuth(); + const { user, canSee, hasRole, logout, brand } = useAuth(); const [menuOpen, setMenuOpen] = useState(false); const [expanded, setExpanded] = useState(['Clínica']); const chatUnread = useChatUnread(); @@ -239,7 +237,7 @@ export const HomeNestLayout: FC = ({ children, title: _title, subti - SKEEN + {brand.nombre}
@@ -515,7 +513,7 @@ export const HomeNestLayout: FC = ({ children, title: _title, subti
setMenuOpen(false)} aria-hidden="true" />