line-gestao-frontend/src/app/services/notifications.service.ts

115 lines
4.1 KiB
TypeScript

import { Injectable } from '@angular/core';
import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http';
import { Observable, Subject, tap } from 'rxjs';
import { environment } from '../../environments/environment';
export type NotificationTipo = 'AVencer' | 'Vencido' | 'RenovacaoAutomatica' | string;
export type NotificationDto = {
id: string;
tipo: NotificationTipo;
titulo: string;
mensagem: string;
data: string;
referenciaData?: string | null;
diasParaVencer?: number | null;
lida: boolean;
lidaEm?: string | null;
vigenciaLineId?: string | null;
cliente?: string | null;
linha?: string | null;
usuario?: string | null;
conta?: string | null;
planoContrato?: string | null;
dtEfetivacaoServico?: string | null;
dtTerminoFidelizacao?: string | null;
};
export type NotificationsEvent =
| { type: 'read'; ids: string[]; readAtIso: string }
| { type: 'unread'; ids: string[] }
| { type: 'readAll'; readAtIso: string }
| { type: 'unreadAll' }
| { type: 'reload' };
@Injectable({ providedIn: 'root' })
export class NotificationsService {
private readonly baseApi: string;
private readonly eventsSubject = new Subject<NotificationsEvent>();
readonly events$ = this.eventsSubject.asObservable();
constructor(private http: HttpClient) {
const raw = (environment.apiUrl || '').replace(/\/+$/, '');
this.baseApi = raw.toLowerCase().endsWith('/api') ? raw : `${raw}/api`;
}
list(): Observable<NotificationDto[]> {
return this.http.get<NotificationDto[]>(`${this.baseApi}/notifications`);
}
markAsRead(id: string): Observable<void> {
const readAtIso = new Date().toISOString();
return this.http.patch<void>(`${this.baseApi}/notifications/${id}/read`, {}).pipe(
tap(() => this.eventsSubject.next({ type: 'read', ids: [id], readAtIso }))
);
}
markAsUnread(id: string): Observable<void> {
return this.http.patch<void>(`${this.baseApi}/notifications/${id}/unread`, {}).pipe(
tap(() => this.eventsSubject.next({ type: 'unread', ids: [id] }))
);
}
markAllAsRead(filter?: string, notificationIds?: string[]): Observable<void> {
let params = new HttpParams();
if (filter) params = params.set('filter', filter);
const body = notificationIds && notificationIds.length ? { notificationIds } : {};
const readAtIso = new Date().toISOString();
return this.http.patch<void>(`${this.baseApi}/notifications/read-all`, body, { params }).pipe(
tap(() => {
if (notificationIds && notificationIds.length) {
this.eventsSubject.next({ type: 'read', ids: notificationIds, readAtIso });
return;
}
// Se não sabemos o escopo (sem IDs), preferimos sinalizar que "todas" foram lidas.
// Para casos futuros de filtros sem IDs, o consumer pode optar por recarregar.
this.eventsSubject.next(filter ? { type: 'reload' } : { type: 'readAll', readAtIso });
})
);
}
markAllAsUnread(filter?: string, notificationIds?: string[]): Observable<void> {
let params = new HttpParams();
if (filter) params = params.set('filter', filter);
const body = notificationIds && notificationIds.length ? { notificationIds } : {};
return this.http.patch<void>(`${this.baseApi}/notifications/unread-all`, body, { params }).pipe(
tap(() => {
if (notificationIds && notificationIds.length) {
this.eventsSubject.next({ type: 'unread', ids: notificationIds });
return;
}
this.eventsSubject.next(filter ? { type: 'reload' } : { type: 'unreadAll' });
})
);
}
export(filter?: string, notificationIds?: string[]): Observable<HttpResponse<Blob>> {
let params = new HttpParams();
if (filter) params = params.set('filter', filter);
if (notificationIds && notificationIds.length) {
return this.http.post(`${this.baseApi}/notifications/export`, { notificationIds }, {
params,
observe: 'response',
responseType: 'blob'
});
}
return this.http.get(`${this.baseApi}/notifications/export`, {
params,
observe: 'response',
responseType: 'blob'
});
}
}