side by side txte exemple
This commit is contained in:
@@ -26,6 +26,8 @@ interface FileUploadComponentProps {
|
||||
outputText?: string;
|
||||
copyToClipboard?: () => void;
|
||||
downloadText?: () => void;
|
||||
isExampleLoaded?: boolean; // NOUVEAU
|
||||
setIsExampleLoaded?: (loaded: boolean) => void; // NOUVEAU
|
||||
}
|
||||
|
||||
export const FileUploadComponent = ({
|
||||
@@ -43,9 +45,13 @@ export const FileUploadComponent = ({
|
||||
outputText,
|
||||
copyToClipboard,
|
||||
downloadText,
|
||||
setIsExampleLoaded, // NOUVEAU - Ajouté ici
|
||||
}: FileUploadComponentProps) => {
|
||||
// Si un fichier est uploadé ou qu'il y a du texte d'exemple, on affiche le preview
|
||||
if (uploadedFile || (sourceText && sourceText.trim())) {
|
||||
// On passe en preview seulement si :
|
||||
// 1. Un fichier est uploadé OU
|
||||
// 2. On a un résultat d'anonymisation
|
||||
// (On retire isExampleLoaded pour permettre l'édition du texte d'exemple)
|
||||
if (uploadedFile || outputText) {
|
||||
return (
|
||||
<div className="w-full flex flex-col space-y-6">
|
||||
{/* Si on a un résultat, afficher 2 blocs côte à côte */}
|
||||
@@ -269,28 +275,123 @@ export const FileUploadComponent = ({
|
||||
|
||||
// Si pas de fichier ni de texte, on affiche la zone de drop
|
||||
return (
|
||||
<div className="w-full flex flex-col space-y-5">
|
||||
{/* Drop Zone - Responsive */}
|
||||
<div className="w-full flex flex-col space-y-3">
|
||||
{/* Deux colonnes côte à côte */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
{/* Colonne gauche - Zone de texte */}
|
||||
<div className="border-2 border-dashed border-[#092727] rounded-xl bg-gray-50 hover:bg-gray-100 hover:border-[#0a3030] transition-all duration-300">
|
||||
{/* Zone cliquable pour le glisser-déposer */}
|
||||
<label className="flex flex-col items-center justify-center cursor-pointer group p-6 sm:p-8">
|
||||
{/* Upload Icon */}
|
||||
<div className="w-12 h-12 sm:w-16 sm:h-16 bg-[#f7ab6e] group-hover:bg-[#f7ab6e]/75 rounded-full flex items-center justify-center mb-4 transition-colors duration-300">
|
||||
<Upload className="h-6 w-6 sm:h-8 sm:w-8 text-white transition-colors duration-300" />
|
||||
<div className="p-3 sm:p-4">
|
||||
{/* Header avec icône */}
|
||||
<div className="flex items-center justify-center mb-2">
|
||||
<div className="w-8 h-8 bg-[#f7ab6e] rounded-full flex items-center justify-center">
|
||||
<FileText className="h-4 w-4 text-white" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Main Text */}
|
||||
<h3 className="text-base sm:text-lg font-semibold text-[#092727] mb-2 group-hover:text-[#0a3030] transition-colors duration-300 text-center">
|
||||
{/* Titre */}
|
||||
<h3 className="text-sm font-semibold text-[#092727] mb-1 text-center">
|
||||
Saisissez votre texte
|
||||
</h3>
|
||||
<p className="text-xs text-[#092727] opacity-80 mb-2 text-center">
|
||||
Tapez ou collez votre texte ici
|
||||
</p>
|
||||
|
||||
{/* Zone de texte éditable */}
|
||||
<div className="relative border-2 border-gray-200 rounded-lg bg-white focus-within:border-[#f7ab6e] focus-within:ring-1 focus-within:ring-[#f7ab6e]/20 transition-all duration-300">
|
||||
{/* Zone pour le texte - SANS overflow */}
|
||||
<div className="h-40 p-2 relative">
|
||||
{/* Placeholder personnalisé avec lien cliquable */}
|
||||
{!sourceText && (
|
||||
<div className="absolute inset-2 text-gray-400 text-xs leading-relaxed pointer-events-none">
|
||||
<span>Commencez à taper du texte, ou </span>
|
||||
<SampleTextComponent
|
||||
setSourceText={setSourceText}
|
||||
setFileContent={setFileContent}
|
||||
setUploadedFile={setUploadedFile}
|
||||
setIsExampleLoaded={setIsExampleLoaded}
|
||||
variant="link"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<textarea
|
||||
value={sourceText}
|
||||
onChange={(e) => setSourceText(e.target.value)}
|
||||
placeholder="" // Placeholder vide car on utilise le custom
|
||||
className="w-full h-full border-none outline-none resize-none text-[#092727] text-xs leading-relaxed bg-transparent overflow-y-auto"
|
||||
style={{
|
||||
fontFamily:
|
||||
'ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Barre du bas avec compteur et bouton */}
|
||||
<div className="flex items-center justify-between p-2 border-t border-gray-200 bg-gray-50">
|
||||
{/* Indicateur de caractères */}
|
||||
<div className="text-gray-400 text-xs">
|
||||
{sourceText.length} caractères
|
||||
</div>
|
||||
|
||||
{/* Bouton Anonymiser */}
|
||||
<button
|
||||
onClick={onAnonymize}
|
||||
disabled={isProcessing || !sourceText.trim()}
|
||||
className="bg-[#f7ab6e] hover:bg-[#f7ab6e]/90 disabled:opacity-50 disabled:cursor-not-allowed text-white px-4 py-2 rounded-lg text-xs font-medium transition-colors duration-300 flex items-center space-x-2 shadow-sm"
|
||||
title={
|
||||
sourceText.trim()
|
||||
? "Anonymiser les données"
|
||||
: "Saisissez du texte pour anonymiser"
|
||||
}
|
||||
>
|
||||
{isProcessing ? (
|
||||
<>
|
||||
<div className="animate-spin rounded-full h-3 w-3 border-b border-white"></div>
|
||||
<span>Traitement...</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<svg
|
||||
className="w-3 h-3"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
|
||||
/>
|
||||
</svg>
|
||||
<span>Anonymisez les données</span>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Colonne droite - Zone upload */}
|
||||
<div className="border-2 border-dashed border-[#092727] rounded-xl bg-gray-50 hover:bg-gray-100 hover:border-[#0a3030] transition-all duration-300">
|
||||
<label className="flex flex-col items-center justify-center cursor-pointer group p-3 sm:p-4 h-full min-h-[200px]">
|
||||
{/* Upload Icon */}
|
||||
<div className="w-10 h-10 bg-[#092727] group-hover:bg-[#0a3030] rounded-full flex items-center justify-center mb-3 transition-colors duration-300">
|
||||
<Upload className="h-5 w-5 text-white" />
|
||||
</div>
|
||||
|
||||
{/* Titre */}
|
||||
<h3 className="text-sm font-semibold text-[#092727] mb-1 group-hover:text-[#0a3030] transition-colors duration-300 text-center">
|
||||
Déposez votre fichier ici
|
||||
</h3>
|
||||
<p className="text-sm sm:text-base text-[#092727] opacity-80 mb-4 text-center group-hover:opacity-90 transition-opacity duration-300">
|
||||
ou cliquez pour sélectionner un fichier
|
||||
<p className="text-xs text-[#092727] opacity-80 mb-3 text-center group-hover:opacity-90 transition-opacity duration-300">
|
||||
ou cliquez pour sélectionner
|
||||
</p>
|
||||
|
||||
{/* File Info */}
|
||||
<div className="flex flex-col sm:flex-row items-center gap-2 text-xs sm:text-sm text-[#092727] opacity-70">
|
||||
<div className="flex flex-col items-center gap-1 text-xs text-[#092727] opacity-60">
|
||||
<span>📄 Fichiers TXT, PDF</span>
|
||||
<span className="hidden sm:inline">•</span>
|
||||
<span>Max 5MB</span>
|
||||
</div>
|
||||
|
||||
@@ -302,22 +403,6 @@ export const FileUploadComponent = ({
|
||||
className="hidden"
|
||||
/>
|
||||
</label>
|
||||
|
||||
{/* Démarcation avec trait horizontal - NON CLIQUABLE */}
|
||||
<div className="w-full flex items-center px-6 sm:px-8 py-4">
|
||||
<div className="flex-1 h-px bg-[#092727] opacity-30"></div>
|
||||
<span className="px-3 text-xs text-[#092727] opacity-60">ou</span>
|
||||
<div className="flex-1 h-px bg-[#092727] opacity-30"></div>
|
||||
</div>
|
||||
|
||||
{/* Bouton d'exemple - NON CLIQUABLE pour le drag & drop */}
|
||||
<div className="flex justify-center pb-6 sm:pb-8">
|
||||
<SampleTextComponent
|
||||
setSourceText={setSourceText}
|
||||
setFileContent={setFileContent}
|
||||
setUploadedFile={setUploadedFile}
|
||||
variant="button"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -2,13 +2,16 @@ interface SampleTextComponentProps {
|
||||
setSourceText: (text: string) => void;
|
||||
setFileContent: (content: string) => void;
|
||||
setUploadedFile: (file: File | null) => void;
|
||||
variant?: "default" | "button"; // Ajouter une variante
|
||||
setIsExampleLoaded?: (loaded: boolean) => void;
|
||||
variant?: "button" | "link"; // Nouvelle prop
|
||||
}
|
||||
|
||||
export const SampleTextComponent = ({
|
||||
setSourceText,
|
||||
setFileContent,
|
||||
setUploadedFile,
|
||||
setIsExampleLoaded,
|
||||
variant = "button",
|
||||
}: SampleTextComponentProps) => {
|
||||
const loadSampleText = () => {
|
||||
const sampleText = `Date : 15 mars 2025
|
||||
@@ -31,16 +34,20 @@ TVA intracommunautaire : BE0987.654.321`;
|
||||
setSourceText(sampleText);
|
||||
setFileContent(sampleText);
|
||||
setUploadedFile(null);
|
||||
if (setIsExampleLoaded) {
|
||||
setIsExampleLoaded(true); // NOUVEAU - Marquer qu'un exemple est chargé
|
||||
}
|
||||
};
|
||||
|
||||
if (variant === "link") {
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
<span
|
||||
onClick={loadSampleText}
|
||||
className="bg-[#f7ab6e] hover:bg-[#f7ab6e]/90 cursor-pointer text-white px-6 py-3 rounded-lg text-sm font-medium transition-colors duration-300"
|
||||
className="text-[#f7ab6e] hover:text-[#f7ab6e]/80 underline pointer-events-auto transition-colors duration-200 cursor-pointer"
|
||||
title="Cliquez pour charger un exemple de texte"
|
||||
>
|
||||
Essayez avec un texte d'exemple
|
||||
</button>
|
||||
</>
|
||||
générez un texte d'exemple
|
||||
</span>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -25,6 +25,7 @@ export default function Home() {
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [isLoadingFile, setIsLoadingFile] = useState(false);
|
||||
const [entityMappings, setEntityMappings] = useState<EntityMapping[]>([]);
|
||||
const [isExampleLoaded, setIsExampleLoaded] = useState(false); // NOUVEAU
|
||||
|
||||
const progressSteps = ["Téléversement", "Prévisualisation", "Anonymisation"];
|
||||
|
||||
@@ -43,6 +44,7 @@ export default function Home() {
|
||||
setError(null);
|
||||
setIsLoadingFile(false);
|
||||
setEntityMappings([]);
|
||||
setIsExampleLoaded(false); // NOUVEAU
|
||||
};
|
||||
|
||||
// Hooks personnalisés pour la logique métier
|
||||
@@ -105,6 +107,8 @@ export default function Home() {
|
||||
outputText={outputText}
|
||||
copyToClipboard={copyToClipboard}
|
||||
downloadText={downloadText}
|
||||
isExampleLoaded={isExampleLoaded} // NOUVEAU
|
||||
setIsExampleLoaded={setIsExampleLoaded} // NOUVEAU
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user