Sync: code local unifié

Synchronisation du code source local (fait foi).

Signed-off-by: lions dev Team
This commit is contained in:
dahoud
2026-03-15 16:25:45 +00:00
parent 6b28cf751e
commit 0dc050f422
179 changed files with 3355 additions and 992 deletions

View File

@@ -520,7 +520,7 @@
<div class="field col-12 md:col-6">
<p:outputLabel for="newDossier" value="Dossier de destination" />
<p:selectOneMenu id="newDossier" value="#{documentsBean.nouveauDocument.dossierId}">
<p:selectOneMenu id="newDossier" value="#{documentsBean.nouveauDocument.dossierId}" converter="uuidConverter">
<f:selectItem itemLabel="Racine" itemValue="" />
<f:selectItems value="#{documentsBean.dossiersDisponibles}"
var="dossier"

View File

@@ -31,6 +31,7 @@
<p:outputLabel for="membreId" value="Membre" />
<p:selectOneMenu id="membreId"
value="#{adhesionsBean.nouvelleAdhesion.membreId}"
converter="uuidConverter"
required="true"
requiredMessage="Veuillez sélectionner un membre"
filter="true"
@@ -46,6 +47,7 @@
<p:outputLabel for="organisationId" value="Organisation" />
<p:selectOneMenu id="organisationId"
value="#{adhesionsBean.nouvelleAdhesion.organisationId}"
converter="uuidConverter"
required="true"
requiredMessage="Veuillez sélectionner une organisation"
filter="true"

View File

@@ -216,6 +216,7 @@
<p:outputLabel for="membreId" value="Membre" />
<p:selectOneMenu id="membreId"
value="#{adhesionsBean.nouvelleAdhesion.membreId}"
converter="uuidConverter"
required="true"
requiredMessage="Veuillez sélectionner un membre"
filter="true"
@@ -230,6 +231,7 @@
<p:outputLabel for="organisationId" value="Organisation" />
<p:selectOneMenu id="organisationId"
value="#{adhesionsBean.nouvelleAdhesion.organisationId}"
converter="uuidConverter"
required="true"
requiredMessage="Veuillez sélectionner une organisation"
filter="true"

View File

@@ -31,6 +31,7 @@
<p:outputLabel for="membreId" value="Membre" />
<p:selectOneMenu id="membreId"
value="#{adhesionsBean.nouvelleAdhesion.membreId}"
converter="uuidConverter"
required="true"
requiredMessage="Veuillez sélectionner un membre"
filter="true"
@@ -46,6 +47,7 @@
<p:outputLabel for="organisationId" value="Organisation" />
<p:selectOneMenu id="organisationId"
value="#{adhesionsBean.nouvelleAdhesion.organisationId}"
converter="uuidConverter"
required="true"
requiredMessage="Veuillez sélectionner une organisation"
filter="true"

View File

@@ -32,8 +32,8 @@
</ui:define>
</ui:include>
<!-- Statistiques de paiement -->
<div class="grid">
<!-- Statistiques de paiement - TRESORIER/ADMIN SEULEMENT -->
<div class="grid" rendered="#{menuBean.gestionFinancesMenuVisible}">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.totalCollecteFormatte}" />
<ui:param name="label" value="Total Collecté" />
@@ -63,8 +63,8 @@
</ui:include>
</div>
<!-- Répartition par méthode de paiement -->
<div class="card">
<!-- Répartition par méthode de paiement - TRESORIER/ADMIN SEULEMENT -->
<div class="card" rendered="#{menuBean.gestionFinancesMenuVisible}">
<h5>
<i class="pi pi-chart-pie mr-2"></i>
Répartition par Méthode de Paiement
@@ -118,6 +118,7 @@
value="#{cotisationsBean.cotisationsFiltrees}"
var="cotisation"
filteredValue="#{cotisationsBean.cotisationsFiltrees}"
rowKey="#{cotisation.id}"
paginator="true"
rows="20"
emptyMessage="Aucune cotisation en attente"
@@ -137,7 +138,9 @@
</div>
</f:facet>
<p:column headerText="Membre" sortBy="#{cotisation.nomMembre}">
<!-- Colonne Membre - TRESORIER/ADMIN SEULEMENT -->
<p:column headerText="Membre" sortBy="#{cotisation.nomMembre}"
rendered="#{menuBean.gestionFinancesMenuVisible}">
<div>
<div class="font-medium">#{cotisation.nomMembre}</div>
<div class="text-600 text-sm">#{cotisation.numeroMembre}</div>

View File

