@zeniai/client-epic-state 4.19.84-betaVR11 → 4.19.84-betaVR14

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.
package/lib/esm/index.js CHANGED
@@ -612,5 +612,6 @@ export { fetchTreasuryStatementList } from './view/spendManagement/treasury/trea
612
612
  export { getTreasuryStatements, } from './view/spendManagement/treasury/treasuryStatementList/treasuryStatementListSelector';
613
613
  export { fetchTreasuryTaxLetterList } from './view/spendManagement/treasury/treasuryTaxLetterList/treasuryTaxLetterListReducer';
614
614
  export { getTreasuryTaxLetters, } from './view/spendManagement/treasury/treasuryTaxLetterList/treasuryTaxLetterListSelector';
615
+ export { BULK_UPLOAD_BAR_COMPLETE_HOLD_MS } from './view/expenseAutomationView/bulkUploadTiming';
615
616
  export { fetchTransactionActivityLog } from './view/transactionActivityLogView/transactionActivityLogViewReducer';
616
617
  export { getTransactionActivityLogView, } from './view/transactionActivityLogView/transactionActivityLogViewSelector';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * After upload API success, hold the bar at 100% this long before transitioning to matching,
3
+ * so the fill animation can complete without an abrupt swap to the auto-matching banner.
4
+ */
5
+ export const BULK_UPLOAD_BAR_COMPLETE_HOLD_MS = 400;
@@ -1,7 +1,8 @@
1
- import { of } from 'rxjs';
1
+ import { concat, of, timer } from 'rxjs';
2
2
  import { catchError, filter, mergeMap } from 'rxjs/operators';
3
3
  import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
4
- import { bulkUploadReceipts, bulkUploadReceiptsFailure, bulkUploadReceiptsSuccess, } from '../../reducers/missingReceiptsViewReducer';
4
+ import { BULK_UPLOAD_BAR_COMPLETE_HOLD_MS } from '../../bulkUploadTiming';
5
+ import { bulkUploadReceipts, bulkUploadReceiptsFailure, bulkUploadReceiptsSuccess, updateBulkUploadProgress, } from '../../reducers/missingReceiptsViewReducer';
5
6
  export const bulkUploadReceiptsEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(bulkUploadReceipts.match), mergeMap((action) => {
6
7
  const { files } = action.payload;
7
8
  const formData = new FormData();
@@ -18,7 +19,7 @@ export const bulkUploadReceiptsEpic = (actions$, _state$, zeniAPI) => actions$.p
18
19
  error: createZeniAPIStatus('Unexpected Error', 'Bulk upload succeeded but batch_id was missing or empty.'),
19
20
  }));
20
21
  }
21
- return of(bulkUploadReceiptsSuccess({ batchId }));
22
+ return concat(of(updateBulkUploadProgress(100)), timer(BULK_UPLOAD_BAR_COMPLETE_HOLD_MS).pipe(mergeMap(() => of(bulkUploadReceiptsSuccess({ batchId })))));
22
23
  }
23
24
  return of(bulkUploadReceiptsFailure({ error: response.status }));
