diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
index 775fbbb..1180ca1 100644
--- a/src/app/app.routes.ts
+++ b/src/app/app.routes.ts
@@ -1,11 +1,18 @@
-import { Routes } from '@angular/router';
+import { inject } from '@angular/core';
+import { CanActivateFn, Routes } from '@angular/router';
+import { AuthComponent } from './auth/auth.component';
+import { LoginService } from './login.service';
import { RecipeAddComponent } from './recipe-add/recipe-add.component';
import { RecipeComponent } from './recipe/recipe.component';
import { RecipesComponent } from './recipes/recipes.component';
+const LoggedGuard: CanActivateFn = () => inject(LoginService).isLoggedIn();
export const routes: Routes = [
{ path: 'recipes', component: RecipesComponent },
{ path: 'recipe/add', component: RecipeAddComponent },
{ path: 'recipe/:id', component: RecipeComponent },
{ path: 'recipe/:id/edit', component: RecipeAddComponent },
+ { path: 'ingredients', component: RecipesComponent, canActivate: [LoggedGuard] },
+ { path: 'login', component: AuthComponent },
+ { path: 'logout', component: AuthComponent, data: { registering: false }, canActivate: [LoggedGuard] },
];
diff --git a/src/app/auth/auth.component.html b/src/app/auth/auth.component.html
new file mode 100644
index 0000000..135e858
--- /dev/null
+++ b/src/app/auth/auth.component.html
@@ -0,0 +1,19 @@
+
+ Login
+
+
+
+
diff --git a/src/app/auth/auth.component.spec.ts b/src/app/auth/auth.component.spec.ts
new file mode 100644
index 0000000..e597a45
--- /dev/null
+++ b/src/app/auth/auth.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AuthComponent } from './auth.component';
+
+describe('AuthComponent', () => {
+ let component: AuthComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [AuthComponent],
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(AuthComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/auth/auth.component.ts b/src/app/auth/auth.component.ts
new file mode 100644
index 0000000..7a3ca95
--- /dev/null
+++ b/src/app/auth/auth.component.ts
@@ -0,0 +1,48 @@
+import { Component } from '@angular/core';
+import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
+import { MatCard, MatCardContent, MatCardTitle } from '@angular/material/card';
+import { MatFormField } from '@angular/material/form-field';
+import { MatInput } from '@angular/material/input';
+import { ActivatedRoute, Router } from '@angular/router';
+import { LoginService } from '../login.service';
+
+@Component({
+ selector: 'app-auth',
+ standalone: true,
+ imports: [ReactiveFormsModule, MatCard, MatCardTitle, MatCardContent, MatFormField, MatInput],
+ templateUrl: './auth.component.html',
+})
+export class AuthComponent {
+ loginForm = this.formBuilder.group({
+ login: '',
+ password: '',
+ });
+
+ constructor(
+ private loginService: LoginService,
+ private formBuilder: FormBuilder,
+ private router: Router,
+ activatedRoute: ActivatedRoute,
+ ) {
+ activatedRoute.data.subscribe(({ registering }) => {
+ if (!registering) {
+ loginService.logOut();
+ }
+ });
+ }
+
+ onSubmit(): void {
+ if (this.loginForm.invalid) {
+ return;
+ }
+ const value = this.loginForm.value;
+ this.loginService.logIn(value.login!, value.password!)
+ .then((logged) => {
+ if (logged) {
+ this.router.navigateByUrl('/ingredients');
+ } else {
+ alert('Invalid login!');
+ }
+ });
+ }
+}
diff --git a/src/app/login.service.ts b/src/app/login.service.ts
new file mode 100644
index 0000000..c21beb0
--- /dev/null
+++ b/src/app/login.service.ts
@@ -0,0 +1,56 @@
+import { Injectable } from '@angular/core';
+import { User } from '../cookbook/type';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class LoginService {
+ async logIn(username: string, password: string): Promise {
+ const res = await fetch('https://dummyjson.com/user/login', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Accept': 'application/json',
+ },
+ body: JSON.stringify({
+ username,
+ password,
+ expiresInMins: 30,
+ }),
+ });
+ if (res.status !== 200) {
+ return false;
+ }
+ const user: User = await res.json();
+ localStorage.setItem('user', JSON.stringify(user));
+ return true;
+ }
+
+ me(): Promise {
+ const token = this.currentToken();
+ if (!token) {
+ return Promise.resolve(null);
+ }
+ return fetch('http://dummyjson.com/user/me', {
+ method: 'GET',
+ headers: {
+ 'Authorization': `Bearer ${token}`,
+ },
+ })
+ .then(res => res.json());
+ }
+
+ isLoggedIn(): boolean {
+ return this.currentToken() !== null;
+ }
+
+ currentToken(): string | null {
+ const json = localStorage?.getItem('user');
+ if (!json) return null;
+ return JSON.parse(json).token;
+ }
+
+ logOut(): void {
+ localStorage?.removeItem('user');
+ }
+}
diff --git a/src/app/recipe-add/recipe-add.component.ts b/src/app/recipe-add/recipe-add.component.ts
index 1e0e2d7..9e23cb2 100644
--- a/src/app/recipe-add/recipe-add.component.ts
+++ b/src/app/recipe-add/recipe-add.component.ts
@@ -1,18 +1,27 @@
import { Component, Input } from '@angular/core';
import { FormBuilder, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
-import { Router } from '@angular/router';
-import { Ingredient, IngredientEntry, Recipe } from '../../cookbook/type';
-import { RecipeService } from '../recipe.service';
-import { MatInputModule } from '@angular/material/input';
-import { MatFormFieldModule } from '@angular/material/form-field';
import { MatButton } from '@angular/material/button';
import { MatOption } from '@angular/material/core';
+import { MatFormFieldModule } from '@angular/material/form-field';
+import { MatInputModule } from '@angular/material/input';
import { MatSelect } from '@angular/material/select';
+import { Router } from '@angular/router';
+import { Ingredient, IngredientEntry, Recipe } from '../../cookbook/type';
+import { RecipeService } from '../recipe.service';
@Component({
selector: 'app-recipe-add',
standalone: true,
- imports: [ReactiveFormsModule, FormsModule, MatFormFieldModule, MatOption, MatSelect, MatInputModule, MatButton, MatFormFieldModule],
+ imports: [
+ ReactiveFormsModule,
+ FormsModule,
+ MatFormFieldModule,
+ MatOption,
+ MatSelect,
+ MatInputModule,
+ MatButton,
+ MatFormFieldModule,
+ ],
templateUrl: './recipe-add.component.html',
})
export class RecipeAddComponent {
@@ -28,7 +37,7 @@ export class RecipeAddComponent {
selectedFilename: string = '';
getIngredient(n: number): Ingredient {
- return this.ingredients.find(v => v.id === n)!
+ return this.ingredients.find(v => v.id === n)!;
}
#recipeId: number = -1;
@@ -98,9 +107,9 @@ export class RecipeAddComponent {
const reader = new FileReader();
reader.onload = (event) => {
this.createForm.patchValue({
- image: event.target!.result?.toString()
+ image: event.target!.result?.toString(),
});
- }
+ };
reader.readAsDataURL(file);
}
}
diff --git a/src/app/recipe.service.ts b/src/app/recipe.service.ts
index 4b40f6a..eea5f4e 100644
--- a/src/app/recipe.service.ts
+++ b/src/app/recipe.service.ts
@@ -6,10 +6,16 @@ import { Ingredient, Recipe } from '../cookbook/type';
})
export class RecipeService {
#recipes: Recipe[] = [
- { id: 0, name: 'crepe1', description: 'La meilleure recette de pâte à crêpes', image: '', ingredients: [
- {idIngredient:1,idRecipe:0,quantity:10},
- {idIngredient:2,idRecipe:0,quantity:15}
- ] },
+ {
+ id: 0,
+ name: 'crepe1',
+ description: 'La meilleure recette de pâte à crêpes',
+ image: '',
+ ingredients: [
+ { idIngredient: 1, idRecipe: 0, quantity: 10 },
+ { idIngredient: 2, idRecipe: 0, quantity: 15 },
+ ],
+ },
{ id: 1, name: 'crepe2', description: 'La meilleure recette de pâte à crêpes', image: '', ingredients: [] },
{ id: 2, name: 'crepe3', description: 'La meilleure recette de pâte à crêpes', image: '', ingredients: [] },
{ id: 3, name: 'crepe4', description: 'La meilleure recette de pâte à crêpes', image: '', ingredients: [] },
@@ -26,9 +32,9 @@ export class RecipeService {
];
#ingredients: Ingredient[] = [
- { id:1, name:'Sucre'},
- { id:2, name:'Farine'}
- ]
+ { id: 1, name: 'Sucre' },
+ { id: 2, name: 'Farine' },
+ ];
getAll(): Recipe[] {
return this.#recipes;
diff --git a/src/app/recipe/recipe.component.ts b/src/app/recipe/recipe.component.ts
index 4a54e03..d566f26 100644
--- a/src/app/recipe/recipe.component.ts
+++ b/src/app/recipe/recipe.component.ts
@@ -1,5 +1,5 @@
-import { Component, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
+import { Component, Input } from '@angular/core';
import { Recipe } from '../../cookbook/type';
import { RecipeService } from '../recipe.service';
import { MatIconModule } from '@angular/material/icon';
diff --git a/src/cookbook/type.ts b/src/cookbook/type.ts
index 7e12ef2..3003ec5 100644
--- a/src/cookbook/type.ts
+++ b/src/cookbook/type.ts
@@ -16,3 +16,9 @@ export type IngredientEntry = {
idRecipe: number;
quantity: number;
};
+
+export type User = {
+ username: string;
+ email: string;
+ token: string;
+};