@zeniai/client-epic-state 5.1.73-betaRD2 → 5.1.73-betaRD3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8,6 +8,7 @@ import { fetchJeSchedulesPage } from '../../reducers/jeSchedulesViewReducer';
8
8
  import { fetchMissingReceipts } from '../../reducers/missingReceiptsViewReducer';
9
9
  import { fetchReconciliation } from '../../reducers/reconciliationViewReducer';
10
10
  import { fetchTransactionCategorizationView } from '../../reducers/transactionsViewReducer';
11
+ import { getJESchedulePeriodTabKey } from '../../types/jeSchedulesViewState';
11
12
  export const fetchAllExpenseAutomationTabsEpic = (actions$, state$) => actions$.pipe(filter(fetchAllExpenseAutomationTabs.match), switchMap((action) => {
12
13
  const { cacheOverride, refreshViewInBackground } = action.payload;
13
14
  const state = state$.value;
@@ -59,14 +60,16 @@ export const fetchAllExpenseAutomationTabsEpic = (actions$, state$) => actions$.
59
60
  state.expenseAutomationFluxAnalysisViewState.groupsBySelectedPeriod[monthYearPeriodId] == null)) {
60
61
  fetchActions.push(fetchFluxAnalysisView(selectedPeriod, cacheOverride, refreshViewInBackground, null));
61
62
  }
63
+ // The two JE tabs cache separately, so only the tab actually being shown decides whether a
64
+ // fetch is still needed.
65
+ const jeSchedulesPeriodTabKey = getJESchedulePeriodTabKey(state.expenseAutomationJESchedulesViewState.uiState.selectedPageTab, monthYearPeriodId);
62
66
  if (state.expenseAutomationJESchedulesViewState.fetchState !==
63
67
  'In-Progress' &&
64
68
  (!state.expenseAutomationJESchedulesViewState.hasValidState() ||
65
69
  state.expenseAutomationJESchedulesViewState
66
- .jeScheduleTransactionKeysByPeriod[monthYearPeriodId] == null ||
70
+ .jeScheduleTransactionKeysByPeriodAndTab[jeSchedulesPeriodTabKey] == null ||
67
71
  state.expenseAutomationJESchedulesViewState
68
- .failedJeScheduleTransactionKeysByPeriod[monthYearPeriodId] ==
69
- null)) {
72
+ .failedJeScheduleTransactionKeysByPeriodAndTab[jeSchedulesPeriodTabKey] == null)) {
70
73
  fetchActions.push(fetchJeSchedulesPage({ start: timePeriodStart, end: timePeriodEnd }, cacheOverride));
71
74
  }
72
75
  if (state.expenseAutomationReconciliationViewState.fetchState !==
@@ -13,8 +13,8 @@ export const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe
13
13
  const { period, refreshViewInBackground } = action.payload;
14
14
  const currentTenant = getCurrentTenant(state);
15
15
  const selectedPeriod = selectedPeriodByTenantId[currentTenant.tenantId];
16
- const isClosePeriodTab = state.expenseAutomationJESchedulesViewState.uiState.selectedPageTab ===
17
- 'schedules';
16
+ const { selectedPageTab } = state.expenseAutomationJESchedulesViewState.uiState;
17
+ const isClosePeriodTab = selectedPageTab === 'schedules';
18
18
  const existingEndDate = toAbsoluteDay(date(toString(period.start))
19
19
  .subtract(1, 'month')
20
20
  .endOf('month')
@@ -52,6 +52,7 @@ export const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe
52
52
  ],
53
53
  accruedJeSchedules: accruedJeSchedules,
54
54
  selectedPeriod: selectedPeriod,
55
+ selectedPageTab: selectedPageTab,
55
56
  refreshViewInBackground: refreshViewInBackground,
56
57
  }));
57
58
  return from(updateActions);
@@ -60,11 +61,13 @@ export const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe
60
61
  return of(fetchJeSchedulesFailure({
61
62
  status: response.status,
62
63
  selectedPeriod,
64
+ selectedPageTab,
63
65
  }));
64
66
  }
65
67
  }), catchError((error) => of(fetchJeSchedulesFailure({
66
68
  status: createZeniAPIStatus('Unexpected Error', 'fetch JE schedules REST API call errored out' +
67
69
  JSON.stringify(error)),
68
70
  selectedPeriod,
71
+ selectedPageTab,
69
72
  }))));
70
73
  }));
@@ -4,7 +4,12 @@ import { toMonthYearPeriodId, } from '../../../commonStateTypes/timePeriod';
4
4
  import { mapAccountBasePayloadToAccountBase, mapAccountMetadataPayloadToAccountMetadata, } from '../../../entity/account/accountPayload';
5
5
  import { getJEScheduleKey, getJEScheduleTransactionDetailKeyPayload, } from '../../../entity/jeSchedules/jeSchedulesPayload';
6
6
  import { mapAccountTypeRecommendationPayloadToAccountRecommendationByType, } from '../../accountMappingView/accountTypeRecommendation/accountTypeRecommendationPayload';
