Configure Maven repository for unionflow-server-api dependency

This commit is contained in:
dahoud
2025-12-10 01:12:54 +00:00
commit 2910809949
1173 changed files with 435718 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
<!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">Accès Refusé - UnionFlow</ui:define>
<ui:define name="content">
<div class="flex align-items-center justify-content-center min-h-screen">
<div class="surface-card p-6 shadow-2 border-round text-center" style="max-width: 500px;">
<!-- Icône d'erreur -->
<div class="text-red-500 mb-4">
<i class="pi pi-lock" style="font-size: 4rem;"></i>
</div>
<!-- Titre -->
<h2 class="text-900 font-bold text-4xl mb-3">Accès Refusé</h2>
<!-- Message -->
<div class="text-600 mb-5">
<p class="mb-3">Vous n'avez pas les permissions nécessaires pour accéder à cette page.</p>
<p class="text-sm">
Connecté en tant que : <strong>#{userSession.currentUser.nomComplet}</strong><br/>
Type de compte : <strong>#{userSession.typeCompte}</strong>
</p>
</div>
<!-- Actions -->
<h:form>
<div class="flex gap-3 justify-content-center">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Retour au tableau de bord" />
<ui:param name="icon" value="pi pi-home" />
<ui:param name="action" value="#{navigationBean.goToDashboard}" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Se déconnecter" />
<ui:param name="icon" value="pi pi-sign-out" />
<ui:param name="action" value="#{loginBean.logout}" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</h:form>
<!-- Contact support -->
<div class="mt-5 pt-4 border-top-1 surface-border">
<p class="text-600 text-sm mb-2">Besoin d'aide ?</p>
<p:link href="mailto:support@unionflow.dev"
value="Contacter le support technique"
styleClass="text-primary font-medium" />
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,115 @@
<!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:param name="page" value="#{adhesionsBean}"/>
<ui:define name="title">Demande d'Adhésion - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-user-plus text-green-500" />
<ui:param name="title" value="Demande d'Adhésion" />
<ui:param name="description" value="Formulaire de demande d'adhésion à une organisation" />
</ui:include>
<!-- Formulaire de demande -->
<div class="card">
<h:form id="formDemande">
<h5>Nouvelle Demande d'Adhésion</h5>
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Informations du Membre" />
<ui:define name="content">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="membreId" value="Membre" />
<p:selectOneMenu id="membreId"
value="#{adhesionsBean.nouvelleAdhesion.membreId}"
required="true"
requiredMessage="Veuillez sélectionner un membre"
filter="true"
filterMatchMode="contains"
styleClass="w-full">
<f:selectItems value="#{adhesionsBean.membresSelectItems}" />
</p:selectOneMenu>
<p:message for="membreId" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="organisationId" value="Organisation" />
<p:selectOneMenu id="organisationId"
value="#{adhesionsBean.nouvelleAdhesion.organisationId}"
required="true"
requiredMessage="Veuillez sélectionner une organisation"
filter="true"
filterMatchMode="contains"
styleClass="w-full">
<f:selectItems value="#{adhesionsBean.associationsSelectItems}" />
</p:selectOneMenu>
<p:message for="organisationId" />
</div>
</div>
</div>
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Frais d'Adhésion" />
<ui:define name="content">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="fraisAdhesion" value="Frais d'adhésion (FCFA)" />
<p:inputNumber id="fraisAdhesion"
value="#{adhesionsBean.nouvelleAdhesion.fraisAdhesion}"
symbol=""
minValue="0"
styleClass="w-full" />
</div>
</div>
</div>
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Observations" />
<ui:define name="content">
<div class="grid">
<div class="col-12">
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="observations" />
<ui:param name="label" value="Observations (optionnel)" />
<ui:param name="value" value="#{adhesionsBean.nouvelleAdhesion.observations}" />
<ui:param name="rows" value="4" />
</ui:include>
</div>
</div>
</ui:define>
</ui:include>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="action" value="#{navigationBean.goToDashboard}" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Soumettre la demande" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{adhesionsBean.enregistrerAdhesion}" />
<ui:param name="update" value="@form" />
</ui:include>
</div>
</h:form>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,259 @@
<!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:param name="page" value="#{adhesionsBean}"/>
<ui:define name="title">Historique des Adhésions - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-history text-blue-500" />
<ui:param name="title" value="Historique des Adhésions" />
<ui:param name="description" value="Consultation de l'historique complet des adhésions" />
<ui:define name="actions">
<h:form id="formActionsHistory">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{adhesionsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Filtres d'historique -->
<div class="card">
<h:form id="formFiltresHistory">
<h5>Filtres de Recherche</h5>
<div class="grid">
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateDebut" />
<ui:param name="label" value="Date début" />
<ui:param name="value" value="#{adhesionsBean.filtres.dateDebut}" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateFin" />
<ui:param name="label" value="Date fin" />
<ui:param name="value" value="#{adhesionsBean.filtres.dateFin}" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="statutHistory" />
<ui:param name="label" value="Statut" />
<ui:param name="value" value="#{adhesionsBean.filtres.statut}" />
<ui:define name="items">
<f:selectItem itemLabel="Tous" itemValue="" />
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE" />
<f:selectItem itemLabel="Approuvée" itemValue="APPROUVEE" />
<f:selectItem itemLabel="Rejetée" itemValue="REJETEE" />
<f:selectItem itemLabel="Payée" itemValue="PAYEE" />
<f:selectItem itemLabel="En paiement" itemValue="EN_PAIEMENT" />
<f:selectItem itemLabel="Annulée" itemValue="ANNULEE" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel />
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Rechercher" />
<ui:param name="icon" value="pi pi-search" />
<ui:param name="action" value="#{adhesionsBean.rechercher}" />
<ui:param name="update" value=":formHistory" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Réinitialiser" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="action" value="#{adhesionsBean.reinitialiserFiltres}" />
<ui:param name="update" value="@form :formHistory" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</div>
</div>
</div>
</h:form>
</div>
<!-- Tableau d'historique -->
<div class="card">
<h:form id="formHistory">
<h5>Historique des Adhésions</h5>
<p:dataTable id="dtHistory"
value="#{adhesionsBean.adhesionsFiltrees}"
var="adhesion"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50,100"
sortMode="multiple"
emptyMessage="Aucune adhésion trouvée">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Historique (#{adhesionsBean.adhesionsFiltrees.size()} adhésion(s))</span>
</div>
</f:facet>
<p:column headerText="Date" sortBy="#{adhesion.dateDemande}" style="width:120px">
<h:outputText value="#{adhesion.dateDemandeFormatee}" />
</p:column>
<p:column headerText="Référence" sortBy="#{adhesion.numeroReference}" style="width:150px">
<h:outputText value="#{adhesion.numeroReference}" />
</p:column>
<p:column headerText="Membre" sortBy="#{adhesion.nomMembre}">
<div>
<div class="font-medium">#{adhesion.nomMembre}</div>
<div class="text-600 text-sm">#{adhesion.numeroMembre}</div>
</div>
</p:column>
<p:column headerText="Organisation" sortBy="#{adhesion.nomOrganisation}">
<h:outputText value="#{adhesion.nomOrganisation}" />
</p:column>
<p:column headerText="Frais" sortBy="#{adhesion.fraisAdhesion}" style="width:120px">
<h:outputText value="#{adhesion.fraisAdhesionFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Statut" sortBy="#{adhesion.statut}" style="width:150px">
<p:tag value="#{adhesion.statutLibelle}"
severity="#{adhesion.statutSeverity}"
icon="#{adhesion.statutIcon}" />
</p:column>
<p:column headerText="Date Approbation" sortBy="#{adhesion.dateApprobation}" style="width:150px">
<h:outputText value="#{adhesion.dateApprobationFormatee}" />
</p:column>
<p:column headerText="Date Paiement" sortBy="#{adhesion.datePaiement}" style="width:150px">
<h:outputText value="#{adhesion.datePaiementFormatee}" />
</p:column>
<p:column headerText="Actions" style="width:100px">
<p:commandButton icon="pi pi-eye"
title="Voir les détails"
styleClass="p-button-rounded p-button-text p-button-info"
action="#{adhesionsBean.selectionnerAdhesion(adhesion)}"
update=":formDetailsAdhesion"
oncomplete="PF('dlgDetailsAdhesion').show();" />
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Détails Adhésion -->
<p:dialog header="Détails de l'Adhésion" widgetVar="dlgDetailsAdhesion" modal="true" width="600" resizable="false">
<h:form id="formDetailsAdhesion">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Référence</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Statut</label>
<p:tag value="#{adhesionsBean.adhesionSelectionnee.statutLibelle}"
severity="#{adhesionsBean.adhesionSelectionnee.statutSeverity}" />
</div>
</div>
<div class="col-12">
<div class="field">
<label class="font-medium">Membre</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">N° #{adhesionsBean.adhesionSelectionnee.numeroMembre}</p>
</div>
</div>
<div class="col-12">
<div class="field">
<label class="font-medium">Organisation</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.nomOrganisation}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date de demande</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.dateDemandeFormatee}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Frais d'adhésion</label>
<p class="text-600 font-bold">#{adhesionsBean.adhesionSelectionnee.fraisAdhesionFormatte}</p>
</div>
</div>
<div class="col-12 md:col-4">
<div class="field">
<label class="font-medium">Montant payé</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.montantPayeFormatte}</p>
</div>
</div>
<div class="col-12 md:col-4">
<div class="field">
<label class="font-medium">Montant restant</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.montantRestantFormatte}</p>
</div>
</div>
<div class="col-12 md:col-4">
<div class="field">
<label class="font-medium">Date d'approbation</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.dateApprobationFormatee}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date de paiement</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.datePaiementFormatee}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Méthode de paiement</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.methodePaiementLibelle}</p>
</div>
</div>
<div class="col-12" rendered="#{adhesionsBean.adhesionSelectionnee.observations != null}">
<div class="field">
<label class="font-medium">Observations</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.observations}</p>
</div>
</div>
<div class="col-12" rendered="#{adhesionsBean.adhesionSelectionnee.motifRejet != null}">
<div class="field">
<label class="font-medium">Motif de rejet</label>
<p class="text-600 text-red-500">#{adhesionsBean.adhesionSelectionnee.motifRejet}</p>
</div>
</div>
</div>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,417 @@
<!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:param name="page" value="#{adhesionsBean}"/>
<ui:define name="title">Liste des Adhésions - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-users text-blue-500" />
<ui:param name="title" value="Liste des Adhésions" />
<ui:param name="description" value="Gestion complète des demandes d'adhésion" />
<ui:define name="actions">
<h:form id="formActionsListe">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Nouvelle adhésion" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="onclick" value="PF('dlgNouvelleAdhesion').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{adhesionsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.totalAdhesions}" />
<ui:param name="label" value="Total Adhésions" />
<ui:param name="icon" value="pi pi-users" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.adhesionsEnAttente}" />
<ui:param name="label" value="En Attente" />
<ui:param name="icon" value="pi pi-clock" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.adhesionsApprouvees}" />
<ui:param name="label" value="Approuvées" />
<ui:param name="icon" value="pi pi-check-circle" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.tauxApprobationInt}%" />
<ui:param name="label" value="Taux d'Approbation" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Filtres -->
<div class="card">
<h:form id="formFiltres">
<h5>Filtres de Recherche</h5>
<div class="grid">
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="filtreStatut" />
<ui:param name="label" value="Statut" />
<ui:param name="value" value="#{adhesionsBean.filtres.statut}" />
<ui:define name="items">
<f:selectItem itemLabel="Tous" itemValue="" />
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE" />
<f:selectItem itemLabel="Approuvée" itemValue="APPROUVEE" />
<f:selectItem itemLabel="Rejetée" itemValue="REJETEE" />
<f:selectItem itemLabel="Payée" itemValue="PAYEE" />
<f:selectItem itemLabel="En paiement" itemValue="EN_PAIEMENT" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="filtreNomMembre" />
<ui:param name="label" value="Nom du membre" />
<ui:param name="value" value="#{adhesionsBean.filtres.nomMembre}" />
<ui:param name="placeholder" value="Rechercher par nom..." />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="filtreDateDebut" />
<ui:param name="label" value="Date début" />
<ui:param name="value" value="#{adhesionsBean.filtres.dateDebut}" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel />
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Rechercher" />
<ui:param name="icon" value="pi pi-search" />
<ui:param name="action" value="#{adhesionsBean.rechercher}" />
<ui:param name="update" value=":formListe" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Réinitialiser" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="action" value="#{adhesionsBean.reinitialiserFiltres}" />
<ui:param name="update" value="@form :formListe" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</div>
</div>
</div>
</h:form>
</div>
<!-- Liste des adhésions -->
<div class="card">
<h:form id="formListe">
<h5>Adhésions</h5>
<p:dataTable id="dtAdhesions"
value="#{adhesionsBean.adhesionsFiltrees}"
var="adhesion"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50,100"
sortMode="multiple"
emptyMessage="Aucune adhésion trouvée"
selection="#{adhesionsBean.adhesionsSelectionnees}"
selectionMode="multiple">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Liste des adhésions (#{adhesionsBean.adhesionsFiltrees.size()} adhésion(s))</span>
</div>
</f:facet>
<p:column selectionMode="multiple" style="width:50px" />
<p:column headerText="Référence" sortBy="#{adhesion.numeroReference}" style="width:150px">
<h:outputText value="#{adhesion.numeroReference}" />
</p:column>
<p:column headerText="Membre" sortBy="#{adhesion.nomMembre}">
<div>
<div class="font-medium">#{adhesion.nomMembre}</div>
<div class="text-600 text-sm">#{adhesion.numeroMembre}</div>
</div>
</p:column>
<p:column headerText="Organisation" sortBy="#{adhesion.nomOrganisation}">
<h:outputText value="#{adhesion.nomOrganisation}" />
</p:column>
<p:column headerText="Date Demande" sortBy="#{adhesion.dateDemande}" style="width:120px">
<h:outputText value="#{adhesion.dateDemandeFormatee}" />
</p:column>
<p:column headerText="Frais" sortBy="#{adhesion.fraisAdhesion}" style="width:120px">
<h:outputText value="#{adhesion.fraisAdhesionFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Statut" sortBy="#{adhesion.statut}" style="width:150px">
<p:tag value="#{adhesion.statutLibelle}"
severity="#{adhesion.statutSeverity}"
icon="#{adhesion.statutIcon}" />
</p:column>
<p:column headerText="Actions" style="width:200px">
<div class="flex gap-1">
<p:commandButton icon="pi pi-eye"
title="Voir les détails"
styleClass="p-button-rounded p-button-text p-button-info"
action="#{adhesionsBean.selectionnerAdhesion(adhesion)}"
update=":formDetailsAdhesion"
oncomplete="PF('dlgDetailsAdhesion').show();" />
<p:commandButton icon="pi pi-check"
title="Approuver"
styleClass="p-button-rounded p-button-text p-button-success"
rendered="#{'EN_ATTENTE' == adhesion.statut}"
action="#{adhesionsBean.selectionnerAdhesion(adhesion)}"
update=":formApprobation"
oncomplete="PF('dlgApprobation').show();" />
<p:commandButton icon="pi pi-times"
title="Rejeter"
styleClass="p-button-rounded p-button-text p-button-danger"
rendered="#{'EN_ATTENTE' == adhesion.statut}"
action="#{adhesionsBean.selectionnerAdhesion(adhesion)}"
update=":formRejet"
oncomplete="PF('dlgRejet').show();" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Nouvelle Adhésion -->
<p:dialog header="Nouvelle Adhésion" widgetVar="dlgNouvelleAdhesion" modal="true" width="600" resizable="false">
<h:form id="formNouvelleAdhesion">
<div class="ui-fluid">
<div class="field">
<p:outputLabel for="membreId" value="Membre" />
<p:selectOneMenu id="membreId"
value="#{adhesionsBean.nouvelleAdhesion.membreId}"
required="true"
requiredMessage="Veuillez sélectionner un membre"
filter="true"
filterMatchMode="contains"
styleClass="w-full">
<f:selectItems value="#{adhesionsBean.membresSelectItems}" />
</p:selectOneMenu>
<p:message for="membreId" />
</div>
<div class="field">
<p:outputLabel for="organisationId" value="Organisation" />
<p:selectOneMenu id="organisationId"
value="#{adhesionsBean.nouvelleAdhesion.organisationId}"
required="true"
requiredMessage="Veuillez sélectionner une organisation"
filter="true"
filterMatchMode="contains"
styleClass="w-full">
<f:selectItems value="#{adhesionsBean.associationsSelectItems}" />
</p:selectOneMenu>
<p:message for="organisationId" />
</div>
<div class="field">
<p:outputLabel for="fraisAdhesion" value="Frais d'adhésion (FCFA)" />
<p:inputNumber id="fraisAdhesion"
value="#{adhesionsBean.nouvelleAdhesion.fraisAdhesion}"
symbol=""
minValue="0"
styleClass="w-full" />
</div>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="observations" />
<ui:param name="label" value="Observations" />
<ui:param name="value" value="#{adhesionsBean.nouvelleAdhesion.observations}" />
<ui:param name="rows" value="3" />
</ui:include>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgNouvelleAdhesion').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Créer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{adhesionsBean.enregistrerAdhesion}" />
<ui:param name="update" value="@form :formListe" />
<ui:param name="oncomplete" value="PF('dlgNouvelleAdhesion').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Détails Adhésion -->
<p:dialog header="Détails de l'Adhésion" widgetVar="dlgDetailsAdhesion" modal="true" width="600" resizable="false">
<h:form id="formDetailsAdhesion">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Référence</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Statut</label>
<p:tag value="#{adhesionsBean.adhesionSelectionnee.statutLibelle}"
severity="#{adhesionsBean.adhesionSelectionnee.statutSeverity}" />
</div>
</div>
<div class="col-12">
<div class="field">
<label class="font-medium">Membre</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">N° #{adhesionsBean.adhesionSelectionnee.numeroMembre}</p>
</div>
</div>
<div class="col-12">
<div class="field">
<label class="font-medium">Organisation</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.nomOrganisation}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date de demande</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.dateDemandeFormatee}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Frais d'adhésion</label>
<p class="text-600 font-bold">#{adhesionsBean.adhesionSelectionnee.fraisAdhesionFormatte}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Montant payé</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.montantPayeFormatte}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Montant restant</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.montantRestantFormatte}</p>
</div>
</div>
<div class="col-12" rendered="#{adhesionsBean.adhesionSelectionnee.dateApprobation != null}">
<div class="field">
<label class="font-medium">Date d'approbation</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.dateApprobationFormatee}</p>
</div>
</div>
<div class="col-12" rendered="#{adhesionsBean.adhesionSelectionnee.observations != null}">
<div class="field">
<label class="font-medium">Observations</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.observations}</p>
</div>
</div>
</div>
</div>
</h:form>
</p:dialog>
<!-- Dialog Approbation -->
<p:dialog header="Approuver l'Adhésion" widgetVar="dlgApprobation" modal="true" width="500" resizable="false">
<h:form id="formApprobation">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Adhésion</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference} - #{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">Frais: #{adhesionsBean.adhesionSelectionnee.fraisAdhesionFormatte}</p>
</div>
<p:message id="msgApprobation" />
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgApprobation').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Approuver" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{adhesionsBean.approuverAdhesion}" />
<ui:param name="update" value="@form :formListe" />
<ui:param name="oncomplete" value="PF('dlgApprobation').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Rejet -->
<p:dialog header="Rejeter l'Adhésion" widgetVar="dlgRejet" modal="true" width="500" resizable="false">
<h:form id="formRejet">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Adhésion</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference} - #{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
</div>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="motifRejet" />
<ui:param name="label" value="Motif du rejet" />
<ui:param name="value" value="#{adhesionsBean.adhesionSelectionnee.motifRejet}" />
<ui:param name="required" value="true" />
<ui:param name="rows" value="4" />
</ui:include>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgRejet').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<p:commandButton value="Rejeter"
icon="pi pi-times"
styleClass="p-button-danger"
action="#{adhesionsBean.rejeterAdhesion(adhesionsBean.adhesionSelectionnee.motifRejet)}"
update="@form :formListe"
oncomplete="PF('dlgRejet').hide();" />
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,115 @@
<!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:param name="page" value="#{adhesionsBean}"/>
<ui:define name="title">Nouvelle Adhésion - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-user-plus text-green-500" />
<ui:param name="title" value="Nouvelle Adhésion" />
<ui:param name="description" value="Création d'une nouvelle demande d'adhésion" />
</ui:include>
<!-- Formulaire de nouvelle adhésion -->
<div class="card">
<h:form id="formNouvelleAdhesion">
<h5>Créer une Nouvelle Adhésion</h5>
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Informations du Membre" />
<ui:define name="content">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="membreId" value="Membre" />
<p:selectOneMenu id="membreId"
value="#{adhesionsBean.nouvelleAdhesion.membreId}"
required="true"
requiredMessage="Veuillez sélectionner un membre"
filter="true"
filterMatchMode="contains"
styleClass="w-full">
<f:selectItems value="#{adhesionsBean.membresSelectItems}" />
</p:selectOneMenu>
<p:message for="membreId" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="organisationId" value="Organisation" />
<p:selectOneMenu id="organisationId"
value="#{adhesionsBean.nouvelleAdhesion.organisationId}"
required="true"
requiredMessage="Veuillez sélectionner une organisation"
filter="true"
filterMatchMode="contains"
styleClass="w-full">
<f:selectItems value="#{adhesionsBean.associationsSelectItems}" />
</p:selectOneMenu>
<p:message for="organisationId" />
</div>
</div>
</div>
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Frais d'Adhésion" />
<ui:define name="content">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="fraisAdhesion" value="Frais d'adhésion (FCFA)" />
<p:inputNumber id="fraisAdhesion"
value="#{adhesionsBean.nouvelleAdhesion.fraisAdhesion}"
symbol=""
minValue="0"
styleClass="w-full" />
</div>
</div>
</div>
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Observations" />
<ui:define name="content">
<div class="grid">
<div class="col-12">
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="observations" />
<ui:param name="label" value="Observations (optionnel)" />
<ui:param name="value" value="#{adhesionsBean.nouvelleAdhesion.observations}" />
<ui:param name="rows" value="4" />
</ui:include>
</div>
</div>
</ui:define>
</ui:include>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="action" value="#{navigationBean.goToDashboard}" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Créer l'adhésion" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{adhesionsBean.enregistrerAdhesion}" />
<ui:param name="update" value="@form" />
</ui:include>
</div>
</h:form>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,261 @@
<!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:param name="page" value="#{adhesionsBean}"/>
<ui:define name="title">Paiement des Adhésions - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-credit-card text-green-500" />
<ui:param name="title" value="Paiement des Adhésions" />
<ui:param name="description" value="Enregistrement et suivi des paiements d'adhésion" />
<ui:define name="actions">
<h:form id="formActionsPaiement">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{adhesionsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques de paiement -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.totalCollecteFormatte}" />
<ui:param name="label" value="Total Collecté" />
<ui:param name="icon" value="pi pi-wallet" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.adhesionsPayees}" />
<ui:param name="label" value="Adhésions Payées" />
<ui:param name="icon" value="pi pi-check-circle" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.tauxPaiementInt}%" />
<ui:param name="label" value="Taux de Paiement" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.adhesionsApprouvees - adhesionsBean.statistiques.adhesionsPayees}" />
<ui:param name="label" value="En Attente de Paiement" />
<ui:param name="icon" value="pi pi-clock" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Adhésions approuvées en attente de paiement -->
<div class="card">
<h:form id="formPaiements">
<h5>Adhésions Approuvées en Attente de Paiement</h5>
<p:dataTable id="dtPaiements"
value="#{adhesionsBean.adhesionsFiltrees}"
var="adhesion"
filteredValue="#{adhesionsBean.adhesionsFiltrees}"
paginator="true"
rows="20"
emptyMessage="Aucune adhésion en attente de paiement"
selection="#{adhesionsBean.adhesionSelectionnee}"
selectionMode="single">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Adhésions à payer</span>
<p:selectOneMenu value="#{adhesionsBean.filtres.statut}" styleClass="w-12rem">
<f:selectItem itemLabel="Tous" itemValue="" />
<f:selectItem itemLabel="Approuvée" itemValue="APPROUVEE" />
<f:selectItem itemLabel="En paiement" itemValue="EN_PAIEMENT" />
<p:ajax update="dtPaiements" />
</p:selectOneMenu>
</div>
</f:facet>
<p:column headerText="Membre" sortBy="#{adhesion.nomMembre}">
<div>
<div class="font-medium">#{adhesion.nomMembre}</div>
<div class="text-600 text-sm">#{adhesion.numeroMembre}</div>
</div>
</p:column>
<p:column headerText="Organisation" sortBy="#{adhesion.nomOrganisation}">
<h:outputText value="#{adhesion.nomOrganisation}" />
</p:column>
<p:column headerText="Frais" sortBy="#{adhesion.fraisAdhesion}" style="width:120px">
<h:outputText value="#{adhesion.fraisAdhesionFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Montant Payé" sortBy="#{adhesion.montantPaye}" style="width:120px">
<h:outputText value="#{adhesion.montantPayeFormatte}" />
</p:column>
<p:column headerText="Restant" style="width:120px">
<h:outputText value="#{adhesion.montantRestantFormatte}"
styleClass="#{adhesion.montantRestant.compareTo(java.math.BigDecimal.ZERO) > 0 ? 'text-orange-500 font-bold' : 'text-green-500'}" />
</p:column>
<p:column headerText="Date Approbation" sortBy="#{adhesion.dateApprobation}" style="width:150px">
<h:outputText value="#{adhesion.dateApprobationFormatee}" />
</p:column>
<p:column headerText="Actions" style="width:200px">
<div class="flex gap-1">
<p:commandButton value="Payer"
icon="pi pi-check"
styleClass="p-button-success p-button-sm"
action="#{adhesionsBean.selectionnerAdhesion(adhesion)}"
update=":formPaiement"
oncomplete="PF('dlgPaiement').show();" />
<p:commandButton value="Partiel"
icon="pi pi-minus"
styleClass="p-button-info p-button-sm"
action="#{adhesionsBean.selectionnerAdhesion(adhesion)}"
update=":formPaiementPartiel"
oncomplete="PF('dlgPaiementPartiel').show();" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Paiement Complet -->
<p:dialog header="Enregistrer un Paiement" widgetVar="dlgPaiement" modal="true" width="500" resizable="false">
<h:form id="formPaiement">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Adhésion</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference} - #{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">Frais d'adhésion: #{adhesionsBean.adhesionSelectionnee.fraisAdhesionFormatte}</p>
</div>
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="methodePaiement" />
<ui:param name="label" value="Méthode de paiement" />
<ui:param name="value" value="#{adhesionsBean.adhesionSelectionnee.methodePaiement}" />
<ui:param name="required" value="true" />
<ui:define name="items">
<f:selectItem itemLabel="Wave Money" itemValue="WAVE_MONEY" />
<f:selectItem itemLabel="Espèces" itemValue="ESPECES" />
<f:selectItem itemLabel="Virement bancaire" itemValue="VIREMENT" />
<f:selectItem itemLabel="Chèque" itemValue="CHEQUE" />
<f:selectItem itemLabel="Orange Money" itemValue="ORANGE_MONEY" />
<f:selectItem itemLabel="Free Money" itemValue="FREE_MONEY" />
<f:selectItem itemLabel="Carte bancaire" itemValue="CARTE_BANCAIRE" />
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="referencePaiement" />
<ui:param name="label" value="Référence de paiement" />
<ui:param name="value" value="#{adhesionsBean.adhesionSelectionnee.referencePaiement}" />
<ui:param name="placeholder" value="Ex: WAVE-123456789" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="observationsPaiement" />
<ui:param name="label" value="Observations" />
<ui:param name="value" value="#{adhesionsBean.adhesionSelectionnee.observations}" />
<ui:param name="rows" value="3" />
</ui:include>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgPaiement').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Enregistrer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{adhesionsBean.enregistrerPaiement(adhesionsBean.adhesionSelectionnee.fraisAdhesion, adhesionsBean.adhesionSelectionnee.methodePaiement, adhesionsBean.adhesionSelectionnee.referencePaiement)}" />
<ui:param name="update" value="@form :formPaiements" />
<ui:param name="oncomplete" value="PF('dlgPaiement').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Paiement Partiel -->
<p:dialog header="Enregistrer un Paiement Partiel" widgetVar="dlgPaiementPartiel" modal="true" width="500" resizable="false">
<h:form id="formPaiementPartiel">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Adhésion</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference} - #{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">Frais d'adhésion: #{adhesionsBean.adhesionSelectionnee.fraisAdhesionFormatte}</p>
<p class="text-500 text-sm">Montant restant: #{adhesionsBean.adhesionSelectionnee.montantRestantFormatte}</p>
</div>
<div class="field">
<p:outputLabel for="montantPaye" value="Montant à payer (FCFA)" />
<p:inputNumber id="montantPaye"
value="#{adhesionsBean.adhesionSelectionnee.montantPaye}"
symbol=""
minValue="0"
maxValue="#{adhesionsBean.adhesionSelectionnee.fraisAdhesion}"
styleClass="w-full" />
</div>
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="methodePaiementPartiel" />
<ui:param name="label" value="Méthode de paiement" />
<ui:param name="value" value="#{adhesionsBean.adhesionSelectionnee.methodePaiement}" />
<ui:param name="required" value="true" />
<ui:define name="items">
<f:selectItem itemLabel="Wave Money" itemValue="WAVE_MONEY" />
<f:selectItem itemLabel="Espèces" itemValue="ESPECES" />
<f:selectItem itemLabel="Virement bancaire" itemValue="VIREMENT" />
<f:selectItem itemLabel="Chèque" itemValue="CHEQUE" />
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="referencePaiementPartiel" />
<ui:param name="label" value="Référence de paiement" />
<ui:param name="value" value="#{adhesionsBean.adhesionSelectionnee.referencePaiement}" />
</ui:include>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgPaiementPartiel').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Enregistrer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{adhesionsBean.enregistrerPaiement(adhesionsBean.adhesionSelectionnee.montantPaye, adhesionsBean.adhesionSelectionnee.methodePaiement, adhesionsBean.adhesionSelectionnee.referencePaiement)}" />
<ui:param name="update" value="@form :formPaiements" />
<ui:param name="oncomplete" value="PF('dlgPaiementPartiel').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,257 @@
<!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:param name="page" value="#{adhesionsBean}"/>
<ui:define name="title">Adhésions en Attente - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-clock text-orange-500" />
<ui:param name="title" value="Adhésions en Attente" />
<ui:param name="description" value="Validation et traitement des demandes d'adhésion en attente" />
<ui:define name="actions">
<h:form id="formActionsPending">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{adhesionsBean.chargerAdhesionsEnAttente}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.adhesionsEnAttente}" />
<ui:param name="label" value="En Attente" />
<ui:param name="icon" value="pi pi-clock" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.adhesionsApprouvees}" />
<ui:param name="label" value="Approuvées" />
<ui:param name="icon" value="pi pi-check-circle" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.tauxApprobationInt}%" />
<ui:param name="label" value="Taux d'Approbation" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.totalCollecteFormatte}" />
<ui:param name="label" value="Total Collecté" />
<ui:param name="icon" value="pi pi-wallet" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Liste des adhésions en attente -->
<div class="card">
<h:form id="formPending">
<h5>Adhésions en Attente de Validation</h5>
<p:dataTable id="dtPending"
value="#{adhesionsBean.adhesionsFiltrees}"
var="adhesion"
paginator="true"
rows="20"
emptyMessage="Aucune adhésion en attente">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Demandes en attente d'approbation</span>
</div>
</f:facet>
<p:column headerText="Référence" sortBy="#{adhesion.numeroReference}" style="width:150px">
<h:outputText value="#{adhesion.numeroReference}" />
</p:column>
<p:column headerText="Membre" sortBy="#{adhesion.nomMembre}">
<div>
<div class="font-medium">#{adhesion.nomMembre}</div>
<div class="text-600 text-sm">#{adhesion.numeroMembre}</div>
<div class="text-500 text-xs">#{adhesion.emailMembre}</div>
</div>
</p:column>
<p:column headerText="Organisation" sortBy="#{adhesion.nomOrganisation}">
<h:outputText value="#{adhesion.nomOrganisation}" />
</p:column>
<p:column headerText="Date Demande" sortBy="#{adhesion.dateDemande}" style="width:120px">
<h:outputText value="#{adhesion.dateDemandeFormatee}" />
</p:column>
<p:column headerText="Jours" style="width:80px">
<h:outputText value="#{adhesion.joursDepuisDemande} jour(s)" />
</p:column>
<p:column headerText="Frais" sortBy="#{adhesion.fraisAdhesion}" style="width:120px">
<h:outputText value="#{adhesion.fraisAdhesionFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Actions" style="width:200px">
<div class="flex gap-1">
<p:commandButton icon="pi pi-check"
title="Approuver"
styleClass="p-button-rounded p-button-text p-button-success"
action="#{adhesionsBean.selectionnerAdhesion(adhesion)}"
update=":formApprobation"
oncomplete="PF('dlgApprobation').show();" />
<p:commandButton icon="pi pi-times"
title="Rejeter"
styleClass="p-button-rounded p-button-text p-button-danger"
action="#{adhesionsBean.selectionnerAdhesion(adhesion)}"
update=":formRejet"
oncomplete="PF('dlgRejet').show();" />
<p:commandButton icon="pi pi-eye"
title="Voir les détails"
styleClass="p-button-rounded p-button-text p-button-info"
action="#{adhesionsBean.selectionnerAdhesion(adhesion)}"
update=":formDetailsAdhesion"
oncomplete="PF('dlgDetailsAdhesion').show();" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Approbation -->
<p:dialog header="Approuver l'Adhésion" widgetVar="dlgApprobation" modal="true" width="500" resizable="false">
<h:form id="formApprobation">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Adhésion</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference} - #{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">Frais: #{adhesionsBean.adhesionSelectionnee.fraisAdhesionFormatte}</p>
</div>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgApprobation').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Approuver" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{adhesionsBean.approuverAdhesion}" />
<ui:param name="update" value="@form :formPending" />
<ui:param name="oncomplete" value="PF('dlgApprobation').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Rejet -->
<p:dialog header="Rejeter l'Adhésion" widgetVar="dlgRejet" modal="true" width="500" resizable="false">
<h:form id="formRejet">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Adhésion</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference} - #{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
</div>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="motifRejet" />
<ui:param name="label" value="Motif du rejet" />
<ui:param name="value" value="#{adhesionsBean.adhesionSelectionnee.motifRejet}" />
<ui:param name="required" value="true" />
<ui:param name="rows" value="4" />
</ui:include>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgRejet').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<p:commandButton value="Rejeter"
icon="pi pi-times"
styleClass="p-button-danger"
action="#{adhesionsBean.rejeterAdhesion(adhesionsBean.adhesionSelectionnee.motifRejet)}"
update="@form :formPending"
oncomplete="PF('dlgRejet').hide();" />
</div>
</h:form>
</p:dialog>
<!-- Dialog Détails Adhésion -->
<p:dialog header="Détails de l'Adhésion" widgetVar="dlgDetailsAdhesion" modal="true" width="600" resizable="false">
<h:form id="formDetailsAdhesion">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Référence</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Statut</label>
<p:tag value="#{adhesionsBean.adhesionSelectionnee.statutLibelle}"
severity="#{adhesionsBean.adhesionSelectionnee.statutSeverity}" />
</div>
</div>
<div class="col-12">
<div class="field">
<label class="font-medium">Membre</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">N° #{adhesionsBean.adhesionSelectionnee.numeroMembre} - #{adhesionsBean.adhesionSelectionnee.emailMembre}</p>
</div>
</div>
<div class="col-12">
<div class="field">
<label class="font-medium">Organisation</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.nomOrganisation}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date de demande</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.dateDemandeFormatee}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Frais d'adhésion</label>
<p class="text-600 font-bold">#{adhesionsBean.adhesionSelectionnee.fraisAdhesionFormatte}</p>
</div>
</div>
<div class="col-12" rendered="#{adhesionsBean.adhesionSelectionnee.observations != null}">
<div class="field">
<label class="font-medium">Observations</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.observations}</p>
</div>
</div>
</div>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,167 @@
<!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:param name="page" value="#{adhesionsBean}"/>
<ui:define name="title">Renouvellement d'Adhésion - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-refresh text-blue-500" />
<ui:param name="title" value="Renouvellement d'Adhésion" />
<ui:param name="description" value="Gestion des renouvellements d'adhésion" />
<ui:define name="actions">
<h:form id="formActionsRenouvellement">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{adhesionsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.adhesionsPayees}" />
<ui:param name="label" value="Adhésions Actives" />
<ui:param name="icon" value="pi pi-check-circle" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="À Renouveler (ce mois)" />
<ui:param name="icon" value="pi pi-clock" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="Renouvelées (ce mois)" />
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.totalAdhesions}" />
<ui:param name="label" value="Total Adhésions" />
<ui:param name="icon" value="pi pi-users" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Liste des adhésions à renouveler -->
<div class="card">
<h:form id="formRenouvellement">
<h5>Adhésions à Renouveler</h5>
<p:dataTable id="dtRenouvellement"
value="#{adhesionsBean.adhesionsFiltrees}"
var="adhesion"
paginator="true"
rows="20"
emptyMessage="Aucune adhésion à renouveler">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Adhésions nécessitant un renouvellement</span>
</div>
</f:facet>
<p:column headerText="Membre" sortBy="#{adhesion.nomMembre}">
<div>
<div class="font-medium">#{adhesion.nomMembre}</div>
<div class="text-600 text-sm">#{adhesion.numeroMembre}</div>
</div>
</p:column>
<p:column headerText="Organisation" sortBy="#{adhesion.nomOrganisation}">
<h:outputText value="#{adhesion.nomOrganisation}" />
</p:column>
<p:column headerText="Date Approbation" sortBy="#{adhesion.dateApprobation}" style="width:150px">
<h:outputText value="#{adhesion.dateApprobationFormatee}" />
</p:column>
<p:column headerText="Frais" sortBy="#{adhesion.fraisAdhesion}" style="width:120px">
<h:outputText value="#{adhesion.fraisAdhesionFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Statut" style="width:150px">
<p:tag value="#{adhesion.statutLibelle}"
severity="#{adhesion.statutSeverity}"
icon="#{adhesion.statutIcon}" />
</p:column>
<p:column headerText="Actions" style="width:150px">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Renouveler" />
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="onclick" value="PF('dlgRenouvellement').show(); adhesionsBean.selectionnerAdhesion(adhesion);" />
<ui:param name="styleClass" value="p-button-sm" />
</ui:include>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Renouvellement -->
<p:dialog header="Renouveler l'Adhésion" widgetVar="dlgRenouvellement" modal="true" width="500" resizable="false">
<h:form id="formRenouvellement">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Adhésion actuelle</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference} - #{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">Frais actuel: #{adhesionsBean.adhesionSelectionnee.fraisAdhesionFormatte}</p>
</div>
<div class="field">
<p:outputLabel for="nouveauxFrais" value="Nouveaux frais d'adhésion (FCFA)" />
<p:inputNumber id="nouveauxFrais"
value="#{adhesionsBean.nouvelleAdhesion.fraisAdhesion}"
symbol=""
minValue="0"
styleClass="w-full" />
</div>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="observationsRenouvellement" />
<ui:param name="label" value="Observations" />
<ui:param name="value" value="#{adhesionsBean.nouvelleAdhesion.observations}" />
<ui:param name="rows" value="3" />
</ui:include>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgRenouvellement').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Créer le renouvellement" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{adhesionsBean.enregistrerAdhesion}" />
<ui:param name="update" value="@form :formRenouvellement" />
<ui:param name="oncomplete" value="PF('dlgRenouvellement').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,254 @@
<!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:param name="page" value="#{adhesionsBean}"/>
<ui:define name="title">Validation des Adhésions - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-check-circle text-green-500" />
<ui:param name="title" value="Validation des Adhésions" />
<ui:param name="description" value="Approbation et rejet des demandes d'adhésion" />
<ui:define name="actions">
<h:form id="formActionsValidation">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{adhesionsBean.chargerAdhesionsEnAttente}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.adhesionsEnAttente}" />
<ui:param name="label" value="En Attente" />
<ui:param name="icon" value="pi pi-clock" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.adhesionsApprouvees}" />
<ui:param name="label" value="Approuvées" />
<ui:param name="icon" value="pi pi-check-circle" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.tauxApprobationInt}%" />
<ui:param name="label" value="Taux d'Approbation" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{adhesionsBean.statistiques.totalAdhesions}" />
<ui:param name="label" value="Total" />
<ui:param name="icon" value="pi pi-users" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Liste des adhésions en attente -->
<div class="card">
<h:form id="formValidation">
<h5>Adhésions en Attente de Validation</h5>
<p:dataTable id="dtValidation"
value="#{adhesionsBean.adhesionsFiltrees}"
var="adhesion"
paginator="true"
rows="20"
emptyMessage="Aucune adhésion en attente">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Demandes nécessitant une validation</span>
</div>
</f:facet>
<p:column headerText="Référence" sortBy="#{adhesion.numeroReference}" style="width:150px">
<h:outputText value="#{adhesion.numeroReference}" />
</p:column>
<p:column headerText="Membre" sortBy="#{adhesion.nomMembre}">
<div>
<div class="font-medium">#{adhesion.nomMembre}</div>
<div class="text-600 text-sm">#{adhesion.numeroMembre}</div>
</div>
</p:column>
<p:column headerText="Organisation" sortBy="#{adhesion.nomOrganisation}">
<h:outputText value="#{adhesion.nomOrganisation}" />
</p:column>
<p:column headerText="Date Demande" sortBy="#{adhesion.dateDemande}" style="width:120px">
<h:outputText value="#{adhesion.dateDemandeFormatee}" />
</p:column>
<p:column headerText="Frais" sortBy="#{adhesion.fraisAdhesion}" style="width:120px">
<h:outputText value="#{adhesion.fraisAdhesionFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Actions" style="width:250px">
<div class="flex gap-1">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Approuver" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{adhesionsBean.selectionnerAdhesion(adhesion)}" />
<ui:param name="update" value=":formApprobation" />
<ui:param name="oncomplete" value="PF('dlgApprobation').show();" />
<ui:param name="styleClass" value="p-button-sm" />
</ui:include>
<p:commandButton value="Rejeter"
icon="pi pi-times"
styleClass="p-button-danger p-button-sm"
action="#{adhesionsBean.selectionnerAdhesion(adhesion)}"
update=":formRejet"
oncomplete="PF('dlgRejet').show();" />
<p:commandButton icon="pi pi-eye"
title="Voir les détails"
styleClass="p-button-rounded p-button-text p-button-info p-button-sm"
action="#{adhesionsBean.selectionnerAdhesion(adhesion)}"
update=":formDetailsAdhesion"
oncomplete="PF('dlgDetailsAdhesion').show();" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Approbation -->
<p:dialog header="Approuver l'Adhésion" widgetVar="dlgApprobation" modal="true" width="500" resizable="false">
<h:form id="formApprobation">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Adhésion</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference} - #{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">Frais: #{adhesionsBean.adhesionSelectionnee.fraisAdhesionFormatte}</p>
</div>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgApprobation').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Approuver" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{adhesionsBean.approuverAdhesion}" />
<ui:param name="update" value="@form :formValidation" />
<ui:param name="oncomplete" value="PF('dlgApprobation').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Rejet -->
<p:dialog header="Rejeter l'Adhésion" widgetVar="dlgRejet" modal="true" width="500" resizable="false">
<h:form id="formRejet">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Adhésion</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference} - #{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
</div>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="motifRejet" />
<ui:param name="label" value="Motif du rejet" />
<ui:param name="value" value="#{adhesionsBean.adhesionSelectionnee.motifRejet}" />
<ui:param name="required" value="true" />
<ui:param name="rows" value="4" />
</ui:include>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgRejet').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<p:commandButton value="Rejeter"
icon="pi pi-times"
styleClass="p-button-danger"
action="#{adhesionsBean.rejeterAdhesion(adhesionsBean.adhesionSelectionnee.motifRejet)}"
update="@form :formValidation"
oncomplete="PF('dlgRejet').hide();" />
</div>
</h:form>
</p:dialog>
<!-- Dialog Détails Adhésion -->
<p:dialog header="Détails de l'Adhésion" widgetVar="dlgDetailsAdhesion" modal="true" width="600" resizable="false">
<h:form id="formDetailsAdhesion">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Référence</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.numeroReference}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Statut</label>
<p:tag value="#{adhesionsBean.adhesionSelectionnee.statutLibelle}"
severity="#{adhesionsBean.adhesionSelectionnee.statutSeverity}" />
</div>
</div>
<div class="col-12">
<div class="field">
<label class="font-medium">Membre</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">N° #{adhesionsBean.adhesionSelectionnee.numeroMembre}</p>
</div>
</div>
<div class="col-12">
<div class="field">
<label class="font-medium">Organisation</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.nomOrganisation}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date de demande</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.dateDemandeFormatee}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Frais d'adhésion</label>
<p class="text-600 font-bold">#{adhesionsBean.adhesionSelectionnee.fraisAdhesionFormatte}</p>
</div>
</div>
<div class="col-12" rendered="#{adhesionsBean.adhesionSelectionnee.observations != null}">
<div class="field">
<label class="font-medium">Observations</label>
<p class="text-600">#{adhesionsBean.adhesionSelectionnee.observations}</p>
</div>
</div>
</div>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,32 @@
<!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:param name="page" value="#{configurationBean}"/>
<ui:define name="title">Journal d'Audit - UnionFlow</ui:define>
<ui:define name="content">
<!-- Redirection vers la page principale d'audit -->
<div class="card">
<div class="text-center p-4">
<i class="pi pi-history text-4xl text-indigo-500 mb-3"></i>
<h5>Journal d'Audit</h5>
<p class="text-600 mt-2">
Redirection vers la page principale du journal d'audit...
</p>
<div class="mt-4">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Accéder au Journal d'Audit" />
<ui:param name="icon" value="pi pi-arrow-right" />
<ui:param name="outcome" value="/pages/admin/audit/journal.xhtml" />
</ui:include>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,47 @@
<!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:param name="page" value="#{configurationBean}"/>
<ui:define name="title">Paramètres Système - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-cog text-orange-500" />
<ui:param name="title" value="Paramètres Système" />
<ui:param name="description" value="Configuration des paramètres généraux de l'application" />
<ui:define name="actions">
<h:form id="formActions">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Enregistrer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{configurationBean.enregistrer}" />
<ui:param name="update" value="@form" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Information -->
<div class="card">
<div class="text-center p-4">
<i class="pi pi-info-circle text-4xl text-orange-500 mb-3"></i>
<h5>Configuration Système</h5>
<p class="text-600 mt-2">
La page de configuration système sera disponible prochainement.
</p>
<p class="text-600 mt-2">
Elle permettra de configurer les paramètres généraux de l'application.
</p>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,53 @@
<!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:param name="page" value="#{configurationBean}"/>
<ui:define name="title">Gestion des Rôles - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-shield text-purple-500" />
<ui:param name="title" value="Gestion des Rôles" />
<ui:param name="description" value="Gestion des rôles et permissions via Keycloak" />
<ui:define name="actions">
<h:form id="formActions">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Documentation Keycloak" />
<ui:param name="icon" value="pi pi-book" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Information -->
<div class="card">
<div class="text-center p-4">
<i class="pi pi-info-circle text-4xl text-purple-500 mb-3"></i>
<h5>Gestion des Rôles via Keycloak</h5>
<p class="text-600 mt-2">
La gestion des rôles et permissions se fait directement via Keycloak Admin Console.
</p>
<p class="text-600 mt-2">
Les rôles disponibles incluent : SUPER_ADMIN, ADMIN_ORG, SECRETAIRE, TRESORIER, MEMBRE, etc.
</p>
<div class="mt-4">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Accéder à Keycloak Admin" />
<ui:param name="icon" value="pi pi-external-link" />
<ui:param name="onclick" value="window.open('https://security.lions.dev/admin', '_blank');" />
</ui:include>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,122 @@
<!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:param name="page" value="#{configurationBean}"/>
<ui:define name="title">Sauvegarde et Restauration - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formSauvegarde">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div>
<h3 class="m-0">
<i class="pi pi-database text-green-500 mr-2"></i>
Sauvegarde et Restauration
</h3>
<p class="text-600 m-0 mt-2">
Gérez les sauvegardes et restaurez la base de données
</p>
</div>
<div class="flex gap-2 mt-2 md:mt-0">
<p:commandButton value="Créer une sauvegarde"
icon="pi pi-save"
styleClass="ui-button-success"
action="#{configurationBean.creerSauvegarde}"
update="@form"/>
</div>
</div>
</div>
<!-- Information système -->
<div class="card mb-3">
<h5 class="mb-3">État du Système</h5>
<div class="grid">
<div class="col-12 md:col-3">
<div class="surface-100 border-round p-3">
<div class="text-600 text-sm mb-1">Dernière sauvegarde</div>
<div class="font-bold text-lg">#{configurationBean.derniereSauvegarde}</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="surface-100 border-round p-3">
<div class="text-600 text-sm mb-1">Fréquence</div>
<div class="font-bold text-lg">#{configurationBean.frequenceSauvegarde}</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="surface-100 border-round p-3">
<div class="text-600 text-sm mb-1">Rétention</div>
<div class="font-bold text-lg">#{configurationBean.retentionSauvegardes} jours</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="surface-100 border-round p-3">
<div class="text-600 text-sm mb-1">Temps d'activité</div>
<div class="font-bold text-lg text-green-500">#{configurationBean.tempsActivite}</div>
</div>
</div>
</div>
</div>
<!-- Liste des sauvegardes -->
<div class="card">
<h5 class="mb-3">Sauvegardes Disponibles</h5>
<p:dataTable id="dtSauvegardes"
var="sauvegarde"
value="#{configurationBean.sauvegardes}"
paginator="true"
rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,25">
<p:column headerText="Date" sortBy="#{sauvegarde.date}">
<h:outputText value="#{sauvegarde.date}">
<f:convertDateTime pattern="dd/MM/yyyy HH:mm"/>
</h:outputText>
</p:column>
<p:column headerText="Taille" sortBy="#{sauvegarde.taille}">
<div class="font-medium">#{sauvegarde.taille}</div>
</p:column>
<p:column headerText="Type" sortBy="#{sauvegarde.type}">
<p:tag value="#{sauvegarde.type}" severity="info"/>
</p:column>
<p:column headerText="Statut" sortBy="#{sauvegarde.statut}">
<p:tag value="#{sauvegarde.statut}"
severity="#{sauvegarde.statutSeverity}"
icon="pi #{sauvegarde.statutIcon}"/>
</p:column>
<p:column headerText="Actions" style="width:200px">
<div class="flex gap-1">
<p:commandButton icon="pi pi-download"
styleClass="ui-button-rounded ui-button-text ui-button-info"
action="#{configurationBean.telechargerSauvegarde(sauvegarde)}"
title="Télécharger"/>
<p:commandButton icon="pi pi-refresh"
styleClass="ui-button-rounded ui-button-text ui-button-success"
action="#{configurationBean.restaurerSauvegarde(sauvegarde)}"
title="Restaurer"
onclick="return confirm('Êtes-vous sûr de vouloir restaurer cette sauvegarde ?');"/>
<p:commandButton icon="pi pi-trash"
styleClass="ui-button-rounded ui-button-text ui-button-danger"
action="#{configurationBean.supprimerSauvegarde(sauvegarde)}"
title="Supprimer"/>
</div>
</p:column>
</p:dataTable>
</div>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,53 @@
<!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:param name="page" value="#{configurationBean}"/>
<ui:define name="title">Gestion des Utilisateurs - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-users text-blue-500" />
<ui:param name="title" value="Gestion des Utilisateurs" />
<ui:param name="description" value="Gestion des utilisateurs et de leurs accès via Keycloak" />
<ui:define name="actions">
<h:form id="formActions">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Documentation Keycloak" />
<ui:param name="icon" value="pi pi-book" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Information -->
<div class="card">
<div class="text-center p-4">
<i class="pi pi-info-circle text-4xl text-blue-500 mb-3"></i>
<h5>Gestion des Utilisateurs via Keycloak</h5>
<p class="text-600 mt-2">
La gestion des utilisateurs se fait directement via Keycloak Admin Console.
</p>
<p class="text-600 mt-2">
Pour accéder à la console d'administration Keycloak, veuillez utiliser l'interface dédiée.
</p>
<div class="mt-4">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Accéder à Keycloak Admin" />
<ui:param name="icon" value="pi pi-external-link" />
<ui:param name="onclick" value="window.open('https://security.lions.dev/admin', '_blank');" />
</ui:include>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,73 @@
<!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:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Demandes d'Aide Approuvées - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formApproved">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div>
<h3 class="m-0">
<i class="pi pi-check-circle text-success mr-2"></i>
Demandes d'Aide Approuvées
</h3>
<p class="text-600 m-0 mt-2">
Liste des demandes d'aide approuvées et en cours de traitement
</p>
</div>
</div>
</div>
<!-- Liste des demandes approuvées -->
<div class="card">
<h5 class="mb-3">Demandes Approuvées</h5>
<p:dataTable id="dtApproved"
var="demande"
value="#{demandesAideBean.demandesFiltrees}"
paginator="true"
rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,25"
currentPageReportTemplate="Affichage {startRecord}-{endRecord} sur {totalRecords}">
<p:column headerText="Demandeur" sortBy="#{demande.demandeur}">
<div>
<div class="font-medium">#{demande.demandeur}</div>
<small class="text-600">#{demande.telephone}</small>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{demande.type}">
<p:tag value="#{demande.typeLibelle}" severity="#{demande.typeSeverity}" icon="pi #{demande.typeIcon}"/>
</p:column>
<p:column headerText="Montant accordé" sortBy="#{demande.montantAccorde}">
<div class="font-bold text-green-500">#{demande.montantAccorde} FCFA</div>
</p:column>
<p:column headerText="Date approbation" sortBy="#{demande.dateDemande}">
<h:outputText value="#{demande.dateDemande}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:outputText>
</p:column>
<p:column headerText="Actions" style="width:150px">
<p:commandButton icon="pi pi-eye"
styleClass="ui-button-rounded ui-button-text ui-button-info"
action="#{demandesAideBean.voirDetails(demande)}"
title="Voir détails"/>
</p:column>
</p:dataTable>
</div>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,327 @@
<!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:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">À Propos d'UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête principal -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-6 text-center">
<div class="mb-4">
<i class="pi pi-heart-fill text-6xl text-primary mb-3"></i>
<h1 class="text-900 font-bold text-5xl mb-3">UnionFlow</h1>
<p class="text-600 text-xl mb-4">
La solution complète de gestion d'associations et organisations
</p>
<div class="flex align-items-center justify-content-center gap-3">
<p:tag value="Version 2.1.3" severity="success" styleClass="text-lg p-2" />
<p:tag value="Build 20240118" severity="info" styleClass="text-lg p-2" />
<p:tag value="Stable" severity="secondary" styleClass="text-lg p-2" />
</div>
</div>
<!-- Statistiques système -->
<div class="grid">
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4" style="min-height: 9rem">
<div class="text-2xl font-bold text-blue-500 mb-2">99.9%</div>
<div class="text-900 font-semibold mb-1">Disponibilité</div>
<div class="text-600 text-sm">30 derniers jours</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4" style="min-height: 9rem">
<div class="text-2xl font-bold text-green-500 mb-2">2.3s</div>
<div class="text-900 font-semibold mb-1">Temps de Réponse</div>
<div class="text-600 text-sm">Moyen</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4" style="min-height: 9rem">
<div class="text-2xl font-bold text-purple-500 mb-2">15,647</div>
<div class="text-900 font-semibold mb-1">Utilisateurs</div>
<div class="text-600 text-sm">Actifs ce mois</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4" style="min-height: 9rem">
<div class="text-2xl font-bold text-orange-500 mb-2">4.8★</div>
<div class="text-900 font-semibold mb-1">Satisfaction</div>
<div class="text-600 text-sm">Note moyenne</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Mission et valeurs -->
<div class="grid mb-4">
<div class="col-12 lg:col-6">
<div class="surface-card border-round p-4 h-full">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-flag text-primary mr-2"></i>
Notre Mission
</h4>
<p class="text-700 line-height-3 mb-4">
UnionFlow a été créé avec la vision de simplifier et moderniser la gestion des associations,
coopératives et organisations communautaires. Notre objectif est de fournir des outils
puissants et accessibles qui permettent aux dirigeants de se concentrer sur leur mission
plutôt que sur la paperasse administrative.
</p>
<div class="surface-blue-50 border-left-3 border-blue-500 p-4">
<h6 class="text-blue-800 font-semibold mb-2">
<i class="pi pi-lightbulb mr-2"></i>Vision 2025
</h6>
<p class="text-blue-700 text-sm mb-0">
Devenir la plateforme de référence pour la gestion d'organisations en Afrique
de l'Ouest avec plus de 100,000 utilisateurs actifs.
</p>
</div>
</div>
</div>
<div class="col-12 lg:col-6">
<div class="surface-card border-round p-4 h-full">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-heart text-red-500 mr-2"></i>
Nos Valeurs
</h4>
<div class="grid">
<div class="col-6">
<div class="mb-3">
<i class="pi pi-users text-blue-500 text-xl mb-2"></i>
<h6 class="text-900 font-semibold mb-1">Communauté</h6>
<p class="text-600 text-sm">Favoriser l'entraide et la collaboration</p>
</div>
</div>
<div class="col-6">
<div class="mb-3">
<i class="pi pi-shield text-green-500 text-xl mb-2"></i>
<h6 class="text-900 font-semibold mb-1">Confiance</h6>
<p class="text-600 text-sm">Sécurité et transparence totales</p>
</div>
</div>
<div class="col-6">
<div class="mb-3">
<i class="pi pi-cog text-purple-500 text-xl mb-2"></i>
<h6 class="text-900 font-semibold mb-1">Innovation</h6>
<p class="text-600 text-sm">Solutions modernes et évolutives</p>
</div>
</div>
<div class="col-6">
<div>
<i class="pi pi-globe text-orange-500 text-xl mb-2"></i>
<h6 class="text-900 font-semibold mb-1">Accessibilité</h6>
<p class="text-600 text-sm">Pour tous, partout, sur tout appareil</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Informations techniques -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-server mr-2"></i>
Informations Système
</h4>
<div class="grid">
<div class="col-12 lg:col-6">
<h6 class="text-900 font-semibold mb-3">🏗️ Architecture</h6>
<div class="grid">
<div class="col-6">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Framework</div>
<div class="text-900 font-semibold">Quarkus 3.15.1</div>
</div>
</div>
<div class="col-6">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Interface</div>
<div class="text-900 font-semibold">PrimeFaces 14.0.5</div>
</div>
</div>
<div class="col-6">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Base de données</div>
<div class="text-900 font-semibold">PostgreSQL 15</div>
</div>
</div>
<div class="col-6">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Cache</div>
<div class="text-900 font-semibold">Redis 7.2</div>
</div>
</div>
</div>
</div>
<div class="col-12 lg:col-6">
<h6 class="text-900 font-semibold mb-3">🔧 Environnement</h6>
<div class="grid">
<div class="col-6">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">JVM</div>
<div class="text-900 font-semibold">OpenJDK 21</div>
</div>
</div>
<div class="col-6">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Serveur</div>
<div class="text-900 font-semibold">Kubernetes</div>
</div>
</div>
<div class="col-6">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">CDN</div>
<div class="text-900 font-semibold">Cloudflare</div>
</div>
</div>
<div class="col-6">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Monitoring</div>
<div class="text-900 font-semibold">Prometheus</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Équipe et crédits -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-users mr-2"></i>
Équipe de Développement
</h4>
<div class="grid">
<div class="col-12 lg:col-4">
<div class="surface-100 border-round p-4 text-center">
<div class="w-6rem h-6rem border-circle bg-primary-100 flex align-items-center justify-content-center mx-auto mb-3">
<i class="pi pi-crown text-primary text-3xl"></i>
</div>
<h6 class="text-900 font-semibold mb-2">Équipe Core</h6>
<p class="text-600 text-sm mb-3">
Architectes et développeurs principaux responsables
de la vision produit et de l'architecture technique.
</p>
<div class="flex align-items-center justify-content-center gap-2">
<p:tag value="5 développeurs" severity="info" styleClass="text-xs" />
</div>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-100 border-round p-4 text-center">
<div class="w-6rem h-6rem border-circle bg-green-100 flex align-items-center justify-content-center mx-auto mb-3">
<i class="pi pi-wrench text-green-500 text-3xl"></i>
</div>
<h6 class="text-900 font-semibold mb-2">Support Technique</h6>
<p class="text-600 text-sm mb-3">
Équipe dédiée à l'assistance utilisateurs,
maintenance et résolution des incidents.
</p>
<div class="flex align-items-center justify-content-center gap-2">
<p:tag value="3 techniciens" severity="success" styleClass="text-xs" />
</div>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-100 border-round p-4 text-center">
<div class="w-6rem h-6rem border-circle bg-purple-100 flex align-items-center justify-content-center mx-auto mb-3">
<i class="pi pi-palette text-purple-500 text-3xl"></i>
</div>
<h6 class="text-900 font-semibold mb-2">UX/UI Design</h6>
<p class="text-600 text-sm mb-3">
Designers spécialisés dans l'expérience utilisateur
et l'interface moderne.
</p>
<div class="flex align-items-center justify-content-center gap-2">
<p:tag value="2 designers" severity="help" styleClass="text-xs" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Contact et liens -->
<div class="grid">
<div class="col-12">
<div class="surface-card border-round p-4 text-center">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-send mr-2"></i>
Nous Contacter
</h4>
<div class="grid">
<div class="col-12 lg:col-3">
<div class="surface-100 hover:surface-200 border-round p-4 cursor-pointer transition-duration-200">
<i class="pi pi-envelope text-3xl text-blue-500 mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Email</h6>
<p class="text-600 text-sm">contact@unionflow.dev</p>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 hover:surface-200 border-round p-4 cursor-pointer transition-duration-200">
<i class="pi pi-globe text-3xl text-green-500 mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Site Web</h6>
<p class="text-600 text-sm">www.unionflow.dev</p>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 hover:surface-200 border-round p-4 cursor-pointer transition-duration-200">
<i class="pi pi-github text-3xl text-purple-500 mb-3"></i>
<h6 class="text-900 font-semibold mb-2">GitHub</h6>
<p class="text-600 text-sm">github.com/unionflow</p>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 hover:surface-200 border-round p-4 cursor-pointer transition-duration-200">
<i class="pi pi-twitter text-3xl text-blue-400 mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Twitter</h6>
<p class="text-600 text-sm">@unionflow_dev</p>
</div>
</div>
</div>
<div class="mt-6 pt-4 border-top-1 border-200">
<p class="text-600 text-sm mb-2">
© 2024 UnionFlow. Tous droits réservés.
</p>
<p class="text-500 text-xs">
Développé avec ❤️ pour les communautés d'Afrique de l'Ouest par Lions Dev
</p>
</div>
</div>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,158 @@
<!DOCTYPE html>
<ui:composition template="/templates/main-template.xhtml"
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">
<ui:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Demande d'Aide - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formDemande">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div>
<h3 class="m-0">
<i class="pi pi-heart text-primary mr-2"></i>
Nouvelle Demande d'Aide
</h3>
<p class="text-600 m-0 mt-2">
Soumettez une demande d'aide pour vous ou un membre de votre organisation
</p>
</div>
</div>
</div>
<!-- Formulaire de demande -->
<div class="card">
<h5 class="mb-3">Informations de la Demande</h5>
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="typeAide" value="Type d'aide *"/>
<p:selectOneMenu id="typeAide" value="#{demandesAideBean.nouvelleDemande.type}" styleClass="w-full">
<f:selectItem itemLabel="Sélectionnez un type" itemValue=""/>
<f:selectItem itemLabel="Aide Médicale" itemValue="AIDE_MEDICALE"/>
<f:selectItem itemLabel="Aide Alimentaire" itemValue="AIDE_ALIMENTAIRE"/>
<f:selectItem itemLabel="Aide Éducative" itemValue="AIDE_EDUCATIVE"/>
<f:selectItem itemLabel="Aide Logement" itemValue="AIDE_LOGEMENT"/>
<f:selectItem itemLabel="Aide d'Urgence" itemValue="AIDE_URGENCE"/>
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="urgence" value="Niveau d'urgence *"/>
<p:selectOneMenu id="urgence" value="#{demandesAideBean.nouvelleDemande.urgence}" styleClass="w-full">
<f:selectItem itemLabel="Sélectionnez un niveau" itemValue=""/>
<f:selectItem itemLabel="Faible" itemValue="FAIBLE"/>
<f:selectItem itemLabel="Moyenne" itemValue="MOYENNE"/>
<f:selectItem itemLabel="Haute" itemValue="HAUTE"/>
<f:selectItem itemLabel="Critique" itemValue="CRITIQUE"/>
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="demandeur" value="Nom du demandeur *"/>
<p:inputText id="demandeur" value="#{demandesAideBean.nouvelleDemande.demandeur}"
styleClass="w-full" required="true"/>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="telephone" value="Téléphone *"/>
<p:inputText id="telephone" value="#{demandesAideBean.nouvelleDemande.telephone}"
styleClass="w-full" required="true"/>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="email" value="Email"/>
<p:inputText id="email" value="#{demandesAideBean.nouvelleDemande.email}"
styleClass="w-full"/>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="localisation" value="Localisation *"/>
<p:inputText id="localisation" value="#{demandesAideBean.nouvelleDemande.localisation}"
styleClass="w-full" required="true"/>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="montantDemande" value="Montant demandé (FCFA) *"/>
<p:inputNumber id="montantDemande" value="#{demandesAideBean.nouvelleDemande.montantDemande}"
styleClass="w-full" required="true" minValue="0"/>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="dateLimite" value="Date limite souhaitée"/>
<p:calendar id="dateLimite" value="#{demandesAideBean.nouvelleDemande.dateLimite}"
styleClass="w-full" pattern="dd/MM/yyyy"/>
</div>
</div>
<div class="col-12">
<div class="field">
<p:outputLabel for="motif" value="Motif de la demande *"/>
<p:inputText id="motif" value="#{demandesAideBean.nouvelleDemande.motif}"
styleClass="w-full" required="true"/>
</div>
</div>
<div class="col-12">
<div class="field">
<p:outputLabel for="description" value="Description détaillée *"/>
<p:inputTextarea id="description" value="#{demandesAideBean.nouvelleDemande.description}"
rows="5" styleClass="w-full" required="true"/>
</div>
</div>
</div>
<div class="flex justify-content-end gap-2 mt-4">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler"/>
<ui:param name="icon" value="pi pi-times"/>
<ui:param name="outcome" value="dashboardPage"/>
</ui:include>
<p:commandButton value="Soumettre la demande"
icon="pi pi-send"
styleClass="ui-button-success"
action="#{demandesAideBean.creerDemande}"
update="@form"
oncomplete="if(!args.validationFailed) {PF('dlgConfirmation').show();}"/>
</div>
</div>
</h:form>
<!-- Dialog de confirmation -->
<p:dialog header="Demande soumise" widgetVar="dlgConfirmation" modal="true" width="400">
<div class="text-center p-4">
<i class="pi pi-check-circle text-green-500 text-6xl mb-3"></i>
<h4 class="mb-2">Votre demande a été soumise avec succès</h4>
<p class="text-600">Elle sera traitée dans les plus brefs délais.</p>
<div class="flex justify-content-center gap-2 mt-4">
<p:commandButton value="OK"
styleClass="ui-button-primary"
onclick="PF('dlgConfirmation').hide(); window.location.href='#{request.contextPath}/pages/secure/dashboard.xhtml';"/>
</div>
</div>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,170 @@
<!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:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Documentation Complète - UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête -->
<div class="grid mb-4">
<div class="col-12">
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
<div class="flex align-items-center justify-content-between mb-4">
<div>
<h2 class="text-900 font-bold text-4xl mb-2">
<i class="pi pi-info-circle text-blue-500 mr-3"></i>
Documentation Complète
</h2>
<p class="text-600 text-lg mb-0">
Documentation technique et fonctionnelle d'UnionFlow
</p>
</div>
<div class="flex gap-2">
<p:commandButton value="Version PDF"
styleClass="p-button-outlined"
icon="pi pi-file-pdf" />
<p:commandButton value="API Docs"
styleClass="p-button-info p-button-outlined"
icon="pi pi-code" />
</div>
</div>
<!-- Statistiques -->
<div class="grid">
<div class="col-12 lg:col-3">
<div class="surface-100 border-round-lg p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-blue-500 mb-2">45</div>
<div class="text-900 font-semibold mb-1">Articles</div>
<div class="text-600 text-sm">Documentation complète</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round-lg p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-green-500 mb-2">12</div>
<div class="text-900 font-semibold mb-1">Mis à Jour</div>
<div class="text-600 text-sm">Ce mois-ci</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round-lg p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-purple-500 mb-2">6</div>
<div class="text-900 font-semibold mb-1">Catégories</div>
<div class="text-600 text-sm">Thématiques</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round-lg p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-orange-500 mb-2">3</div>
<div class="text-900 font-semibold mb-1">Langages</div>
<div class="text-600 text-sm">API supportées</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Catégories de documentation -->
<div class="grid">
<div class="col-12 lg:col-6 xl:col-4">
<div class="surface-100 hover:surface-200 border-round-lg p-4 cursor-pointer transition-all transition-duration-200 h-full">
<div class="flex align-items-center mb-3">
<i class="pi pi-book text-2xl mr-3 text-blue-500"></i>
<p:tag value="GUIDE" severity="success" styleClass="text-xs" />
</div>
<h5 class="text-900 font-bold mb-2">Guide Utilisateur</h5>
<p class="text-600 text-sm mb-3">Documentation complète pour l'utilisation d'UnionFlow</p>
<div class="flex justify-content-between">
<span class="text-600 text-xs"><i class="pi pi-clock mr-1"></i>15 min</span>
<span class="text-600 text-xs"><i class="pi pi-eye mr-1"></i>250</span>
</div>
</div>
</div>
<div class="col-12 lg:col-6 xl:col-4">
<div class="surface-100 hover:surface-200 border-round-lg p-4 cursor-pointer transition-all transition-duration-200 h-full">
<div class="flex align-items-center mb-3">
<i class="pi pi-code text-2xl mr-3 text-green-500"></i>
<p:tag value="API" severity="info" styleClass="text-xs" />
</div>
<h5 class="text-900 font-bold mb-2">API REST</h5>
<p class="text-600 text-sm mb-3">Documentation complète de l'API REST UnionFlow</p>
<div class="flex justify-content-between">
<span class="text-600 text-xs"><i class="pi pi-clock mr-1"></i>25 min</span>
<span class="text-600 text-xs"><i class="pi pi-eye mr-1"></i>180</span>
</div>
</div>
</div>
<div class="col-12 lg:col-6 xl:col-4">
<div class="surface-100 hover:surface-200 border-round-lg p-4 cursor-pointer transition-all transition-duration-200 h-full">
<div class="flex align-items-center mb-3">
<i class="pi pi-cog text-2xl mr-3 text-orange-500"></i>
<p:tag value="CONFIG" severity="warning" styleClass="text-xs" />
</div>
<h5 class="text-900 font-bold mb-2">Configuration</h5>
<p class="text-600 text-sm mb-3">Guide de configuration et paramétrage du système</p>
<div class="flex justify-content-between">
<span class="text-600 text-xs"><i class="pi pi-clock mr-1"></i>20 min</span>
<span class="text-600 text-xs"><i class="pi pi-eye mr-1"></i>95</span>
</div>
</div>
</div>
<div class="col-12 lg:col-6 xl:col-4">
<div class="surface-100 hover:surface-200 border-round-lg p-4 cursor-pointer transition-all transition-duration-200 h-full">
<div class="flex align-items-center mb-3">
<i class="pi pi-wrench text-2xl mr-3 text-red-500"></i>
<p:tag value="DEPANNAGE" severity="danger" styleClass="text-xs" />
</div>
<h5 class="text-900 font-bold mb-2">Dépannage</h5>
<p class="text-600 text-sm mb-3">Solutions aux problèmes courants et dépannage</p>
<div class="flex justify-content-between">
<span class="text-600 text-xs"><i class="pi pi-clock mr-1"></i>30 min</span>
<span class="text-600 text-xs"><i class="pi pi-eye mr-1"></i>340</span>
</div>
</div>
</div>
<div class="col-12 lg:col-6 xl:col-4">
<div class="surface-100 hover:surface-200 border-round-lg p-4 cursor-pointer transition-all transition-duration-200 h-full">
<div class="flex align-items-center mb-3">
<i class="pi pi-link text-2xl mr-3 text-purple-500"></i>
<p:tag value="INTEGRATION" severity="success" styleClass="text-xs" />
</div>
<h5 class="text-900 font-bold mb-2">Intégrations</h5>
<p class="text-600 text-sm mb-3">Intégration avec des systèmes tiers et webhooks</p>
<div class="flex justify-content-between">
<span class="text-600 text-xs"><i class="pi pi-clock mr-1"></i>35 min</span>
<span class="text-600 text-xs"><i class="pi pi-eye mr-1"></i>75</span>
</div>
</div>
</div>
<div class="col-12 lg:col-6 xl:col-4">
<div class="surface-100 hover:surface-200 border-round-lg p-4 cursor-pointer transition-all transition-duration-200 h-full">
<div class="flex align-items-center mb-3">
<i class="pi pi-shield text-2xl mr-3 text-indigo-500"></i>
<p:tag value="SECURITE" severity="info" styleClass="text-xs" />
</div>
<h5 class="text-900 font-bold mb-2">Sécurité</h5>
<p class="text-600 text-sm mb-3">Bonnes pratiques de sécurité et authentification</p>
<div class="flex justify-content-between">
<span class="text-600 text-xs"><i class="pi pi-clock mr-1"></i>28 min</span>
<span class="text-600 text-xs"><i class="pi pi-eye mr-1"></i>120</span>
</div>
</div>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,469 @@
<!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:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Questions Fréquentes - UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<div class="flex align-items-center justify-content-between mb-4">
<div>
<h2 class="text-900 font-bold text-4xl mb-2">
<i class="pi pi-question-circle text-blue-500 mr-3"></i>
Questions Fréquentes
</h2>
<p class="text-600 text-lg mb-0">
Trouvez rapidement des réponses aux questions les plus courantes
</p>
</div>
<div class="flex gap-2">
<p:commandButton value="Poser une Question"
styleClass="p-button-primary"
icon="pi pi-plus"
onclick="PF('questionDialog').show()" />
<p:commandButton value="Contacter le Support"
styleClass="p-button-outlined"
icon="pi pi-phone" />
</div>
</div>
<!-- Statistiques -->
<div class="grid">
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-blue-500 mb-2">47</div>
<div class="text-900 font-semibold mb-1">Questions</div>
<div class="text-600 text-sm">Dans la FAQ</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-green-500 mb-2">94%</div>
<div class="text-900 font-semibold mb-1">Résolution</div>
<div class="text-600 text-sm">Taux de satisfaction</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-purple-500 mb-2">2.3m</div>
<div class="text-900 font-semibold mb-1">Temps Moyen</div>
<div class="text-600 text-sm">De réponse</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-orange-500 mb-2">8</div>
<div class="text-900 font-semibold mb-1">Catégories</div>
<div class="text-600 text-sm">Thématiques</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Recherche rapide -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h:form id="rechercheForm">
<div class="formgrid grid">
<div class="field col-12 lg:col-8">
<label for="rechercheQuestion" class="block text-900 font-semibold mb-2">
<i class="pi pi-search mr-2"></i>Rechercher dans la FAQ
</label>
<p:inputText id="rechercheQuestion"
placeholder="Tapez votre question ou mots-clés..."
styleClass="w-full" />
</div>
<div class="field col-12 lg:col-4">
<label for="categorieRecherche" class="block text-900 font-semibold mb-2">Catégorie</label>
<p:selectOneMenu id="categorieRecherche" styleClass="w-full">
<f:selectItem itemLabel="Toutes les catégories" itemValue="" />
<f:selectItem itemLabel="Compte et Connexion" itemValue="compte" />
<f:selectItem itemLabel="Gestion des Membres" itemValue="membres" />
<f:selectItem itemLabel="Finances et Cotisations" itemValue="finances" />
<f:selectItem itemLabel="Événements" itemValue="evenements" />
<f:selectItem itemLabel="Rapports et Exports" itemValue="rapports" />
<f:selectItem itemLabel="Administration" itemValue="admin" />
<f:selectItem itemLabel="Support Technique" itemValue="technique" />
<f:selectItem itemLabel="Sécurité" itemValue="securite" />
</p:selectOneMenu>
</div>
</div>
</h:form>
</div>
</div>
</div>
<!-- Questions populaires -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-star-fill text-yellow-500 mr-2"></i>
Questions les Plus Populaires
</h4>
<div class="grid">
<div class="col-12 lg:col-6">
<div class="surface-100 hover:surface-200 border-round p-3 cursor-pointer transition-duration-200 mb-3">
<div class="flex align-items-center justify-content-between">
<div class="flex-1">
<h6 class="text-900 font-semibold mb-1">Comment réinitialiser mon mot de passe ?</h6>
<p class="text-600 text-sm mb-0">Procédure de récupération de compte</p>
</div>
<div class="flex align-items-center gap-2 ml-3">
<p:tag value="3.2k vues" severity="info" styleClass="text-xs" />
<i class="pi pi-angle-right text-300"></i>
</div>
</div>
</div>
<div class="surface-100 hover:surface-200 border-round p-3 cursor-pointer transition-duration-200 mb-3">
<div class="flex align-items-center justify-content-between">
<div class="flex-1">
<h6 class="text-900 font-semibold mb-1">Comment exporter la liste des membres ?</h6>
<p class="text-600 text-sm mb-0">Export Excel et PDF personnalisés</p>
</div>
<div class="flex align-items-center gap-2 ml-3">
<p:tag value="2.8k vues" severity="success" styleClass="text-xs" />
<i class="pi pi-angle-right text-300"></i>
</div>
</div>
</div>
<div class="surface-100 hover:surface-200 border-round p-3 cursor-pointer transition-duration-200">
<div class="flex align-items-center justify-content-between">
<div class="flex-1">
<h6 class="text-900 font-semibold mb-1">Configurer les notifications email ?</h6>
<p class="text-600 text-sm mb-0">Paramétrage des alertes automatiques</p>
</div>
<div class="flex align-items-center gap-2 ml-3">
<p:tag value="2.1k vues" severity="warning" styleClass="text-xs" />
<i class="pi pi-angle-right text-300"></i>
</div>
</div>
</div>
</div>
<div class="col-12 lg:col-6">
<div class="surface-100 hover:surface-200 border-round p-3 cursor-pointer transition-duration-200 mb-3">
<div class="flex align-items-center justify-content-between">
<div class="flex-1">
<h6 class="text-900 font-semibold mb-1">Organiser un événement étape par étape ?</h6>
<p class="text-600 text-sm mb-0">Guide complet de création d'événement</p>
</div>
<div class="flex align-items-center gap-2 ml-3">
<p:tag value="1.9k vues" severity="help" styleClass="text-xs" />
<i class="pi pi-angle-right text-300"></i>
</div>
</div>
</div>
<div class="surface-100 hover:surface-200 border-round p-3 cursor-pointer transition-duration-200 mb-3">
<div class="flex align-items-center justify-content-between">
<div class="flex-1">
<h6 class="text-900 font-semibold mb-1">Gérer les rôles et permissions ?</h6>
<p class="text-600 text-sm mb-0">Attribution des droits d'accès</p>
</div>
<div class="flex align-items-center gap-2 ml-3">
<p:tag value="1.7k vues" severity="danger" styleClass="text-xs" />
<i class="pi pi-angle-right text-300"></i>
</div>
</div>
</div>
<div class="surface-100 hover:surface-200 border-round p-3 cursor-pointer transition-duration-200">
<div class="flex align-items-center justify-content-between">
<div class="flex-1">
<h6 class="text-900 font-semibold mb-1">Problème de connexion lente ?</h6>
<p class="text-600 text-sm mb-0">Solutions de performance</p>
</div>
<div class="flex align-items-center gap-2 ml-3">
<p:tag value="1.4k vues" severity="info" styleClass="text-xs" />
<i class="pi pi-angle-right text-300"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- FAQ par catégories -->
<div class="grid">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-list mr-2"></i>
FAQ par Catégories
</h4>
<p:tabView>
<!-- Compte et Connexion -->
<p:tab title="🔐 Compte et Connexion">
<div class="p-0">
<div class="mb-4">
<h6 class="text-900 font-semibold mb-3 p-3 surface-100 border-round">
<i class="pi pi-key mr-2"></i>Authentification et Sécurité
</h6>
<div class="surface-100 border-round p-3 mb-3">
<div class="flex align-items-center justify-content-between cursor-pointer">
<h6 class="text-900 font-semibold mb-2">Comment créer un compte utilisateur ?</h6>
<i class="pi pi-angle-down text-600"></i>
</div>
<p class="text-600 line-height-3 mb-3">
Seul un administrateur peut créer de nouveaux comptes utilisateurs. Rendez-vous dans "Administration" → "Gestion Utilisateurs" → "Nouvel Utilisateur".
Remplissez les informations obligatoires et attribuez un rôle approprié.
</p>
<div class="flex gap-2">
<p:commandButton value="Voir le Guide"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-book" />
<p:commandButton value="Tutoriel Vidéo"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-video" />
</div>
</div>
<div class="surface-100 border-round p-3 mb-3">
<div class="flex align-items-center justify-content-between cursor-pointer">
<h6 class="text-900 font-semibold mb-2">Pourquoi ma session expire-t-elle souvent ?</h6>
<i class="pi pi-angle-down text-600"></i>
</div>
<p class="text-600 line-height-3 mb-3">
Par sécurité, les sessions expirent après 30 minutes d'inactivité. Vous pouvez cocher "Se souvenir de moi"
lors de la connexion pour étendre cette durée. Si le problème persiste, videz le cache de votre navigateur.
</p>
<div class="surface-blue-50 border-left-3 border-blue-500 p-3">
<h6 class="text-blue-800 font-semibold mb-2">
<i class="pi pi-info-circle mr-2"></i>Conseil Pro
</h6>
<p class="text-blue-700 text-sm mb-0">
Activez les notifications push pour être alerté avant l'expiration de votre session.
</p>
</div>
</div>
<div class="surface-100 border-round p-3">
<div class="flex align-items-center justify-content-between cursor-pointer">
<h6 class="text-900 font-semibold mb-2">Comment activer l'authentification à deux facteurs ?</h6>
<i class="pi pi-angle-down text-600"></i>
</div>
<p class="text-600 line-height-3 mb-3">
Allez dans "Mon Espace Personnel" → "Paramètres Compte" → "Sécurité" → "Authentification 2FA".
Scannez le QR code avec Google Authenticator ou Authy, puis validez avec le code généré.
</p>
</div>
</div>
</div>
</p:tab>
<!-- Gestion des Membres -->
<p:tab title="👥 Gestion des Membres">
<div class="p-0">
<div class="mb-4">
<h6 class="text-900 font-semibold mb-3 p-3 surface-100 border-round">
<i class="pi pi-users mr-2"></i>Inscription et Modification
</h6>
<div class="surface-100 border-round p-3 mb-3">
<div class="flex align-items-center justify-content-between cursor-pointer">
<h6 class="text-900 font-semibold mb-2">Que faire si un membre refuse son adhésion ?</h6>
<i class="pi pi-angle-down text-600"></i>
</div>
<p class="text-600 line-height-3 mb-3">
Rendez-vous dans "Gestion des Adhésions" → "Validation des Demandes", trouvez la demande concernée
et cliquez sur "Rejeter". Ajoutez un motif de refus qui sera envoyé automatiquement au demandeur.
</p>
<div class="surface-orange-50 border-left-3 border-orange-500 p-3">
<h6 class="text-orange-800 font-semibold mb-2">
<i class="pi pi-exclamation-triangle mr-2"></i>Important
</h6>
<p class="text-orange-700 text-sm mb-0">
Assurez-vous de documenter les raisons du refus pour le suivi administratif.
</p>
</div>
</div>
<div class="surface-100 border-round p-3 mb-3">
<div class="flex align-items-center justify-content-between cursor-pointer">
<h6 class="text-900 font-semibold mb-2">Comment transférer un membre vers une autre organisation ?</h6>
<i class="pi pi-angle-down text-600"></i>
</div>
<p class="text-600 line-height-3">
Cette fonctionnalité n'est disponible que pour les Super-Administrateurs. Contactez le support
avec les détails du transfert : membre concerné, organisation de destination et justification.
</p>
</div>
</div>
</div>
</p:tab>
<!-- Finances -->
<p:tab title="💰 Finances">
<div class="p-0">
<div class="mb-4">
<h6 class="text-900 font-semibold mb-3 p-3 surface-100 border-round">
<i class="pi pi-dollar mr-2"></i>Cotisations et Paiements
</h6>
<div class="surface-100 border-round p-3 mb-3">
<div class="flex align-items-center justify-content-between cursor-pointer">
<h6 class="text-900 font-semibold mb-2">Comment configurer les cotisations automatiques ?</h6>
<i class="pi pi-angle-down text-600"></i>
</div>
<p class="text-600 line-height-3 mb-3">
Allez dans "Gestion Financière" → "Cotisations" → "Configuration Auto". Définissez le montant,
la périodicité (mensuelle/annuelle) et les conditions de prélèvement automatique.
</p>
<div class="grid">
<div class="col-12 md:col-6">
<p:commandButton value="Guide Configuration"
styleClass="p-button-outlined p-button-sm w-full"
icon="pi pi-cog" />
</div>
<div class="col-12 md:col-6">
<p:commandButton value="Tester la Config"
styleClass="p-button-outlined p-button-sm w-full"
icon="pi pi-play" />
</div>
</div>
</div>
<div class="surface-100 border-round p-3">
<div class="flex align-items-center justify-content-between cursor-pointer">
<h6 class="text-900 font-semibold mb-2">Un paiement mobile money a échoué, que faire ?</h6>
<i class="pi pi-angle-down text-600"></i>
</div>
<p class="text-600 line-height-3 mb-3">
Vérifiez d'abord le statut dans "Historique Paiements". Si le paiement est marqué "Échec",
cliquez sur "Relancer" ou demandez au membre de réessayer avec un solde suffisant.
</p>
</div>
</div>
</div>
</p:tab>
<!-- Support Technique -->
<p:tab title="🔧 Support Technique">
<div class="p-0">
<div class="mb-4">
<h6 class="text-900 font-semibold mb-3 p-3 surface-100 border-round">
<i class="pi pi-wrench mr-2"></i>Problèmes Courants
</h6>
<div class="surface-100 border-round p-3 mb-3">
<div class="flex align-items-center justify-content-between cursor-pointer">
<h6 class="text-900 font-semibold mb-2">L'application est lente ou ne répond pas ?</h6>
<i class="pi pi-angle-down text-600"></i>
</div>
<p class="text-600 line-height-3 mb-3">
1. Vérifiez votre connexion internet<br/>
2. Videz le cache : Ctrl+Maj+Suppr (Chrome)<br/>
3. Redémarrez votre navigateur<br/>
4. Essayez en navigation privée
</p>
<div class="surface-green-50 border-left-3 border-green-500 p-3">
<h6 class="text-green-800 font-semibold mb-2">
<i class="pi pi-check-circle mr-2"></i>Solution Rapide
</h6>
<p class="text-green-700 text-sm mb-0">
90% des problèmes de lenteur sont résolus en vidant le cache navigateur.
</p>
</div>
</div>
<div class="surface-100 border-round p-3">
<div class="flex align-items-center justify-content-between cursor-pointer">
<h6 class="text-900 font-semibold mb-2">Erreur "Page non trouvée" en naviguant ?</h6>
<i class="pi pi-angle-down text-600"></i>
</div>
<p class="text-600 line-height-3 mb-3">
Cette erreur peut survenir après une mise à jour. Déconnectez-vous complètement,
fermez tous les onglets UnionFlow, puis reconnectez-vous.
</p>
</div>
</div>
</div>
</p:tab>
</p:tabView>
</div>
</div>
</div>
<!-- Dialog Nouvelle Question -->
<p:dialog id="questionDialog"
widgetVar="questionDialog"
header="Poser une Nouvelle Question"
modal="true"
width="700"
styleClass="surface-0">
<h:form id="questionForm">
<div class="ui-fluid">
<div class="formgrid grid">
<div class="field col-12 lg:col-6">
<label for="categorieQuestion" class="block text-900 font-semibold mb-2">Catégorie *</label>
<p:selectOneMenu id="categorieQuestion" styleClass="w-full">
<f:selectItem itemLabel="Sélectionnez une catégorie" itemValue="" />
<f:selectItem itemLabel="Compte et Connexion" itemValue="compte" />
<f:selectItem itemLabel="Gestion des Membres" itemValue="membres" />
<f:selectItem itemLabel="Finances" itemValue="finances" />
<f:selectItem itemLabel="Événements" itemValue="evenements" />
<f:selectItem itemLabel="Support Technique" itemValue="technique" />
<f:selectItem itemLabel="Autre" itemValue="autre" />
</p:selectOneMenu>
</div>
<div class="field col-12 lg:col-6">
<label for="prioriteQuestion" class="block text-900 font-semibold mb-2">Priorité</label>
<p:selectOneMenu id="prioriteQuestion" styleClass="w-full">
<f:selectItem itemLabel="Normale" itemValue="normale" />
<f:selectItem itemLabel="Haute" itemValue="haute" />
<f:selectItem itemLabel="Urgente" itemValue="urgente" />
</p:selectOneMenu>
</div>
<div class="field col-12">
<label for="titreQuestion" class="block text-900 font-semibold mb-2">Titre de votre question *</label>
<p:inputText id="titreQuestion"
placeholder="Résumez votre question en une phrase"
styleClass="w-full" />
</div>
<div class="field col-12">
<label for="detailQuestion" class="block text-900 font-semibold mb-2">Description détaillée *</label>
<p:inputTextarea id="detailQuestion"
rows="6"
placeholder="Décrivez votre problème ou question en détail..."
styleClass="w-full" />
</div>
</div>
<div class="flex justify-content-end gap-2 mt-4">
<p:commandButton value="Annuler"
styleClass="p-button-outlined"
onclick="PF('questionDialog').hide()"
type="button" />
<p:commandButton value="Envoyer la Question"
styleClass="p-button-primary"
icon="pi pi-send" />
</div>
</div>
</h:form>
</p:dialog>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,435 @@
<!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:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Guide Utilisateur - UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête -->
<div class="grid mb-4">
<div class="col-12">
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
<div class="flex align-items-center justify-content-between mb-4">
<div>
<h2 class="text-900 font-bold text-4xl mb-2">
<i class="pi pi-book text-primary mr-3"></i>
Guide Utilisateur UnionFlow
</h2>
<p class="text-600 text-lg mb-0">
Apprenez à utiliser efficacement toutes les fonctionnalités d'UnionFlow
</p>
</div>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Version PDF" />
<ui:param name="icon" value="pi pi-file-pdf" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Rechercher" />
<ui:param name="icon" value="pi pi-search" />
<ui:param name="onclick" value="PF('rechercheDialog').show()" />
<ui:param name="styleClass" value="ui-button-outlined" />
</ui:include>
</div>
</div>
<!-- Barre de progression des sections lues -->
<div class="surface-100 border-round-lg p-4">
<div class="flex align-items-center justify-content-between mb-3">
<h4 class="text-900 font-semibold mb-0">Votre Progression</h4>
<span class="text-600 text-sm">#{guideBean.sectionsLues} / #{guideBean.totalSections} sections</span>
</div>
<p:progressBar value="#{guideBean.pourcentageProgression}"
styleClass="mb-2"
displayValue="true" />
<div class="flex gap-2">
<p:tag value="Débutant" severity="info" rendered="#{guideBean.pourcentageProgression lt 30}" />
<p:tag value="Intermédiaire" severity="warning" rendered="#{guideBean.pourcentageProgression ge 30 and guideBean.pourcentageProgression lt 70}" />
<p:tag value="Avancé" severity="success" rendered="#{guideBean.pourcentageProgression ge 70}" />
</div>
</div>
</div>
</div>
</div>
<!-- Navigation et contenu principal -->
<div class="grid">
<!-- Navigation latérale -->
<div class="col-12 lg:col-3">
<div class="surface-section border-round">
<h:form id="navigationForm">
<!-- Header avec progression -->
<div class="surface-card border-round p-4 mb-3">
<div class="flex align-items-center justify-content-between mb-3">
<h5 class="text-900 font-semibold m-0">
<i class="pi pi-bookmark text-primary mr-2"></i>
Table des Matières
</h5>
<p:tag value="#{guideBean.sectionsLues}/#{guideBean.totalSections}"
severity="info"
styleClass="text-xs" />
</div>
<p:progressBar value="#{guideBean.pourcentageProgression}"
showValue="false"
styleClass="h-1rem" />
<div class="text-600 text-xs mt-1">#{guideBean.pourcentageProgression}% terminé</div>
</div>
<!-- Navigation par PanelMenu -->
<p:panelMenu styleClass="border-none">
<!-- Section 1: Premiers pas -->
<p:submenu label="🚀 Premiers Pas" icon="pi pi-play">
<ui:repeat value="#{guideBean.sectionsPremiersPas}" var="item">
<p:menuitem value="#{item.titre}"
icon="#{item.lu ? 'pi pi-check-circle text-green-500' : 'pi pi-circle text-300'}"
action="#{guideBean.naviguerVers(item.id)}"
styleClass="#{item.lu ? 'text-900' : 'text-600'} p-menuitem-link" />
</ui:repeat>
</p:submenu>
<!-- Section 2: Gestion des membres -->
<p:submenu label="👥 Gestion des Membres" icon="pi pi-users">
<ui:repeat value="#{guideBean.sectionsMembres}" var="item">
<p:menuitem value="#{item.titre}"
icon="#{item.lu ? 'pi pi-check-circle text-green-500' : 'pi pi-circle text-300'}"
action="#{guideBean.naviguerVers(item.id)}"
styleClass="#{item.lu ? 'text-900' : 'text-600'} p-menuitem-link" />
</ui:repeat>
</p:submenu>
<!-- Section 3: Finances -->
<p:submenu label="💰 Finances et Cotisations" icon="pi pi-dollar">
<ui:repeat value="#{guideBean.sectionsFinances}" var="item">
<p:menuitem value="#{item.titre}"
icon="#{item.lu ? 'pi pi-check-circle text-green-500' : 'pi pi-circle text-300'}"
action="#{guideBean.naviguerVers(item.id)}"
styleClass="#{item.lu ? 'text-900' : 'text-600'} p-menuitem-link" />
</ui:repeat>
</p:submenu>
<!-- Section 4: Événements -->
<p:submenu label="📅 Événements" icon="pi pi-calendar">
<ui:repeat value="#{guideBean.sectionsEvenements}" var="item">
<p:menuitem value="#{item.titre}"
icon="#{item.lu ? 'pi pi-check-circle text-green-500' : 'pi pi-circle text-300'}"
action="#{guideBean.naviguerVers(item.id)}"
styleClass="#{item.lu ? 'text-900' : 'text-600'} p-menuitem-link" />
</ui:repeat>
</p:submenu>
<!-- Section 5: Rapports -->
<p:submenu label="📊 Rapports et Analyses" icon="pi pi-chart-bar">
<ui:repeat value="#{guideBean.sectionsRapports}" var="item">
<p:menuitem value="#{item.titre}"
icon="#{item.lu ? 'pi pi-check-circle text-green-500' : 'pi pi-circle text-300'}"
action="#{guideBean.naviguerVers(item.id)}"
styleClass="#{item.lu ? 'text-900' : 'text-600'} p-menuitem-link" />
</ui:repeat>
</p:submenu>
<!-- Section 6: Administration -->
<p:submenu label="⚙️ Administration" icon="pi pi-cog">
<ui:repeat value="#{guideBean.sectionsAdmin}" var="item">
<p:menuitem value="#{item.titre}"
icon="#{item.lu ? 'pi pi-check-circle text-green-500' : 'pi pi-circle text-300'}"
action="#{guideBean.naviguerVers(item.id)}"
styleClass="#{item.lu ? 'text-900' : 'text-600'} p-menuitem-link" />
</ui:repeat>
</p:submenu>
</p:panelMenu>
<!-- Actions rapides -->
<div class="surface-card border-round p-3 mt-3">
<div class="text-center">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Tout marquer comme lu" />
<ui:param name="icon" value="pi pi-check-square" />
<ui:param name="outlined" value="false" />
<ui:param name="styleClass" value="ui-button-text ui-button-sm w-full" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Réinitialiser progression" />
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="outlined" value="false" />
<ui:param name="styleClass" value="ui-button-text ui-button-sm w-full mt-2" />
</ui:include>
</div>
</div>
</h:form>
</div>
</div>
<!-- Contenu principal -->
<div class="col-12 lg:col-9">
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
<!-- En-tête de section -->
<div class="flex align-items-center justify-content-between mb-4 pb-3 border-bottom-1 border-200">
<div>
<h3 class="text-900 font-bold text-2xl mb-1">#{guideBean.sectionCourante.titre}</h3>
<div class="flex align-items-center gap-2">
<p:tag value="#{guideBean.sectionCourante.categorie}" severity="info" styleClass="text-xs" />
<span class="text-600 text-sm">#{guideBean.sectionCourante.tempsLecture} min de lecture</span>
</div>
</div>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-bookmark" />
<ui:param name="title" value="Marquer comme favori" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-sm" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-share-alt" />
<ui:param name="title" value="Partager" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-sm" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-print" />
<ui:param name="title" value="Imprimer" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-sm" />
</ui:include>
</div>
</div>
<!-- Contenu de la section -->
<div class="line-height-3">
<ui:fragment rendered="#{guideBean.sectionCourante.id == 'premiers-pas-connexion'}">
<h4 class="text-primary font-semibold mb-3">Se connecter à UnionFlow</h4>
<p class="text-700 mb-4">
Pour accéder à UnionFlow, vous devez disposer d'un compte utilisateur avec les droits appropriés.
Voici comment procéder pour votre première connexion.
</p>
<div class="surface-100 border-round-lg p-4 mb-4">
<h5 class="text-900 font-semibold mb-3">
<i class="pi pi-lightbulb text-yellow-500 mr-2"></i>
Étapes de connexion
</h5>
<ol class="text-700 pl-4">
<li class="mb-2">Rendez-vous sur la page de connexion UnionFlow</li>
<li class="mb-2">Sélectionnez votre type de compte (Membre, Admin, etc.)</li>
<li class="mb-2">Saisissez votre email ou nom d'utilisateur</li>
<li class="mb-2">Entrez votre mot de passe</li>
<li class="mb-2">Cliquez sur "Se connecter"</li>
</ol>
</div>
<div class="surface-orange-50 border-left-3 border-orange-500 p-4 mb-4">
<h6 class="text-orange-800 font-semibold mb-2">
<i class="pi pi-exclamation-triangle mr-2"></i>
Mot de passe oublié ?
</h6>
<p class="text-orange-700 mb-0">
Cliquez sur "Mot de passe oublié ?" sur la page de connexion pour recevoir
un lien de réinitialisation par email.
</p>
</div>
<h5 class="text-900 font-semibold mb-3">Types de comptes disponibles</h5>
<div class="grid">
<div class="col-12 md:col-4">
<div class="surface-100 border-round p-3 text-center">
<i class="pi pi-crown text-red-500 text-2xl mb-2"></i>
<h6 class="text-900 font-semibold">Super-Admin</h6>
<p class="text-600 text-sm mb-0">Accès complet au système</p>
</div>
</div>
<div class="col-12 md:col-4">
<div class="surface-100 border-round p-3 text-center">
<i class="pi pi-shield text-blue-500 text-2xl mb-2"></i>
<h6 class="text-900 font-semibold">Admin Organisation</h6>
<p class="text-600 text-sm mb-0">Gestion d'une organisation</p>
</div>
</div>
<div class="col-12 md:col-4">
<div class="surface-100 border-round p-3 text-center">
<i class="pi pi-user text-green-500 text-2xl mb-2"></i>
<h6 class="text-900 font-semibold">Membre</h6>
<p class="text-600 text-sm mb-0">Accès membre standard</p>
</div>
</div>
</div>
</ui:fragment>
<ui:fragment rendered="#{guideBean.sectionCourante.id == 'membres-inscription'}">
<h4 class="text-primary font-semibold mb-3">Inscrire un nouveau membre</h4>
<p class="text-700 mb-4">
L'inscription d'un nouveau membre est une procédure simple qui permet d'ajouter
une personne à votre organisation avec toutes les informations nécessaires.
</p>
<div class="surface-blue-50 border-left-3 border-blue-500 p-4 mb-4">
<h6 class="text-blue-800 font-semibold mb-2">
<i class="pi pi-info-circle mr-2"></i>
Prérequis
</h6>
<ul class="text-blue-700 pl-4 mb-0">
<li>Avoir les droits d'administration ou de gestion des membres</li>
<li>Disposer des informations personnelles du futur membre</li>
<li>Connaître le type d'adhésion souhaité</li>
</ul>
</div>
<h5 class="text-900 font-semibold mb-3">Processus d'inscription</h5>
<div class="timeline-container mb-4">
<div class="flex mb-4">
<div class="flex flex-column align-items-center mr-4">
<div class="w-3rem h-3rem border-circle bg-blue-500 text-white flex align-items-center justify-content-center font-bold">1</div>
<div class="w-1 h-4rem bg-blue-200 mt-2"></div>
</div>
<div class="flex-1">
<h6 class="text-900 font-semibold mb-2">Accéder au formulaire</h6>
<p class="text-600 mb-0">Menu "Gestion des Membres" → "Nouvelle Inscription"</p>
</div>
</div>
<div class="flex mb-4">
<div class="flex flex-column align-items-center mr-4">
<div class="w-3rem h-3rem border-circle bg-blue-500 text-white flex align-items-center justify-content-center font-bold">2</div>
<div class="w-1 h-4rem bg-blue-200 mt-2"></div>
</div>
<div class="flex-1">
<h6 class="text-900 font-semibold mb-2">Remplir les informations personnelles</h6>
<p class="text-600 mb-0">Nom, prénom, date de naissance, contact, adresse</p>
</div>
</div>
<div class="flex mb-4">
<div class="flex flex-column align-items-center mr-4">
<div class="w-3rem h-3rem border-circle bg-blue-500 text-white flex align-items-center justify-content-center font-bold">3</div>
<div class="w-1 h-4rem bg-blue-200 mt-2"></div>
</div>
<div class="flex-1">
<h6 class="text-900 font-semibold mb-2">Choisir le type d'adhésion</h6>
<p class="text-600 mb-0">Membre actif, associé, d'honneur, etc.</p>
</div>
</div>
<div class="flex">
<div class="flex flex-column align-items-center mr-4">
<div class="w-3rem h-3rem border-circle bg-green-500 text-white flex align-items-center justify-content-center">
<i class="pi pi-check"></i>
</div>
</div>
<div class="flex-1">
<h6 class="text-900 font-semibold mb-2">Validation et enregistrement</h6>
<p class="text-600 mb-0">Le membre reçoit automatiquement ses identifiants par email</p>
</div>
</div>
</div>
</ui:fragment>
<ui:fragment rendered="#{guideBean.sectionCourante.id == 'default'}">
<div class="text-center py-8">
<i class="pi pi-book text-6xl text-300 mb-4"></i>
<h4 class="text-600 mb-3">Sélectionnez une section</h4>
<p class="text-500">Choisissez un sujet dans le menu de gauche pour commencer la lecture</p>
</div>
</ui:fragment>
</div>
<!-- Navigation entre sections -->
<div class="flex justify-content-between align-items-center mt-6 pt-4 border-top-1 border-200">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Section précédente" />
<ui:param name="icon" value="pi pi-angle-left" />
<ui:param name="action" value="#{guideBean.sectionPrecedente}" />
<ui:param name="outlined" value="true" />
<ui:param name="rendered" value="#{guideBean.APrecedent}" />
</ui:include>
<div class="flex gap-2" rendered="#{guideBean.sectionCourante.id != 'default'}">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Marquer comme lu" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{guideBean.marquerCommeLu}" />
<ui:param name="rendered" value="#{not guideBean.sectionCourante.lu}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Lu" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="outlined" value="true" />
<ui:param name="disabled" value="true" />
<ui:param name="rendered" value="#{guideBean.sectionCourante.lu}" />
</ui:include>
</div>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Section suivante" />
<ui:param name="icon" value="pi pi-angle-right" />
<ui:param name="action" value="#{guideBean.sectionSuivante}" />
<ui:param name="outlined" value="true" />
<ui:param name="rendered" value="#{guideBean.ASuivant}" />
</ui:include>
</div>
</div>
</div>
</div>
<!-- Dialog de recherche -->
<p:dialog id="rechercheDialog"
widgetVar="rechercheDialog"
header="Rechercher dans le guide"
modal="true"
width="600"
styleClass="surface-0">
<h:form id="rechercheForm">
<div class="ui-fluid">
<div class="field">
<label for="termeRecherche" class="block text-900 font-semibold mb-2">
<i class="pi pi-search mr-2"></i>Terme à rechercher
</label>
<p:inputText id="termeRecherche"
value="#{guideBean.termeRecherche}"
placeholder="Ex: connexion, membre, cotisation..."
styleClass="w-full">
<p:ajax event="keyup" update="resultatsRecherche" delay="300" />
</p:inputText>
</div>
<h:panelGroup id="resultatsRecherche" layout="block">
<ui:repeat value="#{guideBean.resultatsRecherche}" var="resultat" rendered="#{not empty guideBean.termeRecherche}">
<div class="surface-100 border-round p-3 mb-3 cursor-pointer hover:surface-200 transition-duration-200"
onclick="#{guideBean.naviguerVers(resultat.id)}; PF('rechercheDialog').hide();">
<div class="flex align-items-center justify-content-between">
<div>
<h6 class="text-900 font-semibold mb-1">#{resultat.titre}</h6>
<p class="text-600 text-sm mb-1">#{resultat.description}</p>
<p:tag value="#{resultat.categorie}" severity="info" styleClass="text-xs" />
</div>
<i class="pi pi-angle-right text-300"></i>
</div>
</div>
</ui:repeat>
<div class="text-center py-4" rendered="#{not empty guideBean.termeRecherche and empty guideBean.resultatsRecherche}">
<i class="pi pi-search text-3xl text-300 mb-2"></i>
<p class="text-600">Aucun résultat trouvé pour "#{guideBean.termeRecherche}"</p>
</div>
</h:panelGroup>
</div>
</h:form>
</p:dialog>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<ui:composition template="/templates/main-template.xhtml"
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">
<ui:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Historique des Demandes d'Aide - UnionFlow</ui:define>
<ui:define name="content">
<!-- Redirection vers history.xhtml (WOU/DRY - réutiliser la même page) -->
<h:form>
<p:commandButton value="Voir l'historique"
action="#{demandesAideBean.voirHistorique()}"
styleClass="ui-button-primary"/>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,132 @@
<!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:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Historique des Demandes d'Aide - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formHistory">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div>
<h3 class="m-0">
<i class="pi pi-history text-primary mr-2"></i>
Historique des Demandes d'Aide
</h3>
<p class="text-600 m-0 mt-2">
Consultez l'historique complet de toutes les demandes d'aide
</p>
</div>
</div>
</div>
<!-- Filtres -->
<div class="card mb-3">
<h5 class="mb-3">Filtres</h5>
<div class="grid">
<div class="col-12 md:col-3">
<p:outputLabel for="statutFilter" value="Statut"/>
<p:selectOneMenu id="statutFilter" value="#{demandesAideBean.filtres.statut}" styleClass="w-full">
<f:selectItem itemLabel="Tous" itemValue=""/>
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE"/>
<f:selectItem itemLabel="Approuvée" itemValue="APPROUVEE"/>
<f:selectItem itemLabel="Rejetée" itemValue="REJETEE"/>
<p:ajax event="change" update="dtHistory"/>
</p:selectOneMenu>
</div>
<div class="col-12 md:col-3">
<p:outputLabel for="typeFilter" value="Type"/>
<p:selectOneMenu id="typeFilter" value="#{demandesAideBean.filtres.type}" styleClass="w-full">
<f:selectItem itemLabel="Tous" itemValue=""/>
<f:selectItem itemLabel="Médicale" itemValue="AIDE_MEDICALE"/>
<f:selectItem itemLabel="Alimentaire" itemValue="AIDE_ALIMENTAIRE"/>
<f:selectItem itemLabel="Éducative" itemValue="AIDE_EDUCATIVE"/>
<p:ajax event="change" update="dtHistory"/>
</p:selectOneMenu>
</div>
<div class="col-12 md:col-3">
<p:outputLabel for="dateDebut" value="Date début"/>
<p:calendar id="dateDebut" value="#{demandesAideBean.filtres.dateDebut}"
styleClass="w-full" pattern="dd/MM/yyyy">
<p:ajax event="dateSelect" update="dtHistory"/>
</p:calendar>
</div>
<div class="col-12 md:col-3">
<p:outputLabel for="dateFin" value="Date fin"/>
<p:calendar id="dateFin" value="#{demandesAideBean.filtres.dateFin}"
styleClass="w-full" pattern="dd/MM/yyyy">
<p:ajax event="dateSelect" update="dtHistory"/>
</p:calendar>
</div>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<p:commandButton value="Rechercher"
icon="pi pi-search"
styleClass="ui-button-primary"
action="#{demandesAideBean.rechercher}"
update="dtHistory"/>
<p:commandButton value="Réinitialiser"
icon="pi pi-refresh"
styleClass="ui-button-outlined ui-button-secondary"
action="#{demandesAideBean.reinitialiserFiltres}"
update="@form"/>
</div>
</div>
<!-- Liste -->
<div class="card">
<h5 class="mb-3">Historique Complet</h5>
<p:dataTable id="dtHistory"
var="demande"
value="#{demandesAideBean.demandesFiltrees}"
paginator="true"
rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,25"
currentPageReportTemplate="Affichage {startRecord}-{endRecord} sur {totalRecords}">
<p:column headerText="Demandeur" sortBy="#{demande.demandeur}">
<div>
<div class="font-medium">#{demande.demandeur}</div>
<small class="text-600">#{demande.localisation}</small>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{demande.type}">
<p:tag value="#{demande.typeLibelle}" severity="#{demande.typeSeverity}" icon="pi #{demande.typeIcon}"/>
</p:column>
<p:column headerText="Montant" sortBy="#{demande.montantDemande}">
<div class="font-bold text-green-500">#{demande.montantDemande} FCFA</div>
</p:column>
<p:column headerText="Statut" sortBy="#{demande.statut}">
<p:tag value="#{demande.statutLibelle}"
severity="#{demande.statutSeverity}"
icon="pi #{demande.statutIcon}"/>
</p:column>
<p:column headerText="Date" sortBy="#{demande.dateDemande}">
<h:outputText value="#{demande.dateDemande}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:outputText>
</p:column>
<p:column headerText="Actions" style="width:150px">
<p:commandButton icon="pi pi-eye"
styleClass="ui-button-rounded ui-button-text ui-button-info"
action="#{demandesAideBean.voirDetails(demande)}"
title="Voir détails"/>
</p:column>
</p:dataTable>
</div>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,401 @@
<!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:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Nouveautés - UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<div class="flex align-items-center justify-content-between mb-4">
<div>
<h2 class="text-900 font-bold text-4xl mb-2">
<i class="pi pi-sparkles text-purple-500 mr-3"></i>
Nouveautés UnionFlow
</h2>
<p class="text-600 text-lg mb-0">
Découvrez les dernières fonctionnalités, améliorations et corrections
</p>
</div>
<div class="flex gap-2">
<p:commandButton value="S'abonner aux Notifications"
styleClass="p-button-primary"
icon="pi pi-bell" />
<p:commandButton value="Historique Complet"
styleClass="p-button-outlined"
icon="pi pi-history" />
</div>
</div>
<!-- Statistiques des versions -->
<div class="grid">
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-blue-500 mb-2">v2.1.3</div>
<div class="text-900 font-semibold mb-1">Version Actuelle</div>
<div class="text-600 text-sm">Stable</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-green-500 mb-2">47</div>
<div class="text-900 font-semibold mb-1">Nouvelles Fonctionnalités</div>
<div class="text-600 text-sm">Cette année</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-orange-500 mb-2">134</div>
<div class="text-900 font-semibold mb-1">Améliorations</div>
<div class="text-600 text-sm">Depuis v2.0</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-red-500 mb-2">89</div>
<div class="text-900 font-semibold mb-1">Corrections</div>
<div class="text-600 text-sm">Bugs résolus</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Filtres -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h:form id="filtresForm">
<div class="formgrid grid">
<div class="field col-12 md:col-3">
<label for="typeChangement" class="block text-900 font-semibold mb-2">Type de changement</label>
<p:selectOneMenu id="typeChangement" styleClass="w-full">
<f:selectItem itemLabel="Tous les changements" itemValue="" />
<f:selectItem itemLabel="Nouvelles fonctionnalités" itemValue="feature" />
<f:selectItem itemLabel="Améliorations" itemValue="enhancement" />
<f:selectItem itemLabel="Corrections de bugs" itemValue="bugfix" />
<f:selectItem itemLabel="Sécurité" itemValue="security" />
<f:selectItem itemLabel="Performance" itemValue="performance" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-3">
<label for="versionFilter" class="block text-900 font-semibold mb-2">Version</label>
<p:selectOneMenu id="versionFilter" styleClass="w-full">
<f:selectItem itemLabel="Toutes les versions" itemValue="" />
<f:selectItem itemLabel="v2.1.x" itemValue="2.1" />
<f:selectItem itemLabel="v2.0.x" itemValue="2.0" />
<f:selectItem itemLabel="v1.9.x" itemValue="1.9" />
<f:selectItem itemLabel="v1.8.x" itemValue="1.8" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-3">
<label for="periodeFilter" class="block text-900 font-semibold mb-2">Période</label>
<p:selectOneMenu id="periodeFilter" styleClass="w-full">
<f:selectItem itemLabel="Toutes les périodes" itemValue="" />
<f:selectItem itemLabel="Ce mois-ci" itemValue="mois" />
<f:selectItem itemLabel="3 derniers mois" itemValue="trimestre" />
<f:selectItem itemLabel="Cette année" itemValue="annee" />
<f:selectItem itemLabel="Année dernière" itemValue="annee_precedente" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-3">
<label for="rechercheNouveautes" class="block text-900 font-semibold mb-2">Rechercher</label>
<p:inputText id="rechercheNouveautes"
placeholder="Fonctionnalité, mot-clé..."
styleClass="w-full" />
</div>
</div>
</h:form>
</div>
</div>
</div>
<!-- Version actuelle highlight -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4 border-2 border-primary">
<div class="flex align-items-center gap-3 mb-4">
<div class="w-4rem h-4rem border-circle bg-primary flex align-items-center justify-content-center">
<i class="pi pi-star text-white text-2xl"></i>
</div>
<div>
<h4 class="text-primary font-bold text-2xl mb-1">Version 2.1.3 - Dernière version stable</h4>
<p class="text-600 mb-0">Publiée le 18 janvier 2024 • Mise à jour de sécurité importante</p>
</div>
<div class="ml-auto">
<p:tag value="ACTUELLE" severity="success" styleClass="text-lg p-2" />
</div>
</div>
<div class="grid">
<div class="col-12 lg:col-8">
<h6 class="text-900 font-semibold mb-3">🔒 Améliorations de Sécurité</h6>
<ul class="list-none p-0 m-0 mb-4">
<li class="flex align-items-start mb-2">
<i class="pi pi-check-circle text-green-500 mr-2 mt-1"></i>
<span class="text-700">Correction de faille XSS dans les formulaires de commentaires</span>
</li>
<li class="flex align-items-start mb-2">
<i class="pi pi-check-circle text-green-500 mr-2 mt-1"></i>
<span class="text-700">Mise à jour des dépendances de sécurité critiques</span>
</li>
<li class="flex align-items-start">
<i class="pi pi-check-circle text-green-500 mr-2 mt-1"></i>
<span class="text-700">Renforcement de la validation des uploads de fichiers</span>
</li>
</ul>
<h6 class="text-900 font-semibold mb-3">🐛 Corrections de Bugs</h6>
<ul class="list-none p-0 m-0">
<li class="flex align-items-start mb-2">
<i class="pi pi-check-circle text-blue-500 mr-2 mt-1"></i>
<span class="text-700">Résolution du problème d'export Excel sur Chrome 120+</span>
</li>
<li class="flex align-items-start">
<i class="pi pi-check-circle text-blue-500 mr-2 mt-1"></i>
<span class="text-700">Correction de l'affichage des dates sur mobile</span>
</li>
</ul>
</div>
<div class="col-12 lg:col-4">
<div class="surface-100 border-round p-3">
<h6 class="text-900 font-semibold mb-3">📊 Impact de la mise à jour</h6>
<div class="flex align-items-center justify-content-between mb-2">
<span class="text-600 text-sm">Sécurité</span>
<p:tag value="CRITIQUE" severity="danger" styleClass="text-xs" />
</div>
<div class="flex align-items-center justify-content-between mb-2">
<span class="text-600 text-sm">Compatibilité</span>
<p:tag value="100%" severity="success" styleClass="text-xs" />
</div>
<div class="flex align-items-center justify-content-between">
<span class="text-600 text-sm">Taille</span>
<span class="text-600 text-sm">15.2 MB</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Historique des versions -->
<div class="grid">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-history mr-2"></i>
Historique des Versions
</h4>
<!-- Version 2.1.2 -->
<div class="surface-100 border-round p-4 mb-4">
<div class="flex align-items-center gap-3 mb-3">
<div class="w-3rem h-3rem border-circle bg-blue-100 flex align-items-center justify-content-center">
<i class="pi pi-code text-blue-600 text-xl"></i>
</div>
<div class="flex-1">
<h5 class="text-900 font-bold mb-1">Version 2.1.2</h5>
<p class="text-600 text-sm mb-0">Publiée le 3 janvier 2024</p>
</div>
<div class="flex gap-2">
<p:tag value="STABLE" severity="success" styleClass="text-xs" />
<p:tag value="MAJEURE" severity="info" styleClass="text-xs" />
</div>
</div>
<div class="grid">
<div class="col-12 lg:col-6">
<h6 class="text-blue-600 font-semibold mb-2">✨ Nouvelles Fonctionnalités</h6>
<ul class="list-none p-0 m-0 mb-3">
<li class="flex align-items-start mb-2">
<i class="pi pi-plus-circle text-green-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Système de notifications en temps réel</span>
</li>
<li class="flex align-items-start mb-2">
<i class="pi pi-plus-circle text-green-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Export PDF avec signature électronique</span>
</li>
<li class="flex align-items-start">
<i class="pi pi-plus-circle text-green-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Interface de gestion des rôles avancée</span>
</li>
</ul>
</div>
<div class="col-12 lg:col-6">
<h6 class="text-orange-600 font-semibold mb-2">⚡ Améliorations</h6>
<ul class="list-none p-0 m-0">
<li class="flex align-items-start mb-2">
<i class="pi pi-arrow-up text-orange-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Performance des rapports (+40%)</span>
</li>
<li class="flex align-items-start">
<i class="pi pi-arrow-up text-orange-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Interface mobile optimisée</span>
</li>
</ul>
</div>
</div>
</div>
<!-- Version 2.1.1 -->
<div class="surface-100 border-round p-4 mb-4">
<div class="flex align-items-center gap-3 mb-3">
<div class="w-3rem h-3rem border-circle bg-green-100 flex align-items-center justify-content-center">
<i class="pi pi-wrench text-green-600 text-xl"></i>
</div>
<div class="flex-1">
<h5 class="text-900 font-bold mb-1">Version 2.1.1</h5>
<p class="text-600 text-sm mb-0">Publiée le 15 décembre 2023</p>
</div>
<div class="flex gap-2">
<p:tag value="MAINTENANCE" severity="warning" styleClass="text-xs" />
</div>
</div>
<h6 class="text-red-600 font-semibold mb-2">🐛 Corrections</h6>
<ul class="list-none p-0 m-0">
<li class="flex align-items-start mb-2">
<i class="pi pi-times-circle text-red-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Correction du bug d'affichage dans les tableaux de données</span>
</li>
<li class="flex align-items-start mb-2">
<i class="pi pi-times-circle text-red-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Résolution des problèmes de connexion SSO</span>
</li>
<li class="flex align-items-start">
<i class="pi pi-times-circle text-red-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Correction des erreurs de validation de formulaires</span>
</li>
</ul>
</div>
<!-- Version 2.1.0 -->
<div class="surface-100 border-round p-4 mb-4">
<div class="flex align-items-center gap-3 mb-3">
<div class="w-3rem h-3rem border-circle bg-purple-100 flex align-items-center justify-content-center">
<i class="pi pi-star text-purple-600 text-xl"></i>
</div>
<div class="flex-1">
<h5 class="text-900 font-bold mb-1">Version 2.1.0 - Release Majeure</h5>
<p class="text-600 text-sm mb-0">Publiée le 1er décembre 2023</p>
</div>
<div class="flex gap-2">
<p:tag value="MAJEURE" severity="success" styleClass="text-xs" />
<p:tag value="LTS" severity="info" styleClass="text-xs" />
</div>
</div>
<div class="grid">
<div class="col-12">
<div class="surface-blue-50 border-left-3 border-blue-500 p-3 mb-3">
<h6 class="text-blue-800 font-semibold mb-2">
<i class="pi pi-info-circle mr-2"></i>Points forts de cette version
</h6>
<p class="text-blue-700 text-sm mb-0">
Version LTS avec support étendu jusqu'en décembre 2025.
Architecture modernisée et nouvelles API REST.
</p>
</div>
</div>
<div class="col-12 lg:col-4">
<h6 class="text-blue-600 font-semibold mb-2">✨ Nouvelles Fonctionnalités</h6>
<ul class="list-none p-0 m-0">
<li class="flex align-items-start mb-1">
<i class="pi pi-plus-circle text-green-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">API REST v2 complète</span>
</li>
<li class="flex align-items-start mb-1">
<i class="pi pi-plus-circle text-green-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Workflow personnalisables</span>
</li>
<li class="flex align-items-start">
<i class="pi pi-plus-circle text-green-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Tableau de bord configurable</span>
</li>
</ul>
</div>
<div class="col-12 lg:col-4">
<h6 class="text-orange-600 font-semibold mb-2">⚡ Améliorations</h6>
<ul class="list-none p-0 m-0">
<li class="flex align-items-start mb-1">
<i class="pi pi-arrow-up text-orange-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Performances globales +60%</span>
</li>
<li class="flex align-items-start mb-1">
<i class="pi pi-arrow-up text-orange-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Sécurité renforcée (2FA)</span>
</li>
<li class="flex align-items-start">
<i class="pi pi-arrow-up text-orange-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">UX/UI redesignée</span>
</li>
</ul>
</div>
<div class="col-12 lg:col-4">
<h6 class="text-purple-600 font-semibold mb-2">🔧 Technique</h6>
<ul class="list-none p-0 m-0">
<li class="flex align-items-start mb-1">
<i class="pi pi-cog text-purple-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Migration Quarkus 3.x</span>
</li>
<li class="flex align-items-start mb-1">
<i class="pi pi-cog text-purple-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Base de données optimisée</span>
</li>
<li class="flex align-items-start">
<i class="pi pi-cog text-purple-500 mr-2 mt-1"></i>
<span class="text-700 text-sm">Cache distribué Redis</span>
</li>
</ul>
</div>
</div>
</div>
<!-- Version 2.0.5 -->
<div class="surface-100 border-round p-4 opacity-70">
<div class="flex align-items-center gap-3 mb-3">
<div class="w-3rem h-3rem border-circle bg-gray-100 flex align-items-center justify-content-center">
<i class="pi pi-history text-gray-600 text-xl"></i>
</div>
<div class="flex-1">
<h5 class="text-900 font-bold mb-1">Version 2.0.5</h5>
<p class="text-600 text-sm mb-0">Publiée le 10 novembre 2023 • Support terminé</p>
</div>
<div class="flex gap-2">
<p:tag value="EOL" severity="danger" styleClass="text-xs" />
<p:tag value="ARCHIVÉE" severity="secondary" styleClass="text-xs" />
</div>
</div>
<p class="text-600 text-sm mb-0">
Dernière version de la branche 2.0.x. Migration vers 2.1.x recommandée pour les corrections de sécurité.
</p>
</div>
<!-- Pagination ou Load More -->
<div class="text-center mt-4">
<p:commandButton value="Charger Plus de Versions"
styleClass="p-button-outlined"
icon="pi pi-angle-down" />
</div>
</div>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,79 @@
<!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:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Mes Demandes d'Aide - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formRequests">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div>
<h3 class="m-0">
<i class="pi pi-list text-primary mr-2"></i>
Mes Demandes d'Aide
</h3>
<p class="text-600 m-0 mt-2">
Consultez l'état de vos demandes d'aide
</p>
</div>
<div class="flex gap-2 mt-2 md:mt-0">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouvelle demande"/>
<ui:param name="icon" value="pi pi-plus"/>
<ui:param name="outcome" value="aideDemandePage"/>
</ui:include>
</div>
</div>
</div>
<!-- Liste des demandes -->
<div class="card">
<h5 class="mb-3">Historique de mes Demandes</h5>
<p:dataTable id="dtDemandes"
var="demande"
value="#{demandesAideBean.demandesFiltrees}"
paginator="true"
rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,25"
currentPageReportTemplate="Affichage {startRecord}-{endRecord} sur {totalRecords}">
<p:column headerText="Type" sortBy="#{demande.type}">
<p:tag value="#{demande.typeLibelle}" severity="#{demande.typeSeverity}" icon="pi #{demande.typeIcon}"/>
</p:column>
<p:column headerText="Montant" sortBy="#{demande.montantDemande}">
<div class="font-bold text-green-500">#{demande.montantDemande} FCFA</div>
</p:column>
<p:column headerText="Statut" sortBy="#{demande.statut}">
<p:tag value="#{demande.statutLibelle}"
severity="#{demande.statutSeverity}"
icon="pi #{demande.statutIcon}"/>
</p:column>
<p:column headerText="Date" sortBy="#{demande.dateDemande}">
<h:outputText value="#{demande.dateDemande}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:outputText>
</p:column>
<p:column headerText="Actions" style="width:150px">
<p:commandButton icon="pi pi-eye"
styleClass="ui-button-rounded ui-button-text ui-button-info"
action="#{demandesAideBean.voirDetails(demande)}"
title="Voir détails"/>
</p:column>
</p:dataTable>
</div>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,120 @@
<!DOCTYPE html>
<ui:composition template="/templates/main-template.xhtml"
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">
<ui:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Statistiques des Demandes d'Aide - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formStatistiques">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div>
<h3 class="m-0">
<i class="pi pi-chart-bar text-primary mr-2"></i>
Statistiques des Demandes d'Aide
</h3>
<p class="text-600 m-0 mt-2">
Analyse et statistiques détaillées des demandes d'aide
</p>
</div>
<div class="flex gap-2 mt-2 md:mt-0">
<p:commandButton value="Actualiser"
icon="pi pi-refresh"
styleClass="ui-button-outlined ui-button-secondary"
action="#{demandesAideBean.actualiser}"
update="@form"/>
</div>
</div>
</div>
<!-- Statistiques principales -->
<div class="grid mb-3">
<div class="col-12 md:col-3">
<div class="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">#{demandesAideBean.statistiques.totalDemandes}</div>
<div class="text-blue-700">Total Demandes</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-inbox text-xl"></i>
</div>
</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="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">#{demandesAideBean.statistiques.demandesEnAttente}</div>
<div class="text-orange-700">En Attente</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-clock text-xl"></i>
</div>
</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="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">#{demandesAideBean.statistiques.demandesApprouvees}</div>
<div class="text-green-700">Approuvées</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-check text-xl"></i>
</div>
</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="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">#{demandesAideBean.statistiques.montantTotalAide}</div>
<div class="text-purple-700">Montant Total</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-dollar text-xl"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Répartition par type -->
<div class="card">
<h5 class="mb-3">Répartition par Type d'Aide</h5>
<div class="grid">
<div class="col-12 md:col-6">
<div class="surface-100 border-round p-4 text-center">
<i class="pi pi-chart-pie text-6xl text-blue-500 mb-3"></i>
<p class="text-600">Graphique de répartition par type</p>
<small class="text-500">À implémenter avec PrimeNG Charts</small>
</div>
</div>
<div class="col-12 md:col-6">
<div class="surface-100 border-round p-4 text-center">
<i class="pi pi-chart-bar text-6xl text-green-500 mb-3"></i>
<p class="text-600">Graphique de répartition par statut</p>
<small class="text-500">À implémenter avec PrimeNG Charts</small>
</div>
</div>
</div>
</div>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,463 @@
<!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:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Suggestions et Feedback - UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<div class="flex align-items-center justify-content-between mb-4">
<div>
<h2 class="text-900 font-bold text-4xl mb-2">
<i class="pi pi-lightbulb text-yellow-500 mr-3"></i>
Suggestions et Feedback
</h2>
<p class="text-600 text-lg mb-0">
Partagez vos idées pour améliorer UnionFlow et votez pour les suggestions de la communauté
</p>
</div>
<div class="flex gap-2">
<p:commandButton value="Nouvelle Suggestion"
styleClass="p-button-primary"
icon="pi pi-plus"
onclick="PF('nouvelleSuggestionDialog').show()" />
<p:commandButton value="Mes Suggestions"
styleClass="p-button-outlined"
icon="pi pi-user" />
</div>
</div>
<!-- Statistiques communauté -->
<div class="grid">
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-blue-500 mb-2">247</div>
<div class="text-900 font-semibold mb-1">Suggestions</div>
<div class="text-600 text-sm">Soumises</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-green-500 mb-2">43</div>
<div class="text-900 font-semibold mb-1">Implémentées</div>
<div class="text-600 text-sm">Dans la v2.0</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-purple-500 mb-2">1,523</div>
<div class="text-900 font-semibold mb-1">Votes</div>
<div class="text-600 text-sm">Ce mois-ci</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-orange-500 mb-2">156</div>
<div class="text-900 font-semibold mb-1">Contributeurs</div>
<div class="text-600 text-sm">Actifs</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Filtres et tri -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h:form id="filtresForm">
<div class="formgrid grid">
<div class="field col-12 md:col-3">
<label for="statutSuggestion" class="block text-900 font-semibold mb-2">Statut</label>
<p:selectOneMenu id="statutSuggestion" styleClass="w-full">
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
<f:selectItem itemLabel="Nouvelle" itemValue="nouvelle" />
<f:selectItem itemLabel="En cours d'évaluation" itemValue="evaluation" />
<f:selectItem itemLabel="Approuvée" itemValue="approuvee" />
<f:selectItem itemLabel="En développement" itemValue="developpement" />
<f:selectItem itemLabel="Implémentée" itemValue="implementee" />
<f:selectItem itemLabel="Rejetée" itemValue="rejetee" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-3">
<label for="categorieSuggestion" class="block text-900 font-semibold mb-2">Catégorie</label>
<p:selectOneMenu id="categorieSuggestion" styleClass="w-full">
<f:selectItem itemLabel="Toutes les catégories" itemValue="" />
<f:selectItem itemLabel="Interface Utilisateur" itemValue="ui" />
<f:selectItem itemLabel="Fonctionnalité" itemValue="feature" />
<f:selectItem itemLabel="Performance" itemValue="performance" />
<f:selectItem itemLabel="Sécurité" itemValue="securite" />
<f:selectItem itemLabel="Intégration" itemValue="integration" />
<f:selectItem itemLabel="Mobile" itemValue="mobile" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-3">
<label for="triSuggestion" class="block text-900 font-semibold mb-2">Trier par</label>
<p:selectOneMenu id="triSuggestion" styleClass="w-full">
<f:selectItem itemLabel="Plus récentes" itemValue="date_desc" />
<f:selectItem itemLabel="Plus anciennes" itemValue="date_asc" />
<f:selectItem itemLabel="Plus votées" itemValue="votes_desc" />
<f:selectItem itemLabel="Moins votées" itemValue="votes_asc" />
<f:selectItem itemLabel="Statut" itemValue="statut" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-3">
<label for="rechercheSuggestion" class="block text-900 font-semibold mb-2">Rechercher</label>
<p:inputText id="rechercheSuggestion"
placeholder="Mots-clés..."
styleClass="w-full" />
</div>
</div>
</h:form>
</div>
</div>
</div>
<!-- Suggestions populaires -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-star-fill text-yellow-500 mr-2"></i>
Suggestions les Plus Populaires
</h4>
<!-- Suggestion 1 - Très populaire -->
<div class="surface-100 hover:surface-200 border-round p-4 mb-4 cursor-pointer transition-duration-200">
<div class="flex align-items-start justify-content-between mb-3">
<div class="flex-1">
<div class="flex align-items-center gap-2 mb-2">
<h6 class="text-900 font-semibold mb-0">Mode sombre pour l'interface</h6>
<p:tag value="EN DÉVELOPPEMENT" severity="info" styleClass="text-xs" />
<p:tag value="INTERFACE" severity="help" styleClass="text-xs" />
</div>
<p class="text-600 text-sm mb-2">Proposé par Marie Dubois • il y a 2 semaines</p>
<p class="text-700 line-height-3 mb-3">
Ajouter un thème sombre à l'interface pour réduire la fatigue visuelle lors de longues sessions de travail.
Particulièrement utile pour les utilisateurs travaillant en soirée ou dans des environnements peu éclairés.
</p>
<div class="flex align-items-center gap-3">
<span class="text-600 text-sm">
<i class="pi pi-comments mr-1"></i>24 commentaires
</span>
<span class="text-600 text-sm">
<i class="pi pi-eye mr-1"></i>847 vues
</span>
</div>
</div>
<div class="text-center ml-4">
<div class="surface-blue-100 border-round p-3 cursor-pointer hover:surface-blue-200 transition-duration-200">
<i class="pi pi-thumbs-up text-blue-600 text-xl mb-1"></i>
<div class="text-blue-600 font-bold text-lg">156</div>
<div class="text-blue-600 text-xs">votes</div>
</div>
</div>
</div>
<div class="surface-blue-50 border-left-3 border-blue-500 p-3">
<p class="text-blue-700 text-sm mb-0">
<i class="pi pi-info-circle mr-2"></i>
<strong>Mise à jour:</strong> Cette fonctionnalité est en cours de développement et sera disponible dans la version 2.2.
</p>
</div>
</div>
<!-- Suggestion 2 - Populaire -->
<div class="surface-100 hover:surface-200 border-round p-4 mb-4 cursor-pointer transition-duration-200">
<div class="flex align-items-start justify-content-between mb-3">
<div class="flex-1">
<div class="flex align-items-center gap-2 mb-2">
<h6 class="text-900 font-semibold mb-0">Export PDF personnalisé avec logo</h6>
<p:tag value="APPROUVÉE" severity="success" styleClass="text-xs" />
<p:tag value="FONCTIONNALITÉ" severity="warning" styleClass="text-xs" />
</div>
<p class="text-600 text-sm mb-2">Proposé par Thomas Martin • il y a 1 mois</p>
<p class="text-700 line-height-3 mb-3">
Permettre l'ajout du logo de l'organisation sur tous les exports PDF (rapports, listes membres, etc.)
pour une meilleure présentation des documents officiels.
</p>
<div class="flex align-items-center gap-3">
<span class="text-600 text-sm">
<i class="pi pi-comments mr-1"></i>18 commentaires
</span>
<span class="text-600 text-sm">
<i class="pi pi-eye mr-1"></i>523 vues
</span>
</div>
</div>
<div class="text-center ml-4">
<div class="surface-green-100 border-round p-3 cursor-pointer hover:surface-green-200 transition-duration-200">
<i class="pi pi-thumbs-up text-green-600 text-xl mb-1"></i>
<div class="text-green-600 font-bold text-lg">98</div>
<div class="text-green-600 text-xs">votes</div>
</div>
</div>
</div>
</div>
<!-- Suggestion 3 - Récente -->
<div class="surface-100 hover:surface-200 border-round p-4 cursor-pointer transition-duration-200">
<div class="flex align-items-start justify-content-between mb-3">
<div class="flex-1">
<div class="flex align-items-center gap-2 mb-2">
<h6 class="text-900 font-semibold mb-0">Notifications push mobiles</h6>
<p:tag value="NOUVELLE" severity="secondary" styleClass="text-xs" />
<p:tag value="MOBILE" severity="info" styleClass="text-xs" />
<p:tag value="NOUVEAU" severity="danger" styleClass="text-xs" />
</div>
<p class="text-600 text-sm mb-2">Proposé par Sophie Leroy • il y a 3 jours</p>
<p class="text-700 line-height-3 mb-3">
Recevoir des notifications push sur mobile pour les événements importants :
nouvelles adhésions, rappels de cotisations, événements à venir, etc.
</p>
<div class="flex align-items-center gap-3">
<span class="text-600 text-sm">
<i class="pi pi-comments mr-1"></i>7 commentaires
</span>
<span class="text-600 text-sm">
<i class="pi pi-eye mr-1"></i>156 vues
</span>
</div>
</div>
<div class="text-center ml-4">
<div class="surface-purple-100 border-round p-3 cursor-pointer hover:surface-purple-200 transition-duration-200">
<i class="pi pi-thumbs-up text-purple-600 text-xl mb-1"></i>
<div class="text-purple-600 font-bold text-lg">34</div>
<div class="text-purple-600 text-xs">votes</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Mes contributions -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-user mr-2"></i>
Mes Contributions
</h4>
<div class="grid">
<!-- Ma suggestion 1 -->
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4">
<div class="flex align-items-center justify-content-between mb-3">
<h6 class="text-900 font-semibold mb-0">Import CSV automatisé</h6>
<p:tag value="EN ÉVALUATION" severity="warning" styleClass="text-xs" />
</div>
<p class="text-600 text-sm mb-2">Soumise il y a 1 semaine</p>
<p class="text-700 text-sm mb-3">
Permettre l'import automatique de fichiers CSV pour les inscriptions en masse...
</p>
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-2">
<i class="pi pi-thumbs-up text-blue-500"></i>
<span class="text-600 text-sm">12 votes</span>
</div>
<p:commandButton value="Modifier"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-pencil" />
</div>
</div>
</div>
<!-- Ma suggestion 2 -->
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4">
<div class="flex align-items-center justify-content-between mb-3">
<h6 class="text-900 font-semibold mb-0">Calendrier partagé équipe</h6>
<p:tag value="IMPLÉMENTÉE" severity="success" styleClass="text-xs" />
</div>
<p class="text-600 text-sm mb-2">Soumise il y a 3 mois</p>
<p class="text-700 text-sm mb-3">
Calendrier collaboratif pour planifier les événements et réunions...
</p>
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-2">
<i class="pi pi-thumbs-up text-green-500"></i>
<span class="text-600 text-sm">67 votes</span>
</div>
<p:commandButton value="Voir Implémentation"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-external-link" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Roadmap des suggestions -->
<div class="grid">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-map mr-2"></i>
Roadmap des Suggestions
</h4>
<div class="grid">
<div class="col-12 lg:col-4">
<div class="surface-100 border-round p-4 h-full">
<h6 class="text-blue-600 font-semibold mb-3">
<i class="pi pi-calendar mr-2"></i>Version 2.2 (Q2 2024)
</h6>
<ul class="list-none p-0 m-0">
<li class="flex align-items-center mb-2">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span class="text-700 text-sm">Mode sombre</span>
</li>
<li class="flex align-items-center mb-2">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span class="text-700 text-sm">Export PDF avec logo</span>
</li>
<li class="flex align-items-center">
<i class="pi pi-clock text-orange-500 mr-2"></i>
<span class="text-700 text-sm">Recherche avancée globale</span>
</li>
</ul>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-100 border-round p-4 h-full">
<h6 class="text-purple-600 font-semibold mb-3">
<i class="pi pi-calendar mr-2"></i>Version 2.3 (Q3 2024)
</h6>
<ul class="list-none p-0 m-0">
<li class="flex align-items-center mb-2">
<i class="pi pi-clock text-orange-500 mr-2"></i>
<span class="text-700 text-sm">Notifications push mobiles</span>
</li>
<li class="flex align-items-center mb-2">
<i class="pi pi-clock text-orange-500 mr-2"></i>
<span class="text-700 text-sm">API REST publique</span>
</li>
<li class="flex align-items-center">
<i class="pi pi-clock text-orange-500 mr-2"></i>
<span class="text-700 text-sm">Tableau de bord personnalisable</span>
</li>
</ul>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-100 border-round p-4 h-full">
<h6 class="text-orange-600 font-semibold mb-3">
<i class="pi pi-calendar mr-2"></i>Version 3.0 (Q4 2024)
</h6>
<ul class="list-none p-0 m-0">
<li class="flex align-items-center mb-2">
<i class="pi pi-circle text-300 mr-2"></i>
<span class="text-700 text-sm">Application mobile native</span>
</li>
<li class="flex align-items-center mb-2">
<i class="pi pi-circle text-300 mr-2"></i>
<span class="text-700 text-sm">Intelligence artificielle</span>
</li>
<li class="flex align-items-center">
<i class="pi pi-circle text-300 mr-2"></i>
<span class="text-700 text-sm">Intégrations avancées</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Dialog Nouvelle Suggestion -->
<p:dialog id="nouvelleSuggestionDialog"
widgetVar="nouvelleSuggestionDialog"
header="Soumettre une Nouvelle Suggestion"
modal="true"
width="800"
styleClass="surface-0">
<h:form id="nouvelleSuggestionForm">
<div class="ui-fluid">
<div class="formgrid grid">
<div class="field col-12 lg:col-6">
<label for="categorieSugg" class="block text-900 font-semibold mb-2">Catégorie *</label>
<p:selectOneMenu id="categorieSugg" styleClass="w-full">
<f:selectItem itemLabel="Sélectionnez une catégorie" itemValue="" />
<f:selectItem itemLabel="Interface Utilisateur" itemValue="ui" />
<f:selectItem itemLabel="Nouvelle Fonctionnalité" itemValue="feature" />
<f:selectItem itemLabel="Amélioration Performance" itemValue="performance" />
<f:selectItem itemLabel="Sécurité" itemValue="securite" />
<f:selectItem itemLabel="Intégration Externe" itemValue="integration" />
<f:selectItem itemLabel="Application Mobile" itemValue="mobile" />
<f:selectItem itemLabel="Rapports et Analytics" itemValue="reporting" />
</p:selectOneMenu>
</div>
<div class="field col-12 lg:col-6">
<label for="prioriteSugg" class="block text-900 font-semibold mb-2">Priorité estimée</label>
<p:selectOneMenu id="prioriteSugg" styleClass="w-full">
<f:selectItem itemLabel="Basse" itemValue="basse" />
<f:selectItem itemLabel="Moyenne" itemValue="moyenne" />
<f:selectItem itemLabel="Haute" itemValue="haute" />
<f:selectItem itemLabel="Critique" itemValue="critique" />
</p:selectOneMenu>
</div>
<div class="field col-12">
<label for="titreSugg" class="block text-900 font-semibold mb-2">Titre de votre suggestion *</label>
<p:inputText id="titreSugg"
placeholder="Résumez votre idée en une phrase claire"
styleClass="w-full" />
</div>
<div class="field col-12">
<label for="descriptionSugg" class="block text-900 font-semibold mb-2">Description détaillée *</label>
<p:inputTextarea id="descriptionSugg"
rows="6"
placeholder="Décrivez votre suggestion : problème rencontré, solution proposée, bénéfices attendus..."
styleClass="w-full" />
</div>
<div class="field col-12">
<label for="justificationSugg" class="block text-900 font-semibold mb-2">Justification métier</label>
<p:inputTextarea id="justificationSugg"
rows="3"
placeholder="Expliquez pourquoi cette fonctionnalité serait utile et pour quels utilisateurs..."
styleClass="w-full" />
</div>
<div class="field col-12">
<label class="block text-900 font-semibold mb-2">Maquettes ou références (optionnel)</label>
<p:fileUpload mode="basic"
multiple="true"
chooseLabel="Choisir des fichiers"
styleClass="w-full" />
<small class="text-500">Images, schémas, liens vers des exemples similaires (max 5MB par fichier)</small>
</div>
</div>
<div class="flex justify-content-end gap-2 mt-4">
<p:commandButton value="Annuler"
styleClass="p-button-outlined"
onclick="PF('nouvelleSuggestionDialog').hide()"
type="button" />
<p:commandButton value="Soumettre la Suggestion"
styleClass="p-button-primary"
icon="pi pi-send" />
</div>
</div>
</h:form>
</p:dialog>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,322 @@
<!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:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Contacter le Support - UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête -->
<div class="grid mb-4">
<div class="col-12">
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
<div class="flex align-items-center justify-content-between mb-4">
<div>
<h2 class="text-900 font-bold text-4xl mb-2">
<i class="pi pi-phone text-green-500 mr-3"></i>
Contacter le Support
</h2>
<p class="text-600 text-lg mb-0">
Notre équipe support est là pour vous aider
</p>
</div>
<div class="flex gap-2">
<p:commandButton value="Nouveau Ticket"
styleClass="p-button-success"
icon="pi pi-plus"
onclick="PF('ticketDialog').show()" />
<p:commandButton value="Base de Connaissances"
styleClass="p-button-info p-button-outlined"
icon="pi pi-book" />
</div>
</div>
<!-- Informations de contact -->
<div class="grid">
<div class="col-12 lg:col-3">
<div class="surface-100 border-round-lg p-4 text-center" style="min-height: 9rem">
<i class="pi pi-clock text-2xl text-blue-500 mb-2"></i>
<div class="text-900 font-semibold mb-1">Temps de Réponse</div>
<div class="text-600 text-sm">Moins de 2h</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round-lg p-4 text-center" style="min-height: 9rem">
<i class="pi pi-check-circle text-2xl text-green-500 mb-2"></i>
<div class="text-900 font-semibold mb-1">Taux de Résolution</div>
<div class="text-600 text-sm">98.5%</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round-lg p-4 text-center" style="min-height: 9rem">
<i class="pi pi-users text-2xl text-purple-500 mb-2"></i>
<div class="text-900 font-semibold mb-1">Satisfaction Client</div>
<div class="text-600 text-sm">4.8/5</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round-lg p-4 text-center" style="min-height: 9rem">
<i class="pi pi-calendar text-2xl text-orange-500 mb-2"></i>
<div class="text-900 font-semibold mb-1">Support</div>
<div class="text-600 text-sm">7j/7 - 24h/24</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Canaux de support -->
<div class="grid mb-4">
<div class="col-12">
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-comment mr-2"></i>
Choisissez votre canal de support
</h4>
<div class="grid">
<div class="col-12 lg:col-4">
<div class="surface-100 hover:surface-200 border-round-lg p-4 cursor-pointer transition-all transition-duration-200 h-full">
<div class="text-center">
<i class="pi pi-ticket text-4xl text-blue-500 mb-3"></i>
<h5 class="text-900 font-bold mb-2">Ticket Support</h5>
<p class="text-600 text-sm mb-3">Pour les problèmes techniques et demandes complexes</p>
<p:commandButton value="Créer un Ticket"
styleClass="p-button-sm w-full"
onclick="PF('ticketDialog').show()" />
<p class="text-500 text-xs mt-2">Réponse sous 2h</p>
</div>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-100 hover:surface-200 border-round-lg p-4 cursor-pointer transition-all transition-duration-200 h-full">
<div class="text-center">
<i class="pi pi-comments text-4xl text-green-500 mb-3"></i>
<h5 class="text-900 font-bold mb-2">Chat en Direct</h5>
<p class="text-600 text-sm mb-3">Support instantané pour les questions urgentes</p>
<p:commandButton value="Démarrer le Chat"
styleClass="p-button-sm w-full p-button-success" />
<p class="text-500 text-xs mt-2">Disponible 9h-18h</p>
</div>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-100 hover:surface-200 border-round-lg p-4 cursor-pointer transition-all transition-duration-200 h-full">
<div class="text-center">
<i class="pi pi-phone text-4xl text-orange-500 mb-3"></i>
<h5 class="text-900 font-bold mb-2">Support Téléphonique</h5>
<p class="text-600 text-sm mb-3">Appelez-nous directement pour une assistance immédiate</p>
<div class="text-900 font-bold text-lg mb-2">+33 1 23 45 67 89</div>
<p class="text-500 text-xs">Lun-Ven 8h-19h</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- FAQ rapide -->
<div class="grid mb-4">
<div class="col-12">
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-question-circle mr-2"></i>
Questions Fréquentes
</h4>
<p:tabView>
<p:tab title="Comment réinitialiser mon mot de passe ?">
<p class="text-600 line-height-3 mb-3">
Pour réinitialiser votre mot de passe, cliquez sur "Mot de passe oublié ?"
sur la page de connexion. Vous recevrez un email avec un lien de réinitialisation
valable pendant 24 heures.
</p>
<p:commandButton value="Réinitialiser maintenant"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-key" />
</p:tab>
<p:tab title="Comment exporter mes données ?">
<p class="text-600 line-height-3 mb-3">
Vous pouvez exporter vos données depuis le menu "Rapports" → "Export Personnalisés".
Plusieurs formats sont disponibles : Excel, PDF, CSV et JSON.
</p>
<div class="flex gap-2">
<p:commandButton value="Guide d'Export"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-book" />
<p:commandButton value="Accéder aux Exports"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-download" />
</div>
</p:tab>
<p:tab title="Problème de performance lente ?">
<p class="text-600 line-height-3 mb-3">
Si l'application semble lente, vérifiez votre connexion internet et
videz le cache de votre navigateur. Pour Chrome : Ctrl+Maj+Suppr.
</p>
<div class="surface-blue-50 border-left-3 border-blue-500 p-3">
<h6 class="text-blue-800 font-semibold mb-2">
<i class="pi pi-info-circle mr-2"></i>Diagnostic automatique
</h6>
<p class="text-blue-700 text-sm mb-0">
Utilisez l'outil de diagnostic intégré pour identifier les problèmes.
</p>
</div>
</p:tab>
<p:tab title="Comment configurer les notifications ?">
<p class="text-600 line-height-3 mb-3">
Rendez-vous dans "Mon Espace Personnel" → "Mes Préférences" → "Notifications"
pour configurer vos alertes par email et dans l'application.
</p>
</p:tab>
</p:tabView>
</div>
</div>
</div>
<!-- Ressources utiles -->
<div class="grid">
<div class="col-12">
<div class="card surface-0 hover:surface-100 border-round-lg transition-all transition-duration-200">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-bookmark mr-2"></i>
Ressources Utiles
</h4>
<div class="grid">
<div class="col-12 lg:col-3">
<div class="flex align-items-center p-3 surface-100 border-round hover:surface-200 cursor-pointer transition-duration-200">
<i class="pi pi-video text-2xl text-purple-500 mr-3"></i>
<div>
<h6 class="text-900 font-semibold mb-1">Tutoriels Vidéo</h6>
<p class="text-600 text-sm mb-0">Guides visuels étape par étape</p>
</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="flex align-items-center p-3 surface-100 border-round hover:surface-200 cursor-pointer transition-duration-200">
<i class="pi pi-book text-2xl text-blue-500 mr-3"></i>
<div>
<h6 class="text-900 font-semibold mb-1">Documentation</h6>
<p class="text-600 text-sm mb-0">Guide complet d'utilisation</p>
</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="flex align-items-center p-3 surface-100 border-round hover:surface-200 cursor-pointer transition-duration-200">
<i class="pi pi-users text-2xl text-green-500 mr-3"></i>
<div>
<h6 class="text-900 font-semibold mb-1">Communauté</h6>
<p class="text-600 text-sm mb-0">Forum d'entraide utilisateurs</p>
</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="flex align-items-center p-3 surface-100 border-round hover:surface-200 cursor-pointer transition-duration-200">
<i class="pi pi-sparkles text-2xl text-orange-500 mr-3"></i>
<div>
<h6 class="text-900 font-semibold mb-1">Nouveautés</h6>
<p class="text-600 text-sm mb-0">Dernières fonctionnalités</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Dialog Nouveau Ticket -->
<p:dialog id="ticketDialog"
widgetVar="ticketDialog"
header="Créer un Ticket Support"
modal="true"
width="700"
styleClass="surface-0">
<h:form id="ticketForm">
<div class="ui-fluid">
<div class="formgrid grid">
<div class="field col-12 lg:col-6">
<label for="sujetTicket" class="block text-900 font-semibold mb-2">Sujet *</label>
<p:inputText id="sujetTicket"
placeholder="Résumé du problème"
required="true"
styleClass="w-full" />
</div>
<div class="field col-12 lg:col-6">
<label for="prioriteTicket" class="block text-900 font-semibold mb-2">Priorité</label>
<p:selectOneMenu id="prioriteTicket" styleClass="w-full">
<f:selectItem itemLabel="Basse" itemValue="BASSE" />
<f:selectItem itemLabel="Normale" itemValue="NORMALE" />
<f:selectItem itemLabel="Haute" itemValue="HAUTE" />
<f:selectItem itemLabel="Urgente" itemValue="URGENTE" />
</p:selectOneMenu>
</div>
<div class="field col-12 lg:col-6">
<label for="categorieTicket" class="block text-900 font-semibold mb-2">Catégorie</label>
<p:selectOneMenu id="categorieTicket" styleClass="w-full">
<f:selectItem itemLabel="Problème Technique" itemValue="TECHNIQUE" />
<f:selectItem itemLabel="Demande de Fonctionnalité" itemValue="FONCTIONNALITE" />
<f:selectItem itemLabel="Question d'Utilisation" itemValue="UTILISATION" />
<f:selectItem itemLabel="Problème de Compte" itemValue="COMPTE" />
<f:selectItem itemLabel="Autre" itemValue="AUTRE" />
</p:selectOneMenu>
</div>
<div class="field col-12 lg:col-6">
<label for="environnement" class="block text-900 font-semibold mb-2">Environnement</label>
<p:inputText id="environnement"
placeholder="Ex: Chrome 120, Windows 11"
styleClass="w-full" />
</div>
<div class="field col-12">
<label for="descriptionTicket" class="block text-900 font-semibold mb-2">Description *</label>
<p:inputTextarea id="descriptionTicket"
rows="5"
placeholder="Décrivez votre problème en détail..."
required="true"
styleClass="w-full" />
</div>
<div class="field col-12">
<label class="block text-900 font-semibold mb-2">Pièces Jointes</label>
<p:fileUpload mode="basic"
multiple="true"
chooseLabel="Choisir des fichiers"
uploadLabel="Télécharger"
cancelLabel="Annuler"
styleClass="w-full" />
<small class="text-500">Formats acceptés: jpg, png, pdf, doc, xlsx (max 10MB)</small>
</div>
</div>
<div class="flex justify-content-end gap-2 mt-4">
<p:commandButton value="Annuler"
styleClass="p-button-outlined"
onclick="PF('ticketDialog').hide()"
type="button" />
<p:commandButton value="Créer le Ticket"
styleClass="p-button-success"
icon="pi pi-send" />
</div>
</div>
</h:form>
</p:dialog>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,437 @@
<!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:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Mes Tickets Support - UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<div class="flex align-items-center justify-content-between mb-4">
<div>
<h2 class="text-900 font-bold text-4xl mb-2">
<i class="pi pi-ticket text-purple-500 mr-3"></i>
Mes Tickets Support
</h2>
<p class="text-600 text-lg mb-0">
Suivez l'état de vos demandes d'assistance et échangez avec notre équipe
</p>
</div>
<div class="flex gap-2">
<p:commandButton value="Nouveau Ticket"
styleClass="p-button-primary"
icon="pi pi-plus"
onclick="PF('nouveauTicketDialog').show()" />
<p:commandButton value="FAQ"
styleClass="p-button-outlined"
icon="pi pi-question-circle" />
</div>
</div>
<!-- Statistiques personnelles -->
<div class="grid">
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-blue-500 mb-2">12</div>
<div class="text-900 font-semibold mb-1">Tickets Créés</div>
<div class="text-600 text-sm">Au total</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-orange-500 mb-2">3</div>
<div class="text-900 font-semibold mb-1">En Attente</div>
<div class="text-600 text-sm">Réponse support</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-green-500 mb-2">8</div>
<div class="text-900 font-semibold mb-1">Résolus</div>
<div class="text-600 text-sm">Avec succès</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-red-500 mb-2">1</div>
<div class="text-900 font-semibold mb-1">Fermé</div>
<div class="text-600 text-sm">Sans résolution</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Filtres -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h:form id="filtresForm">
<div class="formgrid grid">
<div class="field col-12 md:col-3">
<label for="statutFilter" class="block text-900 font-semibold mb-2">Statut</label>
<p:selectOneMenu id="statutFilter" styleClass="w-full">
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
<f:selectItem itemLabel="Ouvert" itemValue="ouvert" />
<f:selectItem itemLabel="En cours" itemValue="en_cours" />
<f:selectItem itemLabel="En attente" itemValue="en_attente" />
<f:selectItem itemLabel="Résolu" itemValue="resolu" />
<f:selectItem itemLabel="Fermé" itemValue="ferme" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-3">
<label for="prioriteFilter" class="block text-900 font-semibold mb-2">Priorité</label>
<p:selectOneMenu id="prioriteFilter" styleClass="w-full">
<f:selectItem itemLabel="Toutes les priorités" itemValue="" />
<f:selectItem itemLabel="Basse" itemValue="basse" />
<f:selectItem itemLabel="Normale" itemValue="normale" />
<f:selectItem itemLabel="Haute" itemValue="haute" />
<f:selectItem itemLabel="Urgente" itemValue="urgente" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-3">
<label for="categorieFilter" class="block text-900 font-semibold mb-2">Catégorie</label>
<p:selectOneMenu id="categorieFilter" styleClass="w-full">
<f:selectItem itemLabel="Toutes les catégories" itemValue="" />
<f:selectItem itemLabel="Problème Technique" itemValue="technique" />
<f:selectItem itemLabel="Demande de Fonctionnalité" itemValue="fonctionnalite" />
<f:selectItem itemLabel="Question d'Utilisation" itemValue="utilisation" />
<f:selectItem itemLabel="Problème de Compte" itemValue="compte" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-3">
<label for="rechercheTicket" class="block text-900 font-semibold mb-2">Rechercher</label>
<p:inputText id="rechercheTicket"
placeholder="Numéro, sujet..."
styleClass="w-full" />
</div>
</div>
</h:form>
</div>
</div>
</div>
<!-- Liste des tickets -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-list mr-2"></i>
Historique de vos Tickets
</h4>
<!-- Ticket 1 - En cours -->
<div class="surface-100 hover:surface-200 border-round p-4 mb-3 cursor-pointer transition-duration-200">
<div class="flex align-items-center justify-content-between mb-3">
<div class="flex align-items-center gap-3">
<div class="w-3rem h-3rem border-circle bg-orange-100 flex align-items-center justify-content-center">
<i class="pi pi-clock text-orange-600 text-xl"></i>
</div>
<div>
<h6 class="text-900 font-semibold mb-1">#TK-2024-0157 - Problème d'export Excel</h6>
<div class="flex align-items-center gap-2 mb-1">
<p:tag value="EN COURS" severity="warning" styleClass="text-xs" />
<p:tag value="HAUTE" severity="danger" styleClass="text-xs" />
<p:tag value="TECHNIQUE" severity="info" styleClass="text-xs" />
</div>
<p class="text-600 text-sm mb-0">Créé le 15 janvier 2024 • Dernière réponse il y a 2h</p>
</div>
</div>
<div class="text-right">
<div class="text-600 text-sm mb-2">Agent: Marie Dubois</div>
<p:commandButton value="Voir Détails"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-eye" />
</div>
</div>
<p class="text-700 line-height-3 mb-3">
Impossible d'exporter la liste des membres en format Excel. Le fichier généré est corrompu
et ne s'ouvre pas dans Excel. Cela concerne tous les exports depuis la version 2.1.
</p>
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-2">
<i class="pi pi-comments text-blue-500"></i>
<span class="text-600 text-sm">5 messages</span>
<i class="pi pi-paperclip text-600 ml-3"></i>
<span class="text-600 text-sm">2 fichiers</span>
</div>
<div class="flex align-items-center gap-2">
<i class="pi pi-clock text-600"></i>
<span class="text-600 text-sm">SLA: 4h restantes</span>
</div>
</div>
</div>
<!-- Ticket 2 - En attente -->
<div class="surface-100 hover:surface-200 border-round p-4 mb-3 cursor-pointer transition-duration-200">
<div class="flex align-items-center justify-content-between mb-3">
<div class="flex align-items-center gap-3">
<div class="w-3rem h-3rem border-circle bg-blue-100 flex align-items-center justify-content-center">
<i class="pi pi-pause text-blue-600 text-xl"></i>
</div>
<div>
<h6 class="text-900 font-semibold mb-1">#TK-2024-0143 - Demande de formation personnalisée</h6>
<div class="flex align-items-center gap-2 mb-1">
<p:tag value="EN ATTENTE" severity="info" styleClass="text-xs" />
<p:tag value="NORMALE" severity="success" styleClass="text-xs" />
<p:tag value="FONCTIONNALITÉ" severity="help" styleClass="text-xs" />
</div>
<p class="text-600 text-sm mb-0">Créé le 12 janvier 2024 • En attente de votre réponse</p>
</div>
</div>
<div class="text-right">
<div class="text-600 text-sm mb-2">Agent: Thomas Martin</div>
<p:commandButton value="Répondre"
styleClass="p-button-primary p-button-sm"
icon="pi pi-reply" />
</div>
</div>
<p class="text-700 line-height-3 mb-3">
Souhaitons organiser une formation sur mesure pour notre équipe administrative.
Besoin de devis pour 15 personnes sur 2 jours.
</p>
<div class="surface-blue-50 border-left-3 border-blue-500 p-3 mb-3">
<p class="text-blue-700 text-sm mb-0">
<i class="pi pi-info-circle mr-2"></i>
<strong>Action requise:</strong> Merci de préciser vos disponibilités pour les dates proposées.
</p>
</div>
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-2">
<i class="pi pi-comments text-blue-500"></i>
<span class="text-600 text-sm">3 messages</span>
</div>
<div class="flex align-items-center gap-2">
<i class="pi pi-exclamation-triangle text-orange-500"></i>
<span class="text-orange-600 text-sm">Réponse attendue depuis 3 jours</span>
</div>
</div>
</div>
<!-- Ticket 3 - Résolu -->
<div class="surface-100 hover:surface-200 border-round p-4 mb-3 cursor-pointer transition-duration-200">
<div class="flex align-items-center justify-content-between mb-3">
<div class="flex align-items-center gap-3">
<div class="w-3rem h-3rem border-circle bg-green-100 flex align-items-center justify-content-center">
<i class="pi pi-check text-green-600 text-xl"></i>
</div>
<div>
<h6 class="text-900 font-semibold mb-1">#TK-2024-0128 - Problème de connexion mobile</h6>
<div class="flex align-items-center gap-2 mb-1">
<p:tag value="RÉSOLU" severity="success" styleClass="text-xs" />
<p:tag value="BASSE" severity="secondary" styleClass="text-xs" />
<p:tag value="TECHNIQUE" severity="info" styleClass="text-xs" />
</div>
<p class="text-600 text-sm mb-0">Créé le 8 janvier 2024 • Résolu le 10 janvier 2024</p>
</div>
</div>
<div class="text-right">
<div class="text-600 text-sm mb-2">Agent: Sophie Leroy</div>
<div class="flex gap-2">
<p:commandButton value="Noter"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-star" />
<p:commandButton value="Détails"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-eye" />
</div>
</div>
</div>
<p class="text-700 line-height-3 mb-3">
Application ne se charge pas sur smartphone Android. Écran blanc après connexion.
</p>
<div class="surface-green-50 border-left-3 border-green-500 p-3 mb-3">
<p class="text-green-700 text-sm mb-0">
<i class="pi pi-check-circle mr-2"></i>
<strong>Résolution:</strong> Problème résolu en vidant le cache de l'application mobile.
</p>
</div>
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-2">
<i class="pi pi-comments text-blue-500"></i>
<span class="text-600 text-sm">6 messages</span>
<i class="pi pi-clock text-600 ml-3"></i>
<span class="text-600 text-sm">Résolu en 2 jours</span>
</div>
<div class="flex align-items-center gap-1">
<i class="pi pi-star-fill text-yellow-400"></i>
<span class="text-600 text-sm">Note: 5/5</span>
</div>
</div>
</div>
<!-- Ticket 4 - Fermé -->
<div class="surface-100 hover:surface-200 border-round p-4 cursor-pointer transition-duration-200 opacity-70">
<div class="flex align-items-center justify-content-between mb-3">
<div class="flex align-items-center gap-3">
<div class="w-3rem h-3rem border-circle bg-red-100 flex align-items-center justify-content-center">
<i class="pi pi-times text-red-600 text-xl"></i>
</div>
<div>
<h6 class="text-900 font-semibold mb-1">#TK-2024-0095 - Demande modification base</h6>
<div class="flex align-items-center gap-2 mb-1">
<p:tag value="FERMÉ" severity="danger" styleClass="text-xs" />
<p:tag value="HAUTE" severity="danger" styleClass="text-xs" />
<p:tag value="FONCTIONNALITÉ" severity="help" styleClass="text-xs" />
</div>
<p class="text-600 text-sm mb-0">Créé le 28 décembre 2023 • Fermé le 5 janvier 2024</p>
</div>
</div>
<div class="text-right">
<div class="text-600 text-sm mb-2">Agent: Marc Durand</div>
<p:commandButton value="Rouvrir"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-replay" />
</div>
</div>
<p class="text-700 line-height-3 mb-3">
Demande de modification des champs de la base de données membres pour ajouter
des informations métier spécifiques.
</p>
<div class="surface-red-50 border-left-3 border-red-500 p-3 mb-3">
<p class="text-red-700 text-sm mb-0">
<i class="pi pi-times-circle mr-2"></i>
<strong>Fermé:</strong> Demande non compatible avec l'architecture actuelle.
</p>
</div>
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-2">
<i class="pi pi-comments text-blue-500"></i>
<span class="text-600 text-sm">8 messages</span>
</div>
<div class="flex align-items-center gap-2">
<i class="pi pi-ban text-red-500"></i>
<span class="text-red-600 text-sm">Non résolu</span>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Actions rapides -->
<div class="grid">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-bolt mr-2"></i>
Actions Rapides
</h4>
<div class="grid">
<div class="col-12 lg:col-3">
<div class="surface-100 hover:surface-200 border-round p-4 text-center cursor-pointer transition-duration-200">
<i class="pi pi-plus-circle text-3xl text-primary mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Nouveau Ticket</h6>
<p class="text-600 text-sm mb-0">Créer une demande d'assistance</p>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 hover:surface-200 border-round p-4 text-center cursor-pointer transition-duration-200">
<i class="pi pi-question-circle text-3xl text-blue-500 mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Consulter la FAQ</h6>
<p class="text-600 text-sm mb-0">Réponses aux questions courantes</p>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 hover:surface-200 border-round p-4 text-center cursor-pointer transition-duration-200">
<i class="pi pi-book text-3xl text-green-500 mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Guide Utilisateur</h6>
<p class="text-600 text-sm mb-0">Documentation complète</p>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 hover:surface-200 border-round p-4 text-center cursor-pointer transition-duration-200">
<i class="pi pi-phone text-3xl text-orange-500 mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Contact Direct</h6>
<p class="text-600 text-sm mb-0">Appelez le support</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Dialog Nouveau Ticket -->
<p:dialog id="nouveauTicketDialog"
widgetVar="nouveauTicketDialog"
header="Créer un Nouveau Ticket"
modal="true"
width="800"
styleClass="surface-0">
<h:form id="nouveauTicketForm">
<div class="ui-fluid">
<div class="formgrid grid">
<div class="field col-12 lg:col-6">
<label for="categorieTicket" class="block text-900 font-semibold mb-2">Catégorie *</label>
<p:selectOneMenu id="categorieTicket" styleClass="w-full">
<f:selectItem itemLabel="Sélectionnez une catégorie" itemValue="" />
<f:selectItem itemLabel="Problème Technique" itemValue="technique" />
<f:selectItem itemLabel="Demande de Fonctionnalité" itemValue="fonctionnalite" />
<f:selectItem itemLabel="Question d'Utilisation" itemValue="utilisation" />
<f:selectItem itemLabel="Problème de Compte" itemValue="compte" />
<f:selectItem itemLabel="Autre" itemValue="autre" />
</p:selectOneMenu>
</div>
<div class="field col-12 lg:col-6">
<label for="prioriteTicket" class="block text-900 font-semibold mb-2">Priorité</label>
<p:selectOneMenu id="prioriteTicket" styleClass="w-full">
<f:selectItem itemLabel="Basse" itemValue="basse" />
<f:selectItem itemLabel="Normale" itemValue="normale" />
<f:selectItem itemLabel="Haute" itemValue="haute" />
<f:selectItem itemLabel="Urgente" itemValue="urgente" />
</p:selectOneMenu>
</div>
<div class="field col-12">
<label for="sujetTicket" class="block text-900 font-semibold mb-2">Sujet *</label>
<p:inputText id="sujetTicket"
placeholder="Résumé du problème ou de la demande"
styleClass="w-full" />
</div>
<div class="field col-12">
<label for="descriptionTicket" class="block text-900 font-semibold mb-2">Description détaillée *</label>
<p:inputTextarea id="descriptionTicket"
rows="6"
placeholder="Décrivez votre problème en détail, incluez les étapes pour reproduire..."
styleClass="w-full" />
</div>
<div class="field col-12">
<label class="block text-900 font-semibold mb-2">Pièces jointes</label>
<p:fileUpload mode="basic"
multiple="true"
chooseLabel="Choisir des fichiers"
styleClass="w-full" />
<small class="text-500">Formats acceptés: jpg, png, pdf, doc, xlsx (max 10MB par fichier)</small>
</div>
</div>
<div class="flex justify-content-end gap-2 mt-4">
<p:commandButton value="Annuler"
styleClass="p-button-outlined"
onclick="PF('nouveauTicketDialog').hide()"
type="button" />
<p:commandButton value="Créer le Ticket"
styleClass="p-button-primary"
icon="pi pi-send" />
</div>
</div>
</h:form>
</p:dialog>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,161 @@
<!DOCTYPE html>
<ui:composition template="/templates/main-template.xhtml"
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">
<ui:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Traitement des Demandes d'Aide - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formTraitement">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div>
<h3 class="m-0">
<i class="pi pi-inbox text-primary mr-2"></i>
Traitement des Demandes d'Aide
</h3>
<p class="text-600 m-0 mt-2">
Gérez et traitez les demandes d'aide des membres
</p>
</div>
<div class="flex gap-2 mt-2 md:mt-0">
<p:commandButton value="Actualiser"
icon="pi pi-refresh"
styleClass="ui-button-outlined ui-button-secondary"
action="#{demandesAideBean.actualiser}"
update="@form"/>
</div>
</div>
</div>
<!-- Statistiques -->
<div class="grid mb-3">
<div class="col-12 md:col-3">
<div class="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">#{demandesAideBean.statistiques.totalDemandes}</div>
<div class="text-blue-700">Total Demandes</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-inbox text-xl"></i>
</div>
</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="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">#{demandesAideBean.statistiques.demandesEnAttente}</div>
<div class="text-orange-700">En Attente</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-clock text-xl"></i>
</div>
</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="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">#{demandesAideBean.statistiques.demandesApprouvees}</div>
<div class="text-green-700">Approuvées</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-check text-xl"></i>
</div>
</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="card bg-red-100 border-left-3 border-red-500">
<div class="flex justify-content-between">
<div>
<div class="text-red-900 font-bold text-2xl">#{demandesAideBean.statistiques.demandesRejetees}</div>
<div class="text-red-700">Rejetées</div>
</div>
<div class="bg-red-500 text-white border-round text-center"
style="width: 3rem; height: 3rem; line-height: 3rem;">
<i class="pi pi-times text-xl"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Liste des demandes -->
<div class="card">
<h5 class="mb-3">Demandes à Traiter</h5>
<p:dataTable id="dtDemandes"
var="demande"
value="#{demandesAideBean.demandesFiltrees}"
paginator="true"
rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,25"
currentPageReportTemplate="Affichage {startRecord}-{endRecord} sur {totalRecords}"
styleClass="mt-3">
<p:column headerText="Demandeur" sortBy="#{demande.demandeur}">
<div>
<div class="font-medium">#{demande.demandeur}</div>
<small class="text-600">#{demande.telephone}</small>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{demande.type}">
<p:tag value="#{demande.typeLibelle}" severity="#{demande.typeSeverity}" icon="pi #{demande.typeIcon}"/>
</p:column>
<p:column headerText="Montant" sortBy="#{demande.montantDemande}">
<div class="font-bold text-green-500">#{demande.montantDemande} FCFA</div>
</p:column>
<p:column headerText="Statut" sortBy="#{demande.statut}">
<p:tag value="#{demande.statut}"
severity="#{demande.statutSeverity}"
icon="pi #{demande.statutIcon}"/>
</p:column>
<p:column headerText="Date" sortBy="#{demande.dateDemande}">
<h:outputText value="#{demande.dateDemande}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:outputText>
</p:column>
<p:column headerText="Actions" style="width:200px">
<div class="flex gap-1">
<p:commandButton icon="pi pi-eye"
styleClass="ui-button-rounded ui-button-text ui-button-info"
action="#{demandesAideBean.voirDetails(demande)}"
title="Voir détails"/>
<p:commandButton icon="pi pi-check"
styleClass="ui-button-rounded ui-button-text ui-button-success"
action="#{demandesAideBean.approuver(demande)}"
title="Approuver"
rendered="#{demande.statut == 'EN_ATTENTE'}"/>
<p:commandButton icon="pi pi-times"
styleClass="ui-button-rounded ui-button-text ui-button-danger"
action="#{demandesAideBean.rejeter(demande)}"
title="Rejeter"
rendered="#{demande.statut == 'EN_ATTENTE'}"/>
</div>
</p:column>
</p:dataTable>
</div>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,368 @@
<!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:param name="page" value="#{demandesAideBean}"/>
<ui:define name="title">Tutoriels Vidéo - UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<div class="flex align-items-center justify-content-between mb-4">
<div>
<h2 class="text-900 font-bold text-4xl mb-2">
<i class="pi pi-video text-orange-500 mr-3"></i>
Tutoriels Vidéo
</h2>
<p class="text-600 text-lg mb-0">
Apprenez UnionFlow grâce à nos tutoriels vidéo étape par étape
</p>
</div>
<div class="flex gap-2">
<p:commandButton value="Playlist Complète"
styleClass="p-button-outlined"
icon="pi pi-play-circle" />
<p:commandButton value="Télécharger"
styleClass="p-button-primary p-button-outlined"
icon="pi pi-download" />
</div>
</div>
<!-- Statistiques -->
<div class="grid">
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-blue-500 mb-2">24</div>
<div class="text-900 font-semibold mb-1">Tutoriels</div>
<div class="text-600 text-sm">Disponibles</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-green-500 mb-2">4h 32m</div>
<div class="text-900 font-semibold mb-1">Durée Totale</div>
<div class="text-600 text-sm">Contenu vidéo</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-purple-500 mb-2">1,847</div>
<div class="text-900 font-semibold mb-1">Vues</div>
<div class="text-600 text-sm">Ce mois-ci</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-orange-500 mb-2">4.8★</div>
<div class="text-900 font-semibold mb-1">Note Moyenne</div>
<div class="text-600 text-sm">Sur 156 avis</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Filtrres et recherche -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h:form id="filtresForm">
<div class="formgrid grid">
<div class="field col-12 md:col-4">
<label for="categorieFilter" class="block text-900 font-semibold mb-2">Catégorie</label>
<p:selectOneMenu id="categorieFilter" styleClass="w-full">
<f:selectItem itemLabel="Toutes les catégories" itemValue="" />
<f:selectItem itemLabel="Premiers Pas" itemValue="debutant" />
<f:selectItem itemLabel="Gestion des Membres" itemValue="membres" />
<f:selectItem itemLabel="Finances" itemValue="finances" />
<f:selectItem itemLabel="Événements" itemValue="evenements" />
<f:selectItem itemLabel="Administration" itemValue="admin" />
<f:selectItem itemLabel="Rapports" itemValue="rapports" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-4">
<label for="dureeFilter" class="block text-900 font-semibold mb-2">Durée</label>
<p:selectOneMenu id="dureeFilter" styleClass="w-full">
<f:selectItem itemLabel="Toutes les durées" itemValue="" />
<f:selectItem itemLabel="Moins de 5 min" itemValue="court" />
<f:selectItem itemLabel="5-15 min" itemValue="moyen" />
<f:selectItem itemLabel="Plus de 15 min" itemValue="long" />
</p:selectOneMenu>
</div>
<div class="field col-12 md:col-4">
<label for="rechercheVideo" class="block text-900 font-semibold mb-2">Rechercher</label>
<p:inputText id="rechercheVideo"
placeholder="Titre, mots-clés..."
styleClass="w-full" />
</div>
</div>
</h:form>
</div>
</div>
</div>
<!-- Liste des tutoriels par catégorie -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-play mr-2"></i>
Premiers Pas avec UnionFlow
</h4>
<div class="grid">
<!-- Tutoriel 1 -->
<div class="col-12 lg:col-6 xl:col-4">
<div class="surface-100 hover:surface-200 border-round transition-duration-200 cursor-pointer">
<div class="relative">
<div class="w-full h-12rem bg-primary-50 border-round-top flex align-items-center justify-content-center">
<i class="pi pi-play-circle text-6xl text-primary-500"></i>
</div>
<div class="absolute top-0 right-0 m-2">
<p:tag value="3:45" severity="info" styleClass="text-xs" />
</div>
<div class="absolute bottom-0 left-0 right-0 h-1rem bg-blue-500" style="width: 25%; opacity: 0.8;"></div>
</div>
<div class="p-3">
<h6 class="text-900 font-semibold mb-2">Première Connexion</h6>
<p class="text-600 text-sm mb-3">Découvrez comment vous connecter pour la première fois à UnionFlow</p>
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-2">
<i class="pi pi-eye text-600 text-sm"></i>
<span class="text-600 text-sm">2,341 vues</span>
</div>
<div class="flex align-items-center gap-1">
<i class="pi pi-star-fill text-yellow-400"></i>
<span class="text-600 text-sm">4.9</span>
</div>
</div>
</div>
</div>
</div>
<!-- Tutoriel 2 -->
<div class="col-12 lg:col-6 xl:col-4">
<div class="surface-100 hover:surface-200 border-round transition-duration-200 cursor-pointer">
<div class="relative">
<div class="w-full h-12rem bg-green-50 border-round-top flex align-items-center justify-content-center">
<i class="pi pi-play-circle text-6xl text-green-500"></i>
</div>
<div class="absolute top-0 right-0 m-2">
<p:tag value="7:22" severity="success" styleClass="text-xs" />
</div>
<div class="absolute bottom-0 left-0 right-0 h-1rem bg-blue-500" style="width: 100%; opacity: 0.8;"></div>
</div>
<div class="p-3">
<h6 class="text-900 font-semibold mb-2">Navigation dans l'Interface</h6>
<p class="text-600 text-sm mb-3">Tour complet de l'interface utilisateur et des menus principaux</p>
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-2">
<i class="pi pi-eye text-600 text-sm"></i>
<span class="text-600 text-sm">1,876 vues</span>
</div>
<div class="flex align-items-center gap-1">
<i class="pi pi-star-fill text-yellow-400"></i>
<span class="text-600 text-sm">4.7</span>
</div>
</div>
</div>
</div>
</div>
<!-- Tutoriel 3 -->
<div class="col-12 lg:col-6 xl:col-4">
<div class="surface-100 hover:surface-200 border-round transition-duration-200 cursor-pointer">
<div class="relative">
<div class="w-full h-12rem bg-orange-50 border-round-top flex align-items-center justify-content-center">
<i class="pi pi-play-circle text-6xl text-orange-500"></i>
</div>
<div class="absolute top-0 right-0 m-2">
<p:tag value="5:18" severity="warning" styleClass="text-xs" />
</div>
<div class="absolute bottom-0 left-0 right-0 h-1rem bg-blue-500" style="width: 60%; opacity: 0.8;"></div>
</div>
<div class="p-3">
<h6 class="text-900 font-semibold mb-2">Personnaliser son Profil</h6>
<p class="text-600 text-sm mb-3">Comment configurer vos informations personnelles et préférences</p>
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-2">
<i class="pi pi-eye text-600 text-sm"></i>
<span class="text-600 text-sm">1,432 vues</span>
</div>
<div class="flex align-items-center gap-1">
<i class="pi pi-star-fill text-yellow-400"></i>
<span class="text-600 text-sm">4.8</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Gestion des Membres -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-users mr-2"></i>
Gestion des Membres
</h4>
<div class="grid">
<!-- Tutoriel Membre 1 -->
<div class="col-12 lg:col-6 xl:col-4">
<div class="surface-100 hover:surface-200 border-round transition-duration-200 cursor-pointer">
<div class="relative">
<div class="w-full h-12rem bg-blue-50 border-round-top flex align-items-center justify-content-center">
<i class="pi pi-play-circle text-6xl text-blue-500"></i>
</div>
<div class="absolute top-0 right-0 m-2">
<p:tag value="12:45" severity="info" styleClass="text-xs" />
</div>
<div class="absolute top-0 left-0 m-2">
<p:tag value="NOUVEAU" severity="danger" styleClass="text-xs" />
</div>
</div>
<div class="p-3">
<h6 class="text-900 font-semibold mb-2">Inscrire un Nouveau Membre</h6>
<p class="text-600 text-sm mb-3">Processus complet d'inscription d'un membre avec toutes les étapes</p>
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-2">
<i class="pi pi-eye text-600 text-sm"></i>
<span class="text-600 text-sm">987 vues</span>
</div>
<div class="flex align-items-center gap-1">
<i class="pi pi-star-fill text-yellow-400"></i>
<span class="text-600 text-sm">5.0</span>
</div>
</div>
</div>
</div>
</div>
<!-- Tutoriel Membre 2 -->
<div class="col-12 lg:col-6 xl:col-4">
<div class="surface-100 hover:surface-200 border-round transition-duration-200 cursor-pointer">
<div class="relative">
<div class="w-full h-12rem bg-purple-50 border-round-top flex align-items-center justify-content-center">
<i class="pi pi-play-circle text-6xl text-purple-500"></i>
</div>
<div class="absolute top-0 right-0 m-2">
<p:tag value="8:33" severity="help" styleClass="text-xs" />
</div>
</div>
<div class="p-3">
<h6 class="text-900 font-semibold mb-2">Recherche Avancée</h6>
<p class="text-600 text-sm mb-3">Utiliser les filtres et critères de recherche pour trouver des membres</p>
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-2">
<i class="pi pi-eye text-600 text-sm"></i>
<span class="text-600 text-sm">1,234 vues</span>
</div>
<div class="flex align-items-center gap-1">
<i class="pi pi-star-fill text-yellow-400"></i>
<span class="text-600 text-sm">4.6</span>
</div>
</div>
</div>
</div>
</div>
<!-- Tutoriel Membre 3 -->
<div class="col-12 lg:col-6 xl:col-4">
<div class="surface-100 hover:surface-200 border-round transition-duration-200 cursor-pointer">
<div class="relative">
<div class="w-full h-12rem bg-teal-50 border-round-top flex align-items-center justify-content-center">
<i class="pi pi-play-circle text-6xl text-teal-500"></i>
</div>
<div class="absolute top-0 right-0 m-2">
<p:tag value="15:27" severity="success" styleClass="text-xs" />
</div>
</div>
<div class="p-3">
<h6 class="text-900 font-semibold mb-2">Export et Rapports Membres</h6>
<p class="text-600 text-sm mb-3">Générer des exports Excel et des rapports personnalisés</p>
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-2">
<i class="pi pi-eye text-600 text-sm"></i>
<span class="text-600 text-sm">765 vues</span>
</div>
<div class="flex align-items-center gap-1">
<i class="pi pi-star-fill text-yellow-400"></i>
<span class="text-600 text-sm">4.9</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Playlist recommandées -->
<div class="grid">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-bookmark mr-2"></i>
Playlists Recommandées
</h4>
<div class="grid">
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4">
<div class="flex align-items-center mb-3">
<i class="pi pi-play-circle text-2xl text-primary mr-3"></i>
<div>
<h6 class="text-900 font-semibold mb-1">Formation Complète Débutant</h6>
<p class="text-600 text-sm mb-0">8 vidéos • 45 min</p>
</div>
</div>
<p class="text-600 text-sm mb-3">
Parcours complet pour débuter avec UnionFlow, de la connexion à la première utilisation
</p>
<p:commandButton value="Commencer"
styleClass="p-button-primary p-button-sm w-full"
icon="pi pi-play" />
</div>
</div>
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4">
<div class="flex align-items-center mb-3">
<i class="pi pi-cog text-2xl text-orange-500 mr-3"></i>
<div>
<h6 class="text-900 font-semibold mb-1">Administration Avancée</h6>
<p class="text-600 text-sm mb-0">12 vidéos • 2h 15min</p>
</div>
</div>
<p class="text-600 text-sm mb-3">
Maîtrisez l'administration d'UnionFlow : utilisateurs, rôles, permissions et configuration
</p>
<p:commandButton value="Commencer"
styleClass="p-button-outlined p-button-sm w-full"
icon="pi pi-play" />
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,456 @@
<!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:param name="page" value="#{cotisationsBean}"/>
<ui:define name="title">Gestion des Cotisations - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-money-bill text-green-500" />
<ui:param name="title" value="Gestion des Cotisations" />
<ui:param name="description" value="Suivi et gestion des cotisations des membres" />
<ui:define name="actions">
<h:form id="formActionsCotisations">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouvelle cotisation" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="onclick" value="PF('dlgNouvelleCotisation').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="action" value="#{cotisationsBean.exporterCotisations}" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{cotisationsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.totalCollecteFormatte}" />
<ui:param name="label" value="Total Collecté" />
<ui:param name="icon" value="pi pi-wallet" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.tauxRecouvrementInt}%" />
<ui:param name="label" value="Taux de Recouvrement" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.cotisationsEnRetard}" />
<ui:param name="label" value="En Retard" />
<ui:param name="icon" value="pi pi-exclamation-triangle" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.montantRetardFormatte}" />
<ui:param name="label" value="Montant Retard" />
<ui:param name="icon" value="pi pi-clock" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Liste des cotisations -->
<div class="card">
<h:form id="formCotisations">
<h5>Liste des Cotisations</h5>
<!-- Filtres et recherche (DRY/WOU: filter-bar) -->
<ui:decorate template="/templates/components/cards/filter-bar.xhtml">
<ui:param name="title" value="Filtres" />
<ui:param name="styleClass" value="mb-3" />
<ui:define name="filters">
<div class="col-12 md:col-4">
<div class="field">
<p:outputLabel for="searchMembre" value="Rechercher" />
<span class="p-input-icon-left w-full">
<i class="pi pi-search"></i>
<p:inputText id="searchMembre"
placeholder="Rechercher par membre..."
value="#{cotisationsBean.filtres.nomMembre}"
styleClass="w-full">
<p:ajax event="keyup" update="dtCotisations" delay="500"/>
</p:inputText>
</span>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreStatut" value="Statut" />
<p:selectOneMenu id="filtreStatut"
value="#{cotisationsBean.filtres.statut}"
styleClass="w-full">
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE" />
<f:selectItem itemLabel="Payée" itemValue="PAYEE" />
<f:selectItem itemLabel="Partiellement payée" itemValue="PARTIELLEMENT_PAYEE" />
<f:selectItem itemLabel="En retard" itemValue="EN_RETARD" />
<f:selectItem itemLabel="Annulée" itemValue="ANNULEE" />
<p:ajax event="change" update="dtCotisations" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreType" value="Type" />
<p:selectOneMenu id="filtreType"
value="#{cotisationsBean.filtres.typeCotisation}"
styleClass="w-full">
<f:selectItem itemLabel="Tous les types" itemValue="" />
<f:selectItem itemLabel="Mensuelle" itemValue="MENSUELLE" />
<f:selectItem itemLabel="Trimestrielle" itemValue="TRIMESTRIELLE" />
<f:selectItem itemLabel="Semestrielle" itemValue="SEMESTRIELLE" />
<f:selectItem itemLabel="Annuelle" itemValue="ANNUELLE" />
<f:selectItem itemLabel="Adhésion" itemValue="ADHESION" />
<f:selectItem itemLabel="Exceptionnelle" itemValue="EXCEPTIONNELLE" />
<p:ajax event="change" update="dtCotisations" />
</p:selectOneMenu>
</div>
</div>
</ui:define>
<ui:define name="actions">
<div class="col-12 md:col-2">
<div class="field">
<label class="invisible">Actions</label>
<p:commandButton value="Filtres avancés"
icon="pi pi-filter"
onclick="PF('dlgFiltresAvances').show();"
styleClass="ui-button-secondary w-full" />
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<label class="invisible">Réinitialiser</label>
<p:commandButton value="Réinitialiser"
icon="pi pi-filter-slash"
action="#{cotisationsBean.reinitialiserFiltres}"
update="dtCotisations searchMembre filtreStatut filtreType"
styleClass="ui-button-secondary w-full" />
</div>
</div>
</ui:define>
</ui:decorate>
<!-- Tableau des cotisations -->
<p:dataTable id="dtCotisations"
value="#{cotisationsBean.cotisationsFiltrees}"
var="cotisation"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50,100"
paginatorTemplate="{RowsPerPageDropdown} {FirstPageLink} {PreviousPageLink} {CurrentPageReport} {NextPageLink} {LastPageLink}"
currentPageReportTemplate="{startRecord} - {endRecord} sur {totalRecords}"
emptyMessage="Aucune cotisation trouvée"
selection="#{cotisationsBean.cotisationsSelectionnees}"
selectionMode="multiple">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Cotisations (#{cotisationsBean.cotisationsFiltrees.size()})</span>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Rappels groupés" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{cotisationsBean.envoyerRappelsGroupes}" />
<ui:param name="update" value="@form" />
<ui:param name="disabled" value="#{empty cotisationsBean.cotisationsSelectionnees}" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</div>
</f:facet>
<p:column selectionMode="multiple" style="width:50px" />
<p:column headerText="Référence" sortBy="#{cotisation.numeroReference}" style="width:150px">
<h:outputText value="#{cotisation.numeroReference}" />
</p:column>
<p:column headerText="Membre" sortBy="#{cotisation.nomMembre}">
<div class="flex align-items-center gap-2">
<div>
<div class="font-medium">#{cotisation.nomMembre}</div>
<div class="text-600 text-sm">#{cotisation.numeroMembre}</div>
</div>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{cotisation.typeCotisation}" style="width:120px">
<p:tag value="#{cotisation.typeCotisationLibelle}"
severity="info"
icon="#{cotisation.typeCotisation == 'ADHESION' ? 'pi-user-plus' : 'pi-calendar'}" />
</p:column>
<p:column headerText="Montant Dû" sortBy="#{cotisation.montantDu}" style="width:120px">
<h:outputText value="#{cotisation.montantDuFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Montant Payé" sortBy="#{cotisation.montantPaye}" style="width:120px">
<h:outputText value="#{cotisation.montantPayeFormatte}" />
</p:column>
<p:column headerText="Statut" sortBy="#{cotisation.statut}" style="width:150px">
<p:tag value="#{cotisation.statutLibelle}"
severity="#{cotisation.statutSeverity}"
icon="#{cotisation.statutIcon}" />
</p:column>
<p:column headerText="Échéance" sortBy="#{cotisation.dateEcheance}" style="width:120px">
<h:outputText value="#{cotisation.dateEcheanceFormatee}" />
</p:column>
<p:column headerText="Actions" style="width:200px">
<div class="flex gap-1">
<p:commandButton icon="pi pi-check"
title="Marquer comme payée"
styleClass="p-button-rounded p-button-text p-button-success"
disabled="#{cotisation.statut == 'PAYEE'}"
action="#{cotisationsBean.marquerCommePaye(cotisation)}"
update="@form" />
<p:commandButton icon="pi pi-send"
title="Envoyer un rappel"
styleClass="p-button-rounded p-button-text p-button-warning"
action="#{cotisationsBean.envoyerRappel(cotisation)}"
update="@form" />
<p:commandButton icon="pi pi-eye"
title="Voir les détails"
styleClass="p-button-rounded p-button-text p-button-info"
action="#{cotisationsBean.selectionnerCotisation(cotisation)}"
update=":formDetailsCotisation"
oncomplete="PF('dlgDetailsCotisation').show();" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Nouvelle Cotisation -->
<p:dialog header="Nouvelle Cotisation" widgetVar="dlgNouvelleCotisation" modal="true" width="600" resizable="false">
<h:form id="formNouvelleCotisation">
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:define name="title">Informations de la cotisation</ui:define>
<ui:define name="content">
<div class="grid">
<div class="col-12">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="libelle" />
<ui:param name="label" value="Libellé" />
<ui:param name="value" value="#{cotisationsBean.nouvelleCotisation.libelle}" />
<ui:param name="required" value="true" />
<ui:param name="placeholder" value="Ex: Cotisation mensuelle janvier 2024" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="typeCotisation" />
<ui:param name="label" value="Type de cotisation" />
<ui:param name="value" value="#{cotisationsBean.nouvelleCotisation.typeCotisation}" />
<ui:param name="required" value="true" />
<ui:define name="items">
<f:selectItem itemLabel="Mensuelle" itemValue="MENSUELLE" />
<f:selectItem itemLabel="Trimestrielle" itemValue="TRIMESTRIELLE" />
<f:selectItem itemLabel="Semestrielle" itemValue="SEMESTRIELLE" />
<f:selectItem itemLabel="Annuelle" itemValue="ANNUELLE" />
<f:selectItem itemLabel="Adhésion" itemValue="ADHESION" />
<f:selectItem itemLabel="Exceptionnelle" itemValue="EXCEPTIONNELLE" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateEcheance" />
<ui:param name="label" value="Date d'échéance" />
<ui:param name="value" value="#{cotisationsBean.nouvelleCotisation.dateEcheance}" />
<ui:param name="required" value="true" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="montantDu" value="Montant dû (FCFA)" />
<p:inputNumber id="montantDu"
value="#{cotisationsBean.nouvelleCotisation.montantDu}"
symbol=""
minValue="0"
styleClass="w-full" />
</div>
</div>
<div class="col-12">
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="observations" />
<ui:param name="label" value="Observations" />
<ui:param name="value" value="#{cotisationsBean.nouvelleCotisation.observations}" />
<ui:param name="rows" value="3" />
</ui:include>
</div>
</div>
</ui:define>
</ui:include>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgNouvelleCotisation').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Enregistrer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{cotisationsBean.enregistrerCotisation}" />
<ui:param name="update" value="@form :formCotisations" />
<ui:param name="oncomplete" value="PF('dlgNouvelleCotisation').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Filtres Avancés -->
<p:dialog header="Filtres Avancés" widgetVar="dlgFiltresAvances" modal="true" width="500" resizable="false">
<h:form id="formFiltresAvances">
<div class="ui-fluid">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="club" />
<ui:param name="label" value="Club/Association" />
<ui:param name="value" value="#{cotisationsBean.filtres.club}" />
<ui:param name="placeholder" value="Rechercher par club..." />
</ui:include>
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="methodePaiement" />
<ui:param name="label" value="Méthode de paiement" />
<ui:param name="value" value="#{cotisationsBean.filtres.methodePaiement}" />
<ui:define name="items">
<f:selectItem itemLabel="Toutes" itemValue="" />
<f:selectItem itemLabel="Wave Money" itemValue="WAVE_MONEY" />
<f:selectItem itemLabel="Espèces" itemValue="ESPECES" />
<f:selectItem itemLabel="Virement" itemValue="VIREMENT" />
<f:selectItem itemLabel="Chèque" itemValue="CHEQUE" />
</ui:define>
</ui:include>
<div class="grid">
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateDebut" />
<ui:param name="label" value="Date début" />
<ui:param name="value" value="#{cotisationsBean.filtres.dateDebut}" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateFin" />
<ui:param name="label" value="Date fin" />
<ui:param name="value" value="#{cotisationsBean.filtres.dateFin}" />
</ui:include>
</div>
</div>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgFiltresAvances').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Appliquer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{cotisationsBean.rechercher}" />
<ui:param name="update" value=":formCotisations" />
<ui:param name="oncomplete" value="PF('dlgFiltresAvances').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Détails Cotisation -->
<p:dialog header="Détails de la Cotisation" widgetVar="dlgDetailsCotisation" modal="true" width="600" resizable="false">
<h:form id="formDetailsCotisation">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Référence</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.numeroReference}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Statut</label>
<p:tag value="#{cotisationsBean.cotisationSelectionnee.statutLibelle}"
severity="#{cotisationsBean.cotisationSelectionnee.statutSeverity}" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Membre</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">#{cotisationsBean.cotisationSelectionnee.numeroMembre}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Type</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.typeCotisationLibelle}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Montant dû</label>
<p class="text-600 font-bold">#{cotisationsBean.cotisationSelectionnee.montantDuFormatte}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Montant payé</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.montantPayeFormatte}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date d'échéance</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.dateEcheanceFormatee}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date de paiement</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.datePaiementFormatee}</p>
</div>
</div>
</div>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,253 @@
<!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:param name="page" value="#{cotisationsBean}"/>
<ui:define name="title">Historique des Cotisations - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-history text-blue-500" />
<ui:param name="title" value="Historique des Cotisations" />
<ui:param name="description" value="Consultation de l'historique complet des cotisations et paiements" />
<ui:define name="actions">
<h:form id="formActionsHistorique">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="action" value="#{cotisationsBean.exporterCotisations}" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{cotisationsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Filtres d'historique -->
<div class="card">
<h:form id="formFiltresHistorique">
<h5>Filtres de Recherche</h5>
<div class="grid">
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateDebut" />
<ui:param name="label" value="Date début" />
<ui:param name="value" value="#{cotisationsBean.filtres.dateDebut}" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateFin" />
<ui:param name="label" value="Date fin" />
<ui:param name="value" value="#{cotisationsBean.filtres.dateFin}" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="statutHistorique" />
<ui:param name="label" value="Statut" />
<ui:param name="value" value="#{cotisationsBean.filtres.statut}" />
<ui:define name="items">
<f:selectItem itemLabel="Tous" itemValue="" />
<f:selectItem itemLabel="Payée" itemValue="PAYEE" />
<f:selectItem itemLabel="Partiellement payée" itemValue="PARTIELLEMENT_PAYEE" />
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE" />
<f:selectItem itemLabel="En retard" itemValue="EN_RETARD" />
<f:selectItem itemLabel="Annulée" itemValue="ANNULEE" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel />
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Rechercher" />
<ui:param name="icon" value="pi pi-search" />
<ui:param name="action" value="#{cotisationsBean.rechercher}" />
<ui:param name="update" value=":formHistorique" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Réinitialiser" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="action" value="#{cotisationsBean.reinitialiserFiltres}" />
<ui:param name="update" value="@form :formHistorique" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</div>
</div>
</div>
</h:form>
</div>
<!-- Tableau d'historique -->
<div class="card">
<h:form id="formHistorique">
<h5>Historique des Cotisations</h5>
<p:dataTable id="dtHistorique"
value="#{cotisationsBean.cotisationsFiltrees}"
var="cotisation"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50,100"
sortMode="multiple"
emptyMessage="Aucune cotisation trouvée">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Historique (#{cotisationsBean.cotisationsFiltrees.size()} cotisation(s))</span>
</div>
</f:facet>
<p:column headerText="Date" sortBy="#{cotisation.dateCreation}" style="width:120px">
<h:outputText value="#{cotisation.dateCreation}" rendered="#{cotisation.dateCreation != null}">
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:outputText>
</p:column>
<p:column headerText="Référence" sortBy="#{cotisation.numeroReference}" style="width:150px">
<h:outputText value="#{cotisation.numeroReference}" />
</p:column>
<p:column headerText="Membre" sortBy="#{cotisation.nomMembre}">
<div>
<div class="font-medium">#{cotisation.nomMembre}</div>
<div class="text-600 text-sm">#{cotisation.numeroMembre}</div>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{cotisation.typeCotisation}" style="width:120px">
<p:tag value="#{cotisation.typeCotisationLibelle}" severity="info" />
</p:column>
<p:column headerText="Montant Dû" sortBy="#{cotisation.montantDu}" style="width:120px">
<h:outputText value="#{cotisation.montantDuFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Montant Payé" sortBy="#{cotisation.montantPaye}" style="width:120px">
<h:outputText value="#{cotisation.montantPayeFormatte}" />
</p:column>
<p:column headerText="Statut" sortBy="#{cotisation.statut}" style="width:150px">
<p:tag value="#{cotisation.statutLibelle}"
severity="#{cotisation.statutSeverity}"
icon="#{cotisation.statutIcon}" />
</p:column>
<p:column headerText="Date Paiement" sortBy="#{cotisation.datePaiement}" style="width:150px">
<h:outputText value="#{cotisation.datePaiementFormatee}" />
</p:column>
<p:column headerText="Méthode" style="width:120px">
<h:outputText value="#{cotisation.methodePaiementLibelle}" rendered="#{cotisation.methodePaiement != null}" />
</p:column>
<p:column headerText="Actions" style="width:100px">
<p:commandButton icon="pi pi-eye"
title="Voir les détails"
styleClass="p-button-rounded p-button-text p-button-info"
action="#{cotisationsBean.selectionnerCotisation(cotisation)}"
update=":formDetailsCotisation"
oncomplete="PF('dlgDetailsCotisation').show();" />
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Détails Cotisation -->
<p:dialog header="Détails de la Cotisation" widgetVar="dlgDetailsCotisation" modal="true" width="600" resizable="false">
<h:form id="formDetailsCotisation">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Référence</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.numeroReference}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Statut</label>
<p:tag value="#{cotisationsBean.cotisationSelectionnee.statutLibelle}"
severity="#{cotisationsBean.cotisationSelectionnee.statutSeverity}" />
</div>
</div>
<div class="col-12">
<div class="field">
<label class="font-medium">Membre</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">N° #{cotisationsBean.cotisationSelectionnee.numeroMembre}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Type</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.typeCotisationLibelle}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date d'échéance</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.dateEcheanceFormatee}</p>
</div>
</div>
<div class="col-12 md:col-4">
<div class="field">
<label class="font-medium">Montant dû</label>
<p class="text-600 font-bold">#{cotisationsBean.cotisationSelectionnee.montantDuFormatte}</p>
</div>
</div>
<div class="col-12 md:col-4">
<div class="field">
<label class="font-medium">Montant payé</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.montantPayeFormatte}</p>
</div>
</div>
<div class="col-12 md:col-4">
<div class="field">
<label class="font-medium">Montant restant</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.montantRestantFormatte}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Date de paiement</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.datePaiementFormatee}</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-medium">Méthode de paiement</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.methodePaiementLibelle}</p>
</div>
</div>
<div class="col-12" rendered="#{cotisationsBean.cotisationSelectionnee.observations != null}">
<div class="field">
<label class="font-medium">Observations</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.observations}</p>
</div>
</div>
</div>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,307 @@
<!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:param name="page" value="#{cotisationsBean}"/>
<ui:define name="title">Paiement de Cotisations - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-credit-card text-green-500" />
<ui:param name="title" value="Paiement de Cotisations" />
<ui:param name="description" value="Enregistrement et suivi des paiements de cotisations" />
<ui:define name="actions">
<h:form id="formActionsPaiement">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{cotisationsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques de paiement -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.totalCollecteFormatte}" />
<ui:param name="label" value="Total Collecté" />
<ui:param name="icon" value="pi pi-wallet" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.moyenneMensuelleFormattee}" />
<ui:param name="label" value="Moyenne Mensuelle" />
<ui:param name="icon" value="pi pi-chart-line" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.objectifAnnuelFormatte}" />
<ui:param name="label" value="Objectif Annuel" />
<ui:param name="icon" value="pi pi-target" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.tauxRecouvrementInt}%" />
<ui:param name="label" value="Taux de Recouvrement" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Répartition par méthode de paiement -->
<div class="card">
<h5>
<i class="pi pi-chart-pie mr-2"></i>
Répartition par Méthode de Paiement
</h5>
<div class="grid">
<div class="col-12 md:col-6">
<div class="flex flex-column gap-3">
<ui:repeat value="#{cotisationsBean.repartitionMethodes}" var="methode">
<div class="flex align-items-center justify-content-between p-3 border-round surface-50">
<div class="flex align-items-center gap-2">
<div class="border-round text-white text-center"
style="width: 2.5rem; height: 2.5rem; line-height: 2.5rem; background: var(--#{methode.couleur});">
<i class="#{methode.icon}"></i>
</div>
<div>
<div class="font-medium">#{methode.methode}</div>
<div class="text-600 text-sm">#{methode.montantFormatte}</div>
</div>
</div>
<div class="text-right">
<div class="font-bold text-xl">#{methode.pourcentageInt}%</div>
</div>
</div>
</ui:repeat>
</div>
</div>
<div class="col-12 md:col-6">
<div class="flex flex-column gap-2">
<ui:repeat value="#{cotisationsBean.repartitionMethodes}" var="methode">
<div>
<div class="flex justify-content-between mb-1">
<span class="font-medium">#{methode.methode}</span>
<span class="text-600">#{methode.pourcentageInt}%</span>
</div>
<p:progressBar value="#{methode.pourcentageInt}"
showValue="false"
styleClass="progressbar-custom" />
</div>
</ui:repeat>
</div>
</div>
</div>
</div>
<!-- Cotisations en attente de paiement -->
<div class="card">
<h:form id="formPaiements">
<h5>Cotisations en Attente de Paiement</h5>
<p:dataTable id="dtPaiements"
value="#{cotisationsBean.cotisationsFiltrees}"
var="cotisation"
filteredValue="#{cotisationsBean.cotisationsFiltrees}"
paginator="true"
rows="20"
emptyMessage="Aucune cotisation en attente"
selection="#{cotisationsBean.cotisationSelectionnee}"
selectionMode="single">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Cotisations à payer</span>
<p:selectOneMenu value="#{cotisationsBean.filtres.statut}" styleClass="w-12rem">
<f:selectItem itemLabel="Tous" itemValue="" />
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE" />
<f:selectItem itemLabel="Partiellement payée" itemValue="PARTIELLEMENT_PAYEE" />
<f:selectItem itemLabel="En retard" itemValue="EN_RETARD" />
<p:ajax update="dtPaiements" />
</p:selectOneMenu>
</div>
</f:facet>
<p:column headerText="Membre" sortBy="#{cotisation.nomMembre}">
<div>
<div class="font-medium">#{cotisation.nomMembre}</div>
<div class="text-600 text-sm">#{cotisation.numeroMembre}</div>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{cotisation.typeCotisation}" style="width:120px">
<p:tag value="#{cotisation.typeCotisationLibelle}" severity="info" />
</p:column>
<p:column headerText="Montant Dû" sortBy="#{cotisation.montantDu}" style="width:120px">
<h:outputText value="#{cotisation.montantDuFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Montant Payé" sortBy="#{cotisation.montantPaye}" style="width:120px">
<h:outputText value="#{cotisation.montantPayeFormatte}" />
</p:column>
<p:column headerText="Restant" style="width:120px">
<h:outputText value="#{cotisation.montantRestantFormatte}"
styleClass="#{cotisation.montantRestant.compareTo(java.math.BigDecimal.ZERO) > 0 ? 'text-orange-500 font-bold' : 'text-green-500'}" />
</p:column>
<p:column headerText="Échéance" sortBy="#{cotisation.dateEcheance}" style="width:120px">
<h:outputText value="#{cotisation.dateEcheanceFormatee}" />
</p:column>
<p:column headerText="Actions" style="width:200px">
<div class="flex gap-1">
<p:commandButton value="Payer"
icon="pi pi-check"
styleClass="p-button-success p-button-sm"
action="#{cotisationsBean.selectionnerCotisation(cotisation)}"
update=":formPaiement"
oncomplete="PF('dlgPaiement').show();" />
<p:commandButton value="Partiel"
icon="pi pi-minus"
styleClass="p-button-info p-button-sm"
action="#{cotisationsBean.selectionnerCotisation(cotisation)}"
update=":formPaiementPartiel"
oncomplete="PF('dlgPaiementPartiel').show();" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Paiement Complet -->
<p:dialog header="Enregistrer un Paiement" widgetVar="dlgPaiement" modal="true" width="500" resizable="false">
<h:form id="formPaiement">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Cotisation</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.numeroReference} - #{cotisationsBean.cotisationSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">Montant dû: #{cotisationsBean.cotisationSelectionnee.montantDuFormatte}</p>
</div>
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="methodePaiement" />
<ui:param name="label" value="Méthode de paiement" />
<ui:param name="value" value="#{cotisationsBean.cotisationSelectionnee.methodePaiement}" />
<ui:param name="required" value="true" />
<ui:define name="items">
<f:selectItem itemLabel="Wave Money" itemValue="WAVE_MONEY" />
<f:selectItem itemLabel="Espèces" itemValue="ESPECES" />
<f:selectItem itemLabel="Virement bancaire" itemValue="VIREMENT" />
<f:selectItem itemLabel="Chèque" itemValue="CHEQUE" />
<f:selectItem itemLabel="Orange Money" itemValue="ORANGE_MONEY" />
<f:selectItem itemLabel="Free Money" itemValue="FREE_MONEY" />
<f:selectItem itemLabel="Carte bancaire" itemValue="CARTE_BANCAIRE" />
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="referencePaiement" />
<ui:param name="label" value="Référence de paiement" />
<ui:param name="value" value="#{cotisationsBean.cotisationSelectionnee.referencePaiement}" />
<ui:param name="placeholder" value="Ex: WAVE-123456789" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="observationsPaiement" />
<ui:param name="label" value="Observations" />
<ui:param name="value" value="#{cotisationsBean.cotisationSelectionnee.observations}" />
<ui:param name="rows" value="3" />
</ui:include>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgPaiement').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Enregistrer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{cotisationsBean.marquerCommePaye}" />
<ui:param name="update" value="@form :formPaiements" />
<ui:param name="oncomplete" value="PF('dlgPaiement').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Paiement Partiel -->
<p:dialog header="Enregistrer un Paiement Partiel" widgetVar="dlgPaiementPartiel" modal="true" width="500" resizable="false">
<h:form id="formPaiementPartiel">
<div class="ui-fluid">
<div class="field">
<label class="font-medium">Cotisation</label>
<p class="text-600">#{cotisationsBean.cotisationSelectionnee.numeroReference} - #{cotisationsBean.cotisationSelectionnee.nomMembre}</p>
<p class="text-500 text-sm">Montant dû: #{cotisationsBean.cotisationSelectionnee.montantDuFormatte}</p>
<p class="text-500 text-sm">Montant restant: #{cotisationsBean.cotisationSelectionnee.montantRestantFormatte}</p>
</div>
<div class="field">
<p:outputLabel for="montantPaye" value="Montant à payer (FCFA)" />
<p:inputNumber id="montantPaye"
value="#{cotisationsBean.cotisationSelectionnee.montantPaye}"
symbol=""
minValue="0"
maxValue="#{cotisationsBean.cotisationSelectionnee.montantDu}"
styleClass="w-full" />
</div>
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="methodePaiementPartiel" />
<ui:param name="label" value="Méthode de paiement" />
<ui:param name="value" value="#{cotisationsBean.cotisationSelectionnee.methodePaiement}" />
<ui:param name="required" value="true" />
<ui:define name="items">
<f:selectItem itemLabel="Wave Money" itemValue="WAVE_MONEY" />
<f:selectItem itemLabel="Espèces" itemValue="ESPECES" />
<f:selectItem itemLabel="Virement bancaire" itemValue="VIREMENT" />
<f:selectItem itemLabel="Chèque" itemValue="CHEQUE" />
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="referencePaiementPartiel" />
<ui:param name="label" value="Référence de paiement" />
<ui:param name="value" value="#{cotisationsBean.cotisationSelectionnee.referencePaiement}" />
</ui:include>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgPaiementPartiel').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Enregistrer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{cotisationsBean.enregistrerPaiementPartiel(cotisationsBean.cotisationSelectionnee.montantPaye, cotisationsBean.cotisationSelectionnee.methodePaiement, cotisationsBean.cotisationSelectionnee.referencePaiement)}" />
<ui:param name="update" value="@form :formPaiements" />
<ui:param name="oncomplete" value="PF('dlgPaiementPartiel').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,185 @@
<!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:param name="page" value="#{cotisationsGestionBean}"/>
<ui:define name="title">Rapports Financiers - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-chart-bar text-purple-500" />
<ui:param name="title" value="Rapports Financiers" />
<ui:param name="description" value="Analyse et rapports détaillés sur les cotisations et paiements" />
<ui:define name="actions">
<h:form id="formActionsRapports">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Générer rapport" />
<ui:param name="icon" value="pi pi-file-pdf" />
<ui:param name="action" value="#{cotisationsBean.genererRapportFinancier}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{cotisationsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Vue d'ensemble -->
<div class="grid">
<div class="col-12 md:col-8">
<div class="card">
<h5>
<i class="pi pi-chart-line mr-2"></i>
Évolution des Paiements (12 derniers mois)
</h5>
<div class="flex flex-column gap-2 mt-3">
<ui:repeat value="#{cotisationsBean.evolutionPaiements}" var="evolution">
<div class="flex align-items-center gap-3">
<div class="text-600" style="width: 60px;">#{evolution.mois}</div>
<div class="flex-1">
<div class="flex align-items-center gap-2">
<div class="bg-blue-500 border-round"
style="width: #{evolution.hauteur}px; height: 20px; min-width: 10px;"></div>
<span class="text-600 text-sm">#{evolution.montantFormatte}</span>
</div>
</div>
</div>
</ui:repeat>
</div>
</div>
</div>
<div class="col-12 md:col-4">
<div class="card">
<h5>
<i class="pi pi-chart-pie mr-2"></i>
Répartition par Méthode
</h5>
<div class="flex flex-column gap-3 mt-3">
<ui:repeat value="#{cotisationsBean.repartitionMethodes}" var="methode">
<div>
<div class="flex justify-content-between mb-1">
<span class="font-medium">#{methode.methode}</span>
<span class="text-600">#{methode.pourcentageInt}%</span>
</div>
<p:progressBar value="#{methode.pourcentageInt}"
showValue="false" />
</div>
</ui:repeat>
</div>
</div>
</div>
</div>
<!-- Statistiques détaillées -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.totalCollecteFormatte}" />
<ui:param name="label" value="Total Collecté" />
<ui:param name="icon" value="pi pi-wallet" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.objectifAnnuelFormatte}" />
<ui:param name="label" value="Objectif Annuel" />
<ui:param name="icon" value="pi pi-target" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.moyenneMensuelleFormattee}" />
<ui:param name="label" value="Moyenne Mensuelle" />
<ui:param name="icon" value="pi pi-chart-line" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.tauxRecouvrementInt}%" />
<ui:param name="label" value="Taux de Recouvrement" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Résumé des cotisations -->
<div class="card">
<h5>
<i class="pi pi-list mr-2"></i>
Résumé des Cotisations
</h5>
<div class="grid mt-3">
<div class="col-12 md:col-6">
<h6 class="mb-3">Par Statut</h6>
<div class="flex flex-column gap-2">
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Payées</span>
<p:tag value="#{cotisationsBean.compterParStatut('PAYEE')}"
severity="success" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Partiellement payées</span>
<p:tag value="#{cotisationsBean.compterParStatut('PARTIELLEMENT_PAYEE')}"
severity="info" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">En attente</span>
<p:tag value="#{cotisationsBean.compterParStatut('EN_ATTENTE')}"
severity="warning" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">En retard</span>
<p:tag value="#{cotisationsBean.compterParStatut('EN_RETARD')}"
severity="danger" />
</div>
</div>
</div>
<div class="col-12 md:col-6">
<h6 class="mb-3">Par Type</h6>
<div class="flex flex-column gap-2">
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Mensuelle</span>
<p:tag value="#{cotisationsBean.compterParType('MENSUELLE')}" severity="info" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Trimestrielle</span>
<p:tag value="#{cotisationsBean.compterParType('TRIMESTRIELLE')}" severity="info" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Semestrielle</span>
<p:tag value="#{cotisationsBean.compterParType('SEMESTRIELLE')}" severity="info" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Annuelle</span>
<p:tag value="#{cotisationsBean.compterParType('ANNUELLE')}" severity="info" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Adhésion</span>
<p:tag value="#{cotisationsBean.compterParType('ADHESION')}" severity="info" />
</div>
<div class="flex justify-content-between align-items-center p-2 border-round surface-50">
<span class="font-medium">Exceptionnelle</span>
<p:tag value="#{cotisationsBean.compterParType('EXCEPTIONNELLE')}" severity="info" />
</div>
</div>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,229 @@
<!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:param name="page" value="#{cotisationsGestionBean}"/>
<ui:define name="title">Relances de Cotisations - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-send text-orange-500" />
<ui:param name="title" value="Relances de Cotisations" />
<ui:param name="description" value="Gestion et envoi des relances pour les cotisations en retard" />
<ui:define name="actions">
<h:form id="formActionsRelances">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Relances groupées" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="onclick" value="PF('dlgRelancesGroupes').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{cotisationsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques de relances -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.cotisationsEnRetard}" />
<ui:param name="label" value="Cotisations en Retard" />
<ui:param name="icon" value="pi pi-exclamation-triangle" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.montantRetardFormatte}" />
<ui:param name="label" value="Montant en Retard" />
<ui:param name="icon" value="pi pi-clock" />
<ui:param name="bgColor" value="red" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.rappelsEnAttente.size()}" />
<ui:param name="label" value="Rappels en Attente" />
<ui:param name="icon" value="pi pi-bell" />
<ui:param name="bgColor" value="purple" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{cotisationsBean.statistiques.tauxRecouvrementInt}%" />
<ui:param name="label" value="Taux de Recouvrement" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="blue" />
</ui:include>
</div>
<!-- Liste des rappels en attente -->
<div class="card">
<h5>
<i class="pi pi-bell mr-2"></i>
Rappels en Attente
</h5>
<p:dataTable id="dtRappels"
value="#{cotisationsBean.rappelsEnAttente}"
var="rappel"
paginator="true"
rows="20"
emptyMessage="Aucun rappel en attente">
<p:column headerText="Membre" sortBy="#{rappel.nomMembre}">
<div>
<div class="font-medium">#{rappel.nomMembre}</div>
<div class="text-600 text-sm">#{rappel.club}</div>
</div>
</p:column>
<p:column headerText="Montant Dû" sortBy="#{rappel.montantDu}" style="width:120px">
<h:outputText value="#{rappel.montantDuFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Jours de Retard" sortBy="#{rappel.joursRetard}" style="width:120px">
<h:outputText value="#{rappel.joursRetard} jour(s)" />
</p:column>
<p:column headerText="Priorité" sortBy="#{rappel.priorite}" style="width:120px">
<p:tag value="#{rappel.priorite}"
severity="#{rappel.prioriteSeverity}" />
</p:column>
<p:column headerText="Actions" style="width:150px">
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Envoyer" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{cotisationsBean.envoyerRappel}" />
<ui:param name="update" value="@form" />
<ui:param name="styleClass" value="p-button-sm" />
</ui:include>
</p:column>
</p:dataTable>
</div>
<!-- Cotisations en retard -->
<div class="card">
<h:form id="formRelances">
<h5>Cotisations en Retard</h5>
<p:dataTable id="dtRetard"
value="#{cotisationsBean.cotisationsFiltrees}"
var="cotisation"
filteredValue="#{cotisationsBean.cotisationsFiltrees}"
paginator="true"
rows="20"
emptyMessage="Aucune cotisation en retard"
selection="#{cotisationsBean.cotisationsSelectionnees}"
selectionMode="multiple">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Cotisations nécessitant une relance</span>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Relancer sélectionnées" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{cotisationsBean.envoyerRappelsGroupes}" />
<ui:param name="update" value="@form" />
<ui:param name="disabled" value="#{empty cotisationsBean.cotisationsSelectionnees}" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</div>
</f:facet>
<p:column selectionMode="multiple" style="width:50px" />
<p:column headerText="Membre" sortBy="#{cotisation.nomMembre}">
<div>
<div class="font-medium">#{cotisation.nomMembre}</div>
<div class="text-600 text-sm">#{cotisation.numeroMembre}</div>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{cotisation.typeCotisation}" style="width:120px">
<p:tag value="#{cotisation.typeCotisationLibelle}" severity="info" />
</p:column>
<p:column headerText="Montant Dû" sortBy="#{cotisation.montantDu}" style="width:120px">
<h:outputText value="#{cotisation.montantDuFormatte}" styleClass="font-bold" />
</p:column>
<p:column headerText="Échéance" sortBy="#{cotisation.dateEcheance}" style="width:120px">
<h:outputText value="#{cotisation.dateEcheanceFormatee}" />
</p:column>
<p:column headerText="Jours Retard" style="width:120px">
<h:outputText value="#{cotisation.joursRetard} jour(s)"
styleClass="#{cotisation.joursRetard > 30 ? 'text-red-500 font-bold' : cotisation.joursRetard > 15 ? 'text-orange-500' : 'text-yellow-500'}" />
</p:column>
<p:column headerText="Actions" style="width:150px">
<div class="flex gap-1">
<p:commandButton icon="pi pi-send"
title="Envoyer un rappel"
styleClass="p-button-rounded p-button-text p-button-warning"
action="#{cotisationsBean.envoyerRappel(cotisation)}"
update="@form" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Relances Groupées -->
<p:dialog header="Relances Groupées" widgetVar="dlgRelancesGroupes" modal="true" width="500" resizable="false">
<h:form id="formRelancesGroupes">
<div class="ui-fluid">
<div class="field">
<p:outputLabel for="messageRelance" value="Message de relance" />
<p:inputTextarea id="messageRelance"
rows="5"
styleClass="w-full"
placeholder="Message personnalisé pour les relances..." />
</div>
<div class="field">
<p:selectBooleanCheckbox id="relanceUrgente" />
<p:outputLabel for="relanceUrgente" value=" Marquer comme urgente" />
</div>
<div class="surface-50 p-3 border-round">
<div class="font-medium mb-2">Destinataires :</div>
<div class="text-600 text-sm">#{cotisationsBean.cotisationsSelectionnees.size()} cotisation(s) sélectionnée(s)</div>
</div>
</div>
<div class="flex justify-content-end gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgRelancesGroupes').hide();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Envoyer les relances" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{cotisationsBean.envoyerRappelsGroupes}" />
<ui:param name="update" value="@form :formRelances" />
<ui:param name="oncomplete" value="PF('dlgRelancesGroupes').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,108 @@
<!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:param name="page" value="#{cotisationsGestionBean}"/>
<ui:define name="title">Rappels de Cotisations - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formReminders">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div>
<h3 class="m-0">
<i class="pi pi-bell text-primary mr-2"></i>
Rappels de Cotisations
</h3>
<p class="text-600 m-0 mt-2">
Gérez et envoyez les rappels de cotisations aux membres
</p>
</div>
<div class="flex gap-2 mt-2 md:mt-0">
<p:commandButton value="Envoyer rappels"
icon="pi pi-send"
styleClass="ui-button-success"
action="#{cotisationsGestionBean.envoyerRappelsGroupes}"/>
</div>
</div>
</div>
<!-- Statistiques -->
<div class="grid mb-3">
<div class="col-12 md:col-3">
<div class="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">#{cotisationsGestionBean.nombreMembresEnRetard}</div>
<div class="text-orange-700">En Retard</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 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">#{cotisationsGestionBean.nombreRappelsEnvoyes}</div>
<div class="text-blue-700">Rappels Envoyés</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-send text-xl"></i>
</div>
</div>
</div>
</div>
</div>
<!-- Liste des membres en retard -->
<div class="card">
<h5 class="mb-3">Membres avec Cotisations en Retard</h5>
<p:dataTable id="dtRetard"
var="membre"
value="#{cotisationsGestionBean.membresEnRetard}"
paginator="true"
rows="10"
selection="#{cotisationsGestionBean.membresSelectionnes}"
selectionMode="multiple"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,25">
<p:column selectionMode="multiple" style="width:50px"/>
<p:column headerText="Membre" sortBy="#{membre.nomComplet}">
<div>
<div class="font-medium">#{membre.nomComplet}</div>
<small class="text-600">#{membre.numeroMembre}</small>
</div>
</p:column>
<p:column headerText="Montant dû" sortBy="#{membre.montantDu}">
<div class="font-bold text-red-500">#{membre.montantDu} FCFA</div>
</p:column>
<p:column headerText="Jours de retard" sortBy="#{membre.joursRetard}">
<p:tag value="#{membre.joursRetard} jours" severity="danger"/>
</p:column>
<p:column headerText="Actions" style="width:150px">
<p:commandButton icon="pi pi-send"
styleClass="ui-button-rounded ui-button-text ui-button-primary"
action="#{cotisationsGestionBean.envoyerRappel(membre)}"
title="Envoyer rappel"/>
</p:column>
</p:dataTable>
</div>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,117 @@
<!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:param name="page" value="#{cotisationsGestionBean}"/>
<ui:define name="title">Rapports de Cotisations - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formReport">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div>
<h3 class="m-0">
<i class="pi pi-file-pdf text-primary mr-2"></i>
Rapports de Cotisations
</h3>
<p class="text-600 m-0 mt-2">
Générez et consultez les rapports détaillés sur les cotisations
</p>
</div>
<div class="flex gap-2 mt-2 md:mt-0">
<p:commandButton value="Générer rapport"
icon="pi pi-file-pdf"
styleClass="ui-button-success"
action="#{cotisationsGestionBean.genererRapport}"/>
</div>
</div>
</div>
<!-- Filtres pour le rapport -->
<div class="card mb-3">
<h5 class="mb-3">Paramètres du Rapport</h5>
<div class="grid">
<div class="col-12 md:col-4">
<p:outputLabel for="periodeRapport" value="Période"/>
<p:selectOneMenu id="periodeRapport" styleClass="w-full">
<f:selectItem itemLabel="Ce mois" itemValue="MOIS_COURANT"/>
<f:selectItem itemLabel="Ce trimestre" itemValue="TRIMESTRE_COURANT"/>
<f:selectItem itemLabel="Cette année" itemValue="ANNEE_COURANTE"/>
<f:selectItem itemLabel="Personnalisée" itemValue="PERSONNALISEE"/>
</p:selectOneMenu>
</div>
<div class="col-12 md:col-4">
<p:outputLabel for="typeRapport" value="Type de rapport"/>
<p:selectOneMenu id="typeRapport" styleClass="w-full">
<f:selectItem itemLabel="Rapport complet" itemValue="COMPLET"/>
<f:selectItem itemLabel="Rapport simplifié" itemValue="SIMPLIFIE"/>
<f:selectItem itemLabel="Rapport analytique" itemValue="ANALYTIQUE"/>
</p:selectOneMenu>
</div>
<div class="col-12 md:col-4">
<p:outputLabel for="formatRapport" value="Format"/>
<p:selectOneMenu id="formatRapport" styleClass="w-full">
<f:selectItem itemLabel="PDF" itemValue="PDF"/>
<f:selectItem itemLabel="Excel" itemValue="EXCEL"/>
<f:selectItem itemLabel="CSV" itemValue="CSV"/>
</p:selectOneMenu>
</div>
</div>
</div>
<!-- Rapports disponibles -->
<div class="card">
<h5 class="mb-3">Rapports Disponibles</h5>
<div class="grid">
<div class="col-12 md:col-4">
<div class="surface-100 border-round p-4 cursor-pointer hover:surface-200 transition-duration-200">
<div class="flex align-items-center mb-3">
<i class="pi pi-file-pdf text-red-500 text-2xl mr-3"></i>
<div>
<h6 class="m-0">Rapport Mensuel</h6>
<small class="text-600">Rapport complet du mois</small>
</div>
</div>
<p:commandButton value="Générer"
styleClass="ui-button-outlined ui-button-primary w-full"
action="#{cotisationsGestionBean.genererRapportMensuel}"/>
</div>
</div>
<div class="col-12 md:col-4">
<div class="surface-100 border-round p-4 cursor-pointer hover:surface-200 transition-duration-200">
<div class="flex align-items-center mb-3">
<i class="pi pi-file-excel text-green-500 text-2xl mr-3"></i>
<div>
<h6 class="m-0">Rapport Annuel</h6>
<small class="text-600">Synthèse de l'année</small>
</div>
</div>
<p:commandButton value="Générer"
styleClass="ui-button-outlined ui-button-success w-full"
action="#{cotisationsGestionBean.genererRapportAnnuel}"/>
</div>
</div>
<div class="col-12 md:col-4">
<div class="surface-100 border-round p-4 cursor-pointer hover:surface-200 transition-duration-200">
<div class="flex align-items-center mb-3">
<i class="pi pi-chart-bar text-blue-500 text-2xl mr-3"></i>
<div>
<h6 class="m-0">Rapport Analytique</h6>
<small class="text-600">Analyses et statistiques</small>
</div>
</div>
<p:commandButton value="Générer"
styleClass="ui-button-outlined ui-button-info w-full"
action="#{cotisationsGestionBean.genererRapportAnalytique}"/>
</div>
</div>
</div>
</div>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,533 @@
<!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">UnionFlow - Tableau de bord</ui:define>
<ui:define name="content">
<div class="grid">
<!-- Header avec informations contextuelles -->
<div class="col-12">
<div class="card">
<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>
<div class="flex align-items-center">
<i class="pi pi-calendar text-blue-500"></i>
<span class="text-700 ml-2">#{dashboardBean.currentDate}</span>
<span class="mx-3">|</span>
<i class="pi pi-users text-green-500"></i>
<span class="text-700 ml-2">#{dashboardBean.totalMembers} membres inscrits</span>
</div>
</div>
<div class="mt-3 lg:mt-0">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Rapport mensuel" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="action" value="#{dashboardBean.generateRapport}" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="mr-2" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Aide" />
<ui:param name="icon" value="pi pi-question-circle" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="ui-button-help" />
</ui:include>
</div>
</div>
</div>
</div>
<!-- Alertes URGENTES - En premier pour l'attention immédiate -->
<ui:fragment rendered="#{dashboardBean.hasAlerts}">
<div class="col-12">
<div class="card surface-50 border-round">
<h5 class="text-900 font-bold mb-3">
<i class="pi pi-exclamation-circle text-orange-500 mr-2"></i>
Actions requises aujourd'hui
</h5>
<div class="grid">
<!-- URGENT : Cotisations en retard -->
<div class="col-12 md:col-6 lg:col-3">
<div class="surface-card border-round p-3 border-left-3 border-red-500 hover-elevate-2">
<div class="flex align-items-center">
<div class="bg-red-100 border-round flex align-items-center justify-content-center mr-3"
style="width: 2.5rem; height: 2.5rem;">
<i class="pi pi-exclamation-triangle text-red-600"></i>
</div>
<div class="flex-1">
<div class="text-red-900 font-bold text-2xl">#{dashboardBean.cotisationsRetard}</div>
<div class="text-red-700 text-sm font-medium">Cotisations en retard</div>
</div>
</div>
</div>
</div>
<!-- IMPORTANT : Adhésions à renouveler -->
<div class="col-12 md:col-6 lg:col-3">
<div class="surface-card border-round p-3 border-left-3 border-orange-500 hover-elevate-2">
<div class="flex align-items-center">
<div class="bg-orange-100 border-round flex align-items-center justify-content-center mr-3"
style="width: 2.5rem; height: 2.5rem;">
<i class="pi pi-clock text-orange-600"></i>
</div>
<div class="flex-1">
<div class="text-orange-900 font-bold text-2xl">#{dashboardBean.adhesionsExpiration}</div>
<div class="text-orange-700 text-sm font-medium">Expire dans 7 jours</div>
</div>
</div>
</div>
</div>
<!-- À TRAITER : Demandes en attente -->
<div class="col-12 md:col-6 lg:col-3">
<div class="surface-card border-round p-3 border-left-3 border-blue-500 hover-elevate-2">
<div class="flex align-items-center">
<div class="bg-blue-100 border-round flex align-items-center justify-content-center mr-3"
style="width: 2.5rem; height: 2.5rem;">
<i class="pi pi-inbox text-blue-600"></i>
</div>
<div class="flex-1">
<div class="text-blue-900 font-bold text-2xl">#{dashboardBean.demandesToTraiter}</div>
<div class="text-blue-700 text-sm font-medium">Demandes en attente</div>
</div>
</div>
</div>
</div>
<!-- SUCCÈS : Tâches complétées -->
<div class="col-12 md:col-6 lg:col-3">
<div class="surface-card border-round p-3 border-left-3 border-green-500 hover-elevate-2">
<div class="flex align-items-center">
<div class="bg-green-100 border-round flex align-items-center justify-content-center mr-3"
style="width: 2.5rem; height: 2.5rem;">
<i class="pi pi-check-circle text-green-600"></i>
</div>
<div class="flex-1">
<div class="text-green-900 font-bold text-2xl">#{dashboardBean.tachesCompletees}</div>
<div class="text-green-700 text-sm font-medium">Complétées aujourd'hui</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</ui:fragment>
<!-- KPIs principaux - Ordre psychologique optimal -->
<div class="col-12">
<h5 class="text-900 font-bold mb-3">
<i class="pi pi-chart-bar text-primary mr-2"></i>
Vue d'ensemble
</h5>
</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>
<!-- 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>
<!-- 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>
<!-- 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>
<!-- Tendances financières et analyses -->
<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>
<h:form>
<p:selectOneButton value="#{dashboardBean.periodeGraph}">
<f:selectItem itemLabel="3M" itemValue="3M" />
<f:selectItem itemLabel="6M" itemValue="6M" />
<f:selectItem itemLabel="1A" itemValue="1A" />
<p:ajax update="tendancesPanel" />
</p:selectOneButton>
</h:form>
</div>
</div>
<h:panelGroup id="tendancesPanel" layout="block">
<!-- Graphique avec données dynamiques -->
<div class="grid">
<ui:repeat value="#{dashboardBean.evolutionFinanciere}" var="mois">
<div class="col-4 text-center">
<h6 class="text-600 mb-2">#{mois.libelle}</h6>
<div class="flex flex-column align-items-center">
<div class="bg-blue-500 border-round mb-2" style="width:20px;height:#{mois.hauteur}px;"></div>
<span class="text-sm text-600">#{mois.montantFormatte}</span>
</div>
</div>
</ui:repeat>
</div>
<!-- Indicateurs de tendance dynamiques -->
<div class="grid mt-4">
<div class="col-12 md:col-4">
<div class="flex align-items-center">
<i class="#{dashboardBean.evolutionRecettesIcon} text-2xl mr-2"></i>
<div>
<div class="text-900 font-medium">#{dashboardBean.evolutionRecettesPrefix}#{dashboardBean.evolutionRecettesPourcent}%</div>
<span class="text-600 text-sm">Recettes vs mois dernier</span>
</div>
</div>
</div>
<div class="col-12 md:col-4">
<div class="flex align-items-center">
<i class="#{dashboardBean.evolutionDepensesIcon} text-2xl mr-2"></i>
<div>
<div class="text-900 font-medium">#{dashboardBean.evolutionDepensesPrefix}#{dashboardBean.evolutionDepensesPourcent}%</div>
<span class="text-600 text-sm">Dépenses vs mois dernier</span>
</div>
</div>
</div>
<div class="col-12 md:col-4">
<div class="flex align-items-center">
<i class="pi pi-minus text-blue-500 text-2xl mr-2"></i>
<div>
<div class="text-900 font-medium">#{dashboardBean.tendanceParticipation}</div>
<span class="text-600 text-sm">Taux de participation</span>
</div>
</div>
</div>
</div>
</h:panelGroup>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="card">
<h5>État des cotisations</h5>
<!-- Graphique circulaire dynamique -->
<div class="text-center mb-4">
<div class="relative inline-block">
<div class="w-8rem h-8rem border-circle border-8 border-blue-200 mx-auto mb-3 relative">
<div class="absolute top-50 left-50 bg-white border-circle flex align-items-center justify-content-center" style="width: 60px; height: 60px; margin-top: -30px; margin-left: -30px;">
<span class="text-900 font-bold">#{dashboardBean.cotisationsAJourPourcent}%</span>
</div>
</div>
</div>
</div>
<!-- Légende avec données dynamiques -->
<div class="mt-3">
<div class="flex align-items-center justify-content-between py-2">
<div class="flex align-items-center">
<div class="w-1rem h-1rem bg-blue-500 border-round mr-2"></div>
<span class="text-600">À jour</span>
</div>
<span class="text-900 font-medium">#{dashboardBean.cotisationsAJourPourcent}%</span>
</div>
<div class="flex align-items-center justify-content-between py-2">
<div class="flex align-items-center">
<div class="w-1rem h-1rem bg-orange-500 border-round mr-2"></div>
<span class="text-600">En retard</span>
</div>
<span class="text-900 font-medium">#{dashboardBean.cotisationsRetardPourcent}%</span>
</div>
<div class="flex align-items-center justify-content-between py-2">
<div class="flex align-items-center">
<div class="w-1rem h-1rem bg-red-500 border-round mr-2"></div>
<span class="text-600">Impayées</span>
</div>
<span class="text-900 font-medium">#{dashboardBean.cotisationsImpayeesPourcent}%</span>
</div>
</div>
<!-- Barres de progression dynamiques -->
<div class="mt-4">
<div class="mb-3">
<div class="flex align-items-center justify-content-between mb-2">
<span class="text-600">Taux de collecte</span>
<span class="text-900 font-medium">#{dashboardBean.tauxCollecte}%</span>
</div>
<div class="bg-gray-200 border-round overflow-hidden" style="height: 8px;">
<div class="bg-green-500 h-full border-round" style="width: #{dashboardBean.tauxCollecte}%;"></div>
</div>
</div>
<div class="mb-3">
<div class="flex align-items-center justify-content-between mb-2">
<span class="text-600">Objectif mensuel</span>
<span class="text-900 font-medium">#{dashboardBean.tauxObjectifCotisations}%</span>
</div>
<div class="bg-gray-200 border-round overflow-hidden" style="height: 8px;">
<div class="bg-blue-500 h-full border-round" style="width: #{dashboardBean.tauxObjectifCotisations}%;"></div>
</div>
</div>
</div>
</div>
</div>
<!-- Journal d'activités et Tâches prioritaires -->
<div class="col-12 lg:col-8">
<h:form>
<div class="card">
<div class="flex align-items-center justify-content-between mb-4">
<h5>Journal d'activités</h5>
<div>
<p:selectOneMenu value="#{dashboardBean.filtreActivite}">
<f:selectItem itemLabel="Toutes" itemValue="ALL" />
<f:selectItem itemLabel="Cotisations" itemValue="COTISATION" />
<f:selectItem itemLabel="Adhésions" itemValue="ADHESION" />
<f:selectItem itemLabel="Aides" itemValue="AIDE" />
<f:selectItem itemLabel="Événements" itemValue="EVENEMENT" />
<p:ajax update="activitiesTable" />
</p:selectOneMenu>
</div>
</div>
<p:dataTable id="activitiesTable" value="#{dashboardBean.recentActivities}" var="activity"
rows="8" paginator="true" paginatorPosition="bottom">
<p:column headerText="Date" style="width:120px">
<div class="flex flex-column">
<span class="text-900 font-medium">
<h:outputText value="#{activity.date}">
<f:convertDateTime pattern="dd/MM HH:mm" type="localDateTime"/>
</h:outputText>
</span>
<small class="text-500">
<h:outputText value="#{activity.date}">
<f:convertDateTime pattern="yyyy" type="localDateTime"/>
</h:outputText>
</small>
</div>
</p:column>
<p:column headerText="Activité" style="width:100px">
<p:tag value="#{activity.type}" severity="#{activity.severity}"
icon="#{activity.icon}" styleClass="mr-2"/>
</p:column>
<p:column headerText="Description">
<div>
<div class="text-900 font-medium">#{activity.titre}</div>
<div class="text-600 mt-1">#{activity.description}</div>
<ui:fragment rendered="#{activity.montant != null}">
<div class="mt-2">
<span class="text-green-600 font-medium">#{activity.montant} FCFA</span>
</div>
</ui:fragment>
</div>
</p:column>
<p:column headerText="Acteur" style="width:150px">
<div class="flex align-items-center">
<p:graphicImage name="images/avatar/profile.jpg" library="demo"
styleClass="w-2rem h-2rem border-circle mr-2"/>
<div>
<div class="text-900 font-medium">#{activity.userNom}</div>
<small class="text-500">#{activity.userRole}</small>
</div>
</div>
</p:column>
<p:column headerText="Action" style="width:80px">
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-eye" />
<ui:param name="title" value="Voir détails" />
</ui:include>
</p:column>
</p:dataTable>
</div>
</h:form>
</div>
<!-- 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>
</div>
</div>
</div>
</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>
</div>
</div>
</div>
</div>
<!-- Tableau de bord financier détaillé -->
<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">
<h:form>
<p:calendar value="#{dashboardBean.moisSelectionne}" view="month"
yearNavigator="true" yearRange="2020:2030">
<p:ajax update="financialSummary" listener="#{dashboardBean.onMoisChange}"/>
</p:calendar>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="action" value="#{dashboardBean.exportFinancialReport}" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="ui-button-sm" />
</ui:include>
</h:form>
</div>
</div>
<h:panelGroup id="financialSummary" layout="block" styleClass="grid">
<div class="col-12 md:col-3">
<div class="text-center p-3 border-round bg-green-50">
<div class="text-green-600 font-medium text-xl">#{dashboardBean.recettesMois} FCFA</div>
<div class="text-500">Recettes totales</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="text-center p-3 border-round bg-red-50">
<div class="text-red-600 font-medium text-xl">#{dashboardBean.depensesMois} FCFA</div>
<div class="text-500">Dépenses totales</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="text-center p-3 border-round bg-blue-50">
<div class="text-blue-600 font-medium text-xl">#{dashboardBean.soldeMois} FCFA</div>
<div class="text-500">Solde net</div>
</div>
</div>
<div class="col-12 md:col-3">
<div class="text-center p-3 border-round bg-purple-50">
<div class="text-purple-600 font-medium text-xl">#{dashboardBean.tresorerie} FCFA</div>
<div class="text-500">Trésorerie actuelle</div>
</div>
</div>
</h:panelGroup>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,198 @@
<!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:param name="page" value="#{evenementsBean}"/>
<ui:define name="title">Bilan des Événements - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-chart-bar text-green-500" />
<ui:param name="title" value="Bilan des Événements" />
<ui:param name="description" value="Analysez les performances et les résultats de vos événements" />
<ui:define name="actions">
<h:form id="formActionsBilan">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{evenementsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques globales -->
<div class="grid mb-3">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{evenementsBean.statistiques.totalEvenements}" />
<ui:param name="label" value="Total événements" />
<ui:param name="icon" value="pi pi-calendar" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{evenementsBean.statistiques.participantsTotal}" />
<ui:param name="label" value="Total participants" />
<ui:param name="icon" value="pi pi-users" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{evenementsBean.statistiques.budgetTotal}" />
<ui:param name="label" value="Budget total" />
<ui:param name="icon" value="pi pi-wallet" />
<ui:param name="bgColor" value="purple" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0%" />
<ui:param name="label" value="Taux de participation moyen" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="orange" />
</ui:include>
</div>
<!-- Filtres et recherche (DRY/WOU: filter-bar) -->
<ui:decorate template="/templates/components/cards/filter-bar.xhtml">
<ui:param name="title" value="Filtres" />
<ui:param name="styleClass" value="mb-3" />
<ui:define name="filters">
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel for="searchBilan" value="Rechercher" />
<span class="p-input-icon-left w-full">
<i class="pi pi-search"></i>
<p:inputText id="searchBilan"
placeholder="Titre événement..."
styleClass="w-full">
<p:ajax event="keyup" delay="500"/>
</p:inputText>
</span>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtrePeriode" value="Période" />
<p:selectOneMenu id="filtrePeriode" styleClass="w-full">
<f:selectItem itemLabel="Toutes périodes" itemValue="" />
<f:selectItem itemLabel="Ce mois" itemValue="MOIS" />
<f:selectItem itemLabel="Ce trimestre" itemValue="TRIMESTRE" />
<f:selectItem itemLabel="Cette année" itemValue="ANNEE" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreType" value="Type" />
<p:selectOneMenu id="filtreType" styleClass="w-full">
<f:selectItem itemLabel="Tous types" itemValue="" />
<f:selectItem itemLabel="Assemblée Générale" itemValue="ASSEMBLEE_GENERALE" />
<f:selectItem itemLabel="Formation" itemValue="FORMATION" />
<f:selectItem itemLabel="Activité Sociale" itemValue="ACTIVITE_SOCIALE" />
</p:selectOneMenu>
</div>
</div>
</ui:define>
<ui:define name="actions">
<div class="col-12 md:col-2">
<div class="field">
<label class="invisible">Actions</label>
<p:commandButton value="Réinitialiser"
icon="pi pi-filter-slash"
styleClass="ui-button-secondary w-full" />
</div>
</div>
</ui:define>
</ui:decorate>
<!-- Tableau de bord des bilans -->
<div class="grid">
<!-- Liste des événements avec bilans -->
<div class="col-12">
<div class="card">
<h:form id="formBilans">
<h5>Bilans par Événement</h5>
<p:dataTable id="dtBilans"
value="#{evenementsBean.evenementsFiltres}"
var="evenement"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50,100"
emptyMessage="Aucun bilan trouvé"
styleClass="table-responsive">
<p:column headerText="Événement" sortBy="#{evenement.titre}">
<div>
<span class="font-semibold">#{evenement.titre}</span>
<br/>
<span class="text-sm text-600">#{evenement.typeEvenementLibelle}</span>
</div>
</p:column>
<p:column headerText="Date">
<span>#{evenement.dateDebutFormatee}</span>
</p:column>
<p:column headerText="Participants">
<div>
<span class="font-medium">0</span>
<span class="text-sm text-600"> / 0 prévus</span>
</div>
</p:column>
<p:column headerText="Budget">
<div>
<span class="font-medium">0 XOF</span>
<br/>
<span class="text-sm text-600">0 XOF prévu</span>
</div>
</p:column>
<p:column headerText="Taux participation">
<p:tag value="0%" severity="info" />
</p:column>
<p:column headerText="Actions" style="width: 150px;">
<p:commandButton value="Voir bilan"
icon="pi pi-chart-bar"
styleClass="ui-button-rounded ui-button-text ui-button-secondary"
outcome="/pages/secure/evenement/bilan-detail" />
</p:column>
</p:dataTable>
</h:form>
</div>
</div>
</div>
<!-- Graphiques et analyses -->
<div class="grid mt-3">
<div class="col-12 md:col-6">
<div class="card">
<h5>Évolution des participations</h5>
<p class="text-600">Graphique en développement</p>
</div>
</div>
<div class="col-12 md:col-6">
<div class="card">
<h5>Répartition par type</h5>
<p class="text-600">Graphique en développement</p>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,18 @@
<!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:param name="page" value="#{evenementsBean}"/>
<ui:define name="title">Calendrier des Événements - UnionFlow</ui:define>
<ui:define name="content">
<!-- Redirection vers calendrier.xhtml (WOU/DRY - réutiliser la même page) -->
<h:form>
<p:commandButton value="Voir le calendrier"
action="evenementCalendrierPage?faces-redirect=true"
styleClass="ui-button-primary"/>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,183 @@
<!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:param name="page" value="#{evenementsBean}"/>
<ui:define name="title">Calendrier des Événements - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-calendar-plus text-blue-500" />
<ui:param name="title" value="Calendrier des Événements" />
<ui:param name="description" value="Vue calendrier de tous les événements de l'organisation" />
<ui:define name="actions">
<h:form id="formActionsCalendrier">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouvel événement" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="outcome" value="/pages/secure/evenement/creation.xhtml" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{evenementsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Calendrier -->
<div class="card">
<h:form id="formCalendrier">
<h5>Calendrier</h5>
<div class="text-center p-4">
<i class="pi pi-calendar text-4xl text-blue-500 mb-3"></i>
<h5>Calendrier des Événements</h5>
<p class="text-600">La vue calendrier interactive sera disponible prochainement</p>
<p class="text-600 mt-2">En attendant, utilisez la liste des événements à venir ci-dessous</p>
</div>
</h:form>
</div>
<!-- Liste des événements à venir -->
<div class="card">
<h:form id="formListeProchains">
<h5>Événements à Venir</h5>
<p:dataTable id="dtProchains"
value="#{evenementsBean.evenementsProchains}"
var="evenement"
paginator="false"
emptyMessage="Aucun événement à venir"
rowKey="#{evenement.id}">
<p:column headerText="Date">
<div>
<div class="font-medium">#{evenement.dateDebutFormatee}</div>
<div class="text-sm text-600">#{evenement.heureDebutFormatee} - #{evenement.heureFinFormatee}</div>
</div>
</p:column>
<p:column headerText="Événement">
<div class="flex align-items-center gap-2">
<i class="#{evenement.typeEvenementIcon} text-#{evenement.typeEvenementSeverity}"></i>
<div>
<div class="font-semibold">#{evenement.titre}</div>
<div class="text-sm text-600">#{evenement.lieu}</div>
</div>
</div>
</p:column>
<p:column headerText="Statut">
<p:tag value="#{evenement.statutLibelle}"
severity="#{evenement.statutSeverity}"
icon="#{evenement.statutIcon}" />
</p:column>
<p:column headerText="Participants">
<div>#{evenement.participantsInscrits} / #{evenement.capaciteMax}</div>
</p:column>
<p:column headerText="Actions">
<p:commandButton icon="pi pi-eye"
title="Voir détails"
styleClass="p-button-text p-button-rounded"
action="#{evenementsBean.selectionnerEvenement(evenement)}"
update=":formCalendrier:dlgDetails"
oncomplete="PF('dlgDetails').show();" />
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Détails -->
<h:form id="formDetails">
<p:dialog id="dlgDetails" header="Détails de l'Événement"
widgetVar="dlgDetails"
modal="true"
resizable="false"
style="width: 90vw; max-width: 700px;">
<div class="grid" rendered="#{evenementsBean.evenementSelectionne != null}">
<div class="col-12">
<h4>#{evenementsBean.evenementSelectionne.titre}</h4>
<p class="text-600">#{evenementsBean.evenementSelectionne.description}</p>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Type</label>
<p:tag value="#{evenementsBean.evenementSelectionne.typeEvenementLibelle}"
severity="#{evenementsBean.evenementSelectionne.typeEvenementSeverity}" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Statut</label>
<p:tag value="#{evenementsBean.evenementSelectionne.statutLibelle}"
severity="#{evenementsBean.evenementSelectionne.statutSeverity}" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Date de début</label>
<div>#{evenementsBean.evenementSelectionne.dateDebutFormatee}</div>
<div class="text-sm text-600">#{evenementsBean.evenementSelectionne.heureDebutFormatee}</div>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Lieu</label>
<div>#{evenementsBean.evenementSelectionne.lieu}</div>
<div class="text-sm text-600">#{evenementsBean.evenementSelectionne.adresseComplete}</div>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Participants</label>
<div>#{evenementsBean.evenementSelectionne.participantsInscrits} / #{evenementsBean.evenementSelectionne.capaciteMax}</div>
<p:progressBar value="#{evenementsBean.evenementSelectionne.tauxRemplissage}"
showValue="true" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Budget</label>
<div>#{evenementsBean.evenementSelectionne.budgetFormate}</div>
</div>
</div>
</div>
<f:facet name="footer">
<div class="flex gap-2">
<p:commandButton value="Voir détails"
icon="pi pi-eye"
outcome="/pages/secure/evenement/gestion.xhtml"
styleClass="p-button-outlined" />
<p:commandButton value="Fermer"
icon="pi pi-times"
onclick="PF('dlgDetails').hide();"
styleClass="p-button-secondary p-button-outlined" />
</div>
</f:facet>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,18 @@
<!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:param name="page" value="#{evenementsBean}"/>
<ui:define name="title">Créer un Événement - UnionFlow</ui:define>
<ui:define name="content">
<!-- Redirection vers creation.xhtml (WOU/DRY - réutiliser la même page) -->
<h:form>
<p:commandButton value="Créer un événement"
action="evenementCreationPage?faces-redirect=true"
styleClass="ui-button-primary"/>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,268 @@
<!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:param name="page" value="#{evenementsBean}"/>
<ui:define name="title">Création d'Événement - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-plus-circle text-green-500" />
<ui:param name="title" value="Créer un Nouvel Événement" />
<ui:param name="description" value="Remplissez le formulaire pour créer un nouvel événement" />
<ui:define name="actions">
<h:form id="formActionsCreation">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Retour" />
<ui:param name="icon" value="pi pi-arrow-left" />
<ui:param name="outcome" value="/pages/secure/evenement/gestion.xhtml" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Formulaire de création -->
<div class="card">
<h:form id="formCreation">
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:define name="title">Informations Générales</ui:define>
<ui:define name="content">
<div class="grid">
<div class="col-12">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="titre" />
<ui:param name="label" value="Titre de l'événement *" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.titre}" />
<ui:param name="required" value="true" />
<ui:param name="placeholder" value="Ex: Assemblée Générale Annuelle 2025" />
</ui:include>
</div>
<div class="col-12">
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="description" />
<ui:param name="label" value="Description" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.description}" />
<ui:param name="rows" value="4" />
<ui:param name="placeholder" value="Description détaillée de l'événement..." />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="typeEvenement" />
<ui:param name="label" value="Type d'événement *" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.typeEvenement}" />
<ui:param name="required" value="true" />
<ui:define name="items">
<f:selectItem itemLabel="Sélectionner un type" itemValue="" />
<f:selectItem itemLabel="Assemblée Générale" itemValue="ASSEMBLEE_GENERALE" />
<f:selectItem itemLabel="Formation" itemValue="FORMATION" />
<f:selectItem itemLabel="Activité Sociale" itemValue="ACTIVITE_SOCIALE" />
<f:selectItem itemLabel="Action Caritative" itemValue="ACTION_CARITATIVE" />
<f:selectItem itemLabel="Réunion de Bureau" itemValue="REUNION_BUREAU" />
<f:selectItem itemLabel="Conférence" itemValue="CONFERENCE" />
<f:selectItem itemLabel="Atelier" itemValue="ATELIER" />
<f:selectItem itemLabel="Cérémonie" itemValue="CEREMONIE" />
<f:selectItem itemLabel="Autre" itemValue="AUTRE" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="priorite" />
<ui:param name="label" value="Priorité" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.priorite}" />
<ui:define name="items">
<f:selectItem itemLabel="Normale" itemValue="NORMALE" />
<f:selectItem itemLabel="Haute" itemValue="HAUTE" />
<f:selectItem itemLabel="Critique" itemValue="CRITIQUE" />
<f:selectItem itemLabel="Basse" itemValue="BASSE" />
</ui:define>
</ui:include>
</div>
</div>
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:define name="title">Dates et Horaires</ui:define>
<ui:define name="content">
<div class="grid">
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateDebut" />
<ui:param name="label" value="Date de début *" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.dateDebut}" />
<ui:param name="required" value="true" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateFin" />
<ui:param name="label" value="Date de fin" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.dateFin}" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="heureDebut" value="Heure de début" />
<p:inputMask id="heureDebut"
value="#{evenementsBean.nouvelEvenement.heureDebut}"
mask="99:99"
placeholder="HH:mm" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="heureFin" value="Heure de fin" />
<p:inputMask id="heureFin"
value="#{evenementsBean.nouvelEvenement.heureFin}"
mask="99:99"
placeholder="HH:mm" />
</div>
</div>
</div>
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:define name="title">Localisation</ui:define>
<ui:define name="content">
<div class="grid">
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="lieu" />
<ui:param name="label" value="Lieu *" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.lieu}" />
<ui:param name="required" value="true" />
<ui:param name="placeholder" value="Ex: Salle de conférence" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="adresse" />
<ui:param name="label" value="Adresse" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.adresse}" />
<ui:param name="placeholder" value="Adresse complète" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="ville" />
<ui:param name="label" value="Ville" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.ville}" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="region" />
<ui:param name="label" value="Région" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.region}" />
</ui:include>
</div>
</div>
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:define name="title">Organisation et Participants</ui:define>
<ui:define name="content">
<div class="grid">
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="organisateur" />
<ui:param name="label" value="Organisateur" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.organisateur}" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-number.xhtml">
<ui:param name="id" value="capaciteMax" />
<ui:param name="label" value="Capacité maximale" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.capaciteMax}" />
<ui:param name="min" value="1" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateLimiteInscription" />
<ui:param name="label" value="Date limite d'inscription" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.dateLimiteInscription}" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-boolean.xhtml">
<ui:param name="id" value="inscriptionObligatoire" />
<ui:param name="label" value="Inscription obligatoire" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.inscriptionObligatoire}" />
</ui:include>
</div>
</div>
</ui:define>
</ui:include>
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:define name="title">Budget</ui:define>
<ui:define name="content">
<div class="grid">
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-number.xhtml">
<ui:param name="id" value="budget" />
<ui:param name="label" value="Budget prévu" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.budget}" />
<ui:param name="min" value="0" />
<ui:param name="suffix" value=" FCFA" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="codeDevise" />
<ui:param name="label" value="Devise" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.codeDevise}" />
<ui:param name="placeholder" value="XOF" />
</ui:include>
</div>
</div>
</ui:define>
</ui:include>
<!-- Actions -->
<div class="flex justify-content-end gap-2 mt-4">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="outcome" value="/pages/secure/evenement/gestion.xhtml" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Créer l'événement" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{evenementsBean.creerEvenement}" />
<ui:param name="update" value="@form" />
</ui:include>
</div>
</h:form>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,528 @@
<!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:param name="page" value="#{evenementsBean}"/>
<ui:define name="title">Gestion des Événements - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-calendar text-blue-500" />
<ui:param name="title" value="Gestion des Événements" />
<ui:param name="description" value="Création, suivi et gestion des événements de l'organisation" />
<ui:define name="actions">
<h:form id="formActionsEvenements">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouvel événement" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="onclick" value="PF('dlgNouvelEvenement').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{evenementsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{evenementsBean.statistiques.totalEvenements}" />
<ui:param name="label" value="Total Événements" />
<ui:param name="icon" value="pi pi-calendar" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{evenementsBean.statistiques.evenementsActifs}" />
<ui:param name="label" value="Événements Actifs" />
<ui:param name="icon" value="pi pi-check-circle" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{evenementsBean.statistiques.participantsTotal}" />
<ui:param name="label" value="Total Participants" />
<ui:param name="icon" value="pi pi-users" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{evenementsBean.statistiques.budgetTotal}" />
<ui:param name="label" value="Budget Total" />
<ui:param name="icon" value="pi pi-wallet" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Liste des événements -->
<div class="card">
<h:form id="formEvenements">
<h5>Liste des Événements</h5>
<!-- Filtres et recherche (DRY/WOU: filter-bar) -->
<ui:decorate template="/templates/components/cards/filter-bar.xhtml">
<ui:param name="title" value="Filtres" />
<ui:param name="styleClass" value="mb-3" />
<ui:define name="filters">
<div class="col-12 md:col-4">
<div class="field">
<p:outputLabel for="searchTitre" value="Rechercher" />
<span class="p-input-icon-left w-full">
<i class="pi pi-search"></i>
<p:inputText id="searchTitre"
placeholder="Rechercher par titre..."
value="#{evenementsBean.filtres.titre}"
styleClass="w-full">
<p:ajax event="keyup" update="dtEvenements" delay="500"/>
</p:inputText>
</span>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreType" value="Type" />
<p:selectOneMenu id="filtreType"
value="#{evenementsBean.filtres.type}"
styleClass="w-full">
<f:selectItem itemLabel="Tous les types" itemValue="" />
<f:selectItem itemLabel="Assemblée Générale" itemValue="ASSEMBLEE_GENERALE" />
<f:selectItem itemLabel="Formation" itemValue="FORMATION" />
<f:selectItem itemLabel="Activité Sociale" itemValue="ACTIVITE_SOCIALE" />
<f:selectItem itemLabel="Action Caritative" itemValue="ACTION_CARITATIVE" />
<f:selectItem itemLabel="Réunion de Bureau" itemValue="REUNION_BUREAU" />
<f:selectItem itemLabel="Conférence" itemValue="CONFERENCE" />
<f:selectItem itemLabel="Atelier" itemValue="ATELIER" />
<f:selectItem itemLabel="Cérémonie" itemValue="CEREMONIE" />
<f:selectItem itemLabel="Autre" itemValue="AUTRE" />
<p:ajax event="change" update="dtEvenements" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreStatut" value="Statut" />
<p:selectOneMenu id="filtreStatut"
value="#{evenementsBean.filtres.statut}"
styleClass="w-full">
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
<f:selectItem itemLabel="Planifié" itemValue="PLANIFIE" />
<f:selectItem itemLabel="Confirmé" itemValue="CONFIRME" />
<f:selectItem itemLabel="En cours" itemValue="EN_COURS" />
<f:selectItem itemLabel="Terminé" itemValue="TERMINE" />
<f:selectItem itemLabel="Annulé" itemValue="ANNULE" />
<f:selectItem itemLabel="Reporté" itemValue="REPORTE" />
<p:ajax event="change" update="dtEvenements" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtrePriorite" value="Priorité" />
<p:selectOneMenu id="filtrePriorite"
value="#{evenementsBean.filtres.priorite}"
styleClass="w-full">
<f:selectItem itemLabel="Toutes les priorités" itemValue="" />
<f:selectItem itemLabel="Critique" itemValue="CRITIQUE" />
<f:selectItem itemLabel="Haute" itemValue="HAUTE" />
<f:selectItem itemLabel="Normale" itemValue="NORMALE" />
<f:selectItem itemLabel="Basse" itemValue="BASSE" />
<p:ajax event="change" update="dtEvenements" />
</p:selectOneMenu>
</div>
</div>
</ui:define>
<ui:define name="actions">
<div class="col-12 md:col-2">
<div class="field">
<label class="invisible">Actions</label>
<p:commandButton value="Réinitialiser"
icon="pi pi-filter-slash"
action="#{evenementsBean.reinitialiserFiltres}"
update="dtEvenements searchTitre filtreType filtreStatut filtrePriorite"
styleClass="ui-button-secondary w-full" />
</div>
</div>
</ui:define>
</ui:decorate>
<!-- Tableau des événements -->
<p:dataTable id="dtEvenements"
value="#{evenementsBean.evenementsFiltres}"
var="evenement"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50,100"
emptyMessage="Aucun événement trouvé"
selection="#{evenementsBean.evenementSelectionne}"
selectionMode="single"
rowKey="#{evenement.id}">
<p:column headerText="Titre" sortBy="#{evenement.titre}" filterBy="#{evenement.titre}">
<div class="flex align-items-center gap-2">
<i class="#{evenement.typeEvenementIcon} text-#{evenement.typeEvenementSeverity}"></i>
<span class="font-semibold">#{evenement.titre}</span>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{evenement.typeEvenement}">
<p:tag value="#{evenement.typeEvenementLibelle}"
severity="#{evenement.typeEvenementSeverity}" />
</p:column>
<p:column headerText="Date" sortBy="#{evenement.dateDebut}">
<div>
<div class="font-medium">#{evenement.dateDebutFormatee}</div>
<div class="text-sm text-600">#{evenement.heureDebutFormatee} - #{evenement.heureFinFormatee}</div>
</div>
</p:column>
<p:column headerText="Lieu">
<div>
<div class="font-medium">#{evenement.lieu}</div>
<div class="text-sm text-600">#{evenement.ville}</div>
</div>
</p:column>
<p:column headerText="Statut" sortBy="#{evenement.statut}">
<p:tag value="#{evenement.statutLibelle}"
severity="#{evenement.statutSeverity}"
icon="#{evenement.statutIcon}" />
</p:column>
<p:column headerText="Priorité" sortBy="#{evenement.priorite}">
<p:tag value="#{evenement.prioriteLibelle}"
severity="#{evenement.prioriteSeverity}" />
</p:column>
<p:column headerText="Participants">
<div>
<div class="font-medium">#{evenement.participantsInscrits} / #{evenement.capaciteMax}</div>
<p:progressBar value="#{evenement.tauxRemplissage}"
styleClass="mt-1"
showValue="false" />
</div>
</p:column>
<p:column headerText="Actions" style="width: 200px;">
<div class="flex gap-1">
<p:commandButton icon="pi pi-eye"
title="Voir détails"
styleClass="p-button-text p-button-rounded"
action="#{evenementsBean.selectionnerEvenement(evenement)}"
update=":formEvenements:dlgDetails"
oncomplete="PF('dlgDetails').show();" />
<p:commandButton icon="pi pi-pencil"
title="Modifier"
styleClass="p-button-text p-button-rounded p-button-success"
action="#{evenementsBean.selectionnerEvenement(evenement)}"
update=":formEvenements:dlgModifier"
oncomplete="PF('dlgModifier').show();" />
<p:commandButton icon="pi pi-trash"
title="Supprimer"
styleClass="p-button-text p-button-rounded p-button-danger"
action="#{evenementsBean.supprimerEvenement}"
update="@form"
onclick="return confirm('Êtes-vous sûr de vouloir supprimer cet événement ?');" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Nouvel Événement -->
<h:form id="formNouvelEvenement">
<p:dialog id="dlgNouvelEvenement" header="Nouvel Événement"
widgetVar="dlgNouvelEvenement"
modal="true"
resizable="false"
style="width: 90vw; max-width: 800px;"
rendered="#{evenementsBean.nouvelEvenement != null}">
<ui:include src="/templates/components/forms/form-section.xhtml">
<ui:define name="content">
<div class="grid">
<div class="col-12">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="titre" />
<ui:param name="label" value="Titre *" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.titre}" />
<ui:param name="required" value="true" />
</ui:include>
</div>
<div class="col-12">
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="description" />
<ui:param name="label" value="Description" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.description}" />
<ui:param name="rows" value="3" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="typeEvenement" />
<ui:param name="label" value="Type d'événement *" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.typeEvenement}" />
<ui:param name="required" value="true" />
<ui:define name="items">
<f:selectItem itemLabel="Assemblée Générale" itemValue="ASSEMBLEE_GENERALE" />
<f:selectItem itemLabel="Formation" itemValue="FORMATION" />
<f:selectItem itemLabel="Activité Sociale" itemValue="ACTIVITE_SOCIALE" />
<f:selectItem itemLabel="Action Caritative" itemValue="ACTION_CARITATIVE" />
<f:selectItem itemLabel="Réunion de Bureau" itemValue="REUNION_BUREAU" />
<f:selectItem itemLabel="Conférence" itemValue="CONFERENCE" />
<f:selectItem itemLabel="Atelier" itemValue="ATELIER" />
<f:selectItem itemLabel="Cérémonie" itemValue="CEREMONIE" />
<f:selectItem itemLabel="Autre" itemValue="AUTRE" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="priorite" />
<ui:param name="label" value="Priorité" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.priorite}" />
<ui:define name="items">
<f:selectItem itemLabel="Critique" itemValue="CRITIQUE" />
<f:selectItem itemLabel="Haute" itemValue="HAUTE" />
<f:selectItem itemLabel="Normale" itemValue="NORMALE" />
<f:selectItem itemLabel="Basse" itemValue="BASSE" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateDebut" />
<ui:param name="label" value="Date de début *" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.dateDebut}" />
<ui:param name="required" value="true" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateFin" />
<ui:param name="label" value="Date de fin" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.dateFin}" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="lieu" />
<ui:param name="label" value="Lieu *" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.lieu}" />
<ui:param name="required" value="true" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-number.xhtml">
<ui:param name="id" value="capaciteMax" />
<ui:param name="label" value="Capacité maximale" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.capaciteMax}" />
<ui:param name="min" value="1" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-number.xhtml">
<ui:param name="id" value="budget" />
<ui:param name="label" value="Budget prévu" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.budget}" />
<ui:param name="min" value="0" />
<ui:param name="suffix" value=" FCFA" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="organisateur" />
<ui:param name="label" value="Organisateur" />
<ui:param name="value" value="#{evenementsBean.nouvelEvenement.organisateur}" />
</ui:include>
</div>
</div>
</ui:define>
</ui:include>
<f:facet name="footer">
<div class="flex justify-content-end gap-2" rendered="#{evenementsBean.nouvelEvenement != null}">
<p:commandButton value="Annuler"
icon="pi pi-times"
onclick="PF('dlgNouvelEvenement').hide();"
styleClass="p-button-outlined" />
<p:commandButton value="Créer"
icon="pi pi-check"
action="#{evenementsBean.creerEvenement}"
update="@form"
oncomplete="if(!args.validationFailed) { PF('dlgNouvelEvenement').hide(); }" />
</div>
</f:facet>
</p:dialog>
</h:form>
<!-- Dialog Détails -->
<h:form id="formDetails">
<p:dialog id="dlgDetails" header="Détails de l'Événement"
widgetVar="dlgDetails"
modal="true"
resizable="false"
style="width: 90vw; max-width: 700px;">
<div class="grid" rendered="#{evenementsBean.evenementSelectionne != null}">
<div class="col-12">
<h4>#{evenementsBean.evenementSelectionne.titre}</h4>
<p class="text-600">#{evenementsBean.evenementSelectionne.description}</p>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Type</label>
<p:tag value="#{evenementsBean.evenementSelectionne.typeEvenementLibelle}"
severity="#{evenementsBean.evenementSelectionne.typeEvenementSeverity}" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Statut</label>
<p:tag value="#{evenementsBean.evenementSelectionne.statutLibelle}"
severity="#{evenementsBean.evenementSelectionne.statutSeverity}" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Date de début</label>
<div>#{evenementsBean.evenementSelectionne.dateDebutFormatee}</div>
<div class="text-sm text-600">#{evenementsBean.evenementSelectionne.heureDebutFormatee}</div>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Lieu</label>
<div>#{evenementsBean.evenementSelectionne.lieu}</div>
<div class="text-sm text-600">#{evenementsBean.evenementSelectionne.adresseComplete}</div>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Participants</label>
<div>#{evenementsBean.evenementSelectionne.participantsInscrits} / #{evenementsBean.evenementSelectionne.capaciteMax}</div>
<p:progressBar value="#{evenementsBean.evenementSelectionne.tauxRemplissage}"
showValue="true" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Budget</label>
<div>#{evenementsBean.evenementSelectionne.budgetFormate}</div>
</div>
</div>
</div>
<f:facet name="footer">
<p:commandButton value="Fermer"
icon="pi pi-times"
onclick="PF('dlgDetails').hide();"
styleClass="p-button-outlined" />
</f:facet>
</p:dialog>
</h:form>
<!-- Dialog Modifier -->
<h:form id="formModifier">
<p:dialog id="dlgModifier" header="Modifier l'Événement"
widgetVar="dlgModifier"
modal="true"
resizable="false"
style="width: 90vw; max-width: 800px;">
<div class="grid" rendered="#{evenementsBean.evenementSelectionne != null}">
<div class="col-12">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="titreModif" />
<ui:param name="label" value="Titre *" />
<ui:param name="value" value="#{evenementsBean.evenementSelectionne.titre}" />
<ui:param name="required" value="true" />
</ui:include>
</div>
<div class="col-12">
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="descriptionModif" />
<ui:param name="label" value="Description" />
<ui:param name="value" value="#{evenementsBean.evenementSelectionne.description}" />
<ui:param name="rows" value="3" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="statutModif" />
<ui:param name="label" value="Statut" />
<ui:param name="value" value="#{evenementsBean.evenementSelectionne.statut}" />
<ui:define name="items">
<f:selectItem itemLabel="Planifié" itemValue="PLANIFIE" />
<f:selectItem itemLabel="Confirmé" itemValue="CONFIRME" />
<f:selectItem itemLabel="En cours" itemValue="EN_COURS" />
<f:selectItem itemLabel="Terminé" itemValue="TERMINE" />
<f:selectItem itemLabel="Annulé" itemValue="ANNULE" />
<f:selectItem itemLabel="Reporté" itemValue="REPORTE" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateDebutModif" />
<ui:param name="label" value="Date de début *" />
<ui:param name="value" value="#{evenementsBean.evenementSelectionne.dateDebut}" />
<ui:param name="required" value="true" />
</ui:include>
</div>
</div>
<f:facet name="footer">
<div class="flex justify-content-end gap-2">
<p:commandButton value="Annuler"
icon="pi pi-times"
onclick="PF('dlgModifier').hide();"
styleClass="p-button-outlined" />
<p:commandButton value="Enregistrer"
icon="pi pi-check"
action="#{evenementsBean.modifierEvenement}"
update="@form"
oncomplete="if(!args.validationFailed) { PF('dlgModifier').hide(); }" />
</div>
</f:facet>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,180 @@
<!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:param name="page" value="#{evenementsBean}"/>
<ui:define name="title">Logistique des Événements - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-truck text-purple-500" />
<ui:param name="title" value="Logistique des Événements" />
<ui:param name="description" value="Gérez le matériel, les équipements et les ressources nécessaires pour vos événements" />
<ui:define name="actions">
<h:form id="formActionsLogistique">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouvelle demande" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="onclick" value="PF('dlgNouvelleDemande').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{evenementsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques -->
<div class="grid mb-3">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="Demandes actives" />
<ui:param name="icon" value="pi pi-shopping-cart" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="Matériel disponible" />
<ui:param name="icon" value="pi pi-box" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="En attente livraison" />
<ui:param name="icon" value="pi pi-hourglass" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="Fournisseurs" />
<ui:param name="icon" value="pi pi-building" />
<ui:param name="bgColor" value="purple" />
</ui:include>
</div>
<!-- Filtres et recherche (DRY/WOU: filter-bar) -->
<ui:decorate template="/templates/components/cards/filter-bar.xhtml">
<ui:param name="title" value="Filtres" />
<ui:param name="styleClass" value="mb-3" />
<ui:define name="filters">
<div class="col-12 md:col-4">
<div class="field">
<p:outputLabel for="searchLogistique" value="Rechercher" />
<span class="p-input-icon-left w-full">
<i class="pi pi-search"></i>
<p:inputText id="searchLogistique"
placeholder="Événement, matériel..."
styleClass="w-full">
<p:ajax event="keyup" delay="500"/>
</p:inputText>
</span>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreTypeMateriel" value="Type matériel" />
<p:selectOneMenu id="filtreTypeMateriel" styleClass="w-full">
<f:selectItem itemLabel="Tous types" itemValue="" />
<f:selectItem itemLabel="Sonorisation" itemValue="SONO" />
<f:selectItem itemLabel="Éclairage" itemValue="ECLAIRAGE" />
<f:selectItem itemLabel="Mobilier" itemValue="MOBILIER" />
<f:selectItem itemLabel="Catering" itemValue="CATERING" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreStatut" value="Statut" />
<p:selectOneMenu id="filtreStatut" styleClass="w-full">
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE" />
<f:selectItem itemLabel="Validé" itemValue="VALIDE" />
<f:selectItem itemLabel="Livré" itemValue="LIVRE" />
</p:selectOneMenu>
</div>
</div>
</ui:define>
<ui:define name="actions">
<div class="col-12 md:col-2">
<div class="field">
<label class="invisible">Actions</label>
<p:commandButton value="Réinitialiser"
icon="pi pi-filter-slash"
styleClass="ui-button-secondary w-full" />
</div>
</div>
</ui:define>
</ui:decorate>
<!-- Liste des demandes logistiques -->
<div class="card">
<h:form id="formLogistique">
<h5>Demandes Logistiques</h5>
<p:dataTable id="dtLogistique"
value="#{evenementsBean.evenementsFiltres}"
var="evenement"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50,100"
emptyMessage="Aucune demande logistique trouvée"
styleClass="table-responsive">
<p:column headerText="Événement" sortBy="#{evenement.titre}">
<span class="font-semibold">#{evenement.titre}</span>
</p:column>
<p:column headerText="Type matériel">
<p:tag value="À définir" severity="info" />
</p:column>
<p:column headerText="Quantité">
<span>0</span>
</p:column>
<p:column headerText="Date livraison">
<span class="text-600">À planifier</span>
</p:column>
<p:column headerText="Statut">
<p:tag value="En attente" severity="warning" />
</p:column>
<p:column headerText="Actions" style="width: 200px;">
<p:commandButton icon="pi pi-eye"
title="Voir détails"
styleClass="ui-button-rounded ui-button-text ui-button-secondary mr-2" />
<p:commandButton icon="pi pi-pencil"
title="Modifier"
styleClass="ui-button-rounded ui-button-text ui-button-secondary mr-2" />
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Message d'information -->
<div class="card">
<div class="flex align-items-center gap-3 p-3">
<i class="pi pi-info-circle text-blue-500 text-2xl"></i>
<div>
<h6 class="m-0">Fonctionnalité en développement</h6>
<p class="m-0 text-600">La gestion logistique complète des événements sera disponible prochainement.</p>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,120 @@
<!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:param name="page" value="#{evenementsBean}"/>
<ui:define name="title">Gestion des Participants - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-users text-green-500" />
<ui:param name="title" value="Gestion des Participants" />
<ui:param name="description" value="Gérer les participants et les inscriptions aux événements" />
<ui:define name="actions">
<h:form id="formActionsParticipants">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Retour" />
<ui:param name="icon" value="pi pi-arrow-left" />
<ui:param name="outcome" value="/pages/secure/evenement/gestion.xhtml" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{evenementsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Sélection d'événement -->
<div class="card">
<h:form id="formSelection">
<h5>Sélectionner un Événement</h5>
<div class="grid">
<div class="col-12 md:col-6">
<p:selectOneMenu value="#{evenementsBean.evenementSelectionne}"
styleClass="w-full"
filter="true"
filterMatchMode="contains"
placeholder="Sélectionner un événement...">
<f:selectItem itemLabel="Sélectionner un événement" itemValue="#{null}" />
<f:selectItems value="#{evenementsBean.tousLesEvenements}"
var="evt"
itemLabel="#{evt.titre} - #{evt.dateDebutFormatee}"
itemValue="#{evt}" />
<p:ajax event="change" update=":formParticipants" />
</p:selectOneMenu>
</div>
</div>
</h:form>
</div>
<!-- Liste des participants -->
<div class="card" rendered="#{evenementsBean.evenementSelectionne != null}">
<h:form id="formParticipants">
<h5>Participants - #{evenementsBean.evenementSelectionne.titre}</h5>
<div class="grid mb-3">
<div class="col-12 md:col-4">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{evenementsBean.evenementSelectionne.participantsInscrits}" />
<ui:param name="label" value="Inscrits" />
<ui:param name="icon" value="pi pi-user-plus" />
<ui:param name="bgColor" value="blue" />
</ui:include>
</div>
<div class="col-12 md:col-4">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{evenementsBean.evenementSelectionne.participantsPresents}" />
<ui:param name="label" value="Présents" />
<ui:param name="icon" value="pi pi-check-circle" />
<ui:param name="bgColor" value="green" />
</ui:include>
</div>
<div class="col-12 md:col-4">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{evenementsBean.evenementSelectionne.placesDisponibles}" />
<ui:param name="label" value="Places disponibles" />
<ui:param name="icon" value="pi pi-ticket" />
<ui:param name="bgColor" value="orange" />
</ui:include>
</div>
</div>
<div class="text-center p-4">
<i class="pi pi-info-circle text-4xl text-blue-500 mb-3"></i>
<h5>Gestion des Participants</h5>
<p class="text-600">La gestion détaillée des participants sera disponible prochainement</p>
<p class="text-600 mt-2">
Participants inscrits: <strong>#{evenementsBean.evenementSelectionne.participantsInscrits}</strong> /
Capacité: <strong>#{evenementsBean.evenementSelectionne.capaciteMax}</strong>
</p>
</div>
</h:form>
</div>
<!-- Message si aucun événement sélectionné -->
<div class="card" rendered="#{evenementsBean.evenementSelectionne == null}">
<div class="text-center p-4">
<i class="pi pi-info-circle text-4xl text-blue-500 mb-3"></i>
<h5>Sélectionnez un événement</h5>
<p class="text-600">Veuillez sélectionner un événement pour voir ses participants</p>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,255 @@
<!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:param name="page" value="#{evenementsBean}"/>
<ui:define name="title">Participation aux Événements - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-calendar-check text-purple-500" />
<ui:param name="title" value="Participation aux Événements" />
<ui:param name="description" value="Consultez et inscrivez-vous aux événements disponibles" />
<ui:define name="actions">
<h:form id="formActionsParticipation">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{evenementsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Filtres -->
<div class="card">
<h:form id="formFiltres">
<h5>Filtres</h5>
<div class="grid">
<div class="col-12 md:col-4">
<p:selectOneMenu value="#{evenementsBean.filtres.type}" styleClass="w-full">
<f:selectItem itemLabel="Tous les types" itemValue="" />
<f:selectItem itemLabel="Assemblée Générale" itemValue="ASSEMBLEE_GENERALE" />
<f:selectItem itemLabel="Formation" itemValue="FORMATION" />
<f:selectItem itemLabel="Activité Sociale" itemValue="ACTIVITE_SOCIALE" />
<f:selectItem itemLabel="Action Caritative" itemValue="ACTION_CARITATIVE" />
<p:ajax event="change" update=":formListe" />
</p:selectOneMenu>
</div>
<div class="col-12 md:col-4">
<p:selectOneMenu value="#{evenementsBean.filtres.statut}" styleClass="w-full">
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
<f:selectItem itemLabel="Planifié" itemValue="PLANIFIE" />
<f:selectItem itemLabel="Confirmé" itemValue="CONFIRME" />
<f:selectItem itemLabel="En cours" itemValue="EN_COURS" />
<p:ajax event="change" update=":formListe" />
</p:selectOneMenu>
</div>
<div class="col-12 md:col-4">
<div class="flex gap-2">
<p:commandButton value="Rechercher"
icon="pi pi-search"
action="#{evenementsBean.rechercher}"
update=":formListe"
styleClass="p-button-primary" />
<p:commandButton value="Réinitialiser"
icon="pi pi-filter-slash"
action="#{evenementsBean.reinitialiserFiltres}"
update="@form :formListe"
styleClass="p-button-outlined" />
</div>
</div>
</div>
</h:form>
</div>
<!-- Liste des événements disponibles -->
<div class="card">
<h:form id="formListe">
<h5>Événements Disponibles</h5>
<p:dataTable id="dtEvenements"
value="#{evenementsBean.evenementsFiltres}"
var="evenement"
paginator="true"
rows="10"
emptyMessage="Aucun événement disponible"
rowKey="#{evenement.id}">
<p:column headerText="Événement" style="width: 40%;">
<div class="flex align-items-center gap-2">
<i class="#{evenement.typeEvenementIcon} text-2xl text-#{evenement.typeEvenementSeverity}"></i>
<div>
<div class="font-semibold text-lg">#{evenement.titre}</div>
<div class="text-sm text-600">#{evenement.description}</div>
</div>
</div>
</p:column>
<p:column headerText="Date et Heure">
<div>
<div class="font-medium">#{evenement.dateDebutFormatee}</div>
<div class="text-sm text-600">
<i class="pi pi-clock"></i> #{evenement.heureDebutFormatee} - #{evenement.heureFinFormatee}
</div>
</div>
</p:column>
<p:column headerText="Lieu">
<div>
<div class="font-medium">#{evenement.lieu}</div>
<div class="text-sm text-600">#{evenement.ville}</div>
</div>
</p:column>
<p:column headerText="Places">
<div>
<div class="font-medium">#{evenement.participantsInscrits} / #{evenement.capaciteMax}</div>
<p:progressBar value="#{evenement.tauxRemplissage}"
showValue="true"
styleClass="mt-1" />
</div>
</p:column>
<p:column headerText="Statut">
<p:tag value="#{evenement.statutLibelle}"
severity="#{evenement.statutSeverity}"
icon="#{evenement.statutIcon}" />
</p:column>
<p:column headerText="Actions" style="width: 150px;">
<div class="flex gap-1">
<p:commandButton value="Voir détails"
icon="pi pi-eye"
styleClass="p-button-text p-button-sm"
action="#{evenementsBean.selectionnerEvenement(evenement)}"
update=":formDetails:dlgDetails"
oncomplete="PF('dlgDetails').show();" />
<p:commandButton value="S'inscrire"
icon="pi pi-check"
styleClass="p-button-success p-button-sm"
rendered="#{evenement.sontInscriptionsOuvertes()}"
action="#{evenementsBean.sinscrireEvenement(evenement)}"
update="@form"
onclick="return confirm('Confirmer votre inscription à cet événement ?');" />
<p:tag value="Complet"
severity="error"
rendered="#{evenement.isComplet()}" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Dialog Détails -->
<h:form id="formDetails">
<p:dialog id="dlgDetails" header="Détails de l'Événement"
widgetVar="dlgDetails"
modal="true"
resizable="false"
style="width: 90vw; max-width: 800px;">
<div class="grid" rendered="#{evenementsBean.evenementSelectionne != null}">
<div class="col-12">
<h3>#{evenementsBean.evenementSelectionne.titre}</h3>
<p class="text-600 mt-2">#{evenementsBean.evenementSelectionne.description}</p>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Type</label>
<p:tag value="#{evenementsBean.evenementSelectionne.typeEvenementLibelle}"
severity="#{evenementsBean.evenementSelectionne.typeEvenementSeverity}" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Statut</label>
<p:tag value="#{evenementsBean.evenementSelectionne.statutLibelle}"
severity="#{evenementsBean.evenementSelectionne.statutSeverity}" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Date de début</label>
<div>#{evenementsBean.evenementSelectionne.dateDebutFormatee}</div>
<div class="text-sm text-600">#{evenementsBean.evenementSelectionne.heureDebutFormatee}</div>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Date de fin</label>
<div>#{evenementsBean.evenementSelectionne.dateFinFormatee}</div>
<div class="text-sm text-600">#{evenementsBean.evenementSelectionne.heureFinFormatee}</div>
</div>
</div>
<div class="col-12">
<div class="field">
<label class="font-semibold">Lieu</label>
<div>#{evenementsBean.evenementSelectionne.adresseComplete}</div>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Participants</label>
<div>#{evenementsBean.evenementSelectionne.participantsInscrits} / #{evenementsBean.evenementSelectionne.capaciteMax}</div>
<p:progressBar value="#{evenementsBean.evenementSelectionne.tauxRemplissage}"
showValue="true" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<label class="font-semibold">Organisateur</label>
<div>#{evenementsBean.evenementSelectionne.organisateur}</div>
<div class="text-sm text-600">#{evenementsBean.evenementSelectionne.emailOrganisateur}</div>
<div class="text-sm text-600">#{evenementsBean.evenementSelectionne.telephoneOrganisateur}</div>
</div>
</div>
<div class="col-12" rendered="#{evenementsBean.evenementSelectionne.instructions != null}">
<div class="field">
<label class="font-semibold">Instructions</label>
<div class="surface-50 p-3 border-round">#{evenementsBean.evenementSelectionne.instructions}</div>
</div>
</div>
</div>
<f:facet name="footer">
<div class="flex gap-2">
<p:commandButton value="S'inscrire"
icon="pi pi-check"
rendered="#{evenementsBean.evenementSelectionne != null and evenementsBean.evenementSelectionne.sontInscriptionsOuvertes()}"
action="#{evenementsBean.sinscrireEvenement(evenementsBean.evenementSelectionne)}"
update="@form"
onclick="PF('dlgDetails').hide(); return confirm('Confirmer votre inscription ?');" />
<p:commandButton value="Fermer"
icon="pi pi-times"
onclick="PF('dlgDetails').hide();"
styleClass="p-button-secondary p-button-outlined" />
</div>
</f:facet>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,179 @@
<!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:param name="page" value="#{evenementsBean}"/>
<ui:define name="title">Planification des Événements - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-clock text-orange-500" />
<ui:param name="title" value="Planification des Événements" />
<ui:param name="description" value="Planifiez et organisez vos événements à l'avance" />
<ui:define name="actions">
<h:form id="formActionsPlanification">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouvelle planification" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="onclick" value="PF('dlgNouvellePlanification').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{evenementsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques -->
<div class="grid mb-3">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="Événements planifiés" />
<ui:param name="icon" value="pi pi-calendar-check" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="À venir (7 jours)" />
<ui:param name="icon" value="pi pi-clock" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="En attente validation" />
<ui:param name="icon" value="pi pi-hourglass" />
<ui:param name="bgColor" value="yellow" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="Taux de réalisation" />
<ui:param name="icon" value="pi pi-percentage" />
<ui:param name="bgColor" value="green" />
</ui:include>
</div>
<!-- Filtres et recherche (DRY/WOU: filter-bar) -->
<ui:decorate template="/templates/components/cards/filter-bar.xhtml">
<ui:param name="title" value="Filtres" />
<ui:param name="styleClass" value="mb-3" />
<ui:define name="filters">
<div class="col-12 md:col-4">
<div class="field">
<p:outputLabel for="searchPlanification" value="Rechercher" />
<span class="p-input-icon-left w-full">
<i class="pi pi-search"></i>
<p:inputText id="searchPlanification"
placeholder="Titre, description..."
styleClass="w-full">
<p:ajax event="keyup" delay="500"/>
</p:inputText>
</span>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtrePeriode" value="Période" />
<p:selectOneMenu id="filtrePeriode" styleClass="w-full">
<f:selectItem itemLabel="Toutes périodes" itemValue="" />
<f:selectItem itemLabel="Cette semaine" itemValue="SEMAINE" />
<f:selectItem itemLabel="Ce mois" itemValue="MOIS" />
<f:selectItem itemLabel="Ce trimestre" itemValue="TRIMESTRE" />
<f:selectItem itemLabel="Cette année" itemValue="ANNEE" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreStatut" value="Statut" />
<p:selectOneMenu id="filtreStatut" styleClass="w-full">
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
<f:selectItem itemLabel="Planifié" itemValue="PLANIFIE" />
<f:selectItem itemLabel="Confirmé" itemValue="CONFIRME" />
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE" />
</p:selectOneMenu>
</div>
</div>
</ui:define>
<ui:define name="actions">
<div class="col-12 md:col-2">
<div class="field">
<label class="invisible">Actions</label>
<p:commandButton value="Réinitialiser"
icon="pi pi-filter-slash"
styleClass="ui-button-secondary w-full" />
</div>
</div>
</ui:define>
</ui:decorate>
<!-- Liste des planifications -->
<div class="card">
<h:form id="formPlanifications">
<h5>Planifications</h5>
<p:dataTable id="dtPlanifications"
value="#{evenementsBean.evenementsFiltres}"
var="evenement"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50,100"
emptyMessage="Aucune planification trouvée"
styleClass="table-responsive">
<p:column headerText="Titre" sortBy="#{evenement.titre}">
<span class="font-semibold">#{evenement.titre}</span>
</p:column>
<p:column headerText="Date prévue">
<div>
<div class="font-medium">Date à définir</div>
<div class="text-sm text-600">Période: À planifier</div>
</div>
</p:column>
<p:column headerText="Statut">
<p:tag value="Planifié" severity="info" />
</p:column>
<p:column headerText="Priorité">
<p:tag value="Normale" severity="info" />
</p:column>
<p:column headerText="Actions" style="width: 200px;">
<p:commandButton icon="pi pi-pencil"
title="Modifier"
styleClass="ui-button-rounded ui-button-text ui-button-secondary mr-2" />
<p:commandButton icon="pi pi-trash"
title="Supprimer"
styleClass="ui-button-rounded ui-button-text ui-button-danger" />
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Message d'information -->
<div class="card">
<div class="flex align-items-center gap-3 p-3">
<i class="pi pi-info-circle text-blue-500 text-2xl"></i>
<div>
<h6 class="m-0">Fonctionnalité en développement</h6>
<p class="m-0 text-600">La planification avancée des événements sera disponible prochainement.</p>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,187 @@
<!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:param name="page" value="#{evenementsBean}"/>
<ui:define name="title">Réservations d'Événements - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-ticket text-cyan-500" />
<ui:param name="title" value="Réservations d'Événements" />
<ui:param name="description" value="Gérez les réservations et inscriptions aux événements" />
<ui:define name="actions">
<h:form id="formActionsReservations">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{evenementsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques -->
<div class="grid mb-3">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="Réservations totales" />
<ui:param name="icon" value="pi pi-ticket" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="En attente" />
<ui:param name="icon" value="pi pi-hourglass" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="Confirmées" />
<ui:param name="icon" value="pi pi-check-circle" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="0" />
<ui:param name="label" value="Annulées" />
<ui:param name="icon" value="pi pi-times-circle" />
<ui:param name="bgColor" value="red" />
</ui:include>
</div>
<!-- Filtres et recherche (DRY/WOU: filter-bar) -->
<ui:decorate template="/templates/components/cards/filter-bar.xhtml">
<ui:param name="title" value="Filtres" />
<ui:param name="styleClass" value="mb-3" />
<ui:define name="filters">
<div class="col-12 md:col-4">
<div class="field">
<p:outputLabel for="searchReservation" value="Rechercher" />
<span class="p-input-icon-left w-full">
<i class="pi pi-search"></i>
<p:inputText id="searchReservation"
placeholder="Membre, événement..."
styleClass="w-full">
<p:ajax event="keyup" delay="500"/>
</p:inputText>
</span>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreStatut" value="Statut" />
<p:selectOneMenu id="filtreStatut" styleClass="w-full">
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE" />
<f:selectItem itemLabel="Confirmée" itemValue="CONFIRMEE" />
<f:selectItem itemLabel="Annulée" itemValue="ANNULEE" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreEvenement" value="Événement" />
<p:selectOneMenu id="filtreEvenement" styleClass="w-full">
<f:selectItem itemLabel="Tous événements" itemValue="" />
</p:selectOneMenu>
</div>
</div>
</ui:define>
<ui:define name="actions">
<div class="col-12 md:col-2">
<div class="field">
<label class="invisible">Actions</label>
<p:commandButton value="Réinitialiser"
icon="pi pi-filter-slash"
styleClass="ui-button-secondary w-full" />
</div>
</div>
</ui:define>
</ui:decorate>
<!-- Liste des réservations -->
<div class="card">
<h:form id="formReservations">
<h5>Réservations</h5>
<p:dataTable id="dtReservations"
value="#{evenementsBean.evenementsFiltres}"
var="evenement"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50,100"
emptyMessage="Aucune réservation trouvée"
styleClass="table-responsive">
<p:column headerText="Membre">
<div>
<span class="font-semibold">Nom du membre</span>
<br/>
<span class="text-sm text-600">email@example.com</span>
</div>
</p:column>
<p:column headerText="Événement" sortBy="#{evenement.titre}">
<span class="font-semibold">#{evenement.titre}</span>
</p:column>
<p:column headerText="Date réservation">
<span>À définir</span>
</p:column>
<p:column headerText="Nombre places">
<span class="font-medium">1</span>
</p:column>
<p:column headerText="Montant">
<span class="font-medium">0 XOF</span>
</p:column>
<p:column headerText="Statut">
<p:tag value="En attente" severity="warning" />
</p:column>
<p:column headerText="Actions" style="width: 250px;">
<p:commandButton icon="pi pi-check"
title="Confirmer"
styleClass="ui-button-rounded ui-button-text ui-button-success mr-2" />
<p:commandButton icon="pi pi-times"
title="Annuler"
styleClass="ui-button-rounded ui-button-text ui-button-danger mr-2" />
<p:commandButton icon="pi pi-eye"
title="Voir détails"
styleClass="ui-button-rounded ui-button-text ui-button-secondary" />
</p:column>
</p:dataTable>
</h:form>
</div>
<!-- Message d'information -->
<div class="card">
<div class="flex align-items-center gap-3 p-3">
<i class="pi pi-info-circle text-blue-500 text-2xl"></i>
<div>
<h6 class="m-0">Fonctionnalité en développement</h6>
<p class="m-0 text-600">Le système de réservations complet sera disponible prochainement.</p>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,198 @@
<!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">
<f:metadata>
<f:viewParam name="id" value="#{membreCotisationBean.membreId}"/>
<f:event type="preRenderView" listener="#{membreCotisationBean.init}"/>
</f:metadata>
<ui:param name="page" value="#{membreCotisationBean}"/>
<ui:define name="title">Cotisations du Membre - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formCotisations">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div>
<h3 class="m-0">
<i class="pi pi-dollar text-green-500 mr-2"></i>
Cotisations du Membre
</h3>
<p class="text-600 m-0 mt-2">
Membre: #{membreCotisationBean.numeroMembre} •
Statut: #{membreCotisationBean.statutCotisations}
</p>
</div>
<div class="flex gap-2 mt-2 md:mt-0">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Retour au profil"/>
<ui:param name="icon" value="pi pi-arrow-left"/>
<ui:param name="outcome" value="membreProfilPage"/>
</ui:include>
</div>
</div>
</div>
<!-- Résumé cotisations -->
<div class="grid mb-3">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Payées" />
<ui:param name="value" value="#{membreCotisationBean.cotisationsPayees}" />
<ui:param name="icon" value="pi-check" />
<ui:param name="iconColor" value="green-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
<ui:param name="colSize" value="col-12 md:col-3" />
</ui:include>
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="En Attente" />
<ui:param name="value" value="#{membreCotisationBean.cotisationsEnAttente}" />
<ui:param name="icon" value="pi-clock" />
<ui:param name="iconColor" value="orange-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
<ui:param name="colSize" value="col-12 md:col-3" />
</ui:include>
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Montant Dû" />
<ui:param name="value" value="#{membreCotisationBean.montantDu}" />
<ui:param name="icon" value="pi-exclamation-triangle" />
<ui:param name="iconColor" value="red-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
<ui:param name="colSize" value="col-12 md:col-3" />
</ui:include>
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Total Versé" />
<ui:param name="value" value="#{membreCotisationBean.totalVerse}" />
<ui:param name="icon" value="pi-dollar" />
<ui:param name="iconColor" value="blue-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
<ui:param name="colSize" value="col-12 md:col-3" />
</ui:include>
</div>
<!-- Liste des cotisations -->
<div class="card">
<h5 class="mb-3">Historique des Cotisations</h5>
<!-- Filtres -->
<p:toolbar>
<p:toolbarGroup>
<div class="flex align-items-center gap-2">
<p:selectOneMenu value="#{membreCotisationBean.anneeFilter}">
<f:selectItem itemLabel="Cette année" itemValue="2024"/>
<f:selectItem itemLabel="2023" itemValue="2023"/>
<f:selectItem itemLabel="2022" itemValue="2022"/>
<f:selectItem itemLabel="Toutes" itemValue=""/>
<p:ajax event="change" update="dtCotisations"/>
</p:selectOneMenu>
<p:selectOneMenu value="#{membreCotisationBean.statutFilter}">
<f:selectItem itemLabel="Tous les statuts" itemValue=""/>
<f:selectItem itemLabel="Payées" itemValue="PAYE"/>
<f:selectItem itemLabel="En attente" itemValue="EN_ATTENTE"/>
<f:selectItem itemLabel="En retard" itemValue="EN_RETARD"/>
<p:ajax event="change" update="dtCotisations"/>
</p:selectOneMenu>
</div>
</p:toolbarGroup>
<p:toolbarGroup align="right">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="" />
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{membreCotisationBean.actualiser}" />
<ui:param name="update" value=":formCotisations:dtCotisations" />
<ui:param name="title" value="Actualiser" />
<ui:param name="outlined" value="true" />
</ui:include>
</p:toolbarGroup>
</p:toolbar>
<!-- DataTable -->
<p:dataTable id="dtCotisations"
var="cotisation"
value="#{membreCotisationBean.cotisations}"
paginator="true"
rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,25"
currentPageReportTemplate="Affichage {startRecord}-{endRecord} sur {totalRecords}"
styleClass="mt-3">
<p:column headerText="Référence" sortBy="#{cotisation.reference}" style="width:120px">
<h:outputText value="#{cotisation.reference}" styleClass="font-mono font-bold"/>
</p:column>
<p:column headerText="Période" sortBy="#{cotisation.periode}">
<div>
<div class="font-medium">#{cotisation.libelle}</div>
<small class="text-600">#{cotisation.periode}</small>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{cotisation.type}" style="width:140px">
<p:tag value="#{cotisation.type}"
severity="#{cotisation.typeSeverity}"
icon="pi #{cotisation.typeIcon}"/>
</p:column>
<p:column headerText="Montant" sortBy="#{cotisation.montant}" style="width:120px">
<div class="text-center">
<div class="font-bold text-green-500">#{cotisation.montant}</div>
<small class="text-600">FCFA</small>
</div>
</p:column>
<p:column headerText="Statut" sortBy="#{cotisation.statut}" style="width:120px">
<p:tag value="#{cotisation.statut}"
severity="#{cotisation.statutSeverity}"
icon="pi #{cotisation.statutIcon}"/>
</p:column>
<p:column headerText="Échéance" sortBy="#{cotisation.dateEcheance}" style="width:120px">
<div>
<div class="font-medium">#{cotisation.dateEcheance}</div>
<small class="#{cotisation.retardColor}">#{cotisation.statutEcheance}</small>
</div>
</p:column>
<p:column headerText="Date paiement" sortBy="#{cotisation.datePaiement}" style="width:120px">
<h:outputText value="#{cotisation.datePaiement}" rendered="#{cotisation.datePaiement != null}">
<f:convertDateTime pattern="dd/MM/yyyy" type="localDate"/>
</h:outputText>
<span class="text-400" rendered="#{cotisation.datePaiement == null}">Non payée</span>
</p:column>
<p:column headerText="Actions" style="width:150px">
<div class="flex gap-1">
<p:commandButton icon="pi pi-credit-card"
styleClass="ui-button-rounded ui-button-text ui-button-success"
action="#{membreCotisationBean.payerCotisation(cotisation)}"
title="Payer"
rendered="#{cotisation.statut != 'PAYE' and cotisation.statut != 'PAYEE'}"/>
<p:commandButton icon="pi pi-file-pdf"
styleClass="ui-button-rounded ui-button-text ui-button-info"
action="#{membreCotisationBean.telechargerRecu(cotisation)}"
title="Télécharger reçu"
rendered="#{cotisation.statut == 'PAYE' or cotisation.statut == 'PAYEE'}"/>
</div>
</p:column>
</p:dataTable>
</div>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,310 @@
<!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:param name="page" value="#{membreExportBean}"/>
<ui:define name="title">Export des Membres - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-download text-blue-500" />
<ui:param name="title" value="Export des Membres" />
<ui:param name="description" value="Exportez les données des membres dans différents formats" />
<ui:define name="actions">
<h:form id="formActionsEntete">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Retour" />
<ui:param name="icon" value="pi pi-arrow-left" />
<ui:param name="outcome" value="/pages/secure/membre/liste" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques -->
<div class="grid mb-3">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Total Membres" />
<ui:param name="value" value="#{membreExportBean.totalMembres}" />
<ui:param name="icon" value="pi-users" />
<ui:param name="iconColor" value="blue-600" />
<ui:param name="colSize" value="col-12 md:col-4" />
</ui:include>
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Membres Actifs" />
<ui:param name="value" value="#{membreExportBean.membresActifs}" />
<ui:param name="icon" value="pi-check-circle" />
<ui:param name="iconColor" value="green-600" />
<ui:param name="colSize" value="col-12 md:col-4" />
</ui:include>
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Membres Inactifs" />
<ui:param name="value" value="#{membreExportBean.membresInactifs}" />
<ui:param name="icon" value="pi-times-circle" />
<ui:param name="iconColor" value="orange-600" />
<ui:param name="colSize" value="col-12 md:col-4" />
</ui:include>
</div>
<!-- Formulaire d'export -->
<div class="card">
<h:form id="formExport">
<h5 class="mb-4">Configuration de l'export</h5>
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="formatExport" value="Format d'export *" />
<p:selectOneMenu id="formatExport" value="#{membreExportBean.formatExport}" required="true" styleClass="w-full">
<f:selectItem itemLabel="Excel (.xlsx)" itemValue="EXCEL" />
<f:selectItem itemLabel="CSV (.csv)" itemValue="CSV" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="scopeExport" value="Portée de l'export *" />
<p:selectOneMenu id="scopeExport" value="#{membreExportBean.scopeExport}" required="true" styleClass="w-full">
<f:selectItem itemLabel="Tous les membres" itemValue="TOUS" />
<f:selectItem itemLabel="Membres actifs uniquement" itemValue="ACTIFS" />
<f:selectItem itemLabel="Membres inactifs uniquement" itemValue="INACTIFS" />
<f:selectItem itemLabel="Membres sélectionnés" itemValue="SELECTION" />
<p:ajax event="change" listener="#{membreExportBean.actualiserCompteur}" update=":formExport" />
</p:selectOneMenu>
</div>
</div>
</div>
<ui:decorate template="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Colonnes à exporter" />
<ui:define name="content">
<div class="field">
<p:outputLabel for="colonnesExport" value="Sélectionnez les colonnes à inclure *" />
<p:selectCheckboxMenu id="colonnesExport"
value="#{membreExportBean.colonnesExport}"
multiple="true"
styleClass="w-full">
<f:selectItem itemLabel="Informations personnelles (Nom, Prénom, Date naissance, Genre)" itemValue="PERSO" />
<f:selectItem itemLabel="Coordonnées (Email, Téléphone, Adresse)" itemValue="CONTACT" />
<f:selectItem itemLabel="Informations adhésion (Date adhésion, Type membre, Statut)" itemValue="ADHESION" />
<f:selectItem itemLabel="Cotisations (Statut cotisations, Dernier paiement)" itemValue="COTISATIONS" />
<f:selectItem itemLabel="Participation événements (Taux participation, Événements)" itemValue="EVENEMENTS" />
<f:selectItem itemLabel="Organisation (Entité, Ville)" itemValue="ORGANISATION" />
<f:selectItem itemLabel="Famille (Membres de famille déclarés)" itemValue="FAMILLE" />
</p:selectCheckboxMenu>
<small class="text-600">Sélectionnez au moins une catégorie de colonnes</small>
</div>
</ui:define>
</ui:decorate>
<ui:decorate template="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Filtres optionnels" />
<ui:define name="content">
<div class="grid">
<div class="col-12 md:col-4">
<div class="field">
<p:outputLabel for="statutFilter" value="Statut" />
<p:selectOneMenu id="statutFilter" value="#{membreExportBean.statutFilter}" styleClass="w-full">
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
<f:selectItem itemLabel="Actif" itemValue="ACTIF" />
<f:selectItem itemLabel="Inactif" itemValue="INACTIF" />
<f:selectItem itemLabel="Suspendu" itemValue="SUSPENDU" />
<f:selectItem itemLabel="Radié" itemValue="RADIE" />
<p:ajax event="change" listener="#{membreExportBean.actualiserCompteur}" update=":formExport" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-4">
<div class="field">
<p:outputLabel for="typeFilter" value="Type de membre" />
<p:selectOneMenu id="typeFilter" value="#{membreExportBean.typeFilter}" styleClass="w-full">
<f:selectItem itemLabel="Tous les types" itemValue="" />
<f:selectItem itemLabel="Actif" itemValue="ACTIF" />
<f:selectItem itemLabel="Associé" itemValue="ASSOCIE" />
<f:selectItem itemLabel="Bienfaiteur" itemValue="BIENFAITEUR" />
<f:selectItem itemLabel="Honoraire" itemValue="HONORAIRE" />
<p:ajax event="change" listener="#{membreExportBean.actualiserCompteur}" update=":formExport" />
</p:selectOneMenu>
</div>
</div>
<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">
<f:selectItem itemLabel="Toutes les organisations" itemValue="" />
<f:selectItems value="#{membreExportBean.organisationsDisponibles}"
var="org"
itemLabel="#{org.nom} (#{org.ville})"
itemValue="#{org.id}" />
<p:ajax event="change" listener="#{membreExportBean.actualiserCompteur}" update=":formExport" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="dateAdhesionDebut" value="Adhésion après le" />
<p:calendar id="dateAdhesionDebut"
value="#{membreExportBean.dateAdhesionDebut}"
showIcon="true"
navigator="true"
locale="fr"
pattern="dd/MM/yyyy"
styleClass="w-full">
<p:ajax event="dateSelect" listener="#{membreExportBean.actualiserCompteur}" update=":formExport" />
</p:calendar>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="dateAdhesionFin" value="Adhésion avant le" />
<p:calendar id="dateAdhesionFin"
value="#{membreExportBean.dateAdhesionFin}"
showIcon="true"
navigator="true"
locale="fr"
pattern="dd/MM/yyyy"
styleClass="w-full">
<p:ajax event="dateSelect" listener="#{membreExportBean.actualiserCompteur}" update=":formExport" />
</p:calendar>
</div>
</div>
</div>
</ui:define>
</ui:decorate>
<!-- Options d'export -->
<ui:decorate template="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Options d'export" />
<ui:define name="content">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<p:selectBooleanCheckbox id="inclureHeaders" value="#{membreExportBean.inclureHeaders}" />
<p:outputLabel for="inclureHeaders" value="Inclure les en-têtes de colonnes" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:selectBooleanCheckbox id="formaterDates" value="#{membreExportBean.formaterDates}" />
<p:outputLabel for="formaterDates" value="Formater les dates (DD/MM/YYYY)" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:selectBooleanCheckbox id="inclureStatistiques" value="#{membreExportBean.inclureStatistiques}" />
<p:outputLabel for="inclureStatistiques" value="Inclure un onglet statistiques (Excel uniquement)" />
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:selectBooleanCheckbox id="chiffrerDonnees" value="#{membreExportBean.chiffrerDonnees}" />
<p:outputLabel for="chiffrerDonnees" value="Chiffrer le fichier exporté" />
<small class="text-600 block mt-1">Le fichier sera protégé par un mot de passe (généré automatiquement ou personnalisé ci-dessous)</small>
</div>
</div>
<div class="col-12" rendered="#{membreExportBean.chiffrerDonnees}">
<div class="field">
<p:outputLabel for="motDePasseExport" value="Mot de passe personnalisé (optionnel)" />
<p:password id="motDePasseExport" value="#{membreExportBean.motDePasseExport}"
placeholder="Laisser vide pour générer automatiquement"
styleClass="w-full" />
<small class="text-600 block mt-1">Si vide, un mot de passe aléatoire sera généré et affiché après l'export</small>
</div>
</div>
</div>
</ui:define>
</ui:decorate>
<!-- Aperçu du nombre de membres à exporter -->
<div class="surface-50 p-3 border-round mb-4">
<div class="flex align-items-center justify-content-between">
<div>
<div class="font-medium mb-1">Nombre de membres à exporter :</div>
<div class="text-600">#{membreExportBean.nombreMembresAExporter} membre(s) correspond(ent) aux critères sélectionnés</div>
</div>
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Actualiser le compteur" />
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{membreExportBean.actualiserCompteur}" />
<ui:param name="update" value=":formExport" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="ui-button-sm" />
</ui:include>
</div>
</div>
<!-- Actions -->
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Générer l'export" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="action" value="#{membreExportBean.exporterMembres}" />
<ui:param name="update" value="none" />
<ui:param name="disabled" value="#{membreExportBean.colonnesExport == null or membreExportBean.colonnesExport.isEmpty() or membreExportBean.nombreMembresAExporter == 0}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Réinitialiser" />
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{membreExportBean.reinitialiser}" />
<ui:param name="update" value=":formExport" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</h:form>
</div>
<!-- Historique des exports -->
<div class="card mt-3">
<h5 class="mb-3">Historique des exports</h5>
<p:dataTable value="#{membreExportBean.historiqueExports}" var="export"
styleClass="p-datatable-sm"
emptyMessage="Aucun export effectué">
<p:column headerText="Date">
<h:outputText value="#{export.date}">
<f:convertDateTime pattern="dd/MM/yyyy HH:mm" type="localDateTime" />
</h:outputText>
</p:column>
<p:column headerText="Format">
<p:tag value="#{export.format}" severity="info" />
</p:column>
<p:column headerText="Nombre de membres">
<h:outputText value="#{export.nombreMembres}" />
</p:column>
<p:column headerText="Taille">
<h:outputText value="#{export.taille}" />
</p:column>
<p:column headerText="Actions">
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="action" value="#{membreExportBean.telechargerExport(export)}" />
<ui:param name="update" value="none" />
<ui:param name="title" value="Télécharger" />
<ui:param name="styleClass" value="ui-button-sm" />
</ui:include>
</p:column>
</p:dataTable>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,243 @@
<!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:param name="page" value="#{membreImportBean}"/>
<ui:define name="title">Import en Masse des Membres - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-upload text-green-500" />
<ui:param name="title" value="Import en Masse des Membres" />
<ui:param name="description" value="Importez plusieurs membres à la fois depuis un fichier Excel" />
<ui:define name="actions">
<h:form id="formActionsEntete">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Retour" />
<ui:param name="icon" value="pi pi-arrow-left" />
<ui:param name="outcome" value="/pages/secure/membre/liste" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Instructions -->
<div class="card mb-3">
<div class="flex align-items-start">
<i class="pi pi-info-circle text-blue-500 text-2xl mr-3"></i>
<div class="flex-1">
<h5 class="mt-0 mb-2">Instructions d'import</h5>
<p class="text-600 mb-3">
Téléchargez le modèle Excel, remplissez-le avec les données des membres, puis importez-le ici.
</p>
<div class="grid">
<div class="col-12 md:col-6">
<h6 class="mb-2">Format du fichier :</h6>
<ul class="text-600 text-sm m-0 pl-3">
<li>Format Excel (.xlsx) ou CSV (.csv)</li>
<li>Maximum 1000 lignes par import</li>
<li>Taille maximale : 10 MB</li>
</ul>
</div>
<div class="col-12 md:col-6">
<h6 class="mb-2">Colonnes requises :</h6>
<ul class="text-600 text-sm m-0 pl-3">
<li>Nom, Prénom (obligatoires)</li>
<li>Email, Téléphone (obligatoires)</li>
<li>Date de naissance, Adresse</li>
<li>Profession, Type membre</li>
</ul>
</div>
</div>
</div>
</div>
</div>
<!-- Formulaire d'import -->
<div class="card">
<h:form id="formImport" enctype="multipart/form-data">
<h5 class="mb-4">Fichier à importer</h5>
<div class="grid">
<div class="col-12 md:col-8">
<div class="field">
<p:outputLabel for="fichierImport" value="Fichier Excel/CSV *" />
<p:fileUpload id="fichierImport"
mode="advanced"
dragDropSupport="true"
skinSimple="false"
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel,text/csv"
fileLimit="1"
sizeLimit="10485760"
uploadLabel="Importer"
cancelLabel="Annuler"
chooseLabel="Sélectionner le fichier"
invalidFileMessage="Type de fichier non supporté"
fileLimitMessage="Un seul fichier autorisé"
invalidSizeMessage="Taille de fichier trop importante (max 10MB)"
fileUploadListener="#{membreImportBean.handleFileUpload}"
update=":formImport"
styleClass="w-full" />
<small class="text-600">Formats acceptés : .xlsx, .xls, .csv - Maximum 10 MB</small>
</div>
</div>
<div class="col-12 md:col-4">
<div class="field">
<p:outputLabel />
<div class="flex flex-column gap-2">
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Télécharger modèle" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="action" value="#{membreImportBean.telechargerModele}" />
<ui:param name="update" value="none" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full" />
</ui:include>
</div>
</div>
</div>
</div>
<ui:decorate template="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Options d'import" />
<ui:define name="content">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<p:selectBooleanCheckbox id="mettreAJourExistants" value="#{membreImportBean.mettreAJourExistants}" />
<p:outputLabel for="mettreAJourExistants" value="Mettre à jour les membres existants" />
<small class="text-600 block mt-1">Si coché, les membres existants (même email) seront mis à jour</small>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:selectBooleanCheckbox id="ignorerErreurs" value="#{membreImportBean.ignorerErreurs}" />
<p:outputLabel for="ignorerErreurs" value="Ignorer les lignes en erreur" />
<small class="text-600 block mt-1">Continuer l'import même si certaines lignes contiennent des erreurs</small>
</div>
</div>
<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">
<f:selectItem itemLabel="Sélectionner une organisation..." itemValue="" />
<f:selectItems value="#{membreImportBean.organisationsDisponibles}"
var="org"
itemLabel="#{org.nom} (#{org.ville})"
itemValue="#{org.id}" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="typeMembreImport" value="Type de membre par défaut" />
<p:selectOneMenu id="typeMembreImport" value="#{membreImportBean.typeMembreDefaut}" styleClass="w-full">
<f:selectItem itemLabel="Sélectionner..." itemValue="" />
<f:selectItem itemLabel="Actif" itemValue="ACTIF" />
<f:selectItem itemLabel="Associé" itemValue="ASSOCIE" />
<f:selectItem itemLabel="Bienfaiteur" itemValue="BIENFAITEUR" />
<f:selectItem itemLabel="Honoraire" itemValue="HONORAIRE" />
</p:selectOneMenu>
</div>
</div>
</div>
</ui:define>
</ui:decorate>
<!-- Résultats de l'import -->
<div class="mt-4" rendered="#{membreImportBean.resultatImport != null}">
<ui:decorate template="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Résultat de l'import" />
<ui:define name="content">
<div class="grid">
<div class="col-12 md:col-3">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Total traité" />
<ui:param name="value" value="#{membreImportBean.resultatImport.totalTraite}" />
<ui:param name="icon" value="pi-file" />
<ui:param name="iconColor" value="blue-600" />
<ui:param name="colSize" value="col-12" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Réussis" />
<ui:param name="value" value="#{membreImportBean.resultatImport.reussis}" />
<ui:param name="icon" value="pi-check" />
<ui:param name="iconColor" value="green-600" />
<ui:param name="colSize" value="col-12" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Échecs" />
<ui:param name="value" value="#{membreImportBean.resultatImport.echecs}" />
<ui:param name="icon" value="pi-times" />
<ui:param name="iconColor" value="red-600" />
<ui:param name="colSize" value="col-12" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Ignorés" />
<ui:param name="value" value="#{membreImportBean.resultatImport.ignores}" />
<ui:param name="icon" value="pi-eye-slash" />
<ui:param name="iconColor" value="orange-600" />
<ui:param name="colSize" value="col-12" />
</ui:include>
</div>
</div>
<div class="mt-3" rendered="#{not empty membreImportBean.resultatImport.erreurs}">
<h6 class="mb-2">Détails des erreurs :</h6>
<div class="surface-50 p-3 border-round">
<ui:repeat value="#{membreImportBean.resultatImport.erreurs}" var="erreur">
<div class="mb-2">
<span class="font-medium">Ligne #{erreur.ligne}:</span>
<span class="text-red-500 ml-2">#{erreur.message}</span>
</div>
</ui:repeat>
</div>
</div>
</ui:define>
</ui:decorate>
</div>
<!-- Actions -->
<div class="flex gap-2 mt-4">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Lancer l'import" />
<ui:param name="icon" value="pi pi-upload" />
<ui:param name="action" value="#{membreImportBean.importerMembres}" />
<ui:param name="update" value=":formImport" />
<ui:param name="disabled" value="#{membreImportBean.fichierImport == null}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Réinitialiser" />
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{membreImportBean.reinitialiser}" />
<ui:param name="update" value=":formImport" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</h:form>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,759 @@
<!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:param name="page" value="#{membreInscriptionBean}"/>
<ui:define name="title">Inscription Membre - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-user-plus text-primary" />
<ui:param name="title" value="Inscription Nouveau Membre" />
<ui:param name="description" value="Formulaire complet d'inscription avec photo et documents" />
<ui:define name="actions">
<div>
<div class="text-900 font-medium">Numéro: #{membreInscriptionBean.numeroGenere}</div>
<small class="text-600">Généré automatiquement</small>
</div>
</ui:define>
</ui:include>
<h:form>
<p:messages id="messages" showDetail="true" closable="true" globalOnly="false" />
<div class="grid">
<div class="col-12 md:col-6">
<ui:decorate template="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Informations personnelles" />
<ui:param name="fluid" value="true" />
<ui:define name="content">
<!-- Section photo intégrée -->
<div class="text-center mb-4 pb-3" style="border-bottom: 1px solid var(--surface-border);">
<div class="mb-3 relative">
<div id="photoContainer" style="width: 120px; height: 120px; margin: 0 auto; position: relative; overflow: hidden; border-radius: 50%; border: 3px solid var(--surface-border); background: #f8f9fa;">
<img id="photoPreview"
alt="Photo du membre"
style="width: auto; height: 120px; min-width: 120px; object-fit: cover; display: none; position: absolute; cursor: move; user-select: none;"
draggable="false" />
<div id="photoPlaceholder"
style="width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; position: absolute; top: 0; left: 0;">
<i class="pi pi-camera" style="font-size: 2rem; color: #6c757d;"></i>
</div>
<div id="photoOverlay"
style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.1); display: none; pointer-events: none; border-radius: 50%;">
<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-size: 0.75rem; text-align: center;">
<i class="pi pi-arrows-alt"></i><br/>
<small>Glisser pour positionner<br/>Molette pour zoomer</small>
</div>
</div>
</div>
</div>
<div class="flex align-items-center justify-content-center gap-2">
<input type="file"
id="photoInput"
accept="image/*"
style="position: absolute; left: -9999px; opacity: 0;" />
<h:inputHidden id="photoCadree" value="#{membreInscriptionBean.photoBase64}" />
<label for="photoInput"
class="ui-button ui-button-outlined ui-button-secondary"
style="cursor: pointer; display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; min-height: 2.5rem; padding: 0.75rem 1rem;">
<i class="pi pi-camera"></i>
<span>Choisir une photo</span>
</label>
<button type="button"
id="removePhotoBtn"
class="ui-button ui-button-outlined ui-button-danger"
onclick="removePhoto()"
style="display: none; min-height: 2.5rem; padding: 0.75rem 1rem;">
<i class="pi pi-trash"></i>
<span>Supprimer</span>
</button>
</div>
<small class="text-600">JPG, PNG ou GIF - Maximum 2MB</small>
</div>
<!-- Champs d'informations personnelles -->
<div class="field">
<p:outputLabel for="prenom" value="Prénom" />
<p:inputText id="prenom" value="#{membreInscriptionBean.prenom}" required="true"
requiredMessage="Le prénom est obligatoire" styleClass="w-full" />
<p:message for="prenom" />
</div>
<div class="field">
<p:outputLabel for="nom" value="Nom" />
<p:inputText id="nom" value="#{membreInscriptionBean.nom}" required="true"
requiredMessage="Le nom est obligatoire" styleClass="w-full" />
<p:message for="nom" />
</div>
<div class="field">
<p:outputLabel for="dateNaissance" value="Date de naissance" />
<p:calendar id="dateNaissance" value="#{membreInscriptionBean.dateNaissance}" required="true"
pattern="dd/MM/yyyy" showIcon="true" yearNavigator="true" yearRange="1920:2030"
monthNavigator="true" requiredMessage="La date de naissance est obligatoire"
styleClass="w-full" />
<p:message for="dateNaissance" />
</div>
<div class="field">
<p:outputLabel for="lieuNaissance" value="Lieu de naissance" />
<p:inputText id="lieuNaissance" value="#{membreInscriptionBean.lieuNaissance}" styleClass="w-full" />
</div>
<div class="field">
<p:outputLabel for="sexe" value="Sexe" />
<p:selectOneMenu id="sexe" value="#{membreInscriptionBean.sexe}" required="true" styleClass="w-full">
<f:selectItem itemLabel="Sélectionner..." itemValue="" noSelectionOption="true" />
<f:selectItems value="#{membreInscriptionBean.sexeOptions}" />
</p:selectOneMenu>
</div>
<div class="field">
<p:outputLabel for="nationalite" value="Nationalité" />
<p:inputText id="nationalite" value="#{membreInscriptionBean.nationalite}" styleClass="w-full" />
</div>
<div class="field">
<p:outputLabel for="situationMatrimoniale" value="Situation matrimoniale" />
<p:selectOneMenu id="situationMatrimoniale" value="#{membreInscriptionBean.situationMatrimoniale}" styleClass="w-full">
<f:selectItem itemLabel="Sélectionner..." itemValue="" noSelectionOption="true" />
<f:selectItems value="#{membreInscriptionBean.situationMatrimonialeOptions}" />
</p:selectOneMenu>
</div>
<div class="field">
<p:outputLabel for="profession" value="Profession" />
<p:inputText id="profession" value="#{membreInscriptionBean.profession}" styleClass="w-full" />
</div>
<div class="field">
<p:outputLabel for="employeur" value="Employeur / Entreprise" />
<p:inputText id="employeur" value="#{membreInscriptionBean.employeur}" styleClass="w-full" />
</div>
</ui:define>
</ui:decorate>
<ui:decorate template="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Contact d'urgence" />
<ui:param name="fluid" value="true" />
<ui:define name="content">
<div class="field">
<p:outputLabel for="contactUrgenceNom" value="Nom complet" />
<p:inputText id="contactUrgenceNom" value="#{membreInscriptionBean.contactUrgenceNom}"
required="true" requiredMessage="Le nom du contact d'urgence est obligatoire"
styleClass="w-full" />
<p:message for="contactUrgenceNom" />
</div>
<div class="field">
<p:outputLabel for="contactUrgenceTelephone" value="Téléphone" />
<p:inputText id="contactUrgenceTelephone" value="#{membreInscriptionBean.contactUrgenceTelephone}"
required="true" requiredMessage="Le téléphone du contact d'urgence est obligatoire"
styleClass="w-full" />
<p:message for="contactUrgenceTelephone" />
</div>
<div class="field">
<p:outputLabel for="contactUrgenceLien" value="Lien de parenté" />
<p:selectOneMenu id="contactUrgenceLien" value="#{membreInscriptionBean.contactUrgenceLien}" required="true" styleClass="w-full">
<f:selectItem itemLabel="Sélectionner..." itemValue="" noSelectionOption="true" />
<f:selectItems value="#{membreInscriptionBean.contactUrgenceLienOptions}" />
</p:selectOneMenu>
</div>
</ui:define>
</ui:decorate>
<ui:decorate template="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Documents justificatifs" />
<ui:define name="content">
<p:fileUpload listener="#{membreInscriptionBean.handleFileUpload}"
mode="advanced"
dragDropSupport="true"
multiple="true"
update="messages documentsListPanel"
sizeLimit="5000000"
fileLimit="5"
allowTypes="/(\.|\/)(pdf|doc|docx|jpg|jpeg|png)$/"
uploadLabel="Télécharger"
cancelLabel="Annuler"
chooseLabel="Sélectionner les fichiers"
invalidFileMessage="Type de fichier non supporté"
fileLimitMessage="Nombre maximum de fichiers dépassé"
invalidSizeMessage="Taille de fichier trop importante"
style="width:100%" />
<h:panelGroup id="documentsListPanel" layout="block" styleClass="mt-3">
<h6 class="mb-2" rendered="#{not empty membreInscriptionBean.documentsJoints}">Fichiers ajoutés:</h6>
<ui:repeat value="#{membreInscriptionBean.documentsJoints}" var="document">
<div class="flex align-items-center justify-content-between p-2 border-round mb-2"
style="background: var(--surface-50);">
<div class="flex align-items-center">
<i class="pi pi-file text-blue-500 mr-2"></i>
<span class="text-900">#{document}</span>
</div>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-times" />
<ui:param name="action" value="#{membreInscriptionBean.supprimerDocument(document)}" />
<ui:param name="update" value="documentsListPanel" />
<ui:param name="title" value="Supprimer le fichier" />
<ui:param name="severity" value="danger" />
<ui:param name="styleClass" value="ui-button-sm" />
</ui:include>
</div>
</ui:repeat>
</h:panelGroup>
<small class="text-600">Formats acceptés: PDF, DOC, DOCX, JPG, PNG - Maximum 5 fichiers de 5MB chacun</small>
</ui:define>
</ui:decorate>
</div>
<div class="col-12 md:col-6">
<ui:decorate template="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Coordonnées" />
<ui:param name="fluid" value="true" />
<ui:define name="content">
<div class="field">
<p:outputLabel for="adresse" value="Adresse complète" />
<p:inputTextarea id="adresse" value="#{membreInscriptionBean.adresse}" rows="4"
required="true" requiredMessage="L'adresse est obligatoire"
styleClass="w-full" />
<p:message for="adresse" />
</div>
<div class="formgrid grid">
<div class="field col">
<p:outputLabel for="ville" value="Ville" />
<p:inputText id="ville" value="#{membreInscriptionBean.ville}" required="true"
requiredMessage="La ville est obligatoire" styleClass="w-full" />
<p:message for="ville" />
</div>
<div class="field col">
<p:outputLabel for="codePostal" value="Code postal" />
<p:inputText id="codePostal" value="#{membreInscriptionBean.codePostal}" styleClass="w-full" />
</div>
</div>
<div class="field">
<p:outputLabel for="pays" value="Pays" />
<p:inputText id="pays" value="#{membreInscriptionBean.pays}" styleClass="w-full" />
</div>
<div class="field">
<p:outputLabel for="email" value="Email" />
<p:inputText id="email" value="#{membreInscriptionBean.email}" required="true" styleClass="w-full">
<f:validateRegex pattern="[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}" />
</p:inputText>
</div>
<div class="formgrid grid">
<div class="field col">
<p:outputLabel for="telephone" value="Téléphone fixe" />
<p:inputText id="telephone" value="#{membreInscriptionBean.telephone}" styleClass="w-full" />
</div>
<div class="field col">
<p:outputLabel for="telephoneMobile" value="Téléphone mobile" />
<p:inputText id="telephoneMobile" value="#{membreInscriptionBean.telephoneMobile}"
required="true" requiredMessage="Le téléphone mobile est obligatoire"
styleClass="w-full" />
<p:message for="telephoneMobile" />
</div>
</div>
</ui:define>
</ui:decorate>
<ui:decorate template="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Adhésion" />
<ui:param name="fluid" value="true" />
<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">
<f:selectItem itemLabel="--- Sélectionner une organisation ---" itemValue="" noSelectionOption="true" />
<f:selectItems value="#{membreInscriptionBean.organisationsDisponibles}"
var="org"
itemLabel="#{org.nom} (#{org.ville})"
itemValue="#{org.id}" />
</p:selectOneMenu>
<p:message for="organisationId" />
</div>
<div class="field">
<p:outputLabel for="typeAdhesion" value="Type d'adhésion" />
<p:selectOneMenu id="typeAdhesion" value="#{membreInscriptionBean.typeAdhesion}" required="true" styleClass="w-full">
<f:selectItem itemLabel="Sélectionner..." itemValue="" noSelectionOption="true" />
<f:selectItems value="#{membreInscriptionBean.typeAdhesionOptions}" />
</p:selectOneMenu>
</div>
<div class="field">
<p:outputLabel for="numeroParrain" value="N° Membre parrain" />
<div class="ui-inputgroup">
<p:inputText id="numeroParrain" value="#{membreInscriptionBean.numeroParrain}" styleClass="w-full" />
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-search" />
<ui:param name="action" value="#{membreInscriptionBean.rechercherParrain}" />
<ui:param name="severity" value="info" />
<ui:param name="rounded" value="false" />
<ui:param name="text" value="false" />
</ui:include>
</div>
</div>
<div class="field">
<p:outputLabel for="nomParrain" value="Nom du parrain" />
<p:inputText id="nomParrain" value="#{membreInscriptionBean.nomParrain}" readonly="true" styleClass="w-full" />
</div>
<div class="field">
<p:outputLabel for="motifAdhesion" value="Motif d'adhésion" />
<p:inputTextarea id="motifAdhesion" value="#{membreInscriptionBean.motifAdhesion}"
rows="3" styleClass="w-full" />
</div>
</ui:define>
</ui:decorate>
</div>
<div class="col-12">
<ui:decorate template="/templates/components/forms/form-section.xhtml">
<ui:param name="title" value="Informations complémentaires" />
<ui:define name="content">
<div class="ui-fluid formgrid grid">
<div class="field col-12 md:col-4">
<p:outputLabel for="nomBanque" value="Nom de la banque" />
<p:inputText id="nomBanque" value="#{membreInscriptionBean.nomBanque}" styleClass="w-full" />
</div>
<div class="field col-12 md:col-4">
<p:outputLabel for="numeroBanque" value="Numéro de compte" />
<p:inputText id="numeroBanque" value="#{membreInscriptionBean.numeroBanque}" styleClass="w-full" />
</div>
<div class="field col-12 md:col-4">
<p:outputLabel for="ribIban" value="RIB / IBAN" />
<p:inputText id="ribIban" value="#{membreInscriptionBean.ribIban}" styleClass="w-full" />
</div>
<div class="field col-12 md:col-6">
<p:outputLabel for="competencesSpeciales" value="Compétences spéciales" />
<p:inputTextarea id="competencesSpeciales" value="#{membreInscriptionBean.competencesSpeciales}"
rows="3" styleClass="w-full" />
</div>
<div class="field col-12 md:col-6">
<p:outputLabel for="centresInteret" value="Centres d'intérêt" />
<p:inputTextarea id="centresInteret" value="#{membreInscriptionBean.centresInteret}"
rows="3" styleClass="w-full" />
</div>
<div class="field col-12">
<p:outputLabel for="commentaires" value="Commentaires" />
<p:inputTextarea id="commentaires" value="#{membreInscriptionBean.commentaires}"
rows="3" styleClass="w-full" />
</div>
</div>
<h5>Autorisations</h5>
<div class="formgroup-inline">
<div class="field-checkbox">
<p:selectBooleanCheckbox id="accepteReglement" value="#{membreInscriptionBean.accepteReglement}" />
<p:outputLabel for="accepteReglement" value="J'accepte le règlement intérieur" />
</div>
<div class="field-checkbox">
<p:selectBooleanCheckbox id="acceptePrelevement" value="#{membreInscriptionBean.acceptePrelevement}" />
<p:outputLabel for="acceptePrelevement" value="J'autorise le prélèvement automatique" />
</div>
<div class="field-checkbox">
<p:selectBooleanCheckbox id="autorisationMarketing" value="#{membreInscriptionBean.autorisationMarketing}" />
<p:outputLabel for="autorisationMarketing" value="J'accepte de recevoir des communications" />
</div>
</div>
</ui:define>
</ui:decorate>
</div>
</div>
<!-- Actions finales -->
<div class="card">
<h5>Finaliser l'inscription</h5>
<div class="surface-50 p-4 border-round mb-4">
<div class="flex align-items-center">
<i class="pi pi-info-circle text-blue-500 mr-3"></i>
<div>
<div class="font-medium text-900">Vérifiez toutes les informations</div>
<div class="text-600">Assurez-vous que tous les champs requis sont remplis correctement</div>
</div>
</div>
</div>
<div class="flex flex-wrap gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="🎯 Inscrire le membre" />
<ui:param name="icon" value="pi pi-user-plus" />
<ui:param name="action" value="#{membreInscriptionBean.inscrire}" />
<ui:param name="update" value="messages" />
<ui:param name="onclick" value="PF('statusDialog').show();" />
<ui:param name="oncomplete" value="PF('statusDialog').hide();" />
<ui:param name="title" value="Soumettre l'inscription" />
</ui:include>
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="💾 Enregistrer brouillon" />
<ui:param name="icon" value="pi pi-save" />
<ui:param name="action" value="#{membreInscriptionBean.enregistrerBrouillon}" />
<ui:param name="update" value="messages" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="🔄 Réinitialiser" />
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="onclick" value="removePhoto(); return confirm('Êtes-vous sûr de vouloir réinitialiser le formulaire ?');" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="❌ Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="action" value="#{membreInscriptionBean.annuler}" />
<ui:param name="onclick" value="return confirm('Êtes-vous sûr de vouloir annuler l\'inscription ?');" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
<div class="mt-4 text-600">
<small>
<i class="pi pi-shield mr-1"></i>
Toutes les données sont chiffrées et sécurisées selon les standards RGPD
</small>
</div>
</div>
</h:form>
</ui:define>
<ui:define name="head">
<script type="text/javascript">
// Configuration de la previsualisation photo
window.addEventListener('load', function() {
var photoInput = document.getElementById('photoInput');
if (photoInput) {
photoInput.addEventListener('change', function(event) {
previewPhoto(event.target);
});
}
});
function previewPhoto(input) {
if (input.files &amp;&amp; input.files.length > 0) {
var file = input.files[0];
// Verifier que c'est une image
if (!file.type.startsWith('image/')) {
alert('Veuillez selectionner un fichier image');
input.value = '';
return;
}
// Verifier la taille (2MB max)
if (file.size > 2097152) {
alert('La taille du fichier depasse 2MB');
input.value = '';
return;
}
var reader = new FileReader();
reader.onload = function(e) {
var preview = document.getElementById('photoPreview');
var placeholder = document.getElementById('photoPlaceholder');
var removeBtn = document.getElementById('removePhotoBtn');
if (preview &amp;&amp; placeholder &amp;&amp; removeBtn) {
preview.src = e.target.result;
preview.style.display = 'block';
preview.style.left = '0px';
preview.style.top = '0px';
placeholder.style.display = 'none';
removeBtn.style.display = 'inline-block';
// Stocker l'image originale pour le recadrage
preview.originalSrc = e.target.result;
// Activer le positionnement interactif
enablePhotoPositioning(preview);
}
};
reader.onerror = function() {
alert('Erreur lors de la lecture du fichier');
};
reader.readAsDataURL(file);
}
}
function enablePhotoPositioning(photoElement) {
var isDragging = false;
var startX, startY, initialLeft, initialTop;
var overlay = document.getElementById('photoOverlay');
var currentScale = 1;
var minScale = 0.5;
var maxScale = 3;
// Fonctionnalité de zoom avec la molette
var container = document.getElementById('photoContainer');
container.addEventListener('wheel', function(e) {
e.preventDefault();
var delta = e.deltaY > 0 ? -0.1 : 0.1;
var newScale = Math.max(minScale, Math.min(maxScale, currentScale + delta));
if (newScale !== currentScale) {
currentScale = newScale;
photoElement.style.transform = 'scale(' + currentScale + ')';
// Ajuster la position si l'image sort des limites après zoom
var currentLeft = parseInt(photoElement.style.left) || 0;
var currentTop = parseInt(photoElement.style.top) || 0;
var containerWidth = container.offsetWidth;
var containerHeight = container.offsetHeight;
var photoWidth = photoElement.offsetWidth * currentScale;
var photoHeight = photoElement.offsetHeight * currentScale;
var maxLeft = photoWidth > containerWidth ? 0 : (containerWidth - photoWidth) / 2;
var minLeft = photoWidth > containerWidth ? -(photoWidth - containerWidth) : (containerWidth - photoWidth) / 2;
var maxTop = photoHeight > containerHeight ? 0 : (containerHeight - photoHeight) / 2;
var minTop = photoHeight > containerHeight ? -(photoHeight - containerHeight) : (containerHeight - photoHeight) / 2;
var adjustedLeft = Math.max(minLeft, Math.min(maxLeft, currentLeft));
var adjustedTop = Math.max(minTop, Math.min(maxTop, currentTop));
photoElement.style.left = adjustedLeft + 'px';
photoElement.style.top = adjustedTop + 'px';
// Afficher temporairement l'overlay avec le niveau de zoom
if (overlay) {
overlay.style.display = 'block';
overlay.innerHTML = '<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-size: 0.8rem; text-align: center;"><i class="pi pi-search-plus"></i><br/><small>Zoom: ' + Math.round(currentScale * 100) + '%</small></div>';
// Masquer l'overlay après 1 seconde
setTimeout(function() {
if (overlay &amp;&amp; !isDragging) {
overlay.style.display = 'none';
overlay.innerHTML = '<div style="position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); color: white; font-size: 0.75rem; text-align: center;"><i class="pi pi-arrows-alt"></i><br/><small>Glisser pour positionner<br/>Molette pour zoomer</small></div>';
}
}, 1000);
}
}
});
photoElement.addEventListener('mousedown', function(e) {
isDragging = true;
startX = e.clientX;
startY = e.clientY;
initialLeft = parseInt(photoElement.style.left) || 0;
initialTop = parseInt(photoElement.style.top) || 0;
if (overlay) overlay.style.display = 'block';
e.preventDefault();
});
document.addEventListener('mousemove', function(e) {
if (!isDragging) return;
var deltaX = e.clientX - startX;
var deltaY = e.clientY - startY;
var newLeft = initialLeft + deltaX;
var newTop = initialTop + deltaY;
// Limiter le déplacement en tenant compte du zoom
var container = document.getElementById('photoContainer');
var containerWidth = container.offsetWidth;
var containerHeight = container.offsetHeight;
var photoWidth = photoElement.offsetWidth * currentScale;
var photoHeight = photoElement.offsetHeight * currentScale;
// Calculer les limites en fonction du zoom
var maxLeft = photoWidth > containerWidth ? 0 : (containerWidth - photoWidth) / 2;
var minLeft = photoWidth > containerWidth ? -(photoWidth - containerWidth) : (containerWidth - photoWidth) / 2;
var maxTop = photoHeight > containerHeight ? 0 : (containerHeight - photoHeight) / 2;
var minTop = photoHeight > containerHeight ? -(photoHeight - containerHeight) : (containerHeight - photoHeight) / 2;
newLeft = Math.max(minLeft, Math.min(maxLeft, newLeft));
newTop = Math.max(minTop, Math.min(maxTop, newTop));
photoElement.style.left = newLeft + 'px';
photoElement.style.top = newTop + 'px';
});
document.addEventListener('mouseup', function() {
isDragging = false;
if (overlay) overlay.style.display = 'none';
});
// Support tactile pour mobile
photoElement.addEventListener('touchstart', function(e) {
var touch = e.touches[0];
isDragging = true;
startX = touch.clientX;
startY = touch.clientY;
initialLeft = parseInt(photoElement.style.left) || 0;
initialTop = parseInt(photoElement.style.top) || 0;
if (overlay) overlay.style.display = 'block';
e.preventDefault();
});
document.addEventListener('touchmove', function(e) {
if (!isDragging) return;
var touch = e.touches[0];
var deltaX = touch.clientX - startX;
var deltaY = touch.clientY - startY;
var newLeft = initialLeft + deltaX;
var newTop = initialTop + deltaY;
// Limiter le déplacement en tenant compte du zoom pour mobile
var container = document.getElementById('photoContainer');
var containerWidth = container.offsetWidth;
var containerHeight = container.offsetHeight;
var photoWidth = photoElement.offsetWidth * currentScale;
var photoHeight = photoElement.offsetHeight * currentScale;
// Calculer les limites en fonction du zoom
var maxLeft = photoWidth > containerWidth ? 0 : (containerWidth - photoWidth) / 2;
var minLeft = photoWidth > containerWidth ? -(photoWidth - containerWidth) : (containerWidth - photoWidth) / 2;
var maxTop = photoHeight > containerHeight ? 0 : (containerHeight - photoHeight) / 2;
var minTop = photoHeight > containerHeight ? -(photoHeight - containerHeight) : (containerHeight - photoHeight) / 2;
newLeft = Math.max(minLeft, Math.min(maxLeft, newLeft));
newTop = Math.max(minTop, Math.min(maxTop, newTop));
photoElement.style.left = newLeft + 'px';
photoElement.style.top = newTop + 'px';
e.preventDefault();
});
document.addEventListener('touchend', function() {
isDragging = false;
if (overlay) overlay.style.display = 'none';
});
}
function capturePhoto() {
var preview = document.getElementById('photoPreview');
var container = document.getElementById('photoContainer');
if (!preview || !preview.originalSrc || preview.style.display === 'none') {
return null;
}
return new Promise(function(resolve) {
var img = new Image();
img.onload = function() {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// Taille du cercle de sortie (120px)
var outputSize = 120;
canvas.width = outputSize;
canvas.height = outputSize;
// Obtenir les paramètres actuels
var currentScale = parseFloat(preview.style.transform.replace(/[^\d.]/g, '')) || 1;
var currentLeft = parseInt(preview.style.left) || 0;
var currentTop = parseInt(preview.style.top) || 0;
// Calculer les dimensions de l'image affichée
var displayWidth = preview.offsetWidth;
var displayHeight = preview.offsetHeight;
// Calculer le ratio entre l'image originale et l'affichage
var ratioX = img.width / displayWidth;
var ratioY = img.height / displayHeight;
// Calculer la zone source dans l'image originale
var sourceX = Math.abs(currentLeft) * ratioX;
var sourceY = Math.abs(currentTop) * ratioY;
var sourceWidth = (outputSize / currentScale) * ratioX;
var sourceHeight = (outputSize / currentScale) * ratioY;
// S'assurer que la zone source reste dans les limites de l'image
sourceX = Math.max(0, Math.min(img.width - sourceWidth, sourceX));
sourceY = Math.max(0, Math.min(img.height - sourceHeight, sourceY));
sourceWidth = Math.min(sourceWidth, img.width - sourceX);
sourceHeight = Math.min(sourceHeight, img.height - sourceY);
// Créer un masque circulaire
ctx.beginPath();
ctx.arc(outputSize/2, outputSize/2, outputSize/2, 0, 2 * Math.PI);
ctx.clip();
// Dessiner la portion cadrée de l'image
ctx.drawImage(img, sourceX, sourceY, sourceWidth, sourceHeight, 0, 0, outputSize, outputSize);
// Convertir en blob
canvas.toBlob(function(blob) {
resolve(blob);
}, 'image/jpeg', 0.9);
};
img.src = preview.originalSrc;
});
}
function removePhoto() {
var photoInput = document.getElementById('photoInput');
var preview = document.getElementById('photoPreview');
var placeholder = document.getElementById('photoPlaceholder');
var removeBtn = document.getElementById('removePhotoBtn');
if (photoInput) photoInput.value = '';
if (preview) {
preview.style.display = 'none';
preview.style.transform = 'scale(1)';
preview.style.left = '0px';
preview.style.top = '0px';
preview.originalSrc = null;
}
if (placeholder) placeholder.style.display = 'flex';
if (removeBtn) removeBtn.style.display = 'none';
}
function preparePhotoForSubmission(button) {
var preview = document.getElementById('photoPreview');
if (preview &amp;&amp; preview.style.display !== 'none') {
// Empêcher la soumission immédiate
button.disabled = true;
button.innerHTML = '<i class="pi pi-spin pi-spinner"></i> <span>Traitement...</span>';
capturePhoto().then(function(blob) {
if (blob) {
var reader = new FileReader();
reader.onload = function(e) {
var base64Data = e.target.result.split(',')[1];
var hiddenInput = document.getElementById('photoCadree');
if (hiddenInput) {
hiddenInput.value = base64Data;
}
// Maintenant soumettre le formulaire
button.click();
};
reader.readAsDataURL(blob);
} else {
// Pas de photo, soumettre directement
button.click();
}
});
return false; // Empêcher la soumission immédiate
}
return true; // Permettre la soumission si pas de photo
}
</script>
<!-- Dialogue de chargement -->
<p:dialog id="statusDialog" widgetVar="statusDialog" modal="true" closable="false"
showHeader="false" styleClass="no-border" resizable="false">
<div class="flex flex-column align-items-center p-4">
<i class="pi pi-spin pi-spinner text-4xl text-primary mb-3"></i>
<div class="text-xl font-medium text-900">Traitement en cours...</div>
<div class="text-600">Veuillez patienter pendant l'enregistrement</div>
</div>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,657 @@
<!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"
xmlns:uf="http://xmlns.jcp.org/jsf/composite/components"
template="/templates/main-template.xhtml">
<ui:param name="page" value="#{membreListeBean}"/>
<ui:define name="title">Liste des Membres - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-users text-blue-500" />
<ui:param name="title" value="Liste des Membres" />
<ui:param name="description" value="Gestion et suivi des membres de l'association" />
<ui:define name="actions">
<h:form id="formActionsMembres">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouveau membre" />
<ui:param name="icon" value="pi pi-user-plus" />
<ui:param name="outcome" value="/pages/secure/membre/inscription" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Import/Export" />
<ui:param name="icon" value="pi pi-upload" />
<ui:param name="onclick" value="PF('dlgImportExport').show();" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Liste des membres -->
<div class="card">
<h:form id="formMembres">
<h5>Tous les Membres</h5>
<!-- Filtres et recherche (DRY/WOU: filter-bar avec composants réutilisables) -->
<ui:decorate template="/templates/components/cards/filter-bar.xhtml">
<ui:param name="title" value="Filtres" />
<ui:param name="styleClass" value="mb-3" />
<ui:define name="filters">
<!-- Recherche globale (DRY/WOU: form-field-search-text avec icône) -->
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel for="searchFilter" value="Rechercher" />
<span class="p-input-icon-left w-full">
<i class="pi pi-search"></i>
<p:inputText id="searchFilter"
placeholder="Nom, prénom, email..."
value="#{membreListeBean.searchFilter}"
styleClass="w-full">
<p:ajax event="keyup" update="dtMembres" delay="500"/>
</p:inputText>
</span>
</div>
</div>
<!-- Statut (DRY/WOU: form-field-select avec AJAX) -->
<div class="col-12 md:col-2">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="statutFilter" />
<ui:param name="label" value="Statut" />
<ui:param name="value" value="#{membreListeBean.statutFilter}" />
<ui:define name="items">
<f:selectItem itemLabel="Tous les statuts" itemValue="" />
<f:selectItem itemLabel="Actif" itemValue="ACTIF" />
<f:selectItem itemLabel="Inactif" itemValue="INACTIF" />
<f:selectItem itemLabel="Suspendu" itemValue="SUSPENDU" />
<f:selectItem itemLabel="Radié" itemValue="RADIE" />
</ui:define>
<ui:define name="ajax">
<p:ajax event="change" update="dtMembres" />
</ui:define>
</ui:include>
</div>
<!-- Type (DRY/WOU: form-field-select avec AJAX) -->
<div class="col-12 md:col-2">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="typeFilter" />
<ui:param name="label" value="Type" />
<ui:param name="value" value="#{membreListeBean.typeFilter}" />
<ui:define name="items">
<f:selectItem itemLabel="Tous les types" itemValue="" />
<f:selectItem itemLabel="Actif" itemValue="ACTIF" />
<f:selectItem itemLabel="Associé" itemValue="ASSOCIE" />
<f:selectItem itemLabel="Bienfaiteur" itemValue="BIENFAITEUR" />
<f:selectItem itemLabel="Honoraire" itemValue="HONORAIRE" />
</ui:define>
<ui:define name="ajax">
<p:ajax event="change" update="dtMembres" />
</ui:define>
</ui:include>
</div>
<!-- Cotisation (DRY/WOU: form-field-select avec AJAX) -->
<div class="col-12 md:col-2">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="cotisationFilter" />
<ui:param name="label" value="Cotisation" />
<ui:param name="value" value="#{membreListeBean.cotisationFilter}" />
<ui:define name="items">
<f:selectItem itemLabel="Toutes cotisations" itemValue="" />
<f:selectItem itemLabel="À jour" itemValue="A_JOUR" />
<f:selectItem itemLabel="En retard" itemValue="EN_RETARD" />
<f:selectItem itemLabel="Jamais payé" itemValue="JAMAIS_PAYE" />
</ui:define>
<ui:define name="ajax">
<p:ajax event="change" update="dtMembres" />
</ui:define>
</ui:include>
</div>
<!-- Entité/Organisation (DRY/WOU: form-field-select avec AJAX) -->
<div class="col-12 md:col-2">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="entiteFilter" />
<ui:param name="label" value="Entité" />
<ui:param name="value" value="#{membreListeBean.entiteFilter}" />
<ui:define name="items">
<f:selectItem itemLabel="Toutes entités" itemValue="" />
<f:selectItems value="#{membreListeBean.entitesDisponibles}"
var="entite"
itemLabel="#{entite.nom}"
itemValue="#{entite.id}" />
</ui:define>
<ui:define name="ajax">
<p:ajax event="change" update="dtMembres" />
</ui:define>
</ui:include>
</div>
</ui:define>
<ui:define name="actions">
<!-- Filtres avancés (DRY/WOU: button-secondary) -->
<div class="col-12 md:col-auto">
<div class="field">
<label class="invisible">Filtres avancés</label>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Filtres avancés" />
<ui:param name="icon" value="pi pi-filter" />
<ui:param name="onclick" value="PF('dlgFiltresAvances').show();" />
<ui:param name="styleClass" value="w-full" />
</ui:include>
</div>
</div>
<!-- Actualiser (DRY/WOU: button-secondary avec icône seule) -->
<div class="col-12 md:col-auto">
<div class="field">
<label class="invisible">Actualiser</label>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="" />
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{membreListeBean.actualiser}" />
<ui:param name="update" value=":formMembres:dtMembres" />
<ui:param name="title" value="Actualiser" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full" />
</ui:include>
</div>
</div>
<!-- Réinitialiser (DRY/WOU: button-secondary) -->
<div class="col-12 md:col-auto">
<div class="field">
<label class="invisible">Réinitialiser</label>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Réinitialiser" />
<ui:param name="icon" value="pi pi-filter-slash" />
<ui:param name="action" value="#{membreListeBean.reinitialiserFiltres}" />
<ui:param name="update" value="dtMembres searchFilter statutFilter typeFilter cotisationFilter entiteFilter" />
<ui:param name="styleClass" value="w-full" />
</ui:include>
</div>
</div>
</ui:define>
</ui:decorate>
<!-- DataTable -->
<p:dataTable id="dtMembres"
var="membre"
value="#{membreListeBean.membres}"
paginator="true"
rows="15"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="10,15,25,50"
currentPageReportTemplate="Affichage {startRecord}-{endRecord} sur {totalRecords}"
selection="#{membreListeBean.selectedMembres}"
rowKey="#{membre.id}"
selectionMode="multiple"
styleClass="mt-3">
<p:column selectionMode="multiple" style="width:50px" />
<p:column headerText="N° Membre" sortBy="#{membre.numeroMembre}" style="width:120px">
<h:outputText value="#{membre.numeroMembre}" styleClass="font-mono font-bold" />
</p:column>
<p:column headerText="Membre" sortBy="#{membre.nom}">
<div class="flex align-items-center">
<div class="border-circle overflow-hidden mr-3"
style="width: 40px; height: 40px;">
<h:graphicImage value="#{membre.photoUrl}"
style="width: 100%; height: 100%; object-fit: cover;"
rendered="#{membre.photoUrl != null}" />
<div class="bg-primary text-white flex align-items-center justify-content-center w-full h-full"
rendered="#{membre.photoUrl == null}">
<span style="font-size: 0.9rem;">#{membre.initiales}</span>
</div>
</div>
<div>
<div class="font-medium text-900">#{membre.nomComplet}</div>
<div class="text-600 text-sm">
<span>#{membre.telephone}</span>
<span class="mx-2"></span>
<span>#{membre.email}</span>
</div>
</div>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{membre.typeMembre}" style="width:120px">
<p:tag value="#{membre.typeMembre}"
severity="#{membre.typeSeverity != null ? membre.typeSeverity : 'info'}"
icon="pi #{membre.typeIcon != null ? membre.typeIcon : 'pi-user'}" />
</p:column>
<p:column headerText="Statut" sortBy="#{membre.statut}" style="width:100px">
<p:tag value="#{membre.statut}"
severity="#{membre.statutSeverity}"
icon="pi #{membre.statutIcon}" />
</p:column>
<p:column headerText="Organisation" sortBy="#{membre.associationNom}" style="width:150px">
<h:outputText value="#{membre.associationNom != null ? membre.associationNom : 'Non renseigné'}" />
</p:column>
<p:column headerText="Adhésion" sortBy="#{membre.dateAdhesion}" style="width:120px">
<div>
<div class="font-medium">#{membre.dateAdhesion != null ? membre.dateAdhesion : 'Non renseigné'}</div>
<small class="text-600">#{membre.anciennete}</small>
</div>
</p:column>
<p:column headerText="Cotisations" style="width:120px">
<div class="text-center">
<div class="font-bold #{membre.cotisationColor}">#{membre.cotisationStatut}</div>
<small class="text-600">#{membre.dernierPaiement}</small>
</div>
</p:column>
<p:column headerText="Participation" style="width:100px">
<div class="text-center">
<div class="font-bold text-blue-500">#{membre.tauxParticipation}%</div>
<small class="text-600">#{membre.evenementsAnnee} événements</small>
</div>
</p:column>
<p:column headerText="Actions" style="width:200px">
<div class="flex gap-1">
<!-- DRY/WOU: Composite Component action-button-view -->
<uf:action-button-view itemId="#{membre.id}"
detailPage="/pages/secure/membre/profil.xhtml"
iconOnly="true"/>
<!-- DRY/WOU: Composite Component action-button-edit-nav -->
<uf:action-button-edit-nav itemId="#{membre.id}"
editPage="/pages/secure/membre/modifier.xhtml"
iconOnly="true"/>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-dollar" />
<ui:param name="action" value="#{membreListeBean.gererCotisations(membre)}" />
<ui:param name="title" value="Cotisations" />
<ui:param name="severity" value="success" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-envelope" />
<ui:param name="action" value="#{membreListeBean.contacterMembre(membre)}" />
<ui:param name="update" value=":formMembres :formContact" />
<ui:param name="oncomplete" value="PF('dlgContact').show();" />
<ui:param name="title" value="Contacter" />
<ui:param name="severity" value="" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-ban" />
<ui:param name="action" value="#{membreListeBean.suspendreMembre(membre)}" />
<ui:param name="onclick" value="return confirm('Êtes-vous sûr de vouloir suspendre ce membre ?');" />
<ui:param name="title" value="Suspendre" />
<ui:param name="severity" value="danger" />
<ui:param name="rendered" value="#{membre.statut == 'ACTIF'}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{membreListeBean.reactiverMembre(membre)}" />
<ui:param name="title" value="Réactiver" />
<ui:param name="severity" value="success" />
<ui:param name="rendered" value="#{membre.statut == 'SUSPENDU'}" />
</ui:include>
</div>
</p:column>
</p:dataTable>
<!-- Actions groupées -->
<div class="mt-3 flex justify-content-between align-items-center">
<div>
<span class="text-600">#{membreListeBean.selectedMembres.size()} membre(s) sélectionné(s)</span>
<span class="text-400 ml-2" rendered="#{empty membreListeBean.selectedMembres}">
- Cochez des cases pour activer les actions
</span>
</div>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Envoyer message" />
<ui:param name="icon" value="pi pi-envelope" />
<ui:param name="onclick" value="PF('dlgMessageGroupe').show();" />
<ui:param name="outlined" value="true" />
<ui:param name="disabled" value="#{empty membreListeBean.selectedMembres}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Rappel cotisations" />
<ui:param name="icon" value="pi pi-bell" />
<ui:param name="action" value="#{membreListeBean.rappelCotisationsGroupe}" />
<ui:param name="update" value=":formMembres" />
<ui:param name="outlined" value="true" />
<ui:param name="disabled" value="#{empty membreListeBean.selectedMembres}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Exporter sélection" />
<ui:param name="icon" value="pi pi-file-excel" />
<ui:param name="action" value="#{membreListeBean.exporterSelection}" />
<ui:param name="outlined" value="true" />
<ui:param name="disabled" value="#{empty membreListeBean.selectedMembres}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Modifier en lot" />
<ui:param name="icon" value="pi pi-pencil" />
<ui:param name="onclick" value="PF('dlgModificationLot').show();" />
<ui:param name="outlined" value="true" />
<ui:param name="disabled" value="#{empty membreListeBean.selectedMembres}" />
</ui:include>
</div>
</div>
</h:form>
</div>
<!-- Dialog Filtres Avancés -->
<p:dialog header="Filtres Avancés" widgetVar="dlgFiltresAvances" modal="true" width="600">
<h:form id="formFiltresAvances">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="ageMin" value="Âge minimum" />
<p:inputNumber id="ageMin" value="#{membreListeBean.ageMin}" symbol="" styleClass="w-full" />
</div>
<div class="field">
<p:outputLabel for="ageMax" value="Âge maximum" />
<p:inputNumber id="ageMax" value="#{membreListeBean.ageMax}" symbol="" styleClass="w-full" />
</div>
<div class="field">
<p:outputLabel for="genre" value="Genre" />
<p:selectOneMenu id="genre" value="#{membreListeBean.genreFilter}" styleClass="w-full">
<f:selectItem itemLabel="Tous" itemValue="" />
<f:selectItem itemLabel="Homme" itemValue="M" />
<f:selectItem itemLabel="Femme" itemValue="F" />
</p:selectOneMenu>
</div>
<div class="field">
<p:outputLabel for="ville" value="Ville" />
<p:autoComplete id="ville"
value="#{membreListeBean.villeFilter}"
completeMethod="#{membreListeBean.completerVilles}"
placeholder="Saisir une ville..."
styleClass="w-full" />
</div>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateAdhesionDebut" />
<ui:param name="label" value="Adhésion après le" />
<ui:param name="value" value="#{membreListeBean.dateAdhesionDebut}" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateAdhesionFin" />
<ui:param name="label" value="Adhésion avant le" />
<ui:param name="value" value="#{membreListeBean.dateAdhesionFin}" />
</ui:include>
<div class="field">
<p:outputLabel for="profession" value="Profession" />
<p:autoComplete id="profession"
value="#{membreListeBean.professionFilter}"
completeMethod="#{membreListeBean.completerProfessions}"
placeholder="Saisir une profession..."
styleClass="w-full" />
</div>
<div class="field">
<p:selectBooleanCheckbox id="desEnfants" value="#{membreListeBean.desEnfants}" />
<p:outputLabel for="desEnfants" value=" A des enfants déclarés" />
</div>
</div>
</div>
</div>
<div class="flex gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Appliquer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{membreListeBean.appliquerFiltresAvances}" />
<ui:param name="update" value=":formMembres:dtMembres" />
<ui:param name="onclick" value="PF('dlgFiltresAvances').hide();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Réinitialiser" />
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{membreListeBean.reinitialiserFiltres}" />
<ui:param name="update" value=":formFiltresAvances :formMembres:dtMembres" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgFiltresAvances').hide();" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="ui-button-danger" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Message Groupé -->
<p:dialog header="Envoyer un Message Groupé" widgetVar="dlgMessageGroupe" modal="true" width="600">
<h:form id="formMessageGroupe">
<div class="ui-fluid">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="sujetMessage" />
<ui:param name="label" value="Sujet" />
<ui:param name="value" value="#{membreListeBean.sujetMessage}" />
<ui:param name="required" value="true" />
<ui:param name="placeholder" value="Objet du message" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="contenuMessage" />
<ui:param name="label" value="Message" />
<ui:param name="value" value="#{membreListeBean.contenuMessage}" />
<ui:param name="required" value="true" />
<ui:param name="rows" value="6" />
</ui:include>
<div class="field">
<p:outputLabel for="canauxMessage" value="Canaux de diffusion" />
<p:selectCheckboxMenu id="canauxMessage" value="#{membreListeBean.canauxMessage}"
multiple="true" styleClass="w-full">
<f:selectItem itemLabel="📧 Email" itemValue="EMAIL" />
<f:selectItem itemLabel="📱 SMS" itemValue="SMS" />
<f:selectItem itemLabel="💬 WhatsApp" itemValue="WHATSAPP" />
<f:selectItem itemLabel="🔔 Notification push" itemValue="PUSH" />
</p:selectCheckboxMenu>
</div>
<div class="surface-50 p-3 border-round">
<div class="font-medium mb-2">Destinataires :</div>
<div class="text-600">#{membreListeBean.selectedMembres.size()} membre(s) recevront ce message</div>
</div>
</div>
<div class="flex gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Envoyer" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{membreListeBean.envoyerMessageGroupe}" />
<ui:param name="update" value=":formMessageGroupe :formMembres" />
<ui:param name="onclick" value="if(!args.validationFailed) PF('dlgMessageGroupe').hide();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgMessageGroupe').hide();" />
<ui:param name="outlined" value="false" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Import/Export -->
<p:dialog header="Import/Export des Membres" widgetVar="dlgImportExport" modal="true" width="500">
<h:form id="formImportExport">
<p:tabView>
<p:tab title="Import">
<div class="ui-fluid">
<div class="field">
<p:outputLabel for="fichierImport" value="Fichier Excel" />
<p:fileUpload id="fichierImport" mode="simple" skinSimple="true"
accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.ms-excel" />
</div>
<div class="field">
<p:selectBooleanCheckbox id="mettreAJourExistants" value="#{membreListeBean.mettreAJourExistants}" />
<p:outputLabel for="mettreAJourExistants" value=" Mettre à jour les membres existants" />
</div>
<div class="surface-50 p-3 border-round">
<div class="font-medium mb-2">Format attendu :</div>
<small class="text-600">
Colonnes : Nom, Prénom, Email, Téléphone, Date naissance, Adresse, Profession, Type membre
</small>
</div>
</div>
<div class="flex gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Importer" />
<ui:param name="icon" value="pi pi-upload" />
<ui:param name="action" value="#{membreListeBean.importerMembres}" />
<ui:param name="update" value=":formImportExport :formMembres" />
</ui:include>
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Télécharger modèle" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="action" value="#{membreListeBean.telechargerModele}" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</p:tab>
<p:tab title="Export">
<div class="ui-fluid">
<div class="field">
<p:outputLabel for="formatExport" value="Format" />
<p:selectOneMenu id="formatExport" value="#{membreListeBean.formatExport}">
<f:selectItem itemLabel="Excel (.xlsx)" itemValue="EXCEL" />
<f:selectItem itemLabel="CSV (.csv)" itemValue="CSV" />
<f:selectItem itemLabel="PDF (.pdf)" itemValue="PDF" />
</p:selectOneMenu>
</div>
<div class="field">
<p:outputLabel for="colonnesExport" value="Colonnes à exporter" />
<p:selectCheckboxMenu id="colonnesExport" value="#{membreListeBean.colonnesExport}"
multiple="true">
<f:selectItem itemLabel="Informations personnelles" itemValue="PERSO" />
<f:selectItem itemLabel="Coordonnées" itemValue="CONTACT" />
<f:selectItem itemLabel="Informations adhésion" itemValue="ADHESION" />
<f:selectItem itemLabel="Cotisations" itemValue="COTISATIONS" />
<f:selectItem itemLabel="Participation événements" itemValue="EVENEMENTS" />
</p:selectCheckboxMenu>
</div>
<div class="field">
<p:selectBooleanCheckbox id="exporterSelection" value="#{membreListeBean.exporterSelection}" />
<p:outputLabel for="exporterSelection" value=" Exporter seulement la sélection" />
</div>
</div>
<div class="flex gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="action" value="#{membreListeBean.exporterMembres}" />
</ui:include>
</div>
</p:tab>
</p:tabView>
<div class="flex justify-content-end mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Fermer" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgImportExport').hide();" />
<ui:param name="outlined" value="false" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Contact Membre -->
<h:form id="formContact">
<p:dialog id="dlgContact"
header="Contacter #{membreListeBean.membreAContacter != null ? membreListeBean.membreAContacter.nomComplet : 'Membre'}"
widgetVar="dlgContact"
modal="true"
resizable="false"
style="width: 90vw; max-width: 600px;"
visible="#{membreListeBean.dialogContactVisible}">
<div class="ui-fluid" rendered="#{membreListeBean.membreAContacter != null}">
<div class="field mb-4">
<div class="surface-100 border-round p-3">
<div class="flex align-items-center">
<div class="w-3rem h-3rem border-circle bg-primary-100 flex align-items-center justify-content-center mr-3">
<i class="pi pi-user text-primary text-xl"></i>
</div>
<div>
<div class="font-semibold text-900">#{membreListeBean.membreAContacter.nomComplet}</div>
<div class="text-600 text-sm">#{membreListeBean.membreAContacter.email != null ? membreListeBean.membreAContacter.email : 'Email non renseigné'}</div>
<div class="text-600 text-sm">#{membreListeBean.membreAContacter.telephone != null ? membreListeBean.membreAContacter.telephone : 'Téléphone non renseigné'}</div>
</div>
</div>
</div>
</div>
<div class="field">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="sujetContact" />
<ui:param name="label" value="Sujet" />
<ui:param name="value" value="#{membreListeBean.sujetContact}" />
<ui:param name="placeholder" value="Sujet du message (optionnel)" />
</ui:include>
</div>
<div class="field">
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="messageContact" />
<ui:param name="label" value="Message *" />
<ui:param name="value" value="#{membreListeBean.messageContact}" />
<ui:param name="required" value="true" />
<ui:param name="rows" value="6" />
<ui:param name="placeholder" value="Saisissez votre message..." />
</ui:include>
</div>
</div>
<f:facet name="footer">
<div class="flex justify-content-end gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="action" value="#{membreListeBean.annulerContact}" />
<ui:param name="update" value=":formContact" />
<ui:param name="oncomplete" value="PF('dlgContact').hide();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Envoyer" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{membreListeBean.envoyerMessageContact}" />
<ui:param name="update" value=":formContact :formMembres" />
<ui:param name="oncomplete" value="if(!args.validationFailed) { PF('dlgContact').hide(); }" />
</ui:include>
</div>
</f:facet>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,660 @@
<!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">Profil de #{membreProfilBean.membre.nomComplet} - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête avec photo et informations principales -->
<div class="grid">
<div class="col-12">
<div class="card">
<div class="flex align-items-start justify-content-between">
<div class="flex align-items-start">
<!-- Photo de profil -->
<div class="mr-4">
<ui:include src="/templates/components/profile-photo.xhtml">
<ui:param name="photoId" value="photoProfil" />
<ui:param name="photoUrl" value="#{membreProfilBean.membre.photoUrl}" />
<ui:param name="initiales" value="#{membreProfilBean.membre.initiales}" />
<ui:param name="formId" value="formPhoto" />
<ui:param name="listener" value="#{membreProfilBean.changerPhoto}" />
<ui:param name="update" value=":photoProfil" />
<ui:param name="size" value="120" />
</ui:include>
</div>
<!-- Informations principales -->
<div class="flex-1">
<div class="flex align-items-center mb-3">
<h2 class="m-0 mr-3">#{membreProfilBean.membre.nomComplet}</h2>
<p:tag value="#{membreProfilBean.membre.statut}"
severity="#{membreProfilBean.membre.statutSeverity}"
icon="pi #{membreProfilBean.membre.statutIcon}" />
</div>
<div class="grid">
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Numéro membre" />
<ui:param name="value" value="#{membreProfilBean.membre.numeroMembre}" />
<ui:param name="valueClass" value="font-bold text-primary" />
</ui:include>
<div class="mb-2">
<span class="font-medium text-900">Type:</span>
<p:tag value="#{membreProfilBean.membre.typeMembre}"
severity="#{membreProfilBean.membre.typeSeverity}"
icon="pi #{membreProfilBean.membre.typeIcon}"
styleClass="ml-2" />
</div>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Entité" />
<ui:param name="value" value="#{membreProfilBean.membre.entite}" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Adhésion" />
<ui:param name="value" value="#{membreProfilBean.membre.dateAdhesion}" />
<ui:param name="suffix" value="(#{membreProfilBean.membre.anciennete})" />
</ui:include>
<div class="mb-2">
<span class="font-medium text-900">Cotisations:</span>
<span class="ml-2 #{membreProfilBean.membre.cotisationColor}">#{membreProfilBean.membre.cotisationStatut}</span>
</div>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Participation" />
<ui:param name="value" value="#{membreProfilBean.membre.tauxParticipation}%" />
<ui:param name="valueClass" value="font-bold text-blue-500" />
</ui:include>
</div>
</div>
</div>
</div>
<!-- Actions principales -->
<h:form id="formActionsPrincipales">
<div class="flex flex-column gap-2">
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Modifier" />
<ui:param name="icon" value="pi pi-pencil" />
<ui:param name="onclick" value="PF('dlgModifierProfil').show();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Cotisations" />
<ui:param name="icon" value="pi pi-dollar" />
<ui:param name="action" value="#{membreProfilBean.gererCotisations}" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Contacter" />
<ui:param name="icon" value="pi pi-envelope" />
<ui:param name="onclick" value="PF('dlgContacter').show();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Actions" />
<ui:param name="icon" value="pi pi-cog" />
<ui:param name="onclick" value="PF('dlgActions').show();" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</h:form>
</div>
</div>
</div>
</div>
<!-- Statistiques et KPIs -->
<div class="grid">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Événements" />
<ui:param name="value" value="#{membreProfilBean.statistiques.evenementsParticipes}" />
<ui:param name="icon" value="pi-calendar" />
<ui:param name="iconColor" value="blue-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
<ui:param name="colSize" value="col-12 md:col-3" />
</ui:include>
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Cotisations" />
<ui:param name="value" value="#{membreProfilBean.statistiques.cotisationsPayees}" />
<ui:param name="icon" value="pi-dollar" />
<ui:param name="iconColor" value="green-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
<ui:param name="colSize" value="col-12 md:col-3" />
</ui:include>
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Aides reçues" />
<ui:param name="value" value="#{membreProfilBean.statistiques.aidesRecues}" />
<ui:param name="icon" value="pi-heart" />
<ui:param name="iconColor" value="orange-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
<ui:param name="colSize" value="col-12 md:col-3" />
</ui:include>
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Score engagement" />
<ui:param name="value" value="#{membreProfilBean.statistiques.scoreEngagement}" />
<ui:param name="icon" value="pi-star" />
<ui:param name="iconColor" value="purple-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
<ui:param name="colSize" value="col-12 md:col-3" />
</ui:include>
</div>
<!-- Contenu principal avec onglets -->
<div class="card">
<p:tabView>
<!-- Onglet Informations personnelles -->
<p:tab title="👤 Informations personnelles">
<div class="grid">
<div class="col-12 md:col-6">
<h6 class="mb-3">Informations de base</h6>
<div class="surface-50 p-3 border-round">
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Nom complet" />
<ui:param name="value" value="#{membreProfilBean.membre.nomComplet}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Date de naissance" />
<ui:param name="value" value="#{membreProfilBean.membre.dateNaissance}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Genre" />
<ui:param name="value" value="#{membreProfilBean.membre.genre}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Situation familiale" />
<ui:param name="value" value="#{membreProfilBean.membre.situationFamiliale}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Profession" />
<ui:param name="value" value="#{membreProfilBean.membre.profession}" />
</ui:include>
</div>
</div>
<div class="col-12 md:col-6">
<h6 class="mb-3">Coordonnées</h6>
<div class="surface-50 p-3 border-round">
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Email" />
<ui:param name="value" value="#{membreProfilBean.membre.email}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Téléphone" />
<ui:param name="value" value="#{membreProfilBean.membre.telephone}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Adresse" />
<ui:param name="value" value="#{membreProfilBean.membre.adresse}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Ville" />
<ui:param name="value" value="#{membreProfilBean.membre.ville}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Pays" />
<ui:param name="value" value="#{membreProfilBean.membre.pays}" />
</ui:include>
</div>
</div>
<div class="col-12">
<h6 class="mb-3">Famille</h6>
<p:dataTable value="#{membreProfilBean.membre.famille}" var="membre_famille"
styleClass="p-datatable-sm" emptyMessage="Aucun membre de famille déclaré">
<p:column headerText="Nom complet">
<h:outputText value="#{membre_famille.nomComplet}" />
</p:column>
<p:column headerText="Relation">
<p:tag value="#{membre_famille.relation}" severity="info" />
</p:column>
<p:column headerText="Date de naissance">
<h:outputText value="#{membre_famille.dateNaissance}">
<f:convertDateTime pattern="dd/MM/yyyy" type="localDate" />
</h:outputText>
</p:column>
<p:column headerText="Bénéficiaire">
<p:tag value="#{membre_famille.beneficiaire ? 'Oui' : 'Non'}"
severity="#{membre_famille.beneficiaire ? 'success' : 'secondary'}" />
</p:column>
</p:dataTable>
</div>
</div>
</p:tab>
<!-- Onglet Cotisations -->
<p:tab title="💰 Cotisations">
<div class="grid">
<div class="col-12 md:col-6">
<h6 class="mb-3">État des cotisations</h6>
<div class="surface-50 p-3 border-round mb-3">
<div class="flex justify-content-between align-items-center mb-2">
<span class="font-medium">Statut actuel:</span>
<p:tag value="#{membreProfilBean.cotisations.statutActuel}"
severity="#{membreProfilBean.cotisations.statutSeverity}" />
</div>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Dernier paiement" />
<ui:param name="value" value="#{membreProfilBean.cotisations.dernierPaiement}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Prochaine échéance" />
<ui:param name="value" value="#{membreProfilBean.cotisations.prochaineEcheance}" />
<ui:param name="valueClass" value="#{membreProfilBean.cotisations.prochaineEcheanceClass}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Total payé cette année" />
<ui:param name="value" value="#{membreProfilBean.cotisations.totalAnnee}" />
<ui:param name="valueClass" value="font-bold text-green-500" />
</ui:include>
</div>
<h:form id="formCotisationsActions">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouveau paiement" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="onclick" value="PF('dlgNouveauPaiement').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Envoyer rappel" />
<ui:param name="icon" value="pi pi-bell" />
<ui:param name="action" value="#{membreProfilBean.envoyerRappelCotisation}" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</h:form>
</div>
<div class="col-12 md:col-6">
<h6 class="mb-3">Historique des paiements</h6>
<p:dataTable value="#{membreProfilBean.cotisations.historique}" var="paiement"
rows="5" paginator="true" styleClass="p-datatable-sm">
<p:column headerText="Date">
<h:outputText value="#{paiement.date}">
<f:convertDateTime pattern="dd/MM/yyyy" type="localDate" />
</h:outputText>
</p:column>
<p:column headerText="Montant">
<h:outputText value="#{paiement.montant}" styleClass="font-bold">
<f:convertNumber type="currency" currencySymbol="FCFA " />
</h:outputText>
</p:column>
<p:column headerText="Mode">
<div class="flex align-items-center">
<i class="pi #{paiement.modeIcon} mr-2"></i>
<span>#{paiement.modePaiement}</span>
</div>
</p:column>
<p:column headerText="Statut">
<p:tag value="#{paiement.statut}" severity="#{paiement.statutSeverity}" />
</p:column>
</p:dataTable>
</div>
</div>
</p:tab>
<!-- Onglet Participation -->
<p:tab title="📅 Participation">
<div class="grid">
<div class="col-12 md:col-8">
<h6 class="mb-3">Événements récents</h6>
<ui:repeat value="#{membreProfilBean.evenements.recents}" var="evenement">
<div class="flex align-items-center p-3 mb-2 border-round surface-50">
<div class="border-round p-2 mr-3 bg-#{evenement.typeEvenementSeverity}">
<i class="pi #{evenement.typeEvenementIcon} text-white"></i>
</div>
<div class="flex-1">
<div class="font-medium text-900">#{evenement.titre}</div>
<div class="text-600 text-sm">
#{evenement.date} • #{evenement.lieu}
</div>
</div>
<div class="text-right">
<p:tag value="#{evenement.participation}"
severity="#{evenement.participationSeverity}" />
<div class="text-sm text-600 mt-1">
#{evenement.role}
</div>
</div>
</div>
</ui:repeat>
</div>
<div class="col-12 md:col-4">
<h6 class="mb-3">Statistiques participation</h6>
<div class="surface-50 p-3 border-round">
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Taux de participation" />
<ui:param name="value" value="#{membreProfilBean.statistiques.tauxParticipation}%" />
<ui:param name="valueClass" value="font-bold text-blue-500" />
</ui:include>
<p:progressBar value="#{membreProfilBean.statistiques.tauxParticipation}"
labelTemplate="" styleClass="mb-3" />
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Cette année" />
<ui:param name="value" value="#{membreProfilBean.statistiques.evenementsAnnee}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Total" />
<ui:param name="value" value="#{membreProfilBean.statistiques.evenementsTotal}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="En tant qu'organisateur" />
<ui:param name="value" value="#{membreProfilBean.statistiques.evenementsOrganises}" />
</ui:include>
<ui:include src="/templates/components/forms/detail-field-row.xhtml">
<ui:param name="label" value="Absences" />
<ui:param name="value" value="#{membreProfilBean.statistiques.absences}" />
<ui:param name="valueClass" value="text-red-500" />
</ui:include>
</div>
</div>
</div>
</p:tab>
<!-- Onglet Aides et Services -->
<p:tab title="🤝 Aides et Services">
<div class="grid">
<div class="col-12 md:col-6">
<h6 class="mb-3">Aides reçues</h6>
<p:dataTable value="#{membreProfilBean.aides.recues}" var="aide"
styleClass="p-datatable-sm" emptyMessage="Aucune aide reçue">
<p:column headerText="Type">
<div class="flex align-items-center">
<i class="pi #{aide.typeIcon} mr-2 #{aide.typeColor}"></i>
<span>#{aide.type}</span>
</div>
</p:column>
<p:column headerText="Montant">
<h:outputText value="#{aide.montant}" styleClass="font-bold">
<f:convertNumber type="currency" currencySymbol="FCFA " />
</h:outputText>
</p:column>
<p:column headerText="Date">
<h:outputText value="#{aide.date}">
<f:convertDateTime pattern="dd/MM/yyyy" type="localDate" />
</h:outputText>
</p:column>
<p:column headerText="Statut">
<p:tag value="#{aide.statut}" severity="#{aide.statutSeverity}" />
</p:column>
</p:dataTable>
</div>
<div class="col-12 md:col-6">
<h6 class="mb-3">Demandes en cours</h6>
<p:dataTable value="#{membreProfilBean.demandes.enCours}" var="demande"
styleClass="p-datatable-sm" emptyMessage="Aucune demande en cours">
<p:column headerText="Type">
<h:outputText value="#{demande.type}" />
</p:column>
<p:column headerText="Objet">
<h:outputText value="#{demande.objet}" />
</p:column>
<p:column headerText="Date">
<h:outputText value="#{demande.dateDepot}">
<f:convertDateTime pattern="dd/MM/yyyy" type="localDate" />
</h:outputText>
</p:column>
<p:column headerText="Statut">
<p:tag value="#{demande.statut}" severity="#{demande.statutSeverity}" />
</p:column>
</p:dataTable>
<h:form id="formNouvelleDemande">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouvelle demande" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="onclick" value="PF('dlgNouvelleDemande').show();" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mt-3" />
</ui:include>
</h:form>
</div>
</div>
</p:tab>
<!-- Onglet Historique -->
<p:tab title="📋 Historique">
<h6 class="mb-3">Activité récente</h6>
<ui:repeat value="#{membreProfilBean.historique.activites}" var="activite" varStatus="status">
<div class="flex align-items-start p-3 mb-3 border-round surface-50">
<div class="border-circle bg-primary text-white flex align-items-center justify-content-center mr-3"
style="width: 40px; height: 40px; min-width: 40px;">
<i class="pi #{activite.icone}"></i>
</div>
<div class="flex-1">
<div class="flex align-items-center justify-content-between mb-2">
<span class="font-medium text-900">#{activite.description}</span>
<small class="text-600">#{activite.date}</small>
</div>
<div class="text-600 text-sm mb-1">
Par #{activite.auteur}
</div>
<div class="text-sm text-700" rendered="#{activite.details != null}">
#{activite.details}
</div>
</div>
</div>
<!-- Ligne de connexion pour les éléments suivants -->
<div class="flex justify-content-center mb-3" rendered="#{!status.last}">
<div class="bg-300" style="width: 2px; height: 20px;"></div>
</div>
</ui:repeat>
<!-- Message si aucune activité -->
<div class="text-center p-4 text-600" rendered="#{empty membreProfilBean.historique.activites}">
<i class="pi pi-info-circle text-3xl mb-3"></i>
<div>Aucune activité récente</div>
</div>
</p:tab>
</p:tabView>
</div>
<!-- Dialog Modifier Profil -->
<p:dialog header="Modifier le Profil" widgetVar="dlgModifierProfil" modal="true" width="800">
<h:form id="formModifierProfil">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="editPrenom" />
<ui:param name="label" value="Prénom" />
<ui:param name="value" value="#{membreProfilBean.membreEdit.prenom}" />
<ui:param name="required" value="true" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="editNom" />
<ui:param name="label" value="Nom" />
<ui:param name="value" value="#{membreProfilBean.membreEdit.nom}" />
<ui:param name="required" value="true" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="editEmail" />
<ui:param name="label" value="Email" />
<ui:param name="value" value="#{membreProfilBean.membreEdit.email}" />
<ui:param name="required" value="true" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="editTelephone" />
<ui:param name="label" value="Téléphone" />
<ui:param name="value" value="#{membreProfilBean.membreEdit.telephone}" />
<ui:param name="required" value="true" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="editDateNaissance" />
<ui:param name="label" value="Date de naissance" />
<ui:param name="value" value="#{membreProfilBean.membreEdit.dateNaissance}" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="editProfession" />
<ui:param name="label" value="Profession" />
<ui:param name="value" value="#{membreProfilBean.membreEdit.profession}" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="editAdresse" />
<ui:param name="label" value="Adresse" />
<ui:param name="value" value="#{membreProfilBean.membreEdit.adresse}" />
<ui:param name="rows" value="3" />
</ui:include>
</div>
</div>
</div>
<div class="flex gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Enregistrer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{membreProfilBean.sauvegarderModifications}" />
<ui:param name="update" value=":formModifierProfil :photoProfil" />
<ui:param name="onclick" value="if(!args.validationFailed) PF('dlgModifierProfil').hide();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgModifierProfil').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Contacter -->
<p:dialog header="Contacter #{membreProfilBean.membre.prenom}" widgetVar="dlgContacter" modal="true" width="500">
<h:form id="formContacter">
<div class="ui-fluid">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="sujetContact" />
<ui:param name="label" value="Sujet" />
<ui:param name="value" value="#{membreProfilBean.contact.sujet}" />
<ui:param name="required" value="true" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="messageContact" />
<ui:param name="label" value="Message" />
<ui:param name="value" value="#{membreProfilBean.contact.message}" />
<ui:param name="required" value="true" />
<ui:param name="rows" value="5" />
</ui:include>
<div class="field">
<p:outputLabel for="canalContact" value="Canal de communication" />
<p:selectCheckboxMenu id="canalContact" value="#{membreProfilBean.contact.canaux}" multiple="true" styleClass="w-full">
<f:selectItem itemLabel="📧 Email" itemValue="EMAIL" />
<f:selectItem itemLabel="📱 SMS" itemValue="SMS" />
<f:selectItem itemLabel="💬 WhatsApp" itemValue="WHATSAPP" />
</p:selectCheckboxMenu>
</div>
</div>
<div class="flex gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Envoyer" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{membreProfilBean.envoyerMessage}" />
<ui:param name="update" value=":formContacter" />
<ui:param name="oncomplete" value="if(!args.validationFailed) PF('dlgContacter').hide();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgContacter').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Actions -->
<p:dialog header="Actions sur le Membre" widgetVar="dlgActions" modal="true" width="400">
<h:form id="formActions">
<div class="grid">
<div class="col-12">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Suspendre membre" />
<ui:param name="icon" value="pi pi-ban" />
<ui:param name="action" value="#{membreProfilBean.suspendre}" />
<ui:param name="onclick" value="return confirm('Êtes-vous sûr de vouloir suspendre ce membre ?');" />
<ui:param name="styleClass" value="ui-button-danger w-full mb-2" />
<ui:param name="rendered" value="#{membreProfilBean.membre.statut == 'ACTIF'}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Réactiver membre" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{membreProfilBean.reactiver}" />
<ui:param name="styleClass" value="w-full mb-2" />
<ui:param name="rendered" value="#{membreProfilBean.membre.statut == 'SUSPENDU'}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Changer de type" />
<ui:param name="icon" value="pi pi-user-edit" />
<ui:param name="onclick" value="PF('dlgChangerType').show();" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
</ui:include>
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Transférer vers entité" />
<ui:param name="icon" value="pi pi-arrow-right" />
<ui:param name="onclick" value="PF('dlgTransferer').show();" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Exporter données" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="action" value="#{membreProfilBean.exporterDonnees}" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="w-full mb-2" />
<ui:param name="update" value="none" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Supprimer membre" />
<ui:param name="icon" value="pi pi-trash" />
<ui:param name="action" value="#{membreProfilBean.supprimer}" />
<ui:param name="onclick" value="return confirm('ATTENTION: Cette action est irréversible. Confirmer la suppression ?');" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="ui-button-danger w-full" />
</ui:include>
</div>
</div>
<div class="flex justify-content-end mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Fermer" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgActions').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,713 @@
<!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">Recherche Avancée des Membres - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-search text-blue-500" />
<ui:param name="title" value="Recherche Avancée des Membres" />
<ui:param name="description" value="Outil de recherche puissant pour retrouver et analyser les membres" />
<ui:define name="actions">
<h:form id="formActionsEntete">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Recherches sauvegardées" />
<ui:param name="icon" value="pi pi-bookmark" />
<ui:param name="onclick" value="PF('dlgRecherchesSauvegardees').show();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Nouvelle recherche" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="action" value="#{membreRechercheBean.nouvelleRecherche}" />
<ui:param name="outlined" value="true" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques de recherche -->
<div class="grid">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Total Membres" />
<ui:param name="value" value="#{membreRechercheBean.statistiques.totalMembres}" />
<ui:param name="icon" value="pi-users" />
<ui:param name="iconColor" value="blue-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
<ui:param name="colSize" value="col-12 md:col-6 lg:col-3" />
</ui:include>
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Résultats trouvés" />
<ui:param name="value" value="#{membreRechercheBean.statistiques.resultatsActuels}" />
<ui:param name="icon" value="pi-check" />
<ui:param name="iconColor" value="green-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
<ui:param name="colSize" value="col-12 md:col-6 lg:col-3" />
</ui:include>
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Filtres actifs" />
<ui:param name="value" value="#{membreRechercheBean.statistiques.filtresActifs}" />
<ui:param name="icon" value="pi-filter" />
<ui:param name="iconColor" value="orange-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
<ui:param name="colSize" value="col-12 md:col-6 lg:col-3" />
</ui:include>
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Temps de recherche" />
<ui:param name="value" value="#{membreRechercheBean.statistiques.tempsRecherche}ms" />
<ui:param name="icon" value="pi-clock" />
<ui:param name="iconColor" value="purple-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
<ui:param name="colSize" value="col-12 md:col-6 lg:col-3" />
</ui:include>
</div>
<!-- Formulaire de recherche avancée -->
<div class="card">
<h:form id="formRechercheAvancee">
<h5>
<i class="pi pi-filter mr-2"></i>
Critères de Recherche
</h5>
<p:tabView>
<!-- Onglet Informations de base -->
<p:tab title="👤 Informations Personnelles">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-4">
<ui:include src="/templates/components/forms/form-field-search-text.xhtml">
<ui:param name="id" value="searchNom" />
<ui:param name="label" value="Nom" />
<ui:param name="value" value="#{membreRechercheBean.filtres.nom}" />
<ui:param name="placeholder" value="Rechercher par nom..." />
</ui:include>
</div>
<div class="col-12 md:col-4">
<ui:include src="/templates/components/forms/form-field-search-text.xhtml">
<ui:param name="id" value="searchPrenom" />
<ui:param name="label" value="Prénom" />
<ui:param name="value" value="#{membreRechercheBean.filtres.prenom}" />
<ui:param name="placeholder" value="Rechercher par prénom..." />
</ui:include>
</div>
<div class="col-12 md:col-4">
<ui:include src="/templates/components/forms/form-field-search-text.xhtml">
<ui:param name="id" value="searchEmail" />
<ui:param name="label" value="Email" />
<ui:param name="value" value="#{membreRechercheBean.filtres.email}" />
<ui:param name="placeholder" value="Rechercher par email..." />
</ui:include>
</div>
<div class="col-12 md:col-4">
<ui:include src="/templates/components/forms/form-field-search-text.xhtml">
<ui:param name="id" value="searchTelephone" />
<ui:param name="label" value="Téléphone" />
<ui:param name="value" value="#{membreRechercheBean.filtres.telephone}" />
<ui:param name="placeholder" value="Rechercher par téléphone..." />
</ui:include>
</div>
<div class="col-12 md:col-4">
<ui:include src="/templates/components/forms/form-field-search-text.xhtml">
<ui:param name="id" value="searchNumeroMembre" />
<ui:param name="label" value="Numéro membre" />
<ui:param name="value" value="#{membreRechercheBean.filtres.numeroMembre}" />
<ui:param name="placeholder" value="Ex: M2024001" />
</ui:include>
</div>
<div class="col-12 md:col-4">
<ui:include src="/templates/components/forms/form-field-autocomplete.xhtml">
<ui:param name="id" value="searchProfession" />
<ui:param name="label" value="Profession" />
<ui:param name="value" value="#{membreRechercheBean.filtres.profession}" />
<ui:param name="completeMethod" value="#{membreRechercheBean.completerProfessions}" />
<ui:param name="placeholder" value="Saisir une profession..." />
</ui:include>
</div>
</div>
</div>
</p:tab>
<!-- Onglet Critères d'adhésion -->
<p:tab title="🏢 Adhésion et Statut">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-checkbox-menu.xhtml">
<ui:param name="id" value="searchStatut" />
<ui:param name="label" value="Statut" />
<ui:param name="value" value="#{membreRechercheBean.filtres.statuts}" />
<ui:define name="items">
<f:selectItem itemLabel="Actif" itemValue="ACTIF" />
<f:selectItem itemLabel="Inactif" itemValue="INACTIF" />
<f:selectItem itemLabel="Suspendu" itemValue="SUSPENDU" />
<f:selectItem itemLabel="Radié" itemValue="RADIE" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-checkbox-menu.xhtml">
<ui:param name="id" value="searchTypeMembre" />
<ui:param name="label" value="Type de membre" />
<ui:param name="value" value="#{membreRechercheBean.filtres.typesMembre}" />
<ui:define name="items">
<f:selectItem itemLabel="Actif" itemValue="ACTIF" />
<f:selectItem itemLabel="Associé" itemValue="ASSOCIE" />
<f:selectItem itemLabel="Bienfaiteur" itemValue="BIENFAITEUR" />
<f:selectItem itemLabel="Honoraire" itemValue="HONORAIRE" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel for="searchEntite" value="Entité" />
<p:selectCheckboxMenu id="searchEntite" value="#{membreRechercheBean.filtres.entites}"
multiple="true" styleClass="w-full">
<f:selectItems value="#{membreRechercheBean.entitesDisponibles}"
var="entite"
itemLabel="#{entite.nom}"
itemValue="#{entite.id}" />
<p:ajax update=":formResultats:dtResultats @(.search-summary)" />
</p:selectCheckboxMenu>
</div>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-checkbox-menu.xhtml">
<ui:param name="id" value="searchCotisationStatut" />
<ui:param name="label" value="Statut cotisations" />
<ui:param name="value" value="#{membreRechercheBean.filtres.statutsCotisation}" />
<ui:define name="items">
<f:selectItem itemLabel="À jour" itemValue="A_JOUR" />
<f:selectItem itemLabel="En retard" itemValue="EN_RETARD" />
<f:selectItem itemLabel="Jamais payé" itemValue="JAMAIS_PAYE" />
</ui:define>
</ui:include>
</div>
</div>
<div class="grid">
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="adhesionDateDebut" />
<ui:param name="label" value="Adhésion après le" />
<ui:param name="value" value="#{membreRechercheBean.filtres.dateAdhesionDebut}" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="adhesionDateFin" />
<ui:param name="label" value="Adhésion avant le" />
<ui:param name="value" value="#{membreRechercheBean.filtres.dateAdhesionFin}" />
</ui:include>
</div>
</div>
</div>
</p:tab>
<!-- Onglet Critères démographiques -->
<p:tab title="📊 Critères Démographiques">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-checkbox-menu.xhtml">
<ui:param name="id" value="searchGenre" />
<ui:param name="label" value="Genre" />
<ui:param name="value" value="#{membreRechercheBean.filtres.genres}" />
<ui:define name="items">
<f:selectItem itemLabel="Masculin" itemValue="M" />
<f:selectItem itemLabel="Féminin" itemValue="F" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-number.xhtml">
<ui:param name="id" value="ageMin" />
<ui:param name="label" value="Âge minimum" />
<ui:param name="value" value="#{membreRechercheBean.filtres.ageMin}" />
<ui:param name="placeholder" value="Ex: 25" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-number.xhtml">
<ui:param name="id" value="ageMax" />
<ui:param name="label" value="Âge maximum" />
<ui:param name="value" value="#{membreRechercheBean.filtres.ageMax}" />
<ui:param name="placeholder" value="Ex: 65" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-autocomplete.xhtml">
<ui:param name="id" value="searchVille" />
<ui:param name="label" value="Ville" />
<ui:param name="value" value="#{membreRechercheBean.filtres.ville}" />
<ui:param name="completeMethod" value="#{membreRechercheBean.completerVilles}" />
<ui:param name="placeholder" value="Saisir une ville..." />
</ui:include>
</div>
</div>
</div>
</p:tab>
<!-- Onglet Critères d'activité -->
<p:tab title="📈 Activité et Engagement">
<div class="ui-fluid">
<div class="grid">
<div class="col-12 md:col-4">
<ui:include src="/templates/components/forms/form-field-number.xhtml">
<ui:param name="id" value="tauxParticipationMin" />
<ui:param name="label" value="Taux participation min (%)" />
<ui:param name="value" value="#{membreRechercheBean.filtres.tauxParticipationMin}" />
<ui:param name="minValue" value="0" />
<ui:param name="maxValue" value="100" />
</ui:include>
</div>
<div class="col-12 md:col-4">
<ui:include src="/templates/components/forms/form-field-number.xhtml">
<ui:param name="id" value="evenementsMin" />
<ui:param name="label" value="Événements min (cette année)" />
<ui:param name="value" value="#{membreRechercheBean.filtres.evenementsMin}" />
</ui:include>
</div>
<div class="col-12 md:col-4">
<ui:include src="/templates/components/forms/form-field-number.xhtml">
<ui:param name="id" value="cotisationsMin" />
<ui:param name="label" value="Cotisations payées min" />
<ui:param name="value" value="#{membreRechercheBean.filtres.cotisationsMin}" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-boolean.xhtml">
<ui:param name="id" value="aDesEnfants" />
<ui:param name="label" value=" A des enfants déclarés" />
<ui:param name="value" value="#{membreRechercheBean.filtres.aDesEnfants}" />
</ui:include>
</div>
<div class="col-12 md:col-6">
<ui:include src="/templates/components/forms/form-field-boolean.xhtml">
<ui:param name="id" value="aRecuAides" />
<ui:param name="label" value=" A reçu des aides" />
<ui:param name="value" value="#{membreRechercheBean.filtres.aRecuAides}" />
</ui:include>
</div>
</div>
</div>
</p:tab>
</p:tabView>
<!-- Actions de recherche -->
<div class="flex gap-2 mt-4">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Rechercher" />
<ui:param name="icon" value="pi pi-search" />
<ui:param name="action" value="#{membreRechercheBean.effectuerRecherche}" />
<ui:param name="update" value=":formResultats:dtResultats @(.search-summary)" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Réinitialiser" />
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{membreRechercheBean.reinitialiserFiltres}" />
<ui:param name="update" value=":formRechercheAvancee :formResultats:dtResultats @(.search-summary)" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Sauvegarder recherche" />
<ui:param name="icon" value="pi pi-bookmark" />
<ui:param name="onclick" value="PF('dlgSauvegarderRecherche').show();" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Exporter résultats" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="onclick" value="PF('dlgExporterResultats').show();" />
<ui:param name="outlined" value="true" />
<ui:param name="disabled" value="#{empty membreRechercheBean.resultats}" />
</ui:include>
</div>
</h:form>
</div>
<!-- Résumé de recherche -->
<div class="card search-summary">
<div class="flex align-items-center justify-content-between">
<div>
<h6 class="mb-2">
<i class="pi pi-list mr-2"></i>
Résultats de recherche
</h6>
<p class="text-600 m-0">
#{membreRechercheBean.resultats.size()} membre(s) trouvé(s)
sur #{membreRechercheBean.statistiques.totalMembres} total
<span class="ml-2" rendered="#{membreRechercheBean.statistiques.filtresActifs > 0}">
• #{membreRechercheBean.statistiques.filtresActifs} filtre(s) actif(s)
</span>
</p>
</div>
<div class="flex gap-2">
<p:tag value="#{membreRechercheBean.resultats.size()} résultats"
severity="#{membreRechercheBean.resultats.size() > 0 ? 'success' : 'warning'}"
icon="pi pi-check" />
</div>
</div>
</div>
<!-- Tableau des résultats -->
<div class="card">
<h:form id="formResultats">
<p:dataTable id="dtResultats"
var="membre"
value="#{membreRechercheBean.resultats}"
paginator="true"
rows="15"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="10,15,25,50"
currentPageReportTemplate="Affichage {startRecord}-{endRecord} sur {totalRecords}"
selection="#{membreRechercheBean.selectedMembres}"
rowKey="#{membre.id}"
selectionMode="multiple"
emptyMessage="Aucun membre ne correspond aux critères de recherche">
<f:facet name="header">
<div class="flex align-items-center justify-content-between">
<span>Liste des membres</span>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="" />
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{membreRechercheBean.actualiserResultats}" />
<ui:param name="update" value=":formResultats:dtResultats" />
<ui:param name="title" value="Actualiser" />
<ui:param name="outlined" value="true" />
<ui:param name="styleClass" value="ui-button-sm" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-cog" />
<ui:param name="onclick" value="PF('dlgOptionsAffichage').show();" />
<ui:param name="title" value="Options d'affichage" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</div>
</f:facet>
<p:column selectionMode="multiple" style="width:50px" />
<p:column headerText="N° Membre" sortBy="#{membre.numeroMembre}" style="width:120px">
<h:outputText value="#{membre.numeroMembre}" styleClass="font-mono font-bold" />
</p:column>
<p:column headerText="Membre" sortBy="#{membre.nom}">
<div class="flex align-items-center">
<div class="border-circle overflow-hidden mr-3"
style="width: 40px; height: 40px;">
<h:graphicImage value="#{membre.photoUrl}"
style="width: 100%; height: 100%; object-fit: cover;"
rendered="#{membre.photoUrl != null}" />
<div class="bg-primary text-white flex align-items-center justify-content-center w-full h-full"
rendered="#{membre.photoUrl == null}">
<span style="font-size: 0.9rem;">#{membre.initiales}</span>
</div>
</div>
<div>
<div class="font-medium text-900">#{membre.nomComplet}</div>
<div class="text-600 text-sm">
<span>#{membre.telephone}</span>
<span class="mx-2"></span>
<span>#{membre.email}</span>
</div>
</div>
</div>
</p:column>
<p:column headerText="Type" sortBy="#{membre.typeMembre}" style="width:120px">
<p:tag value="#{membre.typeMembre}"
severity="#{membre.typeSeverity}"
icon="pi #{membre.typeIcon}" />
</p:column>
<p:column headerText="Statut" sortBy="#{membre.statut}" style="width:100px">
<p:tag value="#{membre.statut}"
severity="#{membre.statutSeverity}"
icon="pi #{membre.statutIcon}" />
</p:column>
<p:column headerText="Entité" sortBy="#{membre.entite}" style="width:150px">
<h:outputText value="#{membre.entite}" />
</p:column>
<p:column headerText="Adhésion" sortBy="#{membre.dateAdhesion}" style="width:120px">
<div>
<div class="font-medium">#{membre.dateAdhesion}</div>
<small class="text-600">#{membre.anciennete}</small>
</div>
</p:column>
<p:column headerText="Cotisations" style="width:120px">
<div class="text-center">
<div class="font-bold #{membre.cotisationColor}">#{membre.cotisationStatut}</div>
<small class="text-600">#{membre.dernierPaiement}</small>
</div>
</p:column>
<p:column headerText="Participation" style="width:100px">
<div class="text-center">
<div class="font-bold text-blue-500">#{membre.tauxParticipation}%</div>
<small class="text-600">#{membre.evenementsAnnee} événements</small>
</div>
</p:column>
<p:column headerText="Actions" style="width:150px">
<div class="flex gap-1">
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-eye" />
<ui:param name="action" value="#{membreRechercheBean.voirProfil(membre)}" />
<ui:param name="title" value="Voir profil" />
<ui:param name="severity" value="info" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-envelope" />
<ui:param name="action" value="#{membreRechercheBean.contacterMembre(membre)}" />
<ui:param name="title" value="Contacter" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="action" value="#{membreRechercheBean.ajouterAuGroupe(membre)}" />
<ui:param name="title" value="Ajouter au groupe de travail" />
<ui:param name="severity" value="success" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="true" />
</ui:include>
</div>
</p:column>
</p:dataTable>
<!-- Actions groupées -->
<div class="mt-3 flex justify-content-between align-items-center">
<div>
<span class="text-600">#{membreRechercheBean.selectedMembres.size()} membre(s) sélectionné(s)</span>
</div>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-info.xhtml">
<ui:param name="value" value="Envoyer message groupé" />
<ui:param name="icon" value="pi pi-envelope" />
<ui:param name="onclick" value="PF('dlgMessageGroupe').show();" />
<ui:param name="outlined" value="true" />
<ui:param name="disabled" value="#{empty membreRechercheBean.selectedMembres}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Créer groupe de travail" />
<ui:param name="icon" value="pi pi-users" />
<ui:param name="onclick" value="PF('dlgCreerGroupe').show();" />
<ui:param name="outlined" value="true" />
<ui:param name="disabled" value="#{empty membreRechercheBean.selectedMembres}" />
</ui:include>
<ui:include src="/templates/components/buttons/button-warning.xhtml">
<ui:param name="value" value="Exporter sélection" />
<ui:param name="icon" value="pi pi-file-excel" />
<ui:param name="action" value="#{membreRechercheBean.exporterSelection}" />
<ui:param name="outlined" value="true" />
<ui:param name="disabled" value="#{empty membreRechercheBean.selectedMembres}" />
</ui:include>
</div>
</div>
</h:form>
</div>
<!-- Dialog Sauvegarder Recherche -->
<p:dialog header="Sauvegarder la Recherche" widgetVar="dlgSauvegarderRecherche" modal="true" width="500">
<h:form id="formSauvegarderRecherche">
<div class="ui-fluid">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="nomRecherche" />
<ui:param name="label" value="Nom de la recherche" />
<ui:param name="value" value="#{membreRechercheBean.nouvelleRechercheSauvegardee.nom}" />
<ui:param name="required" value="true" />
<ui:param name="placeholder" value="Ex: Membres actifs 2024" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="descriptionRecherche" />
<ui:param name="label" value="Description" />
<ui:param name="value" value="#{membreRechercheBean.nouvelleRechercheSauvegardee.description}" />
<ui:param name="rows" value="3" />
</ui:include>
<div class="field">
<p:selectBooleanCheckbox id="recherchePublique" value="#{membreRechercheBean.nouvelleRechercheSauvegardee.publique}" />
<p:outputLabel for="recherchePublique" value=" Partager avec les autres administrateurs" />
</div>
<div class="surface-50 p-3 border-round">
<div class="font-medium mb-2">Critères à sauvegarder :</div>
<div class="text-600 text-sm">#{membreRechercheBean.statistiques.filtresActifs} filtre(s) actif(s) seront sauvegardés</div>
</div>
</div>
<div class="flex gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Sauvegarder" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{membreRechercheBean.sauvegarderRecherche}" />
<ui:param name="update" value=":formSauvegarderRecherche" />
<ui:param name="onclick" value="if(!args.validationFailed) PF('dlgSauvegarderRecherche').hide();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgSauvegarderRecherche').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Recherches Sauvegardées -->
<p:dialog header="Recherches Sauvegardées" widgetVar="dlgRecherchesSauvegardees" modal="true" width="700">
<h:form id="formRecherchesSauvegardees">
<p:dataTable value="#{membreRechercheBean.recherchesSauvegardees}" var="recherche"
styleClass="p-datatable-sm" emptyMessage="Aucune recherche sauvegardée">
<p:column headerText="Nom">
<div>
<div class="font-medium">#{recherche.nom}</div>
<small class="text-600">#{recherche.description}</small>
</div>
</p:column>
<p:column headerText="Critères">
<p:tag value="#{recherche.nombreCriteres} critères" severity="info" />
</p:column>
<p:column headerText="Créée le">
<h:outputText value="#{recherche.dateCreation}">
<f:convertDateTime pattern="dd/MM/yyyy" type="localDate" />
</h:outputText>
</p:column>
<p:column headerText="Publique">
<p:tag value="#{recherche.publique ? 'Oui' : 'Non'}"
severity="#{recherche.publique ? 'success' : 'secondary'}" />
</p:column>
<p:column headerText="Actions">
<div class="flex gap-1">
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-play" />
<ui:param name="action" value="#{membreRechercheBean.chargerRecherche(recherche)}" />
<ui:param name="update" value=":formRechercheAvancee :formResultats" />
<ui:param name="onclick" value="PF('dlgRecherchesSauvegardees').hide();" />
<ui:param name="title" value="Charger" />
<ui:param name="severity" value="success" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-trash" />
<ui:param name="action" value="#{membreRechercheBean.supprimerRecherche(recherche)}" />
<ui:param name="update" value=":formRecherchesSauvegardees" />
<ui:param name="onclick" value="return confirm('Supprimer cette recherche ?');" />
<ui:param name="title" value="Supprimer" />
<ui:param name="severity" value="danger" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="true" />
</ui:include>
</div>
</p:column>
</p:dataTable>
<div class="flex justify-content-end mt-3">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Fermer" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgRecherchesSauvegardees').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
<!-- Dialog Message Groupé -->
<p:dialog header="Envoyer un Message Groupé" widgetVar="dlgMessageGroupe" modal="true" width="600">
<h:form id="formMessageGroupe">
<div class="ui-fluid">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="sujetMessageGroupe" />
<ui:param name="label" value="Sujet" />
<ui:param name="value" value="#{membreRechercheBean.messageGroupe.sujet}" />
<ui:param name="required" value="true" />
<ui:param name="placeholder" value="Objet du message" />
</ui:include>
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="contenuMessageGroupe" />
<ui:param name="label" value="Message" />
<ui:param name="value" value="#{membreRechercheBean.messageGroupe.contenu}" />
<ui:param name="required" value="true" />
<ui:param name="rows" value="6" />
</ui:include>
<div class="field">
<p:outputLabel for="canauxMessageGroupe" value="Canaux de diffusion" />
<p:selectCheckboxMenu id="canauxMessageGroupe" value="#{membreRechercheBean.messageGroupe.canaux}"
multiple="true" styleClass="w-full">
<f:selectItem itemLabel="📧 Email" itemValue="EMAIL" />
<f:selectItem itemLabel="📱 SMS" itemValue="SMS" />
<f:selectItem itemLabel="💬 WhatsApp" itemValue="WHATSAPP" />
<f:selectItem itemLabel="🔔 Notification push" itemValue="PUSH" />
</p:selectCheckboxMenu>
</div>
<div class="surface-50 p-3 border-round">
<div class="font-medium mb-2">Destinataires :</div>
<div class="text-600">#{membreRechercheBean.selectedMembres.size()} membre(s) recevront ce message</div>
</div>
</div>
<div class="flex gap-2 mt-3">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Envoyer" />
<ui:param name="icon" value="pi pi-send" />
<ui:param name="action" value="#{membreRechercheBean.envoyerMessageGroupe}" />
<ui:param name="update" value=":formMessageGroupe :formResultats" />
<ui:param name="onclick" value="if(!args.validationFailed) PF('dlgMessageGroupe').hide();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler" />
<ui:param name="icon" value="pi pi-times" />
<ui:param name="onclick" value="PF('dlgMessageGroupe').hide();" />
</ui:include>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,263 @@
<!DOCTYPE html>
<html 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">
<ui:composition template="/templates/main-template.xhtml">
<ui:param name="page" value="#{organisationDetailBean}"/>
<ui:define name="title">Détail de l'Organisation</ui:define>
<ui:define name="content">
<h:form id="formDetail">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête résumé -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div class="flex align-items-center gap-3 mb-2 md:mb-0">
<ui:include src="/templates/components/layout/organisation-logo.xhtml">
<ui:param name="logo" value="#{organisationDetailBean.organisation.logo}"/>
<ui:param name="size" value="64"/>
</ui:include>
<div>
<h3 class="m-0">
<h:outputText value="#{empty organisationDetailBean.organisation ? 'Organisation introuvable' : organisationDetailBean.organisation.nom}" />
</h3>
<div class="mt-2 flex align-items-center gap-2">
<p:tag value="#{organisationDetailBean.organisation.typeLibelle}" severity="info" />
<p:tag value="#{organisationDetailBean.organisation.statutLibelle}"
severity="#{organisationDetailBean.organisation.statutSeverity}" />
</div>
</div>
</div>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Retour à la liste"/>
<ui:param name="icon" value="pi pi-arrow-left"/>
<ui:param name="outcome" value="/pages/secure/organisation/liste"/>
</ui:include>
</div>
</div>
</div>
<h:panelGroup rendered="#{not empty organisationDetailBean.organisation}">
<div class="grid">
<!-- Bloc identité -->
<div class="col-12 md:col-6">
<div class="card">
<h5 class="mb-3">Identité</h5>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Nom complet"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.nom}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Nom court / Sigle"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.nomCourt}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Type"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.typeLibelle}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Statut"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.statutLibelle}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Date de fondation"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.dateFondation}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Numéro d'enregistrement"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.numeroRegistre}"/>
</ui:include>
</div>
</div>
<!-- Bloc contact -->
<div class="col-12 md:col-6">
<div class="card">
<h5 class="mb-3">Contacts</h5>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Email"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.email}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Email secondaire"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.emailSecondaire}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Téléphone"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.telephone}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Téléphone secondaire"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.telephoneSecondaire}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Site web"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.siteWeb}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Responsable principal"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.responsablePrincipal}"/>
</ui:include>
</div>
</div>
<!-- Bloc localisation -->
<div class="col-12 md:col-6">
<div class="card">
<h5 class="mb-3">Localisation</h5>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Adresse complète"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.adresseComplete}"/>
<ui:param name="multiline" value="true"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Ville"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.ville}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Région"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.region}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Pays"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.pays}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Code postal"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.codePostal}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Latitude"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.latitude}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Longitude"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.longitude}"/>
</ui:include>
</div>
</div>
<!-- Bloc description, objectifs et activités -->
<div class="col-12 md:col-6">
<div class="card">
<h5 class="mb-3">Description, objectifs &amp; activités</h5>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Description"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.description}"/>
<ui:param name="multiline" value="true"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Objectifs"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.objectifs}"/>
<ui:param name="multiline" value="true"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Activités principales"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.activitesPrincipales}"/>
<ui:param name="multiline" value="true"/>
</ui:include>
</div>
</div>
<!-- Bloc gouvernance & membres -->
<div class="col-12 md:col-6">
<div class="card">
<h5 class="mb-3">Gouvernance &amp; membres</h5>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Nombre de membres"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.nombreMembres}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Nombre d'administrateurs"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.nombreAdministrateurs}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Organisation publique"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.organisationPublique ? 'Oui' : 'Non'}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Accepte de nouveaux membres"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.accepteNouveauxMembres ? 'Oui' : 'Non'}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Cotisation obligatoire"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.cotisationObligatoire ? 'Oui' : 'Non'}"/>
</ui:include>
</div>
</div>
<!-- Bloc budget & cotisations -->
<div class="col-12 md:col-6">
<div class="card">
<h5 class="mb-3">Budget &amp; cotisations</h5>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Budget annuel"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.budgetAnnuel}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Devise"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.devise}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Montant cotisation annuelle"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.montantCotisationAnnuelle}"/>
</ui:include>
</div>
</div>
<!-- Bloc réseaux & partenariats -->
<div class="col-12 md:col-6">
<div class="card">
<h5 class="mb-3">Réseaux &amp; partenariats</h5>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Réseaux sociaux"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.reseauxSociaux}"/>
<ui:param name="multiline" value="true"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Certifications / labels"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.certifications}"/>
<ui:param name="multiline" value="true"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Partenaires principaux"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.partenaires}"/>
<ui:param name="multiline" value="true"/>
</ui:include>
</div>
</div>
<!-- Bloc notes & hiérarchie -->
<div class="col-12 md:col-6">
<div class="card">
<h5 class="mb-3">Notes &amp; hiérarchie</h5>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Organisation parente"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.nomOrganisationParente}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="ID organisation parente"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.organisationParenteId}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Niveau hiérarchique"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.niveauHierarchique}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Notes administratives"/>
<ui:param name="value" value="#{organisationDetailBean.organisation.notes}"/>
<ui:param name="multiline" value="true"/>
</ui:include>
</div>
</div>
</div>
</h:panelGroup>
</h:form>
</ui:define>
</ui:composition>
</html>

View File

@@ -0,0 +1,251 @@
<!DOCTYPE html>
<html 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"
xmlns:uf="http://xmlns.jcp.org/jsf/composite/components">
<ui:composition template="/templates/main-template.xhtml">
<ui:param name="page" value="#{organisationsBean}"/>
<ui:define name="title">Gestion des Organisations</ui:define>
<ui:define name="content">
<h:form id="formOrganisations">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête avec titre et action principale (DRY/WOU: card-header) -->
<ui:decorate template="/templates/components/cards/card-header.xhtml">
<ui:param name="title" value="Gestion des Organisations" />
<ui:param name="subtitle" value="Liste complète des organisations avec filtres et actions." />
<ui:param name="styleClass" value="mb-3" />
<ui:define name="actions">
<p:button value="Nouvelle Organisation"
icon="pi pi-plus"
outcome="/pages/secure/organisation/nouvelle"
styleClass="ui-button-success" />
</ui:define>
</ui:decorate>
<!-- Statistiques (DRY/WOU: stat-card) -->
<div class="grid mb-3">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{organisationsBean.totalOrganisations}" />
<ui:param name="label" value="Total" />
<ui:param name="icon" value="pi pi-building" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{organisationsBean.organisationsActives}" />
<ui:param name="label" value="Actives" />
<ui:param name="icon" value="pi pi-check-circle" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{organisationsBean.organisationsInactives}" />
<ui:param name="label" value="Inactives" />
<ui:param name="icon" value="pi pi-times-circle" />
<ui:param name="bgColor" value="orange" />
</ui:include>
</div>
<!-- Filtres et recherche (DRY/WOU: filter-bar) -->
<ui:decorate template="/templates/components/cards/filter-bar.xhtml">
<ui:param name="title" value="Filtres" />
<ui:param name="styleClass" value="mb-3" />
<ui:define name="filters">
<div class="col-12 md:col-4">
<div class="field">
<p:outputLabel for="rechercheGlobale" value="Rechercher" />
<p:inputText id="rechercheGlobale"
value="#{organisationsBean.rechercheGlobale}"
placeholder="Nom, ville, description..."
styleClass="w-full">
<p:ajax event="keyup" update="dtOrganisations" listener="#{organisationsBean.appliquerFiltres}" delay="500"/>
</p:inputText>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreStatut" value="Statut" />
<p:selectOneMenu id="filtreStatut"
value="#{organisationsBean.filtreStatut}"
styleClass="w-full">
<f:selectItems value="#{organisationsBean.statutsSelectItems}" />
<p:ajax event="change" update="dtOrganisations" listener="#{organisationsBean.appliquerFiltres}"/>
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<p:outputLabel for="filtreType" value="Type" />
<p:selectOneMenu id="filtreType"
value="#{organisationsBean.filtreType}"
styleClass="w-full">
<f:selectItems value="#{organisationsBean.typesSelectItems}" />
<p:ajax event="change" update="dtOrganisations" listener="#{organisationsBean.appliquerFiltres}"/>
</p:selectOneMenu>
</div>
</div>
</ui:define>
<ui:define name="actions">
<div class="col-12 md:col-2">
<div class="field">
<label class="invisible">Actions</label>
<p:commandButton value="Réinitialiser"
icon="pi pi-filter-slash"
action="#{organisationsBean.reinitialiserFiltres}"
update="dtOrganisations rechercheGlobale filtreStatut filtreType"
styleClass="ui-button-secondary w-full" />
</div>
</div>
<div class="col-12 md:col-2">
<div class="field">
<label class="invisible">Actions</label>
<p:commandButton value="Rafraîchir"
icon="pi pi-refresh"
action="#{organisationsBean.recharger}"
update="@form"
styleClass="ui-button-secondary w-full" />
</div>
</div>
</ui:define>
</ui:decorate>
<!-- Table des organisations (DRY/WOU: card-simple) -->
<ui:decorate template="/templates/components/cards/card-simple.xhtml">
<ui:param name="title" value="Liste des Organisations" />
<ui:define name="content">
<!-- Note: p:dataTable avec var, sortBy, filterBy doit être directement dans la page -->
<p:dataTable id="dtOrganisations"
value="#{organisationsBean.organisationsFiltrees}"
var="org"
paginator="true"
rows="20"
rowsPerPageTemplate="10,20,50,100"
paginatorPosition="bottom"
emptyMessage="Aucune organisation trouvée"
styleClass="table-responsive"
size="small">
<!-- Logo (DRY/WOU: organisation-logo) -->
<p:column headerText="" style="width: 80px;">
<ui:include src="/templates/components/layout/organisation-logo.xhtml">
<ui:param name="logo" value="#{org.logo}"/>
<ui:param name="size" value="40"/>
</ui:include>
</p:column>
<!-- Nom avec sous-titre -->
<p:column headerText="Nom" sortBy="#{org.nom}" filterBy="#{org.nom}">
<h:outputText value="#{org.nom}" styleClass="font-bold"/>
<br/>
<h:outputText value="#{org.typeLibelle}" styleClass="text-sm text-500"/>
</p:column>
<!-- Type -->
<p:column headerText="Type" sortBy="#{org.typeAssociation}" style="width: 150px;">
<p:tag value="#{org.typeLibelle}"
severity="#{org.typeAssociation == 'LIONS_CLUB' ? 'info' : 'primary'}"/>
</p:column>
<!-- Localisation -->
<p:column headerText="Localisation" style="width: 200px;">
<i class="pi pi-map-marker mr-2 text-500"/>
<h:outputText value="#{org.ville}, #{org.region}"/>
</p:column>
<!-- Membres -->
<p:column headerText="Membres" styleClass="text-center" style="width: 100px;">
<p:tag value="#{org.nombreMembres}" severity="info" icon="pi pi-users"/>
</p:column>
<!-- Statut -->
<p:column headerText="Statut" sortBy="#{org.statut}" styleClass="text-center" style="width: 100px;">
<p:tag value="#{org.statut}"
severity="#{org.statut == organisationsBean.statutActive ? 'success' : 'warning'}"
icon="#{org.statut == organisationsBean.statutActive ? 'pi pi-check' : 'pi pi-times'}"/>
</p:column>
<!-- Actions (DRY/WOU: Composite Components) -->
<p:column headerText="Actions" style="width:200px">
<div class="flex gap-1">
<!-- DRY/WOU: Composite Component action-button-view -->
<uf:action-button-view itemId="#{org.id.toString()}"
detailPage="/pages/secure/organisation/detail.xhtml"
iconOnly="true"/>
<!-- DRY/WOU: button-icon pour Modifier -->
<p:commandButton icon="pi pi-pencil"
actionListener="#{organisationsBean.setOrganisationSelectionnee(org)}"
oncomplete="PF('dlgModifier').show();"
update=":formModifier"
styleClass="ui-button-rounded ui-button-warning"
title="Modifier"/>
<!-- DRY/WOU: button-icon pour Activer/Désactiver -->
<p:commandButton icon="#{org.statut == organisationsBean.statutActive ? 'pi pi-ban' : 'pi pi-check'}"
actionListener="#{organisationsBean.basculerStatutOrganisation(org)}"
update=":formOrganisations:dtOrganisations :formOrganisations:messages"
styleClass="ui-button-rounded #{org.statut == organisationsBean.statutActive ? 'ui-button-secondary' : 'ui-button-success'}"
title="#{org.statut == organisationsBean.statutActive ? 'Désactiver' : 'Activer'}">
<p:confirm header="Confirmation"
message="Êtes-vous sûr de vouloir changer le statut de cette organisation ?"
icon="pi pi-exclamation-triangle"/>
</p:commandButton>
<!-- DRY/WOU: button-icon pour Supprimer -->
<p:commandButton icon="pi pi-trash"
actionListener="#{organisationsBean.supprimerOrganisation(org)}"
update=":formOrganisations:dtOrganisations :formOrganisations:messages"
styleClass="ui-button-rounded ui-button-danger"
title="Supprimer">
<p:confirm header="Confirmation"
message="Êtes-vous sûr de vouloir supprimer cette organisation ? Cette action est irréversible."
icon="pi pi-exclamation-triangle"/>
</p:commandButton>
</div>
</p:column>
</p:dataTable>
</ui:define>
</ui:decorate>
<!-- Dialogue de confirmation global (DRY/WOU: confirm-dialog) -->
<ui:include src="/templates/components/dialogs/confirm-dialog.xhtml" />
</h:form>
<!-- Dialogue Modifier Organisation (DRY/WOU: form-dialog) -->
<ui:decorate template="/templates/components/dialogs/form-dialog.xhtml">
<ui:param name="dialogId" value="dlgModifier" />
<ui:param name="header" value="Modifier Organisation" />
<ui:param name="widgetVar" value="dlgModifier" />
<ui:param name="formId" value="formModifier" />
<ui:param name="width" value="900" />
<ui:param name="maximizable" value="true" />
<ui:param name="fitViewport" value="true" />
<ui:define name="content">
<ui:fragment rendered="#{organisationsBean.organisationSelectionnee != null}">
<ui:include src="/ui/includes/organisation-form.xhtml">
<ui:param name="model" value="#{organisationsBean.organisationSelectionnee}" />
<ui:param name="typesItems" value="#{organisationsBean.typesSelectItemsForForm}" />
</ui:include>
</ui:fragment>
</ui:define>
<ui:define name="footer">
<!-- Bouton Annuler : type="button" pour éviter la soumission -->
<p:commandButton value="Annuler"
icon="pi pi-times"
type="button"
onclick="PF('dlgModifier').hide();"
styleClass="ui-button-secondary" />
<!-- DRY/WOU: button-form-submit pour action backend -->
<ui:decorate template="/templates/components/buttons/button-form-submit.xhtml">
<ui:param name="value" value="Enregistrer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{organisationsBean.modifierOrganisation}" />
<ui:param name="update" value=":formOrganisations:dtOrganisations :formOrganisations:messages" />
<ui:param name="oncomplete" value="if(!args.validationFailed) PF('dlgModifier').hide();" />
<ui:param name="severity" value="success" />
</ui:decorate>
</ui:define>
</ui:decorate>
</ui:define>
</ui:composition>
</html>

View File

@@ -0,0 +1,64 @@
<!DOCTYPE html>
<html 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">
<ui:composition template="/templates/main-template.xhtml">
<ui:param name="page" value="#{organisationsBean}"/>
<ui:define name="title">Nouvelle Organisation</ui:define>
<ui:define name="content">
<!-- Initialiser le modèle et le catalogue des types à chaque affichage de la vue -->
<f:event type="preRenderView" listener="#{organisationsBean.preparerNouvelleOrganisation}" />
<h:form id="formNouvelleOrganisation">
<p:messages id="messages" showDetail="true" closable="true"/>
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div class="mb-2 md:mb-0">
<h3 class="m-0">Nouvelle Organisation</h3>
<span class="text-600">
Renseignez l'ensemble des informations de l'organisation.
</span>
</div>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler"/>
<ui:param name="icon" value="pi pi-times"/>
<ui:param name="outcome" value="/pages/secure/organisation/liste"/>
</ui:include>
</div>
</div>
</div>
<div class="card">
<h5 class="mb-3">Informations de l'Organisation</h5>
<ui:include src="/ui/includes/organisation-form.xhtml">
<ui:param name="model" value="#{organisationsBean.nouvelleOrganisation}" />
<ui:param name="typesItems" value="#{organisationsBean.typesSelectItemsForForm}" />
</ui:include>
</div>
<div class="mt-3 flex justify-content-end gap-2">
<!-- DRY/WOU: button-secondary pour navigation -->
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Annuler"/>
<ui:param name="icon" value="pi pi-times"/>
<ui:param name="outcome" value="/pages/secure/organisation/liste"/>
</ui:include>
<!-- Bouton Créer : p:commandButton direct car action avec méthode backend -->
<p:commandButton value="Créer"
icon="pi pi-check"
action="#{organisationsBean.creerOrganisation}"
update=":formNouvelleOrganisation:messages"
styleClass="ui-button-success" />
</div>
</h:form>
</ui:define>
</ui:composition>
</html>

View File

@@ -0,0 +1,100 @@
<!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:param name="page" value="#{personnelBean}"/>
<ui:define name="title">Mes Activités - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-history text-purple-500" />
<ui:param name="title" value="Mes Activités" />
<ui:param name="description" value="Suivez toutes vos interactions et participations dans UnionFlow" />
<ui:define name="actions">
<h:form id="formActions">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Filtrer" />
<ui:param name="icon" value="pi pi-filter" />
<ui:param name="onclick" value="PF('dlgFiltres').show();" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques d'activité -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{personnelBean.statistiques.actionsRealisees}" />
<ui:param name="label" value="Actions Totales" />
<ui:param name="subLabel" value="Toutes périodes" />
<ui:param name="icon" value="pi pi-check-circle" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{personnelBean.statistiques.evenementsParticipes}" />
<ui:param name="label" value="Événements" />
<ui:param name="subLabel" value="Participés" />
<ui:param name="icon" value="pi pi-calendar" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{personnelBean.statistiques.tauxParticipation}%" />
<ui:param name="label" value="Taux Participation" />
<ui:param name="subLabel" value="Global" />
<ui:param name="icon" value="pi pi-chart-line" />
<ui:param name="bgColor" value="purple" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="8h" />
<ui:param name="label" value="Temps Connecté" />
<ui:param name="subLabel" value="Cette semaine" />
<ui:param name="icon" value="pi pi-clock" />
<ui:param name="bgColor" value="orange" />
</ui:include>
</div>
<!-- Activités récentes -->
<div class="card">
<h5>Activités Récentes</h5>
<ui:repeat value="#{personnelBean.activitesRecentes}" var="activite">
<div class="surface-100 hover:surface-200 border-round p-4 mb-3 cursor-pointer transition-duration-200">
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-3">
<div class="w-3rem h-3rem border-circle bg-#{activite.couleur}-100 flex align-items-center justify-content-center">
<i class="pi #{activite.icon} text-#{activite.couleur}-600 text-xl"></i>
</div>
<div>
<h6 class="text-900 font-semibold mb-1">#{activite.titre}</h6>
<p class="text-600 text-sm mb-0">#{activite.description}</p>
</div>
</div>
<div class="text-right">
<div class="text-900 font-semibold text-sm">#{activite.dateHeure}</div>
</div>
</div>
</div>
</ui:repeat>
<div class="text-center text-600 text-sm" rendered="#{empty personnelBean.activitesRecentes}">
Aucune activité récente
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,87 @@
<!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:param name="page" value="#{personnelBean}"/>
<ui:define name="title">Mon Agenda - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-calendar text-blue-500" />
<ui:param name="title" value="Mon Agenda" />
<ui:param name="description" value="Organisez votre planning et ne manquez aucun événement important" />
<ui:define name="actions">
<h:form id="formActions">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Synchroniser" />
<ui:param name="icon" value="pi pi-sync" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Nouvel Événement" />
<ui:param name="icon" value="pi pi-plus" />
<ui:param name="onclick" value="PF('nouvelEvenementDialog').show();" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques agenda -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="7" />
<ui:param name="label" value="Cette Semaine" />
<ui:param name="subLabel" value="Événements" />
<ui:param name="icon" value="pi pi-calendar" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="3" />
<ui:param name="label" value="Aujourd'hui" />
<ui:param name="subLabel" value="Rendez-vous" />
<ui:param name="icon" value="pi pi-clock" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{personnelBean.statistiques.evenementsParticipes}" />
<ui:param name="label" value="Ce Mois" />
<ui:param name="subLabel" value="Total" />
<ui:param name="icon" value="pi pi-calendar-times" />
<ui:param name="bgColor" value="purple" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{personnelBean.statistiques.tauxParticipation}%" />
<ui:param name="label" value="Taux Présence" />
<ui:param name="subLabel" value="Moyenne" />
<ui:param name="icon" value="pi pi-chart-bar" />
<ui:param name="bgColor" value="orange" />
</ui:include>
</div>
<!-- Calendrier -->
<div class="card">
<h5>Calendrier Mensuel</h5>
<p:schedule value="#{evenementsBean.evenementsCalendrier}"
widgetVar="scheduleWidget"
view="month"
locale="fr"
timeZone="Africa/Dakar"
styleClass="w-full"
height="600">
<p:ajax event="dateSelect" listener="#{evenementsBean.onDateSelect}" />
<p:ajax event="eventSelect" listener="#{evenementsBean.onEventSelect}" />
</p:schedule>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,146 @@
<!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:param name="page" value="#{personnelBean}"/>
<ui:define name="title">Mes Documents - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-folder text-green-500" />
<ui:param name="title" value="Mes Documents" />
<ui:param name="description" value="Gérez vos documents personnels et accédez aux fichiers partagés" />
<ui:define name="actions">
<h:form id="formActions">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Nouveau Dossier" />
<ui:param name="icon" value="pi pi-folder-plus" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Télécharger" />
<ui:param name="icon" value="pi pi-upload" />
<ui:param name="onclick" value="PF('uploadDialog').show();" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques stockage -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{personnelBean.documents != null ? personnelBean.documents.size() : 0}" />
<ui:param name="label" value="Documents" />
<ui:param name="subLabel" value="Personnels" />
<ui:param name="icon" value="pi pi-file" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="2.4 GB" />
<ui:param name="label" value="Utilisé" />
<ui:param name="subLabel" value="Sur 5 GB" />
<ui:param name="icon" value="pi pi-database" />
<ui:param name="bgColor" value="green" />
</ui:include>
</div>
<!-- Liste des documents -->
<div class="card">
<h5>Mes Documents</h5>
<p:dataTable value="#{personnelBean.documents}" var="document"
emptyMessage="Aucun document disponible"
styleClass="p-datatable-sm">
<p:column headerText="Nom">
<div class="flex align-items-center gap-2">
<i class="pi pi-file text-lg"></i>
<span class="font-semibold">#{document.nom}</span>
</div>
</p:column>
<p:column headerText="Type">
<span>#{document.type}</span>
</p:column>
<p:column headerText="Date">
<span>#{document.dateCreation}</span>
</p:column>
<p:column headerText="Taille">
<span>#{document.taille} bytes</span>
</p:column>
<p:column headerText="Actions" styleClass="text-center">
<div class="flex justify-content-center gap-1">
<p:commandButton icon="pi pi-eye"
title="Voir"
styleClass="p-button-sm p-button-rounded p-button-info" />
<p:commandButton icon="pi pi-download"
title="Télécharger"
styleClass="p-button-sm p-button-rounded p-button-success" />
</div>
</p:column>
</p:dataTable>
</div>
<!-- Dialog Upload -->
<h:form id="formUpload">
<p:dialog id="uploadDialog"
widgetVar="uploadDialog"
header="Télécharger des Documents"
modal="true"
resizable="false"
style="width: 90vw; max-width: 700px;">
<div class="grid">
<div class="col-12">
<div class="field">
<p:outputLabel for="dossierDestination" value="Dossier de destination" />
<p:selectOneMenu id="dossierDestination" styleClass="w-full">
<f:selectItem itemLabel="Documents Personnels" itemValue="personnel" />
<f:selectItem itemLabel="Certificats" itemValue="certificats" />
<f:selectItem itemLabel="Formations" itemValue="formations" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12">
<div class="field">
<p:outputLabel for="fichierUpload" value="Fichier" />
<p:fileUpload id="fichierUpload"
mode="advanced"
multiple="true"
uploadLabel="Télécharger"
cancelLabel="Annuler"
chooseLabel="Choisir les fichiers"
sizeLimit="10485760"
allowTypes="/(\.|\/)(gif|jpe?g|png|pdf|docx?|xlsx?|pptx?)$/" />
</div>
</div>
</div>
<f:facet name="footer">
<div class="flex justify-content-end gap-2">
<p:commandButton value="Annuler"
styleClass="p-button-outlined"
onclick="PF('uploadDialog').hide();"
type="button" />
<p:commandButton value="Télécharger"
icon="pi pi-upload"
styleClass="p-button-primary"
action="#{personnelBean.actualiser}" />
</div>
</f:facet>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,374 @@
<!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:param name="page" value="#{personnelBean}"/>
<ui:define name="title">Mes Favoris - UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<div class="flex align-items-center justify-content-between mb-4">
<div>
<h2 class="text-900 font-bold text-4xl mb-2">
<i class="pi pi-star-fill text-yellow-500 mr-3"></i>
Mes Favoris
</h2>
<p class="text-600 text-lg mb-0">
Accédez rapidement à vos pages, documents et fonctionnalités préférés
</p>
</div>
<div class="flex gap-2">
<p:commandButton value="Organiser"
styleClass="p-button-outlined"
icon="pi pi-sort" />
<p:commandButton value="Tout nettoyer"
styleClass="p-button-secondary"
icon="pi pi-trash"
action="#{favorisBean.nettoyerTousFavoris}"
update="@form"
process="@this" />
</div>
</div>
<!-- Statistiques favoris -->
<div class="grid">
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-yellow-500 mb-2">#{favorisBean.totalFavoris}</div>
<div class="text-900 font-semibold mb-1">Favoris</div>
<div class="text-600 text-sm">Total</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-blue-500 mb-2">#{favorisBean.totalPages}</div>
<div class="text-900 font-semibold mb-1">Pages</div>
<div class="text-600 text-sm">Fonctionnalités</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-green-500 mb-2">#{favorisBean.totalDocuments}</div>
<div class="text-900 font-semibold mb-1">Documents</div>
<div class="text-600 text-sm">Fichiers</div>
</div>
</div>
<div class="col-12 lg:col-3">
<div class="surface-100 border-round p-4 text-center" style="min-height: 9rem">
<div class="text-2xl font-bold text-purple-500 mb-2">#{favorisBean.totalContacts}</div>
<div class="text-900 font-semibold mb-1">Contacts</div>
<div class="text-600 text-sm">Personnes</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Accès rapide favoris -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-bolt mr-2"></i>
Accès Rapide
</h4>
<div class="grid">
<ui:repeat value="#{favorisBean.pagesFavorites}" var="page" varStatus="status">
<div class="col-12 lg:col-3">
<div class="surface-#{page.couleur}-50 hover:surface-#{page.couleur}-100 border-round p-4 cursor-pointer transition-duration-200 border-2 border-#{page.couleur}-500">
<div class="flex align-items-center justify-content-between mb-3">
<i class="pi #{page.icon} text-#{page.couleur}-600 text-2xl"></i>
<p:tag value="#{page.estPlusUtilise ? 'PLUS UTILISÉ' : ''}" severity="info" styleClass="text-xs" rendered="#{page.estPlusUtilise}" />
<i class="pi pi-star-fill text-yellow-500" rendered="#{!page.estPlusUtilise}"></i>
</div>
<h6 class="text-#{page.couleur}-800 font-bold mb-2">#{page.titre}</h6>
<p class="text-#{page.couleur}-600 text-sm mb-2">#{page.description}</p>
<div class="flex align-items-center gap-2">
<i class="pi pi-clock text-#{page.couleur}-500"></i>
<span class="text-#{page.couleur}-600 text-xs">#{page.derniereVisite}</span>
</div>
<div class="flex justify-content-end mt-2">
<p:commandButton icon="pi pi-times"
styleClass="p-button-text p-button-sm p-button-rounded"
title="Retirer des favoris"
action="#{favorisBean.retirerPageFavorite(page.id)}"
update="@form"
process="@this" />
</div>
</div>
</div>
</ui:repeat>
<!-- Favori 2 -->
<div class="col-12 lg:col-3">
<div class="surface-green-50 hover:surface-green-100 border-round p-4 cursor-pointer transition-duration-200 border-2 border-green-500">
<div class="flex align-items-center justify-content-between mb-3">
<i class="pi pi-calendar text-green-600 text-2xl"></i>
<i class="pi pi-star-fill text-yellow-500"></i>
</div>
<h6 class="text-green-800 font-bold mb-2">Mon Agenda</h6>
<p class="text-green-600 text-sm mb-2">Planning et événements personnels</p>
<div class="flex align-items-center gap-2">
<i class="pi pi-clock text-green-500"></i>
<span class="text-green-600 text-xs">Utilisé il y a 2h</span>
</div>
</div>
</div>
<!-- Favori 3 -->
<div class="col-12 lg:col-3">
<div class="surface-purple-50 hover:surface-purple-100 border-round p-4 cursor-pointer transition-duration-200 border-2 border-purple-500">
<div class="flex align-items-center justify-content-between mb-3">
<i class="pi pi-users text-purple-600 text-2xl"></i>
<i class="pi pi-star-fill text-yellow-500"></i>
</div>
<h6 class="text-purple-800 font-bold mb-2">Liste des Membres</h6>
<p class="text-purple-600 text-sm mb-2">Annuaire et contacts membres</p>
<div class="flex align-items-center gap-2">
<i class="pi pi-clock text-purple-500"></i>
<span class="text-purple-600 text-xs">Utilisé hier</span>
</div>
</div>
</div>
<!-- Favori 4 -->
<div class="col-12 lg:col-3">
<div class="surface-orange-50 hover:surface-orange-100 border-round p-4 cursor-pointer transition-duration-200 border-2 border-orange-500">
<div class="flex align-items-center justify-content-between mb-3">
<i class="pi pi-dollar text-orange-600 text-2xl"></i>
<i class="pi pi-star-fill text-yellow-500"></i>
</div>
<h6 class="text-orange-800 font-bold mb-2">Cotisations</h6>
<p class="text-orange-600 text-sm mb-2">Paiements et historique</p>
<div class="flex align-items-center gap-2">
<i class="pi pi-clock text-orange-500"></i>
<span class="text-orange-600 text-xs">Utilisé il y a 3 jours</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Pages favorites -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-window-maximize mr-2"></i>
Pages Favorites
</h4>
<div class="grid">
<ui:repeat value="#{favorisBean.pagesFavorites}" var="page" varStatus="status">
<div class="col-12 lg:col-4">
<div class="surface-100 hover:surface-200 border-round p-4 cursor-pointer transition-duration-200">
<div class="flex align-items-center justify-content-between mb-3">
<div class="flex align-items-center gap-2">
<i class="pi #{page.icon} text-#{page.couleur}-500 text-xl"></i>
<h6 class="text-900 font-semibold mb-0">#{page.titre}</h6>
</div>
<div class="flex gap-1">
<i class="pi pi-star-fill text-yellow-500"></i>
<p:commandButton icon="pi pi-times"
styleClass="p-button-text p-button-sm p-button-rounded"
title="Retirer des favoris"
action="#{favorisBean.retirerPageFavorite(page.id)}"
update="@form"
process="@this" />
</div>
</div>
<p class="text-600 text-sm mb-2">#{page.description}</p>
<div class="flex align-items-center gap-2">
<p:tag value="#{page.categorie}" severity="success" styleClass="text-xs" />
<span class="text-500 text-xs">#{page.nbVisites} visite#{page.nbVisites > 1 ? 's' : ''} cette semaine</span>
</div>
</div>
</div>
</ui:repeat>
</div>
<div class="text-center mt-4">
<p:commandButton value="Voir toutes les pages favorites"
styleClass="p-button-outlined"
icon="pi pi-eye" />
</div>
</div>
</div>
</div>
<!-- Documents favoris -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-file mr-2"></i>
Documents Favoris
</h4>
<ui:repeat value="#{favorisBean.documentsFavoris}" var="doc">
<div class="surface-100 hover:surface-200 border-round p-4 mb-3 cursor-pointer transition-duration-200">
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-3">
<div class="w-3rem h-3rem border-circle bg-red-100 flex align-items-center justify-content-center">
<i class="pi pi-file-#{doc.type == 'PDF' ? 'pdf' : doc.type == 'XLSX' ? 'excel' : 'file'} text-red-600 text-xl"></i>
</div>
<div>
<h6 class="text-900 font-semibold mb-1">#{doc.nom}</h6>
<div class="flex align-items-center gap-3 mb-1">
<span class="text-600 text-sm">#{doc.tailleFormatee}</span>
<span class="text-600 text-sm">Ajouté aux favoris le #{doc.dateAjout}</span>
<p:tag value="#{doc.categorie}" severity="success" styleClass="text-xs" />
</div>
<p class="text-700 text-sm mb-0">#{doc.description}</p>
</div>
</div>
<div class="flex gap-2">
<i class="pi pi-star-fill text-yellow-500 text-xl"></i>
<p:commandButton icon="pi pi-download"
styleClass="p-button-outlined p-button-sm"
title="Télécharger" />
<p:commandButton icon="pi pi-times"
styleClass="p-button-text p-button-sm"
title="Retirer des favoris"
action="#{favorisBean.retirerDocumentFavorite(doc.id)}"
update="@form"
process="@this" />
</div>
</div>
</div>
</ui:repeat>
</div>
</div>
</div>
<!-- Contacts favoris -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-users mr-2"></i>
Contacts Favoris
</h4>
<div class="grid">
<ui:repeat value="#{favorisBean.contactsFavoris}" var="contact">
<div class="col-12 lg:col-4">
<div class="surface-100 hover:surface-200 border-round p-4 cursor-pointer transition-duration-200">
<div class="flex align-items-center justify-content-between mb-3">
<div class="flex align-items-center gap-3">
<div class="w-3rem h-3rem border-circle bg-blue-100 flex align-items-center justify-content-center">
<i class="pi pi-user text-blue-600 text-xl"></i>
</div>
<div>
<h6 class="text-900 font-semibold mb-1">#{contact.nom}</h6>
<p class="text-600 text-sm mb-0">#{contact.fonction}</p>
</div>
</div>
<div class="flex gap-2">
<i class="pi pi-star-fill text-yellow-500"></i>
<p:commandButton icon="pi pi-times"
styleClass="p-button-text p-button-sm"
title="Retirer des favoris"
action="#{favorisBean.retirerContactFavorite(contact.id)}"
update="@form"
process="@this" />
</div>
</div>
<div class="flex align-items-center gap-3">
<span class="text-600 text-sm">#{contact.email}</span>
<p:tag value="#{contact.categorie}" severity="warning" styleClass="text-xs" />
</div>
</div>
</div>
</ui:repeat>
</div>
</div>
</div>
</div>
<!-- Raccourcis personnalisés -->
<div class="grid">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-link mr-2"></i>
Raccourcis Personnalisés
</h4>
<div class="grid">
<ui:repeat value="#{favorisBean.raccourcis}" var="racc">
<div class="col-12 lg:col-3">
<div class="surface-100 hover:surface-200 border-round p-4 text-center cursor-pointer transition-duration-200">
<div class="flex align-items-center justify-content-between mb-3">
<i class="pi #{racc.icon} text-#{racc.couleur}-500 text-2xl"></i>
<p:commandButton icon="pi pi-times"
styleClass="p-button-text p-button-sm p-button-rounded"
title="Supprimer"
action="#{favorisBean.supprimerRaccourci(racc.id)}"
update="@form"
process="@this" />
</div>
<h6 class="text-900 font-semibold mb-2">#{racc.titre}</h6>
<p class="text-600 text-sm mb-3">#{racc.description}</p>
<p:commandButton value="Accéder"
styleClass="p-button-outlined p-button-sm w-full"
icon="pi pi-external-link"
onclick="window.location.href='#{racc.url}'; return false;" />
</div>
</div>
</ui:repeat>
<!-- Ajouter nouveau raccourci -->
<div class="col-12 lg:col-3">
<div class="surface-100 hover:surface-200 border-round p-4 text-center cursor-pointer transition-duration-200 border-dashed border-primary">
<i class="pi pi-plus-circle text-primary text-3xl mb-3"></i>
<h6 class="text-primary font-semibold mb-2">Ajouter</h6>
<p class="text-600 text-sm mb-3">Créer un nouveau raccourci</p>
<p:commandButton value="Créer"
styleClass="p-button-primary p-button-sm w-full"
icon="pi pi-plus" />
</div>
</div>
</div>
<!-- Conseils d'utilisation -->
<div class="surface-blue-50 border-left-3 border-blue-500 p-4 mt-4">
<h6 class="text-blue-800 font-semibold mb-2">
<i class="pi pi-info-circle mr-2"></i>Conseils d'utilisation
</h6>
<ul class="list-none p-0 m-0">
<li class="flex align-items-start mb-2">
<i class="pi pi-angle-right text-blue-500 mr-2 mt-1"></i>
<span class="text-blue-700 text-sm">Cliquez sur l'étoile ⭐ à côté des éléments pour les ajouter aux favoris</span>
</li>
<li class="flex align-items-start mb-2">
<i class="pi pi-angle-right text-blue-500 mr-2 mt-1"></i>
<span class="text-blue-700 text-sm">Organisez vos favoris par catégorie pour un accès plus rapide</span>
</li>
<li class="flex align-items-start">
<i class="pi pi-angle-right text-blue-500 mr-2 mt-1"></i>
<span class="text-blue-700 text-sm">Créez des raccourcis personnalisés vers vos actions les plus fréquentes</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,99 @@
<!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:param name="page" value="#{personnelBean}"/>
<ui:define name="title">Mes Notifications - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-bell text-orange-500" />
<ui:param name="title" value="Mes Notifications" />
<ui:param name="description" value="Gérez vos notifications et restez informé des événements importants" />
<ui:define name="actions">
<h:form id="formActions">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Marquer toutes comme lues" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="outlined" value="true" />
</ui:include>
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Paramètres" />
<ui:param name="icon" value="pi pi-cog" />
<ui:param name="outcome" value="/pages/secure/personnel/parametres" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques notifications -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{personnelBean.notifications != null ? personnelBean.notifications.stream().filter(n -> !n.lue).count() : 0}" />
<ui:param name="label" value="Non Lues" />
<ui:param name="subLabel" value="Nouvelles" />
<ui:param name="icon" value="pi pi-bell" />
<ui:param name="bgColor" value="red" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{personnelBean.notifications != null ? personnelBean.notifications.size() : 0}" />
<ui:param name="label" value="Total" />
<ui:param name="subLabel" value="Notifications" />
<ui:param name="icon" value="pi pi-inbox" />
<ui:param name="bgColor" value="blue" />
</ui:include>
</div>
<!-- Liste des notifications -->
<div class="card">
<h5>Notifications Récentes</h5>
<p:dataTable value="#{personnelBean.notifications}" var="notification"
emptyMessage="Aucune notification"
styleClass="p-datatable-sm">
<p:column headerText="Titre">
<div class="flex align-items-center gap-2">
<div class="w-1rem h-1rem border-circle"
styleClass="#{notification.lue ? 'bg-gray-300' : 'bg-blue-500'}"></div>
<span class="font-semibold">#{notification.titre}</span>
</div>
</p:column>
<p:column headerText="Message">
<span>#{notification.message}</span>
</p:column>
<p:column headerText="Date">
<span>#{notification.dateCreation}</span>
</p:column>
<p:column headerText="Statut">
<p:tag value="#{notification.lue ? 'Lue' : 'Non lue'}"
severity="#{notification.lue ? 'success' : 'warning'}" />
</p:column>
<p:column headerText="Actions" styleClass="text-center">
<div class="flex justify-content-center gap-1">
<p:commandButton icon="pi pi-check"
title="Marquer comme lue"
styleClass="p-button-sm p-button-rounded p-button-success"
rendered="#{!notification.lue}" />
<p:commandButton icon="pi pi-trash"
title="Supprimer"
styleClass="p-button-sm p-button-rounded p-button-danger" />
</div>
</p:column>
</p:dataTable>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,704 @@
<!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:param name="page" value="#{personnelBean}"/>
<ui:define name="title">Paramètres Compte - UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<div class="flex align-items-center justify-content-between mb-4">
<div>
<h2 class="text-900 font-bold text-4xl mb-2">
<i class="pi pi-shield text-red-500 mr-3"></i>
Paramètres de Compte
</h2>
<p class="text-600 text-lg mb-0">
Gérez la sécurité, la confidentialité et les paramètres avancés de votre compte
</p>
</div>
<div class="flex gap-2">
<p:commandButton value="Sauvegarder"
styleClass="p-button-primary"
icon="pi pi-save" />
<p:commandButton value="Exporter mes données"
styleClass="p-button-outlined"
icon="pi pi-download" />
</div>
</div>
<!-- Statut sécurité -->
<div class="surface-green-50 border-left-3 border-green-500 p-4">
<div class="flex align-items-center gap-3">
<i class="pi pi-shield text-green-600 text-2xl"></i>
<div>
<h6 class="text-green-800 font-semibold mb-1">Compte sécurisé</h6>
<p class="text-green-700 text-sm mb-0">
Votre compte respecte toutes les bonnes pratiques de sécurité. Score: #{parametresBean.scoreSecurite}/100
</p>
</div>
<div class="ml-auto">
<p:tag value="EXCELLENT" severity="success" styleClass="text-sm" />
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Onglets de paramètres -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<p:tabView styleClass="w-full">
<!-- Onglet Sécurité -->
<p:tab title="Sécurité">
<div class="grid">
<!-- Mot de passe -->
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4 h-full">
<h6 class="text-900 font-semibold mb-4">
<i class="pi pi-key text-blue-500 mr-2"></i>
Mot de Passe
</h6>
<h:form id="passwordForm">
<div class="field">
<label for="currentPassword" class="block text-900 font-semibold mb-2">Mot de passe actuel *</label>
<p:password id="currentPassword"
feedback="false"
toggleMask="true"
placeholder="Saisissez votre mot de passe actuel"
styleClass="w-full" />
</div>
<div class="field">
<label for="newPassword" class="block text-900 font-semibold mb-2">Nouveau mot de passe *</label>
<p:password id="newPassword"
feedback="true"
toggleMask="true"
placeholder="Minimum 8 caractères"
styleClass="w-full" />
</div>
<div class="field">
<label for="confirmPassword" class="block text-900 font-semibold mb-2">Confirmer le mot de passe *</label>
<p:password id="confirmPassword"
feedback="false"
toggleMask="true"
placeholder="Confirmez votre nouveau mot de passe"
styleClass="w-full" />
</div>
<div class="surface-blue-50 border-round p-3 mb-3">
<h6 class="text-blue-800 font-semibold mb-2">Critères de sécurité</h6>
<ul class="list-none p-0 m-0">
<li class="flex align-items-center mb-1">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span class="text-blue-700 text-sm">Au moins 8 caractères</span>
</li>
<li class="flex align-items-center mb-1">
<i class="pi pi-times-circle text-red-500 mr-2"></i>
<span class="text-blue-700 text-sm">Une majuscule</span>
</li>
<li class="flex align-items-center mb-1">
<i class="pi pi-check-circle text-green-500 mr-2"></i>
<span class="text-blue-700 text-sm">Un chiffre</span>
</li>
<li class="flex align-items-center">
<i class="pi pi-times-circle text-red-500 mr-2"></i>
<span class="text-blue-700 text-sm">Un caractère spécial</span>
</li>
</ul>
</div>
<p:commandButton value="Modifier le mot de passe"
styleClass="p-button-primary w-full"
icon="pi pi-save" />
</h:form>
</div>
</div>
<!-- Authentification à deux facteurs -->
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4 h-full">
<h6 class="text-900 font-semibold mb-4">
<i class="pi pi-mobile text-green-500 mr-2"></i>
Authentification à Deux Facteurs (2FA)
</h6>
<div class="surface-green-50 border-left-3 border-green-500 p-3 mb-4">
<div class="flex align-items-center justify-content-between">
<div>
<h6 class="text-green-800 font-semibold mb-1">2FA Activée</h6>
<p class="text-green-700 text-sm mb-0">Votre compte est protégé par l'authentification à deux facteurs</p>
</div>
<p:inputSwitch value="true" />
</div>
</div>
<div class="mb-3">
<h6 class="text-900 font-semibold mb-2">Méthode configurée</h6>
<div class="surface-white border-round p-3 border-1 border-200">
<div class="flex align-items-center gap-3">
<i class="pi pi-mobile text-blue-500 text-xl"></i>
<div>
<div class="text-900 font-semibold text-sm">Application Authenticator</div>
<div class="text-600 text-xs">Google Authenticator, Authy, etc.</div>
</div>
<p:tag value="ACTIVE" severity="success" styleClass="text-xs ml-auto" />
</div>
</div>
</div>
<div class="grid gap-2">
<div class="col-6">
<p:commandButton value="Reconfigurer"
styleClass="p-button-outlined w-full"
icon="pi pi-cog" />
</div>
<div class="col-6">
<p:commandButton value="Codes de secours"
styleClass="p-button-secondary w-full"
icon="pi pi-key" />
</div>
</div>
</div>
</div>
<!-- Sessions actives -->
<div class="col-12">
<div class="surface-100 border-round p-4">
<h6 class="text-900 font-semibold mb-4">
<i class="pi pi-desktop text-purple-500 mr-2"></i>
Sessions Actives
</h6>
<!-- Session actuelle -->
<div class="surface-white border-round p-4 mb-3 border-2 border-primary">
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-3">
<i class="pi pi-desktop text-primary text-2xl"></i>
<div>
<h6 class="text-900 font-semibold mb-1">Session Actuelle</h6>
<div class="text-600 text-sm mb-1">Chrome 120.0 sur Windows 11</div>
<div class="text-500 text-xs">IP: 192.168.1.45 • Dakar, Sénégal</div>
</div>
</div>
<div class="text-right">
<p:tag value="ACTIVE" severity="success" styleClass="text-xs mb-2" />
<div class="text-600 text-xs">Connecté depuis 2h</div>
</div>
</div>
</div>
<!-- Autres sessions -->
<div class="surface-white border-round p-4 mb-3">
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-3">
<i class="pi pi-mobile text-blue-500 text-2xl"></i>
<div>
<h6 class="text-900 font-semibold mb-1">iPhone 14</h6>
<div class="text-600 text-sm mb-1">Safari Mobile</div>
<div class="text-500 text-xs">IP: 41.82.45.123 • Dernière activité: il y a 3h</div>
</div>
</div>
<div class="text-right">
<p:commandButton value="Déconnecter"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-sign-out" />
</div>
</div>
</div>
<div class="surface-white border-round p-4">
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center gap-3">
<i class="pi pi-tablet text-green-500 text-2xl"></i>
<div>
<h6 class="text-900 font-semibold mb-1">iPad Pro</h6>
<div class="text-600 text-sm mb-1">Safari</div>
<div class="text-500 text-xs">IP: 197.25.78.156 • Dernière activité: il y a 1 jour</div>
</div>
</div>
<div class="text-right">
<p:commandButton value="Déconnecter"
styleClass="p-button-outlined p-button-sm"
icon="pi pi-sign-out" />
</div>
</div>
</div>
<div class="text-center mt-4">
<p:commandButton value="Déconnecter toutes les autres sessions"
styleClass="p-button-danger"
icon="pi pi-power-off" />
</div>
</div>
</div>
</div>
</p:tab>
<!-- Onglet Confidentialité -->
<p:tab title="Confidentialité">
<div class="grid">
<!-- Visibilité du profil -->
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4 h-full">
<h6 class="text-900 font-semibold mb-4">
<i class="pi pi-eye text-blue-500 mr-2"></i>
Visibilité du Profil
</h6>
<h:form id="visibiliteForm">
<div class="field-radiobutton mb-4">
<p:radioButton id="visiPublic" name="visibilite" value="public" />
<label for="visiPublic" class="ml-2">
<div class="surface-white border-round p-3 cursor-pointer border-1 border-200">
<h6 class="text-900 font-semibold mb-1">Public</h6>
<p class="text-600 text-sm mb-0">
Votre profil est visible par tous les membres de l'association
</p>
</div>
</label>
</div>
<div class="field-radiobutton mb-4">
<p:radioButton id="visiLimite" name="visibilite" value="limite" />
<label for="visiLimite" class="ml-2">
<div class="surface-white border-round p-3 cursor-pointer border-1 border-200">
<h6 class="text-900 font-semibold mb-1">Limité</h6>
<p class="text-600 text-sm mb-0">
Visible uniquement par les administrateurs et organisateurs
</p>
</div>
</label>
</div>
<div class="field-radiobutton">
<p:radioButton id="visiPrive" name="visibilite" value="prive" />
<label for="visiPrive" class="ml-2">
<div class="surface-white border-round p-3 cursor-pointer border-1 border-200">
<h6 class="text-900 font-semibold mb-1">Privé</h6>
<p class="text-600 text-sm mb-0">
Votre profil n'est visible que par vous-même
</p>
</div>
</label>
</div>
</h:form>
</div>
</div>
<!-- Partage des données -->
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4 h-full">
<h6 class="text-900 font-semibold mb-4">
<i class="pi pi-share-alt text-green-500 mr-2"></i>
Partage des Données
</h6>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="shareEmail" value="true" />
<label for="shareEmail" class="ml-2">
<div class="text-900 font-semibold">Adresse email</div>
<div class="text-600 text-sm">Permettre aux autres membres de voir votre email</div>
</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="sharePhone" />
<label for="sharePhone" class="ml-2">
<div class="text-900 font-semibold">Numéro de téléphone</div>
<div class="text-600 text-sm">Afficher votre numéro dans l'annuaire</div>
</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="shareActivities" value="true" />
<label for="shareActivities" class="ml-2">
<div class="text-900 font-semibold">Activités publiques</div>
<div class="text-600 text-sm">Participation aux événements et formations</div>
</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="shareStats" />
<label for="shareStats" class="ml-2">
<div class="text-900 font-semibold">Statistiques anonymes</div>
<div class="text-600 text-sm">Contribuer aux statistiques générales</div>
</label>
</div>
<div class="surface-orange-50 border-left-3 border-orange-500 p-3">
<h6 class="text-orange-800 font-semibold mb-1">
<i class="pi pi-info-circle mr-2"></i>Information
</h6>
<p class="text-orange-700 text-sm mb-0">
Ces paramètres n'affectent pas les données nécessaires au fonctionnement de l'association.
</p>
</div>
</div>
</div>
<!-- Données personnelles -->
<div class="col-12">
<div class="surface-100 border-round p-4">
<h6 class="text-900 font-semibold mb-4">
<i class="pi pi-database text-purple-500 mr-2"></i>
Gestion des Données Personnelles
</h6>
<div class="grid">
<div class="col-12 lg:col-4">
<div class="surface-white border-round p-4 text-center">
<i class="pi pi-download text-blue-500 text-3xl mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Exporter mes données</h6>
<p class="text-600 text-sm mb-3">
Téléchargez toutes vos données personnelles au format JSON
</p>
<p:commandButton value="Télécharger"
styleClass="p-button-outlined w-full"
icon="pi pi-download" />
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-white border-round p-4 text-center">
<i class="pi pi-refresh text-green-500 text-3xl mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Actualiser le consentement</h6>
<p class="text-600 text-sm mb-3">
Revoir et mettre à jour vos consentements RGPD
</p>
<p:commandButton value="Actualiser"
styleClass="p-button-outlined w-full"
icon="pi pi-refresh" />
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-white border-round p-4 text-center">
<i class="pi pi-trash text-red-500 text-3xl mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Supprimer mon compte</h6>
<p class="text-600 text-sm mb-3">
Suppression définitive de toutes vos données
</p>
<p:commandButton value="Supprimer"
styleClass="p-button-danger w-full"
icon="pi pi-trash" />
</div>
</div>
</div>
</div>
</div>
</div>
</p:tab>
<!-- Onglet Préférences -->
<p:tab title="Préférences">
<div class="grid">
<!-- Préférences de communication -->
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4 h-full">
<h6 class="text-900 font-semibold mb-4">
<i class="pi pi-envelope text-blue-500 mr-2"></i>
Communications
</h6>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="emailNewsletter" value="true" />
<label for="emailNewsletter" class="ml-2 text-900">Newsletter hebdomadaire</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="emailEvents" value="true" />
<label for="emailEvents" class="ml-2 text-900">Notifications d'événements</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="emailReminders" value="true" />
<label for="emailReminders" class="ml-2 text-900">Rappels de cotisations</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="emailPromo" />
<label for="emailPromo" class="ml-2 text-900">Offres promotionnelles</label>
</div>
<div class="field-checkbox">
<p:selectBooleanCheckbox id="smsUrgent" />
<label for="smsUrgent" class="ml-2 text-900">SMS pour urgences uniquement</label>
</div>
</div>
</div>
<!-- Paramètres d'affichage -->
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4 h-full">
<h6 class="text-900 font-semibold mb-4">
<i class="pi pi-desktop text-green-500 mr-2"></i>
Affichage
</h6>
<div class="field">
<label for="themeChoice" class="block text-900 font-semibold mb-2">Thème</label>
<p:selectOneMenu id="themeChoice" styleClass="w-full">
<f:selectItem itemLabel="Clair (par défaut)" itemValue="light" />
<f:selectItem itemLabel="Sombre" itemValue="dark" />
<f:selectItem itemLabel="Automatique" itemValue="auto" />
</p:selectOneMenu>
</div>
<div class="field">
<label for="languageChoice" class="block text-900 font-semibold mb-2">Langue</label>
<p:selectOneMenu id="languageChoice" styleClass="w-full">
<f:selectItem itemLabel="Français" itemValue="fr" />
<f:selectItem itemLabel="English" itemValue="en" />
<f:selectItem itemLabel="العربية" itemValue="ar" />
<f:selectItem itemLabel="Wolof" itemValue="wo" />
</p:selectOneMenu>
</div>
<div class="field">
<label for="timezoneChoice" class="block text-900 font-semibold mb-2">Fuseau horaire</label>
<p:selectOneMenu id="timezoneChoice" styleClass="w-full">
<f:selectItem itemLabel="GMT (Dakar, Casablanca)" itemValue="GMT" />
<f:selectItem itemLabel="GMT+1 (Paris, Madrid)" itemValue="CET" />
<f:selectItem itemLabel="GMT-5 (New York)" itemValue="EST" />
</p:selectOneMenu>
</div>
<div class="field-checkbox">
<p:selectBooleanCheckbox id="animationsEnabled" value="true" />
<label for="animationsEnabled" class="ml-2 text-900">Activer les animations</label>
</div>
</div>
</div>
<!-- Sauvegarde et synchronisation -->
<div class="col-12">
<div class="surface-100 border-round p-4">
<h6 class="text-900 font-semibold mb-4">
<i class="pi pi-cloud text-blue-500 mr-2"></i>
Sauvegarde et Synchronisation
</h6>
<div class="grid">
<div class="col-12 lg:col-4">
<div class="surface-white border-round p-4">
<div class="flex align-items-center justify-content-between mb-3">
<h6 class="text-900 font-semibold mb-0">Sauvegarde automatique</h6>
<p:inputSwitch value="true" />
</div>
<p class="text-600 text-sm mb-2">
Sauvegarde quotidienne de vos préférences et données
</p>
<div class="text-500 text-xs">Dernière sauvegarde: il y a 2h</div>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-white border-round p-4">
<div class="flex align-items-center justify-content-between mb-3">
<h6 class="text-900 font-semibold mb-0">Sync calendriers</h6>
<p:inputSwitch value="true" />
</div>
<p class="text-600 text-sm mb-2">
Synchronisation avec Google Calendar et Outlook
</p>
<div class="text-500 text-xs">2 calendriers connectés</div>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-white border-round p-4">
<div class="flex align-items-center justify-content-between mb-3">
<h6 class="text-900 font-semibold mb-0">Mode hors ligne</h6>
<p:inputSwitch />
</div>
<p class="text-600 text-sm mb-2">
Accès limité aux fonctionnalités sans connexion
</p>
<div class="text-500 text-xs">Cache: 25 MB</div>
</div>
</div>
</div>
</div>
</div>
</div>
</p:tab>
<!-- Onglet Avancé -->
<p:tab title="Avancé">
<div class="grid">
<!-- API et intégrations -->
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4 h-full">
<h6 class="text-900 font-semibold mb-4">
<i class="pi pi-cog text-purple-500 mr-2"></i>
API et Intégrations
</h6>
<div class="surface-white border-round p-3 mb-3">
<div class="flex align-items-center justify-content-between mb-2">
<h6 class="text-900 font-semibold mb-0">Clé API personnelle</h6>
<p:tag value="ACTIVE" severity="success" styleClass="text-xs" />
</div>
<div class="text-600 text-sm mb-2">Utilisée pour les intégrations tierces</div>
<div class="surface-100 border-round p-2 font-mono text-sm">
uk_1a2b3c4d5e6f7g8h9i0j...
</div>
</div>
<div class="grid gap-2">
<div class="col-6">
<p:commandButton value="Regénérer"
styleClass="p-button-outlined w-full"
icon="pi pi-refresh" />
</div>
<div class="col-6">
<p:commandButton value="Révoquer"
styleClass="p-button-danger w-full"
icon="pi pi-times" />
</div>
</div>
<div class="surface-orange-50 border-left-3 border-orange-500 p-3 mt-3">
<h6 class="text-orange-800 font-semibold mb-1">
<i class="pi pi-exclamation-triangle mr-2"></i>Sécurité
</h6>
<p class="text-orange-700 text-sm mb-0">
Ne partagez jamais votre clé API. Changez-la si elle est compromise.
</p>
</div>
</div>
</div>
<!-- Logs d'activité -->
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4 h-full">
<h6 class="text-900 font-semibold mb-4">
<i class="pi pi-file-o text-orange-500 mr-2"></i>
Logs d'Activité
</h6>
<div class="field">
<label for="logLevel" class="block text-900 font-semibold mb-2">Niveau de logging</label>
<p:selectOneMenu id="logLevel" styleClass="w-full">
<f:selectItem itemLabel="Minimal (erreurs uniquement)" itemValue="error" />
<f:selectItem itemLabel="Standard (recommandé)" itemValue="info" />
<f:selectItem itemLabel="Détaillé (debug)" itemValue="debug" />
</p:selectOneMenu>
</div>
<div class="field">
<label for="logRetention" class="block text-900 font-semibold mb-2">Durée de conservation</label>
<p:selectOneMenu id="logRetention" styleClass="w-full">
<f:selectItem itemLabel="30 jours" itemValue="30" />
<f:selectItem itemLabel="90 jours" itemValue="90" />
<f:selectItem itemLabel="1 an" itemValue="365" />
</p:selectOneMenu>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="downloadLogs" />
<label for="downloadLogs" class="ml-2 text-900">Permettre le téléchargement des logs</label>
</div>
<p:commandButton value="Télécharger mes logs"
styleClass="p-button-outlined w-full"
icon="pi pi-download" />
</div>
</div>
<!-- Zone dangereuse -->
<div class="col-12">
<div class="surface-red-50 border-round p-4 border-2 border-red-500">
<h6 class="text-red-800 font-semibold mb-4">
<i class="pi pi-exclamation-triangle text-red-600 mr-2"></i>
Zone Dangereuse
</h6>
<div class="grid">
<div class="col-12 lg:col-4">
<div class="surface-white border-round p-4">
<h6 class="text-900 font-semibold mb-2">Réinitialiser les préférences</h6>
<p class="text-600 text-sm mb-3">
Remet tous vos paramètres aux valeurs par défaut
</p>
<p:commandButton value="Réinitialiser"
styleClass="p-button-outlined w-full"
icon="pi pi-refresh" />
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-white border-round p-4">
<h6 class="text-900 font-semibold mb-2">Désactiver le compte</h6>
<p class="text-600 text-sm mb-3">
Suspend temporairement votre accès
</p>
<p:commandButton value="Désactiver"
styleClass="p-button-warning w-full"
icon="pi pi-pause" />
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-white border-round p-4">
<h6 class="text-900 font-semibold mb-2">Supprimer le compte</h6>
<p class="text-600 text-sm mb-3">
Action irréversible. Toutes vos données seront perdues
</p>
<p:commandButton value="Supprimer"
styleClass="p-button-danger w-full"
icon="pi pi-trash" />
</div>
</div>
</div>
</div>
</div>
</div>
</p:tab>
</p:tabView>
</div>
</div>
</div>
<!-- Actions globales -->
<div class="grid">
<div class="col-12">
<div class="surface-card border-round p-4">
<div class="flex align-items-center justify-content-between">
<div>
<h6 class="text-900 font-semibold mb-1">Sauvegarder toutes les modifications</h6>
<p class="text-600 text-sm mb-0">
Les changements seront appliqués immédiatement à votre compte
</p>
</div>
<div class="flex gap-2">
<p:commandButton value="Annuler"
styleClass="p-button-outlined"
icon="pi pi-times" />
<p:commandButton value="Enregistrer tous les paramètres"
styleClass="p-button-primary"
icon="pi pi-save" />
</div>
</div>
</div>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,510 @@
<!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:param name="page" value="#{personnelBean}"/>
<ui:define name="title">Mes Préférences - UnionFlow</ui:define>
<ui:define name="content">
<div class="ui-fluid">
<!-- En-tête -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<div class="flex align-items-center justify-content-between mb-4">
<div>
<h2 class="text-900 font-bold text-4xl mb-2">
<i class="pi pi-cog text-blue-500 mr-3"></i>
Mes Préférences
</h2>
<p class="text-600 text-lg mb-0">
Personnalisez votre expérience UnionFlow selon vos besoins
</p>
</div>
<div class="flex gap-2">
<p:commandButton value="Réinitialiser"
styleClass="p-button-outlined"
icon="pi pi-refresh"
action="#{preferencesBean.reinitialiserPreferences}"
update="@form" />
<p:commandButton value="Enregistrer"
styleClass="p-button-primary"
icon="pi pi-save"
action="#{preferencesBean.sauvegarderPreferences}"
update="@form" />
</div>
</div>
<!-- Raccourcis préférences -->
<div class="grid">
<div class="col-12 lg:col-4">
<div class="surface-100 hover:surface-200 border-round p-4 text-center cursor-pointer transition-duration-200">
<i class="pi pi-palette text-3xl text-purple-500 mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Apparence</h6>
<p class="text-600 text-sm mb-0">Thème, couleurs, mise en page</p>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-100 hover:surface-200 border-round p-4 text-center cursor-pointer transition-duration-200">
<i class="pi pi-bell text-3xl text-orange-500 mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Notifications</h6>
<p class="text-600 text-sm mb-0">Alertes, emails, SMS</p>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-100 hover:surface-200 border-round p-4 text-center cursor-pointer transition-duration-200">
<i class="pi pi-shield text-3xl text-green-500 mb-3"></i>
<h6 class="text-900 font-semibold mb-2">Confidentialité</h6>
<p class="text-600 text-sm mb-0">Sécurité, permissions</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Préférences d'apparence -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-palette text-purple-500 mr-2"></i>
Apparence et Interface
</h4>
<h:form id="apparenceForm">
<div class="grid">
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4">
<h6 class="text-900 font-semibold mb-3">Thème</h6>
<p:selectOneRadio id="theme" value="#{preferencesBean.theme}" layout="custom">
<f:selectItem itemLabel="Clair" itemValue="light" />
<f:selectItem itemLabel="Sombre" itemValue="dark" />
</p:selectOneRadio>
<div class="grid">
<div class="col-6">
<div class="field-radiobutton">
<p:radioButton id="themeLight" for="theme" itemIndex="0" />
<label for="themeLight" class="ml-2">
<div class="surface-100 border-round p-3 cursor-pointer">
<i class="pi pi-sun text-yellow-500 text-xl mb-2"></i>
<div class="text-900 font-semibold text-sm">Clair</div>
<div class="text-600 text-xs">Mode jour</div>
</div>
</label>
</div>
</div>
<div class="col-6">
<div class="field-radiobutton">
<p:radioButton id="themeDark" for="theme" itemIndex="1" />
<label for="themeDark" class="ml-2">
<div class="surface-800 border-round p-3 cursor-pointer">
<i class="pi pi-moon text-blue-400 text-xl mb-2"></i>
<div class="text-white font-semibold text-sm">Sombre</div>
<div class="text-300 text-xs">Mode nuit</div>
</div>
</label>
</div>
</div>
</div>
</div>
</div>
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4">
<h6 class="text-900 font-semibold mb-3">Couleur d'accent</h6>
<p:selectOneRadio id="accentColor" value="#{preferencesBean.couleurAccent}" layout="custom">
<f:selectItem itemLabel="Bleu" itemValue="blue" />
<f:selectItem itemLabel="Vert" itemValue="green" />
<f:selectItem itemLabel="Violet" itemValue="purple" />
<f:selectItem itemLabel="Orange" itemValue="orange" />
</p:selectOneRadio>
<div class="grid">
<div class="col-3">
<div class="field-radiobutton">
<p:radioButton id="colorBlue" for="accentColor" itemIndex="0" />
<label for="colorBlue" class="w-2rem h-2rem border-circle bg-blue-500 cursor-pointer block ml-2"></label>
</div>
</div>
<div class="col-3">
<div class="field-radiobutton">
<p:radioButton id="colorGreen" for="accentColor" itemIndex="1" />
<label for="colorGreen" class="w-2rem h-2rem border-circle bg-green-500 cursor-pointer block ml-2"></label>
</div>
</div>
<div class="col-3">
<div class="field-radiobutton">
<p:radioButton id="colorPurple" for="accentColor" itemIndex="2" />
<label for="colorPurple" class="w-2rem h-2rem border-circle bg-purple-500 cursor-pointer block ml-2"></label>
</div>
</div>
<div class="col-3">
<div class="field-radiobutton">
<p:radioButton id="colorOrange" for="accentColor" itemIndex="3" />
<label for="colorOrange" class="w-2rem h-2rem border-circle bg-orange-500 cursor-pointer block ml-2"></label>
</div>
</div>
</div>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="field">
<label for="langue" class="block text-900 font-semibold mb-2">Langue</label>
<p:selectOneMenu id="langue" value="#{preferencesBean.langue}" styleClass="w-full">
<f:selectItem itemLabel="Français" itemValue="fr" />
<f:selectItem itemLabel="English" itemValue="en" />
<f:selectItem itemLabel="العربية" itemValue="ar" />
<f:selectItem itemLabel="Wolof" itemValue="wo" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="field">
<label for="fuseau" class="block text-900 font-semibold mb-2">Fuseau horaire</label>
<p:selectOneMenu id="fuseau" value="#{preferencesBean.fuseauHoraire}" styleClass="w-full">
<f:selectItem itemLabel="GMT (Casablanca)" itemValue="GMT" />
<f:selectItem itemLabel="GMT+1 (Paris)" itemValue="CET" />
<f:selectItem itemLabel="GMT-5 (New York)" itemValue="EST" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="field">
<label for="format" class="block text-900 font-semibold mb-2">Format de date</label>
<p:selectOneMenu id="format" value="#{preferencesBean.formatDate}" styleClass="w-full">
<f:selectItem itemLabel="DD/MM/YYYY" itemValue="dd/mm/yyyy" />
<f:selectItem itemLabel="MM/DD/YYYY" itemValue="mm/dd/yyyy" />
<f:selectItem itemLabel="YYYY-MM-DD" itemValue="yyyy-mm-dd" />
</p:selectOneMenu>
</div>
</div>
</div>
</h:form>
</div>
</div>
</div>
<!-- Préférences de notifications -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-bell text-orange-500 mr-2"></i>
Notifications et Alertes
</h4>
<h:form id="notificationsForm">
<div class="grid">
<div class="col-12 lg:col-4">
<div class="surface-100 border-round p-4">
<h6 class="text-900 font-semibold mb-3">
<i class="pi pi-desktop mr-2"></i>Notifications navigateur
</h6>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="notifEvenements" value="#{preferencesBean.notifEvenements}" />
<label for="notifEvenements" class="ml-2 text-900">Nouveaux événements</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="notifMessages" value="#{preferencesBean.notifMessages}" />
<label for="notifMessages" class="ml-2 text-900">Messages privés</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="notifCotisations" value="#{preferencesBean.notifCotisations}" />
<label for="notifCotisations" class="ml-2 text-900">Rappels cotisations</label>
</div>
<div class="field-checkbox">
<p:selectBooleanCheckbox id="notifSysteme" value="#{preferencesBean.notifSysteme}" />
<label for="notifSysteme" class="ml-2 text-900">Mises à jour système</label>
</div>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-100 border-round p-4">
<h6 class="text-900 font-semibold mb-3">
<i class="pi pi-envelope mr-2"></i>Notifications email
</h6>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="emailQuotidien" value="#{preferencesBean.emailQuotidien}" />
<label for="emailQuotidien" class="ml-2 text-900">Résumé quotidien</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="emailHebdo" value="#{preferencesBean.emailHebdo}" />
<label for="emailHebdo" class="ml-2 text-900">Newsletter hebdomadaire</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="emailUrgent" value="#{preferencesBean.emailUrgent}" />
<label for="emailUrgent" class="ml-2 text-900">Alertes urgentes</label>
</div>
<div class="field-checkbox">
<p:selectBooleanCheckbox id="emailPromo" value="#{preferencesBean.emailPromo}" />
<label for="emailPromo" class="ml-2 text-900">Offres promotionnelles</label>
</div>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-100 border-round p-4">
<h6 class="text-900 font-semibold mb-3">
<i class="pi pi-mobile mr-2"></i>Notifications SMS
</h6>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="smsUrgent" value="#{preferencesBean.smsUrgent}" />
<label for="smsUrgent" class="ml-2 text-900">Urgences uniquement</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="smsRappels" value="#{preferencesBean.smsRappels}" />
<label for="smsRappels" class="ml-2 text-900">Rappels importants</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="smsEvenements" value="#{preferencesBean.smsEvenements}" />
<label for="smsEvenements" class="ml-2 text-900">Événements du jour</label>
</div>
<div class="field">
<label for="heuresSMS" class="block text-900 font-semibold mb-2">Heures autorisées</label>
<p:selectOneMenu id="heuresSMS" value="#{preferencesBean.heuresSMS}" styleClass="w-full">
<f:selectItem itemLabel="08h - 20h" itemValue="08-20" />
<f:selectItem itemLabel="09h - 18h" itemValue="09-18" />
<f:selectItem itemLabel="24h/24" itemValue="00-24" />
</p:selectOneMenu>
</div>
</div>
</div>
</div>
</h:form>
</div>
</div>
</div>
<!-- Préférences de confidentialité -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-shield text-green-500 mr-2"></i>
Confidentialité et Sécurité
</h4>
<h:form id="confidentialiteForm">
<div class="grid">
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4">
<h6 class="text-900 font-semibold mb-3">Visibilité du profil</h6>
<p:selectOneRadio id="visibilite" value="#{preferencesBean.visibiliteProfil}" layout="custom">
<f:selectItem itemLabel="Public" itemValue="publique" />
<f:selectItem itemLabel="Limité" itemValue="limitee" />
<f:selectItem itemLabel="Privé" itemValue="prive" />
</p:selectOneRadio>
<div class="field-radiobutton mb-3">
<p:radioButton id="visibilitePublique" for="visibilite" itemIndex="0" />
<label for="visibilitePublique" class="ml-2">
<div class="text-900 font-semibold">Public</div>
<div class="text-600 text-sm">Visible par tous les membres</div>
</label>
</div>
<div class="field-radiobutton mb-3">
<p:radioButton id="visibiliteLimitee" for="visibilite" itemIndex="1" />
<label for="visibiliteLimitee" class="ml-2">
<div class="text-900 font-semibold">Limité</div>
<div class="text-600 text-sm">Visible par les administrateurs</div>
</label>
</div>
<div class="field-radiobutton">
<p:radioButton id="visibilitePrive" for="visibilite" itemIndex="2" />
<label for="visibilitePrive" class="ml-2">
<div class="text-900 font-semibold">Privé</div>
<div class="text-600 text-sm">Visible par vous uniquement</div>
</label>
</div>
</div>
</div>
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4">
<h6 class="text-900 font-semibold mb-3">Paramètres de sécurité</h6>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="doubleAuth" value="#{preferencesBean.doubleAuth}" />
<label for="doubleAuth" class="ml-2 text-900">Authentification à deux facteurs</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="connexionSecure" value="#{preferencesBean.connexionSecure}" />
<label for="connexionSecure" class="ml-2 text-900">Connexion HTTPS obligatoire</label>
</div>
<div class="field-checkbox mb-3">
<p:selectBooleanCheckbox id="deconnexionAuto" value="#{preferencesBean.deconnexionAuto}" />
<label for="deconnexionAuto" class="ml-2 text-900">Déconnexion automatique</label>
</div>
<div class="field">
<label for="dureeSession" class="block text-900 font-semibold mb-2">Durée max session</label>
<p:selectOneMenu id="dureeSession" styleClass="w-full">
<f:selectItem itemLabel="30 minutes" itemValue="30" />
<f:selectItem itemLabel="1 heure" itemValue="60" />
<f:selectItem itemLabel="2 heures" itemValue="120" />
<f:selectItem itemLabel="4 heures" itemValue="240" />
<f:selectItem itemLabel="8 heures" itemValue="480" />
</p:selectOneMenu>
</div>
</div>
</div>
</div>
</h:form>
</div>
</div>
</div>
<!-- Préférences tableau de bord -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-chart-bar text-blue-500 mr-2"></i>
Tableau de Bord Personnel
</h4>
<h:form id="dashboardForm">
<div class="grid">
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4">
<h6 class="text-900 font-semibold mb-3">Widgets à afficher</h6>
<div class="field-checkbox mb-2">
<p:selectBooleanCheckbox id="widgetActivites" value="#{preferencesBean.widgetActivites}" />
<label for="widgetActivites" class="ml-2 text-900">Activités récentes</label>
</div>
<div class="field-checkbox mb-2">
<p:selectBooleanCheckbox id="widgetEvenements" value="#{preferencesBean.widgetEvenements}" />
<label for="widgetEvenements" class="ml-2 text-900">Événements à venir</label>
</div>
<div class="field-checkbox mb-2">
<p:selectBooleanCheckbox id="widgetCotisations" value="#{preferencesBean.widgetCotisations}" />
<label for="widgetCotisations" class="ml-2 text-900">État des cotisations</label>
</div>
<div class="field-checkbox mb-2">
<p:selectBooleanCheckbox id="widgetNotifications" value="#{preferencesBean.widgetNotifications}" />
<label for="widgetNotifications" class="ml-2 text-900">Notifications récentes</label>
</div>
<div class="field-checkbox mb-2">
<p:selectBooleanCheckbox id="widgetStatistiques" value="#{preferencesBean.widgetStatistiques}" />
<label for="widgetStatistiques" class="ml-2 text-900">Mes statistiques</label>
</div>
<div class="field-checkbox">
<p:selectBooleanCheckbox id="widgetMeteo" value="#{preferencesBean.widgetMeteo}" />
<label for="widgetMeteo" class="ml-2 text-900">Météo locale</label>
</div>
</div>
</div>
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-4">
<h6 class="text-900 font-semibold mb-3">Configuration d'affichage</h6>
<div class="field">
<label for="layoutDashboard" class="block text-900 font-semibold mb-2">Disposition</label>
<p:selectOneMenu id="layoutDashboard" value="#{preferencesBean.layoutDashboard}" styleClass="w-full">
<f:selectItem itemLabel="Grille 2 colonnes" itemValue="grid-2" />
<f:selectItem itemLabel="Grille 3 colonnes" itemValue="grid-3" />
<f:selectItem itemLabel="Liste verticale" itemValue="list" />
<f:selectItem itemLabel="Compact" itemValue="compact" />
</p:selectOneMenu>
</div>
<div class="field">
<label for="pageAccueil" class="block text-900 font-semibold mb-2">Page d'accueil</label>
<p:selectOneMenu id="pageAccueil" value="#{preferencesBean.pageAccueil}" styleClass="w-full">
<f:selectItem itemLabel="Tableau de bord" itemValue="dashboard" />
<f:selectItem itemLabel="Mes activités" itemValue="activites" />
<f:selectItem itemLabel="Mon agenda" itemValue="agenda" />
<f:selectItem itemLabel="Dernière page visitée" itemValue="last" />
</p:selectOneMenu>
</div>
<div class="field">
<label for="elementsPage" class="block text-900 font-semibold mb-2">Éléments par page</label>
<p:selectOneMenu id="elementsPage" value="#{preferencesBean.elementsPage}" styleClass="w-full">
<f:selectItem itemLabel="10" itemValue="10" />
<f:selectItem itemLabel="25" itemValue="25" />
<f:selectItem itemLabel="50" itemValue="50" />
<f:selectItem itemLabel="100" itemValue="100" />
</p:selectOneMenu>
</div>
<div class="field-checkbox">
<p:selectBooleanCheckbox id="animations" value="#{preferencesBean.animations}" />
<label for="animations" class="ml-2 text-900">Activer les animations</label>
</div>
</div>
</div>
</div>
</h:form>
</div>
</div>
</div>
<!-- Actions -->
<div class="grid">
<div class="col-12">
<div class="surface-card border-round p-4">
<div class="flex align-items-center justify-content-between">
<div>
<h6 class="text-900 font-semibold mb-1">Enregistrer les modifications</h6>
<p class="text-600 text-sm mb-0">Vos préférences seront appliquées immédiatement</p>
</div>
<div class="flex gap-2">
<p:commandButton value="Annuler"
styleClass="p-button-outlined"
icon="pi pi-times" />
<p:commandButton value="Réinitialiser par défaut"
styleClass="p-button-secondary"
icon="pi pi-refresh" />
<p:commandButton value="Enregistrer les préférences"
styleClass="p-button-primary"
icon="pi pi-save" />
</div>
</div>
<div class="surface-blue-50 border-left-3 border-blue-500 p-3 mt-3">
<p class="text-blue-700 text-sm mb-0">
<i class="pi pi-info-circle mr-2"></i>
Certaines modifications nécessiteront une reconnexion pour être appliquées.
</p>
</div>
</div>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,301 @@
<!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:param name="page" value="#{personnelBean}"/>
<ui:define name="title">Mon Profil - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formProfil">
<!-- En-tête profil -->
<div class="grid mb-4">
<div class="col-12">
<div class="surface-card border-round p-4">
<div class="flex align-items-center justify-content-between mb-4">
<div class="flex align-items-center gap-4">
<div class="w-6rem h-6rem border-circle bg-primary-100 flex align-items-center justify-content-center">
<h:graphicImage value="#{personnelBean.membre.photoUrl}"
style="width: 100%; height: 100%; object-fit: cover; border-radius: 50%;"
rendered="#{personnelBean.membre != null and personnelBean.membre.photoUrl != null}" />
<i class="pi pi-user text-primary text-4xl"
rendered="#{personnelBean.membre == null or personnelBean.membre.photoUrl == null}"></i>
</div>
<div>
<h2 class="text-900 font-bold text-3xl mb-2">
#{personnelBean.membre != null ? personnelBean.membre.nomComplet : 'Chargement...'}
</h2>
<p class="text-600 text-lg mb-1" rendered="#{personnelBean.membre != null and personnelBean.membre.dateAdhesion != null}">
Membre depuis le #{personnelBean.membre.dateAdhesionFormatee}
</p>
<div class="flex align-items-center gap-2" rendered="#{personnelBean.membre != null}">
<p:tag value="#{personnelBean.membre.statut}"
severity="#{personnelBean.membre.statutSeverity}"
styleClass="text-sm" />
<p:tag value="#{personnelBean.membre.typeMembre}"
severity="#{personnelBean.membre.typeSeverity}"
styleClass="text-sm" />
</div>
</div>
</div>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Modifier" />
<ui:param name="icon" value="pi pi-pencil" />
<ui:param name="onclick" value="PF('modifierProfilDialog').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{personnelBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</div>
<!-- Statistiques profil -->
<div class="grid" rendered="#{personnelBean.statistiques != null}">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{personnelBean.statistiques.actionsRealisees}" />
<ui:param name="label" value="Actions Réalisées" />
<ui:param name="subLabel" value="Ce mois-ci" />
<ui:param name="icon" value="pi pi-check-circle" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{personnelBean.statistiques.evenementsParticipes}" />
<ui:param name="label" value="Événements" />
<ui:param name="subLabel" value="Participés" />
<ui:param name="icon" value="pi pi-calendar" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{personnelBean.statistiques.tauxParticipation}%" />
<ui:param name="label" value="Taux Participation" />
<ui:param name="subLabel" value="Global" />
<ui:param name="icon" value="pi pi-chart-line" />
<ui:param name="bgColor" value="purple" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{personnelBean.statistiques.evaluationMoyenne}★" />
<ui:param name="label" value="Évaluation" />
<ui:param name="subLabel" value="Moyenne" />
<ui:param name="icon" value="pi pi-star" />
<ui:param name="bgColor" value="orange" />
</ui:include>
</div>
</div>
</div>
</div>
<!-- Informations personnelles -->
<div class="grid mb-4" rendered="#{personnelBean.membre != null}">
<div class="col-12 lg:col-8">
<div class="surface-card border-round p-4 h-full">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-id-card text-primary mr-2"></i>
Informations Personnelles
</h4>
<div class="grid">
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Nom complet</div>
<div class="text-900 font-semibold">#{personnelBean.membre.nomComplet}</div>
</div>
</div>
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Email</div>
<div class="text-900 font-semibold">#{personnelBean.membre.email}</div>
</div>
</div>
<div class="col-12 lg:col-6">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Téléphone</div>
<div class="text-900 font-semibold">#{personnelBean.membre.telephone}</div>
</div>
</div>
<div class="col-12 lg:col-6" rendered="#{personnelBean.membre.dateNaissance != null}">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Date de naissance</div>
<div class="text-900 font-semibold">#{personnelBean.membre.dateNaissanceFormatee}</div>
</div>
</div>
<div class="col-12" rendered="#{personnelBean.membre.adresse != null}">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Adresse</div>
<div class="text-900 font-semibold">#{personnelBean.membre.adresse}</div>
</div>
</div>
<div class="col-12 lg:col-6" rendered="#{personnelBean.membre.profession != null}">
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Profession</div>
<div class="text-900 font-semibold">#{personnelBean.membre.profession}</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-12 lg:col-4">
<div class="surface-card border-round p-4 h-full">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-bookmark text-blue-500 mr-2"></i>
Adhésion et Statut
</h4>
<div class="surface-100 border-round p-3 mb-3">
<div class="text-600 text-sm mb-1">Numéro de membre</div>
<div class="text-900 font-bold text-lg">#{personnelBean.membre.numeroMembre}</div>
</div>
<div class="surface-100 border-round p-3 mb-3" rendered="#{personnelBean.membre.typeMembre != null}">
<div class="text-600 text-sm mb-1">Type d'adhésion</div>
<div class="text-900 font-semibold">#{personnelBean.membre.typeMembre}</div>
</div>
<div class="surface-100 border-round p-3 mb-3" rendered="#{personnelBean.membre.dateAdhesion != null}">
<div class="text-600 text-sm mb-1">Date d'inscription</div>
<div class="text-900 font-semibold">#{personnelBean.membre.dateAdhesionFormatee}</div>
</div>
</div>
</div>
</div>
<!-- Activités récentes -->
<div class="grid mb-4">
<div class="col-12 lg:col-6">
<div class="surface-card border-round p-4 h-full">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-history text-purple-500 mr-2"></i>
Activités Récentes
</h4>
<ui:repeat value="#{personnelBean.activitesRecentes}" var="activite">
<div class="surface-100 border-round p-3 mb-3">
<div class="flex align-items-center justify-content-between mb-2">
<span class="text-900 font-semibold text-sm">#{activite.titre}</span>
<span class="text-600 text-xs">#{activite.dateHeure}</span>
</div>
<div class="text-600 text-sm">#{activite.description}</div>
</div>
</ui:repeat>
<div class="text-center text-600 text-sm" rendered="#{empty personnelBean.activitesRecentes}">
Aucune activité récente
</div>
</div>
</div>
<div class="col-12 lg:col-6">
<div class="surface-card border-round p-4 h-full">
<h4 class="text-900 font-bold mb-4">
<i class="pi pi-shield text-orange-500 mr-2"></i>
Rôles et Permissions
</h4>
<div class="text-600 text-sm" rendered="#{userSession != null and userSession.roles != null}">
<ui:repeat value="#{userSession.roles}" var="role">
<div class="mb-2">
<p:tag value="#{role}" severity="info" styleClass="text-xs" />
</div>
</ui:repeat>
</div>
</div>
</div>
</div>
</h:form>
<!-- Dialog Modifier Profil -->
<p:dialog id="modifierProfilDialog"
widgetVar="modifierProfilDialog"
header="Modifier Mon Profil"
modal="true"
width="900"
styleClass="surface-0">
<h:form id="modifierProfilForm">
<div class="ui-fluid">
<div class="formgrid grid" rendered="#{personnelBean.membre != null}">
<div class="field col-12 lg:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="nom" />
<ui:param name="label" value="Nom *" />
<ui:param name="value" value="#{personnelBean.membre.nom}" />
<ui:param name="required" value="true" />
</ui:include>
</div>
<div class="field col-12 lg:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="prenom" />
<ui:param name="label" value="Prénom *" />
<ui:param name="value" value="#{personnelBean.membre.prenom}" />
<ui:param name="required" value="true" />
</ui:include>
</div>
<div class="field col-12">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="email" />
<ui:param name="label" value="Email *" />
<ui:param name="value" value="#{personnelBean.membre.email}" />
<ui:param name="required" value="true" />
</ui:include>
</div>
<div class="field col-12 lg:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="telephone" />
<ui:param name="label" value="Téléphone" />
<ui:param name="value" value="#{personnelBean.membre.telephone}" />
</ui:include>
</div>
<div class="field col-12 lg:col-6">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateNaissance" />
<ui:param name="label" value="Date de naissance" />
<ui:param name="value" value="#{personnelBean.membre.dateNaissance}" />
</ui:include>
</div>
<div class="field col-12">
<ui:include src="/templates/components/forms/form-field-textarea.xhtml">
<ui:param name="id" value="adresse" />
<ui:param name="label" value="Adresse" />
<ui:param name="value" value="#{personnelBean.membre.adresse}" />
<ui:param name="rows" value="3" />
</ui:include>
</div>
<div class="field col-12 lg:col-6">
<ui:include src="/templates/components/forms/form-field-text.xhtml">
<ui:param name="id" value="profession" />
<ui:param name="label" value="Profession" />
<ui:param name="value" value="#{personnelBean.membre.profession}" />
</ui:include>
</div>
</div>
<div class="flex justify-content-end gap-2 mt-4">
<p:commandButton value="Annuler"
styleClass="p-button-outlined"
onclick="PF('modifierProfilDialog').hide();"
type="button" />
<p:commandButton value="Enregistrer"
styleClass="p-button-primary"
icon="pi pi-save"
action="#{personnelBean.mettreAJourProfil}"
update="@form :formProfil"
onclick="if(!args.validationFailed) PF('modifierProfilDialog').hide();" />
</div>
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,241 @@
<!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">Mon Profil - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête du profil -->
<div class="grid">
<div class="col-12">
<div class="card">
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center">
<div class="bg-primary text-white border-round flex align-items-center justify-content-center mr-4"
style="width: 5rem; height: 5rem; font-size: 2rem; font-weight: bold;">
#{userSession.currentUser.initiales}
</div>
<div>
<h2 class="mb-2">#{userSession.currentUser.nomComplet}</h2>
<div class="flex align-items-center gap-2 mb-2">
<p:tag value="#{userSession.typeCompte}"
severity="#{userSession.isSuperAdmin() ? 'danger' : (userSession.isAdmin() ? 'warning' : 'info')}" />
<span class="text-600"></span>
<span class="text-600">#{userSession.currentUser.email}</span>
</div>
<div class="text-600">
<i class="pi pi-building mr-1"></i>
#{userSession.entite.description}
</div>
</div>
</div>
<div>
<p:commandButton value="Modifier le profil"
icon="pi pi-pencil"
styleClass="ui-button-outlined"
onclick="PF('dlgEditProfile').show();" />
</div>
</div>
</div>
</div>
</div>
<!-- Informations détaillées -->
<div class="grid">
<div class="col-12 md:col-6">
<div class="card">
<h5>📋 Informations Personnelles</h5>
<div class="field-group">
<div class="field">
<label class="font-medium text-900">Nom complet</label>
<div class="text-600">#{userSession.currentUser.nomComplet}</div>
</div>
<div class="field">
<label class="font-medium text-900">Nom d'utilisateur</label>
<div class="text-600">#{userSession.currentUser.username}</div>
</div>
<div class="field">
<label class="font-medium text-900">Adresse email</label>
<div class="text-600">#{userSession.currentUser.email}</div>
</div>
<div class="field">
<label class="font-medium text-900">Type de compte</label>
<div>
<p:tag value="#{userSession.typeCompte}"
severity="#{userSession.isSuperAdmin() ? 'danger' : (userSession.isAdmin() ? 'warning' : 'info')}" />
</div>
</div>
</div>
</div>
</div>
<div class="col-12 md:col-6">
<div class="card">
<h5>🏢 Informations de l'Entité</h5>
<div class="field-group">
<div class="field">
<label class="font-medium text-900">Nom de l'entité</label>
<div class="text-600">#{userSession.entite.nom}</div>
</div>
<div class="field">
<label class="font-medium text-900">Type d'entité</label>
<div class="text-600">#{userSession.entite.type}</div>
</div>
<div class="field">
<label class="font-medium text-900">Localisation</label>
<div class="text-600">
<i class="pi pi-map-marker mr-1"></i>
#{userSession.entite.ville}, #{userSession.entite.pays}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Rôles et permissions -->
<div class="grid">
<div class="col-12 md:col-6">
<div class="card">
<h5>🔐 Rôles et Permissions</h5>
<div class="field-group">
<div class="field">
<label class="font-medium text-900">Rôles assignés</label>
<div class="flex gap-2 flex-wrap">
<ui:repeat value="#{userSession.roles}" var="role">
<p:tag value="#{role}"
severity="#{role == 'SUPER_ADMIN' ? 'danger' : (role == 'ADMIN_ENTITE' ? 'warning' : 'info')}" />
</ui:repeat>
</div>
</div>
<div class="field" rendered="#{userSession.permissions != null}">
<label class="font-medium text-900">Permissions spéciales</label>
<div class="flex gap-1 flex-wrap">
<ui:repeat value="#{userSession.permissions}" var="permission">
<p:tag value="#{permission}" severity="secondary" />
</ui:repeat>
</div>
</div>
</div>
</div>
</div>
<div class="col-12 md:col-6">
<div class="card">
<h5>🔒 Sécurité de la Session</h5>
<div class="field-group">
<div class="field">
<label class="font-medium text-900">Statut de connexion</label>
<div>
<p:tag value="Connecté" severity="success" />
<span class="text-600 ml-2">Session active</span>
</div>
</div>
<div class="field">
<label class="font-medium text-900">Temps restant</label>
<div class="text-600">
<i class="pi pi-clock mr-1"></i>
#{jwtTokenManager.timeUntilExpiration / 60} minutes
</div>
</div>
<div class="field">
<label class="font-medium text-900">Actions sécurisées</label>
<div class="flex gap-2">
<p:commandButton value="Changer mot de passe"
icon="pi pi-key"
styleClass="ui-button-outlined ui-button-warning ui-button-sm"
onclick="PF('dlgChangePassword').show();" />
<p:commandButton value="Déconnecter autres sessions"
icon="pi pi-sign-out"
styleClass="ui-button-outlined ui-button-danger ui-button-sm" />
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Dialog pour modifier le profil -->
<p:dialog header="Modifier le Profil" widgetVar="dlgEditProfile" modal="true" width="500">
<h:form id="formEditProfile">
<div class="ui-fluid">
<div class="field">
<p:outputLabel for="editNom" value="Nom" />
<p:inputText id="editNom" value="#{userSession.currentUser.nom}" />
</div>
<div class="field">
<p:outputLabel for="editPrenom" value="Prénom" />
<p:inputText id="editPrenom" value="#{userSession.currentUser.prenom}" />
</div>
<div class="field">
<p:outputLabel for="editEmail" value="Email" />
<p:inputText id="editEmail" value="#{userSession.currentUser.email}" />
</div>
</div>
<div class="flex gap-2 mt-3">
<p:commandButton value="Enregistrer"
icon="pi pi-check"
styleClass="ui-button-success"
update="@form"
oncomplete="if(!args.validationFailed) PF('dlgEditProfile').hide();" />
<p:commandButton value="Annuler"
icon="pi pi-times"
styleClass="ui-button-secondary"
onclick="PF('dlgEditProfile').hide();"
type="button" />
</div>
</h:form>
</p:dialog>
<!-- Dialog pour changer le mot de passe -->
<p:dialog header="Changer le Mot de Passe" widgetVar="dlgChangePassword" modal="true" width="400">
<h:form id="formChangePassword">
<div class="ui-fluid">
<div class="field">
<p:outputLabel for="currentPassword" value="Mot de passe actuel" />
<p:password id="currentPassword" required="true" />
</div>
<div class="field">
<p:outputLabel for="newPassword" value="Nouveau mot de passe" />
<p:password id="newPassword" required="true" toggleMask="true" />
</div>
<div class="field">
<p:outputLabel for="confirmPassword" value="Confirmer le mot de passe" />
<p:password id="confirmPassword" required="true" />
</div>
</div>
<div class="flex gap-2 mt-3">
<p:commandButton value="Changer"
icon="pi pi-check"
styleClass="ui-button-warning"
update="@form"
oncomplete="if(!args.validationFailed) PF('dlgChangePassword').hide();" />
<p:commandButton value="Annuler"
icon="pi pi-times"
styleClass="ui-button-secondary"
onclick="PF('dlgChangePassword').hide();"
type="button" />
</div>
</h:form>
</p:dialog>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,116 @@
<!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:param name="page" value="#{rapportsBean}"/>
<ui:define name="title">Rapports Activités - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-calendar text-orange-500" />
<ui:param name="title" value="Rapports Activités" />
<ui:param name="description" value="Analyse des activités et événements" />
<ui:define name="actions">
<h:form id="formActions">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="onclick" value="PF('dlgExport').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{rapportsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques activités -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{rapportsBean.indicateurs.totalEvenements}" />
<ui:param name="label" value="Total Événements" />
<ui:param name="icon" value="pi pi-calendar" />
<ui:param name="bgColor" value="orange" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{rapportsBean.indicateurs.croissanceEvenements}%" />
<ui:param name="label" value="Croissance Événements" />
<ui:param name="icon" value="pi pi-arrow-up" />
<ui:param name="bgColor" value="green" />
</ui:include>
</div>
<!-- KPIs Activités -->
<div class="card">
<h5>Indicateurs d'Activité</h5>
<div class="formgrid grid">
<ui:repeat value="#{rapportsBean.kpis}" var="kpi">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="#{kpi.libelle}" />
<ui:param name="value" value="#{kpi.valeur}" />
<ui:param name="icon" value="#{kpi.icon}" />
<ui:param name="iconColor" value="#{kpi.couleur}" />
<ui:param name="growthValue" value="#{kpi.variation}" />
<ui:param name="growthLabel" value="variation" />
<ui:param name="colSize" value="col-12 md:col-4" />
<ui:param name="showProgress" value="false" />
</ui:include>
</ui:repeat>
</div>
</div>
<!-- Dialog Export -->
<h:form id="formExport">
<p:dialog id="dlgExport"
widgetVar="dlgExport"
header="Exporter le Rapport Activités"
modal="true"
resizable="false"
style="width: 90vw; max-width: 500px;">
<div class="grid">
<div class="col-12">
<div class="field">
<p:outputLabel for="formatExport" value="Format d'Export" />
<p:selectOneRadio id="formatExport"
value="#{rapportsBean.nouveauRapport.format}"
layout="grid"
columns="1">
<f:selectItem itemLabel="PDF" itemValue="PDF" />
<f:selectItem itemLabel="Excel (.xlsx)" itemValue="EXCEL" />
<f:selectItem itemLabel="CSV" itemValue="CSV" />
</p:selectOneRadio>
</div>
</div>
</div>
<f:facet name="footer">
<div class="flex justify-content-end gap-2">
<p:commandButton value="Annuler"
styleClass="p-button-outlined"
onclick="PF('dlgExport').hide();"
type="button" />
<p:commandButton value="Exporter"
icon="pi pi-download"
styleClass="p-button-success"
action="#{rapportsBean.exporterDonnees}" />
</div>
</f:facet>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,145 @@
<!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:param name="page" value="#{rapportDetailsBean}"/>
<ui:define name="title">Détails du Rapport - UnionFlow</ui:define>
<ui:define name="content">
<h:form id="formDetails">
<p:messages id="messages" showDetail="true" closable="true"/>
<!-- En-tête -->
<div class="card mb-3">
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
<div class="flex align-items-center gap-3 mb-2 md:mb-0">
<div class="bg-primary text-white border-round text-center"
style="width: 64px; height: 64px; line-height: 64px;">
<i class="pi #{rapportDetailsBean.rapport.typeIcon} text-3xl"></i>
</div>
<div>
<h3 class="m-0">#{rapportDetailsBean.rapport.typeLibelle}</h3>
<div class="mt-2 flex align-items-center gap-2">
<p:tag value="#{rapportDetailsBean.rapport.statut}"
severity="#{rapportDetailsBean.rapport.statutSeverity}" />
<span class="text-600">Généré le #{rapportDetailsBean.dateGenerationFormatee}</span>
</div>
</div>
</div>
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Retour"/>
<ui:param name="icon" value="pi pi-arrow-left"/>
<ui:param name="action" value="#{rapportDetailsBean.retourner}"/>
</ui:include>
<p:commandButton value="Télécharger"
icon="pi pi-download"
styleClass="ui-button-success"
action="#{rapportDetailsBean.telechargerRapport}"
update="messages"
rendered="#{rapportDetailsBean.isRapportDisponible()}"/>
<p:commandButton value="Régénérer"
icon="pi pi-refresh"
styleClass="ui-button-outlined ui-button-warning"
action="#{rapportDetailsBean.regenererRapport}"
update="messages"/>
</div>
</div>
</div>
<h:panelGroup rendered="#{not empty rapportDetailsBean.rapport}">
<div class="grid">
<!-- Informations générales -->
<div class="col-12 md:col-6">
<div class="card">
<h5 class="mb-3">Informations Générales</h5>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Type de rapport"/>
<ui:param name="value" value="#{rapportDetailsBean.rapport.typeLibelle}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Date de génération"/>
<ui:param name="value" value="#{rapportDetailsBean.dateGenerationFormatee}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Période couverte"/>
<ui:param name="value" value="#{rapportDetailsBean.rapport.periodeCouverte}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Généré par"/>
<ui:param name="value" value="#{rapportDetailsBean.rapport.generePar}"/>
</ui:include>
<ui:include src="/templates/components/forms/detail-field.xhtml">
<ui:param name="label" value="Statut"/>
<ui:param name="value" value="#{rapportDetailsBean.rapport.statut}"/>
</ui:include>
</div>
</div>
<!-- Résumé du rapport -->
<div class="col-12 md:col-6">
<div class="card">
<h5 class="mb-3">Résumé</h5>
<div class="surface-50 p-3 border-round">
<p class="text-600 m-0">
Ce rapport contient les données analytiques et statistiques
pour la période sélectionnée. Les informations détaillées
sont disponibles dans le fichier téléchargeable.
</p>
</div>
</div>
</div>
</div>
<!-- Actions rapides -->
<div class="card mt-3">
<h5 class="mb-3">Actions</h5>
<div class="flex flex-wrap gap-2">
<p:commandButton value="Télécharger PDF"
icon="pi pi-file-pdf"
styleClass="ui-button-success"
action="#{rapportDetailsBean.telechargerRapport}"
update="messages"
rendered="#{rapportDetailsBean.isRapportDisponible()}"/>
<p:commandButton value="Télécharger Excel"
icon="pi pi-file-excel"
styleClass="ui-button-outlined ui-button-success"
action="#{rapportDetailsBean.telechargerRapport}"
update="messages"
rendered="#{rapportDetailsBean.isRapportDisponible()}"/>
<p:commandButton value="Régénérer le rapport"
icon="pi pi-refresh"
styleClass="ui-button-outlined ui-button-warning"
action="#{rapportDetailsBean.regenererRapport}"
update="messages"/>
<p:commandButton value="Partager"
icon="pi pi-share-alt"
styleClass="ui-button-outlined ui-button-info"
onclick="PF('dlgPartage').show();"/>
</div>
</div>
</h:panelGroup>
<!-- Message si rapport non trouvé -->
<h:panelGroup rendered="#{empty rapportDetailsBean.rapport}">
<div class="card">
<div class="text-center p-5">
<i class="pi pi-exclamation-triangle text-6xl text-orange-500 mb-3"></i>
<h3 class="mb-2">Rapport introuvable</h3>
<p class="text-600 mb-4">Le rapport demandé n'a pas été trouvé.</p>
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
<ui:param name="value" value="Retour aux rapports"/>
<ui:param name="icon" value="pi pi-arrow-left"/>
<ui:param name="action" value="#{rapportDetailsBean.retourner}"/>
</ui:include>
</div>
</div>
</h:panelGroup>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,170 @@
<!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:param name="page" value="#{rapportsBean}"/>
<ui:define name="title">Export de Rapports - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-download text-indigo-500" />
<ui:param name="title" value="Export de Rapports" />
<ui:param name="description" value="Générer et exporter des rapports personnalisés" />
</ui:include>
<!-- Formulaire de génération de rapport -->
<div class="card">
<h:form id="formRapport">
<h5>Nouveau Rapport</h5>
<div class="grid">
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="typeRapport" value="Type de Rapport *" />
<p:selectOneMenu id="typeRapport"
value="#{rapportsBean.nouveauRapport.type}"
styleClass="w-full"
required="true">
<f:selectItem itemLabel="Sélectionner un type" itemValue="" />
<f:selectItem itemLabel="Rapport Financier" itemValue="FINANCIER" />
<f:selectItem itemLabel="Rapport Membres" itemValue="MEMBRES" />
<f:selectItem itemLabel="Rapport Activités" itemValue="ACTIVITES" />
<f:selectItem itemLabel="Rapport Performance" itemValue="PERFORMANCE" />
<f:selectItem itemLabel="Rapport Complet" itemValue="COMPLET" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="formatRapport" value="Format *" />
<p:selectOneMenu id="formatRapport"
value="#{rapportsBean.nouveauRapport.format}"
styleClass="w-full"
required="true">
<f:selectItem itemLabel="PDF" itemValue="PDF" />
<f:selectItem itemLabel="Excel (.xlsx)" itemValue="EXCEL" />
<f:selectItem itemLabel="CSV" itemValue="CSV" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="periodeRapport" value="Période *" />
<p:selectOneMenu id="periodeRapport"
value="#{rapportsBean.nouveauRapport.periode}"
styleClass="w-full"
required="true">
<f:selectItem itemLabel="7 derniers jours" itemValue="7_JOURS" />
<f:selectItem itemLabel="30 derniers jours" itemValue="30_JOURS" />
<f:selectItem itemLabel="3 derniers mois" itemValue="3_MOIS" />
<f:selectItem itemLabel="6 derniers mois" itemValue="6_MOIS" />
<f:selectItem itemLabel="Année en cours" itemValue="ANNEE_COURANTE" />
<f:selectItem itemLabel="Période personnalisée" itemValue="PERSONNALISEE" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12 md:col-6">
<div class="field">
<p:outputLabel for="detailRapport" value="Niveau de Détail" />
<p:selectOneMenu id="detailRapport"
value="#{rapportsBean.nouveauRapport.detail}"
styleClass="w-full">
<f:selectItem itemLabel="Résumé" itemValue="RESUME" />
<f:selectItem itemLabel="Standard" itemValue="STANDARD" />
<f:selectItem itemLabel="Détaillé" itemValue="DETAILLE" />
</p:selectOneMenu>
</div>
</div>
<div class="col-12">
<div class="field">
<p:outputLabel for="commentairesRapport" value="Commentaires (optionnel)" />
<p:inputTextarea id="commentairesRapport"
value="#{rapportsBean.nouveauRapport.commentaires}"
rows="3"
styleClass="w-full"
placeholder="Ajoutez des commentaires ou notes pour ce rapport..." />
</div>
</div>
<div class="col-12">
<div class="flex justify-content-end gap-2">
<p:commandButton value="Réinitialiser"
icon="pi pi-refresh"
styleClass="p-button-outlined p-button-secondary"
action="#{rapportsBean.nouveauRapport = null}"
update="@form" />
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Générer le Rapport" />
<ui:param name="icon" value="pi pi-file" />
<ui:param name="action" value="#{rapportsBean.genererRapport}" />
<ui:param name="update" value="@form :formHistorique" />
</ui:include>
</div>
</div>
</div>
</h:form>
</div>
<!-- Historique des rapports -->
<div class="card">
<h:form id="formHistorique">
<h5>Historique des Rapports</h5>
<p:dataTable value="#{rapportsBean.historiqueRapports}" var="rapport"
emptyMessage="Aucun rapport généré"
paginator="true"
rows="10"
styleClass="p-datatable-sm">
<p:column headerText="Type">
<div class="flex align-items-center gap-2">
<i class="#{rapport.typeIcon} text-#{rapport.typeCouleur}"></i>
<span class="font-semibold">#{rapport.typeLibelle}</span>
</div>
</p:column>
<p:column headerText="Période">
<span>#{rapport.periodeCouverte}</span>
</p:column>
<p:column headerText="Date Génération">
<span>#{rapport.dateGenerationFormatee}</span>
</p:column>
<p:column headerText="Généré par">
<span>#{rapport.generePar}</span>
</p:column>
<p:column headerText="Statut">
<p:tag value="#{rapport.statut}"
severity="#{rapport.statutSeverity}" />
</p:column>
<p:column headerText="Actions" styleClass="text-center">
<div class="flex justify-content-center gap-1">
<p:commandButton icon="pi pi-eye"
title="Voir"
styleClass="p-button-sm p-button-rounded p-button-info"
action="#{rapportsBean.voirRapport(rapport)}" />
<p:commandButton icon="pi pi-download"
title="Télécharger"
styleClass="p-button-sm p-button-rounded p-button-success"
action="#{rapportsBean.telechargerRapport(rapport)}"
rendered="#{rapport.statut == 'GENERE'}" />
</div>
</p:column>
</p:dataTable>
</h:form>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,209 @@
<!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:param name="page" value="#{rapportsBean}"/>
<ui:define name="title">Rapports Financiers - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-dollar text-green-500" />
<ui:param name="title" value="Rapports Financiers" />
<ui:param name="description" value="Analyse financière et suivi des revenus" />
<ui:define name="actions">
<h:form id="formActions">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="onclick" value="PF('dlgExport').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{rapportsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Filtres de période -->
<div class="card">
<h:form id="formFiltres">
<h5>Période d'Analyse</h5>
<div class="grid">
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-select.xhtml">
<ui:param name="id" value="periodeRapide" />
<ui:param name="label" value="Période Rapide" />
<ui:param name="value" value="#{rapportsBean.periodeRapide}" />
<ui:param name="update" value="@form" />
<ui:define name="items">
<f:selectItem itemLabel="7 derniers jours" itemValue="7_JOURS" />
<f:selectItem itemLabel="30 derniers jours" itemValue="30_JOURS" />
<f:selectItem itemLabel="3 derniers mois" itemValue="3_MOIS" />
<f:selectItem itemLabel="6 derniers mois" itemValue="6_MOIS" />
<f:selectItem itemLabel="Année en cours" itemValue="ANNEE_COURANTE" />
</ui:define>
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateDebut" />
<ui:param name="label" value="Date Début" />
<ui:param name="value" value="#{rapportsBean.dateDebut}" />
<ui:param name="update" value="@form" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<ui:include src="/templates/components/forms/form-field-calendar.xhtml">
<ui:param name="id" value="dateFin" />
<ui:param name="label" value="Date Fin" />
<ui:param name="value" value="#{rapportsBean.dateFin}" />
<ui:param name="update" value="@form" />
</ui:include>
</div>
<div class="col-12 md:col-3">
<div class="field">
<p:outputLabel />
<ui:include src="/templates/components/buttons/button-primary.xhtml">
<ui:param name="value" value="Appliquer" />
<ui:param name="icon" value="pi pi-check" />
<ui:param name="action" value="#{rapportsBean.chargerDonnees}" />
<ui:param name="update" value="@form" />
</ui:include>
</div>
</div>
</div>
</h:form>
</div>
<!-- Indicateurs financiers -->
<div class="grid">
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{rapportsBean.indicateurs.revenus}" />
<ui:param name="label" value="Revenus Totaux" />
<ui:param name="icon" value="pi pi-dollar" />
<ui:param name="bgColor" value="green" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{rapportsBean.indicateurs.croissanceRevenus}%" />
<ui:param name="label" value="Croissance Revenus" />
<ui:param name="icon" value="pi pi-arrow-up" />
<ui:param name="bgColor" value="blue" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{rapportsBean.indicateurs.totalMembres}" />
<ui:param name="label" value="Membres Actifs" />
<ui:param name="icon" value="pi pi-users" />
<ui:param name="bgColor" value="purple" />
</ui:include>
<ui:include src="/templates/components/cards/stat-card.xhtml">
<ui:param name="value" value="#{rapportsBean.indicateurs.croissanceMembres}%" />
<ui:param name="label" value="Croissance Membres" />
<ui:param name="icon" value="pi pi-chart-line" />
<ui:param name="bgColor" value="orange" />
</ui:include>
</div>
<!-- Sources de revenus -->
<div class="card">
<h5>Sources de Revenus</h5>
<p:dataTable value="#{rapportsBean.sourceRevenus}" var="source"
emptyMessage="Aucune donnée disponible"
styleClass="p-datatable-sm">
<p:column headerText="Source">
<div class="flex align-items-center gap-2">
<i class="#{source.icon} text-lg"></i>
<span class="font-semibold">#{source.libelle}</span>
</div>
</p:column>
<p:column headerText="Montant">
<span class="font-bold">#{source.montant} FCFA</span>
</p:column>
<p:column headerText="Pourcentage">
<p:progressBar value="#{source.pourcentage}"
showValue="true"
styleClass="p-progressbar-sm" />
</p:column>
</p:dataTable>
</div>
<!-- KPIs Financiers -->
<div class="card">
<h5>Indicateurs Clés de Performance</h5>
<div class="formgrid grid">
<ui:repeat value="#{rapportsBean.kpis}" var="kpi">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="#{kpi.libelle}" />
<ui:param name="value" value="#{kpi.valeur}" />
<ui:param name="icon" value="#{kpi.icon}" />
<ui:param name="iconColor" value="#{kpi.couleur}" />
<ui:param name="growthValue" value="#{kpi.variation}" />
<ui:param name="growthLabel" value="variation" />
<ui:param name="colSize" value="col-12 md:col-4" />
<ui:param name="showProgress" value="false" />
</ui:include>
</ui:repeat>
</div>
</div>
<!-- Dialog Export -->
<h:form id="formExport">
<p:dialog id="dlgExport"
widgetVar="dlgExport"
header="Exporter le Rapport Financier"
modal="true"
resizable="false"
style="width: 90vw; max-width: 500px;">
<div class="grid">
<div class="col-12">
<div class="field">
<p:outputLabel for="formatExport" value="Format d'Export" />
<p:selectOneRadio id="formatExport"
value="#{rapportsBean.nouveauRapport.format}"
layout="grid"
columns="1">
<f:selectItem itemLabel="PDF" itemValue="PDF" />
<f:selectItem itemLabel="Excel (.xlsx)" itemValue="EXCEL" />
<f:selectItem itemLabel="CSV" itemValue="CSV" />
</p:selectOneRadio>
</div>
</div>
</div>
<f:facet name="footer">
<div class="flex justify-content-end gap-2">
<p:commandButton value="Annuler"
styleClass="p-button-outlined"
onclick="PF('dlgExport').hide();"
type="button" />
<p:commandButton value="Exporter"
icon="pi pi-download"
styleClass="p-button-success"
action="#{rapportsBean.exporterDonnees}" />
</div>
</f:facet>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,150 @@
<!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:param name="page" value="#{rapportsBean}"/>
<ui:define name="title">Rapports Membres - UnionFlow</ui:define>
<ui:define name="content">
<!-- En-tête -->
<ui:include src="/templates/components/layout/page-header.xhtml">
<ui:param name="icon" value="pi pi-users text-blue-500" />
<ui:param name="title" value="Rapports Membres" />
<ui:param name="description" value="Analyse et statistiques sur les membres" />
<ui:define name="actions">
<h:form id="formActions">
<div class="flex gap-2">
<ui:include src="/templates/components/buttons/button-success.xhtml">
<ui:param name="value" value="Exporter" />
<ui:param name="icon" value="pi pi-download" />
<ui:param name="onclick" value="PF('dlgExport').show();" />
</ui:include>
<ui:include src="/templates/components/buttons/button-icon.xhtml">
<ui:param name="icon" value="pi pi-refresh" />
<ui:param name="action" value="#{rapportsBean.actualiser}" />
<ui:param name="update" value="@form" />
<ui:param name="title" value="Actualiser" />
<ui:param name="rounded" value="true" />
<ui:param name="text" value="false" />
<ui:param name="styleClass" value="ui-button-outlined ui-button-secondary" />
</ui:include>
</div>
</h:form>
</ui:define>
</ui:include>
<!-- Statistiques membres -->
<div class="formgrid grid">
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Total Membres" />
<ui:param name="value" value="#{rapportsBean.indicateurs.totalMembres}" />
<ui:param name="icon" value="pi-users" />
<ui:param name="iconColor" value="blue-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
</ui:include>
<ui:include src="/templates/components/cards/kpi-card.xhtml">
<ui:param name="title" value="Croissance" />
<ui:param name="value" value="#{rapportsBean.indicateurs.croissanceMembres}%" />
<ui:param name="icon" value="pi-arrow-up" />
<ui:param name="iconColor" value="green-600" />
<ui:param name="showGrowth" value="false" />
<ui:param name="showProgress" value="false" />
</ui:include>
</div>
<!-- Répartition des membres -->
<div class="card">
<h5>Répartition des Membres</h5>
<p:dataTable value="#{rapportsBean.repartitionMembres}" var="repartition"
emptyMessage="Aucune donnée disponible"
styleClass="p-datatable-sm">
<p:column headerText="Statut">
<div class="flex align-items-center gap-2">
<div class="w-1rem h-1rem border-circle bg-#{repartition.couleur}"></div>
<span class="font-semibold">#{repartition.libelle}</span>
</div>
</p:column>
<p:column headerText="Nombre">
<span class="font-bold">#{repartition.nombre}</span>
</p:column>
<p:column headerText="Pourcentage">
<p:progressBar value="#{repartition.pourcentage}"
showValue="true"
styleClass="p-progressbar-sm" />
</p:column>
</p:dataTable>
</div>
<!-- Objectifs -->
<div class="card">
<h5>Objectifs</h5>
<div class="grid">
<ui:repeat value="#{rapportsBean.objectifs}" var="objectif">
<div class="col-12 md:col-6">
<div class="surface-100 border-round-lg p-4">
<div class="flex align-items-center justify-content-between mb-3">
<span class="font-semibold">#{objectif.libelle}</span>
<span class="text-sm text-600">#{objectif.pourcentage}%</span>
</div>
<p:progressBar value="#{objectif.pourcentage}"
showValue="false"
styleClass="p-progressbar-sm mb-2" />
<div class="flex justify-content-between text-sm">
<span class="text-600">Réalisé: #{objectif.realise}</span>
<span class="text-600">Cible: #{objectif.cible}</span>
</div>
</div>
</div>
</ui:repeat>
</div>
</div>
<!-- Dialog Export -->
<h:form id="formExport">
<p:dialog id="dlgExport"
widgetVar="dlgExport"
header="Exporter le Rapport Membres"
modal="true"
resizable="false"
style="width: 90vw; max-width: 500px;">
<div class="grid">
<div class="col-12">
<div class="field">
<p:outputLabel for="formatExport" value="Format d'Export" />
<p:selectOneRadio id="formatExport"
value="#{rapportsBean.nouveauRapport.format}"
layout="grid"
columns="1">
<f:selectItem itemLabel="PDF" itemValue="PDF" />
<f:selectItem itemLabel="Excel (.xlsx)" itemValue="EXCEL" />
<f:selectItem itemLabel="CSV" itemValue="CSV" />
</p:selectOneRadio>
</div>
</div>
</div>
<f:facet name="footer">
<div class="flex justify-content-end gap-2">
<p:commandButton value="Annuler"
styleClass="p-button-outlined"
onclick="PF('dlgExport').hide();"
type="button" />
<p:commandButton value="Exporter"
icon="pi pi-download"
styleClass="p-button-success"
action="#{rapportsBean.exporterDonnees}" />
</div>
</f:facet>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,26 @@
<!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">UnionFlow - Rapports</ui:define>
<ui:define name="content">
<div class="grid">
<div class="col-12">
<div class="card">
<h2>Rapports</h2>
<p>Génération et consultation de rapports</p>
<p:button value="Retour au tableau de bord"
icon="pi pi-arrow-left"
outcome="/pages/secure/dashboard"/>
</div>
</div>
</div>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,355 @@
<!DOCTYPE html>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
template="/templates/main-template.xhtml">
<ui:define name="title">Gestion de la Souscription - UnionFlow</ui:define>
<ui:define name="head">
<style>
.subscription-header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 2rem;
border-radius: 12px;
margin-bottom: 2rem;
}
.quota-gauge {
position: relative;
width: 120px;
height: 120px;
margin: 0 auto;
}
.quota-progress {
transform: rotate(-90deg);
}
.quota-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}
.feature-badge {
display: inline-flex;
align-items: center;
padding: 4px 8px;
border-radius: 16px;
font-size: 0.75rem;
font-weight: 600;
margin: 2px;
}
.feature-active {
background: #dcfce7;
color: #166534;
}
.feature-inactive {
background: #f3f4f6;
color: #6b7280;
}
.upgrade-card {
border: 2px solid #10b981;
position: relative;
overflow: hidden;
}
.upgrade-card::before {
content: 'RECOMMANDÉ';
position: absolute;
top: 12px;
right: -30px;
background: #10b981;
color: white;
padding: 4px 40px;
font-size: 0.7rem;
font-weight: 600;
transform: rotate(45deg);
}
</style>
</ui:define>
<ui:define name="content">
<!-- En-tête de souscription -->
<div class="subscription-header">
<div class="flex align-items-center justify-content-between">
<div>
<h1 class="text-4xl font-bold mb-2">
<i class="#{souscriptionBean.iconeStatut} mr-2"></i>
#{souscriptionBean.souscriptionActive.formulaireNom}
</h1>
<div class="text-xl opacity-90 mb-1">
#{souscriptionBean.souscriptionActive.organisationNom}
</div>
<div class="text-lg opacity-80">
Souscription #{souscriptionBean.souscriptionActive.statut.libelle}
- #{souscriptionBean.souscriptionActive.typeFacturation.libelle}
</div>
</div>
<div class="text-right">
<div class="text-2xl font-bold mb-1">
#{souscriptionBean.souscriptionActive.montantFormat}
</div>
<div class="opacity-90">
Expire le #{souscriptionBean.souscriptionActive.dateFin}
</div>
<h:panelGroup rendered="#{souscriptionBean.joursAvantExpiration le 30}">
<div class="text-yellow-300 font-semibold mt-1">
<i class="pi pi-clock mr-1"></i>
#{souscriptionBean.joursAvantExpiration} jour(s) restant(s)
</div>
</h:panelGroup>
</div>
</div>
</div>
<!-- Alertes quota et expiration -->
<h:panelGroup rendered="#{not empty souscriptionBean.alertesQuota}">
<div class="grid mb-4">
<ui:repeat value="#{souscriptionBean.alertesQuota}" var="alerte">
<div class="col-12">
<p:message severity="#{alerte.severite}"
summary="#{alerte.titre}"
detail="#{alerte.message}"
closable="false">
<div class="flex align-items-center justify-content-between">
<div class="flex align-items-center">
<i class="#{alerte.icone} mr-2"></i>
<div>
<div class="font-semibold">#{alerte.titre}</div>
<div>#{alerte.message}</div>
</div>
</div>
<p:commandButton value="#{alerte.action}"
action="#{alerte.actionUrl}"
styleClass="p-button-sm p-button-outlined"
rendered="#{not empty alerte.action}"/>
</div>
</p:message>
</div>
</ui:repeat>
</div>
</h:panelGroup>
<div class="grid">
<!-- Utilisation du quota -->
<div class="col-12 md:col-4">
<div class="surface-card p-4 border-round shadow-2">
<div class="text-center mb-4">
<div class="text-900 font-bold text-xl mb-2">Quota de Membres</div>
<!-- Jauge circulaire du quota -->
<div class="quota-gauge mb-3">
<svg width="120" height="120" class="quota-progress">
<circle cx="60" cy="60" r="50"
stroke="#e5e7eb" stroke-width="8"
fill="transparent"/>
<circle cx="60" cy="60" r="50"
stroke="#{souscriptionBean.couleurJaugeQuota == 'success' ? '#10b981' : souscriptionBean.couleurJaugeQuota == 'warning' ? '#f59e0b' : '#ef4444'}"
stroke-width="8"
fill="transparent"
stroke-dasharray="314"
stroke-dashoffset="#{314 - (314 * souscriptionBean.souscriptionActive.pourcentageUtilisation / 100)}"
stroke-linecap="round"/>
</svg>
<div class="quota-text">
<div class="text-2xl font-bold text-900">#{souscriptionBean.souscriptionActive.pourcentageUtilisation}%</div>
<div class="text-sm text-600">utilisé</div>
</div>
</div>
<div class="text-600 mb-2">
#{souscriptionBean.membresActuels} / #{souscriptionBean.quotaMaximum} membres
</div>
<div class="text-900 font-semibold">
#{souscriptionBean.membresRestants} membre(s) restant(s)
</div>
</div>
<div class="flex gap-2">
<p:commandButton value="Upgrader"
action="#{souscriptionBean.upgraderFormulaire()}"
styleClass="p-button-success flex-1"
rendered="#{souscriptionBean.alerteQuotaProche or souscriptionBean.quotaAtteint}"/>
<p:commandButton value="Gérer les membres"
action="/pages/secure/membre/liste"
styleClass="p-button-outlined flex-1"/>
</div>
</div>
</div>
<!-- Détails de la souscription -->
<div class="col-12 md:col-5">
<div class="surface-card p-4 border-round shadow-2">
<div class="text-900 font-bold text-xl mb-3">Détails de la Souscription</div>
<div class="formgrid grid">
<div class="field col-6">
<label class="block text-600 font-medium mb-2">Date de début</label>
<div class="text-900">#{souscriptionBean.souscriptionActive.dateDebut}</div>
</div>
<div class="field col-6">
<label class="block text-600 font-medium mb-2">Date de fin</label>
<div class="text-900">#{souscriptionBean.souscriptionActive.dateFin}</div>
</div>
<div class="field col-6">
<label class="block text-600 font-medium mb-2">Dernier paiement</label>
<div class="text-900">#{souscriptionBean.souscriptionActive.dateDernierPaiement}</div>
</div>
<div class="field col-6">
<label class="block text-600 font-medium mb-2">Prochain paiement</label>
<div class="text-900">#{souscriptionBean.souscriptionActive.dateProchainPaiement}</div>
</div>
<div class="field col-12">
<label class="block text-600 font-medium mb-2">Référence de paiement</label>
<div class="text-900 font-mono">#{souscriptionBean.souscriptionActive.referencePaiement}</div>
</div>
</div>
<!-- Notifications -->
<div class="mt-4 pt-3 border-top-1 surface-border">
<div class="text-900 font-semibold mb-3">Notifications</div>
<div class="flex align-items-center justify-content-between mb-2">
<label for="notif-expiration" class="text-900">Expiration de souscription</label>
<p:inputSwitch id="notif-expiration"
value="#{souscriptionBean.souscriptionActive.notificationExpiration}"
onLabel="ON" offLabel="OFF">
<p:ajax listener="#{souscriptionBean.activerNotificationExpiration(souscriptionBean.souscriptionActive.notificationExpiration)}" />
</p:inputSwitch>
</div>
<div class="flex align-items-center justify-content-between">
<label for="notif-quota" class="text-900">Quota de membres atteint</label>
<p:inputSwitch id="notif-quota"
value="#{souscriptionBean.souscriptionActive.notificationQuotaAtteint}"
onLabel="ON" offLabel="OFF">
<p:ajax listener="#{souscriptionBean.activerNotificationQuota(souscriptionBean.souscriptionActive.notificationQuotaAtteint)}" />
</p:inputSwitch>
</div>
</div>
</div>
</div>
<!-- Actions rapides -->
<div class="col-12 md:col-3">
<div class="surface-card p-4 border-round shadow-2">
<div class="text-900 font-bold text-xl mb-3">Actions</div>
<div class="flex flex-column gap-3">
<p:commandButton value="Renouveler"
action="#{souscriptionBean.renouvelerSouscription()}"
styleClass="p-button w-full"
icon="pi pi-refresh"/>
<p:commandButton value="Changer de plan"
action="#{souscriptionBean.changerFormulaire()}"
styleClass="p-button-outlined w-full"
icon="pi pi-sync"/>
<p:commandButton value="Historique des paiements"
action="/pages/secure/souscription/historique"
styleClass="p-button-outlined w-full"
icon="pi pi-history"/>
<p:commandButton value="Télécharger facture"
styleClass="p-button-outlined w-full"
icon="pi pi-download"/>
</div>
</div>
</div>
</div>
<!-- Formulaires disponibles pour upgrade -->
<h:panelGroup rendered="#{souscriptionBean.alerteQuotaProche or souscriptionBean.quotaAtteint}">
<div class="surface-card p-6 border-round shadow-2 mt-4">
<div class="text-center mb-4">
<h2 class="text-900 text-3xl font-bold mb-2">Besoin de plus d'espace ?</h2>
<p class="text-600 text-lg">Découvrez nos formules supérieures pour accueillir plus de membres</p>
</div>
<div class="grid">
<div class="col-12 md:col-6">
<div class="surface-border border-round p-4">
<div class="text-center mb-3">
<div class="bg-green-500 text-white inline-flex align-items-center justify-content-center border-circle mb-3" style="width: 60px; height: 60px;">
<i class="pi pi-users text-2xl"></i>
</div>
<div class="text-900 font-bold text-2xl">Premium</div>
<div class="text-600">Jusqu'à 500 membres</div>
</div>
<div class="text-center mb-4">
<div class="text-900 text-3xl font-bold">4 000 FCFA/mois</div>
<div class="text-600">40 000 FCFA/an (économisez 16%)</div>
</div>
<div class="flex flex-wrap gap-1 mb-4">
<span class="feature-badge feature-active">
<i class="pi pi-check mr-1"></i>Gestion complète
</span>
<span class="feature-badge feature-active">
<i class="pi pi-check mr-1"></i>Rapports avancés
</span>
<span class="feature-badge feature-active">
<i class="pi pi-check mr-1"></i>Support prioritaire
</span>
<span class="feature-badge feature-active">
<i class="pi pi-check mr-1"></i>Intégrations
</span>
</div>
<p:commandButton value="Upgrader vers Premium"
styleClass="p-button-success w-full"
action="/pages/secure/souscription/upgrade?plan=premium"/>
</div>
</div>
<div class="col-12 md:col-6">
<div class="upgrade-card surface-border border-round p-4">
<div class="text-center mb-3">
<div class="bg-indigo-500 text-white inline-flex align-items-center justify-content-center border-circle mb-3" style="width: 60px; height: 60px;">
<i class="pi pi-diamond text-2xl"></i>
</div>
<div class="text-900 font-bold text-2xl">Cristal</div>
<div class="text-600">Jusqu'à 2000 membres</div>
</div>
<div class="text-center mb-4">
<div class="text-900 text-3xl font-bold">5 000 FCFA/mois</div>
<div class="text-600">50 000 FCFA/an (économisez 16%)</div>
</div>
<div class="flex flex-wrap gap-1 mb-4">
<span class="feature-badge feature-active">
<i class="pi pi-check mr-1"></i>Tout Premium +
</span>
<span class="feature-badge feature-active">
<i class="pi pi-check mr-1"></i>Personnalisation
</span>
<span class="feature-badge feature-active">
<i class="pi pi-check mr-1"></i>API complète
</span>
<span class="feature-badge feature-active">
<i class="pi pi-check mr-1"></i>Support dédié
</span>
</div>
<p:commandButton value="Upgrader vers Cristal"
styleClass="p-button-help w-full"
action="/pages/secure/souscription/upgrade?plan=cristal"/>
</div>
</div>
</div>
</div>
</h:panelGroup>
</ui:define>
</ui:composition>

View File

@@ -0,0 +1,18 @@
<!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:param name="page" value="#{dashboardBean}"/>
<ui:define name="title">Statistiques - UnionFlow</ui:define>
<ui:define name="content">
<!-- Redirection vers dashboard (WOU/DRY - réutiliser la même page) -->
<h:form>
<p:commandButton value="Voir le tableau de bord"
action="dashboardPage?faces-redirect=true"
styleClass="ui-button-primary"/>
</h:form>
</ui:define>
</ui:composition>