diff --git a/src/main/java/com/example/demo/config/SecurityConfig.java b/src/main/java/com/example/demo/config/SecurityConfig.java index ddd1cc9..0831b95 100644 --- a/src/main/java/com/example/demo/config/SecurityConfig.java +++ b/src/main/java/com/example/demo/config/SecurityConfig.java @@ -6,7 +6,6 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.csrf.CsrfAuthenticationStrategy; @Configuration public class SecurityConfig { @@ -22,6 +21,7 @@ public class SecurityConfig { .authorizeHttpRequests(auth -> auth .requestMatchers("/login", "/register", "/css/**", "/images/**").permitAll() .requestMatchers("/api/users").permitAll() + .requestMatchers("/users/**").permitAll() .requestMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated() ) diff --git a/src/main/java/com/example/demo/controller/ProfileController.java b/src/main/java/com/example/demo/controller/ProfileController.java new file mode 100644 index 0000000..546d3bb --- /dev/null +++ b/src/main/java/com/example/demo/controller/ProfileController.java @@ -0,0 +1,54 @@ +package com.example.demo.controller; + +import java.security.Principal; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.ModelAttribute; + +import com.example.demo.dto.ProfileDto; +import com.example.demo.dto.UpdateProfileDto; +import com.example.demo.service.UserService; + +@Controller +public class ProfileController { + + private final UserService userService; + + public ProfileController(UserService userService) { + this.userService = userService; + } + + @GetMapping("/users/{id}") + public String viewPublicProfile(@PathVariable Integer id, Model model) { + ProfileDto profile = userService.getProfileByUserId(id); + model.addAttribute("profile", profile); + return "public-profile"; + } + + @GetMapping("/my-profile") + public String viewMyProfile(Principal principal, Model model) { + String username = principal.getName(); + + ProfileDto profile = userService.getCurrentUserProfile(username); + + UpdateProfileDto updateProfileDto = new UpdateProfileDto(); + updateProfileDto.setDisplayName(profile.getDisplayName()); + updateProfileDto.setBio(profile.getBio()); + + model.addAttribute("profile", profile); + model.addAttribute("updateProfileDto", updateProfileDto); + + return "my-profile"; + } + + @PostMapping("/my-profile/update") + public String updateMyProfile(@ModelAttribute UpdateProfileDto dto, Principal principal) { + String username = principal.getName(); + userService.updateProfile(username, dto); + return "redirect:/my-profile"; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/controller/RecipeController.java b/src/main/java/com/example/demo/controller/RecipeController.java index 360314c..5560a87 100644 --- a/src/main/java/com/example/demo/controller/RecipeController.java +++ b/src/main/java/com/example/demo/controller/RecipeController.java @@ -36,7 +36,8 @@ public class RecipeController { // build create recipe REST API @PostMapping - public ResponseEntity saveRecipe(@RequestBody RecipeDto recipeDto, Authentication authentication) { + public ResponseEntity saveRecipe(@Valid @RequestBody Recipe recipe, Authentication authentication) { + RecipeDto recipeDto = recipeService.convertToDto(recipe); String currentUsername = authentication.getName(); return new ResponseEntity<>(recipeService.saveRecipe(recipeDto, currentUsername), HttpStatus.CREATED); } @@ -58,12 +59,15 @@ public class RecipeController { @GetMapping("/search") public ResponseEntity> searchRecipes( @RequestParam(required = false) String name, // by not adding a name all recipes will appear basically - @RequestParam(required = false) List tags // since users can choose no tags this isnt required + @RequestParam(required = false) List tags, // since users can choose no tags this isnt required + @RequestParam(required = false) List prices, + @RequestParam(required = false) List cookTime, + @RequestParam(required = false) List prepTime ) { - List recipes = recipeService.getRecipes(name, tags); + List recipes = recipeService.getRecipes(name, tags, prices, cookTime, prepTime); return new ResponseEntity<>(recipes, HttpStatus.OK); } diff --git a/src/main/java/com/example/demo/controller/SiteController.java b/src/main/java/com/example/demo/controller/SiteController.java index 8c4d0f8..db3b44c 100644 --- a/src/main/java/com/example/demo/controller/SiteController.java +++ b/src/main/java/com/example/demo/controller/SiteController.java @@ -2,14 +2,13 @@ package com.example.demo.controller; import java.util.List; -import org.springframework.beans.factory.annotation.Autowired; import com.example.demo.service.RecipeService; import com.example.demo.dto.RecipeDto; -import com.example.demo.entity.Recipe; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestParam; @Controller public class SiteController { @@ -19,10 +18,10 @@ public class SiteController { public SiteController(RecipeService recipeService) { this.recipeService = recipeService; } + @GetMapping("/") public String viewHomePage(Model model) { - //model.addAttribute("allemplist", employeeServiceImpl.getAllEmployee()); - List recipes = recipeService.getAllRecipes(); + List recipes = recipeService.getAllRecipes(); model.addAttribute("recipes", recipes); return "home"; } @@ -48,13 +47,27 @@ public class SiteController { model.addAttribute("recipe", recipe); return "view-recipe"; } - - @GetMapping("/explore") - public String viewExplorePage(Model model) { - //model.addAttribute("allemplist", employeeServiceImpl.getAllEmployee()); - List recipes = recipeService.getAllRecipes(); - model.addAttribute("recipes", recipes); - return "explore"; + + @GetMapping("/recipes/{id}/edit") + public String viewEditRecipePage(@PathVariable Integer id, Model model) { + RecipeDto recipe = recipeService.getRecipeById(id); + model.addAttribute("recipe", recipe); + return "update-recipe"; } + @GetMapping("/explore") + public String explore( + @RequestParam(required = false) String q, + @RequestParam(required = false) List tags, + @RequestParam(required = false) List prices, + @RequestParam(required = false) List cookTime, + @RequestParam(required = false) List prepTime, + Model model + ) { + List recipes = recipeService.getRecipes(q, tags, prices, cookTime, prepTime); + model.addAttribute("recipes", recipes); + model.addAttribute("q", q); + model.addAttribute("tags", tags); + return "explore"; + } } \ No newline at end of file diff --git a/src/main/java/com/example/demo/controller/UserController.java b/src/main/java/com/example/demo/controller/UserController.java index 059a688..0250e33 100644 --- a/src/main/java/com/example/demo/controller/UserController.java +++ b/src/main/java/com/example/demo/controller/UserController.java @@ -4,8 +4,11 @@ import java.security.Principal; import java.util.List; import java.util.Optional; +import org.springframework.context.annotation.Bean; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -33,11 +36,11 @@ public class UserController { this.userService = userService; this.userRepo = userRepo; } + // build create user REST API @PostMapping public ResponseEntity saveUser(@RequestBody User user) { - return new ResponseEntity(userService.saveUser(user), HttpStatus.CREATED); } diff --git a/src/main/java/com/example/demo/dto/ProfileDto.java b/src/main/java/com/example/demo/dto/ProfileDto.java new file mode 100644 index 0000000..ca7e057 --- /dev/null +++ b/src/main/java/com/example/demo/dto/ProfileDto.java @@ -0,0 +1,61 @@ +package com.example.demo.dto; + +import java.util.List; + +public class ProfileDto { + private Integer id; + private String username; + private String displayName; + private String bio; + private List recipes; + + public ProfileDto() { + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getBio() { + return bio; + } + + public void setBio(String bio) { + this.bio = bio; + } + + public List getRecipes() { + return recipes; + } + + public void setRecipes(List recipes) { + this.recipes = recipes; + } + + public String getEffectiveDisplayName() { + if (displayName != null && !displayName.isBlank()) { + return displayName; + } + return username; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/dto/RecipeDto.java b/src/main/java/com/example/demo/dto/RecipeDto.java index ff5cb80..7a2531b 100644 --- a/src/main/java/com/example/demo/dto/RecipeDto.java +++ b/src/main/java/com/example/demo/dto/RecipeDto.java @@ -17,6 +17,7 @@ public class RecipeDto { private List steps; private List images; private List tags; + private Integer cost; public RecipeDto() { super(); @@ -24,7 +25,7 @@ public class RecipeDto { public RecipeDto(String title, String description, Integer prepTimeMinutes, Integer cookTimeMinutes, Integer servings, UserDto userDto, String status, List ingredients, - List steps, List images, List tags) { + List steps, List images, List tags, Integer cost) { super(); this.title = title; this.description = description; @@ -37,6 +38,7 @@ public class RecipeDto { this.steps = steps; this.images = images; this.tags = tags; + this.cost = cost; } // getters and setters @@ -136,4 +138,14 @@ public class RecipeDto { public void setId(Integer id) { this.id = id; } + + public Integer getCost() { + return cost; + } + + public void setCost(Integer cost) { + this.cost = cost; + } + + } diff --git a/src/main/java/com/example/demo/dto/UpdateProfileDto.java b/src/main/java/com/example/demo/dto/UpdateProfileDto.java new file mode 100644 index 0000000..fce6e13 --- /dev/null +++ b/src/main/java/com/example/demo/dto/UpdateProfileDto.java @@ -0,0 +1,25 @@ +package com.example.demo.dto; + +public class UpdateProfileDto { + private String displayName; + private String bio; + + public UpdateProfileDto() { + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getBio() { + return bio; + } + + public void setBio(String bio) { + this.bio = bio; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/dto/UserDto.java b/src/main/java/com/example/demo/dto/UserDto.java index 7b8a011..2cc8c70 100644 --- a/src/main/java/com/example/demo/dto/UserDto.java +++ b/src/main/java/com/example/demo/dto/UserDto.java @@ -4,6 +4,8 @@ public class UserDto { private Integer id; private String username; private String email; + private String displayName; + private String bio; public UserDto() { } @@ -14,6 +16,14 @@ public class UserDto { this.email = email; } + public UserDto(Integer id, String username, String email, String displayName, String bio) { + this.id = id; + this.username = username; + this.email = email; + this.displayName = displayName; + this.bio = bio; + } + public Integer getId() { return id; } @@ -38,4 +48,26 @@ public class UserDto { this.email = email; } -} + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getBio() { + return bio; + } + + public void setBio(String bio) { + this.bio = bio; + } + + public String getEffectiveDisplayName() { + if (displayName != null && !displayName.isBlank()) { + return displayName; + } + return username; + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/entity/Recipe.java b/src/main/java/com/example/demo/entity/Recipe.java index 616ed38..3acf02d 100644 --- a/src/main/java/com/example/demo/entity/Recipe.java +++ b/src/main/java/com/example/demo/entity/Recipe.java @@ -40,6 +40,10 @@ public class Recipe { private String status; + @NotNull(message = "Please Provide a cost") + @Positive(message = "This value cannot be negative") + private Integer cost; + private LocalDateTime createdAt; private LocalDateTime updatedAt; @@ -76,7 +80,7 @@ public class Recipe { } public Recipe(String title, String description, Integer prepTimeMinutes, Integer cookTimeMinutes, Integer servings, - User user, String status) { + User user, String status, Integer cost) { this.title = title; this.description = description; this.prepTimeMinutes = prepTimeMinutes; @@ -86,6 +90,7 @@ public class Recipe { this.status = status; this.createdAt = LocalDateTime.now(); this.updatedAt = LocalDateTime.now(); + this.cost = cost; } // Getters and setters @@ -208,4 +213,12 @@ public class Recipe { public void setUsers(Set users) { this.users = users; } + + public Integer getCost() { + return cost; + } + + public void setCost(Integer cost) { + this.cost = cost; + } } \ No newline at end of file diff --git a/src/main/java/com/example/demo/entity/User.java b/src/main/java/com/example/demo/entity/User.java index f7b0a1d..1597aeb 100644 --- a/src/main/java/com/example/demo/entity/User.java +++ b/src/main/java/com/example/demo/entity/User.java @@ -34,6 +34,12 @@ public class User implements UserDetails { @Column(nullable = false, unique = true) private String username; + @Column(length = 100) + private String displayName; + + @Column(length = 1000) + private String bio; + @Column(nullable = false) private String role; @@ -118,6 +124,22 @@ public class User implements UserDetails { this.username = username; } + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(String displayName) { + this.displayName = displayName; + } + + public String getBio() { + return bio; + } + + public void setBio(String bio) { + this.bio = bio; + } + public String getRole() { return role; } @@ -173,4 +195,11 @@ public class User implements UserDetails { public void setFavRecipes(Set favRecipes) { this.FavRecipes = favRecipes; } + + public String getEffectiveDisplayName() { + if (displayName != null && !displayName.isBlank()) { + return displayName; + } + return username; + } } \ No newline at end of file diff --git a/src/main/java/com/example/demo/service/Impl/RecipeServiceImpl.java b/src/main/java/com/example/demo/service/Impl/RecipeServiceImpl.java index da898cb..d729629 100644 --- a/src/main/java/com/example/demo/service/Impl/RecipeServiceImpl.java +++ b/src/main/java/com/example/demo/service/Impl/RecipeServiceImpl.java @@ -71,12 +71,17 @@ public class RecipeServiceImpl implements RecipeService { List tagDtos = recipe.getTags().stream().map(ri -> new TagDto(ri.getName())).toList(); - UserDto userDto = new UserDto(recipe.getUser().getId(), recipe.getUser().getUsername(), - recipe.getUser().getEmail()); + UserDto userDto = new UserDto( + recipe.getUser().getId(), + recipe.getUser().getUsername(), + recipe.getUser().getEmail(), + recipe.getUser().getDisplayName(), + recipe.getUser().getBio() + ); RecipeDto dto = new RecipeDto(recipe.getTitle(), recipe.getDescription(), recipe.getPrepTimeMinutes(), recipe.getCookTimeMinutes(), recipe.getServings(), userDto, recipe.getStatus(), ingredientDtos, - stepDtos, imageDtos, tagDtos); + stepDtos, imageDtos, tagDtos, recipe.getCost()); dto.setId(recipe.getId()); @@ -130,7 +135,7 @@ public class RecipeServiceImpl implements RecipeService { enforceUploadLimit(currentUser); Recipe recipe = new Recipe(dto.getTitle(), dto.getDescription(), dto.getPrepTimeMinutes(), - dto.getCookTimeMinutes(), dto.getServings(), currentUser, dto.getStatus()); + dto.getCookTimeMinutes(), dto.getServings(), currentUser, dto.getStatus(), dto.getCost()); if (dto.getIngredients() != null) { for (RecipeIngredientDto riDto : dto.getIngredients()) { @@ -146,6 +151,7 @@ public class RecipeServiceImpl implements RecipeService { riDto.getNotes()); recipe.getRecipeIngredients().add(ri); + } } @@ -216,6 +222,7 @@ public class RecipeServiceImpl implements RecipeService { existingRecipe.setCookTimeMinutes(recipeDto.getCookTimeMinutes()); existingRecipe.setServings(recipeDto.getServings()); existingRecipe.setStatus(recipeDto.getStatus()); + existingRecipe.setCost(recipeDto.getCost()); List updatedIngredients = recipeDto.getIngredients(); List ingredientsToRemove = new ArrayList<>(); @@ -369,11 +376,11 @@ public class RecipeServiceImpl implements RecipeService { @Override @Transactional - public List getRecipes(String name, List tags) { + public List getRecipes(String name, List tags, List prices, List cookTime, List prepTime) { List recipes; - if (!name.isBlank()) { + if ((name != null) && (!name.isBlank())) { recipes = recipeRepository.findByTitleContainingIgnoreCase(name); } @@ -381,12 +388,50 @@ public class RecipeServiceImpl implements RecipeService { recipes = recipeRepository.findAll(); } - if (!tags.isEmpty() && !recipes.isEmpty()) { + if ((tags != null) && (!tags.isEmpty()) && !recipes.isEmpty()) { recipes = recipes.stream() .filter(recipe -> recipe.getTags().stream().anyMatch(tag -> tags.contains(tag.getName()))) .collect(Collectors.toList()); } + if (prices != null && !prices.isEmpty() && !recipes.isEmpty()) { + recipes = recipes.stream() + .filter(recipe -> prices.contains(recipe.getCost())) + .collect(Collectors.toList()); + } + + if (cookTime != null && !cookTime.isEmpty() && !recipes.isEmpty()) { + recipes = recipes.stream() + .filter(recipe -> { + int minutes = recipe.getCookTimeMinutes(); + for (Integer ct : cookTime) { + if (ct == 15 && minutes <= 15) return true; + if (ct == 30 && minutes > 15 && minutes <= 30) return true; + if (ct == 60 && minutes > 30 && minutes <= 60) return true; + if (ct == 120 && minutes > 60 && minutes <= 120) return true; + if (ct == 121 && minutes > 120) return true; + } + return false; + }) + .collect(Collectors.toList()); + } + + if (prepTime != null && !prepTime.isEmpty() && !recipes.isEmpty()) { + recipes = recipes.stream() + .filter(recipe -> { + int minutes = recipe.getPrepTimeMinutes(); + for (Integer ct : prepTime) { + if (ct == 15 && minutes <= 15) return true; + if (ct == 30 && minutes > 15 && minutes <= 30) return true; + if (ct == 60 && minutes > 30 && minutes <= 60) return true; + if (ct == 240 && minutes > 60 && minutes <= 240) return true; + if (ct == 241 && minutes > 240) return true; + } + return false; + }) + .collect(Collectors.toList()); + } + List recipeList = new ArrayList<>(); for (Recipe recipe : recipes) { diff --git a/src/main/java/com/example/demo/service/Impl/UserServiceImpl.java b/src/main/java/com/example/demo/service/Impl/UserServiceImpl.java index dd29369..3283988 100644 --- a/src/main/java/com/example/demo/service/Impl/UserServiceImpl.java +++ b/src/main/java/com/example/demo/service/Impl/UserServiceImpl.java @@ -2,21 +2,20 @@ package com.example.demo.service.Impl; import java.util.ArrayList; import java.util.List; -import java.util.Optional; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; -import com.example.demo.dto.ImageDto; -import com.example.demo.dto.RecipeDto; -import com.example.demo.dto.RecipeIngredientDto; -import com.example.demo.dto.StepDto; -import com.example.demo.dto.TagDto; +import com.example.demo.dto.ProfileDto; +import com.example.demo.dto.UpdateProfileDto; import com.example.demo.dto.UserDto; +import com.example.demo.dto.RecipeDto; import com.example.demo.entity.Recipe; import com.example.demo.entity.User; import com.example.demo.exception.NotFoundException; import com.example.demo.repository.RecipeRepo; import com.example.demo.repository.UserRepo; +import com.example.demo.service.RecipeService; import com.example.demo.service.UserService; import jakarta.transaction.Transactional; @@ -26,15 +25,27 @@ public class UserServiceImpl implements UserService { private UserRepo userRepository; private RecipeRepo recipeRepository; + private PasswordEncoder passwordEncoder; + private RecipeService recipeService; - public UserServiceImpl(UserRepo userRepository, RecipeRepo recipeRepository) { + public UserServiceImpl(UserRepo userRepository, RecipeRepo recipeRepository, + PasswordEncoder passwordEncoder, RecipeService recipeService) { super(); this.userRepository = userRepository; this.recipeRepository = recipeRepository; + this.passwordEncoder = passwordEncoder; + this.recipeService = recipeService; } + @Override public UserDto convertToDto(User user) { - return new UserDto(user.getId(), user.getUsername(), user.getEmail()); + return new UserDto( + user.getId(), + user.getUsername(), + user.getEmail(), + user.getDisplayName(), + user.getBio() + ); } @Override @@ -43,25 +54,24 @@ public class UserServiceImpl implements UserService { user.setRole("ROLE_USER"); } user.setBanned(false); + user.setHashedpassword(passwordEncoder.encode(user.getPassword())); return userRepository.save(user); } @Override public List getAllUsers() { - List list = new ArrayList<>(); for (User user : userRepository.findAll()) { UserDto userDto = convertToDto(user); list.add(userDto); } - return list; } @Override - public UserDto getUserById(Integer Id) { - - return convertToDto(userRepository.findById(Id).orElseThrow(() -> new NotFoundException("User", "id", Id))); + public UserDto getUserById(Integer id) { + return convertToDto(userRepository.findById(id) + .orElseThrow(() -> new NotFoundException("User", "id", id))); } @Override @@ -80,9 +90,9 @@ public class UserServiceImpl implements UserService { } @Override - public UserDto updateUser(User user, Integer Id) { - - User existingUser = userRepository.findById(Id).orElseThrow(() -> new NotFoundException("User", "id", Id)); + public UserDto updateUser(User user, Integer id) { + User existingUser = userRepository.findById(id) + .orElseThrow(() -> new NotFoundException("User", "id", id)); existingUser.setUsername(user.getUsername()); existingUser.setEmail(user.getEmail()); @@ -93,9 +103,10 @@ public class UserServiceImpl implements UserService { } @Override - public void deleteUser(Integer Id) { - userRepository.findById(Id).orElseThrow(() -> new NotFoundException("User", "id", Id)); - userRepository.deleteById(Id); + public void deleteUser(Integer id) { + userRepository.findById(id) + .orElseThrow(() -> new NotFoundException("User", "id", id)); + userRepository.deleteById(id); } @Override @@ -106,27 +117,26 @@ public class UserServiceImpl implements UserService { Recipe existingRecipe = recipeRepository.findById(recipeId) .orElseThrow(() -> new NotFoundException("Recipe", "id", recipeId)); - userRepository.save(existingUser); existingUser.getFavRecipes().remove(existingRecipe); - + userRepository.save(existingUser); } @Override public List getUsersByName(String name) { List users = userRepository.findByUsernameContainingIgnoreCase(name); - if (users.isEmpty()) { - throw new NotFoundException("User", "username containing", name); - } + if (users.isEmpty()) { + throw new NotFoundException("User", "username containing", name); + } - List userList = new ArrayList<>(); + List userList = new ArrayList<>(); - for (User user : users) { - UserDto dto = convertToDto(user); - userList.add(dto); - } - return userList; + for (User user : users) { + UserDto dto = convertToDto(user); + userList.add(dto); + } + return userList; } @Override @@ -164,4 +174,50 @@ public class UserServiceImpl implements UserService { userRepository.save(user); return convertToDto(user); } -} + + @Override + @Transactional + public ProfileDto getProfileByUserId(Integer userId) { + User user = userRepository.findById(userId) + .orElseThrow(() -> new NotFoundException("User", "id", userId)); + + List recipes = recipeRepository.findByUserId(userId); + List recipeDtos = new ArrayList<>(); + + for (Recipe recipe : recipes) { + recipeDtos.add(recipeService.convertToDto(recipe)); + } + + ProfileDto profile = new ProfileDto(); + profile.setId(user.getId()); + profile.setUsername(user.getUsername()); + profile.setDisplayName(user.getDisplayName()); + profile.setBio(user.getBio()); + profile.setRecipes(recipeDtos); + + return profile; + } + + @Override + @Transactional + public ProfileDto getCurrentUserProfile(String username) { + User user = userRepository.findByUsername(username) + .orElseThrow(() -> new NotFoundException("User", "username", username)); + + return getProfileByUserId(user.getId()); + } + + @Override + @Transactional + public ProfileDto updateProfile(String username, UpdateProfileDto dto) { + User user = userRepository.findByUsername(username) + .orElseThrow(() -> new NotFoundException("User", "username", username)); + + user.setDisplayName(dto.getDisplayName()); + user.setBio(dto.getBio()); + + userRepository.save(user); + + return getProfileByUserId(user.getId()); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/demo/service/RecipeService.java b/src/main/java/com/example/demo/service/RecipeService.java index 623a07c..0882b35 100644 --- a/src/main/java/com/example/demo/service/RecipeService.java +++ b/src/main/java/com/example/demo/service/RecipeService.java @@ -17,7 +17,7 @@ public interface RecipeService { RecipeDto getRecipeById(Integer recipeId); - List getRecipes(String name, List tags); + List getRecipes(String name, List tags, List prices, List cookTime, List prepTime); RecipeDto updateRecipe(RecipeDto recipedto, Integer Id, String currentUsername); diff --git a/src/main/java/com/example/demo/service/UserService.java b/src/main/java/com/example/demo/service/UserService.java index cf315f5..ec96be1 100644 --- a/src/main/java/com/example/demo/service/UserService.java +++ b/src/main/java/com/example/demo/service/UserService.java @@ -2,6 +2,8 @@ package com.example.demo.service; import java.util.List; +import com.example.demo.dto.ProfileDto; +import com.example.demo.dto.UpdateProfileDto; import com.example.demo.dto.UserDto; import com.example.demo.entity.User; @@ -31,4 +33,10 @@ public interface UserService { UserDto makeAdmin(Integer id); UserDto makeUser(Integer id); + + ProfileDto getProfileByUserId(Integer userId); + + ProfileDto getCurrentUserProfile(String username); + + ProfileDto updateProfile(String username, UpdateProfileDto dto); } diff --git a/src/main/resources/static/css/explore.css b/src/main/resources/static/css/explore.css index 8503a41..042e0c0 100644 --- a/src/main/resources/static/css/explore.css +++ b/src/main/resources/static/css/explore.css @@ -191,28 +191,22 @@ body, html { .main-content { width: 100%; flex-grow: 1; - display: flex; + /*display: flex; this line was breaking the searched results. They returned recipes would not load at the top of the page*/ flex-direction: column; justify-content: flex-start; align-items: flex-start; - overflow: scroll; + overflow: auto; scrollbar-color: var(--dusty-red) var(--pale-yellow); - height: 100%; + height: auto; } -/* safari and old browsers*/ -::-webkit-scrollbar-track { - background: var(--pale-yellow); -} -::-webkit-scrollbar-thumb { - background: var(--dusty-red); -} + /* ========================= Search Bar ========================= */ .search-bar, input[type="search"] { - width: 90%; +/* width: 90%; */ margin: 10px; flex-grow: 1; display: flex; @@ -266,10 +260,76 @@ input[type="search"]::-webkit-search-cancel-button { } +#tag-input-wrapper { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 5px; + background: var(--dusty-red); + border-radius: 10px; + padding: 6px 10px; + min-height: 50px; + flex: 1; + cursor: text; +} + +#tag-input-wrapper input[type="text"] { + flex: 1; + min-width: 140px; + background: transparent; + border: none; + outline: none; + color: var(--dark-yellow); + font-size: 20px; + font-family: 'Mali', cursive; + font-weight: 600; + height: auto; + padding: 0; + margin: 0; + width: auto; +} + +#chips-container { + display: flex; + flex-wrap: wrap; + gap: 15px; +} + +.tag-chip { + display: inline-flex; + align-items: center; + gap: 5px; + background: var(--dark); + min-height: 32px; + color: var(--dark-yellow); + border-radius: 20px; + padding: 2px 8px 3px 12px; + font-size: 0.75em; + font-weight: 700; + white-space: nowrap; +} + +.tag-chip button { + background: none; + border: none; + color: var(--dark-yellow); + cursor: pointer; + padding: 0; + font-size: 1.4em; + line-height: 1; + opacity: 0.8; + font-family: 'Mali', cursive; + font-weight: 800; +} + +.tag-chip button:hover { opacity: 1; } + + /* ========================= Recipe Cards Layout ========================= */ .recipe-card { + padding-top: 20px; margin-top: 35px; width: 99.5%; display: flex; @@ -279,8 +339,12 @@ input[type="search"]::-webkit-search-cancel-button { flex-direction: row; height: fit-content; padding-right: 10px; + overflow-y: auto; + flex: 1; + scrollbar-color: var(--dusty-red) var(--pale-yellow); } + a { text-decoration: none; color: var(--dark); diff --git a/src/main/resources/templates/create-account.html b/src/main/resources/templates/create-account.html index 9343426..7e304aa 100644 --- a/src/main/resources/templates/create-account.html +++ b/src/main/resources/templates/create-account.html @@ -2,6 +2,9 @@ + + + Create Thyme Crunch Account @@ -57,34 +60,39 @@ - + \ No newline at end of file diff --git a/src/main/resources/templates/home.html b/src/main/resources/templates/home.html index 619f36c..bd28522 100644 --- a/src/main/resources/templates/home.html +++ b/src/main/resources/templates/home.html @@ -21,7 +21,7 @@
  • Home
  • Explore
  • -
  • Profile
  • +
  • Profile
  • Saved
  • diff --git a/src/main/resources/templates/my-profile.html b/src/main/resources/templates/my-profile.html new file mode 100644 index 0000000..3784d47 --- /dev/null +++ b/src/main/resources/templates/my-profile.html @@ -0,0 +1,61 @@ + + + + + My Profile + + +

    My Profile

    + +

    Username: username

    +

    + Public Profile: + View my public profile +

    + +

    Edit Profile

    + +
    +
    + +
    + +
    + +
    +
    + +
    + +
    + + +
    + +

    My Recipes

    + +
    +

    You have not created any recipes yet.

    +
    + +
    +
    +

    Recipe Title

    + +

    + Author: + + Author Name + +

    + +

    Recipe description

    + + View Recipe + | + Edit Recipe +
    +
    + + \ No newline at end of file diff --git a/src/main/resources/templates/public-profile.html b/src/main/resources/templates/public-profile.html new file mode 100644 index 0000000..6bc91c8 --- /dev/null +++ b/src/main/resources/templates/public-profile.html @@ -0,0 +1,195 @@ + + + + + Explore Recipes + + +

    Explore Recipes

    + + + +
    + + + +

    Prep Time

    +
    +
    +
    +
    + + +

    Cook Time

    +
    +
    +
    +
    + + +

    Price

    +
    +
    +
    + +
    + +
    +

    No recipes found.

    +
    + +
    +
    +

    + Recipe Title +

    + +

    + Author: + + Author Name + +

    + +

    Recipe description

    + +

    + Prep: 0 min | + Cook: 0 min | + Servings: 0 | + Cost: 0 +

    + +
    + Recipe Image +
    + +

    View Recipe

    +
    +
    + + + + \ No newline at end of file diff --git a/src/main/resources/templates/update-recipe.html b/src/main/resources/templates/update-recipe.html new file mode 100644 index 0000000..e69de29