feat(translate): implement intelligent language filtering and creation links for glossaries
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m34s

This commit is contained in:
2026-05-31 11:09:56 +02:00
parent 8ab45f1b6e
commit 3f635e809e

View File

@@ -1,6 +1,6 @@
'use client';
import { useState, useEffect, useCallback, useRef } from 'react';
import { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import { BookOpen, Plus, Loader2, Check, ChevronDown, X, Globe, ChevronRight } from 'lucide-react';
import { API_BASE } from '@/lib/config';
import { useI18n } from '@/lib/i18n';
@@ -48,6 +48,12 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
const [showTemplates, setShowTemplates] = useState(false);
const containerRef = useRef<HTMLDivElement>(null);
const [filterByLang, setFilterByLang] = useState(sourceLang !== 'auto');
useEffect(() => {
setFilterByLang(sourceLang !== 'auto');
}, [sourceLang]);
// Form states for adding term
const [newSource, setNewSource] = useState('');
const [newTarget, setNewTarget] = useState('');
@@ -222,7 +228,13 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
const sourceFlag = SUPPORTED_LANGUAGES.find(l => l.code === sourceLang)?.flag ?? '';
const targetFlag = SUPPORTED_LANGUAGES.find(l => l.code === targetLang)?.flag ?? '';
const filteredGlossaries = glossaries;
const filteredGlossaries = useMemo(() => {
if (!filterByLang || sourceLang === 'auto') {
return glossaries;
}
return glossaries.filter(g => g.source_language === sourceLang);
}, [glossaries, filterByLang, sourceLang]);
const selected = glossaries.find(g => g.id === glossaryId);
return (
<div
@@ -317,6 +329,25 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
{/* Selector Dropdown list */}
{isOpen && !disabled && (
<div className="absolute top-[102%] left-0 right-0 bg-white dark:bg-[#1a1a1a] border border-black/10 dark:border-white/10 rounded-xl shadow-2xl p-1.5 z-40 max-h-48 overflow-y-auto animate-fade-in">
{/* Filter toggle header */}
{sourceLang !== 'auto' && glossaries.length > 0 && (
<div className="px-2 py-1 border-b border-black/[0.03] dark:border-white/[0.03] flex justify-between items-center mb-1">
<span className="text-[8px] font-black text-brand-dark/40 dark:text-white/40 uppercase tracking-widest">
Filtrer par langue ({sourceFlag})
</span>
<button
type="button"
onClick={() => setFilterByLang(!filterByLang)}
className={cn(
"text-[8px] font-bold px-1.5 py-0.5 rounded transition-colors",
filterByLang ? "bg-brand-accent/10 text-brand-accent" : "bg-brand-dark/10 dark:bg-white/10 text-brand-dark/50 dark:text-white/50"
)}
>
{filterByLang ? "Actif" : "Inactif"}
</button>
</div>
)}
{filteredGlossaries.length > 0 ? (
filteredGlossaries.map(g => {
const flag = SUPPORTED_LANGUAGES.find(l => l.code === g.source_language)?.flag ?? '';
@@ -347,12 +378,28 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
);
})
) : (
<p className="px-3 py-4 text-[8px] text-brand-dark/40 dark:text-white/30 italic text-center font-light">
{sourceLang !== 'auto'
? `Aucun glossaire pour ${sourceFlag}${targetFlag}`
: "Aucun glossaire disponible"
}
</p>
<div className="px-2.5 py-4 text-center">
<p className="text-[9px] text-brand-dark/45 dark:text-white/45 italic mb-3">
Aucun glossaire pour la langue {sourceFlag || sourceLang.toUpperCase()}.
</p>
<div className="flex flex-col gap-1.5">
{filterByLang && glossaries.length > 0 && (
<button
type="button"
onClick={() => setFilterByLang(false)}
className="w-full py-1.5 px-2 bg-brand-muted dark:bg-white/5 hover:bg-brand-muted/70 text-brand-dark dark:text-white rounded-lg text-[8px] font-bold uppercase tracking-wider transition-colors"
>
Afficher tous les glossaires
</button>
)}
<a
href="/dashboard/glossaries"
className="w-full py-1.5 px-2 bg-brand-dark dark:bg-white text-white dark:text-brand-dark hover:opacity-90 rounded-lg text-[8px] font-bold uppercase tracking-wider block text-center transition-opacity"
>
Créer un glossaire
</a>
</div>
</div>
)}
</div>
)}