298 lines
9.6 KiB
TypeScript
298 lines
9.6 KiB
TypeScript
import { useState, useCallback, useRef } from 'react';
|
|
import { PhaseChantier, PhaseFormData } from '../types/btp-extended';
|
|
import phaseService from '../services/phaseService';
|
|
import { Toast } from 'primereact/toast';
|
|
|
|
interface UsePhasesManagerProps {
|
|
chantierId?: string;
|
|
onPhasesChange?: () => void;
|
|
}
|
|
|
|
export const usePhasesManager = ({ chantierId, onPhasesChange }: UsePhasesManagerProps = {}) => {
|
|
const [phases, setPhases] = useState<PhaseChantier[]>([]);
|
|
const [loading, setLoading] = useState(false);
|
|
const [selectedPhase, setSelectedPhase] = useState<PhaseChantier | null>(null);
|
|
const toast = useRef<Toast>(null);
|
|
|
|
// Chargement des phases
|
|
const loadPhases = useCallback(async () => {
|
|
setLoading(true);
|
|
try {
|
|
let phasesData: PhaseChantier[];
|
|
|
|
if (chantierId) {
|
|
console.log('Chargement des phases pour le chantier:', chantierId);
|
|
phasesData = await phaseService.getByChantier(chantierId);
|
|
} else {
|
|
console.log('Chargement de toutes les phases');
|
|
phasesData = await phaseService.getAll();
|
|
}
|
|
|
|
console.log('Phases récupérées:', phasesData);
|
|
setPhases(phasesData);
|
|
|
|
if (onPhasesChange) {
|
|
onPhasesChange();
|
|
}
|
|
} catch (error) {
|
|
console.error('Erreur lors du chargement des phases:', error);
|
|
showError('Impossible de charger les phases');
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [chantierId, onPhasesChange]);
|
|
|
|
// Création d'une phase
|
|
const createPhase = useCallback(async (phaseData: PhaseFormData) => {
|
|
try {
|
|
setLoading(true);
|
|
const newPhase = await phaseService.create({
|
|
...phaseData,
|
|
chantierId: chantierId || phaseData.chantierId,
|
|
statut: 'PLANIFIEE'
|
|
});
|
|
|
|
await loadPhases();
|
|
showSuccess(`La phase "${phaseData.nom}" a été créée`);
|
|
|
|
return newPhase;
|
|
} catch (error) {
|
|
console.error('Erreur lors de la création de la phase:', error);
|
|
showError('Impossible de créer la phase');
|
|
throw error;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [chantierId, loadPhases]);
|
|
|
|
// Mise à jour d'une phase
|
|
const updatePhase = useCallback(async (phaseId: string, phaseData: Partial<PhaseChantier>) => {
|
|
try {
|
|
setLoading(true);
|
|
const updatedPhase = await phaseService.update(phaseId, phaseData);
|
|
|
|
await loadPhases();
|
|
showSuccess(`La phase a été mise à jour`);
|
|
|
|
return updatedPhase;
|
|
} catch (error) {
|
|
console.error('Erreur lors de la mise à jour de la phase:', error);
|
|
showError('Impossible de mettre à jour la phase');
|
|
throw error;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [loadPhases]);
|
|
|
|
// Suppression d'une phase
|
|
const deletePhase = useCallback(async (phaseId: string) => {
|
|
try {
|
|
setLoading(true);
|
|
await phaseService.delete(phaseId);
|
|
|
|
await loadPhases();
|
|
showSuccess('La phase a été supprimée');
|
|
} catch (error) {
|
|
console.error('Erreur lors de la suppression de la phase:', error);
|
|
showError('Impossible de supprimer la phase');
|
|
throw error;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [loadPhases]);
|
|
|
|
// Démarrage d'une phase
|
|
const startPhase = useCallback(async (phaseId: string) => {
|
|
try {
|
|
setLoading(true);
|
|
await phaseService.demarrer(phaseId);
|
|
|
|
await loadPhases();
|
|
showSuccess('La phase a été démarrée');
|
|
} catch (error) {
|
|
console.error('Erreur lors du démarrage de la phase:', error);
|
|
showError('Impossible de démarrer la phase');
|
|
throw error;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [loadPhases]);
|
|
|
|
// Mise à jour de l'avancement
|
|
const updateProgress = useCallback(async (phaseId: string, pourcentage: number) => {
|
|
try {
|
|
setLoading(true);
|
|
await phaseService.updateAvancement(phaseId, pourcentage);
|
|
|
|
await loadPhases();
|
|
showSuccess('L\'avancement a été mis à jour');
|
|
} catch (error) {
|
|
console.error('Erreur lors de la mise à jour de l\'avancement:', error);
|
|
showError('Impossible de mettre à jour l\'avancement');
|
|
throw error;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [loadPhases]);
|
|
|
|
// Terminer une phase
|
|
const completePhase = useCallback(async (phaseId: string) => {
|
|
try {
|
|
setLoading(true);
|
|
await phaseService.terminer(phaseId);
|
|
|
|
await loadPhases();
|
|
showSuccess('La phase a été terminée');
|
|
} catch (error) {
|
|
console.error('Erreur lors de la terminaison de la phase:', error);
|
|
showError('Impossible de terminer la phase');
|
|
throw error;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [loadPhases]);
|
|
|
|
// Suspendre une phase
|
|
const suspendPhase = useCallback(async (phaseId: string, motif: string) => {
|
|
try {
|
|
setLoading(true);
|
|
await phaseService.suspendre(phaseId, motif);
|
|
|
|
await loadPhases();
|
|
showSuccess('La phase a été suspendue');
|
|
} catch (error) {
|
|
console.error('Erreur lors de la suspension de la phase:', error);
|
|
showError('Impossible de suspendre la phase');
|
|
throw error;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [loadPhases]);
|
|
|
|
// Reprendre une phase
|
|
const resumePhase = useCallback(async (phaseId: string) => {
|
|
try {
|
|
setLoading(true);
|
|
await phaseService.reprendre(phaseId);
|
|
|
|
await loadPhases();
|
|
showSuccess('La phase a été reprise');
|
|
} catch (error) {
|
|
console.error('Erreur lors de la reprise de la phase:', error);
|
|
showError('Impossible de reprendre la phase');
|
|
throw error;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [loadPhases]);
|
|
|
|
// Créer une sous-phase
|
|
const createSubPhase = useCallback(async (parentPhaseId: string, subPhaseData: PhaseFormData) => {
|
|
try {
|
|
setLoading(true);
|
|
const parentPhase = phases.find(p => p.id === parentPhaseId);
|
|
|
|
if (!parentPhase) {
|
|
throw new Error('Phase parente non trouvée');
|
|
}
|
|
|
|
const newSubPhase = await phaseService.create({
|
|
...subPhaseData,
|
|
chantierId: parentPhase.chantierId || chantierId,
|
|
phaseParent: parentPhaseId,
|
|
statut: 'PLANIFIEE'
|
|
});
|
|
|
|
await loadPhases();
|
|
showSuccess(`La sous-phase "${subPhaseData.nom}" a été créée`);
|
|
|
|
return newSubPhase;
|
|
} catch (error) {
|
|
console.error('Erreur lors de la création de la sous-phase:', error);
|
|
showError('Impossible de créer la sous-phase');
|
|
throw error;
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
}, [phases, chantierId, loadPhases]);
|
|
|
|
// Statistiques
|
|
const getStatistics = useCallback(() => {
|
|
const stats = {
|
|
total: phases.length,
|
|
planifiees: phases.filter(p => p.statut === 'PLANIFIEE').length,
|
|
enCours: phases.filter(p => p.statut === 'EN_COURS').length,
|
|
terminees: phases.filter(p => p.statut === 'TERMINEE').length,
|
|
enRetard: phases.filter(p => {
|
|
if (!p.dateFinPrevue || p.statut === 'TERMINEE') return false;
|
|
return new Date(p.dateFinPrevue) < new Date();
|
|
}).length,
|
|
critiques: phases.filter(p => p.priorite === 'CRITIQUE' || p.priorite === 'HAUTE').length,
|
|
avancementMoyen: phases.length > 0
|
|
? Math.round(phases.reduce((sum, p) => sum + (p.pourcentageAvancement || 0), 0) / phases.length)
|
|
: 0
|
|
};
|
|
|
|
return stats;
|
|
}, [phases]);
|
|
|
|
// Helpers pour les notifications
|
|
const showSuccess = (message: string) => {
|
|
if (toast.current) {
|
|
toast.current.show({
|
|
severity: 'success',
|
|
summary: 'Succès',
|
|
detail: message,
|
|
life: 3000
|
|
});
|
|
}
|
|
};
|
|
|
|
const showError = (message: string) => {
|
|
if (toast.current) {
|
|
toast.current.show({
|
|
severity: 'error',
|
|
summary: 'Erreur',
|
|
detail: message,
|
|
life: 5000
|
|
});
|
|
}
|
|
};
|
|
|
|
// Attacher la ref toast
|
|
const setToastRef = (ref: any) => {
|
|
toast.current = ref;
|
|
};
|
|
|
|
return {
|
|
// État
|
|
phases,
|
|
loading,
|
|
selectedPhase,
|
|
setSelectedPhase,
|
|
|
|
// Actions CRUD
|
|
loadPhases,
|
|
createPhase,
|
|
updatePhase,
|
|
deletePhase,
|
|
createSubPhase,
|
|
|
|
// Actions métier
|
|
startPhase,
|
|
completePhase,
|
|
suspendPhase,
|
|
resumePhase,
|
|
updateProgress,
|
|
|
|
// Statistiques
|
|
getStatistics,
|
|
|
|
// Helpers
|
|
setToastRef,
|
|
showSuccess,
|
|
showError
|
|
};
|
|
};
|
|
|
|
export default usePhasesManager; |