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:
dahoud
2025-11-08 10:49:19 +00:00
parent 0fad42ccaf
commit ec38f6a23a
192 changed files with 12029 additions and 271 deletions

View File

@@ -0,0 +1,121 @@
<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:c="http://xmlns.jcp.org/jsp/jstl/core">
<!--
Composant réutilisable: Badge de statut coloré
Principe DRY: Un seul composant pour tous les badges de statut dans l'application
Write Once, Use Anywhere: Mapping automatique statut → couleur
Paramètres:
- value: Valeur du statut (requis)
- severity: Gravité explicite (success, info, warning, danger) - optionnel
- icon: Icône à afficher - optionnel
- rounded: Badge arrondi (true/false - défaut: true)
- size: Taille (normal, large - défaut: normal)
Mapping automatique des statuts métier:
SUCCESS (vert): EN_COURS, ACTIF, TERMINE, VALIDE, PAYE, LIVRE, DISPONIBLE, APPROUVE
INFO (bleu): PLANIFIE, NOUVEAU, EN_ATTENTE, BROUILLON, PENDING
WARNING (orange): RETARD, SUSPENDU, IMPAYE, ALERTE, MAINTENANCE
DANGER (rouge): ANNULE, REFUSE, EXPIRE, HORS_SERVICE, BLOQUE
Utilisation:
<ui:include src="/WEB-INF/components/status-badge.xhtml">
<ui:param name="value" value="#{chantier.statut}"/>
</ui:include>
Avec icône personnalisée:
<ui:include src="/WEB-INF/components/status-badge.xhtml">
<ui:param name="value" value="#{facture.statut}"/>
<ui:param name="icon" value="pi pi-check-circle"/>
</ui:include>
Gravité manuelle:
<ui:include src="/WEB-INF/components/status-badge.xhtml">
<ui:param name="value" value="#{custom.status}"/>
<ui:param name="severity" value="danger"/>
</ui:include>
-->
<c:set var="upperValue" value="#{value.toString().toUpperCase().replace(' ', '_')}"/>
<!-- Déterminer la gravité automatiquement si non fournie -->
<c:choose>
<!-- SUCCESS - Vert -->
<c:when test="#{not empty severity}">
<c:set var="badgeSeverity" value="#{severity}"/>
</c:when>
<c:when test="#{upperValue eq 'EN_COURS' or upperValue eq 'ACTIF' or upperValue eq 'ACTIVE' or
upperValue eq 'TERMINE' or upperValue eq 'COMPLETE' or upperValue eq 'VALIDE' or
upperValue eq 'PAYE' or upperValue eq 'PAYEE' or upperValue eq 'LIVRE' or
upperValue eq 'DISPONIBLE' or upperValue eq 'APPROUVE' or upperValue eq 'ACCEPTE' or
upperValue eq 'OPERATIONNEL'}">
<c:set var="badgeSeverity" value="success"/>
</c:when>
<!-- INFO - Bleu -->
<c:when test="#{upperValue eq 'PLANIFIE' or upperValue eq 'PLANIFIEE' or upperValue eq 'NOUVEAU' or
upperValue eq 'NOUVELLE' or upperValue eq 'EN_ATTENTE' or upperValue eq 'BROUILLON' or
upperValue eq 'PENDING' or upperValue eq 'PROGRAMME' or upperValue eq 'PREVU'}">
<c:set var="badgeSeverity" value="info"/>
</c:when>
<!-- WARNING - Orange -->
<c:when test="#{upperValue eq 'RETARD' or upperValue eq 'EN_RETARD' or upperValue eq 'SUSPENDU' or
upperValue eq 'IMPAYE' or upperValue eq 'IMPAYEE' or upperValue eq 'ALERTE' or
upperValue eq 'MAINTENANCE' or upperValue eq 'UTILISE' or upperValue eq 'OCCUPE' or
upperValue eq 'PARTIEL' or upperValue eq 'PARTIELLE'}">
<c:set var="badgeSeverity" value="warning"/>
</c:when>
<!-- DANGER - Rouge -->
<c:when test="#{upperValue eq 'ANNULE' or upperValue eq 'ANNULEE' or upperValue eq 'REFUSE' or
upperValue eq 'REFUSEE' or upperValue eq 'EXPIRE' or upperValue eq 'EXPIREE' or
upperValue eq 'HORS_SERVICE' or upperValue eq 'BLOQUE' or upperValue eq 'INACTIVE' or
upperValue eq 'INACTIF' or upperValue eq 'URGENT' or upperValue eq 'CRITIQUE'}">
<c:set var="badgeSeverity" value="danger"/>
</c:when>
<!-- Par défaut - Info (bleu) -->
<c:otherwise>
<c:set var="badgeSeverity" value="info"/>
</c:otherwise>
</c:choose>
<!-- Déterminer l'icône automatiquement -->
<c:choose>
<c:when test="#{not empty icon}">
<c:set var="badgeIcon" value="#{icon}"/>
</c:when>
<c:when test="#{badgeSeverity eq 'success'}">
<c:set var="badgeIcon" value="pi pi-check-circle"/>
</c:when>
<c:when test="#{badgeSeverity eq 'info'}">
<c:set var="badgeIcon" value="pi pi-info-circle"/>
</c:when>
<c:when test="#{badgeSeverity eq 'warning'}">
<c:set var="badgeIcon" value="pi pi-exclamation-triangle"/>
</c:when>
<c:when test="#{badgeSeverity eq 'danger'}">
<c:set var="badgeIcon" value="pi pi-times-circle"/>
</c:when>
</c:choose>
<!-- Rendu du badge -->
<p:badge value="#{value}"
severity="#{badgeSeverity}"
styleClass="#{rounded eq false ? '' : 'border-round'}
#{size eq 'large' ? 'text-lg px-3 py-2' : 'px-2'}"
style="display: inline-flex; align-items: center; gap: 0.5rem;">
<i class="#{badgeIcon}" style="font-size: 0.875rem;"/>
<span style="font-weight: 600; text-transform: capitalize;">
#{value.toString().toLowerCase().replace('_', ' ')}
</span>
</p:badge>
</ui:composition>