Merge pull request 'formAdvanced' (#3) from formAdvanced into master
continuous-integration/drone/push Build is passing Details

Reviewed-on: #3
listIngredients
Corentin RICHARD 10 months ago
commit 62b1b37320

@ -1,3 +1,5 @@
import { Routes } from '@angular/router'; import { Routes } from '@angular/router';
import {AuthGuard} from "./guard.guard";
export const routes: Routes = []; export const routes: Routes = [
];

@ -62,10 +62,20 @@
</head> </head>
<body> <body>
<div class="navbar"> <div class="navbar">
<a href="#home">Accueil</a> <div *ngIf="isLogged()">
<a href="#recipes">Recettes</a> <a href="" (click)="onClickLogout($event)">Logout</a>
<a href="#about">À Propos</a> </div>
<a href="#contact">Contact</a> <div *ngIf="!isLogged()">
<a href="" (click)="onClickLogin($event)">Login</a>
</div>
<div *ngFor="let link of links">
<a routerLink="/{{link.$link}}" routerLinkActive="active" ariaCurrentWhenActive="page">{{link.$name}}</a>
</div>
<!-- <a href="#home">Accueil</a>-->
<!-- <a href="#recipes">Recettes</a>-->
<!-- <a href="#about">À Propos</a>-->
<!-- <a href="#contact">Contact</a>-->
</div> </div>
<div class="content" [class.show-form]="isFormVisible"> <div class="content" [class.show-form]="isFormVisible">

@ -3,21 +3,35 @@ import {RecipeListComponent} from "../recipe-list/recipe-list.component";
import {RecipeFormComponent} from "../recipe-form/recipe-form.component"; import {RecipeFormComponent} from "../recipe-form/recipe-form.component";
import {Recipe} from "../../model/recipe.model"; import {Recipe} from "../../model/recipe.model";
import {RecipeService} from "../../service/recipe.service"; import {RecipeService} from "../../service/recipe.service";
import {NgIf} from "@angular/common"; import {NgForOf, NgIf} from "@angular/common";
import {LinkService} from "../../service/link.service";
import {Link} from "../../model/link.model";
import {LoginService} from "../../service/login.service";
import {RouterLink, RouterLinkActive,RouterOutlet} from "@angular/router";
import {CommonModule} from "@angular/common";
@Component({ @Component({
selector: 'app-accueil', selector: 'app-accueil',
standalone: true, standalone: true,
imports: [ imports: [
RecipeListComponent, RecipeListComponent,
RecipeFormComponent, RecipeFormComponent,
NgIf CommonModule,
NgForOf,
RouterLink,
RouterOutlet,
RouterLinkActive
], ],
templateUrl: './accueil.component.html' templateUrl: './accueil.component.html'
}) })
export class AccueilComponent { export class AccueilComponent {
isFormVisible: boolean = false; isFormVisible: boolean = false;
links: Link[] = this.linkService.getLinks()
constructor(private recipeService: RecipeService,private linkService: LinkService,private loginService: LoginService) {
}
constructor(private recipeService: RecipeService){}
onRecipeSubmitted(recipe : Recipe){ onRecipeSubmitted(recipe : Recipe){
this.recipeService.addRecipe(recipe); this.recipeService.addRecipe(recipe);
@ -26,4 +40,19 @@ export class AccueilComponent {
toggleForm() { toggleForm() {
this.isFormVisible = !this.isFormVisible; this.isFormVisible = !this.isFormVisible;
} }
onClickLogin(event: Event): void {
event.preventDefault(); // Prevent the default anchor behavior
this.loginService.login();
}
onClickLogout(event: Event): void {
event.preventDefault(); // Prevent the default anchor behavior
this.loginService.logout();
}
isLogged(): boolean {
return this.loginService.isLogged();
}
} }

@ -2,12 +2,32 @@
<label for="id">ID: </label> <label for="id">ID: </label>
<input id="id" type="number" formControlName="id"> <input id="id" type="number" formControlName="id">
<label for="name">name: </label> <label for="name">Name: </label>
<input id="name" type="text" formControlName="name"> <input id="name" type="text" formControlName="name">
<label for="description">description: </label> <label for="description">Description: </label>
<input id="description" type="text" formControlName="description"> <input id="description" type="text" formControlName="description">
<div formArrayName="ingredients">
<div *ngFor="let ingredient of ingredients.controls; let i=index" [formGroupName]="i">
<label for="ingredient-quantity">Quantity:</label>
<input id="ingredient-quantity" type="number" formControlName="quantity">
<label for="ingredient-unit">Unit:</label>
<select id="ingredient-unit" formControlName="unit">
<option *ngFor="let unit of unity" [value]="unit">{{ unit }}</option>
</select>
<label for="ingredient-name">Ingredient:</label>
<select id="ingredient-name" formControlName="ingredient">
<option *ngFor="let ingredient of ingredientsList" [value]="ingredient.$name">{{ ingredient.$name }}</option>
</select>
<button type="button" (click)="removeIngredient(i)">Remove</button>
</div>
</div>
<button type="button" (click)="addIngredient()">Add Ingredient</button>
<p>Complete the form to enable the button.</p> <p>Complete the form to enable the button.</p>
<button type="submit" [disabled]="!recipeForm.valid">Submit</button> <button type="submit" [disabled]="!recipeForm.valid">Submit</button>

@ -1,24 +1,55 @@
import {Component, EventEmitter, Output} from '@angular/core'; import {Component, EventEmitter, Output} from '@angular/core';
import {Recipe} from "../../model/recipe.model"; import {Recipe} from "../../model/recipe.model";
import {FormControl, FormGroup, ReactiveFormsModule} from "@angular/forms"; import {FormControl, FormGroup, ReactiveFormsModule, FormArray, FormBuilder} from "@angular/forms";
import { Ingredient } from '../../model/ingredient.model';
import { Unity } from '../../model/unity';
import { IngredientService } from '../../service/ingredient.service';
import {NgFor} from "@angular/common";
@Component({ @Component({
selector: 'app-recipe-form', selector: 'app-recipe-form',
standalone: true, standalone: true,
imports: [ReactiveFormsModule], imports: [ReactiveFormsModule,NgFor],
templateUrl: './recipe-form.component.html', templateUrl: './recipe-form.component.html',
styleUrl: './recipe-form.component.css' styleUrl: './recipe-form.component.css'
}) })
export class RecipeFormComponent { export class RecipeFormComponent {
@Output() formSubmitted = new EventEmitter<Recipe>(); @Output() formSubmitted = new EventEmitter<Recipe>();
ingredientsList: Ingredient[] = [];
unity = Object.values(Unity);
constructor(private formBuilder: FormBuilder, private ingredientService : IngredientService){}
recipeForm = new FormGroup({ ngOnInit(): void {
this.ingredientService.getAll().subscribe(ingredients => {
this.ingredientsList = ingredients;
});
}
recipeForm: FormGroup = this.formBuilder.group({
id: new FormControl('', { nonNullable: true }), id: new FormControl('', { nonNullable: true }),
name: new FormControl('', { nonNullable: true }), name: new FormControl('', { nonNullable: true }),
description: new FormControl('', { nonNullable: true }), description: new FormControl('', { nonNullable: true }),
ingredients: this.formBuilder.array([])
});
get ingredients():FormArray{
return this.recipeForm.get('ingredients') as FormArray;
}
newIngredient(): FormGroup{
return this.formBuilder.group({
quantity: new FormControl(0, { nonNullable: true }),
unit: new FormControl('', { nonNullable: true }),
ingredient: new FormControl('', { nonNullable: true })
}); });
}
addIngredient() {
this.ingredients.push(this.newIngredient());
}
removeIngredient(index: number) {
this.ingredients.removeAt(index);
}
onSubmit() { onSubmit() {
if(this.recipeForm.valid){ if(this.recipeForm.valid){
@ -27,11 +58,18 @@ export class RecipeFormComponent {
$name: this.recipeForm.value.name!, $name: this.recipeForm.value.name!,
$description: this.recipeForm.value.description!, $description: this.recipeForm.value.description!,
$createdAt: new Date(), $createdAt: new Date(),
$ingredients: [] $ingredients: this.recipeForm.value.ingredients!.map((ingredient : any) => ({
quantity: ingredient.quantity,
unit: ingredient.unit,
ingredient: this.ingredientsList.find(ing => ing.$name === ingredient.ingredient)
}))
}; };
this.formSubmitted.emit(recipe); this.formSubmitted.emit(recipe);
this.recipeForm.reset() this.recipeForm.reset()
this.ingredients.clear()
} }
} }
} }

@ -1,6 +1,6 @@
import {Link} from "../model/link.model"; import {Link} from "../model/link.model";
export var LINKS :Link[] = [ export var LINKS :Link[] = [
{$name:"Lien1",$link:"Lien1"}, {$name:"Accueil",$link:""},
{$name:"Lien2",$link:'Lien2'} {$name:"Ingredients",$link:"/ingredients"}
] ]

@ -0,0 +1,17 @@
import {CanActivateFn, Router} from '@angular/router';
import {LoginService} from "./service/login.service";
import {inject} from "@angular/core";
export const AuthGuard: CanActivateFn = (route, state) => {
const auth = inject(LoginService)
const router = inject(Router);
if(!auth.isLogged()){
router.navigateByUrl('/login');
auth.login();
return false;
}
auth.logout();
return true;
};

@ -1,6 +1,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import {Ingredient} from "../model/ingredient.model"; import {Ingredient} from "../model/ingredient.model";
import {$INGREDIENTS} from "../data/ingredient.stub"; import {$INGREDIENTS} from "../data/ingredient.stub";
import {Observable, of} from "rxjs";
@Injectable({ @Injectable({
@ -8,9 +9,7 @@ import {$INGREDIENTS} from "../data/ingredient.stub";
}) })
export class IngredientService { export class IngredientService {
constructor() { } getAll() : Observable<Ingredient[]> {
return of($INGREDIENTS);
getAll() : Ingredient[] {
return $INGREDIENTS;
} }
} }

@ -0,0 +1,20 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class LoginService {
login(): void {
localStorage.setItem('login', 'true');
}
logout(): void {
localStorage.setItem('login', 'false');
}
isLogged(): boolean {
const login = localStorage.getItem('login');
return login === 'true';
}
}

@ -1,5 +1,5 @@
import { TestBed } from '@angular/core/testing'; import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component'; import { AppComponent } from '../../app/app.component';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(async () => { beforeEach(async () => {

@ -0,0 +1,17 @@
import { TestBed } from '@angular/core/testing';
import { CanActivateFn } from '@angular/router';
import { AuthGuard } from '../../app/guard.guard';
describe('guardGuard', () => {
const executeGuard: CanActivateFn = (...guardParameters) =>
TestBed.runInInjectionContext(() => AuthGuard(...guardParameters));
beforeEach(() => {
TestBed.configureTestingModule({});
});
it('should be created', () => {
expect(executeGuard).toBeTruthy();
});
});

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { LoginService } from '../../app/service/login.service';
describe('LoginService', () => {
let service: LoginService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(LoginService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
Loading…
Cancel
Save