{items.map((item, index) => {
- let name = getItemName(item);
+ const name = getItemName(item);
return (
{
+ const defaultGetHighlightedIndex = filteredSuggestions => {
return highlightFirst && filteredSuggestions.length ? 0 : null;
};
- let highlightedIndex = (
+ const highlightedIndex = (
getHighlightedIndex || defaultGetHighlightedIndex
)(filteredSuggestions);
// @ts-expect-error Types say there is no type
@@ -415,7 +415,7 @@ function SingleAutocomplete({
// If not using table behavior, reset the input on blur. Tables
// handle saving the value on blur.
- let value = selectedItem ? getItemId(selectedItem) : null;
+ const value = selectedItem ? getItemId(selectedItem) : null;
resetState(value);
} else {
@@ -423,7 +423,7 @@ function SingleAutocomplete({
}
},
onKeyDown: (e: KeyboardEvent
) => {
- let { onKeyDown } = inputProps || {};
+ const { onKeyDown } = inputProps || {};
// If the dropdown is open, an item is highlighted, and the user
// pressed enter, always capture that and handle it ourselves
@@ -561,15 +561,15 @@ function MultiAutocomplete({
strict,
...props
}: MultiAutocompleteProps) {
- let [focused, setFocused] = useState(false);
- let lastSelectedItems = useRef();
+ const [focused, setFocused] = useState(false);
+ const lastSelectedItems = useRef();
useEffect(() => {
lastSelectedItems.current = selectedItems;
});
function onRemoveItem(id) {
- let items = selectedItems.filter(i => i !== id);
+ const items = selectedItems.filter(i => i !== id);
onSelect(items);
}
diff --git a/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx b/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx
index 1ed1009f978..b8c07ba36db 100644
--- a/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx
+++ b/packages/desktop-client/src/components/autocomplete/CategoryAutocomplete.tsx
@@ -15,6 +15,7 @@ import {
} from 'loot-core/src/types/models';
import Split from '../../icons/v0/Split';
+import { useResponsive } from '../../ResponsiveProvider';
import { type CSSProperties, theme } from '../../style';
import Text from '../common/Text';
import View from '../common/View';
@@ -116,7 +117,7 @@ export default function CategoryAutocomplete({
renderCategoryItem,
...props
}: CategoryAutocompleteProps) {
- let categorySuggestions: Array<
+ const categorySuggestions: Array<
CategoryEntity & { group?: CategoryGroupEntity }
> = useMemo(
() =>
@@ -220,6 +221,7 @@ export function SplitTransactionButton({
style,
...props
}: SplitTransactionButtonProps) {
+ const { isNarrowWidth } = useResponsive();
return (
{
- let type = item.transfer_acct ? 'account' : 'payee';
+ const type = item.transfer_acct ? 'account' : 'payee';
let title;
if (type === 'payee' && lastType !== type) {
title = 'Payees';
} else if (type === 'account' && lastType !== type) {
title = 'Transfer To/From';
}
- let showMoreMessage = idx === items.length - 1 && isFiltered;
+ const showMoreMessage = idx === items.length - 1 && isFiltered;
lastType = type;
return (
@@ -184,20 +185,20 @@ export default function PayeeAutocomplete({
payees,
...props
}: PayeeAutocompleteProps) {
- let cachedPayees = useCachedPayees();
+ const cachedPayees = useCachedPayees();
if (!payees) {
payees = cachedPayees;
}
- let cachedAccounts = useCachedAccounts();
+ const cachedAccounts = useCachedAccounts();
if (!accounts) {
accounts = cachedAccounts;
}
- let [focusTransferPayees, setFocusTransferPayees] = useState(false);
- let [rawPayee, setRawPayee] = useState('');
- let hasPayeeInput = !!rawPayee;
- let payeeSuggestions = useMemo(() => {
+ const [focusTransferPayees, setFocusTransferPayees] = useState(false);
+ const [rawPayee, setRawPayee] = useState('');
+ const hasPayeeInput = !!rawPayee;
+ const payeeSuggestions = useMemo(() => {
const suggestions = getPayeeSuggestions(
payees,
focusTransferPayees,
@@ -210,13 +211,13 @@ export default function PayeeAutocomplete({
return [{ id: 'new', name: '' }, ...suggestions];
}, [payees, focusTransferPayees, accounts, hasPayeeInput]);
- let dispatch = useDispatch();
+ const dispatch = useDispatch();
async function handleSelect(value, rawInputValue) {
if (tableBehavior) {
onSelect?.(makeNew(value, rawInputValue));
} else {
- let create = () => dispatch(createPayee(rawInputValue));
+ const create = () => dispatch(createPayee(rawInputValue));
if (Array.isArray(value)) {
value = await Promise.all(value.map(v => (v === 'new' ? create() : v)));
@@ -278,10 +279,10 @@ export default function PayeeAutocomplete({
});
filtered.sort((p1, p2) => {
- let r1 = p1.name.toLowerCase().startsWith(value.toLowerCase());
- let r2 = p2.name.toLowerCase().startsWith(value.toLowerCase());
- let r1exact = p1.name.toLowerCase() === value.toLowerCase();
- let r2exact = p2.name.toLowerCase() === value.toLowerCase();
+ const r1 = p1.name.toLowerCase().startsWith(value.toLowerCase());
+ const r2 = p2.name.toLowerCase().startsWith(value.toLowerCase());
+ const r1exact = p1.name.toLowerCase() === value.toLowerCase();
+ const r2exact = p2.name.toLowerCase() === value.toLowerCase();
// (maniacal laughter) mwahaHAHAHAHAH
if (p1.id === 'new') {
@@ -305,7 +306,7 @@ export default function PayeeAutocomplete({
}
});
- let isf = filtered.length > 100;
+ const isf = filtered.length > 100;
filtered = filtered.slice(0, 100);
filtered.filtered = isf;
@@ -373,19 +374,21 @@ export function CreatePayeeButton({
style,
...props
}: CreatePayeeButtonProps) {
+ const { isNarrowWidth } = useResponsive();
return (
{
- let items = useMemo(() => {
- let [expenseGroups, incomeGroup] = separateGroups(categoryGroups);
+ const items = useMemo(() => {
+ const [expenseGroups, incomeGroup] = separateGroups(categoryGroups);
let items = Array.prototype.concat.apply(
[],
@@ -53,7 +53,7 @@ const BudgetCategories = memo(
cat => showHiddenCategories || !cat.hidden,
);
- let items = [{ type: 'expense-group', value: { ...group } }];
+ const items = [{ type: 'expense-group', value: { ...group } }];
if (newCategoryForGroup === group.id) {
items.push({ type: 'new-category' });
@@ -103,13 +103,13 @@ const BudgetCategories = memo(
showHiddenCategories,
]);
- let [dragState, setDragState] = useState(null);
- let [savedCollapsed, setSavedCollapsed] = useState(null);
+ const [dragState, setDragState] = useState(null);
+ const [savedCollapsed, setSavedCollapsed] = useState(null);
// TODO: If we turn this into a reducer, we could probably memoize
// each item in the list for better perf
function onDragChange(newDragState) {
- let { state } = newDragState;
+ const { state } = newDragState;
if (state === 'start-preview') {
setDragState({
@@ -283,7 +283,7 @@ const BudgetCategories = memo(
throw new Error('Unknown item type: ' + item.type);
}
- let pos =
+ const pos =
idx === 0 ? 'first' : idx === items.length - 1 ? 'last' : null;
return (
diff --git a/packages/desktop-client/src/components/budget/BudgetMonthCountContext.tsx b/packages/desktop-client/src/components/budget/BudgetMonthCountContext.tsx
index 4a825f4ec20..a69e40fb69f 100644
--- a/packages/desktop-client/src/components/budget/BudgetMonthCountContext.tsx
+++ b/packages/desktop-client/src/components/budget/BudgetMonthCountContext.tsx
@@ -12,7 +12,8 @@ type BudgetMonthCountContextValue = {
setDisplayMax: Dispatch>;
};
-let BudgetMonthCountContext = createContext(null);
+const BudgetMonthCountContext =
+ createContext(null);
type BudgetMonthCountProviderProps = {
children: ReactNode;
@@ -21,7 +22,7 @@ type BudgetMonthCountProviderProps = {
export function BudgetMonthCountProvider({
children,
}: BudgetMonthCountProviderProps) {
- let [displayMax, setDisplayMax] = useState(1);
+ const [displayMax, setDisplayMax] = useState(1);
return (
diff --git a/packages/desktop-client/src/components/budget/BudgetPageHeader.tsx b/packages/desktop-client/src/components/budget/BudgetPageHeader.tsx
index c5f3576c70b..919793bc3f6 100644
--- a/packages/desktop-client/src/components/budget/BudgetPageHeader.tsx
+++ b/packages/desktop-client/src/components/budget/BudgetPageHeader.tsx
@@ -17,8 +17,8 @@ type BudgetPageHeaderProps = {
const BudgetPageHeader = memo(
({ startMonth, onMonthSelect, numMonths, monthBounds }) => {
function getValidMonth(month) {
- let start = monthBounds.start;
- let end = monthUtils.subMonths(monthBounds.end, numMonths - 1);
+ const start = monthBounds.start;
+ const end = monthUtils.subMonths(monthBounds.end, numMonths - 1);
if (month < start) {
return start;
diff --git a/packages/desktop-client/src/components/budget/BudgetSummaries.tsx b/packages/desktop-client/src/components/budget/BudgetSummaries.tsx
index 11dc77f5bc2..1367005cc11 100644
--- a/packages/desktop-client/src/components/budget/BudgetSummaries.tsx
+++ b/packages/desktop-client/src/components/budget/BudgetSummaries.tsx
@@ -25,37 +25,37 @@ type BudgetSummariesProps = {
export default function BudgetSummaries({
SummaryComponent,
}: BudgetSummariesProps) {
- let { months } = useContext(MonthsContext);
+ const { months } = useContext(MonthsContext);
- let [widthState, setWidthState] = useState(0);
- let [styles, spring] = useSpring(() => ({
+ const [widthState, setWidthState] = useState(0);
+ const [styles, spring] = useSpring(() => ({
x: 0,
config: { mass: 3, tension: 600, friction: 80 },
}));
- let containerRef = useResizeObserver(
+ const containerRef = useResizeObserver(
useCallback(rect => {
setWidthState(rect.width);
}, []),
);
- let prevMonth0 = useRef(months[0]);
- let allMonths = [...months];
+ const prevMonth0 = useRef(months[0]);
+ const allMonths = [...months];
allMonths.unshift(subMonths(months[0], 1));
allMonths.push(addMonths(months[months.length - 1], 1));
- let monthWidth = widthState / months.length;
+ const monthWidth = widthState / months.length;
useLayoutEffect(() => {
- let prevMonth = prevMonth0.current;
- let reversed = prevMonth > months[0];
- let offsetX = monthWidth;
+ const prevMonth = prevMonth0.current;
+ const reversed = prevMonth > months[0];
+ const offsetX = monthWidth;
let from = reversed ? -offsetX * 2 : 0;
if (prevMonth !== allMonths[0] && prevMonth !== allMonths[2]) {
from = -offsetX;
}
- let to = -offsetX;
+ const to = -offsetX;
spring.start({ from: { x: from }, x: to });
}, [months[0]]);
diff --git a/packages/desktop-client/src/components/budget/BudgetTable.js b/packages/desktop-client/src/components/budget/BudgetTable.js
index 46568a28847..1059c0633fd 100644
--- a/packages/desktop-client/src/components/budget/BudgetTable.js
+++ b/packages/desktop-client/src/components/budget/BudgetTable.js
@@ -33,16 +33,20 @@ class BudgetTable extends Component {
};
onReorderCategory = (id, dropPos, targetId) => {
- let { categoryGroups } = this.props;
+ const { categoryGroups } = this.props;
- let isGroup = !!categoryGroups.find(g => g.id === targetId);
+ const isGroup = !!categoryGroups.find(g => g.id === targetId);
if (isGroup) {
- let { targetId: groupId } = findSortUp(categoryGroups, dropPos, targetId);
- let group = categoryGroups.find(g => g.id === groupId);
+ const { targetId: groupId } = findSortUp(
+ categoryGroups,
+ dropPos,
+ targetId,
+ );
+ const group = categoryGroups.find(g => g.id === groupId);
if (group) {
- let { categories } = group;
+ const { categories } = group;
this.props.onReorderCategory({
id,
groupId: group.id,
@@ -55,7 +59,7 @@ class BudgetTable extends Component {
} else {
let targetGroup;
- for (let group of categoryGroups) {
+ for (const group of categoryGroups) {
if (group.categories.find(cat => cat.id === targetId)) {
targetGroup = group;
break;
@@ -71,7 +75,7 @@ class BudgetTable extends Component {
};
onReorderGroup = (id, dropPos, targetId) => {
- let { categoryGroups } = this.props;
+ const { categoryGroups } = this.props;
this.props.onReorderGroup({
id,
@@ -80,8 +84,8 @@ class BudgetTable extends Component {
};
moveVertically = dir => {
- let { editing } = this.state;
- let { type, categoryGroups, collapsed } = this.props;
+ const { editing } = this.state;
+ const { type, categoryGroups, collapsed } = this.props;
const flattened = categoryGroups.reduce((all, group) => {
if (collapsed.includes(group.id)) {
@@ -151,12 +155,12 @@ class BudgetTable extends Component {
};
collapseAllCategories = () => {
- let { setCollapsed, categoryGroups } = this.props;
+ const { setCollapsed, categoryGroups } = this.props;
setCollapsed(categoryGroups.map(g => g.id));
};
render() {
- let {
+ const {
type,
categoryGroups,
prewarmStartMonth,
@@ -177,7 +181,7 @@ class BudgetTable extends Component {
onShowNewGroup,
onHideNewGroup,
} = this.props;
- let { editing, draggingState, showHiddenCategories } = this.state;
+ const { editing, draggingState, showHiddenCategories } = this.state;
return (
{
- let prefs = useSelector(state => state.prefs.local);
- let { setDisplayMax } = useBudgetMonthCount();
- let actions = useActions();
+ const prefs = useSelector(state => state.prefs.local);
+ const { setDisplayMax } = useBudgetMonthCount();
+ const actions = useActions();
- let numPossible = getNumPossibleMonths(width);
- let numMonths = Math.min(numPossible, maxMonths);
- let maxWidth = 200 + 500 * numMonths;
+ const numPossible = getNumPossibleMonths(width);
+ const numMonths = Math.min(numPossible, maxMonths);
+ const maxWidth = 200 + 500 * numMonths;
useEffect(() => {
setDisplayMax(numPossible);
diff --git a/packages/desktop-client/src/components/budget/ExpenseCategory.tsx b/packages/desktop-client/src/components/budget/ExpenseCategory.tsx
index af20de7e541..cc131396687 100644
--- a/packages/desktop-client/src/components/budget/ExpenseCategory.tsx
+++ b/packages/desktop-client/src/components/budget/ExpenseCategory.tsx
@@ -52,14 +52,14 @@ function ExpenseCategory({
dragging = true;
}
- let { dragRef } = useDraggable({
+ const { dragRef } = useDraggable({
type: 'category',
onDragChange,
item: cat,
canDrag: editingCell === null,
});
- let { dropRef, dropPos } = useDroppable({
+ const { dropRef, dropPos } = useDroppable({
types: 'category',
id: cat.id,
onDrop: onReorder,
diff --git a/packages/desktop-client/src/components/budget/ExpenseGroup.tsx b/packages/desktop-client/src/components/budget/ExpenseGroup.tsx
index 6104e012545..7c1bfd8983f 100644
--- a/packages/desktop-client/src/components/budget/ExpenseGroup.tsx
+++ b/packages/desktop-client/src/components/budget/ExpenseGroup.tsx
@@ -48,22 +48,22 @@ function ExpenseGroup({
onToggleCollapse,
onShowNewCategory,
}: ExpenseGroupProps) {
- let dragging = dragState && dragState.item === group;
+ const dragging = dragState && dragState.item === group;
- let { dragRef } = useDraggable({
+ const { dragRef } = useDraggable({
type: 'group',
onDragChange,
item: group,
canDrag: editingCell === null,
});
- let { dropRef, dropPos } = useDroppable({
+ const { dropRef, dropPos } = useDroppable({
types: 'group',
id: group.id,
onDrop: onReorderGroup,
});
- let { dropRef: catDropRef, dropPos: catDropPos } = useDroppable({
+ const { dropRef: catDropRef, dropPos: catDropPos } = useDroppable({
types: 'category',
id: group.id,
onDrop: onReorderCategory,
diff --git a/packages/desktop-client/src/components/budget/IncomeCategory.tsx b/packages/desktop-client/src/components/budget/IncomeCategory.tsx
index 110da55231e..0d5625186da 100644
--- a/packages/desktop-client/src/components/budget/IncomeCategory.tsx
+++ b/packages/desktop-client/src/components/budget/IncomeCategory.tsx
@@ -43,14 +43,14 @@ function IncomeCategory({
onReorder,
onShowActivity,
}: IncomeCategoryProps) {
- let { dragRef } = useDraggable({
+ const { dragRef } = useDraggable({
type: 'income-category',
onDragChange,
item: cat,
canDrag: editingCell === null,
});
- let { dropRef, dropPos } = useDroppable({
+ const { dropRef, dropPos } = useDroppable({
types: 'income-category',
id: cat.id,
onDrop: onReorder,
diff --git a/packages/desktop-client/src/components/budget/MobileBudget.js b/packages/desktop-client/src/components/budget/MobileBudget.js
index 4f9e1601c18..8c3e7327c65 100644
--- a/packages/desktop-client/src/components/budget/MobileBudget.js
+++ b/packages/desktop-client/src/components/budget/MobileBudget.js
@@ -41,7 +41,7 @@ class Budget extends Component {
}
async loadCategories() {
- let result = await this.props.getCategories();
+ const result = await this.props.getCategories();
this.setState({ categoryGroups: result.grouped });
}
@@ -63,7 +63,7 @@ class Budget extends Component {
this.setState({ initialized: true });
- let unlisten = listen('sync-event', ({ type, tables }) => {
+ const unlisten = listen('sync-event', ({ type, tables }) => {
if (
type === 'success' &&
(tables.includes('categories') ||
@@ -145,14 +145,14 @@ class Budget extends Component {
};
onDeleteGroup = async groupId => {
- let group = this.state.categoryGroups?.find(g => g.id === groupId);
+ const group = this.state.categoryGroups?.find(g => g.id === groupId);
if (!group) {
return;
}
let mustTransfer = false;
- for (let category of group.categories) {
+ for (const category of group.categories) {
if (await send('must-category-transfer', { id: category.id })) {
mustTransfer = true;
break;
@@ -210,21 +210,22 @@ class Budget extends Component {
};
onReorderCategory = (id, { inGroup, aroundCategory }) => {
- let { categoryGroups } = this.state;
+ const { categoryGroups } = this.state;
let groupId, targetId;
if (inGroup) {
groupId = inGroup;
} else if (aroundCategory) {
- let { id: catId, position } = aroundCategory;
+ const { id: originalCatId, position } = aroundCategory;
- let group = categoryGroups.find(group =>
+ let catId = originalCatId;
+ const group = categoryGroups.find(group =>
group.categories.find(cat => cat.id === catId),
);
if (position === 'bottom') {
- let { categories } = group;
- let idx = categories.findIndex(cat => cat.id === catId);
+ const { categories } = group;
+ const idx = categories.findIndex(cat => cat.id === catId);
catId = idx < categories.length - 1 ? categories[idx + 1].id : null;
}
@@ -240,10 +241,10 @@ class Budget extends Component {
};
onReorderGroup = (id, targetId, position) => {
- let { categoryGroups } = this.state;
+ const { categoryGroups } = this.state;
if (position === 'bottom') {
- let idx = categoryGroups.findIndex(group => group.id === targetId);
+ const idx = categoryGroups.findIndex(group => group.id === targetId);
targetId =
idx < categoryGroups.length - 1 ? categoryGroups[idx + 1].id : null;
}
@@ -266,23 +267,23 @@ class Budget extends Component {
};
onPrevMonth = async () => {
- let { spreadsheet, budgetType } = this.props;
- let month = monthUtils.subMonths(this.state.currentMonth, 1);
+ const { spreadsheet, budgetType } = this.props;
+ const month = monthUtils.subMonths(this.state.currentMonth, 1);
await prewarmMonth(budgetType, spreadsheet, month);
this.setState({ currentMonth: month, initialized: true });
};
onNextMonth = async () => {
- let { spreadsheet, budgetType } = this.props;
- let month = monthUtils.addMonths(this.state.currentMonth, 1);
+ const { spreadsheet, budgetType } = this.props;
+ const month = monthUtils.addMonths(this.state.currentMonth, 1);
await prewarmMonth(budgetType, spreadsheet, month);
this.setState({ currentMonth: month, initialized: true });
};
onOpenActionSheet = () => {
- let { budgetType } = this.props;
+ const { budgetType } = this.props;
- let options = [
+ const options = [
'Edit Categories',
'Copy last month’s budget',
'Set budgets to zero',
@@ -352,8 +353,8 @@ class Budget extends Component {
applyBudgetAction,
pushModal,
} = this.props;
- let numberFormat = prefs.numberFormat || 'comma-dot';
- let hideFraction = prefs.hideFraction || false;
+ const numberFormat = prefs.numberFormat || 'comma-dot';
+ const hideFraction = prefs.hideFraction || false;
if (!categoryGroups || !initialized) {
return (
@@ -414,14 +415,14 @@ class Budget extends Component {
}
export default function BudgetWrapper() {
- let { list: categories, grouped: categoryGroups } = useCategories();
- let budgetType = useSelector(
+ const { list: categories, grouped: categoryGroups } = useCategories();
+ const budgetType = useSelector(
state => state.prefs.local.budgetType || 'rollover',
);
- let prefs = useSelector(state => state.prefs.local);
+ const prefs = useSelector(state => state.prefs.local);
- let actions = useActions();
- let spreadsheet = useSpreadsheet();
+ const actions = useActions();
+ const spreadsheet = useSpreadsheet();
useSetThemeColor(theme.mobileViewTheme);
return (
{
if (isBudgetActionMenuOpen) {
@@ -277,7 +276,7 @@ const ExpenseCategory = memo(function ExpenseCategory({
}
}, [isEditing, tooltip]);
- let onSubmit = () => {
+ const onSubmit = () => {
if (categoryName) {
onSave?.({
...category,
@@ -289,7 +288,7 @@ const ExpenseCategory = memo(function ExpenseCategory({
onEdit?.(null);
};
- let onMenuSelect = type => {
+ const onMenuSelect = type => {
onEdit?.(null);
switch (type) {
case 'toggle-visibility':
@@ -307,10 +306,10 @@ const ExpenseCategory = memo(function ExpenseCategory({
}
};
- let listItemRef = useRef();
- let inputRef = useRef();
+ const listItemRef = useRef();
+ const inputRef = useRef();
- let _onBudgetAction = (monthIndex, action, arg) => {
+ const _onBudgetAction = (monthIndex, action, arg) => {
onBudgetAction?.(
monthUtils.getMonthFromIndex(monthUtils.getYear(month), monthIndex),
action,
@@ -318,7 +317,7 @@ const ExpenseCategory = memo(function ExpenseCategory({
);
};
- let content = (
+ const content = (
{
if (!isEditing && tooltip.isOpen) {
@@ -570,7 +569,7 @@ const ExpenseGroupTotals = memo(function ExpenseGroupTotals({
}
}, [isEditing]);
- let onSubmit = () => {
+ const onSubmit = () => {
if (groupName) {
onSave?.({
...group,
@@ -582,7 +581,7 @@ const ExpenseGroupTotals = memo(function ExpenseGroupTotals({
onEdit?.(null);
};
- let onMenuSelect = type => {
+ const onMenuSelect = type => {
onEdit?.(null);
switch (type) {
case 'add-category':
@@ -603,10 +602,10 @@ const ExpenseGroupTotals = memo(function ExpenseGroupTotals({
}
};
- let listItemRef = useRef();
- let inputRef = useRef();
+ const listItemRef = useRef();
+ const inputRef = useRef();
- let content = (
+ const content = (
{
if (!isEditing && tooltip.isOpen) {
@@ -824,7 +823,7 @@ const IncomeGroupTotals = memo(function IncomeGroupTotals({
}
}, [isEditing]);
- let onSubmit = () => {
+ const onSubmit = () => {
if (groupName) {
onSave?.({
...group,
@@ -836,7 +835,7 @@ const IncomeGroupTotals = memo(function IncomeGroupTotals({
onEdit?.(null);
};
- let onMenuSelect = type => {
+ const onMenuSelect = type => {
onEdit?.(null);
switch (type) {
case 'add-category':
@@ -857,8 +856,8 @@ const IncomeGroupTotals = memo(function IncomeGroupTotals({
}
};
- let listItemRef = useRef();
- let inputRef = useRef();
+ const listItemRef = useRef();
+ const inputRef = useRef();
return (
{
if (!isEditing && tooltip.isOpen) {
@@ -1032,7 +1031,7 @@ const IncomeCategory = memo(function IncomeCategory({
}
}, [isEditing]);
- let onSubmit = () => {
+ const onSubmit = () => {
if (categoryName) {
onSave?.({
...category,
@@ -1044,7 +1043,7 @@ const IncomeCategory = memo(function IncomeCategory({
onEdit?.(null);
};
- let onMenuSelect = type => {
+ const onMenuSelect = type => {
onEdit?.(null);
switch (type) {
case 'toggle-visibility':
@@ -1062,8 +1061,8 @@ const IncomeCategory = memo(function IncomeCategory({
}
};
- let listItemRef = useRef();
- let inputRef = useRef();
+ const listItemRef = useRef();
+ const inputRef = useRef();
return (
= 360;
// let editMode = false; // neuter editMode -- sorry, not rewriting drag-n-drop right now
- let currentMonth = monthUtils.currentMonth();
- let format = useFormat();
+ const format = useFormat();
const mobileShowBudgetedColPref = useSelector(state => {
return state.prefs?.local?.toggleMobileDisplayPref || true;
@@ -1706,7 +1704,7 @@ export function BudgetTable(props) {
return state.prefs?.local?.['budget.showHiddenCategories'] || false;
});
- let [showBudgetedCol, setShowBudgetedCol] = useState(
+ const [showBudgetedCol, setShowBudgetedCol] = useState(
!mobileShowBudgetedColPref &&
!document.cookie.match(/mobileShowBudgetedColPref=true/),
);
@@ -1718,33 +1716,68 @@ export function BudgetTable(props) {
}
}
- let buttonStyle = {
+ const buttonStyle = {
padding: 0,
backgroundColor: 'transparent',
borderRadius: 'unset',
};
+ const _onSwitchBudgetType = () => {
+ pushModal('switch-budget-type', {
+ onSwitch: onSwitchBudgetType,
+ });
+ };
+
+ const onToggleHiddenCategories = () => {
+ savePrefs({
+ 'budget.showHiddenCategories': !showHiddenCategories,
+ });
+ };
+
return (
-
-
+
+ }
+ headerRightContent={
+ !editMode ? (
+
+ ) : (
+
+ )
+ }
+ style={{ flex: 1 }}
+ >
{type === 'report' ? (
= currentMonth}
+ projected={month >= monthUtils.currentMonth()}
onClick={onShowBudgetSummary}
/>
) : (
@@ -1873,308 +1906,222 @@ export function BudgetTable(props) {
/>
-
-
- {!editMode ? (
- // (this.list = el)}
- // keyboardShouldPersistTaps="always"
- // refreshControl={refreshControl}
- // style={{ backgroundColor: colors.n10 }}
- // automaticallyAdjustContentInsets={false}
- // >
-
-
-
- ) : (
- //
- //
- // {({
- // dragging,
- // onGestureEvent,
- // onHandlerStateChange,
- // scrollRef,
- // onScroll
- // }) => (
-
-
-
+
+ {!editMode ? (
+ // (this.list = el)}
+ // keyboardShouldPersistTaps="always"
+ // refreshControl={refreshControl}
+ // style={{ backgroundColor: colors.n10 }}
+ // automaticallyAdjustContentInsets={false}
+ // >
+
+
+
+ ) : (
+ //
+ //
+ // {({
+ // dragging,
+ // onGestureEvent,
+ // onHandlerStateChange,
+ // scrollRef,
+ // onScroll
+ // }) => (
+
+
+
- //
- //
- )}
-
-
-
+ //
+ //
+ )}
+
+
);
}
-const LEFT_RIGHT_FLEX_WIDTH = 80;
-const BUDGET_HEADER_HEIGHT = 50;
-
-function BudgetHeader({
- currentMonth,
- monthBounds,
- onPrevMonth,
- onNextMonth,
- editMode,
+function BudgetMenu({
onEditMode,
- showHiddenCategories,
- savePrefs,
- pushModal,
+ onToggleHiddenCategories,
onSwitchBudgetType,
}) {
- let serverURL = useServerURL();
+ const tooltip = useTooltip();
+ const isReportBudgetEnabled = useFeatureFlag('reportBudget');
- let prevEnabled = currentMonth > monthBounds.start;
- let nextEnabled = currentMonth < monthUtils.subMonths(monthBounds.end, 1);
-
- let buttonStyle = {
- padding: 10,
- margin: 2,
- };
-
- let toggleHiddenCategories = () => {
- savePrefs({
- 'budget.showHiddenCategories': !showHiddenCategories,
- });
- };
-
- let tooltip = useTooltip();
- let isReportBudgetEnabled = useFeatureFlag('reportBudget');
-
- let onMenuSelect = name => {
+ const onMenuSelect = name => {
tooltip.close();
switch (name) {
case 'edit-mode':
onEditMode?.(true);
break;
case 'toggle-hidden-categories':
- toggleHiddenCategories();
+ onToggleHiddenCategories?.();
break;
case 'switch-budget-type':
- pushModal('switch-budget-type', {
- onSwitch: onSwitchBudgetType,
- });
+ onSwitchBudgetType?.();
break;
default:
throw new Error(`Unrecognized menu option: ${name}`);
}
};
+ return (
+ <>
+
+ {tooltip.isOpen && (
+
+
+
+ )}
+ >
+ );
+}
+
+function MonthSelector({ month, monthBounds, onPrevMonth, onNextMonth }) {
+ const prevEnabled = month > monthBounds.start;
+ const nextEnabled = month < monthUtils.subMonths(monthBounds.end, 1);
+
+ const arrowButtonStyle = {
+ padding: 10,
+ margin: 2,
+ };
+
return (
-
- {serverURL && (
-
- )}
-
-
-
+
+
-
-
- {/* eslint-disable-next-line rulesdir/typography */}
- {monthUtils.format(currentMonth, "MMMM ''yy")}
-
-
-
-
+
+
+
);
}
diff --git a/packages/desktop-client/src/components/budget/MonthCountSelector.tsx b/packages/desktop-client/src/components/budget/MonthCountSelector.tsx
index 8a325e18f23..c3509bc20bc 100644
--- a/packages/desktop-client/src/components/budget/MonthCountSelector.tsx
+++ b/packages/desktop-client/src/components/budget/MonthCountSelector.tsx
@@ -29,7 +29,7 @@ export function MonthCountSelector({
maxMonths,
onChange,
}: MonthCountSelectorProps) {
- let { displayMax } = useBudgetMonthCount();
+ const { displayMax } = useBudgetMonthCount();
// It doesn't make sense to show anything if we can only fit one
// month
@@ -37,7 +37,7 @@ export function MonthCountSelector({
return null;
}
- let calendars = [];
+ const calendars = [];
for (let i = 1; i <= displayMax; i++) {
calendars.push(
(null);
+export const MonthsContext = createContext(null);
type MonthsProviderProps = {
startMonth: string | undefined;
@@ -40,9 +40,9 @@ export function MonthsProvider({
type,
children,
}: MonthsProviderProps) {
- let endMonth = monthUtils.addMonths(startMonth, numMonths - 1);
- let bounds = getValidMonthBounds(monthBounds, startMonth, endMonth);
- let months = monthUtils.rangeInclusive(bounds.start, bounds.end);
+ const endMonth = monthUtils.addMonths(startMonth, numMonths - 1);
+ const bounds = getValidMonthBounds(monthBounds, startMonth, endMonth);
+ const months = monthUtils.rangeInclusive(bounds.start, bounds.end);
return (
diff --git a/packages/desktop-client/src/components/budget/RenderMonths.tsx b/packages/desktop-client/src/components/budget/RenderMonths.tsx
index 362ebafcec4..649734d9755 100644
--- a/packages/desktop-client/src/components/budget/RenderMonths.tsx
+++ b/packages/desktop-client/src/components/budget/RenderMonths.tsx
@@ -25,10 +25,10 @@ function RenderMonths({
args,
style,
}: RenderMonthsProps) {
- let { months } = useContext(MonthsContext);
+ const { months } = useContext(MonthsContext);
return months.map((month, index) => {
- let editing = editingIndex === index;
+ const editing = editingIndex === index;
return (
{
- let { titlebar, budgetType } = props;
+ const { titlebar, budgetType } = props;
async function run() {
loadCategories();
- let { start, end } = await send('get-budget-bounds');
+ const { start, end } = await send('get-budget-bounds');
setBounds({ start, end });
await prewarmAllMonths(
@@ -147,7 +147,7 @@ function Budget(props: BudgetProps) {
run();
- let unlistens = [
+ const unlistens = [
listen('sync-event', ({ type, tables }) => {
if (
type === 'success' &&
@@ -255,7 +255,7 @@ function Budget(props: BudgetProps) {
};
const onSaveCategory = async category => {
- let exists =
+ const exists =
(await props.getCategories()).grouped
.filter(g => g.id === category.cat_group)[0]
.categories.filter(
@@ -270,7 +270,7 @@ function Budget(props: BudgetProps) {
}
if (category.id === 'new') {
- let id = await props.createCategory(
+ const id = await props.createCategory(
category.name,
category.cat_group,
category.is_income,
@@ -313,7 +313,7 @@ function Budget(props: BudgetProps) {
const onSaveGroup = async group => {
if (group.id === 'new') {
- let id = await props.createGroup(group.name);
+ const id = await props.createGroup(group.name);
setIsAddingGroup(false);
setCategoryGroups(state =>
addGroup(state, {
@@ -330,10 +330,10 @@ function Budget(props: BudgetProps) {
};
const onDeleteGroup = async id => {
- let group = categoryGroups.find(g => g.id === id);
+ const group = categoryGroups.find(g => g.id === id);
let mustTransfer = false;
- for (let category of group.categories) {
+ for (const category of group.categories) {
if (await send('must-category-transfer', { id: category.id })) {
mustTransfer = true;
break;
@@ -377,9 +377,9 @@ function Budget(props: BudgetProps) {
};
const onReorderCategory = async sortInfo => {
- let cats = await props.getCategories();
- let moveCandidate = cats.list.filter(c => c.id === sortInfo.id)[0];
- let exists =
+ const cats = await props.getCategories();
+ const moveCandidate = cats.list.filter(c => c.id === sortInfo.id)[0];
+ const exists =
cats.grouped
.filter(g => g.id === sortInfo.groupId)[0]
.categories.filter(
@@ -406,7 +406,7 @@ function Budget(props: BudgetProps) {
};
const onToggleCollapse = () => {
- let collapsed = !summaryCollapsed;
+ const collapsed = !summaryCollapsed;
setSummaryCollapsed(collapsed);
props.savePrefs({ 'budget.summaryCollapsed': collapsed });
};
@@ -427,14 +427,14 @@ function Budget(props: BudgetProps) {
}
};
- let {
- maxMonths,
+ const {
+ maxMonths: originalMaxMonths,
budgetType: type,
reportComponents,
rolloverComponents,
} = props;
- maxMonths = maxMonths || 1;
+ const maxMonths = originalMaxMonths || 1;
if (!initialized || !categoryGroups) {
return null;
@@ -532,27 +532,29 @@ const RolloverBudgetSummary = memo<{ month: string }>(props => {
});
export default function BudgetWrapper(props) {
- let startMonth = useSelector(state => state.prefs.local['budget.startMonth']);
- let collapsedPrefs = useSelector(
+ const startMonth = useSelector(
+ state => state.prefs.local['budget.startMonth'],
+ );
+ const collapsedPrefs = useSelector(
state => state.prefs.local['budget.collapsed'],
);
- let summaryCollapsed = useSelector(
+ const summaryCollapsed = useSelector(
state => state.prefs.local['budget.summaryCollapsed'],
);
- let budgetType = useSelector(
+ const budgetType = useSelector(
state => state.prefs.local.budgetType || 'rollover',
);
- let maxMonths = useSelector(state => state.prefs.global.maxMonths);
- let { grouped: categoryGroups } = useCategories();
+ const maxMonths = useSelector(state => state.prefs.global.maxMonths);
+ const { grouped: categoryGroups } = useCategories();
- let actions = useActions();
- let spreadsheet = useSpreadsheet();
- let titlebar = useContext(TitlebarContext);
- let location = useLocation();
- let match = useMatch(location.pathname);
- let navigate = useNavigate();
+ const actions = useActions();
+ const spreadsheet = useSpreadsheet();
+ const titlebar = useContext(TitlebarContext);
+ const location = useLocation();
+ const match = useMatch(location.pathname);
+ const navigate = useNavigate();
- let reportComponents = useMemo(
+ const reportComponents = useMemo(
() => ({
SummaryComponent: report.BudgetSummary,
ExpenseCategoryComponent: report.ExpenseCategoryMonth,
@@ -565,7 +567,7 @@ export default function BudgetWrapper(props) {
[report],
);
- let rolloverComponents = useMemo(
+ const rolloverComponents = useMemo(
() => ({
SummaryComponent: RolloverBudgetSummary,
ExpenseCategoryComponent: rollover.ExpenseCategoryMonth,
diff --git a/packages/desktop-client/src/components/budget/report/BalanceTooltip.tsx b/packages/desktop-client/src/components/budget/report/BalanceTooltip.tsx
index 4d34915a5e3..c1c297518a8 100644
--- a/packages/desktop-client/src/components/budget/report/BalanceTooltip.tsx
+++ b/packages/desktop-client/src/components/budget/report/BalanceTooltip.tsx
@@ -22,9 +22,9 @@ export default function BalanceTooltip({
onClose,
...tooltipProps
}: BalanceTooltipProps) {
- let carryover = useSheetValue(reportBudget.catCarryover(categoryId));
+ const carryover = useSheetValue(reportBudget.catCarryover(categoryId));
- let _onClose = () => {
+ const _onClose = () => {
tooltip.close();
onClose?.();
};
diff --git a/packages/desktop-client/src/components/budget/report/ReportComponents.tsx b/packages/desktop-client/src/components/budget/report/ReportComponents.tsx
index 1d3d03bb8d3..ed38d3bab9d 100644
--- a/packages/desktop-client/src/components/budget/report/ReportComponents.tsx
+++ b/packages/desktop-client/src/components/budget/report/ReportComponents.tsx
@@ -20,7 +20,7 @@ import { makeAmountGrey } from '../util';
import BalanceTooltip from './BalanceTooltip';
-let headerLabelStyle: CSSProperties = {
+const headerLabelStyle: CSSProperties = {
flex: 1,
padding: '0 5px',
textAlign: 'right',
@@ -91,7 +91,7 @@ type GroupMonthProps = {
group: { id: string; is_income: boolean };
};
export const GroupMonth = memo(function GroupMonth({ group }: GroupMonthProps) {
- let { id } = group;
+ const { id } = group;
return (
@@ -156,7 +156,7 @@ export const CategoryMonth = memo(function CategoryMonth({
onBudgetAction,
onShowActivity,
}: CategoryMonthProps) {
- let balanceTooltip = useTooltip();
+ const balanceTooltip = useTooltip();
const [menuOpen, setMenuOpen] = useState(false);
const [hover, setHover] = useState(false);
const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
diff --git a/packages/desktop-client/src/components/budget/report/ReportContext.tsx b/packages/desktop-client/src/components/budget/report/ReportContext.tsx
index fc9927882e7..e38b4da869f 100644
--- a/packages/desktop-client/src/components/budget/report/ReportContext.tsx
+++ b/packages/desktop-client/src/components/budget/report/ReportContext.tsx
@@ -2,7 +2,7 @@ import React, { type ReactNode, createContext, useContext } from 'react';
import * as monthUtils from 'loot-core/src/shared/months';
-let Context = createContext(null);
+const Context = createContext(null);
type ReportProviderProps = {
summaryCollapsed: boolean;
@@ -16,7 +16,7 @@ export function ReportProvider({
onToggleSummaryCollapse,
children,
}: ReportProviderProps) {
- let currentMonth = monthUtils.currentMonth();
+ const currentMonth = monthUtils.currentMonth();
return (
+ >
+ {children}
+
);
}
diff --git a/packages/desktop-client/src/components/budget/report/budgetsummary/BudgetSummary.tsx b/packages/desktop-client/src/components/budget/report/budgetsummary/BudgetSummary.tsx
index d1f726a7ed5..58e18d32a0a 100644
--- a/packages/desktop-client/src/components/budget/report/budgetsummary/BudgetSummary.tsx
+++ b/packages/desktop-client/src/components/budget/report/budgetsummary/BudgetSummary.tsx
@@ -26,7 +26,7 @@ type BudgetSummaryProps = {
month?: string;
};
export default function BudgetSummary({ month }: BudgetSummaryProps) {
- let {
+ const {
currentMonth,
summaryCollapsed: collapsed,
onBudgetAction,
@@ -35,7 +35,7 @@ export default function BudgetSummary({ month }: BudgetSummaryProps) {
const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
- let [menuOpen, setMenuOpen] = useState(false);
+ const [menuOpen, setMenuOpen] = useState(false);
function onMenuOpen() {
setMenuOpen(true);
}
@@ -44,7 +44,7 @@ export default function BudgetSummary({ month }: BudgetSummaryProps) {
setMenuOpen(false);
}
- let ExpandOrCollapseIcon = collapsed ? ArrowButtonDown1 : ArrowButtonUp1;
+ const ExpandOrCollapseIcon = collapsed ? ArrowButtonDown1 : ArrowButtonUp1;
return (
diff --git a/packages/desktop-client/src/components/budget/report/budgetsummary/Saved.tsx b/packages/desktop-client/src/components/budget/report/budgetsummary/Saved.tsx
index 8c8768e3e72..80fbf1b74ac 100644
--- a/packages/desktop-client/src/components/budget/report/budgetsummary/Saved.tsx
+++ b/packages/desktop-client/src/components/budget/report/budgetsummary/Saved.tsx
@@ -20,11 +20,11 @@ type SavedProps = {
style?: CSSProperties;
};
export default function Saved({ projected, style }: SavedProps) {
- let budgetedSaved = useSheetValue(reportBudget.totalBudgetedSaved) || 0;
- let totalSaved = useSheetValue(reportBudget.totalSaved) || 0;
- let format = useFormat();
- let saved = projected ? budgetedSaved : totalSaved;
- let isNegative = saved < 0;
+ const budgetedSaved = useSheetValue(reportBudget.totalBudgetedSaved) || 0;
+ const totalSaved = useSheetValue(reportBudget.totalSaved) || 0;
+ const format = useFormat();
+ const saved = projected ? budgetedSaved : totalSaved;
+ const isNegative = saved < 0;
return (
@@ -39,7 +39,7 @@ export default function Saved({ projected, style }: SavedProps) {
{
if (!projected) {
- let diff = totalSaved - budgetedSaved;
+ const diff = totalSaved - budgetedSaved;
return (
{
+ const _onClose = () => {
tooltip.close();
onClose?.();
};
diff --git a/packages/desktop-client/src/components/budget/rollover/CoverTooltip.tsx b/packages/desktop-client/src/components/budget/rollover/CoverTooltip.tsx
index 9e24fcaf682..2605e5df23b 100644
--- a/packages/desktop-client/src/components/budget/rollover/CoverTooltip.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/CoverTooltip.tsx
@@ -22,7 +22,7 @@ export default function CoverTooltip({
categoryGroups = addToBeBudgetedGroup(
categoryGroups.filter(g => !g.is_income),
);
- let [category, setCategory] = useState(null);
+ const [category, setCategory] = useState(null);
function submit() {
if (category) {
diff --git a/packages/desktop-client/src/components/budget/rollover/RolloverComponents.tsx b/packages/desktop-client/src/components/budget/rollover/RolloverComponents.tsx
index 747770a7d86..e34a1322d2f 100644
--- a/packages/desktop-client/src/components/budget/rollover/RolloverComponents.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/RolloverComponents.tsx
@@ -20,7 +20,7 @@ import { makeAmountGrey } from '../util';
import BalanceTooltip from './BalanceTooltip';
-let headerLabelStyle: CSSProperties = {
+const headerLabelStyle: CSSProperties = {
flex: 1,
padding: '0 5px',
textAlign: 'right',
@@ -89,7 +89,7 @@ type ExpenseGroupMonthProps = {
export const ExpenseGroupMonth = memo(function ExpenseGroupMonth({
group,
}: ExpenseGroupMonthProps) {
- let { id } = group;
+ const { id } = group;
return (
@@ -152,7 +152,7 @@ export const ExpenseCategoryMonth = memo(function ExpenseCategoryMonth({
onBudgetAction,
onShowActivity,
}: ExpenseCategoryMonthProps) {
- let balanceTooltip = useTooltip();
+ const balanceTooltip = useTooltip();
const [menuOpen, setMenuOpen] = useState(false);
const [hover, setHover] = useState(false);
const isGoalTemplatesEnabled = useFeatureFlag('goalTemplatesEnabled');
diff --git a/packages/desktop-client/src/components/budget/rollover/RolloverContext.tsx b/packages/desktop-client/src/components/budget/rollover/RolloverContext.tsx
index 706999c7cbb..3d825c834e2 100644
--- a/packages/desktop-client/src/components/budget/rollover/RolloverContext.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/RolloverContext.tsx
@@ -2,7 +2,7 @@ import React, { type ReactNode, createContext, useContext } from 'react';
import * as monthUtils from 'loot-core/src/shared/months';
-let Context = createContext(null);
+const Context = createContext(null);
type RolloverContextProps = {
categoryGroups: unknown[];
@@ -18,7 +18,7 @@ export function RolloverContext({
onToggleSummaryCollapse,
children,
}: RolloverContextProps) {
- let currentMonth = monthUtils.currentMonth();
+ const currentMonth = monthUtils.currentMonth();
return (
+ >
+ {children}
+
);
}
diff --git a/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx b/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx
index 4aa10527c9e..5e7c382165b 100644
--- a/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/TransferTooltip.tsx
@@ -34,8 +34,8 @@ export default function TransferTooltip({
position = 'bottom-right',
...props
}: TransferTooltipProps) {
- let spreadsheet = useSpreadsheet();
- let sheetName = useContext(NamespaceContext);
+ const spreadsheet = useSpreadsheet();
+ const sheetName = useContext(NamespaceContext);
let { grouped: categoryGroups } = useCategories();
categoryGroups = categoryGroups.filter(g => !g.is_income);
@@ -43,8 +43,8 @@ export default function TransferTooltip({
categoryGroups = addToBeBudgetedGroup(categoryGroups);
}
- let [amount, setAmount] = useState(null);
- let [category, setCategory] = useState(null);
+ const [amount, setAmount] = useState(null);
+ const [category, setCategory] = useState(null);
useEffect(() => {
(async () => {
@@ -58,7 +58,7 @@ export default function TransferTooltip({
}, []);
function submit() {
- let parsedAmount = evalArithmetic(amount, null);
+ const parsedAmount = evalArithmetic(amount, null);
if (parsedAmount && category) {
onSubmit(amountToInteger(parsedAmount), category);
onClose();
diff --git a/packages/desktop-client/src/components/budget/rollover/budgetsummary/BudgetSummary.tsx b/packages/desktop-client/src/components/budget/rollover/budgetsummary/BudgetSummary.tsx
index 5cbf8f57343..0a5c73b9c7a 100644
--- a/packages/desktop-client/src/components/budget/rollover/budgetsummary/BudgetSummary.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/budgetsummary/BudgetSummary.tsx
@@ -27,14 +27,14 @@ export default function BudgetSummary({
month,
isGoalTemplatesEnabled,
}: BudgetSummaryProps) {
- let {
+ const {
currentMonth,
summaryCollapsed: collapsed,
onBudgetAction,
onToggleSummaryCollapse,
} = useRollover();
- let [menuOpen, setMenuOpen] = useState(false);
+ const [menuOpen, setMenuOpen] = useState(false);
function onMenuOpen(e) {
setMenuOpen(true);
}
@@ -43,9 +43,9 @@ export default function BudgetSummary({
setMenuOpen(false);
}
- let prevMonthName = monthUtils.format(monthUtils.prevMonth(month), 'MMM');
+ const prevMonthName = monthUtils.format(monthUtils.prevMonth(month), 'MMM');
- let ExpandOrCollapseIcon = collapsed ? ArrowButtonDown1 : ArrowButtonUp1;
+ const ExpandOrCollapseIcon = collapsed ? ArrowButtonDown1 : ArrowButtonUp1;
return (
diff --git a/packages/desktop-client/src/components/budget/rollover/budgetsummary/TotalsList.tsx b/packages/desktop-client/src/components/budget/rollover/budgetsummary/TotalsList.tsx
index 0805b8bacf0..20a5fd4b9cf 100644
--- a/packages/desktop-client/src/components/budget/rollover/budgetsummary/TotalsList.tsx
+++ b/packages/desktop-client/src/components/budget/rollover/budgetsummary/TotalsList.tsx
@@ -75,7 +75,7 @@ export default function TotalsList({ prevMonthName, style }: TotalsListProps) {
binding={rolloverBudget.lastMonthOverspent}
type="financial"
formatter={value => {
- let v = format(value, 'financial');
+ const v = format(value, 'financial');
return value > 0 ? '+' + v : value === 0 ? '-' + v : v;
}}
style={{ fontWeight: 600, ...styles.tnum }}
@@ -85,7 +85,7 @@ export default function TotalsList({ prevMonthName, style }: TotalsListProps) {
binding={rolloverBudget.totalBudgeted}
type="financial"
formatter={value => {
- let v = format(value, 'financial');
+ const v = format(value, 'financial');
return value > 0 ? '+' + v : value === 0 ? '-' + v : v;
}}
style={{ fontWeight: 600, ...styles.tnum }}
@@ -95,8 +95,8 @@ export default function TotalsList({ prevMonthName, style }: TotalsListProps) {
binding={rolloverBudget.forNextMonth}
type="financial"
formatter={value => {
- let n = parseInt(value) || 0;
- let v = format(Math.abs(n), 'financial');
+ const n = parseInt(value) || 0;
+ const v = format(Math.abs(n), 'financial');
return n >= 0 ? '-' + v : '+' + v;
}}
style={{ fontWeight: 600, ...styles.tnum }}
diff --git a/packages/desktop-client/src/components/budget/util.ts b/packages/desktop-client/src/components/budget/util.ts
index 6e9f7dd1427..b1e7d7d5c24 100644
--- a/packages/desktop-client/src/components/budget/util.ts
+++ b/packages/desktop-client/src/components/budget/util.ts
@@ -85,13 +85,13 @@ export function findSortDown(
if (pos === 'top') {
return { targetId };
} else {
- let idx = arr.findIndex(item => item.id === targetId);
+ const idx = arr.findIndex(item => item.id === targetId);
if (idx === -1) {
throw new Error('findSort: item not found: ' + targetId);
}
- let newIdx = idx + 1;
+ const newIdx = idx + 1;
if (newIdx < arr.length - 1) {
return { targetId: arr[newIdx].id };
} else {
@@ -109,13 +109,13 @@ export function findSortUp(
if (pos === 'bottom') {
return { targetId };
} else {
- let idx = arr.findIndex(item => item.id === targetId);
+ const idx = arr.findIndex(item => item.id === targetId);
if (idx === -1) {
throw new Error('findSort: item not found: ' + targetId);
}
- let newIdx = idx - 1;
+ const newIdx = idx - 1;
if (newIdx >= 0) {
return { targetId: arr[newIdx].id };
} else {
@@ -134,12 +134,12 @@ export async function prewarmMonth(
spreadsheet: ReturnType,
month: string,
) {
- let method: keyof Handlers =
+ const method: keyof Handlers =
budgetType === 'report' ? 'report-budget-month' : 'rollover-budget-month';
- let values = await send(method, { month });
+ const values = await send(method, { month });
- for (let value of values) {
+ for (const value of values) {
spreadsheet.prewarmCache(value.name, value);
}
}
@@ -150,14 +150,14 @@ export async function prewarmAllMonths(
bounds: { start: string; end: string },
startMonth: string,
) {
- let numMonths = 3;
+ const numMonths = 3;
bounds = getValidMonthBounds(
bounds,
monthUtils.subMonths(startMonth, 1),
monthUtils.addMonths(startMonth, numMonths + 1),
);
- let months = monthUtils.rangeInclusive(bounds.start, bounds.end);
+ const months = monthUtils.rangeInclusive(bounds.start, bounds.end);
await Promise.all(
months.map(month => prewarmMonth(budgetType, spreadsheet, month)),
diff --git a/packages/desktop-client/src/components/common/AnchorLink.tsx b/packages/desktop-client/src/components/common/AnchorLink.tsx
index c1ea4749385..2cc6ba3fd01 100644
--- a/packages/desktop-client/src/components/common/AnchorLink.tsx
+++ b/packages/desktop-client/src/components/common/AnchorLink.tsx
@@ -18,7 +18,7 @@ export default function AnchorLink({
activeStyle,
children,
}: AnchorLinkProps) {
- let match = useMatch({ path: to });
+ const match = useMatch({ path: to });
return (
(
},
ref,
) => {
- let typeWithDisabled = disabled ? type + 'Disabled' : type;
+ const typeWithDisabled = disabled ? type + 'Disabled' : type;
hoveredStyle = {
...(type !== 'bare' && styles.shadow),
@@ -163,8 +163,8 @@ const Button = forwardRef(
...activeStyle,
};
- let Component = as;
- let buttonStyle = {
+ const Component = as;
+ const buttonStyle = {
alignItems: 'center',
justifyContent: 'center',
flexShrink: 0,
@@ -211,7 +211,7 @@ export const ButtonWithLoading = forwardRef<
HTMLButtonElement,
ButtonWithLoadingProps
>((props, ref) => {
- let { loading, children, ...buttonProps } = props;
+ const { loading, children, ...buttonProps } = props;
return (
{
if (!disabled) {
diff --git a/packages/desktop-client/src/components/common/InitialFocus.tsx b/packages/desktop-client/src/components/common/InitialFocus.tsx
index 7c6ad0a651e..6f88cbb60f0 100644
--- a/packages/desktop-client/src/components/common/InitialFocus.tsx
+++ b/packages/desktop-client/src/components/common/InitialFocus.tsx
@@ -11,7 +11,7 @@ type InitialFocusProps = {
};
export default function InitialFocus({ children }: InitialFocusProps) {
- let node = useRef(null);
+ const node = useRef(null);
useEffect(() => {
if (node.current && !global.IS_DESIGN_MODE) {
diff --git a/packages/desktop-client/src/components/common/Input.tsx b/packages/desktop-client/src/components/common/Input.tsx
index d5284251426..6a4e6eaf965 100644
--- a/packages/desktop-client/src/components/common/Input.tsx
+++ b/packages/desktop-client/src/components/common/Input.tsx
@@ -37,7 +37,7 @@ export default function Input({
focused,
...nativeProps
}: InputProps) {
- let ref = useRef();
+ const ref = useRef();
useProperFocus(ref, focused);
return (
diff --git a/packages/desktop-client/src/components/common/InputWithContent.tsx b/packages/desktop-client/src/components/common/InputWithContent.tsx
index 6321a7d857c..24b357342a8 100644
--- a/packages/desktop-client/src/components/common/InputWithContent.tsx
+++ b/packages/desktop-client/src/components/common/InputWithContent.tsx
@@ -22,7 +22,7 @@ export default function InputWithContent({
getStyle,
...props
}: InputWithContentProps) {
- let [focused, setFocused] = useState(props.focused);
+ const [focused, setFocused] = useState(props.focused);
return (
x);
- let [hoveredIndex, setHoveredIndex] = useState(null);
+ const elRef = useRef(null);
+ const items = allItems.filter(x => x);
+ const [hoveredIndex, setHoveredIndex] = useState(null);
useEffect(() => {
const el = elRef.current;
el.focus();
- let onKeyDown = e => {
- let filteredItems = items.filter(
+ const onKeyDown = e => {
+ const filteredItems = items.filter(
item => item && item !== Menu.line && item.type !== Menu.label,
);
- let currentIndex = filteredItems.indexOf(items[hoveredIndex]);
+ const currentIndex = filteredItems.indexOf(items[hoveredIndex]);
- let transformIndex = idx => items.indexOf(filteredItems[idx]);
+ const transformIndex = idx => items.indexOf(filteredItems[idx]);
switch (e.key) {
case 'ArrowUp':
@@ -131,7 +131,7 @@ export default function Menu({
);
}
- let lastItem = items[idx - 1];
+ const lastItem = items[idx - 1];
return (
hotkeys.setScope(prevScope);
}, []);
@@ -243,9 +243,9 @@ const ModalContent = ({
stackIndex,
children,
}: ModalContentProps) => {
- let contentRef = useRef(null);
- let mounted = useRef(false);
- let rotateFactor = useRef(Math.random() * 10 - 5);
+ const contentRef = useRef(null);
+ const mounted = useRef(false);
+ const rotateFactor = useRef(Math.random() * 10 - 5);
useLayoutEffect(() => {
if (contentRef.current == null) {
@@ -319,11 +319,11 @@ export const ModalButtons = ({
focusButton = false,
children,
}: ModalButtonsProps) => {
- let containerRef = useRef(null);
+ const containerRef = useRef(null);
useEffect(() => {
if (focusButton && containerRef.current) {
- let button = containerRef.current.querySelector(
+ const button = containerRef.current.querySelector(
'button:not([data-hidden])',
);
diff --git a/packages/desktop-client/src/components/common/Stack.tsx b/packages/desktop-client/src/components/common/Stack.tsx
index a59cf5a9fc3..1a3df4f0f1d 100644
--- a/packages/desktop-client/src/components/common/Stack.tsx
+++ b/packages/desktop-client/src/components/common/Stack.tsx
@@ -66,7 +66,7 @@ const Stack = forwardRef(
{...props}
>
{validChildren.map(({ key, child }, index) => {
- let isLastChild = validChildren.length === index + 1;
+ const isLastChild = validChildren.length === index + 1;
let marginProp;
if (isHorizontal) {
diff --git a/packages/desktop-client/src/components/filters/FiltersMenu.js b/packages/desktop-client/src/components/filters/FiltersMenu.js
index 544c3cedda1..16034382cca 100644
--- a/packages/desktop-client/src/components/filters/FiltersMenu.js
+++ b/packages/desktop-client/src/components/filters/FiltersMenu.js
@@ -21,7 +21,7 @@ import {
FIELD_TYPES,
TYPE_INFO,
} from 'loot-core/src/shared/rules';
-import { titleFirst } from 'loot-core/src/shared/util';
+import { titleFirst, integerToCurrency } from 'loot-core/src/shared/util';
import DeleteIcon from '../../icons/v0/Delete';
import { theme } from '../../style';
@@ -40,7 +40,7 @@ import CompactFiltersButton from './CompactFiltersButton';
import FiltersButton from './FiltersButton';
import { CondOpMenu } from './SavedFilters';
-let filterFields = [
+const filterFields = [
'date',
'account',
'payee',
@@ -119,7 +119,7 @@ function OpButton({ op, selected, style, onClick }) {
function updateFilterReducer(state, action) {
switch (action.type) {
case 'set-op': {
- let type = FIELD_TYPES.get(state.field);
+ const type = FIELD_TYPES.get(state.field);
let value = state.value;
if (
(type === 'id' || type === 'string') &&
@@ -135,7 +135,7 @@ function updateFilterReducer(state, action) {
return { ...state, op: action.op, value };
}
case 'set-value': {
- let { value } = makeValue(action.value, {
+ const { value } = makeValue(action.value, {
type: FIELD_TYPES.get(state.field),
});
return { ...state, value };
@@ -153,9 +153,9 @@ function ConfigureField({
dispatch,
onApply,
}) {
- let [subfield, setSubfield] = useState(initialSubfield);
- let inputRef = useRef();
- let prevOp = useRef(null);
+ const [subfield, setSubfield] = useState(initialSubfield);
+ const inputRef = useRef();
+ const prevOp = useRef(null);
useEffect(() => {
if (prevOp.current !== op && inputRef.current) {
@@ -164,7 +164,7 @@ function ConfigureField({
prevOp.current = op;
}, [op]);
- let type = FIELD_TYPES.get(field);
+ const type = FIELD_TYPES.get(field);
let ops = TYPE_INFO[type].ops.filter(op => op !== 'isbetween');
// Month and year fields are quite hacky right now! Figure out how
@@ -338,23 +338,23 @@ function ConfigureField({
}
export function FilterButton({ onApply, compact, hover }) {
- let filters = useFilters();
+ const filters = useFilters();
- let { dateFormat } = useSelector(state => {
+ const { dateFormat } = useSelector(state => {
return {
dateFormat: state.prefs.local.dateFormat || 'MM/dd/yyyy',
};
});
- let [state, dispatch] = useReducer(
+ const [state, dispatch] = useReducer(
(state, action) => {
switch (action.type) {
case 'select-field':
return { ...state, fieldsOpen: true, condOpen: false };
case 'configure': {
- let { field } = deserializeField(action.field);
- let type = FIELD_TYPES.get(field);
- let ops = TYPE_INFO[type].ops;
+ const { field } = deserializeField(action.field);
+ const type = FIELD_TYPES.get(field);
+ const ops = TYPE_INFO[type].ops;
return {
...state,
fieldsOpen: false,
@@ -378,7 +378,7 @@ export function FilterButton({ onApply, compact, hover }) {
if (cond.type === 'date' && cond.options) {
if (cond.options.month) {
- let date = parseDate(
+ const date = parseDate(
cond.value,
getMonthYearFormat(dateFormat),
new Date(),
@@ -390,7 +390,7 @@ export function FilterButton({ onApply, compact, hover }) {
return;
}
} else if (cond.options.year) {
- let date = parseDate(cond.value, 'yyyy', new Date());
+ const date = parseDate(cond.value, 'yyyy', new Date());
if (isDateValid(date)) {
cond.value = formatDate(date, 'yyyy');
} else {
@@ -400,17 +400,17 @@ export function FilterButton({ onApply, compact, hover }) {
}
}
- let { error } =
+ const { error } =
cond.field !== 'saved' &&
(await send('rule-validate', {
conditions: [cond],
actions: [],
}));
- let saved = filters.find(f => cond.value === f.id);
+ const saved = filters.find(f => cond.value === f.id);
if (error && error.conditionErrors.length > 0) {
- let field = titleFirst(mapField(cond.field));
+ const field = titleFirst(mapField(cond.field));
alert(field + ': ' + getFieldError(error.conditionErrors[0]));
} else {
onApply(saved ? saved : cond);
@@ -478,7 +478,7 @@ export function FilterButton({ onApply, compact, hover }) {
}
function FilterEditor({ field, op, value, options, onSave, onClose }) {
- let [state, dispatch] = useReducer(
+ const [state, dispatch] = useReducer(
(state, action) => {
switch (action.type) {
case 'close':
@@ -500,6 +500,7 @@ function FilterEditor({ field, op, value, options, onSave, onClose }) {
options={state.options}
dispatch={dispatch}
onApply={cond => {
+ cond = unparse({ ...cond, type: FIELD_TYPES.get(cond.field) });
onSave(cond);
onClose();
}}
@@ -518,9 +519,9 @@ function FilterExpression({
onChange,
onDelete,
}) {
- let [editing, setEditing] = useState(false);
+ const [editing, setEditing] = useState(false);
- let field = subfieldFromFilter({ field: originalField, value });
+ const field = subfieldFromFilter({ field: originalField, value });
return (
{
if (inputRef.current) {
@@ -130,13 +130,13 @@ function SavedFilterMenuButton({
onReloadSavedFilter,
filtersList,
}) {
- let [nameOpen, setNameOpen] = useState(false);
- let [adding, setAdding] = useState(false);
- let [menuOpen, setMenuOpen] = useState(false);
- let [err, setErr] = useState(null);
- let [menuItem, setMenuItem] = useState(null);
- let [name, setName] = useState(filterId.name);
- let id = filterId.id;
+ const [nameOpen, setNameOpen] = useState(false);
+ const [adding, setAdding] = useState(false);
+ const [menuOpen, setMenuOpen] = useState(false);
+ const [err, setErr] = useState(null);
+ const [menuItem, setMenuItem] = useState(null);
+ const [name, setName] = useState(filterId.name);
+ const id = filterId.id;
let res;
let savedFilter;
diff --git a/packages/desktop-client/src/components/manager/BudgetList.js b/packages/desktop-client/src/components/manager/BudgetList.js
index 0f57c29f954..0d702504f38 100644
--- a/packages/desktop-client/src/components/manager/BudgetList.js
+++ b/packages/desktop-client/src/components/manager/BudgetList.js
@@ -51,13 +51,13 @@ function FileMenu({ onDelete, onClose }) {
}
}
- let items = [{ name: 'delete', text: 'Delete' }];
+ const items = [{ name: 'delete', text: 'Delete' }];
return ;
}
function DetailButton({ state, onDelete }) {
- let [menuOpen, setMenuOpen] = useState(false);
+ const [menuOpen, setMenuOpen] = useState(false);
return (
@@ -137,7 +137,7 @@ function FileState({ file }) {
}
function File({ file, onSelect, onDelete }) {
- let selecting = useRef(false);
+ const selecting = useRef(false);
async function _onSelect(file) {
// Never allow selecting the file while uploading/downloading, and
@@ -223,7 +223,7 @@ function BudgetTable({ files, onSelect, onDelete }) {
}
function RefreshButton({ onRefresh }) {
- let [loading, setLoading] = useState(false);
+ const [loading, setLoading] = useState(false);
async function _onRefresh() {
setLoading(true);
@@ -231,7 +231,7 @@ function RefreshButton({ onRefresh }) {
setLoading(false);
}
- let Icon = loading ? Loading : RefreshArrow;
+ const Icon = loading ? Loading : RefreshArrow;
return (
state.budgets.allFiles || []);
+ const files = useSelector(state => state.budgets.allFiles || []);
- let {
+ const {
getUserData,
loadAllFiles,
pushModal,
diff --git a/packages/desktop-client/src/components/manager/ConfigServer.tsx b/packages/desktop-client/src/components/manager/ConfigServer.tsx
index cda664eb51a..20cf42356f7 100644
--- a/packages/desktop-client/src/components/manager/ConfigServer.tsx
+++ b/packages/desktop-client/src/components/manager/ConfigServer.tsx
@@ -19,16 +19,16 @@ import { Title } from './subscribe/common';
export default function ConfigServer() {
useSetThemeColor(theme.mobileConfigServerViewTheme);
- let { createBudget, signOut, loggedIn } = useActions();
- let navigate = useNavigate();
- let [url, setUrl] = useState('');
- let currentUrl = useServerURL();
- let setServerUrl = useSetServerURL();
+ const { createBudget, signOut, loggedIn } = useActions();
+ const navigate = useNavigate();
+ const [url, setUrl] = useState('');
+ const currentUrl = useServerURL();
+ const setServerUrl = useSetServerURL();
useEffect(() => {
setUrl(currentUrl);
}, [currentUrl]);
- let [loading, setLoading] = useState(false);
- let [error, setError] = useState(null);
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(null);
function getErrorMessage(error: string) {
switch (error) {
@@ -46,14 +46,14 @@ export default function ConfigServer() {
setError(null);
setLoading(true);
- let { error } = await setServerUrl(url);
+ const { error } = await setServerUrl(url);
if (
['network-failure', 'get-server-failure'].includes(error) &&
!url.startsWith('http://') &&
!url.startsWith('https://')
) {
- let { error } = await setServerUrl('https://' + url);
+ const { error } = await setServerUrl('https://' + url);
if (error) {
setUrl('https://' + url);
setError(error);
diff --git a/packages/desktop-client/src/components/manager/DeleteFile.js b/packages/desktop-client/src/components/manager/DeleteFile.js
index 28eb1dc3fa5..a801fa346af 100644
--- a/packages/desktop-client/src/components/manager/DeleteFile.js
+++ b/packages/desktop-client/src/components/manager/DeleteFile.js
@@ -7,7 +7,7 @@ import Text from '../common/Text';
import View from '../common/View';
export default function DeleteMenu({ modalProps, actions, file }) {
- let [loadingState, setLoadingState] = useState(null);
+ const [loadingState, setLoadingState] = useState(null);
async function onDeleteCloud() {
setLoadingState('cloud');
@@ -28,7 +28,7 @@ export default function DeleteMenu({ modalProps, actions, file }) {
// If the state is "broken" that means it was created by another
// user. The current user should be able to delete the local file,
// but not the remote one
- let isRemote = file.cloudFileId && file.state !== 'broken';
+ const isRemote = file.cloudFileId && file.state !== 'broken';
return (
state.budgets.allFiles);
- let userData = useSelector(state => state.user.data);
- let managerHasInitialized = useSelector(
+ const files = useSelector(state => state.budgets.allFiles);
+ const userData = useSelector(state => state.user.data);
+ const managerHasInitialized = useSelector(
state => state.app.managerHasInitialized,
);
- let { setAppState, getUserData, loadAllFiles } = useActions();
+ const { setAppState, getUserData, loadAllFiles } = useActions();
// runs on mount only
useEffect(() => {
@@ -74,7 +74,7 @@ export default function ManagementApp({ isLoading }) {
}
async function fetchData() {
- let userData = await getUserData();
+ const userData = await getUserData();
if (userData) {
await loadAllFiles();
}
diff --git a/packages/desktop-client/src/components/manager/Modals.js b/packages/desktop-client/src/components/manager/Modals.js
index fa645165867..cc7637a332c 100644
--- a/packages/desktop-client/src/components/manager/Modals.js
+++ b/packages/desktop-client/src/components/manager/Modals.js
@@ -14,11 +14,11 @@ import ImportYNAB4 from './ImportYNAB4';
import ImportYNAB5 from './ImportYNAB5';
export default function Modals() {
- let modalStack = useSelector(state => state.modals.modalStack);
- let isHidden = useSelector(state => state.modals.isHidden);
- let actions = useActions();
+ const modalStack = useSelector(state => state.modals.modalStack);
+ const isHidden = useSelector(state => state.modals.isHidden);
+ const actions = useActions();
- let stack = modalStack.map(({ name, options = {} }, idx) => {
+ const stack = modalStack.map(({ name, options = {} }, idx) => {
const modalProps = {
onClose: actions.popModal,
onPush: actions.pushModal,
diff --git a/packages/desktop-client/src/components/manager/WelcomeScreen.tsx b/packages/desktop-client/src/components/manager/WelcomeScreen.tsx
index 5f05c5cf5d1..89f45cf1074 100644
--- a/packages/desktop-client/src/components/manager/WelcomeScreen.tsx
+++ b/packages/desktop-client/src/components/manager/WelcomeScreen.tsx
@@ -9,7 +9,7 @@ import Text from '../common/Text';
import View from '../common/View';
export default function WelcomeScreen() {
- let { createBudget, pushModal } = useActions();
+ const { createBudget, pushModal } = useActions();
return (
{
async function run() {
- let ensure = url => {
+ const ensure = url => {
if (location.pathname !== url) {
navigate(url);
} else {
@@ -32,12 +32,12 @@ export function useBootstrapped() {
}
};
- let url = await send('get-server-url');
- let bootstrapped = await send('get-did-bootstrap');
+ const url = await send('get-server-url');
+ const bootstrapped = await send('get-did-bootstrap');
if (url == null && !bootstrapped) {
// A server hasn't been specified yet
- let serverURL = window.location.origin;
- let result = await send('subscribe-needs-bootstrap', {
+ const serverURL = window.location.origin;
+ const result = await send('subscribe-needs-bootstrap', {
url: serverURL,
});
if ('error' in result || !result.hasServer) {
@@ -54,7 +54,7 @@ export function useBootstrapped() {
ensure('/bootstrap');
}
} else {
- let result = await send('subscribe-needs-bootstrap');
+ const result = await send('subscribe-needs-bootstrap');
if ('error' in result) {
navigate('/error', { state: { error: result.error } });
} else if (result.bootstrapped) {
diff --git a/packages/desktop-client/src/components/mobile/MobileAmountInput.js b/packages/desktop-client/src/components/mobile/MobileAmountInput.js
index a1c6895a5f8..4155bffab6a 100644
--- a/packages/desktop-client/src/components/mobile/MobileAmountInput.js
+++ b/packages/desktop-client/src/components/mobile/MobileAmountInput.js
@@ -132,7 +132,7 @@ class AmountInput extends PureComponent {
};
onChangeText = text => {
- let { onChange } = this.props;
+ const { onChange } = this.props;
this.setState({ text });
onChange(text);
@@ -142,7 +142,7 @@ class AmountInput extends PureComponent {
const { style, textStyle } = this.props;
const { editing, value, text } = this.state;
- let input = (
+ const input = (
(this.input = el)}
diff --git a/packages/desktop-client/src/components/modals/CloseAccount.tsx b/packages/desktop-client/src/components/modals/CloseAccount.tsx
index 48f63a61ff7..2b58b0852d3 100644
--- a/packages/desktop-client/src/components/modals/CloseAccount.tsx
+++ b/packages/desktop-client/src/components/modals/CloseAccount.tsx
@@ -51,12 +51,12 @@ function CloseAccount({
actions,
modalProps,
}: CloseAccountProps) {
- let [loading, setLoading] = useState(false);
- let [transfer, setTransfer] = useState('');
- let [category, setCategory] = useState('');
+ const [loading, setLoading] = useState(false);
+ const [transfer, setTransfer] = useState('');
+ const [category, setCategory] = useState('');
- let [transferError, setTransferError] = useState(false);
- let [categoryError, setCategoryError] = useState(false);
+ const [transferError, setTransferError] = useState(false);
+ const [categoryError, setCategoryError] = useState(false);
return (
{
event.preventDefault();
- let transferError = balance !== 0 && transfer === '';
+ const transferError = balance !== 0 && transfer === '';
setTransferError(transferError);
- let categoryError =
+ const categoryError =
needsCategory(account, transfer, accounts) && category === '';
setCategoryError(categoryError);
diff --git a/packages/desktop-client/src/components/modals/CreateEncryptionKey.tsx b/packages/desktop-client/src/components/modals/CreateEncryptionKey.tsx
index 33c8f94f078..8a18eff5f7a 100644
--- a/packages/desktop-client/src/components/modals/CreateEncryptionKey.tsx
+++ b/packages/desktop-client/src/components/modals/CreateEncryptionKey.tsx
@@ -30,19 +30,19 @@ export default function CreateEncryptionKey({
actions,
options = {},
}: CreateEncryptionKeyProps) {
- let [password, setPassword] = useState('');
- let [loading, setLoading] = useState(false);
- let [error, setError] = useState('');
- let [showPassword, setShowPassword] = useState(false);
+ const [password, setPassword] = useState('');
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState('');
+ const [showPassword, setShowPassword] = useState(false);
- let isRecreating = options.recreate;
+ const isRecreating = options.recreate;
async function onCreateKey() {
if (password !== '' && !loading) {
setLoading(true);
setError(null);
- let res = await send('key-make', { password });
+ const res = await send('key-make', { password });
if (res.error) {
setLoading(null);
setError(getCreateKeyError(res.error));
diff --git a/packages/desktop-client/src/components/modals/CreateLocalAccount.tsx b/packages/desktop-client/src/components/modals/CreateLocalAccount.tsx
index 62d208cb39c..5f5cc59e6ff 100644
--- a/packages/desktop-client/src/components/modals/CreateLocalAccount.tsx
+++ b/packages/desktop-client/src/components/modals/CreateLocalAccount.tsx
@@ -23,15 +23,15 @@ type CreateLocalAccountProps = {
};
function CreateLocalAccount({ modalProps, actions }: CreateLocalAccountProps) {
- let navigate = useNavigate();
- let [name, setName] = useState('');
- let [offbudget, setOffbudget] = useState(false);
- let [balance, setBalance] = useState('0');
+ const navigate = useNavigate();
+ const [name, setName] = useState('');
+ const [offbudget, setOffbudget] = useState(false);
+ const [balance, setBalance] = useState('0');
- let [nameError, setNameError] = useState(false);
- let [balanceError, setBalanceError] = useState(false);
+ const [nameError, setNameError] = useState(false);
+ const [balanceError, setBalanceError] = useState(false);
- let validateBalance = balance => !isNaN(parseFloat(balance));
+ const validateBalance = balance => !isNaN(parseFloat(balance));
return (
@@ -41,15 +41,15 @@ function CreateLocalAccount({ modalProps, actions }: CreateLocalAccountProps) {
onSubmit={async event => {
event.preventDefault();
- let nameError = !name;
+ const nameError = !name;
setNameError(nameError);
- let balanceError = !validateBalance(balance);
+ const balanceError = !validateBalance(balance);
setBalanceError(balanceError);
if (!nameError && !balanceError) {
actions.closeModal();
- let id = await actions.createAccount(
+ const id = await actions.createAccount(
name,
toRelaxedNumber(balance),
offbudget,
@@ -65,7 +65,7 @@ function CreateLocalAccount({ modalProps, actions }: CreateLocalAccountProps) {
value={name}
onChange={event => setName(event.target.value)}
onBlur={event => {
- let name = event.target.value.trim();
+ const name = event.target.value.trim();
setName(name);
if (name && nameError) {
setNameError(false);
@@ -139,7 +139,7 @@ function CreateLocalAccount({ modalProps, actions }: CreateLocalAccountProps) {
value={balance}
onChange={event => setBalance(event.target.value)}
onBlur={event => {
- let balance = event.target.value.trim();
+ const balance = event.target.value.trim();
setBalance(balance);
if (validateBalance(balance) && balanceError) {
setBalanceError(false);
diff --git a/packages/desktop-client/src/components/modals/EditField.js b/packages/desktop-client/src/components/modals/EditField.js
index cc54d60bcfb..853c85534be 100644
--- a/packages/desktop-client/src/components/modals/EditField.js
+++ b/packages/desktop-client/src/components/modals/EditField.js
@@ -35,14 +35,14 @@ function CreatePayeeIcon(props) {
}
export default function EditField({ modalProps, name, onSubmit }) {
- let dateFormat = useSelector(
+ const dateFormat = useSelector(
state => state.prefs.local.dateFormat || 'MM/dd/yyyy',
);
- let { grouped: categoryGroups } = useCategories();
- let accounts = useSelector(state => state.queries.accounts);
- let payees = useSelector(state => state.queries.payees);
+ const { grouped: categoryGroups } = useCategories();
+ const accounts = useSelector(state => state.queries.accounts);
+ const payees = useSelector(state => state.queries.payees);
- let { createPayee } = useActions();
+ const { createPayee } = useActions();
function onSelect(value) {
if (value != null) {
@@ -65,18 +65,18 @@ export default function EditField({ modalProps, name, onSubmit }) {
const { isNarrowWidth } = useResponsive();
let label, editor, minWidth;
- let inputStyle = {
+ const inputStyle = {
':focus': { boxShadow: 0 },
...(isNarrowWidth && itemStyle),
};
- let autocompleteProps = {
+ const autocompleteProps = {
inputProps: { style: inputStyle },
containerProps: { style: { height: isNarrowWidth ? '90vh' : 275 } },
};
switch (name) {
case 'date': {
- let today = currentDay();
+ const today = currentDay();
label = 'Date';
minWidth = 350;
editor = (
@@ -108,28 +108,30 @@ export default function EditField({ modalProps, name, onSubmit }) {
onSelect(value);
}
}}
- renderAccountItemGroupHeader={props => (
-
- )}
- renderAccountItem={props => (
-
- )}
+ {...(isNarrowWidth && {
+ renderAccountItemGroupHeader: props => (
+
+ ),
+ renderAccountItem: props => (
+
+ ),
+ })}
{...autocompleteProps}
/>
);
@@ -155,35 +157,37 @@ export default function EditField({ modalProps, name, onSubmit }) {
onSelect(value);
}}
isCreatable
- renderCreatePayeeButton={props => (
-
- )}
- renderPayeeItemGroupHeader={props => (
-
- )}
- renderPayeeItem={props => (
-
- )}
+ {...(isNarrowWidth && {
+ renderCreatePayeeButton: props => (
+
+ ),
+ renderPayeeItemGroupHeader: props => (
+
+ ),
+ renderPayeeItem: props => (
+
+ ),
+ })}
{...autocompleteProps}
/>
);
@@ -214,28 +218,30 @@ export default function EditField({ modalProps, name, onSubmit }) {
onSelect={value => {
onSelect(value);
}}
- renderCategoryItemGroupHeader={props => (
-
- )}
- renderCategoryItem={props => (
-
- )}
+ {...(isNarrowWidth && {
+ renderCategoryItemGroupHeader: props => (
+
+ ),
+ renderCategoryItem: props => (
+
+ ),
+ })}
{...autocompleteProps}
/>
);
diff --git a/packages/desktop-client/src/components/modals/EditRule.js b/packages/desktop-client/src/components/modals/EditRule.js
index 1af0c6e29c7..9893fa71f43 100644
--- a/packages/desktop-client/src/components/modals/EditRule.js
+++ b/packages/desktop-client/src/components/modals/EditRule.js
@@ -54,7 +54,7 @@ function applyErrors(array, errorsArray) {
}
function getTransactionFields(conditions, actions) {
- let fields = ['date'];
+ const fields = ['date'];
if (conditions.find(c => c.field === 'imported_payee')) {
fields.push('imported_payee');
@@ -191,8 +191,9 @@ function ConditionEditor({
onDelete,
onAdd,
}) {
- let { field, op, value, type, options, error } = condition;
+ const { field: originalField, op, value, type, options, error } = condition;
+ let field = originalField;
if (field === 'amount' && options) {
if (options.inflow) {
field = 'amount-inflow';
@@ -251,10 +252,10 @@ function formatAmount(amount) {
}
function ScheduleDescription({ id }) {
- let dateFormat = useSelector(state => {
+ const dateFormat = useSelector(state => {
return state.prefs.local.dateFormat || 'MM/dd/yyyy';
});
- let scheduleData = useSchedules({
+ const scheduleData = useSchedules({
transform: useCallback(q => q.filter({ id }), []),
});
@@ -266,8 +267,8 @@ function ScheduleDescription({ id }) {
return {id};
}
- let [schedule] = scheduleData.schedules;
- let status = schedule && scheduleData.statuses.get(schedule.id);
+ const [schedule] = scheduleData.schedules;
+ const status = schedule && scheduleData.statuses.get(schedule.id);
return (
@@ -300,7 +301,7 @@ function ScheduleDescription({ id }) {
);
}
-let actionFields = [
+const actionFields = [
'category',
'payee',
'notes',
@@ -310,7 +311,7 @@ let actionFields = [
'amount',
].map(field => [field, mapField(field)]);
function ActionEditor({ ops, action, editorStyle, onChange, onDelete, onAdd }) {
- let { field, op, value, type, error, inputKey = 'initial' } = action;
+ const { field, op, value, type, error, inputKey = 'initial' } = action;
return (
@@ -364,7 +365,7 @@ function ActionEditor({ ops, action, editorStyle, onChange, onDelete, onAdd }) {
}
function StageInfo() {
- let [open, setOpen] = useState();
+ const [open, setOpen] = useState();
return (
@@ -439,9 +440,9 @@ function ConditionsList({
f => !conditions.some(c => c.field.includes(f) || f.includes(c.field)),
);
}
- let field = fields[0] || 'payee';
+ const field = fields[0] || 'payee';
- let copy = [...conditions];
+ const copy = [...conditions];
copy.splice(index + 1, 0, {
type: FIELD_TYPES.get(field),
field,
@@ -463,7 +464,7 @@ function ConditionsList({
onChangeConditions(
updateValue(conditions, cond, () => {
if (field === 'field') {
- let newCond = { field: value };
+ const newCond = { field: value };
if (value === 'amount-inflow') {
newCond.field = 'amount';
@@ -475,7 +476,7 @@ function ConditionsList({
newCond.type = FIELD_TYPES.get(newCond.field);
- let prevType = FIELD_TYPES.get(cond.field);
+ const prevType = FIELD_TYPES.get(cond.field);
if (
(prevType === 'string' || prevType === 'number') &&
prevType === newCond.type &&
@@ -490,7 +491,7 @@ function ConditionsList({
return newInput(makeValue(null, newCond));
}
} else if (field === 'op') {
- let op = value;
+ const op = value;
// Switching between oneOf and other operators is a
// special-case. It changes the input type, so we need to
@@ -589,7 +590,7 @@ function ConditionsList({
// TODO:
// * Dont touch child transactions?
-let conditionFields = [
+const conditionFields = [
'imported_payee',
'account',
'category',
@@ -609,15 +610,17 @@ export default function EditRule({
defaultRule,
onSave: originalOnSave,
}) {
- let [conditions, setConditions] = useState(defaultRule.conditions.map(parse));
- let [actions, setActions] = useState(defaultRule.actions.map(parse));
- let [stage, setStage] = useState(defaultRule.stage);
- let [conditionsOp, setConditionsOp] = useState(defaultRule.conditionsOp);
- let [transactions, setTransactions] = useState([]);
- let dispatch = useDispatch();
- let scrollableEl = useRef();
+ const [conditions, setConditions] = useState(
+ defaultRule.conditions.map(parse),
+ );
+ const [actions, setActions] = useState(defaultRule.actions.map(parse));
+ const [stage, setStage] = useState(defaultRule.stage);
+ const [conditionsOp, setConditionsOp] = useState(defaultRule.conditionsOp);
+ const [transactions, setTransactions] = useState([]);
+ const dispatch = useDispatch();
+ const scrollableEl = useRef();
- let isSchedule = actions.some(action => action.op === 'link-schedule');
+ const isSchedule = actions.some(action => action.op === 'link-schedule');
useEffect(() => {
dispatch(initiallyLoadPayees());
@@ -630,21 +633,21 @@ export default function EditRule({
useEffect(() => {
// Flash the scrollbar
if (scrollableEl.current) {
- let el = scrollableEl.current;
- let top = el.scrollTop;
+ const el = scrollableEl.current;
+ const top = el.scrollTop;
el.scrollTop = top + 1;
el.scrollTop = top;
}
// Run it here
async function run() {
- let { filters } = await send('make-filters-from-conditions', {
+ const { filters } = await send('make-filters-from-conditions', {
conditions: conditions.map(unparse),
});
if (filters.length > 0) {
const conditionsOpKey = conditionsOp === 'or' ? '$or' : '$and';
- let { data: transactions } = await runQuery(
+ const { data: transactions } = await runQuery(
q('transactions')
.filter({ [conditionsOpKey]: filters })
.select('*'),
@@ -657,7 +660,7 @@ export default function EditRule({
run();
}, [actions, conditions, conditionsOp]);
- let selectedInst = useSelected('transactions', transactions, []);
+ const selectedInst = useSelected('transactions', transactions, []);
function addInitialAction() {
addAction(-1);
@@ -665,12 +668,12 @@ export default function EditRule({
function addAction(index) {
let fields = actionFields.map(f => f[0]);
- for (let action of actions) {
+ for (const action of actions) {
fields = fields.filter(f => f !== action.field);
}
- let field = fields[0] || 'category';
+ const field = fields[0] || 'category';
- let copy = [...actions];
+ const copy = [...actions];
copy.splice(index + 1, 0, {
type: FIELD_TYPES.get(field),
field,
@@ -683,7 +686,7 @@ export default function EditRule({
function onChangeAction(action, field, value) {
setActions(
updateValue(actions, action, () => {
- let a = { ...action };
+ const a = { ...action };
a[field] = value;
if (field === 'field') {
@@ -724,7 +727,7 @@ export default function EditRule({
}
async function onSave() {
- let rule = {
+ const rule = {
...defaultRule,
stage,
conditionsOp,
@@ -732,8 +735,8 @@ export default function EditRule({
actions: actions.map(unparse),
};
- let method = rule.id ? 'rule-update' : 'rule-add';
- let { error, id: newId } = await send(method, rule);
+ const method = rule.id ? 'rule-update' : 'rule-add';
+ const { error, id: newId } = await send(method, rule);
if (error) {
if (error.conditionErrors) {
@@ -754,7 +757,7 @@ export default function EditRule({
}
}
- let editorStyle = {
+ const editorStyle = {
color: theme.pillText,
backgroundColor: theme.pillBackground,
borderRadius: 4,
diff --git a/packages/desktop-client/src/components/modals/FixEncryptionKey.tsx b/packages/desktop-client/src/components/modals/FixEncryptionKey.tsx
index d327898f928..c7e0d96365a 100644
--- a/packages/desktop-client/src/components/modals/FixEncryptionKey.tsx
+++ b/packages/desktop-client/src/components/modals/FixEncryptionKey.tsx
@@ -27,19 +27,19 @@ export default function FixEncryptionKey({
actions,
options = {},
}: FixEncryptionKeyProps) {
- let { hasExistingKey, cloudFileId, onSuccess } = options;
+ const { hasExistingKey, cloudFileId, onSuccess } = options;
- let [password, setPassword] = useState('');
- let [error, setError] = useState('');
- let [loading, setLoading] = useState(false);
- let [showPassword, setShowPassword] = useState(false);
+ const [password, setPassword] = useState('');
+ const [error, setError] = useState('');
+ const [loading, setLoading] = useState(false);
+ const [showPassword, setShowPassword] = useState(false);
async function onUpdateKey() {
if (password !== '' && !loading) {
setLoading(true);
setError(null);
- let { error } = await send('key-test', {
+ const { error } = await send('key-test', {
password,
fileId: cloudFileId,
});
diff --git a/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.tsx b/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.tsx
index 53355f33642..ccdcad5a0a5 100644
--- a/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.tsx
+++ b/packages/desktop-client/src/components/modals/GoCardlessExternalMsg.tsx
@@ -93,16 +93,16 @@ export default function GoCardlessExternalMsg({
}: GoCardlessExternalMsgProps) {
const dispatch = useDispatch();
- let [waiting, setWaiting] = useState(null);
- let [success, setSuccess] = useState(false);
- let [institutionId, setInstitutionId] = useState();
- let [country, setCountry] = useState();
- let [error, setError] = useState<'unknown' | 'timeout' | null>(null);
- let [isGoCardlessSetupComplete, setIsGoCardlessSetupComplete] = useState<
+ const [waiting, setWaiting] = useState(null);
+ const [success, setSuccess] = useState(false);
+ const [institutionId, setInstitutionId] = useState();
+ const [country, setCountry] = useState();
+ const [error, setError] = useState<'unknown' | 'timeout' | null>(null);
+ const [isGoCardlessSetupComplete, setIsGoCardlessSetupComplete] = useState<
boolean | null
>(null);
- let [menuOpen, setMenuOpen] = useState(false);
- let data = useRef(null);
+ const [menuOpen, setMenuOpen] = useState(false);
+ const data = useRef(null);
const {
data: bankOptions,
@@ -116,7 +116,7 @@ export default function GoCardlessExternalMsg({
setError(null);
setWaiting('browser');
- let res = await onMoveExternal({ institutionId });
+ const res = await onMoveExternal({ institutionId });
if (res.error) {
setError(res.error);
setWaiting(null);
diff --git a/packages/desktop-client/src/components/modals/ImportTransactions.js b/packages/desktop-client/src/components/modals/ImportTransactions.js
index 11665ea71e8..b66597e1125 100644
--- a/packages/desktop-client/src/components/modals/ImportTransactions.js
+++ b/packages/desktop-client/src/components/modals/ImportTransactions.js
@@ -23,7 +23,7 @@ import View from '../common/View';
import { Checkbox, SectionLabel } from '../forms';
import { TableHeader, TableWithNavigator, Row, Field } from '../table';
-let dateFormats = [
+const dateFormats = [
{ format: 'yyyy mm dd', label: 'YYYY MM DD' },
{ format: 'yy mm dd', label: 'YY MM DD' },
{ format: 'mm dd yyyy', label: 'MM DD YYYY' },
@@ -108,7 +108,7 @@ export function parseDate(str, order) {
day = parts[1];
}
- let parsed = `${year}-${pad(month)}-${pad(day)}`;
+ const parsed = `${year}-${pad(month)}-${pad(day)}`;
if (!d.isValid(d.parseISO(parsed))) {
return null;
}
@@ -126,15 +126,15 @@ function formatDate(date, format) {
}
function getFileType(filepath) {
- let m = filepath.match(/\.([^.]*)$/);
+ const m = filepath.match(/\.([^.]*)$/);
if (!m) return 'ofx';
- let rawType = m[1].toLowerCase();
+ const rawType = m[1].toLowerCase();
if (rawType === 'tsv') return 'csv';
return rawType;
}
function ParsedDate({ parseDateFormat, showParsed, dateFormat, date }) {
- let parsed =
+ const parsed =
date &&
formatDate(
parseDateFormat ? parseDate(date, parseDateFormat) : date,
@@ -162,10 +162,10 @@ function getInitialDateFormat(transactions, mappings) {
return 'yyyy mm dd';
}
- let transaction = transactions[0];
- let date = transaction[mappings.date];
+ const transaction = transactions[0];
+ const date = transaction[mappings.date];
- let found =
+ const found =
date == null
? null
: dateFormats.find(f => parseDate(date, f.format) != null);
@@ -177,35 +177,35 @@ function getInitialMappings(transactions) {
return {};
}
- let transaction = transactions[0];
- let fields = Object.entries(transaction);
+ const transaction = transactions[0];
+ const fields = Object.entries(transaction);
function key(entry) {
return entry ? entry[0] : null;
}
- let dateField = key(
+ const dateField = key(
fields.find(([name, value]) => name.toLowerCase().includes('date')) ||
fields.find(([name, value]) => value.match(/^\d+[-/]\d+[-/]\d+$/)),
);
- let amountField = key(
+ const amountField = key(
fields.find(([name, value]) => name.toLowerCase().includes('amount')) ||
fields.find(([name, value]) => value.match(/^-?[.,\d]+$/)),
);
- let payeeField = key(
+ const payeeField = key(
fields.find(([name, value]) => name !== dateField && name !== amountField),
);
- let notesField = key(
+ const notesField = key(
fields.find(
([name, value]) =>
name !== dateField && name !== amountField && name !== payeeField,
),
);
- let inOutField = key(
+ const inOutField = key(
fields.find(
([name, value]) =>
name !== dateField &&
@@ -225,8 +225,9 @@ function getInitialMappings(transactions) {
}
function applyFieldMappings(transaction, mappings) {
- let result = {};
- for (let [field, target] of Object.entries(mappings)) {
+ const result = {};
+ for (const [originalField, target] of Object.entries(mappings)) {
+ let field = originalField;
if (field === 'payee') {
field = 'payee_name';
}
@@ -240,8 +241,9 @@ function parseAmount(amount, mapper) {
if (amount == null) {
return null;
}
- let parsed = typeof amount === 'string' ? looselyParseAmount(amount) : amount;
- let value = mapper(parsed);
+ const parsed =
+ typeof amount === 'string' ? looselyParseAmount(amount) : amount;
+ const value = mapper(parsed);
return value;
}
@@ -259,8 +261,8 @@ function parseAmountFields(
// Split mode is a little weird; first we look for an outflow and
// if that has a value, we never want to show a number in the
// inflow. Same for `amount`; we choose outflow first and then inflow
- let outflow = parseAmount(trans.outflow, n => -Math.abs(n)) * multiplier;
- let inflow = outflow
+ const outflow = parseAmount(trans.outflow, n => -Math.abs(n)) * multiplier;
+ const inflow = outflow
? 0
: parseAmount(trans.inflow, n => Math.abs(n)) * multiplier;
@@ -300,7 +302,7 @@ function Transaction({
flipAmount,
multiplierAmount,
}) {
- let transaction = useMemo(
+ const transaction = useMemo(
() =>
fieldMappings
? applyFieldMappings(rawTransaction, fieldMappings)
@@ -434,8 +436,8 @@ function DateFormatSelect({
// to space if we can't figure it out.
let delimiter = '-';
if (transactions.length > 0 && fieldMappings && fieldMappings.date != null) {
- let date = transactions[0][fieldMappings.date];
- let m = date && date.match(/[/.,-/\\]/);
+ const date = transactions[0][fieldMappings.date];
+ const m = date && date.match(/[/.,-/\\]/);
delimiter = m ? m[0] : ' ';
}
@@ -555,7 +557,7 @@ function FieldMappings({
return null;
}
- let options = Object.keys(transactions[0]);
+ const options = Object.keys(transactions[0]);
mappings = mappings || {};
return (
@@ -655,53 +657,53 @@ function FieldMappings({
}
export default function ImportTransactions({ modalProps, options }) {
- let dateFormat = useSelector(
+ const dateFormat = useSelector(
state => state.prefs.local.dateFormat || 'MM/dd/yyyy',
);
- let prefs = useSelector(state => state.prefs.local);
- let { parseTransactions, importTransactions, getPayees, savePrefs } =
+ const prefs = useSelector(state => state.prefs.local);
+ const { parseTransactions, importTransactions, getPayees, savePrefs } =
useActions();
- let [multiplierAmount, setMultiplierAmount] = useState('');
- let [loadingState, setLoadingState] = useState('parsing');
- let [error, setError] = useState(null);
- let [filename, setFilename] = useState(options.filename);
- let [transactions, setTransactions] = useState([]);
- let [filetype, setFileType] = useState(null);
- let [fieldMappings, setFieldMappings] = useState(null);
- let [splitMode, setSplitMode] = useState(false);
- let [inOutMode, setInOutMode] = useState(false);
- let [outValue, setOutValue] = useState('');
- let [flipAmount, setFlipAmount] = useState(false);
- let [multiplierEnabled, setMultiplierEnabled] = useState(false);
- let { accountId, onImported } = options;
+ const [multiplierAmount, setMultiplierAmount] = useState('');
+ const [loadingState, setLoadingState] = useState('parsing');
+ const [error, setError] = useState(null);
+ const [filename, setFilename] = useState(options.filename);
+ const [transactions, setTransactions] = useState([]);
+ const [filetype, setFileType] = useState(null);
+ const [fieldMappings, setFieldMappings] = useState(null);
+ const [splitMode, setSplitMode] = useState(false);
+ const [inOutMode, setInOutMode] = useState(false);
+ const [outValue, setOutValue] = useState('');
+ const [flipAmount, setFlipAmount] = useState(false);
+ const [multiplierEnabled, setMultiplierEnabled] = useState(false);
+ const { accountId, onImported } = options;
// This cannot be set after parsing the file, because changing it
// requires re-parsing the file. This is different from the other
// options which are simple post-processing. That means if you
// parsed different files without closing the modal, it wouldn't
// re-read this.
- let [delimiter, setDelimiter] = useState(
+ const [delimiter, setDelimiter] = useState(
prefs[`csv-delimiter-${accountId}`] ||
(filename.endsWith('.tsv') ? '\t' : ','),
);
- let [hasHeaderRow, setHasHeaderRow] = useState(
+ const [hasHeaderRow, setHasHeaderRow] = useState(
prefs[`csv-has-header-${accountId}`] ?? true,
);
- let [fallbackMissingPayeeToMemo, setFallbackMissingPayeeToMemo] = useState(
+ const [fallbackMissingPayeeToMemo, setFallbackMissingPayeeToMemo] = useState(
prefs[`ofx-fallback-missing-payee-${accountId}`] ?? true,
);
- let [parseDateFormat, setParseDateFormat] = useState(null);
+ const [parseDateFormat, setParseDateFormat] = useState(null);
- let [clearOnImport, setClearOnImport] = useState(true);
+ const [clearOnImport, setClearOnImport] = useState(true);
const enableExperimentalOfxParser = useFeatureFlag('experimentalOfxParser');
async function parse(filename, options) {
setLoadingState('parsing');
- let filetype = getFileType(filename);
+ const filetype = getFileType(filename);
setFilename(filename);
setFileType(filetype);
@@ -710,7 +712,7 @@ export default function ImportTransactions({ modalProps, options }) {
enableExperimentalOfxParser,
};
- let { errors, transactions } = await parseTransactions(filename, options);
+ const { errors, transactions } = await parseTransactions(filename, options);
setLoadingState(null);
setError(null);
@@ -734,7 +736,7 @@ export default function ImportTransactions({ modalProps, options }) {
setFieldMappings(mappings);
// Set initial split mode based on any saved mapping
- let initialSplitMode = !!(mappings.outflow || mappings.inflow);
+ const initialSplitMode = !!(mappings.outflow || mappings.inflow);
setSplitMode(initialSplitMode);
setParseDateFormat(
@@ -785,16 +787,16 @@ export default function ImportTransactions({ modalProps, options }) {
setFlipAmount(!flipAmount);
}
- let isSplit = !splitMode;
+ const isSplit = !splitMode;
setSplitMode(isSplit);
setInOutMode(false);
setFlipAmount(false);
// Run auto-detection on the fields to try to detect the fields
// automatically
- let mappings = getInitialMappings(transactions);
+ const mappings = getInitialMappings(transactions);
- let newFieldMappings = isSplit
+ const newFieldMappings = isSplit
? {
amount: null,
outflow: mappings.amount,
@@ -835,13 +837,13 @@ export default function ImportTransactions({ modalProps, options }) {
async function onImport() {
setLoadingState('importing');
- let finalTransactions = [];
+ const finalTransactions = [];
let errorMessage;
for (let trans of transactions) {
trans = fieldMappings ? applyFieldMappings(trans, fieldMappings) : trans;
- let date = isOfxFile(filetype)
+ const date = isOfxFile(filetype)
? trans.date
: parseDate(trans.date, parseDateFormat);
if (date == null) {
@@ -851,7 +853,7 @@ export default function ImportTransactions({ modalProps, options }) {
break;
}
- let { amount } = parseAmountFields(
+ const { amount } = parseAmountFields(
trans,
splitMode,
inOutMode,
@@ -864,7 +866,7 @@ export default function ImportTransactions({ modalProps, options }) {
break;
}
- let { inflow, outflow, inOut, ...finalTransaction } = trans;
+ const { inflow, outflow, inOut, ...finalTransaction } = trans;
finalTransactions.push({
...finalTransaction,
date,
@@ -880,7 +882,7 @@ export default function ImportTransactions({ modalProps, options }) {
}
if (!isOfxFile(filetype)) {
- let key = `parse-date-${accountId}-${filetype}`;
+ const key = `parse-date-${accountId}-${filetype}`;
savePrefs({ [key]: parseDateFormat });
}
@@ -901,7 +903,7 @@ export default function ImportTransactions({ modalProps, options }) {
savePrefs({ [`flip-amount-${accountId}-${filetype}`]: flipAmount });
}
- let didChange = await importTransactions(accountId, finalTransactions);
+ const didChange = await importTransactions(accountId, finalTransactions);
if (didChange) {
await getPayees();
}
@@ -913,7 +915,7 @@ export default function ImportTransactions({ modalProps, options }) {
modalProps.onClose();
}
- let headers = [
+ const headers = [
{ name: 'Date', width: 200 },
{ name: 'Payee', width: 'flex' },
{ name: 'Notes', width: 'flex' },
diff --git a/packages/desktop-client/src/components/modals/LoadBackup.js b/packages/desktop-client/src/components/modals/LoadBackup.js
index 6e0f3d98e66..64786e72407 100644
--- a/packages/desktop-client/src/components/modals/LoadBackup.js
+++ b/packages/desktop-client/src/components/modals/LoadBackup.js
@@ -54,7 +54,7 @@ function LoadBackup({
actions,
modalProps,
}) {
- let [backups, setBackups] = useState([]);
+ const [backups, setBackups] = useState([]);
useEffect(() => {
send('backups-get', { id: budgetId }).then(setBackups);
diff --git a/packages/desktop-client/src/components/modals/ManageRulesModal.tsx b/packages/desktop-client/src/components/modals/ManageRulesModal.tsx
index 72a7d202ac0..59dccf84a5a 100644
--- a/packages/desktop-client/src/components/modals/ManageRulesModal.tsx
+++ b/packages/desktop-client/src/components/modals/ManageRulesModal.tsx
@@ -16,8 +16,8 @@ export default function ManageRulesModal({
modalProps,
payeeId,
}: ManageRulesModalProps) {
- let [loading, setLoading] = useState(true);
- let location = useLocation();
+ const [loading, setLoading] = useState(true);
+ const location = useLocation();
if (isNonProductionEnvironment()) {
if (location.pathname !== '/payees') {
throw new Error(
diff --git a/packages/desktop-client/src/components/modals/MergeUnusedPayees.js b/packages/desktop-client/src/components/modals/MergeUnusedPayees.js
index 50d3f36ec9e..d857cdd6a90 100644
--- a/packages/desktop-client/src/components/modals/MergeUnusedPayees.js
+++ b/packages/desktop-client/src/components/modals/MergeUnusedPayees.js
@@ -12,27 +12,27 @@ import Paragraph from '../common/Paragraph';
import Text from '../common/Text';
import View from '../common/View';
-let highlightStyle = { color: theme.pageTextPositive };
+const highlightStyle = { color: theme.pageTextPositive };
export default function MergeUnusedPayees({
modalProps,
payeeIds,
targetPayeeId,
}) {
- let { payees: allPayees, modalStack } = useSelector(state => ({
+ const { payees: allPayees, modalStack } = useSelector(state => ({
payees: state.queries.payees,
modalStack: state.modals.modalStack,
}));
- let isEditingRule = !!modalStack.find(m => m.name === 'edit-rule');
- let dispatch = useDispatch();
- let [shouldCreateRule, setShouldCreateRule] = useState(true);
- let flashRef = useRef(null);
+ const isEditingRule = !!modalStack.find(m => m.name === 'edit-rule');
+ const dispatch = useDispatch();
+ const [shouldCreateRule, setShouldCreateRule] = useState(true);
+ const flashRef = useRef(null);
useEffect(() => {
// Flash the scrollbar
if (flashRef.current) {
- let el = flashRef.current;
- let top = el.scrollTop;
+ const el = flashRef.current;
+ const top = el.scrollTop;
el.scrollTop = top + 1;
el.scrollTop = top;
}
@@ -44,10 +44,10 @@ export default function MergeUnusedPayees({
//
// TODO: I think a custom `useSelector` hook that doesn't bind would
// be nice
- let [payees] = useState(() =>
+ const [payees] = useState(() =>
payeeIds.map(id => allPayees.find(p => p.id === id)),
);
- let targetPayee = allPayees.find(p => p.id === targetPayeeId);
+ const targetPayee = allPayees.find(p => p.id === targetPayeeId);
if (!targetPayee) {
return null;
@@ -61,7 +61,7 @@ export default function MergeUnusedPayees({
let ruleId;
if (shouldCreateRule && !isEditingRule) {
- let id = await send('rule-add-payee-rename', {
+ const id = await send('rule-add-payee-rename', {
fromNames: payees.map(p => p.name),
to: targetPayee.id,
});
@@ -74,10 +74,10 @@ export default function MergeUnusedPayees({
}
async function onMergeAndCreateRule() {
- let ruleId = await onMerge();
+ const ruleId = await onMerge();
if (ruleId) {
- let rule = await send('rule-get', { id: ruleId });
+ const rule = await send('rule-get', { id: ruleId });
dispatch(replaceModal('edit-rule', { rule }));
}
}
diff --git a/packages/desktop-client/src/components/modals/PlaidExternalMsg.tsx b/packages/desktop-client/src/components/modals/PlaidExternalMsg.tsx
index 1b19f09c3b8..e9146a7e039 100644
--- a/packages/desktop-client/src/components/modals/PlaidExternalMsg.tsx
+++ b/packages/desktop-client/src/components/modals/PlaidExternalMsg.tsx
@@ -33,16 +33,16 @@ export default function PlaidExternalMsg({
onSuccess,
onClose: originalOnClose,
}: PlainExternalMsgProps) {
- let [waiting, setWaiting] = useState(null);
- let [success, setSuccess] = useState(false);
- let [error, setError] = useState(null);
- let data = useRef(null);
+ const [waiting, setWaiting] = useState(null);
+ const [success, setSuccess] = useState(false);
+ const [error, setError] = useState(null);
+ const data = useRef(null);
async function onJump() {
setError(null);
setWaiting('browser');
- let res = await onMoveExternal();
+ const res = await onMoveExternal();
if (res.error) {
setError(res.error);
setWaiting(null);
diff --git a/packages/desktop-client/src/components/payees/ManagePayees.js b/packages/desktop-client/src/components/payees/ManagePayees.js
index 0f8f968555b..3e60c6a7508 100644
--- a/packages/desktop-client/src/components/payees/ManagePayees.js
+++ b/packages/desktop-client/src/components/payees/ManagePayees.js
@@ -29,16 +29,16 @@ import { TableHeader, Cell, SelectCell, useTableNavigator } from '../table';
import PayeeMenu from './PayeeMenu';
import PayeeTable from './PayeeTable';
-let getPayeesById = memoizeOne(payees => groupById(payees));
+const getPayeesById = memoizeOne(payees => groupById(payees));
function plural(count, singleText, pluralText) {
return count === 1 ? singleText : pluralText;
}
function PayeeTableHeader() {
- let borderColor = theme.tableborder;
- let dispatchSelected = useSelectedDispatch();
- let selectedItems = useSelectedItems();
+ const borderColor = theme.tableborder;
+ const dispatchSelected = useSelectedDispatch();
+ const selectedItems = useSelectedItems();
return (
@@ -97,14 +97,14 @@ export const ManagePayees = forwardRef(
},
ref,
) => {
- let [highlightedRows, setHighlightedRows] = useState(null);
- let [filter, setFilter] = useState('');
- let table = useRef(null);
- let scrollTo = useRef(null);
- let resetAnimation = useRef(false);
+ const [highlightedRows, setHighlightedRows] = useState(null);
+ const [filter, setFilter] = useState('');
+ const table = useRef(null);
+ const scrollTo = useRef(null);
+ const resetAnimation = useRef(false);
const [orphanedOnly, setOrphanedOnly] = useState(false);
- let filteredPayees = useMemo(() => {
+ const filteredPayees = useMemo(() => {
let filtered = payees;
if (filter) {
filtered = filtered.filter(p =>
@@ -119,7 +119,7 @@ export const ManagePayees = forwardRef(
return filtered;
}, [payees, filter, orphanedOnly]);
- let selected = useSelected('payees', filteredPayees, initialSelectedIds);
+ const selected = useSelected('payees', filteredPayees, initialSelectedIds);
function applyFilter(f) {
if (filter !== f) {
@@ -179,14 +179,14 @@ export const ManagePayees = forwardRef(
}
});
- let onUpdate = useStableCallback((id, name, value) => {
- let payee = payees.find(p => p.id === id);
+ const onUpdate = useStableCallback((id, name, value) => {
+ const payee = payees.find(p => p.id === id);
if (payee[name] !== value) {
onBatchChange({ updated: [{ id, [name]: value }] });
}
});
- let getSelectableIds = useCallback(() => {
+ const getSelectableIds = useCallback(() => {
return filteredPayees.filter(p => p.transfer_acct == null).map(p => p.id);
}, [filteredPayees]);
@@ -196,7 +196,7 @@ export const ManagePayees = forwardRef(
}
async function onMerge() {
- let ids = [...selected.items];
+ const ids = [...selected.items];
await props.onMerge(ids);
tableNavigator.onEdit(ids[0], 'name');
@@ -204,9 +204,9 @@ export const ManagePayees = forwardRef(
_scrollTo(ids[0]);
}
- let buttonsDisabled = selected.items.size === 0;
+ const buttonsDisabled = selected.items.size === 0;
- let tableNavigator = useTableNavigator(filteredPayees, item =>
+ const tableNavigator = useTableNavigator(filteredPayees, item =>
['select', 'name', 'rule-count'].filter(name => {
switch (name) {
case 'select':
@@ -217,9 +217,9 @@ export const ManagePayees = forwardRef(
}),
);
- let payeesById = getPayeesById(payees);
+ const payeesById = getPayeesById(payees);
- let [menuOpen, setMenuOpen] = useState(false);
+ const [menuOpen, setMenuOpen] = useState(false);
return (
diff --git a/packages/desktop-client/src/components/payees/ManagePayeesPage.js b/packages/desktop-client/src/components/payees/ManagePayeesPage.js
index 2d707f39131..e3b1bdf72af 100644
--- a/packages/desktop-client/src/components/payees/ManagePayeesPage.js
+++ b/packages/desktop-client/src/components/payees/ManagePayeesPage.js
@@ -6,7 +6,7 @@ import { Page } from '../Page';
import ManagePayeesWithData from './ManagePayeesWithData';
export function ManagePayeesPage() {
- let location = useLocation();
+ const location = useLocation();
return (
state.queries.payees);
- let lastUndoState = useSelector(state => state.app.lastUndoState);
- let { grouped: categoryGroups } = useCategories();
+ const initialPayees = useSelector(state => state.queries.payees);
+ const lastUndoState = useSelector(state => state.app.lastUndoState);
+ const { grouped: categoryGroups } = useCategories();
- let { initiallyLoadPayees, getPayees, setLastUndoState, pushModal } =
+ const { initiallyLoadPayees, getPayees, setLastUndoState, pushModal } =
useActions();
- let [payees, setPayees] = useState(initialPayees);
- let [ruleCounts, setRuleCounts] = useState({ value: new Map() });
- let [orphans, setOrphans] = useState({ value: new Map() });
- let payeesRef = useRef();
+ const [payees, setPayees] = useState(initialPayees);
+ const [ruleCounts, setRuleCounts] = useState({ value: new Map() });
+ const [orphans, setOrphans] = useState({ value: new Map() });
+ const payeesRef = useRef();
async function refetchOrphanedPayees() {
- let orphs = await send('payees-get-orphaned');
+ const orphs = await send('payees-get-orphaned');
setOrphans(orphs);
}
@@ -35,7 +35,7 @@ export default function ManagePayeesWithData({ initialSelectedIds }) {
useEffect(() => {
async function loadData() {
- let result = await initiallyLoadPayees();
+ const result = await initiallyLoadPayees();
// Wait a bit before setting the data. This lets the modal
// settle and makes for a smoother experience.
@@ -50,7 +50,7 @@ export default function ManagePayeesWithData({ initialSelectedIds }) {
}
loadData();
- let unlisten = listen('sync-event', async ({ type, tables }) => {
+ const unlisten = listen('sync-event', async ({ type, tables }) => {
if (type === 'applied') {
if (tables.includes('rules')) {
refetchRuleCounts();
@@ -94,7 +94,7 @@ export default function ManagePayeesWithData({ initialSelectedIds }) {
}
function onCreateRule(id) {
- let rule = {
+ const rule = {
stage: null,
conditionsOp: 'and',
conditions: [
@@ -134,20 +134,21 @@ export default function ManagePayeesWithData({ initialSelectedIds }) {
onMerge={async ([targetId, ...mergeIds]) => {
await send('payees-merge', { targetId, mergeIds });
- let targetIdIsOrphan = orphans.map(o => o.id).includes(targetId);
- let mergeIdsOrphans = mergeIds.filter(m =>
+ const targetIdIsOrphan = orphans.map(o => o.id).includes(targetId);
+ const mergeIdsOrphans = mergeIds.filter(m =>
orphans.map(o => o.id).includes(m),
);
+ let filtedOrphans = orphans;
if (targetIdIsOrphan && mergeIdsOrphans.length !== mergeIds.length) {
// there is a non-orphan in mergeIds, target can be removed from orphan arr
- orphans = orphans.filter(o => o.id !== targetId);
+ filtedOrphans = filtedOrphans.filter(o => o.id !== targetId);
}
- orphans = orphans.filter(o => !mergeIds.includes(o.id));
+ filtedOrphans = filtedOrphans.filter(o => !mergeIds.includes(o.id));
- let result = payees.filter(p => !mergeIds.includes(p.id));
+ const result = payees.filter(p => !mergeIds.includes(p.id));
mergeIds.forEach(id => {
- let count = ruleCounts.value.get(id) || 0;
+ const count = ruleCounts.value.get(id) || 0;
ruleCounts.value.set(
targetId,
(ruleCounts.value.get(targetId) || 0) + count,
@@ -155,7 +156,7 @@ export default function ManagePayeesWithData({ initialSelectedIds }) {
});
setPayees(result);
- setOrphans(orphans);
+ setOrphans(filtedOrphans);
setRuleCounts({ value: ruleCounts.value });
}}
onViewRules={onViewRules}
diff --git a/packages/desktop-client/src/components/payees/PayeeMenu.tsx b/packages/desktop-client/src/components/payees/PayeeMenu.tsx
index cb13de4be27..479ee0242ca 100644
--- a/packages/desktop-client/src/components/payees/PayeeMenu.tsx
+++ b/packages/desktop-client/src/components/payees/PayeeMenu.tsx
@@ -23,7 +23,7 @@ export default function PayeeMenu({
onClose,
}: PayeeMenuProps) {
// Transfer accounts are never editable
- let isDisabled = [...selectedPayees].some(
+ const isDisabled = [...selectedPayees].some(
id => payeesById[id] == null || payeesById[id].transfer_acct,
);
diff --git a/packages/desktop-client/src/components/payees/PayeeTable.tsx b/packages/desktop-client/src/components/payees/PayeeTable.tsx
index 6a25680c905..b376752ae30 100644
--- a/packages/desktop-client/src/components/payees/PayeeTable.tsx
+++ b/packages/desktop-client/src/components/payees/PayeeTable.tsx
@@ -36,18 +36,18 @@ const PayeeTable = forwardRef<
{ payees, ruleCounts, navigator, onUpdate, onViewRules, onCreateRule },
ref,
) => {
- let [hovered, setHovered] = useState(null);
- let selectedItems = useSelectedItems();
+ const [hovered, setHovered] = useState(null);
+ const selectedItems = useSelectedItems();
useLayoutEffect(() => {
- let firstSelected = [...selectedItems][0] as string;
+ const firstSelected = [...selectedItems][0] as string;
if (typeof ref !== 'function') {
ref.current.scrollTo(firstSelected, 'center');
}
navigator.onEdit(firstSelected, 'select');
}, []);
- let onHover = useCallback(id => {
+ const onHover = useCallback(id => {
setHovered(id);
}, []);
diff --git a/packages/desktop-client/src/components/payees/PayeeTableRow.tsx b/packages/desktop-client/src/components/payees/PayeeTableRow.tsx
index 3875c847770..07d05ddb553 100644
--- a/packages/desktop-client/src/components/payees/PayeeTableRow.tsx
+++ b/packages/desktop-client/src/components/payees/PayeeTableRow.tsx
@@ -87,10 +87,12 @@ const PayeeTableRow = memo(
onUpdate,
style,
}: PayeeTableRowProps) => {
- let { id } = payee;
- let dispatchSelected = useSelectedDispatch();
- let borderColor = selected ? theme.tableBorderSelected : theme.tableBorder;
- let backgroundFocus = hovered || focusedField === 'select';
+ const { id } = payee;
+ const dispatchSelected = useSelectedDispatch();
+ const borderColor = selected
+ ? theme.tableBorderSelected
+ : theme.tableBorder;
+ const backgroundFocus = hovered || focusedField === 'select';
return (
categoryGroup.categories.map(category => selectAll.push(category)),
);
diff --git a/packages/desktop-client/src/components/reports/Header.js b/packages/desktop-client/src/components/reports/Header.js
index e1b6408bd1b..dffee4321ca 100644
--- a/packages/desktop-client/src/components/reports/Header.js
+++ b/packages/desktop-client/src/components/reports/Header.js
@@ -77,8 +77,8 @@ function Header({
headerPrefixItems,
selectGraph,
}) {
- let location = useLocation();
- let path = location.pathname;
+ const location = useLocation();
+ const path = location.pathname;
return (
state.queries.accounts);
+ const accounts = useSelector(state => state.queries.accounts);
return (
data.totalAssets ? 'EXPENSE' : 'INCOME';
+ const net = data.totalDebts > data.totalAssets ? 'EXPENSE' : 'INCOME';
const average = amountToInteger(data[balanceTypeOp]) / monthsCount;
return (
(null);
+ const contentRef = useRef(null);
useLayoutEffect(() => {
if (contentRef.current && saveScrollWidth) {
diff --git a/packages/desktop-client/src/components/reports/SaveReport.tsx b/packages/desktop-client/src/components/reports/SaveReport.tsx
index b6303870ace..f9554bc2073 100644
--- a/packages/desktop-client/src/components/reports/SaveReport.tsx
+++ b/packages/desktop-client/src/components/reports/SaveReport.tsx
@@ -38,7 +38,7 @@ function SaveReportMenu({ setMenuOpen }) {
}
export function SaveReportMenuButton() {
- let [menuOpen, setMenuOpen] = useState(false);
+ const [menuOpen, setMenuOpen] = useState(false);
return (
{
if (!privacyMode) return `${Math.round(tick).toLocaleString()}`; // Formats the tick values as strings with commas
diff --git a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
index 767817fb4ce..dd8b5558e83 100644
--- a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx
@@ -144,7 +144,7 @@ function BarGraph({
balanceTypeOp,
compact,
}: BarGraphProps) {
- let privacyMode = usePrivacyMode();
+ const privacyMode = usePrivacyMode();
const colorScale = getColorScale('qualitative');
const yAxis = ['Month', 'Year'].includes(groupBy) ? 'date' : 'name';
diff --git a/packages/desktop-client/src/components/reports/graphs/SankeyGraph.tsx b/packages/desktop-client/src/components/reports/graphs/SankeyGraph.tsx
index de73a14d6f2..753009a029f 100644
--- a/packages/desktop-client/src/components/reports/graphs/SankeyGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/SankeyGraph.tsx
@@ -79,7 +79,7 @@ function convertToCondensed(data) {
}
function SankeyGraph({ style, data, compact }: SankeyProps) {
- let sankeyData = compact ? convertToCondensed(data) : data;
+ const sankeyData = compact ? convertToCondensed(data) : data;
if (!data.links || data.links.length === 0) return null;
const margin = {
diff --git a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
index 42ec09863e6..37e2b3ea41c 100644
--- a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
+++ b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx
@@ -120,7 +120,7 @@ type StackedBarGraphProps = {
};
function StackedBarGraph({ style, data, compact }: StackedBarGraphProps) {
- let privacyMode = usePrivacyMode();
+ const privacyMode = usePrivacyMode();
const colorScale = getColorScale('qualitative');
return (
diff --git a/packages/desktop-client/src/components/reports/reports/CustomReport.js b/packages/desktop-client/src/components/reports/reports/CustomReport.js
index 369c660084c..a8d1f3a42cf 100644
--- a/packages/desktop-client/src/components/reports/reports/CustomReport.js
+++ b/packages/desktop-client/src/components/reports/reports/CustomReport.js
@@ -63,7 +63,7 @@ export default function CustomReport() {
const [viewSummary, setViewSummary] = useState(false);
const [viewLabels, setViewLabels] = useState(false);
//const [legend, setLegend] = useState([]);
- let legend = [];
+ const legend = [];
const dateRangeLine = ReportOptions.dateRange.length - 3;
const months = monthUtils.rangeInclusive(start, end);
@@ -101,10 +101,9 @@ export default function CustomReport() {
}
run();
}, []);
-
- let balanceTypeOp = ReportOptions.balanceTypeMap.get(balanceType);
- let payees = useCachedPayees();
- let accounts = useCachedAccounts();
+ const balanceTypeOp = ReportOptions.balanceTypeMap.get(balanceType);
+ const payees = useCachedPayees();
+ const accounts = useCachedAccounts();
const getGroupData = useMemo(() => {
return groupedSpreadsheet({
@@ -164,7 +163,7 @@ export default function CustomReport() {
const data = { ...graphData, groupedData };
- let [scrollWidth, setScrollWidth] = useState(0);
+ const [scrollWidth, setScrollWidth] = useState(0);
if (!allMonths || !data) {
return null;
diff --git a/packages/desktop-client/src/components/reports/reports/NetWorth.js b/packages/desktop-client/src/components/reports/reports/NetWorth.js
index e3f928b5fb4..8d9be68073d 100644
--- a/packages/desktop-client/src/components/reports/reports/NetWorth.js
+++ b/packages/desktop-client/src/components/reports/reports/NetWorth.js
@@ -20,7 +20,7 @@ import useReport from '../useReport';
import { fromDateRepr } from '../util';
function NetWorth() {
- let accounts = useSelector(state => state.queries.accounts);
+ const accounts = useSelector(state => state.queries.accounts);
const {
filters,
saved,
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/cash-flow-spreadsheet.tsx b/packages/desktop-client/src/components/reports/spreadsheets/cash-flow-spreadsheet.tsx
index 34502fb48a2..20ae05ef9c3 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/cash-flow-spreadsheet.tsx
+++ b/packages/desktop-client/src/components/reports/spreadsheets/cash-flow-spreadsheet.tsx
@@ -52,13 +52,13 @@ export function cashFlowByDate(
conditionsOp,
) {
return async (spreadsheet, setData) => {
- let { filters } = await send('make-filters-from-conditions', {
+ const { filters } = await send('make-filters-from-conditions', {
conditions: conditions.filter(cond => !cond.customName),
});
const conditionsOpKey = conditionsOp === 'or' ? '$or' : '$and';
function makeQuery(where) {
- let query = q('transactions')
+ const query = q('transactions')
.filter({
[conditionsOpKey]: [...filters],
})
@@ -109,11 +109,11 @@ export function cashFlowByDate(
}
function recalculate(data, start, end, isConcise) {
- let [startingBalance, income, expense] = data;
- let convIncome = income.map(t => {
+ const [startingBalance, income, expense] = data;
+ const convIncome = income.map(t => {
return { ...t, isTransfer: t.isTransfer !== null };
});
- let convExpense = expense.map(t => {
+ const convExpense = expense.map(t => {
return { ...t, isTransfer: t.isTransfer !== null };
});
const dates = isConcise
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/default-spreadsheet.tsx b/packages/desktop-client/src/components/reports/spreadsheets/default-spreadsheet.tsx
index 56b115ae322..6d4a7453b32 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/default-spreadsheet.tsx
+++ b/packages/desktop-client/src/components/reports/spreadsheets/default-spreadsheet.tsx
@@ -49,9 +49,9 @@ export default function createSpreadsheet({
accounts,
setDataCheck,
}) {
- let [catList, catGroup] = categoryLists(hidden, uncat, categories);
+ const [catList, catGroup] = categoryLists(hidden, uncat, categories);
- let categoryFilter = (catList || []).filter(
+ const categoryFilter = (catList || []).filter(
category =>
!category.hidden &&
selectedCategories &&
@@ -60,7 +60,7 @@ export default function createSpreadsheet({
),
);
- let [groupByList, groupByLabel] = groupBySelections(
+ const [groupByList, groupByLabel] = groupBySelections(
groupBy,
catList,
catGroup,
@@ -73,7 +73,7 @@ export default function createSpreadsheet({
return null;
}
- let { filters } = await send('make-filters-from-conditions', {
+ const { filters } = await send('make-filters-from-conditions', {
conditions: conditions.filter(cond => !cond.customName),
});
const conditionsOpKey = conditionsOp === 'or' ? '$or' : '$and';
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/net-worth-spreadsheet.tsx b/packages/desktop-client/src/components/reports/spreadsheets/net-worth-spreadsheet.tsx
index 81a685be8e6..4bc90d04124 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/net-worth-spreadsheet.tsx
+++ b/packages/desktop-client/src/components/reports/spreadsheets/net-worth-spreadsheet.tsx
@@ -23,14 +23,14 @@ export default function createSpreadsheet(
return null;
}
- let { filters } = await send('make-filters-from-conditions', {
+ const { filters } = await send('make-filters-from-conditions', {
conditions: conditions.filter(cond => !cond.customName),
});
const conditionsOpKey = conditionsOp === 'or' ? '$or' : '$and';
const data = await Promise.all(
accounts.map(async acct => {
- let [starting, balances] = await Promise.all([
+ const [starting, balances] = await Promise.all([
runQuery(
q('transactions')
.filter({
diff --git a/packages/desktop-client/src/components/reports/spreadsheets/sankey-spreadsheet.tsx b/packages/desktop-client/src/components/reports/spreadsheets/sankey-spreadsheet.tsx
index 7946aff2a50..cafb5ae568f 100644
--- a/packages/desktop-client/src/components/reports/spreadsheets/sankey-spreadsheet.tsx
+++ b/packages/desktop-client/src/components/reports/spreadsheets/sankey-spreadsheet.tsx
@@ -11,7 +11,7 @@ export default function createSpreadsheet(
) {
return async (spreadsheet, setData) => {
// gather filters user has set
- let { filters } = await send('make-filters-from-conditions', {
+ const { filters } = await send('make-filters-from-conditions', {
conditions: conditions.filter(cond => !cond.customName),
});
const conditionsOpKey = conditionsOp === 'or' ? '$or' : '$and';
@@ -28,7 +28,7 @@ export default function createSpreadsheet(
try {
return await Promise.all(
categories.map(async mainCategory => {
- let subcategoryBalances = await Promise.all(
+ const subcategoryBalances = await Promise.all(
mainCategory.categories
.filter(subcategory => subcategory.is_income !== 1)
.map(async subcategory => {
@@ -91,7 +91,7 @@ export default function createSpreadsheet(
const resultsArrays = await Promise.all(promises);
// unravel the results
- let payeesDict = {};
+ const payeesDict = {};
resultsArrays.forEach(item => {
item.data.forEach(innerItem => {
payeesDict[innerItem.payee] = innerItem.amount;
@@ -99,7 +99,7 @@ export default function createSpreadsheet(
});
// First, collect all unique IDs from payeesDict
- let payeeIds = Object.keys(payeesDict);
+ const payeeIds = Object.keys(payeesDict);
const results = await runQuery(
q('payees')
@@ -108,7 +108,7 @@ export default function createSpreadsheet(
);
// Convert the resulting array to a payee-name-map
- let payeeNames = {};
+ const payeeNames = {};
results.data.forEach(item => {
if (item.name && payeesDict[item.id]) {
payeeNames[item.name] = payeesDict[item.id];
@@ -146,10 +146,10 @@ function transformToSankeyData(categoryData, incomeData) {
});
// add all category expenses that have valid subcategories and a balance
- for (let mainCategory of categoryData) {
+ for (const mainCategory of categoryData) {
if (!nodeNames.has(mainCategory.name) && mainCategory.balances.length > 0) {
let mainCategorySum = 0;
- for (let subCategory of mainCategory.balances) {
+ for (const subCategory of mainCategory.balances) {
if (!nodeNames.has(subCategory.subcategory) && subCategory.value > 0) {
mainCategorySum += subCategory.value;
}
@@ -166,7 +166,7 @@ function transformToSankeyData(categoryData, incomeData) {
});
// add the subcategories of the main category
- for (let subCategory of mainCategory.balances) {
+ for (const subCategory of mainCategory.balances) {
if (!nodeNames.has(subCategory.subcategory) && subCategory.value > 0) {
data.nodes.push({ name: subCategory.subcategory });
nodeNames.add(subCategory.subcategory);
diff --git a/packages/desktop-client/src/components/reports/util.js b/packages/desktop-client/src/components/reports/util.js
index 1cae0b43d3f..2689e0e147a 100644
--- a/packages/desktop-client/src/components/reports/util.js
+++ b/packages/desktop-client/src/components/reports/util.js
@@ -5,7 +5,7 @@ export function fromDateRepr(date) {
}
export async function runAll(queries, cb) {
- let data = await Promise.all(
+ const data = await Promise.all(
queries.map(q => {
return runQuery(q).then(({ data }) => data);
}),
@@ -24,12 +24,12 @@ export function index(data, field, mapper) {
export function indexCashFlow(data, date, isTransfer) {
const results = {};
data.forEach(item => {
- let findExisting = results[item.date]
+ const findExisting = results[item.date]
? results[item.date][item.isTransfer]
? results[item.date][item.isTransfer]
: 0
: 0;
- let result = { [item[isTransfer]]: item.amount + findExisting };
+ const result = { [item[isTransfer]]: item.amount + findExisting };
results[item[date]] = { ...results[item[date]], ...result };
});
return results;
diff --git a/packages/desktop-client/src/components/responsive/index.tsx b/packages/desktop-client/src/components/responsive/index.tsx
index 570e533aabe..579f70009d8 100644
--- a/packages/desktop-client/src/components/responsive/index.tsx
+++ b/packages/desktop-client/src/components/responsive/index.tsx
@@ -4,9 +4,10 @@ import { LoadComponent } from '../util/LoadComponent';
import type * as NarrowComponents from './narrow';
import type * as WideComponents from './wide';
-let loadNarrow = () =>
+const loadNarrow = () =>
import(/* webpackChunkName: "narrow-components" */ './narrow');
-let loadWide = () => import(/* webpackChunkName: "wide-components" */ './wide');
+const loadWide = () =>
+ import(/* webpackChunkName: "wide-components" */ './wide');
export function WideComponent({ name }: { name: keyof typeof WideComponents }) {
return ;
diff --git a/packages/desktop-client/src/components/rules/ActionExpression.tsx b/packages/desktop-client/src/components/rules/ActionExpression.tsx
index cb1d5b2cea9..607276cdcad 100644
--- a/packages/desktop-client/src/components/rules/ActionExpression.tsx
+++ b/packages/desktop-client/src/components/rules/ActionExpression.tsx
@@ -14,7 +14,7 @@ import View from '../common/View';
import ScheduleValue from './ScheduleValue';
import Value from './Value';
-let valueStyle = {
+const valueStyle = {
color: theme.pageTextPositive,
};
diff --git a/packages/desktop-client/src/components/rules/ConditionExpression.tsx b/packages/desktop-client/src/components/rules/ConditionExpression.tsx
index 1a97c27a3d0..48f957d06bc 100644
--- a/packages/desktop-client/src/components/rules/ConditionExpression.tsx
+++ b/packages/desktop-client/src/components/rules/ConditionExpression.tsx
@@ -8,7 +8,7 @@ import View from '../common/View';
import Value from './Value';
-let valueStyle = {
+const valueStyle = {
color: theme.pageTextPositive,
};
diff --git a/packages/desktop-client/src/components/rules/RuleRow.tsx b/packages/desktop-client/src/components/rules/RuleRow.tsx
index 037a85cba91..c9977fb19bf 100644
--- a/packages/desktop-client/src/components/rules/RuleRow.tsx
+++ b/packages/desktop-client/src/components/rules/RuleRow.tsx
@@ -25,9 +25,9 @@ type RuleRowProps = {
const RuleRow = memo(
({ rule, hovered, selected, onHover, onEditRule }: RuleRowProps) => {
- let dispatchSelected = useSelectedDispatch();
- let borderColor = selected ? theme.tableBorderSelected : 'none';
- let backgroundFocus = hovered;
+ const dispatchSelected = useSelectedDispatch();
+ const borderColor = selected ? theme.tableBorderSelected : 'none';
+ const backgroundFocus = hovered;
return (
diff --git a/packages/desktop-client/src/components/rules/RulesList.tsx b/packages/desktop-client/src/components/rules/RulesList.tsx
index 1f5a45437ac..c56b58cbf8f 100644
--- a/packages/desktop-client/src/components/rules/RulesList.tsx
+++ b/packages/desktop-client/src/components/rules/RulesList.tsx
@@ -28,8 +28,8 @@ export default function RulesList({
return (
{rules.map(rule => {
- let hovered = hoveredRule === rule.id;
- let selected = selectedItems.has(rule.id);
+ const hovered = hoveredRule === rule.id;
+ const selected = selectedItems.has(rule.id);
return (
state.queries.payees);
- let byId = getPayeesById(payees);
- let { data: schedules } = SchedulesQuery.useQuery();
+ const payees = useSelector(state => state.queries.payees);
+ const byId = getPayeesById(payees);
+ const { data: schedules } = SchedulesQuery.useQuery();
return (
();
- let contentHeight = useRef();
- let scrollRef = useRef();
+ const contentRef = useRef();
+ const contentHeight = useRef();
+ const scrollRef = useRef();
function onScroll(e) {
if (contentHeight.current != null) {
diff --git a/packages/desktop-client/src/components/rules/Value.tsx b/packages/desktop-client/src/components/rules/Value.tsx
index 74474f1ec02..eb802b288d3 100644
--- a/packages/desktop-client/src/components/rules/Value.tsx
+++ b/packages/desktop-client/src/components/rules/Value.tsx
@@ -12,7 +12,7 @@ import { theme } from '../../style';
import LinkButton from '../common/LinkButton';
import Text from '../common/Text';
-let valueStyle = {
+const valueStyle = {
color: theme.pageTextPositive,
};
@@ -34,14 +34,14 @@ export default function Value({
// @ts-expect-error fix this later
describe = x => x.name,
}: ValueProps) {
- let dateFormat = useSelector(
+ const dateFormat = useSelector(
state => state.prefs.local.dateFormat || 'MM/dd/yyyy',
);
- let payees = useSelector(state => state.queries.payees);
- let { list: categories } = useCategories();
- let accounts = useSelector(state => state.queries.accounts);
+ const payees = useSelector(state => state.queries.payees);
+ const { list: categories } = useCategories();
+ const accounts = useSelector(state => state.queries.accounts);
- let data =
+ const data =
dataProp ||
(field === 'payee'
? payees
@@ -51,7 +51,7 @@ export default function Value({
? accounts
: []);
- let [expanded, setExpanded] = useState(false);
+ const [expanded, setExpanded] = useState(false);
function onExpand(e) {
e.preventDefault();
@@ -92,7 +92,7 @@ export default function Value({
return value;
}
if (data && Array.isArray(data)) {
- let item = data.find(item => item.id === value);
+ const item = data.find(item => item.id === value);
if (item) {
return describe(item);
} else {
@@ -122,12 +122,12 @@ export default function Value({
if (!expanded && value.length > 4) {
displayed = value.slice(0, 3);
}
- let numHidden = value.length - displayed.length;
+ const numHidden = value.length - displayed.length;
return (
[
{displayed.map((v, i) => {
- let text = {formatValue(v)};
+ const text = {formatValue(v)};
let spacing;
if (inline) {
spacing = i !== 0 ? ' ' : '';
diff --git a/packages/desktop-client/src/components/schedules/DiscoverSchedules.tsx b/packages/desktop-client/src/components/schedules/DiscoverSchedules.tsx
index 8315dc33168..74a9f2646d6 100644
--- a/packages/desktop-client/src/components/schedules/DiscoverSchedules.tsx
+++ b/packages/desktop-client/src/components/schedules/DiscoverSchedules.tsx
@@ -142,7 +142,7 @@ export default function DiscoverSchedules({
const selected = schedules.filter(s => selectedInst.items.has(s.id));
setCreating(true);
- for (let schedule of selected) {
+ for (const schedule of selected) {
const scheduleId = await send('schedule/create', {
conditions: schedule._conditions,
schedule: {},
diff --git a/packages/desktop-client/src/components/schedules/EditSchedule.js b/packages/desktop-client/src/components/schedules/EditSchedule.js
index d4d0353973c..3a8d0e0258c 100644
--- a/packages/desktop-client/src/components/schedules/EditSchedule.js
+++ b/packages/desktop-client/src/components/schedules/EditSchedule.js
@@ -27,9 +27,9 @@ import { AmountInput, BetweenAmountInput } from '../util/AmountInput';
import GenericInput from '../util/GenericInput';
function updateScheduleConditions(schedule, fields) {
- let conds = extractScheduleConds(schedule._conditions);
+ const conds = extractScheduleConds(schedule._conditions);
- let updateCond = (cond, op, field, value) => {
+ const updateCond = (cond, op, field, value) => {
if (cond) {
return { ...cond, value };
}
@@ -67,23 +67,23 @@ function updateScheduleConditions(schedule, fields) {
}
export default function ScheduleDetails({ modalProps, actions, id }) {
- let adding = id == null;
- let payees = useCachedPayees({ idKey: true });
- let globalDispatch = useDispatch();
- let dateFormat = useSelector(state => {
+ const adding = id == null;
+ const payees = useCachedPayees({ idKey: true });
+ const globalDispatch = useDispatch();
+ const dateFormat = useSelector(state => {
return state.prefs.local.dateFormat || 'MM/dd/yyyy';
});
- let [state, dispatch] = useReducer(
+ const [state, dispatch] = useReducer(
(state, action) => {
switch (action.type) {
case 'set-schedule': {
- let schedule = action.schedule;
+ const schedule = action.schedule;
// See if there are custom rules
- let conds = extractScheduleConds(schedule._conditions);
- let condsSet = new Set(Object.values(conds));
- let isCustom =
+ const conds = extractScheduleConds(schedule._conditions);
+ const condsSet = new Set(Object.values(conds));
+ const isCustom =
schedule._conditions.find(c => !condsSet.has(c)) ||
schedule._actions.find(a => a.op !== 'link-schedule');
@@ -107,7 +107,7 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
throw new Error('Unknown field: ' + action.field);
}
- let fields = { [action.field]: action.value };
+ const fields = { [action.field]: action.value };
// If we are changing the amount operator either to or
// away from the `isbetween` operator, the amount value is
@@ -192,21 +192,21 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
);
async function loadSchedule() {
- let { data } = await runQuery(q('schedules').filter({ id }).select('*'));
+ const { data } = await runQuery(q('schedules').filter({ id }).select('*'));
return data[0];
}
useEffect(() => {
async function run() {
if (adding) {
- let date = {
+ const date = {
start: monthUtils.currentDay(),
frequency: 'monthly',
patterns: [],
skipWeekend: false,
weekendSolveMode: 'after',
};
- let schedule = {
+ const schedule = {
posts_transaction: false,
_date: date,
_conditions: [{ op: 'isapprox', field: 'date', value: date }],
@@ -215,7 +215,7 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
dispatch({ type: 'set-schedule', schedule });
} else {
- let schedule = await loadSchedule();
+ const schedule = await loadSchedule();
if (schedule && state.schedule == null) {
dispatch({ type: 'set-schedule', schedule });
@@ -227,19 +227,19 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
useEffect(() => {
async function run() {
- let date = state.fields.date;
+ const date = state.fields.date;
if (date == null) {
dispatch({ type: 'set-upcoming-dates', dates: null });
} else {
if (date.frequency) {
- let { data } = await sendCatch('schedule/get-upcoming-dates', {
+ const { data } = await sendCatch('schedule/get-upcoming-dates', {
config: date,
count: 3,
});
dispatch({ type: 'set-upcoming-dates', dates: data });
} else {
- let today = monthUtils.currentDay();
+ const today = monthUtils.currentDay();
if (date === today || monthUtils.isAfter(date, today)) {
dispatch({ type: 'set-upcoming-dates', dates: [date] });
} else {
@@ -257,7 +257,7 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
state.schedule.id &&
state.transactionsMode === 'linked'
) {
- let live = liveQuery(
+ const live = liveQuery(
q('transactions')
.filter({ schedule: state.schedule.id })
.select('*')
@@ -273,10 +273,8 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
let unsubscribe;
if (state.schedule && state.transactionsMode === 'matched') {
- let { error, conditions } = updateScheduleConditions(
- state.schedule,
- state.fields,
- );
+ const { error, conditions: originalConditions } =
+ updateScheduleConditions(state.schedule, state.fields);
if (error) {
dispatch({ type: 'form-error', error });
@@ -286,7 +284,7 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
// *Extremely* gross hack because the rules are not mapped to
// public names automatically. We really should be doing that
// at the database layer
- conditions = conditions.map(cond => {
+ const conditions = originalConditions.map(cond => {
if (cond.field === 'description') {
return { ...cond, field: 'payee' };
} else if (cond.field === 'acct') {
@@ -299,7 +297,7 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
conditions,
}).then(({ filters }) => {
if (current) {
- let live = liveQuery(
+ const live = liveQuery(
q('transactions')
.filter({ $and: filters })
.select('*')
@@ -319,12 +317,12 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
};
}, [state.schedule, state.transactionsMode, state.fields]);
- let selectedInst = useSelected('transactions', state.transactions, []);
+ const selectedInst = useSelected('transactions', state.transactions, []);
async function onSave() {
dispatch({ type: 'form-error', error: null });
if (state.fields.name) {
- let { data: sameName } = await runQuery(
+ const { data: sameName } = await runQuery(
q('schedules').filter({ name: state.fields.name }).select('id'),
);
if (sameName.length > 0 && sameName[0].id !== state.schedule.id) {
@@ -336,7 +334,7 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
}
}
- let { error, conditions } = updateScheduleConditions(
+ const { error, conditions } = updateScheduleConditions(
state.schedule,
state.fields,
);
@@ -346,14 +344,17 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
return;
}
- let res = await sendCatch(adding ? 'schedule/create' : 'schedule/update', {
- schedule: {
- id: state.schedule.id,
- posts_transaction: state.fields.posts_transaction,
- name: state.fields.name,
+ const res = await sendCatch(
+ adding ? 'schedule/create' : 'schedule/update',
+ {
+ schedule: {
+ id: state.schedule.id,
+ posts_transaction: state.fields.posts_transaction,
+ name: state.fields.name,
+ },
+ conditions,
},
- conditions,
- });
+ );
if (res.error) {
dispatch({
@@ -370,13 +371,13 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
}
async function onEditRule(ruleId) {
- let rule = await send('rule-get', { id: ruleId || state.schedule.rule });
+ const rule = await send('rule-get', { id: ruleId || state.schedule.rule });
globalDispatch(
pushModal('edit-rule', {
rule,
onSave: async () => {
- let schedule = await loadSchedule();
+ const schedule = await loadSchedule();
dispatch({ type: 'set-schedule', schedule });
},
}),
@@ -409,10 +410,10 @@ export default function ScheduleDetails({ modalProps, actions, id }) {
selectedInst.dispatch({ type: 'select-none' });
}
- let payee = payees ? payees[state.fields.payee] : null;
+ const payee = payees ? payees[state.fields.payee] : null;
// This is derived from the date
- let repeats = state.fields.date ? !!state.fields.date.frequency : false;
+ const repeats = state.fields.date ? !!state.fields.date.frequency : false;
return (
q.filter({ completed: false }), []),
});
- let searchInput = useRef(null);
+ const searchInput = useRef(null);
if (scheduleData == null) {
return null;
}
- let { schedules, statuses } = scheduleData;
+ const { schedules, statuses } = scheduleData;
async function onSelect(scheduleId: string) {
if (ids?.length > 0) {
diff --git a/packages/desktop-client/src/components/schedules/PostsOfflineNotification.js b/packages/desktop-client/src/components/schedules/PostsOfflineNotification.js
index 5f991b5d78e..48c5c2d2edd 100644
--- a/packages/desktop-client/src/components/schedules/PostsOfflineNotification.js
+++ b/packages/desktop-client/src/components/schedules/PostsOfflineNotification.js
@@ -12,10 +12,10 @@ import Text from '../common/Text';
import DisplayId from '../util/DisplayId';
export default function PostsOfflineNotification({ modalProps, actions }) {
- let location = useLocation();
+ const location = useLocation();
- let payees = (location.state && location.state.payees) || [];
- let plural = payees.length > 1;
+ const payees = (location.state && location.state.payees) || [];
+ const plural = payees.length > 1;
async function onPost() {
await send('schedule/force-run-service');
diff --git a/packages/desktop-client/src/components/select/DateSelect.tsx b/packages/desktop-client/src/components/select/DateSelect.tsx
index e08d8e60bb0..0e3754bf2cc 100644
--- a/packages/desktop-client/src/components/select/DateSelect.tsx
+++ b/packages/desktop-client/src/components/select/DateSelect.tsx
@@ -33,7 +33,7 @@ import { Tooltip } from '../tooltips';
import DateSelectLeft from './DateSelect.left.png';
import DateSelectRight from './DateSelect.right.png';
-let pickerStyles = {
+const pickerStyles = {
'& .pika-single.actual-date-picker': {
color: theme.calendarText,
background: theme.calendarBackground,
@@ -89,10 +89,10 @@ type DatePickerProps = {
type DatePickerForwardedRef = {
handleInputKeyDown: (e: KeyboardEvent) => void;
};
-let DatePicker = forwardRef(
+const DatePicker = forwardRef(
({ value, firstDayOfWeekIdx, dateFormat, onUpdate, onSelect }, ref) => {
- let picker = useRef(null);
- let mountPoint = useRef(null);
+ const picker = useRef(null);
+ const mountPoint = useRef(null);
useImperativeHandle(
ref,
@@ -200,9 +200,9 @@ export default function DateSelect({
onUpdate,
onSelect,
}: DateSelectProps) {
- let parsedDefaultValue = useMemo(() => {
+ const parsedDefaultValue = useMemo(() => {
if (defaultValue) {
- let date = parseISO(defaultValue);
+ const date = parseISO(defaultValue);
if (isValid(date)) {
return format(date, dateFormat);
}
@@ -210,10 +210,10 @@ export default function DateSelect({
return '';
}, [defaultValue, dateFormat]);
- let picker = useRef(null);
- let [value, setValue] = useState(parsedDefaultValue);
- let [open, setOpen] = useState(embedded || isOpen || false);
- let inputRef = useRef(null);
+ const picker = useRef(null);
+ const [value, setValue] = useState(parsedDefaultValue);
+ const [open, setOpen] = useState(embedded || isOpen || false);
+ const inputRef = useRef(null);
useLayoutEffect(() => {
if (originalInputRef) {
@@ -227,8 +227,8 @@ export default function DateSelect({
// around. `userSelectedValue` represents the last value that the
// user actually selected (with enter or click). Having both allows
// us to make various UX decisions
- let [selectedValue, setSelectedValue] = useState(value);
- let userSelectedValue = useRef(selectedValue);
+ const [selectedValue, setSelectedValue] = useState(value);
+ const userSelectedValue = useRef(selectedValue);
const firstDayOfWeekIdx = useSelector(state =>
state.prefs.local?.firstDayOfWeekIdx
@@ -247,22 +247,22 @@ export default function DateSelect({
// Support only entering the month and day (4/5). This is complex
// because of the various date formats - we need to derive
// the right day/month format from it
- let test = parse(value, getDayMonthFormat(dateFormat), new Date());
+ const test = parse(value, getDayMonthFormat(dateFormat), new Date());
if (isValid(test)) {
onUpdate?.(format(test, 'yyyy-MM-dd'));
setSelectedValue(format(test, dateFormat));
}
} else if (getShortYearRegex(dateFormat).test(value)) {
// Support entering the year as only two digits (4/5/19)
- let test = parse(value, getShortYearFormat(dateFormat), new Date());
+ const test = parse(value, getShortYearFormat(dateFormat), new Date());
if (isValid(test)) {
onUpdate?.(format(test, 'yyyy-MM-dd'));
setSelectedValue(format(test, dateFormat));
}
} else {
- let test = parse(value, dateFormat, new Date());
+ const test = parse(value, dateFormat, new Date());
if (isValid(test)) {
- let date = format(test, 'yyyy-MM-dd');
+ const date = format(test, 'yyyy-MM-dd');
onUpdate?.(date);
setSelectedValue(value);
}
@@ -298,7 +298,7 @@ export default function DateSelect({
setValue(selectedValue);
setOpen(false);
- let date = parse(selectedValue, dateFormat, new Date());
+ const date = parse(selectedValue, dateFormat, new Date());
onSelect(format(date, 'yyyy-MM-dd'));
if (open && e.key === 'Enter') {
@@ -307,7 +307,7 @@ export default function DateSelect({
e.preventDefault();
}
- let { onKeyDown } = inputProps || {};
+ const { onKeyDown } = inputProps || {};
onKeyDown?.(e);
} else if (!open) {
setOpen(true);
@@ -321,7 +321,7 @@ export default function DateSelect({
setValue(e.target.value);
}
- let maybeWrapTooltip = content => {
+ const maybeWrapTooltip = content => {
return embedded ? (
content
) : (
@@ -372,7 +372,7 @@ export default function DateSelect({
} else {
setValue(selectedValue || '');
- let date = parse(selectedValue, dateFormat, new Date());
+ const date = parse(selectedValue, dateFormat, new Date());
if (date instanceof Date && !isNaN(date.valueOf())) {
onSelect(format(date, 'yyyy-MM-dd'));
}
diff --git a/packages/desktop-client/src/components/select/RecurringSchedulePicker.js b/packages/desktop-client/src/components/select/RecurringSchedulePicker.js
index 2c5b47c16e7..d6f4525e30b 100644
--- a/packages/desktop-client/src/components/select/RecurringSchedulePicker.js
+++ b/packages/desktop-client/src/components/select/RecurringSchedulePicker.js
@@ -202,7 +202,7 @@ function validInterval(interval) {
}
function MonthlyPatterns({ config, dispatch }) {
- let updateRecurrence = (recurrence, field, value) =>
+ const updateRecurrence = (recurrence, field, value) =>
dispatch({ type: 'update-recurrence', recurrence, field, value });
return (
@@ -269,16 +269,16 @@ function MonthlyPatterns({ config, dispatch }) {
}
function RecurringScheduleTooltip({ config: currentConfig, onClose, onSave }) {
- let [previewDates, setPreviewDates] = useState(null);
+ const [previewDates, setPreviewDates] = useState(null);
- let [state, dispatch] = useReducer(reducer, {
+ const [state, dispatch] = useReducer(reducer, {
config: parseConfig(currentConfig),
});
- let skipWeekend = state.config.hasOwnProperty('skipWeekend')
+ const skipWeekend = state.config.hasOwnProperty('skipWeekend')
? state.config.skipWeekend
: false;
- let dateFormat = useSelector(
+ const dateFormat = useSelector(
state => state.prefs.local.dateFormat || 'MM/dd/yyyy',
);
@@ -289,14 +289,14 @@ function RecurringScheduleTooltip({ config: currentConfig, onClose, onSave }) {
});
}, [currentConfig]);
- let { config } = state;
+ const { config } = state;
- let updateField = (field, value) =>
+ const updateField = (field, value) =>
dispatch({ type: 'change-field', field, value });
useEffect(() => {
async function run() {
- let { data, error } = await sendCatch('schedule/get-upcoming-dates', {
+ const { data, error } = await sendCatch('schedule/get-upcoming-dates', {
config: unparseConfig(config),
count: 4,
});
@@ -440,7 +440,7 @@ export default function RecurringSchedulePicker({
buttonStyle,
onChange,
}) {
- let { isOpen, close, getOpenEvents } = useTooltip();
+ const { isOpen, close, getOpenEvents } = useTooltip();
function onSave(config) {
onChange(config);
diff --git a/packages/desktop-client/src/components/settings/Experimental.tsx b/packages/desktop-client/src/components/settings/Experimental.tsx
index 38aaf4981a5..e82840a4a77 100644
--- a/packages/desktop-client/src/components/settings/Experimental.tsx
+++ b/packages/desktop-client/src/components/settings/Experimental.tsx
@@ -26,8 +26,8 @@ function FeatureToggle({
error,
children,
}: FeatureToggleProps) {
- let { savePrefs } = useActions();
- let enabled = useFeatureFlag(flag);
+ const { savePrefs } = useActions();
+ const enabled = useFeatureFlag(flag);
return (
);
}
diff --git a/packages/desktop-client/src/components/sidebar/Account.tsx b/packages/desktop-client/src/components/sidebar/Account.tsx
index a59337f2763..d0f7ef70105 100644
--- a/packages/desktop-client/src/components/sidebar/Account.tsx
+++ b/packages/desktop-client/src/components/sidebar/Account.tsx
@@ -58,7 +58,7 @@ function Account({
onDragChange,
onDrop,
}: AccountProps) {
- let type = account
+ const type = account
? account.closed
? 'account-closed'
: account.offbudget
@@ -66,14 +66,14 @@ function Account({
: 'account-onbudget'
: 'title';
- let { dragRef } = useDraggable({
+ const { dragRef } = useDraggable({
type,
onDragChange,
item: { id: account && account.id },
canDrag: account != null,
});
- let { dropRef, dropPos } = useDroppable({
+ const { dropRef, dropPos } = useDroppable({
types: account ? [type] : [],
id: account && account.id,
onDrop,
diff --git a/packages/desktop-client/src/components/sidebar/Accounts.tsx b/packages/desktop-client/src/components/sidebar/Accounts.tsx
index d250ec3311a..e15559709b2 100644
--- a/packages/desktop-client/src/components/sidebar/Accounts.tsx
+++ b/packages/desktop-client/src/components/sidebar/Accounts.tsx
@@ -53,22 +53,22 @@ function Accounts({
onToggleClosedAccounts,
onReorder,
}: AccountsProps) {
- let [isDragging, setIsDragging] = useState(false);
- let offbudgetAccounts = useMemo(
+ const [isDragging, setIsDragging] = useState(false);
+ const offbudgetAccounts = useMemo(
() =>
accounts.filter(
account => account.closed === 0 && account.offbudget === 1,
),
[accounts],
);
- let budgetedAccounts = useMemo(
+ const budgetedAccounts = useMemo(
() =>
accounts.filter(
account => account.closed === 0 && account.offbudget === 0,
),
[accounts],
);
- let closedAccounts = useMemo(
+ const closedAccounts = useMemo(
() => accounts.filter(account => account.closed === 1),
[accounts],
);
@@ -77,7 +77,7 @@ function Accounts({
setIsDragging(drag.state === 'start');
}
- let makeDropPadding = (i, length) => {
+ const makeDropPadding = (i, length) => {
if (i === 0) {
return {
paddingTop: isDragging ? 15 : 0,
diff --git a/packages/desktop-client/src/components/sidebar/Sidebar.tsx b/packages/desktop-client/src/components/sidebar/Sidebar.tsx
index 7b51e2d7a8f..c6aa9435979 100644
--- a/packages/desktop-client/src/components/sidebar/Sidebar.tsx
+++ b/packages/desktop-client/src/components/sidebar/Sidebar.tsx
@@ -61,7 +61,7 @@ function Sidebar({
onToggleClosedAccounts,
onReorder,
}: SidebarProps) {
- let hasWindowButtons = !Platform.isBrowser && Platform.OS === 'mac';
+ const hasWindowButtons = !Platform.isBrowser && Platform.OS === 'mac';
const sidebar = useSidebar();
diff --git a/packages/desktop-client/src/components/sidebar/SidebarWithData.tsx b/packages/desktop-client/src/components/sidebar/SidebarWithData.tsx
index 5fa7122b7b4..3ea71ba13f9 100644
--- a/packages/desktop-client/src/components/sidebar/SidebarWithData.tsx
+++ b/packages/desktop-client/src/components/sidebar/SidebarWithData.tsx
@@ -26,8 +26,8 @@ type EditableBudgetNameProps = {
};
function EditableBudgetName({ prefs, savePrefs }: EditableBudgetNameProps) {
- let dispatch = useDispatch();
- let navigate = useNavigate();
+ const dispatch = useDispatch();
+ const navigate = useNavigate();
const [editing, setEditing] = useState(false);
const [menuOpen, setMenuOpen] = useState(false);
@@ -51,7 +51,7 @@ function EditableBudgetName({ prefs, savePrefs }: EditableBudgetNameProps) {
}
}
- let items = [
+ const items = [
{ name: 'rename', text: 'Rename budget' },
{ name: 'settings', text: 'Settings' },
...(Platform.isBrowser ? [{ name: 'help', text: 'Help' }] : []),
@@ -114,21 +114,22 @@ function EditableBudgetName({ prefs, savePrefs }: EditableBudgetNameProps) {
}
function SidebarWithData() {
- let accounts = useSelector(state => state.queries.accounts);
- let failedAccounts = useSelector(state => state.account.failedAccounts);
- let updatedAccounts = useSelector(state => state.queries.updatedAccounts);
- let prefs = useSelector(state => state.prefs.local);
- let floatingSidebar = useSelector(
+ const accounts = useSelector(state => state.queries.accounts);
+ const failedAccounts = useSelector(state => state.account.failedAccounts);
+ const updatedAccounts = useSelector(state => state.queries.updatedAccounts);
+ const prefs = useSelector(state => state.prefs.local);
+ const floatingSidebar = useSelector(
state => state.prefs.global.floatingSidebar,
);
- let { getAccounts, replaceModal, savePrefs, saveGlobalPrefs } = useActions();
+ const { getAccounts, replaceModal, savePrefs, saveGlobalPrefs } =
+ useActions();
useEffect(() => void getAccounts(), [getAccounts]);
async function onReorder(id, dropPos, targetId) {
if (dropPos === 'bottom') {
- let idx = accounts.findIndex(a => a.id === targetId) + 1;
+ const idx = accounts.findIndex(a => a.id === targetId) + 1;
targetId = idx < accounts.length ? accounts[idx].id : null;
}
diff --git a/packages/desktop-client/src/components/sidebar/Tools.tsx b/packages/desktop-client/src/components/sidebar/Tools.tsx
index d07e50ea8b8..e8bad134a41 100644
--- a/packages/desktop-client/src/components/sidebar/Tools.tsx
+++ b/packages/desktop-client/src/components/sidebar/Tools.tsx
@@ -12,9 +12,9 @@ import Item from './Item';
import SecondaryItem from './SecondaryItem';
function Tools() {
- let [isOpen, setOpen] = useState(false);
- let onToggle = useCallback(() => setOpen(open => !open), []);
- let location = useLocation();
+ const [isOpen, setOpen] = useState(false);
+ const onToggle = useCallback(() => setOpen(open => !open), []);
+ const location = useLocation();
const isActive = ['/payees', '/rules', '/settings', '/tools'].some(route =>
location.pathname.startsWith(route),
diff --git a/packages/desktop-client/src/components/sidebar/index.tsx b/packages/desktop-client/src/components/sidebar/index.tsx
index 8735f354f41..1ed74fb329e 100644
--- a/packages/desktop-client/src/components/sidebar/index.tsx
+++ b/packages/desktop-client/src/components/sidebar/index.tsx
@@ -29,13 +29,13 @@ type SidebarProviderProps = {
};
function SidebarProvider({ children }: SidebarProviderProps) {
- let floatingSidebar = useSelector(
+ const floatingSidebar = useSelector(
state => state.prefs.global.floatingSidebar,
);
- let [hidden, setHidden] = useState(true);
- let { width } = useResponsive();
- let alwaysFloats = width < 668;
- let floating = floatingSidebar || alwaysFloats;
+ const [hidden, setHidden] = useState(true);
+ const { width } = useResponsive();
+ const alwaysFloats = width < 668;
+ const floating = floatingSidebar || alwaysFloats;
return (
state.prefs.global.floatingSidebar,
);
- let sidebar = useSidebar();
- let { isNarrowWidth } = useResponsive();
+ const sidebar = useSidebar();
+ const { isNarrowWidth } = useResponsive();
- let sidebarShouldFloat = floatingSidebar || sidebar.alwaysFloats;
+ const sidebarShouldFloat = floatingSidebar || sidebar.alwaysFloats;
return isNarrowWidth ? null : (
({
canDrag,
onDragChange,
}: UseDraggableArgs) {
- let _onDragChange = useRef(onDragChange);
+ const _onDragChange = useRef(onDragChange);
const [, dragRef] = useDrag({
type,
@@ -92,20 +92,21 @@ export function useDroppable({
onDrop,
onLongHover,
}: UseDroppableArgs) {
- let ref = useRef(null);
- let [dropPos, setDropPos] = useState(null);
+ const ref = useRef(null);
+ const [dropPos, setDropPos] = useState(null);
- let [{ isOver }, dropRef] = useDrop({
+ const [{ isOver }, dropRef] = useDrop({
accept: types,
drop({ item }) {
onDrop(item.id, dropPos, id);
},
hover(_, monitor) {
- let hoverBoundingRect = ref.current.getBoundingClientRect();
- let hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
- let clientOffset = monitor.getClientOffset();
- let hoverClientY = clientOffset.y - hoverBoundingRect.top;
- let pos: DropPosition = hoverClientY < hoverMiddleY ? 'top' : 'bottom';
+ const hoverBoundingRect = ref.current.getBoundingClientRect();
+ const hoverMiddleY =
+ (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
+ const clientOffset = monitor.getClientOffset();
+ const hoverClientY = clientOffset.y - hoverBoundingRect.top;
+ const pos: DropPosition = hoverClientY < hoverMiddleY ? 'top' : 'bottom';
setDropPos(pos);
},
@@ -141,16 +142,16 @@ type DropHighlightProps = {
};
};
export function DropHighlight({ pos, offset }: DropHighlightProps) {
- let itemPos = useContext(DropHighlightPosContext);
+ const itemPos = useContext(DropHighlightPosContext);
if (pos == null) {
return null;
}
- let topOffset = (itemPos === 'first' ? 2 : 0) + (offset?.top || 0);
- let bottomOffset = (itemPos === 'last' ? 2 : 0) + (offset?.bottom || 0);
+ const topOffset = (itemPos === 'first' ? 2 : 0) + (offset?.top || 0);
+ const bottomOffset = (itemPos === 'last' ? 2 : 0) + (offset?.bottom || 0);
- let posStyle =
+ const posStyle =
pos === 'top' ? { top: -2 + topOffset } : { bottom: -1 + bottomOffset };
return (
diff --git a/packages/desktop-client/src/components/spreadsheet/CellValue.tsx b/packages/desktop-client/src/components/spreadsheet/CellValue.tsx
index 6c1e725826c..02bee9c23db 100644
--- a/packages/desktop-client/src/components/spreadsheet/CellValue.tsx
+++ b/packages/desktop-client/src/components/spreadsheet/CellValue.tsx
@@ -33,9 +33,9 @@ function CellValue({
'data-testid': testId,
...props
}: CellValueProps) {
- let { fullSheetName } = useSheetName(binding);
- let sheetValue = useSheetValue(binding);
- let format = useFormat();
+ const { fullSheetName } = useSheetName(binding);
+ const sheetValue = useSheetValue(binding);
+ const format = useFormat();
return (
= 0) {
return '+' + formatted;
}
diff --git a/packages/desktop-client/src/components/spreadsheet/useSheetName.ts b/packages/desktop-client/src/components/spreadsheet/useSheetName.ts
index a08fac549b1..8b80e5ac28c 100644
--- a/packages/desktop-client/src/components/spreadsheet/useSheetName.ts
+++ b/packages/desktop-client/src/components/spreadsheet/useSheetName.ts
@@ -5,7 +5,7 @@ import NamespaceContext from './NamespaceContext';
import { type Binding } from '.';
function unresolveName(name) {
- let idx = name.indexOf('!');
+ const idx = name.indexOf('!');
if (idx !== -1) {
return {
sheet: name.slice(0, idx),
@@ -35,7 +35,7 @@ export default function useSheetName(binding: Binding) {
// Get the current sheet name, and unresolve the binding name if
// necessary (you might pass a fully resolved name like foo!name)
let sheetName = useContext(NamespaceContext) || '__global';
- let unresolved = unresolveName(bindingName);
+ const unresolved = unresolveName(bindingName);
if (unresolved.sheet) {
sheetName = unresolved.sheet;
bindingName = unresolved.name;
diff --git a/packages/desktop-client/src/components/spreadsheet/useSheetValue.ts b/packages/desktop-client/src/components/spreadsheet/useSheetValue.ts
index 154ea11fd10..faac71e234c 100644
--- a/packages/desktop-client/src/components/spreadsheet/useSheetValue.ts
+++ b/packages/desktop-client/src/components/spreadsheet/useSheetValue.ts
@@ -10,19 +10,19 @@ export default function useSheetValue(
binding: Binding,
onChange?: (result) => void,
) {
- let { sheetName, fullSheetName } = useSheetName(binding);
+ const { sheetName, fullSheetName } = useSheetName(binding);
const bindingObj =
typeof binding === 'string' ? { name: binding, value: null } : binding;
- let spreadsheet = useSpreadsheet();
- let [result, setResult] = useState({
+ const spreadsheet = useSpreadsheet();
+ const [result, setResult] = useState({
name: fullSheetName,
value: bindingObj.value === undefined ? null : bindingObj.value,
query: bindingObj.query,
});
- let latestOnChange = useRef(onChange);
- let latestValue = useRef(result.value);
+ const latestOnChange = useRef(onChange);
+ const latestValue = useRef(result.value);
useLayoutEffect(() => {
latestOnChange.current = onChange;
diff --git a/packages/desktop-client/src/components/table.tsx b/packages/desktop-client/src/components/table.tsx
index e11e65a6864..42e41e6b7e3 100644
--- a/packages/desktop-client/src/components/table.tsx
+++ b/packages/desktop-client/src/components/table.tsx
@@ -162,8 +162,8 @@ export function Cell({
privacyFilter,
...viewProps
}: CellProps) {
- let mouseCoords = useRef(null);
- let viewRef = useRef(null);
+ const mouseCoords = useRef(null);
+ const viewRef = useRef(null);
useProperFocus(viewRef, focused !== undefined ? focused : exposed);
@@ -179,7 +179,7 @@ export function Cell({
alignItems,
};
- let conditionalPrivacyFilter = useMemo(
+ const conditionalPrivacyFilter = useMemo(
() => (
{
+ const sheetValue = useSheetValue(binding, e => {
// "close" the cell if it's editing
if (props.exposed && inputProps && inputProps.onBlur) {
inputProps.onBlur(e);
}
});
- let format = useFormat();
+ const format = useFormat();
return (
,
TableWithNavigatorProps
>(({ fields, ...props }, ref) => {
- let navigator = useTableNavigator(props.items, fields);
+ const navigator = useTableNavigator(props.items, fields);
return ;
});
@@ -922,16 +922,16 @@ export const Table: (
};
}
- let { onEdit, editingId, focusedField, getNavigatorProps } = navigator;
- let list = useRef(null);
- let listContainer = useRef(null);
- let scrollContainer = useRef(null);
- let initialScrollTo = useRef(null);
- let listInitialized = useRef(false);
+ const { onEdit, editingId, focusedField, getNavigatorProps } = navigator;
+ const list = useRef(null);
+ const listContainer = useRef(null);
+ const scrollContainer = useRef(null);
+ const initialScrollTo = useRef(null);
+ const listInitialized = useRef(false);
useImperativeHandle(ref, () => ({
scrollTo: (id, alignment = 'smart') => {
- let index = items.findIndex(item => item.id === id);
+ const index = items.findIndex(item => item.id === id);
if (index !== -1) {
if (!list.current) {
// If the table hasn't been laid out yet, we need to wait for
@@ -949,8 +949,8 @@ export const Table: (
getScrolledItem: () => {
if (scrollContainer.current) {
- let offset = scrollContainer.current.scrollTop;
- let index = list.current.getStartIndexForOffset(offset);
+ const offset = scrollContainer.current.scrollTop;
+ const index = list.current.getStartIndexForOffset(offset);
return items[index].id;
}
return 0;
@@ -1002,11 +1002,11 @@ export const Table: (
});
function renderRow({ index, style, key }) {
- let item = items[index];
- let editing = editingId === item.id;
- let selected = isSelected && isSelected(item.id);
+ const item = items[index];
+ const editing = editingId === item.id;
+ const selected = isSelected && isSelected(item.id);
- let row = renderItem({
+ const row = renderItem({
item,
editing,
focusedField: editing && focusedField,
@@ -1087,7 +1087,7 @@ export const Table: (
);
}
- let isEmpty = (count || items.length) === 0;
+ const isEmpty = (count || items.length) === 0;
return (
(
data: T[],
fields: string[] | ((item?: T) => string[]),
): TableNavigator {
- let getFields = typeof fields !== 'function' ? () => fields : fields;
- let [editingId, setEditingId] = useState(null);
- let [focusedField, setFocusedField] = useState(null);
- let containerRef = useRef();
+ const getFields = typeof fields !== 'function' ? () => fields : fields;
+ const [editingId, setEditingId] = useState(null);
+ const [focusedField, setFocusedField] = useState(null);
+ const containerRef = useRef();
// See `onBlur` for why we need this
- let store = useStore();
- let modalStackLength = useRef(0);
+ const store = useStore();
+ const modalStackLength = useRef(0);
// onEdit is passed to children, so make sure it maintains identity
- let onEdit = useCallback((id: T['id'], field?: string) => {
+ const onEdit = useCallback((id: T['id'], field?: string) => {
setEditingId(id);
setFocusedField(id ? field : null);
}, []);
@@ -1210,10 +1210,10 @@ export function useTableNavigator(
}
function onFocusPrevious() {
- let idx = data.findIndex(item => item.id === editingId);
+ const idx = data.findIndex(item => item.id === editingId);
if (idx > 0) {
- let item = data[idx - 1];
- let fields = getFields(item);
+ const item = data[idx - 1];
+ const fields = getFields(item);
onEdit(item.id, fields[fields.length - 1]);
} else {
flashInput();
@@ -1221,10 +1221,10 @@ export function useTableNavigator(
}
function onFocusNext() {
- let idx = data.findIndex(item => item.id === editingId);
+ const idx = data.findIndex(item => item.id === editingId);
if (idx < data.length - 1) {
- let item = data[idx + 1];
- let fields = getFields(item);
+ const item = data[idx + 1];
+ const fields = getFields(item);
onEdit(item.id, fields[0]);
} else {
flashInput();
@@ -1233,8 +1233,8 @@ export function useTableNavigator(
function moveHorizontally(dir) {
if (editingId) {
- let fields = getFields(data.find(item => item.id === editingId));
- let idx = fields.indexOf(focusedField) + dir;
+ const fields = getFields(data.find(item => item.id === editingId));
+ const idx = fields.indexOf(focusedField) + dir;
if (idx < 0) {
onFocusPrevious();
@@ -1248,7 +1248,7 @@ export function useTableNavigator(
function moveVertically(dir) {
if (editingId) {
- let idx = data.findIndex(item => item.id === editingId);
+ const idx = data.findIndex(item => item.id === editingId);
let nextIdx = idx;
while (true) {
@@ -1346,8 +1346,8 @@ export function useTableNavigator(
// The last tricky edge case: we don't want to blur if a new
// modal just opened. This way the field still shows an
// input, and it will be refocused when the modal closes.
- let prevNumModals = modalStackLength.current;
- let numModals = store.getState().modals.modalStack.length;
+ const prevNumModals = modalStackLength.current;
+ const numModals = store.getState().modals.modalStack.length;
if (
document.hasFocus() &&
diff --git a/packages/desktop-client/src/components/tooltips.js b/packages/desktop-client/src/components/tooltips.js
index 6969e63d3f4..99039766883 100644
--- a/packages/desktop-client/src/components/tooltips.js
+++ b/packages/desktop-client/src/components/tooltips.js
@@ -8,7 +8,7 @@ import { styles, theme } from '../style';
export const IntersectionBoundary = createContext();
export function useTooltip() {
- let [isOpen, setIsOpen] = useState(false);
+ const [isOpen, setIsOpen] = useState(false);
return {
getOpenEvents: (events = {}) => ({
@@ -37,7 +37,7 @@ export class Tooltip extends Component {
setup() {
this.layout();
- let pointerDownHandler = e => {
+ const pointerDownHandler = e => {
let node = e.target;
while (node && node !== document.documentElement) {
@@ -56,7 +56,7 @@ export class Tooltip extends Component {
}
};
- let escHandler = e => {
+ const escHandler = e => {
if (e.key === 'Escape') {
this.props.onClose?.();
}
@@ -108,7 +108,7 @@ export class Tooltip extends Component {
}
getContainer() {
- let { ignoreBoundary = false } = this.props;
+ const { ignoreBoundary = false } = this.props;
if (!ignoreBoundary && this.context) {
return this.context.current;
@@ -119,7 +119,7 @@ export class Tooltip extends Component {
getBoundsContainer() {
// If the container is a scrollable element, we want to do all the
// bounds checking on the parent DOM element instead
- let container = this.getContainer();
+ const container = this.getContainer();
if (
container.parentNode &&
@@ -131,14 +131,14 @@ export class Tooltip extends Component {
}
layout() {
- let { targetRect, offset = 0 } = this.props;
- let contentEl = this.contentRef.current;
+ const { targetRect, offset = 0 } = this.props;
+ const contentEl = this.contentRef.current;
if (!contentEl) {
return;
}
- let box = contentEl.getBoundingClientRect();
- let anchorEl = this.target.parentNode;
+ const box = contentEl.getBoundingClientRect();
+ const anchorEl = this.target.parentNode;
let anchorRect = targetRect || anchorEl.getBoundingClientRect();
@@ -150,12 +150,12 @@ export class Tooltip extends Component {
height: anchorRect.height,
};
- let container = this.getBoundsContainer();
+ const container = this.getBoundsContainer();
if (!container) {
return;
}
- let containerRect = container.getBoundingClientRect();
+ const containerRect = container.getBoundingClientRect();
anchorRect.left -= containerRect.left;
anchorRect.top -= containerRect.top;
@@ -165,9 +165,9 @@ export class Tooltip extends Component {
if (this.props.forceTop) {
anchorRect.top = this.props.forceTop;
} else {
- let boxHeight = box.height + offset;
- let testTop = anchorRect.top - boxHeight;
- let testBottom = anchorRect.top + anchorRect.height + boxHeight;
+ const boxHeight = box.height + offset;
+ const testTop = anchorRect.top - boxHeight;
+ const testBottom = anchorRect.top + anchorRect.height + boxHeight;
if (
// If it doesn't fit above it, switch it to below
diff --git a/packages/desktop-client/src/components/transactions/MobileTransaction.js b/packages/desktop-client/src/components/transactions/MobileTransaction.js
index 499f02e677b..369ea54da8f 100644
--- a/packages/desktop-client/src/components/transactions/MobileTransaction.js
+++ b/packages/desktop-client/src/components/transactions/MobileTransaction.js
@@ -7,7 +7,7 @@ import React, {
useRef,
} from 'react';
import { useSelector } from 'react-redux';
-import { useParams, Link } from 'react-router-dom';
+import { useParams } from 'react-router-dom';
import { useFocusRing } from '@react-aria/focus';
import { useListBox, useListBoxSection, useOption } from '@react-aria/listbox';
@@ -48,7 +48,6 @@ import useCategories from '../../hooks/useCategories';
import useNavigate from '../../hooks/useNavigate';
import { useSetThemeColor } from '../../hooks/useSetThemeColor';
import SvgAdd from '../../icons/v1/Add';
-import CheveronLeft from '../../icons/v1/CheveronLeft';
import SvgTrash from '../../icons/v1/Trash';
import ArrowsSynchronize from '../../icons/v2/ArrowsSynchronize';
import CheckCircle1 from '../../icons/v2/CheckCircle1';
@@ -66,14 +65,16 @@ import {
InputField,
BooleanField,
} from '../mobile/MobileForms';
+import MobileBackButton from '../MobileBackButton';
+import { Page } from '../Page';
const zIndices = { SECTION_HEADING: 10 };
-let getPayeesById = memoizeOne(payees => groupById(payees));
-let getAccountsById = memoizeOne(accounts => groupById(accounts));
+const getPayeesById = memoizeOne(payees => groupById(payees));
+const getAccountsById = memoizeOne(accounts => groupById(accounts));
function getDescriptionPretty(transaction, payee, transferAcct) {
- let { amount } = transaction;
+ const { amount } = transaction;
if (transferAcct) {
return `Transfer ${amount > 0 ? 'from' : 'to'} ${transferAcct.name}`;
@@ -85,7 +86,7 @@ function getDescriptionPretty(transaction, payee, transferAcct) {
}
function serializeTransaction(transaction, dateFormat) {
- let { date, amount } = transaction;
+ const { date, amount } = transaction;
return {
...transaction,
date: formatDate(parseISO(date), dateFormat),
@@ -94,11 +95,12 @@ function serializeTransaction(transaction, dateFormat) {
}
function deserializeTransaction(transaction, originalTransaction, dateFormat) {
- let { amount, date, ...realTransaction } = transaction;
+ const { amount, date: originalDate, ...realTransaction } = transaction;
- let dayMonth = monthUtils.getDayMonthRegex(dateFormat);
+ const dayMonth = monthUtils.getDayMonthRegex(dateFormat);
+ let date = originalDate;
if (dayMonth.test(date)) {
- let test = parseDate(
+ const test = parseDate(
date,
monthUtils.getDayMonthFormat(dateFormat),
new Date(),
@@ -109,7 +111,7 @@ function deserializeTransaction(transaction, originalTransaction, dateFormat) {
date = null;
}
} else {
- let test = parseDate(date, dateFormat, new Date());
+ const test = parseDate(date, dateFormat, new Date());
// This is a quick sanity check to make sure something invalid
// like "year 201" was entered
if (test.getFullYear() > 2000 && isValidDate(test)) {
@@ -165,9 +167,6 @@ function Status({ status }) {
);
}
-const LEFT_RIGHT_FLEX_WIDTH = 70;
-const BUDGET_HEADER_HEIGHT = 50;
-
class TransactionEditInner extends PureComponent {
constructor(props) {
super(props);
@@ -204,11 +203,11 @@ class TransactionEditInner extends PureComponent {
};
onSave = async () => {
- let onConfirmSave = async () => {
+ const onConfirmSave = async () => {
let { transactions } = this.state;
const [transaction, ..._childTransactions] = transactions;
const { account: accountId } = transaction;
- let account = getAccountsById(this.props.accounts)[accountId];
+ const account = getAccountsById(this.props.accounts)[accountId];
if (transactions.find(t => t.account == null)) {
// Ignore transactions if any of them don't have an account
@@ -221,7 +220,7 @@ class TransactionEditInner extends PureComponent {
// updated value so we "apply" a queued change. Maybe there's a
// better way to do this (lift the state?)
if (this._queuedChange) {
- let [transaction, name, value] = this._queuedChange;
+ const [transaction, name, value] = this._queuedChange;
transactions = await this.onEdit(transaction, name, value);
}
@@ -255,14 +254,14 @@ class TransactionEditInner extends PureComponent {
};
onEdit = async (transaction, name, value) => {
- let { transactions } = this.state;
+ const { transactions } = this.state;
let newTransaction = { ...transaction, [name]: value };
if (this.props.onEdit) {
newTransaction = await this.props.onEdit(newTransaction);
}
- let { data: newTransactions } = updateTransaction(
+ const { data: newTransactions } = updateTransaction(
transactions,
deserializeTransaction(newTransaction, null, this.props.dateFormat),
);
@@ -282,13 +281,13 @@ class TransactionEditInner extends PureComponent {
};
onClick = (transactionId, name) => {
- let { dateFormat } = this.props;
+ const { dateFormat } = this.props;
this.props.pushModal('edit-field', {
name,
onSubmit: (name, value) => {
- let { transactions } = this.state;
- let transaction = transactions.find(t => t.id === transactionId);
+ const { transactions } = this.state;
+ const transaction = transactions.find(t => t.id === transactionId);
// This is a deficiency of this API, need to fix. It
// assumes that it receives a serialized transaction,
// but we only have access to the raw transaction
@@ -298,7 +297,7 @@ class TransactionEditInner extends PureComponent {
};
onDelete = () => {
- let onConfirmDelete = () => {
+ const onConfirmDelete = () => {
this.props.onDelete();
const { transactions } = this.state;
@@ -325,9 +324,7 @@ class TransactionEditInner extends PureComponent {
};
render() {
- const { adding, categories, accounts, payees, renderChildEdit, navigate } =
- this.props;
- const { editingChild } = this.state;
+ const { adding, categories, accounts, payees } = this.props;
const transactions = this.serializeTransactions(
this.state.transactions || [],
);
@@ -336,7 +333,7 @@ class TransactionEditInner extends PureComponent {
// Child transactions should always default to the signage
// of the parent transaction
- const forcedSign = transaction.amount < 0 ? 'negative' : 'positive';
+ // const forcedSign = transaction.amount < 0 ? 'negative' : 'positive';
const account = getAccountsById(accounts)[accountId];
const isOffBudget = account && !!account.offbudget;
@@ -360,350 +357,24 @@ class TransactionEditInner extends PureComponent {
const dateDefaultValue = monthUtils.dayFromDate(transactionDate);
return (
- //
-
-
-
-
-
-
-
-
- Back
-
-
-
-
-
-
-
- {payeeId == null
- ? adding
- ? 'New Transaction'
- : 'Transaction'
- : descriptionPretty}
-
-
- {/* For centering the transaction title */}
-
-
-
- {/* (this.scrollView = el)}
- automaticallyAdjustContentInsets={false}
- keyboardShouldPersistTaps="always"
- style={{
- flexGrow: 1,
- overflow: 'hidden',
- }}
- contentContainerStyle={{ flexGrow: 1 }}
- > */}
-
-
-
- (this.amount = el)}
- value={transaction.amount}
- zeroIsNegative={true}
- onBlur={value =>
- this.onEdit(transaction, 'amount', value.toString())
- }
- onChange={value =>
- this.onQueueChange(transaction, 'amount', value)
- }
- style={{ transform: [] }}
- focusedStyle={{
- width: 'auto',
- padding: '5px',
- paddingLeft: '20px',
- paddingRight: '20px',
- minWidth: 120,
- transform: [{ translateY: -0.5 }],
- }}
- textStyle={{ fontSize: 30, textAlign: 'center' }}
- />
-
-
-
-
- this.onClick(transaction.id, 'payee')}
- data-testid="payee-field"
- />
-
-
-
-
- {!transaction.is_parent ? (
-
- // Split
- // |
- // }
- onClick={() => this.onClick(transaction.id, 'category')}
- data-testid="category-field"
- />
- ) : (
-
- Split transaction editing is not supported on mobile at this
- time.
-
- )}
-
-
-
-
- this.onClick(transaction.id, 'account')}
- data-testid="account-field"
- />
-
-
-
-
-
-
- this.onEdit(
- transaction,
- 'date',
- formatDate(parseISO(value), this.props.dateFormat),
- )
- }
- onChange={e =>
- this.onQueueChange(
- transaction,
- 'date',
- formatDate(
- parseISO(e.target.value),
- this.props.dateFormat,
- ),
- )
- }
- />
-
- {transaction.reconciled ? (
-
-
-
-
- ) : (
-
-
-
- this.onEdit(transaction, 'cleared', checked)
- }
- style={{
- margin: 'auto',
- width: 22,
- height: 22,
- }}
- />
-
- )}
-
-
-
-
- this.onEdit(transaction, 'notes', value)}
- onChange={e =>
- this.onQueueChange(transaction, 'notes', e.target.value)
- }
- style={{ marginBottom: 10 }}
- />
-
-
- {!adding && (
-
- this.onDelete()}
- style={{
- height: 40,
- borderWidth: 0,
- paddingVertical: 5,
- marginLeft: styles.mobileEditingPadding,
- marginRight: styles.mobileEditingPadding,
- marginTop: 10,
- marginBottom: 15,
- backgroundColor: 'transparent',
- }}
- type="bare"
- >
-
-
- Delete transaction
-
-
-
- )}
-
-
+ headerLeftContent={}
+ footer={
{adding ? (
@@ -737,7 +406,11 @@ class TransactionEditInner extends PureComponent {
) : (
this.onSave()}>
)}
-
- {/* t.id === editingChild),
+ }
+ padding={0}
+ >
+
+ */}
- {renderChildEdit({
- transaction:
- editingChild && transactions.find(t => t.id === editingChild),
- amountSign: forcedSign,
- getCategoryName: id => lookupName(categories, id),
- navigate,
- onEdit: this.onEdit,
- onStartClose: this.onSaveChild,
- })}
- {/* */}
+ >
+
+ (this.amount = el)}
+ value={transaction.amount}
+ zeroIsNegative={true}
+ onBlur={value =>
+ this.onEdit(transaction, 'amount', value.toString())
+ }
+ onChange={value =>
+ this.onQueueChange(transaction, 'amount', value)
+ }
+ style={{ transform: [] }}
+ focusedStyle={{
+ width: 'auto',
+ padding: '5px',
+ paddingLeft: '20px',
+ paddingRight: '20px',
+ minWidth: 120,
+ transform: [{ translateY: -0.5 }],
+ }}
+ textStyle={{ fontSize: 30, textAlign: 'center' }}
+ />
+
+
+
+
+ this.onClick(transaction.id, 'payee')}
+ data-testid="payee-field"
+ />
+
+
+
+
+ {!transaction.is_parent ? (
+
+ // Split
+ //
+ // }
+ onClick={() => this.onClick(transaction.id, 'category')}
+ data-testid="category-field"
+ />
+ ) : (
+
+ Split transaction editing is not supported on mobile at this
+ time.
+
+ )}
+
+
+
+
+ this.onClick(transaction.id, 'account')}
+ data-testid="account-field"
+ />
+
+
+
+
+
+
+ this.onEdit(
+ transaction,
+ 'date',
+ formatDate(parseISO(value), this.props.dateFormat),
+ )
+ }
+ onChange={e =>
+ this.onQueueChange(
+ transaction,
+ 'date',
+ formatDate(parseISO(e.target.value), this.props.dateFormat),
+ )
+ }
+ />
+
+ {transaction.reconciled ? (
+
+
+
+
+ ) : (
+
+
+
+ this.onEdit(transaction, 'cleared', checked)
+ }
+ style={{
+ margin: 'auto',
+ width: 22,
+ height: 22,
+ }}
+ />
+
+ )}
+
+
+
+
+ this.onEdit(transaction, 'notes', value)}
+ onChange={e =>
+ this.onQueueChange(transaction, 'notes', e.target.value)
+ }
+ />
+
+
+ {!adding && (
+
+ this.onDelete()}
+ style={{
+ height: 40,
+ borderWidth: 0,
+ marginLeft: styles.mobileEditingPadding,
+ marginRight: styles.mobileEditingPadding,
+ marginTop: 10,
+ backgroundColor: 'transparent',
+ }}
+ type="bare"
+ >
+
+
+ Delete transaction
+
+
+
+ )}
-
- //
+
);
}
}
@@ -794,9 +652,9 @@ function makeTemporaryTransactions(currentAccountId, lastDate) {
function TransactionEditUnconnected(props) {
const { categories, accounts, payees, lastTransaction, dateFormat } = props;
- let { id: accountId, transactionId } = useParams();
- let navigate = useNavigate();
- let [fetchedTransactions, setFetchedTransactions] = useState(null);
+ const { id: accountId, transactionId } = useParams();
+ const navigate = useNavigate();
+ const [fetchedTransactions, setFetchedTransactions] = useState(null);
let transactions = [];
let adding = false;
let deleted = false;
@@ -820,7 +678,7 @@ function TransactionEditUnconnected(props) {
// The edit item components expect to work with a flat array of
// transactions when handling splits, so we call ungroupTransactions to
// flatten parent and children into one array.
- let { data } = await runQuery(
+ const { data } = await runQuery(
q('transactions')
.filter({ id: transactionId })
.select('*')
@@ -855,10 +713,10 @@ function TransactionEditUnconnected(props) {
// Run the rules to auto-fill in any data. Right now we only do
// this on new transactions because that's how desktop works.
if (isTemporary(transaction)) {
- let afterRules = await send('rules-run', { transaction });
- let diff = getChangedValues(transaction, afterRules);
+ const afterRules = await send('rules-run', { transaction });
+ const diff = getChangedValues(transaction, afterRules);
- let newTransaction = { ...transaction };
+ const newTransaction = { ...transaction };
if (diff) {
Object.keys(diff).forEach(field => {
if (newTransaction[field] == null) {
@@ -981,10 +839,10 @@ class Transaction extends PureComponent {
onSelect,
style,
} = this.props;
- let {
+ const {
id,
payee: payeeId,
- amount,
+ amount: originalAmount,
category,
cleared,
is_parent,
@@ -992,32 +850,33 @@ class Transaction extends PureComponent {
schedule,
} = transaction;
+ let amount = originalAmount;
if (isPreviewId(id)) {
amount = getScheduledAmount(amount);
}
- let categoryName = lookupName(categories, category);
+ const categoryName = lookupName(categories, category);
- let payee = payees && payeeId && getPayeesById(payees)[payeeId];
- let transferAcct =
+ const payee = payees && payeeId && getPayeesById(payees)[payeeId];
+ const transferAcct =
payee &&
payee.transfer_acct &&
getAccountsById(accounts)[payee.transfer_acct];
- let prettyDescription = getDescriptionPretty(
+ const prettyDescription = getDescriptionPretty(
transaction,
payee,
transferAcct,
);
- let prettyCategory = transferAcct
+ const prettyCategory = transferAcct
? 'Transfer'
: is_parent
? 'Split'
: categoryName;
- let isPreview = isPreviewId(id);
- let isReconciled = transaction.reconciled;
- let textStyle = isPreview && {
+ const isPreview = isPreviewId(id);
+ const isReconciled = transaction.reconciled;
+ const textStyle = isPreview && {
fontStyle: 'italic',
color: theme.pageTextLight,
};
@@ -1147,9 +1006,9 @@ export class TransactionList extends Component {
) {
// Mark the last transaction in the section so it can render
// with a different border
- let lastSection = sections[sections.length - 1];
+ const lastSection = sections[sections.length - 1];
if (lastSection && lastSection.data.length > 0) {
- let lastData = lastSection.data;
+ const lastData = lastSection.data;
lastData[lastData.length - 1].isLast = true;
}
@@ -1242,9 +1101,9 @@ export class TransactionList extends Component {
}
function ListBox(props) {
- let state = useListState(props);
- let listBoxRef = useRef();
- let { listBoxProps, labelProps } = useListBox(props, state, listBoxRef);
+ const state = useListState(props);
+ const listBoxRef = useRef();
+ const { listBoxProps, labelProps } = useListBox(props, state, listBoxRef);
useEffect(() => {
function loadMoreTransactions() {
@@ -1288,7 +1147,7 @@ function ListBox(props) {
}
function ListBoxSection({ section, state }) {
- let { itemProps, headingProps, groupProps } = useListBoxSection({
+ const { itemProps, headingProps, groupProps } = useListBoxSection({
heading: section.rendered,
'aria-label': section['aria-label'],
});
@@ -1340,12 +1199,12 @@ function ListBoxSection({ section, state }) {
function Option({ isLast, item, state }) {
// Get props for the option element
- let ref = useRef();
- let { optionProps, isSelected } = useOption({ key: item.key }, state, ref);
+ const ref = useRef();
+ const { optionProps, isSelected } = useOption({ key: item.key }, state, ref);
// Determine whether we should show a keyboard
// focus ring for accessibility
- let { isFocusVisible, focusProps } = useFocusRing();
+ const { isFocusVisible, focusProps } = useFocusRing();
return (
{
- let items = [...selectedItems];
+ const types = useMemo(() => {
+ const items = [...selectedItems];
return {
preview: !!items.find(id => isPreviewId(id)),
trans: !!items.find(id => !isPreviewId(id)),
};
}, [selectedItems]);
- let ambiguousDuplication = useMemo(() => {
- let transactions = [...selectedItems].map(id => getTransaction(id));
+ const ambiguousDuplication = useMemo(() => {
+ const transactions = [...selectedItems].map(id => getTransaction(id));
return transactions.some(t => t && t.is_child);
}, [selectedItems]);
- let linked = useMemo(() => {
+ const linked = useMemo(() => {
return (
!types.preview &&
[...selectedItems].every(id => {
- let t = getTransaction(id);
+ const t = getTransaction(id);
return t && t.schedule;
})
);
@@ -118,13 +118,13 @@ export function SelectedTransactionsButton({
onScheduleAction(name, selectedItems);
break;
case 'view-schedule':
- let firstId = [...selectedItems][0];
+ const firstId = [...selectedItems][0];
let scheduleId;
if (isPreviewId(firstId)) {
- let parts = firstId.split('/');
+ const parts = firstId.split('/');
scheduleId = parts[1];
} else {
- let trans = getTransaction(firstId);
+ const trans = getTransaction(firstId);
scheduleId = trans && trans.schedule;
}
diff --git a/packages/desktop-client/src/components/transactions/SimpleTransactionsTable.js b/packages/desktop-client/src/components/transactions/SimpleTransactionsTable.js
index 076a682c5ed..16d99dce3ae 100644
--- a/packages/desktop-client/src/components/transactions/SimpleTransactionsTable.js
+++ b/packages/desktop-client/src/components/transactions/SimpleTransactionsTable.js
@@ -42,10 +42,10 @@ const TransactionRow = memo(function TransactionRow({
selected,
}) {
// TODO: Convert these to use fetched queries
- let c = getCategoriesById(categories)[transaction.category];
- let a = getAccountsById(accounts)[transaction.account];
+ const c = getCategoriesById(categories)[transaction.category];
+ const a = getAccountsById(accounts)[transaction.account];
- let dispatchSelected = useSelectedDispatch();
+ const dispatchSelected = useSelectedDispatch();
return (
@@ -142,23 +142,23 @@ export default function SimpleTransactionsTable({
fields = ['date', 'payee', 'amount'],
style,
}) {
- let { grouped: categories } = useCategories();
- let { payees, accounts, dateFormat } = useSelector(state => {
+ const { grouped: categories } = useCategories();
+ const { payees, accounts, dateFormat } = useSelector(state => {
return {
payees: state.queries.payees,
accounts: state.queries.accounts,
dateFormat: state.prefs.local.dateFormat || 'MM/dd/yyyy',
};
});
- let selectedItems = useSelectedItems();
- let dispatchSelected = useSelectedDispatch();
- let memoFields = useMemo(() => fields, [JSON.stringify(fields)]);
+ const selectedItems = useSelectedItems();
+ const dispatchSelected = useSelectedDispatch();
+ const memoFields = useMemo(() => fields, [JSON.stringify(fields)]);
- let serializedTransactions = useMemo(() => {
+ const serializedTransactions = useMemo(() => {
return transactions.map(trans => serializeTransaction(trans, dateFormat));
}, [transactions]);
- let renderItem = useCallback(
+ const renderItem = useCallback(
({ item }) => {
return (
{
transactionsLatest.current = transactions;
}, [transactions]);
- let onAdd = useCallback(async newTransactions => {
+ const onAdd = useCallback(async newTransactions => {
newTransactions = realizeTempTransactions(newTransactions);
await saveDiff({ added: newTransactions });
onRefetch();
}, []);
- let onSave = useCallback(async transaction => {
- let changes = updateTransaction(transactionsLatest.current, transaction);
+ const onSave = useCallback(async transaction => {
+ const changes = updateTransaction(transactionsLatest.current, transaction);
if (changes.diff.updated.length > 0) {
- let dateChanged = !!changes.diff.updated[0].date;
+ const dateChanged = !!changes.diff.updated[0].date;
if (dateChanged) {
// Make sure it stays at the top of the list of transactions
// for that date
@@ -118,25 +118,25 @@ export default function TransactionList({
}
}, []);
- let onAddSplit = useCallback(id => {
+ const onAddSplit = useCallback(id => {
const changes = addSplitTransaction(transactionsLatest.current, id);
onChange(changes.newTransaction, changes.data);
saveDiffAndApply(changes.diff, changes, onChange);
return changes.diff.added[0].id;
}, []);
- let onSplit = useCallback(id => {
+ const onSplit = useCallback(id => {
const changes = splitTransaction(transactionsLatest.current, id);
onChange(changes.newTransaction, changes.data);
saveDiffAndApply(changes.diff, changes, onChange);
return changes.diff.added[0].id;
}, []);
- let onApplyRules = useCallback(async transaction => {
- let afterRules = await send('rules-run', { transaction });
- let diff = getChangedValues(transaction, afterRules);
+ const onApplyRules = useCallback(async transaction => {
+ const afterRules = await send('rules-run', { transaction });
+ const diff = getChangedValues(transaction, afterRules);
- let newTransaction = { ...transaction };
+ const newTransaction = { ...transaction };
if (diff) {
Object.keys(diff).forEach(field => {
if (
@@ -152,15 +152,15 @@ export default function TransactionList({
return newTransaction;
}, []);
- let onManagePayees = useCallback(id => {
+ const onManagePayees = useCallback(id => {
navigate('/payees', { selectedPayee: id });
});
- let onNavigateToTransferAccount = useCallback(accountId => {
+ const onNavigateToTransferAccount = useCallback(accountId => {
navigate(`/accounts/${accountId}`);
});
- let onNavigateToSchedule = useCallback(scheduleId => {
+ const onNavigateToSchedule = useCallback(scheduleId => {
pushModal('schedule-edit', { id: scheduleId });
});
diff --git a/packages/desktop-client/src/components/transactions/TransactionsTable.js b/packages/desktop-client/src/components/transactions/TransactionsTable.js
index 4710d7d89ed..26b9f2361dc 100644
--- a/packages/desktop-client/src/components/transactions/TransactionsTable.js
+++ b/packages/desktop-client/src/components/transactions/TransactionsTable.js
@@ -117,11 +117,11 @@ function serializeTransaction(transaction, showZeroInDeposit) {
}
function deserializeTransaction(transaction, originalTransaction) {
- let { debit, credit, date, ...realTransaction } = transaction;
+ const { debit, credit, date: originalDate, ...realTransaction } = transaction;
let amount;
if (debit !== '') {
- let parsed = evalArithmetic(debit, null);
+ const parsed = evalArithmetic(debit, null);
amount = parsed != null ? -parsed : null;
} else {
amount = evalArithmetic(credit, null);
@@ -130,6 +130,7 @@ function deserializeTransaction(transaction, originalTransaction) {
amount =
amount != null ? amountToInteger(amount) : originalTransaction.amount;
+ let date = originalDate;
if (date == null) {
date = originalTransaction.date || currentDay();
}
@@ -138,7 +139,7 @@ function deserializeTransaction(transaction, originalTransaction) {
}
function isLastChild(transactions, index) {
- let trans = transactions[index];
+ const trans = transactions[index];
return (
trans &&
trans.is_child &&
@@ -147,10 +148,10 @@ function isLastChild(transactions, index) {
);
}
-let SplitsExpandedContext = createContext(null);
+const SplitsExpandedContext = createContext(null);
export function useSplitsExpanded() {
- let data = useContext(SplitsExpandedContext);
+ const data = useContext(SplitsExpandedContext);
return useMemo(
() => ({
@@ -165,14 +166,14 @@ export function useSplitsExpanded() {
}
export function SplitsExpandedProvider({ children, initialMode = 'expand' }) {
- let cachedState = useSelector(state => state.app.lastSplitState);
- let reduxDispatch = useDispatch();
+ const cachedState = useSelector(state => state.app.lastSplitState);
+ const reduxDispatch = useDispatch();
- let [state, dispatch] = useReducer((state, action) => {
+ const [state, dispatch] = useReducer((state, action) => {
switch (action.type) {
case 'toggle-split': {
- let ids = new Set([...state.ids]);
- let { id } = action;
+ const ids = new Set([...state.ids]);
+ const { id } = action;
if (ids.has(id)) {
ids.delete(id);
} else {
@@ -181,8 +182,8 @@ export function SplitsExpandedProvider({ children, initialMode = 'expand' }) {
return { ...state, ids };
}
case 'open-split': {
- let ids = new Set([...state.ids]);
- let { id } = action;
+ const ids = new Set([...state.ids]);
+ const { id } = action;
if (state.mode === 'collapse') {
ids.delete(id);
} else {
@@ -233,7 +234,7 @@ export function SplitsExpandedProvider({ children, initialMode = 'expand' }) {
}
}, [state]);
- let value = useMemo(() => ({ state, dispatch }), [state, dispatch]);
+ const value = useMemo(() => ({ state, dispatch }), [state, dispatch]);
return (
@@ -262,7 +263,7 @@ const TransactionHeader = memo(
ascDesc,
field,
}) => {
- let dispatchSelected = useSelectedDispatch();
+ const dispatchSelected = useSelectedDispatch();
return (
account.id !== accountId);
@@ -556,7 +557,7 @@ function PayeeCell({
if (value && value.startsWith('new:') && !isCreatingPayee.current) {
isCreatingPayee.current = true;
- let id = await onCreatePayee(value.slice('new:'.length));
+ const id = await onCreatePayee(value.slice('new:'.length));
onUpdate('payee', id);
isCreatingPayee.current = false;
}
@@ -617,9 +618,9 @@ function PayeeIcons({
onNavigateToSchedule,
children,
}) {
- let scheduleId = transaction.schedule;
- let scheduleData = useCachedSchedules();
- let schedule = scheduleData
+ const scheduleId = transaction.schedule;
+ const scheduleData = useCachedSchedules();
+ const schedule = scheduleData
? scheduleData.schedules.find(s => s.id === scheduleId)
: null;
@@ -628,7 +629,7 @@ function PayeeIcons({
return children;
}
- let buttonStyle = {
+ const buttonStyle = {
marginLeft: -5,
marginRight: 2,
width: 23,
@@ -636,11 +637,11 @@ function PayeeIcons({
color: 'inherit',
};
- let scheduleIconStyle = { width: 13, height: 13 };
+ const scheduleIconStyle = { width: 13, height: 13 };
- let transferIconStyle = { width: 10, height: 10 };
+ const transferIconStyle = { width: 10, height: 10 };
- let recurring = schedule && schedule._date && !!schedule._date.frequency;
+ const recurring = schedule && schedule._date && !!schedule._date.frequency;
return (
<>
@@ -684,7 +685,7 @@ function PayeeIcons({
}
const Transaction = memo(function Transaction(props) {
- let {
+ const {
transaction: originalTransaction,
editing,
showAccount,
@@ -716,14 +717,14 @@ const Transaction = memo(function Transaction(props) {
onNavigateToSchedule,
} = props;
- let dispatchSelected = useSelectedDispatch();
+ const dispatchSelected = useSelectedDispatch();
- let [prevShowZero, setPrevShowZero] = useState(showZeroInDeposit);
- let [prevTransaction, setPrevTransaction] = useState(originalTransaction);
- let [transaction, setTransaction] = useState(() =>
+ const [prevShowZero, setPrevShowZero] = useState(showZeroInDeposit);
+ const [prevTransaction, setPrevTransaction] = useState(originalTransaction);
+ const [transaction, setTransaction] = useState(() =>
serializeTransaction(originalTransaction, showZeroInDeposit),
);
- let isPreview = isPreviewId(transaction.id);
+ const isPreview = isPreviewId(transaction.id);
if (
originalTransaction !== prevTransaction ||
@@ -736,7 +737,7 @@ const Transaction = memo(function Transaction(props) {
setPrevShowZero(showZeroInDeposit);
}
- let [showReconciliationWarning, setShowReconciliationWarning] =
+ const [showReconciliationWarning, setShowReconciliationWarning] =
useState(false);
function onUpdate(name, value) {
@@ -772,7 +773,7 @@ const Transaction = memo(function Transaction(props) {
}
function onUpdateAfterConfirm(name, value) {
- let newTransaction = { ...transaction, [name]: value };
+ const newTransaction = { ...transaction, [name]: value };
// Don't change the note to an empty string if it's null (since they are both rendered the same)
if (name === 'note' && value === '' && transaction.note == null) {
@@ -806,7 +807,7 @@ const Transaction = memo(function Transaction(props) {
if (name === 'payee' && value && value.startsWith('new:')) {
setTransaction(newTransaction);
} else {
- let deserialized = deserializeTransaction(
+ const deserialized = deserializeTransaction(
newTransaction,
originalTransaction,
);
@@ -817,7 +818,7 @@ const Transaction = memo(function Transaction(props) {
}
}
- let {
+ const {
id,
amount,
debit,
@@ -836,8 +837,8 @@ const Transaction = memo(function Transaction(props) {
} = transaction;
// Join in some data
- let payee = payees && payeeId && getPayeesById(payees)[payeeId];
- let account = accounts && accountId && getAccountsById(accounts)[accountId];
+ const payee = payees && payeeId && getPayeesById(payees)[payeeId];
+ const account = accounts && accountId && getAccountsById(accounts)[accountId];
let transferAcct;
if (_inverse) {
@@ -850,15 +851,15 @@ const Transaction = memo(function Transaction(props) {
getAccountsById(accounts)[payee.transfer_acct];
}
- let isChild = transaction.is_child;
- let isBudgetTransfer = transferAcct && transferAcct.offbudget === 0;
- let isOffBudget = account && account.offbudget === 1;
+ const isChild = transaction.is_child;
+ const isBudgetTransfer = transferAcct && transferAcct.offbudget === 0;
+ const isOffBudget = account && account.offbudget === 1;
- let valueStyle = added ? { fontWeight: 600 } : null;
- let backgroundFocus = focusedField === 'select';
- let amountStyle = hideFraction ? { letterSpacing: -0.5 } : null;
+ const valueStyle = added ? { fontWeight: 600 } : null;
+ const backgroundFocus = focusedField === 'select';
+ const amountStyle = hideFraction ? { letterSpacing: -0.5 } : null;
- let runningBalance = !isTemporaryId(id)
+ const runningBalance = !isTemporaryId(id)
? balance
: balance + (_inverse ? -1 : 1) * amount;
@@ -993,7 +994,7 @@ const Transaction = memo(function Transaction(props) {
textAlign="flex"
value={accountId}
formatter={acctId => {
- let acct = acctId && getAccountsById(accounts)[acctId];
+ const acct = acctId && getAccountsById(accounts)[acctId];
if (acct) {
return acct.name;
}
@@ -1532,15 +1533,15 @@ function TransactionTableInner({
}) {
const containerRef = createRef();
const isAddingPrev = usePrevious(props.isAdding);
- let [scrollWidth, setScrollWidth] = useState(0);
+ const [scrollWidth, setScrollWidth] = useState(0);
function saveScrollWidth(parent, child) {
- let width = parent > 0 && child > 0 && parent - child;
+ const width = parent > 0 && child > 0 && parent - child;
setScrollWidth(!width ? 0 : width);
}
- let onNavigateToTransferAccount = useCallback(
+ const onNavigateToTransferAccount = useCallback(
accountId => {
props.onCloseAddTransaction();
props.onNavigateToTransferAccount(accountId);
@@ -1548,7 +1549,7 @@ function TransactionTableInner({
[props.onCloseAddTransaction, props.onNavigateToTransferAccount],
);
- let onNavigateToSchedule = useCallback(
+ const onNavigateToSchedule = useCallback(
scheduleId => {
props.onCloseAddTransaction();
props.onNavigateToSchedule(scheduleId);
@@ -1580,17 +1581,17 @@ function TransactionTableInner({
isExpanded,
} = props;
- let trans = item;
- let selected = selectedItems.has(trans.id);
+ const trans = item;
+ const selected = selectedItems.has(trans.id);
- let parent = props.transactionMap.get(trans.parent_id);
- let isChildDeposit = parent && parent.amount > 0;
- let expanded = isExpanded && isExpanded((parent || trans).id);
+ const parent = props.transactionMap.get(trans.parent_id);
+ const isChildDeposit = parent && parent.amount > 0;
+ const expanded = isExpanded && isExpanded((parent || trans).id);
// For backwards compatibility, read the error of the transaction
// since in previous versions we stored it there. In the future we
// can simplify this to just the parent
- let error = expanded
+ const error = expanded
? (parent && parent.error) || trans.error
: trans.error;
@@ -1751,19 +1752,19 @@ function TransactionTableInner({
);
}
-export let TransactionTable = forwardRef((props, ref) => {
- let [newTransactions, setNewTransactions] = useState(null);
- let [prevIsAdding, setPrevIsAdding] = useState(false);
- let splitsExpanded = useSplitsExpanded();
- let prevSplitsExpanded = useRef(null);
+export const TransactionTable = forwardRef((props, ref) => {
+ const [newTransactions, setNewTransactions] = useState(null);
+ const [prevIsAdding, setPrevIsAdding] = useState(false);
+ const splitsExpanded = useSplitsExpanded();
+ const prevSplitsExpanded = useRef(null);
- let tableRef = useRef(null);
- let mergedRef = useMergedRefs(tableRef, ref);
+ const tableRef = useRef(null);
+ const mergedRef = useMergedRefs(tableRef, ref);
- let transactions = useMemo(() => {
+ const transactions = useMemo(() => {
let result;
if (splitsExpanded.state.transitionId != null) {
- let index = props.transactions.findIndex(
+ const index = props.transactions.findIndex(
t => t.id === splitsExpanded.state.transitionId,
);
result = props.transactions.filter((t, idx) => {
@@ -1811,14 +1812,14 @@ export let TransactionTable = forwardRef((props, ref) => {
}
}, [prevSplitsExpanded.current]);
- let newNavigator = useTableNavigator(newTransactions, getFields);
- let tableNavigator = useTableNavigator(transactions, getFields);
- let shouldAdd = useRef(false);
- let latestState = useRef({ newTransactions, newNavigator, tableNavigator });
- let savePending = useRef(false);
- let afterSaveFunc = useRef(false);
- let [_, forceRerender] = useState({});
- let selectedItems = useSelectedItems();
+ const newNavigator = useTableNavigator(newTransactions, getFields);
+ const tableNavigator = useTableNavigator(transactions, getFields);
+ const shouldAdd = useRef(false);
+ const latestState = useRef({ newTransactions, newNavigator, tableNavigator });
+ const savePending = useRef(false);
+ const afterSaveFunc = useRef(false);
+ const [_, forceRerender] = useState({});
+ const selectedItems = useSelectedItems();
useLayoutEffect(() => {
latestState.current = {
@@ -1851,8 +1852,8 @@ export let TransactionTable = forwardRef((props, ref) => {
});
newNavigator.onEdit('temp', 'account');
} else {
- let transactions = latestState.current.newTransactions;
- let lastDate = transactions.length > 0 ? transactions[0].date : null;
+ const transactions = latestState.current.newTransactions;
+ const lastDate = transactions.length > 0 ? transactions[0].date : null;
setNewTransactions(
makeTemporaryTransactions(
props.currentAccountId,
@@ -1924,7 +1925,7 @@ export let TransactionTable = forwardRef((props, ref) => {
onAddTemporary();
} else if (!e.shiftKey) {
function getLastTransaction(state) {
- let { newTransactions } = state.current;
+ const { newTransactions } = state.current;
return newTransactions[newTransactions.length - 1];
}
@@ -1938,8 +1939,9 @@ export let TransactionTable = forwardRef((props, ref) => {
}
afterSave(() => {
- let lastTransaction = getLastTransaction(latestState);
- let isSplit = lastTransaction.parent_id || lastTransaction.is_parent;
+ const lastTransaction = getLastTransaction(latestState);
+ const isSplit =
+ lastTransaction.parent_id || lastTransaction.is_parent;
if (
latestState.current.newTransactions[0].error &&
@@ -1960,12 +1962,12 @@ export let TransactionTable = forwardRef((props, ref) => {
function onCheckEnter(e) {
if (e.key === 'Enter' && !e.shiftKey) {
- let { editingId: id, focusedField } = tableNavigator;
+ const { editingId: id, focusedField } = tableNavigator;
afterSave(() => {
- let transactions = latestState.current.transactions;
- let idx = transactions.findIndex(t => t.id === id);
- let parent = transactionMap.get(transactions[idx]?.parent_id);
+ const transactions = latestState.current.transactions;
+ const idx = transactions.findIndex(t => t.id === id);
+ const parent = transactionMap.get(transactions[idx]?.parent_id);
if (
isLastChild(transactions, idx) &&
@@ -1980,7 +1982,7 @@ export let TransactionTable = forwardRef((props, ref) => {
}
}
- let onAddTemporary = useCallback(() => {
+ const onAddTemporary = useCallback(() => {
shouldAdd.current = true;
// A little hacky - this forces a rerender which will cause the
// effect we want to run. We have to wait for all updates to be
@@ -1988,7 +1990,7 @@ export let TransactionTable = forwardRef((props, ref) => {
forceRerender({});
}, [props.onAdd, newNavigator.onEdit]);
- let onSave = useCallback(
+ const onSave = useCallback(
async transaction => {
savePending.current = true;
@@ -1997,7 +1999,7 @@ export let TransactionTable = forwardRef((props, ref) => {
transaction = await props.onApplyRules(transaction);
}
- let newTrans = latestState.current.newTransactions;
+ const newTrans = latestState.current.newTransactions;
setNewTransactions(updateTransaction(newTrans, transaction).data);
} else {
props.onSave(transaction);
@@ -2006,11 +2008,11 @@ export let TransactionTable = forwardRef((props, ref) => {
[props.onSave],
);
- let onDelete = useCallback(id => {
- let temporary = isTemporaryId(id);
+ const onDelete = useCallback(id => {
+ const temporary = isTemporaryId(id);
if (temporary) {
- let newTrans = latestState.current.newTransactions;
+ const newTrans = latestState.current.newTransactions;
if (id === newTrans[0].id) {
// You can never delete the parent new transaction
@@ -2021,12 +2023,12 @@ export let TransactionTable = forwardRef((props, ref) => {
}
}, []);
- let onSplit = useMemo(() => {
+ const onSplit = useMemo(() => {
return id => {
if (isTemporaryId(id)) {
- let { newNavigator } = latestState.current;
- let newTrans = latestState.current.newTransactions;
- let { data, diff } = splitTransaction(newTrans, id);
+ const { newNavigator } = latestState.current;
+ const newTrans = latestState.current.newTransactions;
+ const { data, diff } = splitTransaction(newTrans, id);
setNewTransactions(data);
// Jump next to "debit" field if it is empty
@@ -2041,12 +2043,12 @@ export let TransactionTable = forwardRef((props, ref) => {
);
}
} else {
- let trans = latestState.current.transactions.find(t => t.id === id);
- let newId = props.onSplit(id);
+ const trans = latestState.current.transactions.find(t => t.id === id);
+ const newId = props.onSplit(id);
splitsExpanded.dispatch({ type: 'open-split', id: trans.id });
- let { tableNavigator } = latestState.current;
+ const { tableNavigator } = latestState.current;
if (trans.amount === null) {
tableNavigator.onEdit(trans.id, 'debit');
} else {
@@ -2056,18 +2058,18 @@ export let TransactionTable = forwardRef((props, ref) => {
};
}, [props.onSplit, splitsExpanded.dispatch]);
- let onAddSplit = useCallback(
+ const onAddSplit = useCallback(
id => {
if (isTemporaryId(id)) {
- let newTrans = latestState.current.newTransactions;
- let { data, diff } = addSplitTransaction(newTrans, id);
+ const newTrans = latestState.current.newTransactions;
+ const { data, diff } = addSplitTransaction(newTrans, id);
setNewTransactions(data);
newNavigator.onEdit(
diff.added[0].id,
latestState.current.newNavigator.focusedField,
);
} else {
- let newId = props.onAddSplit(id);
+ const newId = props.onAddSplit(id);
tableNavigator.onEdit(
newId,
latestState.current.tableNavigator.focusedField,
@@ -2087,7 +2089,7 @@ export let TransactionTable = forwardRef((props, ref) => {
props.onCloseAddTransaction();
}
- let onToggleSplit = useCallback(
+ const onToggleSplit = useCallback(
id => splitsExpanded.dispatch({ type: 'toggle-split', id }),
[splitsExpanded.dispatch],
);
diff --git a/packages/desktop-client/src/components/transactions/TransactionsTable.test.js b/packages/desktop-client/src/components/transactions/TransactionsTable.test.js
index edc14f7f190..b62d840267a 100644
--- a/packages/desktop-client/src/components/transactions/TransactionsTable.test.js
+++ b/packages/desktop-client/src/components/transactions/TransactionsTable.test.js
@@ -87,13 +87,13 @@ function LiveTransactionTable(props) {
}, [transactions]);
const onSplit = id => {
- let { data, diff } = splitTransaction(transactions, id);
+ const { data, diff } = splitTransaction(transactions, id);
setTransactions(data);
return diff.added[0].id;
};
const onSave = transaction => {
- let { data } = updateTransaction(transactions, transaction);
+ const { data } = updateTransaction(transactions, transaction);
setTransactions(data);
};
@@ -103,7 +103,7 @@ function LiveTransactionTable(props) {
};
const onAddSplit = id => {
- let { data, diff } = addSplitTransaction(transactions, id);
+ const { data, diff } = addSplitTransaction(transactions, id);
setTransactions(data);
return diff.added[0].id;
};
@@ -185,7 +185,7 @@ function renderTransactions(extraProps) {
// various this
transactions[0].amount = -2777;
- let defaultProps = {
+ const defaultProps = {
transactions,
payees,
accounts,
@@ -200,7 +200,7 @@ function renderTransactions(extraProps) {
},
};
- let result = render(
+ const result = render(
,
);
return {
@@ -236,17 +236,17 @@ function queryField(container, name, subSelector = '', idx) {
async function _editField(field, container) {
// We only short-circuit this for inputs
- let input = field.querySelector(`input`);
+ const input = field.querySelector(`input`);
if (input) {
expect(container.ownerDocument.activeElement).toBe(input);
return input;
}
let element;
- let buttonQuery = 'button,div[data-testid=cell-button]';
+ const buttonQuery = 'button,div[data-testid=cell-button]';
if (field.querySelector(buttonQuery)) {
- let btn = field.querySelector(buttonQuery);
+ const btn = field.querySelector(buttonQuery);
await userEvent.click(btn);
element = field.querySelector(':focus');
expect(element).toBeTruthy();
@@ -401,9 +401,9 @@ describe('Transactions', () => {
'{Shift>}[Enter]{/Shift}',
];
- for (let idx in ks) {
- let input = await editField(container, 'notes', 2);
- let oldValue = input.value;
+ for (const idx in ks) {
+ const input = await editField(container, 'notes', 2);
+ const oldValue = input.value;
await userEvent.clear(input);
await userEvent.type(input, 'a happy little note' + idx);
// It's not saved yet
@@ -416,8 +416,8 @@ describe('Transactions', () => {
);
}
- let input = await editField(container, 'notes', 2);
- let oldValue = input.value;
+ const input = await editField(container, 'notes', 2);
+ const oldValue = input.value;
await userEvent.clear(input);
await userEvent.type(input, 'another happy note');
// It's not saved yet
@@ -430,9 +430,9 @@ describe('Transactions', () => {
test('dropdown automatically opens and can be filtered', async () => {
const { container } = renderTransactions();
- let categories = categoryGroups.flatMap(group => group.categories);
- let input = await editField(container, 'category', 2);
- let tooltip = container.querySelector('[data-testid="autocomplete"]');
+ const categories = categoryGroups.flatMap(group => group.categories);
+ const input = await editField(container, 'category', 2);
+ const tooltip = container.querySelector('[data-testid="autocomplete"]');
expect(tooltip).toBeTruthy();
expect(
[...tooltip.querySelectorAll('[data-testid*="category-item"]')].length,
@@ -460,8 +460,8 @@ describe('Transactions', () => {
test('dropdown selects an item with keyboard', async () => {
const { container, getTransactions } = renderTransactions();
- let input = await editField(container, 'category', 2);
- let tooltip = container.querySelector('[data-testid="autocomplete"]');
+ const input = await editField(container, 'category', 2);
+ const tooltip = container.querySelector('[data-testid="autocomplete"]');
// No item should be highlighted
let highlighted = tooltip.querySelector('[data-highlighted]');
@@ -504,7 +504,7 @@ describe('Transactions', () => {
let tooltip = container.querySelector('[data-testid="autocomplete"]');
// Make sure none of the items are highlighted
- let items = tooltip.querySelectorAll('[data-testid$="category-item"]');
+ const items = tooltip.querySelectorAll('[data-testid$="category-item"]');
let highlighted = tooltip.querySelector('[data-highlighted]');
expect(highlighted).toBeNull();
@@ -535,18 +535,18 @@ describe('Transactions', () => {
test('dropdown hovers but doesn’t change value', async () => {
const { container, getTransactions } = renderTransactions();
- let input = await editField(container, 'category', 2);
- let oldCategory = getTransactions()[2].category;
- let tooltip = container.querySelector('[data-testid="autocomplete"]');
+ const input = await editField(container, 'category', 2);
+ const oldCategory = getTransactions()[2].category;
+ const tooltip = container.querySelector('[data-testid="autocomplete"]');
- let items = tooltip.querySelectorAll('[data-testid$="category-item"]');
+ const items = tooltip.querySelectorAll('[data-testid$="category-item"]');
// Hover over a few of the items to highlight them
await userEvent.hover(items[2]);
await userEvent.hover(items[3]);
// Make sure one of them is highlighted
- let highlighted = tooltip.querySelectorAll('[data-highlighted]');
+ const highlighted = tooltip.querySelectorAll('[data-highlighted]');
expect(highlighted).toHaveLength(1);
// Navigate away from the field with the keyboard
@@ -554,7 +554,7 @@ describe('Transactions', () => {
// Make sure the category didn't update, and that the highlighted
// field was different than the transactions' category
- let currentCategory = getTransactions()[2].category;
+ const currentCategory = getTransactions()[2].category;
expect(currentCategory).toBe(oldCategory);
expect(highlighted.textContent).not.toBe(
categories.find(c => c.id === currentCategory).name,
@@ -572,7 +572,7 @@ describe('Transactions', () => {
// For this first test case, make sure the tooltip is gone. We
// don't need to check this in all the other cases
- let tooltipItems = container.querySelectorAll(
+ const tooltipItems = container.querySelectorAll(
'[data-testid="category-item-group"]',
);
expect(tooltipItems.length).toBe(0);
@@ -604,13 +604,13 @@ describe('Transactions', () => {
test('dropdown escape resets the value ', async () => {
const { container } = renderTransactions();
- let input = await editField(container, 'category', 2);
- let oldValue = input.value;
+ const input = await editField(container, 'category', 2);
+ const oldValue = input.value;
await userEvent.type(input, 'aaabbbccc[Escape]');
expect(input.value).toBe(oldValue);
// The tooltip be closed
- let tooltip = container.querySelector('[data-testid="autocomplete"]');
+ const tooltip = container.querySelector('[data-testid="autocomplete"]');
expect(tooltip).toBeNull();
});
@@ -659,7 +659,7 @@ describe('Transactions', () => {
await userEvent.type(input, '55.00');
await editNewField(container, 'category');
- let splitButton = document.body.querySelector(
+ const splitButton = document.body.querySelector(
'[data-testid="autocomplete"] [data-testid="split-transaction-button"]',
);
await userEvent.click(splitButton);
@@ -686,7 +686,7 @@ describe('Transactions', () => {
null,
);
- let addButton = container.querySelector('[data-testid="add-button"]');
+ const addButton = container.querySelector('[data-testid="add-button"]');
expect(getTransactions().length).toBe(5);
await userEvent.click(addButton);
@@ -727,7 +727,7 @@ describe('Transactions', () => {
// The cancel button should also close the new transaction form
updateProps({ isAdding: true });
- let cancelButton = container.querySelectorAll(
+ const cancelButton = container.querySelectorAll(
'[data-testid="new-transaction"] [data-testid="cancel-button"]',
)[0];
await userEvent.click(cancelButton);
@@ -757,7 +757,7 @@ describe('Transactions', () => {
test('transaction can be split, updated, and deleted', async () => {
const { container, getTransactions, updateProps } = renderTransactions();
- let transactions = [...getTransactions()];
+ const transactions = [...getTransactions()];
// Change the id to simulate a new transaction being added, and
// work with that one. This makes sure that the transaction table
// properly references new data.
@@ -781,8 +781,8 @@ describe('Transactions', () => {
}
let input = await editField(container, 'category', 0);
- let tooltip = container.querySelector('[data-testid="autocomplete"]');
- let splitButton = tooltip.querySelector(
+ const tooltip = container.querySelector('[data-testid="autocomplete"]');
+ const splitButton = tooltip.querySelector(
'[data-testid="split-transaction-button"]',
);
@@ -800,12 +800,12 @@ describe('Transactions', () => {
expect(getTransactions()[1].amount).toBe(0);
expectErrorToExist(getTransactions().slice(0, 2));
- let toolbars = container.querySelectorAll(
+ const toolbars = container.querySelectorAll(
'[data-testid="transaction-error"]',
);
// Make sure the toolbar has appeared
expect(toolbars.length).toBe(1);
- let toolbar = toolbars[0];
+ const toolbar = toolbars[0];
// Enter an amount for the new split transaction and make sure the
// toolbar updates
@@ -897,8 +897,8 @@ describe('Transactions', () => {
const { container, getTransactions } = renderTransactions();
let input = await editField(container, 'category', 0);
- let tooltip = container.querySelector('[data-testid="autocomplete"]');
- let splitButton = tooltip.querySelector(
+ const tooltip = container.querySelector('[data-testid="autocomplete"]');
+ const splitButton = tooltip.querySelector(
'[data-testid="split-transaction-button"',
);
diff --git a/packages/desktop-client/src/components/util/AmountInput.tsx b/packages/desktop-client/src/components/util/AmountInput.tsx
index e4e57e0c7a3..632082cf9ea 100644
--- a/packages/desktop-client/src/components/util/AmountInput.tsx
+++ b/packages/desktop-client/src/components/util/AmountInput.tsx
@@ -35,16 +35,16 @@ export function AmountInput({
textStyle,
focused,
}: AmountInputProps) {
- let format = useFormat();
- let [negative, setNegative] = useState(
+ const format = useFormat();
+ const [negative, setNegative] = useState(
(initialValue === 0 && zeroSign === '-') || initialValue < 0,
);
- let initialValueAbsolute = format(Math.abs(initialValue), 'financial');
- let [value, setValue] = useState(initialValueAbsolute);
+ const initialValueAbsolute = format(Math.abs(initialValue), 'financial');
+ const [value, setValue] = useState(initialValueAbsolute);
useEffect(() => setValue(initialValueAbsolute), [initialValueAbsolute]);
- let buttonRef = useRef();
+ const buttonRef = useRef();
function onSwitch() {
setNegative(!negative);
@@ -52,10 +52,10 @@ export function AmountInput({
}
function fireChange(val, neg) {
- let valueOrInitial = Math.abs(
+ const valueOrInitial = Math.abs(
amountToInteger(evalArithmetic(val, initialValueAbsolute)),
);
- let amount = neg ? valueOrInitial * -1 : valueOrInitial;
+ const amount = neg ? valueOrInitial * -1 : valueOrInitial;
onChange?.(amount);
}
@@ -64,8 +64,8 @@ export function AmountInput({
setValue(value ? value : '');
}
- let ref = useRef();
- let mergedRef = useMergedRefs(inputRef, ref);
+ const ref = useRef();
+ const mergedRef = useMergedRefs(inputRef, ref);
useEffect(() => {
if (focused) {
@@ -118,8 +118,8 @@ export function AmountInput({
}
export function BetweenAmountInput({ defaultValue, onChange }) {
- let [num1, setNum1] = useState(defaultValue.num1);
- let [num2, setNum2] = useState(defaultValue.num2);
+ const [num1, setNum1] = useState(defaultValue.num1);
+ const [num2, setNum2] = useState(defaultValue.num2);
return (
diff --git a/packages/desktop-client/src/components/util/DisplayId.tsx b/packages/desktop-client/src/components/util/DisplayId.tsx
index 0a66bf34f2f..ecc14437543 100644
--- a/packages/desktop-client/src/components/util/DisplayId.tsx
+++ b/packages/desktop-client/src/components/util/DisplayId.tsx
@@ -33,7 +33,7 @@ export default function DisplayId({
return (
{data => {
- let item = data[id];
+ const item = data[id];
return (
state.queries.saved);
- let dateFormat = useSelector(
+ const { grouped: categoryGroups } = useCategories();
+ const saved = useSelector(state => state.queries.saved);
+ const dateFormat = useSelector(
state => state.prefs.local.dateFormat || 'MM/dd/yyyy',
);
@@ -38,7 +38,7 @@ export default function GenericInput({
return null;
}
- let showPlaceholder = multi ? value.length === 0 : true;
+ const showPlaceholder = multi ? value.length === 0 : true;
let content;
switch (type) {
diff --git a/packages/desktop-client/src/components/util/LoadComponent.tsx b/packages/desktop-client/src/components/util/LoadComponent.tsx
index 08be27854aa..74a97f62d4c 100644
--- a/packages/desktop-client/src/components/util/LoadComponent.tsx
+++ b/packages/desktop-client/src/components/util/LoadComponent.tsx
@@ -22,7 +22,7 @@ function LoadComponentInner({
message,
importer,
}: LoadComponentProps) {
- let [Component, setComponent] = useState(null);
+ const [Component, setComponent] = useState(null);
useEffect(() => {
importer().then(module => setComponent(() => module[name]));
}, [name, importer]);
diff --git a/packages/desktop-client/src/hooks/useSelected.tsx b/packages/desktop-client/src/hooks/useSelected.tsx
index 21455ab4ecd..934318e3661 100644
--- a/packages/desktop-client/src/hooks/useSelected.tsx
+++ b/packages/desktop-client/src/hooks/useSelected.tsx
@@ -340,10 +340,8 @@ export function SelectedProviderWithItems({
}, [registerDispatch]);
return (
-
- instance={selected}
- fetchAllIds={fetchAllIds}
- children={children}
- />
+ instance={selected} fetchAllIds={fetchAllIds}>
+ {children}
+
);
}
diff --git a/packages/loot-core/src/client/data-hooks/accounts.tsx b/packages/loot-core/src/client/data-hooks/accounts.tsx
index 084060f3b87..7bcde4b7bfc 100644
--- a/packages/loot-core/src/client/data-hooks/accounts.tsx
+++ b/packages/loot-core/src/client/data-hooks/accounts.tsx
@@ -13,7 +13,9 @@ const AccountsContext = createContext(null);
export function AccountsProvider({ children }) {
const data = useAccounts();
- return ;
+ return (
+ {children}
+ );
}
export function CachedAccounts({ children, idKey }) {
diff --git a/packages/loot-core/src/client/data-hooks/payees.tsx b/packages/loot-core/src/client/data-hooks/payees.tsx
index f5b1956aca4..8197d50e7af 100644
--- a/packages/loot-core/src/client/data-hooks/payees.tsx
+++ b/packages/loot-core/src/client/data-hooks/payees.tsx
@@ -13,7 +13,9 @@ const PayeesContext = createContext(null);
export function PayeesProvider({ children }) {
const data = usePayees();
- return ;
+ return (
+ {children}
+ );
}
export function CachedPayees({ children, idKey }) {
diff --git a/packages/loot-core/src/client/data-hooks/schedules.tsx b/packages/loot-core/src/client/data-hooks/schedules.tsx
index a139658c9b2..0a46c38e96f 100644
--- a/packages/loot-core/src/client/data-hooks/schedules.tsx
+++ b/packages/loot-core/src/client/data-hooks/schedules.tsx
@@ -69,7 +69,11 @@ const SchedulesContext = createContext(null);
export function SchedulesProvider({ transform, children }) {
const data = useSchedules({ transform });
- return ;
+ return (
+
+ {children}
+
+ );
}
export function useCachedSchedules() {
diff --git a/packages/loot-core/src/client/query-hooks.tsx b/packages/loot-core/src/client/query-hooks.tsx
index 329f466b736..52314faa376 100644
--- a/packages/loot-core/src/client/query-hooks.tsx
+++ b/packages/loot-core/src/client/query-hooks.tsx
@@ -46,7 +46,7 @@ function makeContext(queryState, opts, QueryClass) {
};
}, []);
- return ;
+ return {children};
}
function useQuery() {
diff --git a/packages/loot-core/src/server/db/index.test.ts b/packages/loot-core/src/server/db/index.test.ts
index 60834456263..007269d56ff 100644
--- a/packages/loot-core/src/server/db/index.test.ts
+++ b/packages/loot-core/src/server/db/index.test.ts
@@ -38,6 +38,21 @@ describe('Database', () => {
expect((await db.getCategories()).length).toBe(1);
});
+ test('using a deleted category name works', async () => {
+ await db.insertCategoryGroup({ id: 'group1', name: 'group1' });
+ const id = await db.insertCategory({
+ name: 'foo',
+ cat_group: 'group1',
+ });
+ await db.deleteCategory({ id });
+ expect((await db.getCategories()).length).toBe(0);
+ await db.insertCategory({
+ name: 'foo',
+ cat_group: 'group1',
+ });
+ expect((await db.getCategories()).length).toBe(1);
+ });
+
test('transactions are sorted by date', async () => {
await insertTransactions([
{ date: '2018-01-05', account: 'foo', amount: -23 },
diff --git a/packages/loot-core/src/server/db/index.ts b/packages/loot-core/src/server/db/index.ts
index 9b152daf858..8ed8f811761 100644
--- a/packages/loot-core/src/server/db/index.ts
+++ b/packages/loot-core/src/server/db/index.ts
@@ -348,7 +348,7 @@ export async function insertCategory(
await batchMessages(async () => {
// Dont allow duplicated names in groups
const existingCatInGroup = await first(
- `SELECT id FROM categories WHERE cat_group = ? and UPPER(name) = ? LIMIT 1`,
+ `SELECT id FROM categories WHERE cat_group = ? and UPPER(name) = ? and tombstone = 0 LIMIT 1`,
[category.cat_group, category.name.toUpperCase()],
);
if (existingCatInGroup) {
diff --git a/upcoming-release-notes/1993.md b/upcoming-release-notes/1993.md
new file mode 100644
index 00000000000..ea16e7de6e4
--- /dev/null
+++ b/upcoming-release-notes/1993.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [joel-jeremy]
+---
+
+Use Page component for mobile pages
diff --git a/upcoming-release-notes/2002.md b/upcoming-release-notes/2002.md
new file mode 100644
index 00000000000..de2fc7cba3d
--- /dev/null
+++ b/upcoming-release-notes/2002.md
@@ -0,0 +1,6 @@
+---
+category: Bugfix
+authors: [kymckay]
+---
+
+Prevent deleted categories blocking creation of new categories with the same name.
diff --git a/upcoming-release-notes/2008.md b/upcoming-release-notes/2008.md
new file mode 100644
index 00000000000..2d170fd6cc3
--- /dev/null
+++ b/upcoming-release-notes/2008.md
@@ -0,0 +1,6 @@
+---
+category: Bugfix
+authors: [vishnukaushik]
+---
+
+Fix filter Amount formatting issue
\ No newline at end of file
diff --git a/upcoming-release-notes/2029.md b/upcoming-release-notes/2029.md
new file mode 100644
index 00000000000..68c09ee2a46
--- /dev/null
+++ b/upcoming-release-notes/2029.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [MatissJanis]
+---
+
+Enable `react/no-children-prop` rule and fix the issues
diff --git a/upcoming-release-notes/2031.md b/upcoming-release-notes/2031.md
new file mode 100644
index 00000000000..cd7fa53c60a
--- /dev/null
+++ b/upcoming-release-notes/2031.md
@@ -0,0 +1,6 @@
+---
+category: Bugfix
+authors: [joel-jeremy]
+---
+
+Fix bulk edit field modal in desktop
diff --git a/upcoming-release-notes/2033.md b/upcoming-release-notes/2033.md
new file mode 100644
index 00000000000..afd0770965a
--- /dev/null
+++ b/upcoming-release-notes/2033.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [joel-jeremy]
+---
+
+Apply ESLint prefer-const on components folder part 1
diff --git a/upcoming-release-notes/2034.md b/upcoming-release-notes/2034.md
new file mode 100644
index 00000000000..82aadd8c442
--- /dev/null
+++ b/upcoming-release-notes/2034.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [joel-jeremy]
+---
+
+Apply ESLint prefer-const on components folder part 2
diff --git a/upcoming-release-notes/2036.md b/upcoming-release-notes/2036.md
new file mode 100644
index 00000000000..913201b7303
--- /dev/null
+++ b/upcoming-release-notes/2036.md
@@ -0,0 +1,6 @@
+---
+category: Maintenance
+authors: [twk3]
+---
+
+Add api tests for categories and category groups