import React, { useState, useRef, useCallback } from 'react'; import TreeView from '@/components/Structure/Competencies/TreeView'; import SectionHeader from '@/components/SectionHeader'; import { Award, CheckCircle } from 'lucide-react'; import SelectChoice from '@/components/Form/SelectChoice'; import CheckBox from '@/components/Form/CheckBox'; import Button from '@/components/Form/Button'; import { useEstablishment } from '@/context/EstablishmentContext'; import { createEstablishmentCompetencies, deleteEstablishmentCompetencies, } from '@/app/actions/schoolAction'; import { useCsrfToken } from '@/context/CsrfContext'; import { useNotification } from '@/context/NotificationContext'; const cycles = [ { id: 1, label: 'Cycle 1' }, { id: 2, label: 'Cycle 2' }, { id: 3, label: 'Cycle 3' }, { id: 4, label: 'Cycle 4' }, ]; export default function CompetenciesList({ establishmentCompetencies, onChangeCycle, }) { const [selectedCycle, setSelectedCycle] = useState(cycles[0].id); const [showSelectedOnlyByCycle, setShowSelectedOnlyByCycle] = useState({ 1: true, 2: true, 3: true, 4: true, }); const [expandAllByCycle, setExpandAllByCycle] = useState({ 1: false, 2: false, 3: false, 4: false, }); const [hasSelectionByCycle, setHasSelectionByCycle] = useState({ 1: false, 2: false, 3: false, 4: false, }); const { selectedEstablishmentId, profileRole } = useEstablishment(); const csrfToken = useCsrfToken(); const { showNotification } = useNotification(); // Référence vers le composant TreeView pour récupérer les compétences sélectionnées const treeViewRef = useRef(); // Met à jour l'état de sélection à chaque changement dans TreeView const handleSelectionChange = useCallback( (selectedCompetencies) => { setHasSelectionByCycle((prev) => ({ ...prev, [selectedCycle]: selectedCompetencies.length > 0, })); }, [selectedCycle] ); // Filtrage : si showSelectedOnly, on affiche uniquement les compétences de l'établissement (state !== "none") // sinon, on affiche toutes les compétences du cycle const filteredData = (establishmentCompetencies.data || []).map( (domaine) => ({ ...domaine, categories: domaine.categories.map((cat) => ({ ...cat, competences: showSelectedOnlyByCycle[selectedCycle] ? cat.competences.filter((c) => c.state !== 'none') : cat.competences, })), }) ); const showSelectedOnly = showSelectedOnlyByCycle[selectedCycle]; const expandAll = expandAllByCycle[selectedCycle]; const handleShowSelectedOnlyChange = () => { setShowSelectedOnlyByCycle((prev) => ({ ...prev, [selectedCycle]: !prev[selectedCycle], })); }; const handleExpandAllChange = () => { setExpandAllByCycle((prev) => ({ ...prev, [selectedCycle]: !prev[selectedCycle], })); }; const handleCycleChange = (e) => { const value = Number(e.target.value); setSelectedCycle(value); setHasSelectionByCycle((prev) => ({ ...prev, [value]: false, })); // Réinitialise la sélection visuelle dans le TreeView if (treeViewRef.current && treeViewRef.current.clearSelection) { treeViewRef.current.clearSelection(); } onChangeCycle(value); }; const handleSubmit = () => { if (!treeViewRef.current || !treeViewRef.current.getSelectedCompetencies) return; const selectedIds = treeViewRef.current.getSelectedCompetencies(); const toCreate = []; const toDelete = []; const selectedCustomKeys = new Set( (establishmentCompetencies.data || []).flatMap((domaine) => domaine.categories.flatMap((cat) => cat.competences .filter( (c) => c.state === 'custom' && (selectedIds.includes(String(c.competence_id)) || selectedIds.includes(Number(c.competence_id))) ) .map((c) => `${cat.categorie_id}__${c.nom.trim().toLowerCase()}`) ) ) ); (establishmentCompetencies.data || []).forEach((domaine) => { domaine.categories.forEach((cat) => { cat.competences.forEach((competence) => { const isSelected = selectedIds.includes(String(competence.competence_id)) || selectedIds.includes(Number(competence.competence_id)); const key = `${cat.categorie_id}__${competence.nom.trim().toLowerCase()}`; // "none" sélectionné => à créer, sauf si une custom du même nom/catégorie est déjà sélectionnée if ( competence.state === 'none' && isSelected && !selectedCustomKeys.has(key) ) { toCreate.push({ category_id: cat.categorie_id, establishment_id: selectedEstablishmentId, nom: competence.nom, }); } else if (competence.state === 'custom' && isSelected) { // Suppression d'une compétence custom toDelete.push({ competence_id: competence.competence_id, // id de EstablishmentCompetency nom: competence.nom, category_id: cat.categorie_id, establishment_id: selectedEstablishmentId, }); } }); }); }); const afterSuccess = () => { if (treeViewRef.current && treeViewRef.current.clearSelection) { treeViewRef.current.clearSelection(); } setHasSelectionByCycle((prev) => ({ ...prev, [selectedCycle]: false, })); onChangeCycle(selectedCycle); showNotification('Opération effectuée avec succès', 'success', 'Succès'); }; if (toCreate.length > 0 && toDelete.length > 0) { Promise.all([ createEstablishmentCompetencies(toCreate, csrfToken), deleteEstablishmentCompetencies( toDelete.map((item) => item.competence_id), csrfToken ), ]) .then(afterSuccess) .catch((error) => { showNotification( error.message || 'Erreur apparue lors de la mise à jour des compétences', 'error', 'Erreur' ); }); } else if (toCreate.length > 0) { createEstablishmentCompetencies(toCreate, csrfToken) .then(afterSuccess) .catch((error) => { showNotification( error.message || 'Erreur apparue lors de la mise à jour des compétences', 'error', 'Erreur' ); }); } else if (toDelete.length > 0) { deleteEstablishmentCompetencies( toDelete.map((item) => item.competence_id), csrfToken ) .then(afterSuccess) .catch((error) => { showNotification( error.message || 'Erreur apparue lors de la mise à jour des compétences', 'error', 'Erreur' ); }); } }; const hasSelection = hasSelectionByCycle[selectedCycle]; return (