Initial commit
This commit is contained in:
298
hooks/usePhasesManager.ts
Normal file
298
hooks/usePhasesManager.ts
Normal file
@@ -0,0 +1,298 @@
|
||||
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;
|
||||
Reference in New Issue
Block a user