/** * Services API pour BTP Xpress */ import axios, { AxiosInstance, AxiosResponse } from 'axios'; import { API_CONFIG } from '../config/api'; import keycloak from '../lib/keycloak'; import { CacheService, CacheKeys } from './cacheService'; import { Client, Chantier, Devis, Facture, DashboardStats, ChantierRecent, FactureEnRetard, DevisEnAttente, FilterOptions, SearchResult, Employe, Equipe, Materiel, MaintenanceMateriel, PlanningEvent, PlanningCalendrierView, PlanningConflict, PlanningStats } from '../types/btp'; import { UserInfo } from '../types/auth'; class ApiService { private api: AxiosInstance; private serverStatusListeners: ((isOnline: boolean) => void)[] = []; constructor() { this.api = axios.create({ baseURL: API_CONFIG.baseURL, timeout: API_CONFIG.timeout, headers: API_CONFIG.headers, }); // Interceptor pour les requĂȘtes this.api.interceptors.request.use( async (config) => { console.log('🔐 API Request:', config.url); // VĂ©rifier si Keycloak est initialisĂ© et l'utilisateur authentifiĂ© if (keycloak && keycloak.authenticated && keycloak.token) { try { // RafraĂźchir le token si nĂ©cessaire (70 secondes avant expiration) await keycloak.updateToken(70); // Ajouter le token Bearer Ă  l'en-tĂȘte Authorization config.headers['Authorization'] = `Bearer ${keycloak.token}`; console.log('✅ Token ajoutĂ© Ă  la requĂȘte'); } catch (error) { console.error('❌ Erreur lors de la mise Ă  jour du token Keycloak:', error); // En cas d'erreur, rediriger vers la page de connexion keycloak.login(); throw error; } } else { console.warn('⚠ Keycloak non authentifiĂ©, requĂȘte sans token'); } // Ajouter des en-tĂȘtes par dĂ©faut config.headers['X-Requested-With'] = 'XMLHttpRequest'; return config; }, (error) => { return Promise.reject(error); } ); // Interceptor pour les rĂ©ponses this.api.interceptors.response.use( (response: AxiosResponse) => response, async (error) => { // Ne pas logger les 404 sur les endpoints de chantiers par client (pas encore implĂ©mentĂ©s) const is404OnChantiersByClient = error.response?.status === 404 && error.config?.url?.includes('/chantiers/client/'); if (!is404OnChantiersByClient) { // Utiliser console.warn au lieu de console.error pour Ă©viter les erreurs React DevTools console.warn('API Error:', error.response?.status, error.response?.data || error.message); } // GĂ©rer les erreurs de connexion rĂ©seau if (!error.response) { // Erreur rĂ©seau (serveur indisponible, pas de connexion, etc.) if (error.code === 'ECONNABORTED') { error.userMessage = 'DĂ©lai d\'attente dĂ©passĂ©. Le serveur backend met trop de temps Ă  rĂ©pondre.'; error.statusCode = 'TIMEOUT'; } else if (error.code === 'ERR_NETWORK') { error.userMessage = 'Impossible de joindre le serveur backend. VĂ©rifiez votre connexion internet et que le serveur backend est dĂ©marrĂ© (mvn quarkus:dev).'; error.statusCode = 'NETWORK_ERROR'; } else { error.userMessage = 'Serveur backend indisponible. VĂ©rifiez que le serveur backend est dĂ©marrĂ© (mvn quarkus:dev) et accessible sur le port 8080.'; error.statusCode = 'SERVER_UNAVAILABLE'; } // Émettre un Ă©vĂ©nement global pour notifier l'application this.notifyServerStatus(false); return Promise.reject(error); } // Serveur rĂ©pond, donc il est disponible this.notifyServerStatus(true); if (error.response?.status === 401) { // Gestion des erreurs d'authentification (token expirĂ© ou absent) if (typeof window !== 'undefined') { const currentUrl = window.location.href; const hasAuthCode = currentUrl.includes('code=') && currentUrl.includes('/dashboard'); if (!hasAuthCode) { console.log('🔄 Token expirĂ© ou absent, redirection vers Keycloak...'); // Essayer de rafraĂźchir le token Keycloak if (keycloak && keycloak.authenticated) { try { await keycloak.updateToken(-1); // Force refresh // Retry the original request return this.api.request(error.config); } catch (refreshError) { console.error('❌ Impossible de rafraĂźchir le token, reconnexion requise'); // Sauvegarder la page actuelle pour y revenir aprĂšs reconnexion const currentPath = window.location.pathname + window.location.search; sessionStorage.setItem('returnUrl', currentPath); // Rediriger vers Keycloak pour authentification keycloak.login(); } } else { // Pas authentifiĂ©, rediriger vers Keycloak console.log('❌ Non authentifiĂ©, redirection vers Keycloak...'); if (keycloak) { keycloak.login(); } } } else { console.log('🔄 API Service: Erreur 401 ignorĂ©e car authentification en cours...'); } } } // CrĂ©er une erreur plus propre pour l'affichage const errorMessage = error.response?.data?.message || error.response?.data?.error || error.message || 'Une erreur est survenue'; const enhancedError = { ...error, userMessage: errorMessage, statusCode: error.response?.status }; return Promise.reject(enhancedError); } ); } // === GESTION STATUT SERVEUR === private notifyServerStatus(isOnline: boolean) { this.serverStatusListeners.forEach(listener => { try { listener(isOnline); } catch (error) { console.error('Erreur dans listener de statut serveur:', error); } }); } public onServerStatusChange(callback: (isOnline: boolean) => void) { this.serverStatusListeners.push(callback); return () => { const index = this.serverStatusListeners.indexOf(callback); if (index > -1) { this.serverStatusListeners.splice(index, 1); } }; } public async checkServerHealth(urgentCheck: boolean = false): Promise { const timeout = urgentCheck ? 3000 : 8000; // Timeout plus long pour checks de routine try { // Endpoint dĂ©diĂ© health check ultra-lĂ©ger await this.api.get('/api/v1/health', { timeout, headers: { 'Cache-Control': 'no-cache' }, params: { _t: Date.now() } // Cache busting }); this.notifyServerStatus(true); return true; } catch (error) { // Fallback sur endpoint Quarkus standard puis clients try { await this.api.get('/q/health', { timeout: timeout * 0.8 }); this.notifyServerStatus(true); return true; } catch (secondError) { try { await this.api.get('/api/v1/clients', { timeout: timeout * 0.6, params: { size: 1 } }); this.notifyServerStatus(true); return true; } catch (thirdError) { this.notifyServerStatus(false); return false; } } } } // === CLIENTS === async getClients(): Promise { return CacheService.getOrSet( CacheKeys.CLIENTS, async () => { const response = await this.api.get('/api/v1/clients'); return Array.isArray(response.data) ? response.data : []; }, 5 * 60 * 1000 // 5 minutes ); } async getClient(id: string): Promise { const response = await this.api.get(`/api/v1/clients/${id}`); return response.data; } async createClient(client: Partial): Promise { const response = await this.api.post('/api/v1/clients', client); return response.data; } async updateClient(id: string, client: Partial): Promise { const response = await this.api.put(`/api/v1/clients/${id}`, client); return response.data; } async deleteClient(id: string): Promise { await this.api.delete(`/api/v1/clients/${id}`); } async searchClients(params: { nom?: string; entreprise?: string; ville?: string; email?: string; }): Promise { const response = await this.api.get('/api/v1/clients/search', { params }); return response.data; } async searchClientsByNom(nom: string): Promise { const response = await this.api.get('/api/v1/clients/search', { params: { nom } }); return response.data; } async searchClientsByEntreprise(entreprise: string): Promise { const response = await this.api.get('/api/v1/clients/search', { params: { entreprise } }); return response.data; } async searchClientsByVille(ville: string): Promise { const response = await this.api.get('/api/v1/clients/search', { params: { ville } }); return response.data; } async searchClientsByEmail(email: string): Promise { const response = await this.api.get('/api/v1/clients/search', { params: { email } }); return response.data; } async getClientsCount(): Promise { const response = await this.api.get('/api/v1/clients/count'); return response.data; } // === CHANTIERS === async getChantiers(): Promise { const response = await this.api.get('/api/v1/chantiers'); return Array.isArray(response.data) ? response.data : []; } async getChantiersActifs(): Promise { const response = await this.api.get('/api/v1/chantiers/actifs'); return Array.isArray(response.data) ? response.data : []; } async getChantier(id: string): Promise { const response = await this.api.get(`/api/v1/chantiers/${id}`); return response.data; } async createChantier(chantier: Partial): Promise { const response = await this.api.post('/api/v1/chantiers', chantier); return response.data; } async updateChantier(id: string, chantier: Partial): Promise { const response = await this.api.put(`/api/v1/chantiers/${id}`, chantier); return response.data; } async deleteChantier(id: string, permanent: boolean = false): Promise { await this.api.delete(`/api/v1/chantiers/${id}`, { params: { permanent } }); } async getChantiersByClient(clientId: string): Promise { try { const response = await this.api.get(`/api/v1/chantiers/client/${clientId}`); return response.data; } catch (error: any) { // Si l'endpoint n'existe pas encore cĂŽtĂ© backend (404) if (error.response?.status === 404) { console.debug(`Endpoint /api/v1/chantiers/client/${clientId} non implĂ©mentĂ©, retour d'une liste vide`); // Retourner une liste vide en attendant l'implĂ©mentation backend return []; } // Relancer l'erreur pour les autres cas throw error; } } async getChantiersRecents(): Promise { const response = await this.api.get('/api/v1/chantiers/recent'); return response.data; } // === DEVIS === async getDevis(): Promise { return CacheService.getOrSet( CacheKeys.DEVIS, async () => { const response = await this.api.get('/api/v1/devis'); return Array.isArray(response.data) ? response.data : []; }, 3 * 60 * 1000 // 3 minutes (plus court car donnĂ©es plus volatiles) ); } async getDevisById(id: string): Promise { const response = await this.api.get(`/api/v1/devis/${id}`); return response.data; } async getDevisEnAttente(): Promise { const response = await this.api.get('/api/v1/devis/en-attente'); return response.data; } async createDevis(devis: Partial): Promise { const response = await this.api.post('/api/v1/devis', devis); // Invalider le cache des devis CacheService.delete(CacheKeys.DEVIS); CacheService.invalidatePattern('devis_.*'); return response.data; } async updateDevis(id: string, devis: Partial): Promise { const response = await this.api.put(`/api/v1/devis/${id}`, devis); // Invalider le cache des devis CacheService.delete(CacheKeys.DEVIS); CacheService.delete(CacheKeys.devisById(id)); CacheService.invalidatePattern('devis_.*'); return response.data; } async deleteDevis(id: string): Promise { await this.api.delete(`/api/v1/devis/${id}`); // Invalider le cache des devis CacheService.delete(CacheKeys.DEVIS); CacheService.delete(CacheKeys.devisById(id)); CacheService.invalidatePattern('devis_.*'); } // === FACTURES === async getFactures(): Promise { return CacheService.getOrSet( CacheKeys.FACTURES, async () => { const response = await this.api.get('/api/v1/factures'); return Array.isArray(response.data) ? response.data : []; }, 3 * 60 * 1000 // 3 minutes ); } async getFacture(id: string): Promise { const response = await this.api.get(`/api/v1/factures/${id}`); return response.data; } async getFacturesEnRetard(): Promise { const response = await this.api.get('/api/v1/factures/en-retard'); return response.data; } async createFacture(facture: Partial): Promise { const response = await this.api.post('/api/v1/factures', facture); // Invalider le cache des factures CacheService.delete(CacheKeys.FACTURES); CacheService.invalidatePattern('factures_.*'); return response.data; } async updateFacture(id: string, facture: Partial): Promise { const response = await this.api.put(`/api/v1/factures/${id}`, facture); // Invalider le cache des factures CacheService.delete(CacheKeys.FACTURES); CacheService.delete(CacheKeys.factureById(id)); CacheService.invalidatePattern('factures_.*'); return response.data; } async deleteFacture(id: string): Promise { await this.api.delete(`/api/v1/factures/${id}`); // Invalider le cache des factures CacheService.delete(CacheKeys.FACTURES); CacheService.delete(CacheKeys.factureById(id)); CacheService.invalidatePattern('factures_.*'); } // === DASHBOARD === async getDashboardStats(): Promise { const response = await this.api.get('/api/v1/dashboard/stats'); return response.data; } // === HEALTH === async getHealth(): Promise<{ status: string; timestamp: string }> { const response = await this.api.get('/api/v1/health'); return response.data; } async getVersion(): Promise<{ version: string; environment: string }> { const response = await this.api.get('/api/v1/version'); return response.data; } // === AUTH === async getCurrentUser(): Promise { const response = await this.api.get('/api/v1/auth/user'); return response.data; } async getAuthStatus(): Promise<{ authenticated: boolean; principal: string | null; hasJWT: boolean; timestamp: number }> { const response = await this.api.get('/api/v1/auth/status'); return response.data; } // === BUDGETS === async getBudgets(params?: { search?: string; statut?: string; tendance?: string }) { const response = await this.api.get('/api/v1/budgets', { params }); return response.data; } async getBudget(id: string) { const response = await this.api.get(`/api/v1/budgets/${id}`); return response.data; } async getBudgetByChantier(chantierId: string) { const response = await this.api.get(`/api/v1/budgets/chantier/${chantierId}`); return response.data; } async getBudgetsEnDepassement() { const response = await this.api.get('/api/v1/budgets/depassement'); return response.data; } async getBudgetsNecessitantAttention() { const response = await this.api.get('/api/v1/budgets/attention'); return response.data; } async createBudget(budget: any) { const response = await this.api.post('/api/v1/budgets', budget); return response.data; } async updateBudget(id: string, budget: any) { const response = await this.api.put(`/api/v1/budgets/${id}`, budget); return response.data; } async deleteBudget(id: string) { const response = await this.api.delete(`/api/v1/budgets/${id}`); return response.data; } async updateBudgetDepenses(id: string, depense: number) { const response = await this.api.put(`/api/v1/budgets/${id}/depenses`, { depense }); return response.data; } async updateBudgetAvancement(id: string, avancement: number) { const response = await this.api.put(`/api/v1/budgets/${id}/avancement`, { avancement }); return response.data; } async ajouterAlerteBudget(id: string, description: string) { const response = await this.api.post(`/api/v1/budgets/${id}/alertes`, { description }); return response.data; } async supprimerAlertesBudget(id: string) { const response = await this.api.delete(`/api/v1/budgets/${id}/alertes`); return response.data; } // === EMPLOYÉS === async getEmployes(): Promise { const response = await this.api.get('/api/v1/employes'); return Array.isArray(response.data) ? response.data : []; } async getEmploye(id: string): Promise { const response = await this.api.get(`/api/v1/employes/${id}`); return response.data; } async createEmploye(employe: Partial): Promise { const response = await this.api.post('/api/v1/employes', employe); return response.data; } async updateEmploye(id: string, employe: Partial): Promise { const response = await this.api.put(`/api/v1/employes/${id}`, employe); return response.data; } async deleteEmploye(id: string): Promise { await this.api.delete(`/api/v1/employes/${id}`); } async searchEmployes(params: { nom?: string; poste?: string; specialite?: string; statut?: string; }): Promise { const response = await this.api.get('/api/v1/employes/search', { params }); return response.data; } async getEmployesDisponibles(dateDebut?: string, dateFin?: string): Promise { const response = await this.api.get('/api/v1/employes/disponibles', { params: { dateDebut, dateFin } }); return response.data; } async getEmployesByEquipe(equipeId: string): Promise { const response = await this.api.get(`/api/v1/employes/by-equipe/${equipeId}`); return response.data; } async getEmployesCount(): Promise { const response = await this.api.get('/api/v1/employes/count'); return response.data; } async getEmployesStats(): Promise { const response = await this.api.get('/api/v1/employes/stats'); return response.data; } // === ÉQUIPES === async getEquipes(): Promise { const response = await this.api.get('/api/v1/equipes'); return Array.isArray(response.data) ? response.data : []; } async getEquipe(id: string): Promise { const response = await this.api.get(`/api/v1/equipes/${id}`); return response.data; } async createEquipe(equipe: Partial): Promise { const response = await this.api.post('/api/v1/equipes', equipe); return response.data; } async updateEquipe(id: string, equipe: Partial): Promise { const response = await this.api.put(`/api/v1/equipes/${id}`, equipe); return response.data; } async deleteEquipe(id: string): Promise { await this.api.delete(`/api/v1/equipes/${id}`); } async searchEquipes(params: { nom?: string; specialite?: string; statut?: string; }): Promise { const response = await this.api.get('/api/v1/equipes/search', { params }); return response.data; } async getEquipesDisponibles(dateDebut?: string, dateFin?: string): Promise { const response = await this.api.get('/api/v1/equipes/disponibles', { params: { dateDebut, dateFin } }); return response.data; } async getMembresEquipe(equipeId: string): Promise { const response = await this.api.get(`/api/v1/equipes/${equipeId}/membres`); return response.data; } async ajouterMembreEquipe(equipeId: string, employeId: string): Promise { await this.api.post(`/api/v1/equipes/${equipeId}/membres/${employeId}`); } async retirerMembreEquipe(equipeId: string, employeId: string): Promise { await this.api.delete(`/api/v1/equipes/${equipeId}/membres/${employeId}`); } async getEquipesCount(): Promise { const response = await this.api.get('/api/v1/equipes/count'); return response.data; } async getEquipesStats(): Promise { const response = await this.api.get('/api/v1/equipes/stats'); return response.data; } // === MATÉRIELS === async getMateriels(): Promise { const response = await this.api.get('/api/v1/materiels'); return Array.isArray(response.data) ? response.data : []; } async getMateriel(id: string): Promise { const response = await this.api.get(`/api/v1/materiels/${id}`); return response.data; } async createMateriel(materiel: Partial): Promise { const response = await this.api.post('/api/v1/materiels', materiel); return response.data; } async updateMateriel(id: string, materiel: Partial): Promise { const response = await this.api.put(`/api/v1/materiels/${id}`, materiel); return response.data; } async deleteMateriel(id: string): Promise { await this.api.delete(`/api/v1/materiels/${id}`); } async searchMateriels(params: { nom?: string; type?: string; marque?: string; statut?: string; localisation?: string; }): Promise { const response = await this.api.get('/api/v1/materiels/search', { params }); return response.data; } async getMaterielsDisponibles(dateDebut?: string, dateFin?: string, type?: string): Promise { const response = await this.api.get('/api/v1/materiels/disponibles', { params: { dateDebut, dateFin, type } }); return response.data; } async getMaterielsMaintenancePrevue(jours: number = 30): Promise { const response = await this.api.get('/api/v1/materiels/maintenance-prevue', { params: { jours } }); return response.data; } async getMaterielsByType(type: string): Promise { const response = await this.api.get(`/api/v1/materiels/by-type/${type}`); return response.data; } async reserverMateriel(id: string, dateDebut: string, dateFin: string): Promise { await this.api.post(`/api/v1/materiels/${id}/reserve`, null, { params: { dateDebut, dateFin } }); } async libererMateriel(id: string): Promise { await this.api.post(`/api/v1/materiels/${id}/liberer`); } async getMaterielsCount(): Promise { const response = await this.api.get('/api/v1/materiels/count'); return response.data; } async getMaterielsStats(): Promise { const response = await this.api.get('/api/v1/materiels/stats'); return response.data; } async getValeurTotaleMateriels(): Promise { const response = await this.api.get('/api/v1/materiels/valeur-totale'); return response.data; } // === MAINTENANCES === async getMaintenances(): Promise { const response = await this.api.get('/api/v1/maintenances'); return Array.isArray(response.data) ? response.data : []; } async getMaintenance(id: string): Promise { const response = await this.api.get(`/api/v1/maintenances/${id}`); return response.data; } async createMaintenance(maintenance: Partial): Promise { const response = await this.api.post('/api/v1/maintenances', maintenance); return response.data; } async updateMaintenance(id: string, maintenance: Partial): Promise { const response = await this.api.put(`/api/v1/maintenances/${id}`, maintenance); return response.data; } async deleteMaintenance(id: string): Promise { await this.api.delete(`/api/v1/maintenances/${id}`); } async getMaintenancesByMateriel(materielId: string): Promise { const response = await this.api.get(`/api/v1/maintenances/by-materiel/${materielId}`); return response.data; } // === PLANNING === async getPlanningEvents(params?: { dateDebut?: string; dateFin?: string; type?: string; statut?: string; }): Promise { const response = await this.api.get('/api/v1/planning/events', { params }); return Array.isArray(response.data) ? response.data : []; } async getPlanningEvent(id: string): Promise { const response = await this.api.get(`/api/v1/planning/events/${id}`); return response.data; } async createPlanningEvent(event: Partial): Promise { const response = await this.api.post('/api/v1/planning/events', event); return response.data; } async updatePlanningEvent(id: string, event: Partial): Promise { const response = await this.api.put(`/api/v1/planning/events/${id}`, event); return response.data; } async deletePlanningEvent(id: string): Promise { await this.api.delete(`/api/v1/planning/events/${id}`); } async getCalendrierView(annee: number, mois: number): Promise { const response = await this.api.get('/api/v1/planning/calendrier', { params: { annee, mois } }); return response.data; } async detecterConflitsPlanification(dateDebut?: string, dateFin?: string): Promise { const response = await this.api.get('/api/v1/planning/conflits', { params: { dateDebut, dateFin } }); return response.data; } async getPlanningEmploye(employeId: string, dateDebut?: string, dateFin?: string): Promise { const response = await this.api.get(`/api/v1/planning/employe/${employeId}`, { params: { dateDebut, dateFin } }); return response.data; } async getPlanningEquipe(equipeId: string, dateDebut?: string, dateFin?: string): Promise { const response = await this.api.get(`/api/v1/planning/equipe/${equipeId}`, { params: { dateDebut, dateFin } }); return response.data; } async getPlanningMateriel(materielId: string, dateDebut?: string, dateFin?: string): Promise { const response = await this.api.get(`/api/v1/planning/materiel/${materielId}`, { params: { dateDebut, dateFin } }); return response.data; } async assignEmployesToEvent(eventId: string, employeIds: string[]): Promise { await this.api.post(`/api/v1/planning/events/${eventId}/assign-employes`, employeIds); } async assignMaterielsToEvent(eventId: string, materielIds: string[]): Promise { await this.api.post(`/api/v1/planning/events/${eventId}/assign-materiels`, materielIds); } async getPlanningStats(): Promise { const response = await this.api.get('/api/v1/planning/stats'); return response.data; } async getTauxOccupation(dateDebut?: string, dateFin?: string): Promise { const response = await this.api.get('/api/v1/planning/occupation', { params: { dateDebut, dateFin } }); return response.data; } // === TEST === async testCreateChantier(chantier: any): Promise { const response = await this.api.post('/api/v1/test/chantier', chantier); return response.data; } } // Instance singleton export const apiService = new ApiService(); // Services spĂ©cialisĂ©s export const clientService = { getAll: () => apiService.getClients(), getById: (id: string) => apiService.getClient(id), create: (client: Partial) => apiService.createClient(client), update: (id: string, client: Partial) => apiService.updateClient(id, client), delete: (id: string) => apiService.deleteClient(id), search: (params: any) => apiService.searchClients(params), searchByNom: (nom: string) => apiService.searchClientsByNom(nom), searchByEntreprise: (entreprise: string) => apiService.searchClientsByEntreprise(entreprise), searchByVille: (ville: string) => apiService.searchClientsByVille(ville), searchByEmail: (email: string) => apiService.searchClientsByEmail(email), count: () => apiService.getClientsCount(), }; export const chantierService = { getAll: () => apiService.getChantiers(), getAllActive: () => apiService.getChantiersActifs(), getById: (id: string) => apiService.getChantier(id), create: (chantier: Partial) => apiService.createChantier(chantier), update: (id: string, chantier: Partial) => apiService.updateChantier(id, chantier), delete: (id: string, permanent: boolean = false) => apiService.deleteChantier(id, permanent), getByClient: (clientId: string) => apiService.getChantiersByClient(clientId), getRecents: () => apiService.getChantiersRecents(), }; export const devisService = { getAll: () => apiService.getDevis(), getById: (id: string) => apiService.getDevisById(id), getEnAttente: () => apiService.getDevisEnAttente(), create: (devis: Partial) => apiService.createDevis(devis), update: (id: string, devis: Partial) => apiService.updateDevis(id, devis), delete: (id: string) => apiService.deleteDevis(id), }; export const factureService = { getAll: () => apiService.getFactures(), getById: (id: string) => apiService.getFacture(id), getEnRetard: () => apiService.getFacturesEnRetard(), create: (facture: Partial) => apiService.createFacture(facture), update: (id: string, facture: Partial) => apiService.updateFacture(id, facture), delete: (id: string) => apiService.deleteFacture(id), }; export const dashboardService = { getStats: () => apiService.getDashboardStats(), }; export const employeService = { getAll: () => apiService.getEmployes(), getById: (id: string) => apiService.getEmploye(id), create: (employe: Partial) => apiService.createEmploye(employe), update: (id: string, employe: Partial) => apiService.updateEmploye(id, employe), delete: (id: string) => apiService.deleteEmploye(id), search: (params: any) => apiService.searchEmployes(params), getDisponibles: (dateDebut?: string, dateFin?: string) => apiService.getEmployesDisponibles(dateDebut, dateFin), getByEquipe: (equipeId: string) => apiService.getEmployesByEquipe(equipeId), count: () => apiService.getEmployesCount(), getStats: () => apiService.getEmployesStats(), }; export const equipeService = { getAll: () => apiService.getEquipes(), getById: (id: string) => apiService.getEquipe(id), create: (equipe: Partial) => apiService.createEquipe(equipe), update: (id: string, equipe: Partial) => apiService.updateEquipe(id, equipe), delete: (id: string) => apiService.deleteEquipe(id), search: (params: any) => apiService.searchEquipes(params), getDisponibles: (dateDebut?: string, dateFin?: string) => apiService.getEquipesDisponibles(dateDebut, dateFin), getMembres: (equipeId: string) => apiService.getMembresEquipe(equipeId), ajouterMembre: (equipeId: string, employeId: string) => apiService.ajouterMembreEquipe(equipeId, employeId), retirerMembre: (equipeId: string, employeId: string) => apiService.retirerMembreEquipe(equipeId, employeId), count: () => apiService.getEquipesCount(), getStats: () => apiService.getEquipesStats(), }; export const materielService = { getAll: () => apiService.getMateriels(), getById: (id: string) => apiService.getMateriel(id), create: (materiel: Partial) => apiService.createMateriel(materiel), update: (id: string, materiel: Partial) => apiService.updateMateriel(id, materiel), delete: (id: string) => apiService.deleteMateriel(id), search: (params: any) => apiService.searchMateriels(params), getDisponibles: (dateDebut?: string, dateFin?: string, type?: string) => apiService.getMaterielsDisponibles(dateDebut, dateFin, type), getMaintenancePrevue: (jours?: number) => apiService.getMaterielsMaintenancePrevue(jours), getByType: (type: string) => apiService.getMaterielsByType(type), reserver: (id: string, dateDebut: string, dateFin: string) => apiService.reserverMateriel(id, dateDebut, dateFin), liberer: (id: string) => apiService.libererMateriel(id), count: () => apiService.getMaterielsCount(), getStats: () => apiService.getMaterielsStats(), getValeurTotale: () => apiService.getValeurTotaleMateriels(), }; export const budgetService = { getAll: (params?: { search?: string; statut?: string; tendance?: string }) => apiService.getBudgets(params), getById: (id: string) => apiService.getBudget(id), getByChantier: (chantierId: string) => apiService.getBudgetByChantier(chantierId), getEnDepassement: () => apiService.getBudgetsEnDepassement(), getNecessitantAttention: () => apiService.getBudgetsNecessitantAttention(), create: (budget: any) => apiService.createBudget(budget), update: (id: string, budget: any) => apiService.updateBudget(id, budget), delete: (id: string) => apiService.deleteBudget(id), updateDepenses: (id: string, depense: number) => apiService.updateBudgetDepenses(id, depense), updateAvancement: (id: string, avancement: number) => apiService.updateBudgetAvancement(id, avancement), ajouterAlerte: (id: string, description: string) => apiService.ajouterAlerteBudget(id, description), supprimerAlertes: (id: string) => apiService.supprimerAlertesBudget(id), }; export const maintenanceService = { getAll: () => apiService.getMaintenances(), getById: (id: string) => apiService.getMaintenance(id), create: (maintenance: Partial) => apiService.createMaintenance(maintenance), update: (id: string, maintenance: Partial) => apiService.updateMaintenance(id, maintenance), delete: (id: string) => apiService.deleteMaintenance(id), getByMateriel: (materielId: string) => apiService.getMaintenancesByMateriel(materielId), }; export const planningService = { getEvents: (params?: any) => apiService.getPlanningEvents(params), getEvent: (id: string) => apiService.getPlanningEvent(id), createEvent: (event: Partial) => apiService.createPlanningEvent(event), updateEvent: (id: string, event: Partial) => apiService.updatePlanningEvent(id, event), deleteEvent: (id: string) => apiService.deletePlanningEvent(id), getCalendrierView: (annee: number, mois: number) => apiService.getCalendrierView(annee, mois), detecterConflits: (dateDebut?: string, dateFin?: string) => apiService.detecterConflitsPlanification(dateDebut, dateFin), getPlanningEmploye: (employeId: string, dateDebut?: string, dateFin?: string) => apiService.getPlanningEmploye(employeId, dateDebut, dateFin), getPlanningEquipe: (equipeId: string, dateDebut?: string, dateFin?: string) => apiService.getPlanningEquipe(equipeId, dateDebut, dateFin), getPlanningMateriel: (materielId: string, dateDebut?: string, dateFin?: string) => apiService.getPlanningMateriel(materielId, dateDebut, dateFin), assignEmployes: (eventId: string, employeIds: string[]) => apiService.assignEmployesToEvent(eventId, employeIds), assignMateriels: (eventId: string, materielIds: string[]) => apiService.assignMaterielsToEvent(eventId, materielIds), getStats: () => apiService.getPlanningStats(), getTauxOccupation: (dateDebut?: string, dateFin?: string) => apiService.getTauxOccupation(dateDebut, dateFin), }; // Service pour les types de chantier // TODO: Implement proper methods in ApiService class export const typeChantierService = { getAll: () => Promise.resolve([]), getByCategorie: () => Promise.resolve([]), getById: (id: string) => Promise.resolve(null), getByCode: (code: string) => Promise.resolve(null), create: (typeChantier: any) => Promise.resolve(typeChantier), update: (id: string, typeChantier: any) => Promise.resolve(typeChantier), delete: (id: string) => Promise.resolve(true), reactivate: (id: string) => Promise.resolve(true), getStatistiques: () => Promise.resolve({}), }; export default apiService;