import React from 'react'; import axios from 'api/axios'; import { Upload, Icon, Modal, Button, Alert } from 'antd'; import Cropper from 'react-cropper'; import 'cropperjs/dist/cropper.css'; import { UploadFile } from 'antd/lib/upload/interface'; import { User } from 'types'; import { getBase64 } from 'utils/blob'; import UserAvatar from 'components/UserAvatar'; import './AvatarEdit.less'; const FILE_TYPES = ['image/jpeg', 'image/png', 'image/gif']; const FILE_MAX_LOAD_MB = 10; interface OwnProps { user: User; onDelete(): void; onDone(url: string): void; } const initialState = { isUploading: false, showModal: false, newAvatarUrl: '', loadError: '', uploadError: '', }; type State = typeof initialState; type Props = OwnProps; export default class AvatarEdit extends React.PureComponent { state = initialState; cropperRef: React.RefObject; constructor(props: Props) { super(props); this.cropperRef = React.createRef(); } render() { const { newAvatarUrl, showModal, loadError, uploadError, isUploading } = this.state; const { user, user: { avatar }, } = this.props; return ( <> {' '}
{avatar && (
Cancel , , ]} > {uploadError && ( )} ); } private handleClose = () => { this.setState({ isUploading: false, showModal: false, newAvatarUrl: '', uploadError: '', }); }; private handleLoadChange = (info: any) => { if (info.file.status === 'done') { getBase64(info.file.originFileObj, newAvatarUrl => this.setState({ newAvatarUrl, }), ); } }; private beforeLoad = (file: UploadFile) => { this.setState({ loadError: '' }); const isTypeOk = !!FILE_TYPES.find(t => t === file.type); if (!isTypeOk) { this.setState({ loadError: 'File must be a jpg, png or gif' }); } const isSizeOk = file.size / 1024 / 1024 < FILE_MAX_LOAD_MB; if (!isSizeOk) { this.setState({ loadError: `File size must be less than ${FILE_MAX_LOAD_MB}MB`, }); } return isTypeOk && isSizeOk; }; private handleLoad = () => { this.setState({ showModal: true }); return Promise.resolve(); }; private handleUpload = () => { this.cropperRef.current .getCroppedCanvas({ width: 400, height: 400 }) .toBlob((blob: Blob) => { const formData = new FormData(); formData.append('file', blob); this.setState({ isUploading: true }); axios .post('/api/v1/users/avatar', formData, { headers: { 'Content-Type': 'multipart/form-data', }, }) .then(res => { this.props.onDone(res.data.url); this.handleClose(); }) .catch(err => { this.setState({ isUploading: false, uploadError: err.message }); }); }); }; }