fix(client): version 1.0.4, accesseurs JavaBean sur OrganisationSummaryResponse (compat JSF/EL)
This commit is contained in:
4
pom.xml
4
pom.xml
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>dev.lions.unionflow</groupId>
|
||||
<artifactId>unionflow-parent</artifactId>
|
||||
<version>1.0.3</version>
|
||||
<version>1.0.4</version>
|
||||
<relativePath>../unionflow-server-api/parent-pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
<dependency>
|
||||
<groupId>dev.lions.unionflow</groupId>
|
||||
<artifactId>unionflow-server-api</artifactId>
|
||||
<version>1.0.3</version>
|
||||
<version>1.0.4</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Lions User Manager Client - Module réutilisable de gestion d'utilisateurs Keycloak -->
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
package dev.lions.unionflow.client.api.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
@@ -7,29 +11,33 @@ import java.time.LocalDate;
|
||||
/**
|
||||
* DTO received from the backend for the member dashboard synthesis.
|
||||
*/
|
||||
public record MembreDashboardResponse(
|
||||
String prenom,
|
||||
String nom,
|
||||
LocalDate dateInscription,
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class MembreDashboardResponse implements Serializable {
|
||||
|
||||
// Cotisations
|
||||
BigDecimal mesCotisationsPaiement,
|
||||
String statutCotisations,
|
||||
Integer tauxCotisationsPerso,
|
||||
private String prenom;
|
||||
private String nom;
|
||||
private LocalDate dateInscription;
|
||||
|
||||
// Epargne
|
||||
BigDecimal monSoldeEpargne,
|
||||
BigDecimal evolutionEpargneNombre,
|
||||
String evolutionEpargne,
|
||||
Integer objectifEpargne,
|
||||
// Cotisations
|
||||
private BigDecimal mesCotisationsPaiement;
|
||||
private String statutCotisations;
|
||||
private Integer tauxCotisationsPerso;
|
||||
|
||||
// Evenements
|
||||
Integer mesEvenementsInscrits,
|
||||
Integer evenementsAVenir,
|
||||
Integer tauxParticipationPerso,
|
||||
// Epargne
|
||||
private BigDecimal monSoldeEpargne;
|
||||
private BigDecimal evolutionEpargneNombre;
|
||||
private String evolutionEpargne;
|
||||
private Integer objectifEpargne;
|
||||
|
||||
// Aides
|
||||
Integer mesDemandesAide,
|
||||
Integer aidesEnCours,
|
||||
Integer tauxAidesApprouvees) implements Serializable {
|
||||
// Evenements
|
||||
private Integer mesEvenementsInscrits;
|
||||
private Integer evenementsAVenir;
|
||||
private Integer tauxParticipationPerso;
|
||||
|
||||
// Aides
|
||||
private Integer mesDemandesAide;
|
||||
private Integer aidesEnCours;
|
||||
private Integer tauxAidesApprouvees;
|
||||
}
|
||||
|
||||
@@ -152,11 +152,11 @@ public class AdhesionsBean implements Serializable {
|
||||
items.add(new SelectItem(null, "Sélectionner une organisation"));
|
||||
if (listeAssociations != null) {
|
||||
for (OrganisationSummaryResponse assoc : listeAssociations) {
|
||||
String label = assoc.nom();
|
||||
if (assoc.typeOrganisation() != null) {
|
||||
label += " (" + assoc.typeOrganisation() + ")";
|
||||
String label = assoc.getNom();
|
||||
if (assoc.getTypeOrganisation() != null) {
|
||||
label += " (" + assoc.getTypeOrganisation() + ")";
|
||||
}
|
||||
items.add(new SelectItem(assoc.id(), label));
|
||||
items.add(new SelectItem(assoc.getId(), label));
|
||||
}
|
||||
}
|
||||
return items;
|
||||
|
||||
@@ -680,7 +680,7 @@ public class CotisationsBean implements Serializable {
|
||||
|
||||
try {
|
||||
IntentionStatutResponse statut = paiementClientService.getStatutIntention(waveIntentionId);
|
||||
this.waveStatut = statut.statut();
|
||||
this.waveStatut = statut.getStatut();
|
||||
|
||||
if ("COMPLETEE".equals(waveStatut)) {
|
||||
waveDialogOuvert = false;
|
||||
|
||||
@@ -352,8 +352,8 @@ public class CotisationsGestionBean implements Serializable {
|
||||
if (response != null && response.getData() != null) {
|
||||
for (OrganisationSummaryResponse assoc : response.getData()) {
|
||||
Organisation org = new Organisation();
|
||||
org.setId(assoc.id());
|
||||
org.setNom(assoc.nom());
|
||||
org.setId(assoc.getId());
|
||||
org.setNom(assoc.getNom());
|
||||
listeOrganisations.add(org);
|
||||
}
|
||||
}
|
||||
@@ -391,7 +391,7 @@ public class CotisationsGestionBean implements Serializable {
|
||||
|
||||
for (OrganisationSummaryResponse assoc : associations.stream().limit(5).collect(Collectors.toList())) {
|
||||
List<CotisationResponse> cotisationsOrg = cotisationsDTO.stream()
|
||||
.filter(c -> c.getOrganisationId() != null && c.getOrganisationId().equals(assoc.id()))
|
||||
.filter(c -> c.getOrganisationId() != null && c.getOrganisationId().equals(assoc.getId()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
long total = cotisationsOrg.size();
|
||||
@@ -404,7 +404,7 @@ public class CotisationsGestionBean implements Serializable {
|
||||
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
|
||||
OrganisationPerformante org = new OrganisationPerformante();
|
||||
org.setNom(assoc.nom());
|
||||
org.setNom(assoc.getNom());
|
||||
org.setTauxRecouvrement(taux);
|
||||
org.setMontantCollecte(formatMontant(montantCollecte));
|
||||
org.setNombreMembresAJour((int) payees);
|
||||
|
||||
@@ -94,22 +94,22 @@ public class DashboardMembreBean implements Serializable {
|
||||
try {
|
||||
MembreDashboardResponse data = dashboardClient.getMonDashboard();
|
||||
if (data != null) {
|
||||
this.prenomMembre = data.prenom();
|
||||
this.nomMembre = data.nom();
|
||||
this.dateInscription = data.dateInscription();
|
||||
this.mesCotisationsPaiement = formatMontant(data.mesCotisationsPaiement());
|
||||
this.statutCotisations = data.statutCotisations() != null ? data.statutCotisations() : "Non disponible";
|
||||
this.tauxCotisationsPerso = data.tauxCotisationsPerso();
|
||||
this.monSoldeEpargne = formatMontant(data.monSoldeEpargne());
|
||||
this.evolutionEpargneNombre = formatMontant(data.evolutionEpargneNombre());
|
||||
this.evolutionEpargne = data.evolutionEpargne() != null ? data.evolutionEpargne() : "+0%";
|
||||
this.objectifEpargne = data.objectifEpargne();
|
||||
this.mesEvenementsInscrits = data.mesEvenementsInscrits() != null ? data.mesEvenementsInscrits() : 0;
|
||||
this.evenementsAVenir = data.evenementsAVenir() != null ? data.evenementsAVenir() : 0;
|
||||
this.tauxParticipationPerso = data.tauxParticipationPerso();
|
||||
this.mesDemandesAide = data.mesDemandesAide() != null ? data.mesDemandesAide() : 0;
|
||||
this.aidesEnCours = data.aidesEnCours() != null ? data.aidesEnCours() : 0;
|
||||
this.tauxAidesApprouvees = data.tauxAidesApprouvees();
|
||||
this.prenomMembre = data.getPrenom();
|
||||
this.nomMembre = data.getNom();
|
||||
this.dateInscription = data.getDateInscription();
|
||||
this.mesCotisationsPaiement = formatMontant(data.getMesCotisationsPaiement());
|
||||
this.statutCotisations = data.getStatutCotisations() != null ? data.getStatutCotisations() : "Non disponible";
|
||||
this.tauxCotisationsPerso = data.getTauxCotisationsPerso();
|
||||
this.monSoldeEpargne = formatMontant(data.getMonSoldeEpargne());
|
||||
this.evolutionEpargneNombre = formatMontant(data.getEvolutionEpargneNombre());
|
||||
this.evolutionEpargne = data.getEvolutionEpargne() != null ? data.getEvolutionEpargne() : "+0%";
|
||||
this.objectifEpargne = data.getObjectifEpargne();
|
||||
this.mesEvenementsInscrits = data.getMesEvenementsInscrits() != null ? data.getMesEvenementsInscrits() : 0;
|
||||
this.evenementsAVenir = data.getEvenementsAVenir() != null ? data.getEvenementsAVenir() : 0;
|
||||
this.tauxParticipationPerso = data.getTauxParticipationPerso();
|
||||
this.mesDemandesAide = data.getMesDemandesAide() != null ? data.getMesDemandesAide() : 0;
|
||||
this.aidesEnCours = data.getAidesEnCours() != null ? data.getAidesEnCours() : 0;
|
||||
this.tauxAidesApprouvees = data.getTauxAidesApprouvees();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LOG.error("Erreur chargement KPI dashboard", e);
|
||||
|
||||
@@ -113,10 +113,10 @@ public class EntitesGestionBean implements Serializable {
|
||||
associations = response.getData();
|
||||
}
|
||||
statistiques.setTotalEntites(associations.size());
|
||||
long actives = associations.stream().filter(a -> "ACTIVE".equals(a.statut())).count();
|
||||
long actives = associations.stream().filter(a -> "ACTIVE".equals(a.getStatut())).count();
|
||||
statistiques.setEntitesActives((int) actives);
|
||||
int totalMembres = associations.stream()
|
||||
.mapToInt(a -> a.nombreMembres() != null ? a.nombreMembres() : 0)
|
||||
.mapToInt(a -> a.getNombreMembres() != null ? a.getNombreMembres() : 0)
|
||||
.sum();
|
||||
statistiques.setTotalMembres(totalMembres);
|
||||
double moyenne = associations.isEmpty() ? 0 : (double) totalMembres / associations.size();
|
||||
@@ -154,15 +154,15 @@ public class EntitesGestionBean implements Serializable {
|
||||
|
||||
private Entite convertToEntite(OrganisationSummaryResponse dto) {
|
||||
Entite entite = new Entite();
|
||||
entite.setId(dto.id());
|
||||
entite.setNom(dto.nom());
|
||||
entite.setCodeEntite(dto.nomCourt()); // Using nomCourt as code
|
||||
entite.setType(dto.typeOrganisation());
|
||||
entite.setTypeLibelle(typeCatalogueService.resolveLibelle(dto.typeOrganisation()));
|
||||
entite.setId(dto.getId());
|
||||
entite.setNom(dto.getNom());
|
||||
entite.setCodeEntite(dto.getNomCourt()); // Using nomCourt as code
|
||||
entite.setType(dto.getTypeOrganisation());
|
||||
entite.setTypeLibelle(typeCatalogueService.resolveLibelle(dto.getTypeOrganisation()));
|
||||
entite.setRegion(null); // Not available in Summary
|
||||
entite.setStatut(dto.statut());
|
||||
entite.setNombreMembres(dto.nombreMembres() != null ? dto.nombreMembres() : 0);
|
||||
entite.setMembresUtilises(dto.nombreMembres() != null ? dto.nombreMembres() : 0);
|
||||
entite.setStatut(dto.getStatut());
|
||||
entite.setNombreMembres(dto.getNombreMembres() != null ? dto.getNombreMembres() : 0);
|
||||
entite.setMembresUtilises(dto.getNombreMembres() != null ? dto.getNombreMembres() : 0);
|
||||
entite.setAdresse(null); // Not available in Summary
|
||||
entite.setTelephone(null); // Not available in Summary
|
||||
entite.setEmail(null); // Not available in Summary
|
||||
@@ -170,7 +170,7 @@ public class EntitesGestionBean implements Serializable {
|
||||
entite.setDerniereActivite(null); // Not available in Summary
|
||||
|
||||
try {
|
||||
SouscriptionStatutResponse souscription = souscriptionService.obtenirActive(dto.id());
|
||||
SouscriptionStatutResponse souscription = souscriptionService.obtenirActive(dto.getId());
|
||||
if (souscription != null) {
|
||||
entite.setForfaitSouscrit(
|
||||
souscription.getPlanCommercial() != null ? souscription.getPlanCommercial() : "Non défini");
|
||||
@@ -572,7 +572,7 @@ public class EntitesGestionBean implements Serializable {
|
||||
|
||||
for (OrganisationSummaryResponse assoc : associations) {
|
||||
try {
|
||||
SouscriptionStatutResponse souscription = souscriptionService.obtenirActive(assoc.id());
|
||||
SouscriptionStatutResponse souscription = souscriptionService.obtenirActive(assoc.getId());
|
||||
if (souscription != null) {
|
||||
totalSouscriptions++;
|
||||
if ("ACTIVE".equals(souscription.getStatut())) {
|
||||
|
||||
@@ -98,8 +98,8 @@ public class MembreExportBean implements Serializable {
|
||||
: new ArrayList<>();
|
||||
for (OrganisationSummaryResponse assoc : associations) {
|
||||
OrganisationResponse org = new OrganisationResponse();
|
||||
org.setId(assoc.id());
|
||||
org.setNom(assoc.nom());
|
||||
org.setId(assoc.getId());
|
||||
org.setNom(assoc.getNom());
|
||||
org.setVille(null /* ville not in Summary */);
|
||||
organisationsDisponibles.add(org);
|
||||
}
|
||||
|
||||
@@ -81,8 +81,8 @@ public class MembreImportBean implements Serializable {
|
||||
: new ArrayList<>();
|
||||
for (OrganisationSummaryResponse assoc : associations) {
|
||||
OrganisationResponse org = new OrganisationResponse();
|
||||
org.setId(assoc.id());
|
||||
org.setNom(assoc.nom());
|
||||
org.setId(assoc.getId());
|
||||
org.setNom(assoc.getNom());
|
||||
org.setVille(null /* ville not in Summary */);
|
||||
organisationsDisponibles.add(org);
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ public class MembreLazyDataModel extends LazyDataModelBase<MembreSummaryResponse
|
||||
|
||||
@Override
|
||||
public String getRowKey(MembreSummaryResponse object) {
|
||||
return object != null && object.id() != null ? object.id().toString() : null;
|
||||
return object != null && object.getId() != null ? object.getId().toString() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -148,8 +148,8 @@ public class MembreRechercheBean implements Serializable {
|
||||
if (response != null && response.getData() != null) {
|
||||
for (dev.lions.unionflow.server.api.dto.organisation.response.OrganisationSummaryResponse assoc : response.getData()) {
|
||||
Entite entite = new Entite();
|
||||
entite.setId(assoc.id());
|
||||
entite.setNom(assoc.nom());
|
||||
entite.setId(assoc.getId());
|
||||
entite.setNom(assoc.getNom());
|
||||
entitesDisponibles.add(entite);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,9 +70,9 @@ public class MessagingBean implements Serializable {
|
||||
|
||||
public void ouvrirConversation(ConversationResponse conversation) {
|
||||
this.conversationActive = conversation;
|
||||
chargerMessages(conversation.id());
|
||||
chargerMessages(conversation.getId());
|
||||
try {
|
||||
conversationService.marquerCommeLue(conversation.id());
|
||||
conversationService.marquerCommeLue(conversation.getId());
|
||||
} catch (Exception e) {
|
||||
LOGGER.warning("Impossible de marquer comme lue: " + e.getMessage());
|
||||
}
|
||||
@@ -94,7 +94,7 @@ public class MessagingBean implements Serializable {
|
||||
}
|
||||
try {
|
||||
SendMessageRequest request = SendMessageRequest.builder()
|
||||
.conversationId(conversationActive.id())
|
||||
.conversationId(conversationActive.getId())
|
||||
.content(contenuMessage.trim())
|
||||
.build();
|
||||
MessageResponse envoye = messageService.envoyer(request);
|
||||
@@ -135,7 +135,7 @@ public class MessagingBean implements Serializable {
|
||||
|
||||
public void archiverConversation(ConversationResponse conversation) {
|
||||
try {
|
||||
conversationService.archiver(conversation.id(), !conversation.isArchived());
|
||||
conversationService.archiver(conversation.getId(), !conversation.isArchived());
|
||||
chargerConversations();
|
||||
} catch (Exception e) {
|
||||
ajouterMessageErreur("Impossible de modifier la conversation.");
|
||||
@@ -144,7 +144,7 @@ public class MessagingBean implements Serializable {
|
||||
|
||||
public void basculerSilence(ConversationResponse conversation) {
|
||||
try {
|
||||
conversationService.basculerSilence(conversation.id());
|
||||
conversationService.basculerSilence(conversation.getId());
|
||||
chargerConversations();
|
||||
} catch (Exception e) {
|
||||
ajouterMessageErreur("Impossible de modifier le silence.");
|
||||
@@ -153,7 +153,7 @@ public class MessagingBean implements Serializable {
|
||||
|
||||
public void basculerEpinglage(ConversationResponse conversation) {
|
||||
try {
|
||||
conversationService.basculerEpinglage(conversation.id());
|
||||
conversationService.basculerEpinglage(conversation.getId());
|
||||
chargerConversations();
|
||||
} catch (Exception e) {
|
||||
ajouterMessageErreur("Impossible de modifier l'épinglage.");
|
||||
@@ -162,7 +162,7 @@ public class MessagingBean implements Serializable {
|
||||
|
||||
public void supprimerMessage(MessageResponse message) {
|
||||
try {
|
||||
messageService.supprimer(message.id());
|
||||
messageService.supprimer(message.getId());
|
||||
messagesConversationActive.remove(message);
|
||||
ajouterMessageSucces("Message supprimé.");
|
||||
} catch (Exception e) {
|
||||
@@ -173,7 +173,7 @@ public class MessagingBean implements Serializable {
|
||||
public void actualiser() {
|
||||
chargerConversations();
|
||||
if (conversationActive != null) {
|
||||
chargerMessages(conversationActive.id());
|
||||
chargerMessages(conversationActive.getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ public class OrganisationStatistiquesBean implements Serializable {
|
||||
|
||||
long total = organisations.size();
|
||||
long actives = organisations.stream()
|
||||
.filter(o -> o.statut() != null && StatutOrganisationConstants.ACTIVE.equals(o.statut()))
|
||||
.filter(o -> o.getStatut() != null && StatutOrganisationConstants.ACTIVE.equals(o.getStatut()))
|
||||
.count();
|
||||
long inactives = total - actives;
|
||||
|
||||
|
||||
@@ -159,7 +159,7 @@ public class OrganisationsBean implements Serializable {
|
||||
|
||||
totalOrganisations = toutes.size();
|
||||
organisationsActives = toutes.stream()
|
||||
.filter(o -> o.statut() != null && StatutOrganisationConstants.ACTIVE.equals(o.statut()))
|
||||
.filter(o -> o.getStatut() != null && StatutOrganisationConstants.ACTIVE.equals(o.getStatut()))
|
||||
.count();
|
||||
organisationsInactives = totalOrganisations - organisationsActives;
|
||||
|
||||
@@ -321,7 +321,7 @@ public class OrganisationsBean implements Serializable {
|
||||
public void preparerModification(OrganisationSummaryResponse org) {
|
||||
try {
|
||||
organisationSelectionnee = retryService.executeWithRetrySupplier(
|
||||
() -> organisationService.obtenirParId(org.id()),
|
||||
() -> organisationService.obtenirParId(org.getId()),
|
||||
"chargement de l'organisation pour modification");
|
||||
} catch (Exception e) {
|
||||
errorHandler.handleException(e, "lors du chargement de l'organisation", null);
|
||||
@@ -368,9 +368,9 @@ public class OrganisationsBean implements Serializable {
|
||||
*/
|
||||
public void preparerSuppression(OrganisationSummaryResponse org) {
|
||||
OrganisationResponse full = new OrganisationResponse();
|
||||
full.setId(org.id());
|
||||
full.setNom(org.nom());
|
||||
full.setStatut(org.statut());
|
||||
full.setId(org.getId());
|
||||
full.setNom(org.getNom());
|
||||
full.setStatut(org.getStatut());
|
||||
organisationPourSuppression = full;
|
||||
}
|
||||
|
||||
@@ -399,9 +399,9 @@ public class OrganisationsBean implements Serializable {
|
||||
*/
|
||||
public void preparerBasculerStatut(OrganisationSummaryResponse org) {
|
||||
OrganisationResponse full = new OrganisationResponse();
|
||||
full.setId(org.id());
|
||||
full.setNom(org.nom());
|
||||
full.setStatut(org.statut());
|
||||
full.setId(org.getId());
|
||||
full.setNom(org.getNom());
|
||||
full.setStatut(org.getStatut());
|
||||
organisationPourStatut = full;
|
||||
}
|
||||
|
||||
@@ -609,22 +609,22 @@ public class OrganisationsBean implements Serializable {
|
||||
.filter(org -> {
|
||||
if (rechercheGlobale != null && !rechercheGlobale.trim().isEmpty()) {
|
||||
String recherche = rechercheGlobale.toLowerCase();
|
||||
return (org.nom() != null && org.nom().toLowerCase().contains(recherche)) ||
|
||||
(org.nomCourt() != null && org.nomCourt().toLowerCase().contains(recherche)) ||
|
||||
(org.typeOrganisationLibelle() != null
|
||||
&& org.typeOrganisationLibelle().toLowerCase().contains(recherche));
|
||||
return (org.getNom() != null && org.getNom().toLowerCase().contains(recherche)) ||
|
||||
(org.getNomCourt() != null && org.getNomCourt().toLowerCase().contains(recherche)) ||
|
||||
(org.getTypeOrganisationLibelle() != null
|
||||
&& org.getTypeOrganisationLibelle().toLowerCase().contains(recherche));
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.filter(org -> {
|
||||
if (filtreStatut != null && !filtreStatut.trim().isEmpty()) {
|
||||
return filtreStatut.equals(org.statut());
|
||||
return filtreStatut.equals(org.getStatut());
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.filter(org -> {
|
||||
if (filtreType != null && !filtreType.trim().isEmpty()) {
|
||||
return filtreType.equals(org.typeOrganisation());
|
||||
return filtreType.equals(org.getTypeOrganisation());
|
||||
}
|
||||
return true;
|
||||
})
|
||||
|
||||
@@ -339,17 +339,17 @@ public class SuperAdminBean implements Serializable {
|
||||
: new ArrayList<>();
|
||||
topEntites = associations.stream()
|
||||
.sorted((a1, a2) -> {
|
||||
int m1 = a1.nombreMembres() != null ? a1.nombreMembres() : 0;
|
||||
int m2 = a2.nombreMembres() != null ? a2.nombreMembres() : 0;
|
||||
int m1 = a1.getNombreMembres() != null ? a1.getNombreMembres() : 0;
|
||||
int m2 = a2.getNombreMembres() != null ? a2.getNombreMembres() : 0;
|
||||
return Integer.compare(m2, m1);
|
||||
})
|
||||
.limit(5)
|
||||
.map(a -> {
|
||||
Entite entite = new Entite();
|
||||
entite.setId(a.id());
|
||||
entite.setNom(a.nom());
|
||||
entite.setTypeEntite(a.typeOrganisation());
|
||||
entite.setNombreMembres(a.nombreMembres() != null ? a.nombreMembres() : 0);
|
||||
entite.setId(a.getId());
|
||||
entite.setNom(a.getNom());
|
||||
entite.setTypeEntite(a.getTypeOrganisation());
|
||||
entite.setNombreMembres(a.getNombreMembres() != null ? a.getNombreMembres() : 0);
|
||||
return entite;
|
||||
})
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
@@ -91,8 +91,8 @@ public class UtilisateursBean implements Serializable {
|
||||
: new ArrayList<>();
|
||||
for (OrganisationSummaryResponse assoc : associations) {
|
||||
Organisation org = new Organisation();
|
||||
org.setId(assoc.id());
|
||||
org.setNom(assoc.nom());
|
||||
org.setId(assoc.getId());
|
||||
org.setNom(assoc.getNom());
|
||||
organisationsDisponibles.add(org);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
BIN
src/main/resources/META-INF/resources/images/unionflow-logo.png
Normal file
BIN
src/main/resources/META-INF/resources/images/unionflow-logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
@@ -13,7 +13,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
|
||||
<!-- Obsolète : apple-mobile-web-app-capable. Remplacé par mobile-web-app-capable -->
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<link rel="icon" href="#{request.contextPath}/resources/freya-layout/images/favicon.ico" type="image/x-icon" />
|
||||
<link rel="icon" href="#{request.contextPath}/resources/freya-layout/images/unionflow-logo.png" type="image/png" />
|
||||
</f:facet>
|
||||
|
||||
<title>UnionFlow - Plateforme de Gestion Intégrée pour Mutuelles, Associations et Clubs</title>
|
||||
@@ -23,6 +23,7 @@
|
||||
<h:outputStylesheet name="css/primeflex.min.css" library="freya-layout" />
|
||||
<h:outputStylesheet name="css/layout-#{guestPreferences.layout}.css" library="freya-layout" />
|
||||
<h:outputStylesheet name="primefaces-freya-#{guestPreferences.componentTheme}/theme.css" />
|
||||
<h:outputStylesheet name="css/topbar-elite.css" />
|
||||
<meta name="description" content="UnionFlow : La solution complète de gestion pour les mutuelles, associations, clubs (informatiques, juridiques, etc.) et organisations similaires. Gestion des membres, cotisations, événements, solidarité et analytics." />
|
||||
</h:head>
|
||||
|
||||
@@ -31,8 +32,13 @@
|
||||
<!-- Landing Topbar -->
|
||||
<div class="landing-topbar">
|
||||
<div class="landing-topbar-left">
|
||||
<h:link id="logolink" outcome="/pages/secure/dashboard" styleClass="logo">
|
||||
<p:graphicImage name="images/logo-freya.svg" library="freya-layout" />
|
||||
<h:link id="logolink" outcome="/pages/secure/dashboard" styleClass="logo unionflow-brand unionflow-brand--landing">
|
||||
<h:graphicImage value="#{request.contextPath}/resources/freya-layout/images/unionflow-logo.png"
|
||||
alt="Logo UnionFlow"
|
||||
styleClass="unionflow-brand-icon" />
|
||||
<span class="unionflow-brand-text">
|
||||
<span class="unionflow-brand-name">UNIONFLOW</span>
|
||||
</span>
|
||||
</h:link>
|
||||
|
||||
<ul class="landing-menu">
|
||||
@@ -75,8 +81,8 @@
|
||||
<div id="home" class="landing-banner">
|
||||
<div class="landing-banner-content">
|
||||
<span class="title">UnionFlow</span>
|
||||
<h3>Plateforme de Gestion Intégrée pour Mutuelles, Associations et Clubs<br/>
|
||||
Simplifiez la gestion de votre organisation avec une solution complète et moderne</h3>
|
||||
<h3>Fédérez vos membres. Sécurisez vos flux. Pilotez l'avenir.<br/>
|
||||
Oubliez la gestion manuelle. La plateforme technologique financière qui apporte transparence et rigueur à votre organisation.</h3>
|
||||
<a href="#{request.contextPath}/pages/secure/dashboard.xhtml"
|
||||
style="display:inline-flex;align-items:center;gap:.6rem;
|
||||
padding:1rem 2.5rem;border-radius:8px;
|
||||
@@ -103,8 +109,8 @@
|
||||
<div class="feature-card">
|
||||
<span>1</span>
|
||||
<div class="card-content">
|
||||
<h3>Gestion des Membres</h3>
|
||||
<h5>Inscription, profils détaillés, gestion des statuts, historique des adhésions et suivi complet de chaque membre.</h5>
|
||||
<h3>Maîtrisez votre Base Membres</h3>
|
||||
<h5>Finies les listes papier perdues. Centralisez les profils, gérez les statuts et gardez le contact avec votre communauté.</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -118,8 +124,8 @@
|
||||
<div class="feature-card">
|
||||
<span>2</span>
|
||||
<div class="card-content">
|
||||
<h3>Gestion des Cotisations</h3>
|
||||
<h5>Types variés (mensuelle, annuelle, adhésion, événement, formation, projet, solidarité), suivi des paiements et rappels automatiques. <strong>Paiements sécurisés via Wave</strong> (bientôt disponible).</h5>
|
||||
<h3>Sécurisez vos Collectes</h3>
|
||||
<h5>Automatisez vos appels à cotisation, suivez vos tontines en temps réel et intégrez <strong>les paiements par mobile money (ex: Wave)</strong>.</h5>
|
||||
<div style="margin-top: 10px;">
|
||||
<!-- Image locale du client (servie depuis META-INF/resources/images) -->
|
||||
<h:graphicImage value="#{request.contextPath}/images/logo-wave.png" style="max-height: 30px; width: auto;" alt="Wave - Paiements mobiles" />
|
||||
@@ -134,8 +140,8 @@
|
||||
<div class="feature-card">
|
||||
<span>3</span>
|
||||
<div class="card-content">
|
||||
<h3>Organisation<br/>d'Événements</h3>
|
||||
<h5>Assemblées générales, réunions, formations, conférences, ateliers, séminaires, événements sociaux avec gestion des inscriptions.</h5>
|
||||
<h3>Faites vivre<br/>vos Réunions et AG</h3>
|
||||
<h5>Gérez l'organisation des assemblées générales, traquez les présences lors des réunions statutaires et boostez l'engagement.</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -150,8 +156,8 @@
|
||||
<div class="feature-card">
|
||||
<span>4</span>
|
||||
<div class="card-content">
|
||||
<h3>Système de Solidarité</h3>
|
||||
<h5>Gestion complète des demandes d'aide, propositions, évaluations, suivi des statuts et coordination des actions solidaires.</h5>
|
||||
<h3>L'entraide Transparente</h3>
|
||||
<h5>Sécurisez la gestion de vos cas sociaux (décès, maladie). Approuvez et décaissez les aides avec une traçabilité totale.</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -162,8 +168,8 @@
|
||||
<div class="feature-card">
|
||||
<span>5</span>
|
||||
<div class="card-content">
|
||||
<h3>Gestion des Organisations</h3>
|
||||
<h5>Gestion des clubs et unions avec hiérarchie organisationnelle, statistiques détaillées, rapports et vue d'ensemble complète.</h5>
|
||||
<h3>Scalabilité Absolue</h3>
|
||||
<h5>Conçu pour évoluer : d'une amicale de quartier à un district international du Lions ou Rotary Club avec des milliers de membres.</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -176,8 +182,8 @@
|
||||
<div class="feature-card">
|
||||
<span>6</span>
|
||||
<div class="card-content">
|
||||
<h3>Analytics & Rapports</h3>
|
||||
<h5>Tableaux de bord interactifs, KPIs en temps réel, analyses approfondies et rapports personnalisables pour une prise de décision éclairée.</h5>
|
||||
<h3>Reporting et Audit</h3>
|
||||
<h5>Générez des états financiers en un clic pour vos comptabilités et instaurez une gouvernance irréprochable.</h5>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -188,9 +194,9 @@
|
||||
<!-- Benefits Section -->
|
||||
<div id="benefits" class="landing-pricing">
|
||||
<div class="section-header">
|
||||
<span class="title">Pourquoi choisir UnionFlow ?</span>
|
||||
<h3>Une plateforme robuste et moderne bâtie pour les organisations du monde entier —<br/>
|
||||
avec une sensibilité particulière pour les réalités africaines.</h3>
|
||||
<span class="title">La technologie au service de la gouvernance</span>
|
||||
<h3>Toute la rigueur exigée par les institutions, accessible depuis votre mobile —<br/>
|
||||
conçu avec une fine compréhension des réalités associatives africaines et mondiales.</h3>
|
||||
</div>
|
||||
|
||||
<!-- Grille des avantages -->
|
||||
@@ -214,15 +220,15 @@
|
||||
<ul style="list-style:none;padding:0;margin:0;">
|
||||
<li style="display:flex;align-items:center;gap:.5rem;color:var(--text-color-secondary);margin-bottom:.4rem;font-size:.85rem;">
|
||||
<i class="pi pi-check" style="color:var(--green-500);"></i>
|
||||
OpenID Connect via Keycloak
|
||||
Infrastructure hautement sécurisée
|
||||
</li>
|
||||
<li style="display:flex;align-items:center;gap:.5rem;color:var(--text-color-secondary);margin-bottom:.4rem;font-size:.85rem;">
|
||||
<i class="pi pi-check" style="color:var(--green-500);"></i>
|
||||
Contrôle d'accès granulaire par rôle
|
||||
Chaque action est loggée et traçable
|
||||
</li>
|
||||
<li style="display:flex;align-items:center;gap:.5rem;color:var(--text-color-secondary);font-size:.85rem;">
|
||||
<i class="pi pi-check" style="color:var(--green-500);"></i>
|
||||
Chiffrement de bout en bout
|
||||
Droits de validation croisée stricts
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -269,16 +275,16 @@
|
||||
<i class="pi pi-server" style="color:var(--purple-600);font-size:1.25rem;"></i>
|
||||
</div>
|
||||
<h3 style="color:var(--text-color);font-size:1.1rem;font-weight:700;margin:0 0 .75rem 0;">
|
||||
Architecture cloud-native
|
||||
Architecture ultra-rapide
|
||||
</h3>
|
||||
<p style="color:var(--text-color-secondary);line-height:1.7;margin:0 0 1.25rem 0;font-size:.9rem;">
|
||||
Bâtie sur Quarkus et une architecture microservices, la plateforme monte en
|
||||
charge automatiquement et garantit une haute disponibilité.
|
||||
Bâtie sur des technologies cloud de dernière génération, la plateforme reste
|
||||
fluide et instantanée même avec des milliers de transactions.
|
||||
</p>
|
||||
<ul style="list-style:none;padding:0;margin:0;">
|
||||
<li style="display:flex;align-items:center;gap:.5rem;color:var(--text-color-secondary);margin-bottom:.4rem;font-size:.85rem;">
|
||||
<i class="pi pi-check" style="color:var(--green-500);"></i>
|
||||
Microservices Quarkus haute performance
|
||||
Temps de réponse quasi-instantané
|
||||
</li>
|
||||
<li style="display:flex;align-items:center;gap:.5rem;color:var(--text-color-secondary);margin-bottom:.4rem;font-size:.85rem;">
|
||||
<i class="pi pi-check" style="color:var(--green-500);"></i>
|
||||
|
||||
@@ -15,9 +15,9 @@
|
||||
<div class="card">
|
||||
<div class="flex align-items-center justify-content-between">
|
||||
<div class="flex align-items-center">
|
||||
<div class="bg-blue-100 border-circle flex align-items-center justify-content-center mr-3"
|
||||
<div class="uf-bg-navy-light border-circle flex align-items-center justify-content-center mr-3"
|
||||
style="width:60px;height:60px;">
|
||||
<i class="pi pi-user text-blue-600 text-3xl"></i>
|
||||
<i class="pi pi-user uf-text-navy text-3xl"></i>
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="m-0 text-900">Bienvenue, #{dashboardMembreBean.prenomMembre}</h4>
|
||||
@@ -42,7 +42,7 @@
|
||||
<ui:param name="title" value="Mes Cotisations" />
|
||||
<ui:param name="value" value="#{dashboardMembreBean.statutCotisations}" />
|
||||
<ui:param name="icon" value="pi-wallet" />
|
||||
<ui:param name="iconColor" value="green-600" />
|
||||
<ui:param name="iconColor" value="uf-text-forest" />
|
||||
<ui:param name="growthValue" value="#{dashboardMembreBean.mesCotisationsPaiement}" />
|
||||
<ui:param name="growthLabel" value="FCFA payés ce mois" />
|
||||
<ui:param name="growthType" value="number" />
|
||||
@@ -55,7 +55,7 @@
|
||||
<ui:param name="title" value="Mon Épargne" />
|
||||
<ui:param name="value" value="#{dashboardMembreBean.monSoldeEpargne} FCFA" />
|
||||
<ui:param name="icon" value="pi-money-bill" />
|
||||
<ui:param name="iconColor" value="blue-600" />
|
||||
<ui:param name="iconColor" value="uf-text-navy" />
|
||||
<ui:param name="growthValue" value="#{dashboardMembreBean.evolutionEpargneNombre}" />
|
||||
<ui:param name="growthLabel" value="FCFA ce mois" />
|
||||
<ui:param name="growthType" value="number" />
|
||||
@@ -68,7 +68,7 @@
|
||||
<ui:param name="title" value="Mes Événements" />
|
||||
<ui:param name="value" value="#{dashboardMembreBean.mesEvenementsInscrits}" />
|
||||
<ui:param name="icon" value="pi-calendar" />
|
||||
<ui:param name="iconColor" value="purple-600" />
|
||||
<ui:param name="iconColor" value="uf-text-gold" />
|
||||
<ui:param name="growthValue" value="#{dashboardMembreBean.evenementsAVenir}" />
|
||||
<ui:param name="growthLabel" value="à venir" />
|
||||
<ui:param name="growthType" value="number" />
|
||||
@@ -81,7 +81,7 @@
|
||||
<ui:param name="title" value="Mes Aides" />
|
||||
<ui:param name="value" value="#{dashboardMembreBean.mesDemandesAide}" />
|
||||
<ui:param name="icon" value="pi-heart" />
|
||||
<ui:param name="iconColor" value="orange-600" />
|
||||
<ui:param name="iconColor" value="uf-text-crimson" />
|
||||
<ui:param name="growthValue" value="#{dashboardMembreBean.aidesEnCours}" />
|
||||
<ui:param name="growthLabel" value="en traitement" />
|
||||
<ui:param name="growthType" value="number" />
|
||||
@@ -149,7 +149,7 @@
|
||||
<span>#{cotisAtt.periode}</span>
|
||||
</p:column>
|
||||
<p:column headerText="Montant dû">
|
||||
<span class="font-medium text-orange-600">#{cotisAtt.montantFormatte} FCFA</span>
|
||||
<span class="font-medium uf-text-gold">#{cotisAtt.montantFormatte} FCFA</span>
|
||||
</p:column>
|
||||
<p:column headerText="Échéance" style="width:110px">
|
||||
<h:outputText value="#{cotisAtt.dateEcheance}">
|
||||
@@ -228,25 +228,25 @@
|
||||
<div class="card">
|
||||
<h5>Statut de mes cotisations</h5>
|
||||
<div class="flex flex-column gap-3">
|
||||
<div class="flex align-items-center justify-content-between p-3 border-round surface-50">
|
||||
<div class="flex align-items-center">
|
||||
<i class="pi pi-check-circle text-green-500 text-xl mr-3"></i>
|
||||
<span class="text-900 font-medium">Total historique</span>
|
||||
<div class="flex align-items-center justify-content-between p-3 border-round surface-50 border-1 uf-border-forest mb-2">
|
||||
<div class="flex align-items-center">
|
||||
<i class="pi pi-check-circle uf-text-forest text-xl mr-3"></i>
|
||||
<span class="text-900 font-medium">Total historique</span>
|
||||
</div>
|
||||
<p:badge value="#{dashboardMembreBean.mesCotisations.size()}" severity="success"/>
|
||||
</div>
|
||||
<p:badge value="#{dashboardMembreBean.mesCotisations.size()}" severity="success"/>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-between p-3 border-round surface-50">
|
||||
<div class="flex align-items-center">
|
||||
<i class="pi pi-clock text-orange-500 text-xl mr-3"></i>
|
||||
<span class="text-900 font-medium">En attente</span>
|
||||
</div>
|
||||
<p:badge value="#{dashboardMembreBean.mesCotisationsEnAttente.size()}" severity="warning"/>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-between p-3 border-round surface-50">
|
||||
<div class="flex align-items-center">
|
||||
<i class="pi pi-chart-line text-blue-500 text-xl mr-3"></i>
|
||||
<span class="text-900 font-medium">Taux de paiement</span>
|
||||
<div class="flex align-items-center justify-content-between p-3 border-round surface-50 border-1 uf-border-gold mb-2">
|
||||
<div class="flex align-items-center">
|
||||
<i class="pi pi-clock uf-text-gold text-xl mr-3"></i>
|
||||
<span class="text-900 font-medium">En attente</span>
|
||||
</div>
|
||||
<p:badge value="#{dashboardMembreBean.mesCotisationsEnAttente.size()}" severity="warning"/>
|
||||
</div>
|
||||
<div class="flex align-items-center justify-content-between p-3 border-round surface-50 border-1 uf-border-navy">
|
||||
<div class="flex align-items-center">
|
||||
<i class="pi pi-chart-line uf-text-navy text-xl mr-3"></i>
|
||||
<span class="text-900 font-medium">Taux de paiement</span>
|
||||
</div>
|
||||
<span class="text-900 font-bold">
|
||||
<h:outputText value="#{dashboardMembreBean.tauxCotisationsPerso}" rendered="#{dashboardMembreBean.tauxCotisationsPerso != null}" />
|
||||
<h:outputText value="%" rendered="#{dashboardMembreBean.tauxCotisationsPerso != null}" />
|
||||
|
||||
@@ -56,21 +56,21 @@
|
||||
<div class="col-12">
|
||||
<div class="card surface-50 border-round">
|
||||
<h5 class="text-900 font-bold mb-3">
|
||||
<i class="pi pi-exclamation-circle text-orange-500 mr-2"></i>
|
||||
<i class="pi pi-exclamation-circle uf-text-gold mr-2"></i>
|
||||
Actions requises aujourd'hui
|
||||
</h5>
|
||||
<div class="grid">
|
||||
<!-- URGENT : Cotisations en retard -->
|
||||
<div class="col-12 md:col-6 lg:col-3">
|
||||
<div class="surface-card border-round p-3 border-left-3 border-red-500 hover-elevate-2">
|
||||
<div class="uf-alert-card p-3 uf-border-left-crimson" style="border-left-width: 4px; border-left-style: solid;">
|
||||
<div class="flex align-items-center">
|
||||
<div class="bg-red-100 border-round flex align-items-center justify-content-center mr-3"
|
||||
<div class="uf-bg-crimson-light border-round flex align-items-center justify-content-center mr-3"
|
||||
style="width: 2.5rem; height: 2.5rem;">
|
||||
<i class="pi pi-exclamation-triangle text-red-600"></i>
|
||||
<i class="pi pi-exclamation-triangle uf-text-crimson"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="text-red-900 font-bold text-2xl">#{dashboardBean.cotisationsRetard}</div>
|
||||
<div class="text-red-700 text-sm font-medium">Cotisations en retard</div>
|
||||
<div class="uf-text-crimson font-bold text-2xl">#{dashboardBean.cotisationsRetard}</div>
|
||||
<div class="text-700 text-sm font-medium">Cotisations en retard</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -78,15 +78,15 @@
|
||||
|
||||
<!-- IMPORTANT : Adhésions à renouveler -->
|
||||
<div class="col-12 md:col-6 lg:col-3">
|
||||
<div class="surface-card border-round p-3 border-left-3 border-orange-500 hover-elevate-2">
|
||||
<div class="uf-alert-card p-3 uf-border-left-gold" style="border-left-width: 4px; border-left-style: solid;">
|
||||
<div class="flex align-items-center">
|
||||
<div class="bg-orange-100 border-round flex align-items-center justify-content-center mr-3"
|
||||
<div class="uf-bg-gold-light border-round flex align-items-center justify-content-center mr-3"
|
||||
style="width: 2.5rem; height: 2.5rem;">
|
||||
<i class="pi pi-clock text-orange-600"></i>
|
||||
<i class="pi pi-clock uf-text-gold"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="text-orange-900 font-bold text-2xl">#{dashboardBean.adhesionsExpiration}</div>
|
||||
<div class="text-orange-700 text-sm font-medium">Expire dans 7 jours</div>
|
||||
<div class="text-900 font-bold text-2xl">#{dashboardBean.adhesionsExpiration}</div>
|
||||
<div class="text-700 text-sm font-medium">Expire dans 7 jours</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -94,15 +94,15 @@
|
||||
|
||||
<!-- À TRAITER : Demandes en attente -->
|
||||
<div class="col-12 md:col-6 lg:col-3">
|
||||
<div class="surface-card border-round p-3 border-left-3 border-blue-500 hover-elevate-2">
|
||||
<div class="uf-alert-card p-3 uf-border-left-navy" style="border-left-width: 4px; border-left-style: solid;">
|
||||
<div class="flex align-items-center">
|
||||
<div class="bg-blue-100 border-round flex align-items-center justify-content-center mr-3"
|
||||
<div class="uf-bg-navy-light border-round flex align-items-center justify-content-center mr-3"
|
||||
style="width: 2.5rem; height: 2.5rem;">
|
||||
<i class="pi pi-inbox text-blue-600"></i>
|
||||
<i class="pi pi-inbox uf-text-navy"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="text-blue-900 font-bold text-2xl">#{dashboardBean.demandesToTraiter}</div>
|
||||
<div class="text-blue-700 text-sm font-medium">Demandes en attente</div>
|
||||
<div class="uf-text-navy font-bold text-2xl">#{dashboardBean.demandesToTraiter}</div>
|
||||
<div class="text-700 text-sm font-medium">Demandes en attente</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -110,15 +110,15 @@
|
||||
|
||||
<!-- SUCCÈS : Tâches complétées -->
|
||||
<div class="col-12 md:col-6 lg:col-3">
|
||||
<div class="surface-card border-round p-3 border-left-3 border-green-500 hover-elevate-2">
|
||||
<div class="uf-alert-card p-3 uf-border-left-forest" style="border-left-width: 4px; border-left-style: solid;">
|
||||
<div class="flex align-items-center">
|
||||
<div class="bg-green-100 border-round flex align-items-center justify-content-center mr-3"
|
||||
<div class="uf-bg-forest-light border-round flex align-items-center justify-content-center mr-3"
|
||||
style="width: 2.5rem; height: 2.5rem;">
|
||||
<i class="pi pi-check-circle text-green-600"></i>
|
||||
<i class="pi pi-check-circle uf-text-forest"></i>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="text-green-900 font-bold text-2xl">#{dashboardBean.tachesCompletees}</div>
|
||||
<div class="text-green-700 text-sm font-medium">Complétées aujourd'hui</div>
|
||||
<div class="uf-text-forest font-bold text-2xl">#{dashboardBean.tachesCompletees}</div>
|
||||
<div class="text-700 text-sm font-medium">Complétées aujourd'hui</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -131,7 +131,7 @@
|
||||
<!-- KPIs principaux - Ordre psychologique optimal -->
|
||||
<div class="col-12">
|
||||
<h5 class="text-900 font-bold mb-3">
|
||||
<i class="pi pi-chart-bar text-primary mr-2"></i>
|
||||
<i class="pi pi-chart-bar uf-text-forest mr-2"></i>
|
||||
Vue d'ensemble
|
||||
</h5>
|
||||
</div>
|
||||
@@ -143,7 +143,7 @@
|
||||
<ui:param name="title" value="Membres Actifs" />
|
||||
<ui:param name="value" value="#{dashboardBean.activeMembers}" />
|
||||
<ui:param name="icon" value="pi-users" />
|
||||
<ui:param name="iconColor" value="blue-600" />
|
||||
<ui:param name="iconColor" value="uf-text-navy" />
|
||||
<ui:param name="growthValue" value="#{dashboardBean.membresEvolutionPourcent}" />
|
||||
<ui:param name="growthLabel" value="ce mois" />
|
||||
<ui:param name="progressValue" value="#{dashboardBean.tauxActivite}" />
|
||||
@@ -157,7 +157,7 @@
|
||||
<ui:param name="title" value="FCFA Collectés" />
|
||||
<ui:param name="value" value="#{dashboardBean.totalCotisations}" />
|
||||
<ui:param name="icon" value="pi-dollar" />
|
||||
<ui:param name="iconColor" value="green-600" />
|
||||
<ui:param name="iconColor" value="uf-text-forest" />
|
||||
<ui:param name="growthValue" value="#{dashboardBean.cotisationsEvolutionPourcent}" />
|
||||
<ui:param name="growthLabel" value="vs mois dernier" />
|
||||
<ui:param name="progressValue" value="#{dashboardBean.tauxObjectifCotisations}" />
|
||||
@@ -171,7 +171,7 @@
|
||||
<ui:param name="title" value="FCFA Distribués" />
|
||||
<ui:param name="value" value="#{dashboardBean.aidesDistribuees}" />
|
||||
<ui:param name="icon" value="pi-heart" />
|
||||
<ui:param name="iconColor" value="purple-600" />
|
||||
<ui:param name="iconColor" value="uf-text-gold" />
|
||||
<ui:param name="statusIcon" value="pi-circle-fill" />
|
||||
<ui:param name="statusLabel" value="Demandes en attente" />
|
||||
<ui:param name="statusValue" value="#{dashboardBean.pendingAides}" />
|
||||
@@ -185,8 +185,8 @@
|
||||
<ui:include src="/templates/components/cards/kpi-card.xhtml">
|
||||
<ui:param name="title" value="Taux de Participation" />
|
||||
<ui:param name="value" value="#{dashboardBean.tauxParticipation}%" />
|
||||
<ui:param name="icon" value="pi-chart-line" />
|
||||
<ui:param name="iconColor" value="orange-600" />
|
||||
<ui:param name="icon" value="pi-calendar" />
|
||||
<ui:param name="iconColor" value="uf-text-navy" />
|
||||
<ui:param name="statusIcon" value="pi-calendar" />
|
||||
<ui:param name="statusLabel" value="Événements prévus" />
|
||||
<ui:param name="statusValue" value="#{dashboardBean.upcomingEvents}" />
|
||||
@@ -469,8 +469,8 @@
|
||||
<div class="flex flex-column gap-3">
|
||||
<!-- Valider adhésions : SECRETAIRE, ADMIN -->
|
||||
<ui:fragment rendered="#{menuBean.isSecretaire() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
|
||||
<div class="flex align-items-center p-3 border-round bg-blue-50 border-blue-200">
|
||||
<i class="pi pi-check-circle text-blue-500 text-xl mr-3"></i>
|
||||
<div class="flex align-items-center p-3 border-round uf-bg-navy-light border-1 uf-border-navy">
|
||||
<i class="pi pi-check-circle uf-text-navy text-xl mr-3"></i>
|
||||
<div class="flex-1">
|
||||
<div class="text-900 font-medium">Valider #{dashboardBean.adhesionsPendantes} adhésions</div>
|
||||
<small class="text-600">Demandes en attente de validation</small>
|
||||
@@ -485,8 +485,8 @@
|
||||
|
||||
<!-- Relancer cotisations : TRESORIER, SECRETAIRE, ADMIN -->
|
||||
<ui:fragment rendered="#{menuBean.isTresorier() or menuBean.isSecretaire() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
|
||||
<div class="flex align-items-center p-3 border-round bg-orange-50 border-orange-200">
|
||||
<i class="pi pi-exclamation-triangle text-orange-500 text-xl mr-3"></i>
|
||||
<div class="flex align-items-center p-3 border-round uf-bg-gold-light border-1 uf-border-gold">
|
||||
<i class="pi pi-exclamation-triangle uf-text-gold text-xl mr-3"></i>
|
||||
<div class="flex-1">
|
||||
<div class="text-900 font-medium">Relancer #{dashboardBean.cotisationsRetard} cotisations</div>
|
||||
<small class="text-600">Paiements en retard</small>
|
||||
@@ -501,8 +501,8 @@
|
||||
|
||||
<!-- Traiter aides : RESPONSABLE_SOCIAL, ADMIN -->
|
||||
<ui:fragment rendered="#{menuBean.isResponsableSocial() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
|
||||
<div class="flex align-items-center p-3 border-round bg-green-50 border-green-200">
|
||||
<i class="pi pi-heart text-green-500 text-xl mr-3"></i>
|
||||
<div class="flex align-items-center p-3 border-round uf-bg-forest-light border-1 uf-border-forest">
|
||||
<i class="pi pi-heart uf-text-forest text-xl mr-3"></i>
|
||||
<div class="flex-1">
|
||||
<div class="text-900 font-medium">Traiter #{dashboardBean.aidesEnAttente} aides</div>
|
||||
<small class="text-600">Demandes d'aide à examiner</small>
|
||||
@@ -561,20 +561,20 @@
|
||||
|
||||
<h:panelGroup id="financialSummary" layout="block" styleClass="grid">
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 border-round bg-green-50">
|
||||
<div class="text-green-600 font-medium text-xl">#{dashboardBean.recettesMois} FCFA</div>
|
||||
<div class="text-center p-3 border-round uf-bg-forest-light">
|
||||
<div class="uf-text-forest font-medium text-xl">#{dashboardBean.recettesMois} FCFA</div>
|
||||
<div class="text-500">Recettes totales</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 border-round bg-red-50">
|
||||
<div class="text-red-600 font-medium text-xl">#{dashboardBean.depensesMois} FCFA</div>
|
||||
<div class="text-center p-3 border-round uf-bg-crimson-light">
|
||||
<div class="uf-text-crimson font-medium text-xl">#{dashboardBean.depensesMois} FCFA</div>
|
||||
<div class="text-500">Dépenses totales</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 border-round bg-blue-50">
|
||||
<div class="text-blue-600 font-medium text-xl">#{dashboardBean.soldeMois} FCFA</div>
|
||||
<div class="text-center p-3 border-round uf-bg-navy-light">
|
||||
<div class="uf-text-navy font-medium text-xl">#{dashboardBean.soldeMois} FCFA</div>
|
||||
<div class="text-500">Solde net</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<ui:param name="title" value="Membres Actifs" />
|
||||
<ui:param name="value" value="#{superAdminBean.totalMembres}" />
|
||||
<ui:param name="icon" value="pi-users" />
|
||||
<ui:param name="iconColor" value="blue-600" />
|
||||
<ui:param name="iconColor" value="uf-text-navy" />
|
||||
<ui:param name="growthValue" value="#{superAdminBean.croissanceMembres}" />
|
||||
<ui:param name="growthLabel" value="ce mois" />
|
||||
<ui:param name="progressValue" value="#{superAdminBean.pourcentageMembres}" />
|
||||
@@ -63,7 +63,7 @@
|
||||
<ui:param name="title" value="Organisations" />
|
||||
<ui:param name="value" value="#{superAdminBean.totalEntites}" />
|
||||
<ui:param name="icon" value="pi-sitemap" />
|
||||
<ui:param name="iconColor" value="green-600" />
|
||||
<ui:param name="iconColor" value="uf-text-forest" />
|
||||
<ui:param name="growthValue" value="#{superAdminBean.nouvellesEntites}" />
|
||||
<ui:param name="growthLabel" value="nouvelles" />
|
||||
<ui:param name="growthType" value="number" />
|
||||
@@ -75,7 +75,7 @@
|
||||
<ui:param name="title" value="Revenus (FCFA)" />
|
||||
<ui:param name="value" value="#{superAdminBean.revenusGlobaux}" />
|
||||
<ui:param name="icon" value="pi-dollar" />
|
||||
<ui:param name="iconColor" value="purple-600" />
|
||||
<ui:param name="iconColor" value="uf-text-gold" />
|
||||
<ui:param name="growthValue" value="#{superAdminBean.croissanceRevenus}" />
|
||||
<ui:param name="growthLabel" value="vs mois dernier" />
|
||||
<ui:param name="progressValue" value="#{superAdminBean.pourcentageRevenus}" />
|
||||
@@ -85,7 +85,7 @@
|
||||
<ui:param name="title" value="Activité du Jour" />
|
||||
<ui:param name="value" value="#{superAdminBean.activiteJournaliere}" />
|
||||
<ui:param name="icon" value="pi-chart-line" />
|
||||
<ui:param name="iconColor" value="orange-600" />
|
||||
<ui:param name="iconColor" value="uf-text-navy" />
|
||||
<ui:param name="statusIcon" value="pi-check-circle" />
|
||||
<ui:param name="statusLabel" value="En ligne" />
|
||||
<ui:param name="statusValue" value="#{superAdminBean.utilisateursActifs} actifs" />
|
||||
@@ -165,16 +165,16 @@
|
||||
<div class="card">
|
||||
<div class="flex align-items-center justify-content-between mb-3">
|
||||
<h5 class="m-0">
|
||||
<i class="pi pi-exclamation-triangle text-orange-500 mr-2"></i>
|
||||
<i class="pi pi-exclamation-triangle uf-text-crimson mr-2"></i>
|
||||
Alertes Système
|
||||
</h5>
|
||||
<p:tag value="#{superAdminBean.alertesCount} alertes" severity="warning" styleClass="text-xs" />
|
||||
</div>
|
||||
|
||||
<ui:repeat value="#{superAdminBean.alertesRecentes}" var="alerte" varStatus="status">
|
||||
<div class="flex align-items-center p-3 mb-2 border-round border-left-3 border-orange-400"
|
||||
style="background: var(--surface-50);">
|
||||
<i class="pi #{alerte.icone} text-orange-500 text-xl mr-3"></i>
|
||||
<div class="uf-alert-card flex align-items-center p-3 mb-2 border-round uf-border-left-crimson"
|
||||
style="background: var(--surface-50); border-left-width: 4px; border-left-style: solid;">
|
||||
<i class="pi #{alerte.icone} uf-text-crimson text-xl mr-3"></i>
|
||||
<div class="flex-1">
|
||||
<div class="font-medium text-900">#{alerte.titre}</div>
|
||||
<small class="text-500">#{alerte.entite} • #{alerte.date}</small>
|
||||
@@ -283,9 +283,9 @@
|
||||
</div>
|
||||
|
||||
<ui:repeat value="#{superAdminBean.activitesRecentes}" var="activite" varStatus="status">
|
||||
<div class="flex align-items-start p-3 mb-2 border-round border-left-3 border-blue-300"
|
||||
style="background: var(--surface-50);">
|
||||
<i class="pi pi-history text-blue-500 text-xl mr-3 mt-1"></i>
|
||||
<div class="flex align-items-start p-3 mb-2 border-round uf-border-left-navy"
|
||||
style="background: var(--surface-50); border-left-width: 4px; border-left-style: solid;">
|
||||
<i class="pi pi-history uf-text-navy text-xl mr-3 mt-1"></i>
|
||||
<div class="flex-1">
|
||||
<div class="font-medium text-900 mb-1">#{activite.description}</div>
|
||||
<div class="text-600 text-sm">#{activite.entite}</div>
|
||||
@@ -326,26 +326,26 @@
|
||||
</div>
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 border-round bg-green-50">
|
||||
<div class="text-green-600 font-medium text-xl">#{superAdminBean.revenus.mensuel}</div>
|
||||
<div class="text-center p-3 border-round uf-bg-forest-light">
|
||||
<div class="uf-text-forest font-medium text-xl">#{superAdminBean.revenus.mensuel}</div>
|
||||
<div class="text-500">Revenus ce mois</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 border-round bg-blue-50">
|
||||
<div class="text-blue-600 font-medium text-xl">#{superAdminBean.revenus.annuel}</div>
|
||||
<div class="text-center p-3 border-round uf-bg-navy-light">
|
||||
<div class="uf-text-navy font-medium text-xl">#{superAdminBean.revenus.annuel}</div>
|
||||
<div class="text-500">Revenus annuels</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 border-round bg-purple-50">
|
||||
<div class="text-purple-600 font-medium text-xl">#{superAdminBean.revenus.croissance}%</div>
|
||||
<div class="text-center p-3 border-round uf-bg-gold-light">
|
||||
<div class="uf-text-gold font-medium text-xl">#{superAdminBean.revenus.croissance}%</div>
|
||||
<div class="text-500">Croissance annuelle</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-3">
|
||||
<div class="text-center p-3 border-round bg-orange-50">
|
||||
<div class="text-orange-600 font-medium text-xl">#{superAdminBean.revenus.moyenne}</div>
|
||||
<div class="text-center p-3 border-round uf-bg-crimson-light">
|
||||
<div class="uf-text-crimson font-medium text-xl">#{superAdminBean.revenus.moyenne}</div>
|
||||
<div class="text-500">Revenu moyen / entité</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/* ==========================================================================
|
||||
UnionFlow Premium Dashboard Design System (Banking / Governance aesthetic)
|
||||
========================================================================== */
|
||||
|
||||
/* 1. Custom Color Tokens (Overrides for PrimeFlex) */
|
||||
|
||||
/* Primary Blue (Bleu Tech/Moderne) */
|
||||
.uf-text-navy { color: var(--primary-color, #4F46E5) !important; }
|
||||
.uf-bg-navy { background-color: var(--primary-color, #4F46E5) !important; }
|
||||
.uf-bg-navy-light { background-color: rgba(79, 70, 229, 0.08) !important; }
|
||||
.uf-border-navy { border-color: var(--primary-color, #4F46E5) !important; }
|
||||
.uf-border-left-navy { border-left-color: var(--primary-color, #4F46E5) !important; }
|
||||
|
||||
/* Forest Green (Vert Forêt) */
|
||||
.uf-text-forest { color: #126A54 !important; }
|
||||
.uf-bg-forest { background-color: #126A54 !important; }
|
||||
.uf-bg-forest-light { background-color: rgba(18, 106, 84, 0.08) !important; }
|
||||
.uf-border-forest { border-color: #126A54 !important; }
|
||||
.uf-border-left-forest { border-left-color: #126A54 !important; }
|
||||
|
||||
/* Premium Gold (Or) */
|
||||
.uf-text-gold { color: #E6C57A !important; }
|
||||
.uf-bg-gold { background-color: #E6C57A !important; }
|
||||
.uf-bg-gold-light { background-color: rgba(230, 197, 122, 0.15) !important; }
|
||||
.uf-border-gold { border-color: #E6C57A !important; }
|
||||
.uf-border-left-gold { border-left-color: #E6C57A !important; }
|
||||
|
||||
/* Critical Premium Red (Deep Burgundy/Carmine instead of bright aggressive red) */
|
||||
.uf-text-crimson { color: #C92A2A !important; }
|
||||
.uf-bg-crimson { background-color: #C92A2A !important; }
|
||||
.uf-bg-crimson-light { background-color: rgba(201, 42, 42, 0.06) !important; }
|
||||
.uf-border-crimson { border-color: #C92A2A !important; }
|
||||
.uf-border-left-crimson { border-left-color: #C92A2A !important; }
|
||||
|
||||
/* Neutral Premium (Deep Gray) */
|
||||
.uf-text-neutral { color: #334155 !important; }
|
||||
.uf-bg-neutral-light { background-color: #F8FAFC !important; }
|
||||
|
||||
|
||||
/* 2. Premium Card Styles (Glassmorphism & Shadows) */
|
||||
|
||||
/* Modernizing the default cards */
|
||||
.layout-content .card {
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(79, 70, 229, 0.08); /* Primary color low opacity */
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.02);
|
||||
background: #FFFFFF;
|
||||
transition: box-shadow 0.3s ease;
|
||||
}
|
||||
|
||||
.layout-content .card:hover {
|
||||
box-shadow: 0 6px 24px rgba(79, 70, 229, 0.1);
|
||||
}
|
||||
|
||||
/* KPI Overview Cards (Elevated, Interactive) */
|
||||
.uf-kpi-card {
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(0,0,0,0.03) !important;
|
||||
background: #FFFFFF !important;
|
||||
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275), box-shadow 0.3s ease !important;
|
||||
}
|
||||
|
||||
.uf-kpi-card:hover {
|
||||
transform: translateY(-5px) !important;
|
||||
box-shadow: 0 15px 35px rgba(79, 70, 229, 0.15) !important;
|
||||
}
|
||||
|
||||
/* Alert/Action Cards (With left border) */
|
||||
.uf-alert-card {
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(0,0,0,0.02);
|
||||
background: #FFFFFF;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.uf-alert-card:hover {
|
||||
transform: translateX(4px);
|
||||
box-shadow: 0 8px 20px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
/* Icon Containers in Cards */
|
||||
.uf-icon-box {
|
||||
width: 3rem;
|
||||
height: 3rem;
|
||||
border-radius: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 3. Specialized Elements */
|
||||
|
||||
/* Activity Timeline/DataTables in Dashboard */
|
||||
.ui-datatable .ui-datatable-header {
|
||||
background: transparent !important;
|
||||
border-bottom: 2px solid rgba(79, 70, 229, 0.1) !important;
|
||||
border-top: none !important;
|
||||
border-left: none !important;
|
||||
border-right: none !important;
|
||||
color: var(--primary-color, #4F46E5) !important;
|
||||
}
|
||||
|
||||
.ui-tag.ui-tag-success { background: #126A54; }
|
||||
.ui-tag.ui-tag-warning { background: #E6C57A; color: var(--primary-color, #4F46E5); }
|
||||
.ui-tag.ui-tag-info { background: var(--primary-color, #4F46E5); }
|
||||
.ui-tag.ui-tag-danger { background: #C92A2A; }
|
||||
|
||||
/* Progress bars */
|
||||
.bg-gray-200 { background-color: #EDF2F7 !important; }
|
||||
@@ -913,3 +913,554 @@
|
||||
color: var(--primary-color, #6366f1);
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
|
||||
/* ═══════════════════════════════════════════════════════════════════ */
|
||||
/* UNIONFLOW BRAND IDENTITY — EXHAUSTIVE DARK/LIGHT MODE SUPPORT */
|
||||
/* Charte: #0B304A (Bleu Nuit), #126A54 (Vert Forêt), */
|
||||
/* #E6C57A (Or Premium), #F4F6F8 (Fond), #E8EAEC */
|
||||
/* */
|
||||
/* Freya theme axes: */
|
||||
/* 1. topbarTheme → .layout-topbar-light | .layout-topbar-dark */
|
||||
/* 2. menuTheme → .layout-menu-light | .layout-menu-dark */
|
||||
/* 3. darkMode → layout-light.css | layout-dark.css */
|
||||
/* 4. menuMode → .layout-sidebar | .layout-static */
|
||||
/* .layout-horizontal | .layout-slim */
|
||||
/* ═══════════════════════════════════════════════════════════════════ */
|
||||
|
||||
/* ──────────────────────────────────────────────────
|
||||
1. BASE — Brand Composition (Logo + Text)
|
||||
Now uses .unionflow-topbar-brand (outside of
|
||||
.layout-topbar-logo to avoid Freya display:none)
|
||||
────────────────────────────────────────────────── */
|
||||
|
||||
.unionflow-topbar-brand,
|
||||
.unionflow-brand {
|
||||
display: flex !important;
|
||||
align-items: center;
|
||||
gap: 0.625rem;
|
||||
text-decoration: none !important;
|
||||
height: auto !important;
|
||||
}
|
||||
|
||||
.unionflow-brand-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
object-fit: contain;
|
||||
flex-shrink: 0;
|
||||
border-radius: 4px;
|
||||
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.unionflow-topbar-brand:hover .unionflow-brand-icon,
|
||||
.unionflow-brand:hover .unionflow-brand-icon {
|
||||
transform: scale(1.05) rotate(-2deg);
|
||||
}
|
||||
|
||||
.unionflow-brand-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 1;
|
||||
gap: 0.1875rem;
|
||||
}
|
||||
|
||||
.unionflow-brand-name {
|
||||
font-size: 1.125rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.15em;
|
||||
text-transform: uppercase;
|
||||
font-family: 'Inter', 'Segoe UI', Roboto, sans-serif;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
.unionflow-brand-slogan {
|
||||
font-size: 0.5625rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.12em;
|
||||
text-transform: uppercase;
|
||||
font-family: 'Inter', 'Segoe UI', Roboto, sans-serif;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────
|
||||
2. TOPBAR — Dark mode (default: gradient/dark bg)
|
||||
Classes: .layout-topbar-dark, .unionflow-elite
|
||||
────────────────────────────────────────────────── */
|
||||
|
||||
.layout-topbar-dark .unionflow-brand-name,
|
||||
.unionflow-elite .unionflow-brand-name {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.layout-topbar-dark .unionflow-brand-slogan,
|
||||
.unionflow-elite .unionflow-brand-slogan {
|
||||
color: rgba(230, 197, 122, 0.9); /* Or Premium #E6C57A */
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────
|
||||
3. TOPBAR — Light mode (white bg)
|
||||
Class: .layout-topbar-light
|
||||
────────────────────────────────────────────────── */
|
||||
|
||||
.layout-topbar-light .unionflow-brand-name {
|
||||
color: #0B304A; /* Bleu Nuit */
|
||||
}
|
||||
|
||||
.layout-topbar-light .unionflow-brand-slogan {
|
||||
color: #126A54; /* Vert Forêt */
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────
|
||||
4. SIDEBAR BRAND — Single source of branding
|
||||
Collapsed (62px): icon only
|
||||
Expanded (230px): icon + UNIONFLOW + slogan + v1.0
|
||||
────────────────────────────────────────────────── */
|
||||
|
||||
/* --- Logo link container --- */
|
||||
.sidebar-logo-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
text-decoration: none !important;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.sidebar-logo-link:hover .unionflow-sidebar-icon {
|
||||
transform: scale(1.08);
|
||||
}
|
||||
|
||||
/* --- Icon (always visible — 24px for visual parity with menu icons) --- */
|
||||
.unionflow-sidebar-icon {
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
object-fit: contain;
|
||||
border-radius: 3px;
|
||||
border: 0 none !important;
|
||||
flex-shrink: 0;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
/* Override Freya's .menu-wrapper .sidebar-logo img { width:17px; height:20px } */
|
||||
.menu-wrapper .sidebar-logo .unionflow-sidebar-icon {
|
||||
width: 24px !important;
|
||||
height: 24px !important;
|
||||
}
|
||||
|
||||
/* --- Text block (hidden when collapsed) --- */
|
||||
.unionflow-sidebar-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 1;
|
||||
gap: 0.125rem;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
transition: opacity 0.2s ease, visibility 0.2s ease;
|
||||
}
|
||||
|
||||
.unionflow-sidebar-name {
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: 0.15em;
|
||||
text-transform: uppercase;
|
||||
font-family: 'Inter', 'Segoe UI', Roboto, sans-serif;
|
||||
}
|
||||
|
||||
.unionflow-sidebar-slogan {
|
||||
font-size: 0.5rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
font-family: 'Inter', 'Segoe UI', Roboto, sans-serif;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* --- Version badge (hidden when collapsed) --- */
|
||||
.unionflow-sidebar-version {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
border-radius: 8px;
|
||||
font-size: 0.625rem;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
overflow: hidden;
|
||||
transition: opacity 0.2s ease, visibility 0.2s ease;
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────
|
||||
4b. SIDEBAR EXPANDED — Show full brand
|
||||
Triggered by: layout-static, layout-sidebar-active (hover)
|
||||
────────────────────────────────────────────────── */
|
||||
|
||||
@media (min-width: 992px) {
|
||||
/* Expanded: icon grows slightly */
|
||||
.layout-wrapper.layout-static .menu-wrapper .sidebar-logo .unionflow-sidebar-icon,
|
||||
.menu-wrapper.layout-sidebar-active .sidebar-logo .unionflow-sidebar-icon {
|
||||
width: 30px !important;
|
||||
height: 30px !important;
|
||||
}
|
||||
|
||||
/* Expanded: show text */
|
||||
.layout-wrapper.layout-static .menu-wrapper .sidebar-logo .unionflow-sidebar-text,
|
||||
.menu-wrapper.layout-sidebar-active .sidebar-logo .unionflow-sidebar-text {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/* Expanded: show version badge */
|
||||
.layout-wrapper.layout-static .menu-wrapper .sidebar-logo .unionflow-sidebar-version,
|
||||
.menu-wrapper.layout-sidebar-active .sidebar-logo .unionflow-sidebar-version {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
width: auto;
|
||||
padding: 0.125rem 0.4rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────
|
||||
5. SIDEBAR — Menu Dark theme
|
||||
Class: .layout-menu-dark (menu bg = #293241)
|
||||
────────────────────────────────────────────────── */
|
||||
|
||||
.layout-menu-dark .unionflow-sidebar-name {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.layout-menu-dark .unionflow-sidebar-slogan {
|
||||
color: rgba(230, 197, 122, 0.85); /* Or Premium */
|
||||
}
|
||||
|
||||
.layout-menu-dark .unionflow-sidebar-version {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.layout-menu-dark .sidebar-logo-link {
|
||||
color: #E9E9E9;
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────
|
||||
6. SIDEBAR — Menu Light theme
|
||||
Class: .layout-menu-light (menu bg = white)
|
||||
────────────────────────────────────────────────── */
|
||||
|
||||
.layout-menu-light .unionflow-sidebar-name {
|
||||
color: #0B304A; /* Bleu Nuit */
|
||||
}
|
||||
|
||||
.layout-menu-light .unionflow-sidebar-slogan {
|
||||
color: #126A54; /* Vert Forêt */
|
||||
}
|
||||
|
||||
.layout-menu-light .unionflow-sidebar-version {
|
||||
background: rgba(11, 48, 74, 0.1);
|
||||
color: #0B304A;
|
||||
}
|
||||
|
||||
.layout-menu-light .sidebar-logo-link {
|
||||
color: #0B304A;
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────
|
||||
9. LANDING PAGE — Variant Premium Unionflow
|
||||
────────────────────────────────────────────────── */
|
||||
|
||||
/* App background */
|
||||
.landing-body {
|
||||
background-color: #F4F6F8 !important; /* Très léger gris/bleu pour le fond de page */
|
||||
}
|
||||
|
||||
/* Banner (Hero section) - Deep Blue modern gradient instead of the generic mountain */
|
||||
.landing-body .landing-banner {
|
||||
background: linear-gradient(135deg, #0B304A 0%, #154B73 50%, #126A54 100%) !important;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Add a subtle geometric overlay effect to the banner for depth */
|
||||
.landing-body .landing-banner::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
width: 200%;
|
||||
height: 200%;
|
||||
background: radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.03) 0%, transparent 60%);
|
||||
opacity: 0.8;
|
||||
pointer-events: none;
|
||||
animation: rotate-slow 60s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes rotate-slow {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Typography on Banner */
|
||||
.landing-body .landing-banner .landing-banner-content .title {
|
||||
color: #FFFFFF !important;
|
||||
text-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
||||
font-family: 'Inter', 'Segoe UI', Roboto, sans-serif;
|
||||
font-weight: 800 !important;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.landing-body .landing-banner .landing-banner-content h3 {
|
||||
color: rgba(255, 255, 255, 0.9) !important;
|
||||
font-family: 'Inter', 'Segoe UI', Roboto, sans-serif;
|
||||
font-weight: 400 !important;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
|
||||
/* Topbar on Landing */
|
||||
.landing-body .landing-topbar {
|
||||
background: rgba(255, 255, 255, 0.95) !important;
|
||||
backdrop-filter: blur(10px);
|
||||
border-bottom: 1px solid rgba(11, 48, 74, 0.05);
|
||||
box-shadow: 0 4px 30px rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
/* Override Freya's tiny 16px landing logo */
|
||||
.landing-body .landing-topbar .landing-topbar-left .logo.unionflow-brand--landing {
|
||||
display: flex !important;
|
||||
align-items: center !important;
|
||||
gap: 0.75rem !important;
|
||||
text-decoration: none !important;
|
||||
}
|
||||
|
||||
.landing-body .landing-topbar .landing-topbar-left .logo.unionflow-brand--landing img.unionflow-brand-icon {
|
||||
width: 36px !important;
|
||||
height: 36px !important;
|
||||
}
|
||||
|
||||
.landing-body .landing-topbar .landing-topbar-left .logo.unionflow-brand--landing .unionflow-brand-name {
|
||||
font-size: 1.35rem !important;
|
||||
letter-spacing: 0.15em !important;
|
||||
color: #0B304A !important;
|
||||
font-weight: 800 !important;
|
||||
font-family: 'Inter', 'Segoe UI', Roboto, sans-serif !important;
|
||||
}
|
||||
|
||||
.landing-body .landing-topbar .landing-menu > li > a {
|
||||
color: #0B304A !important;
|
||||
font-family: 'Inter', 'Segoe UI', Roboto, sans-serif;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
font-size: 0.75rem !important;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.landing-body .landing-topbar .landing-menu > li > a:hover {
|
||||
color: #E6C57A !important; /* Premium Gold */
|
||||
}
|
||||
|
||||
/* Topbar Secondary Button - Premium Hover */
|
||||
.landing-body .landing-topbar-right a[href*="dashboard"] {
|
||||
border: 2px solid #0B304A !important;
|
||||
color: #0B304A !important;
|
||||
transition: all 0.3s ease !important;
|
||||
}
|
||||
|
||||
.landing-body .landing-topbar-right a[href*="dashboard"]:hover {
|
||||
background: transparent !important;
|
||||
border-color: #E6C57A !important; /* Premium Gold */
|
||||
color: #E6C57A !important;
|
||||
box-shadow: 0 4px 15px rgba(230, 197, 122, 0.2);
|
||||
}
|
||||
|
||||
/* Banner CTA Button - Premium Gold */
|
||||
.landing-body .landing-banner-content a[href*="dashboard"] {
|
||||
background: linear-gradient(135deg, #E6C57A 0%, #D4AF37 100%) !important;
|
||||
color: #0B304A !important;
|
||||
border: none !important;
|
||||
box-shadow: 0 8px 24px rgba(230, 197, 122, 0.4) !important;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.landing-body .landing-banner-content a[href*="dashboard"]:hover {
|
||||
transform: translateY(-4px) !important;
|
||||
box-shadow: 0 12px 30px rgba(230, 197, 122, 0.6) !important;
|
||||
}
|
||||
|
||||
/* Feature Cards - Glassmorphism & Shadows */
|
||||
.landing-body .landing-features {
|
||||
background: transparent !important;
|
||||
}
|
||||
|
||||
.landing-body .feature-card {
|
||||
background: #FFFFFF !important;
|
||||
border: 1px solid rgba(11, 48, 74, 0.05) !important;
|
||||
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.04) !important;
|
||||
border-radius: 20px !important;
|
||||
transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275), box-shadow 0.4s ease !important;
|
||||
}
|
||||
|
||||
.landing-body .feature-card:hover {
|
||||
transform: translateY(-12px) !important; /* Increased lift */
|
||||
box-shadow: 0 25px 60px rgba(11, 48, 74, 0.12) !important;
|
||||
}
|
||||
|
||||
.landing-body .feature-card h3 {
|
||||
color: #0B304A !important;
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
|
||||
.landing-body .feature-card h5 {
|
||||
color: rgba(11, 48, 74, 0.7) !important;
|
||||
}
|
||||
|
||||
/* Feature Icon numbers styling */
|
||||
.landing-body .feature > span {
|
||||
color: #E6C57A !important; /* Premium Gold */
|
||||
font-weight: 800 !important;
|
||||
font-size: 28px !important;
|
||||
}
|
||||
|
||||
/* Sub-section headings */
|
||||
.landing-body .section-header .title {
|
||||
color: #0B304A !important;
|
||||
font-weight: 800 !important;
|
||||
}
|
||||
|
||||
.landing-body .section-header h3 {
|
||||
color: rgba(11, 48, 74, 0.7) !important;
|
||||
}
|
||||
|
||||
/* Benefit Icons Scale-up */
|
||||
.landing-body .landing-pricing h3 + p + ul {
|
||||
margin-top: 1rem !important;
|
||||
}
|
||||
|
||||
.landing-body .landing-pricing .pi {
|
||||
font-size: 1.5rem !important; /* Bumped from 1.25 to 1.5 for presence */
|
||||
}
|
||||
|
||||
/* Bottom banner trust section */
|
||||
.landing-body .landing-pricing > div:last-of-type > div {
|
||||
background: linear-gradient(135deg, #0B304A 0%, #126A54 100%) !important;
|
||||
border-radius: 24px !important;
|
||||
box-shadow: 0 15px 40px rgba(11, 48, 74, 0.2) !important;
|
||||
}
|
||||
|
||||
/* Final CTA */
|
||||
.landing-body .mt-5 > a {
|
||||
background: #0B304A !important;
|
||||
color: #FFFFFF !important;
|
||||
box-shadow: 0 4px 18px rgba(11, 48, 74, 0.3) !important;
|
||||
}
|
||||
|
||||
.landing-body .mt-5 > a:hover {
|
||||
transform: translateY(-3px) !important;
|
||||
box-shadow: 0 10px 30px rgba(11, 48, 74, 0.4) !important;
|
||||
background: #154B73 !important;
|
||||
}
|
||||
|
||||
/* Footer styling */
|
||||
.landing-body .layout-footer {
|
||||
border-top: 1px solid rgba(11, 48, 74, 0.05);
|
||||
}
|
||||
|
||||
.landing-body .layout-footer .footer-menutitle {
|
||||
color: #0B304A !important;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.landing-body .layout-footer ul > li,
|
||||
.landing-body .layout-footer ul > li > a {
|
||||
color: rgba(11, 48, 74, 0.6) !important;
|
||||
}
|
||||
|
||||
.landing-body .layout-footer ul > li > a:hover {
|
||||
color: #126A54 !important;
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
.unionflow-brand--landing .unionflow-brand-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.unionflow-brand--landing .unionflow-brand-name {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────
|
||||
10. EXCEPTION PAGES — 404, Access Denied, Error
|
||||
────────────────────────────────────────────────── */
|
||||
|
||||
.exception-body .exception-topbar .unionflow-brand-icon {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.exception-body .exception-topbar .unionflow-brand-name {
|
||||
color: #0B304A;
|
||||
}
|
||||
|
||||
.exception-body .exception-topbar .unionflow-brand-slogan {
|
||||
color: #126A54;
|
||||
}
|
||||
|
||||
/* ──────────────────────────────────────────────────
|
||||
11. RESPONSIVE BREAKPOINTS
|
||||
────────────────────────────────────────────────── */
|
||||
|
||||
@media (max-width: 991px) {
|
||||
/* On tablets: smaller icon, keep text */
|
||||
.unionflow-brand-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.unionflow-brand-name {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.unionflow-brand-slogan {
|
||||
font-size: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
/* On small tablets: hide text, only icon */
|
||||
.unionflow-brand-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.unionflow-brand-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
/* On phones: even smaller icon */
|
||||
.unionflow-brand-icon {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
}
|
||||
|
||||
.unionflow-brand--landing .unionflow-brand-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
/* Still show name on landing for brand recognition */
|
||||
.unionflow-brand--landing .unionflow-brand-text {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.unionflow-brand--landing .unionflow-brand-name {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
@@ -80,14 +80,14 @@
|
||||
<ui:param name="noDataLabel" value="Données non disponibles" />
|
||||
|
||||
<div class="field #{colSize}">
|
||||
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
|
||||
<div class="card uf-kpi-card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
|
||||
<div class="p-4" style="min-height: 9rem;">
|
||||
<!-- Header: Titre et Icône -->
|
||||
<div class="flex align-items-center justify-content-between mb-3">
|
||||
<span class="block text-600 font-medium text-sm">#{title}</span>
|
||||
<div class="flex align-items-center justify-content-center surface-100 border-round-lg"
|
||||
style="width: 2.5rem; height: 2.5rem;">
|
||||
<i class="pi #{icon} text-#{iconColor} text-lg"></i>
|
||||
<i class="pi #{icon} #{iconColor.startsWith('uf-') ? '' : 'text-'}#{iconColor} text-lg"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -7,8 +7,15 @@
|
||||
|
||||
<div class="menu-wrapper">
|
||||
<div class="sidebar-logo">
|
||||
<a href="dashboard.xhtml">
|
||||
<p:graphicImage name="images/logo-freya-single.svg" library="freya-layout" />
|
||||
<a href="dashboard.xhtml" class="sidebar-logo-link">
|
||||
<h:graphicImage value="#{request.contextPath}/resources/freya-layout/images/unionflow-logo.png"
|
||||
alt="UnionFlow"
|
||||
styleClass="unionflow-sidebar-icon" />
|
||||
<span class="unionflow-sidebar-text">
|
||||
<span class="unionflow-sidebar-name">UNIONFLOW</span>
|
||||
<span class="unionflow-sidebar-slogan">Connecter · Unir · Avancer</span>
|
||||
</span>
|
||||
<span class="unionflow-sidebar-version">v1.0</span>
|
||||
</a>
|
||||
<a href="#" class="sidebar-pin" title="Toggle Menu">
|
||||
<span class="pin"></span>
|
||||
|
||||
@@ -21,13 +21,7 @@
|
||||
<a href="#" class="menu-button">
|
||||
<i class="pi pi-bars"/>
|
||||
</a>
|
||||
<h:link id="logolink" outcome="/pages/secure/dashboard" styleClass="layout-topbar-logo">
|
||||
<p:graphicImage name="images/#{guestPreferences.lightLogo ? 'logo-freya-white.svg' : 'logo-freya.svg'}"
|
||||
library="freya-layout"
|
||||
alt="UnionFlow"
|
||||
title="Retour au tableau de bord"/>
|
||||
</h:link>
|
||||
<span class="app-version">v1.0</span>
|
||||
<h:link id="logolink" outcome="/pages/secure/dashboard" styleClass="layout-topbar-logo" style="display:none"/>
|
||||
</div>
|
||||
|
||||
<!-- CENTER - Menu -->
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
|
||||
<!-- Obsolète : apple-mobile-web-app-capable. Remplacé par mobile-web-app-capable -->
|
||||
<meta name="mobile-web-app-capable" content="yes" />
|
||||
<link rel="icon" href="#{request.contextPath}/resources/freya-layout/images/favicon.ico" type="image/x-icon"></link>
|
||||
<link rel="icon" href="#{request.contextPath}/resources/freya-layout/images/unionflow-logo.png" type="image/png"></link>
|
||||
</f:facet>
|
||||
<title><ui:insert name="title">UnionFlow</ui:insert></title>
|
||||
<h:outputScript name="js/layout.js" library="freya-layout" />
|
||||
@@ -52,6 +52,8 @@
|
||||
<h:outputStylesheet name="css/primeflex.min.css" library="freya-layout" />
|
||||
<h:outputStylesheet name="css/layout-#{guestPreferences.layout}.css" library="freya-layout" />
|
||||
<h:outputStylesheet name="primefaces-freya-#{guestPreferences.componentTheme}/theme.css" />
|
||||
<h:outputStylesheet name="css/topbar-elite.css" />
|
||||
<h:outputStylesheet name="css/dashboard-premium.css" />
|
||||
</h:body>
|
||||
|
||||
</html>
|
||||
@@ -12,7 +12,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
|
||||
<!-- Obsolète : apple-mobile-web-app-capable. Remplacé par mobile-web-app-capable -->
|
||||
<meta name="mobile-web-app-capable" content="yes"/>
|
||||
<link rel="icon" type="image/x-icon" href="#{resource['images/favicon.ico']}"/>
|
||||
<link rel="icon" type="image/png" href="#{resource['freya-layout:images/unionflow-logo.png']}"/>
|
||||
</f:facet>
|
||||
|
||||
<title>
|
||||
|
||||
Reference in New Issue
Block a user