diff --git a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-from-accounts-id-page-1-chromium-linux.png b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-from-accounts-id-page-1-chromium-linux.png index 8b6f637184d..6abd4082738 100644 Binary files a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-from-accounts-id-page-1-chromium-linux.png and b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-from-accounts-id-page-1-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-via-footer-button-1-chromium-linux.png b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-via-footer-button-1-chromium-linux.png index 0cfdffe0d74..e2981f282c6 100644 Binary files a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-via-footer-button-1-chromium-linux.png and b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-via-footer-button-1-chromium-linux.png differ diff --git a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-via-footer-button-2-chromium-linux.png b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-via-footer-button-2-chromium-linux.png index 08644ff8375..65935ac1424 100644 Binary files a/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-via-footer-button-2-chromium-linux.png and b/packages/desktop-client/e2e/mobile.test.js-snapshots/Mobile-creates-a-transaction-via-footer-button-2-chromium-linux.png differ diff --git a/packages/desktop-client/package.json b/packages/desktop-client/package.json index 5bd8879c351..921766ab9e2 100644 --- a/packages/desktop-client/package.json +++ b/packages/desktop-client/package.json @@ -1,6 +1,6 @@ { "name": "@actual-app/web", - "version": "23.10.0", + "version": "23.11.0", "license": "MIT", "files": [ "build" diff --git a/packages/desktop-client/src/components/Titlebar.tsx b/packages/desktop-client/src/components/Titlebar.tsx index bab3123ba3f..587b3c2f2a0 100644 --- a/packages/desktop-client/src/components/Titlebar.tsx +++ b/packages/desktop-client/src/components/Titlebar.tsx @@ -41,15 +41,21 @@ import useSheetValue from './spreadsheet/useSheetValue'; import { ThemeSelector } from './ThemeSelector'; import { Tooltip } from './tooltips'; -export let TitlebarContext = createContext(null); +export type TitlebarContextValue = { + sendEvent: (msg: string) => void; + subscribe: (listener) => () => void; +}; + +export let TitlebarContext = createContext(null); type TitlebarProviderProps = { children?: ReactNode; }; + export function TitlebarProvider({ children }: TitlebarProviderProps) { let listeners = useRef([]); - function sendEvent(msg) { + function sendEvent(msg: string) { listeners.current.forEach(func => func(msg)); } diff --git a/packages/desktop-client/src/components/budget/BalanceWithCarryover.tsx b/packages/desktop-client/src/components/budget/BalanceWithCarryover.tsx index 943a6a69298..4cbdb09f754 100644 --- a/packages/desktop-client/src/components/budget/BalanceWithCarryover.tsx +++ b/packages/desktop-client/src/components/budget/BalanceWithCarryover.tsx @@ -58,7 +58,7 @@ export default function BalanceWithCarryover({ alignSelf: 'center', marginLeft: 2, position: 'absolute', - right: -4, + right: -8, top: 0, bottom: 0, justifyContent: 'center', diff --git a/packages/desktop-client/src/components/budget/BudgetPageHeader.js b/packages/desktop-client/src/components/budget/BudgetPageHeader.tsx similarity index 72% rename from packages/desktop-client/src/components/budget/BudgetPageHeader.js rename to packages/desktop-client/src/components/budget/BudgetPageHeader.tsx index 6f711901168..c5f3576c70b 100644 --- a/packages/desktop-client/src/components/budget/BudgetPageHeader.js +++ b/packages/desktop-client/src/components/budget/BudgetPageHeader.tsx @@ -1,4 +1,4 @@ -import React, { memo } from 'react'; +import React, { type ComponentProps, memo } from 'react'; import * as monthUtils from 'loot-core/src/shared/months'; @@ -7,8 +7,15 @@ import View from '../common/View'; import { MonthPicker } from './MonthPicker'; import { getScrollbarWidth } from './util'; -const BudgetPageHeader = memo( - ({ startMonth, onMonthSelect, numMonths, monthBounds, style }) => { +type BudgetPageHeaderProps = { + startMonth: string; + onMonthSelect: (month: string) => void; + numMonths: number; + monthBounds: ComponentProps['monthBounds']; +}; + +const BudgetPageHeader = memo( + ({ startMonth, onMonthSelect, numMonths, monthBounds }) => { function getValidMonth(month) { let start = monthBounds.start; let end = monthUtils.subMonths(monthBounds.end, numMonths - 1); diff --git a/packages/desktop-client/src/components/budget/DynamicBudgetTable.js b/packages/desktop-client/src/components/budget/DynamicBudgetTable.tsx similarity index 76% rename from packages/desktop-client/src/components/budget/DynamicBudgetTable.js rename to packages/desktop-client/src/components/budget/DynamicBudgetTable.tsx index dbd83c50abe..51ab9df2761 100644 --- a/packages/desktop-client/src/components/budget/DynamicBudgetTable.js +++ b/packages/desktop-client/src/components/budget/DynamicBudgetTable.tsx @@ -1,4 +1,4 @@ -import React, { forwardRef, useEffect } from 'react'; +import React, { forwardRef, useEffect, type ComponentProps } from 'react'; import { useSelector } from 'react-redux'; import AutoSizer from 'react-virtualized-auto-sizer'; @@ -9,7 +9,7 @@ import { useBudgetMonthCount } from './BudgetMonthCountContext'; import BudgetPageHeader from './BudgetPageHeader'; import BudgetTable from './BudgetTable'; -function getNumPossibleMonths(width) { +function getNumPossibleMonths(width: number) { let estimatedTableWidth = width - 200; if (estimatedTableWidth < 500) { @@ -27,7 +27,15 @@ function getNumPossibleMonths(width) { return 6; } -const DynamicBudgetTableInner = forwardRef( +type DynamicBudgetTableInnerProps = { + width: number; + height: number; +} & ComponentProps; + +const DynamicBudgetTableInner = forwardRef< + BudgetTable, + DynamicBudgetTableInnerProps +>( ( { width, @@ -92,17 +100,19 @@ const DynamicBudgetTableInner = forwardRef( }, ); -export default forwardRef((props, ref) => { - return ( - - {({ width, height }) => ( - - )} - - ); -}); +export default forwardRef( + (props, ref) => { + return ( + + {({ width, height }) => ( + + )} + + ); + }, +); diff --git a/packages/desktop-client/src/components/budget/index.js b/packages/desktop-client/src/components/budget/index.tsx similarity index 84% rename from packages/desktop-client/src/components/budget/index.js rename to packages/desktop-client/src/components/budget/index.tsx index 65f984d2a08..dbc3f1bf594 100644 --- a/packages/desktop-client/src/components/budget/index.js +++ b/packages/desktop-client/src/components/budget/index.tsx @@ -7,29 +7,37 @@ import React, { useRef, } from 'react'; import { useSelector } from 'react-redux'; -import { useLocation, useMatch } from 'react-router-dom'; +import { + type NavigateFunction, + type PathMatch, + useLocation, + useMatch, +} from 'react-router-dom'; import { useSpreadsheet } from 'loot-core/src/client/SpreadsheetProvider'; +import { type QueriesState } from 'loot-core/src/client/state-types/queries'; import { send, listen } from 'loot-core/src/platform/client/fetch'; import { addCategory, - updateCategory, moveCategory, moveCategoryGroup, + updateCategory, deleteCategory, addGroup, updateGroup, deleteGroup, } from 'loot-core/src/shared/categories'; import * as monthUtils from 'loot-core/src/shared/months'; +import { type Handlers } from 'loot-core/src/types/handlers'; +import { type GlobalPrefs, type LocalPrefs } from 'loot-core/src/types/prefs'; -import { useActions } from '../../hooks/useActions'; +import { type BoundActions, useActions } from '../../hooks/useActions'; import useCategories from '../../hooks/useCategories'; import useFeatureFlag from '../../hooks/useFeatureFlag'; import useNavigate from '../../hooks/useNavigate'; import { styles } from '../../style'; import View from '../common/View'; -import { TitlebarContext } from '../Titlebar'; +import { TitlebarContext, type TitlebarContextValue } from '../Titlebar'; import DynamicBudgetTable from './DynamicBudgetTable'; import { getValidMonthBounds } from './MonthsContext'; @@ -38,7 +46,56 @@ import { ReportProvider } from './report/ReportContext'; import * as rollover from './rollover/rollover-components'; import { RolloverContext } from './rollover/RolloverContext'; -function Budget(props) { +type ReportComponents = { + SummaryComponent: typeof report.BudgetSummary; + ExpenseCategoryComponent: typeof report.ExpenseCategoryMonth; + ExpenseGroupComponent: typeof report.ExpenseGroupMonth; + IncomeCategoryComponent: typeof report.IncomeCategoryMonth; + IncomeGroupComponent: typeof report.IncomeGroupMonth; + BudgetTotalsComponent: typeof report.BudgetTotalsMonth; + IncomeHeaderComponent: typeof report.IncomeHeaderMonth; +}; + +type RolloverComponents = { + SummaryComponent: typeof RolloverBudgetSummary; + ExpenseCategoryComponent: typeof rollover.ExpenseCategoryMonth; + ExpenseGroupComponent: typeof rollover.ExpenseGroupMonth; + IncomeCategoryComponent: typeof rollover.IncomeCategoryMonth; + IncomeGroupComponent: typeof rollover.IncomeGroupMonth; + BudgetTotalsComponent: typeof rollover.BudgetTotalsMonth; + IncomeHeaderComponent: typeof rollover.IncomeHeaderMonth; +}; + +type BudgetProps = { + accountId?: string; + startMonth: LocalPrefs['budget.startMonth']; + collapsedPrefs: LocalPrefs['budget.collapsed']; + summaryCollapsed: LocalPrefs['budget.summaryCollapsed']; + budgetType: LocalPrefs['budgetType']; + maxMonths: GlobalPrefs['maxMonths']; + categoryGroups: QueriesState['categories']['grouped']; + reportComponents: ReportComponents; + rolloverComponents: RolloverComponents; + titlebar: TitlebarContextValue; + match: PathMatch; + spreadsheet: ReturnType; + navigate: NavigateFunction; + getCategories: BoundActions['getCategories']; + savePrefs: BoundActions['savePrefs']; + createCategory: BoundActions['createCategory']; + updateCategory: BoundActions['updateCategory']; + pushModal: BoundActions['pushModal']; + deleteCategory: BoundActions['deleteCategory']; + createGroup: BoundActions['createGroup']; + updateGroup: BoundActions['updateGroup']; + deleteGroup: BoundActions['deleteGroup']; + applyBudgetAction: BoundActions['applyBudgetAction']; + moveCategory: BoundActions['moveCategory']; + moveCategoryGroup: BoundActions['moveCategoryGroup']; + loadPrefs: BoundActions['loadPrefs']; +}; + +function Budget(props: BudgetProps) { const currentMonth = monthUtils.currentMonth(); const tableRef = useRef(null); @@ -130,7 +187,7 @@ function Budget(props) { const prewarmMonth = async (month, type = null) => { type = type || props.budgetType; - let method = + let method: keyof Handlers = type === 'report' ? 'report-budget-month' : 'rollover-budget-month'; let values = await send(method, { month }); @@ -439,7 +496,7 @@ function Budget(props) { return {table}; } -const RolloverBudgetSummary = memo(props => { +const RolloverBudgetSummary = memo<{ month: string }>(props => { const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled'); return ( ( () => ({ SummaryComponent: report.BudgetSummary, ExpenseCategoryComponent: report.ExpenseCategoryMonth, @@ -483,7 +540,7 @@ export default function BudgetWrapper(props) { [report], ); - let rolloverComponents = useMemo( + let rolloverComponents = useMemo( () => ({ SummaryComponent: RolloverBudgetSummary, ExpenseCategoryComponent: rollover.ExpenseCategoryMonth, diff --git a/packages/desktop-client/src/components/budget/report/components.tsx b/packages/desktop-client/src/components/budget/report/components.tsx index fa491dcd10e..9adab83304c 100644 --- a/packages/desktop-client/src/components/budget/report/components.tsx +++ b/packages/desktop-client/src/components/budget/report/components.tsx @@ -360,6 +360,7 @@ export const CategoryMonth = memo(function CategoryMonth({ {!category.is_income && ( diff --git a/packages/desktop-client/src/components/budget/rollover/HoldTooltip.tsx b/packages/desktop-client/src/components/budget/rollover/HoldTooltip.tsx index 74e1228080f..0399184d59d 100644 --- a/packages/desktop-client/src/components/budget/rollover/HoldTooltip.tsx +++ b/packages/desktop-client/src/components/budget/rollover/HoldTooltip.tsx @@ -29,7 +29,7 @@ export default function HoldTooltip({ onSubmit, onClose }: HoldTooltipProps) { useEffect(() => { (async () => { const node = await spreadsheet.get(sheetName, 'to-budget'); - setAmount(integerToCurrency(Math.max(node.value, 0))); + setAmount(integerToCurrency(Math.max(node.value as number, 0))); })(); }, []); diff --git a/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx b/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx index 06e8a099f4e..76a4d3b83e7 100644 --- a/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx +++ b/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx @@ -51,7 +51,7 @@ export default function TransferTooltip({ (async () => { if (initialAmountName) { const node = await spreadsheet.get(sheetName, initialAmountName); - setAmount(integerToCurrency(Math.max(node.value, 0))); + setAmount(integerToCurrency(Math.max(node.value as number, 0))); } else { setAmount(integerToCurrency(Math.max(initialAmount, 0))); } diff --git a/packages/desktop-client/src/components/budget/rollover/rollover-components.tsx b/packages/desktop-client/src/components/budget/rollover/rollover-components.tsx index b63fa03f651..8be56b0bbf8 100644 --- a/packages/desktop-client/src/components/budget/rollover/rollover-components.tsx +++ b/packages/desktop-client/src/components/budget/rollover/rollover-components.tsx @@ -187,9 +187,10 @@ export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({