Всё работает

This commit is contained in:
Nikita Sergeev 2023-04-23 13:00:59 +04:00
parent 52a842d8c9
commit b741f13f4d
24 changed files with 1054 additions and 27 deletions

View File

@ -17,7 +17,6 @@ jar {
}
dependencies {
implementation(project(':front'))
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.h2database:h2:2.1.210'
@ -27,6 +26,14 @@ dependencies {
implementation 'org.springdoc:springdoc-openapi-ui:1.6.5'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-devtools'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
implementation 'org.webjars:bootstrap:5.1.3'
implementation 'org.webjars:jquery:3.6.0'
implementation 'org.webjars:font-awesome:6.1.0'
}
tasks.named('test') {

View File

@ -12,7 +12,8 @@ import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.http.HttpStatus;
@Configuration
class WebConfiguration implements WebMvcConfigurer {
public class WebConfiguration implements WebMvcConfigurer {
public static final String REST_API = "/api";
@Override
public void addCorsMappings(CorsRegistry registry){
registry.addMapping("/**").allowedMethods("*");

View File

@ -1,11 +1,14 @@
package ip.labwork.method.controller;
import ip.labwork.WebConfiguration;
import ip.labwork.method.service.MethodService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(WebConfiguration.REST_API + "/method")
public class MethodController {
private final MethodService speakerService;

View File

@ -1,5 +1,6 @@
package ip.labwork.shop.controller;
import ip.labwork.WebConfiguration;
import ip.labwork.shop.service.ComponentService;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
@ -7,7 +8,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/component")
@RequestMapping(WebConfiguration.REST_API + "/component")
public class ComponentController {
private final ComponentService componentService;

View File

@ -1,6 +1,8 @@
package ip.labwork.shop.controller;
import com.fasterxml.jackson.annotation.JsonProperty;
import ip.labwork.shop.model.Component;
import jakarta.validation.constraints.NotBlank;
public class ComponentDTO {
private long id;
@ -26,15 +28,31 @@ public class ComponentDTO {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getComponentName() {
return componentName;
}
public void setComponentName(String componentName) {
this.componentName = componentName;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getCount() {
return count;
}
public int getPrice() {
return price;
public void setCount(int count) {
this.count = count;
}
}

View File

@ -0,0 +1,55 @@
package ip.labwork.shop.controller;
import ip.labwork.shop.service.ComponentService;
import jakarta.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/component")
public class ComponentMvcController {
private final ComponentService componentService;
public ComponentMvcController(ComponentService componentService) {
this.componentService = componentService;
}
@GetMapping
public String getComponents(Model model) {
model.addAttribute("components", componentService.findAllComponent());
return "component";
}
@GetMapping(value = {"/edit", "/edit/{id}"})
public String editComponent(@PathVariable(required = false) Long id,
Model model) {
if (id == null || id <= 0) {
model.addAttribute("componentDto", new ComponentDTO());
} else {
model.addAttribute("componentId", id);
model.addAttribute("componentDto", new ComponentDTO(componentService.findComponent(id)));
}
return "component-edit";
}
@PostMapping(value = {"/", "/{id}"})
public String saveComponent(@PathVariable(required = false) Long id,
@ModelAttribute @Valid ComponentDTO componentDTO,
BindingResult bindingResult,
Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "component-edit";
}
if (id == null || id <= 0) {
componentService.create(componentDTO);
} else {
componentService.updateComponent(id, componentDTO);
}
return "redirect:/component";
}
@PostMapping("/delete/{id}")
public String deleteComponent(@PathVariable Long id) {
componentService.deleteComponent(id);
return "redirect:/component";
}
}

View File

@ -1,5 +1,6 @@
package ip.labwork.shop.controller;
import ip.labwork.WebConfiguration;
import ip.labwork.shop.service.OrderService;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
@ -7,7 +8,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/order")
@RequestMapping(WebConfiguration.REST_API + "/order")
public class OrderController {
private final OrderService orderService;
public OrderController(OrderService orderService) {

View File

@ -2,6 +2,7 @@ package ip.labwork.shop.controller;
import ip.labwork.shop.model.Order;
import ip.labwork.shop.model.OrderStatus;
import jakarta.validation.constraints.NotBlank;
import java.util.Date;
import java.util.List;
@ -9,7 +10,9 @@ import java.util.Objects;
public class OrderDTO {
private long id;
@NotBlank(message = "Date can't be null or empty")
private Date date = new Date();
@NotBlank(message = "Price can't be null or empty")
private int price;
private OrderStatus status = OrderStatus.Неизвестен;
private List<ProductDTO> productDTOList;
@ -31,10 +34,18 @@ public class OrderDTO {
return id;
}
public void setId(long id) {
this.id = id;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
public int getPrice() {
return price;
}
@ -43,10 +54,6 @@ public class OrderDTO {
this.price = price;
}
public void setDate(Date date) {
this.date = date;
}
public OrderStatus getStatus() {
return status;
}
@ -58,4 +65,8 @@ public class OrderDTO {
public List<ProductDTO> getProductDTOList() {
return productDTOList;
}
public void setProductDTOList(List<ProductDTO> productDTOList) {
this.productDTOList = productDTOList;
}
}

View File

@ -0,0 +1,94 @@
package ip.labwork.shop.controller;
import ip.labwork.shop.model.OrderStatus;
import ip.labwork.shop.service.OrderService;
import ip.labwork.shop.service.ProductService;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
@Controller
@RequestMapping("/order")
public class OrderMvcController {
private final OrderService orderService;
private final ProductService productService;
public OrderMvcController(OrderService orderService, ProductService productService) {
this.orderService = orderService;
this.productService = productService;
}
@GetMapping
public String getOrders(HttpServletRequest request,
Model model) {
Cookie[] cookies = request.getCookies();
List<ProductDTO> productDTOS = new ArrayList<>();
int totalPrice = 0;
for(Cookie cookie : cookies){
if (StringUtils.isNumeric(cookie.getName())){
ProductDTO productDTO = new ProductDTO(productService.findProduct(Long.parseLong(cookie.getName())),Integer.parseInt(cookie.getValue()));
productDTOS.add(productDTO);
totalPrice += productDTO.getPrice() * productDTO.getCount();
}
}
model.addAttribute("productDTOS", productDTOS);
model.addAttribute("totalPrice", totalPrice);
return "order";
}
@PostMapping
public String createOrder(HttpServletRequest request,
HttpServletResponse response) {
Cookie[] cookies = request.getCookies();
OrderDTO orderDTO = new OrderDTO();
List<ProductDTO> productDTOS = new ArrayList<>();
int totalPrice = 0;
for(Cookie temp : cookies){
if (StringUtils.isNumeric(temp.getName())){
ProductDTO productDTO = new ProductDTO(productService.findProduct(Long.parseLong(temp.getName())),Integer.parseInt(temp.getValue()));
productDTOS.add(productDTO);
totalPrice += productDTO.getPrice() * productDTO.getCount();
}
}
orderDTO.setPrice(totalPrice);
orderDTO.setProductDTOList(productDTOS);
orderDTO.setStatus(OrderStatus.Готов);
orderService.create(orderDTO);
response.addCookie(new Cookie("delete",""));
return "redirect:/order";
}
// @PostMapping("/delete/{id}")
// public String deleteProduct(@PathVariable(required = false) Long id, HttpServletRequest request, Model model, HttpServletResponse response){
// Cookie[] cookies = request.getCookies();
// List<ProductDTO> productDTOS = new ArrayList<>();
// int totalPrice = 0;
// for(Cookie temp : cookies){
// if (StringUtils.isNumeric(temp.getName())){
// ProductDTO productDTO;
// if(Long.parseLong(temp.getName()) == id){
// if (Objects.equals(temp.getValue(), "") || Integer.parseInt(temp.getValue()) == 1){
// Cookie userNameCookieRemove = new Cookie(temp.getName(), "");
// userNameCookieRemove.setMaxAge(-1);
// response.addCookie(userNameCookieRemove);
// continue;
// }
// productDTO = new ProductDTO(productService.findProduct(Long.parseLong(temp.getName())),Integer.parseInt(temp.getValue())-1);
// temp.setValue(productDTO.getCount()+"");
// temp.setMaxAge(-1);
// response.addCookie(temp);
// }else{
// productDTO = new ProductDTO(productService.findProduct(Long.parseLong(temp.getName())),Integer.parseInt(temp.getValue()));
// }
// productDTOS.add(productDTO);
// totalPrice += productDTO.getPrice() * productDTO.getCount();
// }
// }
// model.addAttribute("productDTOS", productDTOS);
// model.addAttribute("totalPrice", totalPrice);
// return "order";
// }
}

View File

@ -1,5 +1,6 @@
package ip.labwork.shop.controller;
import ip.labwork.WebConfiguration;
import ip.labwork.shop.service.ProductService;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;
@ -7,7 +8,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/product")
@RequestMapping(WebConfiguration.REST_API + "/product")
public class ProductController {
private final ProductService productService;

View File

@ -1,13 +1,17 @@
package ip.labwork.shop.controller;
import ip.labwork.shop.model.Product;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.util.List;
import java.util.Objects;
public class ProductDTO {
private long id;
@NotBlank(message = "Name can't be null or empty")
private String name;
@NotNull(message = "Price can't be null or empty")
private int price;
private List<ComponentDTO> componentDTOList;
private List<OrderDTO> orderDTOList;
@ -18,7 +22,7 @@ public class ProductDTO {
this.name = product.getProductName();
this.price = product.getPrice();
this.image = product.getImage() == null? "" : new String(product.getImage());
this.componentDTOList = product.getComponents().stream()
this.componentDTOList = product.getComponents() == null ? null : product.getComponents().stream()
.filter(x -> Objects.equals(x.getId().getProductId(), product.getId()))
.map(y -> new ComponentDTO(y.getComponent(), y.getCount()))
.toList();
@ -42,26 +46,42 @@ public class ProductDTO {
return id;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public List<ComponentDTO> getComponentDTOList() {
return componentDTOList;
}
public void setComponentDTOList(List<ComponentDTO> componentDTOList) {
this.componentDTOList = componentDTOList;
}
public List<OrderDTO> getOrderDTOList() {
return orderDTOList;
}
public void setOrderDTOList(List<OrderDTO> orderDTOList) {
this.orderDTOList = orderDTOList;
}
public String getImage() {
return image;
}
@ -70,7 +90,11 @@ public class ProductDTO {
this.image = image;
}
public List<OrderDTO> getOrderDTOList() {
return orderDTOList;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}

View File

@ -0,0 +1,83 @@
package ip.labwork.shop.controller;
import ip.labwork.shop.service.ComponentService;
import ip.labwork.shop.service.ProductService;
import jakarta.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Base64;
@Controller
@RequestMapping("/product")
public class ProductMvcController {
private final ProductService productService;
private final ComponentService componentService;
public ProductMvcController(ProductService productService, ComponentService componentService) {
this.productService = productService;
this.componentService = componentService;
}
@GetMapping
public String getProducts(Model model) {
model.addAttribute("products", productService.findAllProduct());
return "product";
}
@GetMapping(value = {"/edit", "/edit/{id}"})
public String editProduct(@PathVariable(required = false) Long id,
Model model) {
if (id == null || id <= 0) {
model.addAttribute("productDto", new ProductDTO());
} else {
model.addAttribute("productId", id);
model.addAttribute("componentDto", new ComponentDTO());
model.addAttribute("productDto", new ProductDTO(productService.findProduct(id)));
}
model.addAttribute("components", componentService.findAllComponent());
return "product-edit";
}
@PostMapping(value = {"/", "/{id}"})
public String saveProduct(@PathVariable(required = false) Long id,
@RequestParam("file") MultipartFile file,
@ModelAttribute @Valid ProductDTO productDTO,
BindingResult bindingResult,
Model model) throws IOException {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "product-edit";
}
productDTO.setImage("data:image/jpeg;base64," + Base64.getEncoder().encodeToString(file.getBytes()));
if (id == null || id <= 0) {
return "redirect:/product/edit/" + productService.create(productDTO).getId();
} else {
productService.updateFields(id, productDTO);
return "redirect:/product/edit/" + id;
}
}
@PostMapping("/delete/{id}")
public String deleteProduct(@PathVariable Long id) {
productService.deleteProduct(id);
return "redirect:/product";
}
@PostMapping("/delete/{id}/{componentid}")
public String deleteComponent(@PathVariable Long id,
@PathVariable Long componentid) {
productService.deleteComponent(id,componentid);
return "redirect:/product/edit/" + id;
}
@PostMapping("/addproduct/{id}")
public String addComponent(@PathVariable Long id,
@ModelAttribute @Valid ComponentDTO componentDTO,
BindingResult bindingResult,
Model model) {
if (bindingResult.hasErrors()) {
model.addAttribute("errors", bindingResult.getAllErrors());
return "product-edit";
}
productService.addComponent(id, componentDTO);
return "redirect:/product/edit/" + id;
}
}

View File

@ -1,5 +1,6 @@
package ip.labwork.shop.service;
import ip.labwork.shop.controller.ComponentDTO;
import ip.labwork.shop.controller.ProductDTO;
import ip.labwork.shop.model.Component;
import ip.labwork.shop.model.OrderProducts;
@ -30,10 +31,12 @@ public class ProductService {
final Product product = new Product(productDTO.getName(), productDTO.getPrice(),productDTO.getImage().getBytes());
validatorUtil.validate(product);
productRepository.save(product);
if(productDTO.getComponentDTOList() != null){
for (int i = 0; i < productDTO.getComponentDTOList().size(); i++) {
final ProductComponents productComponents = new ProductComponents(componentRepository.findById(productDTO.getComponentDTOList().get(i).getId()).orElseThrow(() -> new ComponentNotFoundException(1L)), product, productDTO.getComponentDTOList().get(i).getCount());
product.addComponent(productComponents);
}
}
productRepository.save(product);
return new ProductDTO(findProduct(product.getId()));
}
@ -85,6 +88,17 @@ public class ProductService {
return new ProductDTO(currentProduct);
}
@Transactional
public ProductDTO updateFields(Long id, ProductDTO product) {
final Product currentProduct = findProduct(id);
currentProduct.setProductName(product.getName());
if (product.getImage().length()>23){
currentProduct.setImage(product.getImage().getBytes());
}
validatorUtil.validate(currentProduct);
productRepository.save(currentProduct);
return new ProductDTO(currentProduct);
}
@Transactional
public ProductDTO deleteProduct(Long id) {
final Product currentProduct = findProduct(id);
int size = currentProduct.getComponents().size();
@ -109,7 +123,44 @@ public class ProductService {
}
@Transactional
public List<Product> findFiltredProducts(Long[] arr) {
return productRepository.findAllById(Arrays.stream(arr).toList());
public ProductDTO addComponent(Long id, ComponentDTO componentDTO) {
if (componentDTO.getCount() <= 0){
return null;
}
final Product currentProduct = findProduct(id);
List<ProductComponents> productComponentsList = productRepository.getProductComponent(id);
if(productComponentsList.stream().filter(x -> x.getId().getComponentId() == componentDTO.getId()).toList().size() != 0) {
final ProductComponents productComponents = productRepository.getProductComponent(id).stream().filter(x -> x.getId().getComponentId().equals(componentDTO.getId())).findFirst().get();
currentProduct.removeComponent(productComponents);
currentProduct.addComponent(new ProductComponents(componentRepository.findById(componentDTO.getId()).orElseThrow(() -> new ComponentNotFoundException(id)), currentProduct, componentDTO.getCount()));
}else{
final ProductComponents productComponents = new ProductComponents(componentRepository.findById(componentDTO.getId()).orElseThrow(() -> new ComponentNotFoundException(id)), currentProduct, componentDTO.getCount());
currentProduct.addComponent(productComponents);
}
productRepository.saveAndFlush(currentProduct);
int price = 0;
for(int i = 0; i < productRepository.getProductComponent(id).size(); i++){
price += productRepository.getProductComponent(id).get(i).getComponent().getPrice() * productRepository.getProductComponent(id).get(i).getCount();
}
currentProduct.setPrice(price);
productRepository.saveAndFlush(currentProduct);
return new ProductDTO(currentProduct);
}
@Transactional
public ProductDTO deleteComponent(Long id, Long componentId) {
Product currentProduct = findProduct(id);
final ProductComponents productComponents = productRepository.getProductComponent(id).stream().filter(x -> x.getId().getComponentId().equals(componentId)).findFirst().get();
currentProduct.removeComponent(productComponents);
Component component = componentRepository.findById(componentId).orElseThrow(() -> new ComponentNotFoundException(componentId));
component.removeProduct(productComponents);
productRepository.save(currentProduct);
currentProduct = findProduct(id);
int price = 0;
for(int i = 0; i < currentProduct.getComponents().size(); i++){
price += currentProduct.getComponents().get(i).getComponent().getPrice() * currentProduct.getComponents().get(i).getCount();
}
currentProduct.setPrice(price);
productRepository.saveAndFlush(currentProduct);
return new ProductDTO(currentProduct);
}
}

View File

@ -1,5 +1,6 @@
package ip.labwork.test.controller;
import ip.labwork.WebConfiguration;
import ip.labwork.test.model.TestDto;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
@ -8,7 +9,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
@RequestMapping(WebConfiguration.REST_API + "/test")
public class TestController {
@PostMapping
public TestDto testValidation(@RequestBody @Valid TestDto testDto) {

View File

@ -10,10 +10,11 @@ import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestController;
import java.util.stream.Collectors;
@ControllerAdvice
@ControllerAdvice(annotations = RestController.class)
public class AdviceController {
@ExceptionHandler({
ComponentNotFoundException.class,

View File

@ -0,0 +1,86 @@
nav {
background-color: #c8afaf;
}
main {
background-color: #8c7b7b;
min-height: 90vh;
}
footer {
background-color: #c8afaf;
color: black;
}
.size {
overflow-x: hidden;
}
.card {
background-color: #8c7b7b;
border-color: #8c7b7b;
}
.card-body {
background-color: #8c7b7b;
}
h1 {
word-wrap: break-word;
}
#banner {
margin: 0px 15px 15px 15px;
padding-top: 15px;
display: flex;
align-items: center;
flex-direction: column;
}
#banner img {
border-radius: 5px;
}
#banner img.show {
width: 100%;
opacity: 1;
transition: opacity 1s, visibility 0s;
}
#banner img.hide {
height: 0;
width: 0;
opacity: 0;
visibility: hidden;
transition: opacity 1s, visibility 0s 1s;
}
@media (max-width: 767px) {
.btn {
padding: 1px 5px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
}
}
@media (min-width: 768px) and (max-width: 991px) {
.btn {
padding: 5px 10px;
font-size: 12px;
line-height: 1.5;
border-radius: 3px;
}
}
@media (min-width: 992px) and (max-width: 1199px) {
.btn {
padding: 6px 12px;
font-size: 14px;
line-height: 1.42857143;
border-radius: 4px;
}
}
@media (min-width: 1200px) {
.btn {
padding: 10px 16px;
font-size: 18px;
line-height: 1.3333333;
border-radius: 6px;
}
}
@media (max-width: 600px) {
.tem {
padding-right: 50px;
}
}

View File

@ -0,0 +1,49 @@
<!DOCTYPE html>
<html
lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}"
>
<head> </head>
<body>
<main style="background-color: white" layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form
action="#"
th:action="@{/component/{id}(id=${id})}"
th:object="${componentDto}"
method="post"
>
<div class="mb-3">
<label for="componentName" class="form-label">Название</label>
<input
type="text"
class="form-control"
id="componentName"
th:field="${componentDto.componentName}"
required="true"
/>
</div>
<div class="mb-3">
<label for="price" class="form-label">Цена</label>
<input
type="text"
class="form-control"
id="price"
th:field="${componentDto.price}"
required="true"
/>
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary button-fixed">
<span th:if="${id == null}">Добавить</span>
<span th:if="${id != null}">Обновить</span>
</button>
<a class="btn btn-secondary button-fixed" th:href="@{/component}">
Назад
</a>
</div>
</form>
</main>
</body>
</html>

View File

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html
lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}"
>
<head> </head>
<body>
<main style="background-color: white" layout:fragment="content">
<div>
<a class="btn btn-success button-fixed" th:href="@{/component/edit}">
<i class="fa-solid fa-plus"></i> Добавить
</a>
</div>
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Название</th>
<th scope="col">Цена</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr th:each="component, iterator: ${components}">
<th scope="row" th:text="${iterator.index} + 1" />
<td th:text="${component.componentName}" />
<td th:text="${component.price}" style="width: 60%" />
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<a
class="btn btn-warning button-fixed button-sm"
th:href="@{/component/edit/{id}(id=${component.id})}"
>
<i class="fa fa-pencil" aria-hidden="true"></i> Изменить
</a>
<button
type="button"
class="btn btn-danger button-fixed button-sm"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${component.id}').click()|"
>
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form
th:action="@{/component/delete/{id}(id=${component.id})}"
method="post"
>
<button
th:id="'remove-' + ${component.id}"
type="submit"
style="display: none"
>
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</main>
</body>
</html>

View File

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html
lang="ru"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
>
<head>
<meta charset="UTF-8" />
<title>Очень вкусно и запятая</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script
type="text/javascript"
src="/webjars/bootstrap/5.1.3/js/bootstrap.bundle.min.js"
></script>
<link
rel="stylesheet"
href="/webjars/bootstrap/5.1.3/css/bootstrap.min.css"
/>
<link rel="stylesheet" href="/webjars/font-awesome/6.1.0/css/all.min.css" />
<link rel="stylesheet" href="/css/style.css" />
</head>
<body class="d-flex flex-column h-100">
<div id="app">
<nav class="navbar navbar-expand-lg">
<div class="container-fluid">
<a class="navbar-brand" href="/product">
<h1 class="text-black">Очень вкусно и запятая</h1>
</a>
<button
class="navbar-toggler"
type="button"
data-bs-toggle="collapse"
data-bs-target="#navbarNav"
aria-controls="navbarNav"
aria-expanded="false"
aria-label="Toggle navigation"
>
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<a class="nav-link fs-4 text-black" href="/component"
>Компоненты</a
>
<a class="nav-link fs-4 text-black" href="/product">Продукты</a>
<a class="nav-link fs-4 text-black" href="/order">Заказы</a>
</ul>
</div>
</div>
</nav>
<div class="container-fluid p-0">
<div
class="container container-padding"
layout:fragment="content"
></div>
</div>
<footer
class="footer mt-auto d-flex justify-content-center align-items-center"
>
ООО "Вкусно" © 2022
</footer>
</div>
</body>
<th:block layout:fragment="scripts"> </th:block>
</html>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html
lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}"
>
<head> </head>
<body>
<div layout:fragment="content">
<div><span th:text="${error}"></span></div>
<a href="/">На главную</a>
</div>
</body>
</html>

View File

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html
lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}"
>
<head> </head>
<body>
<div layout:fragment="content">
<div>It's works!</div>
<a href="123">ERROR</a>
</div>
</body>
</html>

View File

@ -0,0 +1,132 @@
<!DOCTYPE html>
<html
lang="en"
layout:decorate="~{default}"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
>
<head> </head>
<body>
<main
class="flex-shrink-0"
style="background-color: white"
layout:fragment="content"
>
<h1 class="my-5 ms-5 fs-1">
<b>Корзина</b>
</h1>
<h2 class="my-5 ms-5 fs-3"></h2>
<div class="ms-5 my-5">Список товаров</div>
<div>
<div style="max-width: 35%">
<table class="table">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Позиция</th>
<th scope="col"></th>
<th scope="col">Стоимость</th>
<th scope="col"></th>
</tr>
</thead>
<tbody class="table-group-divider">
<tr th:each="product, iterator: ${productDTOS}">
<th scope="row" th:text="${iterator.index+1}"></th>
<td colspan="2" th:text="${product.name}"></td>
<td th:text="${product.count+'x'+product.price+' руб'}"></td>
<td>
<button th:attr="onclick=|remove(${product.id})|">
Удалить
</button>
</td>
</tr>
</tbody>
</table>
</div>
<h2 class="ms-5 my-5" th:text="${'Итого: ' + totalPrice + ' руб'}"></h2>
<button
class="btn btn-success ms-5 w-25"
type="button"
style="color: black"
th:attr="onclick=|document.getElementById('accept').click()|"
>
Купить
</button>
<form th:action="@{/order}" method="post">
<button th:id="'accept'" type="submit" style="display: none">
Купить
</button>
</form>
</div>
<p></p>
<p></p>
</main>
</body>
<th:block layout:fragment="scripts">
<script>
function deleteAll() {
let l = getCookie();
for (let i = 0; i < l.length; i++) {
if (l[i].id === "delete") {
let cookies = document.cookie.split(";");
for (let j = 0; j < cookies.length; j++) {
let cookie = cookies[j];
let eqPos = cookie.indexOf("=");
let name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie;
document.cookie =
name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;";
document.cookie =
name + "=; path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT;";
}
window.location.href = "/order";
}
}
}
deleteAll();
function remove(name) {
let i = getCookie(name);
const d = new Date();
d.setTime(d.getTime() + 24 * 60 * 60 * 1000);
let expires = "expires=" + d.toUTCString();
if (i == "1") {
document.cookie = name + "=;expires=Thu, 01 Jan 1970 00:00:00 GMT;";
document.cookie =
name + "=; path=/; expires=Thu, 01 Jan 1970 00:00:01 GMT;";
} else {
document.cookie =
name + "=" + (Number(i) - Number(1)) + ";" + expires + ";path=/";
}
window.location.href = "/order";
}
function getCookie(name) {
if (name) {
name = name + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(";");
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == " ") {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
} else {
let arrObjects = [];
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split("; ");
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
let cs = c.split("=");
arrObjects[i] = {
id: cs[0],
count: cs[1],
};
}
return arrObjects;
}
}
</script>
</th:block>
</html>

View File

@ -0,0 +1,142 @@
<!DOCTYPE html>
<html
lang="en"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{default}"
>
<head>
<script
type="text/javascript"
src="/webjars/jquery/3.6.0/jquery.min.js"
></script>
</head>
<body>
<main style="background-color: white" layout:fragment="content">
<div th:text="${errors}" class="margin-bottom alert-danger"></div>
<form
action="#"
th:action="@{/product/{id}(id=${id})}"
th:object="${productDto}"
enctype="multipart/form-data"
method="post"
>
<div class="mb-3">
<label for="name" class="form-label">Название</label>
<input
type="text"
class="form-control"
id="name"
th:field="${productDto.name}"
required="true"
/>
</div>
<div class="mb-3">
<label for="price" class="form-label">Цена</label>
<input
type="text"
class="form-control"
id="price"
th:value="${productDto.price}"
disabled
required="true"
/>
</div>
<div class="mb-3">
<label for="image" class="form-label">Изображение</label>
<input type="file" class="form-control" id="image" th:name="file" />
</div>
<div class="mb-3">
<button type="submit" class="btn btn-primary button-fixed">
<span th:if="${id == null}">Добавить</span>
<span th:if="${id != null}">Обновить</span>
</button>
<a class="btn btn-secondary button-fixed" th:href="@{/product}">
Назад
</a>
</div>
</form>
<form
th:if="${id != null}"
action="#"
th:action="@{/product/addproduct/{id}(id=${id})}"
th:object="${componentDto}"
method="post"
>
<div class="mb-3">
<label for="lang" class="form-label">Компонент</label>
<select id="lang" class="form-select" th:field="${componentDto.id}">
<option
th:each="value: ${components}"
th:value="${value.getId()}"
th:selected="true"
th:text="${value.getComponentName()}"
></option>
</select>
</div>
<div class="mb-3">
<label for="count" class="form-label">Количество</label>
<input
type="text"
class="form-control"
id="count"
th:field="${componentDto.count}"
required="true"
/>
</div>
<div>
<div>
<button class="btn btn-success button-fixed" type="submit">
Добавить
</button>
</div>
</div>
</form>
<div class="table-responsive" th:if="${id != null}">
<table class="table">
<thead>
<tr>
<th scope="col">Название</th>
<th scope="col">Количество</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
<tr
th:each="component, iterator: ${productDto.getComponentDTOList()}"
>
<th
scope="row"
th:text="${component.getComponentName()}"
style="width: 60%"
/>
<td th:text="${component.getCount()}" />
<td style="width: 10%">
<div class="btn-group" role="group" aria-label="Basic example">
<button
type="button"
class="btn btn-danger button-fixed button-sm"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${component.id}').click()|"
>
<i class="fa fa-trash" aria-hidden="true"></i> Удалить
</button>
</div>
<form
th:action="@{/product/delete/{productid}/{id} (id=${component.getId()}, productid=${id})}"
method="post"
>
<button
th:id="'remove-' + ${component.getId()}"
type="submit"
style="display: none"
>
Удалить
</button>
</form>
</td>
</tr>
</tbody>
</table>
</div>
</main>
</body>
</html>

View File

@ -0,0 +1,108 @@
<!DOCTYPE html>
<html
lang="en"
layout:decorate="~{default}"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
>
<head> </head>
<body>
<main class="flex-shrink-0" layout:fragment="content">
<div class="btn-group mt-2" role="group">
<a
type="button"
class="btn btn-outline-dark text-center d-flex justify-content-md-center mx-2 mb-3"
th:href="@{/product/edit}"
>
Добавить
</a>
</div>
<div class="temp row row-cols-1 row-cols-md-3 g-4" id="tbl-items">
<div
class="col"
th:each="product, iterator: ${products}"
th:key="${product.getId()}"
>
<div class="card">
<div class="container w-100 h-350px">
<img
alt="Бугер"
class="img-fluid rounded mx-auto d-block"
style="width: 100%; height: 350px; objectfit: contain"
th:src="${product.image}"
/>
</div>
<div class="card-body">
<h5
class="card-title text-center fs-1"
th:text="${product.getPrice()}"
></h5>
<a
class="btn btn-outline-dark text-center d-flex justify-content-md-center mx-5"
th:attr="onclick=|confirm('Удалить запись?') && document.getElementById('remove-${product.id}').click()|"
>
Удалить
</a>
<a
class="btn btn-outline-dark text-center d-flex justify-content-md-center mx-5"
th:href="@{/product/edit/{id}(id=${product.id})}"
type="button"
>Изменить
</a>
<a
class="btn btn-outline-dark text-center d-flex justify-content-md-center mx-5"
type="button"
th:attr="onclick=|add(${product.id})|"
>
в корзину
</a>
<form
th:action="@{/product/delete/{id}(id=${product.id})}"
method="post"
>
<button
th:id="'remove-' + ${product.id}"
type="submit"
style="display: none"
>
Удалить
</button>
</form>
</div>
</div>
</div>
</div>
</main>
</body>
<th:block layout:fragment="scripts">
<script>
function add(name) {
let i = getCookie(name);
const d = new Date();
d.setTime(d.getTime() + 24 * 60 * 60 * 1000);
let expires = "expires=" + d.toUTCString();
if (i == "") {
document.cookie = name + "=" + 1 + ";" + expires + ";path=/";
} else {
document.cookie =
name + "=" + (Number(i) + Number(1)) + ";" + expires + ";path=/";
}
}
function getCookie(name) {
name = name + "=";
let decodedCookie = decodeURIComponent(document.cookie);
let ca = decodedCookie.split(";");
for (let i = 0; i < ca.length; i++) {
let c = ca[i];
while (c.charAt(0) == " ") {
c = c.substring(1);
}
if (c.indexOf(name) == 0) {
return c.substring(name.length, c.length);
}
}
return "";
}
</script>
</th:block>
</html>