Skip to content

Commit

Permalink
Refactor header to reactivity
Browse files Browse the repository at this point in the history
  • Loading branch information
mfp22 committed Nov 13, 2022
1 parent bd18abe commit 6741071
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 62 deletions.
13 changes: 12 additions & 1 deletion src/app/components/header/header.component.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<app-navigate [url]="url$ | async"></app-navigate>
<div class="header">
<div class="content">
<div class="sub_media">
Expand Down Expand Up @@ -36,8 +37,18 @@
type="submit"
value="Buscar"
class="submit"
(click)="onSubmit()"
(click)="search$.next([form.valid, form.value.search])"
/>
<app-swal
[options]="{
title: 'Incorrecto',
text: 'Debes ingresar al menos dos caracteres para hacer una búsqueda..',
icon: 'warning',
dangerMode: true
}"
[show]="invalidAlertOpen.state$ | async"
(close)="invalidAlertOpen.setFalse()"
></app-swal>
</form>
</div>
</div>
Expand Down
64 changes: 21 additions & 43 deletions src/app/components/header/header.component.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,35 @@
import { Component, OnInit } from '@angular/core';
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import swal from 'sweetalert';

import { HeaderService } from 'src/app/services/header-service/header.service';
import { AppStore } from 'src/app/store/app.store';
import { environment } from 'src/environments/environment';
import { filter, map, Subject } from 'rxjs';
import { booleanAdapter } from '@state-adapt/core/adapters';
import { toSource } from '@state-adapt/rxjs';
import { adapt } from '@state-adapt/angular';

@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss'],
})
export class HeaderComponent implements OnInit {
form: any;
constructor(
private headerService: HeaderService,
private store: AppStore,
private router: Router
) {}
export class HeaderComponent {
form = this.headerService.createForm();
constructor(private headerService: HeaderService) {}

ngOnInit(): void {
this.createForm();
}
search$ = new Subject<[boolean, string]>();

createForm() {
this.form = this.headerService.createForm();
}
searchIsInvalid$ = this.search$.pipe(
map(([valid]) => !valid),
toSource('searchIsInvalid$')
);
invalidAlertOpen = adapt(
['invalidAlertOpen', false, booleanAdapter],
this.searchIsInvalid$
);

onSubmit() {
if (this.form.valid) {
this.store.deleteMovies();
this.headerService
.searchMovies(this.form.value)
.subscribe((data: any) => {
data.results.forEach((movie: any) => {
if (movie.poster_path !== null) {
movie.poster_path = `${environment.imageUrl}${movie.poster_path}`;
} else {
movie.poster_path = 'assets/no-image.png';
}
});
this.store.saveSearch(data.results);
this.store.saveSearchHeader(this.form.value);
this.store.switchFlag(true);
this.router.navigate(['/search']);
});
} else {
swal({
title: 'Incorrecto',
text: 'Debes ingresar al menos dos caracteres para hacer una búsqueda..',
icon: 'warning',
dangerMode: true,
});
}
}
url$ = this.search$.pipe(
filter(([valid]) => valid),
map(([, search]) => `search/${search}`)
);
}
12 changes: 8 additions & 4 deletions src/app/components/search/search.component.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';

import { AppStore } from 'src/app/store/app.store';

Expand All @@ -10,7 +10,11 @@ import { AppStore } from 'src/app/store/app.store';
})
export class SearchComponent implements OnInit {
header!: string;
constructor(private store: AppStore, private router: Router) {}
constructor(
private store: AppStore,
private router: Router,
private route: ActivatedRoute
) {}

ngOnInit(): void {
this.store.state$.subscribe((res) => {
Expand All @@ -23,8 +27,8 @@ export class SearchComponent implements OnInit {
}

initialice() {
this.store.state$.subscribe((res: any) => {
this.header = res.header.search.toUpperCase();
this.route.params.subscribe((params) => {
this.header = params['search'];
});
}
}
52 changes: 38 additions & 14 deletions src/app/store/app.store.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,70 @@
import { Injectable } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { filter, map, Observable, pairwise, tap } from 'rxjs';
import { filter, map, merge, Observable, pairwise, switchMap } from 'rxjs';
import { MovieModel } from 'src/app/models/movie.interface';
import { environment } from 'src/environments/environment';
import { HeaderService } from '../services/header-service/header.service';
import { ReactiveStore } from './reactive-store';

export interface OrderState {
movies: MovieModel[];
movieSelected: MovieModel | null;
search: MovieModel[];
flag: boolean;
header: string;
}

@Injectable()
export class AppStore extends ReactiveStore<OrderState> {
constructor(private router: Router) {
constructor(private router: Router, private headerService: HeaderService) {
super({
movies: [],
movieSelected: null,
search: [],
flag: false,
header: '',
});

const urlFromMovieDetailToHome$ = this.router.events.pipe(
const urlAfterNav$ = this.router.events.pipe(
filter((event): event is NavigationEnd => event instanceof NavigationEnd),
map((event) => event.url)
);

const urlFromMovieDetailToHome$ = urlAfterNav$.pipe(
pairwise(),
filter(
([before, after]) =>
before.url === '/movie' && ['/home', '/'].includes(after.url)
before === '/movie' && ['/home', '/'].includes(after)
)
);

const searchRoute$ = urlAfterNav$.pipe(
filter((url) => url.startsWith('/search'))
);

const searchResults$ = searchRoute$.pipe(
switchMap((url) => {
const [, search] = url.split('/search/');
return this.headerService.searchMovies({ search });
}),
map((res: any) =>
res.results.map((movie: any) => ({
...movie,
poster_path:
movie.poster_path !== null
? `${environment.imageUrl}${movie.poster_path}`
: 'assets/no-image.png',
}))
)
);

this.react<AppStore>(this, {
deleteMovies: urlFromMovieDetailToHome$.pipe(map(() => undefined)),
switchFlag: urlFromMovieDetailToHome$.pipe(map(() => false)),
deleteMovies: merge(urlFromMovieDetailToHome$, searchRoute$).pipe(
map(() => undefined)
),
saveSearch: searchResults$,
switchFlag: merge(
urlFromMovieDetailToHome$.pipe(map(() => false)),
searchRoute$.pipe(map(() => true))
),
});
}
saveMovies = this.updater((state: OrderState, movies: MovieModel[]) => ({
Expand All @@ -47,11 +77,6 @@ export class AppStore extends ReactiveStore<OrderState> {
flag: flag,
}));

saveSearchHeader = this.updater((state: OrderState, header: string) => ({
...state,
header: header,
}));

saveSearch = this.updater((state: OrderState, search: MovieModel[]) => ({
...state,
search: [...search, ...state.search],
Expand All @@ -71,7 +96,6 @@ export class AppStore extends ReactiveStore<OrderState> {
movieSelected: movie,
}));
flag$ = this.select((state) => state.flag);
header$ = this.select((state) => state.header);
movies$: Observable<MovieModel[]> = this.select((state) => state.movies);
movieSelected$: Observable<MovieModel | null> = this.select(
(state) => state.movieSelected
Expand Down

0 comments on commit 6741071

Please sign in to comment.