CONFIGURATION CDI: - beans.xml pour activer CDI discovery mode "all" - Nécessaire pour injection des beans SessionScoped (UserSessionBean, GuestPreferences) - Ajouté dans src/main/resources/META-INF/ et src/main/webapp/WEB-INF/ TAGLIB FREYA: - primefaces-freya.taglib.xml définit le namespace xmlns:fr="http://primefaces.org/freya" - Contient les composants: <fr:menu>, <fr:submenu>, <fr:menuitem> - Utilise FreyaMenuRenderer, FreyaSubmenuRenderer, FreyaMenuitemRenderer - Version 5.0.0 compatible Jakarta Faces CSS DASHBOARD: - custom-dashboard.css pour styling spécifique du tableau de bord - Variables CSS pour cohérence avec Freya theme DOCUMENTATION: - DASHBOARD_CONCEPTION.md: Architecture et design du dashboard - VERIFICATION_DASHBOARD.md: Checklist de vérification Ces fichiers supportent l'implémentation du menu Freya et assurent la compatibilité avec Jakarta EE 10 et Quarkus 3.15.1. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
18 KiB
Conception Dashboard BTP Xpress - 100% Données Réelles API
Date: 2025-11-01 Objectif: Dashboard professionnel couvrant TOUS les aspects métiers BTP Xpress Principe: AUCUNE donnée fictive - 100% données réelles de l'API backend
Architecture de disposition
Layout global: 3 colonnes responsives
┌─────────────────────────────────────────────────────────────────┐
│ BARRE D'ALERTES (conditionnelle) │
└─────────────────────────────────────────────────────────────────┘
┌────────────────────────┬────────────────────────┬────────────────┐
│ KPI Principal 1 │ KPI Principal 2 │ KPI Principal 3 │
│ (Chantiers actifs) │ (Équipes dispo) │ (Maintenance) │
└────────────────────────┴────────────────────────┴────────────────┘
┌─────────────────────────────────────┬──────────────────────────────┐
│ │ │
│ GRAPHIQUE D'ACTIVITÉ │ KPIs RESSOURCES │
│ (Chantiers par statut) │ - Employés actifs │
│ │ - Matériel disponible │
│ │ - Taux d'utilisation │
│ │ │
└─────────────────────────────────────┴──────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ │
│ TABLEAU CHANTIERS ACTIFS │
│ (nom, client, budget, avancement, statut) │
│ │
└──────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────┬──────────────────────────────┐
│ │ │
│ CHANTIERS EN RETARD │ MAINTENANCES EN RETARD │
│ (timeline avec détails) │ (liste avec matériel) │
│ │ │
└─────────────────────────────────────┴──────────────────────────────┘
┌─────────────────────────────────────┬──────────────────────────────┐
│ │ │
│ DISPONIBILITÉS EN ATTENTE │ ÉVÉNEMENTS AUJOURD'HUI │
│ (demandes congés/absences) │ (planning du jour) │
│ │ │
└─────────────────────────────────────┴──────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ │
│ DOCUMENTS RÉCENTS │
│ (5 derniers documents ajoutés) │
│ │
└──────────────────────────────────────────────────────────────────┘
Mapping des données API vers composants UI
1. Barre d'alertes (affichée si totalAlertes > 0)
API: GET /api/v1/dashboard/alertes
{
"totalAlertes": 12,
"alerteCritique": true,
"maintenance": { "enRetard": 3, "details": [...] },
"chantiers": { "enRetard": 5, "details": [...] },
"disponibilites": { "enAttente": 2, "details": [...] },
"planning": { "conflits": 2, "details": [...] }
}
UI: Bannière rouge en haut avec icône ⚠️
- "12 alertes nécessitent votre attention" + bouton "Voir les détails"
2. KPIs Principaux (3 cartes en ligne)
KPI 1: Chantiers Actifs
API: GET /api/v1/dashboard → chantiers
"chantiers": {
"total": 45,
"actifs": 28,
"tauxActivite": 62.22
}
UI: Carte blanche avec icône 🏗️
- Titre: "Chantiers actifs"
- Nombre:
28(grand, bold) - Sous-titre: "Sur 45 au total"
- Badge:
62.22%d'activité
KPI 2: Équipes Disponibles
API: GET /api/v1/dashboard → equipes
"equipes": {
"total": 12,
"disponibles": 5,
"tauxDisponibilite": 41.67
}
UI: Carte bleue avec icône 👥
- Titre: "Équipes disponibles"
- Nombre:
5/12 - ProgressBar: 41.67%
- Sous-titre: "Taux de disponibilité"
KPI 3: Maintenances Critiques
API: GET /api/v1/dashboard → maintenance
"maintenance": {
"enRetard": 3,
"planifiees": 8,
"alerteRetard": true
}
UI: Carte rouge (si alerteRetard) ou verte avec icône 🔧
- Titre: "Maintenances en retard"
- Nombre:
3(rouge si > 0) - Sous-titre: "8 planifiées"
- Badge: "URGENT" si enRetard > 0
3. Graphique d'activité (Chart.js)
API: GET /api/v1/dashboard/chantiers → statistiques
Type: Doughnut Chart (camembert)
- EN_COURS: nombre + pourcentage
- PLANIFIE: nombre + pourcentage
- TERMINE: nombre + pourcentage
- SUSPENDU: nombre + pourcentage
- ANNULE: nombre + pourcentage
Couleurs Freya:
- EN_COURS:
--primary-color(violet) - PLANIFIE:
--blue-500 - TERMINE:
--green-500 - SUSPENDU:
--orange-500 - ANNULE:
--red-500
4. KPIs Ressources (colonne droite)
API: GET /api/v1/dashboard/ressources
{
"equipes": { "total": 12, "disponibles": 5, "tauxDisponibilite": 41.67 },
"employes": { "total": 156, "actifs": 142, "tauxActivite": 91.03 },
"materiel": { "total": 89, "disponible": 67, "tauxDisponibilite": 75.28 }
}
UI: 3 sous-cartes empilées
4.1 Employés Actifs
- Icon: 👨💼
- Nombre:
142/156 - Label: "Employés actifs"
- ProgressBar: 91.03% (vert si > 80%, orange si > 60%, rouge sinon)
4.2 Matériel Disponible
- Icon: 🚜
- Nombre:
67/89 - Label: "Matériel disponible"
- ProgressBar: 75.28%
4.3 Taux d'utilisation global
- Calcul frontend: moyenne des 3 taux (chantiers, équipes, employés)
- ProgressBar circulaire: donut chart mini
5. Tableau Chantiers Actifs
API: GET /api/v1/dashboard/chantiers → chantiersActifs (array)
"chantiersActifs": [
{
"id": "uuid",
"nom": "Rénovation Villa Dauphine",
"client": "Jean Dupont",
"dateDebut": "2025-01-15",
"dateFinPrevue": "2025-04-30",
"statut": "EN_COURS",
"budget": 250000.00,
"coutReel": 180000.00,
"avancement": 72
}
]
UI: PrimeFaces DataTable responsive
| Nom | Client | Début | Fin prévue | Avancement | Budget | Coût réel | Statut | Actions |
|---|---|---|---|---|---|---|---|---|
| Rénovation Villa Dauphine | Jean Dupont | 15/01/2025 | 30/04/2025 | ██████░░ 72% | 250 000 Fcfa | 180 000 Fcfa | 🟢 EN_COURS | 👁️ |
Colonnes:
- Nom: Texte (lien vers détails)
- Client: Texte
- Date Début: Format
dd/MM/yyyy - Date Fin Prévue: Format
dd/MM/yyyy - Avancement: ProgressBar avec %
- Budget: Formaté avec
fcfaConverter - Coût Réel: Formaté avec
fcfaConverter+ Badge (vert si < budget, rouge sinon) - Statut: Badge coloré selon statut
- Actions: Bouton "Voir détails"
Pagination: 10 par page Tri: Par date de début (décroissant)
6. Chantiers en Retard (Timeline)
API: GET /api/v1/dashboard/chantiers → chantiersEnRetard (array)
"chantiersEnRetard": [
{
"id": "uuid",
"nom": "Construction Immeuble B",
"dateFinPrevue": "2025-10-15",
"joursRetard": 17
}
]
UI: Timeline Freya (ul.timeline)
<li class="red">
<i class="pi pi-circle-on"></i>
<div class="event-content">
<span class="event-title">Construction Immeuble B</span>
<span>Date prévue : 15/10/2025</span>
<span class="time">+17 jours de retard</span>
</div>
</li>
Affichage: Max 5 chantiers les plus en retard Message si vide: "✅ Tous les chantiers sont dans les temps"
7. Maintenances en Retard
API: GET /api/v1/dashboard/maintenance → maintenancesEnRetard (array)
"maintenancesEnRetard": [
{
"id": "uuid",
"materiel": "Pelleteuse CAT 320",
"type": "PREVENTIVE",
"datePrevue": "2025-10-20",
"description": "Vidange et filtres",
"joursRetard": 12
}
]
UI: Liste avec badges
<div class="maintenance-item urgente">
<h6>🔧 Pelleteuse CAT 320</h6>
<p>Type: PREVENTIVE • Prévue: 20/10/2025</p>
<p class="description">Vidange et filtres</p>
<p:badge value="+12 jours" severity="danger"/>
</div>
Tri: Par nombre de jours de retard (décroissant) Limite: 5 maintenances maximum
8. Disponibilités en Attente
API: GET /api/v1/dashboard/ressources → disponibilites.enAttenteDetails (array)
"disponibilites": {
"enAttenteDetails": [
{
"id": "uuid",
"employe": "Pierre Martin",
"type": "CONGE",
"dateDebut": "2025-11-15T00:00:00",
"dateFin": "2025-11-22T23:59:59",
"motif": "Congés annuels"
}
]
}
UI: Liste avec cartes
<div class="disponibilite-card">
<div class="employee-name">
<i class="pi pi-user"></i>
Pierre Martin
</div>
<div class="dispo-details">
<p:badge value="CONGE" severity="info"/>
<span>Du 15/11 au 22/11 (7 jours)</span>
<small>Motif: Congés annuels</small>
</div>
<div class="actions">
<p:button icon="pi pi-check" label="Approuver" class="ui-button-success ui-button-sm"/>
<p:button icon="pi pi-times" label="Refuser" class="ui-button-danger ui-button-sm"/>
</div>
</div>
Affichage: Toutes les disponibilités en attente Badge: Couleur selon type (CONGE=bleu, MALADIE=orange, FORMATION=vert)
9. Événements Aujourd'hui
API: GET /api/v1/dashboard → planning.evenementsAujourdhui
Données:
"planning": {
"evenementsAujourdhui": 8
}
API détaillée: GET /api/v1/dashboard/planning (si besoin de détails)
UI: Carte avec compteur
<div class="events-today-card">
<i class="pi pi-calendar" style="font-size: 3rem; color: var(--primary-color)"></i>
<h2>8</h2>
<h6>Événements aujourd'hui</h6>
<p:button label="Voir le planning" icon="pi pi-arrow-right" class="ui-button-text"/>
</div>
10. Documents Récents
API: GET /api/v1/dashboard → documents.recents (array)
"documents": {
"total": 2456,
"recents": [
{
"id": "uuid",
"nom": "Devis Villa Dauphine.pdf",
"type": "DEVIS",
"dateCreation": "2025-11-01T14:23:00"
}
]
}
UI: Liste avec icônes de type de document
<ul class="documents-list">
<li>
<i class="pi pi-file-pdf"></i>
<div class="doc-info">
<span class="doc-name">Devis Villa Dauphine.pdf</span>
<small>DEVIS • Ajouté le 01/11/2025 à 14:23</small>
</div>
<p:button icon="pi pi-download" class="ui-button-text ui-button-sm"/>
</li>
</ul>
Icônes selon type:
- DEVIS:
pi-file-pdf - FACTURE:
pi-dollar - CONTRAT:
pi-file-edit - PLAN:
pi-image - AUTRE:
pi-file
Limite: 5 documents récents
Endpoints API utilisés (complet)
| Endpoint | Méthode | Usage | Fréquence |
|---|---|---|---|
/api/v1/dashboard |
GET | KPIs principaux, vue globale | Init |
/api/v1/dashboard/chantiers |
GET | Chantiers actifs, en retard, stats | Init |
/api/v1/dashboard/ressources |
GET | Équipes, employés, matériel, disponibilités | Init |
/api/v1/dashboard/maintenance |
GET | Maintenances en retard et planifiées | Init |
/api/v1/dashboard/alertes |
GET | Toutes les alertes critiques | Init + polling 30s |
/api/v1/dashboard/planning |
GET | Événements du jour, conflits | Optionnel |
Détails techniques
Palette de couleurs Freya
/* KPI Cards */
.card.overview-box.white { background: #FFFFFF; color: var(--text-color); }
.card.overview-box.blue { background: var(--blue-500); color: white; }
.card.overview-box.green { background: var(--green-500); color: white; }
.card.overview-box.orange { background: var(--orange-500); color: white; }
.card.overview-box.red { background: var(--red-500); color: white; }
/* Statuts chantiers */
.badge-en-cours { background: var(--primary-color); } /* Violet */
.badge-planifie { background: var(--blue-500); }
.badge-termine { background: var(--green-500); }
.badge-suspendu { background: var(--orange-500); }
.badge-annule { background: var(--red-500); }
Responsive breakpoints
// Freya breakpoints
$mobile: 768px;
$tablet: 992px;
$desktop: 1200px;
// Grid responsive
col-12 // 100% sur tous écrans
md:col-6 // 50% à partir de tablet
xl:col-4 // 33% à partir de desktop
xl:col-8 // 66% à partir de desktop
Formatage des nombres
// Converter FCFA
@FacesConverter("fcfaConverter")
public class FcfaConverter implements Converter<Double> {
@Override
public String getAsString(FacesContext ctx, UIComponent comp, Double value) {
if (value == null) return "0";
DecimalFormat df = new DecimalFormat("#,##0");
return df.format(value);
}
}
// Usage XHTML
<h:outputText value="#{chantier.budget}">
<f:converter converterId="fcfaConverter"/>
</h:outputText>
<h:outputText value=" Fcfa"/>
Formatage des dates
// Pattern français
private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("dd/MM/yyyy");
private static final DateTimeFormatter DATETIME_FORMATTER =
DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
// Méthodes dans DashboardView
public String formatDate(LocalDate date) {
return date != null ? date.format(DATE_FORMATTER) : "";
}
public String formatDateTime(LocalDateTime dateTime) {
return dateTime != null ? dateTime.format(DATETIME_FORMATTER) : "";
}
Gestion des états vides
Chaque section doit afficher un message approprié si aucune donnée :
| Section | Message si vide |
|---|---|
| Chantiers actifs | "Aucun chantier actif pour le moment" |
| Chantiers en retard | "✅ Tous les chantiers sont dans les temps" |
| Maintenances en retard | "✅ Toutes les maintenances sont à jour" |
| Disponibilités en attente | "Aucune demande de disponibilité en attente" |
| Documents récents | "Aucun document récent" |
| Alertes | Barre d'alertes masquée si totalAlertes === 0 |
Refresh et temps réel
Stratégie de rafraîchissement
- Chargement initial (@PostConstruct): Tous les endpoints
- Bouton "Rafraîchir": Recharge toutes les données
- Polling automatique (optionnel):
- Alertes: toutes les 30 secondes
- Chantiers/ressources: toutes les 5 minutes
Implémentation polling (PrimeFaces Poll)
<!-- Poll automatique des alertes -->
<p:poll interval="30" listener="#{dashboardView.refreshAlertes}"
update="alertes-panel" autoStart="true"/>
<!-- Poll optionnel (désactivé par défaut) -->
<p:poll interval="300" listener="#{dashboardView.rafraichir}"
update="@form" autoStart="false" widgetVar="dashboardPoll"/>
<!-- Bouton manuel -->
<p:commandButton value="Rafraîchir" icon="pi pi-refresh"
action="#{dashboardView.rafraichir}"
update="@form" styleClass="ui-button-text"/>
Aspects métiers couverts
✅ Chantiers: Vue globale, actifs, en retard, budget, avancement ✅ Ressources Humaines: Employés actifs, équipes, disponibilités ✅ Matériel: Disponibilité, maintenance, alertes ✅ Planning: Événements du jour, conflits ✅ Finances: Budget vs coût réel par chantier ✅ Maintenance: En retard, planifiées, alertes critiques ✅ Documents: Récents, accès rapide ✅ Alertes: Vue consolidée de tout ce qui nécessite attention
Points d'attention
🚫 Aucune donnée fictive/mockée ✅ Toutes les données proviennent strictement de l'API ✅ Gestion d'erreur robuste (null checks, try-catch) ✅ Messages appropriés pour les états vides ✅ Performance: Chargement asynchrone si nécessaire ✅ Logging: Toutes les opérations API sont loguées ✅ JavaDoc: Documentation française complète
Prochaine étape: Implémentation du dashboard.xhtml avec cette conception