Всё работает
This commit is contained in:
parent
52a842d8c9
commit
b741f13f4d
@ -17,7 +17,6 @@ jar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(':front'))
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
|
||||||
implementation 'com.h2database:h2:2.1.210'
|
implementation 'com.h2database:h2:2.1.210'
|
||||||
@ -27,6 +26,14 @@ dependencies {
|
|||||||
implementation 'org.springdoc:springdoc-openapi-ui:1.6.5'
|
implementation 'org.springdoc:springdoc-openapi-ui:1.6.5'
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
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') {
|
tasks.named('test') {
|
||||||
|
@ -12,7 +12,8 @@ import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
|
|||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
class WebConfiguration implements WebMvcConfigurer {
|
public class WebConfiguration implements WebMvcConfigurer {
|
||||||
|
public static final String REST_API = "/api";
|
||||||
@Override
|
@Override
|
||||||
public void addCorsMappings(CorsRegistry registry){
|
public void addCorsMappings(CorsRegistry registry){
|
||||||
registry.addMapping("/**").allowedMethods("*");
|
registry.addMapping("/**").allowedMethods("*");
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package ip.labwork.method.controller;
|
package ip.labwork.method.controller;
|
||||||
|
|
||||||
|
import ip.labwork.WebConfiguration;
|
||||||
import ip.labwork.method.service.MethodService;
|
import ip.labwork.method.service.MethodService;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
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.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
|
@RequestMapping(WebConfiguration.REST_API + "/method")
|
||||||
public class MethodController {
|
public class MethodController {
|
||||||
private final MethodService speakerService;
|
private final MethodService speakerService;
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ip.labwork.shop.controller;
|
package ip.labwork.shop.controller;
|
||||||
|
|
||||||
|
import ip.labwork.WebConfiguration;
|
||||||
import ip.labwork.shop.service.ComponentService;
|
import ip.labwork.shop.service.ComponentService;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@ -7,7 +8,7 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/component")
|
@RequestMapping(WebConfiguration.REST_API + "/component")
|
||||||
|
|
||||||
public class ComponentController {
|
public class ComponentController {
|
||||||
private final ComponentService componentService;
|
private final ComponentService componentService;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package ip.labwork.shop.controller;
|
package ip.labwork.shop.controller;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import ip.labwork.shop.model.Component;
|
import ip.labwork.shop.model.Component;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
public class ComponentDTO {
|
public class ComponentDTO {
|
||||||
private long id;
|
private long id;
|
||||||
@ -26,15 +28,31 @@ public class ComponentDTO {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
public String getComponentName() {
|
public String getComponentName() {
|
||||||
return componentName;
|
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() {
|
public int getCount() {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPrice() {
|
public void setCount(int count) {
|
||||||
return price;
|
this.count = count;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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";
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package ip.labwork.shop.controller;
|
package ip.labwork.shop.controller;
|
||||||
|
|
||||||
|
import ip.labwork.WebConfiguration;
|
||||||
import ip.labwork.shop.service.OrderService;
|
import ip.labwork.shop.service.OrderService;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@ -7,7 +8,7 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/order")
|
@RequestMapping(WebConfiguration.REST_API + "/order")
|
||||||
public class OrderController {
|
public class OrderController {
|
||||||
private final OrderService orderService;
|
private final OrderService orderService;
|
||||||
public OrderController(OrderService orderService) {
|
public OrderController(OrderService orderService) {
|
||||||
|
@ -2,6 +2,7 @@ package ip.labwork.shop.controller;
|
|||||||
|
|
||||||
import ip.labwork.shop.model.Order;
|
import ip.labwork.shop.model.Order;
|
||||||
import ip.labwork.shop.model.OrderStatus;
|
import ip.labwork.shop.model.OrderStatus;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -9,7 +10,9 @@ import java.util.Objects;
|
|||||||
|
|
||||||
public class OrderDTO {
|
public class OrderDTO {
|
||||||
private long id;
|
private long id;
|
||||||
|
@NotBlank(message = "Date can't be null or empty")
|
||||||
private Date date = new Date();
|
private Date date = new Date();
|
||||||
|
@NotBlank(message = "Price can't be null or empty")
|
||||||
private int price;
|
private int price;
|
||||||
private OrderStatus status = OrderStatus.Неизвестен;
|
private OrderStatus status = OrderStatus.Неизвестен;
|
||||||
private List<ProductDTO> productDTOList;
|
private List<ProductDTO> productDTOList;
|
||||||
@ -31,10 +34,18 @@ public class OrderDTO {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
public Date getDate() {
|
public Date getDate() {
|
||||||
return date;
|
return date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setDate(Date date) {
|
||||||
|
this.date = date;
|
||||||
|
}
|
||||||
|
|
||||||
public int getPrice() {
|
public int getPrice() {
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
@ -43,10 +54,6 @@ public class OrderDTO {
|
|||||||
this.price = price;
|
this.price = price;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDate(Date date) {
|
|
||||||
this.date = date;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OrderStatus getStatus() {
|
public OrderStatus getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -58,4 +65,8 @@ public class OrderDTO {
|
|||||||
public List<ProductDTO> getProductDTOList() {
|
public List<ProductDTO> getProductDTOList() {
|
||||||
return productDTOList;
|
return productDTOList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setProductDTOList(List<ProductDTO> productDTOList) {
|
||||||
|
this.productDTOList = productDTOList;
|
||||||
|
}
|
||||||
}
|
}
|
@ -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";
|
||||||
|
// }
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package ip.labwork.shop.controller;
|
package ip.labwork.shop.controller;
|
||||||
|
|
||||||
|
import ip.labwork.WebConfiguration;
|
||||||
import ip.labwork.shop.service.ProductService;
|
import ip.labwork.shop.service.ProductService;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@ -7,7 +8,7 @@ import org.springframework.web.bind.annotation.*;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/product")
|
@RequestMapping(WebConfiguration.REST_API + "/product")
|
||||||
public class ProductController {
|
public class ProductController {
|
||||||
private final ProductService productService;
|
private final ProductService productService;
|
||||||
|
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
package ip.labwork.shop.controller;
|
package ip.labwork.shop.controller;
|
||||||
|
|
||||||
import ip.labwork.shop.model.Product;
|
import ip.labwork.shop.model.Product;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ProductDTO {
|
public class ProductDTO {
|
||||||
private long id;
|
private long id;
|
||||||
|
@NotBlank(message = "Name can't be null or empty")
|
||||||
private String name;
|
private String name;
|
||||||
|
@NotNull(message = "Price can't be null or empty")
|
||||||
private int price;
|
private int price;
|
||||||
private List<ComponentDTO> componentDTOList;
|
private List<ComponentDTO> componentDTOList;
|
||||||
private List<OrderDTO> orderDTOList;
|
private List<OrderDTO> orderDTOList;
|
||||||
@ -18,7 +22,7 @@ public class ProductDTO {
|
|||||||
this.name = product.getProductName();
|
this.name = product.getProductName();
|
||||||
this.price = product.getPrice();
|
this.price = product.getPrice();
|
||||||
this.image = product.getImage() == null? "" : new String(product.getImage());
|
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()))
|
.filter(x -> Objects.equals(x.getId().getProductId(), product.getId()))
|
||||||
.map(y -> new ComponentDTO(y.getComponent(), y.getCount()))
|
.map(y -> new ComponentDTO(y.getComponent(), y.getCount()))
|
||||||
.toList();
|
.toList();
|
||||||
@ -42,26 +46,42 @@ public class ProductDTO {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCount() {
|
public void setId(long id) {
|
||||||
return count;
|
this.id = id;
|
||||||
}
|
|
||||||
|
|
||||||
public void setCount(int count) {
|
|
||||||
this.count = count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
public int getPrice() {
|
public int getPrice() {
|
||||||
return price;
|
return price;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setPrice(int price) {
|
||||||
|
this.price = price;
|
||||||
|
}
|
||||||
|
|
||||||
public List<ComponentDTO> getComponentDTOList() {
|
public List<ComponentDTO> getComponentDTOList() {
|
||||||
return componentDTOList;
|
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() {
|
public String getImage() {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
@ -70,7 +90,11 @@ public class ProductDTO {
|
|||||||
this.image = image;
|
this.image = image;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<OrderDTO> getOrderDTOList() {
|
public int getCount() {
|
||||||
return orderDTOList;
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCount(int count) {
|
||||||
|
this.count = count;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package ip.labwork.shop.service;
|
package ip.labwork.shop.service;
|
||||||
|
|
||||||
|
import ip.labwork.shop.controller.ComponentDTO;
|
||||||
import ip.labwork.shop.controller.ProductDTO;
|
import ip.labwork.shop.controller.ProductDTO;
|
||||||
import ip.labwork.shop.model.Component;
|
import ip.labwork.shop.model.Component;
|
||||||
import ip.labwork.shop.model.OrderProducts;
|
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());
|
final Product product = new Product(productDTO.getName(), productDTO.getPrice(),productDTO.getImage().getBytes());
|
||||||
validatorUtil.validate(product);
|
validatorUtil.validate(product);
|
||||||
productRepository.save(product);
|
productRepository.save(product);
|
||||||
|
if(productDTO.getComponentDTOList() != null){
|
||||||
for (int i = 0; i < productDTO.getComponentDTOList().size(); i++) {
|
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());
|
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);
|
product.addComponent(productComponents);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
productRepository.save(product);
|
productRepository.save(product);
|
||||||
return new ProductDTO(findProduct(product.getId()));
|
return new ProductDTO(findProduct(product.getId()));
|
||||||
}
|
}
|
||||||
@ -85,6 +88,17 @@ public class ProductService {
|
|||||||
return new ProductDTO(currentProduct);
|
return new ProductDTO(currentProduct);
|
||||||
}
|
}
|
||||||
@Transactional
|
@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) {
|
public ProductDTO deleteProduct(Long id) {
|
||||||
final Product currentProduct = findProduct(id);
|
final Product currentProduct = findProduct(id);
|
||||||
int size = currentProduct.getComponents().size();
|
int size = currentProduct.getComponents().size();
|
||||||
@ -109,7 +123,44 @@ public class ProductService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public List<Product> findFiltredProducts(Long[] arr) {
|
public ProductDTO addComponent(Long id, ComponentDTO componentDTO) {
|
||||||
return productRepository.findAllById(Arrays.stream(arr).toList());
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package ip.labwork.test.controller;
|
package ip.labwork.test.controller;
|
||||||
|
|
||||||
|
import ip.labwork.WebConfiguration;
|
||||||
import ip.labwork.test.model.TestDto;
|
import ip.labwork.test.model.TestDto;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
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;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/test")
|
@RequestMapping(WebConfiguration.REST_API + "/test")
|
||||||
public class TestController {
|
public class TestController {
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public TestDto testValidation(@RequestBody @Valid TestDto testDto) {
|
public TestDto testValidation(@RequestBody @Valid TestDto testDto) {
|
||||||
|
@ -10,10 +10,11 @@ import org.springframework.context.support.DefaultMessageSourceResolvable;
|
|||||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@ControllerAdvice
|
@ControllerAdvice(annotations = RestController.class)
|
||||||
public class AdviceController {
|
public class AdviceController {
|
||||||
@ExceptionHandler({
|
@ExceptionHandler({
|
||||||
ComponentNotFoundException.class,
|
ComponentNotFoundException.class,
|
||||||
|
86
src/main/resources/public/css/style.css
Normal file
86
src/main/resources/public/css/style.css
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
49
src/main/resources/templates/component-edit.html
Normal file
49
src/main/resources/templates/component-edit.html
Normal 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>
|
65
src/main/resources/templates/component.html
Normal file
65
src/main/resources/templates/component.html
Normal 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>
|
65
src/main/resources/templates/default.html
Normal file
65
src/main/resources/templates/default.html
Normal 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>
|
14
src/main/resources/templates/error.html
Normal file
14
src/main/resources/templates/error.html
Normal 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>
|
14
src/main/resources/templates/index.html
Normal file
14
src/main/resources/templates/index.html
Normal 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>
|
132
src/main/resources/templates/order.html
Normal file
132
src/main/resources/templates/order.html
Normal 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>
|
142
src/main/resources/templates/product-edit.html
Normal file
142
src/main/resources/templates/product-edit.html
Normal 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>
|
108
src/main/resources/templates/product.html
Normal file
108
src/main/resources/templates/product.html
Normal 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>
|
Loading…
Reference in New Issue
Block a user