@zeniai/client-epic-state 4.19.37-betaVR27 → 4.19.37-betaVR4

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.
Files changed (38) hide show
  1. package/lib/epic.d.ts +1 -2
  2. package/lib/epic.js +1 -2
  3. package/lib/esm/epic.js +1 -2
  4. package/lib/esm/index.js +2 -2
  5. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/confirmBulkUploadMatchEpic.js +2 -2
  6. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchDetailsEpic.js +13 -22
  7. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchesEpic.js +1 -7
  8. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchCompletedTransactionsEpic.js +3 -7
  9. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js +23 -45
  10. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +24 -65
  11. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +32 -33
  12. package/lib/esm/view/expenseAutomationView/payload/missingReceiptsPayload.js +16 -63
  13. package/lib/esm/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +26 -163
  14. package/lib/esm/view/expenseAutomationView/selectors/missingReceiptsSelector.js +13 -109
  15. package/lib/index.d.ts +2 -2
  16. package/lib/index.js +32 -37
  17. package/lib/tsconfig.typecheck.tsbuildinfo +1 -0
  18. package/lib/view/expenseAutomationView/epics/missingReceipts/confirmBulkUploadMatchEpic.js +1 -1
  19. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchDetailsEpic.js +11 -20
  20. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchBulkUploadBatchesEpic.js +1 -7
  21. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchCompletedTransactionsEpic.js +2 -6
  22. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.d.ts +2 -3
  23. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMultipleBatchDetailsEpic.js +20 -43
  24. package/lib/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.d.ts +3 -11
  25. package/lib/view/expenseAutomationView/epics/missingReceipts/searchTransactionsForManualMatchEpic.js +22 -63
  26. package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.d.ts +7 -5
  27. package/lib/view/expenseAutomationView/epics/missingReceipts/watchBulkUploadBatchStatusEpic.js +28 -29
  28. package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.d.ts +31 -30
  29. package/lib/view/expenseAutomationView/payload/missingReceiptsPayload.js +18 -69
  30. package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.d.ts +6 -25
  31. package/lib/view/expenseAutomationView/reducers/missingReceiptsViewReducer.js +27 -165
  32. package/lib/view/expenseAutomationView/selectorTypes/missingReceiptsSelectorTypes.d.ts +0 -8
  33. package/lib/view/expenseAutomationView/selectors/missingReceiptsSelector.js +13 -109
  34. package/lib/view/expenseAutomationView/types/missingReceiptsViewState.d.ts +1 -21
  35. package/package.json +2 -2
  36. package/lib/esm/view/expenseAutomationView/epics/missingReceipts/fetchMoreBatchDetailsEpic.js +0 -34
  37. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMoreBatchDetailsEpic.d.ts +0 -8
  38. package/lib/view/expenseAutomationView/epics/missingReceipts/fetchMoreBatchDetailsEpic.js +0 -38
@@ -3,27 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.toBatchFile = toBatchFile;
4
4
  exports.extractTransactionPayloadsFromBatchFiles = extractTransactionPayloadsFromBatchFiles;
5
5
  exports.toBatchSummary = toBatchSummary;
6
+ exports.toBatchStatus = toBatchStatus;
6
7
  exports.toBatchDetails = toBatchDetails;
7
- exports.isBatchListStatusCompleted = isBatchListStatusCompleted;
8
- exports.filterBatchListItemsForBatchDetailsFetch = filterBatchListItemsForBatchDetailsFetch;
9
- exports.isBatchDetailsApiStatusCompleted = isBatchDetailsApiStatusCompleted;
10
- exports.findBatchListItemForBatchId = findBatchListItemForBatchId;
11
- exports.shouldFetchBatchDetailsForBatchId = shouldFetchBatchDetailsForBatchId;
12
8
  exports.toBatchListItem = toBatchListItem;
13
- exports.supportedTransactionPayloadToManualSearchResult = supportedTransactionPayloadToManualSearchResult;
9
+ exports.toManualSearchResult = toManualSearchResult;
14
10
  const urlPayload_1 = require("../../../commonPayloadTypes/urlPayload");
15
- const transactionPayload_1 = require("../../../entity/transaction/payloadTypes/transactionPayload");
16
11
  // -- Converter functions --
