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 { export type EnterRecipeDataSubmitEvent = Omit<
title: string; RecipeDraftViewModel,
slug: string; 'id' | 'created' | 'modified' | 'state' | 'owner' | 'lastInference'
ingredients: Array<{ >;
amount?: string | null;
name: string;
notes?: string | null;
}>;
mainImage: ImageView | null;
rawText: string;
}

View File

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

View File

@ -96,6 +96,34 @@
[selectedUsernameFilename]="mainImageUsernameFilename()" [selectedUsernameFilename]="mainImageUsernameFilename()"
></app-image-select> ></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> <h3>Recipe Text</h3>
<mat-form-field> <mat-form-field>
<mat-label>Recipe Text</mat-label> <mat-label>Recipe Text</mat-label>
@ -106,5 +134,5 @@
(input)="onRecipeTextChange($event)" (input)="onRecipeTextChange($event)"
></textarea> ></textarea>
</mat-form-field> </mat-form-field>
<button matButton="filled" type="submit">Review</button> <button matButton="filled" type="submit" [disabled]="recipeFormGroup.invalid">Review</button>
</form> </form>

View File

@ -13,7 +13,7 @@ import {
viewChild, viewChild,
} from '@angular/core'; } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from '@angular/forms'; 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 { MatButton } from '@angular/material/button';
import { EnterRecipeDataSubmitEvent } from './EnterRecipeDataSubmitEvent'; import { EnterRecipeDataSubmitEvent } from './EnterRecipeDataSubmitEvent';
import { FaIconComponent } from '@fortawesome/angular-fontawesome'; import { FaIconComponent } from '@fortawesome/angular-fontawesome';
@ -67,6 +67,7 @@ import { ImageView } from '../../../../shared/models/ImageView.model';
CdkDrag, CdkDrag,
DatePipe, DatePipe,
ImageSelect, ImageSelect,
MatError,
], ],
templateUrl: './enter-recipe-data.html', templateUrl: './enter-recipe-data.html',
styleUrl: './enter-recipe-data.css', styleUrl: './enter-recipe-data.css',
@ -83,6 +84,9 @@ export class EnterRecipeData implements OnInit {
protected readonly recipeFormGroup = new FormGroup({ protected readonly recipeFormGroup = new FormGroup({
title: new FormControl('', Validators.required), title: new FormControl('', Validators.required),
slug: 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), text: new FormControl('', Validators.required),
}); });
@ -106,6 +110,9 @@ export class EnterRecipeData implements OnInit {
this.recipeFormGroup.patchValue({ this.recipeFormGroup.patchValue({
title: draft.title ?? '', title: draft.title ?? '',
slug: draft.slug ?? '', slug: draft.slug ?? '',
preparationTime: draft.preparationTime?.toString() ?? '',
cookingTime: draft.cookingTime?.toString() ?? '',
totalTime: draft.totalTime?.toString() ?? '',
text: draft.rawText ?? '', text: draft.rawText ?? '',
}); });
if (draft.ingredients) { if (draft.ingredients) {
@ -204,6 +211,16 @@ export class EnterRecipeData implements OnInit {
this.ingredientsTable()!.renderRows(); 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 { protected onSubmit(event: SubmitEvent): void {
event.preventDefault(); event.preventDefault();
const value = this.recipeFormGroup.value; const value = this.recipeFormGroup.value;
@ -211,6 +228,9 @@ export class EnterRecipeData implements OnInit {
title: value.title!, title: value.title!,
slug: value.slug!, slug: value.slug!,
ingredients: this.ingredientModels().map((ingredientModel) => ingredientModel.draft), 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(), mainImage: this.mainImage(),
rawText: value.text!, rawText: value.text!,
}); });

View File

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