@@ -7,7 +7,14 @@
template="/templates/main-template.xhtml">
<ui:define name="title">UnionFlow - Tableau de bord</ui:define>
<ui:define name="metadata">
<!-- Redirection conditionnelle AVANT le rendu (phase INVOKE_APPLICATION) -->
<f:metadata>
<f:viewAction action="#{dashboardBean.checkAccessAndRedirect}" />
</f:metadata>
</ui:define>
<ui:define name="content">
<div class="grid">
<!-- Header avec informations contextuelles -->
@@ -16,7 +23,7 @@
<div class="flex flex-column lg:flex-row lg:align-items-center lg:justify-content-between">
<div>
<h2 class="text-900 font-medium text-4xl">Tableau de bord UnionFlow</h2>
<p class="text-600 text-lg mt-0 mb-3">Bienvenue #{userSession.currentUser.nom}, voici un aperçu de votre union</p>
<p class="text-600 text-lg mt-0 mb-3">Bienvenue #{userSession.currentUser != null ? userSession.currentUser.nomComplet : userSession.username}, voici un aperçu de votre union</p>
<div class="flex align-items-center">
<i class="pi pi-calendar text-blue-500"></i>
<span class="text-700 ml-2">#{dashboardBean.currentDate}</span>
@@ -130,54 +137,68 @@
</div>
<!-- 1. MEMBRES : L'humain d'abord - le plus important -->
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Membres Actifs" />
<ui:param name="value" value="#{dashboardBean.activeMembers}" />
<ui:param name="icon" value="pi-users" />
<ui:param name="iconColor" value="blue-600" />
<ui:param name="growthValue" value="#{dashboardBean.membresEvolutionPourcent}" />
<ui:param name="growthLabel" value="ce mois" />
<ui:param name="progressValue" value="#{dashboardBean.tauxActivite}" />
</ui:include>
<!-- Visible pour : SECRETAIRE, TRESORIER, RESPONSABLE_SOCIAL, RESPONSABLE_EVENEMENTS, ADMIN -->
<ui:fragment rendered="#{menuBean.isSecretaire() or menuBean.isTresorier() or menuBean.isResponsableSocial() or menuBean.isResponsableEvenements() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Membres Actifs" />
<ui:param name="value" value="#{dashboardBean.activeMembers}" />
<ui:param name="icon" value="pi-users" />
<ui:param name="iconColor" value="blue-600" />
<ui:param name="growthValue" value="#{dashboardBean.membresEvolutionPourcent}" />
<ui:param name="growthLabel" value="ce mois" />
<ui:param name="progressValue" value="#{dashboardBean.tauxActivite}" />
</ui:include>
</ui:fragment>
<!-- 2. FINANCES : Santé financière - crucial pour la survie -->
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="FCFA Collectés" />
<ui:param name="value" value="#{dashboardBean.totalCotisations}" />
<ui:param name="icon" value="pi-dollar" />
<ui:param name="iconColor" value="green-600" />
<ui:param name="growthValue" value="#{dashboardBean.cotisationsEvolutionPourcent}" />
<ui:param name="growthLabel" value="vs mois dernier" />
<ui:param name="progressValue" value="#{dashboardBean.tauxObjectifCotisations}" />
</ui:include>
<!-- Visible pour : TRESORIER, ADMIN uniquement -->
<ui:fragment rendered="#{menuBean.isTresorier() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="FCFA Collectés" />
<ui:param name="value" value="#{dashboardBean.totalCotisations}" />
<ui:param name="icon" value="pi-dollar" />
<ui:param name="iconColor" value="green-600" />
<ui:param name="growthValue" value="#{dashboardBean.cotisationsEvolutionPourcent}" />
<ui:param name="growthLabel" value="vs mois dernier" />
<ui:param name="progressValue" value="#{dashboardBean.tauxObjectifCotisations}" />
</ui:include>
</ui:fragment>
<!-- 3. SOLIDARITÉ : Impact social - raison d'être -->
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="FCFA Distribués" />
<ui:param name="value" value="#{dashboardBean.aidesDistribuees}" />
<ui:param name="icon" value="pi-heart" />
<ui:param name="iconColor" value="purple-600" />
<ui:param name="statusIcon" value="pi-circle-fill" />
<ui:param name="statusLabel" value="Demandes en attente" />
<ui:param name="statusValue" value="#{dashboardBean.pendingAides}" />
<ui:param name="progressValue" value="#{dashboardBean.tauxAidesTraitees}" />
</ui:include>
<!-- Visible pour : TRESORIER, RESPONSABLE_SOCIAL, ADMIN -->
<ui:fragment rendered="#{menuBean.isTresorier() or menuBean.isResponsableSocial() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="FCFA Distribués" />
<ui:param name="value" value="#{dashboardBean.aidesDistribuees}" />
<ui:param name="icon" value="pi-heart" />
<ui:param name="iconColor" value="purple-600" />
<ui:param name="statusIcon" value="pi-circle-fill" />
<ui:param name="statusLabel" value="Demandes en attente" />
<ui:param name="statusValue" value="#{dashboardBean.pendingAides}" />
<ui:param name="progressValue" value="#{dashboardBean.tauxAidesTraitees}" />
</ui:include>
</ui:fragment>
<!-- 4. ENGAGEMENT : Vitalité de l'organisation -->
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Taux de Participation" />
<ui:param name="value" value="#{dashboardBean.tauxParticipation}%" />
<ui:param name="icon" value="pi-chart-line" />
<ui:param name="iconColor" value="orange-600" />
<ui:param name="statusIcon" value="pi-calendar" />
<ui:param name="statusLabel" value="Événements prévus" />
<ui:param name="statusValue" value="#{dashboardBean.upcomingEvents}" />
<ui:param name="progressValue" value="#{dashboardBean.tauxEngagement}" />
</ui:include>
<!-- Visible pour : RESPONSABLE_EVENEMENTS, ADMIN -->
<ui:fragment rendered="#{menuBean.isResponsableEvenements() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Taux de Participation" />
<ui:param name="value" value="#{dashboardBean.tauxParticipation}%" />
<ui:param name="icon" value="pi-chart-line" />
<ui:param name="iconColor" value="orange-600" />
<ui:param name="statusIcon" value="pi-calendar" />
<ui:param name="statusLabel" value="Événements prévus" />
<ui:param name="statusValue" value="#{dashboardBean.upcomingEvents}" />
<ui:param name="progressValue" value="#{dashboardBean.tauxEngagement}" />
</ui:include>
</ui:fragment>
<!-- Tendances financières et analyses -->
<div class="col-12 lg:col-8">
<div class="card">
<!-- Visible pour : TRESORIER, ADMIN uniquement -->
<ui:fragment rendered="#{menuBean.isTresorier() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="col-12 lg:col-8">
<div class="card">
<div class="flex align-items-center justify-content-between mb-4">
<h5>Évolution financière (3 derniers mois)</h5>
<div>
@@ -239,7 +260,11 @@
</h:panelGroup>
</div>
</div>
</ui:fragment>
<!-- État des cotisations -->
<!-- Visible pour : TRESORIER, ADMIN uniquement -->
<ui:fragment rendered="#{menuBean.isTresorier() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="col-12 lg:col-4">
<div class="card">
<h5>État des cotisations</h5>
@@ -303,7 +328,8 @@
</div>
</div>
</div>
</ui:fragment>
<!-- Journal d'activités et Tâches prioritaires -->
<div class="col-12 lg:col-8">
<h:form>
@@ -376,110 +402,142 @@
<!-- Actions rapides et Tâches -->
<div class="col-12 lg:col-4">
<h:form>
<div class="card mb-4">
<h5>Actions rapides</h5>
<div class="grid">
<div class="col-6">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Nouveau membre" />
<ui:param name="icon" value="pi pi-user-plus" />
<ui:param name="action" value="#{dashboardBean.redirectToNewMember}" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
</ui:include>
</div>
<div class="col-6">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Collecter" />
<ui:param name="icon" value="pi pi-wallet" />
<ui:param name="action" value="#{dashboardBean.redirectToCotisation}" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
</ui:include>
</div>
<div class="col-6">
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Événement" />
<ui:param name="icon" value="pi pi-calendar-plus" />
<ui:param name="action" value="#{dashboardBean.redirectToEvenement}" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
</ui:include>
</div>
<div class="col-6">
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Rapport" />
<ui:param name="icon" value="pi pi-chart-bar" />
<ui:param name="action" value="#{dashboardBean.generateRapport}" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
</ui:include>
<!-- Actions rapides - Visibilité selon rôles -->
<ui:fragment rendered="#{menuBean.isSecretaire() or menuBean.isTresorier() or menuBean.isResponsableEvenements() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="card mb-4">
<h5>Actions rapides</h5>
<div class="grid">
<!-- Nouveau membre : SECRETAIRE, ADMIN -->
<ui:fragment rendered="#{menuBean.isSecretaire() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="col-6">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Nouveau membre" />
<ui:param name="icon" value="pi pi-user-plus" />
<ui:param name="action" value="#{dashboardBean.redirectToNewMember}" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
</ui:include>
</div>
</ui:fragment>
<!-- Collecter : TRESORIER, ADMIN -->
<ui:fragment rendered="#{menuBean.isTresorier() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="col-6">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Collecter" />
<ui:param name="icon" value="pi pi-wallet" />
<ui:param name="action" value="#{dashboardBean.redirectToCotisation}" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
</ui:include>
</div>
</ui:fragment>
<!-- Événement : RESPONSABLE_EVENEMENTS, SECRETAIRE, ADMIN -->
<ui:fragment rendered="#{menuBean.isResponsableEvenements() or menuBean.isSecretaire() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="col-6">
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Événement" />
<ui:param name="icon" value="pi pi-calendar-plus" />
<ui:param name="action" value="#{dashboardBean.redirectToEvenement}" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
</ui:include>
</div>
</ui:fragment>
<!-- Rapport : TRESORIER, SECRETAIRE, ADMIN -->
<ui:fragment rendered="#{menuBean.isTresorier() or menuBean.isSecretaire() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="col-6">
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Rapport" />
<ui:param name="icon" value="pi pi-chart-bar" />
<ui:param name="action" value="#{dashboardBean.generateRapport}" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
</ui:include>
</div>
</ui:fragment>
</div>
</div>
</div>
</ui:fragment>
</h:form>
<div class="card">
<h5>Tâches prioritaires</h5>
<div class="flex flex-column gap-3">
<div class="flex align-items-center p-3 border-round bg-blue-50 border-blue-200">
<i class="pi pi-check-circle text-blue-500 text-xl mr-3"></i>
<div class="flex-1">
<div class="text-900 font-medium">Valider #{dashboardBean.adhesionsPendantes} adhésions</div>
<small class="text-600">Demandes en attente de validation</small>
</div>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-arrow-right" />
<ui:param name="action" value="#{dashboardBean.redirectToAdhesionValidation}" />
<ui:param name="severity" value="info" />
</ui:include>
</div>
<div class="flex align-items-center p-3 border-round bg-orange-50 border-orange-200">
<i class="pi pi-exclamation-triangle text-orange-500 text-xl mr-3"></i>
<div class="flex-1">
<div class="text-900 font-medium">Relancer #{dashboardBean.cotisationsRetard} cotisations</div>
<small class="text-600">Paiements en retard</small>
</div>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-arrow-right" />
<ui:param name="action" value="#{dashboardBean.redirectToRelances}" />
<ui:param name="severity" value="warning" />
</ui:include>
</div>
<div class="flex align-items-center p-3 border-round bg-green-50 border-green-200">
<i class="pi pi-heart text-green-500 text-xl mr-3"></i>
<div class="flex-1">
<div class="text-900 font-medium">Traiter #{dashboardBean.aidesEnAttente} aides</div>
<small class="text-600">Demandes d'aide à examiner</small>
</div>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-arrow-right" />
<ui:param name="action" value="#{dashboardBean.redirectToAidesTraitement}" />
<ui:param name="severity" value="success" />
</ui:include>
</div>
<div class="flex align-items-center p-3 border-round bg-purple-50 border-purple-200">
<i class="pi pi-calendar text-purple-500 text-xl mr-3"></i>
<div class="flex-1">
<div class="text-900 font-medium">Organiser prochains événements</div>
<small class="text-600">#{dashboardBean.evenementsAPlanifier} événements à planifier</small>
</div>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-arrow-right" />
<ui:param name="action" value="#{dashboardBean.redirectToEvenementPlanning}" />
<ui:param name="styleClass" value="ui-button-help" />
</ui:include>
<!-- Tâches prioritaires - Visibilité selon rôles -->
<ui:fragment rendered="#{menuBean.isSecretaire() or menuBean.isTresorier() or menuBean.isResponsableSocial() or menuBean.isResponsableEvenements() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="card">
<h5>Tâches prioritaires</h5>
<div class="flex flex-column gap-3">
<!-- Valider adhésions : SECRETAIRE, ADMIN -->
<ui:fragment rendered="#{menuBean.isSecretaire() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="flex align-items-center p-3 border-round bg-blue-50 border-blue-200">
<i class="pi pi-check-circle text-blue-500 text-xl mr-3"></i>
<div class="flex-1">
<div class="text-900 font-medium">Valider #{dashboardBean.adhesionsPendantes} adhésions</div>
<small class="text-600">Demandes en attente de validation</small>
</div>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-arrow-right" />
<ui:param name="action" value="#{dashboardBean.redirectToAdhesionValidation}" />
<ui:param name="severity" value="info" />
</ui:include>
</div>
</ui:fragment>
<!-- Relancer cotisations : TRESORIER, SECRETAIRE, ADMIN -->
<ui:fragment rendered="#{menuBean.isTresorier() or menuBean.isSecretaire() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="flex align-items-center p-3 border-round bg-orange-50 border-orange-200">
<i class="pi pi-exclamation-triangle text-orange-500 text-xl mr-3"></i>
<div class="flex-1">
<div class="text-900 font-medium">Relancer #{dashboardBean.cotisationsRetard} cotisations</div>
<small class="text-600">Paiements en retard</small>
</div>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-arrow-right" />
<ui:param name="action" value="#{dashboardBean.redirectToRelances}" />
<ui:param name="severity" value="warning" />
</ui:include>
</div>
</ui:fragment>
<!-- Traiter aides : RESPONSABLE_SOCIAL, ADMIN -->
<ui:fragment rendered="#{menuBean.isResponsableSocial() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="flex align-items-center p-3 border-round bg-green-50 border-green-200">
<i class="pi pi-heart text-green-500 text-xl mr-3"></i>
<div class="flex-1">
<div class="text-900 font-medium">Traiter #{dashboardBean.aidesEnAttente} aides</div>
<small class="text-600">Demandes d'aide à examiner</small>
</div>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-arrow-right" />
<ui:param name="action" value="#{dashboardBean.redirectToAidesTraitement}" />
<ui:param name="severity" value="success" />
</ui:include>
</div>
</ui:fragment>
<!-- Organiser événements : RESPONSABLE_EVENEMENTS, ADMIN -->
<ui:fragment rendered="#{menuBean.isResponsableEvenements() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="flex align-items-center p-3 border-round bg-purple-50 border-purple-200">
<i class="pi pi-calendar text-purple-500 text-xl mr-3"></i>
<div class="flex-1">
<div class="text-900 font-medium">Organiser prochains événements</div>
<small class="text-600">#{dashboardBean.evenementsAPlanifier} événements à planifier</small>
</div>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-arrow-right" />
<ui:param name="action" value="#{dashboardBean.redirectToEvenementPlanning}" />
<ui:param name="styleClass" value="ui-button-help" />
</ui:include>
</div>
</ui:fragment>
</div>
</div>
</div>
</ui:fragment>
</div>
<!-- Tableau de bord financier détaillé -->
<div class="col-12">
<div class="card">
<!-- Visible pour : TRESORIER, ADMIN uniquement -->
<ui:fragment rendered="#{menuBean.isTresorier() or menuBean.isAdminOrganisation() or menuBean.isSuperAdmin()}">
<div class="col-12">
<div class="card">
<div class="flex align-items-center justify-content-between mb-4">
<h5>Résumé financier mensuel</h5>
<div class="flex align-items-center gap-2">
@@ -527,6 +585,7 @@
</h:panelGroup>
</div>
</div>
</ui:fragment>
</div>
</ui:define>

