added searching for recipes and users plus some cleanup

This commit is contained in:
durn
2026-04-08 13:26:22 -06:00
parent f1c2968dce
commit 4cce9018f8
10 changed files with 111 additions and 7 deletions
@@ -11,13 +11,17 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.dto.RecipeDto;
import com.example.demo.dto.UserDto;
import com.example.demo.entity.Recipe;
import com.example.demo.entity.User;
import com.example.demo.service.RecipeService;
import jakarta.validation.Valid;
@RestController
@RequestMapping("/api/recipes")
public class RecipeController {
@@ -31,7 +35,7 @@ public class RecipeController {
// build create recipe REST API
@PostMapping
public ResponseEntity<RecipeDto> saveUser(@RequestBody Recipe recipe) {
public ResponseEntity<RecipeDto> saveRecipe(@Valid @RequestBody Recipe recipe) {
RecipeDto recipeDto = recipeService.convertToDto(recipe);
return new ResponseEntity<RecipeDto>(recipeService.saveRecipe(recipeDto), HttpStatus.CREATED);
}
@@ -48,11 +52,24 @@ public class RecipeController {
public ResponseEntity<RecipeDto> getRecipeById(@PathVariable("id") Integer recipeId) {
return new ResponseEntity<RecipeDto>(recipeService.getRecipeById(recipeId), HttpStatus.OK);
}
// build get recipe by name REST API
@GetMapping("/search")
public ResponseEntity<List<RecipeDto>> searchRecipes(
@RequestParam(required = false) String name, // by not adding a name all recipes will appear basically
@RequestParam(required = false) List<String> tags // since users can choose no tags this isnt required
) {
List<RecipeDto> recipes = recipeService.getRecipes(name, tags);
return new ResponseEntity<>(recipes, HttpStatus.OK);
}
// build update recipe REST API
// http://localhost:8080/api/recipes/(id number goes here)
@PutMapping("{id}")
public ResponseEntity<RecipeDto> updateUser(@PathVariable("id") Integer recipeId, @RequestBody Recipe recipe) {
public ResponseEntity<RecipeDto> updateRecipe(@PathVariable("id") Integer recipeId, @RequestBody Recipe recipe) {
RecipeDto recipeDto = recipeService.convertToDto(recipe);
return new ResponseEntity<RecipeDto>(recipeService.updateRecipe(recipeDto, recipeId), HttpStatus.OK);
}
@@ -60,7 +77,7 @@ public class RecipeController {
// build delete recipe REST API
// http://localhost:8080/api/recipes/(id number goes here)
@DeleteMapping("{id}")
public ResponseEntity<String> deleteUser(@PathVariable("id") Integer recipeId) {
public ResponseEntity<String> deleteRecipe(@PathVariable("id") Integer recipeId) {
recipeService.deleteRecipe(recipeId);
return new ResponseEntity<String>("Recipe deleted succesfully!", HttpStatus.OK);
}
@@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.dto.UserDto;
@@ -40,6 +41,14 @@ public class UserController {
public List<UserDto> getAllUsers() {
return userService.getAllUsers();
}
// build get user by name REST API
@GetMapping("/search")
public ResponseEntity<List<UserDto>> getUsersByName(@RequestParam String string) {
List<UserDto> users = userService.getUsersByName(string);
return new ResponseEntity<>(users, HttpStatus.OK);
}
// build get user by id REST API
// http://localhost:8080/api/users/(id number goes here)
@@ -2,6 +2,9 @@ package com.example.demo.entity;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
@@ -22,16 +25,25 @@ public class Recipe {
@Column(columnDefinition = "TEXT")
private String description;
@NotNull(message = "Please Provide a prep time amount in mintutes")
@Positive(message = "This value cannot be negative")
private Integer prepTimeMinutes;
@NotNull(message = "Please Provide a cook time amount in mintutes")
@Positive(message = "This value cannot be negative")
private Integer cookTimeMinutes;
@NotNull(message = "Please Provide a serving amount")
@Positive(message = "This value cannot be negative")
private Integer servings;
private String status;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
@NotNull(message = "Recipe must be associated with a user")
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
@EqualsAndHashCode.Include
@@ -39,6 +51,7 @@ public class Recipe {
// Recipe ingredients relationship
@OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
@NotEmpty(message = "At least one ingredient is required")
private Set<RecipeIngredient> recipeIngredients = new HashSet<>();
// Recipe Steps relationship
@@ -3,6 +3,8 @@ package com.example.demo.entity;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.Table;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.JoinTable;
@@ -27,14 +29,17 @@ public class User implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@NotNull
private Integer id;
@Column(nullable = false, unique = true)
@NotBlank(message = "Username is required")
private String username;
private String role;
@Column(unique = true)
@NotBlank(message = "Email is required")
private String email;
private String hashedpassword;
@@ -1,8 +1,13 @@
package com.example.demo.repository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.entity.Recipe;
public interface RecipeRepo extends JpaRepository<Recipe, Integer> {
List<Recipe> findByTitleContainingIgnoreCase(String name);
List<Recipe> findByTitleContainingIgnoreCaseAndTags_NameIn(String title, List<String> tags);
}
@@ -4,10 +4,13 @@ import org.springframework.data.jpa.repository.JpaRepository;
import com.example.demo.entity.User;
import java.util.List;
import java.util.Optional;
public interface UserRepo extends JpaRepository<User, Integer> {
Optional<User> findByUsername(String username);
List<User> findByUsernameContainingIgnoreCase(String name);
}
@@ -2,6 +2,7 @@ package com.example.demo.service.Impl;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
@@ -318,4 +319,34 @@ public class RecipeServiceImpl implements RecipeService {
recipeRepository.deleteById(Id);
}
@Override
@Transactional
public List<RecipeDto> getRecipes(String name, List<String> tags) {
List<Recipe> recipes;
if(!name.isBlank()) {
recipes = recipeRepository.findByTitleContainingIgnoreCase(name);
}
else {
recipes = recipeRepository.findAll();
}
if(!tags.isEmpty() && !recipes.isEmpty()) {
recipes = recipes.stream()
.filter(recipe -> recipe.getTags().stream().anyMatch(tag -> tags.contains(tag.getName())))
.collect(Collectors.toList());
}
List<RecipeDto> recipeList = new ArrayList<>();
for (Recipe recipe : recipes) {
RecipeDto dto = convertToDto(recipe);
recipeList.add(dto);
}
return recipeList;
}
}
@@ -108,4 +108,21 @@ public class UserServiceImpl implements UserService {
}
@Override
public List<UserDto> getUsersByName(String name) {
List<User> users = userRepository.findByUsernameContainingIgnoreCase(name);
if (users.isEmpty()) {
throw new NotFoundException("User", "username containing", name);
}
List<UserDto> userList = new ArrayList<>();
for (User user : users) {
UserDto dto = convertToDto(user);
userList.add(dto);
}
return userList;
}
}
@@ -16,6 +16,8 @@ public interface RecipeService {
List<RecipeDto> getAllRecipes();
RecipeDto getRecipeById(Integer recipeId);
List<RecipeDto> getRecipes(String name, List<String> tags);
RecipeDto updateRecipe(RecipeDto recipedto, Integer Id);
@@ -13,6 +13,8 @@ public interface UserService {
List<UserDto> getAllUsers();
UserDto getUserById(Integer Id);
List<UserDto> getUsersByName(String name);
UserDto saveFavorite(Integer userId, Integer recipeId);