Replace CLOSE_BUDGET action

This commit is contained in:
Joel Jeremy Marquez
2025-01-14 12:00:54 -08:00
parent fa3c692292
commit 4d6067cd7c
9 changed files with 95 additions and 58 deletions

View File

@@ -2,6 +2,7 @@ import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
import { send } from '../../platform/client/fetch';
import { type AccountEntity, type TransactionEntity } from '../../types/models';
import { closeBudget, closeBudgetUI } from '../budgets/budgetsSlice';
import { addNotification } from '../notifications/notificationsSlice';
import {
getAccounts,
@@ -62,6 +63,14 @@ const accountsSlice = createSlice({
delete state.failedAccounts[action.payload.id];
},
},
extraReducers: builder => {
builder.addMatcher(
action =>
closeBudget.fulfilled.match(action) ||
closeBudgetUI.fulfilled.match(action),
() => getInitialState(),
);
},
});
type UnlinkAccountPayload = {

View File

@@ -5,6 +5,7 @@ import { getUploadError } from '../../shared/errors';
import { type AccountEntity } from '../../types/models';
import { type AtLeastOne } from '../../types/util';
import { syncAccounts } from '../accounts/accountsSlice';
import { closeBudget, closeBudgetUI } from '../budgets/budgetsSlice';
import { pushModal } from '../modals/modalsSlice';
import { loadPrefs } from '../prefs/prefsSlice';
import { createAppAsyncThunk } from '../redux';
@@ -146,6 +147,18 @@ const appSlice = createSlice({
};
},
},
extraReducers: builder => {
builder.addMatcher(
action =>
closeBudget.fulfilled.match(action) ||
closeBudgetUI.fulfilled.match(action),
state => ({
...getInitialState(),
managerHasInitialized: state.managerHasInitialized || false,
loadingText: state.loadingText || null,
}),
);
},
});
export const { name, reducer, getInitialState } = appSlice;

View File

@@ -12,7 +12,6 @@ import { closeModal, pushModal } from '../modals/modalsSlice';
import { loadGlobalPrefs, loadPrefs } from '../prefs/prefsSlice';
import { createAppAsyncThunk } from '../redux';
import { signOut } from '../users/usersSlice';
import { CLOSE_BUDGET } from '../store';
const sliceName = 'budgets';
@@ -101,28 +100,24 @@ export const closeBudget = createAppAsyncThunk(
`${sliceName}/closeBudget`,
async (_, { dispatch, getState }) => {
const prefs = getState().prefs.local;
if (prefs && prefs.id) {
// This clears out all the app state so the user starts fresh
// TODO: Change to use an action once CLOSE_BUDGET is migrated to redux toolkit.
await dispatch({ type: CLOSE_BUDGET });
await dispatch(setAppState({ loadingText: t('Closing...') }));
await send('close-budget');
await dispatch(setAppState({ loadingText: null }));
if (localStorage.getItem('SharedArrayBufferOverride')) {
window.location.reload();
}
if (!prefs || !prefs.id) {
throw new Error('No open budget.');
}
await dispatch(setAppState({ loadingText: t('Closing...') }));
await send('close-budget');
await dispatch(setAppState({ loadingText: null }));
if (localStorage.getItem('SharedArrayBufferOverride')) {
window.location.reload();
}
},
);
export const closeBudgetUI = createAppAsyncThunk(
`${sliceName}/closeBudgetUI`,
async (_, { dispatch, getState }) => {
async (_, { getState }) => {
const prefs = getState().prefs.local;
if (prefs && prefs.id) {
// TODO: Change to use an action once CLOSE_BUDGET is migrated to redux toolkit.
await dispatch({ type: CLOSE_BUDGET });
if (!prefs || !prefs.id) {
throw new Error('No open budget.');
}
},
);
@@ -444,9 +439,16 @@ const budgetsSlice = createSlice({
},
},
extraReducers: builder => {
builder.addCase(signOut.fulfilled, state => {
state.allFiles = null;
});
builder
.addCase(signOut.fulfilled, state => {
state.allFiles = null;
})
.addMatcher(
action =>
closeBudget.fulfilled.match(action) ||
closeBudgetUI.fulfilled.match(action),
state => state || getInitialState(),
);
},
});

View File

@@ -18,6 +18,7 @@ import {
type NoteEntity,
} from '../../types/models';
import { setAppState } from '../app/appSlice';
import { closeBudget, closeBudgetUI } from '../budgets/budgetsSlice';
import { createAppAsyncThunk } from '../redux';
import { signOut } from '../users/usersSlice';
@@ -607,7 +608,13 @@ const modalsSlice = createSlice({
.addCase(setAppState, (state, action) => {
state.isHidden = action.payload.loadingText !== null;
})
.addCase(signOut.fulfilled, () => initialState);
.addCase(signOut.fulfilled, () => getInitialState())
.addMatcher(
action =>
closeBudget.fulfilled.match(action) ||
closeBudgetUI.fulfilled.match(action),
() => getInitialState(),
);
},
});

View File