View File

@@ -7,7 +7,7 @@
template="/templates/main-template.xhtml">
<f:metadata>
<f:viewParam name="id" value="#{membreCotisationBean.membreId}"/>
<f:viewParam name="id" value="#{membreCotisationBean.membreId}" converter="uuidConverter"/>
<f:event type="preRenderView" listener="#{membreCotisationBean.init}"/>
</f:metadata>
@@ -86,7 +86,7 @@
<!-- Liste des cotisations -->
<div class="card">
<h5 class="mb-3">Historique des Cotisations</h5>
<h5 class="mb-3">Mes Cotisations</h5>
<!-- Filtres -->
<p:toolbar>

View File

@@ -143,7 +143,7 @@
<div class="col-12 md:col-4">
<div class="field">
<p:outputLabel for="organisationFilter" value="Organisation" />
<p:selectOneMenu id="organisationFilter" value="#{membreExportBean.organisationId}" styleClass="w-full">
<p:selectOneMenu id="organisationFilter" value="#{membreExportBean.organisationId}" converter="uuidConverter" styleClass="w-full">
<f:selectItem itemLabel="Toutes les organisations" itemValue="" />
<f:selectItems value="#{membreExportBean.organisationsDisponibles}"
var="org"

View File

@@ -130,7 +130,7 @@
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="organisationImport" value="Organisation par défaut" />
<p:selectOneMenu id="organisationImport" value="#{membreImportBean.organisationId}" styleClass="w-full">
<p:selectOneMenu id="organisationImport" value="#{membreImportBean.organisationId}" converter="uuidConverter" styleClass="w-full">
<f:selectItem itemLabel="Sélectionner une organisation..." itemValue="" />
<f:selectItems value="#{membreImportBean.organisationsDisponibles}"
var="org"

