diff --git a/src/app/app.component.html b/src/app/app.component.html index 3d6e0b2..8998fba 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,12 +1,12 @@ {{ 'title' | transloco }} + {{ 'cart'}} {{ 'logout' | transloco }} {{ 'login' | transloco }} - {{ 'recipe.add.link' | transloco }} 🇬🇧 🇫🇷 diff --git a/src/app/app.config.ts b/src/app/app.config.ts index f666980..52e8f4b 100644 --- a/src/app/app.config.ts +++ b/src/app/app.config.ts @@ -6,6 +6,8 @@ import { routes } from './app.routes'; import { provideHttpClient } from '@angular/common/http'; import { TranslocoHttpLoader } from './transloco-loader'; import { provideTransloco } from '@jsverse/transloco'; +import { withFetch } from '@angular/common/http'; + export const appConfig: ApplicationConfig = { providers: [ @@ -21,6 +23,9 @@ export const appConfig: ApplicationConfig = { } ), provideAnimations(), + provideHttpClient( + withFetch(), + ), ] }; diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 64fc0f6..574f5ac 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -8,12 +8,14 @@ import { LoginComponent } from './components/login/login.component'; import { IngredientListComponent } from './components/ingredient-list/ingredient-list.component'; import { LogoutComponent } from './components/logout/logout.component'; import { AuthGuard } from './auth.guard'; +import { SavedRecipeComponent } from './components/saved-recipe/saved-recipe.component'; export const routes: Routes = [ { path: '', component: RecipeListComponent }, { path: 'error/:status', component: Error404Component}, { path: 'recipe/add', component: RecipeFormComponent}, + { path: 'cart', component: SavedRecipeComponent}, { path: 'recipe/:id', component: RecipeDetailComponent}, { path: 'ingredients', component: IngredientListComponent, canActivate: [AuthGuard] }, { path: 'login', component: LoginComponent }, diff --git a/src/app/components/ingredient-list/ingredient-list.component.html b/src/app/components/ingredient-list/ingredient-list.component.html index 66f9a52..b4ac319 100644 --- a/src/app/components/ingredient-list/ingredient-list.component.html +++ b/src/app/components/ingredient-list/ingredient-list.component.html @@ -1 +1,37 @@ ingredient-list works! + + + ----------- + {{ ingre.name}} + Description: {{ ingre.description}} + Modifier + + + + + + Ajouter un ingrédient + + Nom: + + + + Description: + + + Ajouter + + + + Modifier l'ingrédient + + Nom: + + + + Description: + + + Enregistrer + Annuler + diff --git a/src/app/components/ingredient-list/ingredient-list.component.ts b/src/app/components/ingredient-list/ingredient-list.component.ts index a6d92dd..cdd3a31 100644 --- a/src/app/components/ingredient-list/ingredient-list.component.ts +++ b/src/app/components/ingredient-list/ingredient-list.component.ts @@ -1,12 +1,54 @@ import { Component } from '@angular/core'; +import { Ingredient } from '../../model/ingredient.model'; +import { IngredientService } from '../../services/ingredient.service'; +import { OnInit } from '@angular/core'; +import { NgFor, NgIf } from '@angular/common'; +import { FormsModule } from '@angular/forms'; @Component({ selector: 'app-ingredient-list', standalone: true, - imports: [], + imports: [NgIf, NgFor, FormsModule], + providers: [], templateUrl: './ingredient-list.component.html', styleUrl: './ingredient-list.component.css' }) export class IngredientListComponent { + public ingredients! : Ingredient[]; + newIngredient: Ingredient = { id: 0, name: '', description: '', qty: 0 }; + editIngredient: Ingredient | null = null; + constructor(private serviceIngredient : IngredientService){} + + ngOnInit(): void + { + this.serviceIngredient.getIngredient().subscribe(ingredients => { + this.ingredients = ingredients; + }); + } + + edit(ingre: Ingredient){ + this.editIngredient = ingre; + } + + addIngredient() { + this.serviceIngredient.add(this.newIngredient).subscribe(ingredient => { + this.ingredients.push(ingredient); + this.newIngredient = { id: 0, name: '', description: '', qty: 0} + }); + } + + updateIngredient() { + if (this.editIngredient) { + this.serviceIngredient.update(this.editIngredient).subscribe(updatedIngredient => { + const index = this.ingredients.findIndex(i => i.id === updatedIngredient.id); + this.ingredients[index] = updatedIngredient; + this.editIngredient = null; + }); + } + } + + cancelEdit() { + this.editIngredient = null; + } } diff --git a/src/app/components/recipe-form/recipe-form.component.html b/src/app/components/recipe-form/recipe-form.component.html index 9906ef3..ebbf284 100644 --- a/src/app/components/recipe-form/recipe-form.component.html +++ b/src/app/components/recipe-form/recipe-form.component.html @@ -28,7 +28,7 @@ {{ 'recipe.ingredients' | transloco }} @for (ingredient of ingredientsOptions; track ingredient) { - {{ ingredient }} + {{ ingredient.name }} } @@ -44,4 +44,4 @@ {{ 'recipe.add.button-recipe' | transloco }} - \ No newline at end of file + diff --git a/src/app/components/recipe-form/recipe-form.component.ts b/src/app/components/recipe-form/recipe-form.component.ts index 75808e8..ad94715 100644 --- a/src/app/components/recipe-form/recipe-form.component.ts +++ b/src/app/components/recipe-form/recipe-form.component.ts @@ -1,17 +1,18 @@ import { Component } from '@angular/core'; import { FormArray, FormBuilder, FormGroup, Validators } from '@angular/forms'; import { Recipe } from '../../model/recipe.model'; -import { Ingredient } from '../../model/ingredient.model'; import { CommonModule } from '@angular/common'; import { ReactiveFormsModule } from '@angular/forms'; import { RecipeService } from '../../services/recipe.service'; import { TranslocoPipe } from '@jsverse/transloco'; +import { Ingredient } from '../../model/ingredient.model'; import { MatFormFieldModule } from '@angular/material/form-field'; import { MatInputModule } from '@angular/material/input'; import { MatButtonModule } from '@angular/material/button'; import { MatSelectModule} from '@angular/material/select'; import { Router } from '@angular/router'; +import { IngredientService } from '../../services/ingredient.service'; @Component({ selector: 'app-recipe-form', @@ -32,17 +33,20 @@ import { Router } from '@angular/router'; export class RecipeFormComponent { recipeForm: FormGroup; base64Image: string | ArrayBuffer | null = null; - ingredientsOptions = ['Champignon', 'Tomata', 'Mozarella']; - defaultOption: string = this.ingredientsOptions[2]; + ingredientsOptions! : Ingredient[]; + defaultOption: string = 'Veuillez choisir'; filename: string = ''; - constructor(private fb: FormBuilder, private recipeService: RecipeService, private router: Router) { + constructor(private fb: FormBuilder, private recipeService: RecipeService, private router: Router,private serviceIngredients: IngredientService) { this.recipeForm = this.fb.group({ name: ['', Validators.required], description: ['', Validators.required], image: ['', Validators.required], ingredients: this.fb.array([]), }); + this.serviceIngredients.getIngredient().subscribe(ingredients => { + this.ingredientsOptions = ingredients; + }); } get ingredients(): FormArray { diff --git a/src/app/components/recipe-list/recipe-list.component.css b/src/app/components/recipe-list/recipe-list.component.css index b03bd50..01bf281 100644 --- a/src/app/components/recipe-list/recipe-list.component.css +++ b/src/app/components/recipe-list/recipe-list.component.css @@ -7,4 +7,31 @@ .pagination { font-size: 1.2rem; -} \ No newline at end of file +} + +.plus-button { + position: fixed; + bottom: 20px; + right: 20px; + width: 50px; + height: 50px; + background-color: #28a745; + color: white; + border-radius: 50%; + text-align: center; + line-height: 50px; + font-size: 24px; + text-decoration: none; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2); + transition: background-color 0.3s ease; + z-index: 1000; /* Assure que le bouton est au-dessus des autres éléments */ +} + +.plus-button:hover { + background-color: #218838; +} + +.plus-button:active { + background-color: #1e7e34; +} + diff --git a/src/app/components/recipe-list/recipe-list.component.html b/src/app/components/recipe-list/recipe-list.component.html index 9fbcf83..5a5dc89 100644 --- a/src/app/components/recipe-list/recipe-list.component.html +++ b/src/app/components/recipe-list/recipe-list.component.html @@ -2,9 +2,10 @@ - ++ + - \ No newline at end of file + diff --git a/src/app/components/recipe-list/recipe-list.component.ts b/src/app/components/recipe-list/recipe-list.component.ts index 12fb04e..43e9b61 100644 --- a/src/app/components/recipe-list/recipe-list.component.ts +++ b/src/app/components/recipe-list/recipe-list.component.ts @@ -5,11 +5,12 @@ import { NgFor } from '@angular/common'; import { RecipeMiniComponent } from '../recipe-mini/recipe-mini.component'; import { TranslocoPipe } from '@jsverse/transloco'; import { MatPaginatorModule, PageEvent} from '@angular/material/paginator'; +import { RouterLink } from '@angular/router'; @Component({ selector: 'app-recipe-list', standalone: true, - imports: [NgFor, RecipeMiniComponent, TranslocoPipe, MatPaginatorModule], + imports: [NgFor, RecipeMiniComponent, TranslocoPipe, MatPaginatorModule, RouterLink], templateUrl: './recipe-list.component.html', styleUrl: './recipe-list.component.css' }) diff --git a/src/app/components/recipe-mini/recipe-mini.component.css b/src/app/components/recipe-mini/recipe-mini.component.css index b5beed0..6c0b324 100644 --- a/src/app/components/recipe-mini/recipe-mini.component.css +++ b/src/app/components/recipe-mini/recipe-mini.component.css @@ -143,4 +143,4 @@ button:hover i::after { 100% { box-shadow: #27272c; } -} \ No newline at end of file +} diff --git a/src/app/components/recipe-mini/recipe-mini.component.html b/src/app/components/recipe-mini/recipe-mini.component.html index b3ffb2b..a8637d6 100644 --- a/src/app/components/recipe-mini/recipe-mini.component.html +++ b/src/app/components/recipe-mini/recipe-mini.component.html @@ -7,5 +7,6 @@ {{ recipe.name }} {{ recipe.description | truncate:50:false }} {{ 'recipe.see' | transloco }} + Add Recipe to cart - \ No newline at end of file + diff --git a/src/app/components/recipe-mini/recipe-mini.component.ts b/src/app/components/recipe-mini/recipe-mini.component.ts index 9c08115..9a7595d 100644 --- a/src/app/components/recipe-mini/recipe-mini.component.ts +++ b/src/app/components/recipe-mini/recipe-mini.component.ts @@ -4,6 +4,7 @@ import { Input } from '@angular/core'; import { TruncatePipe } from '../../pipes/truncate.pipe'; import { TranslocoPipe } from '@jsverse/transloco'; import { RouterModule } from '@angular/router'; +import { CommandeService } from '../../services/commandes.service'; @Component({ selector: 'app-recipe-mini', @@ -15,7 +16,10 @@ import { RouterModule } from '@angular/router'; export class RecipeMiniComponent { @Input() recipe!: Recipe; - navigateToRecipe(){ - console.log("TODO"); + constructor(protected serviceCommande: CommandeService){} + + addRecipe(recipe: Recipe) + { + this.serviceCommande.addRecipe(recipe); } } diff --git a/src/app/components/saved-recipe/saved-recipe.component.css b/src/app/components/saved-recipe/saved-recipe.component.css new file mode 100644 index 0000000..7a5f6f8 --- /dev/null +++ b/src/app/components/saved-recipe/saved-recipe.component.css @@ -0,0 +1,21 @@ +.button { + display: inline-block; + padding: 10px 20px; + font-size: 16px; + color: white; + background-color: #007BFF; + text-align: center; + text-decoration: none; + border-radius: 5px; + border: none; + cursor: pointer; + transition: background-color 0.3s ease; +} + +.button:hover { + background-color: #0056b3; +} + +.button:active { + background-color: #004085; +} diff --git a/src/app/components/saved-recipe/saved-recipe.component.html b/src/app/components/saved-recipe/saved-recipe.component.html new file mode 100644 index 0000000..b140ec8 --- /dev/null +++ b/src/app/components/saved-recipe/saved-recipe.component.html @@ -0,0 +1,4 @@ + + + Clear recipes + diff --git a/src/app/components/saved-recipe/saved-recipe.component.spec.ts b/src/app/components/saved-recipe/saved-recipe.component.spec.ts new file mode 100644 index 0000000..224a10a --- /dev/null +++ b/src/app/components/saved-recipe/saved-recipe.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { SavedRecipeComponent } from './saved-recipe.component'; + +describe('SavedRecipeComponent', () => { + let component: SavedRecipeComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [SavedRecipeComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(SavedRecipeComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/saved-recipe/saved-recipe.component.ts b/src/app/components/saved-recipe/saved-recipe.component.ts new file mode 100644 index 0000000..7220d75 --- /dev/null +++ b/src/app/components/saved-recipe/saved-recipe.component.ts @@ -0,0 +1,29 @@ +import { Component } from '@angular/core'; +import { CommandeService } from '../../services/commandes.service'; +import { OnInit } from '@angular/core'; +import { Recipe } from '../../model/recipe.model'; +import { NgFor, NgIf } from '@angular/common'; +import { RecipeMiniComponent } from '../recipe-mini/recipe-mini.component'; + + +@Component({ + selector: 'app-saved-recipe', + standalone: true, + imports: [NgIf, NgFor, RecipeMiniComponent], + templateUrl: './saved-recipe.component.html', + styleUrl: './saved-recipe.component.css' +}) +export class SavedRecipeComponent { + public commandes?: Recipe[]; + + constructor(private serviceCommande : CommandeService){} + + ngOnInit(){ + this.commandes = this.serviceCommande.getRecipe(); + } + + deleteCart(){ + this.commandes = []; + this.serviceCommande.clearRecipes(); + } +} diff --git a/src/app/model/ingredient.model.ts b/src/app/model/ingredient.model.ts index 6421c10..947f9fd 100644 --- a/src/app/model/ingredient.model.ts +++ b/src/app/model/ingredient.model.ts @@ -2,4 +2,5 @@ export interface Ingredient{ id: number; name: string; qty: number; + description: string; } diff --git a/src/app/services/commandes.service.ts b/src/app/services/commandes.service.ts new file mode 100644 index 0000000..4b15c9c --- /dev/null +++ b/src/app/services/commandes.service.ts @@ -0,0 +1,38 @@ +import { Injectable } from "@angular/core"; +import { Recipe } from "../model/recipe.model"; +@Injectable({ + providedIn: 'root' +}) +export class CommandeService { + private commande: Recipe[] = []; + private localStorageKey = 'commande'; + + constructor(){ + console.log(this.commande); + } + + getRecipeById(id: number) { + return this.commande.find(e => e.id === id); + } + + // Get recipes from local storage + getRecipe(): Recipe[] { + const recipesJson = localStorage.getItem(this.localStorageKey) || "[]"; + this.commande = JSON.parse(recipesJson) || []; + return this.commande; + } + + // Add a new recipe + addRecipe(recipe: Recipe): number { + this.getRecipe(); + recipe.id = this.commande.length + let newId = this.commande.push(recipe); + localStorage.setItem(this.localStorageKey, JSON.stringify(this.commande)); + return newId; + } + + // Clear all recipes (for example, if needed) + clearRecipes(): void { + localStorage.removeItem(this.localStorageKey); + } +} diff --git a/src/app/services/ingredient.service.ts b/src/app/services/ingredient.service.ts new file mode 100644 index 0000000..c421e46 --- /dev/null +++ b/src/app/services/ingredient.service.ts @@ -0,0 +1,25 @@ +import { Injectable } from "@angular/core"; +import { Ingredient } from "../model/ingredient.model"; +import { HttpClient } from "@angular/common/http"; +import { Observable } from "rxjs"; + +@Injectable({ + providedIn: 'root' +}) +export class IngredientService { + private path:string = "https://664ba07f35bbda10987d9f99.mockapi.io/api/ingredients"; + + constructor(private http: HttpClient) { } + + getIngredient() : Observable{ + return this.http.get(this.path); + } + + add(ingredient: Ingredient): Observable { + return this.http.post(this.path, ingredient); + } + + update(ingredient: Ingredient): Observable { + return this.http.put(`${this.path}/${ingredient.id}`, ingredient); + } +}
ingredient-list works!
-----------
{{ ingre.name}}
Description: {{ ingre.description}}
Modifier
{{ recipe.description | truncate:50:false }}