'use client'; import React, { useState, useEffect } from 'react'; import { Card } from 'primereact/card'; import { Timeline } from 'primereact/timeline'; import { Badge } from 'primereact/badge'; import { Tag } from 'primereact/tag'; import { Button } from 'primereact/button'; import { Accordion, AccordionTab } from 'primereact/accordion'; import { ProgressBar } from 'primereact/progressbar'; import { Tooltip } from 'primereact/tooltip'; import chantierTemplateService from '../../services/chantierTemplateService'; import type { TypeChantier, PhaseTemplate } from '../../types/chantier-templates'; import type { ChantierPreview } from '../../types/chantier-form'; interface PhasesTimelinePreviewProps { typeChantier: TypeChantier; dateDebut: Date; surface?: number; nombreNiveaux?: number; inclureSousPhases?: boolean; ajusterDelais?: boolean; margeSecurite?: number; className?: string; showDetails?: boolean; compact?: boolean; } interface PhaseTimelineItem { id: string; nom: string; description: string; dateDebut: Date; dateFin: Date; duree: number; ordreExecution: number; critique: boolean; prerequis: string[]; sousPhases?: PhaseTimelineItem[]; competences: string[]; status?: 'planned' | 'current' | 'completed' | 'late'; } const PhasesTimelinePreview: React.FC = ({ typeChantier, dateDebut, surface, nombreNiveaux, inclureSousPhases = true, ajusterDelais = true, margeSecurite = 5, className = '', showDetails = true, compact = false }) => { const [timelineItems, setTimelineItems] = useState([]); const [preview, setPreview] = useState(null); const [loading, setLoading] = useState(true); const [expandedPhases, setExpandedPhases] = useState([]); useEffect(() => { generateTimeline(); }, [typeChantier, dateDebut, surface, nombreNiveaux, inclureSousPhases, ajusterDelais, margeSecurite]); const generateTimeline = async () => { setLoading(true); try { const template = await chantierTemplateService.getTemplate(typeChantier); const complexity = await chantierTemplateService.analyzeComplexity(typeChantier); const planning = await chantierTemplateService.calculatePlanning(typeChantier, dateDebut); // Générer la prévisualisation const previewData: ChantierPreview = { typeChantier, nom: template.nom, dureeEstimee: template.dureeMoyenneJours, dateFinEstimee: planning.dateFin, complexite: complexity, phasesCount: template.phases.length, sousePhasesCount: template.phases.reduce((total, phase) => total + (phase.sousPhases?.length || 0), 0), specificites: template.specificites || [], reglementations: template.reglementations || [] }; setPreview(previewData); // Convertir les phases du template en éléments timeline const items: PhaseTimelineItem[] = []; let currentDate = new Date(dateDebut); template.phases.forEach((phase, index) => { const adjustedDuration = ajusterDelais ? Math.ceil(phase.dureePrevueJours * (complexity.score / 100)) : phase.dureePrevueJours; const phaseItem: PhaseTimelineItem = { id: phase.id, nom: phase.nom, description: phase.description, dateDebut: new Date(currentDate), dateFin: addDays(currentDate, adjustedDuration), duree: adjustedDuration, ordreExecution: phase.ordreExecution, critique: phase.critique, prerequis: phase.prerequis || [], competences: phase.competencesRequises || [], status: 'planned' }; if (inclureSousPhases && phase.sousPhases) { let sousPhaseDate = new Date(currentDate); phaseItem.sousPhases = phase.sousPhases.map(sousPhase => { const sousPhaseAdjustedDuration = ajusterDelais ? Math.ceil(sousPhase.dureePrevueJours * (complexity.score / 100)) : sousPhase.dureePrevueJours; const item: PhaseTimelineItem = { id: sousPhase.id, nom: sousPhase.nom, description: sousPhase.description, dateDebut: new Date(sousPhaseDate), dateFin: addDays(sousPhaseDate, sousPhaseAdjustedDuration), duree: sousPhaseAdjustedDuration, ordreExecution: sousPhase.ordreExecution, critique: false, prerequis: [], competences: sousPhase.competencesRequises || [], status: 'planned' }; sousPhaseDate = addDays(sousPhaseDate, sousPhaseAdjustedDuration); return item; }); } items.push(phaseItem); currentDate = addDays(currentDate, adjustedDuration + (margeSecurite || 0)); }); setTimelineItems(items); } catch (error) { console.error('Erreur lors de la génération du timeline:', error); } finally { setLoading(false); } }; const addDays = (date: Date, days: number): Date => { const result = new Date(date); result.setDate(result.getDate() + days); return result; }; const formatDate = (date: Date): string => { return date.toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit', year: 'numeric' }); }; const getSeverityByStatus = (status: string) => { switch (status) { case 'completed': return 'success'; case 'current': return 'info'; case 'late': return 'danger'; default: return 'secondary'; } }; const getIconByPhase = (phase: PhaseTimelineItem): string => { if (phase.critique) return 'pi pi-exclamation-triangle'; if (phase.competences.includes('ELECTRICITE')) return 'pi pi-bolt'; if (phase.competences.includes('PLOMBERIE')) return 'pi pi-home'; if (phase.competences.includes('MACONNERIE')) return 'pi pi-building'; if (phase.competences.includes('CHARPENTE')) return 'pi pi-sitemap'; return 'pi pi-circle'; }; const renderPhaseCard = (phase: PhaseTimelineItem, isSubPhase = false) => (
{phase.nom} {phase.critique && ( )}

{phase.description}

{/* Compétences requises */} {phase.competences.length > 0 && (
{phase.competences.map(comp => ( ))}
)}
{phase.duree} jour{phase.duree > 1 ? 's' : ''}
{formatDate(phase.dateDebut)} - {formatDate(phase.dateFin)}
{/* Prérequis */} {showDetails && phase.prerequis.length > 0 && (
Prérequis:
{phase.prerequis.join(', ')}
)} {/* Sous-phases */} {!compact && inclureSousPhases && phase.sousPhases && phase.sousPhases.length > 0 && (
)}
); const renderCompactTimeline = () => { const timelineData = timelineItems.map(phase => ({ status: phase.nom, date: formatDate(phase.dateDebut), icon: getIconByPhase(phase), color: phase.critique ? '#ef4444' : '#3b82f6', phase: phase })); return ( (
{item.status}
{item.phase.duree} jour{item.phase.duree > 1 ? 's' : ''}
)} content={(item) => (
{item.date}
{item.phase.critique && ( )}
)} className="w-full" /> ); }; if (loading) { return (
Génération du planning...
); } return ( {/* Métriques rapides */} {preview && (
{preview.phasesCount}
Phases
{preview.sousePhasesCount}
Sous-phases
{preview.dureeEstimee}
Jours
Complexité
)} {/* Affichage compact ou détaillé */} {compact ? ( renderCompactTimeline() ) : (
{timelineItems.map(phase => renderPhaseCard(phase))}
)} {/* Légende */} {showDetails && (
Légende:
Phase critique
Électricité
Plomberie
Maçonnerie
)}
); }; export default PhasesTimelinePreview;