View File

@@ -6,6 +6,11 @@
xmlns:p="http://primefaces.org/ui"
template="/templates/main-template.xhtml">
<!-- Sécurisation de la page basée sur les rôles -->
<ui:include src="/templates/components/security/page-access-control.xhtml">
<ui:param name="allowedRoles" value="SECRETAIRE,ADMIN" />
</ui:include>
<ui:param name="page" value="#{membreInscriptionBean}"/>
<ui:define name="title">Inscription Membre - UnionFlow</ui:define>
@@ -268,7 +273,7 @@
<ui:define name="content">
<div class="field">
<p:outputLabel for="organisationId" value="Organisation *" styleClass="font-bold text-primary" />
<p:selectOneMenu id="organisationId" value="#{membreInscriptionBean.organisationId}" required="true" requiredMessage="Vous devez sélectionner une organisation" styleClass="w-full">
<p:selectOneMenu id="organisationId" value="#{membreInscriptionBean.organisationId}" converter="uuidConverter" required="true" requiredMessage="Vous devez sélectionner une organisation" styleClass="w-full">
<f:selectItem itemLabel="--- Sélectionner une organisation ---" itemValue="" noSelectionOption="true" />
<f:selectItems value="#{membreInscriptionBean.organisationsDisponibles}"
var="org"

