# Notifications Módulo de notificaciones: panel lateral del navbar (notification center) + página de preferencias por canal/módulo. Cubre dos dominios distintos consumiendo la misma API base: - **Notification Center** (`/notification-center/*`) — listado del bell, mark-as-read, deep-link a destino. - **Notification Preferences** (`/notification-preferences/*`) — toggles de canales (PUSH / BELL / MAIL) por módulo + feed email notifications config. --- ## Pantallas y flujos | Pantalla / flujo | Descripción | Entrada | Ruta | |---|---|---|---| | Notifications Config | Página de preferencias: toggles de canales por módulo, configuración de email del feed | `NotificationsConfig/index.tsx` | `/notifications-config` | | Side panel (bell) | Panel lateral montado desde el navbar; lista paginada de notificaciones con mark-as-read, deep-link y settings | `sidepanel/NotificationsSidePanelAdapter.tsx` | No route — mounted from `DashboardNavbar` via `lazyRetry` | --- ## Componentes y hooks clave | Nombre | Descripción | Ubicación | |---|---|---| | `NotificationsSidePanelAdapter` | Entry lazy del side panel; punto de montaje desde el navbar | `sidepanel/NotificationsSidePanelAdapter.tsx` | | `NotificationSidePanel` | Panel propiamente dicho (header + content + states) | `sidepanel/components/NotificationSidePanel.tsx` | | `useNotificationSidePanelController` | Controla queries paginadas, mark-as-read y refetches del bell | `sidepanel/useNotificationSidePanelController.tsx` | | `usePanelMountState` | Maneja mount/unmount delayed del side panel para animaciones de salida | `sidepanel/usePanelMountState.ts` | | `useNotificationLogoutCleanup` | Borra el FCM token antes del logout (registra `beforeLogoutCallback`) | `hooks/useNotificationLogoutCleanup.ts` | | `useNotificationsBellOpenState` | Estado de apertura del bell con callback `onBeforeToggle` | `hooks.ts` | | `useNotificationsConfigPageQueries` / `useThrottle` | Queries de la página de settings + helper de throttle | `hooks.ts` | | `NotificationChannels` / `NotificationModuleCard` | UI cards de la página de settings | `components/` | --- ## Archivos compartidos del módulo | Archivo | Contenido | |---|---| | `routes.ts` | URL builders del módulo (`notificationsRoutes.config()`) | | `services.ts` | Llamados a la API: notification center, preferences, FCM token management | | `queries.ts` | Dos sets de keys disjuntos: `notificationsKeys` (preferences) + `notificationCenterKeys` (bell). Apuntan a APIs distintas — no fusionar | | `constants.ts` | Module codes (`NotificationModuleCodes`), channels (`NotificationChannelCodes`), icons (`moduleIcons`), config del side panel (`NOTIFICATION_PANEL_WIDTH`, `SKELETON_KEYS`, …) | | `types.ts` | Tipos de dominio (`NotificationItem`, `ChannelPreferences`, `NotificationsStatsData`, …) | | `utils.ts` | Utilidades del dominio settings + cross-cutting de tab title/badge (`formatNotificationCountForTitle`, `updateTitleAndBadgeFromCount`, `hasUnreadNotifications`) | | `sidepanel/utils.ts` | Utilidades específicas del notification center: overlay rendering, deep link translation, Amplitude incidence mapping | | `hooks/` | Hooks de scope módulo (actualmente solo `useNotificationLogoutCleanup`). El resto convive en `hooks.ts` por compatibilidad histórica | --- ## Estructura de directorios ``` notifications/ ├── NotificationsConfig/ │ └── index.tsx # Página de preferencias (/notifications-config) ├── sidepanel/ # Notification center (bell) │ ├── NotificationsSidePanelAdapter.tsx │ ├── useNotificationSidePanelController.tsx │ ├── usePanelMountState.ts │ ├── utils.ts # Sidepanel-specific helpers │ └── components/ # Items, states, header, content ├── components/ # Componentes de la página de settings │ ├── NotificationChannels.tsx │ ├── NotificationModuleCard.tsx │ └── NotificationsConfigLoading.tsx ├── hooks/ │ └── useNotificationLogoutCleanup.ts ├── hooks.ts # Hooks compartidos (queries de settings + bell open state) ├── routes.ts ├── services.ts ├── queries.ts ├── constants.ts ├── types.ts └── utils.ts ``` --- ## Wiring externo - `src/routes.tsx` monta `NotificationsConfig` en `/notifications-config` con `Loadable + lazyRetry` (legacy pattern, sin `routeConfig`). - `src/components/dashboard/navbar/DashboardNavbar.tsx` monta `NotificationsSidePanelAdapter` con `lazyRetry`; usa `notificationCenterKeys.stats()` para el badge y `updateTitleAndBadgeFromCount` para tab title. - `src/components/dashboard/GlobalHelmetTitlePrefix.tsx` lee `notificationCenterKeys.stats()` y `formatNotificationCountForTitle` para el prefijo de title. - `src/contexts/NotificationsContext.tsx` (provider global): mantiene el FCM token en estado de App y consume `useNotificationLogoutCleanup`. Se queda en `src/contexts/` porque es un provider montado a nivel App, no scoped a la página. - `src/contexts/NewPostNotificationContext.tsx`: separate concern (feed-scoped); también global. --- ## Known issues / deuda técnica - `hooks.ts` (legacy) convive con la carpeta `hooks/`. La skill `/migrate-module` sugiere split a `hooks/*.ts` individuales — se difiere hasta que haya un cambio sustantivo en los hooks existentes para evitar churn sin valor. - `src/utils/sidebar.ts` y `src/utils/navbar.ts` matchean `/notifications-config/` con regex; podrían tomar `notificationsRoutes.config()` pero el patrón es cross-module y se mantiene como regex por consistencia. --- > Actualizar este README cuando se agreguen pantallas, se reorganicen carpetas o cambie el dominio del side panel vs settings.