'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 { Dialog } from 'primereact/dialog'; import { InputText } from 'primereact/inputtext'; import { Dropdown } from 'primereact/dropdown'; import { Calendar } from 'primereact/calendar'; import { Slider } from 'primereact/slider'; import { Tag } from 'primereact/tag'; import { Card } from 'primereact/card'; import { ProgressBar } from 'primereact/progressbar'; import { Toolbar } from 'primereact/toolbar'; import { Badge } from 'primereact/badge'; import { Divider } from 'primereact/divider'; import { InputTextarea } from 'primereact/inputtextarea'; import { InputNumber } from 'primereact/inputnumber'; import { confirmDialog } from 'primereact/confirmdialog'; import { ConfirmDialog } from 'primereact/confirmdialog'; import { Page } from '@/types'; import phaseChantierService from '@/services/phaseChantierService'; import { PhaseChantier, StatutPhase } from '@/types/btp-extended'; import { ActionButtonGroup, ViewButton, EditButton, DeleteButton, StartButton } from '../../../components/ui/ActionButton'; const PhasesChantierPage: Page = () => { const [phases, setPhases] = useState([]); const [loading, setLoading] = useState(true); const [selectedPhases, setSelectedPhases] = useState([]); const [phaseDialog, setPhaseDialog] = useState(false); const [deletePhaseDialog, setDeletePhaseDialog] = useState(false); const [currentPhase, setCurrentPhase] = useState(null); const [submitted, setSubmitted] = useState(false); const [globalFilter, setGlobalFilter] = useState(''); const [expandedRows, setExpandedRows] = useState(null); const [filters, setFilters] = useState({ statut: '', chantierId: '', enRetard: false }); const toast = useRef(null); const dt = useRef>(null); // État pour le formulaire de phase const [formData, setFormData] = useState({ nom: '', description: '', dateDebutPrevue: null as Date | null, dateFinPrevue: null as Date | null, budgetPrevu: 0, statut: 'PLANIFIEE' as StatutPhase, critique: false, notes: '', ordreExecution: 1 }); const statutOptions = [ { label: 'Planifiée', value: 'PLANIFIEE' }, { label: 'En attente', value: 'EN_ATTENTE' }, { label: 'En cours', value: 'EN_COURS' }, { label: 'En pause', value: 'EN_PAUSE' }, { label: 'Terminée', value: 'TERMINEE' }, { label: 'Annulée', value: 'ANNULEE' }, { label: 'En retard', value: 'EN_RETARD' } ]; useEffect(() => { loadPhases(); }, []); const loadPhases = async () => { try { setLoading(true); // Pour l'exemple, on charge toutes les phases. // En production, on pourrait charger par chantier spécifique const data = await phaseChantierService.getByChantier(1); // ID exemple setPhases(data || []); } catch (error) { console.error('Erreur lors du chargement des phases:', error); toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Impossible de charger les phases', life: 3000 }); } finally { setLoading(false); } }; const openNew = () => { setCurrentPhase(null); setFormData({ nom: '', description: '', dateDebutPrevue: null, dateFinPrevue: null, budgetPrevu: 0, statut: 'PLANIFIEE', critique: false, notes: '', ordreExecution: 1 }); setSubmitted(false); setPhaseDialog(true); }; const editPhase = (phase: PhaseChantier) => { setCurrentPhase(phase); setFormData({ nom: phase.nom || '', description: phase.description || '', dateDebutPrevue: phase.dateDebutPrevue ? new Date(phase.dateDebutPrevue) : null, dateFinPrevue: phase.dateFinPrevue ? new Date(phase.dateFinPrevue) : null, budgetPrevu: phase.budgetPrevu || 0, statut: phase.statut, critique: phase.critique || false, notes: phase.notes || '', ordreExecution: phase.ordreExecution || 1 }); setSubmitted(false); setPhaseDialog(true); }; const confirmDeletePhase = (phase: PhaseChantier) => { setCurrentPhase(phase); setDeletePhaseDialog(true); }; const deletePhase = async () => { try { if (currentPhase?.id) { await phaseChantierService.delete(Number(currentPhase.id)); await loadPhases(); toast.current?.show({ severity: 'success', summary: 'Succès', detail: 'Phase supprimée avec succès', life: 3000 }); } } catch (error) { toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Erreur lors de la suppression', life: 3000 }); } setDeletePhaseDialog(false); setCurrentPhase(null); }; const hideDialog = () => { setSubmitted(false); setPhaseDialog(false); }; const hideDeleteDialog = () => { setDeletePhaseDialog(false); }; const savePhase = async () => { setSubmitted(true); if (formData.nom.trim()) { try { const phaseData = { ...formData, dateDebutPrevue: formData.dateDebutPrevue?.toISOString(), dateFinPrevue: formData.dateFinPrevue?.toISOString(), chantierId: '1', // ID exemple - en production, viendrait du contexte ordreExecution: formData.ordreExecution || 1 }; if (currentPhase?.id) { await phaseChantierService.update(Number(currentPhase.id), phaseData); } else { await phaseChantierService.create(phaseData); } await loadPhases(); hideDialog(); toast.current?.show({ severity: 'success', summary: 'Succès', detail: currentPhase ? 'Phase modifiée avec succès' : 'Phase créée avec succès', life: 3000 }); } catch (error) { toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Erreur lors de la sauvegarde', life: 3000 }); } } }; const onInputChange = (e: React.ChangeEvent, name: string) => { const val = e.target.value || ''; setFormData(prev => ({ ...prev, [name]: val })); }; const onNumberInputChange = (value: number | null, name: string) => { setFormData(prev => ({ ...prev, [name]: value || 0 })); }; const onDateChange = (value: Date | null, name: string) => { setFormData(prev => ({ ...prev, [name]: value })); }; const onDropdownChange = (e: any, name: string) => { setFormData(prev => ({ ...prev, [name]: e.value })); }; // Actions sur les phases const startPhase = async (phase: PhaseChantier) => { try { if (phase.id) { await phaseChantierService.start(Number(phase.id)); await loadPhases(); toast.current?.show({ severity: 'success', summary: 'Succès', detail: 'Phase démarrée', life: 3000 }); } } catch (error) { toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Erreur lors du démarrage', life: 3000 }); } }; const completePhase = async (phase: PhaseChantier) => { try { if (phase.id) { await phaseChantierService.complete(Number(phase.id)); await loadPhases(); toast.current?.show({ severity: 'success', summary: 'Succès', detail: 'Phase terminée', life: 3000 }); } } catch (error) { toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Erreur lors de la finalisation', life: 3000 }); } }; const suspendPhase = async (phase: PhaseChantier) => { try { if (phase.id) { await phaseChantierService.suspend(Number(phase.id)); await loadPhases(); toast.current?.show({ severity: 'success', summary: 'Succès', detail: 'Phase suspendue', life: 3000 }); } } catch (error) { toast.current?.show({ severity: 'error', summary: 'Erreur', detail: 'Erreur lors de la suspension', life: 3000 }); } }; // Templates pour les colonnes const actionBodyTemplate = (rowData: PhaseChantier) => { return ( editPhase(rowData)} tooltip="Modifier" /> confirmDeletePhase(rowData)} tooltip="Supprimer" /> {rowData.statut === 'PLANIFIEE' && ( startPhase(rowData)} tooltip="Démarrer" /> )} {rowData.statut === 'EN_COURS' && ( <>