refactor: toilettage intégral menu et suppression système entités

Supprimé:
- EntitesGestionBean.java (doublon de OrganisationsBean)
- pages/super-admin/entites/ (gestion.xhtml + gestion-enhanced.xhtml)
- pages/super-admin/organisations.xhtml (doublon mort)

Menu restructuré:
- 32→17 sous-menus, 0 lien mort (était 22 url="#")
- Fusionné Annuaire+Gestion Membres en un seul sous-menu contextuel
- Supprimé sous-menu Administration (fourre-tout, doublons redistribués)
- Supprimé sous-menu Formations (inutile, pointait vers dashboard)
- Modules non implémentés: item unique "Bientôt disponible" disabled
- Aide et Support: 9→3 items, Mon Espace: 8→4 items
- Documents: 7→1 item (seul fonctionnel conservé)

Nettoyé:
- ADMIN_ENTITE→ADMIN_ORGANISATION dans scripts, docs, Javadoc
- 3 méthodes @Deprecated supprimées dans MenuBean
- faces-config.xml: 5 rules entite*→3 rules organisation*
- SuperAdminBean: constantes+méthodes entite→organisation
This commit is contained in:
dahoud
2026-04-17 19:20:19 +00:00
parent 4735c1633f
commit 634cc5e30d
16 changed files with 163 additions and 2782 deletions

View File

