Files
btpxpress-frontend/target/classes/META-INF/resources/chantiers/details.xhtml
dahoud ec38f6a23a 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.
2025-11-08 10:49:19 +00:00

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>