2025-12-24 14:23:22 +00:00

238 lines
5.7 KiB
JavaScript

import React, { useState, useRef } from 'react';
import PropTypes from 'prop-types';
import Button from '@mui/material/Button';
import CloseIcon from '@mui/icons-material/Close';
import SearchIcon from '@mui/icons-material/Search';
import Grid from '@mui/material/Grid';
import Box from '@mui/material/Box';
import Dialog from '@mui/material/Dialog';
import FileUploader from 'components/FormItems/uploaders/UploadService';
import Errors from '../../../components/FormItems/error/errors';
import {makeStyles} from "@mui/styles";
const useStyles = makeStyles({
actionButtonsWrapper: {
position: 'relative',
},
previewContent: {
padding: '0px !important',
},
imageItem: {
'&.MuiGrid-root': {
margin: 10,
boxShadow: '2px 2px 8px 0 rgb(0 0 0 / 40%)',
borderRadius: 10,
},
height: '100px',
},
actionButtons: {
position: 'absolute',
bottom: 5,
right: 4,
},
previewContainer: {
'& button': {
position: 'absolute',
top: 10,
right: 10,
'& svg': {
height: 50,
width: 50,
fill: '#FFF',
stroke: '#909090',
strokeWidth: 0.5,
},
},
},
button: {
padding: '0px !important',
minWidth: '45px !important',
'& svg': {
height: 36,
width: 36,
fill: '#FFF',
stroke: '#909090',
strokeWidth: 0.5,
},
}
});
const ImagesUploader = (props) => {
const classes = useStyles();
const { value, onChange, schema, path, max, readonly, name } = props;
const [loading, setLoading] = useState(false);
const [showPreview, setShowPreview] = useState(false);
const [imageMeta, setImageMeta] = useState({
imageSrc: null,
imageAlt: null,
});
const inputElement = useRef(null);
const valuesArr = () => {
if (!value) {
return [];
}
return Array.isArray(value) ? value : [value];
};
const fileList = () => {
return valuesArr().map((item) => ({
uid: item.id || undefined,
name: item.name,
status: 'done',
url: item.publicUrl,
}));
};
const handleRemove = (id) => {
onChange(valuesArr().filter((item) => item.id !== id));
};
const handleChange = async (event) => {
try {
const files = event.target.files;
if (!files || !files.length) {
return;
}
let file = files[0];
FileUploader.validate(file, schema);
setLoading(true);
file = await FileUploader.upload(path, file, schema);
inputElement.current.value = '';
setLoading(false);
onChange([...valuesArr(), file]);
} catch (error) {
inputElement.current.value = '';
console.log('error', error);
setLoading(false);
Errors.showMessage(error);
}
};
const doPreviewImage = (image) => {
setImageMeta({
imageSrc: image.publicUrl,
imageAlt: image.name,
});
setShowPreview(true);
};
const doCloseImageModal = () => {
setImageMeta({
imageSrc: null,
imageAlt: null,
});
setShowPreview(false);
};
const uploadButton = (
<Box>
<label
htmlFor={"button-file-" + name}
style={{ cursor: 'pointer' }}
>
<input
id={"button-file-" + name}
style={{ display: 'none' }}
disabled={loading || readonly}
accept='image/*'
type='file'
onChange={handleChange}
ref={inputElement}
/>
<Button variant="contained" component="span">
Upload an Image
</Button>{" "}
</label>
</Box>
);
return (
<Box>
{readonly || (max && fileList().length >= max) ? null : uploadButton}
{valuesArr() && valuesArr().length ? (
<Grid container>
{valuesArr().map((item) => {
return (
<Grid
item
className={classes.imageItem}
key={item.id}
>
<img
alt={item.name}
src={item.publicUrl}
style={{
width: '100px',
height: '100px',
objectFit: 'cover',
borderRadius: 10,
}}
/>
<div className={classes.actionButtonsWrapper}>
<div className={classes.actionButtons}>
<Button
classes={{ root: classes.button }}
variant="text"
onClick={() => doPreviewImage(item)}
>
<SearchIcon />
</Button>
{!readonly && (
<Button
classes={{ root: classes.button }}
variant="text"
onClick={() => handleRemove(item.id)}
>
<CloseIcon />
</Button>
)}
</div>
</div>
</Grid>
);
})}
</Grid>
) : null}
<Dialog
open={showPreview}
onClose={doCloseImageModal}
classes={{ root: classes.previewContainer }}
>
<Button
variant="text"
onClick={() => doCloseImageModal()}
>
<CloseIcon />
</Button>
<img src={imageMeta.imageSrc} alt={imageMeta.imageAlt} />
</Dialog>
</Box>
);
};
ImagesUploader.propTypes = {
readonly: PropTypes.bool,
path: PropTypes.string,
max: PropTypes.number,
schema: PropTypes.shape({
image: PropTypes.bool,
size: PropTypes.number,
formats: PropTypes.arrayOf(PropTypes.string),
}),
value: PropTypes.any,
onChange: PropTypes.func,
name: PropTypes.string,
};
export default ImagesUploader;