import { Injectable } from '@angular/core'; import { BehaviorSubject, catchError, map, Observable, of, tap } from 'rxjs'; import { IEvent, IUrlData } from './interfaces/event.interface'; import { HttpClient } from '@angular/common/http'; @Injectable({ providedIn: 'root' }) export class AngularEventifyService { public url: string = ''; public addUrl: string = ''; public updateUrl: string = ''; public deleteUrl: string = ''; errorMessage = 'Request failed. Please try again later.'; private eventsSubject = new BehaviorSubject([]); events$: Observable = this.eventsSubject.asObservable(); private eventAddedSubject = new BehaviorSubject(null); eventAdded$: Observable = this.eventAddedSubject.asObservable(); private eventAddFailureSubject = new BehaviorSubject(''); eventAddFailure$: Observable = this.eventAddFailureSubject.asObservable(); private eventUpdatedSubject = new BehaviorSubject(null); eventUpdated$: Observable = this.eventUpdatedSubject.asObservable(); private eventUpdateFailureSubject = new BehaviorSubject(''); eventUpdateFailure$: Observable = this.eventUpdateFailureSubject.asObservable(); private eventDeletionSubject = new BehaviorSubject<{ name: string, id: string } | null>(null); eventDeletion$: Observable<{ name: string, id: string } | null> = this.eventDeletionSubject.asObservable(); private eventDeleteFailureSubject = new BehaviorSubject(''); eventDeleteFailed$: Observable = this.eventDeleteFailureSubject.asObservable(); init(baseUrl: IUrlData ): void { this.url = baseUrl.baseUrl + baseUrl.getUrl; this.addUrl = baseUrl.baseUrl + baseUrl.addUrl; this.updateUrl = baseUrl.baseUrl + baseUrl.updateUrl; this.deleteUrl = baseUrl.baseUrl + baseUrl.deleteUrl; } constructor(private http: HttpClient) { } addEvent(newEvent: IEvent): Observable { if (!newEvent || !newEvent.name || !newEvent.startTime || !newEvent.endTime || !newEvent.date) { return of(false); } return this.http.post(`${this.addUrl}`, newEvent).pipe( tap(response => { if (response && response.id) { this.eventAddedSubject.next(response); // Update the event list when a new event is added const currentEvents = this.eventsSubject.value; this.eventsSubject.next([...currentEvents, response]); } else { this.eventAddFailureSubject.next(this.errorMessage); } }), map((response: IEvent) => !!(response && response.id)), // Convert response to boolean catchError((error) => { this.eventAddFailureSubject.next(this.errorMessage); return of(false); }) ); } getAllEvents(): Observable { return this.url ? this.http.get(this.url).pipe( tap((data) => this.eventsSubject.next(Array.isArray(data) ? data : [])), catchError((error) => { console.error('Error fetching events:', error); return of([]); // Return an empty array on error }) ) : of([] as IEvent[]); } updateEvent(updatedEvent: IEvent): Observable { if (!updatedEvent || !updatedEvent.id) { return of(false); } return this.http.put(`${this.updateUrl}/${updatedEvent.id}/event`, updatedEvent).pipe( tap(response => { if (response && response.id) { // Check if response is valid this.eventUpdatedSubject.next(updatedEvent); const currentEvents = this.eventsSubject.value; const updatedEvents = currentEvents.map(event => event.id === updatedEvent.id ? updatedEvent : event); this.eventsSubject.next(updatedEvents); } else { this.eventUpdateFailureSubject.next(this.errorMessage); } }), map(() => true), // Always return true if no errors catchError((error) => { this.eventUpdateFailureSubject.next(this.errorMessage); return of(false); }) ); } deleteEvent(eventId: string, name: string): Observable { if (!eventId) { return of(false); } return this.http.delete(`${this.deleteUrl}/${eventId}`).pipe( tap(response => { if(response) { this.eventDeletionSubject.next({ id: eventId, name, }); // Update the event list when an event is deleted const currentEvents = this.eventsSubject.value; const updatedEvents = currentEvents.filter(event => event.id !== eventId); this.eventsSubject.next(updatedEvents); } else { // Handle the error inside the pipe this.eventDeleteFailureSubject.next(this.errorMessage); } }), map(() => true), // Always return true if no errors catchError((error) => { // Handle the error inside the pipe this.eventDeleteFailureSubject.next(this.errorMessage); return of(false); }) ); } }