View File

@@ -19,16 +19,20 @@
<ui:param name="styleClass" value="mb-3" />
<ui:define name="actions">
<p:button value="Nouveau Membre" icon="pi pi-user-plus" outcome="membreInscriptionPage"
styleClass="ui-button-success mr-2" />
styleClass="ui-button-success mr-2"
rendered="#{menuBean.gestionMembresMenuVisible}" />
<p:commandButton value="Import / Export" icon="pi pi-file-excel"
onclick="PF('dlgImportExport').show();" type="button" styleClass="ui-button-info" />
onclick="PF('dlgImportExport').show();" type="button" styleClass="ui-button-info"
rendered="#{menuBean.gestionMembresMenuVisible}" />
</ui:define>
</ui:decorate>
<!-- ================================================================
STATISTIQUES (DRY/WOU: stat-card)
Visible uniquement pour SECRETAIRE, ADMIN (pas MEMBRE_ACTIF)
================================================================ -->
<h:panelGroup id="panelStatistiques" layout="block" styleClass="grid mb-3">
<h:panelGroup id="panelStatistiques" layout="block" styleClass="grid mb-3"
rendered="#{menuBean.gestionMembresMenuVisible}">
<div class="col-12 md:col-3">
<ui:decorate template="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{membreListeBean.totalMembres}" />
@@ -125,10 +129,11 @@
<!-- ================================================================
ACTIONS GROUPÉES (visible si sélection)
Visible uniquement pour SECRETAIRE, ADMIN (actions administratives)
================================================================ -->
<h:panelGroup id="panelActionsGroupeesWrapper">
<h:panelGroup id="panelActionsGroupees" layout="block" styleClass="flex gap-2 mb-3"
rendered="#{not empty membreListeBean.selectedMembres}">
rendered="#{not empty membreListeBean.selectedMembres and menuBean.gestionMembresMenuVisible}">
<p:commandButton value="Rappel Cotisations" icon="pi pi-bell"
action="#{membreListeBean.rappelCotisationsGroupe}" update="messages"
styleClass="ui-button-warning ui-button-sm" />
@@ -157,8 +162,9 @@
<p:ajax event="rowUnselect" update=":formMembres:panelActionsGroupeesWrapper" />
<p:ajax event="toggleSelect" update=":formMembres:panelActionsGroupeesWrapper" />
<!-- Colonne sélection checkbox -->
<p:column selectionMode="multiple" headerText="" style="width: 3rem; text-align: center;" />
<!-- Colonne sélection checkbox - ADMIN SEULEMENT (pour actions groupées) -->
<p:column selectionMode="multiple" headerText="" style="width: 3rem; text-align: center;"
rendered="#{menuBean.gestionMembresMenuVisible}" />
<!-- Colonne: Membre (Nom + Email) -->
<ui:decorate template="/templates/components/columns/column-name-with-subtitle.xhtml">
@@ -225,9 +231,10 @@
<f:param name="id" value="#{membre.id}" />
</p:button>
<!-- Éditer -->
<!-- Éditer - ADMIN SEULEMENT -->
<p:button icon="pi pi-pencil" outcome="membreModifierPage" title="Modifier"
styleClass="ui-button-warning ui-button-sm ui-button-rounded mr-1">
styleClass="ui-button-warning ui-button-sm ui-button-rounded mr-1"
rendered="#{menuBean.gestionMembresMenuVisible}">
<f:param name="id" value="#{membre.id}" />
</p:button>
@@ -237,31 +244,34 @@
oncomplete="PF('dlgContact').show();" update=":dlgContact"
styleClass="ui-button-help ui-button-sm ui-button-rounded mr-1" />
<!-- Suspendre (visible si actif) -->
<!-- Suspendre - ADMIN SEULEMENT (visible si actif) -->
<p:commandButton icon="pi pi-ban" title="Suspendre"
action="#{membreListeBean.suspendreMembre(membre)}"
update="dtMembres messages panelStatistiques" rendered="#{membre.statut == 'ACTIF'}"
styleClass="ui-button-danger ui-button-sm ui-button-rounded mr-1">
<p:confirm header="Confirmation" message="Suspendre #{membre.nomComplet} ?"
icon="pi pi-exclamation-triangle" />
</p:commandButton>
actionListener="#{membreListeBean.preparerSuspendre(membre)}"
update=":formMembres:dlgConfirmSuspendre"
oncomplete="PF('dlgConfirmSuspendre').show();"
rendered="#{menuBean.gestionMembresMenuVisible and membre.statut == 'ACTIF'}"
styleClass="ui-button-danger ui-button-sm ui-button-rounded mr-1" />
<!-- Réactiver (visible si suspendu) -->
<!-- Réactiver - ADMIN SEULEMENT (visible si suspendu) -->
<p:commandButton icon="pi pi-replay" title="Réactiver"
action="#{membreListeBean.reactiverMembre(membre)}"
update="dtMembres messages panelStatistiques" rendered="#{membre.statut == 'SUSPENDU'}"
update="dtMembres messages panelStatistiques"
rendered="#{menuBean.gestionMembresMenuVisible and membre.statut == 'SUSPENDU'}"
styleClass="ui-button-success ui-button-sm ui-button-rounded" />
</ui:define>
</ui:decorate>
</p:dataTable>
<!-- Confirmation dialog global -->
<p:confirmDialog global="true" showEffect="fade" hideEffect="fade" responsive="true" width="450">
<p:commandButton value="Oui" type="button" styleClass="ui-button-danger ui-confirmdialog-yes"
icon="pi pi-check" />
<p:commandButton value="Non" type="button" styleClass="ui-button-secondary ui-confirmdialog-no"
icon="pi pi-times" />
</p:confirmDialog>
<p:dialog id="dlgConfirmSuspendre" widgetVar="dlgConfirmSuspendre" header="Confirmation" modal="true" width="400" showEffect="fade" hideEffect="fade">
<p class="mb-3">Suspendre ce membre ?</p>
<f:facet name="footer">
<p:commandButton value="Non" icon="pi pi-times" styleClass="ui-button-secondary" onclick="PF('dlgConfirmSuspendre').hide();" />
<p:commandButton value="Oui" icon="pi pi-check" styleClass="ui-button-danger" process="@this"
actionListener="#{membreListeBean.confirmerSuspendre}"
update=":formMembres:dtMembres :formMembres:messages :formMembres:panelStatistiques"
oncomplete="PF('dlgConfirmSuspendre').hide();" />
</f:facet>
</p:dialog>
</h:form>
<!-- ================================================================