17
- function toBatchFile(payload, filesEndPoint) {
12
+ function toBatchFile(payload) {
18
13
  return {
19
14
  attachmentId: payload.attachment_id,
20
15
  candidates: payload.candidates?.map((c) => ({
21
16
  transactionId: c.transaction_id,
22
17
  matchScore: c.match_score,
23
18
  })),
24
- fileDownloadUrl: payload.file_id != null && filesEndPoint != null
25
- ? `${filesEndPoint}/1.0/files/${payload.file_id}?query=${encodeURIComponent(JSON.stringify({ download_file: true }))}`
26
- : null,
27
19
  fileId: payload.file_id,
28
20
  filePreviewUrl: payload.file_preview_url,
29
21
  filename: payload.filename,
@@ -75,62 +67,22 @@ function toBatchSummary(payload) {
75
67
  total: payload.total,
76
68
  };
77
69
  }
78
- function toBatchDetails(payload, filesEndPoint) {
70
+ function toBatchStatus(payload) {
71
+ return {
72
+ batchId: payload.batch_id,
73
+ progress: payload.progress,
74
+ status: payload.status,
75
+ };
76
+ }
77
+ function toBatchDetails(payload) {
79
78
  return {
80
79
  batchId: payload.batch_id,
81
80
  createdAt: payload.created_at,
82
- files: payload.files.map((f) => toBatchFile(f, filesEndPoint)),
81
+ files: payload.files.map(toBatchFile),
83
82
  status: payload.status,
84
83
  summary: toBatchSummary(payload.summary),
85
84
  };
86
85
  }
87
- /** Batch list `status` is a string from the API — compare case-insensitively. */
88
- function isBatchListStatusCompleted(status) {
89
- return status.toLowerCase() === 'completed';
90
- }
91
- /**
92
- * Subset of the get-all-batches (`/batches?query=...`) list that is eligible for
93
- * `GET /batches/:batchId` details fetches. The stored list may include pending, failed, or other
94
- * statuses for UI; only `completed` rows should trigger batch-details requests.
95
- */
96
- function filterBatchListItemsForBatchDetailsFetch(batches) {
97
- return batches.filter((b) => isBatchListStatusCompleted(b.status));
98
- }
99
- /**
100
- * Batch details API response `status` field — only completed payloads should be stored from
101
- * multi-batch fetch paths (list can be briefly stale vs. live processing state).
102
- */
103
- function isBatchDetailsApiStatusCompleted(status) {
104
- return status.toLowerCase() === 'completed';
105
- }
106
- function findBatchListItemForBatchId(batchListByPeriod, batchId) {
107
- for (const list of Object.values(batchListByPeriod)) {
108
- const found = list.find((b) => b.batchId === batchId);
109
- if (found != null) {
110
- return found;
111
- }
112
- }
113
- return undefined;
114
- }
115
- /**
116
- * Whether it is appropriate to call `GET .../batches/:id` for details.
117
- * Skips when live batch status or batch list row indicates the batch is not completed yet.
118
- * When status is unknown in both sources, allows the request (e.g. dispatch before list refresh).
119
- */
120
- function shouldFetchBatchDetailsForBatchId(batchStatusById, batchListByPeriod, batchId) {
121
- const live = batchStatusById[batchId]?.status;
122
- if (live === 'completed') {
123
- return true;
124
- }
125
- if (live === 'pending' || live === 'processing') {
126
- return false;
127
- }
128
- const listItem = findBatchListItemForBatchId(batchListByPeriod, batchId);
129
- if (listItem != null && !isBatchListStatusCompleted(listItem.status)) {
130
- return false;
131
- }
132
- return true;
133
- }
134
86
  function toBatchListItem(payload) {
135
87
  return {
136
88
  batchId: payload.batch_id,
@@ -143,18 +95,15 @@ function toBatchListItem(payload) {
143
95
  totalFiles: payload.total_files,
144
96
  };
145
97
  }
146
- /** Maps expense-automation transaction rows to manual-search list rows (Unmatched tab). */
147
- function supportedTransactionPayloadToManualSearchResult(payload) {
148
- const amountPayload = (0, transactionPayload_1.getTransactionPayloadAmount)(payload);
98
+ function toManualSearchResult(payload) {
149
99
  return {
150
- amount: amountPayload.amount,
151
- currencyCode: amountPayload.currencyCode,
152
- entityId: payload.vendor_id ?? payload.customer_id ?? '',
153
- memo: payload.transaction_memo ?? '',
100
+ amount: payload.amount,
101
+ currencyCode: payload.currency,
102
+ entityId: payload.entity_id,
103
+ memo: payload.memo,
154
104
  transactionDate: payload.transaction_date,
155
105
  transactionId: payload.transaction_id,
156
106
  transactionType: payload.transaction_type,
157
- vendorName: payload.vendor_name ?? '',
158
- vendorLogo: (0, urlPayload_1.toURL)(payload.logo)?.href,
107
+ vendorName: payload.vendor_name,
159
108
  };
160
109
  }
@@ -6,8 +6,6 @@ import { TransactionPayload } from '../../../entity/transaction/payloadTypes/tra
6
6
  import { SupportedTransactionPayload } from '../../../entity/transaction/transactionState';
7
7
  import { ZeniAPIStatus } from '../../../responsePayload';
8
8
  import type { BatchDetails, BatchListItem, BatchStatus, BulkUploadResultsTab, BulkUploadSortKey, BulkUploadState, CompletedSubTab, ManualSearchResult, MissingReceiptsViewState, MissingReceiptsViewUIState } from '../types/missingReceiptsViewState';
9
- import type { MonthYearPeriodId } from '../../../commonStateTypes/timePeriod';
10
- export declare const getCompletedTransactionsCacheKey: (periodId: MonthYearPeriodId, sortKey: BulkUploadSortKey, sortOrder: SortOrder, subTab: CompletedSubTab) => string;
11
9
  export declare const initialBulkUploadState: BulkUploadState;
12
10
  export declare const initialState: MissingReceiptsViewState;
13
11
  export declare const fetchMissingReceipts: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[period: TimePeriod, minimumTransactionAmount: Amount, cacheOverride?: any, refreshViewInBackground?: any], {
@@ -36,20 +34,10 @@ export declare const fetchMissingReceipts: import("@reduxjs/toolkit").ActionCrea
36
34
  batchId: ID;
37
35
  }, "expenseAutomationMissingReceiptsView/bulkUploadReceiptsSuccess">, bulkUploadReceiptsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
38
36
  error: ZeniAPIStatus;
39
- }, "expenseAutomationMissingReceiptsView/bulkUploadReceiptsFailure">, pusherBatchStatusUpdate: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchStatus, "expenseAutomationMissingReceiptsView/pusherBatchStatusUpdate">, requestMissingReceiptsTabNavigation: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
40
- 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<{
37
+ }, "expenseAutomationMissingReceiptsView/bulkUploadReceiptsFailure">, updateBulkUploadBatchStatus: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchStatus, "expenseAutomationMissingReceiptsView/updateBulkUploadBatchStatus">, pusherBatchStatusUpdate: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchStatus, "expenseAutomationMissingReceiptsView/pusherBatchStatusUpdate">, fetchBulkUploadBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetails">, fetchBulkUploadBatchDetailsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchDetails, "expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetailsSuccess">, fetchBulkUploadBatchDetailsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
42
38
  error: ZeniAPIStatus;
43
- }, "expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetailsFailure">, storeBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchDetails, "expenseAutomationMissingReceiptsView/storeBatchDetails">, batchDetailFetchFailed: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
44
- batchId: ID;
45
- }, "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
- error: ZeniAPIStatus;
47
- }, "expenseAutomationMissingReceiptsView/fetchMoreBatchDetailsFailure">, fetchBulkUploadBatches: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[input?: boolean | {
48
- cacheOverride?: boolean;
49
- invalidateBatchDetailsCache?: boolean;
50
- } | undefined], {
51
- cacheOverride: boolean;
52
- invalidateBatchDetailsCache: boolean;
39
+ }, "expenseAutomationMissingReceiptsView/fetchBulkUploadBatchDetailsFailure">, storeBatchDetails: import("@reduxjs/toolkit").ActionCreatorWithPayload<BatchDetails, "expenseAutomationMissingReceiptsView/storeBatchDetails">, fetchBulkUploadBatches: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[cacheOverride?: any], {
40
+ cacheOverride: any;
53
41
  }, "expenseAutomationMissingReceiptsView/fetchBulkUploadBatches", never, never>, fetchBulkUploadBatchesSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
54
42
  batchList: BatchListItem[];
55
43
  selectedPeriod: MonthYearPeriod;
@@ -71,19 +59,12 @@ export declare const fetchMissingReceipts: import("@reduxjs/toolkit").ActionCrea
71
59
  }, "expenseAutomationMissingReceiptsView/confirmBulkUploadMatchFailure">, setBulkUploadResultsTab: import("@reduxjs/toolkit").ActionCreatorWithPayload<BulkUploadResultsTab, "expenseAutomationMissingReceiptsView/setBulkUploadResultsTab">, setBulkUploadCompletedSubTab: import("@reduxjs/toolkit").ActionCreatorWithPayload<CompletedSubTab, "expenseAutomationMissingReceiptsView/setBulkUploadCompletedSubTab">, setBulkUploadSortConfig: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
