Files
Anonyme/app/components/AnonymizationLogic.tsx
nBiqoz 130929b756 ok
2025-09-12 16:54:40 +02:00

141 lines
4.4 KiB
TypeScript

import { useState } from "react";
import {
PresidioAnalyzerResult,
EntityMapping,
} from "@/app/config/entityLabels";
// Interface pour la réponse de l'API process-document
interface ProcessDocumentResponse {
text?: string;
anonymizedText?: string;
analyzerResults?: PresidioAnalyzerResult[];
replacementValues?: Record<string, string>; // Nouvelle propriété
error?: string;
}
// Props du hook
interface AnonymizationLogicProps {
setOutputText: (text: string) => void;
setError: (error: string | null) => void;
setEntityMappings: (mappings: EntityMapping[]) => void;
}
// NOUVEAU: Définir les types pour le paramètre de anonymizeData
interface AnonymizeDataParams {
file?: File | null;
text?: string;
}
/**
* Hook pour la logique d'anonymisation.
* Gère l'appel API et la création du tableau de mapping de manière simple et directe.
*/
export const useAnonymization = ({
setOutputText,
setError,
setEntityMappings,
}: AnonymizationLogicProps) => {
const [isProcessing, setIsProcessing] = useState(false);
const anonymizeData = async ({ file, text }: AnonymizeDataParams) => {
setIsProcessing(true);
setError(null);
setEntityMappings([]);
setOutputText("");
try {
// ÉTAPE 1: Construire le FormData ici pour garantir le bon format
const formData = new FormData();
if (file) {
formData.append("file", file);
} else if (text) {
// Si c'est du texte, on le transforme en Blob pour l'envoyer comme un fichier
const textBlob = new Blob([text], { type: "text/plain" });
formData.append("file", textBlob, "input.txt");
} else {
throw new Error("Aucune donnée à anonymiser (ni fichier, ni texte).");
}
const response = await fetch("/api/process-document", {
method: "POST",
body: formData, // Le Content-Type sera automatiquement défini par le navigateur
});
const data: ProcessDocumentResponse = await response.json();
if (!response.ok || data.error) {
throw new Error(
data.error || "Erreur lors de la communication avec l'API."
);
}
const originalText = data.text || "";
const presidioResults = data.analyzerResults || [];
const replacementValues = data.replacementValues || {}; // Récupérer les valeurs de remplacement
// 🔍 AJOUT DES CONSOLE.LOG POUR DÉBOGUER
console.log("📊 Données reçues de Presidio:", {
originalTextLength: originalText.length,
presidioResultsCount: presidioResults.length,
presidioResults: presidioResults,
replacementValues: replacementValues,
replacementValuesKeys: Object.keys(replacementValues),
replacementValuesEntries: Object.entries(replacementValues),
});
// ÉTAPE 2 : Passer le texte ORIGINAL à l'état de sortie.
setOutputText(originalText);
// ÉTAPE 3 : Créer le tableau de mapping avec la nouvelle structure
const sortedResults = [...presidioResults].sort(
(a, b) => a.start - b.start
);
const mappings: EntityMapping[] = [];
// Dans la fonction anonymizeData, section création des mappings :
for (const result of sortedResults) {
const { entity_type, start, end } = result;
const detectedText = originalText.substring(start, end);
// 🔍 CONSOLE.LOG POUR CHAQUE ENTITÉ
console.log(`🔍 Entité détectée:`, {
entity_type,
detectedText,
replacementFromMap: replacementValues[detectedText],
fallback: `[${entity_type}]`,
});
mappings.push({
entity_type: entity_type,
start: start,
end: end,
text: detectedText,
replacementValue: replacementValues[detectedText],
displayName: replacementValues[detectedText],
customColor: undefined,
});
}
// 🔍 CONSOLE.LOG FINAL DES MAPPINGS
console.log("📋 Mappings créés:", mappings);
// ÉTAPE 4 : Mettre à jour l'état global avec les mappings créés.
setEntityMappings(mappings);
} catch (error) {
console.error("Erreur dans useAnonymization:", error);
setError(
error instanceof Error
? error.message
: "Une erreur inconnue est survenue."
);
} finally {
setIsProcessing(false);
}
};
return {
anonymizeData,
isProcessing,
};
};