|
|
|
@ -1,39 +1,75 @@
|
|
|
|
|
<form (ngSubmit)="onSubmit(); recipeForm.ngSubmit.emit()" #recipeForm="ngForm" class="ng-submitted">
|
|
|
|
|
<form
|
|
|
|
|
(ngSubmit)="onSubmit(); recipeForm.ngSubmit.emit()"
|
|
|
|
|
#recipeForm="ngForm"
|
|
|
|
|
class="ng-submitted"
|
|
|
|
|
>
|
|
|
|
|
<h2>Add a recipe</h2>
|
|
|
|
|
<div class="form-group my-2 col-md-4">
|
|
|
|
|
<label for="name">Name</label>
|
|
|
|
|
<input class="form-control"
|
|
|
|
|
placeholder="Name"
|
|
|
|
|
type="text"
|
|
|
|
|
id="name"
|
|
|
|
|
[(ngModel)]="recipe.name"
|
|
|
|
|
name="name"
|
|
|
|
|
required
|
|
|
|
|
#nameField="ngModel">
|
|
|
|
|
<div *ngIf="nameField.invalid && (nameField.dirty || nameField.touched || recipeForm.submitted)" class="text-danger">
|
|
|
|
|
<div *ngIf="nameField.errors && nameField.errors['required']">Name is required.</div>
|
|
|
|
|
<input
|
|
|
|
|
class="form-control"
|
|
|
|
|
placeholder="Name"
|
|
|
|
|
type="text"
|
|
|
|
|
id="name"
|
|
|
|
|
[(ngModel)]="recipe.name"
|
|
|
|
|
name="name"
|
|
|
|
|
required
|
|
|
|
|
#nameField="ngModel"
|
|
|
|
|
/>
|
|
|
|
|
<div
|
|
|
|
|
*ngIf="
|
|
|
|
|
nameField.invalid &&
|
|
|
|
|
(nameField.dirty || nameField.touched || recipeForm.submitted)
|
|
|
|
|
"
|
|
|
|
|
class="text-danger"
|
|
|
|
|
>
|
|
|
|
|
<div *ngIf="nameField.errors && nameField.errors['required']">
|
|
|
|
|
Name is required.
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-group my-2 col-md-4">
|
|
|
|
|
<label for="description">Description</label>
|
|
|
|
|
<textarea class="form-control"
|
|
|
|
|
id="description"
|
|
|
|
|
[(ngModel)]="recipe.description"
|
|
|
|
|
name="description"
|
|
|
|
|
required
|
|
|
|
|
rows="2"
|
|
|
|
|
maxlength="{{ maxDescriptionLength }}"
|
|
|
|
|
#descriptionField="ngModel"></textarea>
|
|
|
|
|
<div class="text-muted text-end">Characters left: {{ maxDescriptionLength - recipe.description.length }}</div>
|
|
|
|
|
<div *ngIf="descriptionField.invalid && (descriptionField.dirty || descriptionField.touched || recipeForm.submitted)" class="text-danger">
|
|
|
|
|
<div *ngIf="descriptionField.errors && descriptionField.errors['required']">Description is required.</div>
|
|
|
|
|
<textarea
|
|
|
|
|
class="form-control"
|
|
|
|
|
id="description"
|
|
|
|
|
[(ngModel)]="recipe.description"
|
|
|
|
|
name="description"
|
|
|
|
|
required
|
|
|
|
|
rows="2"
|
|
|
|
|
maxlength="{{ maxDescriptionLength }}"
|
|
|
|
|
#descriptionField="ngModel"
|
|
|
|
|
></textarea>
|
|
|
|
|
<div class="text-muted text-end">
|
|
|
|
|
Characters left: {{ maxDescriptionLength - recipe.description.length }}
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
*ngIf="
|
|
|
|
|
descriptionField.invalid &&
|
|
|
|
|
(descriptionField.dirty ||
|
|
|
|
|
descriptionField.touched ||
|
|
|
|
|
recipeForm.submitted)
|
|
|
|
|
"
|
|
|
|
|
class="text-danger"
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
*ngIf="descriptionField.errors && descriptionField.errors['required']"
|
|
|
|
|
>
|
|
|
|
|
Description is required.
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="form-group my-3">
|
|
|
|
|
<div class="custom-file">
|
|
|
|
|
<label for="image">Image</label>
|
|
|
|
|
<input type="file" class="custom-file-input ms-1" id="image" (change)="onFileChange($event)">
|
|
|
|
|
<input
|
|
|
|
|
type="file"
|
|
|
|
|
class="custom-file-input ms-1"
|
|
|
|
|
id="image"
|
|
|
|
|
(change)="onFileChange($event)"
|
|
|
|
|
/>
|
|
|
|
|
<div *ngIf="imageError" style="color: red">{{ imageError }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
@ -41,13 +77,23 @@
|
|
|
|
|
<mat-form-field class="my-3 me-3">
|
|
|
|
|
<mat-label>Ingredients</mat-label>
|
|
|
|
|
<mat-select [(ngModel)]="selectedIngredient" name="selectedIngredient">
|
|
|
|
|
<mat-option *ngFor="let ingredient of ingredients" [value]="ingredient.id">
|
|
|
|
|
<mat-option
|
|
|
|
|
*ngFor="let ingredient of ingredients"
|
|
|
|
|
[value]="ingredient.id"
|
|
|
|
|
>
|
|
|
|
|
{{ ingredient.name }}
|
|
|
|
|
</mat-option>
|
|
|
|
|
</mat-select>
|
|
|
|
|
</mat-form-field>
|
|
|
|
|
|
|
|
|
|
<button class="me-3" mat-raised-button type="button" (click)="addIngredient()">Add Ingredient</button>
|
|
|
|
|
<button
|
|
|
|
|
class="me-3"
|
|
|
|
|
mat-raised-button
|
|
|
|
|
type="button"
|
|
|
|
|
(click)="addIngredient()"
|
|
|
|
|
>
|
|
|
|
|
Add Ingredient
|
|
|
|
|
</button>
|
|
|
|
|
<div class="mb-3" *ngFor="let ingredientId of getIngredientKeys()">
|
|
|
|
|
<div>
|
|
|
|
|
{{ findIngredientName(ingredientId) }}
|
|
|
|
@ -55,15 +101,31 @@
|
|
|
|
|
type="number"
|
|
|
|
|
[(ngModel)]="ingredientQuantities[ingredientId]"
|
|
|
|
|
name="quantity_{{ ingredientId }}"
|
|
|
|
|
min="1" />
|
|
|
|
|
<button mat-raised-button color="warn" type="button" (click)="removeIngredient(ingredientId)">Remove</button>
|
|
|
|
|
min="1"
|
|
|
|
|
/>
|
|
|
|
|
<button
|
|
|
|
|
mat-raised-button
|
|
|
|
|
color="warn"
|
|
|
|
|
type="button"
|
|
|
|
|
(click)="removeIngredient(ingredientId)"
|
|
|
|
|
>
|
|
|
|
|
Remove
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div *ngIf="getIngredientKeys().length === 0 && recipeForm.submitted" class="text-danger">
|
|
|
|
|
<div
|
|
|
|
|
*ngIf="getIngredientKeys().length === 0 && recipeForm.submitted"
|
|
|
|
|
class="text-danger"
|
|
|
|
|
>
|
|
|
|
|
At least one ingredient is required.
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<button mat-raised-button type="submit" [disabled]="!recipeForm.form.valid || getIngredientKeys().length === 0" [ngClass]="{'disabled-button': getIngredientKeys().length === 0}">
|
|
|
|
|
<br />
|
|
|
|
|
<button
|
|
|
|
|
mat-raised-button
|
|
|
|
|
type="submit"
|
|
|
|
|
[disabled]="!recipeForm.form.valid || getIngredientKeys().length === 0"
|
|
|
|
|
[ngClass]="{ 'disabled-button': getIngredientKeys().length === 0 }"
|
|
|
|
|
>
|
|
|
|
|
Add Recipe
|
|
|
|
|
</button>
|
|
|
|
|
</form>
|
|
|
|
|