@@ -2,6 +2,8 @@ import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
import { t } from 'i18next';
import { v4 as uuidv4 } from 'uuid';
import { closeBudget, closeBudgetUI } from '../budgets/budgetsSlice';
const sliceName = 'notifications';
export type Notification = {
@@ -89,6 +91,14 @@ const notificationsSlice = createSlice({
state.inset = action.payload?.inset ? action.payload.inset : {};
},
},
extraReducers: builder => {
builder.addMatcher(
action =>
closeBudget.fulfilled.match(action) ||
closeBudgetUI.fulfilled.match(action),
() => getInitialState(),
);
},
});
export const { name, reducer, getInitialState } = notificationsSlice;

View File

@@ -7,6 +7,7 @@ import {
type MetadataPrefs,
type SyncedPrefs,
} from '../../types/prefs';
import { closeBudget, closeBudgetUI } from '../budgets/budgetsSlice';
import { closeModal } from '../modals/modalsSlice';
import { createAppAsyncThunk } from '../redux';
@@ -148,6 +149,17 @@ const prefsSlice = createSlice({
state.synced = { ...state.synced, ...action.payload };
},
},
extraReducers: builder => {
builder.addMatcher(
action =>
closeBudget.fulfilled.match(action) ||
closeBudgetUI.fulfilled.match(action),
state => ({
...getInitialState(),
global: state.global || getInitialState().global,
}),
);
},
});
export const { name, reducer, getInitialState } = prefsSlice;

View File

@@ -12,6 +12,7 @@ import {
type AccountEntity,
type PayeeEntity,
} from '../../types/models';
import { closeBudget, closeBudgetUI } from '../budgets/budgetsSlice';
import {
addGenericErrorNotification,
addNotification,
@@ -813,6 +814,13 @@ const queriesSlice = createSlice({
state.payees = action.payload;
state.payeesLoaded = true;
});
builder.addMatcher(
action =>
closeBudget.fulfilled.match(action) ||
closeBudgetUI.fulfilled.match(action),
() => getInitialState(),
);
},
});

View File

@@ -3,45 +3,37 @@ import { combineReducers, configureStore } from '@reduxjs/toolkit';
import {
name as accountsSliceName,
reducer as accountsSliceReducer,
getInitialState as getInitialAccountsState,
} from '../accounts/accountsSlice';
import {
name as appSliceName,
reducer as appSliceReducer,
getInitialState as getInitialAppState,
} from '../app/appSlice';
import {
name as budgetsSliceName,
reducer as budgetsSliceReducer,
getInitialState as getInitialBudgetsState,
} from '../budgets/budgetsSlice';
import {
name as modalsSliceName,
reducer as modalsSliceReducer,
getInitialState as getInitialModalsState,
} from '../modals/modalsSlice';
import {
name as notificationsSliceName,
reducer as notificationsSliceReducer,
getInitialState as getInitialNotificationsState,
} from '../notifications/notificationsSlice';
import {
name as prefsSliceName,
reducer as prefsSliceReducer,
getInitialState as getInitialPrefsState,
} from '../prefs/prefsSlice';
import {
name as queriesSliceName,
reducer as queriesSliceReducer,
getInitialState as getInitialQueriesState,
} from '../queries/queriesSlice';
import {
name as usersSliceName,
reducer as usersSliceReducer,
getInitialState as getInitialUsersState,
} from '../users/usersSlice';
const appReducer = combineReducers({
const rootReducer = combineReducers({
[accountsSliceName]: accountsSliceReducer,
[appSliceName]: appSliceReducer,
[budgetsSliceName]: budgetsSliceReducer,
@@ -52,34 +44,6 @@ const appReducer = combineReducers({
[usersSliceName]: usersSliceReducer,
});
export const CLOSE_BUDGET = 'CLOSE_BUDGET';
const rootReducer: typeof appReducer = (state, action) => {
if (action.type === CLOSE_BUDGET) {
// Reset the state and only keep around things intentionally. This
// blows away everything else
state = {
account: getInitialAccountsState(),
modals: getInitialModalsState(),
notifications: getInitialNotificationsState(),
queries: getInitialQueriesState(),
budgets: state?.budgets || getInitialBudgetsState(),
user: state?.user || getInitialUsersState(),
prefs: {
...getInitialPrefsState(),
global: state?.prefs?.global || getInitialPrefsState().global,
},
app: {
...getInitialAppState(),
managerHasInitialized: state?.app?.managerHasInitialized || false,
loadingText: state?.app?.loadingText || null,
},
};
}
return appReducer(state, action);
};
export const store = configureStore({
reducer: rootReducer,
middleware: getDefaultMiddleware =>

View File

@@ -2,7 +2,11 @@ import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
import { send } from '../../platform/client/fetch';
import { type Handlers } from '../../types/handlers';
import { closeBudget, loadAllFiles } from '../budgets/budgetsSlice';
import {
closeBudget,
closeBudgetUI,
loadAllFiles,
} from '../budgets/budgetsSlice';
import { loadGlobalPrefs } from '../prefs/prefsSlice';
import { createAppAsyncThunk } from '../redux';
@@ -73,6 +77,14 @@ const usersSlice = createSlice({
state.data = action.payload.data;
},
},
extraReducers: builder => {
builder.addMatcher(
action =>
closeBudget.fulfilled.match(action) ||
closeBudgetUI.fulfilled.match(action),
() => getInitialState(),
);
},
});
export const { name, reducer, getInitialState } = usersSlice;