7
- import { MIN_NEW_SCHEDULE_SEARCH_LENGTH, } from '../types/jeSchedulesViewState';
7
+ import { MIN_NEW_SCHEDULE_SEARCH_LENGTH, getJESchedulePeriodTabKey, } from '../types/jeSchedulesViewState';
8
+ function removeKeyFromEveryTabSlot(keysByPeriodAndTab, keyToRemove) {
9
+ for (const periodTabKey of Object.keys(keysByPeriodAndTab)) {
10
+ keysByPeriodAndTab[periodTabKey] = keysByPeriodAndTab[periodTabKey].filter((jeScheduleKey) => jeScheduleKey !== keyToRemove);
11
+ }
12
+ }
8
13
  export const accountSettingsInitialState = {
9
14
  localData: {
10
15
  selectedPrepaidExpensesAccountIds: [],
@@ -50,9 +55,9 @@ export const searchTransactionsInitialState = {
50
55
  error: undefined,
51
56
  };
52
57
  export const initialState = {
53
- jeScheduleTransactionKeysByPeriod: {},
54
- jeScheduleAccruedKeysByPeriod: {},
55
- failedJeScheduleTransactionKeysByPeriod: {},
58
+ jeScheduleTransactionKeysByPeriodAndTab: {},
59
+ jeScheduleAccruedKeysByPeriodAndTab: {},
60
+ failedJeScheduleTransactionKeysByPeriodAndTab: {},
56
61
  postStatusById: {},
57
62
  ignoreStatusById: {},
58
63
  jeScheduleLocalDataById: {},
@@ -124,7 +129,8 @@ const expenseAutomationJESchedulesView = createSlice({
124
129
  },
125
130
  },
126
131
  fetchJeSchedulesSuccess(draft, action) {
127
- const { jeSchedules, selectedPeriod, failedJeSchedules, accruedJeSchedules, refreshViewInBackground, } = action.payload;
132
+ const { jeSchedules, selectedPeriod, selectedPageTab, failedJeSchedules, accruedJeSchedules, refreshViewInBackground, } = action.payload;
133
+ const periodTabKey = getJESchedulePeriodTabKey(selectedPageTab, toMonthYearPeriodId(selectedPeriod));
128
134
  const jeScheduleTransactionKeys = jeSchedules.map((schedules) => getJEScheduleTransactionDetailKeyPayload(schedules.base_transaction));
129
135
  const failedJeScheduleTransactionKeys = failedJeSchedules.map((schedules) => getJEScheduleTransactionDetailKeyPayload(schedules.base_transaction));
130
136
  const jeScheduleAccruedKeys = accruedJeSchedules.map((schedule) => getJEScheduleKey(schedule));
@@ -136,21 +142,24 @@ const expenseAutomationJESchedulesView = createSlice({
136
142
  draft.fetchState = 'Completed';
137
143
  draft.error = undefined;
138
144
  }
139
- draft.jeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] = jeScheduleTransactionKeys;
140
- draft.jeScheduleAccruedKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] =
145
+ draft.jeScheduleTransactionKeysByPeriodAndTab[periodTabKey] =
146
+ jeScheduleTransactionKeys;
147
+ draft.jeScheduleAccruedKeysByPeriodAndTab[periodTabKey] =
141
148
  jeScheduleAccruedKeys;
142
- draft.failedJeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] = failedJeScheduleTransactionKeys;
149
+ draft.failedJeScheduleTransactionKeysByPeriodAndTab[periodTabKey] =
150
+ failedJeScheduleTransactionKeys;
143
151
  },
144
152
  fetchJeSchedulesFailure(draft, action) {
145
- const { status, selectedPeriod } = action.payload;
153
+ const { status, selectedPeriod, selectedPageTab } = action.payload;
154
+ const periodTabKey = getJESchedulePeriodTabKey(selectedPageTab, toMonthYearPeriodId(selectedPeriod));
146
155
  if (draft.refreshStatus.fetchState === 'In-Progress') {
147
156
  draft.refreshStatus = { fetchState: 'Error', error: status };
148
157
  }
149
158
  else {
150
159
  draft.fetchState = 'Error';
151
160
  draft.error = status;
152
- draft.jeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] = [];
153
- draft.jeScheduleAccruedKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] = [];
161
+ draft.jeScheduleTransactionKeysByPeriodAndTab[periodTabKey] = [];
162
+ draft.jeScheduleAccruedKeysByPeriodAndTab[periodTabKey] = [];
154
163
  }
155
164
  },
156
165
  retryJeSchedule(draft, action) {
@@ -239,17 +248,18 @@ const expenseAutomationJESchedulesView = createSlice({
239
248
  };
240
249
  },
241
250
  updateJeScheduleTransactionKeys: {
242
- prepare(jeScheduleKeys, selectedPeriod) {
251
+ prepare(jeScheduleKeys, selectedPeriod, selectedPageTab) {
243
252
  return {
244
253
  payload: {
245
254
  jeScheduleKeys: jeScheduleKeys,
246
255
  selectedPeriod: selectedPeriod,
256
+ selectedPageTab: selectedPageTab,
247
257
  },
248
258
  };
249
259
  },
250
260
  reducer(draft, action) {
251
- const { selectedPeriod, jeScheduleKeys } = action.payload;
252
- draft.jeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] = jeScheduleKeys;
261
+ const { selectedPeriod, selectedPageTab, jeScheduleKeys } = action.payload;
262
+ draft.jeScheduleTransactionKeysByPeriodAndTab[getJESchedulePeriodTabKey(selectedPageTab, toMonthYearPeriodId(selectedPeriod))] = jeScheduleKeys;
253
263
  },
254
264
  },
255
265
  removeJeScheduleTransactionKey: {
@@ -262,12 +272,10 @@ const expenseAutomationJESchedulesView = createSlice({
262
272
  };
263
273
  },
264
274
  reducer(draft, action) {
265
- const { selectedPeriod, jeScheduleKey } = action.payload;
266
- const prevData = [
267
- ...(draft.jeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] ?? []),
268
- ];
269
- const filteredKeys = prevData.filter((jeKey) => jeKey !== jeScheduleKey);
270
- draft.jeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] = filteredKeys;
275
+ const { jeScheduleKey } = action.payload;
276
+ // Dropped from every tab's slot, not just the visible one: once a schedule is ignored or
277
+ // resolved it must not reappear when the user switches tabs and hits a cached list.
278
+ removeKeyFromEveryTabSlot(draft.jeScheduleTransactionKeysByPeriodAndTab, jeScheduleKey);
271
279
  },
272
280
  },
273
281
  removeFailedJeScheduleTransactionKey: {
@@ -280,12 +288,8 @@ const expenseAutomationJESchedulesView = createSlice({
280
288
  };
281
289
  },
282
290
  reducer(draft, action) {
283
- const { selectedPeriod, failedJeScheduleKey } = action.payload;
284
- const prevData = [
285
- ...(draft.failedJeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] ?? []),
286
- ];
287
- const filteredKeys = prevData.filter((jeKey) => jeKey !== failedJeScheduleKey);
288
- draft.failedJeScheduleTransactionKeysByPeriod[toMonthYearPeriodId(selectedPeriod)] = filteredKeys;
291
+ const { failedJeScheduleKey } = action.payload;
292
+ removeKeyFromEveryTabSlot(draft.failedJeScheduleTransactionKeysByPeriodAndTab, failedJeScheduleKey);
289
293
  },
290
294
  },
