diff --git a/src/endpoints/CompactRecipePoint.ts b/src/endpoints/CompactRecipePoint.ts index 17e6d49..0df0e0a 100644 --- a/src/endpoints/CompactRecipePoint.ts +++ b/src/endpoints/CompactRecipePoint.ts @@ -12,7 +12,7 @@ const router = Router(); // Inject repo + mapper here const recipeRepository = new RecipeRepository(); const compactRecipeMapper = new CompactRecipeDtoEntityMapper(); -const compactRecipeController = new CompactRecipeHandler(recipeRepository, compactRecipeMapper); +const compactRecipeHandler = new CompactRecipeHandler(recipeRepository, compactRecipeMapper); /** * Load header data of all recipes * Responds with a list of CompactRecipeDtos @@ -20,7 +20,9 @@ const compactRecipeController = new CompactRecipeHandler(recipeRepository, compa router.get( "/", asyncHandler(async (req, res) => { - const response = await compactRecipeController.getAllCompactRecipes(); + // extract search string from query parameters, convert to lower case for case insensitive search + const searchString : string = req.query.search ? req.query.search.toString().toLowerCase() : ""; + const response = await compactRecipeHandler.getMatchingRecipes(searchString); res.status(201).json(response); }) ); diff --git a/src/handlers/CompactRecipeHandler.ts b/src/handlers/CompactRecipeHandler.ts index dfcebf9..6e332e2 100644 --- a/src/handlers/CompactRecipeHandler.ts +++ b/src/handlers/CompactRecipeHandler.ts @@ -25,4 +25,19 @@ export class CompactRecipeHandler { }); return recipeDtos; } + + /** + * Get all recipes matching search + * + * Recipe title must contain type string + * @todo Full text search?? + */ + async getMatchingRecipes(searchString : string){ + if(!searchString || searchString.length===0){ + // get all + return this.getAllCompactRecipes(); + } else { + return this.repository.findCompactRecipeBySearch(searchString); + } + } } \ No newline at end of file diff --git a/src/repositories/RecipeRepository.ts b/src/repositories/RecipeRepository.ts index 1b7e620..493b7f0 100644 --- a/src/repositories/RecipeRepository.ts +++ b/src/repositories/RecipeRepository.ts @@ -1,6 +1,7 @@ import { AbstractRepository } from "./AbstractRepository.js"; import { RecipeEntity } from "../entities/RecipeEntity.js"; import { AppDataSource } from "../data-source.js"; +import { Like } from "typeorm"; export class RecipeRepository extends AbstractRepository { constructor() { @@ -23,6 +24,23 @@ export class RecipeRepository extends AbstractRepository { }); } + /** + * Find all recipes matching the search. Currently it only searches on the title. Fetches only recipe header data but no relations. + * @param searchString String to search for + * @returns List of recipe entities matching the search criteria + */ + async findCompactRecipeBySearch(searchString : string): Promise{ + // @todo doesn't work like expected... + return this.repo.find( + { where: {title: Like(`%${searchString}%`)}} + ); + } + + /** + * Update recipe and relations + * @param entity Updated entity + * @returns Updated Entity + */ async updateRecipe(entity: RecipeEntity): Promise { return AppDataSource.transaction(async (em) => { // load existing data