diff --git a/src/app/components/header/header.component.html b/src/app/components/header/header.component.html index 63ad0cafdaa12053aef43e034d0e32b1a54d952d..938234ab1a6603e2a0c50a3d8424f35ffdc86b5e 100644 --- a/src/app/components/header/header.component.html +++ b/src/app/components/header/header.component.html @@ -4,7 +4,7 @@ menu -
CLIMBING GYM
+
CLIMBING GYM
diff --git a/src/app/components/header/header.component.ts b/src/app/components/header/header.component.ts index 52b1083f2f986c64329ab9cc920eba214683e144..e13ed1ea937bf2b4299f06429e8fb0477819eccd 100644 --- a/src/app/components/header/header.component.ts +++ b/src/app/components/header/header.component.ts @@ -11,7 +11,7 @@ import { updateCurrentMember, } from '../../store/actions/members.actions'; import { Store } from '@ngrx/store'; -import { getAllMembers } from '../../store/selectors/members.selectors'; +import { selectAllMembers } from '../../store/selectors/members.selectors'; import { Subject, takeUntil } from 'rxjs'; @Component({ @@ -29,7 +29,7 @@ export class HeaderComponent implements OnInit, OnDestroy { ngOnInit(): void { this.store.dispatch(loadMembers()); this.store - .select(getAllMembers) + .select(selectAllMembers) .pipe(takeUntil(this.onDestroy$)) .subscribe((data: Member[]) => { this.members = data; diff --git a/src/app/components/members/member-table/add-member-form/add-member-form.component.html b/src/app/components/members/member-table/add-member-form/add-member-form.component.html index 9ecba0d5d947b3e244fc9ea928c4e0ae5ab478b7..692c93036b9d8f3edcfbdb7894b1e0ce2ad8b1d3 100644 --- a/src/app/components/members/member-table/add-member-form/add-member-form.component.html +++ b/src/app/components/members/member-table/add-member-form/add-member-form.component.html @@ -15,6 +15,7 @@ placeholder="Firstname" formControlName="firstName" /> +
diff --git a/src/app/components/members/member-table/add-member-form/add-member-form.component.ts b/src/app/components/members/member-table/add-member-form/add-member-form.component.ts index 6fad4ea21456c5ad61c0658695a6f3f8d83bf945..44500129349d496eb145c6dc266810dc6b29a4cd 100644 --- a/src/app/components/members/member-table/add-member-form/add-member-form.component.ts +++ b/src/app/components/members/member-table/add-member-form/add-member-form.component.ts @@ -67,13 +67,14 @@ export class AddMemberFormComponent implements OnInit { onSubmit() { if (this.addMemberForm.valid) { const member: Member = { - firstName: this.addMemberForm.get('firstName')?.value, - lastName: this.addMemberForm.get('lastName')?.value, + firstName: this.addMemberForm.get('firstName')?.value as string || "", + lastName: this.addMemberForm.get('lastName')?.value as string || "", addressDto: { - street: this.addMemberForm.get('addressDto.street')?.value, - houseNumber: this.addMemberForm.get('addressDto.houseNumber')?.value, - postCode: this.addMemberForm.get('addressDto.postCode')?.value, + street: this.addMemberForm.get('addressDto.street')?.value as string || "", + houseNumber: this.addMemberForm.get('addressDto.houseNumber')?.value as number || 0, + postCode: this.addMemberForm.get('addressDto.postCode')?.value as string || "", }, + favouriteRoutes: [], }; this.store.dispatch(addMember({ member })); diff --git a/src/app/components/members/member-table/member-details/member-details.component.ts b/src/app/components/members/member-table/member-details/member-details.component.ts index 94f577a5c3de6edbf33a17749f717e6eb9f84e43..f03345380d5ecfa601a7ffa90e4b913732f62c53 100644 --- a/src/app/components/members/member-table/member-details/member-details.component.ts +++ b/src/app/components/members/member-table/member-details/member-details.component.ts @@ -4,10 +4,8 @@ import { Member } from '../../../../models/member'; import { loadMember } from '../../../../store/actions/members.actions'; import { AppState } from '../../../../store/model/app-state-model'; import { Store } from '@ngrx/store'; -import { getMember } from '../../../../store/selectors/members.selectors'; +import { selectMember } from '../../../../store/selectors/members.selectors'; import { Subject, Subscription, takeUntil } from 'rxjs'; -import { Actions, ofType } from '@ngrx/effects'; -import * as MemberActions from '../../../../store/actions/members.actions'; @Component({ selector: 'app-member-details', @@ -22,26 +20,8 @@ export class MemberDetailsComponent implements OnInit, OnDestroy { constructor( private activatedRoute: ActivatedRoute, - private store: Store, - private updates$: Actions - ) { - updates$ - .pipe( - ofType(MemberActions.loadMembersSuccess), - takeUntil(this.onDestroy$) - ) - .subscribe(() => { - this.store - .select(getMember) - .pipe(takeUntil(this.onDestroy$)) - .subscribe((member) => { - this.member = member; - }); - this.subscription = this.activatedRoute.params.subscribe((params) => - this.getMemberById(parseInt(params['id'])) - ); - }); - } + private store: Store + ) {} ngOnInit(): void { this.subscription = this.activatedRoute.params.subscribe((params) => @@ -49,7 +29,7 @@ export class MemberDetailsComponent implements OnInit, OnDestroy { ); this.store - .select(getMember) + .select(selectMember) .pipe(takeUntil(this.onDestroy$)) .subscribe((member) => { this.member = member; diff --git a/src/app/components/members/member-table/member-table.component.ts b/src/app/components/members/member-table/member-table.component.ts index 7d7c39822f5873b9bc86c7d8caadbf9dedf5e14c..7f37e8cc5a5e5a9428429b1fb6b633b1c1eeae49 100644 --- a/src/app/components/members/member-table/member-table.component.ts +++ b/src/app/components/members/member-table/member-table.component.ts @@ -7,7 +7,7 @@ import { MatDialog } from '@angular/material/dialog'; import { AddMemberFormComponent } from './add-member-form/add-member-form.component'; import { AppState } from '../../../store/model/app-state-model'; import { Store } from '@ngrx/store'; -import { getAllMembers } from '../../../store/selectors/members.selectors'; +import { selectAllMembers } from '../../../store/selectors/members.selectors'; import { loadMembers, removeMember, @@ -37,8 +37,10 @@ export class MemberTableComponent implements OnInit, OnDestroy { constructor(private dialog: MatDialog, private store: Store) {} ngOnInit(): void { - this.store.dispatch(loadMembers()); - this.store.select(getAllMembers).subscribe((data) => { + + this.store.select(selectAllMembers) + .pipe(takeUntil(this.onDestroy$)) + .subscribe((data) => { this.dataSource = new MatTableDataSource(data); this.dataSource.paginator = this.paginator; this.dataSource.sort = this.sort; diff --git a/src/app/components/routes/route/add-route-form/add-route-form.component.html b/src/app/components/routes/route/add-route-form/add-route-form.component.html index 4f852b8fb3eb78daf17c4b22d43d336b98183f42..d27bd6e8f430dc1652f9f61b4d8a4a91503ad5da 100644 --- a/src/app/components/routes/route/add-route-form/add-route-form.component.html +++ b/src/app/components/routes/route/add-route-form/add-route-form.component.html @@ -46,6 +46,7 @@ diff --git a/src/app/components/routes/route/route.component.scss b/src/app/components/routes/route/route.component.scss index a8a948420fcd32ef4e5fe5880526a2a446f13e58..b9b50fd583456e056ff097bee942203660b8a3db 100644 --- a/src/app/components/routes/route/route.component.scss +++ b/src/app/components/routes/route/route.component.scss @@ -10,10 +10,6 @@ color: #444444; } -.route:first-of-type { - margin-top: 0; -} - mat-icon { cursor: pointer; } @@ -22,7 +18,6 @@ mat-icon { display: flex; justify-content: flex-start; align-items: center; - cursor: pointer; font-size: 1.5rem; min-width: 320px; color: rgba(0, 0, 0, 0.6); @@ -56,11 +51,7 @@ mat-icon { height: 100%; margin-left: 3px; color: darkgrey; - transition: color .3s ease, transform .3s; - - &:hover{ - color: #fe2c54 !important; - } + } } diff --git a/src/app/components/routes/route/route.component.ts b/src/app/components/routes/route/route.component.ts index 0ad5dd8937ec2d01aaad21d875829dc3cc4b614b..606d47c2cbf73decf508a0725c1be94eff9780f2 100644 --- a/src/app/components/routes/route/route.component.ts +++ b/src/app/components/routes/route/route.component.ts @@ -1,56 +1,60 @@ -import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'; -import { Router } from '@angular/router'; +import { Component, Input, OnChanges, OnInit } from '@angular/core'; + import { Route } from '../../../models/route'; import { Store } from '@ngrx/store'; import { AppState } from '../../../store/model/app-state-model'; import { removeRoute } from '../../../store/actions/routes.actions'; -import { updateMember } from '../../../store/actions/members.actions'; -import { Member } from '../../../models/member'; -import { Subject } from 'rxjs'; +import { addMemberFavorite, removeMemberFavorite } from 'src/app/store/actions/members.actions'; +import { Member } from 'src/app/models/member'; @Component({ selector: 'app-route', templateUrl: './route.component.html', styleUrls: ['./route.component.scss'], }) -export class RouteComponent implements OnInit { +export class RouteComponent implements OnInit, OnChanges { @Input() route: Route | undefined; - @Input() currentMember: Member | undefined; - @Output() refreshParentRoutes = new EventEmitter(); - containsFavorite: boolean = false; - onDestroy$ = new Subject(); - - constructor(private router: Router, private store: Store) {} - - ngOnInit(): void { - // checks if current component is a favorite route and saves it as a boolean - this.containsFavorite = !!this.currentMember?.favouriteRoutes?.filter( - (fav) => fav.id === this.route?.id - ).length; + @Input() member: Member | undefined; + isFavorite: boolean = false; + + constructor(private store: Store) {} + + ngOnInit(): void {} + + ngOnChanges(): void { + this.isFavorite = this.checkFavorite(); } - deleteRoute(route: Route): void { - const id: number = route.id !== undefined ? route.id : 0; + onDeleteRoute(route: Route): void { + const id = route.id !== undefined ? route.id : 0; this.store.dispatch(removeRoute({ id })); this.router .navigateByUrl('/members', { skipLocationChange: true }) .then(() => this.router.navigate(['/routes'])); } - toggleFavoriteRoute() { - if (!this.containsFavorite && this.route !== undefined) { - this.currentMember?.favouriteRoutes?.push(this.route); - } else if (this.containsFavorite && this.route !== undefined) { - const indexOfFav = this.currentMember?.favouriteRoutes?.indexOf( - this.route - ); - if (indexOfFav) this.currentMember?.favouriteRoutes?.splice(indexOfFav); + checkFavorite(): boolean { + if (this.member?.favouriteRoutes && this.route) { + for (let favorite of this.member.favouriteRoutes) { + if (favorite.id === this.route.id) { + return true; + } + } + } + return false; + } + + toggleFavoriteRoute(favoriteRoute: Route) { + if (!this.member || !this.member.id) { + // TODO: handle this case in some way. If id is undefined, member was not saved yet. + return } - const member = this.currentMember; - if (member) { - this.store.dispatch(updateMember({ member })); + if (!this.isFavorite) { + this.store.dispatch(addMemberFavorite({ member: this.member, favoriteRoute })); + } else { + this.store.dispatch(removeMemberFavorite({ member: this.member, favoriteRoute })); } - this.refreshParentRoutes.next(); } + } diff --git a/src/app/components/routes/routes.component.html b/src/app/components/routes/routes.component.html index 4d58bb56d7accef6a52694d2af781a295f279ddb..a55d0a7394359de0a3deaaf843268710cc28fe6c 100644 --- a/src/app/components/routes/routes.component.html +++ b/src/app/components/routes/routes.component.html @@ -1,13 +1,12 @@ - - - - > - - +
+ +
+
+ + + + + +
diff --git a/src/app/components/routes/routes.component.spec.ts b/src/app/components/routes/routes.component.spec.ts index 767780bdff99b46c172974e48a57080600b5ee8e..cad5fafc845d142814cc03f27ec54fbddf9b4bbe 100644 --- a/src/app/components/routes/routes.component.spec.ts +++ b/src/app/components/routes/routes.component.spec.ts @@ -20,4 +20,4 @@ describe('RoutesComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); -}); +}; diff --git a/src/app/components/routes/routes.component.ts b/src/app/components/routes/routes.component.ts index 2c73ec57b4ad50cf66f7dbf818c0742028ca62d6..d3dd76105c2220bd927415b9eea3ebb87f6b5008 100644 --- a/src/app/components/routes/routes.component.ts +++ b/src/app/components/routes/routes.component.ts @@ -1,14 +1,10 @@ import { Component, OnDestroy, OnInit } from '@angular/core'; -import { Route } from '../../models/route'; import { Store } from '@ngrx/store'; -import { Observable, Subject, takeUntil } from 'rxjs'; import { AppState } from '../../store/model/app-state-model'; import { loadRoutes } from '../../store/actions/routes.actions'; import { getAllRoutes } from '../../store/selectors/routes.selectors'; -import { getCurrentMember } from '../../store/selectors/members.selectors'; -import { Member } from '../../models/member'; -import { Actions, ofType } from '@ngrx/effects'; -import * as RouteActions from '../../store/actions/routes.actions'; + +import { selectCurrentMember } from 'src/app/store/selectors/members.selectors'; @Component({ selector: 'app-routes', @@ -16,36 +12,14 @@ import * as RouteActions from '../../store/actions/routes.actions'; styleUrls: ['./routes.component.scss'], }) export class RoutesComponent implements OnInit, OnDestroy { - routes$: Observable = this.store.select(getAllRoutes); - currentMember: Member | undefined; - onDestroy$ = new Subject(); - - constructor(private store: Store, delete$: Actions) { - // JSON.parse creates a copy of the original object - that avoids errors later - this.store - .select(getCurrentMember) - .pipe(takeUntil(this.onDestroy$)) - .subscribe( - (data) => (this.currentMember = JSON.parse(JSON.stringify(data))) - ); - - delete$ - .pipe(ofType(RouteActions.removeRouteSuccess), takeUntil(this.onDestroy$)) - .subscribe(() => { - this.store.dispatch(loadRoutes()); - }); - } + routes$ = this.store.select(getAllRoutes); + member$ = this.store.select(selectCurrentMember); - ngOnInit(): void { + constructor(private store: Store) { this.store.dispatch(loadRoutes()); } - ngOnDestroy(): void { - this.onDestroy$.next(); - this.onDestroy$.complete(); - } + ngOnInit(): void {} - refreshRoutesComponent() { - this.ngOnInit(); - } + ngOnDestroy(): void {} } diff --git a/src/app/models/favoriteRoute.ts b/src/app/models/favoriteRoute.ts new file mode 100644 index 0000000000000000000000000000000000000000..57e406be49161106d231b02c2ea7fe64ef2f72cd --- /dev/null +++ b/src/app/models/favoriteRoute.ts @@ -0,0 +1,8 @@ +import { Action } from '@ngrx/store' + +export interface FavoriteRoute { + id: number | undefined; + name: string; + difficultyEnum: string; + toggleAction: Action; +} diff --git a/src/app/models/member.ts b/src/app/models/member.ts index 1e96dfe868a2845a422956bcd449debdb15e6e88..d67b081d01f48e8eb410b1c8e6f440ed51e58655 100644 --- a/src/app/models/member.ts +++ b/src/app/models/member.ts @@ -3,8 +3,8 @@ import {Route} from "./route"; export interface Member { id?: number; - firstName?: string; - lastName?: string; - addressDto?: Address; - favouriteRoutes?: Route[]; + firstName: string; + lastName: string; + addressDto: Address; + favouriteRoutes: Route[]; } diff --git a/src/app/routes/route/route-detail-page/route-detail-page.component.scss b/src/app/routes/route/route-detail-page/route-detail-page.component.scss deleted file mode 100644 index df222934d787616a84f187b68bf5cac8b3c886e4..0000000000000000000000000000000000000000 --- a/src/app/routes/route/route-detail-page/route-detail-page.component.scss +++ /dev/null @@ -1,50 +0,0 @@ -h2 { - font-size: 1.3rem; - width: 60%; - margin: 30px auto; - display: flex; - justify-content: center; - color: darkred; -} - -mat-divider { - width: 30%; - display: flex; - margin: 0px auto 20px auto; - background-color: darkred; -} -.example-card { - max-width: 500px; - margin: 20px auto; - padding: 20px; - - button { - font-size: 1.2rem; - width: 100px; - height: 40px; - cursor: pointer; - } - - mat-card-title { - font-size: 2rem; - margin-bottom: 40px; - } - - mat-divider { - width: 95%; - background-color: darkgrey; - margin-left: 10px; - margin-top: -10px; - } - - mat-card-subtitle { - font-size: 1.4rem; - margin-top: 50px; - margin-bottom: 30px; - } - - p { - margin-bottom: 30px; - font-size: 1.2rem; - } -} diff --git a/src/app/services/member.service.ts b/src/app/services/member.service.ts index 7e402c2fdabd1f4011196cdfc7149a65e06b7490..28eb7f30c9c23b8bc3f79e48f6ca46254104e621 100644 --- a/src/app/services/member.service.ts +++ b/src/app/services/member.service.ts @@ -25,7 +25,6 @@ export class MemberService { } public updateMember(member: Member, memberId: number | undefined): Observable { - console.log(member, memberId) return this.http.put(`${this.apiServerUrl}/member/${memberId}`, member); } diff --git a/src/app/store/actions/members.actions.ts b/src/app/store/actions/members.actions.ts index 2bffc570a4a3f7939b0fe3ecd9b5048bedffc48d..d822716ff1b6d2ec78a9a65423114478962804cd 100644 --- a/src/app/store/actions/members.actions.ts +++ b/src/app/store/actions/members.actions.ts @@ -1,5 +1,6 @@ import { createAction, props } from '@ngrx/store'; import { Member } from '../../models/member'; +import { Route } from 'src/app/models/route'; // Get all Members export const loadMembers = createAction('[Members] Load Members'); @@ -21,7 +22,7 @@ export const loadMember = createAction( export const loadMemberSuccess = createAction( '[Member] Load Member Success', - props<{ payload: Member }>() + props<{ member: Member }>() ); export const loadMemberFail = createAction( @@ -62,7 +63,7 @@ export const removeMemberFailure = createAction( // add route export const updateMember = createAction( - '[Member] Update Route', + '[Member] Update Member', props<{ member: Member }>() ); @@ -76,10 +77,34 @@ export const updateMemberFail = createAction( props<{ error: string }>() ); -// load specific route +export const addMemberFavorite = createAction( + '[Member] Add Favorite Route', + props<{ member: Member, favoriteRoute: Route }>() +); + +export const addMemberFavoriteSuccess = createAction( + '[Member] Add Favorite Route Success', + props<{ member: Member }>() +); + +export const removeMemberFavorite = createAction( + '[Member] Remove Favorite Route', + props<{ member: Member, favoriteRoute: Route }>() +); + +export const removeMemberFavoriteSuccess = createAction( + '[Member] Remove Favorite Route', + props<{ member: Member }>() +); + export const getCurrentMember = createAction('[Member] Load Current Member'); export const updateCurrentMember = createAction( '[Member] Update Current Member', props<{ id: number }>() ); + +// export const updateCurrentMemberSuccess = createAction( +// '[Member] Update Current Member Success', +// props<{ currentMember: Member }>() +// ); diff --git a/src/app/store/effects/members.effects.ts b/src/app/store/effects/members.effects.ts index 71c66a45949aa648c143422f27d52553c7944fe7..d45863ca8ed94e2ce607a2025d8d716b7c3a0df8 100644 --- a/src/app/store/effects/members.effects.ts +++ b/src/app/store/effects/members.effects.ts @@ -1,16 +1,12 @@ import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; -import { of, switchMap, tap } from 'rxjs'; -import { map, catchError, mergeMap, exhaustMap, concatMap } from 'rxjs/operators'; +import { of } from 'rxjs'; +import { map, catchError, mergeMap, concatMap, withLatestFrom } from 'rxjs/operators'; import * as MembersActions from '../actions/members.actions'; import { MemberService } from '../../services/member.service'; -import { AppState } from '../model/app-state-model'; -import { Store } from '@ngrx/store'; @Injectable() export class MembersEffects { - - loadMembers$ = createEffect(() => this.actions$.pipe( ofType(MembersActions.loadMembers), @@ -31,8 +27,8 @@ export class MembersEffects { ), map( (id) => MembersActions.removeMemberSuccess({ id }), - catchError((error) => of(MembersActions.removeMemberFailure(error))) - ) + ), + catchError((error) => of(MembersActions.removeMemberFailure(error))) ) ); @@ -42,22 +38,11 @@ export class MembersEffects { concatMap((data) => this.memberService.addMember(data.member)), map( (member) => MembersActions.addMemberSuccess({ member }), - catchError((error) => of(MembersActions.addMemberFailure(error))) - ) + ), + catchError((error) => of(MembersActions.addMemberFailure(error))) ) ); - reloadOnAddMemberSuccess$ = createEffect( - () => - this.actions$.pipe( - ofType(MembersActions.addMemberSuccess), - tap(() => { - this.loadMembers$; - }) - ), - {dispatch: false} - ) - updateMember$ = createEffect(() => this.actions$.pipe( ofType(MembersActions.updateMember), @@ -66,14 +51,44 @@ export class MembersEffects { ), map( (member) => MembersActions.updateMemberSuccess({ member }), - catchError((error) => of(MembersActions.updateMemberFail(error))) - ) + ), + catchError((error) => of(MembersActions.updateMemberFailure(error))) + ) + ); + + addMemberFavorite$ = createEffect(() => + this.actions$.pipe( + ofType(MembersActions.addMemberFavorite), + map(({ member, favoriteRoute }) => + MembersActions.updateMember({ + member: { + // TODO: clone address dto? + ...member, + favouriteRoutes: [ ...member.favouriteRoutes, favoriteRoute ] + } + }) + ), + ) + ); + + removeMemberFavorite$ = createEffect(() => + this.actions$.pipe( + ofType(MembersActions.removeMemberFavorite), + map(({ member, favoriteRoute }) => { + return MembersActions.updateMember({ + member: { + // TODO: clone address dto? + ...member, + favouriteRoutes: member.favouriteRoutes.filter(x => x.id !== favoriteRoute.id) + } + }) + } + ), ) ); constructor( private actions$: Actions, - private memberService: MemberService, - private store: Store + private memberService: MemberService ) {} } diff --git a/src/app/store/effects/routes.effects.ts b/src/app/store/effects/routes.effects.ts index 3373b66dde559f5ff7b364ae969c11621c9f2f7c..bfa7a6fd59d3f1adf0d87d1f28a13c3da7582b70 100644 --- a/src/app/store/effects/routes.effects.ts +++ b/src/app/store/effects/routes.effects.ts @@ -8,9 +8,6 @@ import { RouteService } from '../../services/route.service'; import * as RoutesActions from '../actions/routes.actions'; import { Router } from '@angular/router'; -/** - * Effects offer a way to isolate and easily test side-effects within your application. - */ @Injectable() export class RoutesEffects { constructor( @@ -35,27 +32,13 @@ export class RoutesEffects { this.actions$.pipe( ofType(RoutesActions.removeRoute), switchMap((route) => - this.routeService.deleteRoute(route.id).pipe(map(() => route.id)) - ), - map( - (id) => routeActions.removeRouteSuccess({ id }), + this.routeService.deleteRoute(route.id).pipe( + map( + () => routeActions.loadRoutes(), catchError((error) => of(RoutesActions.removeRouteFail(error))) ) - ) - ); - - // Short version without id - // removeRoute$ = createEffect(() => - // this.actions$.pipe( - // ofType(RoutesActions.removeRoute), - // switchMap((route) => - // this.routeService.deleteRoute(route.id)), - // map( - // () => routeActions.removeRouteSuccess(), - // catchError((error) => of(RoutesActions.removeRouteFail(error))) - // ) - // ) - // ); + )) + )); addRoute$ = createEffect(() => this.actions$.pipe( diff --git a/src/app/store/reducers/members.reducer.ts b/src/app/store/reducers/members.reducer.ts index 6dc795a033883b4dca94ccb7bbcd9afe5c1d5193..b000a9e93950e2f0ca14bf83dff84608efa4355a 100644 --- a/src/app/store/reducers/members.reducer.ts +++ b/src/app/store/reducers/members.reducer.ts @@ -1,6 +1,7 @@ import { Member } from '../../models/member'; import { Action, createReducer, on } from '@ngrx/store'; import * as MemberActions from '../actions/members.actions'; +import { Route } from 'src/app/models/route'; export interface MembersState { members: Member[]; @@ -8,6 +9,7 @@ export interface MembersState { error: string | null; loading: boolean; currentMember: Member | undefined; + favorites: Route[]; } const initialState: Readonly = { @@ -15,7 +17,8 @@ const initialState: Readonly = { member: undefined, error: null, loading: false, - currentMember: {}, + currentMember: undefined, + favorites: [], }; export const membersReducer = createReducer( @@ -51,10 +54,10 @@ export const membersReducer = createReducer( loading: true, }; }), - on(MemberActions.loadMemberSuccess, (state, { payload }): MembersState => { + on(MemberActions.loadMemberSuccess, (state, { member }): MembersState => { return { ...state, - members: [...state.members, payload], + members: [...state.members, member], loading: false, }; }), @@ -63,8 +66,7 @@ export const membersReducer = createReducer( on(MemberActions.addMember, (state): MembersState => { return { ...state, - members: [...state.members], - loading: true, + loading: false, }; }), @@ -87,7 +89,7 @@ export const membersReducer = createReducer( }; }), - on(MemberActions.updateMember, (state, { member }): MembersState => { + on(MemberActions.updateMember, (state): MembersState => { return { ...state, loading: true, @@ -108,11 +110,38 @@ export const membersReducer = createReducer( }; }), + on( + MemberActions.addMemberFavorite, + (state, { favoriteRoute }): MembersState => { + if (state.currentMember?.favouriteRoutes) { + const favorites = state.currentMember.favouriteRoutes + .filter((favorite) => favorite.id !== favoriteRoute.id) + .concat(favoriteRoute); + return { ...state, favorites }; + } + return { ...state }; + } + ), + + on( + MemberActions.removeMemberFavorite, + (state, { favoriteRoute }): MembersState => { + if (state.currentMember?.favouriteRoutes) { + const favorites = state.currentMember.favouriteRoutes.filter( + (favorite) => favorite.id !== favoriteRoute.id + ); + return { ...state, favorites }; + } + return { ...state }; + } + + ), + //Get Current member on(MemberActions.getCurrentMember, (state): MembersState => { return { ...state, - // loading:true, + loading: true, }; }), @@ -121,9 +150,16 @@ export const membersReducer = createReducer( ...state, currentMember: state.members.find((member) => member.id === id), - // loading: false, + loading: true, }; }) + // on(MemberActions.updateCurrentMemberSuccess, (state, action): MembersState => { + // return { + // ...state, + // currentMember: action.currentMember, + // loading: false, + // }; + // }), ); export function reducer(state: MembersState, action: Action) { diff --git a/src/app/store/reducers/routes.reducer.ts b/src/app/store/reducers/routes.reducer.ts index 411f9d0e7390fa32ff36949f8d241ba46aa4fc45..80c76ed89ef6fe77a23cc3d6d1d4aef2b4597ba1 100644 --- a/src/app/store/reducers/routes.reducer.ts +++ b/src/app/store/reducers/routes.reducer.ts @@ -48,45 +48,25 @@ export const routesReducer = createReducer( loading: false, }; }), - //add route - on(RouteActions.addRoute, (state, { route }): RoutesState => { + + on(RouteActions.addRoute, (state): RoutesState => { return { ...state, loading: true, }; }), - on(RouteActions.addRouteSuccess, (state, action): RoutesState => { + on(RouteActions.addRouteSuccess, (state, {route}): RoutesState => { return { ...state, - routes: [...state.routes, action.route], + routes: [...state.routes, route], loading: false, }; }), - on(RouteActions.addRouteFail, (state, action): RoutesState => { + on(RouteActions.addRouteFail, (state, {error}): RoutesState => { return { ...state, loading: false, - error: action.error, - }; - }), - on(RouteActions.addRoute, (state, { route }): RoutesState => { - return { - ...state, - loading: true, - }; - }), - on(RouteActions.addRouteSuccess, (state, action): RoutesState => { - return { - ...state, - routes: [...state.routes, action.route], - loading: false, - }; - }), - on(RouteActions.addRouteFail, (state, action): RoutesState => { - return { - ...state, - loading: false, - error: action.error, + error: error, }; }), // remove route diff --git a/src/app/store/selectors/members.selectors.ts b/src/app/store/selectors/members.selectors.ts index 86a1bd6318c9e4a2d338c12516bde32df38790d0..34036208c79ac931207b7494ec1ac9b9a7ace094 100644 --- a/src/app/store/selectors/members.selectors.ts +++ b/src/app/store/selectors/members.selectors.ts @@ -1,16 +1,40 @@ -import { createFeatureSelector, createSelector } from '@ngrx/store'; +import { createFeatureSelector, createSelector} from '@ngrx/store'; import { MembersState } from '../reducers/members.reducer'; -export const MemberState = createFeatureSelector('members'); -export const getAllMembers = createSelector( - MemberState, +export const MEMBER_STATE = 'members'; + +export const memberState = createFeatureSelector(MEMBER_STATE); + +export const selectAllMembers = createSelector( + memberState, (state: MembersState) => state.members ); -export const getMember = createSelector(MemberState, (state) => state.member); +export const selectMember = createSelector(memberState, (state) => state.member); -export const getCurrentMember = createSelector( - MemberState, +export const selectCurrentMember = createSelector( + memberState, (state) => state.currentMember ); + +export const selectCurrentMemberFavorites = createSelector( + memberState, + (state) => state.currentMember?.favouriteRoutes +); + +export const selectFavoriteRouteIds = createSelector(selectCurrentMemberFavorites, favorites => favorites?.map(({ id }) => id)); + +// export const selectFavoriteRouteItem = createSelector(selectCurrentMemberFavorites, favorites => { +// return favorites?.map(favorite => { +// if(favorite){ +// const route: FavoriteRoute = { +// id: favorite.id, +// name: favorite.name, +// difficultyEnum: favorite.difficultyLevelEnum, +// toggleAction: removeFavoriteRoute({ route: favorite }), +// } +// } + +// }) +// })