/** * Notifications Service * * Servicio para leer notificaciones desde Firestore. * El backend escribe las notificaciones, el frontend solo las lee y actualiza estado. * * Se auto-inicializa cuando AuthService tiene un usuario autenticado. * También puede inicializarse manualmente con `initialize(userId)`. */ import { Injector } from '@angular/core'; import { Observable } from 'rxjs'; import { FirestoreCollectionFactory } from './firestore-collection'; import { FirestoreDocument } from './types'; import * as i0 from "@angular/core"; /** * Documento de notificación en Firestore. * Estructura escrita por el backend. */ export interface NotificationDocument extends FirestoreDocument { /** Título de la notificación */ title?: string; /** Cuerpo del mensaje */ body?: string; /** Datos personalizados (ej: route, actionType). Legacy — preferir actionRoute + payload */ data?: Record; /** Tipo de notificación */ type?: 'fcm' | 'system' | 'reminder' | string; /** Si la notificación fue leída */ isRead: boolean; /** AppID origen (ej: 'showcase', 'sigify'). Permite cross-app routing */ appId?: string; /** OrgID asociado (si la notif es org-scoped). Habilita switch-org al abrir */ orgId?: string; /** Route destino al click (ej: '/app/docs/123') */ actionRoute?: string; /** Payload estructurado para acciones (reemplazo tipado de `data`) */ payload?: Record; } /** * Servicio para leer notificaciones desde Firestore. * * Se auto-inicializa cuando AuthService tiene un usuario autenticado. * No requiere llamar a `initialize()` manualmente si AuthService está configurado. * * @example * ```typescript * // Con AuthService configurado: auto-inicialización * // Solo inyectar y usar directamente * private notifications = inject(NotificationsService); * * notifications$ = this.notifications.getAll(); * unreadCount$ = this.notifications.getUnreadCount(); * * // Sin AuthService: inicialización manual * this.notifications.initialize(userId); * ``` */ export declare class NotificationsService { private injector; private collectionFactory; private collection; private currentUserId; private collectionReady$; private authService; private firebaseService; /** * AppID de la app actual (`ValtechAuthConfig.appId`). Cada app filtra su * propio feed — la bandeja de bingo no debe mostrar notificaciones de * showcase ni viceversa (antes se mostraban todas mezcladas, con un badge * "cross-app" que además estaba roto — hardcodeaba 'showcase' como app * actual). Los links de acción de cada notificación siguen apuntando a SU * app de origen (`actionRoute`/handoff en `NotificationActionService`), así * que filtrar acá no rompe nada — solo evita el ruido cross-app en la lista. */ private readonly currentAppId; constructor(injector: Injector, collectionFactory: FirestoreCollectionFactory); /** * Filtro `where(appId == currentAppId)` a anteponer en toda query. Si la app * no configuró `appId` (config ausente/legacy), degrada al comportamiento * previo sin filtro — no romper apps que no lo tengan seteado. */ private appIdWhere; /** * Gate de Firebase Auth: emite la colección lista SOLO cuando la sesión de * Firebase Auth está confirmada. Sin FirebaseService disponible, no gatea * (degrada al comportamiento previo). Espera a que `firebaseAuthReady$` * emita antes de propagar la colección — así el listener Firestore nunca se * adjunta antes de que `request.auth` esté disponible. */ private collectionWhenAuthReady$; /** * Configura auto-inicialización observando el estado de AuthService. * Se ejecuta en el contexto del injector para poder usar effect(). */ private setupAutoInitialization; /** * Inicializa el servicio para un usuario específico. * * NOTA: Se llama automáticamente si AuthService está configurado. * Solo usar manualmente si AuthService no está disponible o se necesita * un userId diferente al del usuario autenticado. */ initialize(userId: string): void; /** * Verifica si el servicio está inicializado. */ get isReady(): boolean; /** * Obtiene el ID del usuario actual. */ get userId(): string | null; /** * Obtiene notificaciones ordenadas por fecha descendente (real-time). * Se actualiza automáticamente cuando cambian los datos. * * El listener Firestore NO se adjunta hasta que la sesión de Firebase Auth * esté confirmada (`FirebaseService.firebaseAuthReady`). Esto cierra la * ventana de `permission-denied` en cold start de PWA, donde el JWT del * backend puede estar listo antes que la sesión de Firebase Auth. * * @param limit - Máximo de notificaciones a cargar (default: 50) */ getAll(limit?: number): Observable; /** * Obtiene notificaciones (one-time fetch sin listener). * Útil para cargas iniciales sin necesidad de updates en tiempo real. * * @param limit - Máximo de notificaciones a cargar (default: 50) */ getAllOnce(limit?: number): Promise; /** * Obtiene solo notificaciones no leídas (real-time, filtrado server-side). * * @param limit - Máximo de notificaciones (default: 50) */ getUnread(limit?: number): Observable; /** * Cuenta notificaciones no leídas usando server-side aggregation query. * No descarga documentos — eficiente para badges en UI. * * Gateado por `firebaseAuthReady` — la aggregation query no se ejecuta hasta * que la sesión de Firebase Auth esté lista. */ getUnreadCount(): Observable; /** * Obtiene una notificación por ID. */ getById(notificationId: string): Promise; /** * Marca una notificación como leída. */ markAsRead(notificationId: string): Promise; /** * Marca todas las notificaciones no leídas como leídas (batch write). */ markAllAsRead(): Promise; /** * Elimina una notificación. */ delete(notificationId: string): Promise; /** * Elimina todas las notificaciones DE ESTA APP del usuario (batch delete). * Scopeado por appId — igual que el resto de las queries — para no borrar * notificaciones de otras apps que ni siquiera se están mostrando acá. */ deleteAll(): Promise; /** * Limpia el estado del servicio. * Útil para logout. */ reset(): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; }