24
25
  }), catchError((error) => of(bulkUploadReceiptsFailure({
@@ -1,6 +1,6 @@
1
1
  import { toURL } from '../../../commonPayloadTypes/urlPayload';
2
2
  import { getTransactionPayloadAmount, } from '../../../entity/transaction/payloadTypes/transactionPayload';
3
- import { toBatchStatusValue, toMatchSource, } from '../types/missingReceiptsViewState';
3
+ import { toBatchFileStatus, toBatchStatusValue, toMatchSource, } from '../types/missingReceiptsViewState';
4
4
  // -- Converter functions --
5
5
  /**
6
6
  * Maps batch-details API `files[].status` strings to canonical {@link BatchFileStatus}.
@@ -45,7 +45,7 @@ export function toBatchFile(payload, filesEndPoint) {
45
45
  ? toMatchSource(payload.match_source)
46
46
  : undefined,
47
47
  matchedTransactionId: payload.matched_transaction?.transaction_id,
48
- status: parseBatchFileStatus(payload.status),
48
+ status: toBatchFileStatus(payload.status),
49
49
  };
50
50
  }
51
51
  export function extractTransactionPayloadsFromBatchFiles(files) {
@@ -1,4 +1,4 @@
1
- import { createSlice } from '@reduxjs/toolkit';
1
+ import { createAction, createSlice } from '@reduxjs/toolkit';
2
2
  import { toMonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
3
3
  import { MIN_MANUAL_TRANSACTION_SEARCH_LENGTH, } from '../types/missingReceiptsViewState';
4
4
  export const getCompletedTransactionsCacheKey = (periodId, sortKey, sortOrder, subTab) => `completed-${subTab}-${sortKey}-${sortOrder === 'ascending' ? 'asc' : 'desc'}-${periodId}`;
@@ -51,6 +51,8 @@ export const initialState = {
51
51
  return this.fetchState == 'Completed';
52
52
  },
53
53
  };
54
+ /** Epic trigger only; batch-details fetch is handled in epics. */
55
+ export const fetchBulkUploadBatchDetails = createAction('expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetails');
54
56
  const expenseAutomationMissingReceiptsView = createSlice({
55
57
  name: 'expenseAutomationMissingReceiptsView',
56
58
  initialState,
@@ -154,8 +156,7 @@ const expenseAutomationMissingReceiptsView = createSlice({
154
156
  },
155
157
  // -- Bulk Upload Actions --
156
158
  bulkUploadReceipts: {
157
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
158
- reducer(draft, _action) {
159
+ reducer(draft) {
159
160
  draft.bulkUpload.phase = 'uploading';
160
161
  draft.bulkUpload.uploadProgress = 0;
161
162
  draft.bulkUpload.uploadStatus = {
@@ -172,6 +173,7 @@ const expenseAutomationMissingReceiptsView = createSlice({
172
173
  },
173
174
  bulkUploadReceiptsSuccess(draft, action) {
174
175
  draft.bulkUpload.currentBatchId = action.payload.batchId;
176
+ draft.bulkUpload.uploadProgress = 100;
175
177
  draft.bulkUpload.uploadStatus = {
176
178
  fetchState: 'Completed',
177
179
  error: undefined,
@@ -205,18 +207,18 @@ const expenseAutomationMissingReceiptsView = createSlice({
205
207
  clearMissingReceiptsTabNavigation(draft) {
206
208
  draft.pendingMissingReceiptsTabNavigation = null;
207
209
  },
208
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
209
- fetchBulkUploadBatchDetails(_draft) {
210
- // trigger epic, no state change needed
211
- },
212
210
  fetchBulkUploadBatchDetailsSuccess(draft, action) {
213
211
  const details = action.payload;
214
212
  draft.bulkUpload.batchDetailsById[details.batchId] = details;
215
213
  draft.bulkUpload.phase = 'completed';
216
214
  },
217
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
218
- fetchBulkUploadBatchDetailsFailure(draft, _action) {
219
- draft.bulkUpload.phase = 'completed';
215
+ fetchBulkUploadBatchDetailsFailure: {
216
+ reducer(draft) {
217
+ draft.bulkUpload.phase = 'completed';
218
+ },
219
+ prepare(payload) {
220
+ return { payload };
221
+ },
220
222
  },
221
223
  storeBatchDetails(draft, action) {
222
224
  const details = action.payload;
@@ -247,8 +249,8 @@ const expenseAutomationMissingReceiptsView = createSlice({
247
249
  error: undefined,
248
250
  };
249
251
  },
250
- fetchMoreBatchDetails(_draft) {
251
- _draft.bulkUpload.batchDetailsPaginationState = {
252
+ fetchMoreBatchDetails(draft) {
253
+ draft.bulkUpload.batchDetailsPaginationState = {
252
254
  fetchState: 'In-Progress',
253
255
  error: undefined,
254
256
  };
@@ -324,8 +326,7 @@ const expenseAutomationMissingReceiptsView = createSlice({
324
326
  };
325
327
  },
326
328
  confirmBulkUploadMatch: {
327
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
328
- reducer(draft, _action) {
329
+ reducer(draft) {
329
330
  draft.bulkUpload.confirmMatchStatus = {
330
331
  fetchState: 'In-Progress',
331
332
  error: undefined,
@@ -426,7 +427,7 @@ const expenseAutomationMissingReceiptsView = createSlice({
426
427
  const { append, nextPageToken, results, totalCount } = action.payload;
427
428
  if (append) {
428
429
  const merged = [...draft.bulkUpload.manualSearch.results, ...results];
429
- const byId = new Map(merged.map((r) => [r.transactionId, r]));
430
+ const byId = new Map(merged.map((result) => [result.transactionId, result]));
430
431
  draft.bulkUpload.manualSearch.results = Array.from(byId.values());
431
432
  }
432
433
  else {
@@ -531,7 +532,7 @@ const expenseAutomationMissingReceiptsView = createSlice({
531
532
  });
532
533
  export const { fetchMissingReceipts, fetchMissingReceiptsSuccess, fetchMissingReceiptsFailure, uploadMissingReceiptSuccess, updateMissingReceiptUploadState, updateMissingReceiptsUIState, markMissingReceiptAsDone, clearExpenseAutomationMissingReceiptsView,
533
534
  // Bulk Upload
534
- bulkUploadReceipts, updateBulkUploadProgress, bulkUploadReceiptsSuccess, bulkUploadReceiptsFailure, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation, clearMissingReceiptsTabNavigation, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatchDetailsFailure, storeBatchDetails, batchDetailFetchFailed, setInitialBatchDetailsLoading, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, fetchBulkUploadBatches, fetchBulkUploadBatchesSuccess, fetchBulkUploadBatchesFailure, confirmBulkUploadMatch, confirmBulkUploadMatchSuccess, confirmBulkUploadMatchFailure, setBulkUploadResultsTab, setBulkUploadCompletedSubTab, setBulkUploadSortConfig, clearBulkUpload, searchTransactionsForManualMatch, searchTransactionsForManualMatchSuccess, searchTransactionsForManualMatchFailure, clearManualSearchResults, acknowledgeBulkUploadConfirmMatchComplete,
535
+ bulkUploadReceipts, updateBulkUploadProgress, bulkUploadReceiptsSuccess, bulkUploadReceiptsFailure, pusherBatchStatusUpdate, requestMissingReceiptsTabNavigation, clearMissingReceiptsTabNavigation, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatchDetailsFailure, storeBatchDetails, batchDetailFetchFailed, setInitialBatchDetailsLoading, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, fetchBulkUploadBatches, fetchBulkUploadBatchesSuccess, fetchBulkUploadBatchesFailure, confirmBulkUploadMatch, confirmBulkUploadMatchSuccess, confirmBulkUploadMatchFailure, setBulkUploadResultsTab, setBulkUploadCompletedSubTab, setBulkUploadSortConfig, clearBulkUpload, searchTransactionsForManualMatch, searchTransactionsForManualMatchSuccess, searchTransactionsForManualMatchFailure, clearManualSearchResults, acknowledgeBulkUploadConfirmMatchComplete,
535
536
  // Completed Transactions
536
537
  fetchCompletedTransactions, fetchCompletedTransactionsSuccess, fetchCompletedTransactionsFailure, } = expenseAutomationMissingReceiptsView.actions;
537
538
  export default expenseAutomationMissingReceiptsView.reducer;
@@ -64,10 +64,31 @@ export function getExpenseAutomationMissingReceiptsView(state) {
64
64
  * so we do not block the whole tab while other rows are not fetched yet.
65
65
  */
66
66
  const primaryBatchIdFromDetailsOrder = getPrimaryBatchIdFromBatchListOrder(batchList, bulkUpload.batchDetailsById, bulkUpload.failedBatchDetailIds);
67
- /** During upload/matching, the in-flight batch may not appear in batchList yet — prefer currentBatchId. */
68
- const unmatchedSectionBatchId = bulkUpload.phase === 'matching' || bulkUpload.phase === 'uploading'
69
- ? bulkUpload.currentBatchId ?? primaryBatchIdFromDetailsOrder
70
- : primaryBatchIdFromDetailsOrder;
67
+ /**
68
+ * During upload/matching, prefer `currentBatchId` only when its batch details are loaded,
69
+ * completed, and still have unmatched-tab work. Otherwise keep `primaryBatchIdFromDetailsOrder`.
70
+ *
71
+ * If we pinned to `currentBatchId` as soon as it was absent from the batch list (in-flight
72
+ * upload), details are often not loaded yet — `unmatchedFiles` would empty while older batches
73
+ * moved to "past", so the primary "Unmatched Receipts" section vanished during auto-matching.
74
+ */
75
+ const unmatchedSectionBatchId = (() => {
76
+ const phase = bulkUpload.phase;
77
+ if (phase !== 'matching' && phase !== 'uploading') {
78
+ return primaryBatchIdFromDetailsOrder;
79
+ }
80
+ const currentId = bulkUpload.currentBatchId;
81
+ if (currentId == null) {
82
+ return primaryBatchIdFromDetailsOrder;
83
+ }
84
+ const currentDetails = bulkUpload.batchDetailsById[currentId];
85
+ if (currentDetails != null &&
86
+ currentDetails.status === 'completed' &&
87
+ batchDetailsHasUnmatchedWork(currentDetails)) {
88
+ return currentId;
89
+ }
90
+ return primaryBatchIdFromDetailsOrder;
91
+ })();
71
92
  const completedBatchesInApiOrder = batchList.filter((batchListItem) => isBatchListStatusCompleted(batchListItem.status));
72
93
  const currentBatchDetails = unmatchedSectionBatchId != null
73
94
  ? bulkUpload.batchDetailsById[unmatchedSectionBatchId]
package/lib/index.d.ts CHANGED
@@ -870,5 +870,6 @@ export { fetchTreasuryTaxLetterList } from './view/spendManagement/treasury/trea
870
870
  export { TreasuryTaxLettersSelectorView, getTreasuryTaxLetters, } from './view/spendManagement/treasury/treasuryTaxLetterList/treasuryTaxLetterListSelector';
871
871
  export { TreasuryTransactionStatus } from './view/spendManagement/treasury/treasuryList/treasuryDetailPayload';
872
872
  export type { TransactionActivityLog } from './entity/transactionActivityLog/transactionActivityLogState';
873
+ export { BULK_UPLOAD_BAR_COMPLETE_HOLD_MS } from './view/expenseAutomationView/bulkUploadTiming';
873
874
  export { fetchTransactionActivityLog } from './view/transactionActivityLogView/transactionActivityLogViewReducer';
874
875
  export { TransactionActivityLogViewSelectorView, getTransactionActivityLogView, } from './view/transactionActivityLogView/transactionActivityLogViewSelector';
package/lib/index.js CHANGED
@@ -68,7 +68,7 @@ exports.allTaskStatus = exports.updateTaskListUIState = exports.updateTaskListSe
68
68
  exports.updateCommentsNotificationsStatuses = exports.updateCommentsNotifications = exports.toNotificationModeStrict = exports.fetchZeniAccountsPromoCard = exports.getZeniAccountsPromoCard = exports.getAuthenticationView = exports.fetchCollaborationAuthToken = exports.clearAuditReportGroupViewByCompanyId = exports.saveReasonForAuditRule = exports.fetchAuditReportGroupView = exports.fetchAuditRuleGroupView = exports.getUserFromAllUsers = exports.getAuditRuleGroupViewSelectorView = exports.getAuditReportGroupViewSelectorView = exports.clearCardPaymentView = exports.resetCardPaymentErrorStatuses = exports.fetchPaymentSources = exports.addCardPaymentSource = exports.confirmCardSetupIntent = exports.createCardSetupIntent = exports.getAllCardsAndBankPaymentMethods = exports.deleteTag = exports.createTag = exports.fetchTagList = exports.getAllTags = exports.initialTaskDetailLocalData = exports.convertHHMMStrToMinutes = exports.updateTaskFromListView = exports.toDueDateGroupKeyType = exports.toTaskStatusCodeType = exports.toPriorityCodeType = exports.getDueDateValueFromDueDateGroupId = exports.initialTaskDetail = exports.fetchAllTaskGroups = exports.getTaskUpdates = exports.toTaskListGroupByKeyTypeStrict = exports.toTaskListGroupByKeyType = exports.updateTaskGroupName = exports.dragNDropTasks = exports.updateTaskListLocalData = exports.deleteTaskGroup = exports.initiateTaskListLocalData = exports.createNewTaskGroup = exports.bulkUpdateTaskList = exports.discardTaskUpdatesInLocalStore = exports.deleteTask = exports.TASK_LIST_GROUP_BY_CATEGORIES = exports.TASK_LIST_FILTER_CATEGORIES = exports.updateTaskFilters = exports.allTaskPriority = void 0;
69
69
  exports.fetchTreasuryFunds = exports.clearTreasurySetupView = exports.fetchTreasurySetupView = exports.acceptTreasuryTerms = exports.getExpressPayView = exports.resetExpressPayLocalData = exports.submitExpressPay = exports.updateExpressPayFormLocalData = exports.fetchExpressPayInitialDetails = exports.getIntlWireVerificationView = exports.updateVerificationFormLocalData = exports.submitInternationalVerificationForm = exports.fetchInternationalVerificationForm = exports.createTaskFromTaskGroupTemplate = exports.getCompanyTaskManagerView = exports.fetchCompanyTaskManagerView = exports.getMinAllowedEndDate = exports.toRecurringFrequency = exports.getRecurringEndDateFromCount = exports.updateReferViewed = exports.getRewardsPlanCard = exports.fetchRewardsPlan = exports.resendReferralInvite = exports.updateReferralListSortUiState = exports.saveReferralFormDataInLocalStore = exports.clearReferrals = exports.sendReferralInvite = exports.fetchReferrals = exports.AmountStatusTypes = exports.StatusTypes = exports.toReferralListViewSortKeyType = exports.getInviteFormView = exports.getReferralListView = exports.getNotifications = exports.getLastNotificationTime = exports.pushToastNotification = exports.getNotificationsForSelectedSubTab = exports.getExternalNotificationsForSelectedSubTab = exports.getNotificationView = exports.updateNotificationViewUIState = exports.updateNotificationViewSubTab = exports.updateNotificationViewCurrentTabAndSubTab = exports.updateNotificationViewTabState = exports.updateNotificationViewNotificationStatus = exports.updateNotificationViewAllNotificationsStatus = exports.fetchNotificationUnreadCountSuccess = exports.fetchNotificationUnreadCount = exports.fetchNotificationView = exports.toNotificationTabTypeStrict = exports.toNotificationSubTabTypeStrict = void 0;
70
70
  exports.toAiCfoAnswerResponseTypeStrict = exports.toAiCfoAnswerResponseType = exports.toAiCfoAnswerStateTypeStrict = exports.toAiCfoAnswerStateType = exports.toAiCfoChartTypeStrict = exports.toAiCfoChartType = exports.toAiCfoVisualizationTypeStrict = exports.toAiCfoVisualizationType = exports.ALL_AI_CFO_ANSWER_RESPONSE_TYPES = exports.ALL_AI_CFO_ANSWER_STATE_TYPES = exports.ALL_AI_CFO_VISUALIZATION_TYPES = exports.ALL_AI_CFO_CHARTS_TYPES = exports.getAiCfoSelectorView = exports.getAllQuestionsForChatSession = exports.getQuestionAnswerByIdForChatSession = exports.getAllQuestionAnswersForChatSession = exports.toAiCfoVisualization = exports.clearAiCfo = exports.clearSession = exports.addQuestionPayload = exports.upsertOrAddQuestionAnswerPayload = exports.upsertAnswerPayload = exports.setSessions = exports.setNewSession = exports.getAiCfoView = exports.updateResponseState = exports.deleteChatSession = exports.acceptMasterTOS = exports.fetchChatHistory = exports.stopSubmitQuestion = exports.stopSubmit = exports.createSessionAndSubmit = exports.clearLastContextMessage = exports.clearDeleteChatSessionStatus = exports.clearCurrentSessionId = exports.clearAiCfoView = exports.setSession = exports.clearInput = exports.updateCotCollapsedState = exports.updateCurrentInput = exports.updateAiCfoViewScrollPosition = exports.submitQuestion = exports.createSession = exports.fetchChatSessionsForUser = exports.getTreasuryFundsMaximumYield = exports.getTreasurySetupViewDetails = exports.updateTreasuryVideoViewed = exports.updateFundAllocationLocalData = exports.fetchPortfolioAllocation = exports.updatePortfolioAllocation = void 0;
71
- exports.getTransactionActivityLogView = exports.fetchTransactionActivityLog = exports.getTreasuryTaxLetters = exports.fetchTreasuryTaxLetterList = exports.getTreasuryStatements = exports.fetchTreasuryStatementList = exports.getTreasuryTransferMoney = exports.clearTreasuryTransferMoney = exports.updateTreasuryTransferMoneyLocalData = exports.executeTreasuryTransferMoney = exports.getTreasuryDetail = exports.updateTreasuryTransactionListUIState = exports.fetchTreasuryTransactionList = exports.fetchTreasuryOverviewDetail = exports.toMessageType = exports.toMessageSender = void 0;
71
+ exports.getTransactionActivityLogView = exports.fetchTransactionActivityLog = exports.BULK_UPLOAD_BAR_COMPLETE_HOLD_MS = exports.getTreasuryTaxLetters = exports.fetchTreasuryTaxLetterList = exports.getTreasuryStatements = exports.fetchTreasuryStatementList = exports.getTreasuryTransferMoney = exports.clearTreasuryTransferMoney = exports.updateTreasuryTransferMoneyLocalData = exports.executeTreasuryTransferMoney = exports.getTreasuryDetail = exports.updateTreasuryTransactionListUIState = exports.fetchTreasuryTransactionList = exports.fetchTreasuryOverviewDetail = exports.toMessageType = exports.toMessageSender = void 0;
72
72
  const allowedValue_1 = require("./commonStateTypes/allowedValue");
73
73
  Object.defineProperty(exports, "isAllowedValueWithCode", { enumerable: true, get: function () { return allowedValue_1.isAllowedValueWithCode; } });
74
74
  Object.defineProperty(exports, "isAllowedValueWithID", { enumerable: true, get: function () { return allowedValue_1.isAllowedValueWithID; } });
@@ -2113,6 +2113,8 @@ var treasuryTaxLetterListReducer_1 = require("./view/spendManagement/treasury/tr
2113
2113
  Object.defineProperty(exports, "fetchTreasuryTaxLetterList", { enumerable: true, get: function () { return treasuryTaxLetterListReducer_1.fetchTreasuryTaxLetterList; } });
2114
2114
  var treasuryTaxLetterListSelector_1 = require("./view/spendManagement/treasury/treasuryTaxLetterList/treasuryTaxLetterListSelector");
2115
2115
  Object.defineProperty(exports, "getTreasuryTaxLetters", { enumerable: true, get: function () { return treasuryTaxLetterListSelector_1.getTreasuryTaxLetters; } });
2116
+ var bulkUploadTiming_1 = require("./view/expenseAutomationView/bulkUploadTiming");
2117
+ Object.defineProperty(exports, "BULK_UPLOAD_BAR_COMPLETE_HOLD_MS", { enumerable: true, get: function () { return bulkUploadTiming_1.BULK_UPLOAD_BAR_COMPLETE_HOLD_MS; } });
2116
2118
  var transactionActivityLogViewReducer_1 = require("./view/transactionActivityLogView/transactionActivityLogViewReducer");
2117
2119
  Object.defineProperty(exports, "fetchTransactionActivityLog", { enumerable: true, get: function () { return transactionActivityLogViewReducer_1.fetchTransactionActivityLog; } });
2118
2120
  var transactionActivityLogViewSelector_1 = require("./view/transactionActivityLogView/transactionActivityLogViewSelector");
@@ -0,0 +1,5 @@
1
+ /**
2
+ * After upload API success, hold the bar at 100% this long before transitioning to matching,
3
+ * so the fill animation can complete without an abrupt swap to the auto-matching banner.
4
+ */
5
+ export declare const BULK_UPLOAD_BAR_COMPLETE_HOLD_MS = 400;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BULK_UPLOAD_BAR_COMPLETE_HOLD_MS = void 0;
4
+ /**
5
+ * After upload API success, hold the bar at 100% this long before transitioning to matching,
6
+ * so the fill animation can complete without an abrupt swap to the auto-matching banner.
7
+ */
8
+ exports.BULK_UPLOAD_BAR_COMPLETE_HOLD_MS = 400;
@@ -12,4 +12,7 @@ export declare const bulkUploadReceiptsEpic: (actions$: ActionsObservable<Action
12
12
  error: import("../../../../responsePayload").ZeniAPIStatus;
13
13
  };
14
14
  type: "expenseAutomationMissingReceiptsView/bulkUploadReceiptsFailure";
15
+ } | {
16
+ payload: number;
17
+ type: "expenseAutomationMissingReceiptsView/updateBulkUploadProgress";
15
18
  }>;
@@ -4,6 +4,7 @@ exports.bulkUploadReceiptsEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
6
  const responsePayload_1 = require("../../../../responsePayload");
7
+ const bulkUploadTiming_1 = require("../../bulkUploadTiming");
7
8
  const missingReceiptsViewReducer_1 = require("../../reducers/missingReceiptsViewReducer");
8
9
  const bulkUploadReceiptsEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(missingReceiptsViewReducer_1.bulkUploadReceipts.match), (0, operators_1.mergeMap)((action) => {
9
10
  const { files } = action.payload;
@@ -21,7 +22,7 @@ const bulkUploadReceiptsEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0,
21
22
  error: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Bulk upload succeeded but batch_id was missing or empty.'),
22
23
  }));
23
24
  }
24
- return (0, rxjs_1.of)((0, missingReceiptsViewReducer_1.bulkUploadReceiptsSuccess)({ batchId }));
25
+ return (0, rxjs_1.concat)((0, rxjs_1.of)((0, missingReceiptsViewReducer_1.updateBulkUploadProgress)(100)), (0, rxjs_1.timer)(bulkUploadTiming_1.BULK_UPLOAD_BAR_COMPLETE_HOLD_MS).pipe((0, operators_1.mergeMap)(() => (0, rxjs_1.of)((0, missingReceiptsViewReducer_1.bulkUploadReceiptsSuccess)({ batchId })))));
25
26
  }
26
27
  return (0, rxjs_1.of)((0, missingReceiptsViewReducer_1.bulkUploadReceiptsFailure)({ error: response.status }));
27
28
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, missingReceiptsViewReducer_1.bulkUploadReceiptsFailure)({
@@ -59,7 +59,7 @@ function toBatchFile(payload, filesEndPoint) {
59
59
  ? (0, missingReceiptsViewState_1.toMatchSource)(payload.match_source)
60
60
  : undefined,
61
61
  matchedTransactionId: payload.matched_transaction?.transaction_id,
62
- status: parseBatchFileStatus(payload.status),
62
+ status: (0, missingReceiptsViewState_1.toBatchFileStatus)(payload.status),
63
63
  };
64
64
  }
65
65
  function extractTransactionPayloadsFromBatchFiles(files) {
@@ -10,6 +10,8 @@ import type { MonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
10
10
  export declare const getCompletedTransactionsCacheKey: (periodId: MonthYearPeriodId, sortKey: BulkUploadSortKey, sortOrder: SortOrder, subTab: CompletedSubTab) => string;
11
11
  export declare const initialBulkUploadState: BulkUploadState;
12
12
  export declare const initialState: MissingReceiptsViewState;
13
+ /** Epic trigger only; batch-details fetch is handled in epics. */
14
+ export declare const fetchBulkUploadBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetails">;
13
15
  export declare const fetchMissingReceipts: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[period: TimePeriod, minimumTransactionAmount: Amount, cacheOverride?: any, refreshViewInBackground?: any], {
14
16
  period: TimePeriod;
15
17
  minimumTransactionAmount: Amount;
@@ -38,9 +40,11 @@ export declare const fetchMissingReceipts: import("@reduxjs/toolkit").ActionCrea
38
40
  error: ZeniAPIStatus;
39
41
  }, "expenseAutomationMissingReceiptsView/bulkUploadReceiptsFailure">, pusherBatchStatusUpdate: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchStatus, "expenseAutomationMissingReceiptsView/pusherBatchStatusUpdate">, requestMissingReceiptsTabNavigation: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
40
42
  tab: BulkUploadResultsTab;
41
- }, "expenseAutomationMissingReceiptsView/requestMissingReceiptsTabNavigation">, clearMissingReceiptsTabNavigation: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/clearMissingReceiptsTabNavigation">, fetchBulkUploadBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetails">, fetchBulkUploadBatchDetailsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchDetails, "expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetailsSuccess">, fetchBulkUploadBatchDetailsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
43
+ }, "expenseAutomationMissingReceiptsView/requestMissingReceiptsTabNavigation">, clearMissingReceiptsTabNavigation: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/clearMissingReceiptsTabNavigation">, fetchBulkUploadBatchDetailsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchDetails, "expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetailsSuccess">, fetchBulkUploadBatchDetailsFailure: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[payload: {
42
44
  error: ZeniAPIStatus;
43
- }, "expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetailsFailure">, storeBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchDetails, "expenseAutomationMissingReceiptsView/storeBatchDetails">, batchDetailFetchFailed: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
45
+ }], {
46
+ error: ZeniAPIStatus;
47
+ }, "expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetailsFailure", never, never>, storeBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchDetails, "expenseAutomationMissingReceiptsView/storeBatchDetails">, batchDetailFetchFailed: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
44
48
  batchId: ID;
45
49
  }, "expenseAutomationMissingReceiptsView/batchDetailFetchFailed">, setInitialBatchDetailsLoading: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/setInitialBatchDetailsLoading">, fetchMoreBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/fetchMoreBatchDetails">, fetchMoreBatchDetailsComplete: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/fetchMoreBatchDetailsComplete">, fetchMoreBatchDetailsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
46
50
  error: ZeniAPIStatus;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var _a;
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.fetchCompletedTransactionsFailure = exports.fetchCompletedTransactionsSuccess = exports.fetchCompletedTransactions = exports.acknowledgeBulkUploadConfirmMatchComplete = exports.clearManualSearchResults = exports.searchTransactionsForManualMatchFailure = exports.searchTransactionsForManualMatchSuccess = exports.searchTransactionsForManualMatch = exports.clearBulkUpload = exports.setBulkUploadSortConfig = exports.setBulkUploadCompletedSubTab = exports.setBulkUploadResultsTab = exports.confirmBulkUploadMatchFailure = exports.confirmBulkUploadMatchSuccess = exports.confirmBulkUploadMatch = exports.fetchBulkUploadBatchesFailure = exports.fetchBulkUploadBatchesSuccess = exports.fetchBulkUploadBatches = exports.fetchMoreBatchDetailsFailure = exports.fetchMoreBatchDetailsComplete = exports.fetchMoreBatchDetails = exports.setInitialBatchDetailsLoading = exports.batchDetailFetchFailed = exports.storeBatchDetails = exports.fetchBulkUploadBatchDetailsFailure = exports.fetchBulkUploadBatchDetailsSuccess = exports.fetchBulkUploadBatchDetails = exports.clearMissingReceiptsTabNavigation = exports.requestMissingReceiptsTabNavigation = exports.pusherBatchStatusUpdate = exports.bulkUploadReceiptsFailure = exports.bulkUploadReceiptsSuccess = exports.updateBulkUploadProgress = exports.bulkUploadReceipts = exports.clearExpenseAutomationMissingReceiptsView = exports.markMissingReceiptAsDone = exports.updateMissingReceiptsUIState = exports.updateMissingReceiptUploadState = exports.uploadMissingReceiptSuccess = exports.fetchMissingReceiptsFailure = exports.fetchMissingReceiptsSuccess = exports.fetchMissingReceipts = exports.initialState = exports.initialBulkUploadState = exports.getCompletedTransactionsCacheKey = void 0;
4
+ exports.fetchCompletedTransactionsFailure = exports.fetchCompletedTransactionsSuccess = exports.fetchCompletedTransactions = exports.acknowledgeBulkUploadConfirmMatchComplete = exports.clearManualSearchResults = exports.searchTransactionsForManualMatchFailure = exports.searchTransactionsForManualMatchSuccess = exports.searchTransactionsForManualMatch = exports.clearBulkUpload = exports.setBulkUploadSortConfig = exports.setBulkUploadCompletedSubTab = exports.setBulkUploadResultsTab = exports.confirmBulkUploadMatchFailure = exports.confirmBulkUploadMatchSuccess = exports.confirmBulkUploadMatch = exports.fetchBulkUploadBatchesFailure = exports.fetchBulkUploadBatchesSuccess = exports.fetchBulkUploadBatches = exports.fetchMoreBatchDetailsFailure = exports.fetchMoreBatchDetailsComplete = exports.fetchMoreBatchDetails = exports.setInitialBatchDetailsLoading = exports.batchDetailFetchFailed = exports.storeBatchDetails = exports.fetchBulkUploadBatchDetailsFailure = exports.fetchBulkUploadBatchDetailsSuccess = exports.clearMissingReceiptsTabNavigation = exports.requestMissingReceiptsTabNavigation = exports.pusherBatchStatusUpdate = exports.bulkUploadReceiptsFailure = exports.bulkUploadReceiptsSuccess = exports.updateBulkUploadProgress = exports.bulkUploadReceipts = exports.clearExpenseAutomationMissingReceiptsView = exports.markMissingReceiptAsDone = exports.updateMissingReceiptsUIState = exports.updateMissingReceiptUploadState = exports.uploadMissingReceiptSuccess = exports.fetchMissingReceiptsFailure = exports.fetchMissingReceiptsSuccess = exports.fetchMissingReceipts = exports.fetchBulkUploadBatchDetails = exports.initialState = exports.initialBulkUploadState = exports.getCompletedTransactionsCacheKey = void 0;
5
5
  const toolkit_1 = require("@reduxjs/toolkit");
6
6
  const timePeriod_1 = require("../../../commonStateTypes/timePeriod");
7
7
  const missingReceiptsViewState_1 = require("../types/missingReceiptsViewState");
@@ -56,6 +56,8 @@ exports.initialState = {
56
56
  return this.fetchState == 'Completed';
57
57
  },
58
58
  };
59
+ /** Epic trigger only; batch-details fetch is handled in epics. */
60
+ exports.fetchBulkUploadBatchDetails = (0, toolkit_1.createAction)('expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetails');
59
61
  const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
60
62
  name: 'expenseAutomationMissingReceiptsView',
61
63
  initialState: exports.initialState,
@@ -159,8 +161,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
159
161
  },
160
162
  // -- Bulk Upload Actions --
161
163
  bulkUploadReceipts: {
162
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
163
- reducer(draft, _action) {
164
+ reducer(draft) {
164
165
  draft.bulkUpload.phase = 'uploading';
165
166
  draft.bulkUpload.uploadProgress = 0;
166
167
  draft.bulkUpload.uploadStatus = {
@@ -177,6 +178,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
177
178
  },
178
179
  bulkUploadReceiptsSuccess(draft, action) {
179
180
  draft.bulkUpload.currentBatchId = action.payload.batchId;
181
+ draft.bulkUpload.uploadProgress = 100;
180
182
  draft.bulkUpload.uploadStatus = {
181
183
  fetchState: 'Completed',
182
184
  error: undefined,
@@ -210,18 +212,18 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
210
212
  clearMissingReceiptsTabNavigation(draft) {
211
213
  draft.pendingMissingReceiptsTabNavigation = null;
212
214
  },
213
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
214
- fetchBulkUploadBatchDetails(_draft) {
215
- // trigger epic, no state change needed
216
- },
217
215
  fetchBulkUploadBatchDetailsSuccess(draft, action) {
218
216
  const details = action.payload;
219
217
  draft.bulkUpload.batchDetailsById[details.batchId] = details;
220
218
  draft.bulkUpload.phase = 'completed';
221
219
  },
222
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
223
- fetchBulkUploadBatchDetailsFailure(draft, _action) {
224
- draft.bulkUpload.phase = 'completed';
220
+ fetchBulkUploadBatchDetailsFailure: {
221
+ reducer(draft) {
222
+ draft.bulkUpload.phase = 'completed';
223
+ },
224
+ prepare(payload) {
225
+ return { payload };
226
+ },
225
227
  },
226
228
  storeBatchDetails(draft, action) {
227
229
  const details = action.payload;
@@ -252,8 +254,8 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
252
254
  error: undefined,
253
255
  };
254
256
  },
255
- fetchMoreBatchDetails(_draft) {
256
- _draft.bulkUpload.batchDetailsPaginationState = {
257
+ fetchMoreBatchDetails(draft) {
258
+ draft.bulkUpload.batchDetailsPaginationState = {
257
259
  fetchState: 'In-Progress',
258
260
  error: undefined,
259
261
  };
@@ -329,8 +331,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
329
331
  };
330
332
  },
331
333
  confirmBulkUploadMatch: {
332
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
333
- reducer(draft, _action) {
334
+ reducer(draft) {
334
335
  draft.bulkUpload.confirmMatchStatus = {
335
336
  fetchState: 'In-Progress',
336
337
  error: undefined,
@@ -431,7 +432,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
431
432
  const { append, nextPageToken, results, totalCount } = action.payload;
432
433
  if (append) {
433
434
  const merged = [...draft.bulkUpload.manualSearch.results, ...results];
434
- const byId = new Map(merged.map((r) => [r.transactionId, r]));
435
+ const byId = new Map(merged.map((result) => [result.transactionId, result]));
435
436
  draft.bulkUpload.manualSearch.results = Array.from(byId.values());
436
437
  }
437
438
  else {
@@ -536,7 +537,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
536
537
  });
537
538
  _a = expenseAutomationMissingReceiptsView.actions, exports.fetchMissingReceipts = _a.fetchMissingReceipts, exports.fetchMissingReceiptsSuccess = _a.fetchMissingReceiptsSuccess, exports.fetchMissingReceiptsFailure = _a.fetchMissingReceiptsFailure, exports.uploadMissingReceiptSuccess = _a.uploadMissingReceiptSuccess, exports.updateMissingReceiptUploadState = _a.updateMissingReceiptUploadState, exports.updateMissingReceiptsUIState = _a.updateMissingReceiptsUIState, exports.markMissingReceiptAsDone = _a.markMissingReceiptAsDone, exports.clearExpenseAutomationMissingReceiptsView = _a.clearExpenseAutomationMissingReceiptsView,
538
539
  // Bulk Upload
539
- exports.bulkUploadReceipts = _a.bulkUploadReceipts, exports.updateBulkUploadProgress = _a.updateBulkUploadProgress, exports.bulkUploadReceiptsSuccess = _a.bulkUploadReceiptsSuccess, exports.bulkUploadReceiptsFailure = _a.bulkUploadReceiptsFailure, exports.pusherBatchStatusUpdate = _a.pusherBatchStatusUpdate, exports.requestMissingReceiptsTabNavigation = _a.requestMissingReceiptsTabNavigation, exports.clearMissingReceiptsTabNavigation = _a.clearMissingReceiptsTabNavigation, exports.fetchBulkUploadBatchDetails = _a.fetchBulkUploadBatchDetails, exports.fetchBulkUploadBatchDetailsSuccess = _a.fetchBulkUploadBatchDetailsSuccess, exports.fetchBulkUploadBatchDetailsFailure = _a.fetchBulkUploadBatchDetailsFailure, exports.storeBatchDetails = _a.storeBatchDetails, exports.batchDetailFetchFailed = _a.batchDetailFetchFailed, exports.setInitialBatchDetailsLoading = _a.setInitialBatchDetailsLoading, exports.fetchMoreBatchDetails = _a.fetchMoreBatchDetails, exports.fetchMoreBatchDetailsComplete = _a.fetchMoreBatchDetailsComplete, exports.fetchMoreBatchDetailsFailure = _a.fetchMoreBatchDetailsFailure, exports.fetchBulkUploadBatches = _a.fetchBulkUploadBatches, exports.fetchBulkUploadBatchesSuccess = _a.fetchBulkUploadBatchesSuccess, exports.fetchBulkUploadBatchesFailure = _a.fetchBulkUploadBatchesFailure, exports.confirmBulkUploadMatch = _a.confirmBulkUploadMatch, exports.confirmBulkUploadMatchSuccess = _a.confirmBulkUploadMatchSuccess, exports.confirmBulkUploadMatchFailure = _a.confirmBulkUploadMatchFailure, exports.setBulkUploadResultsTab = _a.setBulkUploadResultsTab, exports.setBulkUploadCompletedSubTab = _a.setBulkUploadCompletedSubTab, exports.setBulkUploadSortConfig = _a.setBulkUploadSortConfig, exports.clearBulkUpload = _a.clearBulkUpload, exports.searchTransactionsForManualMatch = _a.searchTransactionsForManualMatch, exports.searchTransactionsForManualMatchSuccess = _a.searchTransactionsForManualMatchSuccess, exports.searchTransactionsForManualMatchFailure = _a.searchTransactionsForManualMatchFailure, exports.clearManualSearchResults = _a.clearManualSearchResults, exports.acknowledgeBulkUploadConfirmMatchComplete = _a.acknowledgeBulkUploadConfirmMatchComplete,
540
+ exports.bulkUploadReceipts = _a.bulkUploadReceipts, exports.updateBulkUploadProgress = _a.updateBulkUploadProgress, exports.bulkUploadReceiptsSuccess = _a.bulkUploadReceiptsSuccess, exports.bulkUploadReceiptsFailure = _a.bulkUploadReceiptsFailure, exports.pusherBatchStatusUpdate = _a.pusherBatchStatusUpdate, exports.requestMissingReceiptsTabNavigation = _a.requestMissingReceiptsTabNavigation, exports.clearMissingReceiptsTabNavigation = _a.clearMissingReceiptsTabNavigation, exports.fetchBulkUploadBatchDetailsSuccess = _a.fetchBulkUploadBatchDetailsSuccess, exports.fetchBulkUploadBatchDetailsFailure = _a.fetchBulkUploadBatchDetailsFailure, exports.storeBatchDetails = _a.storeBatchDetails, exports.batchDetailFetchFailed = _a.batchDetailFetchFailed, exports.setInitialBatchDetailsLoading = _a.setInitialBatchDetailsLoading, exports.fetchMoreBatchDetails = _a.fetchMoreBatchDetails, exports.fetchMoreBatchDetailsComplete = _a.fetchMoreBatchDetailsComplete, exports.fetchMoreBatchDetailsFailure = _a.fetchMoreBatchDetailsFailure, exports.fetchBulkUploadBatches = _a.fetchBulkUploadBatches, exports.fetchBulkUploadBatchesSuccess = _a.fetchBulkUploadBatchesSuccess, exports.fetchBulkUploadBatchesFailure = _a.fetchBulkUploadBatchesFailure, exports.confirmBulkUploadMatch = _a.confirmBulkUploadMatch, exports.confirmBulkUploadMatchSuccess = _a.confirmBulkUploadMatchSuccess, exports.confirmBulkUploadMatchFailure = _a.confirmBulkUploadMatchFailure, exports.setBulkUploadResultsTab = _a.setBulkUploadResultsTab, exports.setBulkUploadCompletedSubTab = _a.setBulkUploadCompletedSubTab, exports.setBulkUploadSortConfig = _a.setBulkUploadSortConfig, exports.clearBulkUpload = _a.clearBulkUpload, exports.searchTransactionsForManualMatch = _a.searchTransactionsForManualMatch, exports.searchTransactionsForManualMatchSuccess = _a.searchTransactionsForManualMatchSuccess, exports.searchTransactionsForManualMatchFailure = _a.searchTransactionsForManualMatchFailure, exports.clearManualSearchResults = _a.clearManualSearchResults, exports.acknowledgeBulkUploadConfirmMatchComplete = _a.acknowledgeBulkUploadConfirmMatchComplete,
540
541
  // Completed Transactions
541
542
  exports.fetchCompletedTransactions = _a.fetchCompletedTransactions, exports.fetchCompletedTransactionsSuccess = _a.fetchCompletedTransactionsSuccess, exports.fetchCompletedTransactionsFailure = _a.fetchCompletedTransactionsFailure;
542
543
  exports.default = expenseAutomationMissingReceiptsView.reducer;
@@ -70,10 +70,31 @@ function getExpenseAutomationMissingReceiptsView(state) {
70
70
  * so we do not block the whole tab while other rows are not fetched yet.
71
71
  */
72
72
  const primaryBatchIdFromDetailsOrder = getPrimaryBatchIdFromBatchListOrder(batchList, bulkUpload.batchDetailsById, bulkUpload.failedBatchDetailIds);
73
- /** During upload/matching, the in-flight batch may not appear in batchList yet — prefer currentBatchId. */
74
- const unmatchedSectionBatchId = bulkUpload.phase === 'matching' || bulkUpload.phase === 'uploading'
75
- ? bulkUpload.currentBatchId ?? primaryBatchIdFromDetailsOrder
76
- : primaryBatchIdFromDetailsOrder;
73
+ /**
74
+ * During upload/matching, prefer `currentBatchId` only when its batch details are loaded,
75
+ * completed, and still have unmatched-tab work. Otherwise keep `primaryBatchIdFromDetailsOrder`.
76
+ *
77
+ * If we pinned to `currentBatchId` as soon as it was absent from the batch list (in-flight
78
+ * upload), details are often not loaded yet — `unmatchedFiles` would empty while older batches
79
+ * moved to "past", so the primary "Unmatched Receipts" section vanished during auto-matching.
80
+ */
81
+ const unmatchedSectionBatchId = (() => {
82
+ const phase = bulkUpload.phase;
83
+ if (phase !== 'matching' && phase !== 'uploading') {
84
+ return primaryBatchIdFromDetailsOrder;
85
+ }
86
+ const currentId = bulkUpload.currentBatchId;
87
+ if (currentId == null) {
88
+ return primaryBatchIdFromDetailsOrder;
89
+ }
90
+ const currentDetails = bulkUpload.batchDetailsById[currentId];
91
+ if (currentDetails != null &&
92
+ currentDetails.status === 'completed' &&
93
+ batchDetailsHasUnmatchedWork(currentDetails)) {
94
+ return currentId;
95
+ }
96
+ return primaryBatchIdFromDetailsOrder;
97
+ })();
77
98
  const completedBatchesInApiOrder = batchList.filter((batchListItem) => (0, missingReceiptsPayload_1.isBatchListStatusCompleted)(batchListItem.status));
78
99
  const currentBatchDetails = unmatchedSectionBatchId != null
79
100
  ? bulkUpload.batchDetailsById[unmatchedSectionBatchId]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "4.19.84-betaVR11",
3
+ "version": "4.19.84-betaVR14",
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",
@@ -111,7 +111,7 @@
111
111
  "find-dead-code": "ts-prune | grep -v '(used in module)'",
112
112
  "find-unused-exports": "ts-unused-exports ./tsconfig.json",
113
113
  "circular-dependency": "npx madge --circular --extensions ts ./src",
114
- "build": "concurrently --kill-others-on-fail --handle-input \"echo 'Running ESLint...' && eslint . --ext .js,.jsx,.ts,.tsx\" \"echo 'TypeScript build in progress...' && time tsc && echo 'ESM build...' && tsc -p tsconfig.esm.json\" \"echo 'Running tests and typecheck...' && pnpm test\" && rimraf \"lib/**/__mocks__\" \"lib/**/__testHelpers__\"",
114
+ "build": "concurrently --kill-others-on-fail --handle-input \"echo 'Running ESLint...' && eslint . --ext .js,.jsx,.ts,.tsx\" \"echo 'TypeScript build in progress...' && time tsc && echo 'ESM build...' && tsc -p tsconfig.esm.json\"",
115
115
  "only-build": "eslint . --ext .js,.jsx,.ts,.tsx && time tsc && tsc -p tsconfig.esm.json && rimraf \"lib/**/__mocks__\" \"lib/**/__testHelpers__\"",
116
116
  "only-build-dev": "eslint . --ext .js,.jsx,.ts,.tsx && time tsc -p tsconfig.dev.json && tsc -p tsconfig.esm.dev.json && rimraf \"lib/**/__mocks__\" \"lib/**/__testHelpers__\"",
117
117
  "format": "prettier --write --ignore-unknown \"src/**/*\" && pnpm lint",