72
60
  sortKey: BulkUploadSortKey;
73
61
  sortOrder: SortOrder;
74
- }, "expenseAutomationMissingReceiptsView/setBulkUploadSortConfig">, clearBulkUpload: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/clearBulkUpload">, searchTransactionsForManualMatch: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[query: string, pageToken?: string | null | undefined], {
62
+ }, "expenseAutomationMissingReceiptsView/setBulkUploadSortConfig">, clearBulkUpload: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/clearBulkUpload">, searchTransactionsForManualMatch: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[query: string], {
75
63
  query: string;
76
- pageToken: string | undefined;
77
- }, "expenseAutomationMissingReceiptsView/searchTransactionsForManualMatch", never, never>, searchTransactionsForManualMatchSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
78
- append: boolean;
79
- nextPageToken: string | null;
80
- results: ManualSearchResult[];
81
- totalCount: number;
82
- }, "expenseAutomationMissingReceiptsView/searchTransactionsForManualMatchSuccess">, searchTransactionsForManualMatchFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
64
+ }, "expenseAutomationMissingReceiptsView/searchTransactionsForManualMatch", never, never>, searchTransactionsForManualMatchSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<ManualSearchResult[], "expenseAutomationMissingReceiptsView/searchTransactionsForManualMatchSuccess">, searchTransactionsForManualMatchFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
83
65
  error: ZeniAPIStatus;
