Configure Maven repository for unionflow-server-api dependency
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 && 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 && placeholder && 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 && !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 && 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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user