feat(timesheet): add searchable tag selectors
This commit is contained in:
@@ -56,6 +56,7 @@ function FilterTagMultiSelect({
|
||||
title: string;
|
||||
}) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [searchQuery, setSearchQuery] = useState("");
|
||||
const [dropdownStyle, setDropdownStyle] = useState<CSSProperties>({});
|
||||
const wrapperRef = useRef<HTMLDivElement>(null);
|
||||
const buttonRef = useRef<HTMLButtonElement>(null);
|
||||
@@ -105,7 +106,17 @@ function FilterTagMultiSelect({
|
||||
};
|
||||
}, [isOpen]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
setSearchQuery("");
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
const selectedTags = tags.filter((tag) => selectedTagIds.includes(tag.id));
|
||||
const normalizedSearch = searchQuery.trim().toLowerCase();
|
||||
const filteredTags = normalizedSearch
|
||||
? tags.filter((tag) => tag.name.toLowerCase().includes(normalizedSearch))
|
||||
: tags;
|
||||
const label = selectedTags.length > 0 ? selectedTags.map((tag) => tag.name).join(" | ") : title;
|
||||
|
||||
return (
|
||||
@@ -127,8 +138,20 @@ function FilterTagMultiSelect({
|
||||
style={dropdownStyle}
|
||||
className="rounded-xl border border-slate-200 bg-white p-2 shadow-xl dark:border-slate-700 dark:bg-slate-900"
|
||||
>
|
||||
<div className="max-h-64 space-y-1 overflow-y-auto">
|
||||
{tags.map((tag) => {
|
||||
<div className="border-b border-slate-200 p-2 dark:border-slate-700">
|
||||
<div className="relative">
|
||||
<Search className="pointer-events-none absolute left-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-slate-400" />
|
||||
<input
|
||||
type="text"
|
||||
value={searchQuery}
|
||||
onChange={(event) => setSearchQuery(event.target.value)}
|
||||
placeholder="Search tags..."
|
||||
className="h-8 w-full rounded-md border border-slate-200 bg-slate-50 pl-8 pr-2 text-xs text-slate-900 outline-none transition focus:border-sky-400 focus:bg-white focus:ring-2 focus:ring-sky-500/20 dark:border-slate-700 dark:bg-slate-800 dark:text-white dark:focus:border-sky-500 dark:focus:bg-slate-800"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="max-h-72 space-y-1 overflow-y-auto p-2">
|
||||
{filteredTags.map((tag) => {
|
||||
const selected = selectedTagIds.includes(tag.id);
|
||||
return (
|
||||
<button
|
||||
@@ -156,6 +179,11 @@ function FilterTagMultiSelect({
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
{filteredTags.length === 0 && (
|
||||
<div className="px-2 py-3 text-xs text-slate-500 dark:text-slate-400">
|
||||
No tags found.
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>,
|
||||
document.body,
|
||||
|
||||
Reference in New Issue
Block a user