84
- }, "expenseAutomationMissingReceiptsView/searchTransactionsForManualMatchFailure">, clearManualSearchResults: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/clearManualSearchResults">, acknowledgeBulkUploadConfirmMatchComplete: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/acknowledgeBulkUploadConfirmMatchComplete">, fetchCompletedTransactions: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[pageToken?: string | undefined, cacheOverride?: boolean | undefined], {
66
+ }, "expenseAutomationMissingReceiptsView/searchTransactionsForManualMatchFailure">, clearManualSearchResults: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"expenseAutomationMissingReceiptsView/clearManualSearchResults">, fetchCompletedTransactions: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[pageToken?: string | undefined], {
85
67
  pageToken: string | undefined;
86
- cacheOverride: boolean | undefined;
87
68
  }, "expenseAutomationMissingReceiptsView/fetchCompletedTransactions", never, never>, fetchCompletedTransactionsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
88
69
  isInitialLoad: boolean;
89
70
  nextPageToken: string | null;
@@ -1,14 +1,11 @@
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.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.storeBatchDetails = exports.fetchBulkUploadBatchDetailsFailure = exports.fetchBulkUploadBatchDetailsSuccess = exports.fetchBulkUploadBatchDetails = exports.pusherBatchStatusUpdate = exports.updateBulkUploadBatchStatus = 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 = void 0;
5
5
  const toolkit_1 = require("@reduxjs/toolkit");
6
6
  const timePeriod_1 = require("../../../commonStateTypes/timePeriod");
