import { FetchStateAndError, FetchedState, ID } from '../../../commonStateTypes/common'; import { SortOrder } from '../../../commonStateTypes/selectorTypes/sortOrderTypes'; import { MonthYearPeriodId } from '../../../commonStateTypes/timePeriod'; import { CompletedSubTab } from './completedSubTab'; export declare const toMissingReceiptsSortKey: (v: string) => "date" | "vendor" | "category" | "class" | "amount"; export type MissingReceiptsSortKey = ReturnType; export interface MissingReceiptsViewUIState { scrollPosition: { scrollTop: number; scrollLeft?: number; } | undefined; searchString: string; sortKey: MissingReceiptsSortKey; sortOrder: SortOrder; } /** * Minimum trimmed query length before manual-match search calls the expense-automation API. * Kept in sync with `ManualSearchInput` in web-components (fires search only when length ≥ this). */ export declare const MIN_MANUAL_TRANSACTION_SEARCH_LENGTH = 2; export declare const toBatchStatusValue: (v: string) => "pending" | "completed" | "processing"; export type BatchStatusValue = ReturnType; /** Canonical batch file statuses (API ingress may use aliases; see `parseBatchFileStatus`). */ export declare const BATCH_FILE_STATUSES: readonly ["exact_match", "possible_matches", "no_match", "failed"]; export declare const toBatchFileStatus: (v: string) => "failed" | "exact_match" | "possible_matches" | "no_match"; export type BatchFileStatus = ReturnType; /** True for files that belong in the Unmatched tab (possible matches or no match). */ export declare function isUnmatchedTabFileStatus(status: BatchFileStatus): boolean; export declare const toBulkUploadPhase: (v: string) => "completed" | "idle" | "uploading" | "matching"; export type BulkUploadPhase = ReturnType; export declare const toBulkUploadResultsTab: (v: string) => "completed" | "unmatched"; export type BulkUploadResultsTab = ReturnType; export declare const toMissingReceiptsTab: (v: string) => "completed" | "unmatched" | "missing"; export type MissingReceiptsTab = ReturnType; export declare const toMatchSource: (v: string) => "manual" | "ai"; export type MatchSource = ReturnType; export declare const toBulkUploadSortKey: (v: string) => "date" | "vendor" | "category" | "class" | "amount"; export type BulkUploadSortKey = ReturnType; export interface CandidateRef { matchScore: number; transactionId: ID; } export interface MatchCandidate { amount: number; currencyCode: string; matchScore: number; transactionDate: string; transactionId: ID; transactionType: string; vendorName: string; vendorLogo?: string; } export interface BatchFile { attachmentId: ID; fileDownloadUrl: string | null; fileId: ID; filename: string; filePreviewUrl: string | null; status: BatchFileStatus; candidates?: CandidateRef[]; matchedTransactionId?: ID; matchSource?: MatchSource; } export interface BatchSummary { failed: number; matched: number; noMatch: number; possibleMatches: number; total: number; } export interface BatchStatus { batchId: ID; progress: { processed: number; total: number; }; status: BatchStatusValue; } export interface BatchDetails { batchId: ID; createdAt: string; files: BatchFile[]; status: BatchStatusValue; summary: BatchSummary; /** Present when batch-details API includes `user_id` (uploader). */ userId?: ID; } export interface BatchListItem { batchId: ID; createdAt: string; failedCount: number; matchedCount: number; noMatchCount: number; possibleMatchesCount: number; status: string; totalFiles: number; userId: ID; } export interface ManualSearchResult { amount: number; currencyCode: string; entityId: string; memo: string; transactionDate: string; transactionId: ID; transactionType: string; vendorName: string; /** Present when API/merged transaction state supplies a logo URL. */ vendorLogo?: string; } export interface ManualSearchState { fetchState: FetchStateAndError; /** True while appending the next page (initial search uses fetchState only). */ isLoadingMore: boolean; nextPageToken: string | null; pageSize: number; results: ManualSearchResult[]; searchQuery: string; totalCount: number; } /** Same union as {@link CompletedSubTab} — used for completed-transactions API `match_type`. */ export type CompletedTransactionsMatchType = CompletedSubTab; export interface CompletedTransactionsState { fetchState: FetchStateAndError; nextPageToken: string | null; totalCount: number; transactionIds: ID[]; } export interface BulkUploadState { batchDetailsById: Record; batchDetailsPaginationState: FetchStateAndError; /** * True while a stale-while-revalidate refresh of `batchDetailsById` is in flight (manual refresh * or scope-change replacement). Existing entries are kept on screen during this window; the UI * can surface a lightweight refresh indicator. Cleared on `fetchMoreBatchDetailsComplete` / * `fetchMoreBatchDetailsFailure`. */ batchDetailsRevalidating: boolean; batchListByPeriod: Record; batchListFetchState: FetchStateAndError; batchStatusById: Record; completedSubTab: CompletedSubTab; completedTransactionsByPeriod: Record; confirmMatchStatus: FetchStateAndError; currentResultsTab: BulkUploadResultsTab; failedBatchDetailIds: ID[]; /** * Set to `true` once the first batch-details page has resolved (success or empty completion). * Drives stale-while-revalidate: the Unmatched skeleton is shown only while this is `false`. * Reset only by `clearBulkUpload` or by an explicit scope-change (period/tenant) clear. */ initialBatchDetailsLoaded: boolean; /** * Last time `GET /1.0/batches/:id` was issued for a given batch via the targeted refresh epic. * Used to throttle Pusher resend storms — repeat completion events for the same batchId within * the dedupe window are dropped. */ lastBatchDetailRefreshAtById: Record; /** * Incremented when manual search Redux state is cleared so Unmatched `ManualSearchInput` * instances remount and drop local query text. */ manualSearch: ManualSearchState; manualSearchUiResetKey: number; phase: BulkUploadPhase; sortKey: BulkUploadSortKey | undefined; sortOrder: SortOrder | undefined; uploadedFileCount: number; uploadProgress: number; uploadStatus: FetchStateAndError; currentBatchId?: ID; } export interface MissingReceiptsViewState extends FetchedState { bulkUpload: BulkUploadState; /** * When set, the app shell should switch the Missing Receipts sub-tab (e.g. to Unmatched) * once, then clear via `clearMissingReceiptsTabNavigation`. */ pendingMissingReceiptsTabNavigation: BulkUploadResultsTab | null; refreshStatus: FetchStateAndError; transactionIdsBySelectedPeriod: Record; uiState: MissingReceiptsViewUIState; uploadReceiptStatusById: Record; }