Compare commits
No commits in common. '571df652d6a90a335880116987bd30524469b935' and 'af6efdbbb64ad8c1b44e4bf08122e24dd29504f0' have entirely different histories.
571df652d6
...
af6efdbbb6
@ -1,45 +0,0 @@
|
|||||||
// @ts-check
|
|
||||||
const eslint = require('@eslint/js');
|
|
||||||
const tseslint = require('typescript-eslint');
|
|
||||||
const angular = require('angular-eslint');
|
|
||||||
|
|
||||||
module.exports = tseslint.config(
|
|
||||||
{
|
|
||||||
files: ['**/*.ts'],
|
|
||||||
extends: [
|
|
||||||
eslint.configs.recommended,
|
|
||||||
...tseslint.configs.recommended,
|
|
||||||
...tseslint.configs.stylistic,
|
|
||||||
...angular.configs.tsRecommended,
|
|
||||||
],
|
|
||||||
processor: angular.processInlineTemplates,
|
|
||||||
rules: {
|
|
||||||
'@angular-eslint/directive-selector': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
type: 'attribute',
|
|
||||||
prefix: 'app',
|
|
||||||
style: 'camelCase',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'@angular-eslint/component-selector': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
type: 'element',
|
|
||||||
prefix: 'app',
|
|
||||||
style: 'kebab-case',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'@typescript-eslint/no-inferrable-types': 'off',
|
|
||||||
'@typescript-eslint/consistent-type-definitions': 'off',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
files: ['**/*.html'],
|
|
||||||
extends: [
|
|
||||||
...angular.configs.templateRecommended,
|
|
||||||
...angular.configs.templateAccessibility,
|
|
||||||
],
|
|
||||||
rules: {},
|
|
||||||
},
|
|
||||||
);
|
|
File diff suppressed because it is too large
Load Diff
@ -1,13 +1,7 @@
|
|||||||
Tiramisu
|
Tiramisu
|
||||||
|
|
||||||
<button mat-button routerLink="/recipes">Les recettes</button>
|
<button mat-button [routerLink]="['/recipes']">Les recettes</button>
|
||||||
<button mat-button routerLink="/recipe/add">Ajout recette</button>
|
<button mat-button [routerLink]="['/recipe/add']">Ajout recette</button>
|
||||||
@if (login.isLoggedIn()) {
|
|
||||||
<button mat-button routerLink="/ingredients">Ingrédients</button>
|
|
||||||
<button mat-button routerLink="/ingredients/add">Ajout ingrédient</button>
|
|
||||||
<button mat-button routerLink="/logout">Déconnexion</button>
|
|
||||||
} @else {
|
|
||||||
<button mat-button routerLink="/login">Connexion</button>
|
|
||||||
}
|
|
||||||
|
|
||||||
<router-outlet></router-outlet>
|
|
||||||
|
<router-outlet></router-outlet>
|
@ -1,16 +0,0 @@
|
|||||||
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();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,22 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
<h3>Commande en cours</h3>
|
|
||||||
|
|
||||||
@for (item of delivery.shoppingCart; track item.id) {
|
|
||||||
<div class="container">
|
|
||||||
<img [src]="item.image || 'https://placehold.co/200x200'" [alt]="item.image ? item.name : ''" width="200" height="200">
|
|
||||||
<div class="container_text">
|
|
||||||
<h1>{{item.name}}</h1>
|
|
||||||
<p>
|
|
||||||
{{item.description}}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { DeliveryComponent } from './delivery.component';
|
|
||||||
|
|
||||||
describe('DeliveryComponent', () => {
|
|
||||||
let component: DeliveryComponent;
|
|
||||||
let fixture: ComponentFixture<DeliveryComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
imports: [DeliveryComponent],
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(DeliveryComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,12 +0,0 @@
|
|||||||
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) {}
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
<form [formGroup]="createForm" (ngSubmit)="onSubmit()">
|
|
||||||
<div>
|
|
||||||
<mat-form-field>
|
|
||||||
<label for="name">Nom</label>
|
|
||||||
<input matInput id="name" type="text" formControlName="name" required>
|
|
||||||
@if (createForm.controls.name.errors?.['minlength']) {
|
|
||||||
<mat-error>Le nom doit contenir au moins {{ createForm.controls.name.errors!['minlength'].requiredLength }} caractères.</mat-error>
|
|
||||||
}
|
|
||||||
@if (createForm.controls.name.errors?.['maxlength']) {
|
|
||||||
<mat-error>Le nom ne peut dépasser {{ createForm.controls.name.errors!['maxlength'].requiredLength }} caractères.</mat-error>
|
|
||||||
}
|
|
||||||
</mat-form-field>
|
|
||||||
</div>
|
|
||||||
<button mat-flat-button class="button" type="submit">{{ ingredientId === -1 ? 'Ajouter' : 'Éditer' }}</button>
|
|
||||||
</form>
|
|
@ -1,23 +0,0 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { IngredientAddComponent } from './ingredient-add.component';
|
|
||||||
|
|
||||||
describe('IngredientAddComponent', () => {
|
|
||||||
let component: IngredientAddComponent;
|
|
||||||
let fixture: ComponentFixture<IngredientAddComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
imports: [IngredientAddComponent],
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(IngredientAddComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,63 +0,0 @@
|
|||||||
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');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
<div class="mat-elevation-z8">
|
|
||||||
<table mat-table [dataSource]="dataSource">
|
|
||||||
|
|
||||||
<ng-container matColumnDef="id">
|
|
||||||
<th mat-header-cell *matHeaderCellDef> id </th>
|
|
||||||
<td mat-cell *matCellDef="let element">
|
|
||||||
{{element.id}}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="name">
|
|
||||||
<th mat-header-cell *matHeaderCellDef> name </th>
|
|
||||||
<td mat-cell *matCellDef="let element">
|
|
||||||
{{element.name}}
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<ng-container matColumnDef="actions">
|
|
||||||
<th mat-header-cell *matHeaderCellDef> actions </th>
|
|
||||||
<td mat-cell *matCellDef="let element">
|
|
||||||
<button mat-button [routerLink]="['/ingredients', element.id, 'edit']">Modifier</button>
|
|
||||||
<button mat-button (click)="delete(element)" color="warn">Supprimer</button>
|
|
||||||
</td>
|
|
||||||
</ng-container>
|
|
||||||
|
|
||||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
|
||||||
<tr mat-row *matRowDef="let element; columns: displayedColumns"></tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<mat-paginator [pageSizeOptions]="[5, 10, 20]"
|
|
||||||
showFirstLastButtons
|
|
||||||
aria-label="Select page of recipes">
|
|
||||||
</mat-paginator>
|
|
||||||
</div>
|
|
@ -1,23 +0,0 @@
|
|||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
||||||
|
|
||||||
import { IngredientsComponent } from './ingredients.component';
|
|
||||||
|
|
||||||
describe('IngredientsComponent', () => {
|
|
||||||
let component: IngredientsComponent;
|
|
||||||
let fixture: ComponentFixture<IngredientsComponent>;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
await TestBed.configureTestingModule({
|
|
||||||
imports: [IngredientsComponent],
|
|
||||||
})
|
|
||||||
.compileComponents();
|
|
||||||
|
|
||||||
fixture = TestBed.createComponent(IngredientsComponent);
|
|
||||||
component = fixture.componentInstance;
|
|
||||||
fixture.detectChanges();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should create', () => {
|
|
||||||
expect(component).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,52 +0,0 @@
|
|||||||
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<Ingredient>();
|
|
||||||
|
|
||||||
constructor(protected recipes: RecipeService) {
|
|
||||||
this.dataSource = new MatTableDataSource<Ingredient>(recipes.getAllIngredients());
|
|
||||||
}
|
|
||||||
|
|
||||||
delete(ingredient: Ingredient): void {
|
|
||||||
this.recipes.deleteIngredient(ingredient);
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in new issue