diff --git a/src/app/app.component.html b/src/app/app.component.html
index 46f646e..911bbe5 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,7 +1,13 @@
Tiramisu
-
-
+
+
+@if (login.isLoggedIn()) {
+
+
+
+} @else {
+
+}
-
-
\ No newline at end of file
+
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index bda1aaa..081b544 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -1,8 +1,10 @@
import { Component } from '@angular/core';
+import { MatButtonModule } from '@angular/material/button';
+import { MatMenuModule } from '@angular/material/menu';
import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
+import { DeliveryService } from './delivery.service';
+import { LoginService } from './login.service';
import { RecipeService } from './recipe.service';
-import { MatMenuModule } from '@angular/material/menu';
-import { MatButtonModule } from '@angular/material/button';
@Component({
selector: 'app-root',
@@ -10,11 +12,11 @@ import { MatButtonModule } from '@angular/material/button';
imports: [RouterOutlet, RouterLink, RouterLinkActive, MatMenuModule, MatButtonModule],
templateUrl: './app.component.html',
styleUrl: './app.component.css',
- providers: [RecipeService],
+ providers: [RecipeService, LoginService, DeliveryService],
})
export class AppComponent {
title = 'tiramisu';
- constructor(protected recipes: RecipeService) {
+ constructor(protected recipes: RecipeService, protected login: LoginService) {
}
}
diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts
index 1180ca1..72e5f71 100644
--- a/src/app/app.routes.ts
+++ b/src/app/app.routes.ts
@@ -1,6 +1,9 @@
import { inject } from '@angular/core';
import { CanActivateFn, Routes } from '@angular/router';
import { AuthComponent } from './auth/auth.component';
+import { DeliveryComponent } from './delivery/delivery.component';
+import { IngredientAddComponent } from './ingredient-add/ingredient-add.component';
+import { IngredientsComponent } from './ingredients/ingredients.component';
import { LoginService } from './login.service';
import { RecipeAddComponent } from './recipe-add/recipe-add.component';
import { RecipeComponent } from './recipe/recipe.component';
@@ -8,11 +11,14 @@ import { RecipesComponent } from './recipes/recipes.component';
const LoggedGuard: CanActivateFn = () => inject(LoginService).isLoggedIn();
export const routes: Routes = [
+ { path: '', component: DeliveryComponent, pathMatch: 'full' },
{ 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: 'ingredients', component: IngredientsComponent, canActivate: [LoggedGuard] },
+ { path: 'ingredients/add', component: IngredientAddComponent, canActivate: [LoggedGuard] },
+ { path: 'ingredients/:id/edit', component: IngredientAddComponent, canActivate: [LoggedGuard] },
{ path: 'login', component: AuthComponent },
{ path: 'logout', component: AuthComponent, data: { registering: false }, canActivate: [LoggedGuard] },
];
diff --git a/src/app/delivery.service.spec.ts b/src/app/delivery.service.spec.ts
new file mode 100644
index 0000000..cdbac5f
--- /dev/null
+++ b/src/app/delivery.service.spec.ts
@@ -0,0 +1,16 @@
+import { TestBed } from '@angular/core/testing';
+
+import { DeliveryService } from './delivery.service';
+
+describe('DeliveryService', () => {
+ let service: DeliveryService;
+
+ beforeEach(() => {
+ TestBed.configureTestingModule({});
+ service = TestBed.inject(DeliveryService);
+ });
+
+ it('should be created', () => {
+ expect(service).toBeTruthy();
+ });
+});
diff --git a/src/app/delivery.service.ts b/src/app/delivery.service.ts
new file mode 100644
index 0000000..2739d61
--- /dev/null
+++ b/src/app/delivery.service.ts
@@ -0,0 +1,22 @@
+import { Injectable } from '@angular/core';
+import { Recipe } from '../cookbook/type';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class DeliveryService {
+ readonly #shoppingCart: Recipe[];
+
+ constructor() {
+ this.#shoppingCart = JSON.parse(localStorage.getItem('shoppingCart') || '[]');
+ }
+
+ addToCart(recipe: Recipe): void {
+ this.#shoppingCart.push(recipe);
+ localStorage.setItem('shoppingCart', JSON.stringify(this.#shoppingCart));
+ }
+
+ get shoppingCart(): readonly Recipe[] {
+ return this.#shoppingCart;
+ }
+}
diff --git a/src/app/delivery/delivery.component.html b/src/app/delivery/delivery.component.html
new file mode 100644
index 0000000..49917af
--- /dev/null
+++ b/src/app/delivery/delivery.component.html
@@ -0,0 +1,13 @@
+
Commande en cours
+
+@for (item of delivery.shoppingCart; track item.id) {
+
+
![]()
+
+
{{item.name}}
+
+ {{item.description}}
+
+
+
+}
diff --git a/src/app/delivery/delivery.component.spec.ts b/src/app/delivery/delivery.component.spec.ts
new file mode 100644
index 0000000..1bca60d
--- /dev/null
+++ b/src/app/delivery/delivery.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { DeliveryComponent } from './delivery.component';
+
+describe('DeliveryComponent', () => {
+ let component: DeliveryComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [DeliveryComponent],
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(DeliveryComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/delivery/delivery.component.ts b/src/app/delivery/delivery.component.ts
new file mode 100644
index 0000000..8a0221e
--- /dev/null
+++ b/src/app/delivery/delivery.component.ts
@@ -0,0 +1,12 @@
+import { Component } from '@angular/core';
+import { DeliveryService } from '../delivery.service';
+
+@Component({
+ selector: 'app-delivery',
+ standalone: true,
+ imports: [],
+ templateUrl: './delivery.component.html',
+})
+export class DeliveryComponent {
+ constructor(protected delivery: DeliveryService) {}
+}
diff --git a/src/app/ingredient-add/ingredient-add.component.html b/src/app/ingredient-add/ingredient-add.component.html
new file mode 100644
index 0000000..2c7be28
--- /dev/null
+++ b/src/app/ingredient-add/ingredient-add.component.html
@@ -0,0 +1,15 @@
+
diff --git a/src/app/ingredient-add/ingredient-add.component.spec.ts b/src/app/ingredient-add/ingredient-add.component.spec.ts
new file mode 100644
index 0000000..57a6474
--- /dev/null
+++ b/src/app/ingredient-add/ingredient-add.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { IngredientAddComponent } from './ingredient-add.component';
+
+describe('IngredientAddComponent', () => {
+ let component: IngredientAddComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [IngredientAddComponent],
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(IngredientAddComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/ingredient-add/ingredient-add.component.ts b/src/app/ingredient-add/ingredient-add.component.ts
new file mode 100644
index 0000000..1954bd0
--- /dev/null
+++ b/src/app/ingredient-add/ingredient-add.component.ts
@@ -0,0 +1,63 @@
+import { Component, Input } from '@angular/core';
+import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
+import { MatButton } from '@angular/material/button';
+import { MatOption } from '@angular/material/core';
+import { MatError, MatFormField } from '@angular/material/form-field';
+import { MatInput } from '@angular/material/input';
+import { MatSelect } from '@angular/material/select';
+import { Router } from '@angular/router';
+import { RecipeService } from '../recipe.service';
+
+@Component({
+ selector: 'app-ingredient-add',
+ standalone: true,
+ imports: [
+ MatButton,
+ MatError,
+ MatFormField,
+ MatInput,
+ MatOption,
+ MatSelect,
+ ReactiveFormsModule,
+ ],
+ templateUrl: './ingredient-add.component.html',
+})
+export class IngredientAddComponent {
+ createForm = this.formBuilder.group({
+ name: '',
+ });
+
+ #ingredientId: number = -1;
+ @Input()
+ set id(recipeId: string) {
+ if (recipeId === undefined) return;
+ this.#ingredientId = parseInt(recipeId);
+ const ingredient = this.recipes.getIngredientById(this.#ingredientId);
+ if (ingredient === null) {
+ this.router.navigateByUrl('404');
+ return;
+ }
+ this.createForm.patchValue({
+ name: ingredient.name,
+ });
+ }
+ get ingredientId() {
+ return this.#ingredientId;
+ }
+
+ constructor(private formBuilder: FormBuilder, private recipes: RecipeService, private router: Router) {
+ }
+
+ onSubmit() {
+ if (this.createForm.invalid) {
+ return;
+ }
+ const value = this.createForm.value;
+ if (this.ingredientId !== -1) {
+ this.recipes.editIngredient({ id: this.ingredientId, name: value.name! });
+ } else {
+ this.recipes.addIngredient({ name: value.name! });
+ }
+ this.router.navigateByUrl('/ingredients');
+ }
+}
diff --git a/src/app/ingredients/ingredients.component.html b/src/app/ingredients/ingredients.component.html
new file mode 100644
index 0000000..20c1394
--- /dev/null
+++ b/src/app/ingredients/ingredients.component.html
@@ -0,0 +1,34 @@
+
+
+
+
+ id |
+
+ {{element.id}}
+ |
+
+
+
+ name |
+
+ {{element.name}}
+ |
+
+
+
+ actions |
+
+
+
+ |
+
+
+
+
+
+
+
+
+
diff --git a/src/app/ingredients/ingredients.component.spec.ts b/src/app/ingredients/ingredients.component.spec.ts
new file mode 100644
index 0000000..70dc120
--- /dev/null
+++ b/src/app/ingredients/ingredients.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { IngredientsComponent } from './ingredients.component';
+
+describe('IngredientsComponent', () => {
+ let component: IngredientsComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [IngredientsComponent],
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(IngredientsComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/src/app/ingredients/ingredients.component.ts b/src/app/ingredients/ingredients.component.ts
new file mode 100644
index 0000000..660c32d
--- /dev/null
+++ b/src/app/ingredients/ingredients.component.ts
@@ -0,0 +1,52 @@
+import { Component } from '@angular/core';
+import { MatButton } from '@angular/material/button';
+import { MatPaginator } from '@angular/material/paginator';
+import {
+ MatCell,
+ MatCellDef,
+ MatColumnDef,
+ MatHeaderCell,
+ MatHeaderCellDef,
+ MatHeaderRow,
+ MatHeaderRowDef,
+ MatRow,
+ MatRowDef,
+ MatTable,
+ MatTableDataSource,
+} from '@angular/material/table';
+import { RouterLink } from '@angular/router';
+import { Ingredient } from '../../cookbook/type';
+import { RecipeService } from '../recipe.service';
+
+@Component({
+ selector: 'app-ingredients',
+ standalone: true,
+ imports: [
+ MatButton,
+ MatCell,
+ MatCellDef,
+ MatColumnDef,
+ MatHeaderCell,
+ MatHeaderRow,
+ MatHeaderRowDef,
+ MatPaginator,
+ MatRow,
+ MatRowDef,
+ MatTable,
+ MatHeaderCellDef,
+ RouterLink,
+ ],
+ templateUrl: './ingredients.component.html',
+})
+export class IngredientsComponent {
+ displayedColumns: string[] = ['id', 'name', 'actions'];
+ dataSource = new MatTableDataSource();
+
+ constructor(protected recipes: RecipeService) {
+ this.dataSource = new MatTableDataSource(recipes.getAllIngredients());
+ }
+
+ delete(ingredient: Ingredient): void {
+ this.recipes.deleteIngredient(ingredient);
+ }
+}
diff --git a/src/app/recipe.service.ts b/src/app/recipe.service.ts
index eea5f4e..77b2f51 100644
--- a/src/app/recipe.service.ts
+++ b/src/app/recipe.service.ts
@@ -67,4 +67,28 @@ export class RecipeService {
}
}
}
+
+ addIngredient(ingredient: Omit) {
+ const id = this.#ingredients.length ? Math.max(...this.#ingredients.map((ingredient) => ingredient.id)) + 1 : 1;
+ this.#ingredients.push({
+ id,
+ ...ingredient,
+ });
+ }
+
+ editIngredient(ingredient: Ingredient) {
+ for (let i = 0; i < this.#ingredients.length; ++i) {
+ if (this.#ingredients[i].id === ingredient.id) {
+ this.#ingredients[i] = ingredient;
+ }
+ }
+ }
+
+ deleteIngredient(ingredient: Ingredient) {
+ const index = this.#ingredients.findIndex((v) => v.id === ingredient.id);
+ if (index === -1) {
+ return;
+ }
+ this.#ingredients.splice(index, 1);
+ }
}
diff --git a/src/app/recipe/recipe.component.ts b/src/app/recipe/recipe.component.ts
index d566f26..3496ff0 100644
--- a/src/app/recipe/recipe.component.ts
+++ b/src/app/recipe/recipe.component.ts
@@ -1,10 +1,10 @@
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';
import { MatButtonModule } from '@angular/material/button';
+import { MatIconModule } from '@angular/material/icon';
import { RouterLink } from '@angular/router';
+import { Recipe } from '../../cookbook/type';
+import { RecipeService } from '../recipe.service';
@Component({
selector: 'app-recipe',
diff --git a/src/app/recipes/recipes.component.html b/src/app/recipes/recipes.component.html
index d9e2334..13f9dab 100644
--- a/src/app/recipes/recipes.component.html
+++ b/src/app/recipes/recipes.component.html
@@ -1,10 +1,10 @@
-
+
id |
-
+ |
{{element.id}}
|
@@ -30,13 +30,18 @@
-
+
+ actions |
+
+
+
+ |
+
+
-
-
-
+
diff --git a/src/app/recipes/recipes.component.ts b/src/app/recipes/recipes.component.ts
index d400d66..58cf2d4 100644
--- a/src/app/recipes/recipes.component.ts
+++ b/src/app/recipes/recipes.component.ts
@@ -1,21 +1,23 @@
import { AfterViewInit, Component, ViewChild } from '@angular/core';
+import { MatButton } from '@angular/material/button';
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
import { RouterLink } from '@angular/router';
import { Recipe } from '../../cookbook/type';
+import { DeliveryService } from '../delivery.service';
import { RecipeService } from '../recipe.service';
@Component({
selector: 'app-recipes',
standalone: true,
- imports: [MatTableModule, MatPaginatorModule, RouterLink],
+ imports: [MatTableModule, MatPaginatorModule, RouterLink, MatButton],
templateUrl: './recipes.component.html',
})
export class RecipesComponent implements AfterViewInit {
- displayedColumns: string[] = ['id', 'name', 'description', 'image'];
+ displayedColumns: string[] = ['id', 'name', 'description', 'image', 'actions'];
dataSource = new MatTableDataSource();
- constructor(protected recipes: RecipeService) {
+ constructor(protected recipes: RecipeService, private delivery: DeliveryService) {
this.dataSource = new MatTableDataSource(recipes.getAll());
}
@@ -25,4 +27,8 @@ export class RecipesComponent implements AfterViewInit {
ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
}
+
+ deliver(recipe: Recipe): void {
+ this.delivery.addToCart(recipe);
+ }
}