feat: enhance TagInput component with popular tags loading

- Added `loadPopularTags` function to fetch and display popular tags when the input is empty.
- Updated `TagInput` to show suggestions based on input focus and improved suggestion display with a grid layout.
- Adjusted styles for better visual clarity and user experience.
This commit is contained in:
Julien Froidefond
2025-09-14 21:49:52 +02:00
parent 3cca0fe1dc
commit 7927b0aec2
2 changed files with 50 additions and 23 deletions

View File

@@ -26,7 +26,7 @@ export function TagInput({
const inputRef = useRef<HTMLInputElement>(null);
const suggestionsRef = useRef<HTMLDivElement>(null);
const { suggestions, loading, searchTags, clearSuggestions } = useTagsAutocomplete();
const { suggestions, loading, searchTags, clearSuggestions, loadPopularTags } = useTagsAutocomplete();
// Rechercher des suggestions quand l'input change
useEffect(() => {
@@ -93,6 +93,18 @@ export function TagInput({
}, 150);
};
const handleFocus = () => {
if (inputValue.trim()) {
// Si il y a du texte, afficher les suggestions existantes
setShowSuggestions(true);
} else {
// Si l'input est vide, charger les tags populaires
loadPopularTags(20);
setShowSuggestions(true);
}
setSelectedIndex(-1);
};
return (
<div className={`relative ${className}`}>
{/* Container des tags et input */}
@@ -126,7 +138,7 @@ export function TagInput({
onChange={(e) => setInputValue(e.target.value)}
onKeyDown={handleKeyDown}
onBlur={handleBlur}
onFocus={() => inputValue && setShowSuggestions(true)}
onFocus={handleFocus}
placeholder={tags.length === 0 ? placeholder : ""}
className="flex-1 min-w-[120px] bg-transparent border-none outline-none text-slate-100 placeholder-slate-400 text-sm"
/>
@@ -138,37 +150,38 @@ export function TagInput({
{showSuggestions && (suggestions.length > 0 || loading) && (
<div
ref={suggestionsRef}
className="absolute top-full left-0 right-0 mt-1 bg-slate-800 border border-slate-600 rounded-lg shadow-lg z-50 max-h-48 overflow-y-auto"
className="absolute top-full left-0 right-0 mt-1 bg-slate-800 border border-slate-600 rounded-lg shadow-lg z-50 max-h-64 overflow-y-auto"
>
{loading ? (
<div className="p-3 text-center text-slate-400 text-sm">
Recherche...
</div>
) : (
suggestions.map((tag, index) => (
<button
key={tag.id}
type="button"
onClick={() => handleSuggestionClick(tag)}
className={`w-full text-left px-3 py-2 text-sm transition-colors ${
index === selectedIndex
? 'bg-slate-700 text-cyan-300'
: 'text-slate-200 hover:bg-slate-700'
} ${tags.includes(tag.name) ? 'opacity-50 cursor-not-allowed' : ''}`}
disabled={tags.includes(tag.name)}
>
<div className="flex items-center gap-2">
<div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-2 p-3">
{suggestions.map((tag, index) => (
<button
key={tag.id}
type="button"
onClick={() => handleSuggestionClick(tag)}
className={`flex items-center gap-2 px-2 py-1.5 text-xs rounded-md transition-colors ${
index === selectedIndex
? 'bg-slate-700 text-cyan-300 ring-1 ring-cyan-400'
: 'text-slate-200 hover:bg-slate-700'
} ${tags.includes(tag.name) ? 'opacity-50 cursor-not-allowed' : ''}`}
disabled={tags.includes(tag.name)}
title={tags.includes(tag.name) ? 'Déjà ajouté' : `Ajouter ${tag.name}`}
>
<div
className="w-3 h-3 rounded-full"
className="w-2 h-2 rounded-full flex-shrink-0"
style={{ backgroundColor: tag.color }}
/>
<span>{tag.name}</span>
<span className="truncate">{tag.name}</span>
{tags.includes(tag.name) && (
<span className="text-xs text-slate-400 ml-auto">Déjà ajouté</span>
<span className="text-slate-400 ml-auto"></span>
)}
</div>
</button>
))
</button>
))}
</div>
)}
</div>
)}

View File

@@ -214,10 +214,24 @@ export function useTagsAutocomplete() {
setSuggestions([]);
}, []);
const loadPopularTags = useCallback(async (limit: number = 20) => {
setLoading(true);
try {
const response = await tagsClient.getPopularTags(limit);
setSuggestions(response.data);
} catch (error) {
console.error('Erreur lors du chargement des tags populaires:', error);
setSuggestions([]);
} finally {
setLoading(false);
}
}, []);
return {
suggestions,
loading,
searchTags,
clearSuggestions
clearSuggestions,
loadPopularTags
};
}