.
This commit is contained in:
@@ -3,6 +3,10 @@ package ru.lionarius.isdojplab.controller;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import ru.lionarius.isdojplab.model.Product;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
public class HomeController {
|
||||
@@ -10,6 +14,14 @@ public class HomeController {
|
||||
@GetMapping("/")
|
||||
public String home(Model model) {
|
||||
model.addAttribute("message", "Добро пожаловать в магазин электротоваров!");
|
||||
|
||||
List<Product> products = new ArrayList<>();
|
||||
products.add(new Product("Электрический чайник", 900.0, "Высококачественный чайник с быстрой функцией закипания", "https://example.com/electro1.jpg"));
|
||||
products.add(new Product("Утюг с парогенератором", 1000.0, "Мощный утюг с автоматической подачей пара", "https://example.com/electro2.jpg"));
|
||||
products.add(new Product("Мультиварка", 400.0, "Универсальная мультиварка с множеством режимов приготовления", "https://example.com/electro3.jpg"));
|
||||
|
||||
model.addAttribute("products", products);
|
||||
|
||||
return "home";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package ru.lionarius.isdojplab.controller;
|
||||
|
||||
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.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import ru.lionarius.isdojplab.model.Product;
|
||||
|
||||
@Controller
|
||||
public class ProductFormController {
|
||||
|
||||
@GetMapping("/product_form")
|
||||
public String showForm(Model model) {
|
||||
model.addAttribute("product", new Product());
|
||||
return "product_form";
|
||||
}
|
||||
|
||||
@PostMapping("/product_form")
|
||||
public String submitForm(@Valid @ModelAttribute("product") Product product, BindingResult bindingResult, Model model) {
|
||||
if (bindingResult.hasErrors()) {
|
||||
return "product_form";
|
||||
}
|
||||
model.addAttribute("message", "Товар успешно добавлен: " + product.getName());
|
||||
return "redirect:/";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package ru.lionarius.isdojplab.controller;
|
||||
|
||||
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.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import ru.lionarius.isdojplab.model.User;
|
||||
|
||||
@Controller
|
||||
public class RegisterFormController {
|
||||
|
||||
@GetMapping("/register")
|
||||
public String showForm(Model model) {
|
||||
model.addAttribute("user", new User());
|
||||
|
||||
return "register_form";
|
||||
}
|
||||
|
||||
@PostMapping("/register")
|
||||
public String submitForm(@Valid @ModelAttribute("user") User user, BindingResult bindingResult, Model model) {
|
||||
if (bindingResult.hasErrors()) {
|
||||
return "register_form";
|
||||
}
|
||||
|
||||
model.addAttribute("message", "Пользователь успешно зарегистрирован");
|
||||
|
||||
return "register_form";
|
||||
}
|
||||
}
|
||||
@@ -3,18 +3,16 @@ package ru.lionarius.isdojplab.model;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
public class Product {
|
||||
|
||||
@NotBlank(message = "Название товара обязательно")
|
||||
private String name;
|
||||
|
||||
@NotNull(message = "Цена товара обязательна")
|
||||
@Min(value = 1, message = "Цена должна быть больше 0")
|
||||
private Double price;
|
||||
|
||||
@NotBlank(message = "Описание товара обязательно")
|
||||
private String description;
|
||||
private String imageUrl;
|
||||
}
|
||||
|
||||
18
src/main/java/ru/lionarius/isdojplab/model/User.java
Normal file
18
src/main/java/ru/lionarius/isdojplab/model/User.java
Normal file
@@ -0,0 +1,18 @@
|
||||
package ru.lionarius.isdojplab.model;
|
||||
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class User {
|
||||
@NotBlank(message = "Поле не может быть пустым")
|
||||
private String name;
|
||||
@NotBlank(message = "Поле не может быть пустым")
|
||||
@Email(message = "Неверный формат электронной почты")
|
||||
private String email;
|
||||
@NotBlank(message = "Поле не может быть пустым")
|
||||
@Size(min = 6, message = "Пароль должен состоять не менее 6 символов")
|
||||
private String password;
|
||||
}
|
||||
71
src/main/resources/static/css/styles.css
Normal file
71
src/main/resources/static/css/styles.css
Normal file
@@ -0,0 +1,71 @@
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f4f4f9;
|
||||
color: #333;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
header {
|
||||
background-color: #007BFF;
|
||||
color: white;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
.container {
|
||||
margin: 2rem auto;
|
||||
max-width: 1200px;
|
||||
padding: 1rem;
|
||||
text-align: center;
|
||||
}
|
||||
.catalog {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 1rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
.product {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
padding: 1rem;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
.product img {
|
||||
width: 100%;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.product:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
.product h3 {
|
||||
font-size: 1.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.product p {
|
||||
font-size: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
.product button {
|
||||
background-color: #007BFF;
|
||||
color: white;
|
||||
padding: 0.5rem 1rem;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.product button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
footer {
|
||||
background-color: #333;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 1rem;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
@@ -1,10 +1,43 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="ru">
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Магазин электротоваров</title>
|
||||
<link rel="stylesheet" th:href="@{/css/styles.css}">
|
||||
</head>
|
||||
<body>
|
||||
<h1 th:text="${message}"></h1>
|
||||
|
||||
<header>
|
||||
<h1>Магазин электротоваров</h1>
|
||||
<p>Все для вашего дома и офиса</p>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
<div class="register-container">
|
||||
<a href="/register" class="register-button">Регистрация</a>
|
||||
</div>
|
||||
|
||||
<h2>Каталог товаров</h2>
|
||||
|
||||
<div class="catalog">
|
||||
<div th:each="product : ${products}" class="product">
|
||||
<img th:src="${product.imageUrl}" alt="Product Image" style="width: 300px;">
|
||||
<h3 th:text="${product.name}"></h3>
|
||||
<p th:text="${product.description}"></p>
|
||||
<p>Цена: <span th:text="${product.price} + ' $'"></span></p>
|
||||
<button>Добавить в корзину</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<a href="#" style="margin-top: 2rem; display: inline-block;">
|
||||
<button style="padding: 1rem 2rem; font-size: 1.2rem;">Перейти в корзину</button>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>© 2024 Магазин электротоваров. Все права защищены.</p>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Форма добавления товара</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Добавить новый товар</h1>
|
||||
<form action="#" th:action="@{/product_form}" th:object="${product}" method="post">
|
||||
<p>
|
||||
<label for="name">Название товара: </label>
|
||||
<input type="text" id="name" th:field="*{name}"/>
|
||||
<span style="color: red" th:if="${#fields.hasErrors('name')}" th:errors="*{name}">Ошибка</span>
|
||||
</p>
|
||||
<p>
|
||||
<label for="price">Цена: </label>
|
||||
<input type="text" id="price" th:field="*{price}"/>
|
||||
<span style="color: red" th:if="${#fields.hasErrors('price')}" th:errors="*{price}">Ошибка</span>
|
||||
</p>
|
||||
<p>
|
||||
<label for="description">Описание товара: </label>
|
||||
<input type="text" id="description" th:field="*{description}"/>
|
||||
<span style="color: red" th:if="${#fields.hasErrors('description')}" th:errors="*{description}">Ошибка</span>
|
||||
</p>
|
||||
<button type="submit">Добавить товар</button>
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
49
src/main/resources/templates/register_form.html
Normal file
49
src/main/resources/templates/register_form.html
Normal file
@@ -0,0 +1,49 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Регистрация</title>
|
||||
<link rel="stylesheet" th:href="@{/css/styles.css}">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header>
|
||||
<h1>Регистрация нового пользователя</h1>
|
||||
</header>
|
||||
|
||||
<div class="container">
|
||||
<form th:action="@{/register}" th:object="${user}" method="post">
|
||||
<div>
|
||||
<label for="name">Имя:</label>
|
||||
<input type="text" id="name" th:field="*{name}" />
|
||||
<br />
|
||||
<span style="color: red" th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="email">Email:</label>
|
||||
<input type="email" id="email" th:field="*{email}" />
|
||||
<br />
|
||||
<span style="color: red" th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></span>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="password">Пароль:</label>
|
||||
<input type="password" id="password" th:field="*{password}" />
|
||||
<br />
|
||||
<span style="color: red" th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></span>
|
||||
</div>
|
||||
|
||||
<button type="submit">Зарегистрироваться</button>
|
||||
</form>
|
||||
|
||||
<p th:if="${message}" th:text="${message}"></p>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<p>© 2024 Магазин электротоваров. Все права защищены.</p>
|
||||
</footer>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -15,6 +15,12 @@ public class HomeControllerTest {
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
public void testHomePageReturnsOkStatus() throws Exception {
|
||||
mockMvc.perform(get("/"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHomePageReturnsCorrectView() throws Exception {
|
||||
mockMvc.perform(get("/"))
|
||||
@@ -22,17 +28,11 @@ public class HomeControllerTest {
|
||||
.andExpect(view().name("home"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHomePageContainsMessage() throws Exception {
|
||||
mockMvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(model().attribute("message", "Добро пожаловать в магазин электротоваров!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHomePageRendersCorrectHtml() throws Exception {
|
||||
mockMvc.perform(get("/"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(org.hamcrest.Matchers.containsString("Добро пожаловать в магазин электротоваров!")));
|
||||
.andExpect(content().contentType("text/html;charset=UTF-8"))
|
||||
.andExpect(model().attribute("message", "Добро пожаловать в магазин электротоваров!"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user