View File

@@ -188,8 +188,8 @@
</p:column>
<!-- Type -->
<p:column headerText="Type" sortBy="#{org.typeAssociation}" style="width: 11rem;">
<p:tag value="#{org.typeLibelle}"
<p:column headerText="Type" sortBy="#{org.typeOrganisation}" style="width: 11rem;">
<p:tag value="#{org.typeOrganisationLibelle}"
severity="info"
styleClass="text-xs" />
</p:column>
@@ -247,37 +247,40 @@
<p:commandButton icon="#{org.statut == organisationsBean.statutActive ? 'pi pi-ban' : 'pi pi-check'}"
styleClass="ui-button-rounded ui-button-text ui-button-sm #{org.statut == organisationsBean.statutActive ? 'ui-button-secondary' : 'ui-button-success'}"
title="#{org.statut == organisationsBean.statutActive ? 'Désactiver' : 'Activer'}"
actionListener="#{organisationsBean.basculerStatutOrganisation(org)}"
update=":panelKPIs :formOrganisations:dtOrganisations :formOrganisations:messages">
<p:confirm header="Confirmation"
message="Changer le statut de cette organisation ?"
icon="pi pi-exclamation-triangle" />
</p:commandButton>
actionListener="#{organisationsBean.preparerBasculerStatut(org)}"
update=":formOrganisations:dlgConfirmStatut"
oncomplete="PF('dlgConfirmStatut').show();" />
<p:commandButton icon="pi pi-trash"
styleClass="ui-button-rounded ui-button-text ui-button-danger ui-button-sm"
title="Supprimer"
actionListener="#{organisationsBean.supprimerOrganisation(org)}"
update=":panelKPIs :formOrganisations:dtOrganisations :formOrganisations:messages">
<p:confirm header="Confirmation"
message="Supprimer définitivement cette organisation ? Cette action est irréversible."
icon="pi pi-exclamation-triangle" />
</p:commandButton>
actionListener="#{organisationsBean.preparerSuppression(org)}"
update=":formOrganisations:dlgConfirmSuppr"
oncomplete="PF('dlgConfirmSuppr').show();" />
</div>
</p:column>
</p:dataTable>
<p:confirmDialog global="true" showEffect="fade" hideEffect="fade" responsive="true" width="380">
<p:commandButton value="Non"
type="button"
styleClass="ui-button-secondary ui-button-outlined"
icon="pi pi-times"
onclick="PF('confirmDialog').hide()" />
<p:commandButton value="Oui"
type="button"
styleClass="ui-button-danger"
icon="pi pi-check" />
</p:confirmDialog>
<p:dialog id="dlgConfirmStatut" widgetVar="dlgConfirmStatut" header="Confirmation" modal="true" width="380" showEffect="fade" hideEffect="fade">
<p class="mb-3">Changer le statut de cette 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=":panelKPIs :formOrganisations:dtOrganisations :formOrganisations:messages"
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 définitivement 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=":panelKPIs :formOrganisations:dtOrganisations :formOrganisations:messages"
oncomplete="PF('dlgConfirmSuppr').hide();" />
</f:facet>
</p:dialog>
</h:form>
</div>

