diff --git a/pom.xml b/pom.xml
index c782337..b6c2334 100644
--- a/pom.xml
+++ b/pom.xml
@@ -57,21 +57,30 @@
io.quarkus
quarkus-resteasy-reactive
+
+
+
+
+
- io.quarkus
- quarkus-qute
+ io.quarkiverse.primefaces
+ quarkus-primefaces
+ 3.13.3
-
+
- io.quarkus
- quarkus-resteasy-reactive-qute
+ io.quarkiverse.primefaces
+ quarkus-primefaces-extensions
+ 3.13.3
-
+
- io.quarkus
- quarkus-arc
+ org.primefaces.themes
+ freya
+ 5.0.0
+ jakarta
diff --git a/src/main/java/com/gbcm/client/beans/ClientBean.java b/src/main/java/com/gbcm/client/beans/ClientBean.java
new file mode 100644
index 0000000..a23e4c3
--- /dev/null
+++ b/src/main/java/com/gbcm/client/beans/ClientBean.java
@@ -0,0 +1,101 @@
+package com.gbcm.client.beans;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.logging.Logger;
+
+import com.gbcm.client.service.ClientRestService;
+import com.gbcm.server.api.dto.client.ClientDTO;
+import com.gbcm.server.api.dto.common.PagedResponseDTO;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+
+/**
+ * Bean pour la gestion des clients dans l'interface web.
+ * Connecté au serveur backend pour récupérer les vraies données.
+ *
+ * @author GBCM Development Team
+ * @version 1.0
+ * @since 1.0
+ */
+@Named("clientBean")
+@RequestScoped
+public class ClientBean implements Serializable {
+
+ private static final Logger logger = Logger.getLogger(ClientBean.class.getName());
+
+ @Inject
+ private ClientRestService clientRestService;
+
+ /**
+ * Obtient la liste des clients depuis le serveur backend
+ */
+ public List getClients() {
+ try {
+ logger.info("Récupération de la liste des clients depuis le serveur backend");
+
+ PagedResponseDTO pagedResponse = clientRestService.getClients(0, 50, null, null, null, null);
+ List clients = pagedResponse.getContent();
+
+ logger.info("Retour de " + clients.size() + " clients depuis le serveur");
+ return clients;
+ } catch (Exception e) {
+ logger.severe("Erreur lors de la récupération des clients: " + e.getMessage());
+ // Retourner une liste vide en cas d'erreur
+ return new ArrayList<>();
+ }
+ }
+
+ /**
+ * Obtient la date actuelle pour l'affichage
+ */
+ public Date getCurrentDate() {
+ return new Date();
+ }
+
+ /**
+ * Crée un nouveau client via l'API
+ */
+ public String createClient(ClientDTO clientDTO) {
+ try {
+ logger.info("Création d'un nouveau client via l'API");
+ // TODO: Implémenter la création via clientRestService
+ return "/pages/clients/list?faces-redirect=true";
+ } catch (Exception e) {
+ logger.severe("Erreur lors de la création du client: " + e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * Met à jour un client via l'API
+ */
+ public String updateClient(ClientDTO clientDTO) {
+ try {
+ logger.info("Mise à jour du client via l'API: " + clientDTO.getId());
+ // TODO: Implémenter la mise à jour via clientRestService
+ return "/pages/clients/list?faces-redirect=true";
+ } catch (Exception e) {
+ logger.severe("Erreur lors de la mise à jour du client: " + e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * Supprime un client via l'API
+ */
+ public String deleteClient(Long clientId) {
+ try {
+ logger.info("Suppression du client via l'API: " + clientId);
+ // TODO: Implémenter la suppression via clientRestService
+ return "/pages/clients/list?faces-redirect=true";
+ } catch (Exception e) {
+ logger.severe("Erreur lors de la suppression du client: " + e.getMessage());
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/com/gbcm/client/beans/CoachBean.java b/src/main/java/com/gbcm/client/beans/CoachBean.java
new file mode 100644
index 0000000..4842c17
--- /dev/null
+++ b/src/main/java/com/gbcm/client/beans/CoachBean.java
@@ -0,0 +1,36 @@
+package com.gbcm.client.beans;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import com.gbcm.client.service.CoachRestService;
+import com.gbcm.server.api.dto.coach.CoachDTO;
+import com.gbcm.server.api.dto.common.PagedResponseDTO;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+
+@Named("coachBean")
+@RequestScoped
+public class CoachBean implements Serializable {
+
+ private static final Logger logger = Logger.getLogger(CoachBean.class.getName());
+
+ @Inject
+ private CoachRestService coachRestService;
+
+ public List getCoaches() {
+ try {
+ logger.info("Récupération de la liste des coachs depuis le serveur backend");
+ PagedResponseDTO pagedResponse = coachRestService.getCoaches(0, 50, null, null, null, false,
+ null);
+ return pagedResponse.getContent();
+ } catch (Exception e) {
+ logger.severe("Erreur lors de la récupération des coachs: " + e.getMessage());
+ return new ArrayList<>();
+ }
+ }
+}
diff --git a/src/main/java/com/gbcm/client/beans/CoachingSessionBean.java b/src/main/java/com/gbcm/client/beans/CoachingSessionBean.java
new file mode 100644
index 0000000..db05635
--- /dev/null
+++ b/src/main/java/com/gbcm/client/beans/CoachingSessionBean.java
@@ -0,0 +1,36 @@
+package com.gbcm.client.beans;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import com.gbcm.client.service.CoachingSessionRestService;
+import com.gbcm.server.api.dto.session.CoachingSessionDTO;
+import com.gbcm.server.api.dto.common.PagedResponseDTO;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+
+@Named("sessionBean")
+@RequestScoped
+public class CoachingSessionBean implements Serializable {
+
+ private static final Logger logger = Logger.getLogger(CoachingSessionBean.class.getName());
+
+ @Inject
+ private CoachingSessionRestService sessionRestService;
+
+ public List getSessions() {
+ try {
+ logger.info("Récupération de la liste des sessions");
+ PagedResponseDTO pagedResponse = sessionRestService.getCoachingSessions(0, 50, null,
+ null, null, null, null, null);
+ return pagedResponse.getContent();
+ } catch (Exception e) {
+ logger.severe("Erreur lors de la récupération des sessions: " + e.getMessage());
+ return new ArrayList<>();
+ }
+ }
+}
diff --git a/src/main/java/com/gbcm/client/beans/DashboardBean.java b/src/main/java/com/gbcm/client/beans/DashboardBean.java
new file mode 100644
index 0000000..a075c58
--- /dev/null
+++ b/src/main/java/com/gbcm/client/beans/DashboardBean.java
@@ -0,0 +1,237 @@
+package com.gbcm.client.beans;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import com.gbcm.client.service.DashboardRestService;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+
+@Named("dashboardBean")
+@RequestScoped
+public class DashboardBean implements Serializable {
+
+ @Inject
+ private DashboardRestService dashboardRestService;
+
+ // Propriétés pour les filtres et sélections
+ private String revenuePeriod = "30d";
+
+ // Cache des métriques pour la requête
+ private Map metrics;
+ private Map clientMetrics;
+ private Map sessionMetrics;
+ private Map workshopMetrics;
+ private Map financialMetrics;
+
+ @SuppressWarnings("unchecked")
+ @PostConstruct
+ public void init() {
+ try {
+ metrics = dashboardRestService.getDashboardMetrics();
+ if (metrics != null) {
+ clientMetrics = (Map) metrics.get("clients");
+ sessionMetrics = (Map) metrics.get("sessions");
+ workshopMetrics = (Map) metrics.get("workshops");
+ financialMetrics = (Map) metrics.get("financial");
+ }
+ } catch (Exception e) {
+ // Fallback empty maps to avoid NPE
+ clientMetrics = Map.of();
+ sessionMetrics = Map.of();
+ workshopMetrics = Map.of();
+ financialMetrics = Map.of();
+ }
+ }
+
+ /**
+ * Classe pour représenter une activité récente
+ */
+ public static class Activity {
+ private String icon;
+ private String title;
+ private String description;
+ private String timestamp;
+
+ public Activity(String icon, String title, String description, String timestamp) {
+ this.icon = icon;
+ this.title = title;
+ this.description = description;
+ this.timestamp = timestamp;
+ }
+
+ public String getIcon() {
+ return icon;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getTimestamp() {
+ return timestamp;
+ }
+ }
+
+ /**
+ * Classe pour représenter une tâche
+ */
+ public static class Task {
+ private String title;
+ private String description;
+ private String clientName;
+ private String priority;
+ private String dueDate;
+ private boolean completed;
+
+ public Task(String title, String description, String clientName, String priority, String dueDate,
+ boolean completed) {
+ this.title = title;
+ this.description = description;
+ this.clientName = clientName;
+ this.priority = priority;
+ this.dueDate = dueDate;
+ this.completed = completed;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getClientName() {
+ return clientName;
+ }
+
+ public String getPriority() {
+ return priority;
+ }
+
+ public String getDueDate() {
+ return dueDate;
+ }
+
+ public boolean isCompleted() {
+ return completed;
+ }
+ }
+
+ public List getRecentActivities() {
+ // Activités simulées pour l'instant car pas d'historique d'activités en DB
+ List activities = new ArrayList<>();
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
+ activities.add(new Activity("pi pi-check", "Système prêt", "Transition vers Data Réelle effectuée",
+ LocalDateTime.now().format(formatter)));
+ return activities;
+ }
+
+ public int getActiveClientsCount() {
+ return getIntMetric(clientMetrics, "activeClients");
+ }
+
+ public int getSessionsThisMonth() {
+ return getIntMetric(sessionMetrics, "sessionsThisMonth");
+ }
+
+ public int getPlannedWorkshops() {
+ // Using active or scheduled
+ return getIntMetric(workshopMetrics, "activeWorkshops");
+ }
+
+ public String getMonthlyRevenue() {
+ // From financial metrics
+ if (financialMetrics != null && financialMetrics.get("monthlyRevenue") != null) {
+ return "€" + financialMetrics.get("monthlyRevenue");
+ }
+ return "€0";
+ }
+
+ public String getClientsGrowth() {
+ // Not calculated yet
+ return "+0%";
+ }
+
+ public String getSessionsGrowth() {
+ return "+0%";
+ }
+
+ public String getWorkshopsChange() {
+ return "0%";
+ }
+
+ public String getRevenueGrowth() {
+ return "+0%";
+ }
+
+ public List getTasks() {
+ return new ArrayList<>(); // Empty tasks for now
+ }
+
+ public Object getRevenueChartModel() {
+ return null;
+ }
+
+ public Object getClientTypeChartModel() {
+ return null;
+ }
+
+ public String getRevenuePeriod() {
+ return revenuePeriod;
+ }
+
+ public void setRevenuePeriod(String revenuePeriod) {
+ this.revenuePeriod = revenuePeriod;
+ }
+
+ // Stats d'entreprise
+ public int getEnterpriseClients() {
+ // Can be approximate or estimated from total
+ return getIntMetric(clientMetrics, "totalClients");
+ }
+
+ public int getIndividualClients() {
+ return 0;
+ }
+
+ // KPIs
+ public int getRevenueProgress() {
+ return 0;
+ }
+
+ public int getClientProgress() {
+ return 0;
+ }
+
+ public int getSessionProgress() {
+ return 0;
+ }
+
+ public int getSatisfactionProgress() {
+ return 0;
+ }
+
+ // Helpers
+ private int getIntMetric(Map map, String key) {
+ if (map != null && map.get(key) != null) {
+ Object val = map.get(key);
+ if (val instanceof Number) {
+ return ((Number) val).intValue();
+ }
+ }
+ return 0;
+ }
+}
diff --git a/src/main/java/com/gbcm/client/beans/GuestPreferences.java b/src/main/java/com/gbcm/client/beans/GuestPreferences.java
new file mode 100644
index 0000000..5f5a3f4
--- /dev/null
+++ b/src/main/java/com/gbcm/client/beans/GuestPreferences.java
@@ -0,0 +1,155 @@
+package com.gbcm.client.beans;
+
+import java.io.Serializable;
+
+import jakarta.enterprise.context.SessionScoped;
+import jakarta.inject.Named;
+
+@Named("guestPreferences")
+@SessionScoped
+public class GuestPreferences implements Serializable {
+
+ private String layout = "light";
+ private String menuTheme = "light";
+ private String topbarTheme = "light";
+ private String menuMode = "layout-sidebar";
+ private String darkMode = "light";
+ private String inputStyleClass = "";
+ private String inputStyle = "outlined";
+ private String componentTheme = "blue";
+ private boolean lightLogo = false;
+
+ public String getLayout() {
+ return layout;
+ }
+
+ public void setLayout(String layout) {
+ this.layout = layout;
+ }
+
+ public String getMenuTheme() {
+ return menuTheme;
+ }
+
+ public void setMenuTheme(String menuTheme) {
+ this.menuTheme = menuTheme;
+ }
+
+ public String getTopbarTheme() {
+ return topbarTheme;
+ }
+
+ public void setTopbarTheme(String topbarTheme) {
+ this.topbarTheme = topbarTheme;
+ }
+
+ public String getMenuMode() {
+ return menuMode;
+ }
+
+ public void setMenuMode(String menuMode) {
+ this.menuMode = menuMode;
+ }
+
+ public String getDarkMode() {
+ return darkMode;
+ }
+
+ public void setDarkMode(String darkMode) {
+ this.darkMode = darkMode;
+ this.layout = darkMode;
+ }
+
+ public void toggleDarkMode() {
+ setDarkMode("dark".equals(darkMode) ? "light" : "dark");
+ }
+
+ public String getInputStyleClass() {
+ return inputStyleClass;
+ }
+
+ public void setInputStyleClass(String inputStyleClass) {
+ this.inputStyleClass = inputStyleClass;
+ }
+
+ public String getInputStyle() {
+ return inputStyle;
+ }
+
+ public void setInputStyle(String inputStyle) {
+ this.inputStyle = inputStyle;
+ // Mettre à jour la classe CSS en fonction du style
+ if ("filled".equals(inputStyle)) {
+ this.inputStyleClass = "ui-input-filled";
+ } else {
+ this.inputStyleClass = "";
+ }
+ }
+
+ public String getComponentTheme() {
+ return componentTheme;
+ }
+
+ public void setComponentTheme(String componentTheme) {
+ this.componentTheme = componentTheme;
+ }
+
+ // Propriétés manquantes pour le template Freya complet
+ public boolean isLightLogo() {
+ return "dark".equals(topbarTheme) || "dark".equals(darkMode);
+ }
+
+ public void setLightLogo(boolean lightLogo) {
+ this.lightLogo = lightLogo;
+ }
+
+ public void onMenuTypeChange() {
+ // Méthode appelée lors du changement de type de menu
+ }
+
+ // Liste des thèmes de composants disponibles
+ public java.util.List getComponentThemes() {
+ java.util.List themes = new java.util.ArrayList<>();
+ themes.add(new ComponentTheme("blue", "#007ad9", "Blue"));
+ themes.add(new ComponentTheme("green", "#10ac84", "Green"));
+ themes.add(new ComponentTheme("orange", "#ff9f43", "Orange"));
+ themes.add(new ComponentTheme("purple", "#5f27cd", "Purple"));
+ themes.add(new ComponentTheme("red", "#ee5a52", "Red"));
+ themes.add(new ComponentTheme("teal", "#00d2d3", "Teal"));
+ themes.add(new ComponentTheme("yellow", "#feca57", "Yellow"));
+ themes.add(new ComponentTheme("pink", "#ff6b9d", "Pink"));
+ themes.add(new ComponentTheme("indigo", "#3742fa", "Indigo"));
+ themes.add(new ComponentTheme("cyan", "#0abde3", "Cyan"));
+ return themes;
+ }
+
+ // Classe interne pour les thèmes de composants
+ public static class ComponentTheme {
+ private String file;
+ private String color;
+ private String name;
+
+ public ComponentTheme(String file, String color, String name) {
+ this.file = file;
+ this.color = color;
+ this.name = name;
+ }
+
+ public String getFile() { return file; }
+ public void setFile(String file) { this.file = file; }
+ public String getColor() { return color; }
+ public void setColor(String color) { this.color = color; }
+ public String getName() { return name; }
+ public void setName(String name) { this.name = name; }
+ }
+
+ public String getLayoutClass() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("layout-wrapper ");
+ sb.append("layout-").append(layout).append(" ");
+ sb.append(menuTheme).append(" ");
+ sb.append(topbarTheme).append(" ");
+ sb.append("layout-menu-").append(menuMode);
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/com/gbcm/client/beans/NavigationBean.java b/src/main/java/com/gbcm/client/beans/NavigationBean.java
new file mode 100644
index 0000000..d19bb3d
--- /dev/null
+++ b/src/main/java/com/gbcm/client/beans/NavigationBean.java
@@ -0,0 +1,97 @@
+package com.gbcm.client.beans;
+
+import com.gbcm.client.beans.auth.AuthBean;
+import jakarta.enterprise.context.SessionScoped;
+import jakarta.inject.Named;
+import jakarta.inject.Inject;
+import java.io.Serializable;
+
+@Named("navigationBean")
+@SessionScoped
+public class NavigationBean implements Serializable {
+
+ @Inject
+ private AuthBean authBean;
+
+ /**
+ * Navigation vers la page d'accueil
+ */
+ public String home() {
+ return "/index?faces-redirect=true";
+ }
+
+ /**
+ * Navigation vers le dashboard
+ */
+ public String dashboard() {
+ if (!authBean.isAuthenticated()) {
+ return "/index?faces-redirect=true";
+ }
+ return "/pages/dashboard?faces-redirect=true";
+ }
+
+ /**
+ * Navigation vers la gestion des clients
+ */
+ public String clients() {
+ if (!authBean.isAuthenticated()) {
+ return "/index?faces-redirect=true";
+ }
+ return "/pages/clients?faces-redirect=true";
+ }
+
+ /**
+ * Navigation vers le profil
+ */
+ public String profile() {
+ if (!authBean.isAuthenticated()) {
+ return "/index?faces-redirect=true";
+ }
+ return "/pages/profile?faces-redirect=true";
+ }
+
+ /**
+ * Navigation vers les projets
+ */
+ public String projects() {
+ if (!authBean.isAuthenticated()) {
+ return "/index?faces-redirect=true";
+ }
+ return "/pages/projects?faces-redirect=true";
+ }
+
+ /**
+ * Navigation vers les rapports
+ */
+ public String reports() {
+ if (!authBean.isAuthenticated()) {
+ return "/index?faces-redirect=true";
+ }
+ return "/pages/reports?faces-redirect=true";
+ }
+
+ /**
+ * Navigation vers les paramètres
+ */
+ public String settings() {
+ if (!authBean.isAuthenticated()) {
+ return "/index?faces-redirect=true";
+ }
+ return "/pages/settings?faces-redirect=true";
+ }
+
+ /**
+ * Vérifie si la page actuelle est active
+ */
+ public boolean isPageActive(String page) {
+ // Cette méthode peut être étendue pour vérifier l'URL actuelle
+ return false;
+ }
+
+ /**
+ * Obtient la classe CSS pour un élément de menu
+ */
+ public String getMenuItemClass(String page) {
+ return isPageActive(page) ? "active-menuitem" : "";
+ }
+}
diff --git a/src/main/java/com/gbcm/client/beans/WorkshopBean.java b/src/main/java/com/gbcm/client/beans/WorkshopBean.java
new file mode 100644
index 0000000..36a1f11
--- /dev/null
+++ b/src/main/java/com/gbcm/client/beans/WorkshopBean.java
@@ -0,0 +1,36 @@
+package com.gbcm.client.beans;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import com.gbcm.client.service.WorkshopRestService;
+import com.gbcm.server.api.dto.workshop.WorkshopDTO;
+import com.gbcm.server.api.dto.common.PagedResponseDTO;
+
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+
+@Named("workshopBean")
+@RequestScoped
+public class WorkshopBean implements Serializable {
+
+ private static final Logger logger = Logger.getLogger(WorkshopBean.class.getName());
+
+ @Inject
+ private WorkshopRestService workshopRestService;
+
+ public List getWorkshops() {
+ try {
+ logger.info("Récupération de la liste des ateliers");
+ PagedResponseDTO pagedResponse = workshopRestService.getWorkshops(0, 50, null, null, null,
+ null, null);
+ return pagedResponse.getContent();
+ } catch (Exception e) {
+ logger.severe("Erreur lors de la récupération des ateliers: " + e.getMessage());
+ return new ArrayList<>();
+ }
+ }
+}
diff --git a/src/main/java/com/gbcm/client/beans/auth/AuthBean.java b/src/main/java/com/gbcm/client/beans/auth/AuthBean.java
new file mode 100644
index 0000000..34bb07f
--- /dev/null
+++ b/src/main/java/com/gbcm/client/beans/auth/AuthBean.java
@@ -0,0 +1,319 @@
+package com.gbcm.client.beans.auth;
+
+import java.io.Serializable;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import org.eclipse.microprofile.jwt.JsonWebToken;
+
+import io.quarkus.oidc.IdToken;
+import io.quarkus.oidc.OidcSession;
+import io.quarkus.security.identity.SecurityIdentity;
+import jakarta.enterprise.context.SessionScoped;
+import jakarta.faces.application.FacesMessage;
+import jakarta.faces.context.FacesContext;
+import jakarta.inject.Inject;
+import jakarta.inject.Named;
+
+@Named("authBean")
+@SessionScoped
+public class AuthBean implements Serializable {
+
+ private static final Logger logger = Logger.getLogger(AuthBean.class.getName());
+
+ @Inject
+ SecurityIdentity securityIdentity;
+
+ @Inject
+ OidcSession oidcSession;
+
+ @Inject
+ @IdToken
+ JsonWebToken idToken;
+
+ /**
+ * Vérifie si l'utilisateur est authentifié
+ */
+ public boolean isAuthenticated() {
+ return securityIdentity != null && !securityIdentity.isAnonymous();
+ }
+
+ /**
+ * Obtient le nom d'utilisateur
+ */
+ public String getUsername() {
+ if (!isAuthenticated()) {
+ return "Invité";
+ }
+ return securityIdentity.getPrincipal().getName();
+ }
+
+ /**
+ * Obtient le nom d'utilisateur (alias pour le topbar)
+ */
+ public String getUserName() {
+ return getFullName();
+ }
+
+ /**
+ * Obtient l'email de l'utilisateur depuis le token ID
+ */
+ public String getEmail() {
+ if (!isAuthenticated() || idToken == null) {
+ return "guest@example.com";
+ }
+
+ String email = idToken.getClaim("email");
+ return email != null ? email : getUsername();
+ }
+
+ /**
+ * Obtient l'email de l'utilisateur (alias pour le topbar)
+ */
+ public String getUserEmail() {
+ return getEmail();
+ }
+
+ /**
+ * Obtient l'avatar de l'utilisateur
+ */
+ public String getUserAvatar() {
+ if (!isAuthenticated() || idToken == null) {
+ return "images/avatar-gbcm.png";
+ }
+
+ // Vérifier s'il y a une photo dans le token
+ String picture = idToken.getClaim("picture");
+ if (picture != null && !picture.trim().isEmpty()) {
+ return picture;
+ }
+
+ // Avatar par défaut GBCM
+ return "images/avatar-gbcm.png";
+ }
+
+ /**
+ * Obtient le nom complet de l'utilisateur
+ */
+ public String getFullName() {
+ if (!isAuthenticated() || idToken == null) {
+ return "Utilisateur Invité";
+ }
+
+ String givenName = idToken.getClaim("given_name");
+ String familyName = idToken.getClaim("family_name");
+
+ if (givenName != null && familyName != null) {
+ return givenName + " " + familyName;
+ }
+
+ String name = idToken.getClaim("name");
+ return name != null ? name : getUsername();
+ }
+
+ /**
+ * Obtient les rôles de l'utilisateur
+ */
+ public Set getRoles() {
+ if (!isAuthenticated()) {
+ return Set.of("GUEST");
+ }
+ return securityIdentity.getRoles();
+ }
+
+ /**
+ * Vérifie si l'utilisateur a un rôle spécifique
+ */
+ public boolean hasRole(String role) {
+ return isAuthenticated() && securityIdentity.hasRole(role);
+ }
+
+ /**
+ * Vérifie si l'utilisateur est administrateur
+ */
+ public boolean isAdmin() {
+ return hasRole("ADMIN");
+ }
+
+ /**
+ * Vérifie si l'utilisateur est manager
+ */
+ public boolean isManager() {
+ return hasRole("MANAGER");
+ }
+
+ /**
+ * Vérifie si l'utilisateur est coach
+ */
+ public boolean isCoach() {
+ return hasRole("COACH");
+ }
+
+ /**
+ * Vérifie si l'utilisateur est client
+ */
+ public boolean isClient() {
+ return hasRole("CLIENT");
+ }
+
+ /**
+ * Vérifie si l'utilisateur est prospect
+ */
+ public boolean isProspect() {
+ return hasRole("PROSPECT");
+ }
+
+ /**
+ * Obtient le rôle principal de l'utilisateur
+ */
+ public String getPrimaryRole() {
+ if (!isAuthenticated()) {
+ return "GUEST";
+ }
+
+ Set roles = getRoles();
+ if (roles.contains("ADMIN")) return "ADMIN";
+ if (roles.contains("MANAGER")) return "MANAGER";
+ if (roles.contains("COACH")) return "COACH";
+ if (roles.contains("CLIENT")) return "CLIENT";
+ if (roles.contains("PROSPECT")) return "PROSPECT";
+
+ return roles.isEmpty() ? "USER" : roles.iterator().next();
+ }
+
+ /**
+ * Déconnexion OIDC
+ */
+ public String logout() {
+ try {
+ logger.info("Début de la déconnexion OIDC");
+
+ if (oidcSession != null) {
+ logger.info("Déconnexion de la session OIDC");
+ oidcSession.logout().await().indefinitely();
+ }
+
+ // Invalider la session JSF
+ FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
+
+ // Message de confirmation
+ FacesContext.getCurrentInstance().addMessage(null,
+ new FacesMessage(FacesMessage.SEVERITY_INFO, "Déconnexion réussie",
+ "Vous avez été déconnecté avec succès."));
+
+ logger.info("Déconnexion OIDC terminée");
+ return "/index?faces-redirect=true";
+
+ } catch (Exception e) {
+ logger.severe("Erreur lors de la déconnexion OIDC: " + e.getMessage());
+ FacesContext.getCurrentInstance().addMessage(null,
+ new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur de déconnexion",
+ "Une erreur s'est produite lors de la déconnexion."));
+ return null;
+ }
+ }
+
+ /**
+ * Obtient les informations du token ID pour debug
+ */
+ public String getTokenInfo() {
+ if (!isAuthenticated() || idToken == null) {
+ return "Aucun token disponible";
+ }
+
+ StringBuilder info = new StringBuilder();
+ info.append("Issuer: ").append(idToken.getIssuer()).append("\n");
+ info.append("Subject: ").append(idToken.getSubject()).append("\n");
+ info.append("Expiration: ").append(idToken.getExpirationTime()).append("\n");
+ info.append("Issued At: ").append(idToken.getIssuedAtTime()).append("\n");
+
+ return info.toString();
+ }
+
+ /**
+ * Obtient les informations détaillées du token pour la page profil
+ */
+ public TokenInfo getTokenInfoDetails() {
+ if (!isAuthenticated() || idToken == null) {
+ return new TokenInfo();
+ }
+
+ return new TokenInfo(
+ idToken.getIssuer(),
+ idToken.getSubject(),
+ idToken.getAudience() != null ? String.join(", ", idToken.getAudience()) : "N/A",
+ idToken.getExpirationTime(),
+ idToken.getIssuedAtTime()
+ );
+ }
+
+ /**
+ * Classe interne pour les informations du token
+ */
+ public static class TokenInfo {
+ private String issuer;
+ private String subject;
+ private String audience;
+ private Long expirationTime;
+ private Long issuedAt;
+
+ public TokenInfo() {
+ this.issuer = "N/A";
+ this.subject = "N/A";
+ this.audience = "N/A";
+ this.expirationTime = 0L;
+ this.issuedAt = 0L;
+ }
+
+ public TokenInfo(String issuer, String subject, String audience, Long expirationTime, Long issuedAt) {
+ this.issuer = issuer;
+ this.subject = subject;
+ this.audience = audience;
+ this.expirationTime = expirationTime;
+ this.issuedAt = issuedAt;
+ }
+
+ public String getIssuer() { return issuer; }
+ public String getSubject() { return subject; }
+ public String getAudience() { return audience; }
+ public Long getExpirationTime() { return expirationTime; }
+ public Long getIssuedAt() { return issuedAt; }
+ }
+
+ /**
+ * Navigation vers le login
+ */
+ public String login() {
+ return "/login?faces-redirect=true";
+ }
+
+ /**
+ * Navigation vers le dashboard
+ */
+ public String dashboard() {
+ if (!isAuthenticated()) {
+ return login();
+ }
+ return "/pages/dashboard?faces-redirect=true";
+ }
+
+ /**
+ * Navigation vers le profil
+ */
+ public String profile() {
+ if (!isAuthenticated()) {
+ return login();
+ }
+ return "/pages/profile?faces-redirect=true";
+ }
+
+ /**
+ * Navigation vers les clients
+ */
+ public String clients() {
+ if (!isAuthenticated()) {
+ return login();
+ }
+ return "/pages/clients?faces-redirect=true";
+ }
+}
diff --git a/src/main/java/com/gbcm/client/controller/IndexController.java b/src/main/java/com/gbcm/client/controller/IndexController.java
new file mode 100644
index 0000000..6ad50cb
--- /dev/null
+++ b/src/main/java/com/gbcm/client/controller/IndexController.java
@@ -0,0 +1,21 @@
+package com.gbcm.client.controller;
+
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.core.Response;
+import java.net.URI;
+
+/**
+ * Contrôleur pour gérer la redirection vers la page d'accueil
+ */
+@Path("/")
+public class IndexController {
+
+ /**
+ * Redirige la racine vers index.xhtml
+ */
+ @GET
+ public Response redirectToIndex() {
+ return Response.seeOther(URI.create("index.xhtml")).build();
+ }
+}
diff --git a/src/main/java/com/gbcm/client/resources/HomeController.java b/src/main/java/com/gbcm/client/resources/HomeController.java
deleted file mode 100644
index fc8fff0..0000000
--- a/src/main/java/com/gbcm/client/resources/HomeController.java
+++ /dev/null
@@ -1,76 +0,0 @@
-package com.gbcm.client.resources;
-
-import io.quarkus.qute.Template;
-import io.quarkus.qute.TemplateInstance;
-import io.quarkus.security.identity.SecurityIdentity;
-import io.quarkus.oidc.OidcSession;
-import io.quarkus.oidc.IdToken;
-import org.eclipse.microprofile.jwt.JsonWebToken;
-
-import jakarta.inject.Inject;
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.Path;
-import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.MediaType;
-
-@Path("/")
-public class HomeController {
-
- @Inject
- Template index;
-
- @Inject
- SecurityIdentity securityIdentity;
-
- @Inject
- OidcSession oidcSession;
-
- @Inject
- @IdToken
- JsonWebToken idToken;
-
- @GET
- @Produces(MediaType.TEXT_HTML)
- public TemplateInstance index() {
- return index
- .data("user", getCurrentUser())
- .data("authenticated", isAuthenticated())
- .data("title", "Accueil - GBCM");
- }
-
- @GET
- @Path("/index")
- @Produces(MediaType.TEXT_HTML)
- public TemplateInstance indexPage() {
- return index();
- }
-
- private boolean isAuthenticated() {
- return securityIdentity != null && !securityIdentity.isAnonymous();
- }
-
- private UserInfo getCurrentUser() {
- if (!isAuthenticated()) {
- return new UserInfo("Invité", "guest@example.com", "GUEST");
- }
-
- String username = securityIdentity.getPrincipal().getName();
- String email = idToken != null ? idToken.getClaim("email") : username;
- String role = securityIdentity.getRoles().isEmpty() ? "USER" :
- securityIdentity.getRoles().iterator().next();
-
- return new UserInfo(username, email, role);
- }
-
- public static class UserInfo {
- public final String name;
- public final String email;
- public final String role;
-
- public UserInfo(String name, String email, String role) {
- this.name = name;
- this.email = email;
- this.role = role;
- }
- }
-}
diff --git a/src/main/java/com/gbcm/client/resources/PageController.java b/src/main/java/com/gbcm/client/resources/PageController.java
deleted file mode 100644
index 2202044..0000000
--- a/src/main/java/com/gbcm/client/resources/PageController.java
+++ /dev/null
@@ -1,111 +0,0 @@
-package com.gbcm.client.resources;
-
-import io.quarkus.qute.Template;
-import io.quarkus.qute.TemplateInstance;
-import io.quarkus.security.identity.SecurityIdentity;
-import io.quarkus.oidc.OidcSession;
-import io.quarkus.oidc.IdToken;
-import org.eclipse.microprofile.jwt.JsonWebToken;
-
-import jakarta.inject.Inject;
-import jakarta.ws.rs.GET;
-import jakarta.ws.rs.Path;
-import jakarta.ws.rs.Produces;
-import jakarta.ws.rs.core.MediaType;
-
-@Path("/pages")
-public class PageController {
-
- @Inject
- Template dashboard;
-
- @Inject
- Template clients;
-
- @Inject
- Template profile;
-
- @Inject
- SecurityIdentity securityIdentity;
-
- @Inject
- OidcSession oidcSession;
-
- @Inject
- @IdToken
- JsonWebToken idToken;
-
- @GET
- @Path("/dashboard")
- @Produces(MediaType.TEXT_HTML)
- public TemplateInstance dashboard() {
- return dashboard
- .data("user", getCurrentUser())
- .data("authenticated", isAuthenticated())
- .data("title", "Tableau de Bord - GBCM");
- }
-
- @GET
- @Path("/clients")
- @Produces(MediaType.TEXT_HTML)
- public TemplateInstance clients() {
- return clients
- .data("user", getCurrentUser())
- .data("authenticated", isAuthenticated())
- .data("title", "Gestion des Clients - GBCM");
- }
-
- @GET
- @Path("/profile")
- @Produces(MediaType.TEXT_HTML)
- public TemplateInstance profile() {
- return profile
- .data("user", getCurrentUser())
- .data("authenticated", isAuthenticated())
- .data("title", "Profil Utilisateur - GBCM")
- .data("tokenInfo", getTokenInfo());
- }
-
- private boolean isAuthenticated() {
- return securityIdentity != null && !securityIdentity.isAnonymous();
- }
-
- private UserInfo getCurrentUser() {
- if (!isAuthenticated()) {
- return new UserInfo("Invité", "guest@example.com", "GUEST");
- }
-
- String username = securityIdentity.getPrincipal().getName();
- String email = idToken != null ? idToken.getClaim("email") : username;
- String role = securityIdentity.getRoles().isEmpty() ? "USER" :
- securityIdentity.getRoles().iterator().next();
-
- return new UserInfo(username, email, role);
- }
-
- private String getTokenInfo() {
- if (idToken == null) {
- return "Aucun token disponible";
- }
-
- StringBuilder info = new StringBuilder();
- info.append("Issuer: ").append(idToken.getIssuer()).append("\n");
- info.append("Subject: ").append(idToken.getSubject()).append("\n");
- info.append("Expiration: ").append(idToken.getExpirationTime()).append("\n");
- info.append("Issued At: ").append(idToken.getIssuedAtTime()).append("\n");
-
- return info.toString();
- }
-
- public static class UserInfo {
- public final String name;
- public final String email;
- public final String role;
-
- public UserInfo(String name, String email, String role) {
- this.name = name;
- this.email = email;
- this.role = role;
- }
- }
-}
diff --git a/src/main/java/com/gbcm/client/service/ClientRestService.java b/src/main/java/com/gbcm/client/service/ClientRestService.java
new file mode 100644
index 0000000..159494e
--- /dev/null
+++ b/src/main/java/com/gbcm/client/service/ClientRestService.java
@@ -0,0 +1,127 @@
+package com.gbcm.client.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+
+import com.gbcm.server.api.dto.client.ClientDTO;
+import com.gbcm.server.api.dto.client.CreateClientDTO;
+import com.gbcm.server.api.dto.client.UpdateClientDTO;
+import com.gbcm.server.api.dto.common.PagedResponseDTO;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.QueryParam;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+
+/**
+ * Service REST client pour communiquer avec l'API clients du serveur GBCM.
+ * Utilise MicroProfile REST Client pour les appels HTTP.
+ *
+ * @author GBCM Development Team
+ * @version 1.0
+ * @since 1.0
+ */
+@ApplicationScoped
+public class ClientRestService {
+
+ private static final Logger logger = LoggerFactory.getLogger(ClientRestService.class);
+
+ @Inject
+ @RestClient
+ private ClientRestClient clientRestClient;
+
+ /**
+ * Récupère la liste paginée des clients
+ */
+ public PagedResponseDTO getClients(int page, int size, String sort,
+ String status, String industry, String search) {
+ try {
+ logger.info("Appel API pour récupérer les clients - page: {}, size: {}", page, size);
+ return clientRestClient.getClients(page, size, sort, status, industry, search);
+ } catch (Exception e) {
+ logger.error("Erreur lors de l'appel API getClients: " + e.getMessage(), e);
+ throw new RuntimeException("Impossible de récupérer les clients", e);
+ }
+ }
+
+ /**
+ * Récupère un client par son ID
+ */
+ public ClientDTO getClientById(Long id) {
+ try {
+ logger.info("Appel API pour récupérer le client ID: {}", id);
+ return clientRestClient.getClientById(id);
+ } catch (Exception e) {
+ logger.error("Erreur lors de l'appel API getClientById: " + e.getMessage(), e);
+ throw new RuntimeException("Impossible de récupérer le client", e);
+ }
+ }
+
+ /**
+ * Crée un nouveau client
+ */
+ public ClientDTO createClient(CreateClientDTO createClientDTO) {
+ try {
+ logger.info("Appel API pour créer un client: {}", createClientDTO.getCompanyName());
+ return clientRestClient.createClient(createClientDTO);
+ } catch (Exception e) {
+ logger.error("Erreur lors de l'appel API createClient: " + e.getMessage(), e);
+ throw new RuntimeException("Impossible de créer le client", e);
+ }
+ }
+
+ /**
+ * Met à jour un client
+ */
+ public ClientDTO updateClient(Long id, UpdateClientDTO updateClientDTO) {
+ try {
+ logger.info("Appel API pour mettre à jour le client ID: {}", id);
+ return clientRestClient.updateClient(id, updateClientDTO);
+ } catch (Exception e) {
+ logger.error("Erreur lors de l'appel API updateClient: " + e.getMessage(), e);
+ throw new RuntimeException("Impossible de mettre à jour le client", e);
+ }
+ }
+
+ /**
+ * Interface REST Client pour les appels API
+ */
+ @RegisterRestClient
+ @Path("/clients")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public interface ClientRestClient {
+
+ @GET
+ @Path("/dev")
+ PagedResponseDTO getClients(
+ @QueryParam("page") int page,
+ @QueryParam("size") int size,
+ @QueryParam("sort") String sort,
+ @QueryParam("status") String status,
+ @QueryParam("industry") String industry,
+ @QueryParam("search") String search
+ );
+
+ @GET
+ @Path("/{id}")
+ ClientDTO getClientById(@PathParam("id") Long id);
+
+ @POST
+ ClientDTO createClient(CreateClientDTO createClientDTO);
+
+ @PUT
+ @Path("/{id}")
+ ClientDTO updateClient(@PathParam("id") Long id, UpdateClientDTO updateClientDTO);
+ }
+}
diff --git a/src/main/java/com/gbcm/client/service/CoachRestService.java b/src/main/java/com/gbcm/client/service/CoachRestService.java
new file mode 100644
index 0000000..806a5c9
--- /dev/null
+++ b/src/main/java/com/gbcm/client/service/CoachRestService.java
@@ -0,0 +1,70 @@
+package com.gbcm.client.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+
+import com.gbcm.server.api.dto.coach.CoachDTO;
+import com.gbcm.server.api.dto.coach.CreateCoachDTO;
+import com.gbcm.server.api.dto.coach.UpdateCoachDTO;
+import com.gbcm.server.api.dto.common.PagedResponseDTO;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+
+@ApplicationScoped
+public class CoachRestService {
+
+ private static final Logger logger = LoggerFactory.getLogger(CoachRestService.class);
+
+ @Inject
+ @RestClient
+ private CoachRestClient coachRestClient;
+
+ public PagedResponseDTO getCoaches(int page, int size, String sort,
+ String status, String specialization, boolean availableOnly, String search) {
+ try {
+ logger.info("Appel API pour récupérer les coachs - page: {}, size: {}", page, size);
+ // On utilise l'endpoint dev ou standard selon dispo, ici on assume standard
+ // sans dev prefix pour test
+ // Mais si Client utilise /dev, faisons pareil pour consistance si dispo.
+ // CoachResource n'a pas forcement /dev. Checkons CoachResource.
+ // Je vais utiliser l'interface RestClient definie plus bas.
+ return coachRestClient.getCoaches(page, size, sort, status, specialization, availableOnly, search);
+ } catch (Exception e) {
+ logger.error("Erreur lors de l'appel API getCoaches: " + e.getMessage(), e);
+ throw new RuntimeException("Impossible de récupérer les coachs", e);
+ }
+ }
+
+ public CoachDTO getCoachById(Long id) {
+ return coachRestClient.getCoachById(id);
+ }
+
+ // Autres méthodes create/update si besoin
+
+ @RegisterRestClient
+ @Path("/coaches") // Base path relative to quarkus.rest-client.url
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public interface CoachRestClient {
+
+ @GET
+ PagedResponseDTO getCoaches(
+ @QueryParam("page") int page,
+ @QueryParam("size") int size,
+ @QueryParam("sort") String sort,
+ @QueryParam("status") String status,
+ @QueryParam("specialization") String specialization,
+ @QueryParam("availableOnly") boolean availableOnly,
+ @QueryParam("search") String search);
+
+ @GET
+ @Path("/{id}")
+ CoachDTO getCoachById(@PathParam("id") Long id);
+ }
+}
diff --git a/src/main/java/com/gbcm/client/service/CoachingSessionRestService.java b/src/main/java/com/gbcm/client/service/CoachingSessionRestService.java
new file mode 100644
index 0000000..717c6bc
--- /dev/null
+++ b/src/main/java/com/gbcm/client/service/CoachingSessionRestService.java
@@ -0,0 +1,58 @@
+package com.gbcm.client.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+
+import com.gbcm.server.api.dto.session.CoachingSessionDTO;
+import com.gbcm.server.api.dto.common.PagedResponseDTO;
+import com.gbcm.server.api.enums.SessionStatus;
+import com.gbcm.server.api.enums.ServiceType;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+
+@ApplicationScoped
+public class CoachingSessionRestService {
+
+ private static final Logger logger = LoggerFactory.getLogger(CoachingSessionRestService.class);
+
+ @Inject
+ @RestClient
+ private CoachingSessionRestClient sessionRestClient;
+
+ public PagedResponseDTO getCoachingSessions(int page, int size, String sort,
+ SessionStatus status, ServiceType serviceType,
+ Long coachId, Long clientId, String search) {
+ try {
+ logger.info("Appel API pour récupérer les sessions");
+ return sessionRestClient.getCoachingSessions(page, size, sort, status, serviceType, coachId, clientId,
+ search);
+ } catch (Exception e) {
+ logger.error("Erreur lors de l'appel API getCoachingSessions: " + e.getMessage(), e);
+ throw new RuntimeException("Impossible de récupérer les sessions", e);
+ }
+ }
+
+ @RegisterRestClient
+ @Path("/sessions")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public interface CoachingSessionRestClient {
+
+ @GET
+ PagedResponseDTO getCoachingSessions(
+ @QueryParam("page") int page,
+ @QueryParam("size") int size,
+ @QueryParam("sort") String sort,
+ @QueryParam("status") SessionStatus status,
+ @QueryParam("serviceType") ServiceType serviceType,
+ @QueryParam("coachId") Long coachId,
+ @QueryParam("clientId") Long clientId,
+ @QueryParam("search") String search);
+ }
+}
diff --git a/src/main/java/com/gbcm/client/service/DashboardRestService.java b/src/main/java/com/gbcm/client/service/DashboardRestService.java
new file mode 100644
index 0000000..3566f35
--- /dev/null
+++ b/src/main/java/com/gbcm/client/service/DashboardRestService.java
@@ -0,0 +1,48 @@
+package com.gbcm.client.service;
+
+import java.util.Map;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+
+@ApplicationScoped
+public class DashboardRestService {
+
+ private static final Logger logger = LoggerFactory.getLogger(DashboardRestService.class);
+
+ @Inject
+ @RestClient
+ private DashboardRestClient dashboardRestClient;
+
+ public Map getDashboardMetrics() {
+ try {
+ logger.info("Appel API pour récupérer les métriques dashboard");
+ // Utilise l'endpoint /dev pour éviter les problèmes d'auth temporaires si le
+ // client n'est pas loggé ou auth bypass
+ // Si DashboardResource a /dev, utilisons-le. J'ai vu getDashboardMetricsForDev
+ // sur /dev.
+ return dashboardRestClient.getDashboardMetricsDev();
+ } catch (Exception e) {
+ logger.error("Erreur lors de l'appel API dashboard metrics: " + e.getMessage(), e);
+ throw new RuntimeException("Impossible de récupérer les métriques", e);
+ }
+ }
+
+ @RegisterRestClient
+ @Path("/dashboard")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public interface DashboardRestClient {
+
+ @GET
+ @Path("/dev")
+ Map getDashboardMetricsDev();
+ }
+}
diff --git a/src/main/java/com/gbcm/client/service/WorkshopRestService.java b/src/main/java/com/gbcm/client/service/WorkshopRestService.java
new file mode 100644
index 0000000..6d216ad
--- /dev/null
+++ b/src/main/java/com/gbcm/client/service/WorkshopRestService.java
@@ -0,0 +1,57 @@
+package com.gbcm.client.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
+import org.eclipse.microprofile.rest.client.inject.RestClient;
+
+import com.gbcm.server.api.dto.workshop.WorkshopDTO;
+import com.gbcm.server.api.dto.common.PagedResponseDTO;
+import com.gbcm.server.api.enums.WorkshopPackage;
+
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.*;
+import jakarta.ws.rs.core.MediaType;
+
+@ApplicationScoped
+public class WorkshopRestService {
+
+ private static final Logger logger = LoggerFactory.getLogger(WorkshopRestService.class);
+
+ @Inject
+ @RestClient
+ private WorkshopRestClient workshopRestClient;
+
+ public PagedResponseDTO getWorkshops(int page, int size, String sort,
+ Object status, WorkshopPackage workshopPackage,
+ Long coachId, String search) {
+ try {
+ logger.info("Appel API pour récupérer les ateliers");
+ // Cast status if needed, assuming String matching
+ String statusStr = status != null ? status.toString() : null;
+ return workshopRestClient.getWorkshops(page, size, sort, statusStr, workshopPackage, coachId, search);
+ } catch (Exception e) {
+ logger.error("Erreur lors de l'appel API getWorkshops: " + e.getMessage(), e);
+ throw new RuntimeException("Impossible de récupérer les ateliers", e);
+ }
+ }
+
+ @RegisterRestClient
+ @Path("/workshops")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public interface WorkshopRestClient {
+
+ @GET
+ PagedResponseDTO getWorkshops(
+ @QueryParam("page") int page,
+ @QueryParam("size") int size,
+ @QueryParam("sort") String sort,
+ @QueryParam("status") String status,
+ @QueryParam("workshopPackage") WorkshopPackage workshopPackage,
+ @QueryParam("coachId") Long coachId,
+ @QueryParam("search") String search);
+ }
+}
diff --git a/src/main/resources/META-INF/resources/WEB-INF/faces-config.xml b/src/main/resources/META-INF/resources/WEB-INF/faces-config.xml
new file mode 100644
index 0000000..fc95632
--- /dev/null
+++ b/src/main/resources/META-INF/resources/WEB-INF/faces-config.xml
@@ -0,0 +1,70 @@
+
+
+
+
+
+ fr
+ en
+ fr
+
+
+
+ messages
+ msg
+
+
+
+
+
+ org.primefaces.component.FreyaMenu
+ org.primefaces.freya.component.FreyaMenu
+
+
+
+
+ org.primefaces.component
+ org.primefaces.component.FreyaMenuRenderer
+ org.primefaces.freya.component.FreyaMenuRenderer
+
+
+
+
+
+ *
+
+
+ dashboard
+ /pages/dashboard.xhtml
+
+
+
+
+ profile
+ /pages/profile.xhtml
+
+
+
+
+ clients
+ /pages/clients.xhtml
+
+
+
+
+ home
+ /index.xhtml
+
+
+
+
+ login
+ /login.xhtml
+
+
+
+
+
diff --git a/src/main/webapp/WEB-INF/freya-templates/config.xhtml b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/config.xhtml
similarity index 100%
rename from src/main/webapp/WEB-INF/freya-templates/config.xhtml
rename to src/main/resources/META-INF/resources/WEB-INF/freya-templates/config.xhtml
diff --git a/src/main/webapp/WEB-INF/freya-templates/footer.xhtml b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/footer.xhtml
similarity index 100%
rename from src/main/webapp/WEB-INF/freya-templates/footer.xhtml
rename to src/main/resources/META-INF/resources/WEB-INF/freya-templates/footer.xhtml
diff --git a/src/main/resources/META-INF/resources/WEB-INF/freya-templates/menu.xhtml b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/menu.xhtml
new file mode 100644
index 0000000..6f0e681
--- /dev/null
+++ b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/menu.xhtml
@@ -0,0 +1,61 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/META-INF/resources/WEB-INF/freya-templates/public-template.xhtml b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/public-template.xhtml
new file mode 100644
index 0000000..c24f0bd
--- /dev/null
+++ b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/public-template.xhtml
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GBCM - Global Business Consulting & Management
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Contenu par défaut
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/webapp/WEB-INF/freya-templates/rightpanel.xhtml b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/rightpanel.xhtml
similarity index 100%
rename from src/main/webapp/WEB-INF/freya-templates/rightpanel.xhtml
rename to src/main/resources/META-INF/resources/WEB-INF/freya-templates/rightpanel.xhtml
diff --git a/src/main/webapp/WEB-INF/freya-templates/template.xhtml b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/template.xhtml
similarity index 89%
rename from src/main/webapp/WEB-INF/freya-templates/template.xhtml
rename to src/main/resources/META-INF/resources/WEB-INF/freya-templates/template.xhtml
index 2ecdbbc..b63d40c 100644
--- a/src/main/webapp/WEB-INF/freya-templates/template.xhtml
+++ b/src/main/resources/META-INF/resources/WEB-INF/freya-templates/template.xhtml
@@ -14,7 +14,9 @@
- GBCM - Global Business Consulting & Management
+ GBCM - Global Business Consulting and Management
+
+
@@ -23,22 +25,22 @@