Skip to content

Commit afb1815

Browse files
author
Renante D. Entera
committed
Course Project: Storing recipes via effects
1 parent 9e5ed84 commit afb1815

File tree

7 files changed

+104
-16
lines changed

7 files changed

+104
-16
lines changed

course-project/src/app/auth/store/auth.actions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export class AuthenticateSuccess implements Action {
1717
userId: string;
1818
token: string;
1919
expirationDate: Date;
20+
redirect: boolean;
2021
}
2122
) {}
2223
}

course-project/src/app/auth/store/auth.effects.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ const handleAuthentication = (
3333
email: email,
3434
userId: userId,
3535
token: token,
36-
expirationDate: expirationDate
36+
expirationDate: expirationDate,
37+
redirect: true
3738
});
3839
};
3940

@@ -125,8 +126,10 @@ export class AuthEffects {
125126
@Effect({ dispatch: false })
126127
authRedirect = this.actions$.pipe(
127128
ofType(AuthActions.AUTHENTICATE_SUCCESS),
128-
tap(() => {
129-
this.router.navigate(['/']);
129+
tap((authSuccessAction: AuthActions.AuthenticateSuccess) => {
130+
if (authSuccessAction.payload.redirect) {
131+
this.router.navigate(['/']);
132+
}
130133
})
131134
);
132135

@@ -161,7 +164,8 @@ export class AuthEffects {
161164
email: loadedUser.email,
162165
userId: loadedUser.id,
163166
token: loadedUser.token,
164-
expirationDate: new Date(userData._tokenExpirationDate)
167+
expirationDate: new Date(userData._tokenExpirationDate),
168+
redirect: false
165169
});
166170

167171
// const expirationDuration =

course-project/src/app/recipes/recipe-detail/recipe-detail.component.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { map, switchMap } from 'rxjs/operators';
66
import { Recipe } from '../recipe.model';
77
import { RecipeService } from '../recipe.service';
88
import * as fromApp from '../../store/app.reducer';
9+
import * as RecipesActions from '../store/recipe.actions';
910

1011
@Component({
1112
selector: 'app-recipe-detail',
@@ -54,7 +55,8 @@ export class RecipeDetailComponent implements OnInit {
5455
}
5556

5657
onDeleteRecipe() {
57-
this.recipeService.deleteRecipe(this.id);
58+
// this.recipeService.deleteRecipe(this.id);
59+
this.store.dispatch(new RecipesActions.DeleteRecipe(this.id));
5860
this.router.navigate(['/recipes']);
5961
}
6062
}

course-project/src/app/recipes/recipe-edit/recipe-edit.component.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,26 @@
1-
import { Component, OnInit } from '@angular/core';
1+
import { Component, OnInit, OnDestroy } from '@angular/core';
22
import { ActivatedRoute, Params, Router } from '@angular/router';
33
import { FormGroup, FormControl, FormArray, Validators } from '@angular/forms';
44
import { Store } from '@ngrx/store';
55
import { map } from 'rxjs/operators';
6+
import { Subscription } from 'rxjs';
67

78
import { RecipeService } from '../recipe.service';
89
import * as fromApp from '../../store/app.reducer';
10+
import * as RecipesActions from '../store/recipe.actions';
911

1012
@Component({
1113
selector: 'app-recipe-edit',
1214
templateUrl: './recipe-edit.component.html',
1315
styleUrls: ['./recipe-edit.component.css']
1416
})
15-
export class RecipeEditComponent implements OnInit {
17+
export class RecipeEditComponent implements OnInit, OnDestroy {
1618
id: number;
1719
editMode = false;
1820
recipeForm: FormGroup;
1921

22+
private storeSub: Subscription;
23+
2024
get ingredientsControls() {
2125
return (this.recipeForm.get('ingredients') as FormArray).controls;
2226
}
@@ -43,9 +47,16 @@ export class RecipeEditComponent implements OnInit {
4347
// this.recipeForm.value['imagePath'],
4448
// this.recipeForm.value['ingredients']);
4549
if (this.editMode) {
46-
this.recipeService.updateRecipe(this.id, this.recipeForm.value);
50+
// this.recipeService.updateRecipe(this.id, this.recipeForm.value);
51+
this.store.dispatch(
52+
new RecipesActions.UpdateRecipe({
53+
index: this.id,
54+
newRecipe: this.recipeForm.value
55+
})
56+
);
4757
} else {
48-
this.recipeService.addRecipe(this.recipeForm.value);
58+
// this.recipeService.addRecipe(this.recipeForm.value);
59+
this.store.dispatch(new RecipesActions.AddRecipe(this.recipeForm.value));
4960
}
5061
this.onCancel();
5162
}
@@ -70,6 +81,12 @@ export class RecipeEditComponent implements OnInit {
7081
this.router.navigate(['../'], { relativeTo: this.route });
7182
}
7283

84+
ngOnDestroy() {
85+
if (this.storeSub) {
86+
this.storeSub.unsubscribe();
87+
}
88+
}
89+
7390
private initForm() {
7491
let recipeName = '';
7592
let recipeImagePath = '';
@@ -78,7 +95,7 @@ export class RecipeEditComponent implements OnInit {
7895

7996
if (this.editMode) {
8097
// const recipe = this.recipeService.getRecipe(this.id);
81-
this.store
98+
this.storeSub = this.store
8299
.select('recipes')
83100
.pipe(
84101
map(recipeState => {

course-project/src/app/recipes/recipes-resolver.service.ts

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import {
66
} from '@angular/router';
77
import { Store } from '@ngrx/store';
88
import { Actions, ofType } from '@ngrx/effects';
9-
import { take } from 'rxjs/operators';
9+
import { take, map, switchMap } from 'rxjs/operators';
10+
import { of } from 'rxjs';
1011

1112
import { Recipe } from './recipe.model';
1213
import * as fromApp from '../store/app.reducer';
@@ -21,10 +22,22 @@ export class RecipesResolverService implements Resolve<Recipe[]> {
2122

2223
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
2324
// return this.dataStorageService.fetchRecipes();
24-
this.store.dispatch(new RecipesActions.FetchRecipes());
25-
return this.actions$.pipe(
26-
ofType(RecipesActions.SET_RECIPES),
27-
take(1)
25+
return this.store.select('recipes').pipe(
26+
take(1),
27+
map(recipesState => {
28+
return recipesState.recipes;
29+
}),
30+
switchMap(recipes => {
31+
if (recipes.length === 0) {
32+
this.store.dispatch(new RecipesActions.FetchRecipes());
33+
return this.actions$.pipe(
34+
ofType(RecipesActions.SET_RECIPES),
35+
take(1)
36+
);
37+
} else {
38+
return of(recipes);
39+
}
40+
})
2841
);
2942
}
3043
}

course-project/src/app/recipes/store/recipe.actions.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { Recipe } from '../recipe.model';
44

55
export const SET_RECIPES = '[Recipes] Set Recipes';
66
export const FETCH_RECIPES = '[Recipes] Fetch Recipes';
7+
export const ADD_RECIPE = '[Recipe] Add Recipe';
8+
export const UPDATE_RECIPE = '[Recipe] Update Recipe';
9+
export const DELETE_RECIPE = '[Recipe] Delete Recipe';
710

811
export class SetRecipes implements Action {
912
readonly type = SET_RECIPES;
@@ -15,4 +18,27 @@ export class FetchRecipes implements Action {
1518
readonly type = FETCH_RECIPES;
1619
}
1720

18-
export type RecipesActions = SetRecipes;
21+
export class AddRecipe implements Action {
22+
readonly type = ADD_RECIPE;
23+
24+
constructor(public payload: Recipe) {}
25+
}
26+
27+
export class UpdateRecipe implements Action {
28+
readonly type = UPDATE_RECIPE;
29+
30+
constructor(public payload: { index: number; newRecipe: Recipe }) {}
31+
}
32+
33+
export class DeleteRecipe implements Action {
34+
readonly type = DELETE_RECIPE;
35+
36+
constructor(public payload: number) {}
37+
}
38+
39+
export type RecipesActions =
40+
| SetRecipes
41+
| FetchRecipes
42+
| AddRecipe
43+
| UpdateRecipe
44+
| DeleteRecipe;

course-project/src/app/recipes/store/recipe.reducer.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,31 @@ export function recipeReducer(
1919
...state,
2020
recipes: [...action.payload]
2121
};
22+
case RecipesActions.ADD_RECIPE:
23+
return {
24+
...state,
25+
recipes: [...state.recipes, action.payload]
26+
};
27+
case RecipesActions.UPDATE_RECIPE:
28+
const updatedRecipe = {
29+
...state.recipes[action.payload.index],
30+
...action.payload.newRecipe
31+
};
32+
33+
const updatedRecipes = [...state.recipes];
34+
updatedRecipes[action.payload.index] = updatedRecipe;
35+
36+
return {
37+
...state,
38+
recipes: updatedRecipes
39+
};
40+
case RecipesActions.DELETE_RECIPE:
41+
return {
42+
...state,
43+
recipes: state.recipes.filter((recipe, index) => {
44+
return index !== action.payload;
45+
})
46+
};
2247
default:
2348
return state;
2449
}

0 commit comments

Comments
 (0)