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.
308 lines
21 KiB
HTML
308 lines
21 KiB
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"
|
|
template="/WEB-INF/template.xhtml">
|
|
|
|
<ui:define name="title">Détails du chantier - BTP Xpress</ui:define>
|
|
|
|
<f:metadata>
|
|
<f:viewParam name="id" value="#{chantiersView.chantierId}"/>
|
|
<f:event type="preRenderView" listener="#{chantiersView.loadChantierById()}"/>
|
|
</f:metadata>
|
|
|
|
<ui:define name="content">
|
|
<div class="layout-dashboard">
|
|
<div class="grid">
|
|
<div class="col-12">
|
|
<!-- 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>
|
|
<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>
|
|
|
|
<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>
|