From 0609f47cc386ea9470900b0f6ef8f1a1d5b601d9 Mon Sep 17 00:00:00 2001 From: Neil <55785687+carkom@users.noreply.github.com> Date: Wed, 21 Feb 2024 18:59:05 +0000 Subject: [PATCH] AutoComplete clean-up (#2349) * AutoComplete clean-up * notes * lint fix * fix tests * review fix * type --- .../autocomplete/AccountAutocomplete.tsx | 34 ++---------- .../autocomplete/CategoryAutocomplete.tsx | 40 ++------------ .../autocomplete/FilterAutocomplete.tsx | 34 ++++++++++++ ...dFilterAutocomplete.tsx => FilterList.tsx} | 53 ++++--------------- .../components/autocomplete/ItemHeader.tsx | 26 +++++++++ .../autocomplete/PayeeAutocomplete.tsx | 34 ++---------- .../src/components/modals/EditField.jsx | 10 ++-- .../src/components/util/GenericInput.jsx | 4 +- upcoming-release-notes/2349.md | 6 +++ 9 files changed, 95 insertions(+), 146 deletions(-) create mode 100644 packages/desktop-client/src/components/autocomplete/FilterAutocomplete.tsx rename packages/desktop-client/src/components/autocomplete/{SavedFilterAutocomplete.tsx => FilterList.tsx} (53%) create mode 100644 packages/desktop-client/src/components/autocomplete/ItemHeader.tsx create mode 100644 upcoming-release-notes/2349.md diff --git a/packages/desktop-client/src/components/autocomplete/AccountAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/AccountAutocomplete.tsx index 778480a7d..4610f141e 100644 --- a/packages/desktop-client/src/components/autocomplete/AccountAutocomplete.tsx +++ b/packages/desktop-client/src/components/autocomplete/AccountAutocomplete.tsx @@ -11,6 +11,7 @@ import { type CSSProperties, theme } from '../../style'; import { View } from '../common/View'; import { Autocomplete } from './Autocomplete'; +import { ItemHeader, type ItemHeaderProps } from './ItemHeader'; function AccountList({ items, @@ -71,9 +72,7 @@ function AccountList({ type AccountAutoCompleteProps = { embedded?: boolean; includeClosedAccounts: boolean; - renderAccountItemGroupHeader?: ( - props: AccountItemGroupHeaderProps, - ) => ReactNode; + renderAccountItemGroupHeader?: (props: ItemHeaderProps) => ReactNode; renderAccountItem?: (props: AccountItemProps) => ReactNode; closeOnBlur?: boolean; } & ComponentProps<typeof Autocomplete>; @@ -124,35 +123,10 @@ export function AccountAutocomplete({ ); } -type AccountItemGroupHeaderProps = { - title: string; - style?: CSSProperties; -}; - -export function AccountItemGroupHeader({ - title, - style, - ...props -}: AccountItemGroupHeaderProps) { - return ( - <div - style={{ - color: theme.menuAutoCompleteTextHeader, - padding: '4px 9px', - ...style, - }} - data-testid={`${title}-account-item-group`} - {...props} - > - {title} - </div> - ); -} - function defaultRenderAccountItemGroupHeader( - props: AccountItemGroupHeaderProps, + props: ItemHeaderProps, ): ReactNode { - return <AccountItemGroupHeader {...props} />; + return <ItemHeader {...props} type="account" />; } type AccountItemProps = { diff --git a/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx index bb34a8eea..3716847b6 100644 --- a/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx +++ b/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx @@ -21,6 +21,7 @@ import { Text } from '../common/Text'; import { View } from '../common/View'; import { Autocomplete, defaultFilterSuggestion } from './Autocomplete'; +import { ItemHeader, type ItemHeaderProps } from './ItemHeader'; export type CategoryListProps = { items: Array<CategoryEntity & { group?: CategoryGroupEntity }>; @@ -33,9 +34,7 @@ export type CategoryListProps = { renderSplitTransactionButton?: ( props: SplitTransactionButtonProps, ) => ReactNode; - renderCategoryItemGroupHeader?: ( - props: CategoryItemGroupHeaderProps, - ) => ReactNode; + renderCategoryItemGroupHeader?: (props: ItemHeaderProps) => ReactNode; renderCategoryItem?: (props: CategoryItemProps) => ReactNode; }; function CategoryList({ @@ -103,9 +102,7 @@ type CategoryAutocompleteProps = ComponentProps<typeof Autocomplete> & { renderSplitTransactionButton?: ( props: SplitTransactionButtonProps, ) => ReactNode; - renderCategoryItemGroupHeader?: ( - props: CategoryItemGroupHeaderProps, - ) => ReactNode; + renderCategoryItemGroupHeader?: (props: ItemHeaderProps) => ReactNode; renderCategoryItem?: (props: CategoryItemProps) => ReactNode; }; @@ -177,35 +174,8 @@ export function CategoryAutocomplete({ ); } -type CategoryItemGroupHeaderProps = { - title: string; - style?: CSSProperties; -}; - -export function CategoryItemGroupHeader({ - title, - style, - ...props -}: CategoryItemGroupHeaderProps) { - return ( - <div - style={{ - color: theme.menuAutoCompleteTextHeader, - padding: '4px 9px', - ...style, - }} - data-testid={`${title}-category-item-group`} - {...props} - > - {title} - </div> - ); -} - -function defaultRenderCategoryItemGroupHeader( - props: CategoryItemGroupHeaderProps, -) { - return <CategoryItemGroupHeader {...props} />; +function defaultRenderCategoryItemGroupHeader(props: ItemHeaderProps) { + return <ItemHeader {...props} type="category" />; } type SplitTransactionButtonProps = { diff --git a/packages/desktop-client/src/components/autocomplete/FilterAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/FilterAutocomplete.tsx new file mode 100644 index 000000000..aa51cac18 --- /dev/null +++ b/packages/desktop-client/src/components/autocomplete/FilterAutocomplete.tsx @@ -0,0 +1,34 @@ +import React, { type ComponentProps } from 'react'; + +import { useFilters } from 'loot-core/src/client/data-hooks/filters'; +import { type TransactionFilterEntity } from 'loot-core/types/models/transaction-filter'; + +import { Autocomplete } from './Autocomplete'; +import { FilterList } from './FilterList'; + +export function FilterAutocomplete({ + embedded, + ...props +}: { + embedded?: boolean; +} & ComponentProps<typeof Autocomplete<TransactionFilterEntity>>) { + const filters = useFilters() || []; + + return ( + <Autocomplete + strict={true} + highlightFirst={true} + embedded={embedded} + suggestions={filters} + renderItems={(items, getItemProps, highlightedIndex) => ( + <FilterList + items={items} + getItemProps={getItemProps} + highlightedIndex={highlightedIndex} + embedded={embedded} + /> + )} + {...props} + /> + ); +} diff --git a/packages/desktop-client/src/components/autocomplete/SavedFilterAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/FilterList.tsx similarity index 53% rename from packages/desktop-client/src/components/autocomplete/SavedFilterAutocomplete.tsx rename to packages/desktop-client/src/components/autocomplete/FilterList.tsx index a82ab2b22..7a8350b27 100644 --- a/packages/desktop-client/src/components/autocomplete/SavedFilterAutocomplete.tsx +++ b/packages/desktop-client/src/components/autocomplete/FilterList.tsx @@ -1,26 +1,21 @@ import React, { type ComponentProps } from 'react'; -import { useFilters } from 'loot-core/src/client/data-hooks/filters'; -import { type TransactionFilterEntity } from 'loot-core/src/types/models'; - -import { theme } from '../../style'; +import { theme } from '../../style/theme'; import { View } from '../common/View'; -import { Autocomplete } from './Autocomplete'; +import { ItemHeader } from './ItemHeader'; -type FilterListProps<T> = { - items: T[]; - getItemProps: (arg: { item: T }) => ComponentProps<typeof View>; - highlightedIndex: number; - embedded?: boolean; -}; - -function FilterList<T extends { id: string; name: string }>({ +export function FilterList<T extends { id: string; name: string }>({ items, getItemProps, highlightedIndex, embedded, -}: FilterListProps<T>) { +}: { + items: T[]; + getItemProps: (arg: { item: T }) => ComponentProps<typeof View>; + highlightedIndex: number; + embedded?: boolean; +}) { return ( <View> <View @@ -30,6 +25,7 @@ function FilterList<T extends { id: string; name: string }>({ ...(!embedded && { maxHeight: 175 }), }} > + <ItemHeader title="Saved Filters" type="filter" /> {items.map((item, idx) => { return [ <div @@ -55,32 +51,3 @@ function FilterList<T extends { id: string; name: string }>({ </View> ); } - -type SavedFilterAutocompleteProps = { - embedded?: boolean; -} & ComponentProps<typeof Autocomplete<TransactionFilterEntity>>; - -export function SavedFilterAutocomplete({ - embedded, - ...props -}: SavedFilterAutocompleteProps) { - const filters = useFilters() || []; - - return ( - <Autocomplete - strict={true} - highlightFirst={true} - embedded={embedded} - suggestions={filters} - renderItems={(items, getItemProps, highlightedIndex) => ( - <FilterList - items={items} - getItemProps={getItemProps} - highlightedIndex={highlightedIndex} - embedded={embedded} - /> - )} - {...props} - /> - ); -} diff --git a/packages/desktop-client/src/components/autocomplete/ItemHeader.tsx b/packages/desktop-client/src/components/autocomplete/ItemHeader.tsx new file mode 100644 index 000000000..981c05bec --- /dev/null +++ b/packages/desktop-client/src/components/autocomplete/ItemHeader.tsx @@ -0,0 +1,26 @@ +import React from 'react'; + +import { theme } from '../../style/theme'; +import { type CSSProperties } from '../../style/types'; + +export type ItemHeaderProps = { + title: string; + style?: CSSProperties; + type?: string; +}; + +export function ItemHeader({ title, style, type, ...props }: ItemHeaderProps) { + return ( + <div + style={{ + color: theme.menuAutoCompleteTextHeader, + padding: '4px 9px', + ...style, + }} + data-testid={`${title}-${type}-item-group`} + {...props} + > + {title} + </div> + ); +} diff --git a/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.tsx index 84ee34bfd..5ab2b41ef 100644 --- a/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.tsx +++ b/packages/desktop-client/src/components/autocomplete/PayeeAutocomplete.tsx @@ -32,6 +32,7 @@ import { defaultFilterSuggestion, AutocompleteFooter, } from './Autocomplete'; +import { ItemHeader, type ItemHeaderProps } from './ItemHeader'; function getPayeeSuggestions(payees, focusTransferPayees, accounts) { let activePayees = accounts ? getActivePayees(payees, accounts) : payees; @@ -163,7 +164,7 @@ type PayeeAutocompleteProps = { onSelect?: (value: string) => void; onManagePayees: () => void; renderCreatePayeeButton?: (props: CreatePayeeButtonProps) => ReactNode; - renderPayeeItemGroupHeader?: (props: PayeeItemGroupHeaderProps) => ReactNode; + renderPayeeItemGroupHeader?: (props: ItemHeaderProps) => ReactNode; renderPayeeItem?: (props: PayeeItemProps) => ReactNode; accounts?: AccountEntity[]; payees?: PayeeEntity[]; @@ -422,35 +423,8 @@ function defaultRenderCreatePayeeButton( return <CreatePayeeButton {...props} />; } -type PayeeItemGroupHeaderProps = { - title: string; - style?: CSSProperties; -}; - -export function PayeeItemGroupHeader({ - title, - style, - ...props -}: PayeeItemGroupHeaderProps) { - return ( - <div - style={{ - color: theme.menuAutoCompleteTextHeader, - padding: '4px 9px', - ...style, - }} - data-testid={`${title}-payee-item-group`} - {...props} - > - {title} - </div> - ); -} - -function defaultRenderPayeeItemGroupHeader( - props: PayeeItemGroupHeaderProps, -): ReactNode { - return <PayeeItemGroupHeader {...props} />; +function defaultRenderPayeeItemGroupHeader(props: ItemHeaderProps): ReactNode { + return <ItemHeader {...props} type="payee" />; } type PayeeItemProps = { diff --git a/packages/desktop-client/src/components/modals/EditField.jsx b/packages/desktop-client/src/components/modals/EditField.jsx index 0e2d3f1ff..5b2b4d70b 100644 --- a/packages/desktop-client/src/components/modals/EditField.jsx +++ b/packages/desktop-client/src/components/modals/EditField.jsx @@ -15,18 +15,16 @@ import { useResponsive } from '../../ResponsiveProvider'; import { styles, theme } from '../../style'; import { AccountAutocomplete, - AccountItemGroupHeader, AccountItem, } from '../autocomplete/AccountAutocomplete'; import { CategoryAutocomplete, - CategoryItemGroupHeader, CategoryItem, } from '../autocomplete/CategoryAutocomplete'; +import { ItemHeader } from '../autocomplete/ItemHeader'; import { PayeeAutocomplete, CreatePayeeButton, - PayeeItemGroupHeader, PayeeItem, } from '../autocomplete/PayeeAutocomplete'; import { Input } from '../common/Input'; @@ -118,7 +116,7 @@ export function EditField({ modalProps, name, onSubmit, onClose }) { }} {...(isNarrowWidth && { renderAccountItemGroupHeader: props => ( - <AccountItemGroupHeader + <ItemHeader {...props} style={{ ...styles.largeText, @@ -174,7 +172,7 @@ export function EditField({ modalProps, name, onSubmit, onClose }) { /> ), renderPayeeItemGroupHeader: props => ( - <PayeeItemGroupHeader + <ItemHeader {...props} style={{ ...styles.largeText, @@ -228,7 +226,7 @@ export function EditField({ modalProps, name, onSubmit, onClose }) { }} {...(isNarrowWidth && { renderCategoryItemGroupHeader: props => ( - <CategoryItemGroupHeader + <ItemHeader {...props} style={{ ...styles.largeText, diff --git a/packages/desktop-client/src/components/util/GenericInput.jsx b/packages/desktop-client/src/components/util/GenericInput.jsx index bf2e3c53d..c2e1ec23a 100644 --- a/packages/desktop-client/src/components/util/GenericInput.jsx +++ b/packages/desktop-client/src/components/util/GenericInput.jsx @@ -8,8 +8,8 @@ import { useDateFormat } from '../../hooks/useDateFormat'; import { AccountAutocomplete } from '../autocomplete/AccountAutocomplete'; import { Autocomplete } from '../autocomplete/Autocomplete'; import { CategoryAutocomplete } from '../autocomplete/CategoryAutocomplete'; +import { FilterAutocomplete } from '../autocomplete/FilterAutocomplete'; import { PayeeAutocomplete } from '../autocomplete/PayeeAutocomplete'; -import { SavedFilterAutocomplete } from '../autocomplete/SavedFilterAutocomplete'; import { Input } from '../common/Input'; import { View } from '../common/View'; import { Checkbox } from '../forms'; @@ -98,7 +98,7 @@ export function GenericInput({ switch (field) { case 'saved': content = ( - <SavedFilterAutocomplete + <FilterAutocomplete saved={saved} value={value} multi={multi} diff --git a/upcoming-release-notes/2349.md b/upcoming-release-notes/2349.md new file mode 100644 index 000000000..14be36df5 --- /dev/null +++ b/upcoming-release-notes/2349.md @@ -0,0 +1,6 @@ +--- +category: Maintenance +authors: [carkom] +--- + +Organizing and splitting filters Autocomplete. Splitting out headers function that was duplicated in all autocomplete elements. -- GitLab