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';
|
'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 { BookOpen, Plus, Loader2, Check, ChevronDown, X, Globe, ChevronRight } from 'lucide-react';
|
||||||
import { API_BASE } from '@/lib/config';
|
import { API_BASE } from '@/lib/config';
|
||||||
import { useI18n } from '@/lib/i18n';
|
import { useI18n } from '@/lib/i18n';
|
||||||
@@ -48,6 +48,12 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
|
|||||||
const [showTemplates, setShowTemplates] = useState(false);
|
const [showTemplates, setShowTemplates] = useState(false);
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
const [filterByLang, setFilterByLang] = useState(sourceLang !== 'auto');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setFilterByLang(sourceLang !== 'auto');
|
||||||
|
}, [sourceLang]);
|
||||||
|
|
||||||
// Form states for adding term
|
// Form states for adding term
|
||||||
const [newSource, setNewSource] = useState('');
|
const [newSource, setNewSource] = useState('');
|
||||||
const [newTarget, setNewTarget] = 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 sourceFlag = SUPPORTED_LANGUAGES.find(l => l.code === sourceLang)?.flag ?? '';
|
||||||
const targetFlag = SUPPORTED_LANGUAGES.find(l => l.code === targetLang)?.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);
|
const selected = glossaries.find(g => g.id === glossaryId);
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -317,6 +329,25 @@ export function GlossarySelector({ sourceLang, targetLang, isPro, mode, glossary
|
|||||||
{/* Selector Dropdown list */}
|
{/* Selector Dropdown list */}
|
||||||
{isOpen && !disabled && (
|
{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">
|
<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.length > 0 ? (
|
||||||
filteredGlossaries.map(g => {
|
filteredGlossaries.map(g => {
|
||||||
const flag = SUPPORTED_LANGUAGES.find(l => l.code === g.source_language)?.flag ?? '';
|
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">
|
<div className="px-2.5 py-4 text-center">
|
||||||
{sourceLang !== 'auto'
|
<p className="text-[9px] text-brand-dark/45 dark:text-white/45 italic mb-3">
|
||||||
? `Aucun glossaire pour ${sourceFlag}➔${targetFlag}`
|
Aucun glossaire pour la langue {sourceFlag || sourceLang.toUpperCase()}.
|
||||||
: "Aucun glossaire disponible"
|
</p>
|
||||||
}
|
<div className="flex flex-col gap-1.5">
|
||||||
</p>
|
{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>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
Reference in New Issue
Block a user