feat: add filtering options for tags management

- Introduced `showOnlyWithoutIcons` state in `TagsManagement` to filter tags without icons.
- Updated `TagsFilters` component to include a button for toggling the new filter, displaying the count of tags without icons.
- Enhanced filtering logic to accommodate the new option, improving tag management functionality.
This commit is contained in:
Julien Froidefond
2025-10-01 13:40:51 +02:00
parent 4885871657
commit 7ebf7d491b
2 changed files with 27 additions and 3 deletions

View File

@@ -9,6 +9,8 @@ interface TagsFiltersProps {
onSearchChange: (query: string) => void;
showOnlyUnused: boolean;
onToggleUnused: () => void;
showOnlyWithoutIcons: boolean;
onToggleWithoutIcons: () => void;
tags: (Tag & { usage?: number })[];
onReset: () => void;
}
@@ -18,11 +20,14 @@ export function TagsFilters({
onSearchChange,
showOnlyUnused,
onToggleUnused,
showOnlyWithoutIcons,
onToggleWithoutIcons,
tags,
onReset
}: TagsFiltersProps) {
const unusedCount = tags.filter(tag => (tag.usage || 0) === 0).length;
const hasFilters = searchQuery || showOnlyUnused;
const withoutIconsCount = tags.filter(tag => !tag.name.match(/^[\p{Emoji}\p{Symbol}]/u)).length;
const hasFilters = searchQuery || showOnlyUnused || showOnlyWithoutIcons;
return (
<div className="space-y-3 mb-4">
@@ -45,6 +50,16 @@ export function TagsFilters({
Tags non utilisés ({unusedCount})
</Button>
<Button
variant={showOnlyWithoutIcons ? "primary" : "ghost"}
size="sm"
onClick={onToggleWithoutIcons}
className="flex items-center gap-2"
>
<span className="text-xs">🚫</span>
Tags sans icônes ({withoutIconsCount})
</Button>
{hasFilters && (
<Button
variant="ghost"

View File

@@ -18,6 +18,7 @@ interface TagsManagementProps {
export function TagsManagement({ tags, onRefreshTags, onDeleteTag }: TagsManagementProps) {
const [searchQuery, setSearchQuery] = useState('');
const [showOnlyUnused, setShowOnlyUnused] = useState(false);
const [showOnlyWithoutIcons, setShowOnlyWithoutIcons] = useState(false);
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
const [editingTag, setEditingTag] = useState<Tag | null>(null);
const [deletingTagId, setDeletingTagId] = useState<string | null>(null);
@@ -42,6 +43,11 @@ export function TagsManagement({ tags, onRefreshTags, onDeleteTag }: TagsManagem
});
}
// Filtrer pour afficher seulement les tags sans icônes
if (showOnlyWithoutIcons) {
filtered = filtered.filter(tag => !tag.name.match(/^[\p{Emoji}\p{Symbol}]/u));
}
const sorted = filtered.sort((a, b) => {
const usageA = a.usage || 0;
const usageB = b.usage || 0;
@@ -50,9 +56,9 @@ export function TagsManagement({ tags, onRefreshTags, onDeleteTag }: TagsManagem
});
// Limiter à 12 tags si pas de recherche ni filtre, sinon afficher tous les résultats
const hasFilters = searchQuery.trim() || showOnlyUnused;
const hasFilters = searchQuery.trim() || showOnlyUnused || showOnlyWithoutIcons;
return hasFilters ? sorted : sorted.slice(0, 12);
}, [tags, searchQuery, showOnlyUnused]);
}, [tags, searchQuery, showOnlyUnused, showOnlyWithoutIcons]);
const handleEditTag = (tag: Tag) => {
setEditingTag(tag);
@@ -77,6 +83,7 @@ export function TagsManagement({ tags, onRefreshTags, onDeleteTag }: TagsManagem
const handleReset = () => {
setSearchQuery('');
setShowOnlyUnused(false);
setShowOnlyWithoutIcons(false);
};
return (
@@ -115,6 +122,8 @@ export function TagsManagement({ tags, onRefreshTags, onDeleteTag }: TagsManagem
onSearchChange={setSearchQuery}
showOnlyUnused={showOnlyUnused}
onToggleUnused={() => setShowOnlyUnused(!showOnlyUnused)}
showOnlyWithoutIcons={showOnlyWithoutIcons}
onToggleWithoutIcons={() => setShowOnlyWithoutIcons(!showOnlyWithoutIcons)}
tags={tags}
onReset={handleReset}
/>