LabWork05 #1
@ -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') {
|
||||
|
@ -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("*");
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
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,9 +31,11 @@ public class ProductService {
|
||||
final Product product = new Product(productDTO.getName(), productDTO.getPrice(),productDTO.getImage().getBytes());
|
||||
validatorUtil.validate(product);
|
||||
productRepository.save(product);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
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