Ranghetti 6 месяцев назад
Родитель
Сommit
13b2ca4b1b

+ 6 - 0
pom.xml

@@ -90,6 +90,12 @@
             <artifactId>java-jwt</artifactId>
             <version>4.4.0</version>
         </dependency>
+        <!-- https://mvnrepository.com/artifact/nz.net.ultraq.thymeleaf/thymeleaf-layout-dialect -->
+        <dependency>
+            <groupId>nz.net.ultraq.thymeleaf</groupId>
+            <artifactId>thymeleaf-layout-dialect</artifactId>
+            <version>3.4.0</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 12 - 0
src/main/java/com/platform2easy/genesis/GenesisApplication.java

@@ -1,7 +1,13 @@
 package com.platform2easy.genesis;
 
+import com.platform2easy.genesis.domain.enums.UserRole;
+import com.platform2easy.genesis.domain.model.User;
+import com.platform2easy.genesis.domain.repository.UserRepository;
+import org.springframework.boot.CommandLineRunner;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 
 @SpringBootApplication
 public class GenesisApplication {
@@ -10,4 +16,10 @@ public class GenesisApplication {
         SpringApplication.run(GenesisApplication.class, args);
     }
 
+    @Bean
+    public CommandLineRunner initDataBase(UserRepository user) {
+        return args -> {
+            user.save(new User(null, "admin", new BCryptPasswordEncoder().encode("admin"), UserRole.ADMIN));
+        };
+    }
 }

+ 1 - 1
src/main/java/com/platform2easy/genesis/domain/enums/UserRole.java

@@ -1,5 +1,5 @@
 package com.platform2easy.genesis.domain.enums;
 
 public enum UserRole {
-    ADMIN, ESCROW_USER, SELLER_USER, BUYER_USER;
+    ADMIN, ESCROW_USER, SELLER_USER, BUYER_USER, TRADER_USER;
 }

+ 2 - 0
src/main/java/com/platform2easy/genesis/domain/model/User.java

@@ -11,6 +11,7 @@ import jakarta.persistence.Table;
 import lombok.AllArgsConstructor;
 import lombok.EqualsAndHashCode;
 import lombok.Getter;
+import lombok.NoArgsConstructor;
 import lombok.Setter;
 import org.springframework.security.core.GrantedAuthority;
 import org.springframework.security.core.authority.SimpleGrantedAuthority;
@@ -23,6 +24,7 @@ import java.util.Collections;
 @Getter
 @Setter
 @AllArgsConstructor
