Skip to content

Commit 4a6fff8

Browse files
feat(app): add data service for heroes
1 parent 3a53f9f commit 4a6fff8

6 files changed

Lines changed: 123 additions & 7 deletions

File tree

src/app/configs/app.config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,9 @@ export const AppConfig: any = {
3333
'https://*.google-analytics.com',
3434
],
3535
},
36+
storage: {
37+
keys: {
38+
heroes: 'heroes',
39+
},
40+
},
3641
};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
import { TestBed, waitForAsync } from '@angular/core/testing';
3+
import { NO_ERRORS_SCHEMA } from '@angular/core';
4+
import { HeroDataService } from './hero-data.service';
5+
import { of } from 'rxjs';
6+
import { UsersService } from '~core/services/users.service';
7+
8+
const userMock: any = { name: 'Isma', lang: 'es' };
9+
10+
describe('ApplyDataService', () => {
11+
let service: HeroDataService;
12+
let usersServiceSpy: jasmine.SpyObj<UsersService>;
13+
14+
const spyUser = jasmine.createSpyObj('UsersService', ['getUser']);
15+
const mockUser = () => {
16+
usersServiceSpy = TestBed.inject(UsersService) as jasmine.SpyObj<UsersService>;
17+
usersServiceSpy.getUser.and.returnValue(of(userMock));
18+
};
19+
20+
beforeEach(waitForAsync(() => {
21+
TestBed.configureTestingModule({
22+
imports: [],
23+
providers: [
24+
HeroDataService,
25+
{ provide: UsersService, useValue: spyUser },
26+
],
27+
schemas: [NO_ERRORS_SCHEMA]
28+
}).compileComponents();
29+
}));
30+
31+
beforeEach(() => {
32+
service = TestBed.inject(HeroDataService);
33+
mockUser();
34+
});
35+
36+
it('#getUser', done => {
37+
service.getUser().subscribe(user => {
38+
expect(user.name).toBe(userMock.name);
39+
done();
40+
});
41+
});
42+
43+
it('#setUser', done => {
44+
service.setUser(userMock);
45+
46+
service.getUser().subscribe(user => {
47+
expect(user.name).toBe(userMock.name);
48+
done();
49+
});
50+
});
51+
52+
it('#cleanData', () => {
53+
service.cleanData();
54+
expect((service as any).call).toBeNull();
55+
});
56+
});
57+
*/
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { Injectable } from '@angular/core';
2+
import { Observable, of, take } from 'rxjs';
3+
import { Hero } from '~modules/hero/shared/hero.model';
4+
import { AppConfig } from '~app/configs/app.config';
5+
import { HeroService } from '~modules/hero/shared/hero.service';
6+
import { StorageService } from '~shared/services/storage.service';
7+
8+
@Injectable({
9+
providedIn: 'root',
10+
})
11+
export class HeroDataService {
12+
private heroes: Hero[] | null;
13+
14+
constructor(private readonly heroService: HeroService) {
15+
this.heroes = StorageService.get(AppConfig.storage.keys.heroes) as unknown as Hero[];
16+
}
17+
18+
searchHeroes(): Observable<Hero[]> {
19+
if (this.heroes) {
20+
return of(this.heroes);
21+
}
22+
23+
const heroes$ = this.heroService.searchHeroes({ fetchPolicy: 'no-cache' });
24+
heroes$.pipe(take(1)).subscribe(heroes => {
25+
StorageService.set(AppConfig.storage.keys.heroes, JSON.stringify(heroes));
26+
});
27+
return heroes$;
28+
}
29+
30+
flushCache() {
31+
this.heroes = null;
32+
StorageService.remove(AppConfig.storage.keys.heroes);
33+
}
34+
}

src/app/modules/root/pages/home-page/home-page.component.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Component, OnDestroy, OnInit } from '@angular/core';
22
import { Hero } from '../../../hero/shared/hero.model';
33
import { Observable, Subject, takeUntil } from 'rxjs';
4-
import { HeroService } from '../../../hero/shared/hero.service';
54
import { EventsService, EventsTypes } from '../../../core/services/events.servide';
5+
import { HeroDataService } from '~modules/hero/shared/hero-data.service';
66

77
@Component({
88
selector: 'app-home-page',
@@ -14,7 +14,7 @@ export class HomePageComponent implements OnInit, OnDestroy {
1414

1515
heroes$: Observable<Hero[]> | undefined;
1616

17-
constructor(private heroService: HeroService, private eventsService: EventsService) {
17+
constructor(private heroDataService: HeroDataService, private eventsService: EventsService) {
1818
// @ts-ignore
1919
if (window.Cypress) {
2020
// @ts-ignore
@@ -23,11 +23,12 @@ export class HomePageComponent implements OnInit, OnDestroy {
2323
}
2424

2525
ngOnInit() {
26-
this.heroes$ = this.heroService.searchHeroes({ fetchPolicy: 'no-cache' });
26+
this.heroes$ = this.heroDataService.searchHeroes();
2727

2828
this.eventsService.events$.pipe(takeUntil(this.destroy$)).subscribe(event => {
2929
if (event.type === EventsTypes.UPDATE_HEROES) {
30-
this.heroes$ = this.heroService.searchHeroes({ fetchPolicy: 'no-cache' });
30+
this.heroDataService.flushCache();
31+
this.heroes$ = this.heroDataService.searchHeroes();
3132
}
3233
});
3334
}

src/app/modules/root/shared/search-bar/search-bar.component.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Component, Inject, OnInit } from '@angular/core';
33
import { FormControl } from '@angular/forms';
44
import { Hero } from '../../../hero/shared/hero.model';
55
import { ROUTES_CONFIG } from '~app/configs/routes.config';
6-
import { HeroService } from '../../../hero/shared/hero.service';
6+
import { HeroDataService } from '~modules/hero/shared/hero-data.service';
77

88
@Component({
99
selector: 'app-search-bar',
@@ -15,13 +15,16 @@ export class SearchBarComponent implements OnInit {
1515
heroFormControl: FormControl;
1616
filteredHeroes: any;
1717

18-
constructor(private heroService: HeroService, @Inject(ROUTES_CONFIG) public routesConfig: any) {
18+
constructor(
19+
private heroDataService: HeroDataService,
20+
@Inject(ROUTES_CONFIG) public routesConfig: any
21+
) {
1922
this.defaultHeroes = [];
2023
this.heroFormControl = new FormControl();
2124
}
2225

2326
ngOnInit() {
24-
this.heroService.searchHeroes({ fetchPolicy: 'no-cache' }).subscribe((heroes: Array<Hero>) => {
27+
this.heroDataService.searchHeroes().subscribe((heroes: Array<Hero>) => {
2528
this.defaultHeroes = heroes;
2629

2730
this.heroFormControl.valueChanges

src/app/shared/services/storage.service.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,22 @@ export enum StorageKey {
1313
export class StorageService {
1414
constructor() {}
1515

16+
static get(name: string): string | null {
17+
try {
18+
return JSON.parse(localStorage.getItem(name) as string);
19+
} catch (error) {
20+
return null;
21+
}
22+
}
23+
24+
static set(name: string, value: any): void {
25+
localStorage.setItem(name, value);
26+
}
27+
28+
static remove(name: string): void {
29+
localStorage.removeItem(name);
30+
}
31+
1632
getCookie(name: StorageKey): string | undefined {
1733
return Cookies.get(name);
1834
}

0 commit comments

Comments
 (0)