часть визуала
This commit is contained in:
parent
e60943d591
commit
2a90a06662
BIN
data.mv.db
BIN
data.mv.db
Binary file not shown.
@ -0,0 +1,85 @@
|
|||||||
|
package com.example.demo.users.api;
|
||||||
|
|
||||||
|
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.bind.support.SessionStatus;
|
||||||
|
|
||||||
|
import com.example.demo.core.configuration.Constants;
|
||||||
|
import com.example.demo.core.session.SessionCart;
|
||||||
|
import com.example.demo.games.api.GameDto;
|
||||||
|
import com.example.demo.games.model.GameEntity;
|
||||||
|
import com.example.demo.games.service.GameService;
|
||||||
|
import com.example.demo.genres.model.GenreEntity;
|
||||||
|
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@RequestMapping(UserCatalogController.URL)
|
||||||
|
public class UserCatalogController {
|
||||||
|
|
||||||
|
private static final String CATALOG_VIEW = "catalog";
|
||||||
|
public static final String URL = "/catalog";
|
||||||
|
private static final String PAGE_ATTRIBUTE = "page";
|
||||||
|
private static final String ORDER_ATTRIBUTE = "order";
|
||||||
|
private static final String CART_ATTRIBUTE = "cart";
|
||||||
|
|
||||||
|
|
||||||
|
private final GameService gameService;
|
||||||
|
private final SessionCart cart;
|
||||||
|
|
||||||
|
public UserCatalogController(GameService gameService, SessionCart cart){
|
||||||
|
this.gameService = gameService;
|
||||||
|
this.cart = cart;
|
||||||
|
}
|
||||||
|
|
||||||
|
private GameDto toGameDto(GameEntity entity) {
|
||||||
|
var dto = new GameDto();
|
||||||
|
dto.setId(entity.getId());
|
||||||
|
dto.setGenres(entity.getGenres().stream().map(GenreEntity::getId).toList());
|
||||||
|
dto.setDescription(entity.getDescription());
|
||||||
|
dto.setName(entity.getName());
|
||||||
|
dto.setPrice(entity.getPrice());
|
||||||
|
dto.setTypeId(entity.getType().getId());
|
||||||
|
return dto;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping
|
||||||
|
public String getCatalog(
|
||||||
|
@RequestParam(name = PAGE_ATTRIBUTE, defaultValue = "0") int page,
|
||||||
|
Model model) {
|
||||||
|
model.addAttribute(ORDER_ATTRIBUTE, new UserCartDto());
|
||||||
|
model.addAttribute(PAGE_ATTRIBUTE, page);
|
||||||
|
model.addAttribute("games",
|
||||||
|
gameService.getAll(0, 0).stream()
|
||||||
|
.map(this::toGameDto)
|
||||||
|
.toList());
|
||||||
|
return CATALOG_VIEW;
|
||||||
|
}
|
||||||
|
///catalog/addCart/{id}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
public String addOrderToCart(
|
||||||
|
@ModelAttribute(name = ORDER_ATTRIBUTE) @Valid UserCartDto order,
|
||||||
|
BindingResult bindingResult,
|
||||||
|
SessionStatus status,
|
||||||
|
Model model) {
|
||||||
|
if (bindingResult.hasErrors()) {
|
||||||
|
return CATALOG_VIEW;
|
||||||
|
}
|
||||||
|
status.setComplete();
|
||||||
|
order.setGameName(gameService.get(order.getGame()).getName());
|
||||||
|
order.setPrice(gameService.get(order.getGame()).getPrice());
|
||||||
|
cart.computeIfPresent(order.hashCode(), (key, value) -> {
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
cart.put(order.hashCode(), order);
|
||||||
|
return Constants.REDIRECT_VIEW + URL;
|
||||||
|
}
|
||||||
|
}
|
@ -40,10 +40,12 @@ td form {
|
|||||||
|
|
||||||
.my-navbar {
|
.my-navbar {
|
||||||
background-color: #08D9D6 !important;
|
background-color: #08D9D6 !important;
|
||||||
|
color: rgb(30, 29, 29);
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-navbar .link a:hover {
|
.my-navbar .link a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
|
color: rgb(30, 29, 29);
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-navbar .logo {
|
.my-navbar .logo {
|
||||||
|
BIN
src/main/resources/public/risk-of-rain-returns.jpg
Normal file
BIN
src/main/resources/public/risk-of-rain-returns.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 53 KiB |
@ -0,0 +1,53 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{default}">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Каталог</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<main layout:fragment="content" class="w-50 mx-auto">
|
||||||
|
<div class="tab-content mt-2">
|
||||||
|
<h2 class="text-center">Игры</h2>
|
||||||
|
<div className="row mx-auto">
|
||||||
|
<div className="img pt-4 ps-5 mt-4 col-8">
|
||||||
|
<img className="img" src="/risk-of-rain-returns.jpg" width="100%" />
|
||||||
|
</div>
|
||||||
|
<div className="pe-3 flex-column div col-4">
|
||||||
|
<div className="pt-4 ps-2">Популярные новинки:</div>
|
||||||
|
<div><img className="p-2" src="/risk-of-rain-returns.jpg" width="100%" /></div>
|
||||||
|
<div><img className="p-2" src="/risk-of-rain-returns.jpg" width="100%" /></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tab-pane container active table-responsive" id="orders">
|
||||||
|
<table class="table">
|
||||||
|
<thead>
|
||||||
|
<th class="w-25"></th>
|
||||||
|
<th>Название</th>
|
||||||
|
<th class="w-auto">Описание</th>
|
||||||
|
<th>Цена</th>
|
||||||
|
<th></th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="gamee : ${games}">
|
||||||
|
<th scope="row"><img src="/risk-of-rain-returns.jpg" class="w-100"></th>
|
||||||
|
<th scope="row" th:text="${gamee.name}"></th>
|
||||||
|
<th scope="row" th:text="${gamee.description}"></th>
|
||||||
|
<th scope="row" th:text="${gamee.Price}"></th>
|
||||||
|
<th>
|
||||||
|
<form th:action="@{/catalog}" th:object="${order}" method="post">
|
||||||
|
<select hidden="hidden" th:field="*{game}" class="form-select">
|
||||||
|
<option th:value="${gamee.id}"></option>
|
||||||
|
</select>
|
||||||
|
<button type="submit" class="btn btn-link button-link"><i class="bi bi-cart2 d-inline-block align-top me-1 logo"></i></button>
|
||||||
|
</form>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -47,6 +47,13 @@
|
|||||||
</a>
|
</a>
|
||||||
<a class="nav-link" href="/h2-console/" target="_blank">Консоль H2</a>
|
<a class="nav-link" href="/h2-console/" target="_blank">Консоль H2</a>
|
||||||
</th:block>
|
</th:block>
|
||||||
|
<a class="nav-link" href="/catalog"
|
||||||
|
th:classappend="${activeLink.startsWith('/catalog') ? 'active' : ''}">
|
||||||
|
Каталог
|
||||||
|
</a>
|
||||||
|
<a class="nav-link" href="/">
|
||||||
|
Заказы
|
||||||
|
</a>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="navbar-nav" th:if="${not #strings.isEmpty(userName)}">
|
<ul class="navbar-nav" th:if="${not #strings.isEmpty(userName)}">
|
||||||
<form th:action="@{/logout}" method="post">
|
<form th:action="@{/logout}" method="post">
|
||||||
@ -66,7 +73,7 @@
|
|||||||
<main class="container-fluid p-2" layout:fragment="content">
|
<main class="container-fluid p-2" layout:fragment="content">
|
||||||
</main>
|
</main>
|
||||||
<footer class="my-footer mt-auto d-flex flex-shrink-0 justify-content-center align-items-center">
|
<footer class="my-footer mt-auto d-flex flex-shrink-0 justify-content-center align-items-center">
|
||||||
Автор, [[${#dates.year(#dates.createNow())}]]
|
Яковлев М.Г., [[${#dates.year(#dates.createNow())}]]
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user