Update client web: Add OIDC configuration, new service layer, and Freya Theme integration
This commit is contained in:
18
pom.xml
18
pom.xml
@@ -7,7 +7,7 @@
|
|||||||
<groupId>com.gbcm</groupId>
|
<groupId>com.gbcm</groupId>
|
||||||
<artifactId>gbcm-client-impl-quarkus</artifactId>
|
<artifactId>gbcm-client-impl-quarkus</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<packaging>war</packaging>
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
<name>GBCM Client Implementation - Quarkus</name>
|
<name>GBCM Client Implementation - Quarkus</name>
|
||||||
<description>Interface web GBCM avec Quarkus et PrimeFaces</description>
|
<description>Interface web GBCM avec Quarkus et PrimeFaces</description>
|
||||||
@@ -55,16 +55,14 @@
|
|||||||
<artifactId>quarkus-oidc</artifactId>
|
<artifactId>quarkus-oidc</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Jakarta Faces (JSF) -->
|
<!-- Quarkus Web -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.myfaces.core</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>myfaces-impl</artifactId>
|
<artifactId>quarkus-resteasy-reactive</artifactId>
|
||||||
<version>4.0.1</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.myfaces.core</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>myfaces-api</artifactId>
|
<artifactId>quarkus-qute</artifactId>
|
||||||
<version>4.0.1</version>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- PrimeFaces -->
|
<!-- PrimeFaces -->
|
||||||
@@ -75,13 +73,15 @@
|
|||||||
<classifier>jakarta</classifier>
|
<classifier>jakarta</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Freya Theme -->
|
<!-- Freya Theme - Temporairement désactivé -->
|
||||||
|
<!--
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.primefaces</groupId>
|
<groupId>org.primefaces</groupId>
|
||||||
<artifactId>freya</artifactId>
|
<artifactId>freya</artifactId>
|
||||||
<version>${freya.version}</version>
|
<version>${freya.version}</version>
|
||||||
<classifier>jakarta</classifier>
|
<classifier>jakarta</classifier>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
-->
|
||||||
|
|
||||||
<!-- CDI -->
|
<!-- CDI -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -1,195 +0,0 @@
|
|||||||
package com.gbcm.client.beans.auth;
|
|
||||||
|
|
||||||
import com.gbcm.client.service.GBCMServerClient;
|
|
||||||
import com.gbcm.server.api.dto.UserDTO;
|
|
||||||
import com.gbcm.server.api.dto.LoginRequestDTO;
|
|
||||||
import com.gbcm.server.api.dto.LoginResponseDTO;
|
|
||||||
|
|
||||||
import jakarta.enterprise.context.SessionScoped;
|
|
||||||
import jakarta.faces.application.FacesMessage;
|
|
||||||
import jakarta.faces.context.FacesContext;
|
|
||||||
import jakarta.inject.Inject;
|
|
||||||
import jakarta.inject.Named;
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Managed Bean pour la gestion de l'authentification
|
|
||||||
*/
|
|
||||||
@Named("authBean")
|
|
||||||
@SessionScoped
|
|
||||||
public class AuthBean implements Serializable {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
private GBCMServerClient serverClient;
|
|
||||||
|
|
||||||
// Propriétés de connexion
|
|
||||||
private String email;
|
|
||||||
private String password;
|
|
||||||
private boolean rememberMe;
|
|
||||||
|
|
||||||
// Utilisateur connecté
|
|
||||||
private UserDTO currentUser;
|
|
||||||
private String authToken;
|
|
||||||
private boolean authenticated = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tentative de connexion
|
|
||||||
*/
|
|
||||||
public String login() {
|
|
||||||
try {
|
|
||||||
LoginRequestDTO loginRequest = new LoginRequestDTO();
|
|
||||||
loginRequest.setEmail(email);
|
|
||||||
loginRequest.setPassword(password);
|
|
||||||
loginRequest.setRememberMe(rememberMe);
|
|
||||||
|
|
||||||
LoginResponseDTO response = serverClient.login(loginRequest);
|
|
||||||
|
|
||||||
if (response.isSuccess()) {
|
|
||||||
this.currentUser = response.getUser();
|
|
||||||
this.authToken = response.getToken();
|
|
||||||
this.authenticated = true;
|
|
||||||
|
|
||||||
// Message de succès
|
|
||||||
FacesContext.getCurrentInstance().addMessage(null,
|
|
||||||
new FacesMessage(FacesMessage.SEVERITY_INFO,
|
|
||||||
"Connexion réussie",
|
|
||||||
"Bienvenue " + currentUser.getFirstName()));
|
|
||||||
|
|
||||||
// Redirection selon le rôle
|
|
||||||
return redirectAfterLogin();
|
|
||||||
} else {
|
|
||||||
FacesContext.getCurrentInstance().addMessage(null,
|
|
||||||
new FacesMessage(FacesMessage.SEVERITY_ERROR,
|
|
||||||
"Erreur de connexion",
|
|
||||||
response.getMessage()));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
FacesContext.getCurrentInstance().addMessage(null,
|
|
||||||
new FacesMessage(FacesMessage.SEVERITY_ERROR,
|
|
||||||
"Erreur système",
|
|
||||||
"Impossible de se connecter au serveur"));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Déconnexion
|
|
||||||
*/
|
|
||||||
public String logout() {
|
|
||||||
try {
|
|
||||||
if (authToken != null) {
|
|
||||||
serverClient.logout(authToken);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
// Log l'erreur mais continue la déconnexion
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nettoyage de la session
|
|
||||||
this.currentUser = null;
|
|
||||||
this.authToken = null;
|
|
||||||
this.authenticated = false;
|
|
||||||
this.email = null;
|
|
||||||
this.password = null;
|
|
||||||
this.rememberMe = false;
|
|
||||||
|
|
||||||
// Invalidation de la session JSF
|
|
||||||
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
|
|
||||||
|
|
||||||
return "/index?faces-redirect=true";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Redirection après connexion selon le rôle
|
|
||||||
*/
|
|
||||||
private String redirectAfterLogin() {
|
|
||||||
if (currentUser == null) {
|
|
||||||
return "/index?faces-redirect=true";
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (currentUser.getRole()) {
|
|
||||||
case "ADMIN":
|
|
||||||
return "/pages/admin/dashboard?faces-redirect=true";
|
|
||||||
case "COACH":
|
|
||||||
return "/pages/coaching/dashboard?faces-redirect=true";
|
|
||||||
case "CLIENT":
|
|
||||||
return "/pages/dashboard/client?faces-redirect=true";
|
|
||||||
default:
|
|
||||||
return "/pages/dashboard/home?faces-redirect=true";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Navigation vers le profil
|
|
||||||
*/
|
|
||||||
public String goToProfile() {
|
|
||||||
return "/pages/profile/edit?faces-redirect=true";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Navigation vers les paramètres
|
|
||||||
*/
|
|
||||||
public String goToSettings() {
|
|
||||||
return "/pages/settings/general?faces-redirect=true";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Vérification des permissions
|
|
||||||
*/
|
|
||||||
public boolean hasRole(String role) {
|
|
||||||
return authenticated && currentUser != null &&
|
|
||||||
role.equals(currentUser.getRole());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAdmin() {
|
|
||||||
return hasRole("ADMIN");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCoach() {
|
|
||||||
return hasRole("COACH");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isClient() {
|
|
||||||
return hasRole("CLIENT");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Getters et Setters
|
|
||||||
public String getEmail() {
|
|
||||||
return email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEmail(String email) {
|
|
||||||
this.email = email;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPassword(String password) {
|
|
||||||
this.password = password;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRememberMe() {
|
|
||||||
return rememberMe;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRememberMe(boolean rememberMe) {
|
|
||||||
this.rememberMe = rememberMe;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UserDTO getCurrentUser() {
|
|
||||||
return currentUser;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAuthToken() {
|
|
||||||
return authToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAuthenticated() {
|
|
||||||
return authenticated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
140
src/main/java/com/gbcm/client/service/GBCMServerClient.java
Normal file
140
src/main/java/com/gbcm/client/service/GBCMServerClient.java
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
package com.gbcm.client.service;
|
||||||
|
|
||||||
|
import com.gbcm.server.api.dto.auth.LoginRequestDTO;
|
||||||
|
import com.gbcm.server.api.dto.auth.LoginResponseDTO;
|
||||||
|
import com.gbcm.server.api.dto.user.UserDTO;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.ws.rs.client.Client;
|
||||||
|
import jakarta.ws.rs.client.ClientBuilder;
|
||||||
|
import jakarta.ws.rs.client.Entity;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Client REST pour communiquer avec l'API GBCM Server
|
||||||
|
*
|
||||||
|
* @author GBCM Team
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025-01-01
|
||||||
|
*/
|
||||||
|
@ApplicationScoped
|
||||||
|
public class GBCMServerClient {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(GBCMServerClient.class);
|
||||||
|
|
||||||
|
private static final String BASE_URL = "http://localhost:8080/api";
|
||||||
|
|
||||||
|
private final Client client;
|
||||||
|
|
||||||
|
public GBCMServerClient() {
|
||||||
|
this.client = ClientBuilder.newClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentification utilisateur
|
||||||
|
*
|
||||||
|
* @param loginRequest Données de connexion
|
||||||
|
* @return Réponse d'authentification
|
||||||
|
*/
|
||||||
|
public LoginResponseDTO login(LoginRequestDTO loginRequest) {
|
||||||
|
try {
|
||||||
|
logger.info("Tentative de connexion pour l'utilisateur: {}", loginRequest.getEmail());
|
||||||
|
|
||||||
|
Response response = client
|
||||||
|
.target(BASE_URL + "/auth/login")
|
||||||
|
.request(MediaType.APPLICATION_JSON)
|
||||||
|
.post(Entity.entity(loginRequest, MediaType.APPLICATION_JSON));
|
||||||
|
|
||||||
|
if (response.getStatus() == 200) {
|
||||||
|
LoginResponseDTO loginResponse = response.readEntity(LoginResponseDTO.class);
|
||||||
|
logger.info("Connexion réussie pour l'utilisateur: {}", loginRequest.getEmail());
|
||||||
|
return loginResponse;
|
||||||
|
} else {
|
||||||
|
logger.error("Échec de la connexion pour l'utilisateur: {}. Status: {}",
|
||||||
|
loginRequest.getEmail(), response.getStatus());
|
||||||
|
throw new RuntimeException("Échec de l'authentification: " + response.getStatus());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Erreur lors de la connexion pour l'utilisateur: {}", loginRequest.getEmail(), e);
|
||||||
|
throw new RuntimeException("Erreur de communication avec le serveur", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Déconnexion utilisateur
|
||||||
|
*
|
||||||
|
* @param token Token JWT
|
||||||
|
*/
|
||||||
|
public void logout(String token) {
|
||||||
|
try {
|
||||||
|
logger.info("Déconnexion de l'utilisateur");
|
||||||
|
|
||||||
|
Response response = client
|
||||||
|
.target(BASE_URL + "/auth/logout")
|
||||||
|
.request(MediaType.APPLICATION_JSON)
|
||||||
|
.header("Authorization", "Bearer " + token)
|
||||||
|
.post(Entity.text(""));
|
||||||
|
|
||||||
|
if (response.getStatus() == 200) {
|
||||||
|
logger.info("Déconnexion réussie");
|
||||||
|
} else {
|
||||||
|
logger.warn("Problème lors de la déconnexion. Status: {}", response.getStatus());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Erreur lors de la déconnexion", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Récupération du profil utilisateur
|
||||||
|
*
|
||||||
|
* @param token Token JWT
|
||||||
|
* @return Profil utilisateur
|
||||||
|
*/
|
||||||
|
public UserDTO getUserProfile(String token) {
|
||||||
|
try {
|
||||||
|
logger.info("Récupération du profil utilisateur");
|
||||||
|
|
||||||
|
Response response = client
|
||||||
|
.target(BASE_URL + "/users/profile")
|
||||||
|
.request(MediaType.APPLICATION_JSON)
|
||||||
|
.header("Authorization", "Bearer " + token)
|
||||||
|
.get();
|
||||||
|
|
||||||
|
if (response.getStatus() == 200) {
|
||||||
|
UserDTO user = response.readEntity(UserDTO.class);
|
||||||
|
logger.info("Profil utilisateur récupéré: {}", user.getEmail());
|
||||||
|
return user;
|
||||||
|
} else {
|
||||||
|
logger.error("Échec de la récupération du profil. Status: {}", response.getStatus());
|
||||||
|
throw new RuntimeException("Impossible de récupérer le profil utilisateur");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Erreur lors de la récupération du profil utilisateur", e);
|
||||||
|
throw new RuntimeException("Erreur de communication avec le serveur", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validation d'un token JWT
|
||||||
|
*
|
||||||
|
* @param token Token à valider
|
||||||
|
* @return true si le token est valide
|
||||||
|
*/
|
||||||
|
public boolean validateToken(String token) {
|
||||||
|
try {
|
||||||
|
Response response = client
|
||||||
|
.target(BASE_URL + "/auth/validate")
|
||||||
|
.request(MediaType.APPLICATION_JSON)
|
||||||
|
.header("Authorization", "Bearer " + token)
|
||||||
|
.get();
|
||||||
|
|
||||||
|
return response.getStatus() == 200;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Erreur lors de la validation du token", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
src/main/java/com/gbcm/client/web/HomeController.java
Normal file
42
src/main/java/com/gbcm/client/web/HomeController.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package com.gbcm.client.web;
|
||||||
|
|
||||||
|
import jakarta.ws.rs.GET;
|
||||||
|
import jakarta.ws.rs.Path;
|
||||||
|
import jakarta.ws.rs.Produces;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import io.quarkus.qute.Template;
|
||||||
|
import io.quarkus.qute.TemplateInstance;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contrôleur principal pour l'interface web GBCM
|
||||||
|
*
|
||||||
|
* @author GBCM Team
|
||||||
|
* @version 1.0.0
|
||||||
|
* @since 2025-01-01
|
||||||
|
*/
|
||||||
|
@Path("/")
|
||||||
|
public class HomeController {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Template index;
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Produces(MediaType.TEXT_HTML)
|
||||||
|
public TemplateInstance home() {
|
||||||
|
logger.info("Accès à la page d'accueil GBCM");
|
||||||
|
return index.data("title", "GBCM - Global Business Consulting & Management")
|
||||||
|
.data("message", "Bienvenue dans l'interface web GBCM");
|
||||||
|
}
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/health")
|
||||||
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
|
public String health() {
|
||||||
|
return "{\"status\":\"UP\",\"service\":\"gbcm-client-web\"}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,8 +12,17 @@ quarkus.servlet.context-path=/gbcm
|
|||||||
# Security Configuration
|
# Security Configuration
|
||||||
quarkus.security.auth.enabled=true
|
quarkus.security.auth.enabled=true
|
||||||
|
|
||||||
|
# Keycloak OIDC Configuration
|
||||||
|
quarkus.oidc.auth-server-url=http://localhost:8180/realms/gbcm-llc
|
||||||
|
quarkus.oidc.client-id=gbcm-web-client
|
||||||
|
quarkus.oidc.credentials.secret=gbcm-web-secret
|
||||||
|
quarkus.oidc.tls.verification=none
|
||||||
|
quarkus.oidc.application-type=web-app
|
||||||
|
quarkus.oidc.authentication.redirect-path=/gbcm/login
|
||||||
|
quarkus.oidc.authentication.restore-path-after-redirect=true
|
||||||
|
|
||||||
# REST Client Configuration - GBCM Server API
|
# REST Client Configuration - GBCM Server API
|
||||||
gbcm.server.api.url=http://localhost:8081/api/v1
|
gbcm.server.api.url=http://localhost:8082/api
|
||||||
quarkus.rest-client."com.gbcm.client.service.GBCMServerClient".url=${gbcm.server.api.url}
|
quarkus.rest-client."com.gbcm.client.service.GBCMServerClient".url=${gbcm.server.api.url}
|
||||||
|
|
||||||
# Database Configuration (for session storage)
|
# Database Configuration (for session storage)
|
||||||
|
|||||||
143
src/main/resources/templates/index.html
Normal file
143
src/main/resources/templates/index.html
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{title}</title>
|
||||||
|
<style>
|
||||||
|
* {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
background: linear-gradient(135deg, #1976D2 0%, #1565C0 100%);
|
||||||
|
min-height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
background: white;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||||
|
padding: 3rem;
|
||||||
|
max-width: 600px;
|
||||||
|
width: 90%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #1976D2;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtitle {
|
||||||
|
color: #666;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
color: #333;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-indicator {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #4CAF50;
|
||||||
|
animation: pulse 2s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0% { opacity: 1; }
|
||||||
|
50% { opacity: 0.5; }
|
||||||
|
100% { opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.features {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
||||||
|
gap: 1rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature {
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
border-left: 4px solid #1976D2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature h3 {
|
||||||
|
color: #1976D2;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature p {
|
||||||
|
color: #666;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
margin-top: 2rem;
|
||||||
|
padding-top: 1rem;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
color: #999;
|
||||||
|
font-size: 0.9rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="logo">GBCM</div>
|
||||||
|
<div class="subtitle">Global Business Consulting & Management</div>
|
||||||
|
<div class="message">{message}</div>
|
||||||
|
|
||||||
|
<div class="status">
|
||||||
|
<div class="status-indicator"></div>
|
||||||
|
<span>Interface Web Active</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="features">
|
||||||
|
<div class="feature">
|
||||||
|
<h3>🏢 Gestion Clients</h3>
|
||||||
|
<p>Suivi complet des prospects et clients</p>
|
||||||
|
</div>
|
||||||
|
<div class="feature">
|
||||||
|
<h3>👨💼 Gestion Coaches</h3>
|
||||||
|
<p>Planification et suivi des coaches</p>
|
||||||
|
</div>
|
||||||
|
<div class="feature">
|
||||||
|
<h3>🎯 Ateliers</h3>
|
||||||
|
<p>Organisation des workshops</p>
|
||||||
|
</div>
|
||||||
|
<div class="feature">
|
||||||
|
<h3>💬 Sessions</h3>
|
||||||
|
<p>Coaching individuel personnalisé</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
Interface Web GBCM v1.0.0 - Powered by Quarkus
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
59
src/main/webapp/index.xhtml
Normal file
59
src/main/webapp/index.xhtml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||||
|
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||||
|
xmlns:p="http://primefaces.org/ui">
|
||||||
|
|
||||||
|
<h:head>
|
||||||
|
<title>GBCM - Global Business Consulting and Management</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
<h:outputStylesheet library="css" name="freya-theme.css"/>
|
||||||
|
</h:head>
|
||||||
|
|
||||||
|
<h:body>
|
||||||
|
<div class="layout-wrapper">
|
||||||
|
<div class="layout-main">
|
||||||
|
<div class="layout-content">
|
||||||
|
<div class="layout-content-inner">
|
||||||
|
<div class="content-section introduction">
|
||||||
|
<div class="feature-intro">
|
||||||
|
<h1>GBCM Client Web</h1>
|
||||||
|
<p>Interface web pour la plateforme GBCM</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content-section implementation">
|
||||||
|
<div class="card">
|
||||||
|
<h2>Bienvenue sur GBCM</h2>
|
||||||
|
<p>Global Business Consulting and Management - Plateforme de conseil en entreprise</p>
|
||||||
|
|
||||||
|
<h:form>
|
||||||
|
<div class="p-grid">
|
||||||
|
<div class="p-col-12 p-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<h3>Authentification</h3>
|
||||||
|
<p:commandButton value="Se connecter"
|
||||||
|
action="#{authBean.redirectToLogin}"
|
||||||
|
styleClass="ui-button-success"
|
||||||
|
icon="pi pi-sign-in"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="p-col-12 p-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<h3>Statut du serveur</h3>
|
||||||
|
<p:outputLabel value="Backend API : " />
|
||||||
|
<p:outputLabel value="http://localhost:8080"
|
||||||
|
styleClass="ui-state-highlight"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h:form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</h:body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user