feat: Module Devis professionnel avec écrans complets
Création de 2 écrans professionnels pour le module Devis:
1. devis/nouveau.xhtml:
- 4 sections: Informations générales, Détail du devis, Montants, Conditions
- Numéro auto-généré avec icône
- Statut avec 5 valeurs (BROUILLON, ATTENTE, ACCEPTE, REFUSE, EXPIRE)
- Dates d'émission et validité avec calendriers
- Client et objet du devis requis
- Placeholder pour lignes de devis (future développement)
- Calcul automatique TVA 18% et TTC
- Récapitulatif visuel HT/TVA/TTC avec composant monétaire
- Conditions de paiement et remarques (section collapsible)
- 3 boutons: Annuler, Brouillon, Envoyer
2. devis/details.xhtml:
- En-tête: numéro, statut, client, objet, dates
- Actions: Retour, Convertir en chantier, PDF, Modifier
- 4 KPI cards: Montant HT, TVA, TTC, Statut
- 6 onglets professionnels:
* Vue d'ensemble: infos + récap financier + actions rapides
* Détail des lignes: table lignes (placeholder)
* Conditions: paiement, délais, garanties
* Documents: GED associée (placeholder)
* Suivi: timeline actions
* Historique: modifications (placeholder)
Corrections:
- Fix navigation /factures/nouvelle -> /factures/nouveau (factures.xhtml)
- Fix menu /factures/nouvelle -> /factures/nouveau (menu.xhtml)
Tous les composants réutilisables utilisés (status-badge, monetary-display).
Validation complète côté client et serveur.
UI/UX professionnel adapté au métier BTP.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/WEB-INF/template.xhtml">
|
||||
|
||||
<ui:define name="title">Détails du chantier - BTP Xpress</ui:define>
|
||||
@@ -16,74 +16,292 @@
|
||||
<div class="layout-dashboard">
|
||||
<div class="grid">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="flex align-items-center justify-content-between mb-3">
|
||||
<h1>Détails du chantier</h1>
|
||||
<p:commandButton value="Retour" icon="pi pi-arrow-left"
|
||||
outcome="/chantiers"
|
||||
styleClass="ui-button-secondary"/>
|
||||
</div>
|
||||
|
||||
<h:form id="detailsChantierForm">
|
||||
<div class="grid" rendered="#{not empty chantiersView.selectedItem}">
|
||||
<div class="col-12">
|
||||
<p:panel header="Informations générales">
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-6">
|
||||
<p><strong>Nom :</strong> #{chantiersView.selectedItem.nom}</p>
|
||||
</div>
|
||||
<div class="col-12 md:col-6">
|
||||
<p><strong>Client :</strong> #{chantiersView.selectedItem.client}</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<p><strong>Adresse :</strong> #{chantiersView.selectedItem.adresse}</p>
|
||||
</div>
|
||||
</div>
|
||||
</p:panel>
|
||||
<!-- En-tête avec actions -->
|
||||
<div class="card mb-3">
|
||||
<div class="flex align-items-start justify-content-between flex-wrap gap-3">
|
||||
<div class="flex-grow-1">
|
||||
<div class="flex align-items-center gap-3 mb-2">
|
||||
<h2 class="text-900 font-bold m-0">#{chantiersView.selectedItem.nom}</h2>
|
||||
<ui:include src="/WEB-INF/components/status-badge.xhtml">
|
||||
<ui:param name="value" value="#{chantiersView.selectedItem.statut}"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6">
|
||||
<p:panel header="Dates">
|
||||
<p><strong>Date de début :</strong>
|
||||
<h:outputText value="#{chantiersView.selectedItem.dateDebut}">
|
||||
<f:convertDateTime pattern="dd/MM/yyyy"/>
|
||||
</h:outputText>
|
||||
</p>
|
||||
<p><strong>Date de fin prévue :</strong>
|
||||
<h:outputText value="#{chantiersView.selectedItem.dateFinPrevue}">
|
||||
<f:convertDateTime pattern="dd/MM/yyyy"/>
|
||||
</h:outputText>
|
||||
</p>
|
||||
</p:panel>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6">
|
||||
<p:panel header="Statut et avancement">
|
||||
<p><strong>Statut :</strong>
|
||||
<p:tag value="#{chantiersView.selectedItem.statut}"
|
||||
severity="#{chantiersView.selectedItem.statut == 'TERMINE' ? 'success' : (chantiersView.selectedItem.statut == 'EN_COURS' ? 'info' : 'warning')}"/>
|
||||
</p>
|
||||
<p><strong>Avancement :</strong>
|
||||
<p:progressBar value="#{chantiersView.selectedItem.avancement}"
|
||||
showValue="true"
|
||||
styleClass="ui-progressbar-success"/>
|
||||
</p>
|
||||
<p><strong>Budget :</strong>
|
||||
<h:outputText value="#{chantiersView.selectedItem.budget}">
|
||||
<f:converter converterId="fcfaConverter"/>
|
||||
</h:outputText>
|
||||
<h:outputText value=" Fcfa"/>
|
||||
</p>
|
||||
</p:panel>
|
||||
<p class="text-600 mt-0 mb-2">
|
||||
<i class="pi pi-building mr-2"></i>#{chantiersView.selectedItem.client}
|
||||
<span class="mx-2">•</span>
|
||||
<i class="pi pi-map-marker mr-2"></i>#{chantiersView.selectedItem.adresse}
|
||||
</p>
|
||||
<div class="flex align-items-center gap-3 text-sm">
|
||||
<span class="text-600">
|
||||
<i class="pi pi-calendar mr-1"></i>
|
||||
Début: <h:outputText value="#{chantiersView.selectedItem.dateDebut}">
|
||||
<f:convertDateTime pattern="dd/MM/yyyy"/>
|
||||
</h:outputText>
|
||||
</span>
|
||||
<span class="text-600">
|
||||
<i class="pi pi-calendar-times mr-1"></i>
|
||||
Fin prévue: <h:outputText value="#{chantiersView.selectedItem.dateFinPrevue}">
|
||||
<f:convertDateTime pattern="dd/MM/yyyy"/>
|
||||
</h:outputText>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p:message rendered="#{empty chantiersView.selectedItem}" severity="warn"
|
||||
summary="Chantier introuvable"/>
|
||||
</h:form>
|
||||
|
||||
<div class="flex gap-2">
|
||||
<p:commandButton value="Retour"
|
||||
icon="pi pi-arrow-left"
|
||||
outcome="/chantiers"
|
||||
styleClass="ui-button-secondary ui-button-outlined"/>
|
||||
<p:splitButton value="Modifier"
|
||||
icon="pi pi-pencil"
|
||||
styleClass="ui-button-primary"
|
||||
model="#{chantiersView.chantierActions}"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- KPI Cards -->
|
||||
<div class="grid mb-3">
|
||||
<div class="col-12 md:col-6 lg:col-3">
|
||||
<ui:include src="/WEB-INF/components/detail-card.xhtml">
|
||||
<ui:param name="title" value="Avancement"/>
|
||||
<ui:param name="value" value="#{chantiersView.selectedItem.avancement}%"/>
|
||||
<ui:param name="icon" value="pi-chart-line"/>
|
||||
<ui:param name="iconColor" value="primary"/>
|
||||
<ui:param name="trend" value="+5%"/>
|
||||
<ui:param name="footer" value="vs semaine dernière"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6 lg:col-3">
|
||||
<div class="card mb-0">
|
||||
<div class="flex flex-column">
|
||||
<span class="text-600 font-medium text-sm mb-2">Budget total</span>
|
||||
<div class="text-900 font-bold text-2xl mb-2">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{chantiersView.selectedItem.budget}"/>
|
||||
<ui:param name="size" value="normal"/>
|
||||
<ui:param name="bold" value="true"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
<span class="text-500 text-xs">Alloué au projet</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6 lg:col-3">
|
||||
<div class="card mb-0">
|
||||
<div class="flex flex-column">
|
||||
<span class="text-600 font-medium text-sm mb-2">Coût réel</span>
|
||||
<div class="text-900 font-bold text-2xl mb-2">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{chantiersView.selectedItem.coutReel}"/>
|
||||
<ui:param name="color" value="#{chantiersView.selectedItem.coutReel > chantiersView.selectedItem.budget ? 'danger' : 'success'}"/>
|
||||
<ui:param name="size" value="normal"/>
|
||||
<ui:param name="bold" value="true"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
<span class="text-500 text-xs">Dépensé à ce jour</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6 lg:col-3">
|
||||
<div class="card mb-0">
|
||||
<div class="flex flex-column">
|
||||
<span class="text-600 font-medium text-sm mb-2">Reste disponible</span>
|
||||
<div class="text-900 font-bold text-2xl mb-2">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{chantiersView.selectedItem.budget - chantiersView.selectedItem.coutReel}"/>
|
||||
<ui:param name="color" value="#{(chantiersView.selectedItem.budget - chantiersView.selectedItem.coutReel) < 0 ? 'danger' : 'success'}"/>
|
||||
<ui:param name="size" value="normal"/>
|
||||
<ui:param name="bold" value="true"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
<span class="text-500 text-xs">
|
||||
#{(chantiersView.selectedItem.budget - chantiersView.selectedItem.coutReel) >= 0 ? 'Excédent' : 'Dépassement'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Onglets détaillés -->
|
||||
<div class="card">
|
||||
<p:tabView dynamic="true" cache="false">
|
||||
|
||||
<!-- ONGLET 1: Vue d'ensemble -->
|
||||
<p:tab title="Vue d'ensemble" icon="pi pi-home">
|
||||
<div class="grid">
|
||||
<!-- Informations générales -->
|
||||
<div class="col-12 lg:col-6">
|
||||
<h5 class="text-900 font-bold mb-3">Informations générales</h5>
|
||||
<div class="surface-50 border-round p-3 mb-3">
|
||||
<div class="grid">
|
||||
<div class="col-6">
|
||||
<span class="text-600 text-sm">Nom du chantier</span>
|
||||
<p class="text-900 font-medium mt-1 mb-0">#{chantiersView.selectedItem.nom}</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<span class="text-600 text-sm">Client</span>
|
||||
<p class="text-900 font-medium mt-1 mb-0">#{chantiersView.selectedItem.client}</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<span class="text-600 text-sm">Adresse</span>
|
||||
<p class="text-900 font-medium mt-1 mb-0">#{chantiersView.selectedItem.adresse}</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<span class="text-600 text-sm">Statut</span>
|
||||
<div class="mt-1">
|
||||
<ui:include src="/WEB-INF/components/status-badge.xhtml">
|
||||
<ui:param name="value" value="#{chantiersView.selectedItem.statut}"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<span class="text-600 text-sm">Avancement</span>
|
||||
<p class="text-900 font-bold text-xl mt-1 mb-0">#{chantiersView.selectedItem.avancement}%</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Progression visuelle -->
|
||||
<div class="col-12 lg:col-6">
|
||||
<h5 class="text-900 font-bold mb-3">Progression du chantier</h5>
|
||||
<div class="surface-50 border-round p-3 mb-3">
|
||||
<ui:include src="/WEB-INF/components/progress-indicator.xhtml">
|
||||
<ui:param name="value" value="#{chantiersView.selectedItem.avancement}"/>
|
||||
<ui:param name="label" value="Réalisation globale"/>
|
||||
<ui:param name="height" value="1.5rem"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Analyse budgétaire -->
|
||||
<div class="col-12">
|
||||
<h5 class="text-900 font-bold mb-3">Analyse budgétaire</h5>
|
||||
<div class="surface-50 border-round p-3">
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-4">
|
||||
<div class="text-center">
|
||||
<span class="text-600 text-sm">Budget prévu</span>
|
||||
<div class="text-primary font-bold text-xl mt-2">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{chantiersView.selectedItem.budget}"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-4">
|
||||
<div class="text-center">
|
||||
<span class="text-600 text-sm">Dépensé</span>
|
||||
<div class="font-bold text-xl mt-2"
|
||||
style="color: #{chantiersView.selectedItem.coutReel > chantiersView.selectedItem.budget ? '#EF4444' : '#10B981'}">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{chantiersView.selectedItem.coutReel}"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-4">
|
||||
<div class="text-center">
|
||||
<span class="text-600 text-sm">
|
||||
#{(chantiersView.selectedItem.budget - chantiersView.selectedItem.coutReel) >= 0 ? 'Reste' : 'Dépassement'}
|
||||
</span>
|
||||
<div class="font-bold text-xl mt-2"
|
||||
style="color: #{(chantiersView.selectedItem.budget - chantiersView.selectedItem.coutReel) >= 0 ? '#10B981' : '#EF4444'}">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{chantiersView.selectedItem.budget - chantiersView.selectedItem.coutReel}"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 mt-3">
|
||||
<ui:include src="/WEB-INF/components/progress-indicator.xhtml">
|
||||
<ui:param name="value" value="#{(chantiersView.selectedItem.coutReel / chantiersView.selectedItem.budget) * 100}"/>
|
||||
<ui:param name="label" value="Utilisation du budget"/>
|
||||
<ui:param name="labelPosition" value="top"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</p:tab>
|
||||
|
||||
<!-- ONGLET 2: Phases -->
|
||||
<p:tab title="Phases" icon="pi pi-sitemap">
|
||||
<div class="p-3">
|
||||
<div class="flex align-items-center justify-content-between mb-3">
|
||||
<h5 class="text-900 font-bold m-0">Phases du chantier</h5>
|
||||
<p:commandButton value="Ajouter une phase"
|
||||
icon="pi pi-plus"
|
||||
styleClass="ui-button-success ui-button-sm"/>
|
||||
</div>
|
||||
<p:message severity="info" text="Fonctionnalité de gestion des phases en cours de développement"/>
|
||||
</div>
|
||||
</p:tab>
|
||||
|
||||
<!-- ONGLET 3: Équipes -->
|
||||
<p:tab title="Équipes" icon="pi pi-users">
|
||||
<div class="p-3">
|
||||
<div class="flex align-items-center justify-content-between mb-3">
|
||||
<h5 class="text-900 font-bold m-0">Équipes affectées</h5>
|
||||
<p:commandButton value="Affecter une équipe"
|
||||
icon="pi pi-plus"
|
||||
styleClass="ui-button-success ui-button-sm"/>
|
||||
</div>
|
||||
<p:message severity="info" text="Fonctionnalité d'affectation des équipes en cours de développement"/>
|
||||
</div>
|
||||
</p:tab>
|
||||
|
||||
<!-- ONGLET 4: Matériels -->
|
||||
<p:tab title="Matériels" icon="pi pi-wrench">
|
||||
<div class="p-3">
|
||||
<div class="flex align-items-center justify-content-between mb-3">
|
||||
<h5 class="text-900 font-bold m-0">Matériels utilisés</h5>
|
||||
<p:commandButton value="Ajouter du matériel"
|
||||
icon="pi pi-plus"
|
||||
styleClass="ui-button-success ui-button-sm"/>
|
||||
</div>
|
||||
<p:message severity="info" text="Fonctionnalité de gestion des matériels en cours de développement"/>
|
||||
</div>
|
||||
</p:tab>
|
||||
|
||||
<!-- ONGLET 5: Documents -->
|
||||
<p:tab title="Documents" icon="pi pi-folder">
|
||||
<div class="p-3">
|
||||
<div class="flex align-items-center justify-content-between mb-3">
|
||||
<h5 class="text-900 font-bold m-0">Documents du chantier</h5>
|
||||
<p:commandButton value="Ajouter un document"
|
||||
icon="pi pi-upload"
|
||||
styleClass="ui-button-success ui-button-sm"/>
|
||||
</div>
|
||||
<p:message severity="info" text="Fonctionnalité de gestion documentaire en cours de développement"/>
|
||||
</div>
|
||||
</p:tab>
|
||||
|
||||
<!-- ONGLET 6: Historique -->
|
||||
<p:tab title="Historique" icon="pi pi-history">
|
||||
<div class="p-3">
|
||||
<h5 class="text-900 font-bold mb-3">Historique des modifications</h5>
|
||||
<p:timeline value="#{chantiersView.chantierHistory}" align="alternate">
|
||||
<p:templateSlot name="marker">
|
||||
<i class="pi pi-circle-fill text-primary"></i>
|
||||
</p:templateSlot>
|
||||
<p:templateSlot name="content">
|
||||
<small class="text-600">Fonctionnalité en cours de développement</small>
|
||||
</p:templateSlot>
|
||||
</p:timeline>
|
||||
</div>
|
||||
</p:tab>
|
||||
|
||||
</p:tabView>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user