291
295
  initializeJeScheduleLocalData: {
@@ -12,6 +12,7 @@ import { getAccountsTypesForScheduleDetails } from '../../scheduleView/scheduleD
12
12
  import { filterNestedAccountHierarchyById } from '../../scheduleView/scheduleDetailView/scheduleDetailSelector';
13
13
  import { getAccountLabelForScheduleType, getAccountsTypesForScheduleList, } from '../../scheduleView/scheduleListView/scheduleListHelper';
14
14
  import { getAllSteps } from '../selectorTypes/expenseAutomationViewSelectorTypes';
15
+ import { ALL_JE_PAGE_TABS, getJESchedulePeriodTabKey, } from '../types/jeSchedulesViewState';
15
16
  import { getJEAccountSettingsView } from './jeAccountSettingsViewSelector';
16
17
  import { getNewScheduleView } from './jeNewScheduleViewSelector';
17
18
  // Matches the AI-automation user addresses webc's schedule list row already
@@ -104,7 +105,7 @@ export function getExpenseAutomationJESchedulesView(state) {
104
105
  const failedJeScheduledTransaction = [];
105
106
  const accruedSchedules = [];
106
107
  const { accountState, accountListState, classState, classListState, expenseAutomationJESchedulesViewState, expenseAutomationViewState, monthEndCloseChecksState, monthEndCloseChecksViewState, } = state;
107
- const { jeScheduleTransactionKeysByPeriod, jeScheduleAccruedKeysByPeriod, failedJeScheduleTransactionKeysByPeriod, jeScheduleLocalDataById, postStatusById, ignoreStatusById, uiState, error, fetchState, refreshStatus, newSchedule, } = expenseAutomationJESchedulesViewState;
108
+ const { jeScheduleTransactionKeysByPeriodAndTab, jeScheduleAccruedKeysByPeriodAndTab, failedJeScheduleTransactionKeysByPeriodAndTab, jeScheduleLocalDataById, postStatusById, ignoreStatusById, uiState, error, fetchState, refreshStatus, newSchedule, } = expenseAutomationJESchedulesViewState;
108
109
  const accountSettingsView = getJEAccountSettingsView(state);
109
110
  const newScheduleView = newSchedule.selectedDetailScheduleType === 'fixed_assets' ||
110
111
  newSchedule.selectedDetailScheduleType === 'prepaid_expenses'
@@ -137,17 +138,24 @@ export function getExpenseAutomationJESchedulesView(state) {
137
138
  const filteredDepAccountListNestedAccountHierarchy = filterNestedAccountHierarchyById(depAccountListNestedAccountHierarchy, filteredDepAccounts.map((account) => account.accountId));
138
139
  const classListNestedAccountHierarchy = getNestedClassListHierarchy(classListState);
139
140
  const monthYearPeriodId = selectedPeriod != null ? toMonthYearPeriodId(selectedPeriod) : null;
140
- const jeScheduleTransactionKeysForSelectedPeriod = monthYearPeriodId != null
141
- ? jeScheduleTransactionKeysByPeriod[monthYearPeriodId]
141
+ const selectedPeriodTabKey = monthYearPeriodId != null
142
+ ? getJESchedulePeriodTabKey(uiState.selectedPageTab, monthYearPeriodId)
142
143
  : null;
143
- const failedJeScheduleTransactionKeysForSelectedPeriod = monthYearPeriodId != null
144
- ? failedJeScheduleTransactionKeysByPeriod[monthYearPeriodId]
145
- : null;
146
- const jeScheduleTransactionKeys = jeScheduleTransactionKeysForSelectedPeriod ?? [];
147
- const failedJeScheduleTransactionKeys = failedJeScheduleTransactionKeysForSelectedPeriod ?? [];
148
- const jeScheduleAccruedKeys = (monthYearPeriodId != null
149
- ? jeScheduleAccruedKeysByPeriod[monthYearPeriodId]
150
- : null) ?? [];
144
+ const jeScheduleTransactionKeysForSelectedTab = selectedPeriodTabKey != null
145
+ ? jeScheduleTransactionKeysByPeriodAndTab[selectedPeriodTabKey]
146
+ : undefined;
147
+ const failedJeScheduleTransactionKeysForSelectedTab = selectedPeriodTabKey != null
148
+ ? failedJeScheduleTransactionKeysByPeriodAndTab[selectedPeriodTabKey]
149
+ : undefined;
150
+ // Distinguishes "this tab has never been fetched for this period" from "fetched and genuinely
151
+ // empty". Without it the page cannot tell a first visit from a real empty state, and renders an
152
+ // empty table where it should render a skeleton.
153
+ const hasLoadedForSelectedTab = jeScheduleTransactionKeysForSelectedTab != null;
154
+ const jeScheduleTransactionKeys = jeScheduleTransactionKeysForSelectedTab ?? [];
155
+ const failedJeScheduleTransactionKeys = failedJeScheduleTransactionKeysForSelectedTab ?? [];
156
+ const jeScheduleAccruedKeys = (selectedPeriodTabKey != null
157
+ ? jeScheduleAccruedKeysByPeriodAndTab[selectedPeriodTabKey]
158
+ : undefined) ?? [];
151
159
  jeScheduleTransactionKeys.forEach((jeScheduleKey) => {
152
160
  const jeScheduleDetails = getJEScheduledTransactionByJEScheduleTransactionKey(jeScheduleKey, state);
153
161
  jeScheduledTransaction.push(jeScheduleDetails);
@@ -214,6 +222,33 @@ export function getExpenseAutomationJESchedulesView(state) {
214
222
  amount: sumAmount(allSchedules),
215
223
  },
216
224
  };
225
+ // Each tab's badge counts from that tab's own bucket. A tab that has not been fetched yet
226
+ // reports undefined rather than 0, so the UI can hide the badge instead of asserting "none".
227
+ const scheduleCountsByTab = {};
228
+ ALL_JE_PAGE_TABS.forEach((pageTab) => {
229
+ const periodTabKey = monthYearPeriodId != null
230
+ ? getJESchedulePeriodTabKey(pageTab, monthYearPeriodId)
231
+ : null;
232
+ const transactionKeys = periodTabKey != null
233
+ ? jeScheduleTransactionKeysByPeriodAndTab[periodTabKey]
234
+ : undefined;
235
+ if (transactionKeys == null) {
236
+ return;
237
+ }
238
+ const accruedKeys = (periodTabKey != null
239
+ ? jeScheduleAccruedKeysByPeriodAndTab[periodTabKey]
240
+ : undefined) ?? [];
241
+ const rowsForTab = [
242
+ ...transactionKeys.map((transactionKey) => getJEScheduledTransactionByJEScheduleTransactionKey(transactionKey, state)),
243
+ ...accruedKeys
244
+ .map((accruedKey) => getJEAccruedScheduleByJEScheduleKey(accruedKey, state))
245
+ .filter((accruedRow) => accruedRow != null),
246
+ ];
247
+ scheduleCountsByTab[pageTab] =
248
+ pageTab === 'existing_schedules'
249
+ ? rowsForTab.filter((row) => row.status.code === 'ongoing').length
250
+ : rowsForTab.filter((row) => row.status.code === 'draft' || isCreatedStatus(row)).length;
251
+ });
217
252
  const allSteps = monthYearPeriodId != null
218
253
  ? getAllSteps(monthEndCloseChecksState, monthYearPeriodId, currentTenant.tenantId)
219
254
  : [];
@@ -252,7 +287,9 @@ export function getExpenseAutomationJESchedulesView(state) {
252
287
  allClassList: allClasses,
253
288
  createdSchedules,
254
289
  createdTotal,
290
+ hasLoadedForSelectedTab,
255
291
  jeScheduleTypeCounts,
292
+ scheduleCountsByTab,
256
293
  kpiSummary,
257
294
  pendingReviewSchedules,
258
295
  pendingReviewTotal,
@@ -18,4 +18,6 @@ const JE_SCHEDULE_SORT_KEYS = [
18
18
  export const toJEScheduleSortKey = (v) => stringToUnion(v, JE_SCHEDULE_SORT_KEYS);
19
19
  const JE_PAGE_TABS = ['schedules', 'existing_schedules'];
20
20
  export const toJEPageTab = (v) => stringToUnion(v, JE_PAGE_TABS);
21
+ export const ALL_JE_PAGE_TABS = JE_PAGE_TABS;
22
+ export const getJESchedulePeriodTabKey = (selectedPageTab, monthYearPeriodId) => `${selectedPageTab}_${monthYearPeriodId}`;
21
23
  export const MIN_NEW_SCHEDULE_SEARCH_LENGTH = 2;
@@ -11,6 +11,7 @@ const jeSchedulesViewReducer_1 = require("../../reducers/jeSchedulesViewReducer"
11
11
  const missingReceiptsViewReducer_1 = require("../../reducers/missingReceiptsViewReducer");
12
12
  const reconciliationViewReducer_1 = require("../../reducers/reconciliationViewReducer");
13
13
  const transactionsViewReducer_1 = require("../../reducers/transactionsViewReducer");
14
+ const jeSchedulesViewState_1 = require("../../types/jeSchedulesViewState");
14
15
  const fetchAllExpenseAutomationTabsEpic = (actions$, state$) => actions$.pipe((0, operators_1.filter)(expenseAutomationViewReducer_1.fetchAllExpenseAutomationTabs.match), (0, operators_1.switchMap)((action) => {
15
16
  const { cacheOverride, refreshViewInBackground } = action.payload;
16
17
  const state = state$.value;
@@ -62,14 +63,16 @@ const fetchAllExpenseAutomationTabsEpic = (actions$, state$) => actions$.pipe((0
62
63
  state.expenseAutomationFluxAnalysisViewState.groupsBySelectedPeriod[monthYearPeriodId] == null)) {
63
64
  fetchActions.push((0, fluxAnalysisViewReducer_1.fetchFluxAnalysisView)(selectedPeriod, cacheOverride, refreshViewInBackground, null));
64
65
  }
66
+ // The two JE tabs cache separately, so only the tab actually being shown decides whether a
67
+ // fetch is still needed.
68
+ const jeSchedulesPeriodTabKey = (0, jeSchedulesViewState_1.getJESchedulePeriodTabKey)(state.expenseAutomationJESchedulesViewState.uiState.selectedPageTab, monthYearPeriodId);
65
69
  if (state.expenseAutomationJESchedulesViewState.fetchState !==
66
70
  'In-Progress' &&
67
71
  (!state.expenseAutomationJESchedulesViewState.hasValidState() ||
68
72
  state.expenseAutomationJESchedulesViewState
69
- .jeScheduleTransactionKeysByPeriod[monthYearPeriodId] == null ||
73
+ .jeScheduleTransactionKeysByPeriodAndTab[jeSchedulesPeriodTabKey] == null ||
70
74
  state.expenseAutomationJESchedulesViewState
71
- .failedJeScheduleTransactionKeysByPeriod[monthYearPeriodId] ==
72
- null)) {
75
+ .failedJeScheduleTransactionKeysByPeriodAndTab[jeSchedulesPeriodTabKey] == null)) {
73
76
  fetchActions.push((0, jeSchedulesViewReducer_1.fetchJeSchedulesPage)({ start: timePeriodStart, end: timePeriodEnd }, cacheOverride));
74
77
  }
75
78
  if (state.expenseAutomationReconciliationViewState.fetchState !==
@@ -16,8 +16,8 @@ const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, op
16
16
  const { period, refreshViewInBackground } = action.payload;
17
17
  const currentTenant = (0, tenantSelector_1.getCurrentTenant)(state);
18
18
  const selectedPeriod = selectedPeriodByTenantId[currentTenant.tenantId];
19
- const isClosePeriodTab = state.expenseAutomationJESchedulesViewState.uiState.selectedPageTab ===
20
- 'schedules';
19
+ const { selectedPageTab } = state.expenseAutomationJESchedulesViewState.uiState;
20
+ const isClosePeriodTab = selectedPageTab === 'schedules';
21
21
  const existingEndDate = (0, timePeriod_1.toAbsoluteDay)((0, zeniDayJS_1.date)((0, timePeriod_1.toString)(period.start))
22
22
  .subtract(1, 'month')
23
23
  .endOf('month')
@@ -55,6 +55,7 @@ const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, op
55
55
  ],
56
56
  accruedJeSchedules: accruedJeSchedules,
57
57
  selectedPeriod: selectedPeriod,
58
+ selectedPageTab: selectedPageTab,
58
59
  refreshViewInBackground: refreshViewInBackground,
59
60
  }));
60
61
  return (0, rxjs_1.from)(updateActions);
@@ -63,12 +64,14 @@ const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, op
63
64
  return (0, rxjs_1.of)((0, jeSchedulesViewReducer_1.fetchJeSchedulesFailure)({
64
65
  status: response.status,
65
66
  selectedPeriod,
67
+ selectedPageTab,
66
68
  }));
67
69
  }
68
70
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, jeSchedulesViewReducer_1.fetchJeSchedulesFailure)({
69
71
  status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'fetch JE schedules REST API call errored out' +
70
72
  JSON.stringify(error)),
71
73
  selectedPeriod,
74
+ selectedPageTab,
72
75
  }))));
73
76
  }));
