'use client'; import React, { useState, useEffect } from 'react'; import { Card } from 'primereact/card'; import { Button } from 'primereact/button'; import { InputText } from 'primereact/inputtext'; import { Dropdown } from 'primereact/dropdown'; import { MultiSelect } from 'primereact/multiselect'; import { Calendar } from 'primereact/calendar'; import { InputNumber } from 'primereact/inputnumber'; import { Tag } from 'primereact/tag'; import { Badge } from 'primereact/badge'; import { Toolbar } from 'primereact/toolbar'; import { DataTable } from 'primereact/datatable'; import { Column } from 'primereact/column'; import { ProgressBar } from 'primereact/progressbar'; import { Message } from 'primereact/message'; import { useRouter } from 'next/navigation'; import { apiClient } from '../../../../services/api-client'; interface CriteresRecherche { specialite: string; competencesRequises: string[]; nombreEmployesMin: number; nombreEmployesMax: number; dateDebut: Date | null; dateFin: Date | null; budgetMaxJournalier: number | null; localisation?: string; niveauExperienceMin: string; evaluationMin: number; } interface EquipeRecommandee { id: number; nom: string; specialite: string; nombreEmployes: number; chefEquipeNom?: string; competencesEquipe: string[]; scoreCompatibilite: number; // sur 100 coutJournalier: number; disponibilite: { dateDebut: string; dateFin: string; dureeDisponible: number; }; evaluationPerformance: number; localisation: string; avantages: string[]; inconvenients: string[]; employes: Array<{ id: number; nom: string; prenom: string; metier: string; niveauExperience: string; competences: string[]; }>; } const EquipeOptimalePage = () => { const [criteres, setCriteres] = useState({ specialite: '', competencesRequises: [], nombreEmployesMin: 3, nombreEmployesMax: 8, dateDebut: null, dateFin: null, budgetMaxJournalier: null, niveauExperienceMin: 'DEBUTANT', evaluationMin: 3 }); const [equipesRecommandees, setEquipesRecommandees] = useState([]); const [loading, setLoading] = useState(false); const [rechercheLancee, setRechercheLancee] = useState(false); const router = useRouter(); const specialiteOptions = [ { label: 'Gros œuvre', value: 'GROS_OEUVRE' }, { label: 'Second œuvre', value: 'SECOND_OEUVRE' }, { label: 'Finitions', value: 'FINITIONS' }, { label: 'Électricité', value: 'ELECTRICITE' }, { label: 'Plomberie', value: 'PLOMBERIE' }, { label: 'Charpente', value: 'CHARPENTE' }, { label: 'Couverture', value: 'COUVERTURE' }, { label: 'Terrassement', value: 'TERRASSEMENT' } ]; const competencesOptions = [ { label: 'Maçonnerie', value: 'MACONNERIE' }, { label: 'Coffrage', value: 'COFFRAGE' }, { label: 'Ferraillage', value: 'FERRAILLAGE' }, { label: 'Électricité générale', value: 'ELECTRICITE_GENERALE' }, { label: 'Plomberie sanitaire', value: 'PLOMBERIE_SANITAIRE' }, { label: 'Chauffage', value: 'CHAUFFAGE' }, { label: 'Charpente bois', value: 'CHARPENTE_BOIS' }, { label: 'Couverture tuile', value: 'COUVERTURE_TUILE' }, { label: 'Peinture', value: 'PEINTURE' }, { label: 'Carrelage', value: 'CARRELAGE' }, { label: 'Terrassement', value: 'TERRASSEMENT' } ]; const niveauExperienceOptions = [ { label: 'Débutant', value: 'DEBUTANT' }, { label: 'Intermédiaire', value: 'INTERMEDIAIRE' }, { label: 'Confirmé', value: 'CONFIRME' }, { label: 'Expert', value: 'EXPERT' } ]; const rechercherEquipesOptimales = async () => { if (!criteres.specialite) { return; } try { setLoading(true); setRechercheLancee(true); console.log('🔄 Recherche d\'équipes optimales...', criteres); const response = await apiClient.post('/api/equipes/recommandations', criteres); console.log('✅ Équipes recommandées:', response.data); setEquipesRecommandees(response.data || []); } catch (error) { console.error('❌ Erreur lors de la recherche:', error); setEquipesRecommandees([]); } finally { setLoading(false); } }; const getScoreColor = (score: number) => { if (score >= 90) return 'success'; if (score >= 75) return 'info'; if (score >= 60) return 'warning'; return 'danger'; }; const scoreBodyTemplate = (rowData: EquipeRecommandee) => { return (
); }; const specialiteBodyTemplate = (rowData: EquipeRecommandee) => { const getSpecialiteColor = (specialite: string) => { const colors: { [key: string]: string } = { 'GROS_OEUVRE': 'danger', 'SECOND_OEUVRE': 'warning', 'FINITIONS': 'success', 'ELECTRICITE': 'info', 'PLOMBERIE': 'primary', 'CHARPENTE': 'help', 'COUVERTURE': 'secondary', 'TERRASSEMENT': 'contrast' }; return colors[specialite] || 'secondary'; }; return ; }; const competencesBodyTemplate = (rowData: EquipeRecommandee) => { const competencesCorrespondantes = rowData.competencesEquipe.filter(comp => criteres.competencesRequises.includes(comp) ); return (
{competencesCorrespondantes.slice(0, 3).map((comp, index) => ( ))} {rowData.competencesEquipe.length > competencesCorrespondantes.length && ( )}
); }; const disponibiliteBodyTemplate = (rowData: EquipeRecommandee) => { return (
{new Date(rowData.disponibilite.dateDebut).toLocaleDateString('fr-FR')} - {new Date(rowData.disponibilite.dateFin).toLocaleDateString('fr-FR')} {rowData.disponibilite.dureeDisponible} jours
); }; const coutBodyTemplate = (rowData: EquipeRecommandee) => { const isInBudget = !criteres.budgetMaxJournalier || rowData.coutJournalier <= criteres.budgetMaxJournalier; return (
{rowData.coutJournalier.toLocaleString('fr-FR')} €/jour {rowData.nombreEmployes} employés
); }; const performanceBodyTemplate = (rowData: EquipeRecommandee) => { return (
{[1, 2, 3, 4, 5].map((star) => ( ))}
); }; const avantagesBodyTemplate = (rowData: EquipeRecommandee) => { return (
{rowData.avantages?.slice(0, 2).map((avantage, index) => ( ))} {rowData.avantages?.length > 2 && ( )}
); }; const actionBodyTemplate = (rowData: EquipeRecommandee) => { return (
); }; const leftToolbarTemplate = () => { return (
); }; const rightToolbarTemplate = () => { return (
); }; return (
{/* Formulaire de critères */}
setCriteres({ ...criteres, specialite: e.value })} placeholder="Sélectionner une spécialité" />
setCriteres({ ...criteres, competencesRequises: e.value })} placeholder="Sélectionner les compétences" filter />
setCriteres({ ...criteres, nombreEmployesMin: e.value || 1 })} min={1} max={20} />
setCriteres({ ...criteres, nombreEmployesMax: e.value || 8 })} min={1} max={20} />
setCriteres({ ...criteres, dateDebut: e.value as Date })} showIcon dateFormat="dd/mm/yy" />
setCriteres({ ...criteres, dateFin: e.value as Date })} showIcon dateFormat="dd/mm/yy" />
setCriteres({ ...criteres, budgetMaxJournalier: e.value })} mode="currency" currency="EUR" locale="fr-FR" />
setCriteres({ ...criteres, niveauExperienceMin: e.value })} />
setCriteres({ ...criteres, evaluationMin: e.value || 1 })} min={1} max={5} suffix="/5" />
setCriteres({ ...criteres, localisation: e.target.value })} placeholder="Ville ou région" />
{/* Résultats */}
{!rechercheLancee ? (

Recherche d'équipe optimale

Remplissez les critères de recherche et cliquez sur "Rechercher" pour obtenir les meilleures recommandations d'équipes.

) : loading ? (

Recherche en cours...

Analyse des équipes disponibles et calcul des scores de compatibilité.

) : equipesRecommandees.length === 0 ? (

Aucune équipe trouvée

Aucune équipe ne correspond à vos critères. Essayez d'assouplir certains paramètres.

) : ( <>

Équipes recommandées

équipes trouvées
)}
); }; export default EquipeOptimalePage;