Skip to content

Commit

Permalink
feat(GenericError): 🥅 handle errors in certificates page
Browse files Browse the repository at this point in the history
  • Loading branch information
juamber-rgs committed Nov 27, 2023
1 parent fd9409a commit 72fdf3c
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 107 deletions.
18 changes: 9 additions & 9 deletions src/app/shared/state/common/common.effects.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { createEffect, ofType } from '@ngrx/effects';
import { from, of } from 'rxjs';
import { catchError, delay, exhaustMap, map, mergeMap } from 'rxjs/operators';
import { catchError, concatMap, delay, exhaustMap, map, mergeMap } from 'rxjs/operators';

export abstract class CommonEffect<T> {
constructor(protected actions$: any, protected actions: any, protected service: any) {}

loadAll$ = createEffect(() => {
return this.actions$.pipe(
ofType(this.actions.loadAll),
delay(1500),
delay(0),
map((action: any) => action.payload),
exhaustMap((requestFilter) =>
from(this.service.getAll(requestFilter)).pipe(
Expand All @@ -22,9 +22,9 @@ export abstract class CommonEffect<T> {
loadMore$ = createEffect(() => {
return this.actions$.pipe(
ofType(this.actions.loadMore),
delay(1500),
delay(0),
map((action: any) => action.payload),
exhaustMap((requestFilter) =>
concatMap((requestFilter) =>
from(this.service.getAll(requestFilter)).pipe(
map((page: any) => this.actions.loadMoreSuccess({ payload: page })),
catchError((err) => of(this.actions.loadMoreFail({ error: err }))),
Expand All @@ -36,7 +36,7 @@ export abstract class CommonEffect<T> {
loadOne$ = createEffect(() => {
return this.actions$.pipe(
ofType(this.actions.loadOne),
delay(1500),
delay(0),
mergeMap((action: any) =>
from(this.service.getOne(action.id)).pipe(
map((item: any) => this.actions.loadOneSuccess({ payload: item })),
Expand All @@ -49,7 +49,7 @@ export abstract class CommonEffect<T> {
createOne$ = createEffect(() => {
return this.actions$.pipe(
ofType(this.actions.create),
delay(1500),
delay(0),
mergeMap((action: any) =>
from(this.service.create(action.payload)).pipe(
map((created) => this.actions.createSuccess({ payload: created })),
Expand All @@ -62,7 +62,7 @@ export abstract class CommonEffect<T> {
updateOne$ = createEffect(() => {
return this.actions$.pipe(
ofType(this.actions.update),
delay(1500),
delay(0),
mergeMap((action: any) =>
from(this.service.update(action.payload)).pipe(
map((updated) =>
Expand All @@ -79,7 +79,7 @@ export abstract class CommonEffect<T> {
deleteOne$ = createEffect(() => {
return this.actions$.pipe(
ofType(this.actions.delete),
delay(1500),
delay(0),
mergeMap((action: any) =>
from(this.service.delete(action.id)).pipe(
map(() => this.actions.deleteSuccess({ id: action.id })),
Expand All @@ -92,7 +92,7 @@ export abstract class CommonEffect<T> {
count$ = createEffect(() => {
return this.actions$.pipe(
ofType(this.actions.count),
delay(1500),
delay(0),
mergeMap(() =>
from(this.service.count()).pipe(
map((count: any) => this.actions.countSuccess({ payload: count })),
Expand Down
4 changes: 1 addition & 3 deletions src/app/shared/state/common/common.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ export class CommonReducer<T, S extends CommonState<T>> {
},
})),
on(this.actions.loadMoreSuccess, (state, { payload }) => {
const selected = state.entities.find((i: any) => i.id === state.selectedId);

return {
...state,
loading: false,
Expand All @@ -113,7 +111,7 @@ export class CommonReducer<T, S extends CommonState<T>> {
},
};
}),
on(this.actions.loadAllFail, (state, error) => ({
on(this.actions.loadMoreFail, (state, error) => ({
...state,
loading: false,
action: {
Expand Down
156 changes: 72 additions & 84 deletions src/app/website/pages/certificates/certificates.component.html
Original file line number Diff line number Diff line change
@@ -1,91 +1,79 @@
<ng-container *appLet="loadingMoreCertificateGroups$ | async as loadingMoreCertificateGroups">
<ng-container *appLet="loadingCertificateGroups$ | async as loadingCertificateGroups">
<ng-container *appLet="language$ | async as language">
<div class="certificates">
<ng-container *ngIf="!loadingCertificateGroups; else loading">
<div class="my-container" *ngFor="let certificateGroup of certificateGroups$ | async">
<div class="container-info">
<div
class="title"
#group
[id]="certificateGroup.id"
[@certificateGroupEnterAnimation]="getCertificateGroupEnterAnimationState(certificateGroup.id)"
>
<h3>{{ getTranslation(language.acronym, certificateGroup.nameTranslations) }}</h3>
</div>
<swiper [config]="swiperConfig" id="{{ '.swiper' + certificateGroup?.id }}">
<ng-template swiperSlide *ngFor="let certificate of orderByDate(certificateGroup.certificates)">
<div class="card swiper-slide">
<div class="image-content">
<div class="card-image">
<div class="overlay">
<h4>{{ getTranslation(language.acronym, certificate.nameTranslations) }}</h4>
<h5>{{ certificate.date | date }}</h5>
<p>{{ getTranslation(language.acronym, certificate.descriptionTranslations) }}</p>
</div>
<img
[src]="certificate.image"
[alt]="getTranslation(language.acronym, certificate.nameTranslations)"
class="card-img"
/>
</div>
<ng-container *appLet="language$ | async as language">
<ng-container [ngSwitch]="skillTypesActionStatus$ | async">
<div class="certificates">
<div class="my-container" *ngFor="let certificateGroup of certificateGroups$ | async">
<div class="container-info">
<div
class="title"
#group
[id]="certificateGroup.id"
[@certificateGroupEnterAnimation]="getCertificateGroupEnterAnimationState(certificateGroup.id)"
>
<h3>{{ getTranslation(language.acronym, certificateGroup.nameTranslations) }}</h3>
</div>
<swiper [config]="swiperConfig" id="{{ '.swiper' + certificateGroup?.id }}">
<ng-template swiperSlide *ngFor="let certificate of orderByDate(certificateGroup.certificates)">
<div class="card swiper-slide">
<div class="image-content">
<div class="card-image">
<div class="overlay">
<h4>{{ getTranslation(language.acronym, certificate.nameTranslations) }}</h4>
<h5>{{ certificate.date | date }}</h5>
<p>{{ getTranslation(language.acronym, certificate.descriptionTranslations) }}</p>
</div>
<img
[src]="certificate.image"
[alt]="getTranslation(language.acronym, certificate.nameTranslations)"
class="card-img"
/>
</div>
</div>

<div class="card-content">
<div class="buttons">
<button class="button" *ngIf="certificate.web">
<i (click)="open(certificate.web)" class="fa-solid fa-globe"></i>
</button>
<button class="button" *ngIf="certificate.microsoftStore">
<i (click)="open(certificate.microsoftStore)" class="fa-brands fa-microsoft"></i>
</button>
<button class="button" *ngIf="certificate.playStore">
<i (click)="open(certificate.playStore)" class="fa-brands fa-google-play"></i>
</button>
<button class="button" *ngIf="certificate.github">
<i (click)="open(certificate.github)" class="fa-brands fa-github"></i>
</button>
<button class="button" *ngIf="certificate.url">
<i (click)="open(certificate.url)" class="fa-solid fa-link"></i>
</button>
<button class="button" *ngIf="certificate.pdf">
<i (click)="open(certificate.pdf)" class="fa-solid fa-download"></i>
</button>
</div>
</div>
<div class="card-content">
<div class="buttons">
<button class="button" *ngIf="certificate.web">
<i (click)="open(certificate.web)" class="fa-solid fa-globe"></i>
</button>
<button class="button" *ngIf="certificate.microsoftStore">
<i (click)="open(certificate.microsoftStore)" class="fa-brands fa-microsoft"></i>
</button>
<button class="button" *ngIf="certificate.playStore">
<i (click)="open(certificate.playStore)" class="fa-brands fa-google-play"></i>
</button>
<button class="button" *ngIf="certificate.github">
<i (click)="open(certificate.github)" class="fa-brands fa-github"></i>
</button>
<button class="button" *ngIf="certificate.url">
<i (click)="open(certificate.url)" class="fa-solid fa-link"></i>
</button>
<button class="button" *ngIf="certificate.pdf">
<i (click)="open(certificate.pdf)" class="fa-solid fa-download"></i>
</button>
</div>
</ng-template>
</swiper>
</div>
</div>
</ng-container>
<ng-template #loading>
<div class="my-container" *ngFor="let certificateGroup of [0, 0]">
<div class="container-info">
<div class="title loading-title">
<h3>{{ 'general.loading' | translate }}</h3>
</div>
<swiper [config]="swiperConfig">
<ng-template swiperSlide *ngFor="let certificate of [0, 0, 0]">
<p-skeleton width="100%" height="20em"></p-skeleton>
</ng-template>
</swiper>
</div></div
></ng-template>
<ng-container *ngIf="loadingMoreCertificateGroups">
<div class="my-container" *ngFor="let certificateGroup of [0]">
<div class="container-info">
<div class="title loading-title">
<h3>{{ 'general.loading' | translate }}</h3>
</div>
</div>
<swiper [config]="swiperConfig">
<ng-template swiperSlide *ngFor="let certificate of [0, 0, 0]">
<p-skeleton width="100%" height="20em"></p-skeleton>
</ng-template>
</swiper>
</div></div
></ng-container>
</ng-template>
</swiper>
</div>
</div>
</ng-container>

<ng-container *ngSwitchCase="ActionStatus.PENDING">
<div class="my-container" *ngFor="let certificateGroup of [0]">
<div class="container-info">
<div class="title loading-title">
<h3>{{ 'general.loading' | translate }}</h3>
</div>
<swiper [config]="swiperConfig">
<ng-template swiperSlide *ngFor="let certificate of [0, 0, 0]">
<p-skeleton width="100%" height="20em"></p-skeleton>
</ng-template>
</swiper>
</div>
</div>
</ng-container>
<ng-container *ngSwitchCase="ActionStatus.ERROR">
<app-generic-error></app-generic-error>
</ng-container>
</div>
</ng-container>
</ng-container>
21 changes: 10 additions & 11 deletions src/app/website/pages/certificates/certificates.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@ import {
inject,
} from '@angular/core';
import { Store } from '@ngrx/store';
import { BehaviorSubject, Observable, pairwise, startWith, take, zip } from 'rxjs';
import { BehaviorSubject, Observable, filter, map, pairwise, startWith, zip } from 'rxjs';
import { CertificateGroup } from 'src/app/backoffice/tables/certificate-group/models/certificate-group.model';
import { certificateGroupActions } from 'src/app/backoffice/tables/certificate-group/state/certificate-group.actions';
import { certificateGroupReducer } from 'src/app/backoffice/tables/certificate-group/state/certificate-group.reducer';
import { CertificateType } from 'src/app/backoffice/tables/certificate-type/models/certificate-type.model';
import { certificateTypeReducer } from 'src/app/backoffice/tables/certificate-type/state/certificate-type.reducer';
import { Certificate } from 'src/app/backoffice/tables/certificate/models/certificate.model';
import { certificateReducer } from 'src/app/backoffice/tables/certificate/state/certificate.reducer';
import { Language } from 'src/app/backoffice/tables/language/models/language.model';
import { TranslationProvider } from 'src/app/shared/models/translation-provider.model';
import { ActionStatus, ActionType } from 'src/app/shared/state/common/common-state';
import { publicLanguageReducer } from 'src/app/shared/state/languages/public-language.reducer';
import Swiper, { A11y, Autoplay, Navigation, Pagination, Scrollbar, SwiperOptions } from 'swiper';

Expand All @@ -45,14 +43,11 @@ export class CertificatesComponent extends TranslationProvider implements OnInit

language$: Observable<Language> = this.store.select(publicLanguageReducer.getOne);

certificates$: Observable<Certificate[]> = this.store.select(certificateReducer.getAll);
loadingCertificates$: Observable<boolean> = this.store.select(certificateReducer.getLoading);
certificateTypes$: Observable<CertificateType[]> = this.store.select(certificateTypeReducer.getAll);
loadingCertificateTypes$: Observable<boolean> = this.store.select(certificateTypeReducer.getLoading);

certificateGroups$: Observable<CertificateGroup[]> = this.store.select(certificateGroupReducer.getAll);
loadingMoreCertificateGroups$: Observable<boolean> = this.store.select(certificateGroupReducer.getLoading);
loadingCertificateGroups$: Observable<boolean> = this.store.select(certificateGroupReducer.getLoading).pipe(take(2));
skillTypesActionStatus$: Observable<ActionStatus> = this.store.select(certificateGroupReducer.getAction).pipe(
filter((action) => !!action && action.type === ActionType.LOAD_MANY),
map((action) => action.status),
);
certificateGroupCount$: BehaviorSubject<number> = new BehaviorSubject<number>(0);

tabIndexes: { groupId: any; value: number }[] = [];
Expand Down Expand Up @@ -178,4 +173,8 @@ export class CertificatesComponent extends TranslationProvider implements OnInit
getCertificateGroupEnterAnimationState(certificateGroupId: string): 'inViewport' | 'notInViewport' {
return this.certificateElementStates.get(certificateGroupId) || 'notInViewport';
}

get ActionStatus() {
return ActionStatus;
}
}
2 changes: 2 additions & 0 deletions src/app/website/pages/certificates/certificates.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { SkeletonModule } from 'primeng/skeleton';
import { GenericErrorModule } from 'src/app/shared/components/generic-error/generic-error.module';
import { DirectivesModule } from 'src/app/shared/modules/directives.module';
import { PipesModule } from 'src/app/shared/modules/pipes.module';
import { SwiperModule } from 'swiper/angular';
Expand All @@ -18,6 +19,7 @@ import { CertificatesComponent } from './certificates.component';
SwiperModule,
DirectivesModule,
TranslateModule,
GenericErrorModule,
],
})
export class CertificatesModule {}

0 comments on commit 72fdf3c

Please sign in to comment.