MME-25 Add prep/cook/total time form fields.

This commit is contained in:
Jesse Brault 2026-02-10 16:03:57 -06:00
parent e05ebf5b62
commit 6b78540dd3
5 changed files with 62 additions and 15 deletions

View File

@ -1,13 +1,6 @@
import { ImageView } from '../../../../shared/models/ImageView.model';
import { RecipeDraftViewModel } from '../../../../shared/models/RecipeDraftView.model';
export interface EnterRecipeDataSubmitEvent {
title: string;
slug: string;
ingredients: Array<{
amount?: string | null;
name: string;
notes?: string | null;
}>;
mainImage: ImageView | null;
rawText: string;
}
export type EnterRecipeDataSubmitEvent = Omit<
RecipeDraftViewModel,
'id' | 'created' | 'modified' | 'state' | 'owner' | 'lastInference'
>;

View File

@ -27,6 +27,12 @@ textarea {
row-gap: 10px;
}
.times-container {
display: flex;
flex-direction: column;
row-gap: 10px;
}
.mat-column-reorder {
width: 32px;
text-align: center;

View File

@ -96,6 +96,34 @@
[selectedUsernameFilename]="mainImageUsernameFilename()"
></app-image-select>
<div class="times-container">
<h3>Times</h3>
<p>Enter all as number of minutes, <em>eg.</em> 45</p>
<mat-form-field>
<mat-label>Preparation Time (minutes)</mat-label>
<input matInput [formControl]="recipeFormGroup.controls.preparationTime" />
@if (recipeFormGroup.controls.preparationTime.hasError("pattern")) {
<mat-error>Must be a valid number.</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>Cooking Time (minutes)</mat-label>
<input matInput [formControl]="recipeFormGroup.controls.cookingTime" />
@if (recipeFormGroup.controls.cookingTime.hasError("pattern")) {
<mat-error>Must be a valid number.</mat-error>
}
</mat-form-field>
<mat-form-field>
<mat-label>Total Time (minutes)</mat-label>
<input matInput [formControl]="recipeFormGroup.controls.totalTime" />
@if (recipeFormGroup.controls.totalTime.hasError("pattern")) {
<mat-error>Must be a valid number.</mat-error>
}
</mat-form-field>
</div>
<h3>Recipe Text</h3>
<mat-form-field>
<mat-label>Recipe Text</mat-label>
@ -106,5 +134,5 @@
(input)="onRecipeTextChange($event)"
></textarea>
</mat-form-field>
<button matButton="filled" type="submit">Review</button>
<button matButton="filled" type="submit" [disabled]="recipeFormGroup.invalid">Review</button>
</form>

View File

@ -13,7 +13,7 @@ import {
viewChild,
} from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms';
import { MatFormField, MatInput, MatLabel } from '@angular/material/input';
import { MatError, MatFormField, MatInput, MatLabel } from '@angular/material/input';
import { MatButton } from '@angular/material/button';
import { EnterRecipeDataSubmitEvent } from './EnterRecipeDataSubmitEvent';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
@ -67,6 +67,7 @@ import { ImageView } from '../../../../shared/models/ImageView.model';
CdkDrag,
DatePipe,
ImageSelect,
MatError,
],
templateUrl: './enter-recipe-data.html',
styleUrl: './enter-recipe-data.css',
@ -83,6 +84,9 @@ export class EnterRecipeData implements OnInit {
protected readonly recipeFormGroup = new FormGroup({
title: new FormControl('', Validators.required),
slug: new FormControl('', Validators.required),
preparationTime: new FormControl('', Validators.pattern(/^\d+$/)),
cookingTime: new FormControl('', Validators.pattern(/^\d+$/)),
totalTime: new FormControl('', Validators.pattern(/^\d+$/)),
text: new FormControl('', Validators.required),
});
@ -106,6 +110,9 @@ export class EnterRecipeData implements OnInit {
this.recipeFormGroup.patchValue({
title: draft.title ?? '',
slug: draft.slug ?? '',
preparationTime: draft.preparationTime?.toString() ?? '',
cookingTime: draft.cookingTime?.toString() ?? '',
totalTime: draft.totalTime?.toString() ?? '',
text: draft.rawText ?? '',
});
if (draft.ingredients) {
@ -204,6 +211,16 @@ export class EnterRecipeData implements OnInit {
this.ingredientsTable()!.renderRows();
}
private getTime(s?: string | null): number | null {
if (!s) return null;
try {
return parseInt(s);
} catch (e) {
console.error(`Should not have had a parse error because of form validators: ${e}`);
return null;
}
}
protected onSubmit(event: SubmitEvent): void {
event.preventDefault();
const value = this.recipeFormGroup.value;
@ -211,6 +228,9 @@ export class EnterRecipeData implements OnInit {
title: value.title!,
slug: value.slug!,
ingredients: this.ingredientModels().map((ingredientModel) => ingredientModel.draft),
preparationTime: this.getTime(value.preparationTime),
cookingTime: this.getTime(value.cookingTime),
totalTime: this.getTime(value.totalTime),
mainImage: this.mainImage(),
rawText: value.text!,
});

View File

@ -86,7 +86,7 @@ export class RecipeDraftService {
amount?: string | null;
name: string;
notes?: string | null;
}>;
}> | null;
mainImage?: ImageView | null;
rawText?: string | null;
},