/** * Service pour la gestion des templates de phases BTP via l'API backend * Remplace l'utilisation des données statiques par des appels API */ import { TypeChantier, PhaseTemplate, ChantierTemplate, TYPE_CHANTIER_LABELS, CATEGORIES_CHANTIER } from '../types/chantier-templates'; import { PhaseChantier } from '../types/btp-extended'; class PhaseTemplateService { private apiBaseUrl = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8080/api/v1'; /** * Récupérer la liste des types de chantiers disponibles depuis l'API */ async getAvailableChantierTypes(): Promise<{ value: TypeChantier; label: string; categorie: string }[]> { try { const response = await fetch(`${this.apiBaseUrl}/phase-templates/types-chantier`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error('Erreur lors de la récupération des types de chantiers'); } const typesFromAPI = await response.json(); // Mapper les types de l'API vers le format attendu par le frontend const mappedTypes = typesFromAPI.map((type: any) => { // Trouver la catégorie correspondante let categorie = 'Autre'; for (const [cat, config] of Object.entries(CATEGORIES_CHANTIER)) { if (config.types.includes(type as TypeChantier)) { categorie = config.label; break; } } return { value: type as TypeChantier, label: TYPE_CHANTIER_LABELS[type as TypeChantier] || type, categorie: categorie }; }); return mappedTypes; } catch (error) { console.error('Erreur lors de la récupération des types de chantiers:', error); // Fallback vers les données locales si l'API est indisponible return this.getLocalChantierTypes(); } } /** * Récupérer les templates de phases pour un type de chantier */ async getTemplatesByType(typeChantier: TypeChantier): Promise { try { const response = await fetch(`${this.apiBaseUrl}/phase-templates/by-type/${typeChantier}`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error('Erreur lors de la récupération des templates'); } const templates = await response.json(); return templates; } catch (error) { console.error('Erreur lors de la récupération des templates:', error); throw error; } } /** * Récupérer un template par son ID avec ses sous-phases */ async getTemplateById(id: string): Promise { try { const response = await fetch(`${this.apiBaseUrl}/phase-templates/${id}`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json' } }); if (response.status === 404) { return null; } if (!response.ok) { throw new Error('Erreur lors de la récupération du template'); } const template = await response.json(); return template; } catch (error) { console.error('Erreur lors de la récupération du template:', error); throw error; } } /** * Prévisualiser les phases qui seraient générées pour un type de chantier */ async previewPhases(typeChantier: TypeChantier): Promise { try { const response = await fetch(`${this.apiBaseUrl}/phase-templates/previsualisation/${typeChantier}`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error('Erreur lors de la prévisualisation des phases'); } const phases = await response.json(); return phases; } catch (error) { console.error('Erreur lors de la prévisualisation des phases:', error); throw error; } } /** * Calculer la durée totale estimée pour un type de chantier */ async calculateDureeTotale(typeChantier: TypeChantier): Promise { try { const response = await fetch(`${this.apiBaseUrl}/phase-templates/duree-estimee/${typeChantier}`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error('Erreur lors du calcul de la durée'); } const duree = await response.json(); return duree; } catch (error) { console.error('Erreur lors du calcul de la durée:', error); throw error; } } /** * Analyser la complexité d'un type de chantier */ async analyzeComplexity(typeChantier: TypeChantier): Promise<{ typeChantier: TypeChantier; nombrePhases: number; nombrePhasesCritiques: number; dureeTotal: number; niveauComplexite: string; }> { try { const response = await fetch(`${this.apiBaseUrl}/phase-templates/complexite/${typeChantier}`, { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json' } }); if (!response.ok) { throw new Error('Erreur lors de l\'analyse de complexité'); } const complexite = await response.json(); return complexite; } catch (error) { console.error('Erreur lors de l\'analyse de complexité:', error); throw error; } } /** * Générer automatiquement les phases pour un chantier */ async generatePhases( chantierId: string, dateDebutChantier: Date, inclureSousPhases: boolean = true ): Promise { try { const response = await fetch(`${this.apiBaseUrl}/phase-templates/generer-phases`, { method: 'POST', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ chantierId: chantierId, dateDebutChantier: dateDebutChantier.toISOString().split('T')[0], inclureSousPhases: inclureSousPhases }) }); if (!response.ok) { const error = await response.text(); throw new Error(error || 'Erreur lors de la génération des phases'); } const phasesGenerees = await response.json(); return phasesGenerees; } catch (error) { console.error('Erreur lors de la génération des phases:', error); throw error; } } /** * Créer un nouveau template de phase */ async createTemplate(template: Partial): Promise { try { const response = await fetch(`${this.apiBaseUrl}/phase-templates`, { method: 'POST', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json' }, body: JSON.stringify(template) }); if (!response.ok) { const error = await response.text(); throw new Error(error || 'Erreur lors de la création du template'); } const nouveauTemplate = await response.json(); return nouveauTemplate; } catch (error) { console.error('Erreur lors de la création du template:', error); throw error; } } /** * Mettre à jour un template de phase */ async updateTemplate(id: string, template: Partial): Promise { try { const response = await fetch(`${this.apiBaseUrl}/phase-templates/${id}`, { method: 'PUT', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}`, 'Content-Type': 'application/json' }, body: JSON.stringify(template) }); if (!response.ok) { const error = await response.text(); throw new Error(error || 'Erreur lors de la mise à jour du template'); } const templateMisAJour = await response.json(); return templateMisAJour; } catch (error) { console.error('Erreur lors de la mise à jour du template:', error); throw error; } } /** * Supprimer (désactiver) un template de phase */ async deleteTemplate(id: string): Promise { try { const response = await fetch(`${this.apiBaseUrl}/phase-templates/${id}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); if (!response.ok) { const error = await response.text(); throw new Error(error || 'Erreur lors de la suppression du template'); } } catch (error) { console.error('Erreur lors de la suppression du template:', error); throw error; } } /** * Fallback: Récupérer les types de chantiers depuis les données locales */ private getLocalChantierTypes(): { value: TypeChantier; label: string; categorie: string }[] { const types: { value: TypeChantier; label: string; categorie: string }[] = []; for (const [categorie, config] of Object.entries(CATEGORIES_CHANTIER)) { for (const type of config.types) { types.push({ value: type, label: TYPE_CHANTIER_LABELS[type], categorie: config.label }); } } return types; } } export default new PhaseTemplateService();