feat: add notification to contact response
This commit is contained in:
53
src/app/services/ResponseStateNotificatio.spec.ts
Normal file
53
src/app/services/ResponseStateNotificatio.spec.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
import { ResponseStateNotification } from './ResponseStateNotificatio';
|
||||
import { Notifier } from './notifier';
|
||||
import { catchError, EMPTY, of, throwError } from 'rxjs';
|
||||
import { Notification } from '../models/Notification';
|
||||
|
||||
describe('ResponseStateNotificatio', () => {
|
||||
let service: ResponseStateNotification;
|
||||
let notifier: jasmine.SpyObj<Notifier>;
|
||||
|
||||
let NOTIFICATION_MOCK: Notification;
|
||||
beforeEach(() => {
|
||||
notifier = jasmine.createSpyObj(Notifier.name, ['notify']);
|
||||
NOTIFICATION_MOCK = new Notification('mock', 'success');
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [{ provide: Notifier, useValue: notifier }],
|
||||
});
|
||||
service = TestBed.inject(ResponseStateNotification);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should notify success if observable has no errors', () => {
|
||||
service
|
||||
.handleResponse(
|
||||
of({
|
||||
data: null,
|
||||
message: 'success',
|
||||
success: true,
|
||||
}),
|
||||
NOTIFICATION_MOCK.message,
|
||||
NOTIFICATION_MOCK.message
|
||||
)
|
||||
.subscribe();
|
||||
expect(notifier.notify).toHaveBeenCalledOnceWith(NOTIFICATION_MOCK);
|
||||
});
|
||||
|
||||
it('should notify error if observable throws error', () => {
|
||||
service
|
||||
.handleResponse(
|
||||
throwError(() => new Error('Stream errored!')),
|
||||
NOTIFICATION_MOCK.message,
|
||||
NOTIFICATION_MOCK.message
|
||||
)
|
||||
.pipe(catchError(() => of(EMPTY)))
|
||||
.subscribe();
|
||||
NOTIFICATION_MOCK.type = 'error';
|
||||
expect(notifier.notify).toHaveBeenCalledOnceWith(NOTIFICATION_MOCK);
|
||||
});
|
||||
});
|
||||
26
src/app/services/ResponseStateNotificatio.ts
Normal file
26
src/app/services/ResponseStateNotificatio.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { catchError, Observable, tap, throwError } from 'rxjs';
|
||||
import { Response } from '../models/Response';
|
||||
import { Notification } from '../models/Notification';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { Notifier } from './notifier';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ResponseStateNotification {
|
||||
private readonly notifier = inject(Notifier);
|
||||
|
||||
handleResponse<T>(
|
||||
r: Observable<Response<T>>,
|
||||
success: string,
|
||||
error: string
|
||||
): Observable<Response<T>> {
|
||||
return r.pipe(
|
||||
tap(() => this.notifier.notify(new Notification(success, 'success'))),
|
||||
catchError((err) => {
|
||||
this.notifier.notify(new Notification(error, 'error'));
|
||||
return throwError(() => err);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,19 +4,29 @@ import { environment } from '../../environments/environment';
|
||||
import { ContactDTO } from '../models/ContactDTO';
|
||||
import { Response } from '../models/Response';
|
||||
import { BehaviorSubject, map, switchMap, tap } from 'rxjs';
|
||||
import { ResponseStateNotification } from './ResponseStateNotificatio';
|
||||
import { strings } from '../strings';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class ContactService {
|
||||
private readonly httpClient = inject(HttpClient);
|
||||
private readonly responseStateNotification = inject(ResponseStateNotification);
|
||||
private readonly contacts = new BehaviorSubject<ContactDTO[]>([]);
|
||||
|
||||
readonly contacts$ = this.contacts.asObservable();
|
||||
|
||||
delete(id: number) {
|
||||
return this.httpClient
|
||||
.delete<Response<string>>(`${environment.apiUrl}/contacts/${id}`)
|
||||
.pipe(switchMap(() => this.getAll()));
|
||||
return this.httpClient.delete<Response<string>>(`${environment.apiUrl}/contacts/${id}`).pipe(
|
||||
(r) =>
|
||||
this.responseStateNotification.handleResponse(
|
||||
r,
|
||||
strings.deleteContactSuccessNotification,
|
||||
strings.errorNotification
|
||||
),
|
||||
switchMap(() => this.getAll())
|
||||
);
|
||||
}
|
||||
|
||||
findById(id: string) {
|
||||
@@ -33,15 +43,27 @@ export class ContactService {
|
||||
}
|
||||
|
||||
save(contact: ContactDTO) {
|
||||
return this.httpClient
|
||||
.post<Response<ContactDTO[] | null>>(environment.apiUrl + '/contacts', contact)
|
||||
.pipe(switchMap(() => this.getAll()));
|
||||
return this.httpClient.post<any>(environment.apiUrl + '/contacts', contact).pipe(
|
||||
(r) =>
|
||||
this.responseStateNotification.handleResponse(
|
||||
r,
|
||||
strings.createContactSuccessNotification,
|
||||
strings.errorNotification
|
||||
),
|
||||
|
||||
switchMap(() => this.getAll())
|
||||
);
|
||||
}
|
||||
|
||||
update(contact: ContactDTO) {
|
||||
return this.httpClient.put<Response<ContactDTO[] | null>>(
|
||||
`${environment.apiUrl}/contacts/${contact.id}`,
|
||||
contact
|
||||
return this.httpClient
|
||||
.put<Response<ContactDTO[] | null>>(`${environment.apiUrl}/contacts/${contact.id}`, contact)
|
||||
.pipe((r) =>
|
||||
this.responseStateNotification.handleResponse(
|
||||
r,
|
||||
strings.editContactSuccessNotification,
|
||||
strings.errorNotification
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,15 @@ export const strings = Object.freeze({
|
||||
contactsCompany: "Contact's company",
|
||||
contactsPhone: "Contact's phone",
|
||||
contactList: 'contact list',
|
||||
createContactSuccessNotification: 'Contact created successfully',
|
||||
deleteContactSuccessNotification: 'Contact deleted successfully',
|
||||
editContact: 'edit contact',
|
||||
editContactSuccessNotification: 'Contact edited successfully',
|
||||
editTheContact: 'edit the contact',
|
||||
errorMessageMaxLength: (maxLen: number) => `Must be ${maxLen} characters or fewer.`,
|
||||
errorMessagePhonePattern: `Valid format: + (optional) plus 12 to 15 digits`,
|
||||
errorMessageRequired: 'This field is required.',
|
||||
errorNotification: 'Oops, there was an error',
|
||||
name: 'name',
|
||||
phone: 'phone',
|
||||
save: 'save',
|
||||
|
||||
Reference in New Issue
Block a user