Added a util helper to remove accent and case to improve search logic (#14533)
# [WIP] Make Local Search Non-Accent-Sensitive fixes(#14468) --- **Description:** This PR adds accent- and case-insensitive search for the **SettingsWorkspaceMembers** component’s local search. It ensures that searching for names or emails works correctly even if the user types letters without accents. **Implementation:** - Added a helper util: `removeAccentsAndCase(text: string)` - This util: - Normalizes text to NFD form - Removes diacritics (accents) - Converts text to lowercase - Replaced current `.includes(searchFilter)` logic with a normalized comparison: --- ### Video -> [Screencast from 2025-09-16 16-42-50.webm](https://github.com/user-attachments/assets/7035906c-9c5d-414d-81e5-74e53803628a) --- Opening a draft pr for initial strategy review before extending it to other components. --------- Co-authored-by: Félix Malfait <felix@twenty.com> Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
+12
-7
@@ -1,3 +1,5 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
|
||||
import { getFieldMetadataTypeLabel } from '@/object-record/object-filter-dropdown/utils/getFieldMetadataTypeLabel';
|
||||
import { DO_NOT_IMPORT_OPTION_KEY } from '@/spreadsheet-import/constants/DoNotImportOptionKey';
|
||||
@@ -15,11 +17,11 @@ import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||
import styled from '@emotion/styled';
|
||||
import { useLingui } from '@lingui/react/macro';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useState } from 'react';
|
||||
import { IconForbid, IconX, useIcons } from 'twenty-ui/display';
|
||||
import { type SelectOption } from 'twenty-ui/input';
|
||||
import { MenuItemSelect } from 'twenty-ui/navigation';
|
||||
import { type ReadonlyDeep } from 'type-fest';
|
||||
import { normalizeSearchText } from '~/utils/normalizeSearchText';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
max-height: 360px;
|
||||
@@ -54,12 +56,15 @@ export const MatchColumnSelectFieldSelectDropdownContent = ({
|
||||
|
||||
const { availableFieldMetadataItems } = useSpreadsheetImportInternal();
|
||||
|
||||
const filteredAvailableFieldMetadataItems =
|
||||
availableFieldMetadataItems.filter(
|
||||
(field) =>
|
||||
field.label.toLowerCase().includes(searchFilter.toLowerCase()) ||
|
||||
field.name.toLowerCase().includes(searchFilter.toLowerCase()),
|
||||
);
|
||||
const filteredAvailableFieldMetadataItems = useMemo(() => {
|
||||
const searchTerm = normalizeSearchText(searchFilter);
|
||||
return availableFieldMetadataItems.filter((field) => {
|
||||
return (
|
||||
normalizeSearchText(field.label).includes(searchTerm) ||
|
||||
normalizeSearchText(field.name).includes(searchTerm)
|
||||
);
|
||||
});
|
||||
}, [availableFieldMetadataItems, searchFilter]);
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user