diff --git a/packages/desktop-client/src/components/mobile/budget/BudgetTable.jsx b/packages/desktop-client/src/components/mobile/budget/BudgetTable.jsx index e8465eb7439..3a81c34fa7c 100644 --- a/packages/desktop-client/src/components/mobile/budget/BudgetTable.jsx +++ b/packages/desktop-client/src/components/mobile/budget/BudgetTable.jsx @@ -1,44 +1,31 @@ -import React, { memo, useCallback, useRef } from 'react'; +import React from 'react'; import { useTranslation } from 'react-i18next'; import { Button } from '@actual-app/components/button'; -import { Card } from '@actual-app/components/card'; import { Label } from '@actual-app/components/label'; 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 { AutoTextSize } from 'auto-text-size'; import memoizeOne from 'memoize-one'; -import { collapseModals, pushModal } from 'loot-core/client/actions'; import { envelopeBudget, trackingBudget, uncategorizedCount, } from 'loot-core/client/queries'; import * as monthUtils from 'loot-core/shared/months'; -import { groupById, integerToCurrency } from 'loot-core/shared/util'; -import { useCategories } from '../../../hooks/useCategories'; -import { useFeatureFlag } from '../../../hooks/useFeatureFlag'; import { useLocalPref } from '../../../hooks/useLocalPref'; -import { useNavigate } from '../../../hooks/useNavigate'; import { useSyncedPref } from '../../../hooks/useSyncedPref'; -import { useUndo } from '../../../hooks/useUndo'; import { SvgLogo } from '../../../icons/logo'; -import { SvgExpandArrow } from '../../../icons/v0'; import { SvgArrowThinLeft, SvgArrowThinRight, - SvgArrowThickRight, SvgCheveronRight, } from '../../../icons/v1'; import { SvgCalendar, SvgViewShow } from '../../../icons/v2'; -import { useDispatch } from '../../../redux'; import { theme } from '../../../style'; -import { BalanceWithCarryover } from '../../budget/BalanceWithCarryover'; -import { makeAmountGrey, makeBalanceAmountStyle } from '../../budget/util'; import { Link } from '../../common/Link'; import { MobilePageHeader, Page } from '../../Page'; import { PrivacyFilter } from '../../PrivacyFilter'; @@ -49,9 +36,8 @@ import { useSheetValue } from '../../spreadsheet/useSheetValue'; import { MOBILE_NAV_HEIGHT } from '../MobileNavTabs'; import { PullToRefresh } from '../PullToRefresh'; -import { BudgetCell } from './BudgetCell'; +import { ExpenseGroup } from './ExpenseGroup'; import { IncomeGroup } from './IncomeGroup'; -import { ListItem } from './ListItem'; export const PILL_STYLE = { borderRadius: 16, @@ -60,23 +46,23 @@ export const PILL_STYLE = { }; export function getColumnWidth({ - show3Cols, + show3Columns = false, isSidebar = false, offset = 0, } = {}) { - // If show3Cols = 35vw | 20vw | 20vw | 20vw, + // If show3Columns = 35vw | 20vw | 20vw | 20vw, // Else = 45vw | 25vw | 25vw, if (!isSidebar) { - return show3Cols ? `${20 + offset}vw` : `${25 + offset}vw`; + return show3Columns ? `${20 + offset}vw` : `${25 + offset}vw`; } - return show3Cols ? `${35 + offset}vw` : `${45 + offset}vw`; + return show3Columns ? `${35 + offset}vw` : `${45 + offset}vw`; } -function ToBudget({ toBudget, onPress, show3Cols }) { +function ToBudget({ toBudget, onPress, show3Columns }) { const { t } = useTranslation(); const amount = useSheetValue(toBudget); const format = useFormat(); - const sidebarColumnWidth = getColumnWidth({ show3Cols, isSidebar: true }); + const sidebarColumnWidth = getColumnWidth({ show3Columns, isSidebar: true }); return ( - - - {group.categories.map((cat, index) => ( - - ))} - - ); -} - -// eslint-disable-next-line @typescript-eslint/no-unused-vars -function ExpenseCategoryPreview({ name, pending, style }) { - return ( - - {name} - - ); -} - -const ExpenseCategory = memo(function ExpenseCategory({ - type, - category, - isHidden, - goal, - longGoal, - budgeted, - spent, - balance, - carryover, - index, - // gestures, - blank, - style, - month, - onEdit, - onBudgetAction, - show3Cols, - showBudgetedCol, -}) { - const opacity = blank ? 0 : 1; - - const { t } = useTranslation(); - const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled'); - const goalTemp = useSheetValue(goal); - const goalValue = isGoalTemplatesEnabled ? goalTemp : null; - - const [budgetType = 'rollover'] = useSyncedPref('budgetType'); - const modalBudgetType = budgetType === 'rollover' ? 'envelope' : 'tracking'; - const dispatch = useDispatch(); - const { showUndoNotification } = useUndo(); - const { list: categories } = useCategories(); - const categoriesById = groupById(categories); - - const onCarryover = useCallback( - carryover => { - onBudgetAction(month, 'carryover', { - category: category.id, - flag: carryover, - }); - dispatch(collapseModals(`${modalBudgetType}-balance-menu`)); - }, - [modalBudgetType, category.id, dispatch, month, onBudgetAction], - ); - - const catBalance = useSheetValue( - type === 'rollover' - ? envelopeBudget.catBalance(category.id) - : trackingBudget.catBalance(category.id), - ); - const budgetedtmp = useSheetValue(budgeted); - const balancetmp = useSheetValue(balance); - const isLongGoal = useSheetValue(longGoal) === 1; - const budgetedValue = isGoalTemplatesEnabled - ? isLongGoal - ? balancetmp - : budgetedtmp - : null; - - const onTransfer = useCallback(() => { - dispatch( - pushModal('transfer', { - title: category.name, - categoryId: category.id, - month, - amount: catBalance, - onSubmit: (amount, toCategoryId) => { - onBudgetAction(month, 'transfer-category', { - amount, - from: category.id, - to: toCategoryId, - }); - dispatch(collapseModals(`${modalBudgetType}-balance-menu`)); - showUndoNotification({ - message: `Transferred ${integerToCurrency(amount)} from ${category.name} to ${categoriesById[toCategoryId].name}.`, - }); - }, - showToBeBudgeted: true, - }), - ); - }, [ - modalBudgetType, - catBalance, - categoriesById, - category.id, - category.name, - dispatch, - month, - onBudgetAction, - showUndoNotification, - ]); - - const onCover = useCallback(() => { - dispatch( - pushModal('cover', { - title: category.name, - month, - categoryId: category.id, - onSubmit: fromCategoryId => { - onBudgetAction(month, 'cover-overspending', { - to: category.id, - from: fromCategoryId, - }); - dispatch(collapseModals(`${modalBudgetType}-balance-menu`)); - showUndoNotification({ - message: t( - `Covered {{toCategoryName}} overspending from {{fromCategoryName}}.`, - { - toCategoryName: category.name, - fromCategoryName: categoriesById[fromCategoryId].name, - }, - ), - }); - }, - }), - ); - }, [ - modalBudgetType, - categoriesById, - category.id, - category.name, - dispatch, - month, - onBudgetAction, - showUndoNotification, - t, - ]); - - const onOpenBalanceMenu = useCallback(() => { - dispatch( - pushModal(`${modalBudgetType}-balance-menu`, { - categoryId: category.id, - month, - onCarryover, - ...(budgetType === 'rollover' && { onTransfer, onCover }), - }), - ); - }, [ - modalBudgetType, - budgetType, - category.id, - dispatch, - month, - onCarryover, - onCover, - onTransfer, - ]); - - const listItemRef = useRef(); - const format = useFormat(); - const navigate = useNavigate(); - const onShowActivity = useCallback(() => { - navigate(`/categories/${category.id}?month=${month}`); - }, [category.id, month, navigate]); - - const sidebarColumnWidth = getColumnWidth({ show3Cols, isSidebar: true }); - const columnWidth = getColumnWidth({ show3Cols }); - - const content = ( - 0 ? 1 : 0, - opacity: isHidden ? 0.5 : undefined, - ...style, - }} - data-testid="category-row" - innerRef={listItemRef} - > - - - - - - - - - - {({ type, value }) => ( - - )} - - - - ( - - - - )} - > - {({ type, value }) => ( - - )} - - - - - ); - - return {content}; - - // ( - // - // )} - // gestures={gestures} - // > - // { - // let pos = (y - layout.y) / layout.height; - // return pos < 0.5 ? 'top' : 'bottom'; - // }} - // onDrop={(id, type, droppable, status) => - // props.onReorder(id.replace('category:', ''), { - // aroundCategory: { - // id: category.id, - // position: status - // } - // }) - // } - // > - // {() => content} - // - // -}); - -const ExpenseGroupHeader = memo(function ExpenseGroupHeader({ - group, - budgeted, - spent, - balance, - editMode, - onEdit, - blank, - show3Cols, - showBudgetedCol, - collapsed, - onToggleCollapse, - style, -}) { - const opacity = blank ? 0 : 1; - const listItemRef = useRef(); - const format = useFormat(); - const sidebarColumnWidth = getColumnWidth({ - show3Cols, - isSidebar: true, - offset: -3.5, - }); - const columnWidth = getColumnWidth({ show3Cols }); - - const amountStyle = { - width: columnWidth, - fontSize: 12, - fontWeight: '500', - paddingLeft: 5, - textAlign: 'right', - }; - - const content = ( - - - - - - - - - {({ type, value }) => ( - - - - {format(value, type)} - - - - )} - - - - - {({ type, value }) => ( - - - - {format(value, type)} - - - - )} - - - - {({ type, value }) => ( - - - - {format(value, type)} - - - - )} - - - - {/* {editMode && ( - - - - )} */} - - ); - - if (!editMode) { - return content; - } - - return content; - // { - // return 'bottom'; - // }} - // onDrop={(id, type, droppable, status) => - // props.onReorderCategory(id, { inGroup: group.id }) - // } - // > - // {() => content} - // -}); - -const ExpenseGroup = memo(function ExpenseGroup({ - type, - group, - editMode, - onEditGroup, - onEditCategory, - // gestures, - month, - // onReorderCategory, - // onReorderGroup, - onAddCategory, - onBudgetAction, - showBudgetedCol, - show3Cols, - showHiddenCategories, - collapsed, - onToggleCollapse, -}) { - function editable(content) { - if (!editMode) { - return content; - } - - return content; - // ( - // - // )} - // gestures={gestures} - // > - // { - // let pos = (y - layout.y) / layout.height; - // return pos < 0.5 ? 'top' : 'bottom'; - // }} - // onDrop={(id, type, droppable, status) => { - // onReorderGroup(id, group.id, status); - // }} - // > - // {() => content} - // - // - } - - return editable( - - - - {group.categories - .filter( - category => !collapsed && (!category.hidden || showHiddenCategories), - ) - .map((category, index) => { - return ( - - ); - })} - , - ); -}); - function UncategorizedButton() { const count = useSheetValue(uncategorizedCount()); if (count === null || count <= 0) { @@ -1050,21 +243,13 @@ function UncategorizedButton() { } function BudgetGroups({ - type, categoryGroups, onEditGroup, onEditCategory, - editMode, - gestures, month, - onSaveCategory, - onDeleteCategory, - onAddCategory, - onReorderCategory, - onReorderGroup, onBudgetAction, - showBudgetedCol, - show3Cols, + showBudgetedColumn, + show3Columns, showHiddenCategories, }) { const separateGroups = memoizeOne(groups => { @@ -1097,23 +282,15 @@ function BudgetGroups({ return ( ); @@ -1136,21 +313,12 @@ function BudgetGroups({ } export function BudgetTable({ - type, categoryGroups, month, monthBounds, - // editMode, onPrevMonth, onNextMonth, onCurrentMonth, - onSaveGroup, - onDeleteGroup, - onAddCategory, - onSaveCategory, - onDeleteCategory, - onReorderCategory, - onReorderGroup, onShowBudgetSummary, onBudgetAction, onRefresh, @@ -1161,7 +329,7 @@ export function BudgetTable({ }) { const { t } = useTranslation(); const { width } = useResponsive(); - const show3Cols = width >= 360; + const show3Columns = width >= 360; // let editMode = false; // neuter editMode -- sorry, not rewriting drag-n-drop right now @@ -1177,6 +345,8 @@ export function BudgetTable({ 'budget.showHiddenCategories', ); + const [budgetType = 'rollover'] = useSyncedPref('budgetType'); + return ( @@ -1269,8 +429,7 @@ export function BudgetTable({ } function BudgetTableHeader({ - show3Cols, - type, + show3Columns, month, onShowBudgetSummary, showSpentColumn, @@ -1278,13 +437,14 @@ function BudgetTableHeader({ }) { const { t } = useTranslation(); const format = useFormat(); + const [budgetType = 'rollover'] = useSyncedPref('budgetType'); const buttonStyle = { padding: 0, backgroundColor: 'transparent', borderRadius: 'unset', }; - const sidebarColumnWidth = getColumnWidth({ show3Cols, isSidebar: true }); - const columnWidth = getColumnWidth({ show3Cols }); + const sidebarColumnWidth = getColumnWidth({ show3Columns, isSidebar: true }); + const columnWidth = getColumnWidth({ show3Columns }); const amountStyle = { color: theme.formInputText, @@ -1318,17 +478,17 @@ function BudgetTableHeader({ alignItems: 'center', }} > - {type === 'report' ? ( + {budgetType === 'report' ? ( = monthUtils.currentMonth()} onPress={onShowBudgetSummary} - show3Cols={show3Cols} + show3Columns={show3Columns} /> ) : ( )} @@ -1339,10 +499,10 @@ function BudgetTableHeader({ alignItems: 'center', }} > - {(show3Cols || !showSpentColumn) && ( + {(show3Columns || !showSpentColumn) && ( ( + + ); +} + +type ExpenseCategoryCellsProps = { + category: CategoryEntity; + month: string; + onBudgetAction: (month: string, action: string, args: unknown) => void; + show3Columns: boolean; + showBudgetedCol: boolean; + onOpenBalanceMenu: () => void; + onShowActivity: () => void; +}; + +function ExpenseCategoryCells({ + category, + month, + onBudgetAction, + show3Columns, + showBudgetedCol: showBudgetedColumn, + onOpenBalanceMenu, + onShowActivity, +}: ExpenseCategoryCellsProps) { + const { t } = useTranslation(); + const format = useFormat(); + const columnWidth = getColumnWidth({ + show3Columns, + isSidebar: false, + }); + const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled'); + const [budgetType = 'rollover'] = useSyncedPref('budgetType'); + + const goal = + budgetType === 'report' + ? trackingBudget.catGoal(category.id) + : envelopeBudget.catGoal(category.id); + + const longGoal = + budgetType === 'report' + ? trackingBudget.catLongGoal(category.id) + : envelopeBudget.catLongGoal(category.id); + + const budgeted = + budgetType === 'report' + ? trackingBudget.catBudgeted(category.id) + : envelopeBudget.catBudgeted(category.id); + + const spent = + budgetType === 'report' + ? trackingBudget.catSumAmount(category.id) + : envelopeBudget.catSumAmount(category.id); + + const balance = + budgetType === 'report' + ? trackingBudget.catBalance(category.id) + : envelopeBudget.catBalance(category.id); + + const carryover = + budgetType === 'report' + ? trackingBudget.catCarryover(category.id) + : envelopeBudget.catCarryover(category.id); + + const goalTemp = useSheetValue<'envelope-budget' | 'tracking-budget', 'goal'>( + goal, + ); + const goalValue = isGoalTemplatesEnabled ? goalTemp : null; + + const budgetedtmp = useSheetValue< + 'envelope-budget' | 'tracking-budget', + 'budget' + >(budgeted); + const balancetmp = useSheetValue< + 'envelope-budget' | 'tracking-budget', + 'leftover' + >(balance); + const isLongGoal = + useSheetValue<'envelope-budget' | 'tracking-budget', 'long-goal'>( + longGoal, + ) === 1; + const budgetedValue = isGoalTemplatesEnabled + ? isLongGoal + ? balancetmp + : budgetedtmp + : null; + + return ( + + + + + + + binding={spent} + type="financial" + aria-label={t('Spent amount for {{categoryName}} category', { + categoryName: category.name, + })} // Translated aria-label + > + {({ type, value }) => ( + + )} + + + + ( + + + + )} + > + {({ type, value }) => ( + + )} + + + + ); +} + +type ExpenseCategoryListItemProps = ComponentPropsWithoutRef< + typeof ListBoxItem +> & { + month: string; + isHidden: boolean; + style?: CSSProperties; + show3Columns: boolean; + showBudgetedColumn: boolean; + onEdit: (id: CategoryEntity['id']) => void; + onBudgetAction: (month: string, action: string, args: unknown) => void; +}; + +function ExpenseCategoryListItem({ + month, + isHidden, + onEdit, + onBudgetAction, + show3Columns, + showBudgetedColumn: showBudgetedCol, + ...props +}: ExpenseCategoryListItemProps) { + const { value: category } = props; + + const { t } = useTranslation(); + const [budgetType = 'rollover'] = useSyncedPref('budgetType'); + + const modalBudgetType = budgetType === 'rollover' ? 'envelope' : 'tracking'; + const dispatch = useDispatch(); + const { showUndoNotification } = useUndo(); + const { list: categories } = useCategories(); + const categoriesById = groupById(categories); + + const onCarryover = useCallback( + carryover => { + onBudgetAction(month, 'carryover', { + category: category.id, + flag: carryover, + }); + dispatch(collapseModals(`${modalBudgetType}-balance-menu`)); + }, + [modalBudgetType, category.id, dispatch, month, onBudgetAction], + ); + + const catBalance = useSheetValue< + 'envelope-budget' | 'tracking-budget', + 'leftover' + >( + budgetType === 'rollover' + ? envelopeBudget.catBalance(category.id) + : trackingBudget.catBalance(category.id), + ); + + const onTransfer = useCallback(() => { + dispatch( + pushModal('transfer', { + title: category.name, + categoryId: category.id, + month, + amount: catBalance, + onSubmit: (amount, toCategoryId) => { + onBudgetAction(month, 'transfer-category', { + amount, + from: category.id, + to: toCategoryId, + }); + dispatch(collapseModals(`${modalBudgetType}-balance-menu`)); + showUndoNotification({ + message: `Transferred ${integerToCurrency(amount)} from ${category.name} to ${categoriesById[toCategoryId].name}.`, + }); + }, + showToBeBudgeted: true, + }), + ); + }, [ + modalBudgetType, + catBalance, + categoriesById, + category.id, + category.name, + dispatch, + month, + onBudgetAction, + showUndoNotification, + ]); + + const onCover = useCallback(() => { + dispatch( + pushModal('cover', { + title: category.name, + month, + categoryId: category.id, + onSubmit: fromCategoryId => { + onBudgetAction(month, 'cover-overspending', { + to: category.id, + from: fromCategoryId, + }); + dispatch(collapseModals(`${modalBudgetType}-balance-menu`)); + showUndoNotification({ + message: t( + `Covered {{toCategoryName}} overspending from {{fromCategoryName}}.`, + { + toCategoryName: category.name, + fromCategoryName: categoriesById[fromCategoryId].name, + }, + ), + }); + }, + }), + ); + }, [ + modalBudgetType, + categoriesById, + category.id, + category.name, + dispatch, + month, + onBudgetAction, + showUndoNotification, + t, + ]); + + const onOpenBalanceMenu = useCallback(() => { + dispatch( + pushModal(`${modalBudgetType}-balance-menu`, { + categoryId: category.id, + month, + onCarryover, + ...(budgetType === 'rollover' && { onTransfer, onCover }), + }), + ); + }, [ + modalBudgetType, + budgetType, + category.id, + dispatch, + month, + onCarryover, + onCover, + onTransfer, + ]); + + const listItemRef = useRef(null); + const navigate = useNavigate(); + const onShowActivity = useCallback(() => { + navigate(`/categories/${category.id}?month=${month}`); + }, [category.id, month, navigate]); + + if (!category) { + return null; + } + + return ( + + + + + + + ); +} diff --git a/packages/desktop-client/src/components/mobile/budget/ExpenseGroup.tsx b/packages/desktop-client/src/components/mobile/budget/ExpenseGroup.tsx new file mode 100644 index 00000000000..5d1ff705550 --- /dev/null +++ b/packages/desktop-client/src/components/mobile/budget/ExpenseGroup.tsx @@ -0,0 +1,393 @@ +import { useMemo, useRef } from 'react'; + +import { Button } from '@actual-app/components/button'; +import { Card } from '@actual-app/components/card'; +import { type CSSProperties, styles } from '@actual-app/components/styles'; +import { Text } from '@actual-app/components/text'; +import { theme } from '@actual-app/components/theme'; +import { View } from '@actual-app/components/view'; +import { css } from '@emotion/css'; +import { AutoTextSize } from 'auto-text-size'; + +import { envelopeBudget, trackingBudget } from 'loot-core/client/queries'; +import * as monthUtils from 'loot-core/shared/months'; +import { type CategoryGroupEntity } from 'loot-core/types/models'; + +import { useSyncedPref } from '../../../hooks/useSyncedPref'; +import { SvgExpandArrow } from '../../../icons/v0'; +import { SvgCheveronRight } from '../../../icons/v1'; +import { PrivacyFilter } from '../../PrivacyFilter'; +import { CellValue } from '../../spreadsheet/CellValue'; +import { useFormat } from '../../spreadsheet/useFormat'; + +import { getColumnWidth } from './BudgetTable'; +import { ExpenseCategoryList } from './ExpenseCategoryList'; +import { ListItem } from './ListItem'; + +type ExpenseGroupProps = { + group: CategoryGroupEntity; + month: string; + showHiddenCategories: boolean; + onEditGroup: (id: CategoryGroupEntity['id']) => void; + onEditCategory: (id: string) => void; + onBudgetAction: (month: string, action: string, args: unknown) => void; + isCollapsed: boolean; + onToggleCollapse: (id: CategoryGroupEntity['id']) => void; + showBudgetedColumn: boolean; + show3Columns: boolean; +}; + +export function ExpenseGroup({ + group, + onEditGroup, + onEditCategory, + month, + onBudgetAction, + showBudgetedColumn, + show3Columns, + showHiddenCategories, + isCollapsed, + onToggleCollapse, +}: ExpenseGroupProps) { + const categories = useMemo( + () => + isCollapsed + ? [] + : (group.categories?.filter( + category => !category.hidden || showHiddenCategories, + ) ?? []), + [group.categories, isCollapsed, showHiddenCategories], + ); + + return ( + + + + !!category.hidden || group.hidden} + show3Columns={show3Columns} + showBudgetedColumn={showBudgetedColumn} + /> + + ); +} + +type ExpenseGroupHeaderProps = { + group: CategoryGroupEntity; + month: string; + onEdit: (id: CategoryGroupEntity['id']) => void; + isCollapsed: boolean; + onToggleCollapse: (id: CategoryGroupEntity['id']) => void; + show3Columns: boolean; + showBudgetedColumn: boolean; +}; + +function ExpenseGroupHeader({ + group, + month, + onEdit, + show3Columns, + showBudgetedColumn, + isCollapsed, + onToggleCollapse, +}: ExpenseGroupHeaderProps) { + const listItemRef = useRef(null); + + return ( + + + + + ); +} + +// function ExpenseGroupHeader2({ +// group, +// month, +// onEdit, +// isCollapsed, +// onToggleCollapse, +// style, +// }: ExpenseGroupHeaderProps) { +// const listItemRef = useRef(null); + +// return ( +// +// +// +// +// ); +// } + +type ExpenseGroupNameProps = { + group: CategoryGroupEntity; + onEdit: (id: CategoryGroupEntity['id']) => void; + isCollapsed: boolean; + onToggleCollapse?: (id: CategoryGroupEntity['id']) => void; + show3Columns: boolean; +}; + +function ExpenseGroupName({ + group, + onEdit, + isCollapsed, + onToggleCollapse, + show3Columns, +}: ExpenseGroupNameProps) { + const sidebarColumnWidth = getColumnWidth({ + show3Columns, + isSidebar: true, + offset: -3.5, + }); + return ( + + + + + ); +} + +type ExpenseGroupCellsProps = { + group: CategoryGroupEntity; + show3Columns: boolean; + showBudgetedColumn: boolean; +}; + +function ExpenseGroupCells({ + group, + show3Columns, + showBudgetedColumn, +}: ExpenseGroupCellsProps) { + const [budgetType = 'rollover'] = useSyncedPref('budgetType'); + const format = useFormat(); + + const columnWidth = getColumnWidth({ show3Columns }); + + const amountStyle: CSSProperties = { + width: columnWidth, + fontSize: 12, + fontWeight: '500', + paddingLeft: 5, + textAlign: 'right', + }; + + const budgeted = + budgetType === 'report' + ? trackingBudget.groupBudgeted(group.id) + : envelopeBudget.groupBudgeted(group.id); + + const spent = + budgetType === 'report' + ? trackingBudget.groupSumAmount(group.id) + : envelopeBudget.groupSumAmount(group.id); + + const balance = + budgetType === 'report' + ? trackingBudget.groupBalance(group.id) + : envelopeBudget.groupBalance(group.id); + + return ( + + + + binding={budgeted} + type="financial" + > + {({ type, value }) => ( + + + + {format(value, type)} + + + + )} + + + + + binding={spent} + type="financial" + > + {({ type, value }) => ( + + + + {format(value, type)} + + + + )} + + + + binding={balance} + type="financial" + > + {({ type, value }) => ( + + + + {format(value, type)} + + + + )} + + + ); +} diff --git a/packages/desktop-client/src/components/mobile/budget/IncomeCategoryList.tsx b/packages/desktop-client/src/components/mobile/budget/IncomeCategoryList.tsx index c0a627c725d..b2a783f0f27 100644 --- a/packages/desktop-client/src/components/mobile/budget/IncomeCategoryList.tsx +++ b/packages/desktop-client/src/components/mobile/budget/IncomeCategoryList.tsx @@ -151,7 +151,6 @@ type IncomeCategoryNameProps = { function IncomeCategoryName({ category, onEdit }: IncomeCategoryNameProps) { const sidebarColumnWidth = getColumnWidth({ - show3Cols: false, isSidebar: true, offset: -10, }); @@ -317,10 +316,10 @@ function IncomeCategoryListItem({ borderColor: theme.tableBorder, flexDirection: 'row', alignItems: 'center', + justifyContent: 'space-between', paddingLeft: 5, paddingRight: 5, zIndex: 1, - justifyContent: 'space-between', borderBottomWidth: 0.5, borderTopWidth: 0.5, opacity: !!category.hidden ? 0.5 : undefined, diff --git a/packages/desktop-client/src/components/mobile/budget/IncomeGroup.tsx b/packages/desktop-client/src/components/mobile/budget/IncomeGroup.tsx index d98ed5ec973..42199a9b529 100644 --- a/packages/desktop-client/src/components/mobile/budget/IncomeGroup.tsx +++ b/packages/desktop-client/src/components/mobile/budget/IncomeGroup.tsx @@ -158,7 +158,6 @@ function IncomeGroupName({ onToggleCollapse, }: IncomeGroupNameProps) { const sidebarColumnWidth = getColumnWidth({ - show3Cols: false, isSidebar: true, offset: -13.5, }); diff --git a/packages/desktop-client/src/components/mobile/budget/index.tsx b/packages/desktop-client/src/components/mobile/budget/index.tsx index 498da1e1d4b..8fc75c9376b 100644 --- a/packages/desktop-client/src/components/mobile/budget/index.tsx +++ b/packages/desktop-client/src/components/mobile/budget/index.tsx @@ -11,8 +11,6 @@ import { createGroup, deleteCategory, deleteGroup, - moveCategory, - moveCategoryGroup, updateCategory, updateGroup, } from 'loot-core/client/queries/queriesSlice'; @@ -227,52 +225,6 @@ export function Budget() { [categories, dispatch, onSaveCategory], ); - const onReorderCategory = useCallback( - (id, { inGroup, aroundCategory }) => { - let groupId, targetId; - - if (inGroup) { - groupId = inGroup; - } else if (aroundCategory) { - const { id: originalCatId, position } = aroundCategory; - - let catId = originalCatId; - const group = categoryGroups.find(group => - group.categories?.find(cat => cat.id === catId), - ); - - if (position === 'bottom') { - const idx = - group?.categories?.findIndex(cat => cat.id === catId) ?? -1; - catId = group?.categories - ? idx < group.categories.length - 1 - ? group.categories[idx + 1].id - : null - : null; - } - - groupId = group?.id; - targetId = catId; - } - - dispatch(moveCategory({ id, groupId, targetId })); - }, - [categoryGroups, dispatch], - ); - - const onReorderGroup = useCallback( - (id, targetId, position) => { - if (position === 'bottom') { - const idx = categoryGroups.findIndex(group => group.id === targetId); - targetId = - idx < categoryGroups.length - 1 ? categoryGroups[idx + 1].id : null; - } - - dispatch(moveCategoryGroup({ id, targetId })); - }, - [categoryGroups, dispatch], - ); - const onPrevMonth = useCallback(async () => { const month = monthUtils.subMonths(startMonth, 1); await prewarmMonth(budgetType, spreadsheet, month); @@ -500,21 +452,12 @@ export function Budget() { // format changes key={`${numberFormat}${hideFraction}`} categoryGroups={categoryGroups} - type={budgetType} month={startMonth} monthBounds={bounds} - // editMode={editMode} onShowBudgetSummary={onShowBudgetSummary} onPrevMonth={onPrevMonth} onNextMonth={onNextMonth} onCurrentMonth={onCurrentMonth} - onSaveGroup={onSaveGroup} - onDeleteGroup={onDeleteGroup} - onAddCategory={onOpenNewCategoryModal} - onSaveCategory={onSaveCategory} - onDeleteCategory={onDeleteCategory} - onReorderCategory={onReorderCategory} - onReorderGroup={onReorderGroup} onBudgetAction={onBudgetAction} onRefresh={onRefresh} onEditGroup={onOpenCategoryGroupMenuModal}