import { useState, useCallback, useEffect } from "react"; import { EntityMapping } from "@/app/config/entityLabels"; import { Word } from "./useTextParsing"; // AJOUTER cet import interface ContextMenuState { visible: boolean; x: number; y: number; selectedText: string; wordIndices: number[]; } interface UseContextMenuProps { entityMappings: EntityMapping[]; words: Word[]; // Maintenant le type Word est reconnu onUpdateMapping: ( originalValue: string, newLabel: string, entityType: string, applyToAll?: boolean, customColor?: string, wordStart?: number, wordEnd?: number ) => void; onRemoveMapping?: (originalValue: string, applyToAll?: boolean) => void; getCurrentColor: (selectedText: string) => string; setSelectedWords: (words: Set) => void; } export const useContextMenu = ({ entityMappings, words, // Paramètre ajouté onUpdateMapping, onRemoveMapping, getCurrentColor, setSelectedWords, }: UseContextMenuProps) => { const [contextMenu, setContextMenu] = useState({ visible: false, x: 0, y: 0, selectedText: "", wordIndices: [], }); const closeContextMenu = useCallback(() => { setContextMenu((prev) => ({ ...prev, visible: false })); }, []); const showContextMenu = useCallback( (menuData: Omit) => { setContextMenu({ ...menuData, visible: true }); }, [] ); const getExistingLabels = useCallback(() => { const uniqueLabels = new Set(); entityMappings.forEach((mapping) => { uniqueLabels.add(mapping.displayName || mapping.entity_type); // Utiliser displayName }); return Array.from(uniqueLabels).sort(); }, [entityMappings]); // CORRECTION: Accepter displayName comme premier paramètre const applyLabel = useCallback( (displayName: string, applyToAll?: boolean) => { if (!contextMenu.selectedText) return; const originalText = contextMenu.selectedText; const firstWordIndex = contextMenu.wordIndices[0]; // Calculer les vraies coordonnées start/end du mot cliqué const clickedWord = words[firstWordIndex]; const wordStart = clickedWord?.start; const wordEnd = clickedWord?.end; const existingMapping = entityMappings.find( (m) => m.text === originalText ); const entityType = existingMapping?.entity_type || displayName.replace(/[\[\]]/g, "").toUpperCase(); onUpdateMapping( originalText, displayName, entityType, applyToAll, undefined, // customColor wordStart, // vraies coordonnées start wordEnd // vraies coordonnées end ); setSelectedWords(new Set()); closeContextMenu(); }, [ contextMenu, words, // NOUVEAU entityMappings, onUpdateMapping, closeContextMenu, setSelectedWords, ] ); // CORRECTION: Accepter applyToAll comme paramètre const applyColorDirectly = useCallback( (color: string, colorName: string, applyToAll?: boolean) => { if (!contextMenu.selectedText) return; const existingMapping = entityMappings.find( (mapping) => mapping.text === contextMenu.selectedText ); console.log("useContextMenu - applyColorDirectly:", { color, colorName, applyToAll, existingMapping, }); if (existingMapping) { onUpdateMapping( contextMenu.selectedText, existingMapping.displayName || existingMapping.entity_type, // Utiliser displayName existingMapping.entity_type, applyToAll, color ); } else { onUpdateMapping( contextMenu.selectedText, "CUSTOM_LABEL", "CUSTOM_LABEL", applyToAll, color ); } setSelectedWords(new Set()); closeContextMenu(); }, [ contextMenu.selectedText, entityMappings, // Ajouter cette dépendance onUpdateMapping, closeContextMenu, setSelectedWords, ] ); // CORRECTION: Accepter applyToAll comme paramètre const removeLabel = useCallback( (applyToAll?: boolean) => { if (!contextMenu.selectedText || !onRemoveMapping) return; console.log("useContextMenu - removeLabel:", { selectedText: contextMenu.selectedText, applyToAll, }); onRemoveMapping(contextMenu.selectedText, applyToAll); setSelectedWords(new Set()); closeContextMenu(); }, [ contextMenu.selectedText, onRemoveMapping, closeContextMenu, setSelectedWords, ] ); // Gestion des clics en dehors du menu useEffect(() => { const handleClickOutside = (event: MouseEvent) => { if (contextMenu.visible) { const target = event.target as Element; const contextMenuElement = document.querySelector( "[data-context-menu]" ); if (contextMenuElement && !contextMenuElement.contains(target)) { setTimeout(() => { closeContextMenu(); }, 0); } } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, [contextMenu.visible, closeContextMenu]); return { contextMenu, showContextMenu, closeContextMenu, applyLabel, applyColorDirectly, removeLabel, getExistingLabels, getCurrentColor, }; };