UploadField

import { UploadField } from '@megafon/ui-core';

Компонент для выбора файлов. Пользователь может перетащить в него файлы или загрузить по кнопке.

<UploadField
      required
      onChange={handleChange}
      description="Дополнительная информация"
  />
  <UploadField
      disabled
      onChange={handleChange}
      description="Дополнительная информация"
  />

UploadFileItem

import { UploadFileItem } from '@megafon/ui-core';

Компонент используется для отображения загружаемого файла.

Базовое использование

<UploadFileItem
      fileName='Файл 1.pdf'
      fileSize={2621440}
      loadingProgress={5}
  />
  <UploadFileItem
      fileName='Файл 1.xls'
      fileSize={2621440}
      loadingProgress={20}
  />
  <UploadFileItem
      fileName='Файл 1.doc'
      fileSize={2621440}
      loadingProgress={40}
  />
  <UploadFileItem
      fileName='Файл 1.ppt'
      fileSize={2621440}
      loadingProgress={60}
  />
  <UploadFileItem
      fileName='Файл 1.jpg'
      fileSize={2621440}
      loadingProgress={80}
  />
  <UploadFileItem
      fileName='Файл 1.xxx'
      fileSize={2621440}
      loadingProgress={100}
  />

Состояние ошибки

<UploadFileItem
      fileName='Файл 1.fig'
      fileSize={2621440}
      errorText="Неправильный формат файла"
  />

Состояние проверки файла

<UploadFileItem
      fileName='Файл 1.doc'
      fileSize={2621440}
      isChecking
  />

UploadFormDemo

import { Notification, UploadField, UploadFileItem } from '@megafon/ui-core';

Пример формы с использованием компонентов UploadField, UploadFileItem и Notification.
Обработка загруженных файлов должна быть реализована в компоненте-обертке.

<UploadFormDemo
      maxFiles={2}
      maxFileSizeMb={1}
      allowedExtensions={['doc', 'pdf']}
  />
Код UploadFormDemo
import React from 'react';
import { Notification, UploadField, UploadFileItem } from '@megafon/ui-core';
import AttentionIcon from '@megafon/ui-icons/system-24-attention_invert_24.svg';
const filesMock = [fileMockPdf, fileMockDoc, fileMockJpeg];
type PropsType = {
maxFiles?: number;
maxFileSizeMb?: number;
allowedExtensions?: string[];
};
type FormErrorsType = { [param: string]: string[] };
const generateUniqueID = (file: File) => `${file.name}-${file.lastModified}-${file.size}`;
const getExtension = (fileName: string) => fileName.toLowerCase().split('.').pop();
const megabytesToBytes = (megabytes: number) => megabytes * 1024 * 1024;
const UploadFormDemo: React.FC<PropsType> = ({ maxFiles, maxFileSizeMb, allowedExtensions = [] }) => {
const [attachedFiles, setAttachedFiles] = React.useState<File[]>(filesMock);
const [validationErrors, setValidationErrors] = React.useState<FormErrorsType>({});
const [warningText, setWarningText] = React.useState('');
const validateFiles = React.useCallback(
(files: File[]): { warning: string; errors: FormErrorsType } => {
let warning = '';
const errors: FormErrorsType = {};
if (maxFiles && files.length > maxFiles) {
warning = `Максимальное количество файлов: ${maxFiles}`;
}
files.forEach(file => {
const fileExtension = getExtension(file.name);
const fileSize = file.size;
const fileErrors: string[] = [];
if (allowedExtensions.length > 0 && fileExtension && !allowedExtensions.includes(fileExtension)) {
fileErrors.push('Неправильный формат файла');
}
if (maxFileSizeMb && fileSize > megabytesToBytes(maxFileSizeMb)) {
fileErrors.push(`Размер загружаемого файла не должен превышать ${maxFileSizeMb} Мб`);
}
if (fileErrors.length > 0) {
errors[generateUniqueID(file)] = fileErrors;
}
});
return {
warning,
errors,
};
},
[maxFiles, allowedExtensions, maxFileSizeMb],
);
const handleChange = (uploadFiles: File[]) => {
const files = [...attachedFiles, ...uploadFiles];
setAttachedFiles(files);
};
const handleFileDelete = (index: number) => () => {
const filesCopy = [...attachedFiles];
filesCopy.splice(index, 1);
setAttachedFiles(filesCopy);
};
const hideWarning = () => {
setWarningText('');
};
React.useEffect(() => {
const { warning, errors } = validateFiles(attachedFiles);
setValidationErrors(errors);
setWarningText(warning);
}, [validateFiles, attachedFiles]);
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', maxWidth: '455px' }}>
<UploadField
onChange={handleChange}
description={`Максимум ${maxFiles} файла не более ${maxFileSizeMb} MB каждый`}
disabled={maxFiles ? attachedFiles.length >= maxFiles : false}
/>
{attachedFiles.map((file, index) => {
const id = generateUniqueID(file);
return (
<UploadFileItem
key={id}
fileName={file.name}
fileSize={file.size}
loadingProgress={validationErrors[id] ? 0 : 100}
onDelete={handleFileDelete(index)}
errorText={validationErrors[id] ? validationErrors[id].join(', ') : undefined}
/>
);
})}
{!!warningText && (
<Notification
type="warning"
title={warningText}
hasCloseButton
icon={<AttentionIcon />}
onClose={hideWarning}
/>
)}
</div>
);
};