feat(client): Creation page modification membre exhaustive et formulaire reutilisable
NOUVELLES PAGES: - modifier.xhtml : Page dediee pour modifier un membre (exhaustive) - membre-form.xhtml : Fragment reutilisable pour formulaire membre (DRY/WOU) STRUCTURE DU FORMULAIRE (blocs thematiques): - Identite : nom, prenom, dateNaissance, nationalite - Contact : email, telephone - Localisation : adresse, ville, region, quartier - Professionnel : profession, statutMatrimonial - Piece identite : typeIdentite, numeroIdentite - Organisation : association, role, membreBureau, responsable - Photo : photoUrl BEAN (MembreListeBean): - Ajout membreSelectionneId, membreSelectionne - Ajout chargerMembreSelectionne() : charge membre par ID - Ajout modifierMembreSelectionne() : sauvegarde modifications - Ajout getOrganisationsSelectItems() : dropdown organisations (TODO) - Correction modifierMembre() : redirige vers modifier.xhtml BOUTON MODIFIER dans liste.xhtml: - Navigation directe vers modifier.xhtml au lieu de popup - Coherence avec inscription.xhtml Respecte DRY/WOU avec formulaire reutilisable membre-form.xhtml
This commit is contained in:
@@ -191,7 +191,65 @@ public class MembreListeBean implements Serializable {
|
||||
}
|
||||
|
||||
public String modifierMembre(MembreDTO membre) {
|
||||
return "/pages/secure/membre/modification?id=" + membre.getId() + "&faces-redirect=true";
|
||||
return "/pages/secure/membre/modifier?id=" + membre.getId() + "&faces-redirect=true";
|
||||
}
|
||||
|
||||
// Propriétés pour la page de modification
|
||||
private UUID membreSelectionneId;
|
||||
private MembreDTO membreSelectionne;
|
||||
|
||||
public UUID getMembreSelectionneId() {
|
||||
return membreSelectionneId;
|
||||
}
|
||||
|
||||
public void setMembreSelectionneId(UUID membreSelectionneId) {
|
||||
this.membreSelectionneId = membreSelectionneId;
|
||||
}
|
||||
|
||||
public MembreDTO getMembreSelectionne() {
|
||||
return membreSelectionne;
|
||||
}
|
||||
|
||||
public void setMembreSelectionne(MembreDTO membreSelectionne) {
|
||||
this.membreSelectionne = membreSelectionne;
|
||||
}
|
||||
|
||||
public void chargerMembreSelectionne() {
|
||||
if (membreSelectionneId != null) {
|
||||
try {
|
||||
membreSelectionne = membreService.obtenirParId(membreSelectionneId);
|
||||
LOGGER.info("Membre chargé pour modification: " + membreSelectionne.getNomComplet());
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors du chargement du membre: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de charger le membre: " + e.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String modifierMembreSelectionne() {
|
||||
try {
|
||||
membreService.modifier(membreSelectionne.getId(), membreSelectionne);
|
||||
LOGGER.info("Membre modifié: " + membreSelectionne.getNomComplet());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès",
|
||||
"Le membre a été modifié avec succès"));
|
||||
return "/pages/secure/membre/liste?faces-redirect=true";
|
||||
} catch (Exception e) {
|
||||
LOGGER.severe("Erreur lors de la modification: " + e.getMessage());
|
||||
FacesContext.getCurrentInstance().addMessage(null,
|
||||
new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur",
|
||||
"Impossible de modifier le membre: " + e.getMessage()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Méthode pour obtenir la liste des organisations pour le dropdown
|
||||
public List<jakarta.faces.model.SelectItem> getOrganisationsSelectItems() {
|
||||
// TODO: Implémenter la récupération des organisations
|
||||
// Pour l'instant, retourner une liste vide
|
||||
return new java.util.ArrayList<>();
|
||||
}
|
||||
|
||||
public String gererCotisations(MembreDTO membre) {
|
||||
|
||||
@@ -195,12 +195,10 @@
|
||||
<uf:action-button-view itemId="#{membre.id}"
|
||||
detailPage="/pages/secure/membre/profil.xhtml"
|
||||
iconOnly="true"/>
|
||||
<ui:include src="/templates/components/buttons/button-icon.xhtml">
|
||||
<ui:param name="icon" value="pi pi-pencil" />
|
||||
<ui:param name="action" value="#{membreListeBean.modifierMembre(membre)}" />
|
||||
<ui:param name="title" value="Modifier" />
|
||||
<ui:param name="severity" value="warning" />
|
||||
</ui:include>
|
||||
<p:commandButton icon="pi pi-pencil"
|
||||
title="Modifier"
|
||||
styleClass="ui-button-rounded ui-button-warning"
|
||||
onclick="window.location='#{request.contextPath}/pages/secure/membre/modifier.xhtml?id=#{membre.id}';return false;"/>
|
||||
<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)}" />
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui">
|
||||
|
||||
<ui:composition template="/templates/main-template.xhtml">
|
||||
<ui:define name="title">Modifier le Membre</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<!-- Charger le membre à modifier -->
|
||||
<f:metadata>
|
||||
<f:viewParam name="id" value="#{membreListeBean.membreSelectionneId}" />
|
||||
<f:viewAction action="#{membreListeBean.chargerMembreSelectionne}" />
|
||||
</f:metadata>
|
||||
|
||||
<h:form id="formModifierMembre">
|
||||
<p:messages id="messages" showDetail="true" closable="true"/>
|
||||
|
||||
<div class="card mb-3">
|
||||
<div class="flex justify-content-between align-items-center flex-column md:flex-row">
|
||||
<div class="mb-2 md:mb-0">
|
||||
<h3 class="m-0">Modifier le Membre</h3>
|
||||
<span class="text-600">
|
||||
Modifiez les informations du membre.
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<!-- DRY/WOU: button-secondary pour navigation -->
|
||||
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
|
||||
<ui:param name="value" value="Annuler"/>
|
||||
<ui:param name="icon" value="pi pi-times"/>
|
||||
<ui:param name="outcome" value="/pages/secure/membre/liste"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h5 class="mb-3">Informations du Membre</h5>
|
||||
<ui:include src="/ui/includes/membre-form.xhtml">
|
||||
<ui:param name="model" value="#{membreListeBean.membreSelectionne}" />
|
||||
<ui:param name="organisationsItems" value="#{membreListeBean.organisationsSelectItems}" />
|
||||
</ui:include>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 flex justify-content-end gap-2">
|
||||
<!-- DRY/WOU: button-secondary pour navigation -->
|
||||
<ui:include src="/templates/components/buttons/button-secondary.xhtml">
|
||||
<ui:param name="value" value="Annuler"/>
|
||||
<ui:param name="icon" value="pi pi-times"/>
|
||||
<ui:param name="outcome" value="/pages/secure/membre/liste"/>
|
||||
</ui:include>
|
||||
<!-- Bouton Enregistrer : p:commandButton direct car action avec méthode backend -->
|
||||
<p:commandButton value="Enregistrer"
|
||||
icon="pi pi-check"
|
||||
action="#{membreListeBean.modifierMembreSelectionne}"
|
||||
update=":formModifierMembre:messages"
|
||||
styleClass="ui-button-success" />
|
||||
</div>
|
||||
</h:form>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
<ui:fragment 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">
|
||||
|
||||
<!--
|
||||
Fragment de formulaire réutilisable pour les membres (DRY/WOU)
|
||||
Utilisé pour création et modification
|
||||
|
||||
Paramètres:
|
||||
- model : MembreDTO à éditer
|
||||
- organisationsItems : Liste des organisations pour le dropdown
|
||||
-->
|
||||
|
||||
<div class="ui-fluid">
|
||||
<div class="formgrid grid">
|
||||
|
||||
<!-- Bloc Identité -->
|
||||
<div class="col-12">
|
||||
<div class="card p-fluid mb-3">
|
||||
<h5 class="mb-3">Identité</h5>
|
||||
<div class="grid formgrid">
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:outputLabel for="nom" value="Nom *" />
|
||||
<p:inputText id="nom" value="#{model.nom}" required="true" requiredMessage="Nom: une donnée est requise." maxlength="50" />
|
||||
<p:message for="nom" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:outputLabel for="prenom" value="Prénom *" />
|
||||
<p:inputText id="prenom" value="#{model.prenom}" required="true" requiredMessage="Prénom: une donnée est requise." maxlength="50" />
|
||||
<p:message for="prenom" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:outputLabel for="dateNaissance" value="Date de naissance" />
|
||||
<p:datePicker id="dateNaissance" value="#{model.dateNaissance}" pattern="yyyy-MM-dd" showIcon="true" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:outputLabel for="nationalite" value="Nationalité" />
|
||||
<p:inputText id="nationalite" value="#{model.nationalite}" maxlength="50" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bloc Contact -->
|
||||
<div class="col-12">
|
||||
<div class="card p-fluid mb-3">
|
||||
<h5 class="mb-3">Contact</h5>
|
||||
<div class="grid formgrid">
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:outputLabel for="email" value="Email *" />
|
||||
<p:inputText id="email" value="#{model.email}" required="true" requiredMessage="Email: une donnée est requise." maxlength="100" />
|
||||
<p:message for="email" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:outputLabel for="telephone" value="Téléphone" />
|
||||
<p:inputText id="telephone" value="#{model.telephone}" maxlength="20" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bloc Localisation -->
|
||||
<div class="col-12">
|
||||
<div class="card p-fluid mb-3">
|
||||
<h5 class="mb-3">Localisation</h5>
|
||||
<div class="grid formgrid">
|
||||
<div class="field col-12">
|
||||
<p:outputLabel for="adresse" value="Adresse" />
|
||||
<p:inputTextarea id="adresse" value="#{model.adresse}" rows="2" maxlength="200" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-4">
|
||||
<p:outputLabel for="ville" value="Ville" />
|
||||
<p:inputText id="ville" value="#{model.ville}" maxlength="50" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-4">
|
||||
<p:outputLabel for="region" value="Région" />
|
||||
<p:inputText id="region" value="#{model.region}" maxlength="50" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-4">
|
||||
<p:outputLabel for="quartier" value="Quartier" />
|
||||
<p:inputText id="quartier" value="#{model.quartier}" maxlength="50" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bloc Professionnel -->
|
||||
<div class="col-12">
|
||||
<div class="card p-fluid mb-3">
|
||||
<h5 class="mb-3">Informations professionnelles</h5>
|
||||
<div class="grid formgrid">
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:outputLabel for="profession" value="Profession" />
|
||||
<p:inputText id="profession" value="#{model.profession}" maxlength="100" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:outputLabel for="statutMatrimonial" value="Statut matrimonial" />
|
||||
<p:inputText id="statutMatrimonial" value="#{model.statutMatrimonial}" maxlength="20" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bloc Identité administrative -->
|
||||
<div class="col-12">
|
||||
<div class="card p-fluid mb-3">
|
||||
<h5 class="mb-3">Pièce d'identité</h5>
|
||||
<div class="grid formgrid">
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:outputLabel for="typeIdentite" value="Type de pièce" />
|
||||
<p:selectOneMenu id="typeIdentite" value="#{model.typeIdentite}">
|
||||
<f:selectItem itemLabel="Sélectionner..." itemValue="" />
|
||||
<f:selectItem itemLabel="Carte Nationale d'Identité" itemValue="CNI" />
|
||||
<f:selectItem itemLabel="Passeport" itemValue="PASSEPORT" />
|
||||
<f:selectItem itemLabel="Permis de conduire" itemValue="PERMIS" />
|
||||
<f:selectItem itemLabel="Autre" itemValue="AUTRE" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:outputLabel for="numeroIdentite" value="Numéro de pièce" />
|
||||
<p:inputText id="numeroIdentite" value="#{model.numeroIdentite}" maxlength="50" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bloc Organisation -->
|
||||
<div class="col-12">
|
||||
<div class="card p-fluid mb-3">
|
||||
<h5 class="mb-3">Organisation & Rôle</h5>
|
||||
<div class="grid formgrid">
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:outputLabel for="association" value="Organisation *" />
|
||||
<p:selectOneMenu id="association" value="#{model.associationId}" required="true" requiredMessage="Organisation: une donnée est requise.">
|
||||
<f:selectItems value="#{organisationsItems}" />
|
||||
</p:selectOneMenu>
|
||||
<p:message for="association" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-6">
|
||||
<p:outputLabel for="role" value="Rôle" />
|
||||
<p:inputText id="role" value="#{model.role}" maxlength="50" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-4">
|
||||
<p:selectBooleanCheckbox id="membreBureau" value="#{model.membreBureau}" />
|
||||
<p:outputLabel for="membreBureau" value="Membre du bureau" style="margin-left: 0.5rem;" />
|
||||
</div>
|
||||
<div class="field col-12 md:col-4">
|
||||
<p:selectBooleanCheckbox id="responsable" value="#{model.responsable}" />
|
||||
<p:outputLabel for="responsable" value="Responsable" style="margin-left: 0.5rem;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Bloc Photo -->
|
||||
<div class="col-12">
|
||||
<div class="card p-fluid mb-3">
|
||||
<h5 class="mb-3">Photo de profil</h5>
|
||||
<div class="grid formgrid">
|
||||
<div class="field col-12">
|
||||
<p:outputLabel for="photoUrl" value="URL de la photo" />
|
||||
<p:inputText id="photoUrl" value="#{model.photoUrl}" maxlength="255" placeholder="https://..." />
|
||||
<small class="text-600">Entrez l'URL d'une photo ou laissez vide pour utiliser l'avatar par défaut</small>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</ui:fragment>
|
||||
|
||||
Reference in New Issue
Block a user