diff --git a/packages/desktop-client/src/components/CommandBar.tsx b/packages/desktop-client/src/components/CommandBar.tsx index b7e8e5e563..99fdb2492c 100644 --- a/packages/desktop-client/src/components/CommandBar.tsx +++ b/packages/desktop-client/src/components/CommandBar.tsx @@ -1,5 +1,6 @@ import { type ComponentType, + type ReactNode, type SVGProps, useCallback, useEffect, @@ -22,18 +23,41 @@ import { SvgCalendar3, SvgNotesPaperText, } from '@actual-app/components/icons/v2'; +import { styles } from '@actual-app/components/styles'; +import { Text } from '@actual-app/components/text'; +import { View } from '@actual-app/components/view'; import { css } from '@emotion/css'; import { Command } from 'cmdk'; +import { CellValue, CellValueText } from './spreadsheet/CellValue'; + import { useAccounts } from '@desktop-client/hooks/useAccounts'; import { useMetadataPref } from '@desktop-client/hooks/useMetadataPref'; import { useModalState } from '@desktop-client/hooks/useModalState'; import { useNavigate } from '@desktop-client/hooks/useNavigate'; import { useReports } from '@desktop-client/hooks/useReports'; +import type { + Binding, + SheetFields, + SheetNames, +} from '@desktop-client/spreadsheet'; +import { + accountBalance, + allAccountBalance, + offBudgetAccountBalance, + onBudgetAccountBalance, +} from '@desktop-client/spreadsheet/bindings'; type SearchableItem = { id: string; + /** The name to display and use for searching */ name: string; + /** + * The item content to display. If not provided, {@link SearchableItem.name `name`} will be used. + * + * Meant for complex items that want to display more than just static text. + */ + content?: ReactNode; Icon: ComponentType>; }; @@ -44,6 +68,38 @@ type SearchSection = { onSelect: (item: Pick) => void; }; +function BalanceRow< + SheetName extends SheetNames, + FieldName extends SheetFields, +>({ + label, + binding, +}: { + label: string; + binding: Binding; +}) { + return ( + + {label} + + {props => ( + + )} + + + ); +} + export function CommandBar() { const { t } = useTranslation(); const [open, setOpen] = useState(false); @@ -75,6 +131,12 @@ export function CommandBar() { id: 'accounts', name: t('All Accounts'), path: '/accounts', + content: ( + + label={t('All Accounts')} + binding={allAccountBalance()} + /> + ), Icon: SvgLibrary, }, ], @@ -120,11 +182,7 @@ export function CommandBar() { { key: 'navigation', heading: t('Navigation'), - items: navigationItems.map(({ id, name, Icon }) => ({ - id, - name, - Icon, - })), + items: navigationItems, onSelect: ({ id }) => { const item = navigationItems.find(item => item.id === id); if (!!item) handleNavigate(item.path); @@ -137,15 +195,33 @@ export function CommandBar() { { id: 'onbudget', name: t('On Budget'), + content: ( + + label={t('On Budget')} + binding={onBudgetAccountBalance()} + /> + ), Icon: SvgLibrary, }, { id: 'offbudget', name: t('Off Budget'), + content: ( + + label={t('Off Budget')} + binding={offBudgetAccountBalance()} + /> + ), Icon: SvgLibrary, }, ...accounts.map(account => ({ ...account, + content: ( + + label={account.name} + binding={accountBalance(account.id)} + /> + ), Icon: SvgPiggyBank, })), ], @@ -245,7 +321,7 @@ export function CommandBar() { }, })} > - {section.items.map(({ id, name, Icon }) => ( + {section.items.map(({ id, name, Icon, content }) => ( section.onSelect({ id })} @@ -274,7 +350,7 @@ export function CommandBar() { })} > - {name} + {content || name} ))} diff --git a/upcoming-release-notes/5355.md b/upcoming-release-notes/5355.md new file mode 100644 index 0000000000..33832eb39a --- /dev/null +++ b/upcoming-release-notes/5355.md @@ -0,0 +1,6 @@ +--- +category: Enhancements +authors: [elijaholmos] +--- + +Display account balances in Command Bar