View File

@@ -124,31 +124,40 @@
<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"
update=":formOrgs:dtOrgs :formOrgs:messages :formOrgs:stats"
actionListener="#{organisationsBean.basculerStatutOrganisation(org)}">
<p:confirm header="Confirmation"
message="Confirmez l'action sur le statut de l'organisation ?"
icon="pi pi-exclamation-triangle" />
</p:commandButton>
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"
update=":formOrgs:dtOrgs :formOrgs:messages :formOrgs:stats"
actionListener="#{organisationsBean.supprimerOrganisation(org)}">
<p:confirm header="Confirmation"
message="Supprimer cette organisation ?"
icon="pi pi-exclamation-triangle" />
</p:commandButton>
actionListener="#{organisationsBean.preparerSuppression(org)}"
update=":formOrgs:dlgConfirmSuppr"
oncomplete="PF('dlgConfirmSuppr').show();" />
</p:column>
</p:dataTable>
</div>
<p:confirmDialog global="true" showEffect="fade" hideEffect="fade" responsive="true" width="350">
<p:commandButton value="Non" type="button" styleClass="ui-button-secondary" icon="pi pi-times"
onclick="PF('confirmDialog').hide()" />
<p:commandButton value="Oui" type="button" styleClass="ui-button-danger" icon="pi pi-check" />
</p:confirmDialog>
<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"