@@ -84,7 +84,7 @@ et ce projet adhère au [Semantic Versioning](https://semver.org/lang/fr/).
-**FavorisBean** - Favoris utilisateur
-**WaveBean** - Intégration Wave Money
-**LoginBean** - Authentification
-**EntitesGestionBean** - Gestion des entités
-**OrganisationsBean** - Gestion des organisations
- ✅ Et 9 autres beans...
##### Changements par Bean

View File

@@ -253,7 +253,7 @@ export LOCKOUT_DURATION="300"
- Web Origins: `https://votre-domaine.com`
3. Configurer les rôles:
- `SUPER_ADMIN`: Administrateur système
- `ADMIN_ENTITE`: Administrateur d'organisation
- `ADMIN_ORGANISATION`: Administrateur d'organisation
- `MEMBRE`: Membre standard
4. Configurer les mappers pour inclure les rôles dans les tokens JWT
@@ -302,7 +302,7 @@ docker run -p 8080:8080 \
- **Méthode**: OpenID Connect (OIDC) via Keycloak
- **Tokens**: JWT (JSON Web Tokens)
- **Rôles supportés**: SUPER_ADMIN, ADMIN_ENTITE, MEMBRE
- **Rôles supportés**: SUPER_ADMIN, ADMIN_ORGANISATION, MEMBRE
- **Permissions granulaires**: Basées sur les rôles et fonctionnalités
### Headers de Sécurité (Production)

View File

@@ -98,7 +98,7 @@ quarkus.oidc.tls.verification=required # JAMAIS 'none' en production
#### Hiérarchie des Rôles
1. **SUPER_ADMIN** - Accès complet système
2. **ADMIN_ENTITE** - Administration organisation
2. **ADMIN_ORGANISATION** - Administration organisation
3. **ADMIN** - Administration locale
4. **GESTIONNAIRE_*** - Gestion fonctionnelle
5. **TRESORIER** - Gestion financière

View File

@@ -82,8 +82,8 @@ echo ✅ Rôle SUPER_ADMIN créé
curl -s -X POST "%KEYCLOAK_URL%/admin/realms/%REALM_NAME%/roles" ^
-H "Authorization: Bearer %ADMIN_TOKEN%" ^
-H "Content-Type: application/json" ^
-d "{\"name\":\"ADMIN_ENTITE\",\"description\":\"Administrateur d'entité\"}" > nul 2>&1
echo ✅ Rôle ADMIN_ENTITE créé
-d "{\"name\":\"ADMIN_ORGANISATION\",\"description\":\"Administrateur d'entité\"}" > nul 2>&1
echo ✅ Rôle ADMIN_ORGANISATION créé
curl -s -X POST "%KEYCLOAK_URL%/admin/realms/%REALM_NAME%/roles" ^
-H "Authorization: Bearer %ADMIN_TOKEN%" ^
@@ -205,9 +205,9 @@ if not "%USER_ID%"=="" (
curl -s -X GET "%KEYCLOAK_URL%/admin/realms/%REALM_NAME%/roles" ^
-H "Authorization: Bearer %ADMIN_TOKEN%" > roles.json
REM Assigner les rôles MEMBRE et ADMIN_ENTITE
REM Assigner les rôles MEMBRE et ADMIN_ORGANISATION
for /f "delims=" %%i in ('powershell -Command "(Get-Content roles.json | ConvertFrom-Json) | Where-Object {$_.name -eq 'MEMBRE'} | Select-Object -ExpandProperty id"') do set ROLE_MEMBRE_ID=%%i
for /f "delims=" %%i in ('powershell -Command "(Get-Content roles.json | ConvertFrom-Json) | Where-Object {$_.name -eq 'ADMIN_ENTITE'} | Select-Object -ExpandProperty id"') do set ROLE_ADMIN_ID=%%i
for /f "delims=" %%i in ('powershell -Command "(Get-Content roles.json | ConvertFrom-Json) | Where-Object {$_.name -eq 'ADMIN_ORGANISATION'} | Select-Object -ExpandProperty id"') do set ROLE_ADMIN_ID=%%i
if not "%ROLE_MEMBRE_ID%"=="" (
curl -s -X POST "%KEYCLOAK_URL%/admin/realms/%REALM_NAME%/users/%USER_ID%/role-mappings/realm" ^
@@ -221,8 +221,8 @@ if not "%USER_ID%"=="" (
curl -s -X POST "%KEYCLOAK_URL%/admin/realms/%REALM_NAME%/users/%USER_ID%/role-mappings/realm" ^
-H "Authorization: Bearer %ADMIN_TOKEN%" ^
-H "Content-Type: application/json" ^
-d "[{\"id\":\"%ROLE_ADMIN_ID%\",\"name\":\"ADMIN_ENTITE\"}]" > nul 2>&1
echo ✅ Rôle ADMIN_ENTITE assigné
-d "[{\"id\":\"%ROLE_ADMIN_ID%\",\"name\":\"ADMIN_ORGANISATION\"}]" > nul 2>&1
echo ✅ Rôle ADMIN_ORGANISATION assigné
)
) else (
echo ⚠️ Impossible de configurer l'utilisateur
@@ -262,7 +262,7 @@ echo - Client ID: %CLIENT_ID%
echo - Client Secret: %CLIENT_SECRET%
echo - Utilisateur test: test@unionflow.dev
echo - Mot de passe: test123
echo - Rôles assignés: MEMBRE, ADMIN_ENTITE
echo - Rôles assignés: MEMBRE, ADMIN_ORGANISATION
echo.
echo 📄 Le client secret a été sauvegardé dans le fichier .env
echo.

View File

@@ -78,8 +78,8 @@ echo " ✅ Rôle SUPER_ADMIN créé"
curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"ADMIN_ENTITE","description":"Administrateur d'\''entité"}' > /dev/null 2>&1
echo " ✅ Rôle ADMIN_ENTITE créé"
-d '{"name":"ADMIN_ORGANISATION","description":"Administrateur d'\''entité"}' > /dev/null 2>&1
echo " ✅ Rôle ADMIN_ORGANISATION créé"
curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/roles" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
@@ -240,11 +240,11 @@ if [ -n "$USER_ID" ]; then
-H "Authorization: Bearer $ADMIN_TOKEN")
ROLE_MEMBRE_ID=$(echo "$ROLES" | grep -B2 '"name":"MEMBRE"' | grep '"id"' | cut -d'"' -f4)
ROLE_ADMIN_ID=$(echo "$ROLES" | grep -B2 '"name":"ADMIN_ENTITE"' | grep '"id"' | cut -d'"' -f4)
ROLE_ADMIN_ID=$(echo "$ROLES" | grep -B2 '"name":"ADMIN_ORGANISATION"' | grep '"id"' | cut -d'"' -f4)
if command -v jq &> /dev/null; then
ROLE_MEMBRE_ID=$(echo "$ROLES" | jq -r '.[] | select(.name=="MEMBRE") | .id')
ROLE_ADMIN_ID=$(echo "$ROLES" | jq -r '.[] | select(.name=="ADMIN_ENTITE") | .id')
ROLE_ADMIN_ID=$(echo "$ROLES" | jq -r '.[] | select(.name=="ADMIN_ORGANISATION") | .id')
fi
if [ -n "$ROLE_MEMBRE_ID" ]; then
@@ -259,8 +259,8 @@ if [ -n "$USER_ID" ]; then
curl -s -X POST "$KEYCLOAK_URL/admin/realms/$REALM_NAME/users/$USER_ID/role-mappings/realm" \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d "[{\"id\":\"$ROLE_ADMIN_ID\",\"name\":\"ADMIN_ENTITE\"}]" > /dev/null 2>&1
echo " ✅ Rôle ADMIN_ENTITE assigné"
-d "[{\"id\":\"$ROLE_ADMIN_ID\",\"name\":\"ADMIN_ORGANISATION\"}]" > /dev/null 2>&1
echo " ✅ Rôle ADMIN_ORGANISATION assigné"
fi
else
echo "⚠️ Impossible de configurer l'utilisateur"
@@ -297,7 +297,7 @@ echo " - Client ID: $CLIENT_ID"
echo " - Client Secret: $CLIENT_SECRET"
echo " - Utilisateur test: test@unionflow.dev"
echo " - Mot de passe: test123"
echo " - Rôles assignés: MEMBRE, ADMIN_ENTITE"
echo " - Rôles assignés: MEMBRE, ADMIN_ORGANISATION"
echo ""
echo "📄 Le client secret a été sauvegardé dans le fichier .env"
echo ""

View File

@@ -85,7 +85,7 @@ import org.jboss.logging.Logger;
* <li>OIDC avec Keycloak (realm: unionflow)</li>
* <li>JWT dans HTTP-only cookies (protection XSS)</li>
* <li>CSRF protection avec PrimeFaces ViewState</li>
* <li>RBAC avec rôles: SUPER_ADMIN, ADMIN_ENTITE, MEMBRE</li>
* <li>RBAC avec rôles: SUPER_ADMIN, ADMIN_ORGANISATION, MEMBRE</li>
* <li>ViewExpiredException handling pour timeout session</li>
* <li>HTTPS obligatoire en production</li>
* <li>Content Security Policy headers</li>

View File

@@ -152,15 +152,6 @@ public class MenuBean implements Serializable {
// MEMBRE_ACTIF retiré intentionnellement pour raisons UX et RGPD
}
/**
* DEPRECATED: Utilisez isGestionMembresMenuVisible() ou isAnnuaireMembresVisible()
* @deprecated Remplacé par isGestionMembresMenuVisible() et isAnnuaireMembresVisible()
*/
@Deprecated
public boolean isMembresMenuVisible() {
return hasAnyRole("SUPER_ADMIN", "ADMIN_ORGANISATION", "SECRETAIRE", "MEMBRE_BUREAU", "MEMBRE_ACTIF");
}
/**
* Gestion Financière - Administration finances (trésorerie, budgets, comptabilité)
* Visible pour TRESORIER et ADMIN uniquement
@@ -199,33 +190,6 @@ public class MenuBean implements Serializable {
return hasAnyRole("SUPER_ADMIN", "ADMIN_ORGANISATION", "SECRETAIRE", "MEMBRE_BUREAU");
}
/**
* DEPRECATED: Utilisez isGestionFinancesMenuVisible() ou isMesFinancesMenuVisible()
* @deprecated Remplacé par isGestionFinancesMenuVisible() (admin) et isMesFinancesMenuVisible() (membre)
*/
@Deprecated
public boolean isFinancesMenuVisible() {
return hasAnyRole("SUPER_ADMIN", "ADMIN_ORGANISATION", "TRESORIER", "RESPONSABLE_CREDIT", "MEMBRE_BUREAU");
}
/**
* DEPRECATED: Utilisez isGestionAidesSocialesMenuVisible() ou isMesAidesSocialesMenuVisible()
* @deprecated Remplacé par isGestionAidesSocialesMenuVisible() (admin) et isMesAidesSocialesMenuVisible() (membre)
*/
@Deprecated
public boolean isAidesMenuVisible() {
return hasAnyRole("SUPER_ADMIN", "ADMIN_ORGANISATION", "RESPONSABLE_SOCIAL", "SECRETAIRE", "MEMBRE_BUREAU");
}
/**
* DEPRECATED: Utilisez isGestionEvenementsMenuVisible() ou isMesEvenementsMenuVisible()
* @deprecated Remplacé par isGestionEvenementsMenuVisible() (admin) et isMesEvenementsMenuVisible() (membre)
*/
@Deprecated
public boolean isEvenementsMenuVisible() {
return hasAnyRole("SUPER_ADMIN", "ADMIN_ORGANISATION", "RESPONSABLE_EVENEMENTS", "SECRETAIRE", "MEMBRE_BUREAU", "MEMBRE_ACTIF");
}
/**
* Communication - Visible pour admins, secrétaires, bureau
*/

View File

@@ -127,8 +127,8 @@ public class NavigationBean implements Serializable {
return "Tableau de Bord";
} else if (viewId.contains("membres")) {
return "Gestion des Membres";
} else if (viewId.contains("entites")) {
return "Gestion des Entités";
} else if (viewId.contains("organisation")) {
return "Gestion des Organisations";
} else if (viewId.contains("configuration")) {
return "Configuration";
} else if (viewId.contains("rapports")) {

View File

@@ -37,8 +37,8 @@ public class SuperAdminBean implements Serializable {
private static final Logger LOG = Logger.getLogger(SuperAdminBean.class);
// Constantes de navigation outcomes (WOU/DRY - réutilisables)
private static final String OUTCOME_ENTITE_NOUVELLE = "entiteNouvellePage";
private static final String OUTCOME_ENTITE_GESTION = "entiteGestionPage";
private static final String OUTCOME_ORGANISATION_NOUVELLE = "organisationNouvellePage";
private static final String OUTCOME_ORGANISATION_GESTION = "organisationGestionPage";
private static final String OUTCOME_SUPER_ADMIN_RAPPORTS = "superAdminRapportsPage";
private static final String OUTCOME_SUPER_ADMIN_CONFIGURATION = "superAdminConfigurationPage";
private static final String OUTCOME_SUPER_ADMIN_ALERTES = "superAdminAlertesPage";
@@ -431,12 +431,12 @@ public class SuperAdminBean implements Serializable {
}
// Actions (WOU/DRY - utilisation de navigation outcomes)
public String creerEntite() {
return OUTCOME_ENTITE_NOUVELLE + "?faces-redirect=true";
public String creerOrganisation() {
return OUTCOME_ORGANISATION_NOUVELLE + "?faces-redirect=true";
}
public String gererEntites() {
return OUTCOME_ENTITE_GESTION + "?faces-redirect=true";
public String gererOrganisations() {
return OUTCOME_ORGANISATION_GESTION + "?faces-redirect=true";
}
public String genererRapport() {

View File

@@ -546,16 +546,16 @@
</navigation-case>
<navigation-case>
<description>Page de création d'entité (Super Admin)</description>
<from-outcome>entiteNouvellePage</from-outcome>
<to-view-id>/pages/super-admin/entites/nouvelle.xhtml</to-view-id>
<description>Page de création d'organisation (Super Admin)</description>
<from-outcome>organisationNouvellePage</from-outcome>
<to-view-id>/pages/secure/organisation/nouvelle.xhtml</to-view-id>
<redirect />
</navigation-case>
<navigation-case>
<description>Page de gestion des entités (Super Admin)</description>
<from-outcome>entiteGestionPage</from-outcome>
<to-view-id>/pages/super-admin/entites/gestion.xhtml</to-view-id>
<description>Page de gestion des organisations (Super Admin)</description>
<from-outcome>organisationGestionPage</from-outcome>
<to-view-id>/pages/secure/organisation/liste.xhtml</to-view-id>
<redirect />
</navigation-case>
@@ -588,9 +588,9 @@
</navigation-case>
<navigation-case>
<description>Page de détails d'entité</description>
<from-outcome>entiteDetailsPage</from-outcome>
<to-view-id>/pages/super-admin/entites/details.xhtml</to-view-id>
<description>Page de détails d'organisation</description>
<from-outcome>organisationDetailsPage</from-outcome>
<to-view-id>/pages/secure/organisation/detail.xhtml</to-view-id>
<redirect />
</navigation-case>
@@ -602,16 +602,9 @@
</navigation-case>
<navigation-case>
<description>Page de configuration d'entité</description>
<from-outcome>entiteConfigurationPage</from-outcome>
<to-view-id>/pages/super-admin/entites/configuration.xhtml</to-view-id>
<redirect />
</navigation-case>
<navigation-case>
<description>Page de rapports d'entité</description>
<from-outcome>entiteRapportsPage</from-outcome>
<to-view-id>/pages/super-admin/entites/rapports.xhtml</to-view-id>
<description>Page de statistiques d'organisation</description>
<from-outcome>organisationStatistiquesPage</from-outcome>
<to-view-id>/pages/secure/organisation/statistiques.xhtml</to-view-id>
<redirect />
</navigation-case>

View File

@@ -32,7 +32,7 @@
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouvelle organisation" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="outcome" value="entiteNouvellePage" />
<ui:param name="outcome" value="organisationNouvellePage" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="mr-2" />
</ui:include>
@@ -67,7 +67,7 @@
<ui:param name="growthValue" value="#{superAdminBean.nouvellesEntites}" />
<ui:param name="growthLabel" value="nouvelles" />
<ui:param name="growthType" value="number" />
<ui:param name="noDataLabel" value="Aucune nouvelle entité ce mois" />
<ui:param name="noDataLabel" value="Aucune nouvelle organisation ce mois" />
<ui:param name="progressValue" value="#{superAdminBean.pourcentageOrganisations}" />
</ui:include>
@@ -103,18 +103,18 @@
<div class="grid">
<div class="col-12 md:col-6">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouvelle Entité" />
<ui:param name="value" value="Nouvelle Organisation" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="outcome" value="entiteNouvellePage" />
<ui:param name="outcome" value="organisationNouvellePage" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Gestion Entités" />
<ui:param name="value" value="Gestion Organisations" />
<ui:param name="icon" value="pi pi-building" />
<ui:param name="outcome" value="entiteGestionPage" />
<ui:param name="outcome" value="organisationGestionPage" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
</ui:include>
@@ -205,12 +205,12 @@
</div>
</div>
<!-- Top 5 Entités -->
<!-- Top 5 Organisations -->
<div class="col-12 lg:col-6">
<div class="card">
<h5>
<i class="pi pi-trophy text-yellow-500 mr-2"></i>
Top 5 Entités
Top 5 Organisations
</h5>
<ui:repeat value="#{superAdminBean.topEntites}" var="entite" varStatus="status">
<div class="flex align-items-center p-3 mb-2 border-round"
@@ -231,7 +231,7 @@
</ui:repeat>
<div class="text-center p-3" rendered="#{empty superAdminBean.topEntites}">
<i class="pi pi-info-circle text-300 text-2xl mb-2"></i>
<div class="text-600 text-sm">Aucune entité enregistrée</div>
<div class="text-600 text-sm">Aucune organisation enregistrée</div>
</div>
</div>
</div>
@@ -346,7 +346,7 @@
<div class="col-12 md:col-3">
<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 class="text-500">Revenu moyen / organisation</div>
</div>
</div>
</div>

View File

@@ -1,641 +0,0 @@
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/templates/main-template.xhtml">
<ui:define name="title">Gestion des Entités Enhanced - UnionFlow</ui:define>
<ui:define name="head">
<style>
.subscription-card {
transition: transform 0.2s ease;
}
.subscription-card:hover {
transform: translateY(-2px);
}
.quota-progress {
height: 6px;
border-radius: 3px;
overflow: hidden;
}
.quota-danger { background-color: #ef4444; }
.quota-warning { background-color: #f59e0b; }
.quota-success { background-color: #10b981; }
.expiration-alert { border-left: 4px solid #ef4444; }
.quota-alert { border-left: 4px solid #f59e0b; }
.forfait-starter { background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%); }
.forfait-standard { background: linear-gradient(135deg, #10b981 0%, #047857 100%); }
.forfait-premium { background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); }
.forfait-cristal { background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%); }
</style>
</ui:define>
<ui:define name="content">
<!-- En-tête avec actions -->>
<div class="grid">
<div class="col-12">
<div class="card">
<div class="flex align-items-center justify-content-between">
<div>
<h3 class="mb-2">
<i class="pi pi-building text-blue-500 mr-2"></i>
Gestion des Entités - Stratégie Volume
</h3>
<p class="text-600 m-0">Administration complète avec suivi des souscriptions et quotas</p>
</div>
<h:form id="formActionsEntete">
<div class="flex gap-2">
<p:commandButton value="Nouvelle entité"
icon="pi pi-plus"
styleClass="p-button-success"
onclick="PF('dlgNouvelleEntite').show();" />
<p:commandButton value="Gestion Quotas"
icon="pi pi-users"
styleClass="p-button-outlined p-button-warning"
action="#{entitesGestionBean.gererQuotas}" />
<p:commandButton value="Relances"
icon="pi pi-send"
styleClass="p-button-outlined p-button-info"
action="#{entitesGestionBean.envoyerRelancesSouscriptions}" />
<p:commandButton value="Exporter"
icon="pi pi-download"
styleClass="p-button-outlined p-button-secondary"
action="#{entitesGestionBean.exporterEntites}" />
</div>
</h:form>
</div>
</div>
</div>
</div>
<!-- Statistiques enrichies avec souscriptions -->>
<div class="grid">
<div class="col-12 md:col-3">
<div class="card subscription-card bg-blue-100 border-left-3 border-blue-500">
<div class="flex justify-content-between">
<div>
<div class="text-blue-900 font-bold text-2xl">#{entitesGestionBean.statistiques.totalEntites}</div>
<div class="text-blue-700 mb-2">Total Entités</div>
<div class="text-blue-600 text-sm">
<i class="pi pi-check-circle mr-1"></i>
#{entitesGestionBean.statistiques.entitesActives} actives
</div>
</div>
<div class="bg-blue-500 text-white border-round text-center"
style="width: 3rem; height: 3rem; line-height: 3rem;">
<i class="pi pi-building text-xl"></i>
</div>
</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="card subscription-card bg-green-100 border-left-3 border-green-500">
<div class="flex justify-content-between">
<div>
<div class="text-green-900 font-bold text-2xl">#{entitesGestionBean.statistiques.totalMembres}</div>
<div class="text-green-700 mb-2">Total Membres</div>
<div class="text-green-600 text-sm">
<i class="pi pi-trending-up mr-1"></i>
Moyenne: 146/entité
</div>
</div>
<div class="bg-green-500 text-white border-round text-center"
style="width: 3rem; height: 3rem; line-height: 3rem;">
<i class="pi pi-users text-xl"></i>
</div>
</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="card subscription-card bg-orange-100 border-left-3 border-orange-500">
<div class="flex justify-content-between">
<div>
<div class="text-orange-900 font-bold text-2xl">#{entitesGestionBean.statistiques.souscriptionsExpirantes}</div>
<div class="text-orange-700 mb-2">Expirations Proches</div>
<div class="text-orange-600 text-sm">
<i class="pi pi-clock mr-1"></i>
Sous 30 jours
</div>
</div>
<div class="bg-orange-500 text-white border-round text-center"
style="width: 3rem; height: 3rem; line-height: 3rem;">
<i class="pi pi-exclamation-triangle text-xl"></i>
</div>
</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="card subscription-card bg-purple-100 border-left-3 border-purple-500">
<div class="flex justify-content-between">
<div>
<div class="text-purple-900 font-bold text-2xl">#{entitesGestionBean.statistiques.entitesQuotaAtteint}</div>
<div class="text-purple-700 mb-2">Quotas Atteints</div>
<div class="text-purple-600 text-sm">
<i class="pi pi-info-circle mr-1"></i>
Nécessitent upgrade
</div>
</div>
<div class="bg-purple-500 text-white border-round text-center"
style="width: 3rem; height: 3rem; line-height: 3rem;">
<i class="pi pi-chart-pie text-xl"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Analyse des forfaits -->>
<div class="grid">
<div class="col-12 lg:col-8">
<div class="card">
<h5>Répartition par Forfait - Nouvelle Grille Tarifaire</h5>
<div class="grid">
<div class="col-6 md:col-3">
<div class="forfait-starter text-white p-3 border-round text-center">
<div class="font-bold text-2xl mb-1">44</div>
<div class="text-blue-100 text-sm mb-2">Starter</div>
<div class="text-blue-200 text-xs mb-1">2K FCFA/mois</div>
<div class="text-blue-200 text-xs">100 membres max</div>
</div>
</div>
<div class="col-6 md:col-3">
<div class="forfait-standard text-white p-3 border-round text-center">
<div class="font-bold text-2xl mb-1">60</div>
<div class="text-green-100 text-sm mb-2">Standard</div>
<div class="text-green-200 text-xs mb-1">3K FCFA/mois</div>
<div class="text-green-200 text-xs">200 membres max</div>
</div>
</div>
<div class="col-6 md:col-3">
<div class="forfait-premium text-white p-3 border-round text-center">
<div class="font-bold text-2xl mb-1">20</div>
<div class="text-orange-100 text-sm mb-2">Premium</div>
<div class="text-orange-200 text-xs mb-1">4K FCFA/mois</div>
<div class="text-orange-200 text-xs">500 membres max</div>
</div>
</div>
<div class="col-6 md:col-3">
<div class="forfait-cristal text-white p-3 border-round text-center">
<div class="font-bold text-2xl mb-1">3</div>
<div class="text-purple-100 text-sm mb-2">Cristal</div>
<div class="text-purple-200 text-xs mb-1">5K FCFA/mois</div>
<div class="text-purple-200 text-xs">2000 membres max</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="card">
<h5>Performance Commerciale</h5>
<div class="grid">
<div class="col-6">
<div class="text-center p-3 surface-100 border-round">
<div class="text-2xl font-bold text-green-500 mb-1">#{entitesGestionBean.statistiques.revenus}</div>
<div class="text-600 text-sm">Revenus Mensuels</div>
</div>
</div>
<div class="col-6">
<div class="text-center p-3 surface-100 border-round">
<div class="text-2xl font-bold text-blue-500 mb-1">#{entitesGestionBean.statistiques.tauxRenouvellementFormat}</div>
<div class="text-600 text-sm">Taux Renouvellement</div>
</div>
</div>
</div>
<div class="mt-3 p-3 surface-50 border-round">
<div class="text-900 font-medium mb-2">Forfait le plus populaire</div>
<div class="flex align-items-center">
<p:tag value="#{entitesGestionBean.statistiques.formulairePopulaire}" severity="success" />
<span class="text-600 text-sm ml-2">60 souscriptions</span>
</div>
</div>
</div>
</div>
</div>
<!-- Filtres enrichis -->>
<div class="card">
<h5>Filtres et Recherche Avancée</h5>
<h:form id="formFiltres">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel for="searchNom" value="Nom de l'entité" />
<p:inputText id="searchNom" value="#{entitesGestionBean.filtres.nom}"
placeholder="Rechercher par nom...">
<p:ajax event="keyup" update="dtEntites @(.stats-summary)" />
</p:inputText>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filterType" value="Type" />
<p:selectOneMenu id="filterType" value="#{entitesGestionBean.filtres.type}">
<f:selectItem itemLabel="Tous" itemValue="" />
<f:selectItem itemLabel="Association" itemValue="ASSOCIATION" />
<f:selectItem itemLabel="Club" itemValue="CLUB" />
<f:selectItem itemLabel="Groupe" itemValue="GROUPE" />
<f:selectItem itemLabel="Branche" itemValue="BRANCHE" />
<p:ajax update="dtEntites @(.stats-summary)" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filterStatut" value="Statut" />
<p:selectOneMenu id="filterStatut" value="#{entitesGestionBean.filtres.statut}">
<f:selectItem itemLabel="Tous" itemValue="" />
<f:selectItem itemLabel="Active" itemValue="ACTIVE" />
<f:selectItem itemLabel="Inactive" itemValue="INACTIVE" />
<f:selectItem itemLabel="Suspendue" itemValue="SUSPENDUE" />
<p:ajax update="dtEntites @(.stats-summary)" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filterRegion" value="Région" />
<p:selectOneMenu id="filterRegion" value="#{entitesGestionBean.filtres.region}">
<f:selectItem itemLabel="Toutes" itemValue="" />
<f:selectItem itemLabel="Région 1" itemValue="REGION_1" />
<f:selectItem itemLabel="Région 2" itemValue="REGION_2" />
<f:selectItem itemLabel="Région 3" itemValue="REGION_3" />
<p:ajax update="dtEntites @(.stats-summary)" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel value="Actions rapides" />
<div class="flex gap-2 mt-1">
<p:commandButton value="Rechercher"
icon="pi pi-search"
styleClass="p-button-primary p-button-sm"
action="#{entitesGestionBean.rechercher}"
update="dtEntites @(.stats-summary)" />
<p:commandButton value="Reset"
icon="pi pi-refresh"
styleClass="p-button-outlined p-button-secondary p-button-sm"
action="#{entitesGestionBean.reinitialiserFiltres}"
update="@form dtEntites @(.stats-summary)" />
</div>
</div>
</div>
</div>
<!-- Filtres avancés - Section extensible -->
<p:togglePanel id="filtresAvances" header="Filtres Avancés (Souscriptions &amp; Financier)"
styleClass="mt-3" collapsed="true">
<div class="grid mt-2">
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel for="filterForfait" value="Forfait" />
<p:selectOneMenu id="filterForfait" value="#{entitesGestionBean.filtres.forfait}">
<f:selectItem itemLabel="Tous les forfaits" itemValue="" />
<f:selectItem itemLabel="Starter (2K)" itemValue="Starter" />
<f:selectItem itemLabel="Standard (3K)" itemValue="Standard" />
<f:selectItem itemLabel="Premium (4K)" itemValue="Premium" />
<f:selectItem itemLabel="Cristal (5K)" itemValue="Cristal" />
<p:ajax update="dtEntites @(.stats-summary)" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel for="filterQuota" value="Alerte Quota" />
<p:selectOneMenu id="filterQuota" value="#{entitesGestionBean.filtres.alerteQuota}">
<f:selectItem itemLabel="Toutes" itemValue="" />
<f:selectItem itemLabel="Quota proche/atteint" itemValue="OUI" />
<f:selectItem itemLabel="Quota normal" itemValue="NON" />
<p:ajax update="dtEntites @(.stats-summary)" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel for="filterExpiration" value="Expiration Proche" />
<p:selectOneMenu id="filterExpiration" value="#{entitesGestionBean.filtres.alerteExpiration}">
<f:selectItem itemLabel="Toutes" itemValue="" />
<f:selectItem itemLabel="Expire sous 30j" itemValue="OUI" />
<f:selectItem itemLabel="Valide >30j" itemValue="NON" />
<p:ajax update="dtEntites @(.stats-summary)" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel for="filterStatutSouscription" value="Statut Souscription" />
<p:selectOneMenu id="filterStatutSouscription" value="#{entitesGestionBean.filtres.statutSouscription}">
<f:selectItem itemLabel="Tous" itemValue="" />
<f:selectItem itemLabel="Active" itemValue="ACTIVE" />
<f:selectItem itemLabel="Expirée" itemValue="EXPIRED" />
<f:selectItem itemLabel="Suspendue" itemValue="SUSPENDED" />
<p:ajax update="dtEntites @(.stats-summary)" />
</p:selectOneMenu>
</div>
</div>
</div>
</p:togglePanel>
</div>
</div>
</h:form>
</div>
<!-- Table enrichie des entités -->>
<div class="card">
<div class="flex align-items-center justify-content-between mb-3">
<h5 class="m-0">Entités avec Souscriptions (#{entitesGestionBean.entitesFiltrees.size()})</h5>
<div class="flex align-items-center gap-2">
<h:form id="formActionsGroupees">
<p:commandButton value="Actions groupées"
icon="pi pi-cog"
styleClass="p-button-outlined p-button-warning"
onclick="PF('dlgActionsGroupees').show();"
disabled="#{empty entitesGestionBean.entitesSelectionnees}" />
</h:form>
<span class="text-600 text-sm stats-summary">
#{entitesGestionBean.entitesFiltrees.size()} sur #{entitesGestionBean.toutesLesEntites.size()} entités
</span>
</div>
</div>
<p:dataTable id="dtEntites"
value="#{entitesGestionBean.entitesFiltrees}"
var="entite"
selection="#{entitesGestionBean.entitesSelectionnees}"
rowKey="#{entite.id}"
paginator="true"
rows="15"
paginatorPosition="both"
sortMode="single"
styleClass="p-datatable-sm"
emptyMessage="Aucune entité trouvée">
<p:column selectionMode="multiple" width="40" />
<p:column headerText="Entité" sortBy="#{entite.nom}" width="220">
<div class="flex align-items-center">
<div class="border-circle bg-primary text-white flex align-items-center justify-content-center mr-3"
style="width: 32px; height: 32px;">
<i class="pi #{entite.typeIcon}"></i>
</div>
<div>
<div class="text-900 font-medium">#{entite.nom}</div>
<div class="text-600 text-sm">#{entite.codeEntite}</div>
</div>
</div>
</p:column>
<p:column headerText="Forfait" sortBy="#{entite.forfaitSouscrit}" width="120">
<div class="text-center">
<p:tag value="#{entite.forfaitSouscrit}"
severity="#{entite.forfaitCouleur}"
icon="pi #{entite.forfaitIcone}" />
<div class="text-600 text-xs mt-1">#{entite.montantMensuel}</div>
</div>
</p:column>
<p:column headerText="Quota Membres" sortBy="#{entite.membresUtilises}" width="140">
<div class="text-center">
<div class="text-900 font-bold mb-1">#{entite.membresUtilises}/#{entite.membresQuota}</div>
<div class="quota-progress #{entite.quotaAtteint ? 'quota-danger' : entite.quotaProche ? 'quota-warning' : 'quota-success'}">
<div style="width: #{entite.pourcentageUtilisationQuota}%; height: 100%; background: rgba(255,255,255,0.8);"></div>
</div>
<div class="text-600 text-xs mt-1">#{entite.pourcentageUtilisationQuota}%</div>
</div>
</p:column>
<p:column headerText="Expiration" sortBy="#{entite.dateExpirationSouscription}" width="120">
<div class="text-center">
<div class="text-900 text-sm mb-1">
#{entite.dateExpirationSouscription != null ? entite.dateExpirationSouscription.format(java.time.format.DateTimeFormatter.ofPattern('dd/MM/yyyy')) : 'N/A'}
</div>
<div class="text-#{entite.expirationProche ? 'red' : 'green'}-600 text-xs">
<i class="pi pi-clock mr-1"></i>
#{entite.joursAvantExpiration} jours
</div>
</div>
</p:column>
<p:column headerText="Région" sortBy="#{entite.region}" width="100">
<span class="text-900">#{entite.region}</span>
</p:column>
<p:column headerText="Statut" sortBy="#{entite.statut}" width="100">
<p:tag value="#{entite.statut}"
severity="#{entite.statutSeverity}"
icon="pi #{entite.statutIcon}" />
</p:column>
<p:column headerText="Actions" width="150">
<h:form id="formActions#{entite.id}">
<div class="flex gap-1">
<p:commandButton icon="pi pi-eye"
styleClass="p-button-rounded p-button-text p-button-info"
action="#{entitesGestionBean.voirEntite(entite)}"
title="Voir détails" />
<p:commandButton icon="pi pi-refresh"
styleClass="p-button-rounded p-button-text p-button-success"
onclick="PF('dlgRenouvelerSouscription').show();"
title="Renouveler"
rendered="#{entite.expirationProche}">
<f:setPropertyActionListener target="#{entitesGestionBean.entiteSelectionne}" value="#{entite}" />
</p:commandButton>
<p:commandButton icon="pi pi-arrow-up"
styleClass="p-button-rounded p-button-text p-button-warning"
onclick="PF('dlgUpgraderForfait').show();"
title="Upgrader"
rendered="#{entite.quotaProche}">
<f:setPropertyActionListener target="#{entitesGestionBean.entiteSelectionne}" value="#{entite}" />
</p:commandButton>
<p:commandButton icon="pi pi-cog"
styleClass="p-button-rounded p-button-text p-button-secondary"
onclick="PF('dlgActionsEntite').show();"
title="Actions">
<f:setPropertyActionListener target="#{entitesGestionBean.entiteSelectionne}" value="#{entite}" />
</p:commandButton>
</div>
</h:form>
</p:column>
</p:dataTable>
</div>
<!-- Dialog Renouveler Souscription -->>
<p:dialog header="Renouveler la Souscription" widgetVar="dlgRenouvelerSouscription" modal="true" width="500">
<h:form id="formRenouvelerSouscription">
<div class="ui-fluid">
<div class="text-center mb-4">
<i class="pi pi-refresh text-green-500 text-4xl mb-2"></i>
<h4>Confirmer le renouvellement</h4>
<p class="text-600">
Entité: <strong>#{entitesGestionBean.entiteSelectionne.nom}</strong><br/>
Forfait: <strong>#{entitesGestionBean.entiteSelectionne.forfaitSouscrit}</strong><br/>
Montant: <strong>#{entitesGestionBean.entiteSelectionne.montantMensuel}</strong>
</p>
</div>
<div class="flex gap-2 justify-content-center">
<p:commandButton value="Confirmer" icon="pi pi-check"
styleClass="p-button-success"
action="#{entitesGestionBean.renouvelerSouscription}"
update="dtEntites @(.stats-summary)"
oncomplete="PF('dlgRenouvelerSouscription').hide();" />
<p:commandButton value="Annuler" icon="pi pi-times"
styleClass="p-button-secondary"
onclick="PF('dlgRenouvelerSouscription').hide();" type="button" />
</div>
</div>
</h:form>
</p:dialog>
<!-- Dialog Upgrader Forfait -->>
<p:dialog header="Upgrader le Forfait" widgetVar="dlgUpgraderForfait" modal="true" width="500">
<h:form id="formUpgraderForfait">
<div class="ui-fluid">
<div class="text-center mb-4">
<i class="pi pi-arrow-up text-orange-500 text-4xl mb-2"></i>
<h4>Upgrader le forfait</h4>
<p class="text-600">
Entité: <strong>#{entitesGestionBean.entiteSelectionne.nom}</strong><br/>
Forfait actuel: <strong>#{entitesGestionBean.entiteSelectionne.forfaitSouscrit}</strong><br/>
Quota utilisé: <strong>#{entitesGestionBean.entiteSelectionne.pourcentageUtilisationQuota}%</strong>
</p>
</div>
<div class="flex gap-2 justify-content-center">
<p:commandButton value="Upgrader" icon="pi pi-arrow-up"
styleClass="p-button-warning"
action="#{entitesGestionBean.upgraderForfait}"
update="dtEntites @(.stats-summary)"
oncomplete="PF('dlgUpgraderForfait').hide();" />
<p:commandButton value="Annuler" icon="pi pi-times"
styleClass="p-button-secondary"
onclick="PF('dlgUpgraderForfait').hide();" type="button" />
</div>
</div>
</h:form>
</p:dialog>
<!-- Dialog Actions Groupées -->>
<p:dialog header="Actions Groupées" widgetVar="dlgActionsGroupees" modal="true" width="600">
<h:form id="formActionsGroupees">
<div class="ui-fluid">
<div class="text-center mb-4">
<i class="pi pi-cog text-orange-500 text-4xl mb-2"></i>
<h4>Actions sur #{entitesGestionBean.entitesSelectionnees.size()} entités sélectionnées</h4>
</div>
<div class="grid">
<div class="col-12 md:col-6">
<h6>Actions de Souscription</h6>
<p:commandButton value="Renouveler toutes"
icon="pi pi-refresh"
styleClass="p-button-success w-full mb-2"
action="#{entitesGestionBean.renouvelerSouscriptionsGroupees}"
update="dtEntites @(.stats-summary)"
oncomplete="PF('dlgActionsGroupees').hide();"
onclick="return confirm('Renouveler les souscriptions de toutes les entités sélectionnées ?');" />
<p:commandButton value="Envoyer relances"
icon="pi pi-send"
styleClass="p-button-info w-full mb-2"
action="#{entitesGestionBean.envoyerRelancesSouscriptions}"
oncomplete="PF('dlgActionsGroupees').hide();" />
<p:commandButton value="Proposer upgrade"
icon="pi pi-arrow-up"
styleClass="p-button-warning w-full mb-2"
action="#{entitesGestionBean.proposerUpgradeGroupees}"
oncomplete="PF('dlgActionsGroupees').hide();" />
</div>
<div class="col-12 md:col-6">
<h6>Actions Administratives</h6>
<p:commandButton value="Suspendre toutes"
icon="pi pi-ban"
styleClass="p-button-danger w-full mb-2"
action="#{entitesGestionBean.suspendreEntitesGroupees}"
update="dtEntites @(.stats-summary)"
oncomplete="PF('dlgActionsGroupees').hide();"
onclick="return confirm('ATTENTION: Suspendre toutes les entités sélectionnées ?');" />
<p:commandButton value="Réactiver toutes"
icon="pi pi-check"
styleClass="p-button-success w-full mb-2"
action="#{entitesGestionBean.reactiverEntitesGroupees}"
update="dtEntites @(.stats-summary)"
oncomplete="PF('dlgActionsGroupees').hide();" />
<p:commandButton value="Exporter sélection"
icon="pi pi-download"
styleClass="p-button-secondary w-full mb-2"
action="#{entitesGestionBean.exporterEntites}" />
</div>
</div>
<div class="flex justify-content-end mt-4 pt-3 border-top-1 surface-border">
<p:commandButton value="Fermer" icon="pi pi-times"
styleClass="p-button-secondary"
onclick="PF('dlgActionsGroupees').hide();" type="button" />
</div>
</div>
</h:form>
</p:dialog>
<!-- Dialog Actions Entité (conservé de l'original) -->>
<p:dialog header="Actions sur l'Entité" widgetVar="dlgActionsEntite" modal="true" width="400">
<h:form id="formActionsEntite">
<div class="grid">
<div class="col-12">
<p:commandButton value="Gérer les membres"
icon="pi pi-users"
styleClass="p-button-outlined p-button-info w-full mb-2"
action="#{entitesGestionBean.gererMembres}" />
<p:commandButton value="Configuration"
icon="pi pi-cog"
styleClass="p-button-outlined p-button-warning w-full mb-2"
action="#{entitesGestionBean.configurerEntite}" />
<p:commandButton value="Rapports"
icon="pi pi-chart-bar"
styleClass="p-button-outlined p-button-secondary w-full mb-2"
action="#{entitesGestionBean.voirRapports}" />
<p:commandButton value="Suspendre"
icon="pi pi-ban"
styleClass="p-button-outlined p-button-danger w-full mb-2"
action="#{entitesGestionBean.suspendreEntite}"
onclick="return confirm('Êtes-vous sûr de vouloir suspendre cette entité ?');"
rendered="#{entitesGestionBean.entiteSelectionne.statut == 'ACTIVE'}" />
<p:commandButton value="Réactiver"
icon="pi pi-check"
styleClass="p-button-outlined p-button-success w-full mb-2"
action="#{entitesGestionBean.reactiverEntite}"
rendered="#{entitesGestionBean.entiteSelectionne.statut == 'SUSPENDUE'}" />
</div>
</div>
<div class="flex justify-content-end mt-3">
<p:commandButton value="Fermer" icon="pi pi-times"
styleClass="p-button-secondary"
onclick="PF('dlgActionsEntite').hide();" type="button" />
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -1,426 +0,0 @@
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/templates/main-template.xhtml">
<ui:define name="title">Gestion des Entités - UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête principal avec disposition Freya stricte -->
<div class="card">
<div class="formgrid grid">
<div class="field col-12 lg:col-8">
<h2 class="text-primary font-bold mb-2">
<i class="pi pi-building text-blue-500 mr-2"></i>
Gestion des Entités
</h2>
<p class="text-600 mt-0">
Administration complète des clubs et entités Lions •
<span class="font-semibold">#{entitesGestionBean.statistiques.totalEntites} entités</span>
<span class="font-semibold text-green-600">#{entitesGestionBean.statistiques.entitesActives} actives</span>
</p>
</div>
<div class="field col-12 lg:col-4 text-right">
<h:form id="formActionsEntete">
<p:commandButton icon="pi pi-plus"
title="Nouvelle entité"
styleClass="ui-button-success ui-button-sm mr-3"
onclick="PF('dlgNouvelleEntite').show();" />
<p:commandButton icon="pi pi-upload"
title="Import Excel"
styleClass="ui-button-info ui-button-outlined ui-button-sm mr-3"
onclick="PF('dlgImportEntites').show();" />
<p:commandButton icon="pi pi-download"
title="Exporter"
styleClass="ui-button-secondary ui-button-outlined ui-button-sm"
action="#{entitesGestionBean.exporterEntites}" />
</h:form>
</div>
</div>
</div>
<!-- KPIs avec grille Freya stricte -->
<div class="formgrid grid">
<!-- KPI 1: Total Entités -->
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Total Entités" />
<ui:param name="value" value="#{entitesGestionBean.statistiques.totalEntites}" />
<ui:param name="icon" value="pi-building" />
<ui:param name="iconColor" value="blue-600" />
<ui:param name="growthValue" value="8" />
<ui:param name="growthLabel" value="ce mois" />
<ui:param name="growthType" value="number" />
<ui:param name="showProgress" value="false" />
</ui:include>
<!-- KPI 2: Entités Actives -->
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Entités Actives" />
<ui:param name="value" value="#{entitesGestionBean.statistiques.entitesActives}" />
<ui:param name="icon" value="pi-check" />
<ui:param name="iconColor" value="green-600" />
<ui:param name="progressValue" value="92" />
<ui:param name="noDataLabel" value="92% d'activité" />
<ui:param name="showGrowth" value="false" />
</ui:include>
<!-- KPI 3: Total Membres -->
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Total Membres" />
<ui:param name="value" value="#{entitesGestionBean.statistiques.totalMembres}" />
<ui:param name="icon" value="pi-users" />
<ui:param name="iconColor" value="orange-600" />
<ui:param name="statusIcon" value="pi-info-circle" />
<ui:param name="statusLabel" value="Moyenne" />
<ui:param name="statusValue" value="#{entitesGestionBean.statistiques.moyenneMembresParEntite}/entité" />
<ui:param name="showProgress" value="false" />
</ui:include>
<!-- KPI 4: Revenus Totaux -->
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Revenus Totaux" />
<ui:param name="value" value="#{entitesGestionBean.statistiques.revenus}" />
<ui:param name="icon" value="pi-dollar" />
<ui:param name="iconColor" value="purple-600" />
<ui:param name="growthValue" value="15" />
<ui:param name="growthLabel" value="vs année dernière" />
<ui:param name="showProgress" value="false" />
</ui:include>
</div>
<!-- Section Filtres avec structure Freya -->
<div class="card">
<h5 class="mb-3">
<i class="pi pi-filter text-blue-500 mr-2"></i>
Filtres et Recherche
</h5>
<h:form id="formFiltres">
<div class="formgrid grid">
<div class="field col-12 md:col-6 lg:col-3">
<label for="searchNom" class="block text-900 font-medium mb-2">Nom de l'entité</label>
<span class="p-input-icon-left w-full">
<i class="pi pi-search"></i>
<p:inputText id="searchNom"
value="#{entitesGestionBean.filtres.nom}"
placeholder="Rechercher par nom..."
styleClass="w-full">
<p:ajax event="keyup" delay="300"
update=":formTableEntites:dtEntites" />
</p:inputText>
</span>
</div>
<div class="field col-12 md:col-6 lg:col-3">
<label for="filterType" class="block text-900 font-medium mb-2">Type d'entité</label>
<p:selectOneMenu id="filterType"
value="#{entitesGestionBean.filtres.type}"
styleClass="w-full">
<f:selectItems value="#{entitesGestionBean.typesSelectItems}" />
<p:ajax update=":formTableEntites:dtEntites" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-6 lg:col-3">
<label for="filterStatut" class="block text-900 font-medium mb-2">Statut</label>
<p:selectOneMenu id="filterStatut"
value="#{entitesGestionBean.filtres.statut}"
styleClass="w-full">
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
<f:selectItem itemLabel="Active" itemValue="ACTIVE" />
<f:selectItem itemLabel="Inactive" itemValue="INACTIVE" />
<f:selectItem itemLabel="Suspendue" itemValue="SUSPENDUE" />
<p:ajax update=":formTableEntites:dtEntites" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-6 lg:col-3">
<label for="filterRegion" class="block text-900 font-medium mb-2">Région</label>
<p:selectOneMenu id="filterRegion"
value="#{entitesGestionBean.filtres.region}"
styleClass="w-full">
<f:selectItems value="#{entitesGestionBean.regionsDisponibles}" />
<p:ajax update=":formTableEntites:dtEntites" />
</p:selectOneMenu>
</div>
</div>
<div class="flex justify-content-end mt-3">
<p:commandButton value="Réinitialiser"
icon="pi pi-refresh"
styleClass="ui-button-outlined ui-button-secondary ui-button-sm"
action="#{entitesGestionBean.reinitialiserFiltres}"
update="@form :formTableEntites:dtEntites" />
</div>
</h:form>
</div>
<!-- Table des Entités avec structure Freya -->
<div class="card">
<h:form id="formTableEntites">
<div class="flex align-items-center justify-content-between mb-3">
<h5 class="m-0">
<i class="pi pi-list text-primary mr-2"></i>
Liste des Entités
</h5>
<div>
<p:commandButton value="Actions groupées"
icon="pi pi-bars"
styleClass="ui-button-warning ui-button-sm mr-2"
onclick="PF('dlgActionsGroupees').show();"
disabled="#{empty entitesGestionBean.entitesSelectionnees}" />
<p:commandButton value="Export Excel"
icon="pi pi-file-excel"
styleClass="ui-button-success ui-button-outlined ui-button-sm"
action="#{entitesGestionBean.exporterExcel}" />
</div>
</div>
<p:dataTable id="dtEntites"
value="#{entitesGestionBean.entitesFiltrees}"
var="entite"
selection="#{entitesGestionBean.entitesSelectionnees}"
rowKey="#{entite.id}"
paginator="true"
rows="20"
paginatorPosition="bottom"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="10,20,50,100"
currentPageReportTemplate="Affichage {startRecord}-{endRecord} sur {totalRecords} entités"
styleClass="p-datatable-sm p-datatable-gridlines p-datatable-striped"
emptyMessage="Aucune entité trouvée">
<p:column selectionMode="multiple" style="width:3rem" exportable="false"/>
<p:column headerText="Entité" sortBy="#{entite.nom}" filterBy="#{entite.nom}">
<div class="flex align-items-center">
<div class="flex align-items-center justify-content-center bg-primary-100 border-circle mr-2"
style="width: 2rem; height: 2rem;">
<i class="pi #{entite.typeIcon} text-primary-600"></i>
</div>
<div>
<div class="text-900 font-medium">#{entite.nom}</div>
<div class="text-500 text-xs">#{entite.codeEntite}</div>
</div>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{entite.type}" filterBy="#{entite.type}" style="width:8rem">
<p:tag value="#{entite.typeLibelle}"
severity="#{entite.typeSeverity}"
icon="pi #{entite.typeIcon}"
styleClass="text-xs" />
</p:column>
<p:column headerText="Région" sortBy="#{entite.region}" style="width:8rem">
<span class="text-900 font-medium">#{entite.region}</span>
</p:column>
<p:column headerText="Membres" sortBy="#{entite.nombreMembres}" style="width:6rem; text-align:center">
<div class="text-center">
<div class="text-900 font-bold">#{entite.nombreMembres}</div>
<div class="text-500 text-xs">membres</div>
</div>
</p:column>
<p:column headerText="Administrateur">
<div class="flex align-items-center" rendered="#{entite.administrateur != null}">
<div class="bg-300 border-circle mr-2" style="width: 1.5rem; height: 1.5rem;"></div>
<div>
<div class="text-900 text-sm">#{entite.administrateur.nomComplet}</div>
<div class="text-500 text-xs">#{entite.administrateur.email}</div>
</div>
</div>
<span class="text-400 text-xs" rendered="#{entite.administrateur == null}">
Aucun administrateur
</span>
</p:column>
<p:column headerText="Dernière activité" sortBy="#{entite.derniereActivite}" style="width:10rem">
<div class="text-900 text-sm">#{entite.derniereActiviteFormatee}</div>
<div class="text-500 text-xs">#{entite.derniereActiviteRelative}</div>
</p:column>
<p:column headerText="Statut" sortBy="#{entite.statut}" filterBy="#{entite.statut}" style="width:7rem">
<p:tag value="#{entite.statut}"
severity="#{entite.statutSeverity}"
icon="pi #{entite.statutIcon}"
styleClass="text-xs w-full" />
</p:column>
<p:column headerText="Actions" style="width:8rem" exportable="false">
<div class="flex gap-1">
<p:button icon="pi pi-eye"
title="Voir détails"
styleClass="ui-button-rounded ui-button-text ui-button-info ui-button-sm"
href="/pages/secure/organisation/detail.xhtml?id=#{entite.id}" />
<p:button icon="pi pi-pencil"
styleClass="ui-button-rounded ui-button-text ui-button-warning ui-button-sm"
title="Modifier"
href="/pages/secure/organisation/detail.xhtml?id=#{entite.id}&amp;mode=edit" />
<p:commandButton icon="pi pi-cog"
styleClass="ui-button-rounded ui-button-text ui-button-secondary ui-button-sm"
title="Actions"
update=":formActionsEntite"
oncomplete="PF('dlgActionsEntite').show();">
<f:setPropertyActionListener target="#{entitesGestionBean.entiteSelectionne}" value="#{entite}" />
</p:commandButton>
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
</div>
<!-- Dialogs avec structure Freya -->
<!-- Dialog Nouvelle Entité -->
<p:dialog header="Créer une Nouvelle Entité"
widgetVar="dlgNouvelleEntite"
modal="true"
width="700"
height="auto"
resizable="false">
<h:form id="formNouvelleEntite">
<div class="ui-fluid formgrid grid">
<div class="field col-12 md:col-6">
<label for="newNom" class="block text-900 font-medium mb-2">Nom de l'entité *</label>
<p:inputText id="newNom"
value="#{entitesGestionBean.nouvelleEntite.nom}"
required="true"
placeholder="Ex: Lions Club Dakar Centre" />
</div>
<div class="field col-12 md:col-6">
<label for="newType" class="block text-900 font-medium mb-2">Type d'entité *</label>
<p:selectOneMenu id="newType"
value="#{entitesGestionBean.nouvelleEntite.type}"
required="true"
requiredMessage="Le type d'entité est requis.">
<f:selectItems value="#{entitesGestionBean.typesSelectItemsForForm}" />
</p:selectOneMenu>
<p:message for="newType" />
</div>
<div class="field col-12 md:col-6">
<label for="newRegion" class="block text-900 font-medium mb-2">Région</label>
<p:inputText id="newRegion"
value="#{entitesGestionBean.nouvelleEntite.region}"
placeholder="Ex: Lagunes, Dakar, Abidjan..."
maxlength="100" />
</div>
<div class="field col-12 md:col-6">
<label for="newTelephone" class="block text-900 font-medium mb-2">Téléphone</label>
<p:inputText id="newTelephone"
value="#{entitesGestionBean.nouvelleEntite.telephone}"
placeholder="77 123 45 67" />
</div>
<div class="field col-12">
<label for="newEmail" class="block text-900 font-medium mb-2">Email</label>
<p:inputText id="newEmail"
value="#{entitesGestionBean.nouvelleEntite.email}"
placeholder="contact@lionsclub-dakar.sn" />
</div>
<div class="field col-12">
<label for="newAdresse" class="block text-900 font-medium mb-2">Adresse</label>
<p:inputTextarea id="newAdresse"
value="#{entitesGestionBean.nouvelleEntite.adresse}"
rows="2"
placeholder="Adresse complète de l'entité..." />
</div>
<div class="field col-12">
<label for="newDescription" class="block text-900 font-medium mb-2">Description</label>
<p:inputTextarea id="newDescription"
value="#{entitesGestionBean.nouvelleEntite.description}"
rows="3"
placeholder="Description de l'entité..." />
</div>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<p:commandButton value="Annuler"
icon="pi pi-times"
styleClass="ui-button-secondary ui-button-outlined ui-button-sm"
onclick="PF('dlgNouvelleEntite').hide();"
type="button" />
<p:commandButton value="Créer l'entité"
icon="pi pi-check"
styleClass="ui-button-success ui-button-sm"
action="#{entitesGestionBean.creerEntite}"
update="@form :formTableEntites:dtEntites"
oncomplete="if(!args.validationFailed) PF('dlgNouvelleEntite').hide();" />
</div>
</h:form>
</p:dialog>
<!-- Dialog Actions Entité -->
<p:dialog header="Actions sur l'Entité"
widgetVar="dlgActionsEntite"
modal="true"
width="400"
height="auto"
resizable="false">
<h:form id="formActionsEntite">
<div class="surface-50 border-round-lg p-3 mb-3">
<div class="text-500 text-sm mb-1">Entité sélectionnée</div>
<div class="text-900 font-bold">#{entitesGestionBean.entiteSelectionne.nom}</div>
<div class="text-500 text-sm">#{entitesGestionBean.entiteSelectionne.codeEntite}</div>
</div>
<div class="flex flex-column gap-2">
<p:commandButton value="Gérer les membres"
icon="pi pi-users"
styleClass="ui-button-info ui-button-outlined ui-button-sm w-full"
action="#{entitesGestionBean.gererMembres}"
ajax="false" />
<p:commandButton value="Voir / Configurer"
icon="pi pi-eye"
styleClass="ui-button-warning ui-button-outlined ui-button-sm w-full"
action="#{entitesGestionBean.configurerEntite}"
ajax="false" />
<p:commandButton value="Rapports &amp; Stats"
icon="pi pi-chart-bar"
styleClass="ui-button-secondary ui-button-outlined ui-button-sm w-full"
action="#{entitesGestionBean.voirRapports}"
ajax="false" />
<p:commandButton value="Suspendre"
icon="pi pi-ban"
styleClass="ui-button-danger ui-button-outlined ui-button-sm w-full"
action="#{entitesGestionBean.suspendreEntite}"
update=":formTableEntites:dtEntites :formActionsEntite"
oncomplete="PF('dlgActionsEntite').hide();"
onclick="return confirm('Suspendre cette entité ?');"
rendered="#{entitesGestionBean.entiteSelectionne.statut == 'ACTIVE'}" />
<p:commandButton value="Réactiver"
icon="pi pi-check"
styleClass="ui-button-success ui-button-outlined ui-button-sm w-full"
action="#{entitesGestionBean.reactiverEntite}"
update=":formTableEntites:dtEntites :formActionsEntite"
oncomplete="PF('dlgActionsEntite').hide();"
rendered="#{entitesGestionBean.entiteSelectionne.statut == 'SUSPENDUE'}" />
<hr class="surface-border" />
<p:commandButton value="Supprimer définitivement"
icon="pi pi-trash"
styleClass="ui-button-danger ui-button-sm w-full"
action="#{entitesGestionBean.supprimerEntite}"
update=":formTableEntites:dtEntites"
oncomplete="PF('dlgActionsEntite').hide();"
onclick="return confirm('ATTENTION : action irréversible. Confirmer la suppression ?');" />
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -1,223 +0,0 @@
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
template="/templates/main-template.xhtml">
<ui:define name="title">Gestion des Organisations</ui:define>
<ui:define name="content">
<h:form id="formOrgs">
<p:messages id="messages" showDetail="true" closable="true" />
<div class="card mb-3">
<div class="flex justify-content-between align-items-center">
<div>
<h5 class="mb-1">Organisations</h5>
<span class="text-600">
CRUD complet des organisations. Respect DRY/WOU: composants réutilisés et simplicité.
</span>
</div>
<div>
<p:commandButton value="Nouvelle organisation"
icon="pi pi-plus"
styleClass="ui-button-success"
actionListener="#{organisationsBean.preparerNouvelleOrganisation}"
update=":formOrgs:dlgCreate"
oncomplete="PF('dlgCreate').show();" />
<p:commandButton value="Rafraîchir"
icon="pi pi-refresh"
styleClass="ui-button-secondary ml-2"
actionListener="#{organisationsBean.recharger}"
update=":formOrgs:dtOrgs :formOrgs:stats :formOrgs:messages" />
</div>
</div>
</div>
<p:outputPanel id="stats" styleClass="grid mb-3">
<div class="col-12 md:col-4">
<p:card>
<f:facet name="title">Total</f:facet>
<h:outputText value="#{organisationsBean.totalOrganisations}" />
</p:card>
</div>
<div class="col-12 md:col-4">
<p:card>
<f:facet name="title">Actives</f:facet>
<h:outputText value="#{organisationsBean.organisationsActives}" />
</p:card>
</div>
<div class="col-12 md:col-4">
<p:card>
<f:facet name="title">Inactives</f:facet>
<h:outputText value="#{organisationsBean.organisationsInactives}" />
</p:card>
</div>
</p:outputPanel>
<div class="card">
<div class="grid mb-3 p-3">
<div class="col-12 md:col-4">
<p:inputText placeholder="Recherche (nom, ville, description)"
value="#{organisationsBean.rechercheGlobale}">
<p:ajax event="keyup" update=":formOrgs:dtOrgs" listener="#{organisationsBean.appliquerFiltres}" />
</p:inputText>
</div>
<div class="col-12 md:col-3">
<p:selectOneMenu value="#{organisationsBean.filtreStatut}">
<f:selectItems value="#{organisationsBean.statutsSelectItems}" />
<p:ajax update=":formOrgs:dtOrgs" listener="#{organisationsBean.appliquerFiltres}" />
</p:selectOneMenu>
</div>
<div class="col-12 md:col-3">
<p:selectOneMenu value="#{organisationsBean.filtreType}">
<f:selectItems value="#{organisationsBean.typesSelectItems}" />
<p:ajax update=":formOrgs:dtOrgs" listener="#{organisationsBean.appliquerFiltres}" />
</p:selectOneMenu>
</div>
<div class="col-12 md:col-2 text-right">
<p:commandButton value="Réinitialiser"
icon="pi pi-filter-slash"
styleClass="ui-button-secondary"
actionListener="#{organisationsBean.reinitialiserFiltres}"
update=":formOrgs:dtOrgs :formOrgs:filters" />
</div>
</div>
<p:dataTable id="dtOrgs"
value="#{organisationsBean.organisationsFiltrees}"
var="org"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50"
paginatorPosition="bottom"
emptyMessage="Aucune organisation trouvée">
<p:column headerText="Nom" sortBy="#{org.nom}">
<h:outputText value="#{org.nom}" />
</p:column>
<p:column headerText="Type" sortBy="#{org.typeAssociation}" style="width: 200px;">
<p:tag value="#{org.typeLibelle}" severity="info" />
</p:column>
<p:column headerText="Statut" style="width: 140px; text-align: center;">
<p:tag value="#{org.statutLibelle}" severity="#{org.statutSeverity}" />
</p:column>
<p:column headerText="Localisation" sortBy="#{org.ville}">
<h:outputText value="#{org.ville}" />
<h:outputText value=", " rendered="#{not empty org.ville and not empty org.region}" />
<h:outputText value="#{org.region}" />
</p:column>
<p:column headerText="Actions" style="width: 220px; text-align: center;">
<p:commandButton icon="pi pi-pencil"
title="Modifier"
styleClass="ui-button-rounded ui-button-warning mr-2"
actionListener="#{organisationsBean.setOrganisationSelectionnee(org)}"
update=":formOrgs:dlgEdit"
oncomplete="PF('dlgEdit').show();" />
<p:commandButton icon="#{organisationsBean.estActive(org) ? 'pi pi-ban' : 'pi pi-check'}"
title="#{organisationsBean.estActive(org) ? 'Désactiver' : 'Activer'}"
styleClass="ui-button-rounded #{organisationsBean.estActive(org) ? 'ui-button-secondary' : 'ui-button-success'} mr-2"
actionListener="#{organisationsBean.preparerBasculerStatut(org)}"
update=":formOrgs:dlgConfirmStatut"
oncomplete="PF('dlgConfirmStatut').show();" />
<p:commandButton icon="pi pi-trash"
title="Supprimer"
styleClass="ui-button-rounded ui-button-danger"
actionListener="#{organisationsBean.preparerSuppression(org)}"
update=":formOrgs:dlgConfirmSuppr"
oncomplete="PF('dlgConfirmSuppr').show();" />
</p:column>
</p:dataTable>
</div>
<p:dialog id="dlgConfirmStatut" widgetVar="dlgConfirmStatut" header="Confirmation" modal="true" width="380" showEffect="fade" hideEffect="fade">
<p class="mb-3">Confirmez l'action sur le statut de l'organisation ?</p>
<f:facet name="footer">
<p:commandButton value="Non" icon="pi pi-times" styleClass="ui-button-secondary" onclick="PF('dlgConfirmStatut').hide();" />
<p:commandButton value="Oui" icon="pi pi-check" styleClass="ui-button-success" process="@this"
actionListener="#{organisationsBean.confirmerBasculerStatut}"
update=":formOrgs:dtOrgs :formOrgs:messages :formOrgs:stats"
oncomplete="PF('dlgConfirmStatut').hide();" />
</f:facet>
</p:dialog>
<p:dialog id="dlgConfirmSuppr" widgetVar="dlgConfirmSuppr" header="Supprimer l'organisation" modal="true" width="400" showEffect="fade" hideEffect="fade">
<p class="mb-3">Supprimer cette organisation ? Cette action est irréversible.</p>
<f:facet name="footer">
<p:commandButton value="Non" icon="pi pi-times" styleClass="ui-button-secondary" onclick="PF('dlgConfirmSuppr').hide();" />
<p:commandButton value="Oui" icon="pi pi-check" styleClass="ui-button-danger" process="@this"
actionListener="#{organisationsBean.confirmerSuppression}"
update=":formOrgs:dtOrgs :formOrgs:messages :formOrgs:stats"
oncomplete="PF('dlgConfirmSuppr').hide();" />
</f:facet>
</p:dialog>
<!-- Dialogue création -->
<p:dialog id="dlgCreate"
widgetVar="dlgCreate"
header="Nouvelle organisation"
modal="true"
resizable="false"
responsive="true"
width="700">
<ui:include src="/ui/includes/organisation-form.xhtml">
<ui:param name="model" value="#{organisationsBean.nouvelleOrganisation}" />
<ui:param name="typesItems" value="#{organisationsBean.typesSelectItemsForForm}" />
<ui:param name="completionBean" value="#{organisationsBean}" />
</ui:include>
<f:facet name="footer">
<p:commandButton value="Annuler"
icon="pi pi-times"
onclick="PF('dlgCreate').hide();"
styleClass="ui-button-secondary" />
<p:commandButton value="Créer"
icon="pi pi-check"
process="@form"
update=":formOrgs:dtOrgs :formOrgs:messages :formOrgs:stats"
actionListener="#{organisationsBean.creerOrganisation}"
oncomplete="if(!args.validationFailed) PF('dlgCreate').hide();" />
</f:facet>
</p:dialog>
<!-- Dialogue édition -->
<p:dialog id="dlgEdit"
widgetVar="dlgEdit"
header="Modifier l'organisation"
modal="true"
resizable="false"
responsive="true"
width="700">
<ui:include src="/ui/includes/organisation-form.xhtml">
<ui:param name="model" value="#{organisationsBean.organisationSelectionnee}" />
<ui:param name="typesItems" value="#{organisationsBean.typesSelectItemsForForm}" />
<ui:param name="completionBean" value="#{organisationsBean}" />
</ui:include>
<f:facet name="footer">
<p:commandButton value="Annuler"
icon="pi pi-times"
onclick="PF('dlgEdit').hide();"
styleClass="ui-button-secondary" />
<p:commandButton value="Enregistrer"
icon="pi pi-check"
process="@form"
update=":formOrgs:dtOrgs :formOrgs:messages"
actionListener="#{organisationsBean.modifierOrganisation}"
oncomplete="if(!args.validationFailed) PF('dlgEdit').hide();" />
</f:facet>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -1,7 +1,7 @@
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:p="http://primefaces.org/ui"
xmlns:fr="http://primefaces.org/freya">
@@ -24,271 +24,202 @@
<div class="layout-menu-container">
<h:form id="menuform">
<fr:menu widgetVar="FreyaMenuWidget">
<!-- Dashboard Principal -->
<!-- ════════════════════════════════════════════════════════ -->
<!-- TABLEAU DE BORD -->
<!-- ════════════════════════════════════════════════════════ -->
<p:menuitem id="m_dashboard" value="Tableau de Bord" icon="pi pi-home" outcome="/pages/secure/dashboard" />
<!-- Super Administration -->
<!-- ════════════════════════════════════════════════════════ -->
<!-- SUPER ADMINISTRATION (SUPER_ADMIN uniquement) -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_super_admin" label="Super Administration" icon="pi pi-shield" rendered="#{menuBean.superAdminMenuVisible}">
<p:menuitem id="m_super_dashboard" value="Dashboard Super-Admin" icon="pi pi-chart-bar" outcome="/pages/super-admin/dashboard" />
<p:menuitem id="m_gestion_entites" value="Gestion des Entités" icon="pi pi-sitemap" outcome="/pages/super-admin/entites/gestion" />
<p:menuitem id="m_gestion_types_organisations" value="Types d'Organisation" icon="pi pi-tags" outcome="/pages/super-admin/types/organisations" />
<p:menuitem id="m_roles" value="Rôles Applicatifs" icon="pi pi-key" outcome="/pages/super-admin/roles/gestion" />
<p:menuitem id="m_audit" value="Journal d'Audit" icon="pi pi-file-o" outcome="/pages/admin/audit/journal" />
<p:menuitem id="m_logs_systeme" value="Logs Système" icon="pi pi-list" outcome="/pages/admin/logs/systeme" />
<p:menuitem id="m_sauvegardes" value="Sauvegardes" icon="pi pi-save" outcome="/pages/secure/admin/sauvegarde" />
<p:menuitem id="m_config_systeme" value="Configuration Système" icon="pi pi-cog" outcome="/pages/super-admin/configuration/systeme" />
</p:submenu>
<!-- Administration Générale -->
<p:submenu id="m_administration" label="Administration" icon="pi pi-cog" rendered="#{menuBean.administrationMenuVisible}">
<p:menuitem id="m_gestion_cotisations" value="Gestion Cotisations" icon="pi pi-dollar" outcome="/pages/admin/cotisations/gestion" rendered="#{menuBean.cotisationsAdminVisible}" />
<p:menuitem id="m_admin_evenements" value="Gestion Événements" icon="pi pi-calendar" outcome="/pages/admin/evenements/gestion" rendered="#{menuBean.creationEvenementVisible}" />
<p:menuitem id="m_demandes_aide" value="Demandes d'Aide" icon="pi pi-heart" outcome="/pages/admin/demandes/gestion" rendered="#{menuBean.traitementAideVisible}" />
<p:menuitem id="m_rapports_stats" value="Rapports et Statistiques" icon="pi pi-chart-bar" outcome="/pages/admin/rapports/statistiques" rendered="#{menuBean.rapportsMenuVisible}" />
<p:menuitem id="m_gestion_documents" value="Gestion Documents" icon="pi pi-folder" outcome="/pages/admin/documents/gestion" />
<p:menuitem id="m_parametres" value="Paramètres Système" icon="pi pi-sliders-h" url="#" rendered="#{menuBean.adminOrganisation or menuBean.superAdmin}" />
<p:menuitem id="m_roles" value="Rôles Applicatifs" icon="pi pi-key" outcome="/pages/super-admin/roles/gestion" rendered="#{menuBean.superAdmin}" />
<p:menuitem id="m_audit" value="Journal d'Audit Applicatif" icon="pi pi-file-o" outcome="/pages/admin/audit/journal" rendered="#{menuBean.adminOrganisation or menuBean.superAdmin}" />
<p:separator rendered="#{menuBean.keycloakUserManagerVisible}" />
<!-- Lions User Manager - Gestion Keycloak -->
<p:menuitem id="m_user_manager_list" value="Utilisateurs Keycloak" icon="pi pi-user-edit" url="#" rendered="#{menuBean.keycloakUserManagerVisible}" />
<p:menuitem id="m_user_manager_create" value="Nouvel Utilisateur Keycloak" icon="pi pi-user-plus" url="#" rendered="#{menuBean.keycloakUserManagerVisible}" />
<p:menuitem id="m_user_manager_roles" value="Rôles Keycloak" icon="pi pi-shield" url="#" rendered="#{menuBean.keycloakUserManagerVisible}" />
<p:menuitem id="m_user_manager_audit" value="Journal d'Audit Keycloak" icon="pi pi-history" url="#" rendered="#{menuBean.keycloakUserManagerVisible}" />
</p:submenu>
<!-- Annuaire des Membres (MEMBRE_ACTIF et plus - Consultation) -->
<p:submenu id="m_annuaire" label="Annuaire des Membres" icon="pi pi-users" rendered="#{menuBean.annuaireMembresVisible}">
<p:menuitem id="m_liste_membres_lecture" value="Liste des Membres" icon="pi pi-list" outcome="/pages/secure/membre/liste" />
<p:menuitem id="m_recherche_membres" value="Rechercher un Membre" icon="pi pi-search" outcome="/pages/secure/membre/recherche" />
</p:submenu>
<!-- Gestion des Membres (SECRETAIRE, ADMIN - Administration) -->
<p:submenu id="m_gestion_membres" label="Gestion des Membres" icon="pi pi-users" rendered="#{menuBean.gestionMembresMenuVisible}">
<p:menuitem id="m_inscription" value="Nouvelle Inscription" icon="pi pi-user-plus" outcome="/pages/secure/membre/inscription" />
<p:menuitem id="m_liste_membres" value="Liste Complète" icon="pi pi-list" outcome="/pages/secure/membre/liste" />
<p:menuitem id="m_validation_membres" value="Validation Inscriptions" icon="pi pi-check-circle" outcome="/pages/secure/membre/validation" />
<p:menuitem id="m_import_membres" value="Import en Masse" icon="pi pi-upload" outcome="/pages/secure/membre/import" />
<p:menuitem id="m_export_membres" value="Export Membres" icon="pi pi-download" outcome="/pages/secure/membre/export" />
</p:submenu>
<!-- Gestion des Organisations -->
<!-- ════════════════════════════════════════════════════════ -->
<!-- ORGANISATIONS -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_organisations" label="Organisations" icon="pi pi-building" rendered="#{menuBean.organisationsMenuVisible}">
<p:menuitem id="m_liste_organisations" value="Liste des Organisations" icon="pi pi-list" outcome="/pages/secure/organisation/liste" />
<p:menuitem id="m_nouvelle_organisation" value="Nouvelle Organisation" icon="pi pi-plus" outcome="/pages/secure/organisation/nouvelle" />
<p:menuitem id="m_statistiques_orga" value="Statistiques" icon="pi pi-chart-bar" outcome="/pages/secure/organisation/statistiques" />
<p:menuitem id="m_types_organisations" value="Types d'Organisation" icon="pi pi-tags" outcome="/pages/super-admin/types/organisations" rendered="#{menuBean.superAdmin}" />
</p:submenu>
<!-- Gestion des Adhésions -->
<p:submenu id="m_adhesions" label="Gestion des Adhésions" icon="pi pi-bookmark" rendered="#{menuBean.adhesionsMenuVisible}">
<!-- ════════════════════════════════════════════════════════ -->
<!-- MEMBRES -->
<!-- Un seul sous-menu, items conditionnels par rôle -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_membres" label="Membres" icon="pi pi-users" rendered="#{menuBean.annuaireMembresVisible}">
<p:menuitem id="m_liste_membres" value="Annuaire des Membres" icon="pi pi-list" outcome="/pages/secure/membre/liste" />
<p:menuitem id="m_recherche_membres" value="Rechercher un Membre" icon="pi pi-search" outcome="/pages/secure/membre/recherche" />
<p:menuitem id="m_inscription" value="Nouvelle Inscription" icon="pi pi-user-plus" outcome="/pages/secure/membre/inscription" rendered="#{menuBean.gestionMembresMenuVisible}" />
<p:menuitem id="m_validation_membres" value="Validation Inscriptions" icon="pi pi-check-circle" outcome="/pages/secure/membre/validation" rendered="#{menuBean.gestionMembresMenuVisible}" />
<p:menuitem id="m_import_membres" value="Import en Masse" icon="pi pi-upload" outcome="/pages/secure/membre/import" rendered="#{menuBean.gestionMembresMenuVisible}" />
<p:menuitem id="m_export_membres" value="Export Membres" icon="pi pi-download" outcome="/pages/secure/membre/export" rendered="#{menuBean.gestionMembresMenuVisible}" />
</p:submenu>
<!-- ════════════════════════════════════════════════════════ -->
<!-- ADHÉSIONS -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_adhesions" label="Adhésions" icon="pi pi-bookmark" rendered="#{menuBean.adhesionsMenuVisible}">
<p:menuitem id="m_demande_adhesion" value="Nouvelle Demande" icon="pi pi-plus-circle" outcome="/pages/secure/adhesion/demande" />
<p:menuitem id="m_validation_adhesion" value="Validation des Demandes" icon="pi pi-check-circle" outcome="/pages/secure/adhesion/validation" rendered="#{menuBean.validationAdhesionVisible}" />
<p:menuitem id="m_liste_adhesions" value="Toutes les Adhésions" icon="pi pi-list" outcome="/pages/secure/adhesion/liste" />
<p:menuitem id="m_validation_adhesion" value="Validation des Demandes" icon="pi pi-check-circle" outcome="/pages/secure/adhesion/validation" rendered="#{menuBean.validationAdhesionVisible}" />
<p:menuitem id="m_renouvellement" value="Renouvellements" icon="pi pi-refresh" outcome="/pages/secure/adhesion/renouvellement" />
<p:menuitem id="m_cartes_membres" value="Cartes de Membres" icon="pi pi-id-card" outcome="/pages/secure/adhesion/cartes-membres" rendered="#{menuBean.secretaire or menuBean.adminOrganisation or menuBean.superAdmin}" />
<p:menuitem id="m_historique_adhesions" value="Historique" icon="pi pi-history" outcome="/pages/secure/adhesion/historique" />
</p:submenu>
<!-- Mes Finances (TOUS - Finances personnelles) -->
<!-- ════════════════════════════════════════════════════════ -->
<!-- MES FINANCES (perso — tous les membres) -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_mes_finances" label="Mes Finances" icon="pi pi-wallet" rendered="#{menuBean.mesFinancesMenuVisible}">
<p:menuitem id="m_mes_cotisations" value="Mes Cotisations" icon="pi pi-credit-card" outcome="/pages/secure/membre/cotisations" rendered="#{menuBean.paiementCotisationVisible}" />
<p:menuitem id="m_payer_cotisations" value="Payer mes Cotisations" icon="pi pi-dollar" outcome="/pages/secure/cotisation/paiement" rendered="#{menuBean.paiementCotisationVisible}" />
<p:menuitem id="m_mes_cotisations" value="Mes Cotisations" icon="pi pi-credit-card" outcome="/pages/secure/membre/cotisations" />
<p:menuitem id="m_payer_cotisations" value="Payer mes Cotisations" icon="pi pi-dollar" outcome="/pages/secure/cotisation/paiement" />
<p:menuitem id="m_historique_finances" value="Historique" icon="pi pi-history" outcome="/pages/secure/cotisation/historique" />
</p:submenu>
<!-- Gestion Financière (TRESORIER, ADMIN - Administration finances) -->
<!-- ════════════════════════════════════════════════════════ -->
<!-- GESTION FINANCIÈRE (admin — trésorier, admin org) -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_gestion_finances" label="Gestion Financière" icon="pi pi-dollar" rendered="#{menuBean.gestionFinancesMenuVisible}">
<p:menuitem id="m_gestion_cotisations" value="Gestion Cotisations" icon="pi pi-dollar" outcome="/pages/admin/cotisations/gestion" />
<p:menuitem id="m_tresorerie" value="Trésorerie" icon="pi pi-wallet" outcome="/pages/secure/finance/tresorerie" />
<p:menuitem id="m_budgets" value="Gestion des Budgets" icon="pi pi-chart-pie" outcome="/pages/secure/finance/budgets" />
<p:menuitem id="m_approbations_finance" value="Approbations" icon="pi pi-check-square" outcome="/pages/secure/finance/approbations" />
<p:menuitem id="m_comptabilite" value="Comptabilité" icon="pi pi-calculator" outcome="/pages/secure/comptabilite/gestion" />
<p:menuitem id="m_relances" value="Relances Cotisations" icon="pi pi-bell" outcome="/pages/secure/cotisation/relances" />
<p:menuitem id="m_rapports_cotisations" value="Rapports Cotisations" icon="pi pi-chart-bar" outcome="/pages/secure/cotisation/rapports" />
<p:menuitem id="m_bilans" value="Bilans Financiers" icon="pi pi-chart-line" outcome="/pages/secure/finance/bilans" />
</p:submenu>
<!-- Épargne (module EPARGNE — mutuelle, coopérative) -->
<p:submenu id="m_epargne" label="Épargne" icon="pi pi-wallet" rendered="#{menuBean.epargneMenuVisible}">
<!-- ════════════════════════════════════════════════════════ -->
<!-- ÉPARGNE (module EPARGNE — mutuelle, coopérative) -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_epargne" label="Épargne &amp; Crédit" icon="pi pi-wallet" rendered="#{menuBean.epargneMenuVisible}">
<p:menuitem id="m_epargne_comptes" value="Comptes Épargne" icon="pi pi-wallet" outcome="/pages/secure/epargne/comptes" />
<p:menuitem id="m_epargne_transactions" value="Transactions" icon="pi pi-arrows-v" url="#" />
<p:menuitem id="m_epargne_stats" value="Statistiques Épargne" icon="pi pi-chart-bar" url="#" />
<p:menuitem id="m_demandes_credit" value="Demandes de Crédit" icon="pi pi-inbox" outcome="/pages/secure/credit/demandes" rendered="#{menuBean.creditMenuVisible}" />
<p:menuitem id="m_evaluation_credit" value="Évaluation Solvabilité" icon="pi pi-search" outcome="/pages/secure/credit/evaluation" rendered="#{menuBean.creditMenuVisible}" />
<p:menuitem id="m_suivi_credits" value="Suivi des Crédits" icon="pi pi-eye" outcome="/pages/secure/credit/suivi" rendered="#{menuBean.creditMenuVisible}" />
<p:menuitem id="m_remboursements" value="Remboursements" icon="pi pi-replay" outcome="/pages/secure/credit/remboursements" rendered="#{menuBean.creditMenuVisible}" />
<p:menuitem id="m_stats_credit" value="Statistiques Crédit" icon="pi pi-chart-bar" outcome="/pages/secure/credit/statistiques" rendered="#{menuBean.creditMenuVisible}" />
</p:submenu>
<!-- Mon Épargne (module EPARGNE — membres) -->
<!-- Mon Épargne (membre — visible si pas admin épargne) -->
<p:submenu id="m_mon_epargne" label="Mon Épargne" icon="pi pi-wallet" rendered="#{menuBean.epargneMemberVisible and not menuBean.epargneMenuVisible}">
<p:menuitem id="m_mon_epargne_compte" value="Mon Compte Épargne" icon="pi pi-wallet" outcome="/pages/secure/epargne/comptes" />
<p:menuitem id="m_mon_epargne_historique" value="Historique" icon="pi pi-history" url="#" />
<p:menuitem id="m_demande_pret" value="Demander un Prêt" icon="pi pi-plus" outcome="/pages/secure/credit/demandes" rendered="#{menuBean.creditMemberVisible}" />
<p:menuitem id="m_mes_credits" value="Mes Crédits en Cours" icon="pi pi-list" outcome="/pages/secure/credit/suivi" rendered="#{menuBean.creditMemberVisible}" />
</p:submenu>
<!-- Crédit (module CREDIT — mutuelle, coopérative) -->
<p:submenu id="m_credit_admin" label="Gestion Crédit" icon="pi pi-credit-card" rendered="#{menuBean.creditMenuVisible}">
<p:menuitem id="m_demandes_credit" value="Demandes de Crédit" icon="pi pi-inbox" outcome="/pages/secure/credit/demandes" />
<p:menuitem id="m_evaluation_credit" value="Évaluation Solvabilité" icon="pi pi-search" outcome="/pages/secure/credit/evaluation" />
<p:menuitem id="m_suivi_credits" value="Suivi des Crédits" icon="pi pi-eye" outcome="/pages/secure/credit/suivi" />
<p:menuitem id="m_remboursements" value="Remboursements" icon="pi pi-replay" outcome="/pages/secure/credit/remboursements" />
<p:menuitem id="m_stats_credit" value="Statistiques Crédit" icon="pi pi-chart-bar" outcome="/pages/secure/credit/statistiques" />
</p:submenu>
<!-- Mon Crédit (module CREDIT — membres) -->
<p:submenu id="m_mon_credit" label="Mon Crédit" icon="pi pi-credit-card" rendered="#{menuBean.creditMemberVisible and not menuBean.creditMenuVisible}">
<p:menuitem id="m_demande_pret" value="Demander un Prêt" icon="pi pi-plus" outcome="/pages/secure/credit/demandes" />
<p:menuitem id="m_mes_credits" value="Mes Crédits en Cours" icon="pi pi-list" outcome="/pages/secure/credit/suivi" />
</p:submenu>
<!-- Tontine (module TONTINE) -->
<!-- ════════════════════════════════════════════════════════ -->
<!-- MODULES MÉTIER SPÉCIALISÉS (Coming Soon) -->
<!-- Affichés uniquement si le module est actif pour l'org -->
<!-- Un seul item par module → page "coming soon" à terme -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_tontine" label="Tontine" icon="pi pi-sync" rendered="#{menuBean.tontineMenuVisible}">
<p:menuitem id="m_tontine_cycles" value="Cycles de Tontine" icon="pi pi-calendar" url="#" />
<p:menuitem id="m_tontine_cotisations" value="Cotisations Tontine" icon="pi pi-dollar" url="#" />
<p:menuitem id="m_tontine_remises" value="Remises" icon="pi pi-gift" url="#" />
<p:menuitem id="m_tontine_stats" value="Statistiques" icon="pi pi-chart-bar" url="#" />
<p:menuitem id="m_tontine_info" value="Bientôt disponible" icon="pi pi-info-circle" disabled="true" />
</p:submenu>
<!-- Ma Tontine (module TONTINE — membres) -->
<p:submenu id="m_ma_tontine" label="Ma Tontine" icon="pi pi-sync" rendered="#{menuBean.tontineMemberVisible and not menuBean.tontineMenuVisible}">
<p:menuitem id="m_ma_tontine_cycles" value="Mes Cycles" icon="pi pi-calendar" url="#" />
<p:menuitem id="m_ma_tontine_cotisations" value="Mes Cotisations" icon="pi pi-dollar" url="#" />
</p:submenu>
<!-- Agriculture (module AGRICULTURE — coopératives agricoles) -->
<p:submenu id="m_agricole" label="Agriculture" icon="pi pi-sun" rendered="#{menuBean.agricoleMenuVisible}">
<p:menuitem id="m_campagnes_agricoles" value="Campagnes Agricoles" icon="pi pi-calendar" url="#" />
<p:menuitem id="m_parcelles" value="Gestion des Parcelles" icon="pi pi-map" url="#" />
<p:menuitem id="m_recoltes" value="Récoltes et Stocks" icon="pi pi-database" url="#" />
<p:menuitem id="m_agricole_stats" value="Statistiques" icon="pi pi-chart-bar" url="#" />
<p:menuitem id="m_agricole_info" value="Bientôt disponible" icon="pi pi-info-circle" disabled="true" />
</p:submenu>
<!-- Collecte de Fonds (module COLLECTE_FONDS) -->
<p:submenu id="m_collecte" label="Collecte de Fonds" icon="pi pi-heart" rendered="#{menuBean.collecteFondsMenuVisible}">
<p:menuitem id="m_campagnes_collecte" value="Campagnes" icon="pi pi-megaphone" url="#" />
<p:menuitem id="m_dons_recus" value="Dons Reçus" icon="pi pi-inbox" url="#" />
<p:menuitem id="m_collecte_stats" value="Statistiques" icon="pi pi-chart-bar" url="#" />
<p:menuitem id="m_collecte_info" value="Bientôt disponible" icon="pi pi-info-circle" disabled="true" />
</p:submenu>
<!-- Projets ONG (module PROJETS_ONG) -->
<p:submenu id="m_projets_ong" label="Projets ONG" icon="pi pi-globe" rendered="#{menuBean.projetOngMenuVisible}">
<p:menuitem id="m_liste_projets" value="Projets en Cours" icon="pi pi-list" url="#" />
<p:menuitem id="m_nouveau_projet" value="Nouveau Projet" icon="pi pi-plus" url="#" />
<p:menuitem id="m_suivi_projets" value="Suivi des Projets" icon="pi pi-chart-line" url="#" />
<p:menuitem id="m_rapports_ong" value="Rapports ONG" icon="pi pi-file" url="#" />
<p:menuitem id="m_projets_info" value="Bientôt disponible" icon="pi pi-info-circle" disabled="true" />
</p:submenu>
<!-- Culte / Dons Religieux (module CULTE_DONS) -->
<p:submenu id="m_culte" label="Culte et Dons" icon="pi pi-star" rendered="#{menuBean.culteMenuVisible}">
<p:menuitem id="m_dons_religieux" value="Dons et Offrandes" icon="pi pi-heart" url="#" />
<p:menuitem id="m_services_culte" value="Services / Cultes" icon="pi pi-calendar" url="#" />
<p:menuitem id="m_dons_stats" value="Statistiques Dons" icon="pi pi-chart-bar" url="#" />
<p:menuitem id="m_culte_info" value="Bientôt disponible" icon="pi pi-info-circle" disabled="true" />
</p:submenu>
<!-- Vote (module VOTES) -->
<p:submenu id="m_votes" label="Votes et Élections" icon="pi pi-check-circle" rendered="#{menuBean.voteMenuVisible}">
<p:menuitem id="m_campagnes_vote" value="Campagnes de Vote" icon="pi pi-megaphone" url="#" />
<p:menuitem id="m_resultats_vote" value="Résultats" icon="pi pi-chart-bar" url="#" />
<p:menuitem id="m_votes_info" value="Bientôt disponible" icon="pi pi-info-circle" disabled="true" />
</p:submenu>
<!-- Registre / Agrément (module REGISTRE_AGREMENT) -->
<p:submenu id="m_registre" label="Registre &amp; Agrément" icon="pi pi-verified" rendered="#{menuBean.registreAgrementMenuVisible}">
<p:menuitem id="m_agrement" value="Dossier d'Agrément" icon="pi pi-file" url="#" />
<p:menuitem id="m_statuts" value="Statuts et Règlements" icon="pi pi-book" url="#" />
<p:menuitem id="m_certificats" value="Certificats" icon="pi pi-id-card" url="#" />
<p:menuitem id="m_registre_info" value="Bientôt disponible" icon="pi pi-info-circle" disabled="true" />
</p:submenu>
<!-- Mes Demandes d'Aide (TOUS - Demandes personnelles) -->
<!-- ════════════════════════════════════════════════════════ -->
<!-- AIDE SOCIALE -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_mes_aides" label="Aide Sociale" icon="pi pi-heart" rendered="#{menuBean.mesAidesSocialesMenuVisible}">
<p:menuitem id="m_demande_aide" value="Faire une Demande" icon="pi pi-plus" outcome="/pages/secure/aide/demande" rendered="#{menuBean.demandeAideSocialeVisible}" />
<p:menuitem id="m_mes_demandes_aide" value="Mes Demandes" icon="pi pi-list" outcome="/pages/secure/aide/requests" rendered="#{menuBean.mesDemandesAideVisible}" />
<p:menuitem id="m_demande_aide" value="Faire une Demande" icon="pi pi-plus" outcome="/pages/secure/aide/demande" />
<p:menuitem id="m_mes_demandes_aide" value="Mes Demandes" icon="pi pi-list" outcome="/pages/secure/aide/requests" />
<p:menuitem id="m_historique_aides" value="Historique" icon="pi pi-clock" outcome="/pages/secure/aide/historique" />
<p:menuitem id="m_traitement_aide" value="Traitement des Demandes" icon="pi pi-cog" outcome="/pages/secure/aide/traitement" rendered="#{menuBean.gestionAidesSocialesMenuVisible}" />
<p:menuitem id="m_suivi_aide" value="Suivi des Bénéficiaires" icon="pi pi-eye" outcome="/pages/secure/aide/approved" rendered="#{menuBean.gestionAidesSocialesMenuVisible}" />
<p:menuitem id="m_statistiques_aides" value="Statistiques Sociales" icon="pi pi-chart-line" outcome="/pages/secure/aide/statistiques" rendered="#{menuBean.gestionAidesSocialesMenuVisible}" />
</p:submenu>
<!-- Gestion Aide Sociale (RESPONSABLE_SOCIAL, ADMIN - Administration aide sociale) -->
<p:submenu id="m_gestion_aides" label="Gestion Aide Sociale" icon="pi pi-heart-fill" rendered="#{menuBean.gestionAidesSocialesMenuVisible}">
<p:menuitem id="m_traitement_aide" value="Traitement des Demandes" icon="pi pi-cog" outcome="/pages/secure/aide/traitement" />
<p:menuitem id="m_suivi_aide" value="Suivi des Bénéficiaires" icon="pi pi-eye" outcome="/pages/secure/aide/approved" />
<p:menuitem id="m_statistiques_aides" value="Statistiques Sociales" icon="pi pi-chart-line" outcome="/pages/secure/aide/statistiques" />
</p:submenu>
<!-- Événements (TOUS - Participation) -->
<p:submenu id="m_mes_evenements" label="Événements" icon="pi pi-calendar" rendered="#{menuBean.mesEvenementsMenuVisible}">
<!-- ════════════════════════════════════════════════════════ -->
<!-- ÉVÉNEMENTS -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_evenements" label="Événements" icon="pi pi-calendar" rendered="#{menuBean.mesEvenementsMenuVisible}">
<p:menuitem id="m_calendrier" value="Calendrier" icon="pi pi-calendar-plus" outcome="/pages/secure/evenement/calendrier" />
<p:menuitem id="m_mes_inscriptions_events" value="Mes Inscriptions" icon="pi pi-list" outcome="/pages/secure/evenement/participants" rendered="#{menuBean.mesInscriptionsEvenementsVisible}" />
<p:menuitem id="m_mes_reservations" value="Mes Réservations" icon="pi pi-ticket" outcome="/pages/secure/evenement/reservations" />
<p:menuitem id="m_mes_inscriptions_events" value="Mes Inscriptions" icon="pi pi-list" outcome="/pages/secure/evenement/participants" />
<p:menuitem id="m_creation_evenement" value="Nouvel Événement" icon="pi pi-plus" outcome="/pages/secure/evenement/creation" rendered="#{menuBean.gestionEvenementsMenuVisible}" />
<p:menuitem id="m_planification" value="Planification" icon="pi pi-clock" outcome="/pages/secure/evenement/planification" rendered="#{menuBean.gestionEvenementsMenuVisible}" />
<p:menuitem id="m_logistique" value="Logistique" icon="pi pi-truck" outcome="/pages/secure/evenement/logistique" rendered="#{menuBean.gestionEvenementsMenuVisible}" />
<p:menuitem id="m_gestion_generale_evenements" value="Gestion Générale" icon="pi pi-cog" outcome="/pages/secure/evenement/gestion" rendered="#{menuBean.gestionEvenementsMenuVisible}" />
<p:menuitem id="m_bilan_evenements" value="Bilans" icon="pi pi-chart-bar" outcome="/pages/secure/evenement/bilan" rendered="#{menuBean.gestionEvenementsMenuVisible}" />
</p:submenu>
<!-- Gestion Événements (RESPONSABLE_EVENEMENTS, SECRETAIRE, ADMIN - Organisation) -->
<p:submenu id="m_gestion_evenements" label="Gestion Événements" icon="pi pi-calendar-plus" rendered="#{menuBean.gestionEvenementsMenuVisible}">
<p:menuitem id="m_creation_evenement" value="Nouvel Événement" icon="pi pi-plus" outcome="/pages/secure/evenement/creation" />
<p:menuitem id="m_planification" value="Planification" icon="pi pi-clock" outcome="/pages/secure/evenement/planification" />
<p:menuitem id="m_logistique" value="Logistique" icon="pi pi-truck" outcome="/pages/secure/evenement/logistique" />
<p:menuitem id="m_participation" value="Gestion Participations" icon="pi pi-users" outcome="/pages/secure/evenement/participation" />
<p:menuitem id="m_gestion_generale_evenements" value="Gestion Générale" icon="pi pi-cog" outcome="/pages/secure/evenement/gestion" />
<p:menuitem id="m_bilan_evenements" value="Bilans" icon="pi pi-chart-bar" outcome="/pages/secure/evenement/bilan" />
</p:submenu>
<!-- Communication (TOUS - Messages et notifications personnelles) -->
<p:submenu id="m_mes_communications" label="Communication" icon="pi pi-envelope" rendered="#{menuBean.mesCommunicationsMenuVisible}">
<!-- ════════════════════════════════════════════════════════ -->
<!-- COMMUNICATION -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_communications" label="Communication" icon="pi pi-envelope" rendered="#{menuBean.mesCommunicationsMenuVisible}">
<p:menuitem id="m_messagerie" value="Messagerie" icon="pi pi-comments" outcome="/pages/secure/communication/conversations" />
<p:menuitem id="m_mes_notifications" value="Mes Notifications" icon="pi pi-bell" outcome="/pages/secure/communication/notifications" />
</p:submenu>
<!-- Gestion Documentaire -->
<p:submenu id="m_documents" label="Gestion Documentaire" icon="pi pi-folder" rendered="#{menuBean.documentsMenuVisible}">
<p:menuitem id="m_bibliotheque" value="Bibliothèque" icon="pi pi-book" url="#" />
<!-- ════════════════════════════════════════════════════════ -->
<!-- DOCUMENTS -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_documents" label="Documents" icon="pi pi-folder" rendered="#{menuBean.documentsMenuVisible}">
<p:menuitem id="m_mes_documents" value="Mes Documents" icon="pi pi-file" outcome="/pages/secure/documents/mes-documents" />
<p:menuitem id="m_modeles" value="Modèles et Templates" icon="pi pi-file-o" url="#" rendered="#{menuBean.secretaire or menuBean.adminOrganisation or menuBean.superAdmin}" />
<p:menuitem id="m_archivage" value="Archivage" icon="pi pi-archive" url="#" rendered="#{menuBean.secretaire or menuBean.adminOrganisation or menuBean.superAdmin}" />
<p:menuitem id="m_partage" value="Documents Partagés" icon="pi pi-share-alt" url="#" />
<p:menuitem id="m_signatures" value="Signatures Électroniques" icon="pi pi-verified" url="#" rendered="#{menuBean.adminOrganisation or menuBean.superAdmin}" />
<p:menuitem id="m_workflow_doc" value="Workflow Documentaire" icon="pi pi-sitemap" url="#" rendered="#{menuBean.secretaire or menuBean.adminOrganisation or menuBean.superAdmin}" />
</p:submenu>
<!-- Formations (TOUS - Inscriptions et suivi) -->
<p:submenu id="m_mes_formations" label="Formations" icon="pi pi-book" rendered="#{menuBean.mesFormationsMenuVisible}">
<p:menuitem id="m_info_formations" value="Informations" icon="pi pi-info-circle" outcome="/pages/secure/dashboard" />
</p:submenu>
<!-- Rapports et Analyses -->
<p:submenu id="m_rapports" label="Rapports et Analyses" icon="pi pi-chart-bar" rendered="#{menuBean.rapportsMenuVisible}">
<!-- ════════════════════════════════════════════════════════ -->
<!-- RAPPORTS ET ANALYSES -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_rapports" label="Rapports" icon="pi pi-chart-bar" rendered="#{menuBean.rapportsMenuVisible}">
<p:menuitem id="m_tableaux_bord" value="Tableaux de Bord" icon="pi pi-chart-line" outcome="/pages/secure/rapport/tableaux-bord" />
<p:menuitem id="m_rapport_membres" value="Rapport Membres" icon="pi pi-users" outcome="/pages/secure/rapport/membres" />
<p:menuitem id="m_rapport_finances" value="Rapport Financier" icon="pi pi-dollar" outcome="/pages/secure/rapport/finances" rendered="#{menuBean.rapportFinancierVisible}" />
<p:menuitem id="m_rapport_activites" value="Rapport d'Activités" icon="pi pi-chart-line" outcome="/pages/secure/rapport/activites" />
<p:menuitem id="m_indicateurs" value="Indicateurs de Performance" icon="pi pi-gauge" url="#" rendered="#{menuBean.adminOrganisation or menuBean.superAdmin}" />
<p:menuitem id="m_analyses_predicitives" value="Analyses Prédictives" icon="pi pi-eye" url="#" rendered="#{menuBean.adminOrganisation or menuBean.superAdmin}" />
<p:menuitem id="m_export" value="Exports Personnalisés" icon="pi pi-download" outcome="/pages/secure/rapport/export" rendered="#{menuBean.exportsPersonnalisesVisible}" />
<p:menuitem id="m_export" value="Exports" icon="pi pi-download" outcome="/pages/secure/rapport/export" rendered="#{menuBean.exportsPersonnalisesVisible}" />
</p:submenu>
<!-- Outils et Utilitaires -->
<p:submenu id="m_outils" label="Outils et Utilitaires" icon="pi pi-wrench" rendered="#{menuBean.outilsMenuVisible}">
<p:menuitem id="m_calculatrices" value="Calculatrices" icon="pi pi-calculator" url="#" />
<p:menuitem id="m_generateurs" value="Générateurs" icon="pi pi-cog" url="#" rendered="#{menuBean.adminOrganisation or menuBean.superAdmin}" />
<p:menuitem id="m_imports" value="Imports de Données" icon="pi pi-upload" url="#" rendered="#{menuBean.importExportMembreVisible}" />
<p:menuitem id="m_exports_masse" value="Exports en Masse" icon="pi pi-download" outcome="/pages/secure/outils/exports-masse" rendered="#{menuBean.exportsPersonnalisesVisible}" />
<p:menuitem id="m_sauvegardes" value="Sauvegardes" icon="pi pi-save" outcome="/pages/secure/admin/sauvegarde" rendered="#{menuBean.maintenanceVisible}" />
<p:menuitem id="m_logs_systeme" value="Logs Système" icon="pi pi-list" outcome="/pages/admin/logs/systeme" rendered="#{menuBean.maintenanceVisible}" />
<p:menuitem id="m_synchronisation" value="Synchronisation" icon="pi pi-sync" url="#" rendered="#{menuBean.adminOrganisation or menuBean.superAdmin}" />
<p:menuitem id="m_maintenance" value="Maintenance" icon="pi pi-wrench" url="#" rendered="#{menuBean.maintenanceVisible}" />
<p:menuitem id="m_api_externe" value="APIs Externes" icon="pi pi-cloud" url="#" rendered="#{menuBean.superAdmin}" />
</p:submenu>
<!-- Mon Espace Personnel -->
<p:submenu id="m_personnel" label="Mon Espace Personnel" icon="pi pi-user">
<!-- ════════════════════════════════════════════════════════ -->
<!-- MON ESPACE PERSONNEL -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_personnel" label="Mon Espace" icon="pi pi-user">
<p:menuitem id="m_mon_profil" value="Mon Profil" icon="pi pi-user-edit" outcome="/pages/secure/personnel/profil" />
<p:menuitem id="m_mes_activites" value="Mes Activités" icon="pi pi-history" outcome="/pages/secure/personnel/activites" />
<p:menuitem id="m_mes_preferences" value="Mes Préférences" icon="pi pi-cog" outcome="/pages/secure/personnel/preferences" />
<p:menuitem id="m_personnel_notifications" value="Mes Notifications" icon="pi pi-bell" outcome="/pages/secure/personnel/notifications" />
<p:menuitem id="m_mon_agenda" value="Mon Agenda" icon="pi pi-calendar" outcome="/pages/secure/personnel/agenda" />
<p:menuitem id="m_mes_documents_perso" value="Mes Documents" icon="pi pi-folder" outcome="/pages/secure/personnel/documents" />
<p:menuitem id="m_favoris" value="Mes Favoris" icon="pi pi-star-fill" outcome="/pages/secure/personnel/favoris" />
<p:menuitem id="m_parametres_compte" value="Paramètres Compte" icon="pi pi-lock" outcome="/pages/secure/personnel/parametres" />
</p:submenu>
<!-- Aide et Support -->
<p:submenu id="m_aide_documentation" label="Aide et Support" icon="pi pi-question-circle">
<p:menuitem id="m_guide_utilisateur" value="Guide Utilisateur" icon="pi pi-book" outcome="/pages/secure/aide/guide" />
<p:menuitem id="m_documentation" value="Documentation Complète" icon="pi pi-info-circle" outcome="/pages/secure/aide/documentation" />
<p:menuitem id="m_tutoriels" value="Tutoriels Vidéo" icon="pi pi-video" outcome="/pages/secure/aide/tutoriels" />
<!-- ════════════════════════════════════════════════════════ -->
<!-- AIDE ET SUPPORT -->
<!-- ════════════════════════════════════════════════════════ -->
<p:submenu id="m_aide_documentation" label="Aide" icon="pi pi-question-circle">
<p:menuitem id="m_faq" value="Questions Fréquentes" icon="pi pi-question" outcome="/pages/secure/aide/faq" />
<p:menuitem id="m_support" value="Contacter le Support" icon="pi pi-phone" outcome="/pages/secure/aide/support" />
<p:menuitem id="m_tickets" value="Mes Tickets" icon="pi pi-ticket" outcome="/pages/secure/aide/tickets" />
<p:menuitem id="m_feedback" value="Suggestions" icon="pi pi-comment" outcome="/pages/secure/aide/suggestions" />
<p:menuitem id="m_changelog" value="Nouveautés" icon="pi pi-sparkles" outcome="/pages/secure/aide/nouveautes" />
<p:menuitem id="m_apropos" value="À Propos d'UnionFlow" icon="pi pi-info" outcome="/pages/secure/aide/apropos" />
<p:menuitem id="m_apropos" value="À Propos" icon="pi pi-info" outcome="/pages/secure/aide/apropos" />
</p:submenu>
</fr:menu>
</h:form>
</div>