Skip to content

Commit

Permalink
Category budget modals
Browse files Browse the repository at this point in the history
  • Loading branch information
joel-jeremy committed Mar 24, 2024
1 parent faba272 commit 56ca8bc
Show file tree
Hide file tree
Showing 31 changed files with 609 additions and 154 deletions.
38 changes: 38 additions & 0 deletions packages/desktop-client/src/components/Modals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ import { PayeeAutocompleteModal } from './modals/PayeeAutocompleteModal';
import { PlaidExternalMsg } from './modals/PlaidExternalMsg';
import { ReportBalanceMenuModal } from './modals/ReportBalanceMenuModal';
import { ReportBudgetSummaryModal } from './modals/ReportBudgetSummaryModal';
import { ReportCategoryBudgetMenuModal } from './modals/ReportCategoryBudgetMenuModal';
import { RolloverBalanceMenuModal } from './modals/RolloverBalanceMenuModal';
import { RolloverBudgetSummaryModal } from './modals/RolloverBudgetSummaryModal';
import { RolloverCategoryBudgetMenuModal } from './modals/RolloverCategoryBudgetMenuModal';
import { RolloverToBudgetMenuModal } from './modals/RolloverToBudgetMenuModal';
import { ScheduledTransactionMenuModal } from './modals/ScheduledTransactionMenuModal';
import { SelectLinkedAccounts } from './modals/SelectLinkedAccounts';
Expand Down Expand Up @@ -428,13 +430,49 @@ export function Modals() {
key={name}
modalProps={modalProps}
categoryId={options.categoryId}
month={options.month}
onSave={options.onSave}
onEditNotes={options.onEditNotes}
onDelete={options.onDelete}
onBudgetAction={options.onBudgetAction}
onClose={options.onClose}
/>
);

case 'rollover-category-budget-menu':
return (
<NamespaceContext.Provider
key={name}
value={monthUtils.sheetForMonth(options.month)}
>
<RolloverCategoryBudgetMenuModal
modalProps={modalProps}
categoryId={options.categoryId}
onUpdateBudget={options.onUpdateBudget}
onCopyLastMonthAverage={options.onCopyLastMonthAverage}
onSetMonthsAverage={options.onSetMonthsAverage}
onApplyBudgetTemplate={options.onApplyBudgetTemplate}
/>
</NamespaceContext.Provider>
);

case 'report-category-budget-menu':
return (
<NamespaceContext.Provider
key={name}
value={monthUtils.sheetForMonth(options.month)}
>
<ReportCategoryBudgetMenuModal
modalProps={modalProps}
categoryId={options.categoryId}
onUpdateBudget={options.onUpdateBudget}
onCopyLastMonthAverage={options.onCopyLastMonthAverage}
onSetMonthsAverage={options.onSetMonthsAverage}
onApplyBudgetTemplate={options.onApplyBudgetTemplate}
/>
</NamespaceContext.Provider>
);