7
- const getCompletedTransactionsCacheKey = (periodId, sortKey, sortOrder, subTab) => `completed-${subTab}-${sortKey}-${sortOrder === 'ascending' ? 'asc' : 'desc'}-${periodId}`;
8
- exports.getCompletedTransactionsCacheKey = getCompletedTransactionsCacheKey;
9
7
  exports.initialBulkUploadState = {
10
8
  batchDetailsById: {},
11
- batchDetailsPaginationState: { fetchState: 'Not-Started', error: undefined },
12
9
  batchListByPeriod: {},
13
10
  batchListFetchState: { fetchState: 'Not-Started', error: undefined },
14
11
  batchStatusById: {},
@@ -17,16 +14,10 @@ exports.initialBulkUploadState = {
17
14
  confirmMatchStatus: { fetchState: 'Not-Started', error: undefined },
18
15
  currentBatchId: undefined,
19
16
  currentResultsTab: 'unmatched',
20
- failedBatchDetailIds: [],
21
- manualSearchUiResetKey: 0,
22
17
  manualSearch: {
23
18
  fetchState: { fetchState: 'Not-Started', error: undefined },
24
- isLoadingMore: false,
25
- nextPageToken: null,
26
- pageSize: 25,
27
19
  results: [],
28
20
  searchQuery: '',
29
- totalCount: 0,
30
21
  },
31
22
  phase: 'idle',
32
23
  sortKey: 'date',
@@ -36,7 +27,6 @@ exports.initialBulkUploadState = {
36
27
  };
37
28
  exports.initialState = {
38
29
  bulkUpload: exports.initialBulkUploadState,
39
- pendingMissingReceiptsTabNavigation: null,
40
30
  uploadReceiptStatusById: {},
41
31
  refreshStatus: {
42
32
  fetchState: 'Not-Started',
@@ -189,25 +179,13 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
189
179
  };
190
180
  draft.bulkUpload.phase = 'idle';
191
181
  },
192
- pusherBatchStatusUpdate(draft, action) {
182
+ updateBulkUploadBatchStatus(draft, action) {
193
183
  const batchStatus = action.payload;
194
184
  draft.bulkUpload.batchStatusById[batchStatus.batchId] = batchStatus;
195
- /**
196
- * Auto-matching banner (`phase === 'matching'`) must clear when the server reports this
197
- * upload batch is done — otherwise the Missing tab keeps MatchingProgressBanner until
198
- * batch-details APIs run; EmailUploadBanner should show again for the next upload.
199
- */
200
- if (batchStatus.status === 'completed' &&
201
- draft.bulkUpload.phase === 'matching' &&
202
- draft.bulkUpload.currentBatchId === batchStatus.batchId) {
203
- draft.bulkUpload.phase = 'completed';
204
- }
205
185
  },
206
- requestMissingReceiptsTabNavigation(draft, action) {
207
- draft.pendingMissingReceiptsTabNavigation = action.payload.tab;
208
- },
209
- clearMissingReceiptsTabNavigation(draft) {
210
- draft.pendingMissingReceiptsTabNavigation = null;
186
+ pusherBatchStatusUpdate(draft, action) {
187
+ const batchStatus = action.payload;
188
+ draft.bulkUpload.batchStatusById[batchStatus.batchId] = batchStatus;
211
189
  },
212
190
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
213
191
  fetchBulkUploadBatchDetails(_draft) {
@@ -225,86 +203,17 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
225
203
  storeBatchDetails(draft, action) {
226
204
  const details = action.payload;
227
205
  draft.bulkUpload.batchDetailsById[details.batchId] = details;
228
- /**
229
- * Multi-batch fetch paths use `storeBatchDetails` (not `fetchBulkUploadBatchDetailsSuccess`).
230
- * Without this, `phase` stays `matching` after upload forever and the Unmatched tab keeps
231
- * showing the skeleton (`bulkUploadPhase === 'matching'` in web-components).
232
- */
233
- if (draft.bulkUpload.phase === 'matching' &&
234
- draft.bulkUpload.currentBatchId === details.batchId) {
235
- draft.bulkUpload.phase = 'completed';
236
- }
237
- },
238
- batchDetailFetchFailed(draft, action) {
239
- const { batchId } = action.payload;
240
- if (!draft.bulkUpload.failedBatchDetailIds.includes(batchId)) {
241
- draft.bulkUpload.failedBatchDetailIds.push(batchId);
242
- }
243
- if (draft.bulkUpload.phase === 'matching' &&
244
- draft.bulkUpload.currentBatchId === batchId) {
245
- draft.bulkUpload.phase = 'completed';
246
- }
247
- },
248
- setInitialBatchDetailsLoading(draft) {
249
- draft.bulkUpload.batchDetailsPaginationState = {
250
- fetchState: 'In-Progress',
251
- error: undefined,
252
- };
253
- },
254
- fetchMoreBatchDetails(_draft) {
255
- _draft.bulkUpload.batchDetailsPaginationState = {
256
- fetchState: 'In-Progress',
257
- error: undefined,
258
- };
259
- },
260
- fetchMoreBatchDetailsComplete(draft) {
261
- draft.bulkUpload.batchDetailsPaginationState = {
262
- fetchState: 'Completed',
263
- error: undefined,
264
- };
265
- const currentId = draft.bulkUpload.currentBatchId;
266
- const currentDetails = currentId != null
267
- ? draft.bulkUpload.batchDetailsById[currentId]
268
- : undefined;
269
- if (draft.bulkUpload.phase === 'matching' &&
270
- currentId != null &&
271
- currentDetails?.status === 'completed') {
272
- draft.bulkUpload.phase = 'completed';
273
- }
274
- },
275
- fetchMoreBatchDetailsFailure(draft, action) {
276
- draft.bulkUpload.batchDetailsPaginationState = {
277
- fetchState: 'Error',
278
- error: action.payload.error,
279
- };
280
206
  },
281
207
  fetchBulkUploadBatches: {
282
- reducer(draft, action) {
283
- if (action.payload.invalidateBatchDetailsCache === true) {
284
- draft.bulkUpload.batchDetailsById = {};
285
- draft.bulkUpload.failedBatchDetailIds = [];
286
- }
208
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
209
+ reducer(draft, _action) {
287
210
  draft.bulkUpload.batchListFetchState = {
288
211
  fetchState: 'In-Progress',
289
212
  error: undefined,
290
213
  };
291
214
  },
292
- prepare(input) {
293
- if (input === true || input === false) {
294
- return {
295
- payload: {
296
- cacheOverride: input === true,
297
- invalidateBatchDetailsCache: false,
298
- },
299
- };
300
- }
301
- const o = input ?? {};
302
- return {
303
- payload: {
304
- cacheOverride: o.cacheOverride === true,
305
- invalidateBatchDetailsCache: o.invalidateBatchDetailsCache === true,
306
- },
307
- };
215
+ prepare(cacheOverride = false) {
216
+ return { payload: { cacheOverride } };
308
217
  },
309
218
  },
310
219
  fetchBulkUploadBatchesSuccess(draft, action) {
@@ -314,20 +223,6 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
314
223
  fetchState: 'Completed',
315
224
  error: undefined,
316
225
  };
317
- /**
318
- * When the multi-batch-details epic has nothing to fetch (e.g. list rows not `completed`
319
- * yet, or details already present), `phase` can stay `matching` even though we already
320
- * have completed details for `currentBatchId` (from polling / Pusher). Sync so the UI can
321
- * dismiss the Unmatched skeleton.
322
- */
323
- const currentId = draft.bulkUpload.currentBatchId;
324
- if (draft.bulkUpload.phase === 'matching' &&
325
- currentId != null) {
326
- const existing = draft.bulkUpload.batchDetailsById[currentId];
327
- if (existing?.status === 'completed') {
328
- draft.bulkUpload.phase = 'completed';
329
- }
330
- }
331
226
  },
332
227
  fetchBulkUploadBatchesFailure(draft, action) {
333
228
  draft.bulkUpload.batchListFetchState = {
@@ -370,8 +265,6 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
370
265
  }
371
266
  }
372
267
  }
373
- draft.bulkUpload.manualSearch = exports.initialBulkUploadState.manualSearch;
374
- draft.bulkUpload.manualSearchUiResetKey += 1;
375
268
  },
376
269
  confirmBulkUploadMatchFailure(draft, action) {
377
270
  draft.bulkUpload.confirmMatchStatus = {
@@ -384,6 +277,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
384
277
  },
385
278
  setBulkUploadCompletedSubTab(draft, action) {
386
279
  draft.bulkUpload.completedSubTab = action.payload;
280
+ draft.bulkUpload.completedTransactionsByPeriod = {};
387
281
  },
388
282
  setBulkUploadSortConfig(draft, action) {
389
283
  draft.bulkUpload.sortKey = action.payload.sortKey;
@@ -391,51 +285,28 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
391
285
  },
392
286
  clearBulkUpload(draft) {
393
287
  Object.assign(draft.bulkUpload, exports.initialBulkUploadState);
394
- draft.pendingMissingReceiptsTabNavigation = null;
395
288
  },
396
289
  searchTransactionsForManualMatch: {
397
290
  reducer(draft, action) {
398
- const { query, pageToken } = action.payload;
399
- const isLoadMore = pageToken != null;
400
- draft.bulkUpload.manualSearch.searchQuery = query;
401
- if (isLoadMore) {
402
- draft.bulkUpload.manualSearch.isLoadingMore = true;
403
- }
404
- else {
405
- draft.bulkUpload.manualSearch.isLoadingMore = false;
406
- draft.bulkUpload.manualSearch.results = [];
407
- draft.bulkUpload.manualSearch.nextPageToken = null;
408
- draft.bulkUpload.manualSearch.totalCount = 0;
409
- draft.bulkUpload.manualSearch.fetchState = {
410
- fetchState: 'In-Progress',
411
- error: undefined,
412
- };
413
- }
291
+ draft.bulkUpload.manualSearch.searchQuery = action.payload.query;
292
+ draft.bulkUpload.manualSearch.fetchState = {
293
+ fetchState: 'In-Progress',
294
+ error: undefined,
295
+ };
296
+ draft.bulkUpload.manualSearch.results = [];
414
297
  },
415
- prepare(query, pageToken) {
416
- return { payload: { query, pageToken: pageToken ?? undefined } };
298
+ prepare(query) {
299
+ return { payload: { query } };
417
300
  },
418
301
  },
419
302
  searchTransactionsForManualMatchSuccess(draft, action) {
420
- const { append, nextPageToken, results, totalCount } = action.payload;
421
- if (append) {
422
- const merged = [...draft.bulkUpload.manualSearch.results, ...results];
423
- const byId = new Map(merged.map((r) => [r.transactionId, r]));
424
- draft.bulkUpload.manualSearch.results = Array.from(byId.values());
425
- }
426
- else {
427
- draft.bulkUpload.manualSearch.results = results;
428
- }
429
- draft.bulkUpload.manualSearch.nextPageToken = nextPageToken;
430
- draft.bulkUpload.manualSearch.totalCount = totalCount;
431
- draft.bulkUpload.manualSearch.isLoadingMore = false;
303
+ draft.bulkUpload.manualSearch.results = action.payload;
432
304
  draft.bulkUpload.manualSearch.fetchState = {
433
305
  fetchState: 'Completed',
434
306
  error: undefined,
435
307
  };
436
308
  },
437
309
  searchTransactionsForManualMatchFailure(draft, action) {
438
- draft.bulkUpload.manualSearch.isLoadingMore = false;
439
310
  draft.bulkUpload.manualSearch.fetchState = {
440
311
  fetchState: 'Error',
441
312
  error: action.payload.error,
@@ -443,13 +314,6 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
443
314
  },
444
315
  clearManualSearchResults(draft) {
445
316
  draft.bulkUpload.manualSearch = exports.initialBulkUploadState.manualSearch;
446
- draft.bulkUpload.manualSearchUiResetKey += 1;
447
- },
448
- acknowledgeBulkUploadConfirmMatchComplete(draft) {
449
- draft.bulkUpload.confirmMatchStatus = {
450
- fetchState: 'Not-Started',
451
- error: undefined,
452
- };
453
317
  },
454
318
  // -- Completed Transactions Actions --
455
319
  fetchCompletedTransactions: {
@@ -468,16 +332,15 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
468
332
  }
469
333
  }
470
334
  },
471
- prepare(pageToken, cacheOverride) {
472
- return { payload: { pageToken, cacheOverride } };
335
+ prepare(pageToken) {
336
+ return { payload: { pageToken } };
473
337
  },
474
338
  },
475
339
  fetchCompletedTransactionsSuccess(draft, action) {
476
340
  const { transactionIds, nextPageToken, totalCount, selectedPeriod, isInitialLoad } = action.payload;
477
341
  const periodId = (0, timePeriod_1.toMonthYearPeriodId)(selectedPeriod);
478
- const cacheKey = (0, exports.getCompletedTransactionsCacheKey)(periodId, draft.bulkUpload.sortKey, draft.bulkUpload.sortOrder, draft.bulkUpload.completedSubTab);
479
342
  if (isInitialLoad) {
480
- draft.bulkUpload.completedTransactionsByPeriod[cacheKey] = {
343
+ draft.bulkUpload.completedTransactionsByPeriod[periodId] = {
481
344
  transactionIds,
482
345
  nextPageToken,
483
346
  totalCount,
@@ -485,7 +348,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
485
348
  };
486
349
  }
487
350
  else {
488
- const existing = draft.bulkUpload.completedTransactionsByPeriod[cacheKey];
351
+ const existing = draft.bulkUpload.completedTransactionsByPeriod[periodId];
489
352
  if (existing != null) {
490
353
  existing.transactionIds.push(...transactionIds);
491
354
  existing.nextPageToken = nextPageToken;
@@ -493,7 +356,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
493
356
  existing.fetchState = { fetchState: 'Completed', error: undefined };
494
357
  }
495
358
  else {
496
- draft.bulkUpload.completedTransactionsByPeriod[cacheKey] = {
359
+ draft.bulkUpload.completedTransactionsByPeriod[periodId] = {
497
360
  transactionIds,
498
361
  nextPageToken,
499
362
  totalCount,
@@ -504,8 +367,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
504
367
  },
505
368
  fetchCompletedTransactionsFailure(draft, action) {
506
369
  const periodId = (0, timePeriod_1.toMonthYearPeriodId)(action.payload.selectedPeriod);
507
- const cacheKey = (0, exports.getCompletedTransactionsCacheKey)(periodId, draft.bulkUpload.sortKey, draft.bulkUpload.sortOrder, draft.bulkUpload.completedSubTab);
508
- const existing = draft.bulkUpload.completedTransactionsByPeriod[cacheKey];
370
+ const existing = draft.bulkUpload.completedTransactionsByPeriod[periodId];
509
371
  if (existing != null) {
510
372
  existing.fetchState = {
511
373
  fetchState: 'Error',
@@ -513,7 +375,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
513
375
  };
514
376
  }
515
377
  else {
516
- draft.bulkUpload.completedTransactionsByPeriod[cacheKey] = {
378
+ draft.bulkUpload.completedTransactionsByPeriod[periodId] = {
517
379
  fetchState: { fetchState: 'Error', error: action.payload.error },
518
380
  nextPageToken: null,
519
381
  totalCount: 0,
@@ -525,7 +387,7 @@ const expenseAutomationMissingReceiptsView = (0, toolkit_1.createSlice)({
525
387
  });
526
388
  _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,
527
389
  // Bulk Upload
528
- 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,
390
+ exports.bulkUploadReceipts = _a.bulkUploadReceipts, exports.updateBulkUploadProgress = _a.updateBulkUploadProgress, exports.bulkUploadReceiptsSuccess = _a.bulkUploadReceiptsSuccess, exports.bulkUploadReceiptsFailure = _a.bulkUploadReceiptsFailure, exports.updateBulkUploadBatchStatus = _a.updateBulkUploadBatchStatus, exports.pusherBatchStatusUpdate = _a.pusherBatchStatusUpdate, exports.fetchBulkUploadBatchDetails = _a.fetchBulkUploadBatchDetails, exports.fetchBulkUploadBatchDetailsSuccess = _a.fetchBulkUploadBatchDetailsSuccess, exports.fetchBulkUploadBatchDetailsFailure = _a.fetchBulkUploadBatchDetailsFailure, exports.storeBatchDetails = _a.storeBatchDetails, 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,
529
391
  // Completed Transactions
530
392
  exports.fetchCompletedTransactions = _a.fetchCompletedTransactions, exports.fetchCompletedTransactionsSuccess = _a.fetchCompletedTransactionsSuccess, exports.fetchCompletedTransactionsFailure = _a.fetchCompletedTransactionsFailure;
531
393
  exports.default = expenseAutomationMissingReceiptsView.reducer;
@@ -15,8 +15,6 @@ export interface ResolvedCandidate {
15
15
  }
16
16
  export interface ResolvedBatchFile {
17
17
  attachmentId: ID;
18
- batchId: ID;
19
- fileDownloadUrl: string | null;
20
18
  fileId: ID;
21
19
  filename: string;
22
20
  filePreviewUrl: string | null;
@@ -27,7 +25,6 @@ export interface ResolvedBatchFile {
27
25
  }
28
26
  export interface BulkUploadSelectorData {
29
27
  batchDetails: ResolvedBatchDetails | undefined;
30
- batchDetailsPaginationState: FetchStateAndError;
31
28
  batchList: BatchListItem[];
32
29
  batchListFetchState: FetchStateAndError;
33
30
  batchStatus: BatchStatus | undefined;
@@ -35,10 +32,7 @@ export interface BulkUploadSelectorData {
35
32
  completedTransactions: CompletedTransactionsSelectorData;
36
33
  confirmMatchStatus: FetchStateAndError;
37
34
  currentResultsTab: BulkUploadResultsTab;
38
- hasMoreBatchDetails: boolean;
39
35
  manualSearch: ManualSearchState;
40
- /** Bumps when manual search state is cleared — remount manual search inputs. */
41
- manualSearchUiResetKey: number;
42
36
  matchedFiles: ResolvedBatchFile[];
43
37
  pastBatches: BatchListItem[];
44
38
  pastUnmatchedFiles: ResolvedBatchFile[];
@@ -70,8 +64,6 @@ export interface ResolvedBatchDetails {
70
64
  export interface ExpenseAutomationMissingReceiptsViewSelector extends SelectorView {
71
65
  bulkUpload: BulkUploadSelectorData;
72
66
  completionStatus: CompletionStatusType;
73
- /** When set, UI should switch bulk-upload sub-tab once (e.g. Unmatched on batch completion). */
74
- pendingMissingReceiptsTabNavigation: BulkUploadResultsTab | null;
75
67
  refreshStatus: FetchStateAndError;
76
68
  transactions: SupportedTransaction[];
77
69
  uiState: MissingReceiptsViewUIState;