fix(frontend): improve glossary selector responsiveness and add contextual warning logic
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 3m10s

This commit is contained in:
2026-05-31 11:24:52 +02:00
parent 58d9d8a74c
commit f33da82c29

View File

@@ -309,6 +309,31 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
) : isGlossaryEnabled ? (
<div className="space-y-3 animate-fade-in">
{/* Help Info text */}
<p className="text-[10.5px] text-brand-dark/60 dark:text-white/40 leading-normal font-light">
Le glossaire force la traduction de termes précis. Choisissez un glossaire dont la <strong>langue source</strong> correspond à la langue d'origine de votre document.
</p>
{/* Mismatch Warning */}
{selected && sourceLang !== 'auto' && selected.source_language !== sourceLang && (
<div className="flex items-start gap-1.5 p-2 rounded-lg bg-amber-500/10 border border-amber-500/20 text-amber-600 dark:text-amber-400 text-[10px] leading-normal font-medium animate-fade-in">
<span className="shrink-0 text-amber-500">⚠️</span>
<span>
<strong>Attention :</strong> Ce glossaire utilise la langue source <strong>{getFlag(selected.source_language)} {selected.source_language.toUpperCase()}</strong>, mais votre document est configuré en <strong>{getFlag(sourceLang)} {sourceLang.toUpperCase()}</strong>.
</span>
</div>
)}
{/* Incompatibility Warning */}
{selected && selected.source_language === targetLang && (
<div className="flex items-start gap-1.5 p-2 rounded-lg bg-red-500/10 border border-red-500/20 text-red-600 dark:text-red-400 text-[10px] leading-normal font-medium animate-fade-in">
<span className="shrink-0 text-red-500">⚠️</span>
<span>
<strong>Incompatibilité :</strong> La langue source du glossaire est identique à la langue cible de traduction ({getFlag(targetLang)}). Les termes ne seront pas appliqués correctement.
</span>
</div>
)}
{/* Select Glossary Trigger button */}
<div className="relative">
<button
@@ -458,10 +483,16 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
{/* Empty State */}
{filteredGlossaries.length === 0 && filteredTemplates.length === 0 && (
<div className="px-2.5 py-4 text-center">
<p className="text-xs text-brand-dark/45 dark:text-white/45 italic mb-3">
Aucun glossaire ni modèle disponible pour la langue {sourceFlag || sourceLang.toUpperCase()}.
<p className="text-xs text-brand-dark/45 dark:text-white/45 italic mb-3 font-light">
Aucun glossaire ni modèle pour la langue source {sourceFlag || sourceLang.toUpperCase()}.
</p>
<div className="flex flex-col gap-1.5">
<a
href={`/dashboard/glossaries?new=true&source=${sourceLang}`}
className="w-full py-2 px-2 bg-brand-dark dark:bg-white text-white dark:text-brand-dark hover:opacity-90 rounded-lg text-xs font-bold uppercase tracking-wider block text-center transition-opacity cursor-pointer"
>
Créer un glossaire {sourceLang === 'auto' ? '' : sourceLang.toUpperCase()}
</a>
{filterByLang && (glossaries.length > 0 || templates.length > 0) && (
<button
type="button"
@@ -471,12 +502,6 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
Afficher tous les glossaires
</button>
)}
<a
href="/dashboard/glossaries"
className="w-full py-2 px-2 bg-brand-dark dark:bg-white text-white dark:text-brand-dark hover:opacity-90 rounded-lg text-xs font-bold uppercase tracking-wider block text-center transition-opacity cursor-pointer"
>
Créer un glossaire
</a>
</div>
</div>
)}
@@ -524,7 +549,7 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
{/* Ultra-neat Quick Term Adder */}
{selected && (
<form onSubmit={handleAddTerm} className="flex gap-1.5">
<form onSubmit={handleAddTerm} className="grid grid-cols-2 gap-2">
<input
type="text"
required
@@ -532,29 +557,31 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
value={newSource}
onChange={(e) => setNewSource(e.target.value)}
disabled={isAddingTerm || disabled}
className="flex-1 bg-white dark:bg-[#1a1a1a] border border-black/5 dark:border-white/5 rounded-lg px-2.5 py-1.5 text-xs font-semibold text-brand-dark dark:text-white placeholder:text-brand-dark/30 outline-none focus:border-brand-accent"
className="w-full bg-white dark:bg-[#1a1a1a] border border-black/5 dark:border-white/5 rounded-lg px-2.5 py-1.5 text-xs font-semibold text-brand-dark dark:text-white placeholder:text-brand-dark/30 outline-none focus:border-brand-accent min-w-0"
/>
<input
type="text"
required
placeholder="Traduction"
value={newTarget}
onChange={(e) => setNewTarget(e.target.value)}
disabled={isAddingTerm || disabled}
className="flex-1 bg-white dark:bg-[#1a1a1a] border border-black/5 dark:border-white/5 rounded-lg px-2.5 py-1.5 text-xs font-semibold text-brand-dark dark:text-white placeholder:text-brand-dark/30 outline-none focus:border-brand-accent"
/>
<button
type="submit"
disabled={isAddingTerm || disabled || !newSource.trim() || !newTarget.trim()}
className="px-3 bg-brand-dark dark:bg-white text-white dark:text-brand-dark rounded-lg flex items-center justify-center disabled:opacity-35 transition-colors cursor-pointer"
title="Ajouter le terme"
>
{isAddingTerm ? (
<Loader2 size={12} className="animate-spin" />
) : (
<Plus size={14} />
)}
</button>
<div className="flex gap-1.5">
<input
type="text"
required
placeholder="Traduction"
value={newTarget}
onChange={(e) => setNewTarget(e.target.value)}
disabled={isAddingTerm || disabled}
className="flex-1 bg-white dark:bg-[#1a1a1a] border border-black/5 dark:border-white/5 rounded-lg px-2.5 py-1.5 text-xs font-semibold text-brand-dark dark:text-white placeholder:text-brand-dark/30 outline-none focus:border-brand-accent min-w-0"
/>
<button
type="submit"
disabled={isAddingTerm || disabled || !newSource.trim() || !newTarget.trim()}
className="px-3 bg-brand-dark dark:bg-white text-white dark:text-brand-dark rounded-lg flex items-center justify-center disabled:opacity-35 transition-colors cursor-pointer shrink-0"
title="Ajouter le terme"
>
{isAddingTerm ? (
<Loader2 size={12} className="animate-spin" />
) : (
<Plus size={14} />
)}
</button>
</div>
</form>
)}
</div>