feat: add unaccent support for accent-insensitive search (#1402)

- Add PostgreSQL unaccent and pg_trgm extensions
- Create immutable f_unaccent wrapper function for performance
- Update all search queries to use f_unaccent for accent-insensitive matching
- Add 1MB limit to tsvector content to prevent errors on large documents
- Update full-text search trigger to use f_unaccent
- Fix MultiSelect client-side filtering to show server results properly
This commit is contained in:
Philip Okugbe
2025-07-29 22:47:13 +01:00
committed by GitHub
parent f90c5a636b
commit 5da92a538a
10 changed files with 154 additions and 64 deletions

View File

@ -61,47 +61,26 @@ export function MultiMemberSelect({ onChange }: MultiMemberSelectProps) {
type: "group",
}));
// Function to merge items into groups without duplicates
const mergeItemsIntoGroups = (existingGroups, newItems, groupName) => {
const existingValues = new Set(
existingGroups.flatMap((group) =>
group.items.map((item) => item.value),
),
);
const newItemsFiltered = newItems.filter(
(item) => !existingValues.has(item.value),
);
const updatedGroups = existingGroups.map((group) => {
if (group.group === groupName) {
return { ...group, items: [...group.items, ...newItemsFiltered] };
}
return group;
// Create fresh data structure based on current search results
const newData = [];
if (userItems && userItems.length > 0) {
newData.push({
group: t("Select a user"),
items: userItems,
});
}
if (groupItems && groupItems.length > 0) {
newData.push({
group: t("Select a group"),
items: groupItems,
});
}
// Use spread syntax to avoid mutation
return updatedGroups.some((group) => group.group === groupName)
? updatedGroups
: [...updatedGroups, { group: groupName, items: newItemsFiltered }];
};
// Merge user items into groups
const updatedUserGroups = mergeItemsIntoGroups(
data,
userItems,
t("Select a user"),
);
// Merge group items into groups
const finalData = mergeItemsIntoGroups(
updatedUserGroups,
groupItems,
t("Select a group"),
);
setData(finalData);
setData(newData);
}
}, [suggestion, data]);
}, [suggestion, t]);
return (
<MultiSelect
@ -114,6 +93,7 @@ export function MultiMemberSelect({ onChange }: MultiMemberSelectProps) {
searchable
searchValue={searchValue}
onSearchChange={setSearchValue}
filter={({ options }) => options}
clearable
variant="filled"
onChange={onChange}