74
77
  exports.fetchJeSchedulesEpic = fetchJeSchedulesEpic;
@@ -5,7 +5,7 @@ import { JEAccruedScheduledTransactionPayload, JEScheduledTransactionPayload } f
5
5
  import { JEScheduleTransactionKey, ScheduleTypes } from '../../../entity/jeSchedules/jeSchedulesTypes';
6
6
  import { ZeniAPIStatus } from '../../../responsePayload';
7
7
  import { AccountTypeRecommendationPayload } from '../../accountMappingView/accountTypeRecommendation/accountTypeRecommendationPayload';
8
- import { AccountSettingsLocalData, AccountSettingsState, JEScheduleLocalData, JESchedulesViewState, JESchedulesViewUIState, NewScheduleLocalData, NewScheduleLocalDataFixedAssets, SearchTransactionsState } from '../types/jeSchedulesViewState';
8
+ import { AccountSettingsLocalData, AccountSettingsState, JEPageTab, JEScheduleLocalData, JESchedulesViewState, JESchedulesViewUIState, NewScheduleLocalData, NewScheduleLocalDataFixedAssets, SearchTransactionsState } from '../types/jeSchedulesViewState';
9
9
  export declare const accountSettingsInitialState: AccountSettingsState;
10
10
  export declare const getBaseNewScheduleLocalData: (scheduleType: ScheduleTypes) => NewScheduleLocalData;
11
11
  export declare const newScheduleInitialState: JESchedulesViewState['newSchedule']['newScheduleState'];
@@ -15,6 +15,7 @@ export declare const clearExpenseAutomationJESchedulesView: import("@reduxjs/too
15
15
  period: TimePeriod;
16
16
  refreshViewInBackground: any;
17
17
  }, "expenseAutomationJESchedulesView/fetchJeSchedules", never, never>, fetchJeSchedulesFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
18
+ selectedPageTab: JEPageTab;
18
19
  selectedPeriod: MonthYearPeriod;
19
20
  status: ZeniAPIStatus;
