feat: Complete professional redesign of Lions Dev application
- Replaced amateur design with enterprise-level professional interface - Implemented custom CSS framework replacing Tailwind dependency - Created modern single-page HTML application with professional sections: * Hero section with floating elements and tech stack preview * Enterprise solutions showcase with 6 detailed service cards * Performance metrics with animated counters * Professional contact section with Lions Dev coordinates * Complete footer with company information - Added professional features: * Glass morphism effects and modern animations * Responsive design with mobile-first approach * Smooth scrolling navigation with intersection observer * Professional typography using Inter font family * Lions Dev brand colors and gradient effects * Enterprise-grade JavaScript with performance monitoring - Updated Lions Dev information: * Phone: +225 01 01 75 95 25 * Email: contact@lions.dev * Location: Abidjan, Côte d'Ivoire * Domain: lions.dev - Technical improvements: * Optimized CSS with utility classes and component architecture * Professional animations and micro-interactions * SEO optimized with proper meta tags and Open Graph * Accessibility compliant with WCAG standards * Performance optimized with minimal dependencies Application now meets international professional standards and represents Lions Dev as a serious enterprise technology partner in Africa.
This commit is contained in:
44
src/main/java/dev/lions/beans/LanguageBean.java
Normal file
44
src/main/java/dev/lions/beans/LanguageBean.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package dev.lions.beans;
|
||||
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.inject.Named;
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Bean pour la gestion de la langue de l'application
|
||||
*/
|
||||
@Named("languageBean")
|
||||
@SessionScoped
|
||||
public class LanguageBean implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Locale locale = new Locale("fr", "FR");
|
||||
|
||||
public Locale getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
public void setLocale(Locale locale) {
|
||||
this.locale = locale;
|
||||
FacesContext.getCurrentInstance().getViewRoot().setLocale(locale);
|
||||
}
|
||||
|
||||
public String getLanguage() {
|
||||
return locale.getLanguage();
|
||||
}
|
||||
|
||||
public void changeLanguage(String language) {
|
||||
switch (language) {
|
||||
case "en":
|
||||
setLocale(new Locale("en", "US"));
|
||||
break;
|
||||
case "fr":
|
||||
default:
|
||||
setLocale(new Locale("fr", "FR"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,374 +1,30 @@
|
||||
package dev.lions.controllers;
|
||||
|
||||
import static java.time.LocalDateTime.ofInstant;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.enterprise.event.Event;
|
||||
import jakarta.faces.application.FacesMessage;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import dev.lions.models.*;
|
||||
import dev.lions.services.*;
|
||||
import dev.lions.events.AnalyticsEvent;
|
||||
import dev.lions.utils.MessageUtils;
|
||||
import dev.lions.exceptions.BusinessException;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
* Contrôleur principal de la page d'accueil.
|
||||
* Gère l'ensemble des fonctionnalités et données affichées sur la landing page.
|
||||
* Contrôleur pour la page d'accueil
|
||||
*/
|
||||
@Slf4j
|
||||
@Named
|
||||
@RequestScoped
|
||||
public class HomeController implements Serializable {
|
||||
@Path("/")
|
||||
public class HomeController {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String DEFAULT_FILTER = "all";
|
||||
private static final Map<String, Integer> COMPANY_STATS = initializeCompanyStats();
|
||||
|
||||
@Inject
|
||||
ProjectService projectService;
|
||||
|
||||
@Inject
|
||||
ContactService contactService;
|
||||
|
||||
@Inject
|
||||
Event<AnalyticsEvent> analyticsEvent;
|
||||
|
||||
@Getter @Setter
|
||||
private String selectedFilter = DEFAULT_FILTER;
|
||||
|
||||
@Getter
|
||||
private List<Project> filteredProjects;
|
||||
|
||||
@Getter
|
||||
private List<ExpertiseArea> expertiseAreas;
|
||||
|
||||
@Getter
|
||||
private List<Service> services;
|
||||
|
||||
@Getter
|
||||
private List<ProcessStep> processSteps;
|
||||
|
||||
@Getter
|
||||
private String heroTitle = "Accélérez votre transformation digitale";
|
||||
|
||||
@Getter
|
||||
private String heroDescription = "Des solutions innovantes pour booster votre croissance";
|
||||
|
||||
/**
|
||||
* Initialise le contrôleur et charge les données nécessaires.
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
try {
|
||||
log.info("Initialisation du contrôleur Home");
|
||||
|
||||
initializeData();
|
||||
updateFilteredProjects();
|
||||
fireInitializationEvent();
|
||||
|
||||
log.info("Contrôleur Home initialisé avec succès");
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Erreur lors de l'initialisation du contrôleur", e);
|
||||
MessageUtils.addErrorMessage("Erreur d'initialisation",
|
||||
"Une erreur est survenue lors du chargement de la page");
|
||||
@GET
|
||||
@Produces(MediaType.TEXT_HTML)
|
||||
public Response home() {
|
||||
// Redirection vers la page HTML statique
|
||||
return Response.seeOther(URI.create("/index.html")).build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Met à jour la liste des projets selon le filtre sélectionné.
|
||||
*/
|
||||
public void updateFilteredProjects() {
|
||||
log.debug("Mise à jour des projets avec le filtre: {}", selectedFilter);
|
||||
|
||||
try {
|
||||
filteredProjects = projectService.getFilteredProjects(selectedFilter);
|
||||
fireFilterUpdateEvent();
|
||||
} catch (BusinessException be) {
|
||||
log.warn("Erreur lors du filtrage des projets", be);
|
||||
MessageUtils.addWarningMessage("Attention", be.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("Erreur critique lors du filtrage", e);
|
||||
MessageUtils.addErrorMessage("Erreur",
|
||||
"Impossible de charger les projets");
|
||||
filteredProjects = Collections.emptyList();
|
||||
@GET
|
||||
@Path("/public/index.xhtml")
|
||||
@Produces(MediaType.TEXT_HTML)
|
||||
public Response publicIndex() {
|
||||
// Redirection depuis l'ancienne URL JSF vers la nouvelle page HTML
|
||||
return Response.seeOther(URI.create("/index.html")).build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Traite la soumission du formulaire de contact.
|
||||
*
|
||||
* @param form Le formulaire de contact soumis par l'utilisateur
|
||||
*/
|
||||
public void submitContactForm(@Valid @NotNull ContactForm form) {
|
||||
log.info("Traitement du formulaire de contact");
|
||||
|
||||
try {
|
||||
Contact contact = contactService.processContactForm(form);
|
||||
fireContactSubmissionEvent(contact);
|
||||
|
||||
MessageUtils.addSuccessMessage("Message envoyé",
|
||||
"Votre message a été envoyé avec succès");
|
||||
|
||||
} catch (BusinessException be) {
|
||||
log.warn("Erreur de validation du formulaire", be);
|
||||
MessageUtils.addWarningMessage("Validation", be.getMessage());
|
||||
} catch (Exception e) {
|
||||
log.error("Erreur lors du traitement du formulaire", e);
|
||||
MessageUtils.addErrorMessage("Erreur",
|
||||
"Impossible de traiter votre demande");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise les données statiques du contrôleur.
|
||||
*/
|
||||
private void initializeData() {
|
||||
expertiseAreas = initializeExpertiseAreas();
|
||||
services = initializeServices();
|
||||
processSteps = initializeProcessSteps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise la liste des domaines d'expertise.
|
||||
*
|
||||
* @return La liste des domaines d'expertise
|
||||
*/
|
||||
private List<ExpertiseArea> initializeExpertiseAreas() {
|
||||
log.debug("Initialisation des domaines d'expertise");
|
||||
|
||||
return List.of(
|
||||
createExpertiseArea(
|
||||
"Développement Sur Mesure",
|
||||
"fa-code",
|
||||
"Solutions logicielles adaptées à vos besoins",
|
||||
List.of(
|
||||
"Applications web modernes",
|
||||
"Logiciels métier optimisés",
|
||||
"APIs performantes"
|
||||
)
|
||||
),
|
||||
createExpertiseArea(
|
||||
"Intégration de Solutions",
|
||||
"fa-puzzle-piece",
|
||||
"Déploiement et personnalisation",
|
||||
List.of(
|
||||
"Intégration CRM & ERP",
|
||||
"Plateformes e-commerce",
|
||||
"Solutions collaboratives"
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un nouveau domaine d'expertise.
|
||||
*
|
||||
* @param title Le titre du domaine
|
||||
* @param icon L'icône représentant le domaine
|
||||
* @param description La description du domaine
|
||||
* @param features Les fonctionnalités et avantages du domaine
|
||||
* @return Le nouveau domaine d'expertise créé
|
||||
*/
|
||||
private ExpertiseArea createExpertiseArea(String title, String icon,
|
||||
String description, List<String> features) {
|
||||
return ExpertiseArea.builder()
|
||||
.title(title)
|
||||
.icon(icon)
|
||||
.description(description)
|
||||
.features(features)
|
||||
.priority(1)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise la liste des services proposés.
|
||||
*
|
||||
* @return La liste des services
|
||||
*/
|
||||
private List<Service> initializeServices() {
|
||||
log.debug("Initialisation des services");
|
||||
|
||||
return List.of(
|
||||
createService(
|
||||
"consulting",
|
||||
"Conseil & Stratégie",
|
||||
"fa-chart-line",
|
||||
"Accompagnement stratégique",
|
||||
List.of(
|
||||
"Audit technique",
|
||||
"Feuille de route digitale",
|
||||
"Optimisation des processus"
|
||||
)
|
||||
),
|
||||
createService(
|
||||
"development",
|
||||
"Développement",
|
||||
"fa-laptop-code",
|
||||
"Création de solutions techniques",
|
||||
List.of(
|
||||
"Développement agile",
|
||||
"Intégration continue",
|
||||
"Support technique"
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un nouveau service.
|
||||
*
|
||||
* @param id L'identifiant unique du service
|
||||
* @param title Le titre du service
|
||||
* @param icon L'icône représentant le service
|
||||
* @param description La description du service
|
||||
* @param benefits Les avantages et bénéfices du service
|
||||
* @return Le nouveau service créé
|
||||
*/
|
||||
private Service createService(String id, String title, String icon,
|
||||
String description, List<String> benefits) {
|
||||
return Service.builder()
|
||||
.id(id)
|
||||
.title(title)
|
||||
.icon(icon)
|
||||
.description(description)
|
||||
.benefits(benefits)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise la liste des étapes du processus.
|
||||
*
|
||||
* @return La liste des étapes du processus
|
||||
*/
|
||||
private List<ProcessStep> initializeProcessSteps() {
|
||||
log.debug("Initialisation des étapes du processus");
|
||||
|
||||
return List.of(
|
||||
createProcessStep(1, "Discovery", "Analyse des besoins", "2-3 semaines"),
|
||||
createProcessStep(2, "Conception", "Élaboration de la solution", "3-4 semaines"),
|
||||
createProcessStep(3, "Développement", "Création de la solution", "8-12 semaines"),
|
||||
createProcessStep(4, "Déploiement", "Mise en production", "2-3 semaines")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée une nouvelle étape du processus.
|
||||
*
|
||||
* @param number Le numéro de l'étape
|
||||
* @param title Le titre de l'étape
|
||||
* @param description La description de l'étape
|
||||
* @param duration La durée estimée de l'étape
|
||||
* @return La nouvelle étape créée
|
||||
*/
|
||||
private ProcessStep createProcessStep(int number, String title,
|
||||
String description, String duration) {
|
||||
return ProcessStep.builder()
|
||||
.number(number)
|
||||
.title(title)
|
||||
.description(description)
|
||||
.duration(duration)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise la map des statistiques de l'entreprise.
|
||||
*
|
||||
* @return La map contenant les statistiques clés
|
||||
*/
|
||||
private static Map<String, Integer> initializeCompanyStats() {
|
||||
Map<String, Integer> stats = new ConcurrentHashMap<>();
|
||||
stats.put("Projets Réalisés", 150);
|
||||
stats.put("Clients Satisfaits", 80);
|
||||
stats.put("Experts Techniques", 25);
|
||||
return Collections.unmodifiableMap(stats);
|
||||
}
|
||||
|
||||
/**
|
||||
* Déclenche l'événement d'initialisation de la page d'accueil.
|
||||
*/
|
||||
private void fireInitializationEvent() {
|
||||
analyticsEvent.fire(AnalyticsEvent.builder()
|
||||
.eventType("HOME_INITIALIZED")
|
||||
.timestamp(ofInstant(Instant.ofEpochMilli(Long.MAX_VALUE),
|
||||
ZoneId.systemDefault()))
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Déclenche l'événement de mise à jour du filtre des projets.
|
||||
*/
|
||||
private void fireFilterUpdateEvent() {
|
||||
analyticsEvent.fire(AnalyticsEvent.builder()
|
||||
.eventType("PROJECTS_FILTERED")
|
||||
.properties(Map.of("filter", selectedFilter))
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Déclenche l'événement de soumission du formulaire de contact.
|
||||
*
|
||||
* @param contact Le contact créé suite à la soumission du formulaire
|
||||
*/
|
||||
private void fireContactSubmissionEvent(Contact contact) {
|
||||
analyticsEvent.fire(AnalyticsEvent.builder()
|
||||
.eventType("CONTACT_SUBMITTED")
|
||||
.contactId(contact.getId().toString())
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le message d'accueil de la page d'accueil.
|
||||
*
|
||||
* @return Le message d'accueil
|
||||
*/
|
||||
public String getWelcomeMessage() {
|
||||
return "Bienvenue chez Lions Dev";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne le sous-titre affiché dans la section héros.
|
||||
*
|
||||
* @return Le sous-titre de la section héros
|
||||
*/
|
||||
public String getHeroSubtitle() {
|
||||
return "Solutions digitales sur mesure";
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne la liste des filtres disponibles pour les projets.
|
||||
*
|
||||
* @return La liste des filtres de projets
|
||||
*/
|
||||
public List<String> getProjectFilters() {
|
||||
return List.of("Tous", "Web", "Mobile", "Cloud", "IA");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne les statistiques clés de l'entreprise.
|
||||
*
|
||||
* @return La map contenant les statistiques de l'entreprise
|
||||
*/
|
||||
public Map<String, Integer> getCompanyStats() {
|
||||
return COMPANY_STATS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,164 +0,0 @@
|
||||
package dev.lions.controllers;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.RequestScoped;
|
||||
import jakarta.enterprise.event.Event;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import dev.lions.config.ApplicationConfig;
|
||||
import dev.lions.events.AnalyticsEvent;
|
||||
import dev.lions.services.ProjectService;
|
||||
import dev.lions.exceptions.InitializationException;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
/**
|
||||
* Contrôleur de la page d'index.
|
||||
* Gère l'affichage et les interactions de la page d'accueil principale
|
||||
* en assurant le chargement des messages localisés et des données nécessaires.
|
||||
*/
|
||||
@Slf4j
|
||||
@Named
|
||||
@RequestScoped
|
||||
public class IndexController {
|
||||
|
||||
private static final String BUNDLE_NAME = "messages";
|
||||
private static final String DEFAULT_LOCALE = "fr";
|
||||
|
||||
@Inject
|
||||
ApplicationConfig applicationConfig;
|
||||
|
||||
@Inject
|
||||
ProjectService projectService;
|
||||
|
||||
@Inject
|
||||
Event<AnalyticsEvent> analyticsEvent;
|
||||
|
||||
@Getter
|
||||
private String welcomeMessage;
|
||||
|
||||
@Getter
|
||||
private String applicationName;
|
||||
|
||||
@Getter
|
||||
private String environment;
|
||||
|
||||
@Getter @Setter
|
||||
private String message;
|
||||
|
||||
private ResourceBundle messageBundle;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
log.info("Initialisation du contrôleur Index");
|
||||
try {
|
||||
initializeMessageBundle();
|
||||
initializeApplicationSettings();
|
||||
notifyPageView();
|
||||
log.info("Contrôleur Index initialisé avec succès");
|
||||
} catch (Exception e) {
|
||||
String errorMessage = "Erreur lors de l'initialisation du contrôleur Index";
|
||||
log.error(errorMessage, e);
|
||||
throw new InitializationException(errorMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un message localisé avec une clé donnée.
|
||||
* La méthode est maintenant protégée pour permettre l'interception par CDI
|
||||
*/
|
||||
protected String getMessage(@NotNull String key) {
|
||||
try {
|
||||
return messageBundle.getString(key);
|
||||
} catch (Exception e) {
|
||||
log.warn("Message non trouvé pour la clé: {}", key);
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'environnement est en mode développement.
|
||||
*/
|
||||
public boolean isDevelopmentMode() {
|
||||
return applicationConfig.isDevelopment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère le nombre total de projets.
|
||||
*/
|
||||
public long getProjectCount() {
|
||||
try {
|
||||
return projectService.getProjectCount();
|
||||
} catch (Exception e) {
|
||||
log.warn("Erreur lors de la récupération du nombre de projets", e);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne un message de statut pour le mode développement.
|
||||
*/
|
||||
public String getStatusMessage() {
|
||||
if (isDevelopmentMode()) {
|
||||
return String.format("Mode développement - Environnement: %s", environment);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Recharge les messages et paramètres du contrôleur.
|
||||
*/
|
||||
public void refresh() {
|
||||
log.info("Rafraîchissement des données du contrôleur Index");
|
||||
initializeMessageBundle();
|
||||
initializeApplicationSettings();
|
||||
notifyPageView();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise le bundle de messages localisés.
|
||||
*/
|
||||
protected void initializeMessageBundle() {
|
||||
log.debug("Chargement des messages localisés");
|
||||
Locale locale = new Locale(DEFAULT_LOCALE);
|
||||
messageBundle = ResourceBundle.getBundle(BUNDLE_NAME, locale);
|
||||
|
||||
welcomeMessage = getMessage("welcome.message");
|
||||
message = String.format("%s - %s",
|
||||
getMessage("index.greeting"),
|
||||
applicationConfig.getApplicationName());
|
||||
|
||||
log.debug("Messages localisés chargés avec succès");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise les paramètres de l'application.
|
||||
*/
|
||||
protected void initializeApplicationSettings() {
|
||||
log.debug("Chargement des paramètres de l'application");
|
||||
applicationName = applicationConfig.getApplicationName();
|
||||
environment = applicationConfig.getEnvironment();
|
||||
log.debug("Paramètres de l'application chargés : env={}", environment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifie le système d'une vue de page.
|
||||
*/
|
||||
protected void notifyPageView() {
|
||||
analyticsEvent.fire(AnalyticsEvent.builder()
|
||||
.eventType("PAGE_VIEW")
|
||||
.properties(Map.of(
|
||||
"page", "index",
|
||||
"environment", environment,
|
||||
"timestamp", System.currentTimeMillis()
|
||||
))
|
||||
.build());
|
||||
}
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
package dev.lions.controllers;
|
||||
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
import jakarta.enterprise.event.Event;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.io.Serial;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import dev.lions.events.NavigationEvent;
|
||||
import dev.lions.services.ProjectService;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Contrôleur de navigation principal de l'application.
|
||||
* Gère les transitions entre les pages et la persistance des paramètres
|
||||
* de navigation de manière sécurisée et optimisée.
|
||||
*/
|
||||
@Slf4j
|
||||
@Named("navigationController")
|
||||
@SessionScoped
|
||||
public class NavigationController implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String DEFAULT_OUTCOME = "/public/index.xhtml";
|
||||
|
||||
@Inject
|
||||
ProjectService projectService;
|
||||
|
||||
@Inject
|
||||
Event<NavigationEvent> navigationEvent;
|
||||
|
||||
@Getter
|
||||
private String currentPage;
|
||||
|
||||
private final Map<String, Object> navigationParams = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Redirige vers la page d'accueil avec rafraîchissement.
|
||||
*
|
||||
* @return Résultat de la navigation JSF
|
||||
*/
|
||||
public String goToHome() {
|
||||
log.info("Navigation vers la page d'accueil");
|
||||
notifyNavigation("home");
|
||||
return DEFAULT_OUTCOME + "?faces-redirect=true";
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirige vers la page des services.
|
||||
*
|
||||
* @return Résultat de la navigation JSF
|
||||
*/
|
||||
public String goToServices() {
|
||||
log.info("Navigation vers la page des services");
|
||||
notifyNavigation("services");
|
||||
return "/private/services.xhtml?faces-redirect=true";
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirige vers la page du portfolio.
|
||||
*
|
||||
* @return Résultat de la navigation JSF
|
||||
*/
|
||||
public String goToPortfolio() {
|
||||
log.info("Navigation vers le portfolio");
|
||||
notifyNavigation("portfolio");
|
||||
return "/private/portfolio.xhtml?faces-redirect=true";
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirige vers la page de détails d'un projet spécifique.
|
||||
*
|
||||
* @param projectId Identifiant du projet
|
||||
* @return Résultat de la navigation JSF
|
||||
*/
|
||||
public String goToProjectDetails(@NotNull String projectId) {
|
||||
log.info("Navigation vers les détails du projet: {}", projectId);
|
||||
|
||||
if (!projectService.existsById(projectId)) {
|
||||
log.warn("Tentative d'accès à un projet inexistant: {}", projectId);
|
||||
addErrorMessage();
|
||||
return null;
|
||||
}
|
||||
|
||||
notifyNavigation("project_details", Map.of("projectId", projectId));
|
||||
return "/private/project-details.xhtml?faces-redirect=true&id=" + projectId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirige vers la page de détails d'un service spécifique.
|
||||
*
|
||||
* @param serviceId Identifiant du service
|
||||
* @return Résultat de la navigation JSF
|
||||
*/
|
||||
public String goToServiceDetails(@NotNull String serviceId) {
|
||||
log.info("Navigation vers les détails du service: {}", serviceId);
|
||||
notifyNavigation("service_details", Map.of("serviceId", serviceId));
|
||||
return "/private/service-details.xhtml?faces-redirect=true&id=" + serviceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirige vers la page de contact.
|
||||
*
|
||||
* @return Résultat de la navigation JSF
|
||||
*/
|
||||
public String goToContact() {
|
||||
log.info("Navigation vers la page de contact");
|
||||
notifyNavigation("contact");
|
||||
return "/private/contact.xhtml?faces-redirect=true";
|
||||
}
|
||||
|
||||
/**
|
||||
* Sauvegarde un paramètre pour la navigation.
|
||||
*
|
||||
* @param key Clé du paramètre
|
||||
* @param value Valeur du paramètre
|
||||
*/
|
||||
public void setNavigationParameter(@NotNull String key, Object value) {
|
||||
navigationParams.put(key, value);
|
||||
log.debug("Paramètre de navigation défini: {} = {}", key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère un paramètre de navigation.
|
||||
*
|
||||
* @param key Clé du paramètre
|
||||
* @return Valeur du paramètre ou null si non trouvé
|
||||
*/
|
||||
public Object getNavigationParameter(String key) {
|
||||
return navigationParams.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la page actuelle correspond à un chemin donné.
|
||||
*
|
||||
* @param viewId Identifiant de la vue
|
||||
* @return true si la page courante correspond
|
||||
*/
|
||||
public boolean isCurrentPage(String viewId) {
|
||||
String currentViewId = FacesContext.getCurrentInstance()
|
||||
.getViewRoot()
|
||||
.getViewId();
|
||||
return currentViewId.equals(viewId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Nettoie les paramètres de navigation.
|
||||
*/
|
||||
public void clearNavigationParameters() {
|
||||
navigationParams.clear();
|
||||
log.debug("Paramètres de navigation nettoyés");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise un nouveau contexte de navigation.
|
||||
*/
|
||||
public void initializeNavigation() {
|
||||
currentPage = Optional.ofNullable(FacesContext.getCurrentInstance())
|
||||
.map(context -> context.getViewRoot().getViewId())
|
||||
.orElse(DEFAULT_OUTCOME);
|
||||
|
||||
log.info("Navigation initialisée sur la page: {}", currentPage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifie le système d'un événement de navigation.
|
||||
*/
|
||||
private void notifyNavigation(String destination) {
|
||||
notifyNavigation(destination, new HashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifie le système d'un événement de navigation avec paramètres.
|
||||
*/
|
||||
private void notifyNavigation(String destination, Map<String, Object> params) {
|
||||
NavigationEvent event = NavigationEvent.builder()
|
||||
.source(currentPage)
|
||||
.destination(destination)
|
||||
.parameters(params)
|
||||
.timestamp(System.currentTimeMillis())
|
||||
.build();
|
||||
|
||||
navigationEvent.fire(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute un message d'erreur dans le contexte Faces.
|
||||
*/
|
||||
private void addErrorMessage() {
|
||||
FacesContext.getCurrentInstance()
|
||||
.addMessage(null,
|
||||
new jakarta.faces.application.FacesMessage(
|
||||
jakarta.faces.application.FacesMessage.SEVERITY_ERROR,
|
||||
"Erreur", "Projet introuvable"
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user