From 6269c0d096f0239df03031e4fa4961597c2ab7c3 Mon Sep 17 00:00:00 2001 From: DahoudG Date: Wed, 15 Oct 2025 20:12:57 +0000 Subject: [PATCH] fix: Change Button size from normal to small --- app/(main)/phases-chantier/retard/page.tsx | 994 ++++++++++----------- 1 file changed, 497 insertions(+), 497 deletions(-) diff --git a/app/(main)/phases-chantier/retard/page.tsx b/app/(main)/phases-chantier/retard/page.tsx index b6929cd..192b713 100644 --- a/app/(main)/phases-chantier/retard/page.tsx +++ b/app/(main)/phases-chantier/retard/page.tsx @@ -1,497 +1,497 @@ -'use client'; - -import React, { useState, useEffect, useRef } from 'react'; -import { DataTable } from 'primereact/datatable'; -import { Column } from 'primereact/column'; -import { Button } from 'primereact/button'; -import { Toast } from 'primereact/toast'; -import { Card } from 'primereact/card'; -import { Tag } from 'primereact/tag'; -import { Badge } from 'primereact/badge'; -import { ProgressBar } from 'primereact/progressbar'; -import { Toolbar } from 'primereact/toolbar'; -import { Panel } from 'primereact/panel'; -import { Chart } from 'primereact/chart'; -import { Timeline } from 'primereact/timeline'; -import { Message } from 'primereact/message'; -import { Page } from '@/types'; -import phaseChantierService from '@/services/phaseChantierService'; -import { PhaseChantier } from '@/types/btp-extended'; - -const PhasesEnRetardPage: Page = () => { - const [phasesEnRetard, setPhasesEnRetard] = useState([]); - const [loading, setLoading] = useState(true); - const [statistiques, setStatistiques] = useState({ - total: 0, - retardMoyen: 0, - impactBudget: 0, - phasesUrgentes: 0 - }); - const [chartData, setChartData] = useState({}); - const [chartOptions, setChartOptions] = useState({}); - - const toast = useRef(null); - - useEffect(() => { - loadPhasesEnRetard(); - initChart(); - }, []); - - const loadPhasesEnRetard = async () => { - try { - setLoading(true); - const data = await phaseChantierService.getEnRetard(); - setPhasesEnRetard(data || []); - - // Calculer les statistiques - if (data && data.length > 0) { - const retards = data.map(phase => phaseChantierService.calculateRetard(phase)); - const retardMoyen = retards.reduce((a, b) => a + b, 0) / retards.length; - - const impactBudget = data.reduce((total, phase) => { - const ecart = (phase.coutReel || 0) - (phase.budgetPrevu || 0); - return total + (ecart > 0 ? ecart : 0); - }, 0); - - const phasesUrgentes = data.filter(phase => - phaseChantierService.calculateRetard(phase) > 30 - ).length; - - setStatistiques({ - total: data.length, - retardMoyen: Math.round(retardMoyen), - impactBudget, - phasesUrgentes - }); - } - } catch (error) { - console.error('Erreur lors du chargement des phases en retard:', error); - toast.current?.show({ - severity: 'error', - summary: 'Erreur', - detail: 'Impossible de charger les phases en retard', - life: 3000 - }); - } finally { - setLoading(false); - } - }; - - const initChart = () => { - const documentStyle = getComputedStyle(document.documentElement); - const textColor = documentStyle.getPropertyValue('--text-color'); - const textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary'); - const surfaceBorder = documentStyle.getPropertyValue('--surface-border'); - - const data = { - labels: ['1-7 jours', '8-15 jours', '16-30 jours', '> 30 jours'], - datasets: [ - { - label: 'Phases en retard', - backgroundColor: ['#FFF3CD', '#FCF8E3', '#F8D7DA', '#D32F2F'], - borderColor: ['#856404', '#856404', '#721C24', '#B71C1C'], - data: [0, 0, 0, 0] // Sera calculé dynamiquement - } - ] - }; - - const options = { - maintainAspectRatio: false, - aspectRatio: 0.6, - plugins: { - legend: { - labels: { - fontColor: textColor - } - } - }, - scales: { - x: { - ticks: { - color: textColorSecondary - }, - grid: { - color: surfaceBorder - } - }, - y: { - ticks: { - color: textColorSecondary - }, - grid: { - color: surfaceBorder - } - } - } - }; - - setChartData(data); - setChartOptions(options); - }; - - const actionBodyTemplate = (rowData: PhaseChantier) => { - return ( -
-
- ); - }; - - const retardBodyTemplate = (rowData: PhaseChantier) => { - const retard = phaseChantierService.calculateRetard(rowData); - let severity: 'info' | 'warning' | 'danger' = 'info'; - - if (retard > 30) severity = 'danger'; - else if (retard > 15) severity = 'warning'; - - return ( - - ); - }; - - const impactBodyTemplate = (rowData: PhaseChantier) => { - const budgetPrevu = rowData.budgetPrevu || 0; - const coutReel = rowData.coutReel || 0; - const ecart = coutReel - budgetPrevu; - - if (ecart <= 0) return ; - - const pourcentageEcart = budgetPrevu > 0 ? (ecart / budgetPrevu * 100) : 0; - - return ( -
- - - +{pourcentageEcart.toFixed(1)}% - -
- ); - }; - - const prioriteBodyTemplate = (rowData: PhaseChantier) => { - const retard = phaseChantierService.calculateRetard(rowData); - const critique = rowData.critique; - - let priorite = 'Normale'; - let severity: 'info' | 'warning' | 'danger' = 'info'; - - if (critique && retard > 15) { - priorite = 'URGENTE'; - severity = 'danger'; - } else if (retard > 30) { - priorite = 'Très haute'; - severity = 'danger'; - } else if (retard > 15) { - priorite = 'Haute'; - severity = 'warning'; - } - - return ; - }; - - const responsableBodyTemplate = (rowData: PhaseChantier) => { - return rowData.responsable ? - `${rowData.responsable.prenom} ${rowData.responsable.nom}` : - 'Non assigné'; - }; - - const relancerPhase = async (phase: PhaseChantier) => { - try { - if (phase.id) { - await phaseChantierService.resume(phase.id); - await loadPhasesEnRetard(); - toast.current?.show({ - severity: 'success', - summary: 'Succès', - detail: 'Phase relancée avec succès', - life: 3000 - }); - } - } catch (error) { - toast.current?.show({ - severity: 'error', - summary: 'Erreur', - detail: 'Erreur lors de la relance', - life: 3000 - }); - } - }; - - const replanifierPhase = (phase: PhaseChantier) => { - // TODO: Ouvrir un dialog de replanification - toast.current?.show({ - severity: 'info', - summary: 'Fonctionnalité', - detail: 'Replanification à implémenter', - life: 3000 - }); - }; - - const escaladerPhase = (phase: PhaseChantier) => { - // TODO: Implémenter l'escalade (notification aux responsables) - toast.current?.show({ - severity: 'warn', - summary: 'Escalade', - detail: `Phase ${phase.nom} escaladée vers la direction`, - life: 3000 - }); - }; - - const exportData = () => { - // TODO: Implémenter l'export des données - toast.current?.show({ - severity: 'info', - summary: 'Export', - detail: 'Export en cours...', - life: 3000 - }); - }; - - const leftToolbarTemplate = () => { - return ( -
-
- ); - }; - - const rightToolbarTemplate = () => { - return ( -
- -
- ); - }; - - // Timeline des actions recommandées - const actionsRecommandees = [ - { - status: 'Immédiat', - date: 'Aujourd\'hui', - icon: 'pi pi-exclamation-triangle', - color: '#FF6B6B', - description: `${statistiques.phasesUrgentes} phases critiques à traiter en urgence` - }, - { - status: 'Cette semaine', - date: '7 jours', - icon: 'pi pi-calendar', - color: '#4ECDC4', - description: 'Replanification des phases avec retard modéré' - }, - { - status: 'Ce mois', - date: '30 jours', - icon: 'pi pi-chart-line', - color: '#45B7D1', - description: 'Analyse des causes et mise en place d\'actions préventives' - } - ]; - - return ( -
-
- - - {/* Alerte si phases critiques */} - {statistiques.phasesUrgentes > 0 && ( - - )} - - {/* Statistiques de retard */} -
-
- -
-
- - {statistiques.total} -
-
Phases en retard
-
-
-
-
- -
-
- {statistiques.retardMoyen}j -
-
Retard moyen
-
-
-
-
- -
-
- {new Intl.NumberFormat('fr-FR', { - style: 'currency', - currency: 'EUR', - notation: 'compact' - }).format(statistiques.impactBudget)} -
-
Impact budget
-
-
-
-
- -
-
- {statistiques.phasesUrgentes} -
-
Phases urgentes
-
-
-
-
- -
- {/* Liste des phases en retard */} -
- - - - - - rowData.chantier?.nom || 'N/A'} - sortable - style={{ minWidth: '10rem' }} - /> - - - - - - - -
- - {/* Actions recommandées */} -
- - ( - - - - )} - content={(item) => ( - -
-
- {item.status} -
-
- {item.date} -
-
- {item.description} -
-
-
- )} - /> -
- - - - -
-
-
-
- ); -}; - -export default PhasesEnRetardPage; +'use client'; + +import React, { useState, useEffect, useRef } from 'react'; +import { DataTable } from 'primereact/datatable'; +import { Column } from 'primereact/column'; +import { Button } from 'primereact/button'; +import { Toast } from 'primereact/toast'; +import { Card } from 'primereact/card'; +import { Tag } from 'primereact/tag'; +import { Badge } from 'primereact/badge'; +import { ProgressBar } from 'primereact/progressbar'; +import { Toolbar } from 'primereact/toolbar'; +import { Panel } from 'primereact/panel'; +import { Chart } from 'primereact/chart'; +import { Timeline } from 'primereact/timeline'; +import { Message } from 'primereact/message'; +import { Page } from '@/types'; +import phaseChantierService from '@/services/phaseChantierService'; +import { PhaseChantier } from '@/types/btp-extended'; + +const PhasesEnRetardPage: Page = () => { + const [phasesEnRetard, setPhasesEnRetard] = useState([]); + const [loading, setLoading] = useState(true); + const [statistiques, setStatistiques] = useState({ + total: 0, + retardMoyen: 0, + impactBudget: 0, + phasesUrgentes: 0 + }); + const [chartData, setChartData] = useState({}); + const [chartOptions, setChartOptions] = useState({}); + + const toast = useRef(null); + + useEffect(() => { + loadPhasesEnRetard(); + initChart(); + }, []); + + const loadPhasesEnRetard = async () => { + try { + setLoading(true); + const data = await phaseChantierService.getEnRetard(); + setPhasesEnRetard(data || []); + + // Calculer les statistiques + if (data && data.length > 0) { + const retards = data.map(phase => phaseChantierService.calculateRetard(phase)); + const retardMoyen = retards.reduce((a, b) => a + b, 0) / retards.length; + + const impactBudget = data.reduce((total, phase) => { + const ecart = (phase.coutReel || 0) - (phase.budgetPrevu || 0); + return total + (ecart > 0 ? ecart : 0); + }, 0); + + const phasesUrgentes = data.filter(phase => + phaseChantierService.calculateRetard(phase) > 30 + ).length; + + setStatistiques({ + total: data.length, + retardMoyen: Math.round(retardMoyen), + impactBudget, + phasesUrgentes + }); + } + } catch (error) { + console.error('Erreur lors du chargement des phases en retard:', error); + toast.current?.show({ + severity: 'error', + summary: 'Erreur', + detail: 'Impossible de charger les phases en retard', + life: 3000 + }); + } finally { + setLoading(false); + } + }; + + const initChart = () => { + const documentStyle = getComputedStyle(document.documentElement); + const textColor = documentStyle.getPropertyValue('--text-color'); + const textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary'); + const surfaceBorder = documentStyle.getPropertyValue('--surface-border'); + + const data = { + labels: ['1-7 jours', '8-15 jours', '16-30 jours', '> 30 jours'], + datasets: [ + { + label: 'Phases en retard', + backgroundColor: ['#FFF3CD', '#FCF8E3', '#F8D7DA', '#D32F2F'], + borderColor: ['#856404', '#856404', '#721C24', '#B71C1C'], + data: [0, 0, 0, 0] // Sera calculé dynamiquement + } + ] + }; + + const options = { + maintainAspectRatio: false, + aspectRatio: 0.6, + plugins: { + legend: { + labels: { + fontColor: textColor + } + } + }, + scales: { + x: { + ticks: { + color: textColorSecondary + }, + grid: { + color: surfaceBorder + } + }, + y: { + ticks: { + color: textColorSecondary + }, + grid: { + color: surfaceBorder + } + } + } + }; + + setChartData(data); + setChartOptions(options); + }; + + const actionBodyTemplate = (rowData: PhaseChantier) => { + return ( +
+
+ ); + }; + + const retardBodyTemplate = (rowData: PhaseChantier) => { + const retard = phaseChantierService.calculateRetard(rowData); + let severity: 'info' | 'warning' | 'danger' = 'info'; + + if (retard > 30) severity = 'danger'; + else if (retard > 15) severity = 'warning'; + + return ( + + ); + }; + + const impactBodyTemplate = (rowData: PhaseChantier) => { + const budgetPrevu = rowData.budgetPrevu || 0; + const coutReel = rowData.coutReel || 0; + const ecart = coutReel - budgetPrevu; + + if (ecart <= 0) return ; + + const pourcentageEcart = budgetPrevu > 0 ? (ecart / budgetPrevu * 100) : 0; + + return ( +
+ + + +{pourcentageEcart.toFixed(1)}% + +
+ ); + }; + + const prioriteBodyTemplate = (rowData: PhaseChantier) => { + const retard = phaseChantierService.calculateRetard(rowData); + const critique = rowData.critique; + + let priorite = 'Normale'; + let severity: 'info' | 'warning' | 'danger' = 'info'; + + if (critique && retard > 15) { + priorite = 'URGENTE'; + severity = 'danger'; + } else if (retard > 30) { + priorite = 'Très haute'; + severity = 'danger'; + } else if (retard > 15) { + priorite = 'Haute'; + severity = 'warning'; + } + + return ; + }; + + const responsableBodyTemplate = (rowData: PhaseChantier) => { + return rowData.responsable ? + `${rowData.responsable.prenom} ${rowData.responsable.nom}` : + 'Non assigné'; + }; + + const relancerPhase = async (phase: PhaseChantier) => { + try { + if (phase.id) { + await phaseChantierService.resume(phase.id); + await loadPhasesEnRetard(); + toast.current?.show({ + severity: 'success', + summary: 'Succès', + detail: 'Phase relancée avec succès', + life: 3000 + }); + } + } catch (error) { + toast.current?.show({ + severity: 'error', + summary: 'Erreur', + detail: 'Erreur lors de la relance', + life: 3000 + }); + } + }; + + const replanifierPhase = (phase: PhaseChantier) => { + // TODO: Ouvrir un dialog de replanification + toast.current?.show({ + severity: 'info', + summary: 'Fonctionnalité', + detail: 'Replanification à implémenter', + life: 3000 + }); + }; + + const escaladerPhase = (phase: PhaseChantier) => { + // TODO: Implémenter l'escalade (notification aux responsables) + toast.current?.show({ + severity: 'warn', + summary: 'Escalade', + detail: `Phase ${phase.nom} escaladée vers la direction`, + life: 3000 + }); + }; + + const exportData = () => { + // TODO: Implémenter l'export des données + toast.current?.show({ + severity: 'info', + summary: 'Export', + detail: 'Export en cours...', + life: 3000 + }); + }; + + const leftToolbarTemplate = () => { + return ( +
+
+ ); + }; + + const rightToolbarTemplate = () => { + return ( +
+ +
+ ); + }; + + // Timeline des actions recommandées + const actionsRecommandees = [ + { + status: 'Immédiat', + date: 'Aujourd\'hui', + icon: 'pi pi-exclamation-triangle', + color: '#FF6B6B', + description: `${statistiques.phasesUrgentes} phases critiques à traiter en urgence` + }, + { + status: 'Cette semaine', + date: '7 jours', + icon: 'pi pi-calendar', + color: '#4ECDC4', + description: 'Replanification des phases avec retard modéré' + }, + { + status: 'Ce mois', + date: '30 jours', + icon: 'pi pi-chart-line', + color: '#45B7D1', + description: 'Analyse des causes et mise en place d\'actions préventives' + } + ]; + + return ( +
+
+ + + {/* Alerte si phases critiques */} + {statistiques.phasesUrgentes > 0 && ( + + )} + + {/* Statistiques de retard */} +
+
+ +
+
+ + {statistiques.total} +
+
Phases en retard
+
+
+
+
+ +
+
+ {statistiques.retardMoyen}j +
+
Retard moyen
+
+
+
+
+ +
+
+ {new Intl.NumberFormat('fr-FR', { + style: 'currency', + currency: 'EUR', + notation: 'compact' + }).format(statistiques.impactBudget)} +
+
Impact budget
+
+
+
+
+ +
+
+ {statistiques.phasesUrgentes} +
+
Phases urgentes
+
+
+
+
+ +
+ {/* Liste des phases en retard */} +
+ + + + + + rowData.chantier?.nom || 'N/A'} + sortable + style={{ minWidth: '10rem' }} + /> + + + + + + + +
+ + {/* Actions recommandées */} +
+ + ( + + + + )} + content={(item) => ( + +
+
+ {item.status} +
+
+ {item.date} +
+
+ {item.description} +
+
+
+ )} + /> +
+ + + + +
+
+
+
+ ); +}; + +export default PhasesEnRetardPage;