From 54c557bec5e4a5ac534f62e87a0c3ee8711be3ba Mon Sep 17 00:00:00 2001 From: Hayden Hargreaves Date: Sun, 28 Dec 2025 17:39:28 -0700 Subject: [PATCH] (FEAT): Finished fixing up the search page! --- internal/app/service/recipe_service.go | 7 +- internal/domain/recipe/repository.go | 2 +- .../database/repository/recipe_repository.go | 85 +++---------------- web/src/components/display/RecipeMetaData.tsx | 4 +- web/src/components/icons/StarIcon.tsx | 7 +- .../components/items/RecipeSearchResult.tsx | 4 +- 6 files changed, 26 insertions(+), 83 deletions(-) diff --git a/internal/app/service/recipe_service.go b/internal/app/service/recipe_service.go index 6ccc29f..ae732c4 100644 --- a/internal/app/service/recipe_service.go +++ b/internal/app/service/recipe_service.go @@ -193,7 +193,12 @@ func (s *RecipeService) GetRecipe(id int, userId *int) (*domain.Recipe, error) { // // The favorites parameter is used to only return filters favorited by the userId provided. func (s *RecipeService) SearchRecipes(filters domain.SearchFilters, userId *int, favorites bool) ([]domain.Recipe, error) { - return s.recipeRepository.SearchRecipes(filters, userId, favorites) + ids, err := s.recipeRepository.SearchRecipes(filters, userId, favorites) + if err != nil { + return []domain.Recipe{}, err + } + + return s.recipeRepository.GetRecipes(ids, userId) } // GetUserRecipes returns a list of the recipes that the user has created. The user's diff --git a/internal/domain/recipe/repository.go b/internal/domain/recipe/repository.go index 8a9aa9d..c33681d 100644 --- a/internal/domain/recipe/repository.go +++ b/internal/domain/recipe/repository.go @@ -4,7 +4,7 @@ type RecipeRepository interface { CreateRecipe(recipe *Recipe) error GetRecipe(id int, userId *int) (*Recipe, error) GetRecipes(ids []int, userId *int) ([]Recipe, error) - SearchRecipes(filters SearchFilters, userId *int, favorites bool) ([]Recipe, error) + SearchRecipes(filters SearchFilters, userId *int, favorites bool) ([]int, error) CreateRecipeTags(recipe Recipe, tags []string) error GetUserRecipes(id int) ([]Recipe, error) GetUserFavoriteRecipes(id int) ([]Recipe, error) diff --git a/internal/infrastructure/database/repository/recipe_repository.go b/internal/infrastructure/database/repository/recipe_repository.go index bdaadad..c055aad 100644 --- a/internal/infrastructure/database/repository/recipe_repository.go +++ b/internal/infrastructure/database/repository/recipe_repository.go @@ -221,7 +221,10 @@ func isBitActive(bits, pos int) bool { // TODO: Pagination is required, to provide infinite scroll. // // TODO: This does not work in the current build, the DB does not return valid values. -func (r *RecipeRepository) SearchRecipes(filters domain.SearchFilters, userId *int, favorites bool) ([]domain.Recipe, error) { +// +// 12/28/25: This function has changed, now longer returns the recipes, but their IDs for fetching +// elsewhere. +func (r *RecipeRepository) SearchRecipes(filters domain.SearchFilters, userId *int, favorites bool) ([]int, error) { // Compute meals type filters (there are 7 bits) var mealConditions []string for i := range 7 { @@ -305,17 +308,6 @@ func (r *RecipeRepository) SearchRecipes(filters domain.SearchFilters, userId *i // Define columns to select. More fields can be added if the full text search is required columns := []string{ "r.id", - "r.title", - "r.description", - "r.instructions", - "r.serves", - "r.difficulty", - "r.duration", - "r.category", - "r.ingredients", - "r.userid", - "r.modified", - "r.created", } // TODO: Need to add these to the query @@ -392,76 +384,21 @@ func (r *RecipeRepository) SearchRecipes(filters domain.SearchFilters, userId *i // Execute the query rows, err := r.db.Query(query) if err != nil { - return nil, fmt.Errorf("failed to query recipes: %w", err) + return []int{}, fmt.Errorf("failed to query recipes: %w", err) } defer rows.Close() - var recipes []domain.Recipe + var ids []int for rows.Next() { - // Parsed values location - var recipe domain.Recipe - var durationBytes []byte - var ingredientBytes []byte - - if err := rows.Scan( - &recipe.Id, - &recipe.Title, - &recipe.Description, - pq.Array(&recipe.Instructions), - &recipe.Serves, - &recipe.Difficulty, - &durationBytes, - &recipe.Category, - &ingredientBytes, - &recipe.UserId, - &recipe.Modified, - &recipe.Created, - ); err != nil { - return nil, fmt.Errorf("failed to scan recipe row: %w", err) + var id int + if err := rows.Scan(&id); err != nil { + return []int{}, fmt.Errorf("failed to extract ID: %s\n", err.Error()) } - // Parse duration from bytes - if len(durationBytes) > 0 { - var duration domain.RecipeDuration - if err := json.Unmarshal(durationBytes, &duration); err != nil { - return nil, fmt.Errorf("failed to parse duration for recipe ID %d: %w", recipe.Id, err) - } - recipe.Duration = duration - } else { - recipe.Duration = domain.RecipeDuration{} - } - - // Parse ingredients from bytes - if len(ingredientBytes) > 0 { - var ingredients []domain.RecipeIngredient - if err := json.Unmarshal(ingredientBytes, &ingredients); err != nil { - return nil, fmt.Errorf("failed to parse ingredients for recipe ID %d: %w", recipe.Id, err) - } - recipe.Ingredients = ingredients - } else { - recipe.Ingredients = []domain.RecipeIngredient{} - } - - // Add tags - if err := r.GetRecipeTags(&recipe); err != nil { - fmt.Printf("ERROR getting recipe tags. %s\n", err.Error()) - } - - // Add recipe if not a favorite search - if !favorites && userId != nil { - if err := r.GetRecipeFavorite(&recipe, *userId); err != nil { - fmt.Printf("ERROR getting recipe tags. %s\n", err.Error()) - } - } - - if favorites { - recipe.Favorite = true - } - - recipes = append(recipes, recipe) + ids = append(ids, id) } - return recipes, nil + return ids, nil } // CreateRecipeTags accepts a list of tags (names) and a recipe (already created by the DB) and diff --git a/web/src/components/display/RecipeMetaData.tsx b/web/src/components/display/RecipeMetaData.tsx index 6ab7fd2..bbaccad 100644 --- a/web/src/components/display/RecipeMetaData.tsx +++ b/web/src/components/display/RecipeMetaData.tsx @@ -40,10 +40,10 @@ export default function RecipeMetaData({ recipe }: RecipeMetaDataProps) { >
{Array.from({ length: recipe?.Difficulty ?? 0 }).map((_, i) => ( - + ))} {Array.from({ length: 5 - (recipe?.Difficulty ?? 0) }).map((_, i) => ( - + ))}

{displayDifficulty(recipe?.Difficulty ?? 0)}

diff --git a/web/src/components/icons/StarIcon.tsx b/web/src/components/icons/StarIcon.tsx index 9556498..fa35e82 100644 --- a/web/src/components/icons/StarIcon.tsx +++ b/web/src/components/icons/StarIcon.tsx @@ -1,19 +1,20 @@ interface StarIconProps { filled: boolean; + size: number; }; -export default function StarIcon({ filled }: StarIconProps) { +export default function StarIcon({ filled, size = 6 }: StarIconProps) { return <> {filled ? ( - + ) : ( - + diff --git a/web/src/components/items/RecipeSearchResult.tsx b/web/src/components/items/RecipeSearchResult.tsx index 9230bce..756a823 100644 --- a/web/src/components/items/RecipeSearchResult.tsx +++ b/web/src/components/items/RecipeSearchResult.tsx @@ -41,10 +41,10 @@ export default function RecipeSearchResult({ recipe }: RecipeSearchResultProps) {Array.from({ length: recipe.Difficulty }).map((_, i) => ( - + ))} {Array.from({ length: 5 - (recipe.Difficulty) }).map((_, i) => ( - + ))}