View File

@@ -226,13 +226,23 @@
styleClass="p-button-sm p-button-rounded"
style="background-color: #dc3545 !important; border-color: #dc3545 !important; color: white !important;"
title="Supprimer"
rendered="#{role.supprimable}">
<p:confirm message="Êtes-vous sûr de vouloir supprimer ce rôle ?"
icon="pi pi-exclamation-triangle" />
</p:commandButton>
rendered="#{role.supprimable}"
actionListener="#{rolesBean.preparerSuppression(role)}"
update=":tableauForm:dlgConfirmSupprRole"
oncomplete="PF('dlgConfirmSupprRole').show();" />
</div>
</p:column>
</p:dataTable>
<p:dialog id="dlgConfirmSupprRole" widgetVar="dlgConfirmSupprRole" header="Supprimer le rôle" modal="true" width="400" showEffect="fade" hideEffect="fade">
<p class="mb-3">Êtes-vous sûr de vouloir supprimer ce rôle ?</p>
<f:facet name="footer">
<p:commandButton value="Non" icon="pi pi-times" styleClass="ui-button-secondary" onclick="PF('dlgConfirmSupprRole').hide();" />
<p:commandButton value="Oui" icon="pi pi-check" styleClass="ui-button-danger" process="@this"
actionListener="#{rolesBean.confirmerSuppression}"
update=":tableauForm:tableauRoles"
oncomplete="PF('dlgConfirmSupprRole').hide();" />
</f:facet>
</p:dialog>
</h:form>
</div>
</div>

View File

@@ -10,7 +10,7 @@
<ui:define name="content">
<h:form id="formTypes">
<p:messages id="messages" showDetail="true" closable="true" />
<p:messages id="messages" showDetail="true" closable="true" globalOnly="true" />
<div class="card mb-3">
<div class="flex justify-content-between align-items-center">
@@ -67,7 +67,7 @@
severity="#{type.actif ? 'success' : 'danger'}" />
</p:column>
<p:column headerText="Actions" style="width: 140px; text-align: center;">
<p:column headerText="Actions" style="width: 160px; text-align: center;">
<p:commandButton icon="pi pi-pencil"
title="Modifier"
styleClass="ui-button-rounded ui-button-warning mr-2"
@@ -75,24 +75,40 @@
actionListener="#{typeOrganisationsAdminBean.setTypeSelectionne(type)}"
oncomplete="PF('dlgType').show();" />
<p:commandButton icon="pi pi-ban"
title="Désactiver"
styleClass="ui-button-rounded ui-button-secondary"
update="@form"
actionListener="#{typeOrganisationsAdminBean.desactiverType(type.id)}">
<p:confirm header="Confirmation"
message="Désactiver ce type d'organisation ?"
icon="pi pi-exclamation-triangle" />
</p:commandButton>
<p:commandButton icon="pi pi-trash"
title="Supprimer"
styleClass="ui-button-rounded ui-button-danger"
actionListener="#{typeOrganisationsAdminBean.preparerSuppression(type.id)}"
update=":formTypes:dlgConfirmSuppr"
oncomplete="PF('dlgConfirmSuppr').show();" />
</p:column>
</p:dataTable>
</div>
<p:confirmDialog global="true" showEffect="fade" hideEffect="fade" responsive="true" width="350">
<p:commandButton value="Non" type="button" styleClass="ui-button-secondary" icon="pi pi-times"
onclick="PF('confirmDialog').hide()" />
<p:commandButton value="Oui" type="button" styleClass="ui-button-danger" icon="pi pi-check" />
</p:confirmDialog>
<!-- Dialogue de confirmation de suppression (flux explicite pour exécution fiable) -->
<p:dialog id="dlgConfirmSuppr"
widgetVar="dlgConfirmSuppr"
header="Supprimer le type"
modal="true"
resizable="false"
width="400"
showEffect="fade"
hideEffect="fade">
<p class="mb-3">Supprimer définitivement ce type d'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="#{typeOrganisationsAdminBean.confirmerSuppression}"
update="@form"
oncomplete="PF('dlgConfirmSuppr').hide();" />
</f:facet>
</p:dialog>
<!-- Dialogue création / édition type -->
<p:dialog id="dlgType"
@@ -153,8 +169,8 @@
<p:commandButton value="Enregistrer"
icon="pi pi-check"
process="@form"
update=":formTypes:dtTypes :formTypes:messages"
process="dlgType @this"
update=":formTypes:dlgType :formTypes:dtTypes :formTypes:messages"
actionListener="#{typeOrganisationsAdminBean.enregistrerType}"
oncomplete="if(!args.validationFailed) PF('dlgType').hide();" />
</f:facet>