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:
@@ -9,6 +9,8 @@ interface TagsFiltersProps {
|
|||||||
onSearchChange: (query: string) => void;
|
onSearchChange: (query: string) => void;
|
||||||
showOnlyUnused: boolean;
|
showOnlyUnused: boolean;
|
||||||
onToggleUnused: () => void;
|
onToggleUnused: () => void;
|
||||||
|
showOnlyWithoutIcons: boolean;
|
||||||
|
onToggleWithoutIcons: () => void;
|
||||||
tags: (Tag & { usage?: number })[];
|
tags: (Tag & { usage?: number })[];
|
||||||
onReset: () => void;
|
onReset: () => void;
|
||||||
}
|
}
|
||||||
@@ -18,11 +20,14 @@ export function TagsFilters({
|
|||||||
onSearchChange,
|
onSearchChange,
|
||||||
showOnlyUnused,
|
showOnlyUnused,
|
||||||
onToggleUnused,
|
onToggleUnused,
|
||||||
|
showOnlyWithoutIcons,
|
||||||
|
onToggleWithoutIcons,
|
||||||
tags,
|
tags,
|
||||||
onReset
|
onReset
|
||||||
}: TagsFiltersProps) {
|
}: TagsFiltersProps) {
|
||||||
const unusedCount = tags.filter(tag => (tag.usage || 0) === 0).length;
|
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 (
|
return (
|
||||||
<div className="space-y-3 mb-4">
|
<div className="space-y-3 mb-4">
|
||||||
@@ -45,6 +50,16 @@ export function TagsFilters({
|
|||||||
Tags non utilisés ({unusedCount})
|
Tags non utilisés ({unusedCount})
|
||||||
</Button>
|
</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 && (
|
{hasFilters && (
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ interface TagsManagementProps {
|
|||||||
export function TagsManagement({ tags, onRefreshTags, onDeleteTag }: TagsManagementProps) {
|
export function TagsManagement({ tags, onRefreshTags, onDeleteTag }: TagsManagementProps) {
|
||||||
const [searchQuery, setSearchQuery] = useState('');
|
const [searchQuery, setSearchQuery] = useState('');
|
||||||
const [showOnlyUnused, setShowOnlyUnused] = useState(false);
|
const [showOnlyUnused, setShowOnlyUnused] = useState(false);
|
||||||
|
const [showOnlyWithoutIcons, setShowOnlyWithoutIcons] = useState(false);
|
||||||
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
const [isCreateModalOpen, setIsCreateModalOpen] = useState(false);
|
||||||
const [editingTag, setEditingTag] = useState<Tag | null>(null);
|
const [editingTag, setEditingTag] = useState<Tag | null>(null);
|
||||||
const [deletingTagId, setDeletingTagId] = useState<string | 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 sorted = filtered.sort((a, b) => {
|
||||||
const usageA = a.usage || 0;
|
const usageA = a.usage || 0;
|
||||||
const usageB = b.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
|
// 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);
|
return hasFilters ? sorted : sorted.slice(0, 12);
|
||||||
}, [tags, searchQuery, showOnlyUnused]);
|
}, [tags, searchQuery, showOnlyUnused, showOnlyWithoutIcons]);
|
||||||
|
|
||||||
const handleEditTag = (tag: Tag) => {
|
const handleEditTag = (tag: Tag) => {
|
||||||
setEditingTag(tag);
|
setEditingTag(tag);
|
||||||
@@ -77,6 +83,7 @@ export function TagsManagement({ tags, onRefreshTags, onDeleteTag }: TagsManagem
|
|||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
setSearchQuery('');
|
setSearchQuery('');
|
||||||
setShowOnlyUnused(false);
|
setShowOnlyUnused(false);
|
||||||
|
setShowOnlyWithoutIcons(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -115,6 +122,8 @@ export function TagsManagement({ tags, onRefreshTags, onDeleteTag }: TagsManagem
|
|||||||
onSearchChange={setSearchQuery}
|
onSearchChange={setSearchQuery}
|
||||||
showOnlyUnused={showOnlyUnused}
|
showOnlyUnused={showOnlyUnused}
|
||||||
onToggleUnused={() => setShowOnlyUnused(!showOnlyUnused)}
|
onToggleUnused={() => setShowOnlyUnused(!showOnlyUnused)}
|
||||||
|
showOnlyWithoutIcons={showOnlyWithoutIcons}
|
||||||
|
onToggleWithoutIcons={() => setShowOnlyWithoutIcons(!showOnlyWithoutIcons)}
|
||||||
tags={tags}
|
tags={tags}
|
||||||
onReset={handleReset}
|
onReset={handleReset}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user