diff --git a/.eslintrc.js b/.eslintrc.js index 1c9425aa7a9f4b2757af57fe78070cfb3ed9910d..fe5a15013b99dc70f2f85e6c3bedee306ac44d97 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -239,7 +239,7 @@ module.exports = { './packages/api/app/**/*', './packages/crdt/**/*', './packages/desktop-client/src/*', - // './packages/desktop-client/src/components/*', + './packages/desktop-client/src/components/*', './packages/desktop-client/src/components/accounts/**/*', './packages/desktop-client/src/components/autocomplete/**/*', './packages/desktop-client/src/components/budget/**/*', @@ -249,17 +249,17 @@ module.exports = { './packages/desktop-client/src/components/manager/**/*', './packages/desktop-client/src/components/mobile/**/*', './packages/desktop-client/src/components/modals/**/*', - // './packages/desktop-client/src/components/payees/**/*', - // './packages/desktop-client/src/components/reports/**/*', - // './packages/desktop-client/src/components/responsive/**/*', - // './packages/desktop-client/src/components/rules/**/*', - // './packages/desktop-client/src/components/schedules/**/*', - // './packages/desktop-client/src/components/select/**/*', - // './packages/desktop-client/src/components/settings/**/*', - // './packages/desktop-client/src/components/sidebar/**/*', - // './packages/desktop-client/src/components/spreadsheet/**/*', - // './packages/desktop-client/src/components/transactions/**/*', - // './packages/desktop-client/src/components/util/**/*', + './packages/desktop-client/src/components/payees/**/*', + './packages/desktop-client/src/components/reports/**/*', + './packages/desktop-client/src/components/responsive/**/*', + './packages/desktop-client/src/components/rules/**/*', + './packages/desktop-client/src/components/schedules/**/*', + './packages/desktop-client/src/components/select/**/*', + './packages/desktop-client/src/components/settings/**/*', + './packages/desktop-client/src/components/sidebar/**/*', + './packages/desktop-client/src/components/spreadsheet/**/*', + './packages/desktop-client/src/components/transactions/**/*', + './packages/desktop-client/src/components/util/**/*', './packages/desktop-client/src/hooks/**/*', './packages/desktop-client/src/icons/**/*', './packages/desktop-client/src/style/**/*', diff --git a/packages/desktop-client/src/components/AnimatedRefresh.tsx b/packages/desktop-client/src/components/AnimatedRefresh.tsx index 4daa07824734cc640fcae261648d1e62d173d6dd..c6e613c956ec678a30ae106aafcee041523a5bc1 100644 --- a/packages/desktop-client/src/components/AnimatedRefresh.tsx +++ b/packages/desktop-client/src/components/AnimatedRefresh.tsx @@ -7,7 +7,7 @@ import { type CSSProperties } from '../style'; import View from './common/View'; -let spin = keyframes({ +const spin = keyframes({ '0%': { transform: 'rotateZ(0deg)' }, '100%': { transform: 'rotateZ(360deg)' }, }); diff --git a/packages/desktop-client/src/components/App.tsx b/packages/desktop-client/src/components/App.tsx index bdfdd3841a634b853b0264962178c9f7cd6802f3..bf5334c42d789b47572b5ec88011955d1898c025 100644 --- a/packages/desktop-client/src/components/App.tsx +++ b/packages/desktop-client/src/components/App.tsx @@ -68,7 +68,7 @@ function App({ // don't block on this in case they are offline or something) send('get-remote-files').then(files => { if (files) { - let remoteFile = files.find(f => f.fileId === cloudFileId); + const remoteFile = files.find(f => f.fileId === cloudFileId); if (remoteFile && remoteFile.deleted) { closeBudget(); } @@ -122,14 +122,14 @@ function ErrorFallback({ error }: FallbackProps) { } function AppWrapper() { - let budgetId = useSelector( + const budgetId = useSelector( state => state.prefs.local && state.prefs.local.id, ); - let cloudFileId = useSelector( + const cloudFileId = useSelector( state => state.prefs.local && state.prefs.local.cloudFileId, ); - let loadingText = useSelector(state => state.app.loadingText); - let { loadBudget, closeBudget, loadGlobalPrefs, sync } = useActions(); + const loadingText = useSelector(state => state.app.loadingText); + const { loadBudget, closeBudget, loadGlobalPrefs, sync } = useActions(); const [hiddenScrollbars, setHiddenScrollbars] = useState( hasHiddenScrollbars(), ); diff --git a/packages/desktop-client/src/components/BackgroundImage.tsx b/packages/desktop-client/src/components/BackgroundImage.tsx index dd8ee5c38e1a892cc81346a87af6094826586179..7a64bddfc402d70fe7e9ef3e10a8c20c7e43e458 100644 --- a/packages/desktop-client/src/components/BackgroundImage.tsx +++ b/packages/desktop-client/src/components/BackgroundImage.tsx @@ -2,9 +2,9 @@ import * as React from 'react'; import { theme } from '../style'; -let linesTop = theme.pageBackgroundLineTop; // lines top -let linesMid = theme.pageBackgroundLineMid; // lines mid -let linesBottom = theme.pageBackgroundLineBottom; // lines bottom +const linesTop = theme.pageBackgroundLineTop; // lines top +const linesMid = theme.pageBackgroundLineMid; // lines mid +const linesBottom = theme.pageBackgroundLineBottom; // lines bottom export function BackgroundImage() { return ( diff --git a/packages/desktop-client/src/components/BankSyncStatus.tsx b/packages/desktop-client/src/components/BankSyncStatus.tsx index 8095d40670684ef85e075b282aa9d59e6e2c569d..96a0390b4b4a270683b44b58158949bee9a937c0 100644 --- a/packages/desktop-client/src/components/BankSyncStatus.tsx +++ b/packages/desktop-client/src/components/BankSyncStatus.tsx @@ -9,9 +9,9 @@ import Text from './common/Text'; import View from './common/View'; export default function BankSyncStatus() { - let accountsSyncing = useSelector(state => state.account.accountsSyncing); + const accountsSyncing = useSelector(state => state.account.accountsSyncing); - let name = accountsSyncing + const name = accountsSyncing ? accountsSyncing === '__all' ? 'accounts' : accountsSyncing diff --git a/packages/desktop-client/src/components/FatalError.tsx b/packages/desktop-client/src/components/FatalError.tsx index 1d8a7a70b20b7ac844048f1d9b3517834de19a89..25702958ad51cc21cbeed14f59b868d281e794e0 100644 --- a/packages/desktop-client/src/components/FatalError.tsx +++ b/packages/desktop-client/src/components/FatalError.tsx @@ -113,8 +113,8 @@ function RenderUIError() { } function SharedArrayBufferOverride() { - let [expanded, setExpanded] = useState(false); - let [understand, setUnderstand] = useState(false); + const [expanded, setExpanded] = useState(false); + const [understand, setUnderstand] = useState(false); return expanded ? ( <> @@ -152,7 +152,7 @@ function SharedArrayBufferOverride() { } function FatalError({ buttonText, error }: FatalErrorProps) { - let [showError, setShowError] = useState(false); + const [showError, setShowError] = useState(false); const showSimpleRender = 'type' in error && error.type === 'app-init-failure'; diff --git a/packages/desktop-client/src/components/FinancesApp.tsx b/packages/desktop-client/src/components/FinancesApp.tsx index 58792c219c699ea9554bead1e9768f9784ece0e5..3ca0b40c00edf69d4c94e173e631915402c32327 100644 --- a/packages/desktop-client/src/components/FinancesApp.tsx +++ b/packages/desktop-client/src/components/FinancesApp.tsx @@ -71,7 +71,7 @@ function WideNotSupported({ children, redirectTo = '/budget' }) { } function RouterBehaviors({ getAccounts }) { - let navigate = useNavigate(); + const navigate = useNavigate(); useEffect(() => { // Get the accounts and check if any exist. If there are no // accounts, we want to redirect the user to the All Accounts @@ -83,8 +83,8 @@ function RouterBehaviors({ getAccounts }) { }); }, []); - let location = useLocation(); - let href = useHref(location); + const location = useLocation(); + const href = useHref(location); useEffect(() => { undo.setUndoState('url', href); }, [href]); @@ -93,7 +93,7 @@ function RouterBehaviors({ getAccounts }) { } function FinancesApp() { - let actions = useActions(); + const actions = useActions(); useEffect(() => { // The default key handler scope hotkeys.setScope('app'); @@ -251,7 +251,7 @@ function FinancesApp() { } export default function FinancesAppWithContext() { - let app = useMemo(() => <FinancesApp />, []); + const app = useMemo(() => <FinancesApp />, []); return ( <SpreadsheetProvider> diff --git a/packages/desktop-client/src/components/FixedSizeList.js b/packages/desktop-client/src/components/FixedSizeList.js index e99d0971a64558c0e4b6bc1b0c7bc7fdbd5fe847..ce5cb4b4e60d472c9dd1ac4012ee2d7032ffa598 100644 --- a/packages/desktop-client/src/components/FixedSizeList.js +++ b/packages/desktop-client/src/components/FixedSizeList.js @@ -11,7 +11,7 @@ const IS_SCROLLING_DEBOUNCE_INTERVAL = 150; const defaultItemKey = (index, data) => index; function ResizeObserver({ onResize, children }) { - let ref = useResizeObserver(onResize); + const ref = useResizeObserver(onResize); return children(ref); } @@ -92,8 +92,8 @@ export default class FixedSizeList extends PureComponent { getAnchoredScrollPos() { if (this.anchored && this.props.indexForKey && this._outerRef != null) { - let index = this.props.indexForKey(this.anchored.key); - let baseOffset = this.getOffsetForIndexAndAlignment(index, 'start'); + const index = this.props.indexForKey(this.anchored.key); + const baseOffset = this.getOffsetForIndexAndAlignment(index, 'start'); return baseOffset + this.anchored.offset; } return null; @@ -102,7 +102,7 @@ export default class FixedSizeList extends PureComponent { componentDidUpdate() { const { scrollOffset, scrollUpdateWasRequested } = this.state; - let anchoredPos = this.getAnchoredScrollPos(); + const anchoredPos = this.getAnchoredScrollPos(); if (anchoredPos != null) { const outerRef = this._outerRef; outerRef.scrollTop = anchoredPos; @@ -157,9 +157,9 @@ export default class FixedSizeList extends PureComponent { const items = []; if (itemCount > 0) { for (let index = startIndex; index <= stopIndex; index++) { - let key = itemKey(index); + const key = itemKey(index); let style = this._getItemStyle(index); - let lastPosition = this.lastPositions.current.get(key); + const lastPosition = this.lastPositions.current.get(key); let animating = false; positions.set(key, style.top); @@ -191,10 +191,10 @@ export default class FixedSizeList extends PureComponent { // Read this value AFTER items have been created, // So their actual sizes (if variable) are taken into consideration. - let estimatedTotalSize = this.getEstimatedTotalSize(); + const estimatedTotalSize = this.getEstimatedTotalSize(); - let OuterElement = outerElementType || outerTagName || 'div'; - let InnerElement = innerElementType || innerTagName || 'div'; + const OuterElement = outerElementType || outerTagName || 'div'; + const InnerElement = innerElementType || innerTagName || 'div'; return ( <ResizeObserver onResize={this.onHeaderResize}> @@ -231,7 +231,7 @@ export default class FixedSizeList extends PureComponent { setRowAnimation = flag => { this.animationEnabled = flag; - let outerRef = this._outerRef; + const outerRef = this._outerRef; if (outerRef) { if (this.animationEnabled) { outerRef.classList.add('animated'); @@ -246,12 +246,12 @@ export default class FixedSizeList extends PureComponent { }; anchor() { - let itemKey = this.props.itemKey || defaultItemKey; + const itemKey = this.props.itemKey || defaultItemKey; - let outerRef = this._outerRef; - let scrollOffset = outerRef ? outerRef.scrollTop : 0; - let index = this.getStartIndexForOffset(scrollOffset); - let key = itemKey(index); + const outerRef = this._outerRef; + const scrollOffset = outerRef ? outerRef.scrollTop : 0; + const index = this.getStartIndexForOffset(scrollOffset); + const key = itemKey(index); this.anchored = { key, @@ -434,10 +434,15 @@ export default class FixedSizeList extends PureComponent { _getItemStyleCache = memoizeOne((_, __, ___) => ({})); _getRangeToRender() { - let { itemCount, overscanCount } = this.props; - let { isScrolling, scrollDirection, scrollOffset } = this.state; + const { itemCount, overscanCount } = this.props; + const { + isScrolling, + scrollDirection, + scrollOffset: originalScrollOffset, + } = this.state; - let anchoredPos = this.getAnchoredScrollPos(); + const anchoredPos = this.getAnchoredScrollPos(); + let scrollOffset = originalScrollOffset; if (anchoredPos != null) { scrollOffset = anchoredPos; } @@ -469,7 +474,7 @@ export default class FixedSizeList extends PureComponent { } _onScrollVertical = event => { - let { scrollTop } = event.currentTarget; + const { scrollTop } = event.currentTarget; this.setState(prevState => { if (prevState.scrollOffset === scrollTop) { @@ -479,7 +484,7 @@ export default class FixedSizeList extends PureComponent { return null; } - let scrollOffset = scrollTop; + const scrollOffset = scrollTop; return { isScrolling: true, diff --git a/packages/desktop-client/src/components/GlobalKeys.tsx b/packages/desktop-client/src/components/GlobalKeys.tsx index cff3d38ae2ffe6e1d442c6ff960593df7ef413aa..edcfe148aab44fc2de4c6409c42dcc0a938f623e 100644 --- a/packages/desktop-client/src/components/GlobalKeys.tsx +++ b/packages/desktop-client/src/components/GlobalKeys.tsx @@ -5,7 +5,7 @@ import * as Platform from 'loot-core/src/client/platform'; import useNavigate from '../hooks/useNavigate'; export default function GlobalKeys() { - let navigate = useNavigate(); + const navigate = useNavigate(); useEffect(() => { const handleKeys = e => { if (Platform.isBrowser) { diff --git a/packages/desktop-client/src/components/KeyHandlers.tsx b/packages/desktop-client/src/components/KeyHandlers.tsx index 1a38701b5dd1cb98680d35c26074e8490ea91624..3a674e5f4b39c5511111eb94211a2fbcc3974552 100644 --- a/packages/desktop-client/src/components/KeyHandlers.tsx +++ b/packages/desktop-client/src/components/KeyHandlers.tsx @@ -2,11 +2,11 @@ import React, { createContext, useEffect, useContext } from 'react'; import hotkeys, { type KeyHandler as HotKeyHandler } from 'hotkeys-js'; -let KeyScopeContext = createContext('app'); +const KeyScopeContext = createContext('app'); hotkeys.filter = event => { - let target = (event.target || event.srcElement) as HTMLElement; - let tagName = target.tagName; + const target = (event.target || event.srcElement) as HTMLElement; + const tagName = target.tagName; // This is the default behavior of hotkeys, except we only suppress // key presses if the meta key is not pressed @@ -34,7 +34,7 @@ function KeyHandler({ eventType = 'keydown', handler, }: KeyHandlerProps) { - let scope = useContext(KeyScopeContext); + const scope = useContext(KeyScopeContext); if (eventType !== 'keyup' && eventType !== 'keydown') { throw new Error('KeyHandler: unknown event type: ' + eventType); @@ -70,7 +70,7 @@ type KeyHandlersProps = { keys: Record<string, HotKeyHandler>; }; export function KeyHandlers({ eventType, keys = {} }: KeyHandlersProps) { - let handlers = Object.keys(keys).map(key => { + const handlers = Object.keys(keys).map(key => { return ( <KeyHandler key={key} diff --git a/packages/desktop-client/src/components/LoggedInUser.tsx b/packages/desktop-client/src/components/LoggedInUser.tsx index 0459cc9062b48667f243e3552ad5106c24facd6e..91418dc071988874df3818c412e696c1f07e826b 100644 --- a/packages/desktop-client/src/components/LoggedInUser.tsx +++ b/packages/desktop-client/src/components/LoggedInUser.tsx @@ -21,10 +21,10 @@ export default function LoggedInUser({ style, color, }: LoggedInUserProps) { - let userData = useSelector(state => state.user.data); - let { getUserData, signOut, closeBudget } = useActions(); - let [loading, setLoading] = useState(true); - let [menuOpen, setMenuOpen] = useState(false); + const userData = useSelector(state => state.user.data); + const { getUserData, signOut, closeBudget } = useActions(); + const [loading, setLoading] = useState(true); + const [menuOpen, setMenuOpen] = useState(false); const serverUrl = useServerURL(); useEffect(() => { diff --git a/packages/desktop-client/src/components/ManageRules.tsx b/packages/desktop-client/src/components/ManageRules.tsx index 1d6ea7d0a76f8665f88467f554e2bc50f57a524b..36928d655205a8c30389f90d0e4457a3202aaa32 100644 --- a/packages/desktop-client/src/components/ManageRules.tsx +++ b/packages/desktop-client/src/components/ManageRules.tsx @@ -51,14 +51,14 @@ function mapValue(field, value, { payees, categories, accounts }) { } function ruleToString(rule, data) { - let conditions = rule.conditions.flatMap(cond => [ + const conditions = rule.conditions.flatMap(cond => [ mapField(cond.field), friendlyOp(cond.op), cond.op === 'oneOf' || cond.op === 'notOneOf' ? cond.value.map(v => mapValue(cond.field, v, data)).join(', ') : mapValue(cond.field, cond.value, data), ]); - let actions = rule.actions.flatMap(action => { + const actions = rule.actions.flatMap(action => { if (action.op === 'set') { return [ friendlyOp(action.op), @@ -67,7 +67,7 @@ function ruleToString(rule, data) { mapValue(action.field, action.value, data), ]; } else if (action.op === 'link-schedule') { - let schedule = data.schedules.find(s => s.id === action.value); + const schedule = data.schedules.find(s => s.id === action.value); return [ friendlyOp(action.op), describeSchedule( @@ -95,19 +95,19 @@ function ManageRulesContent({ payeeId, setLoading, }: ManageRulesContentProps) { - let [allRules, setAllRules] = useState(null); - let [rules, setRules] = useState(null); - let [filter, setFilter] = useState(''); - let dispatch = useDispatch(); - - let { data: schedules } = SchedulesQuery.useQuery(); - let { list: categories } = useCategories(); - let state = useSelector(state => ({ + const [allRules, setAllRules] = useState(null); + const [rules, setRules] = useState(null); + const [filter, setFilter] = useState(''); + const dispatch = useDispatch(); + + const { data: schedules } = SchedulesQuery.useQuery(); + const { list: categories } = useCategories(); + const state = useSelector(state => ({ payees: state.queries.payees, accounts: state.queries.accounts, schedules, })); - let filterData = useMemo( + const filterData = useMemo( () => ({ ...state, categories, @@ -115,7 +115,7 @@ function ManageRulesContent({ [state, categories], ); - let filteredRules = useMemo( + const filteredRules = useMemo( () => filter === '' || !rules ? rules @@ -126,8 +126,8 @@ function ManageRulesContent({ ), [rules, filter, filterData], ); - let selectedInst = useSelected('manage-rules', allRules, []); - let [hoveredRule, setHoveredRule] = useState(null); + const selectedInst = useSelected('manage-rules', allRules, []); + const [hoveredRule, setHoveredRule] = useState(null); async function loadRules() { setLoading(true); @@ -147,7 +147,7 @@ function ManageRulesContent({ useEffect(() => { async function loadData() { - let loadedRules = await loadRules(); + const loadedRules = await loadRules(); setRules(loadedRules.slice(0, 100)); setLoading(false); @@ -171,7 +171,7 @@ function ManageRulesContent({ async function onDeleteSelected() { setLoading(true); - let { someDeletionsFailed } = await send('rule-delete-all', [ + const { someDeletionsFailed } = await send('rule-delete-all', [ ...selectedInst.items, ]); @@ -179,7 +179,7 @@ function ManageRulesContent({ alert('Some rules were not deleted because they are linked to schedules'); } - let newRules = await loadRules(); + const newRules = await loadRules(); setRules(rules => { return newRules.slice(0, rules.length); }); @@ -187,15 +187,15 @@ function ManageRulesContent({ setLoading(false); } - let onEditRule = useCallback(rule => { + const onEditRule = useCallback(rule => { dispatch( pushModal('edit-rule', { rule, onSave: async newRule => { - let newRules = await loadRules(); + const newRules = await loadRules(); setRules(rules => { - let newIdx = newRules.findIndex(rule => rule.id === newRule.id); + const newIdx = newRules.findIndex(rule => rule.id === newRule.id); if (newIdx > rules.length) { return newRules.slice(0, newIdx + 75); @@ -211,7 +211,7 @@ function ManageRulesContent({ }, []); function onCreateRule() { - let rule: RuleEntity = { + const rule: RuleEntity = { stage: null, conditionsOp: 'and', conditions: [ @@ -236,10 +236,10 @@ function ManageRulesContent({ pushModal('edit-rule', { rule, onSave: async newRule => { - let newRules = await loadRules(); + const newRules = await loadRules(); setRules(rules => { - let newIdx = newRules.findIndex(rule => rule.id === newRule.id); + const newIdx = newRules.findIndex(rule => rule.id === newRule.id); return newRules.slice(0, newIdx + 75); }); @@ -249,7 +249,7 @@ function ManageRulesContent({ ); } - let onHover = useCallback(id => { + const onHover = useCallback(id => { setHoveredRule(id); }, []); diff --git a/packages/desktop-client/src/components/MobileWebMessage.tsx b/packages/desktop-client/src/components/MobileWebMessage.tsx index d68b927f0cc2d38ef93d64c9361765e41ec3ddb0..cf93cbd13de8e67b05293f5df89d066bb0bd9394 100644 --- a/packages/desktop-client/src/components/MobileWebMessage.tsx +++ b/packages/desktop-client/src/components/MobileWebMessage.tsx @@ -11,7 +11,7 @@ import Text from './common/Text'; import View from './common/View'; import { Checkbox } from './forms'; -let buttonStyle = { border: 0, fontSize: 15, padding: '10px 13px' }; +const buttonStyle = { border: 0, fontSize: 15, padding: '10px 13px' }; export default function MobileWebMessage() { const hideMobileMessagePref = useSelector(state => { @@ -20,14 +20,14 @@ export default function MobileWebMessage() { const { isNarrowWidth } = useResponsive(); - let [show, setShow] = useState( + const [show, setShow] = useState( isNarrowWidth && !hideMobileMessagePref && !document.cookie.match(/hideMobileMessage=true/), ); - let [requestDontRemindMe, setRequestDontRemindMe] = useState(false); + const [requestDontRemindMe, setRequestDontRemindMe] = useState(false); - let dispatch = useDispatch(); + const dispatch = useDispatch(); function onTry() { setShow(false); @@ -37,7 +37,7 @@ export default function MobileWebMessage() { dispatch(savePrefs({ hideMobileMessage: true })); } else { // Set a cookie for 5 minutes - let d = new Date(); + const d = new Date(); d.setTime(d.getTime() + 1000 * 60 * 5); document.cookie = 'hideMobileMessage=true;path=/;expires=' + d.toUTCString(); diff --git a/packages/desktop-client/src/components/Modals.tsx b/packages/desktop-client/src/components/Modals.tsx index 643ef4a08994e4f0e341c3a6b87014b3d304099e..6c9238faf2a6e537ef4daad53640afc5d7223653 100644 --- a/packages/desktop-client/src/components/Modals.tsx +++ b/packages/desktop-client/src/components/Modals.tsx @@ -54,7 +54,7 @@ export default function Modals() { const syncServerStatus = useSyncServerStatus(); - let modals = modalStack + const modals = modalStack .map(({ name, options }, idx) => { const modalProps: CommonModalProps = { onClose: actions.popModal, diff --git a/packages/desktop-client/src/components/NotesButton.tsx b/packages/desktop-client/src/components/NotesButton.tsx index 3c65b4a1f86ddb59d972823d5f9873979aec64f9..fb2770d84008a4062bca7b747a61cc91449b410f 100644 --- a/packages/desktop-client/src/components/NotesButton.tsx +++ b/packages/desktop-client/src/components/NotesButton.tsx @@ -95,8 +95,8 @@ function NotesTooltip({ position = 'bottom-left', onClose, }: NotesTooltipProps) { - let [notes, setNotes] = useState<string>(defaultNotes); - let inputRef = createRef<HTMLTextAreaElement>(); + const [notes, setNotes] = useState<string>(defaultNotes); + const inputRef = createRef<HTMLTextAreaElement>(); useEffect(() => { if (editable) { @@ -149,11 +149,11 @@ export default function NotesButton({ tooltipPosition, style, }: NotesButtonProps) { - let [hover, setHover] = useState(false); - let tooltip = useTooltip(); - let data = useLiveQuery(() => q('notes').filter({ id }).select('*'), [id]); - let note = data && data.length > 0 ? data[0].note : null; - let hasNotes = note && note !== ''; + const [hover, setHover] = useState(false); + const tooltip = useTooltip(); + const data = useLiveQuery(() => q('notes').filter({ id }).select('*'), [id]); + const note = data && data.length > 0 ? data[0].note : null; + const hasNotes = note && note !== ''; function onClose(notes) { send('notes-save', { id, note: notes }); diff --git a/packages/desktop-client/src/components/Notifications.tsx b/packages/desktop-client/src/components/Notifications.tsx index a56c529187d9f87e53eb095c22a4e14f4976cb69..8b16e7e86aaa9265a10f66d5f44ff9dda97576b2 100644 --- a/packages/desktop-client/src/components/Notifications.tsx +++ b/packages/desktop-client/src/components/Notifications.tsx @@ -29,17 +29,17 @@ function compileMessage( return ( <Stack spacing={2}> {message.split(/\n\n/).map((paragraph, idx) => { - let parts = paragraph.split(/(\[[^\]]*\]\([^)]*\))/g); + const parts = paragraph.split(/(\[[^\]]*\]\([^)]*\))/g); return ( <Text key={idx} style={{ lineHeight: '1.4em' }}> {parts.map((part, idx) => { - let match = part.match(/\[([^\]]*)\]\(([^)]*)\)/); + const match = part.match(/\[([^\]]*)\]\(([^)]*)\)/); if (match) { - let [_, text, href] = match; + const [_, text, href] = match; if (href[0] === '#') { - let actionName = href.slice(1); + const actionName = href.slice(1); return ( <LinkButton key={idx} @@ -79,11 +79,19 @@ function Notification({ notification: NotificationWithId; onRemove: () => void; }) { - let { type, title, message, pre, messageActions, sticky, internal, button } = - notification; + const { + type, + title, + message, + pre, + messageActions, + sticky, + internal, + button, + } = notification; - let [loading, setLoading] = useState(false); - let [overlayLoading, setOverlayLoading] = useState(false); + const [loading, setLoading] = useState(false); + const [overlayLoading, setOverlayLoading] = useState(false); useEffect(() => { if (type === 'error' && internal) { @@ -95,10 +103,10 @@ function Notification({ } }, []); - let positive = type === 'message'; - let error = type === 'error'; + const positive = type === 'message'; + const error = type === 'error'; - let processedMessage = useMemo( + const processedMessage = useMemo( () => compileMessage(message, messageActions, setOverlayLoading, onRemove), [message, messageActions], ); @@ -228,8 +236,8 @@ function Notification({ } export default function Notifications({ style }: { style?: CSSProperties }) { - let { removeNotification } = useActions(); - let notifications = useSelector(state => state.notifications.notifications); + const { removeNotification } = useActions(); + const notifications = useSelector(state => state.notifications.notifications); return ( <View style={{ diff --git a/packages/desktop-client/src/components/PrivacyFilter.tsx b/packages/desktop-client/src/components/PrivacyFilter.tsx index ac8fd543a756e04104b8f202be9015aee53baf74..5e5d9d0edecadfd47c1c97f8c3286e71388be0f4 100644 --- a/packages/desktop-client/src/components/PrivacyFilter.tsx +++ b/packages/desktop-client/src/components/PrivacyFilter.tsx @@ -22,7 +22,7 @@ export function ConditionalPrivacyFilter({ privacyFilter, defaultPrivacyFilterProps, }: ConditionalPrivacyFilterProps) { - let renderPrivacyFilter = (children, mergedProps) => ( + const renderPrivacyFilter = (children, mergedProps) => ( <PrivacyFilter {...mergedProps}>{children}</PrivacyFilter> ); return privacyFilter ? ( @@ -52,10 +52,10 @@ export default function PrivacyFilter({ children, ...props }: PrivacyFilterProps) { - let privacyMode = usePrivacyMode(); + const privacyMode = usePrivacyMode(); // Limit mobile support for now. - let { isNarrowWidth } = useResponsive(); - let activate = + const { isNarrowWidth } = useResponsive(); + const activate = privacyMode && !isNarrowWidth && (!activationFilters || @@ -63,7 +63,7 @@ export default function PrivacyFilter({ typeof value === 'boolean' ? value : value(), )); - let blurAmount = blurIntensity != null ? `${blurIntensity}px` : '3px'; + const blurAmount = blurIntensity != null ? `${blurIntensity}px` : '3px'; return !activate ? ( <>{Children.toArray(children)}</> @@ -75,11 +75,11 @@ export default function PrivacyFilter({ } function BlurredOverlay({ blurIntensity, children, ...props }) { - let [hovered, setHovered] = useState(false); - let onHover = useCallback(() => setHovered(true), [setHovered]); - let onHoverEnd = useCallback(() => setHovered(false), [setHovered]); + const [hovered, setHovered] = useState(false); + const onHover = useCallback(() => setHovered(true), [setHovered]); + const onHoverEnd = useCallback(() => setHovered(false), [setHovered]); - let blurStyle = { + const blurStyle = { ...(!hovered && { filter: `blur(${blurIntensity})`, WebkitFilter: `blur(${blurIntensity})`, @@ -89,7 +89,7 @@ function BlurredOverlay({ blurIntensity, children, ...props }) { }), }; - let { style, ...restProps } = props; + const { style, ...restProps } = props; return ( <View diff --git a/packages/desktop-client/src/components/ServerContext.tsx b/packages/desktop-client/src/components/ServerContext.tsx index 86c0bf8d653da972f32a91ce9985f01441f9a67a..795a62b794d2b2be9c809026156c45afcbffab67 100644 --- a/packages/desktop-client/src/components/ServerContext.tsx +++ b/packages/desktop-client/src/components/ServerContext.tsx @@ -29,7 +29,7 @@ export const useServerVersion = () => useContext(ServerContext).version; export const useSetServerURL = () => useContext(ServerContext).setURL; async function getServerVersion() { - let result = await send('get-server-version'); + const result = await send('get-server-version'); if ('version' in result) { return result.version; } @@ -37,8 +37,8 @@ async function getServerVersion() { } export function ServerProvider({ children }: { children: ReactNode }) { - let [serverURL, setServerURL] = useState(''); - let [version, setVersion] = useState(''); + const [serverURL, setServerURL] = useState(''); + const [version, setVersion] = useState(''); useEffect(() => { async function run() { @@ -48,9 +48,9 @@ export function ServerProvider({ children }: { children: ReactNode }) { run(); }, []); - let setURL = useCallback( + const setURL = useCallback( async (url: string, opts: { validate?: boolean } = {}) => { - let { error } = await send('set-server-url', { ...opts, url }); + const { error } = await send('set-server-url', { ...opts, url }); if (!error) { setServerURL(await send('get-server-url')); setVersion(await getServerVersion()); diff --git a/packages/desktop-client/src/components/SyncRefresh.tsx b/packages/desktop-client/src/components/SyncRefresh.tsx index ec95d7ea62871ff25a9a0bf1909536054aac6bef..714ba0f6feea8a544292888353ba6f5286bf0a2b 100644 --- a/packages/desktop-client/src/components/SyncRefresh.tsx +++ b/packages/desktop-client/src/components/SyncRefresh.tsx @@ -9,7 +9,7 @@ type SyncRefreshProps = { children: (props: ChildrenProps) => ReactNode; }; export default function SyncRefresh({ onSync, children }: SyncRefreshProps) { - let [syncing, setSyncing] = useState(false); + const [syncing, setSyncing] = useState(false); async function onSync_() { setSyncing(true); diff --git a/packages/desktop-client/src/components/ThemeSelector.tsx b/packages/desktop-client/src/components/ThemeSelector.tsx index e780bfe296d6b68cc5b7b09ad8476ce00c3271d0..e909e4d0e6112751b17a088f8391b65f5577d3f6 100644 --- a/packages/desktop-client/src/components/ThemeSelector.tsx +++ b/packages/desktop-client/src/components/ThemeSelector.tsx @@ -13,10 +13,10 @@ type ThemeSelectorProps = { }; export function ThemeSelector({ style }: ThemeSelectorProps) { - let theme = useTheme(); - let { saveGlobalPrefs } = useActions(); + const theme = useTheme(); + const { saveGlobalPrefs } = useActions(); - let { isNarrowWidth } = useResponsive(); + const { isNarrowWidth } = useResponsive(); return isNarrowWidth ? null : ( <Button diff --git a/packages/desktop-client/src/components/Titlebar.tsx b/packages/desktop-client/src/components/Titlebar.tsx index cf594d1af91437ea1c4a7eed16bc5828ea89da7c..3ccae08b1663421cd3c3d35664632509bdf1cc14 100644 --- a/packages/desktop-client/src/components/Titlebar.tsx +++ b/packages/desktop-client/src/components/Titlebar.tsx @@ -58,14 +58,14 @@ export type TitlebarContextValue = { subscribe: (listener: Listener) => () => void; }; -export let TitlebarContext = createContext<TitlebarContextValue>(null); +export const TitlebarContext = createContext<TitlebarContextValue>(null); type TitlebarProviderProps = { children?: ReactNode; }; export function TitlebarProvider({ children }: TitlebarProviderProps) { - let listeners = useRef<Listener[]>([]); + const listeners = useRef<Listener[]>([]); function sendEvent(msg: TitlebarMessage) { listeners.current.forEach(func => func(msg)); @@ -85,7 +85,7 @@ export function TitlebarProvider({ children }: TitlebarProviderProps) { } function UncategorizedButton() { - let count = useSheetValue(queries.uncategorizedCount()); + const count = useSheetValue(queries.uncategorizedCount()); return ( count !== 0 && ( <Link @@ -103,12 +103,12 @@ function UncategorizedButton() { } function PrivacyButton({ style }) { - let isPrivacyEnabled = useSelector( + const isPrivacyEnabled = useSelector( state => state.prefs.local.isPrivacyEnabled, ); - let { savePrefs } = useActions(); + const { savePrefs } = useActions(); - let privacyIconStyle = { width: 15, height: 15 }; + const privacyIconStyle = { width: 15, height: 15 }; return ( <Button @@ -131,14 +131,14 @@ type SyncButtonProps = { isMobile?: boolean; }; function SyncButton({ style, isMobile = false }: SyncButtonProps) { - let cloudFileId = useSelector(state => state.prefs.local.cloudFileId); - let { sync } = useActions(); + const cloudFileId = useSelector(state => state.prefs.local.cloudFileId); + const { sync } = useActions(); - let [syncing, setSyncing] = useState(false); - let [syncState, setSyncState] = useState(null); + const [syncing, setSyncing] = useState(false); + const [syncState, setSyncState] = useState(null); useEffect(() => { - let unlisten = listen('sync-event', ({ type, subtype, syncDisabled }) => { + const unlisten = listen('sync-event', ({ type, subtype, syncDisabled }) => { if (type === 'start') { setSyncing(true); setSyncState(null); @@ -269,13 +269,13 @@ function SyncButton({ style, isMobile = false }: SyncButtonProps) { } function BudgetTitlebar() { - let maxMonths = useSelector(state => state.prefs.global.maxMonths); - let budgetType = useSelector(state => state.prefs.local.budgetType); - let { saveGlobalPrefs } = useActions(); - let { sendEvent } = useContext(TitlebarContext); + const maxMonths = useSelector(state => state.prefs.global.maxMonths); + const budgetType = useSelector(state => state.prefs.local.budgetType); + const { saveGlobalPrefs } = useActions(); + const { sendEvent } = useContext(TitlebarContext); - let [loading, setLoading] = useState(false); - let [showTooltip, setShowTooltip] = useState(false); + const [loading, setLoading] = useState(false); + const [showTooltip, setShowTooltip] = useState(false); const reportBudgetEnabled = useFeatureFlag('reportBudget'); @@ -364,12 +364,12 @@ function BudgetTitlebar() { } export default function Titlebar({ style }) { - let navigate = useNavigate(); - let location = useLocation(); - let sidebar = useSidebar(); - let { isNarrowWidth } = useResponsive(); - let serverURL = useServerURL(); - let floatingSidebar = useSelector( + const navigate = useNavigate(); + const location = useLocation(); + const sidebar = useSidebar(); + const { isNarrowWidth } = useResponsive(); + const serverURL = useServerURL(); + const floatingSidebar = useSelector( state => state.prefs.global.floatingSidebar, ); diff --git a/packages/desktop-client/src/components/UpdateNotification.tsx b/packages/desktop-client/src/components/UpdateNotification.tsx index 6826f8272b37db4416571fe67f1379420b0ffde7..1d5bec39708b08b6586e7a68eb89cc32eb8bcfec 100644 --- a/packages/desktop-client/src/components/UpdateNotification.tsx +++ b/packages/desktop-client/src/components/UpdateNotification.tsx @@ -19,15 +19,15 @@ function closeNotification(setAppState) { } export default function UpdateNotification() { - let updateInfo = useSelector(state => state.app.updateInfo); - let showUpdateNotification = useSelector( + const updateInfo = useSelector(state => state.app.updateInfo); + const showUpdateNotification = useSelector( state => state.app.showUpdateNotification, ); - let { updateApp, setAppState } = useActions(); + const { updateApp, setAppState } = useActions(); if (updateInfo && showUpdateNotification) { - let notes = updateInfo.releaseNotes; + const notes = updateInfo.releaseNotes; return ( <View diff --git a/packages/desktop-client/src/components/payees/ManagePayees.js b/packages/desktop-client/src/components/payees/ManagePayees.js index 0f8f968555bdcf41139e02026d651371c07d5f48..3e60c6a7508701c7ee1822de074b49f68a203937 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 ( <View> @@ -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 ( <View style={{ height: '100%' }}> diff --git a/packages/desktop-client/src/components/payees/ManagePayeesPage.js b/packages/desktop-client/src/components/payees/ManagePayeesPage.js index 2d707f3913190dc1fc97b1d8c3b3c36e9d0d050a..e3b1bdf72afc9b1df91f1ae7982814ce03f5fe6f 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 ( <Page title="Payees"> <ManagePayeesWithData diff --git a/packages/desktop-client/src/components/payees/ManagePayeesWithData.js b/packages/desktop-client/src/components/payees/ManagePayeesWithData.js index 51ad66eb37cb5006ec97d74843fa1197def83eb2..89f7c5e5ebd5783810a8ffe88fddb198bae14265 100644 --- a/packages/desktop-client/src/components/payees/ManagePayeesWithData.js +++ b/packages/desktop-client/src/components/payees/ManagePayeesWithData.js @@ -10,20 +10,20 @@ import useCategories from '../../hooks/useCategories'; import { ManagePayees } from './ManagePayees'; export default function ManagePayeesWithData({ initialSelectedIds }) { - let initialPayees = useSelector(state => 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 cb13de4be27f52900230b9ca32b653a3168e6688..479ee0242caa5accf8c3cb331765342b7421cc04 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 6a25680c905463979aed4485a43a3a9c3ae0378b..b376752ae3090a43692d6c09d86f68a26b0f02f4 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 3875c847770d666dcc708e6b2b5fae47356ba47c..07d05ddb55395417f76d0cc58f662078913a95e8 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 ( <Row diff --git a/packages/desktop-client/src/components/reports/CategorySelector.tsx b/packages/desktop-client/src/components/reports/CategorySelector.tsx index f22cf6e1f9bbc791f157647d0e17ba596f8b69bf..6c75ba288a590f02c4e60103f74ba6f40bb44fc7 100644 --- a/packages/desktop-client/src/components/reports/CategorySelector.tsx +++ b/packages/desktop-client/src/components/reports/CategorySelector.tsx @@ -43,7 +43,7 @@ export default function CategorySelector({ selectedCategoryMap.includes(category.id), ); - let selectAll: CategoryEntity[] = []; + const selectAll: CategoryEntity[] = []; categoryGroups.map(categoryGroup => categoryGroup.categories.map(category => selectAll.push(category)), ); diff --git a/packages/desktop-client/src/components/reports/ChooseGraph.js b/packages/desktop-client/src/components/reports/ChooseGraph.js index 49318f468e2717038cd345d09a6db633893b4e5b..bf2edbb2e445772fd5ca2aed6074adb30b33918e 100644 --- a/packages/desktop-client/src/components/reports/ChooseGraph.js +++ b/packages/desktop-client/src/components/reports/ChooseGraph.js @@ -28,7 +28,7 @@ export function ChooseGraph({ months, }) { function saveScrollWidth(parent, child) { - let width = parent > 0 && child > 0 && parent - child; + const width = parent > 0 && child > 0 && parent - child; setScrollWidth(!width ? 0 : width); } diff --git a/packages/desktop-client/src/components/reports/Header.js b/packages/desktop-client/src/components/reports/Header.js index e1b6408bd1b811cbb12c7e5c3ba7d6eee168f9c2..dffee4321ca729dd146e61046e2b91b634f2989f 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 ( <View diff --git a/packages/desktop-client/src/components/reports/Overview.js b/packages/desktop-client/src/components/reports/Overview.js index 5c2784bd001221312a62f92e617eea041867d555..e89c0626cd8711c6823ab4b99235697a181c6c16 100644 --- a/packages/desktop-client/src/components/reports/Overview.js +++ b/packages/desktop-client/src/components/reports/Overview.js @@ -12,14 +12,14 @@ import NetWorthCard from './reports/NetWorthCard'; import SankeyCard from './reports/SankeyCard'; export default function Overview() { - let categorySpendingReportFeatureFlag = useFeatureFlag( + const categorySpendingReportFeatureFlag = useFeatureFlag( 'categorySpendingReport', ); - let sankeyFeatureFlag = useFeatureFlag('sankeyReport'); + const sankeyFeatureFlag = useFeatureFlag('sankeyReport'); - let customReportsFeatureFlag = useFeatureFlag('customReports'); + const customReportsFeatureFlag = useFeatureFlag('customReports'); - let accounts = useSelector(state => state.queries.accounts); + const accounts = useSelector(state => state.queries.accounts); return ( <View style={{ diff --git a/packages/desktop-client/src/components/reports/ReportSummary.js b/packages/desktop-client/src/components/reports/ReportSummary.js index 562de586050614acd7aa5d07755462fc5fdea178..cfe2e5b709023419412908725948a7a385ed6e82 100644 --- a/packages/desktop-client/src/components/reports/ReportSummary.js +++ b/packages/desktop-client/src/components/reports/ReportSummary.js @@ -19,7 +19,7 @@ export function ReportSummary({ balanceTypeOp, monthsCount, }) { - let net = data.totalDebts > data.totalAssets ? 'EXPENSE' : 'INCOME'; + const net = data.totalDebts > data.totalAssets ? 'EXPENSE' : 'INCOME'; const average = amountToInteger(data[balanceTypeOp]) / monthsCount; return ( <View diff --git a/packages/desktop-client/src/components/reports/ReportTable.tsx b/packages/desktop-client/src/components/reports/ReportTable.tsx index fd7f8999ef039c297bf9b4ae00d509c8d6de66c9..11673cc45d179a21a8ac915f72f2f29e5cde4c26 100644 --- a/packages/desktop-client/src/components/reports/ReportTable.tsx +++ b/packages/desktop-client/src/components/reports/ReportTable.tsx @@ -3,7 +3,7 @@ import React, { useLayoutEffect, useRef } from 'react'; import View from '../common/View'; export default function ReportTable({ saveScrollWidth, style, children }) { - let contentRef = useRef<HTMLDivElement>(); + const contentRef = useRef<HTMLDivElement>(); 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 b6303870ace16a698d8d2773330b32fb959130e1..f9554bc20738093ad6894dd14180068ab10497da 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 ( <View diff --git a/packages/desktop-client/src/components/reports/Tooltip.js b/packages/desktop-client/src/components/reports/Tooltip.js index 090be01f71fbd1ccf4bcd13e6055be119642edcf..20f2af6b27ee3d7f107b89867e13b84837e36667 100644 --- a/packages/desktop-client/src/components/reports/Tooltip.js +++ b/packages/desktop-client/src/components/reports/Tooltip.js @@ -10,16 +10,16 @@ class Tooltip extends Component { static defaultEvents = VictoryTooltip.defaultEvents; render() { - let { + const { active, x, - y, + y: originalY, scale, datum, portalHost, offsetX = 0, offsetY, - position, + position: originalPosition, light, forceActive, style, @@ -27,6 +27,7 @@ class Tooltip extends Component { const xRange = scale.x.range(); const xPos = x - xRange[0]; + let position = originalPosition; if (!position) { if (datum.labelPosition) { position = datum.labelPosition; @@ -39,7 +40,7 @@ class Tooltip extends Component { return null; } - y = offsetY ? offsetY(y) : y; + const y = offsetY ? offsetY(originalY) : originalY; return ReactDOM.createPortal( <div diff --git a/packages/desktop-client/src/components/reports/chart-theme.js b/packages/desktop-client/src/components/reports/chart-theme.js index 140b1c63d2a0e2af1bbc2f51abd24189815e3e10..f525d3c0cd8027b5b752cd64a2845183adc6721f 100644 --- a/packages/desktop-client/src/components/reports/chart-theme.js +++ b/packages/desktop-client/src/components/reports/chart-theme.js @@ -1,6 +1,6 @@ import { theme } from '../../style'; -let colorFades = { +const colorFades = { blueFadeStart: 'rgba(229, 245, 255, 1)', blueFadeEnd: 'rgba(229, 245, 255, 0)', redFadeStart: 'rgba(255, 243, 242, 1)', diff --git a/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx b/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx index 2370d57d0fe540dc6ea1ebe04ab83b3c4a9d5ec2..b50331b52f34f660695795a54a6426810dcdf68c 100644 --- a/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/AreaGraph.tsx @@ -98,7 +98,7 @@ type AreaGraphProps = { }; function AreaGraph({ style, data, balanceTypeOp, compact }: AreaGraphProps) { - let privacyMode = usePrivacyMode(); + const privacyMode = usePrivacyMode(); const tickFormatter = tick => { 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 6fdaf45a21e3007d2d82cfe5b30db31d66e7119f..2d9ec64b203aed08b90a3dbec9ee4d4572d4ef3f 100644 --- a/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/BarGraph.tsx @@ -148,7 +148,7 @@ function BarGraph({ compact, domain, }: 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 de73a14d6f260ee8e8f9c3cf85f9834f3e240483..753009a029f3aef7c5ae515c56e74e91ace566e6 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 f0925ab9a1d654f2f9e65cac8700d586105d2c5d..8b0ba322245ff1cec1d67444d1c5ca1bd1ca5a90 100644 --- a/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx +++ b/packages/desktop-client/src/components/reports/graphs/StackedBarGraph.tsx @@ -121,7 +121,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 a2b43f8184f86b2e2e9b11ec39adc06f8810fc90..5ec38146d7e943d371491f7839287c74bba0f25d 100644 --- a/packages/desktop-client/src/components/reports/reports/CustomReport.js +++ b/packages/desktop-client/src/components/reports/reports/CustomReport.js @@ -62,7 +62,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,8 +101,8 @@ export default function CustomReport() { run(); }, []); - let payees = useCachedPayees(); - let accounts = useCachedAccounts(); + const payees = useCachedPayees(); + const accounts = useCachedAccounts(); const getGraphData = useMemo(() => { setDataCheck(false); @@ -137,7 +137,7 @@ export default function CustomReport() { ]); const data = useReport('default', getGraphData); - 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 e3f928b5fb4ab045aa92fbbf6433d325060cadff..8d9be68073d6061c4e6f2f69975795d43ebb1fd1 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 34502fb48a2be36303725e5e8876851004ded819..20ae05ef9c39ae57acf44b3efbfc3790a53eb38d 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 b55a7b71bd8517543a566fcb80a9c1a535d03252..e3a9d037fd2a99057badaad34273f5df255b6910 100644 --- a/packages/desktop-client/src/components/reports/spreadsheets/default-spreadsheet.tsx +++ b/packages/desktop-client/src/components/reports/spreadsheets/default-spreadsheet.tsx @@ -22,21 +22,21 @@ export default function createSpreadsheet( uncat, setDataCheck, ) { - let uncatCat = { + const uncatCat = { name: 'Uncategorized', id: null, uncat_id: '1', hidden: 0, offBudget: false, }; - let uncatTransfer = { + const uncatTransfer = { name: 'Transfers', id: null, uncat_id: '2', hidden: 0, transfer: false, }; - let uncatOff = { + const uncatOff = { name: 'OffBudget', id: null, uncat_id: '3', @@ -44,20 +44,20 @@ export default function createSpreadsheet( offBudget: true, }; - let uncatGroup = { + const uncatGroup = { name: 'Uncategorized', id: null, hidden: 0, categories: [uncatCat, uncatTransfer, uncatOff], }; - let catList = uncat + const catList = uncat ? [...categories.list, uncatCat, uncatTransfer, uncatOff] : categories.list; - let catGroup = uncat + const catGroup = uncat ? [...categories.grouped, uncatGroup] : categories.grouped; - let categoryFilter = (catList || []).filter( + const categoryFilter = (catList || []).filter( category => !category.hidden && selectedCategories && @@ -101,13 +101,13 @@ 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'; function makeQuery(splt, name) { - let query = q('transactions') + const query = q('transactions') .filter( //Show Offbudget and hidden categories !hidden && { @@ -181,7 +181,7 @@ export default function createSpreadsheet( const graphData = await Promise.all( groupByList.map(async splt => { - let [starting, assets, debts] = await Promise.all([ + const [starting, assets, debts] = await Promise.all([ runQuery( q('transactions') .filter( 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 81a685be8e658b4c2a077973b10c37e267ebfb26..4bc90d04124824b2f14dfe98382cf2958d2fdd2a 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 7946aff2a5012eb906d526060517c1aaf3d0c121..cafb5ae568ff067f91e465f959e9e6132606ba65 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 b3cb72c85ad34b4e5800e1aac75e448d149121d9..d6ad29ffa14b3a46843d60c616af5a57275e6078 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); }), @@ -32,12 +32,12 @@ export function indexStack(data, fieldName, field) { 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 570e533aabebe75bf7a18b530b630e87eeaa254a..579f70009d8c9d227d27dd1c45b61efd21e0c279 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 <LoadComponent name={name} importer={loadWide} />; diff --git a/packages/desktop-client/src/components/rules/ActionExpression.tsx b/packages/desktop-client/src/components/rules/ActionExpression.tsx index cb1d5b2cea94ee07f6e397ea7634eaa050ffd582..607276cdcada07b0ee1c792793caa0b6a76e3aa2 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 1a97c27a3d0212c0042c9142737c30ff7f1eef52..48f957d06bc6e42cd808856a0da4637305914bf8 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 037a85cba91006cbbd6e6a4fc8553bbd27a094c4..c9977fb19bf841dc584461dfb729379dc47658d7 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 ( <Row diff --git a/packages/desktop-client/src/components/rules/RulesHeader.tsx b/packages/desktop-client/src/components/rules/RulesHeader.tsx index f41c53f9c0c938d1a4e69f2cb1371fd0c76cb9b9..a576c997ac326edd4a0dd29d24a7d16cdf3c5922 100644 --- a/packages/desktop-client/src/components/rules/RulesHeader.tsx +++ b/packages/desktop-client/src/components/rules/RulesHeader.tsx @@ -4,8 +4,8 @@ import { useSelectedItems, useSelectedDispatch } from '../../hooks/useSelected'; import { SelectCell, Cell, TableHeader } from '../table'; export default function RulesHeader() { - let selectedItems = useSelectedItems(); - let dispatchSelected = useSelectedDispatch(); + const selectedItems = useSelectedItems(); + const dispatchSelected = useSelectedDispatch(); return ( <TableHeader version="v2" style={{}}> diff --git a/packages/desktop-client/src/components/rules/RulesList.tsx b/packages/desktop-client/src/components/rules/RulesList.tsx index 1f5a45437ac468ec136e9395197db2f3bbbf303f..c56b58cbf8ff9e0e197b7c643206c067920ab1b7 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 ( <View> {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 ( <RuleRow diff --git a/packages/desktop-client/src/components/rules/ScheduleValue.tsx b/packages/desktop-client/src/components/rules/ScheduleValue.tsx index 9031a19410a558fbede9dac867988aec7c0f58cc..dd256a563d225a706313cb60b641ece64227e630 100644 --- a/packages/desktop-client/src/components/rules/ScheduleValue.tsx +++ b/packages/desktop-client/src/components/rules/ScheduleValue.tsx @@ -13,9 +13,9 @@ type ScheduleValueProps = { }; export default function ScheduleValue({ value }: ScheduleValueProps) { - let payees = useSelector(state => 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 ( <Value diff --git a/packages/desktop-client/src/components/rules/SimpleTable.tsx b/packages/desktop-client/src/components/rules/SimpleTable.tsx index c507792462965bec830def54ed5b706bea9d2a90..836a9ef8523dfa8affac6135810da24c177bb041 100644 --- a/packages/desktop-client/src/components/rules/SimpleTable.tsx +++ b/packages/desktop-client/src/components/rules/SimpleTable.tsx @@ -18,9 +18,9 @@ export default function SimpleTable({ onHoverLeave, children, }: SimpleTableProps) { - let contentRef = useRef<HTMLDivElement>(); - let contentHeight = useRef<number>(); - let scrollRef = useRef<HTMLDivElement>(); + const contentRef = useRef<HTMLDivElement>(); + const contentHeight = useRef<number>(); + const scrollRef = useRef<HTMLDivElement>(); 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 74474f1ec02c964ce45c2a307e8dd29ed44ac699..eb802b288d3a4bb6560bedca8caaec9b5257089a 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<T>({ // @ts-expect-error fix this later describe = x => x.name, }: ValueProps<T>) { - 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<T>({ ? accounts : []); - let [expanded, setExpanded] = useState(false); + const [expanded, setExpanded] = useState(false); function onExpand(e) { e.preventDefault(); @@ -92,7 +92,7 @@ export default function Value<T>({ 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<T>({ if (!expanded && value.length > 4) { displayed = value.slice(0, 3); } - let numHidden = value.length - displayed.length; + const numHidden = value.length - displayed.length; return ( <Text style={{ color: theme.tableText }}> [ {displayed.map((v, i) => { - let text = <Text style={valueStyle}>{formatValue(v)}</Text>; + const text = <Text style={valueStyle}>{formatValue(v)}</Text>; 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 8315dc3316882d291d644f817f70c0329c04547c..74a9f2646d62856be58be27a7d02f03422855b0a 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 d4d0353973c2277574d9c3da383f50de478c1662..3a8d0e0258ccffccc8ea08c1c928510170018922 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 ( <Modal title={payee ? `Schedule: ${payee.name}` : 'Schedule'} diff --git a/packages/desktop-client/src/components/schedules/LinkSchedule.tsx b/packages/desktop-client/src/components/schedules/LinkSchedule.tsx index 2a9554ab7684d59f51e6b9f495db7bd9168ef6d5..dc83aa1103a5b55afcca2492574c5052055f6820 100644 --- a/packages/desktop-client/src/components/schedules/LinkSchedule.tsx +++ b/packages/desktop-client/src/components/schedules/LinkSchedule.tsx @@ -22,18 +22,18 @@ export default function ScheduleLink({ modalProps?: CommonModalProps; transactionIds: string[]; }) { - let [filter, setFilter] = useState(''); + const [filter, setFilter] = useState(''); - let scheduleData = useSchedules({ + const scheduleData = useSchedules({ transform: useCallback((q: Query) => 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 5f991b5d78e4686b45c7ef212a4ad7e05eadaccf..48c5c2d2edd017b7e376d192f7929a00f19cde2c 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 e08d8e60bb0fced72013ebddc892d30ab0e45226..0e3754bf2cc0a76cb3ee418be46eb776e7423241 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<HTMLInputElement>) => void; }; -let DatePicker = forwardRef<DatePickerForwardedRef, DatePickerProps>( +const DatePicker = forwardRef<DatePickerForwardedRef, DatePickerProps>( ({ 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 2c5b47c16e7639f53ce5e82981810beda5ab8497..d6f4525e30b2c215d54a3d52f5eb78d21526234d 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 38aaf4981a5ea6ff24c337a0e42b523c75a7b25e..e82840a4a77bffcf149c87f408bb886d28613d25 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 ( <label style={{ display: 'flex' }}> @@ -61,9 +61,9 @@ function FeatureToggle({ } function ReportBudgetFeature() { - let budgetType = useSelector(state => state.prefs.local?.budgetType); - let enabled = useFeatureFlag('reportBudget'); - let blockToggleOff = budgetType === 'report' && enabled; + const budgetType = useSelector(state => state.prefs.local?.budgetType); + const enabled = useFeatureFlag('reportBudget'); + const blockToggleOff = budgetType === 'report' && enabled; return ( <FeatureToggle flag="reportBudget" @@ -76,7 +76,7 @@ function ReportBudgetFeature() { } export default function ExperimentalFeatures() { - let [expanded, setExpanded] = useState(false); + const [expanded, setExpanded] = useState(false); return ( <Setting diff --git a/packages/desktop-client/src/components/settings/Export.tsx b/packages/desktop-client/src/components/settings/Export.tsx index 73ac0327d1367c643f11cfb3ecd6359ff8e756e0..ee3f8864f054ee91cfc2dc4cac15da0af5e516c3 100644 --- a/packages/desktop-client/src/components/settings/Export.tsx +++ b/packages/desktop-client/src/components/settings/Export.tsx @@ -13,16 +13,16 @@ import Text from '../common/Text'; import { Setting } from './UI'; export default function ExportBudget() { - let [isLoading, setIsLoading] = useState(false); - let [error, setError] = useState<string | null>(null); - let budgetId = useSelector(state => state.prefs.local.id); - let encryptKeyId = useSelector(state => state.prefs.local.encryptKeyId); + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState<string | null>(null); + const budgetId = useSelector(state => state.prefs.local.id); + const encryptKeyId = useSelector(state => state.prefs.local.encryptKeyId); async function onExport() { setIsLoading(true); setError(null); - let response = await send('export-budget'); + const response = await send('export-budget'); if ('error' in response) { setError(response.error); diff --git a/packages/desktop-client/src/components/settings/FixSplits.tsx b/packages/desktop-client/src/components/settings/FixSplits.tsx index bafdf9adc249b1e5afe00e8a6c056fd4e70aff75..85c71fd3522194becd6ff6e9ab9c1387967b2d9e 100644 --- a/packages/desktop-client/src/components/settings/FixSplits.tsx +++ b/packages/desktop-client/src/components/settings/FixSplits.tsx @@ -14,7 +14,7 @@ import { Setting } from './UI'; type Results = Awaited<ReturnType<Handlers['tools/fix-split-transactions']>>; function renderResults(results: Results) { - let { numBlankPayees, numCleared, numDeleted } = results; + const { numBlankPayees, numCleared, numDeleted } = results; let result = ''; if (numBlankPayees === 0 && numCleared === 0 && numDeleted === 0) { result = 'No split transactions found needing repair.'; @@ -52,12 +52,12 @@ function renderResults(results: Results) { } export default function FixSplitsTool() { - let [loading, setLoading] = useState(false); - let [results, setResults] = useState<Results>(null); + const [loading, setLoading] = useState(false); + const [results, setResults] = useState<Results>(null); async function onFix() { setLoading(true); - let res = await send('tools/fix-split-transactions'); + const res = await send('tools/fix-split-transactions'); setResults(res); setLoading(false); } diff --git a/packages/desktop-client/src/components/settings/Format.tsx b/packages/desktop-client/src/components/settings/Format.tsx index 6ae2cd864dcd6c0e0f65aabd74a3408ce1f08023..995d2af3fa87e9fa3c2b700567e052c7c941899e 100644 --- a/packages/desktop-client/src/components/settings/Format.tsx +++ b/packages/desktop-client/src/components/settings/Format.tsx @@ -17,17 +17,18 @@ import { Setting } from './UI'; // Follows Pikaday 'firstDay' numbering // https://github.com/Pikaday/Pikaday -let daysOfWeek: { value: LocalPrefs['firstDayOfWeekIdx']; label: string }[] = [ - { value: '0', label: 'Sunday' }, - { value: '1', label: 'Monday' }, - { value: '2', label: 'Tuesday' }, - { value: '3', label: 'Wednesday' }, - { value: '4', label: 'Thursday' }, - { value: '5', label: 'Friday' }, - { value: '6', label: 'Saturday' }, -]; +const daysOfWeek: { value: LocalPrefs['firstDayOfWeekIdx']; label: string }[] = + [ + { value: '0', label: 'Sunday' }, + { value: '1', label: 'Monday' }, + { value: '2', label: 'Tuesday' }, + { value: '3', label: 'Wednesday' }, + { value: '4', label: 'Thursday' }, + { value: '5', label: 'Friday' }, + { value: '6', label: 'Saturday' }, + ]; -let dateFormats: { value: LocalPrefs['dateFormat']; label: string }[] = [ +const dateFormats: { value: LocalPrefs['dateFormat']; label: string }[] = [ { value: 'MM/dd/yyyy', label: 'MM/DD/YYYY' }, { value: 'dd/MM/yyyy', label: 'DD/MM/YYYY' }, { value: 'yyyy-MM-dd', label: 'YYYY-MM-DD' }, @@ -52,19 +53,19 @@ function Column({ title, children }: { title: string; children: ReactNode }) { } export default function FormatSettings() { - let { savePrefs } = useActions(); + const { savePrefs } = useActions(); - let sidebar = useSidebar(); - let firstDayOfWeekIdx = useSelector( + const sidebar = useSidebar(); + const firstDayOfWeekIdx = useSelector( state => state.prefs.local.firstDayOfWeekIdx || '0', // Sunday ); - let dateFormat = useSelector( + const dateFormat = useSelector( state => state.prefs.local.dateFormat || 'MM/dd/yyyy', ); - let numberFormat = useSelector( + const numberFormat = useSelector( state => state.prefs.local.numberFormat || 'comma-dot', ); - let hideFraction = useSelector(state => state.prefs.local.hideFraction); + const hideFraction = useSelector(state => state.prefs.local.hideFraction); return ( <Setting diff --git a/packages/desktop-client/src/components/settings/Global.tsx b/packages/desktop-client/src/components/settings/Global.tsx index 955a0580bae44c571c01d447a3a718f7b1e376c5..0a28d43d1c9f65198d2a2121c52f73b2a0d3b2a2 100644 --- a/packages/desktop-client/src/components/settings/Global.tsx +++ b/packages/desktop-client/src/components/settings/Global.tsx @@ -11,11 +11,11 @@ import View from '../common/View'; import { Setting } from './UI'; export default function GlobalSettings() { - let documentDir = useSelector(state => state.prefs.global.documentDir); - let { saveGlobalPrefs } = useActions(); + const documentDir = useSelector(state => state.prefs.global.documentDir); + const { saveGlobalPrefs } = useActions(); - let [documentDirChanged, setDirChanged] = useState(false); - let dirScrolled = useRef<HTMLSpanElement>(null); + const [documentDirChanged, setDirChanged] = useState(false); + const dirScrolled = useRef<HTMLSpanElement>(null); useEffect(() => { if (dirScrolled.current) { @@ -24,7 +24,7 @@ export default function GlobalSettings() { }, []); async function onChooseDocumentDir() { - let res = await window.Actual.openFileDialog({ + const res = await window.Actual.openFileDialog({ properties: ['openDirectory'], }); if (res) { diff --git a/packages/desktop-client/src/components/settings/Reset.tsx b/packages/desktop-client/src/components/settings/Reset.tsx index d2fc9b7639da37bc5a1a0e252755d93f67554f28..189e5a11973298e38bbe3ad060de3746014e917e 100644 --- a/packages/desktop-client/src/components/settings/Reset.tsx +++ b/packages/desktop-client/src/components/settings/Reset.tsx @@ -10,7 +10,7 @@ import Text from '../common/Text'; import { Setting } from './UI'; export function ResetCache() { - let [resetting, setResetting] = useState(false); + const [resetting, setResetting] = useState(false); async function onResetCache() { setResetting(true); @@ -38,10 +38,10 @@ export function ResetCache() { } export function ResetSync() { - let isEnabled = useSelector(state => !!state.prefs.local.groupId); - let { resetSync } = useActions(); + const isEnabled = useSelector(state => !!state.prefs.local.groupId); + const { resetSync } = useActions(); - let [resetting, setResetting] = useState(false); + const [resetting, setResetting] = useState(false); async function onResetSync() { setResetting(true); diff --git a/packages/desktop-client/src/components/settings/Themes.tsx b/packages/desktop-client/src/components/settings/Themes.tsx index 2883a972472cbf480d35b94c894f83aa0419807d..c43a1447e2c284a45b045f8679bc1d616f204581 100644 --- a/packages/desktop-client/src/components/settings/Themes.tsx +++ b/packages/desktop-client/src/components/settings/Themes.tsx @@ -9,8 +9,8 @@ import Text from '../common/Text'; import { Setting } from './UI'; export default function ThemeSettings() { - let theme = useTheme(); - let { saveGlobalPrefs } = useActions(); + const theme = useTheme(); + const { saveGlobalPrefs } = useActions(); return ( <Setting diff --git a/packages/desktop-client/src/components/settings/UI.tsx b/packages/desktop-client/src/components/settings/UI.tsx index 8683aeaf7bbabd1218440e253a47339308f348a0..60adc092c4088f3552954b5215d4a135efdbd901 100644 --- a/packages/desktop-client/src/components/settings/UI.tsx +++ b/packages/desktop-client/src/components/settings/UI.tsx @@ -49,8 +49,8 @@ type AdvancedToggleProps = { }; export const AdvancedToggle = ({ children }: AdvancedToggleProps) => { - let location = useLocation(); - let [expanded, setExpanded] = useState(location.hash === '#advanced'); + const location = useLocation(); + const [expanded, setExpanded] = useState(location.hash === '#advanced'); return expanded ? ( <View diff --git a/packages/desktop-client/src/components/settings/index.tsx b/packages/desktop-client/src/components/settings/index.tsx index 00be17e7df9e45482fd8b825a7d7e875c7ad60c2..eb8cefd0a9c28c6f9bc2bb618a5542ecb813ac82 100644 --- a/packages/desktop-client/src/components/settings/index.tsx +++ b/packages/desktop-client/src/components/settings/index.tsx @@ -88,8 +88,8 @@ function IDName({ children }: { children: ReactNode }) { } function AdvancedAbout() { - let budgetId = useSelector(state => state.prefs.local.id); - let groupId = useSelector(state => state.prefs.local.groupId); + const budgetId = useSelector(state => state.prefs.local.id); + const groupId = useSelector(state => state.prefs.local.groupId); return ( <Setting> @@ -117,15 +117,15 @@ function AdvancedAbout() { } export default function Settings() { - let floatingSidebar = useSelector( + const floatingSidebar = useSelector( state => state.prefs.global.floatingSidebar, ); - let budgetName = useSelector(state => state.prefs.local.budgetName); + const budgetName = useSelector(state => state.prefs.local.budgetName); - let { loadPrefs, closeBudget } = useActions(); + const { loadPrefs, closeBudget } = useActions(); useEffect(() => { - let unlisten = listen('prefs-updated', () => { + const unlisten = listen('prefs-updated', () => { loadPrefs(); }); diff --git a/packages/desktop-client/src/components/sidebar/Account.tsx b/packages/desktop-client/src/components/sidebar/Account.tsx index a59337f2763ec815059171bde5bb0cdca0ea800f..d0f7ef70105c0c9c83e7241d0fff14405c4e7aa0 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 d250ec3311a3bcde4bfef723e7222f1a068ed53f..e15559709b28a342b6dc93efa93ebe355c2e52b2 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 7b51e2d7a8f8518fbad71e8487e5be489d3a3a84..c6aa9435979d25ef8caae6dc7f8f5e6ae700b9f5 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 5fa7122b7b4097178b6f08fd7442ce9e80f8ad74..3ea71ba13f937bb620203557193fbc2db999d4ab 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 d07e50ea8b8124bc40b71b03e712058dfa13ef38..e8bad134a41851733f6c0906800b12dd6eaf2351 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 8735f354f41c75826183d362dcfd93de05e040f9..1ed74fb329e7b0d2bad90b275727cdaeb0807b59 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 ( <SidebarContext.Provider @@ -47,7 +47,7 @@ function SidebarProvider({ children }: SidebarProviderProps) { } function useSidebar() { - let { hidden, setHidden, floating, alwaysFloats } = + const { hidden, setHidden, floating, alwaysFloats } = useContext(SidebarContext); return useMemo( @@ -57,14 +57,14 @@ function useSidebar() { } function FloatableSidebar() { - let floatingSidebar = useSelector( + const floatingSidebar = useSelector( state => 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 : ( <View diff --git a/packages/desktop-client/src/components/sort.tsx b/packages/desktop-client/src/components/sort.tsx index 441e1d187f601926b9b73196935794f4f19f8765..10e7d963d110ddb281a8197ec1ee3d4c19a1544a 100644 --- a/packages/desktop-client/src/components/sort.tsx +++ b/packages/desktop-client/src/components/sort.tsx @@ -40,7 +40,7 @@ export function useDraggable<T>({ canDrag, onDragChange, }: UseDraggableArgs<T>) { - 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<DropPosition>(null); + const ref = useRef(null); + const [dropPos, setDropPos] = useState<DropPosition>(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 6c1e725826c4149fa9dc904abae754c42b41d941..02bee9c23db17e29c93394d711a433956f28e791 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 ( <ConditionalPrivacyFilter diff --git a/packages/desktop-client/src/components/spreadsheet/useFormat.ts b/packages/desktop-client/src/components/spreadsheet/useFormat.ts index b99667e5d67f310016954e2955b3d0471c9f5210..2b9a1eb74ab80b8c717750f1af63c1eb0d167063 100644 --- a/packages/desktop-client/src/components/spreadsheet/useFormat.ts +++ b/packages/desktop-client/src/components/spreadsheet/useFormat.ts @@ -20,7 +20,7 @@ function format( case 'number': return '' + value; case 'financial-with-sign': - let formatted = format(value, 'financial', formatter); + const formatted = format(value, 'financial', formatter); if (typeof value === 'number' && value >= 0) { return '+' + formatted; } diff --git a/packages/desktop-client/src/components/spreadsheet/useSheetName.ts b/packages/desktop-client/src/components/spreadsheet/useSheetName.ts index a08fac549b1170f815e1d772fe1179c38d343e20..8b80e5ac28ca5a8275dcdbd51c6d330bf65c165d 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 154ea11fd104a05ea1e8edc3b281126e3338c829..faac71e234c60d7d86a58e4516a4c3b59ad9f909 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 e11e65a6864a840d9a9d672dd54024056fec55a6..42e41e6b7e3a609f7061a99231cc26eedda013e7 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( () => ( <ConditionalPrivacyFilter privacyFilter={mergeConditionalPrivacyFilterProps( @@ -315,7 +315,7 @@ function InputValue({ onBlur, ...props }: InputValueProps) { - let [value, setValue] = useState(defaultValue); + const [value, setValue] = useState(defaultValue); function onBlur_(e) { onUpdate?.(value); @@ -428,8 +428,8 @@ export function CustomCell({ onBlur, ...props }: CustomCellProps) { - let [value, setValue] = useState(defaultValue); - let [prevDefaultValue, setPrevDefaultValue] = useState(defaultValue); + const [value, setValue] = useState(defaultValue); + const [prevDefaultValue, setPrevDefaultValue] = useState(defaultValue); if (prevDefaultValue !== defaultValue) { setValue(defaultValue); @@ -689,13 +689,13 @@ export function SheetCell({ privacyFilter, } = valueProps; - let sheetValue = useSheetValue(binding, e => { + 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 ( <Cell @@ -783,8 +783,8 @@ export function TableHeader({ } export function SelectedItemsButton({ name, keyHandlers, items, onSelect }) { - let selectedItems = useSelectedItems(); - let [menuOpen, setMenuOpen] = useState(null); + const selectedItems = useSelectedItems(); + const [menuOpen, setMenuOpen] = useState(null); if (selectedItems.size === 0) { return null; @@ -827,7 +827,7 @@ export function SelectedItemsButton({ name, keyHandlers, items, onSelect }) { ); } -let rowStyle: CSSProperties = { +const rowStyle: CSSProperties = { position: 'absolute', willChange: 'transform', width: '100%', @@ -851,7 +851,7 @@ export const TableWithNavigator = forwardRef< TableHandleRef<TableItem>, TableWithNavigatorProps >(({ fields, ...props }, ref) => { - let navigator = useTableNavigator(props.items, fields); + const navigator = useTableNavigator(props.items, fields); return <Table {...props} navigator={navigator} />; }); @@ -922,16 +922,16 @@ export const Table: <T extends TableItem>( }; } - 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: <T extends TableItem>( 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: <T extends TableItem>( }); 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: <T extends TableItem>( ); } - let isEmpty = (count || items.length) === 0; + const isEmpty = (count || items.length) === 0; return ( <View @@ -1174,17 +1174,17 @@ export function useTableNavigator<T extends TableItem>( data: T[], fields: string[] | ((item?: T) => string[]), ): TableNavigator<T> { - let getFields = typeof fields !== 'function' ? () => fields : fields; - let [editingId, setEditingId] = useState<T['id']>(null); - let [focusedField, setFocusedField] = useState<string>(null); - let containerRef = useRef<HTMLDivElement>(); + const getFields = typeof fields !== 'function' ? () => fields : fields; + const [editingId, setEditingId] = useState<T['id']>(null); + const [focusedField, setFocusedField] = useState<string>(null); + const containerRef = useRef<HTMLDivElement>(); // 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<T extends TableItem>( } 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<T extends TableItem>( } 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<T extends TableItem>( 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<T extends TableItem>( 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<T extends TableItem>( // 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 6969e63d3f4ac54ddbc0b5a0081950bfc40e38de..9903976688351743b348302551aa57d360b3706a 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 4ae28e15a513caabe9b8de61f22e5953a78a30c3..369ea54da8fab8f866b13ddcbb9e349a60b119d4 100644 --- a/packages/desktop-client/src/components/transactions/MobileTransaction.js +++ b/packages/desktop-client/src/components/transactions/MobileTransaction.js @@ -70,11 +70,11 @@ 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}`; @@ -86,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), @@ -95,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(), @@ -110,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)) { @@ -202,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 @@ -219,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); } @@ -253,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), ); @@ -280,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 @@ -296,7 +297,7 @@ class TransactionEditInner extends PureComponent { }; onDelete = () => { - let onConfirmDelete = () => { + const onConfirmDelete = () => { this.props.onDelete(); const { transactions } = this.state; @@ -651,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; @@ -677,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('*') @@ -712,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) { @@ -838,10 +839,10 @@ class Transaction extends PureComponent { onSelect, style, } = this.props; - let { + const { id, payee: payeeId, - amount, + amount: originalAmount, category, cleared, is_parent, @@ -849,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, }; @@ -1004,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; } @@ -1099,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() { @@ -1145,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'], }); @@ -1197,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 ( <li diff --git a/packages/desktop-client/src/components/transactions/SelectedTransactions.js b/packages/desktop-client/src/components/transactions/SelectedTransactions.js index d29843896ac0437aeb079a1f75011227fdf0a780..0af017a798ec416298e9aa6d69fce99555369be4 100644 --- a/packages/desktop-client/src/components/transactions/SelectedTransactions.js +++ b/packages/desktop-client/src/components/transactions/SelectedTransactions.js @@ -17,27 +17,27 @@ export function SelectedTransactionsButton({ onScheduleAction, pushModal, }) { - let selectedItems = useSelectedItems(); + const selectedItems = useSelectedItems(); - let types = useMemo(() => { - 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 076a682c5edf9ea8bed21f05c211954603ceb666..16d99dce3ae82d2c505cc68b1445707de6f93585 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 ( <Row style={{ color: theme.tableText }}> @@ -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 ( <TransactionRow diff --git a/packages/desktop-client/src/components/transactions/TransactionList.js b/packages/desktop-client/src/components/transactions/TransactionList.js index 417bef7f308ef79d8a59d3248b245c82aca9498a..ad2ac89887627ea3e2dad50176d865fae7c460a2 100644 --- a/packages/desktop-client/src/components/transactions/TransactionList.js +++ b/packages/desktop-client/src/components/transactions/TransactionList.js @@ -36,7 +36,7 @@ import { TransactionTable } from './TransactionsTable'; // one to use when doing updates. async function saveDiff(diff) { - let remoteUpdates = await send('transactions-batch-update', { + const remoteUpdates = await send('transactions-batch-update', { ...diff, learnCategories: true, }); @@ -47,7 +47,7 @@ async function saveDiff(diff) { } async function saveDiffAndApply(diff, changes, onChange) { - let remoteDiff = await saveDiff(diff); + const remoteDiff = await saveDiff(diff); onChange( applyTransactionDiff(changes.newTransaction, remoteDiff), applyChanges(remoteDiff, changes.data), @@ -86,25 +86,25 @@ export default function TransactionList({ onCloseAddTransaction, onCreatePayee, }) { - let transactionsLatest = useRef(); - let navigate = useNavigate(); + const transactionsLatest = useRef(); + const navigate = useNavigate(); useLayoutEffect(() => { 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 4710d7d89ed765dbaba07b0b421404ac2b130b7c..26b9f2361dce2a64f7ef945bcab84032a09edb52 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 ( <SplitsExpandedContext.Provider value={value}> @@ -262,7 +263,7 @@ const TransactionHeader = memo( ascDesc, field, }) => { - let dispatchSelected = useSelectedDispatch(); + const dispatchSelected = useSelectedDispatch(); return ( <Row @@ -373,7 +374,7 @@ const TransactionHeader = memo( ); function getPayeePretty(transaction, payee, transferAcct) { - let { payee: payeeId } = transaction; + const { payee: payeeId } = transaction; if (transferAcct) { return ( @@ -411,11 +412,11 @@ function StatusCell({ onEdit, onUpdate, }) { - let isClearedField = + const isClearedField = status === 'cleared' || status === 'reconciled' || status == null; - let statusProps = getStatusProps(status); + const statusProps = getStatusProps(status); - let statusColor = + const statusColor = status === 'cleared' ? theme.noticeTextLight : status === 'reconciled' @@ -533,7 +534,7 @@ function PayeeCell({ onNavigateToTransferAccount, onNavigateToSchedule, }) { - let isCreatingPayee = useRef(false); + const isCreatingPayee = useRef(false); // Filter out the account we're currently in as it is not a valid transfer accounts = accounts.filter(account => 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 edc14f7f1905d362d8a8e1c36454bf1d18e4f8ef..b62d840267a3116d642c82a49d484cc855e96625 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( <LiveTransactionTable {...defaultProps} {...extraProps} />, ); 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 e4e57e0c7a37e7911e8d449093f3aa260c139c9d..632082cf9eac2ddf10e8e4d62b7ab24b2d5dba21 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<HTMLInputElement>(); - let mergedRef = useMergedRefs<HTMLInputElement>(inputRef, ref); + const ref = useRef<HTMLInputElement>(); + const mergedRef = useMergedRefs<HTMLInputElement>(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 ( <View style={{ flexDirection: 'row', alignItems: 'center' }}> diff --git a/packages/desktop-client/src/components/util/DisplayId.tsx b/packages/desktop-client/src/components/util/DisplayId.tsx index 0a66bf34f2fb913c35cfe749fa2a1ecc37d6c3cd..ecc14437543969204608e5df4dedafa74f3904df 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 ( <DataComponent idKey={true}> {data => { - let item = data[id]; + const item = data[id]; return ( <Text diff --git a/packages/desktop-client/src/components/util/GenericInput.js b/packages/desktop-client/src/components/util/GenericInput.js index be1037e0a02bcc407b36b57e881b2cc8f1bd682a..e62807b60e2728d1584eea60d0d8648cfd2ebe71 100644 --- a/packages/desktop-client/src/components/util/GenericInput.js +++ b/packages/desktop-client/src/components/util/GenericInput.js @@ -25,9 +25,9 @@ export default function GenericInput({ style, onChange, }) { - let { grouped: categoryGroups } = useCategories(); - let saved = useSelector(state => 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 08be27854aae216157a2ed30435f67553ae2ddba..74a97f62d4c77204bc815b12046c254fcd75ff40 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<K extends string>({ message, importer, }: LoadComponentProps<K>) { - let [Component, setComponent] = useState<ProplessComponent | null>(null); + const [Component, setComponent] = useState<ProplessComponent | null>(null); useEffect(() => { importer().then(module => setComponent(() => module[name])); }, [name, importer]); diff --git a/upcoming-release-notes/2034.md b/upcoming-release-notes/2034.md new file mode 100644 index 0000000000000000000000000000000000000000..82aadd8c44203c332f60c121a69cc9378ff8115d --- /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