import React, { useState, useEffect, useRef, useContext } from 'react'; import { connect } from 'react-redux'; import { Switch, Route, withRouter } from 'react-router-dom'; import * as actions from 'loot-core/src/client/actions'; import Platform from 'loot-core/src/client/platform'; import * as queries from 'loot-core/src/client/queries'; import { listen } from 'loot-core/src/platform/client/fetch'; import { View, Text, ButtonLink, Button, ButtonWithLoading, Tooltip, P } from 'loot-design/src/components/common'; import SheetValue from 'loot-design/src/components/spreadsheet/SheetValue'; import { colors } from 'loot-design/src/style'; import ArrowLeft from 'loot-design/src/svg/v1/ArrowLeft'; import AlertTriangle from 'loot-design/src/svg/v2/AlertTriangle'; import ArrowButtonRight1 from 'loot-design/src/svg/v2/ArrowButtonRight1'; import NavigationMenu from 'loot-design/src/svg/v2/NavigationMenu'; import AccountSyncCheck from './accounts/AccountSyncCheck'; import AnimatedRefresh from './AnimatedRefresh'; import { MonthCountSelector } from './budget/MonthCountSelector'; import { useSidebar } from './FloatableSidebar'; import LoggedInUser from './LoggedInUser'; export let TitlebarContext = React.createContext(); export function TitlebarProvider({ children }) { let listeners = useRef([]); function sendEvent(msg) { listeners.current.forEach(func => func(msg)); } function subscribe(listener) { listeners.current.push(listener); return () => (listeners.current = listeners.current.filter(func => func !== listener)); } return ( ); } export function UncategorizedButton() { return ( {node => { const num = node.value; return ( num !== 0 && ( {num} uncategorized {num === 1 ? 'transaction' : 'transactions'} ) ); }} ); } function SyncButton({ localPrefs, style, onSync }) { let [syncing, setSyncing] = useState(false); let [syncState, setSyncState] = useState(null); useEffect(() => { let unlisten = listen('sync-event', ({ type, subtype, syncDisabled }) => { if (type === 'start') { setSyncing(true); setSyncState(null); } else { // Give the layout some time to apply the starting animation // so we always finish it correctly even if it's almost // instant setTimeout(() => { setSyncing(false); }, 20); } if (type === 'error') { // Use the offline state if either there is a network error or // if this file isn't a "cloud file". You can't sync a local // file. if (subtype === 'network') { setSyncState('offline'); } else if (!localPrefs.cloudFileId) { setSyncState('local'); } else { setSyncState('error'); } } else if (type === 'success') { setSyncState(syncDisabled ? 'disabled' : null); } }); return unlisten; }, []); return ( ); } function BudgetTitlebar({ globalPrefs, saveGlobalPrefs, localPrefs }) { let { sendEvent } = useContext(TitlebarContext); let [loading, setLoading] = useState(false); let [showTooltip, setShowTooltip] = useState(false); let reportBudgetEnabled = localPrefs['flags.reportBudget']; function onSwitchType() { setLoading(true); if (!loading) { sendEvent('budget/switch-type'); } } useEffect(() => { setLoading(false); }, [localPrefs.budgetType]); let { budgetType } = localPrefs; return ( saveGlobalPrefs({ maxMonths: value })} /> {reportBudgetEnabled && ( {showTooltip && ( setShowTooltip(false)} style={{ padding: 10, maxWidth: 400 }} >

You are currently using a{' '} {budgetType === 'report' ? 'Report budget' : 'Rollover budget'} . {' '} Switching will not lose any data and you can always switch back.

Switch to a{' '} {budgetType === 'report' ? 'Rollover budget' : 'Report budget'}

How do these types of budgeting work?

)}
)}
); } function Titlebar({ location, globalPrefs, saveGlobalPrefs, localPrefs, userData, floatingSidebar, syncError, setAppState, style, sync }) { let sidebar = useSidebar(); return ( {floatingSidebar && ( )} { let state = props.location.state || {}; return state.goBack ? ( ) : null; }} /> { return ( props.match && ); }} /> ( )} /> ); } export default withRouter( connect( state => ({ globalPrefs: state.prefs.global, localPrefs: state.prefs.local, userData: state.user.data, floatingSidebar: state.prefs.global.floatingSidebar }), actions )(Titlebar) );