save recipes
This commit is contained in:
parent
3a887d8dbb
commit
380eb4cd21
18 changed files with 412 additions and 87 deletions
|
|
@ -1,76 +1,129 @@
|
|||
import { Entity } from "typeorm";
|
||||
import { RecipeDto } from "../dtos/RecipeDto.js";
|
||||
import { RecipeDtoEntityMapper } from "../mappers/RecipeDtoEntityMapper.js";
|
||||
import { RecipeRepository } from "../repositories/RecipeRepository.js";
|
||||
import { RecipeEntity } from "../entities/RecipeEntity.js";
|
||||
import { ValidationError } from "../errors/httpErrors.js";
|
||||
import { RecipeInstructionStepDto } from "../dtos/RecipeInstructionStepDto.js";
|
||||
import { RecipeIngredientGroupDto } from "../dtos/RecipeIngredientGroupDto.js";
|
||||
import { RecipeIngredientDto } from "../dtos/RecipeIngredientDto.js";
|
||||
|
||||
/**
|
||||
* Controls all user specific actions
|
||||
*/
|
||||
export class RecipeController {
|
||||
constructor(
|
||||
private repository: RecipeRepository,
|
||||
private mapper: RecipeDtoEntityMapper
|
||||
) {}
|
||||
constructor(
|
||||
private repository: RecipeRepository,
|
||||
private mapper: RecipeDtoEntityMapper
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Load list of all recipes
|
||||
* @returns List of all recipes
|
||||
*/
|
||||
async getAllRecipes(){
|
||||
const recipeEntities = await this.repository.findAll();
|
||||
let recipeDtos : RecipeDto[] = [];
|
||||
recipeEntities.forEach(recipeEntity => {
|
||||
recipeDtos.push(this.mapper.toDto(recipeEntity));
|
||||
});
|
||||
return recipeDtos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new recipe
|
||||
* @param dto RecipeDto containing the new recipe
|
||||
*/
|
||||
async createRecipe(dto : RecipeDto){
|
||||
if(!this.isRecipeDtoValid(dto)){
|
||||
throw new ValidationError("recipe data is not valid!")
|
||||
/**
|
||||
* Load list of all recipes
|
||||
* @returns List of all recipes
|
||||
*/
|
||||
async getAllRecipes() {
|
||||
const recipeEntities : RecipeEntity[] = await this.repository.findAll();
|
||||
let recipeDtos: RecipeDto[] = [];
|
||||
recipeEntities.forEach(recipeEntity => {
|
||||
recipeDtos.push(this.mapper.toDto(recipeEntity));
|
||||
});
|
||||
return recipeDtos;
|
||||
}
|
||||
const recipeEntity = this.mapper.toEntity(dto)
|
||||
const entity = await this.repository.create(recipeEntity);
|
||||
return this.mapper.toDto(entity);
|
||||
}
|
||||
|
||||
protected isRecipeDtoValid(dto :RecipeDto) : boolean {
|
||||
let isValid = true;
|
||||
if(dto.title == undefined
|
||||
|| dto.title.length == 0
|
||||
|| dto.amount == undefined
|
||||
|| dto.amountDescription == undefined
|
||||
|| dto.amountDescription.length == 0
|
||||
|| !this.isInstructionsValid(dto.instructions)
|
||||
){
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
// @todo ingredient groups
|
||||
|
||||
return isValid;
|
||||
}
|
||||
protected isInstructionsValid(instructions: RecipeInstructionStepDto[]|undefined) : boolean {
|
||||
if(instructions == undefined || instructions.length == 0){
|
||||
return false;
|
||||
}
|
||||
let isValid = true;
|
||||
instructions.forEach(step =>{
|
||||
if(step.text == undefined
|
||||
|| step.text.length == 0
|
||||
|| step.sortOrder == undefined
|
||||
){
|
||||
isValid = false;
|
||||
/**
|
||||
* Create a new recipe
|
||||
* @param dto RecipeDto containing the new recipe
|
||||
*/
|
||||
async createRecipe(dto: RecipeDto) {
|
||||
if (!this.isRecipeDtoValid(dto)) {
|
||||
throw new ValidationError("recipe data is not valid!")
|
||||
}
|
||||
});
|
||||
|
||||
return isValid;
|
||||
}
|
||||
const recipeEntity = this.mapper.toEntity(dto)
|
||||
const entity = await this.repository.create(recipeEntity);
|
||||
return this.mapper.toDto(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a recipe.
|
||||
* A recipe must have a non-empty title, servings info and valid instructions and ingredients
|
||||
* @param dto RecipeDTO
|
||||
* @returns true if the recipe is valid
|
||||
*/
|
||||
protected isRecipeDtoValid(dto: RecipeDto): boolean {
|
||||
|
||||
return dto.title !== undefined
|
||||
&& dto.title.length !== 0
|
||||
&& dto.amount !== undefined
|
||||
&& dto.amountDescription !== undefined
|
||||
&& dto.amountDescription.length !== 0
|
||||
&& this.isInstructionsValid(dto.instructions)
|
||||
&& this.isIngredientGroupsValid(dto.ingredientGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the ingredient groups if a recipe - each group must contain a valid ingredient list
|
||||
* @param ingredientGroups Array of ingredient groups
|
||||
* @returns true if all ingredient groups are valid
|
||||
*/
|
||||
protected isIngredientGroupsValid(ingredientGroups: RecipeIngredientGroupDto[] | undefined): boolean {
|
||||
return ingredientGroups !== undefined
|
||||
&& ingredientGroups.length !== 0
|
||||
&& ingredientGroups.every(group => {
|
||||
return (
|
||||
group.sortOrder !== undefined
|
||||
&& this.isIngredientsValid(group.ingredients)
|
||||
);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Validates an ingredient list ensuring that it is present, contains at least one ingredient and
|
||||
* that all ingredients in the list are valid
|
||||
* @param ingredients Array if ingredients
|
||||
* @returns true if the ingredient list is valid
|
||||
*/
|
||||
isIngredientsValid(ingredients: RecipeIngredientDto[] | undefined): boolean {
|
||||
return ingredients !== undefined
|
||||
&& ingredients.length !== 0
|
||||
&& ingredients.every(ingredient => {
|
||||
return this.isIngredientValid(ingredient);
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Validates an ingredient - An ingredient must have a name and a sortOrder
|
||||
* @param ingredient RecipeIngredientDto
|
||||
* @returns true if the ingredient is valid
|
||||
*/
|
||||
isIngredientValid(ingredient: RecipeIngredientDto): boolean {
|
||||
return ingredient !== null
|
||||
&& ingredient.sortOrder !== undefined
|
||||
&& ingredient.name !== undefined
|
||||
&& ingredient.name.length !== 0
|
||||
}
|
||||
// @todo create instruction handler/controller for validation?
|
||||
/**
|
||||
* Validates instructions
|
||||
* The list must be present and must contain at least one value with a non-empty
|
||||
* text field and sort order
|
||||
* @param instructions Array if instruction step DTOs
|
||||
* @returns Boolean indicating whether the instruction steps are valid
|
||||
*/
|
||||
protected isInstructionsValid(instructions: RecipeInstructionStepDto[] | undefined): boolean {
|
||||
return instructions !== undefined
|
||||
&& instructions.length !== 0
|
||||
&& instructions.every(step => {
|
||||
return this.isInstructionStepValid(step);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a single instruction step. Each step must have a well-defined non-empty text
|
||||
* and a sort order
|
||||
* @param step InstructionStepDto describing a single step of the recipe
|
||||
* @returns true if the step is valid
|
||||
*/
|
||||
private isInstructionStepValid(step: RecipeInstructionStepDto): boolean {
|
||||
return step !== null
|
||||
&& step.text !== undefined
|
||||
&& step.text.length !== 0
|
||||
&& step.sortOrder !== undefined;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue