diff --git a/backend/src/main/java/com/example/backend/BackendApplication.java b/backend/src/main/java/com/example/backend/BackendApplication.java index 0b18e99..183ad5a 100644 --- a/backend/src/main/java/com/example/backend/BackendApplication.java +++ b/backend/src/main/java/com/example/backend/BackendApplication.java @@ -8,6 +8,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication; import com.example.backend.categories.model.CategorieEntity; import com.example.backend.categories.service.CategorieService; +import com.example.backend.favorites.model.FavoriteEntity; +import com.example.backend.favorites.service.FavoriteService; import com.example.backend.movies.model.MovieEntity; import com.example.backend.movies.service.MovieService; import com.example.backend.users.service.UserService; @@ -21,12 +23,15 @@ public class BackendApplication implements CommandLineRunner { private final UserService userService; private final CategorieService categorieService; private final MovieService movieService; + private final FavoriteService favoriyService; public BackendApplication(UserService userService, CategorieService categorieService, - MovieService movieService) { + MovieService movieService, + FavoriteService favoriyService) { this.userService = userService; this.categorieService = categorieService; + this.favoriyService = favoriyService; this.movieService = movieService; } @@ -84,6 +89,11 @@ public class BackendApplication implements CommandLineRunner { // categorieService.create(cat4); // categorieService.create(cat5); // movieService.create(mov1); + favoriyService.create(new FavoriteEntity(null, userService.get(2), movieService.get(98))); + // movieService.get(98)); + // for (var fav : favoriyService.getAll(2)) { + // favoriyService.delete(fav.getId()); + // } _logger.info("The program is started"); } diff --git a/backend/src/main/java/com/example/backend/favorites/repository/FavoriteRepository.java b/backend/src/main/java/com/example/backend/favorites/repository/FavoriteRepository.java index 52b6636..81c27fe 100644 --- a/backend/src/main/java/com/example/backend/favorites/repository/FavoriteRepository.java +++ b/backend/src/main/java/com/example/backend/favorites/repository/FavoriteRepository.java @@ -7,7 +7,10 @@ import org.springframework.data.repository.CrudRepository; import com.example.backend.favorites.model.FavoriteEntity; public interface FavoriteRepository extends CrudRepository<FavoriteEntity, Integer> { + List<FavoriteEntity> findByUserId(Integer userId); + List<FavoriteEntity> findByUserIdAndMovieId(Integer userId, Integer movieId); + Optional<FavoriteEntity> findOneByUserIdAndId(Integer userId, Integer id); } diff --git a/backend/src/main/java/com/example/backend/favorites/service/FavoriteService.java b/backend/src/main/java/com/example/backend/favorites/service/FavoriteService.java index 4058ae6..7849d62 100644 --- a/backend/src/main/java/com/example/backend/favorites/service/FavoriteService.java +++ b/backend/src/main/java/com/example/backend/favorites/service/FavoriteService.java @@ -31,6 +31,12 @@ public class FavoriteService { return repository.findById(id).orElseThrow(() -> new NotFoundException(FavoriteEntity.class, id)); } + // @Transactional(readOnly = true) + // public List<FavoriteEntity> getForAddToFavorite(Integer userId, Integer + // movieId) { + // return repository.findByUserIdAndMovieId(userId, movieId); + // } + @Transactional public FavoriteEntity create(FavoriteEntity entity) { return repository.save(entity); diff --git a/backend/src/main/java/com/example/backend/movies/api/MovieUserController.java b/backend/src/main/java/com/example/backend/movies/api/MovieUserController.java index 7b2cf16..c4ae309 100644 --- a/backend/src/main/java/com/example/backend/movies/api/MovieUserController.java +++ b/backend/src/main/java/com/example/backend/movies/api/MovieUserController.java @@ -1,19 +1,26 @@ package com.example.backend.movies.api; +import java.util.List; + import org.modelmapper.ModelMapper; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import com.example.backend.categories.service.CategorieService; import com.example.backend.core.configurations.Constants; +import com.example.backend.favorites.model.FavoriteEntity; +import com.example.backend.favorites.service.FavoriteService; import com.example.backend.movies.model.MovieEntity; import com.example.backend.movies.service.MovieService; +import com.example.backend.users.service.UserService; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; +import org.springframework.security.core.Authentication; import jakarta.validation.Valid; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; @@ -34,12 +41,21 @@ public class MovieUserController { private final MovieService movieService; private final CategorieService categorieService; + private final UserService userService; + private final FavoriteService favoriteService; + private final ModelMapper modelMapper; - public MovieUserController(MovieService movieService, CategorieService categorieService, ModelMapper modelMapper) { + public MovieUserController(MovieService movieService, + CategorieService categorieService, + ModelMapper modelMapper, + UserService userService, + FavoriteService favoriteService) { this.modelMapper = modelMapper; this.categorieService = categorieService; this.movieService = movieService; + this.userService = userService; + this.favoriteService = favoriteService; } private MovieDTO toDto(MovieEntity entity) { @@ -60,9 +76,15 @@ public class MovieUserController { .stream() .map(this::toDto) .toList()); + model.addAttribute(CATEGORIEID_ATTRIBUTE, model); model.addAttribute("categories", categorieService.getAll()); - model.addAttribute(PAGE_ATTRIBUTE, page); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Integer currentUserId = userService.getCurrentUserId(authentication.getName()); + + List<FavoriteEntity> favs = favoriteService.getAll(currentUserId); + + model.addAttribute("favorites", favs); model.addAttribute(CATEGORIEID_ATTRIBUTE, 0); return MOVIE_VIEW; } @@ -76,13 +98,25 @@ public class MovieUserController { .stream() .map(this::toDto) .toList()); + model.addAttribute("categories", categorieService.getAll()); + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + Integer currentUserId = userService.getCurrentUserId(authentication.getName()); + + List<FavoriteEntity> favs = favoriteService.getAll(currentUserId); + + model.addAttribute("favorites", favs); model.addAttribute(PAGE_ATTRIBUTE, page); model.addAttribute(CATEGORIEID_ATTRIBUTE, categorieId); return MOVIE_VIEW; } + @GetMapping("/addToFavorite/{id}") + public String changeStatusForFavorite() { + return Constants.REDIRECT_VIEW + URL; + } + @GetMapping("/countView") public Integer countView(@RequestParam(name = "movieId", defaultValue = "0") Integer movieId) { return movieService.countView(movieId); diff --git a/backend/src/main/java/com/example/backend/users/repository/UserRepository.java b/backend/src/main/java/com/example/backend/users/repository/UserRepository.java index fd63fff..1a9b14c 100644 --- a/backend/src/main/java/com/example/backend/users/repository/UserRepository.java +++ b/backend/src/main/java/com/example/backend/users/repository/UserRepository.java @@ -9,4 +9,6 @@ import com.example.backend.users.model.UserEntity; public interface UserRepository extends CrudRepository<UserEntity, Integer>, PagingAndSortingRepository<UserEntity, Integer> { Optional<UserEntity> findByLoginIgnoreCase(String login); + + Integer getIdByLoginIgnoreCase(String login); } diff --git a/backend/src/main/java/com/example/backend/users/service/UserService.java b/backend/src/main/java/com/example/backend/users/service/UserService.java index ea0a889..900e891 100644 --- a/backend/src/main/java/com/example/backend/users/service/UserService.java +++ b/backend/src/main/java/com/example/backend/users/service/UserService.java @@ -8,6 +8,7 @@ import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.core.Authentication; import org.springframework.stereotype.Service; import org.springframework.data.domain.Page; import org.springframework.data.domain.Sort; @@ -26,6 +27,7 @@ import com.example.backend.users.repository.UserRepository; @Service public class UserService implements UserDetailsService { + private final UserRepository repository; private final PasswordEncoder passwordEncoder; @@ -96,10 +98,20 @@ public class UserService implements UserDetailsService { return existsentity; } + @Transactional + public Integer getCurrentUserId(String name) { + final Optional<UserEntity> user = repository.findByLoginIgnoreCase(name); + if (user.isEmpty()) { + throw new IllegalArgumentException(); + } + return user.get().getId(); + } + @Override @Transactional(readOnly = true) public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { final UserEntity existUser = getByUsername(username); return new UserPrincipal(existUser); } + } diff --git a/backend/src/main/resources/templates/movie-edit.html b/backend/src/main/resources/templates/movie-edit.html index 713b614..f657b9c 100644 --- a/backend/src/main/resources/templates/movie-edit.html +++ b/backend/src/main/resources/templates/movie-edit.html @@ -30,6 +30,7 @@ <input class="form-control" type="text" id="duration" th:field="*{duration}" /> <div th:if="${#fields.hasErrors('duration')}" th:errors="*{duration}" class="invalid-feedback"></div> </div> + <div class="mb-3"> <label class="form-label" for="categorie">Категория:</label> <select th:field="*{categorieId}" id="categorie" class="form-select"> @@ -40,6 +41,7 @@ <div th:if="${#fields.hasErrors('categorieId')}" th:errors="*{categorieId}" class="invalid-feedback"> </div> </div> + <div class="mb-3 d-flex flex-row"> <button class="btn btn-primary me-2 button-fixed-width" type="submit">Сохранить</button> <a class="btn btn-secondary button-fixed-width" th:href="@{/admin/movies(page=${page})}">Отмена</a> diff --git a/backend/src/main/resources/templates/movies.html b/backend/src/main/resources/templates/movies.html index 40b0056..8495ce5 100644 --- a/backend/src/main/resources/templates/movies.html +++ b/backend/src/main/resources/templates/movies.html @@ -85,10 +85,25 @@ </th:block> + <th:block sec:authorize="hasRole('USER')"> <th:block th:switch="${movies.size()}"> <h2 th:case="0">Данные отсутствуют</h2> <th:block th:case="*"> + + + <!-- + <th:block th:switch="${viewes.size()}"> + <h2 th:case="0"> + д етить колотить + </h2> + <th:block th:case="*"> + + </th:block> + + </th:block> --> + + <div class="categories-container d-flex flex-row justify-content-center mt-3 mb-3"> <div class="category-item d-flex flex-column justify-content-center align-items-center mb-5 mb-md-0" th:each="movie : ${movies}"> @@ -99,39 +114,69 @@ <h5 class="card-title" th:text="${movie.name}"></h5> </div> </div> - <div class="d-flex flex-row me-ms-mt-2"> - <!-- <form th:action="@{/movies/edit/{id}(id=${movie.id})}" method="get"> --> - <input type="hidden" th:name="page" th:value="${page}"> - <button type="submit" class="btn btn-link button-link"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" - class="bi bi-heart-fill" viewBox="0 0 16 16"> - <path fill-rule="evenodd" - d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314" /> - </svg> - </button> - <!-- </form> --> - <!-- <form th:action="@{/movies/delete/{id}(id=${movie.id})}" method="post"> --> - <input type="hidden" th:name="page" th:value="${page}"> - <button type="submit" class="btn btn-link button-link" - onclick="return confirm('Вы уверены?')"> - <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" - class="bi bi-eye-fill" viewBox="0 0 16 16"> - <path d="M10.5 8a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0" /> - <path - d="M0 8s3-5.5 8-5.5S16 8 16 8s-3 5.5-8 5.5S0 8 0 8m8 3.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7" /> - </svg> - </button> - <!-- </form> --> + + + <div class="d-flex flex-row ms-mt-2"> + + <th:block th:switch="${favorites.size()}"> + <h2 th:case="0"> + д етить колотить + </h2> + + <th:block th:case="*"> + <form th:action="@{/movies/addToFavorite/{id}(id=${movie.id})}" method="get"> + <input type="hidden" th:name="page" th:value="${page}"> + <!-- <div th:each="fav : ${favorites}"> --> + <button type="submit" class="btn btn-link button-link" + th:each="fav : ${favorites}"> + <svg th:if="${fav.movie.id} == ${movie.id}" + xmlns="http://www.w3.org/2000/svg" width="16" height="16" + fill="currentColor" class="bi bi-heart-fill" viewBox="0 0 16 16"> + <path fill-rule="evenodd" + d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314" /> + </svg> + <svg th:if="${fav.movie.id} != ${movie.id}" + xmlns="http://www.w3.org/2000/svg" width="16" height="16" + fill="currentColor" class="bi bi-heart" viewBox="0 0 16 16"> + <path fill-rule="evenodd" + d="M8 1.314C12.438-3.248 23.534 4.735 8 15-7.534 4.736 3.562-3.248 8 1.314" /> + </svg> + </button> + <!-- </div> --> + </form> + </th:block> + </th:block> </div> - </div> - </div> </th:block> + + </th:block> - <th:block th:replace="~{ pagination :: pagination ( + + <!-- <form th:action="@{/movies/delete/{id}(id=${movie.id})}" method="post"> --> + <!-- <input type="hidden" th:name="page" th:value="${page}"> + <button type="submit" class="btn btn-link button-link" onclick="return confirm('Вы уверены?')"> + <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" + class="bi bi-eye-fill" viewBox="0 0 16 16"> + <path d="M10.5 8a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0" /> + <path + d="M0 8s3-5.5 8-5.5S16 8 16 8s-3 5.5-8 5.5S0 8 0 8m8 3.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7" /> + </svg> + </button> --> + <!-- </form> --> + <!-- </div> + </div> + </div> --> + + </th:block> + + <th:block th:replace="~{ pagination :: pagination ( url=${'movies'}, totalPages=${totalPages}, - currentPage=${currentPage}) }" /> + currentPage=${currentPage}) }"> + </th:block> + + </th:block> </th:block> diff --git a/data.mv.db b/data.mv.db index 235d3e1..c9d04f6 100644 Binary files a/data.mv.db and b/data.mv.db differ