diff --git a/packages/desktop-client/src/components/FinancesApp.tsx b/packages/desktop-client/src/components/FinancesApp.tsx index fa50fbe7e3..f61e6f1b1b 100644 --- a/packages/desktop-client/src/components/FinancesApp.tsx +++ b/packages/desktop-client/src/components/FinancesApp.tsx @@ -17,7 +17,6 @@ import { GlobalKeys } from './GlobalKeys'; import { MobileNavTabs } from './mobile/MobileNavTabs'; import { TransactionEdit } from './mobile/transactions/TransactionEdit'; import { Notifications } from './Notifications'; -import { ManagePayeesPage } from './payees/ManagePayeesPage'; import { Reports } from './reports'; import { LoadingIndicator } from './reports/LoadingIndicator'; import { NarrowAlternate, WideComponent } from './responsive'; @@ -267,7 +266,10 @@ export function FinancesApp() { } /> - } /> + } + /> } @@ -346,6 +348,7 @@ export function FinancesApp() { } /> } /> } /> + } /> diff --git a/packages/desktop-client/src/components/mobile/MobileNavTabs.tsx b/packages/desktop-client/src/components/mobile/MobileNavTabs.tsx index 7268e33798..11106bc6ac 100644 --- a/packages/desktop-client/src/components/mobile/MobileNavTabs.tsx +++ b/packages/desktop-client/src/components/mobile/MobileNavTabs.tsx @@ -123,8 +123,8 @@ export function MobileNavTabs() { Icon: SvgCalendar3, }, { - name: t('Payees (Soon)'), - path: '/payees/soon', + name: t('Payees'), + path: '/payees', style: navTabStyle, Icon: SvgStoreFront, }, diff --git a/packages/desktop-client/src/components/mobile/payees/MobilePayeesPage.tsx b/packages/desktop-client/src/components/mobile/payees/MobilePayeesPage.tsx new file mode 100644 index 0000000000..876d81cc78 --- /dev/null +++ b/packages/desktop-client/src/components/mobile/payees/MobilePayeesPage.tsx @@ -0,0 +1,73 @@ +import React, { useCallback, useMemo, useState } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { styles } from '@actual-app/components/styles'; +import { theme } from '@actual-app/components/theme'; +import { View } from '@actual-app/components/view'; + +import { getNormalisedString } from 'loot-core/shared/normalisation'; +import { type PayeeEntity } from 'loot-core/types/models'; + +import { PayeesList } from './PayeesList'; + +import { Search } from '@desktop-client/components/common/Search'; +import { MobilePageHeader, Page } from '@desktop-client/components/Page'; +import { usePayees } from '@desktop-client/hooks/usePayees'; +import { useSelector } from '@desktop-client/redux'; + +export function MobilePayeesPage() { + const { t } = useTranslation(); + const payees = usePayees(); + const [filter, setFilter] = useState(''); + const isLoading = useSelector( + s => s.payees.isPayeesLoading || s.payees.isCommonPayeesLoading, + ); + + const filteredPayees: PayeeEntity[] = useMemo(() => { + if (!filter) return payees; + const norm = getNormalisedString(filter); + return payees.filter(p => getNormalisedString(p.name).includes(norm)); + }, [payees, filter]); + + const onSearchChange = useCallback((value: string) => { + setFilter(value); + }, []); + + const handlePayeePress = useCallback((_payee: PayeeEntity) => { + // Intentionally no-op for now + }, []); + + return ( + } padding={0}> + + + + + + ); +} diff --git a/packages/desktop-client/src/components/mobile/payees/PayeesList.tsx b/packages/desktop-client/src/components/mobile/payees/PayeesList.tsx new file mode 100644 index 0000000000..4d12f5e9ad --- /dev/null +++ b/packages/desktop-client/src/components/mobile/payees/PayeesList.tsx @@ -0,0 +1,86 @@ +import { Trans } from 'react-i18next'; + +import { AnimatedLoading } from '@actual-app/components/icons/AnimatedLoading'; +import { Text } from '@actual-app/components/text'; +import { theme } from '@actual-app/components/theme'; +import { View } from '@actual-app/components/view'; + +import { type PayeeEntity } from 'loot-core/types/models'; + +import { PayeesListItem } from './PayeesListItem'; + +import { MOBILE_NAV_HEIGHT } from '@desktop-client/components/mobile/MobileNavTabs'; + +type PayeesListProps = { + payees: PayeeEntity[]; + isLoading?: boolean; + onPayeePress: (payee: PayeeEntity) => void; +}; + +export function PayeesList({ + payees, + isLoading = false, + onPayeePress, +}: PayeesListProps) { + if (isLoading && payees.length === 0) { + return ( + + + + ); + } + + if (payees.length === 0) { + return ( + + + No payees found. + + + ); + } + + return ( + + {payees.map(payee => ( + onPayeePress(payee)} + /> + ))} + {isLoading && ( + + + + )} + + ); +} diff --git a/packages/desktop-client/src/components/mobile/payees/PayeesListItem.tsx b/packages/desktop-client/src/components/mobile/payees/PayeesListItem.tsx new file mode 100644 index 0000000000..2227a8c6c8 --- /dev/null +++ b/packages/desktop-client/src/components/mobile/payees/PayeesListItem.tsx @@ -0,0 +1,59 @@ +import React from 'react'; + +import { Button } from '@actual-app/components/button'; +import { SvgBookmark } from '@actual-app/components/icons/v1'; +import { theme } from '@actual-app/components/theme'; + +import { type PayeeEntity } from 'loot-core/types/models'; + +type PayeesListItemProps = { + payee: PayeeEntity; + onPress: () => void; +}; + +export function PayeesListItem({ payee, onPress }: PayeesListItemProps) { + return ( + + ); +} diff --git a/packages/desktop-client/src/components/responsive/narrow.ts b/packages/desktop-client/src/components/responsive/narrow.ts index 45c82ae19b..e0b48a0244 100644 --- a/packages/desktop-client/src/components/responsive/narrow.ts +++ b/packages/desktop-client/src/components/responsive/narrow.ts @@ -7,3 +7,4 @@ export { MobileRulesPage as Rules } from '../mobile/rules/MobileRulesPage'; export { MobileRuleEditPage as RuleEdit } from '../mobile/rules/MobileRuleEditPage'; export { CategoryPage as Category } from '../mobile/budget/CategoryPage'; +export { MobilePayeesPage as Payees } from '../mobile/payees/MobilePayeesPage'; diff --git a/packages/desktop-client/src/components/responsive/wide.ts b/packages/desktop-client/src/components/responsive/wide.ts index b95d1f5260..fe7f63f325 100644 --- a/packages/desktop-client/src/components/responsive/wide.ts +++ b/packages/desktop-client/src/components/responsive/wide.ts @@ -9,6 +9,7 @@ export { Account } from '../accounts/Account'; export { ManageRulesPage as Rules } from '../ManageRulesPage'; export { ManageRulesPage as RuleEdit } from '../ManageRulesPage'; +export { ManagePayeesPage as Payees } from '../payees/ManagePayeesPage'; export { UserDirectoryPage } from '../admin/UserDirectory/UserDirectoryPage'; diff --git a/upcoming-release-notes/5767.md b/upcoming-release-notes/5767.md new file mode 100644 index 0000000000..dce46237ce --- /dev/null +++ b/upcoming-release-notes/5767.md @@ -0,0 +1,7 @@ +--- +category: Features +authors: [MatissJanis] +--- + +Create a mobile payees list page with search and filtering capabilities. +