20
21
  }, "expenseAutomationJESchedulesView/fetchJeSchedulesFailure">, fetchJeSchedulesPage: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[period: TimePeriod, refreshViewInBackground?: any], {
@@ -25,6 +26,7 @@ export declare const clearExpenseAutomationJESchedulesView: import("@reduxjs/too
25
26
  failedJeSchedules: JEScheduledTransactionPayload[];
26
27
  jeSchedules: JEScheduledTransactionPayload[];
27
28
  refreshViewInBackground: boolean;
29
+ selectedPageTab: JEPageTab;
28
30
  selectedPeriod: MonthYearPeriod;
29
31
  }, "expenseAutomationJESchedulesView/fetchJeSchedulesSuccess">, fetchRecommendationForAccountSettings: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationJESchedulesView/fetchRecommendationForAccountSettings">, ignoreRecommendedJeSchedule: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[jeScheduleTransactionKey: `${string}_bill_${string}` | `${string}_expense_${string}` | `${string}_check_${string}` | `${string}_refund_${string}` | `${string}_invoice_${string}` | `${string}_payment_${string}` | `${string}_credit_memo_${string}` | `${string}_sales_receipt_${string}` | `${string}_delayed_credit_${string}` | `${string}_delayed_charge_${string}` | `${string}_bill_payment_${string}` | `${string}_bill_payment_check_${string}` | `${string}_bill_payment_credit_card_${string}` | `${string}_vendor_credit_${string}` | `${string}_credit_card_credit_${string}` | `${string}_transfer_${string}` | `${string}_credit_card_payment_${string}` | `${string}_deposit_${string}` | `${string}_journal_entry_${string}`, scheduleType: "prepaid_expenses" | "fixed_assets" | "accrued_expenses" | "deferred_revenue"], {
30
32
  jeScheduleTransactionKey: `${string}_bill_${string}` | `${string}_expense_${string}` | `${string}_check_${string}` | `${string}_refund_${string}` | `${string}_invoice_${string}` | `${string}_payment_${string}` | `${string}_credit_memo_${string}` | `${string}_sales_receipt_${string}` | `${string}_delayed_credit_${string}` | `${string}_delayed_charge_${string}` | `${string}_bill_payment_${string}` | `${string}_bill_payment_check_${string}` | `${string}_bill_payment_credit_card_${string}` | `${string}_vendor_credit_${string}` | `${string}_credit_card_credit_${string}` | `${string}_transfer_${string}` | `${string}_credit_card_payment_${string}` | `${string}_deposit_${string}` | `${string}_journal_entry_${string}`;
@@ -87,9 +89,10 @@ export declare const clearExpenseAutomationJESchedulesView: import("@reduxjs/too
87
89
  }, "expenseAutomationJESchedulesView/updateAccountSettingsListForAccountTypesFailure">, updateJESchedulesUIState: import("@reduxjs/toolkit").ActionCreatorWithPayload<Partial<JESchedulesViewUIState>, "expenseAutomationJESchedulesView/updateJESchedulesUIState">, updateJEScheduleTypeFilter: import("@reduxjs/toolkit").ActionCreatorWithPayload<"prepaid_expenses" | "fixed_assets" | "accrued_expenses" | "deferred_revenue" | null, "expenseAutomationJESchedulesView/updateJEScheduleTypeFilter">, updateJeScheduleLocalDataById: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
88
90
  localData: Partial<JEScheduleLocalData>;
89
91
  scheduledJournalEntryID: ID;
90
- }, "expenseAutomationJESchedulesView/updateJeScheduleLocalDataById">, updateJeScheduleTransactionKeys: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[jeScheduleKeys: (`${string}_bill_${string}` | `${string}_expense_${string}` | `${string}_check_${string}` | `${string}_refund_${string}` | `${string}_invoice_${string}` | `${string}_payment_${string}` | `${string}_credit_memo_${string}` | `${string}_sales_receipt_${string}` | `${string}_delayed_credit_${string}` | `${string}_delayed_charge_${string}` | `${string}_bill_payment_${string}` | `${string}_bill_payment_check_${string}` | `${string}_bill_payment_credit_card_${string}` | `${string}_vendor_credit_${string}` | `${string}_credit_card_credit_${string}` | `${string}_transfer_${string}` | `${string}_credit_card_payment_${string}` | `${string}_deposit_${string}` | `${string}_journal_entry_${string}`)[], selectedPeriod: MonthYearPeriod], {
92
+ }, "expenseAutomationJESchedulesView/updateJeScheduleLocalDataById">, updateJeScheduleTransactionKeys: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[jeScheduleKeys: (`${string}_bill_${string}` | `${string}_expense_${string}` | `${string}_check_${string}` | `${string}_refund_${string}` | `${string}_invoice_${string}` | `${string}_payment_${string}` | `${string}_credit_memo_${string}` | `${string}_sales_receipt_${string}` | `${string}_delayed_credit_${string}` | `${string}_delayed_charge_${string}` | `${string}_bill_payment_${string}` | `${string}_bill_payment_check_${string}` | `${string}_bill_payment_credit_card_${string}` | `${string}_vendor_credit_${string}` | `${string}_credit_card_credit_${string}` | `${string}_transfer_${string}` | `${string}_credit_card_payment_${string}` | `${string}_deposit_${string}` | `${string}_journal_entry_${string}`)[], selectedPeriod: MonthYearPeriod, selectedPageTab: "schedules" | "existing_schedules"], {
91
93
  jeScheduleKeys: (`${string}_bill_${string}` | `${string}_expense_${string}` | `${string}_check_${string}` | `${string}_refund_${string}` | `${string}_invoice_${string}` | `${string}_payment_${string}` | `${string}_credit_memo_${string}` | `${string}_sales_receipt_${string}` | `${string}_delayed_credit_${string}` | `${string}_delayed_charge_${string}` | `${string}_bill_payment_${string}` | `${string}_bill_payment_check_${string}` | `${string}_bill_payment_credit_card_${string}` | `${string}_vendor_credit_${string}` | `${string}_credit_card_credit_${string}` | `${string}_transfer_${string}` | `${string}_credit_card_payment_${string}` | `${string}_deposit_${string}` | `${string}_journal_entry_${string}`)[];
92
94
  selectedPeriod: MonthYearPeriod;
95
+ selectedPageTab: "schedules" | "existing_schedules";
93
96
  }, "expenseAutomationJESchedulesView/updateJeScheduleTransactionKeys", never, never>, updateNewScheduleLocalData: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
94
97
  localData: Partial<NewScheduleLocalDataFixedAssets>;
95
98
  scheduleType: "fixed_assets" | "prepaid_expenses";
@@ -9,6 +9,11 @@ const accountPayload_1 = require("../../../entity/account/accountPayload");
9
9
  const jeSchedulesPayload_1 = require("../../../entity/jeSchedules/jeSchedulesPayload");
10
10
  const accountTypeRecommendationPayload_1 = require("../../accountMappingView/accountTypeRecommendation/accountTypeRecommendationPayload");
11
11
  const jeSchedulesViewState_1 = require("../types/jeSchedulesViewState");