+@NoArgsConstructor
 @EqualsAndHashCode(onlyExplicitlyIncluded = true)
 @Table(name = "PLATFORM_USER")
 public class User implements UserDetails {

+ 12 - 6
src/main/java/com/platform2easy/genesis/security/config/SecurityConfiguration.java

@@ -5,13 +5,13 @@ import com.platform2easy.genesis.security.filter.AuthorizationFilter;
 import lombok.AllArgsConstructor;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
 import org.springframework.security.authentication.AuthenticationManager;
 import org.springframework.security.config.Customizer;
 import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
 import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
-import org.springframework.security.config.http.SessionCreationPolicy;
 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
 import org.springframework.security.crypto.password.PasswordEncoder;
 import org.springframework.security.web.SecurityFilterChain;
@@ -22,7 +22,7 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
 @AllArgsConstructor
 public class SecurityConfiguration {
 
-    private AuthorizationFilter authorizationFilter;
+    private final AuthorizationFilter authorizationFilter;
 
     @Bean
     public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
@@ -30,13 +30,19 @@ public class SecurityConfiguration {
                 .csrf(AbstractHttpConfigurer::disable)
                 .cors(Customizer.withDefaults())
                 .exceptionHandling(Customizer.withDefaults())
-                .sessionManagement(sessionManagementConfigurer -> sessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+                //.sessionManagement(sessionManagementConfigurer -> sessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                 .authorizeHttpRequests(authorizationRegistry -> authorizationRegistry
-                        .requestMatchers("/").permitAll()
+                        .requestMatchers("/login", "/images/**", "/css/**").permitAll()
+                        .requestMatchers(HttpMethod.POST, "/authentication/login").permitAll()
                         .anyRequest().authenticated())
                 .addFilterBefore(authorizationFilter, UsernamePasswordAuthenticationFilter.class)
-                .formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer.defaultSuccessUrl("/", true))
-                .logout(httpSecurityLogoutConfigurer -> httpSecurityLogoutConfigurer.logoutSuccessUrl("/"))
+                .formLogin(httpSecurityFormLoginConfigurer -> httpSecurityFormLoginConfigurer
+                        .loginPage("/login")
+                        .defaultSuccessUrl("/", true)
+                        .permitAll())
+                .logout(httpSecurityLogoutConfigurer -> httpSecurityLogoutConfigurer
+                        .logoutUrl("/logout")
+                        .logoutSuccessUrl("/"))
                 .build();
     }
 

+ 15 - 0
src/main/java/com/platform2easy/genesis/web/controller/LoginController.java

@@ -0,0 +1,15 @@
+package com.platform2easy.genesis.web.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@Controller
+public class LoginController {
+
+    @GetMapping("/login")
+    public String login() {
+        return "login";
+    }
+
+
+}

+ 38 - 3
src/main/resources/static/css/estilo.css

@@ -1,5 +1,40 @@
-@charset "ISO-8859-1";
+html, body {
+  height: 100%;
+  margin: 0;
+  padding: 0;
+  overflow-x: hidden;
+}
 
-h1 {
-	color: green;
+body {
+  display: flex;
+  flex-direction: column;
+}
+
+.sidebar {
+  background-color: #70a7c7;
+  padding-top: 1rem;
+}
+
+.sidebar a {
+  color: #f8f9fa;
+  padding: 0.75rem 1rem;
+  display: block;
+  text-decoration: none;
+}
+
+.sidebar a:hover {
+  background-color: #343a40;
+}
+
+.content-area {
+  padding: 2rem;
+  overflow-y: auto;
+}
+
+footer {
+  height: 60px;
+  line-height: 60px;
+  background-color: #212529;
+  color: white;
+  text-align: center;
 }

BIN
src/main/resources/static/images/luv2easy.png


BIN
src/main/resources/static/images/too-easy-logo.png


BIN
src/main/resources/static/images/too-easy-trade.png


+ 37 - 32
src/main/resources/templates/Index.html

@@ -1,39 +1,44 @@
 <!DOCTYPE html>
-<html lang="en" xmlns:th="http://www.thymeleaf.org">
-<head th:fragment="head">
+<html lang="en"
+      xmlns:th="http://www.thymeleaf.org"
+      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+      layout:decorate="~{layout}">
+<head>
     <meta charset="UTF-8">
-    <title>Compra & Venda</title>
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet"
-          integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">
-    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
-
-    <link rel="stylesheet" th:href="@{/css/estilo.css}">
-
+    <title>Too Easy</title>
 </head>
 <body>
-<div class="container">
-    <div th:fragment="menu">
-        <h1>Compra & Venda</h1>
-        <a type="button" class="btn btn-outline-info" th:href="@{/}">Home</a>
-        <a type="button" class="btn btn-outline-info" th:href="@{/compra/listar}">Compras</a>
-        <a type="button" class="btn btn-outline-info" th:href="@{/compra}">Comprar</a>
-        <a type="button" class="btn btn-outline-warning" th:href="@{/banco}" target="_blank">Banco</a>
-        <div class="alert alert-warning alert-dismissible fade show position-fixed top-0 end-0 m-3" role="alert"
-             style="max-width: 400px; z-index: 9999;">
-            <strong>Holy guacamole!</strong> You should check in on some of those fields below.
-            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
+<section layout:fragment="main-content" >
+    <h1 class="mb-4">Bem-vindo, Administrador!</h1>
+
+    <div class="row">
+        <div class="col-md-4 mb-4">
+            <div class="card shadow-sm">
+                <div class="card-body">
+                    <h5 class="card-title">Total de Usuários</h5>
+                    <p class="card-text fs-4">1.245</p>
+                </div>
+            </div>
         </div>
-    </div>
-</div>
 
-<div th:fragment="script">
-    <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"
-            integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"
-            crossorigin="anonymous"></script>
-    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/js/bootstrap.min.js"
-            integrity="sha384-RuyvpeZCxMJCqVUGFI0Do1mQrods/hhxYlcVfGPOfQtPJh0JCw12tUAZ/Mv10S7D"
-            crossorigin="anonymous"></script>
-</div>
+        <div class="col-md-4 mb-4">
+            <div class="card shadow-sm bg-success text-white">
+                <div class="card-body">
+                    <h5 class="card-title">Vendas do Mês</h5>
+                    <p class="card-text fs-4">R$ 87.000,00</p>
+                </div>
+            </div>
+        </div>
+
+        <div class="col-md-4 mb-4">
+            <div class="card shadow-sm bg-warning text-dark">
+                <div class="card-body">
+                    <h5 class="card-title">Pendências</h5>
+                    <p class="card-text fs-4">32 tickets abertos</p>
+                </div>
+            </div>
+        </div>
+    </div>
+</section>
 </body>
-</html>
+</html>

+ 63 - 57
src/main/resources/templates/compra/formulario.html

@@ -1,66 +1,72 @@
 <!DOCTYPE html>
-<html lang="en" xmlns:th="http://www.thymeleaf.org">
-<head th:insert="~{index :: head}">
+<html lang="en" xmlns:th="http://www.thymeleaf.org"
+      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+      layout:decorate="~{layout}">
+<head>
     <meta charset="UTF-8">
+    <title>Too Easy</title>
 </head>
 <body>
-<div class="container">
-    <div th:insert="~{index :: menu}"></div>
-    <br/>
-    <form>
-        <div class="mb-3">
-            <input hidden="true" name="id" th:value="${compra.id}" type="text">
+<section layout:fragment="main-content">
+    <div class="container">
+        <form>
+            <div class="mb-3">
+                <input hidden="true" name="id" th:value="${compra.id}" type="text">
 
-            <label class="form-label" for="fornecedor">Fornecedor</label>
-            <input class="form-control" id="fornecedor" name="fornecedor" th:value="${compra.fornecedor}" type="text">
-        </div>
+                <label class="form-label" for="fornecedor">Fornecedor</label>
+                <input class="form-control" id="fornecedor" name="fornecedor" th:value="${compra.fornecedor}"
+                       type="text">
+            </div>
 
-        <br/>
-        <div class="mb-3">
-            <table class="table">
-                <thead>
-                <tr>
-                    <th>Código</th>
-                    <th>Item</th>
-                    <th>Valor</th>
-                    <th></th>
-                </tr>
-                </thead>
-                <tbody>
-                <tr th:each="item, stat : ${compra.itens}">
-                    <td>
-                        <input th:value="${item.id}" th:name="|itens[${stat.index}].id|" type="text" hidden="true">
-                        <input th:value="${item.id}" class="form-control" type="text" disabled>
-                    </td>
-                    <td>
-                        <input th:value="${item.descricao}" class="form-control"
-                               th:name="|itens[${stat.index}].descricao|" type="text" required>
-                    </td>
-                    <td><input th:value="${item.valor}" class="form-control" th:name="|itens[${stat.index}].valor|"
-                               type="text" required></td>
-                    <td>
-                        <button class="btn btn-outline-dark" formmethod="post" th:formaction="@{'/compra/' + ${stat.index}}"
-                                type="submit">
-                            <i class="bi bi-dash-square"></i>
-                        </button>
-                    </td>
-                </tr>
-                <tr>
-                    <td><input class="form-control" type="text" disabled></td>
-                    <td><input class="form-control" th:name="descricao" type="text"></td>
-                    <td><input class="form-control" th:name="valor" type="text"></td>
-                    <td>
-                        <button class="btn btn-outline-dark" formmethod="post" th:formaction="@{/compra}" type="submit">
-                            <i class="bi bi-plus-square"></i>
-                        </button>
-                </tr>
-                </tbody>
-            </table>
-        </div>
+            <br/>
+            <div class="mb-3">
+                <table class="table">
+                    <thead>
+                    <tr>
+                        <th>Código</th>
+                        <th>Item</th>
+                        <th>Valor</th>
+                        <th></th>
+                    </tr>
+                    </thead>
+                    <tbody>
+                    <tr th:each="item, stat : ${compra.itens}">
+                        <td>
+                            <input th:value="${item.id}" th:name="|itens[${stat.index}].id|" type="text" hidden="true">
+                            <input th:value="${item.id}" class="form-control" type="text" disabled>
+                        </td>
+                        <td>
+                            <input th:value="${item.descricao}" class="form-control"
+                                   th:name="|itens[${stat.index}].descricao|" type="text" required>
+                        </td>
+                        <td><input th:value="${item.valor}" class="form-control" th:name="|itens[${stat.index}].valor|"
+                                   type="text" required></td>
+                        <td>
+                            <button class="btn btn-outline-dark" formmethod="post"
+                                    th:formaction="@{'/compra/' + ${stat.index}}"
+                                    type="submit">
+                                <i class="bi bi-dash-square"></i>
+                            </button>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td><input class="form-control" type="text" disabled></td>
+                        <td><input class="form-control" th:name="descricao" type="text"></td>
+                        <td><input class="form-control" th:name="valor" type="text"></td>
+                        <td>
+                            <button class="btn btn-outline-dark" formmethod="post" th:formaction="@{/compra}"
+                                    type="submit">
+                                <i class="bi bi-plus-square"></i>
+                            </button>
+                    </tr>
+                    </tbody>
+                </table>
+            </div>
 
-        <button class="btn btn-dark" formmethod="post" th:formaction="@{/compra/salvar}" type="submit">Salvar</button>
-    </form>
-</div>
-<div th:insert="~{index :: script}"></div>
+            <button class="btn btn-dark" formmethod="post" th:formaction="@{/compra/salvar}" type="submit">Salvar
+            </button>
+        </form>
+    </div>
+</section>
 </body>
 </html>

+ 39 - 33
src/main/resources/templates/compra/lista.html

@@ -1,38 +1,44 @@
 <!DOCTYPE html>
-<html lang="en" xmlns:th="http://www.thymeleaf.org">
-<head th:insert="~{index :: head}">
+<html lang="en" xmlns:th="http://www.thymeleaf.org"
+      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
+      layout:decorate="~{layout}">
+<head>
     <meta charset="UTF-8">
+    <title>Too Easy</title>
 </head>
 <body>
-<div class="container">
-    <div th:insert="~{index :: menu}"></div>
-    <br/>
-    <table class="table table-hover">
-        <thead>
-        <tr>
-            <th>Código</th>
-            <th>Fornecedor</th>
-            <th>Ações</th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr th:each="compra : ${compras}">
-            <td th:text="${compra.id}">0</td>
-            <td th:text="${compra.fornecedor}">0</td>
-            <td>
-                <a th:href="@{'/compra/editar/' + ${compra.id}}" type="button" class="btn btn-outline-dark"
-                   title="Editar">
-                    <i class="bi bi-pencil-square"></i>
-                </a>
-                <a th:href="@{'/compra/remover/' + ${compra.id}}" type="button" class="btn btn-outline-dark"
-                   title="Remover">
-                    <i class="bi bi-dash-square"></i>
-                </a>
-            </td>
-        </tr>
-        </tbody>
-    </table>
-</div>
-<div th:insert="~{index :: script}"></div>
+<section layout:fragment="main-content">
+    <div class="container">
+        <a th:href="@{/compra}" type="button" class="btn btn-outline-dark"
+           title="Cadastrar">
+            <i class="bi bi-pencil-square"></i>
+        </a>
+        <table class="table table-hover">
+            <thead>
+            <tr>
+                <th>Código</th>
+                <th>Fornecedor</th>
+                <th>Ações</th>
+            </tr>
+            </thead>
+            <tbody>
+            <tr th:each="compra : ${compras}">
+                <td th:text="${compra.id}">0</td>
+                <td th:text="${compra.fornecedor}">0</td>
+                <td>
+                    <a th:href="@{'/compra/editar/' + ${compra.id}}" type="button" class="btn btn-outline-dark"
+                       title="Editar">
+                        <i class="bi bi-pencil-square"></i>
+                    </a>
+                    <a th:href="@{'/compra/remover/' + ${compra.id}}" type="button" class="btn btn-outline-dark"
+                       title="Remover">
+                        <i class="bi bi-dash-square"></i>
+                    </a>
+                </td>
+            </tr>
+            </tbody>
+        </table>
+    </div>
+</section>
 </body>
-</html>
+</html>

+ 56 - 0
src/main/resources/templates/layout.html

@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html lang="en"
+      xmlns:th="http://www.thymeleaf.org"
+      xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
+<head>
+    <meta charset="UTF-8">
+    <title>Too Easy</title>
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <link rel="stylesheet" th:href="@{/css/estilo.css}">
+    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet"
+          integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">
+    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
+</head>
+<body class="d-flex flex-column min-vh-100">
+
+<nav class="navbar navbar-expand-md navbar-dark bg-dark sticky-top">
+    <div class="container-fluid">
+        <div class="navbar-brand">
+            <img th:src="@{/images/too-easy-trade.png}" class="img-fluid" style="max-width: 100px;">
+        </div>
+        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#mobileMenu">
+            <span class="navbar-toggler-icon"></span>
+        </button>
+    </div>
+</nav>
+
+<div class="flex-grow-1 container-fluid">
+    <div class="row h-100">
+        <nav class="col-md-2 bg-dark sidebar collapse d-md-block" id="mobileMenu">
+            <a th:href="@{/}">🏠 Início</a>
+            <a href="#">👥 Usuários</a>
+            <a th:href="@{/compra/listar}">🏷️ Compras</a>
+            <a href="#">📊 Relatórios</a>
+            <a href="#">⚙️ Configurações</a>
+            <a th:href="@{/logout}">🚪 Sair</a>
+        </nav>
+        <main class="col-md-10 ms-sm-auto col-12 content-area" layout:fragment="main-content">
+        </main>
+    </div>
+</div>
+
+<footer class="bg-dark text-white text-center">
+    <div class="container">
+        <small>&copy; 2025 TooEasy. Todos os direitos reservados.</small>
+    </div>
+</footer>
+
+<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.8/dist/umd/popper.min.js"
+        integrity="sha384-I7E8VVD/ismYTF4hNIPjVp/Zjvgyol6VFvRkX/vR+Vc4jQkC+hVqc2pM8ODewa9r"
+        crossorigin="anonymous"></script>
+<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/js/bootstrap.min.js"
+        integrity="sha384-RuyvpeZCxMJCqVUGFI0Do1mQrods/hhxYlcVfGPOfQtPJh0JCw12tUAZ/Mv10S7D"
+        crossorigin="anonymous"></script>
+
+</body>
+</html>

+ 24 - 0
src/main/resources/templates/login.html

@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html lang="pt-br" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="UTF-8">
+    <title>Login</title>
+    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
+</head>
+<body class="bg-light">
+<div class="container d-flex justify-content-center align-items-center" style="height: 100vh;">
+    <form class="p-4 shadow bg-white rounded" method="post" th:action="@{/login}">
+        <h4 class="mb-4">Login Admin</h4>
+        <div class="mb-3">
+            <input class="form-control" type="text" name="username" placeholder="Usuário">
+        </div>
+        <div class="mb-3">
+            <input class="form-control" type="password" name="password" placeholder="Senha">
+        </div>
+        <div class="d-grid">
+            <button class="btn btn-dark" type="submit">Entrar</button>
+        </div>
+    </form>
+</div>
+</body>
+</html>