frontAnswerer/lib/components/ViewPublicationPage/questions/File/UploadFile.tsx

149 lines
4.8 KiB
TypeScript
Raw Normal View History

2024-04-23 14:45:49 +00:00
import { useState } from "react";
import { Box, ButtonBase, Skeleton, Typography, useTheme } from "@mui/material";
import { enqueueSnackbar } from "notistack";
import { sendAnswer, sendFile } from "@api/quizRelase";
import { useQuizSettings } from "@contexts/QuizDataContext";
2024-04-23 14:45:49 +00:00
import { useRootContainerSize } from "@contexts/RootContainerWidthContext";
import { useQuizViewStore } from "@stores/quizView";
import {
ACCEPT_SEND_FILE_TYPES_MAP,
MAX_FILE_SIZE,
UPLOAD_FILE_DESCRIPTIONS_MAP,
} from "@/components/ViewPublicationPage/tools/fileUpload";
import Info from "@icons/Info";
import UploadIcon from "@icons/UploadIcon";
import type { QuizQuestionFile } from "@model/questionTypes/file";
import type { ModalWarningType } from "./index";
type UploadFileProps = {
currentQuestion: QuizQuestionFile;
setModalWarningType: (modalType: ModalWarningType) => void;
isSending: boolean;
setIsSending: (isSending: boolean) => void;
};
2024-05-31 16:41:18 +00:00
export const UploadFile = ({ currentQuestion, setModalWarningType, isSending, setIsSending }: UploadFileProps) => {
const { quizId, preview } = useQuizSettings();
2024-05-31 16:41:18 +00:00
const [isDropzoneHighlighted, setIsDropzoneHighlighted] = useState<boolean>(false);
2024-04-23 14:45:49 +00:00
const theme = useTheme();
const answers = useQuizViewStore((state) => state.answers);
const { updateAnswer } = useQuizViewStore((state) => state);
const isMobile = useRootContainerSize() < 500;
2024-05-31 16:41:18 +00:00
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer as string;
2024-04-23 14:45:49 +00:00
const uploadFile = async (file: File | undefined) => {
if (isSending) return;
if (!file) return;
if (file.size > MAX_FILE_SIZE) return setModalWarningType("errorSize");
2024-05-31 16:41:18 +00:00
const isFileTypeAccepted = ACCEPT_SEND_FILE_TYPES_MAP[currentQuestion.content.type].some((fileType) =>
file.name.toLowerCase().endsWith(fileType)
);
2024-04-23 14:45:49 +00:00
if (!isFileTypeAccepted) return setModalWarningType("errorType");
setIsSending(true);
try {
const data = await sendFile({
questionId: currentQuestion.id,
body: {
file: file,
name: file.name,
preview,
},
qid: quizId,
});
await sendAnswer({
questionId: currentQuestion.id,
2024-06-18 23:40:11 +00:00
body: `${data!.data.fileIDMap[currentQuestion.id]}`,
2024-04-23 14:45:49 +00:00
qid: quizId,
preview,
});
2024-05-31 16:41:18 +00:00
updateAnswer(currentQuestion.id, `${file.name}|${URL.createObjectURL(file)}`, 0);
2024-04-23 14:45:49 +00:00
} catch (error) {
console.error(error);
2025-02-23 21:46:51 +00:00
enqueueSnackbar("the answer was not counted");
2024-04-23 14:45:49 +00:00
}
setIsSending(false);
};
const onDrop = (event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
setIsDropzoneHighlighted(false);
const file = event.dataTransfer.files[0];
uploadFile(file);
};
return (
<Box sx={{ display: "flex", alignItems: "center" }}>
{isSending ? (
2024-07-15 22:06:38 +00:00
<Skeleton
variant="rounded"
sx={{ width: "100%", height: "120px", maxWidth: "560px" }}
/>
2024-04-23 14:45:49 +00:00
) : (
2024-07-15 22:06:38 +00:00
<ButtonBase
component="label"
sx={{ justifyContent: "flex-start", width: "100%" }}
>
2024-04-23 14:45:49 +00:00
<input
onChange={({ target }) => uploadFile(target.files?.[0])}
hidden
2024-05-31 16:41:18 +00:00
accept={ACCEPT_SEND_FILE_TYPES_MAP[currentQuestion.content.type].join(",")}
2024-04-23 14:45:49 +00:00
multiple
type="file"
/>
<Box
2024-05-31 16:41:18 +00:00
onDragEnter={() => !answer?.split("|")[0] && setIsDropzoneHighlighted(true)}
2024-04-23 14:45:49 +00:00
onDragLeave={() => setIsDropzoneHighlighted(false)}
onDragOver={(event) => event.preventDefault()}
onDrop={onDrop}
sx={{
width: "100%",
height: isMobile ? undefined : "120px",
display: "flex",
gap: "50px",
justifyContent: "flex-start",
alignItems: "center",
padding: "33px 44px 33px 55px",
backgroundColor: "#F2F3F7",
border: `1px solid ${isDropzoneHighlighted ? "red" : "#9A9AAF"}`,
borderRadius: "8px",
}}
>
<UploadIcon />
<Box>
<Typography sx={{ color: "#9A9AAF", fontWeight: 500 }}>
2024-05-31 16:41:18 +00:00
{UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type].title}
2024-04-23 14:45:49 +00:00
</Typography>
<Typography
sx={{
color: "#9A9AAF",
fontSize: "16px",
lineHeight: "19px",
}}
>
2024-05-31 16:41:18 +00:00
{UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type].description}
2024-04-23 14:45:49 +00:00
</Typography>
</Box>
</Box>
</ButtonBase>
)}
<Info
sx={{ width: "40px", height: "40px" }}
color={theme.palette.primary.main}
onClick={() => setModalWarningType(currentQuestion.content.type)}
/>
</Box>
);
};