12
+ function removeKeyFromEveryTabSlot(keysByPeriodAndTab, keyToRemove) {
13
+ for (const periodTabKey of Object.keys(keysByPeriodAndTab)) {
14
+ keysByPeriodAndTab[periodTabKey] = keysByPeriodAndTab[periodTabKey].filter((jeScheduleKey) => jeScheduleKey !== keyToRemove);
15
+ }
16
+ }
12
17
  exports.accountSettingsInitialState = {
13
18
  localData: {
14
19
  selectedPrepaidExpensesAccountIds: [],
@@ -55,9 +60,9 @@ exports.searchTransactionsInitialState = {
55
60
  error: undefined,
56
61
  };
57
62
  exports.initialState = {
58
- jeScheduleTransactionKeysByPeriod: {},
59
- jeScheduleAccruedKeysByPeriod: {},
60
- failedJeScheduleTransactionKeysByPeriod: {},
63
+ jeScheduleTransactionKeysByPeriodAndTab: {},
64
+ jeScheduleAccruedKeysByPeriodAndTab: {},
65
+ failedJeScheduleTransactionKeysByPeriodAndTab: {},
61
66
  postStatusById: {},
62
67
  ignoreStatusById: {},
63
68
  jeScheduleLocalDataById: {},
@@ -129,7 +134,8 @@ const expenseAutomationJESchedulesView = (0, toolkit_1.createSlice)({
129
134
  },
130
135
  },
131
136
  fetchJeSchedulesSuccess(draft, action) {
132
- const { jeSchedules, selectedPeriod, failedJeSchedules, accruedJeSchedules, refreshViewInBackground, } = action.payload;
137
+ const { jeSchedules, selectedPeriod, selectedPageTab, failedJeSchedules, accruedJeSchedules, refreshViewInBackground, } = action.payload;
138
+ const periodTabKey = (0, jeSchedulesViewState_1.getJESchedulePeriodTabKey)(selectedPageTab, (0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod));
133
139
  const jeScheduleTransactionKeys = jeSchedules.map((schedules) => (0, jeSchedulesPayload_1.getJEScheduleTransactionDetailKeyPayload)(schedules.base_transaction));
134
140
  const failedJeScheduleTransactionKeys = failedJeSchedules.map((schedules) => (0, jeSchedulesPayload_1.getJEScheduleTransactionDetailKeyPayload)(schedules.base_transaction));
135
141
  const jeScheduleAccruedKeys = accruedJeSchedules.map((schedule) => (0, jeSchedulesPayload_1.getJEScheduleKey)(schedule));
@@ -141,21 +147,24 @@ const expenseAutomationJESchedulesView = (0, toolkit_1.createSlice)({
141
147
  draft.fetchState = 'Completed';
142
148
  draft.error = undefined;
143
149
  }
144
- draft.jeScheduleTransactionKeysByPeriod[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)] = jeScheduleTransactionKeys;
145
- draft.jeScheduleAccruedKeysByPeriod[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)] =
150
+ draft.jeScheduleTransactionKeysByPeriodAndTab[periodTabKey] =
151
+ jeScheduleTransactionKeys;
152
+ draft.jeScheduleAccruedKeysByPeriodAndTab[periodTabKey] =
146
153
  jeScheduleAccruedKeys;
147
- draft.failedJeScheduleTransactionKeysByPeriod[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)] = failedJeScheduleTransactionKeys;
154
+ draft.failedJeScheduleTransactionKeysByPeriodAndTab[periodTabKey] =
155
+ failedJeScheduleTransactionKeys;
148
156
  },
149
157
  fetchJeSchedulesFailure(draft, action) {
150
- const { status, selectedPeriod } = action.payload;
158
+ const { status, selectedPeriod, selectedPageTab } = action.payload;
159
+ const periodTabKey = (0, jeSchedulesViewState_1.getJESchedulePeriodTabKey)(selectedPageTab, (0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod));
151
160
  if (draft.refreshStatus.fetchState === 'In-Progress') {
152
161
  draft.refreshStatus = { fetchState: 'Error', error: status };
153
162
  }
154
163
  else {
155
164
  draft.fetchState = 'Error';
156
165
  draft.error = status;
157
- draft.jeScheduleTransactionKeysByPeriod[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)] = [];
158
- draft.jeScheduleAccruedKeysByPeriod[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)] = [];
166
+ draft.jeScheduleTransactionKeysByPeriodAndTab[periodTabKey] = [];
167
+ draft.jeScheduleAccruedKeysByPeriodAndTab[periodTabKey] = [];
159
168
  }
160
169
  },
161
170
  retryJeSchedule(draft, action) {
@@ -244,17 +253,18 @@ const expenseAutomationJESchedulesView = (0, toolkit_1.createSlice)({
244
253
  };
245
254
  },
246
255
  updateJeScheduleTransactionKeys: {
247
- prepare(jeScheduleKeys, selectedPeriod) {
256
+ prepare(jeScheduleKeys, selectedPeriod, selectedPageTab) {
248
257
  return {
249
258
  payload: {
250
259
  jeScheduleKeys: jeScheduleKeys,
251
260
  selectedPeriod: selectedPeriod,
261
+ selectedPageTab: selectedPageTab,
252
262
  },
253
263
  };
254
264
  },
255
265
  reducer(draft, action) {
256
- const { selectedPeriod, jeScheduleKeys } = action.payload;
257
- draft.jeScheduleTransactionKeysByPeriod[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)] = jeScheduleKeys;
266
+ const { selectedPeriod, selectedPageTab, jeScheduleKeys } = action.payload;
267
+ draft.jeScheduleTransactionKeysByPeriodAndTab[(0, jeSchedulesViewState_1.getJESchedulePeriodTabKey)(selectedPageTab, (0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod))] = jeScheduleKeys;
258
268
  },
259
269
  },
260
270
  removeJeScheduleTransactionKey: {
@@ -267,12 +277,10 @@ const expenseAutomationJESchedulesView = (0, toolkit_1.createSlice)({
267
277
  };
268
278
  },
269
279
  reducer(draft, action) {
270
- const { selectedPeriod, jeScheduleKey } = action.payload;
271
- const prevData = [
272
- ...(draft.jeScheduleTransactionKeysByPeriod[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)] ?? []),
273
- ];
274
- const filteredKeys = prevData.filter((jeKey) => jeKey !== jeScheduleKey);
275
- draft.jeScheduleTransactionKeysByPeriod[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)] = filteredKeys;
280
+ const { jeScheduleKey } = action.payload;
281
+ // Dropped from every tab's slot, not just the visible one: once a schedule is ignored or
282
+ // resolved it must not reappear when the user switches tabs and hits a cached list.
283
+ removeKeyFromEveryTabSlot(draft.jeScheduleTransactionKeysByPeriodAndTab, jeScheduleKey);
276
284
  },
277
285
  },
278
286
  removeFailedJeScheduleTransactionKey: {
@@ -285,12 +293,8 @@ const expenseAutomationJESchedulesView = (0, toolkit_1.createSlice)({
285
293
  };
286
294
  },
287
295
  reducer(draft, action) {
288
- const { selectedPeriod, failedJeScheduleKey } = action.payload;
289
- const prevData = [
290
- ...(draft.failedJeScheduleTransactionKeysByPeriod[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)] ?? []),
291
- ];
292
- const filteredKeys = prevData.filter((jeKey) => jeKey !== failedJeScheduleKey);
293
- draft.failedJeScheduleTransactionKeysByPeriod[(0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod)] = filteredKeys;
296
+ const { failedJeScheduleKey } = action.payload;
297
+ removeKeyFromEveryTabSlot(draft.failedJeScheduleTransactionKeysByPeriodAndTab, failedJeScheduleKey);
294
298
  },