case 'category-group-menu':
return (
<CategoryGroupMenuModal
Expand Down
22 changes: 4 additions & 18 deletions packages/desktop-client/src/components/budget/BudgetTable.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import React, { useRef, useState } from 'react';

import * as monthUtils from 'loot-core/src/shared/months';

import { useCategories } from '../../hooks/useCategories';
import { useLocalPref } from '../../hooks/useLocalPref';
import { theme, styles } from '../../style';
Expand Down Expand Up @@ -40,8 +38,8 @@ export function BudgetTable(props) {
);
const [editing, setEditing] = useState(null);

const onEditMonth = (id, monthIndex) => {
setEditing(id ? { id, cell: monthIndex } : null);
const onEditMonth = (id, month) => {
setEditing(id ? { id, cell: month } : null);
};

const onEditName = id => {
Expand Down Expand Up @@ -134,18 +132,6 @@ export function BudgetTable(props) {
}
};

const resolveMonth = monthIndex => {
return monthUtils.addMonths(startMonth, monthIndex);
};

const _onShowActivity = (catId, monthIndex) => {
onShowActivity(catId, resolveMonth(monthIndex));
};

const _onBudgetAction = (monthIndex, type, args) => {
onBudgetAction(resolveMonth(monthIndex), type, args);
};

const onCollapse = collapsedIds => {
setCollapsedPref(collapsedIds);
};
Expand Down Expand Up @@ -244,8 +230,8 @@ export function BudgetTable(props) {
onDeleteGroup={onDeleteGroup}
onReorderCategory={_onReorderCategory}
onReorderGroup={_onReorderGroup}
onBudgetAction={_onBudgetAction}
onShowActivity={_onShowActivity}
onBudgetAction={onBudgetAction}
onShowActivity={onShowActivity}
/>
</View>
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ type ExpenseCategoryProps = {
dragState: DragState<CategoryEntity>;
MonthComponent: ComponentProps<typeof RenderMonths>['component'];
onEditName?: ComponentProps<typeof SidebarCategory>['onEditName'];
onEditMonth?: (id: string, monthIndex: number) => void;
onEditMonth?: (id: string, month: string) => void;
onSave?: ComponentProps<typeof SidebarCategory>['onSave'];
onDelete?: ComponentProps<typeof SidebarCategory>['onDelete'];
onDragChange: OnDragChangeCallback<CategoryEntity>;
onBudgetAction: (idx: number, action: string, arg: unknown) => void;
onShowActivity: (id: string, idx: number) => void;
onBudgetAction: (month: number, action: string, arg: unknown) => void;
onShowActivity: (id: string, month: string) => void;
onReorder: OnDropCallback;
};

Expand Down Expand Up @@ -95,7 +95,7 @@ export function ExpenseCategory({

<RenderMonths
component={MonthComponent}
editingIndex={
editingMonth={
editingCell && editingCell.id === cat.id && editingCell.cell
}
args={{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ type IncomeCategoryProps = {
editingCell: { id: string; cell: string } | null;
MonthComponent: ComponentProps<typeof RenderMonths>['component'];
onEditName: ComponentProps<typeof SidebarCategory>['onEditName'];
onEditMonth?: (id: string, monthIndex: number) => void;
onEditMonth?: (id: string, month: string) => void;
onSave: ComponentProps<typeof SidebarCategory>['onSave'];
onDelete: ComponentProps<typeof SidebarCategory>['onDelete'];
onDragChange: OnDragChangeCallback<CategoryEntity>;
onBudgetAction: (idx: number, action: string, arg: unknown) => void;
onBudgetAction: (month: string, action: string, arg: unknown) => void;
onReorder: OnDropCallback;
onShowActivity: (id: string, idx: number) => void;
onShowActivity: (id: string, month: string) => void;
};

export function IncomeCategory({
Expand Down Expand Up @@ -76,7 +76,7 @@ export function IncomeCategory({
/>
<RenderMonths
component={MonthComponent}
editingIndex={
editingMonth={
editingCell && editingCell.id === cat.id && editingCell.cell
}
args={{
Expand Down
10 changes: 5 additions & 5 deletions packages/desktop-client/src/components/budget/RenderMonths.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@ import { NamespaceContext } from '../spreadsheet/NamespaceContext';
import { MonthsContext } from './MonthsContext';

type RenderMonthsProps = {
component?: ComponentType<{ monthIndex: number; editing: boolean }>;
editingIndex?: string | number;
component?: ComponentType<{ month: string; editing: boolean }>;
editingMonth?: string;
args?: object;
style?: CSSProperties;
};

export function RenderMonths({
component: Component,
editingIndex,
editingMonth,
args,
style,
}: RenderMonthsProps) {
const { months } = useContext(MonthsContext);

return months.map((month, index) => {
const editing = editingIndex === index;
const editing = editingMonth === month;

return (
<NamespaceContext.Provider
Expand All @@ -43,7 +43,7 @@ export function RenderMonths({
...style,
}}
>
<Component monthIndex={index} editing={editing} {...args} />
<Component month={month} editing={editing} {...args} />
</View>
</NamespaceContext.Provider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { reportBudget } from 'loot-core/src/client/queries';
import { Menu } from '../../common/Menu';
import { useSheetValue } from '../../spreadsheet/useSheetValue';

export type BalanceMenuProps = Omit<
type BalanceMenuProps = Omit<
ComponentPropsWithoutRef<typeof Menu>,
'onMenuSelect' | 'items'
> & {
Expand All @@ -28,7 +28,7 @@ export function BalanceMenu({
onCarryover?.(!carryover);
break;
default:
throw new Error(`Unsupported item: ${name}`);
throw new Error(`Unrecognized menu item: ${name}`);
}
}}
items={[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ import { BalanceMenu } from './BalanceMenu';
type BalanceTooltipProps = {
categoryId: string;
tooltip: { close: () => void };
monthIndex: number;
onBudgetAction: (idx: number, action: string, arg: unknown) => void;
month: string;
onBudgetAction: (month: string, action: string, arg: unknown) => void;
onClose?: () => void;
};

export function BalanceTooltip({
categoryId,
tooltip,
monthIndex,
month,
onBudgetAction,
onClose,
...tooltipProps
Expand All @@ -36,7 +36,7 @@ export function BalanceTooltip({
<BalanceMenu
categoryId={categoryId}
onCarryover={carryover => {
onBudgetAction?.(monthIndex, 'carryover', {
onBudgetAction?.(month, 'carryover', {
category: categoryId,
flag: !carryover,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import type React, { ComponentPropsWithoutRef } from 'react';

Check failure on line 1 in packages/desktop-client/src/components/budget/report/CategoryBudgetMenu.tsx

View workflow job for this annotation

GitHub Actions / typecheck

A type-only import can specify a default import or named bindings, but not both.

import { useFeatureFlag } from '../../../hooks/useFeatureFlag';
import { Menu } from '../../common/Menu';

type CategoryBudgetMenuProps = Omit<
ComponentPropsWithoutRef<typeof Menu>,
'onMenuSelect' | 'items'
> & {
onCopyLastMonthAverage: () => void;
onSetMonthsAverage: (numberOfMonths: number) => void;
onApplyBudgetTemplate: () => void;
};
export function CategoryBudgetMenu({
onCopyLastMonthAverage,
onSetMonthsAverage,
onApplyBudgetTemplate,
...props
}: CategoryBudgetMenuProps) {
const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
const onMenuSelect = (name: string) => {
switch (name) {
case 'copy-single-last':
onCopyLastMonthAverage?.();
break;
case 'set-single-3-avg':
onSetMonthsAverage?.(3);
break;
case 'set-single-6-avg':
onSetMonthsAverage?.(6);
break;
case 'set-single-12-avg':
onSetMonthsAverage?.(12);
break;
case 'apply-single-category-template':
onApplyBudgetTemplate?.();
break;
default:
throw new Error(`Unrecognized menu item: ${name}`);
}
};

return (
<Menu
{...props}
onMenuSelect={onMenuSelect}
items={[
{
name: 'copy-single-last',
text: 'Copy last month’s budget',
},
{
name: 'set-single-3-avg',
text: 'Set to 3 month average',
},
{
name: 'set-single-6-avg',
text: 'Set to 6 month average',
},
{
name: 'set-single-12-avg',
text: 'Set to yearly average',
},
...(isGoalTemplatesEnabled
? [
{
name: 'apply-single-category-template',
text: 'Apply budget template',
},
]
: []),
]}
/>
);
}
Loading

0 comments on commit 56ca8bc

Please sign in to comment.