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
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m34s
This commit is contained in:
@@ -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>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user