295
299
  },
296
300
  initializeJeScheduleLocalData: {
@@ -9,7 +9,7 @@ import { UncategorizedAccounts } from '../../accountList/accountListSelector';
9
9
  import { JEAccountSettingsView } from '../selectorTypes/jeAccountSettingsViewSelectorTypes';
10
10
  import { NewScheduleView } from '../selectorTypes/jeNewScheduleViewSelectorTypes';
11
11
  import { JEScheduleRow, JEScheduledTransactionWithFailedEntries } from '../selectors/jeSchedulesViewSelector';
12
- import { JEScheduleLocalData, JESchedulesViewUIState } from '../types/jeSchedulesViewState';
12
+ import { JEPageTab, JEScheduleLocalData, JESchedulesViewUIState } from '../types/jeSchedulesViewState';
13
13
  export interface JEKpiSummary {
14
14
  aiAccountant: {
15
15
  amount: number;
@@ -39,6 +39,7 @@ export interface ExpenseAutomationJESchedulesViewSelector extends SelectorView {
39
39
  completionStatus: CompletionStatusType;
40
40
  createdSchedules: JEScheduleRow[];
41
41
  createdTotal: number;
42
+ hasLoadedForSelectedTab: boolean;
42
43
  ignoreStatusById: Record<JEScheduleTransactionKey, FetchStateAndError>;
43
44
  jeScheduleLocalDataById: Record<ID, JEScheduleLocalData>;
44
45
  jeScheduleTypeCounts: {
@@ -52,6 +53,7 @@ export interface ExpenseAutomationJESchedulesViewSelector extends SelectorView {
52
53
  postStatusById: Record<ID, FetchStateAndError>;
53
54
  refreshStatus: FetchStateAndError;
54
55
  resolveSchedules: JEScheduledTransactionWithFailedEntries[];
56
+ scheduleCountsByTab: Partial<Record<JEPageTab, number>>;
55
57
  uiState: JESchedulesViewUIState;
56
58
  uncategorizedAccounts: UncategorizedAccounts;
57
59
  }
@@ -20,6 +20,7 @@ const scheduleDetailLocalDataHelper_1 = require("../../scheduleView/scheduleDeta
20
20
  const scheduleDetailSelector_1 = require("../../scheduleView/scheduleDetailView/scheduleDetailSelector");
21
21
  const scheduleListHelper_1 = require("../../scheduleView/scheduleListView/scheduleListHelper");
22
22
  const expenseAutomationViewSelectorTypes_1 = require("../selectorTypes/expenseAutomationViewSelectorTypes");
23
+ const jeSchedulesViewState_1 = require("../types/jeSchedulesViewState");
23
24
  const jeAccountSettingsViewSelector_1 = require("./jeAccountSettingsViewSelector");
24
25
  const jeNewScheduleViewSelector_1 = require("./jeNewScheduleViewSelector");
25
26
  // Matches the AI-automation user addresses webc's schedule list row already
@@ -113,7 +114,7 @@ function getExpenseAutomationJESchedulesView(state) {
113
114
  const failedJeScheduledTransaction = [];
114
115
  const accruedSchedules = [];
115
116
  const { accountState, accountListState, classState, classListState, expenseAutomationJESchedulesViewState, expenseAutomationViewState, monthEndCloseChecksState, monthEndCloseChecksViewState, } = state;
116
- const { jeScheduleTransactionKeysByPeriod, jeScheduleAccruedKeysByPeriod, failedJeScheduleTransactionKeysByPeriod, jeScheduleLocalDataById, postStatusById, ignoreStatusById, uiState, error, fetchState, refreshStatus, newSchedule, } = expenseAutomationJESchedulesViewState;
117
+ const { jeScheduleTransactionKeysByPeriodAndTab, jeScheduleAccruedKeysByPeriodAndTab, failedJeScheduleTransactionKeysByPeriodAndTab, jeScheduleLocalDataById, postStatusById, ignoreStatusById, uiState, error, fetchState, refreshStatus, newSchedule, } = expenseAutomationJESchedulesViewState;
117
118
  const accountSettingsView = (0, jeAccountSettingsViewSelector_1.getJEAccountSettingsView)(state);
118
119
  const newScheduleView = newSchedule.selectedDetailScheduleType === 'fixed_assets' ||
119
120
  newSchedule.selectedDetailScheduleType === 'prepaid_expenses'
@@ -146,17 +147,24 @@ function getExpenseAutomationJESchedulesView(state) {
146
147
  const filteredDepAccountListNestedAccountHierarchy = (0, scheduleDetailSelector_1.filterNestedAccountHierarchyById)(depAccountListNestedAccountHierarchy, filteredDepAccounts.map((account) => account.accountId));
147
148
  const classListNestedAccountHierarchy = (0, classListSelector_1.getNestedClassListHierarchy)(classListState);
148
149
  const monthYearPeriodId = selectedPeriod != null ? (0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod) : null;
149
- const jeScheduleTransactionKeysForSelectedPeriod = monthYearPeriodId != null
150
- ? jeScheduleTransactionKeysByPeriod[monthYearPeriodId]
150
+ const selectedPeriodTabKey = monthYearPeriodId != null
151
+ ? (0, jeSchedulesViewState_1.getJESchedulePeriodTabKey)(uiState.selectedPageTab, monthYearPeriodId)
151
152
  : null;
152
- const failedJeScheduleTransactionKeysForSelectedPeriod = monthYearPeriodId != null
153
- ? failedJeScheduleTransactionKeysByPeriod[monthYearPeriodId]
154
- : null;
155
- const jeScheduleTransactionKeys = jeScheduleTransactionKeysForSelectedPeriod ?? [];
156
- const failedJeScheduleTransactionKeys = failedJeScheduleTransactionKeysForSelectedPeriod ?? [];
157
- const jeScheduleAccruedKeys = (monthYearPeriodId != null
158
- ? jeScheduleAccruedKeysByPeriod[monthYearPeriodId]
159
- : null) ?? [];
153
+ const jeScheduleTransactionKeysForSelectedTab = selectedPeriodTabKey != null
154
+ ? jeScheduleTransactionKeysByPeriodAndTab[selectedPeriodTabKey]
155
+ : undefined;
156
+ const failedJeScheduleTransactionKeysForSelectedTab = selectedPeriodTabKey != null
157
+ ? failedJeScheduleTransactionKeysByPeriodAndTab[selectedPeriodTabKey]
158
+ : undefined;
159
+ // Distinguishes "this tab has never been fetched for this period" from "fetched and genuinely
160
+ // empty". Without it the page cannot tell a first visit from a real empty state, and renders an
161
+ // empty table where it should render a skeleton.
162
+ const hasLoadedForSelectedTab = jeScheduleTransactionKeysForSelectedTab != null;
163
+ const jeScheduleTransactionKeys = jeScheduleTransactionKeysForSelectedTab ?? [];
164
+ const failedJeScheduleTransactionKeys = failedJeScheduleTransactionKeysForSelectedTab ?? [];
165
+ const jeScheduleAccruedKeys = (selectedPeriodTabKey != null
166
+ ? jeScheduleAccruedKeysByPeriodAndTab[selectedPeriodTabKey]
167
+ : undefined) ?? [];
160
168
  jeScheduleTransactionKeys.forEach((jeScheduleKey) => {
161
169
  const jeScheduleDetails = (0, jeSchedulesSelector_1.getJEScheduledTransactionByJEScheduleTransactionKey)(jeScheduleKey, state);
162
170
  jeScheduledTransaction.push(jeScheduleDetails);
@@ -223,6 +231,33 @@ function getExpenseAutomationJESchedulesView(state) {
223
231
  amount: sumAmount(allSchedules),
224
232
  },
225
233
  };
234
+ // Each tab's badge counts from that tab's own bucket. A tab that has not been fetched yet
235
+ // reports undefined rather than 0, so the UI can hide the badge instead of asserting "none".
236
+ const scheduleCountsByTab = {};
237
+ jeSchedulesViewState_1.ALL_JE_PAGE_TABS.forEach((pageTab) => {
238
+ const periodTabKey = monthYearPeriodId != null
239
+ ? (0, jeSchedulesViewState_1.getJESchedulePeriodTabKey)(pageTab, monthYearPeriodId)
240
+ : null;
241
+ const transactionKeys = periodTabKey != null
242
+ ? jeScheduleTransactionKeysByPeriodAndTab[periodTabKey]
243
+ : undefined;
244
+ if (transactionKeys == null) {
245
+ return;
246
+ }
247
+ const accruedKeys = (periodTabKey != null
248
+ ? jeScheduleAccruedKeysByPeriodAndTab[periodTabKey]
249
+ : undefined) ?? [];
250
+ const rowsForTab = [
251
+ ...transactionKeys.map((transactionKey) => (0, jeSchedulesSelector_1.getJEScheduledTransactionByJEScheduleTransactionKey)(transactionKey, state)),
252
+ ...accruedKeys
253
+ .map((accruedKey) => (0, jeSchedulesSelector_1.getJEAccruedScheduleByJEScheduleKey)(accruedKey, state))
254
+ .filter((accruedRow) => accruedRow != null),
255
+ ];
256
+ scheduleCountsByTab[pageTab] =
257
+ pageTab === 'existing_schedules'
258
+ ? rowsForTab.filter((row) => row.status.code === 'ongoing').length
259
+ : rowsForTab.filter((row) => row.status.code === 'draft' || isCreatedStatus(row)).length;
260
+ });
226
261
  const allSteps = monthYearPeriodId != null
227
262
  ? (0, expenseAutomationViewSelectorTypes_1.getAllSteps)(monthEndCloseChecksState, monthYearPeriodId, currentTenant.tenantId)
228
263
  : [];
@@ -261,7 +296,9 @@ function getExpenseAutomationJESchedulesView(state) {
261
296
  allClassList: allClasses,
262
297
  createdSchedules,
263
298
  createdTotal,
299
+ hasLoadedForSelectedTab,
264
300
  jeScheduleTypeCounts,
301
+ scheduleCountsByTab,
265
302
  kpiSummary,
266
303
  pendingReviewSchedules,
267
304
  pendingReviewTotal,
@@ -13,6 +13,9 @@ export declare const toJEScheduleSortKey: (v: string) => "vendor" | "type" | "ca
13
13
  export type JEScheduleSortKey = ReturnType<typeof toJEScheduleSortKey>;
14
14
  export declare const toJEPageTab: (v: string) => "schedules" | "existing_schedules";
15
15
  export type JEPageTab = ReturnType<typeof toJEPageTab>;
16
+ export declare const ALL_JE_PAGE_TABS: readonly JEPageTab[];
17
+ export type JESchedulePeriodTabKey = `${JEPageTab}_${MonthYearPeriodId}`;
18
+ export declare const getJESchedulePeriodTabKey: (selectedPageTab: JEPageTab, monthYearPeriodId: MonthYearPeriodId) => JESchedulePeriodTabKey;
16
19
  export interface JESchedulesViewUIState {
17
20
  createdGroupCollapsed: boolean;
18
21
  pendingGroupCollapsed: boolean;
@@ -39,11 +42,11 @@ export interface JEScheduleLocalData {
39
42
  }
40
43
  export interface JESchedulesViewState extends FetchedState {
41
44
  accountSettings: AccountSettingsState;
42
- failedJeScheduleTransactionKeysByPeriod: Record<MonthYearPeriodId, JEScheduleTransactionKey[]>;
45
+ failedJeScheduleTransactionKeysByPeriodAndTab: Record<JESchedulePeriodTabKey, JEScheduleTransactionKey[]>;
43
46
  ignoreStatusById: Record<JEScheduleTransactionKey, FetchStateAndError>;
44
- jeScheduleAccruedKeysByPeriod: Record<MonthYearPeriodId, JEScheduleKey[]>;
47
+ jeScheduleAccruedKeysByPeriodAndTab: Record<JESchedulePeriodTabKey, JEScheduleKey[]>;
45
48
  jeScheduleLocalDataById: Record<ID, JEScheduleLocalData>;
46
- jeScheduleTransactionKeysByPeriod: Record<MonthYearPeriodId, JEScheduleTransactionKey[]>;
49
+ jeScheduleTransactionKeysByPeriodAndTab: Record<JESchedulePeriodTabKey, JEScheduleTransactionKey[]>;
47
50
  newSchedule: NewJeScheduleState;
48
51
  postStatusById: Record<ID, FetchStateAndError>;
49
52
  refreshStatus: FetchStateAndError;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MIN_NEW_SCHEDULE_SEARCH_LENGTH = exports.toJEPageTab = exports.toJEScheduleSortKey = void 0;
3
+ exports.MIN_NEW_SCHEDULE_SEARCH_LENGTH = exports.getJESchedulePeriodTabKey = exports.ALL_JE_PAGE_TABS = exports.toJEPageTab = exports.toJEScheduleSortKey = void 0;
4
4
  const stringToUnion_1 = require("../../../commonStateTypes/stringToUnion");
5
5
  const JE_SCHEDULE_SORT_KEYS = [
6
6
  'vendor',
@@ -23,4 +23,7 @@ exports.toJEScheduleSortKey = toJEScheduleSortKey;
23
23
  const JE_PAGE_TABS = ['schedules', 'existing_schedules'];
24
24
  const toJEPageTab = (v) => (0, stringToUnion_1.stringToUnion)(v, JE_PAGE_TABS);
25
25
  exports.toJEPageTab = toJEPageTab;
26
+ exports.ALL_JE_PAGE_TABS = JE_PAGE_TABS;
27
+ const getJESchedulePeriodTabKey = (selectedPageTab, monthYearPeriodId) => `${selectedPageTab}_${monthYearPeriodId}`;
28
+ exports.getJESchedulePeriodTabKey = getJESchedulePeriodTabKey;
26
29
  exports.MIN_NEW_SCHEDULE_SEARCH_LENGTH = 2;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.1.73-betaRD2",
3
+ "version": "5.1.73-betaRD3",
4
4
  "description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/esm/index.js",