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:
28
target/classes/META-INF/resources/devis/brouillon.xhtml
Normal file
28
target/classes/META-INF/resources/devis/brouillon.xhtml
Normal file
@@ -0,0 +1,28 @@
|
||||
<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">Devis brouillons - BTP Xpress</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<div class="layout-dashboard">
|
||||
<div class="grid">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h6>Devis brouillons</h6>
|
||||
<p class="subtitle">Devis en cours de rédaction</p>
|
||||
</div>
|
||||
</div>
|
||||
<p>Page en développement</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
|
||||
354
target/classes/META-INF/resources/devis/details.xhtml
Normal file
354
target/classes/META-INF/resources/devis/details.xhtml
Normal file
@@ -0,0 +1,354 @@
|
||||
<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 devis - BTP Xpress</ui:define>
|
||||
|
||||
<f:metadata>
|
||||
<f:viewParam name="id" value="#{devisView.devisId}"/>
|
||||
<f:event type="preRenderView" listener="#{devisView.loadDevisById()}"/>
|
||||
</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">Devis #{devisView.selectedItem.numero}</h2>
|
||||
<ui:include src="/WEB-INF/components/status-badge.xhtml">
|
||||
<ui:param name="value" value="#{devisView.selectedItem.statut}"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
<p class="text-600 mt-0 mb-2">
|
||||
<i class="pi pi-building mr-2"></i>#{devisView.selectedItem.client}
|
||||
</p>
|
||||
<p class="text-sm text-600 mt-0 mb-0">#{devisView.selectedItem.objet}</p>
|
||||
<div class="flex align-items-center gap-3 text-sm mt-2">
|
||||
<span class="text-600">
|
||||
<i class="pi pi-calendar mr-1"></i>
|
||||
Émis le: <h:outputText value="#{devisView.selectedItem.dateEmission}">
|
||||
<f:convertDateTime pattern="dd/MM/yyyy"/>
|
||||
</h:outputText>
|
||||
</span>
|
||||
<span class="text-600">
|
||||
<i class="pi pi-calendar-times mr-1"></i>
|
||||
Valide jusqu'au: <h:outputText value="#{devisView.selectedItem.dateValidite}">
|
||||
<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="/devis"
|
||||
styleClass="ui-button-secondary ui-button-outlined"/>
|
||||
<p:commandButton value="Convertir en chantier"
|
||||
icon="pi pi-arrow-right"
|
||||
rendered="#{devisView.selectedItem.statut eq 'ACCEPTE'}"
|
||||
styleClass="ui-button-success"/>
|
||||
<p:commandButton value="Télécharger PDF"
|
||||
icon="pi pi-file-pdf"
|
||||
styleClass="ui-button-danger ui-button-outlined"/>
|
||||
<p:splitButton value="Modifier"
|
||||
icon="pi pi-pencil"
|
||||
styleClass="ui-button-primary">
|
||||
</p:splitButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- KPI Cards -->
|
||||
<div class="grid mb-3">
|
||||
<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">Montant HT</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="#{devisView.selectedItem.montantHT}"/>
|
||||
<ui:param name="size" value="normal"/>
|
||||
<ui:param name="bold" value="true"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
<span class="text-500 text-xs">Hors taxes</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">TVA (18%)</span>
|
||||
<div class="text-orange-600 font-bold text-2xl mb-2">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{devisView.selectedItem.montantHT * 0.18}"/>
|
||||
<ui:param name="size" value="normal"/>
|
||||
<ui:param name="bold" value="true"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
<span class="text-500 text-xs">Taxe sur la valeur ajoutée</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">Montant TTC</span>
|
||||
<div class="text-primary font-bold text-2xl mb-2">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{devisView.selectedItem.montantHT * 1.18}"/>
|
||||
<ui:param name="size" value="normal"/>
|
||||
<ui:param name="bold" value="true"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
<span class="text-500 text-xs">Toutes taxes comprises</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">Statut</span>
|
||||
<div class="mt-2 mb-2">
|
||||
<ui:include src="/WEB-INF/components/status-badge.xhtml">
|
||||
<ui:param name="value" value="#{devisView.selectedItem.statut}"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
<span class="text-500 text-xs">
|
||||
<h:outputText value="Valide" rendered="#{devisView.selectedItem.statut ne 'EXPIRE'}"/>
|
||||
<h:outputText value="Expiré" rendered="#{devisView.selectedItem.statut eq 'EXPIRE'}"/>
|
||||
</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 du devis -->
|
||||
<div class="col-12 lg:col-6">
|
||||
<h5 class="text-900 font-bold mb-3">Informations du devis</h5>
|
||||
<div class="surface-50 border-round p-3 mb-3">
|
||||
<div class="grid">
|
||||
<div class="col-6">
|
||||
<span class="text-600 text-sm">Numéro</span>
|
||||
<p class="text-900 font-bold mt-1 mb-0">#{devisView.selectedItem.numero}</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<span class="text-600 text-sm">Client</span>
|
||||
<p class="text-900 font-medium mt-1 mb-0">#{devisView.selectedItem.client}</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<span class="text-600 text-sm">Objet</span>
|
||||
<p class="text-900 font-medium mt-1 mb-0">#{devisView.selectedItem.objet}</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<span class="text-600 text-sm">Date d'émission</span>
|
||||
<p class="text-900 font-medium mt-1 mb-0">
|
||||
<h:outputText value="#{devisView.selectedItem.dateEmission}">
|
||||
<f:convertDateTime pattern="dd/MM/yyyy"/>
|
||||
</h:outputText>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<span class="text-600 text-sm">Date de validité</span>
|
||||
<p class="text-900 font-medium mt-1 mb-0">
|
||||
<h:outputText value="#{devisView.selectedItem.dateValidite}">
|
||||
<f:convertDateTime pattern="dd/MM/yyyy"/>
|
||||
</h:outputText>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<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="#{devisView.selectedItem.statut}"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Récapitulatif financier -->
|
||||
<div class="col-12 lg:col-6">
|
||||
<h5 class="text-900 font-bold mb-3">Récapitulatif financier</h5>
|
||||
<div class="surface-50 border-round p-3 mb-3">
|
||||
<div class="grid">
|
||||
<div class="col-12">
|
||||
<div class="flex justify-content-between align-items-center mb-2">
|
||||
<span class="text-600">Montant HT</span>
|
||||
<span class="text-900 font-bold">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{devisView.selectedItem.montantHT}"/>
|
||||
</ui:include>
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex justify-content-between align-items-center mb-2">
|
||||
<span class="text-600">TVA (18%)</span>
|
||||
<span class="text-orange-600 font-medium">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{devisView.selectedItem.montantHT * 0.18}"/>
|
||||
</ui:include>
|
||||
</span>
|
||||
</div>
|
||||
<div class="border-top-1 surface-border pt-2 mt-2">
|
||||
<div class="flex justify-content-between align-items-center">
|
||||
<span class="text-900 font-bold text-lg">Total TTC</span>
|
||||
<span class="text-primary font-bold text-xl">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{devisView.selectedItem.montantHT * 1.18}"/>
|
||||
<ui:param name="size" value="large"/>
|
||||
<ui:param name="bold" value="true"/>
|
||||
</ui:include>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Actions rapides -->
|
||||
<div class="col-12">
|
||||
<h5 class="text-900 font-bold mb-3">Actions rapides</h5>
|
||||
<div class="surface-50 border-round p-3">
|
||||
<div class="flex flex-wrap gap-2">
|
||||
<p:commandButton value="Accepter le devis"
|
||||
icon="pi pi-check"
|
||||
rendered="#{devisView.selectedItem.statut eq 'ATTENTE'}"
|
||||
styleClass="ui-button-success"/>
|
||||
<p:commandButton value="Refuser"
|
||||
icon="pi pi-times"
|
||||
rendered="#{devisView.selectedItem.statut eq 'ATTENTE'}"
|
||||
styleClass="ui-button-danger ui-button-outlined"/>
|
||||
<p:commandButton value="Convertir en chantier"
|
||||
icon="pi pi-arrow-right"
|
||||
rendered="#{devisView.selectedItem.statut eq 'ACCEPTE'}"
|
||||
styleClass="ui-button-primary"/>
|
||||
<p:commandButton value="Dupliquer"
|
||||
icon="pi pi-copy"
|
||||
styleClass="ui-button-secondary ui-button-outlined"/>
|
||||
<p:commandButton value="Envoyer par email"
|
||||
icon="pi pi-send"
|
||||
styleClass="ui-button-info ui-button-outlined"/>
|
||||
<p:commandButton value="Télécharger PDF"
|
||||
icon="pi pi-file-pdf"
|
||||
styleClass="ui-button-danger ui-button-outlined"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</p:tab>
|
||||
|
||||
<!-- ONGLET 2: Lignes du devis -->
|
||||
<p:tab title="Détail des lignes" icon="pi pi-list">
|
||||
<div class="p-3">
|
||||
<div class="flex align-items-center justify-content-between mb-3">
|
||||
<h5 class="text-900 font-bold m-0">Lignes du devis</h5>
|
||||
<p:commandButton value="Ajouter une ligne"
|
||||
icon="pi pi-plus"
|
||||
styleClass="ui-button-success ui-button-sm"/>
|
||||
</div>
|
||||
<p:message severity="info" text="Fonctionnalité de gestion des lignes de devis en cours de développement"/>
|
||||
<div class="surface-50 border-round p-4 text-center mt-3">
|
||||
<i class="pi pi-list text-400 mb-3" style="font-size: 3rem;"></i>
|
||||
<p class="text-600">Bientôt disponible: tableau des prestations avec quantités, prix unitaires, sous-totaux</p>
|
||||
</div>
|
||||
</div>
|
||||
</p:tab>
|
||||
|
||||
<!-- ONGLET 3: Conditions -->
|
||||
<p:tab title="Conditions" icon="pi pi-file-edit">
|
||||
<div class="p-3">
|
||||
<h5 class="text-900 font-bold mb-3">Conditions commerciales</h5>
|
||||
<div class="surface-50 border-round p-3 mb-3">
|
||||
<h6 class="text-900 font-medium mb-2">Conditions de paiement</h6>
|
||||
<p class="text-600 text-sm">
|
||||
Les conditions de paiement seront affichées ici (exemple: paiement en 3 fois, 30% à la commande, etc.)
|
||||
</p>
|
||||
</div>
|
||||
<div class="surface-50 border-round p-3 mb-3">
|
||||
<h6 class="text-900 font-medium mb-2">Délais de livraison</h6>
|
||||
<p class="text-600 text-sm">
|
||||
Information sur les délais de réalisation du projet
|
||||
</p>
|
||||
</div>
|
||||
<div class="surface-50 border-round p-3">
|
||||
<h6 class="text-900 font-medium mb-2">Garanties</h6>
|
||||
<p class="text-600 text-sm">
|
||||
Conditions de garantie et assurances
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</p:tab>
|
||||
|
||||
<!-- ONGLET 4: 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 associés</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 5: Suivi -->
|
||||
<p:tab title="Suivi" icon="pi pi-chart-line">
|
||||
<div class="p-3">
|
||||
<h5 class="text-900 font-bold mb-3">Suivi du devis</h5>
|
||||
<div class="surface-50 border-round p-3">
|
||||
<p:timeline 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">Historique des actions (création, envoi, acceptation, etc.)</small>
|
||||
</p:templateSlot>
|
||||
</p:timeline>
|
||||
</div>
|
||||
</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 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>
|
||||
@@ -1 +1,312 @@
|
||||
<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">DEVIS - BTP Xpress</ui:define><ui:define name="content"><div class="layout-dashboard"><div class="grid"><div class="col-12"><div class="card"><h1>DEVIS</h1><p>Module en cours de développement...</p></div></div></div></div></ui:define></ui:composition>
|
||||
<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">Nouveau devis - BTP Xpress</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<div class="layout-dashboard">
|
||||
<div class="grid">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<!-- En-tête avec breadcrumb -->
|
||||
<div class="flex align-items-center justify-content-between mb-4">
|
||||
<div>
|
||||
<h2 class="text-900 font-bold mb-2">Créer un nouveau devis</h2>
|
||||
<p class="text-600 mt-0">Établissez un devis détaillé pour votre client</p>
|
||||
</div>
|
||||
<p:commandButton value="Retour à la liste"
|
||||
icon="pi pi-arrow-left"
|
||||
outcome="/devis"
|
||||
styleClass="ui-button-secondary ui-button-outlined"/>
|
||||
</div>
|
||||
|
||||
<p:messages id="messages" showDetail="true" closable="true"/>
|
||||
|
||||
<h:form id="nouveauDevisForm" styleClass="p-fluid">
|
||||
|
||||
<!-- SECTION 1: Informations générales -->
|
||||
<p:panel header="Informations générales" toggleable="true" collapsed="false" class="mb-4">
|
||||
<div class="formgrid grid">
|
||||
<!-- Numéro (auto-généré) -->
|
||||
<div class="field col-12 md:col-4">
|
||||
<label for="numero" class="font-bold">Numéro de devis</label>
|
||||
<div class="p-inputgroup">
|
||||
<span class="p-inputgroup-addon">
|
||||
<i class="pi pi-hashtag"></i>
|
||||
</span>
|
||||
<p:inputText id="numero"
|
||||
value="#{devisView.entity.numero}"
|
||||
disabled="true"
|
||||
placeholder="Auto-généré"
|
||||
styleClass="text-center font-bold"/>
|
||||
</div>
|
||||
<small class="text-600">Généré automatiquement lors de l'enregistrement</small>
|
||||
</div>
|
||||
|
||||
<!-- Statut -->
|
||||
<div class="field col-12 md:col-4">
|
||||
<label for="statut" class="font-bold">Statut <span class="text-red-500">*</span></label>
|
||||
<p:selectOneMenu id="statut"
|
||||
value="#{devisView.entity.statut}"
|
||||
required="true">
|
||||
<f:selectItem itemLabel="Sélectionner..." itemValue="" noSelectionOption="true"/>
|
||||
<f:selectItem itemLabel="Brouillon" itemValue="BROUILLON"/>
|
||||
<f:selectItem itemLabel="En attente" itemValue="ATTENTE"/>
|
||||
<f:selectItem itemLabel="Accepté" itemValue="ACCEPTE"/>
|
||||
<f:selectItem itemLabel="Refusé" itemValue="REFUSE"/>
|
||||
<f:selectItem itemLabel="Expiré" itemValue="EXPIRE"/>
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
|
||||
<!-- Date d'émission -->
|
||||
<div class="field col-12 md:col-4">
|
||||
<label for="dateEmission" class="font-bold">Date d'émission <span class="text-red-500">*</span></label>
|
||||
<p:calendar id="dateEmission"
|
||||
value="#{devisView.entity.dateEmission}"
|
||||
pattern="dd/MM/yyyy"
|
||||
locale="fr"
|
||||
required="true"
|
||||
requiredMessage="La date d'émission est obligatoire"
|
||||
showIcon="true"
|
||||
showButtonBar="true"
|
||||
monthNavigator="true"
|
||||
yearNavigator="true"
|
||||
yearRange="2020:2030"
|
||||
placeholder="Sélectionner une date">
|
||||
</p:calendar>
|
||||
</div>
|
||||
|
||||
<!-- Client -->
|
||||
<div class="field col-12 md:col-8">
|
||||
<label for="client" class="font-bold">Client <span class="text-red-500">*</span></label>
|
||||
<p:inputText id="client"
|
||||
value="#{devisView.entity.client}"
|
||||
required="true"
|
||||
requiredMessage="Le client est obligatoire"
|
||||
placeholder="Ex: Entreprise ABC SARL">
|
||||
<f:validateLength minimum="2" maximum="200"/>
|
||||
</p:inputText>
|
||||
<small class="text-600">Nom du client ou de l'entreprise</small>
|
||||
</div>
|
||||
|
||||
<!-- Date de validité -->
|
||||
<div class="field col-12 md:col-4">
|
||||
<label for="dateValidite" class="font-bold">Date de validité <span class="text-red-500">*</span></label>
|
||||
<p:calendar id="dateValidite"
|
||||
value="#{devisView.entity.dateValidite}"
|
||||
pattern="dd/MM/yyyy"
|
||||
locale="fr"
|
||||
required="true"
|
||||
requiredMessage="La date de validité est obligatoire"
|
||||
showIcon="true"
|
||||
showButtonBar="true"
|
||||
monthNavigator="true"
|
||||
yearNavigator="true"
|
||||
yearRange="2020:2035"
|
||||
mindate="#{devisView.entity.dateEmission}"
|
||||
placeholder="Sélectionner une date">
|
||||
</p:calendar>
|
||||
<small class="text-600">Date limite de validité du devis (généralement 30 jours)</small>
|
||||
</div>
|
||||
|
||||
<!-- Objet du devis -->
|
||||
<div class="field col-12">
|
||||
<label for="objet" class="font-bold">Objet du devis <span class="text-red-500">*</span></label>
|
||||
<p:inputTextarea id="objet"
|
||||
value="#{devisView.entity.objet}"
|
||||
required="true"
|
||||
requiredMessage="L'objet du devis est obligatoire"
|
||||
rows="3"
|
||||
placeholder="Ex: Construction d'un immeuble R+3 à usage résidentiel"
|
||||
autoResize="false">
|
||||
<f:validateLength minimum="10" maximum="500"/>
|
||||
</p:inputTextarea>
|
||||
<small class="text-600">Description détaillée de la prestation</small>
|
||||
</div>
|
||||
</div>
|
||||
</p:panel>
|
||||
|
||||
<!-- SECTION 2: Lignes du devis -->
|
||||
<p:panel header="Détail du devis" toggleable="true" collapsed="false" class="mb-4">
|
||||
<div class="mb-3">
|
||||
<div class="surface-100 border-round p-3">
|
||||
<div class="flex align-items-center gap-2 mb-2">
|
||||
<i class="pi pi-info-circle text-blue-500"></i>
|
||||
<span class="text-900 font-medium">Lignes de devis</span>
|
||||
</div>
|
||||
<p class="text-600 text-sm mt-0 mb-0">
|
||||
Ajoutez les différentes prestations, fournitures et main d'œuvre.
|
||||
Cette fonctionnalité sera disponible dans une prochaine version.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Placeholder pour table de lignes -->
|
||||
<div class="surface-50 border-round p-4 text-center">
|
||||
<i class="pi pi-list text-400 mb-3" style="font-size: 3rem;"></i>
|
||||
<p class="text-600 mt-0 mb-3">Gestion des lignes de devis en cours de développement</p>
|
||||
<p class="text-500 text-sm">
|
||||
Bientôt disponible: ajout de lignes avec désignation, quantité, prix unitaire, TVA, etc.
|
||||
</p>
|
||||
</div>
|
||||
</p:panel>
|
||||
|
||||
<!-- SECTION 3: Montants et totaux -->
|
||||
<p:panel header="Montants" toggleable="true" collapsed="false" class="mb-4">
|
||||
<div class="formgrid grid">
|
||||
<!-- Montant HT -->
|
||||
<div class="field col-12 md:col-6">
|
||||
<label for="montantHT" class="font-bold">Montant HT (FCFA) <span class="text-red-500">*</span></label>
|
||||
<p:inputNumber id="montantHT"
|
||||
value="#{devisView.entity.montantHT}"
|
||||
required="true"
|
||||
requiredMessage="Le montant HT est obligatoire"
|
||||
minValue="0"
|
||||
decimalPlaces="0"
|
||||
thousandSeparator=" "
|
||||
suffix=" FCFA"
|
||||
placeholder="0">
|
||||
</p:inputNumber>
|
||||
<small class="text-600">Montant hors taxes</small>
|
||||
</div>
|
||||
|
||||
<!-- TVA (calculée) -->
|
||||
<div class="field col-12 md:col-6">
|
||||
<label class="font-bold">TVA (18%)</label>
|
||||
<div class="p-inputgroup">
|
||||
<span class="p-inputgroup-addon">
|
||||
<i class="pi pi-percentage"></i>
|
||||
</span>
|
||||
<p:inputNumber value="#{devisView.entity.montantHT * 0.18}"
|
||||
disabled="true"
|
||||
decimalPlaces="0"
|
||||
thousandSeparator=" "
|
||||
suffix=" FCFA"
|
||||
styleClass="text-center font-medium"/>
|
||||
</div>
|
||||
<small class="text-600">Calculé automatiquement (18% du montant HT)</small>
|
||||
</div>
|
||||
|
||||
<!-- Montant TTC (calculé) -->
|
||||
<div class="field col-12">
|
||||
<label class="font-bold">Montant TTC (FCFA)</label>
|
||||
<div class="p-inputgroup">
|
||||
<span class="p-inputgroup-addon bg-primary">
|
||||
<i class="pi pi-dollar text-white"></i>
|
||||
</span>
|
||||
<p:inputNumber value="#{devisView.entity.montantHT * 1.18}"
|
||||
disabled="true"
|
||||
decimalPlaces="0"
|
||||
thousandSeparator=" "
|
||||
suffix=" FCFA"
|
||||
styleClass="text-center font-bold text-xl text-primary"/>
|
||||
</div>
|
||||
<small class="text-600">Montant toutes taxes comprises (HT + TVA)</small>
|
||||
</div>
|
||||
|
||||
<!-- Récapitulatif visuel -->
|
||||
<div class="field col-12">
|
||||
<div class="surface-100 border-round p-3">
|
||||
<div class="grid">
|
||||
<div class="col-12 md:col-4">
|
||||
<div class="text-center">
|
||||
<span class="text-600 text-sm block mb-2">Montant HT</span>
|
||||
<div class="text-900 font-bold text-xl">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{devisView.entity.montantHT}"/>
|
||||
<ui:param name="size" value="normal"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-4">
|
||||
<div class="text-center">
|
||||
<span class="text-600 text-sm block mb-2">TVA (18%)</span>
|
||||
<div class="text-orange-600 font-bold text-xl">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{devisView.entity.montantHT * 0.18}"/>
|
||||
<ui:param name="size" value="normal"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12 md:col-4">
|
||||
<div class="text-center">
|
||||
<span class="text-600 text-sm block mb-2">Total TTC</span>
|
||||
<div class="text-primary font-bold text-2xl">
|
||||
<ui:include src="/WEB-INF/components/monetary-display.xhtml">
|
||||
<ui:param name="amount" value="#{devisView.entity.montantHT * 1.18}"/>
|
||||
<ui:param name="size" value="large"/>
|
||||
<ui:param name="bold" value="true"/>
|
||||
</ui:include>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</p:panel>
|
||||
|
||||
<!-- SECTION 4: Conditions (optionnel) -->
|
||||
<p:panel header="Conditions et remarques" toggleable="true" collapsed="true" class="mb-4">
|
||||
<div class="formgrid grid">
|
||||
<div class="field col-12">
|
||||
<label for="conditions" class="font-bold">Conditions de paiement</label>
|
||||
<p:inputTextarea id="conditions"
|
||||
rows="3"
|
||||
placeholder="Ex: Paiement en 3 fois : 30% à la commande, 40% à mi-parcours, 30% à la livraison"
|
||||
autoResize="false">
|
||||
</p:inputTextarea>
|
||||
<small class="text-600">Détaillez les modalités de paiement</small>
|
||||
</div>
|
||||
<div class="field col-12">
|
||||
<label for="remarques" class="font-bold">Remarques</label>
|
||||
<p:inputTextarea id="remarques"
|
||||
rows="3"
|
||||
placeholder="Toutes remarques ou précisions supplémentaires"
|
||||
autoResize="false">
|
||||
</p:inputTextarea>
|
||||
</div>
|
||||
</div>
|
||||
</p:panel>
|
||||
|
||||
<!-- Boutons d'action -->
|
||||
<div class="flex align-items-center justify-content-between pt-4 border-top-1 surface-border">
|
||||
<div>
|
||||
<span class="text-600 text-sm">Les champs marqués d'un </span>
|
||||
<span class="text-red-500 font-bold">*</span>
|
||||
<span class="text-600 text-sm"> sont obligatoires</span>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<p:commandButton value="Annuler"
|
||||
icon="pi pi-times"
|
||||
action="/devis?faces-redirect=true"
|
||||
styleClass="ui-button-secondary"
|
||||
immediate="true"/>
|
||||
<p:commandButton value="Enregistrer comme brouillon"
|
||||
icon="pi pi-save"
|
||||
action="#{devisView.save}"
|
||||
update="@form messages"
|
||||
oncomplete="if (args && !args.validationFailed) window.location.href='/devis.xhtml';"
|
||||
styleClass="ui-button-secondary"/>
|
||||
<p:commandButton value="Enregistrer et envoyer"
|
||||
icon="pi pi-send"
|
||||
action="#{devisView.save}"
|
||||
update="@form messages"
|
||||
oncomplete="if (args && !args.validationFailed) window.location.href='/devis.xhtml';"
|
||||
styleClass="ui-button-primary"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</h:form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
|
||||
28
target/classes/META-INF/resources/devis/refuses.xhtml
Normal file
28
target/classes/META-INF/resources/devis/refuses.xhtml
Normal file
@@ -0,0 +1,28 @@
|
||||
<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">Devis refusés - BTP Xpress</ui:define>
|
||||
|
||||
<ui:define name="content">
|
||||
<div class="layout-dashboard">
|
||||
<div class="grid">
|
||||
<div class="col-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">
|
||||
<h6>Devis refusés</h6>
|
||||
<p class="subtitle">Devis refusés par les clients</p>
|
||||
</div>
|
||||
</div>
|
||||
<p>Page en développement</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
|
||||
Reference in New Issue
Block a user