Initial commit

This commit is contained in:
dahoud
2025-10-01 01:39:07 +00:00
commit b430bf3b96
826 changed files with 255287 additions and 0 deletions

298
hooks/usePhasesManager.ts Normal file
View 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;