import type { HTMLAttributes } from 'react' import React from 'react' import { Button, Icon } from '../..' export enum FileUploadState { Uploading = 'uploading', Processing = 'processing', Completed = 'completed', Error = 'error', } export enum FileUploadErrorType { Unexpected = 'unexpected', Unsupported = 'unsupported', Unreadable = 'unreadable', InvalidStructure = 'invalid-structure', Empty = 'empty', TooLarge = 'too-large', NoProductsFound = 'no-products-found', } export interface FileUploadStatusProps extends HTMLAttributes { /** * ID to find this component in testing tools (e.g.: cypress, testing library, and jest). */ testId?: string /** * The file being uploaded. */ file: File /** * Current upload state. * @default 'uploading' */ state?: FileUploadState /** * Type of error when state is 'error'. */ errorType?: FileUploadErrorType /** * Custom error message. If provided, overrides the default error message for the errorType. */ errorMessage?: string /** * Callback when the remove/cancel button is clicked. */ onRemove?: () => void /** * Callback when the search button is clicked (only shown when state is 'completed'). */ onSearch?: () => void /** * Callback when download template is clicked (only shown when state is 'error'). */ onDownloadTemplate?: () => void /** * Callback when select file is clicked (only shown when state is 'error'). */ onSelectFile?: () => void /** * Aria-label for the remove button (e.g. from CMS). */ removeButtonAriaLabel: string /** * Label for the search button when state is 'completed' (e.g. from CMS). */ searchButtonLabel: string /** * Label for the download template button (e.g. from CMS). */ downloadTemplateButtonLabel: string /** * Label for the select file button (e.g. from CMS). */ selectFileButtonLabel: string /** * Error messages per error type (e.g. from CMS). Required when state is Error to show messages. */ errorMessages: Partial< Record > /** * Status text when state is Uploading (e.g. from CMS). */ uploadingStatusText: string /** * Status text when state is Processing/polling (e.g. from CMS). * @default 'Importing...' */ processingStatusText?: string /** * Status text when state is Completed (e.g. from CMS). May include file size. */ completedStatusText: string /** * Custom file name display (optional). */ fileName?: string } const FileUploadStatus = ({ testId = 'fs-file-upload-status', file, state = FileUploadState.Uploading, errorType, errorMessage, onRemove, onSearch, onDownloadTemplate, onSelectFile, removeButtonAriaLabel, searchButtonLabel, downloadTemplateButtonLabel, selectFileButtonLabel, errorMessages, uploadingStatusText, processingStatusText, completedStatusText, fileName, ...otherProps }: FileUploadStatusProps) => { const getErrorMessage = (): { title: string; description: string } => { if (errorMessage) { return { title: errorMessage, description: '' } } if (errorType && errorMessages?.[errorType]) { return errorMessages[errorType]! } return ( errorMessages?.[FileUploadErrorType.Unexpected] ?? { title: '', description: '', } ) } const getStatusText = (): string => { switch (state) { case FileUploadState.Uploading: return uploadingStatusText case FileUploadState.Processing: return processingStatusText ?? 'Importing...' case FileUploadState.Completed: return completedStatusText default: return '' } } const getIcon = () => { switch (state) { case FileUploadState.Uploading: return ( ) case FileUploadState.Processing: return ( ) case FileUploadState.Completed: return ( ) case FileUploadState.Error: return ( ) default: return null } } return ( {getIcon()} {state === FileUploadState.Error ? ( <> {getErrorMessage().title} {getErrorMessage().description} > ) : ( <> {fileName ?? file.name} {getStatusText()} > )} {onRemove && ( )} {state === FileUploadState.Completed && onSearch && ( {searchButtonLabel} )} {state === FileUploadState.Error && ( {onDownloadTemplate && ( {downloadTemplateButtonLabel} )} {onSelectFile && ( {selectFileButtonLabel} )} )} ) } export default FileUploadStatus
{getErrorMessage().title}
{getErrorMessage().description}
{fileName ?? file.name}
{getStatusText()}