frontPanel/src/pages/startPage/dropZone.tsx

157 lines
4.7 KiB
TypeScript
Raw Normal View History

2023-11-23 18:52:15 +00:00
import UploadIcon from "@icons/UploadIcon";
2023-12-03 17:23:28 +00:00
import DeleteIcon from '@mui/icons-material/Delete';
2023-11-01 13:31:15 +00:00
import {
2023-11-14 13:13:10 +00:00
Box,
ButtonBase,
2023-12-03 17:23:28 +00:00
IconButton,
2023-11-14 13:13:10 +00:00
SxProps,
Theme,
2023-11-23 18:52:15 +00:00
Typography,
useTheme,
2023-11-01 13:31:15 +00:00
} from "@mui/material";
2023-11-14 13:13:10 +00:00
import { useCurrentQuiz } from "@root/quizes/hooks";
2023-11-23 18:52:15 +00:00
import { enqueueSnackbar } from "notistack";
import { useState } from "react";
2023-11-14 13:13:10 +00:00
2023-11-01 13:31:15 +00:00
interface Props {
2023-11-14 13:13:10 +00:00
text?: string;
sx?: SxProps<Theme>;
heightImg: string;
widthImg?: string;
2023-12-03 17:23:28 +00:00
onFileChange?: (file: File) => void;
onDeleteClick?: () => void;
2023-12-01 18:05:59 +00:00
imageUrl: string | null;
}
//Научи функцию принимать данные для валидации
2023-12-03 17:23:28 +00:00
export const DropZone = ({ text, sx, heightImg, widthImg, onFileChange, onDeleteClick, imageUrl }: Props) => {
2023-11-14 13:13:10 +00:00
const theme = useTheme();
2023-11-27 23:07:24 +00:00
const quiz = useCurrentQuiz();
2023-11-14 13:13:10 +00:00
const [ready, setReady] = useState(false);
if (!quiz) return null; // TODO throw and catch with error boundary
2023-12-01 18:05:59 +00:00
const imgHC = async (imgInp: HTMLInputElement) => {
if (!quiz) return;
2023-11-14 13:13:10 +00:00
const file = imgInp.files?.[0];
2023-12-01 18:05:59 +00:00
if (!file) return;
if (file.size > 5 * 2 ** 20) return enqueueSnackbar("Размер картинки слишком велик");
2023-12-03 17:23:28 +00:00
onFileChange?.(file);
2023-11-14 13:13:10 +00:00
};
2023-11-14 13:13:10 +00:00
const dragenterHC = () => {
setReady(true);
};
2023-11-14 13:13:10 +00:00
const dragexitHC = () => {
setReady(false);
};
2023-11-14 13:13:10 +00:00
const dropHC = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
setReady(false);
2023-11-14 13:13:10 +00:00
const file = event.dataTransfer.files[0];
2023-12-01 18:05:59 +00:00
if (file.size < 5 * 2 ** 20) return enqueueSnackbar("Размер картинки слишком велик");
2023-12-03 17:23:28 +00:00
onFileChange?.(file);
2023-11-14 13:13:10 +00:00
};
2023-11-14 13:13:10 +00:00
const dragOverHC = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
};
2023-12-03 17:23:28 +00:00
return imageUrl ? (
<Box
onDragEnter={dragenterHC}
onDragExit={dragexitHC}
onDrop={dropHC}
onDragOver={dragOverHC}
sx={{
width: "100%",
height: "120px",
position: "relative",
display: "flex",
justifyContent: "center",
alignItems: "center",
backgroundColor: theme.palette.background.default,
border: `1px solid ${ready ? "red" : theme.palette.grey2.main}`,
borderRadius: "8px",
...sx,
}}
>
<img
height={heightImg}
width={widthImg}
src={imageUrl}
style={{
objectFit: "scale-down",
}}
alt="img"
/>
<IconButton
onClick={onDeleteClick}
sx={{
position: "absolute",
right: 0,
top: 0,
color: theme.palette.orange.main,
fontSize: "16px",
lineHeight: "19px",
cursor: "pointer",
}}
>
<DeleteIcon />
</IconButton>
</Box>
) : (
2023-11-14 13:13:10 +00:00
<ButtonBase component="label" sx={{ justifyContent: "flex-start" }}>
<input
onChange={(event) => imgHC(event.target)}
hidden
accept="image/*"
multiple
type="file"
/>
<Box
onDragEnter={dragenterHC}
onDragExit={dragexitHC}
onDrop={dropHC}
onDragOver={dragOverHC}
sx={{
width: "100%",
height: "120px",
position: "relative",
display: "flex",
justifyContent: "center",
alignItems: "center",
backgroundColor: theme.palette.background.default,
border: `1px solid ${ready ? "red" : theme.palette.grey2.main}`,
borderRadius: "8px",
2023-12-01 18:05:59 +00:00
opacity: imageUrl ? "0.5" : 1,
2023-11-14 13:13:10 +00:00
...sx,
}}
>
<UploadIcon />
<Typography
sx={{
position: "absolute",
right: "10px",
bottom: "10px",
color: theme.palette.orange.main,
fontSize: "16px",
lineHeight: "19px",
textDecoration: "underline",
}}
>
{text}
</Typography>
</Box>
</ButtonBase>
);
};