import React from 'react'; import type { DashboardFetcher } from './types'; import type { WidgetRegistry } from './components/LazyWidget'; import type { WidgetAccessAdapter } from './access/types'; import { type DashboardCompany } from './components/DashboardCompanySelector'; import type { DashboardVocabularyTerm } from './types'; interface DashboardPageProps { /** Fetcher del host con autenticación y headers incluidos. */ fetcher: DashboardFetcher; /** ID del usuario autenticado (del JWT del host). */ userId: string; /** Roles del usuario autenticado (del JWT del host). */ userRoles: string[]; /** Muestra el selector de periodo (Hoy/Semana/Mes). Default false. */ showPeriodSelector?: boolean; /** Permite crear widgets con endpoints externos en el Builder. Default false. */ showExternalEndpoints?: boolean; /** * Si la puerta del Constructor existe, separada de si ofrece fuentes externas. Sin valor cae a * `showExternalEndpoints` — ningún host cambia de conducta. Ver `WidgetManagerPanel`. */ showWidgetBuilder?: boolean; /** Registro custom del host: mapea widget_id → componente React para widgets específicos. */ customWidgetRegistry?: WidgetRegistry; /** Orden preferido de categorías en la vista cascada. Las no listadas van al final alfabéticamente. */ categoryOrder?: string[]; /** * Vocabulario de segmentación que el Widget Builder ofrece al administrador, y que se guarda en * `roles_permitidos` del widget. * * Debe ser EL MISMO que el backend del host entrega como `roles`: el catálogo se filtra cruzando * ambos, así que si divergen el widget queda invisible para todos —incluido quien lo creó— sin * error ni log. * * Si se omite, la lista sale VACÍA y el Widget Builder lo dice. Antes caía a * `admin | ventas | compras | inventario` —el vocabulario de Siesa Comercial—, y un host de * Financiero o Nómina terminaba segmentando con módulos que no son suyos, sin ningún aviso. * * El `id` es lo que se persiste: puede ser el código de permiso del RBAC del host. */ /** * 🔴 **RETIRADO el 2026-09-14 (F3.b.5).** Ver `WidgetManagerPanel`. El Constructor ya no pregunta * la vertical, así que esta prop no llegaba a ningún sitio. */ /** * Vocabulario de categorías del host. `{ id, label }`: el `id` se persiste en `categoria` del * widget y el `label` es lo que se pinta — esa separación es lo que permite traducirlas. * * Admite `string[]` por compatibilidad: cada elemento se toma como `id` y `label` a la vez, que * es exactamente lo que hacía antes. */ availableCategories?: Array; /** * Si el usuario administra el catálogo: puede borrar widgets que no sean semilla y —con * `showExternalEndpoints`— conectar APIs externas. * * Lo decide el host, y por eso es una prop. Hasta ahora el kit lo deducía buscando el * literal `'admin'` dentro de `userRoles`, que es justo lo que el resto de este módulo dejó de * hacer: un host cuyo rol de administración se llame `nomina_admin` o `administrador` no lo * activaba nunca. Y era una mina para el propio Comercial: el día que los ids pasen a ser códigos * de permiso (`…dashboard.admin`), el literal deja de coincidir y el Widget Builder pierde sus * funciones de administración sin ningún error. * * Si se omite, se conserva la deducción anterior por compatibilidad. */ isAdmin?: boolean; /** * Capacidad de crear y editar definiciones de widget. Es lo que abre el Widget Builder. * * 🔴 Se separa de `isAdmin` porque son dos preguntas distintas y estaban colapsadas: un host * cuyo backend gatea la escritura con una capacidad propia —y no con el permiso de * administración— tenía la capacidad **inerte en la pantalla**, con el botón ausente para quien * el API sí autorizaba. Sin valor cae a `isAdmin` y nada cambia. */ canWriteWidgets?: boolean; /** * Capacidad de cambiar la EXPOSICION de un widget: a quien alcanza (`es_privado`, * `roles_permitidos`) y con que autoridad se pide su dato (`is_internal`). * * 🔴 Separada tambien de `isAdmin`, y por un motivo mas duro que el de escribir: el backend la * exige en el PATCH del catalogo, asi que un asistente que ofrezca el paso de permisos a quien no * la tiene acaba en 403 -y, en la version anterior, mandaba `es_privado: true` sin decirlo y * volvia privado un widget de modulo-. Sin valor cae a `isAdmin`. */ canPublishWidgets?: boolean; /** * 🔴 El adaptador del **diálogo de acceso** por widget: quién ve este indicador y qué exige para * verse. **Opcional**: sin él no se pinta ningún control de acceso y el tablero queda como estaba. * * El kit no habla HTTP — recibe las operaciones y las llama. Quien las implementa contra su * API vive en el host, igual que `IWidgetAccessPolicy` en el backend del componente: el modelo de * acceso es del host, el formulario es del kit. Y todo lo que el diálogo ofrece sale de las * capacidades que el adaptador declara, así que un host con un modelo más pequeño obtiene un * formulario más pequeño en vez de casillas que su backend va a rechazar. */ accessAdapter?: WidgetAccessAdapter; /** * Titulo de la pantalla. El kit trae uno neutro ("Tablero de indicadores"); un host que quiera * llamarlo por su producto lo declara aqui — el kit no puede saber si es Comercial, Financiero o * Nomina, y hasta ahora decia "Dashboard Comercial" para todos. */ title?: string; /** * Compañías entre las que el usuario puede cambiar. * * Sin esta prop el tablero no dibuja selector, y el host queda como estaba: * puede seguir poniendo el suyo por fuera. Es lo que permite adoptarlo sin migrar * de golpe. * * El tablero no gestiona el alcance: lo pinta y avisa del cambio. Quién es * la compañía activa, cómo se persiste y qué cabecera se envía siguen siendo del * host, que es quien tiene el contexto de sesión. */ companies?: DashboardCompany[]; /** La compañía activa. La decide el host — ver la advertencia de abajo. */ selectedCompanyId?: string | null; /** * Se llama al elegir una compañía distinta. * * ⚠️ El tablero NUNCA preselecciona por su cuenta. Si no llega * `selectedCompanyId`, el chip muestra su texto de marcador y no se dispara nada. * * Es la lección de `MasterCrud`: allí el kit preseleccionaba una compañía por * defecto y no emitía el evento para esa elección silenciosa, así que host * y kit discrepaban sobre cuál era la activa — y hubo que agregar * `isSelectedByDefault` para salir del lío. Aquí no puede pasar: el kit no elige. */ onCompanyChange?: (company: DashboardCompany) => void; /** * Opciones visibles pero no elegibles, con su motivo. * `{ '000': 'Las compañías habilitadas manejan monedas distintas' }` */ companyDisabledReasons?: Record; } export declare const DashboardPage: React.FC; export {}; //# sourceMappingURL=DashboardPage.d.ts.map