import { Box, ButtonBase, IconButton, Modal, Skeleton, Typography, useTheme } from "@mui/material"; import { updateAnswer, useQuizViewStore } from "@stores/quizView"; import CloseBold from "@icons/CloseBold"; import UploadIcon from "@icons/UploadIcon"; import { sendAnswer, sendFile } from "@api/quizRelase"; import { useQuizData } from "@contexts/QuizDataContext"; import Info from "@icons/Info"; import { enqueueSnackbar } from "notistack"; import { useState } from "react"; import { useRootContainerSize } from "../../../contexts/RootContainerWidthContext"; import type { QuizQuestionFile } from "../../../model/questionTypes/file"; import { ACCEPT_SEND_FILE_TYPES_MAP, MAX_FILE_SIZE, UPLOAD_FILE_DESCRIPTIONS_MAP } from "../tools/fileUpload"; type ModalWarningType = "errorType" | "errorSize" | "picture" | "video" | "audio" | "document" | null; type FileProps = { currentQuestion: QuizQuestionFile; }; export const File = ({ currentQuestion }: FileProps) => { const theme = useTheme(); const { answers } = useQuizViewStore(); const { quizId } = useQuizData(); const [modalWarningType, setModalWarningType] = useState(null); const [isSending, setIsSending] = useState(false); const [isDropzoneHighlighted, setIsDropzoneHighlighted] = useState(false); const isMobile = useRootContainerSize() < 500; const answer = answers.find( ({ questionId }) => questionId === currentQuestion.id )?.answer as string; const uploadFile = async (file: File | undefined) => { if (isSending) return; if (!file) return; console.log(file.size) console.log(MAX_FILE_SIZE) if (file.size > MAX_FILE_SIZE) return setModalWarningType("errorSize"); const isFileTypeAccepted = ACCEPT_SEND_FILE_TYPES_MAP[currentQuestion.content.type].some( fileType => file.name.toLowerCase().endsWith(fileType) ); if (!isFileTypeAccepted) return setModalWarningType("errorType"); setIsSending(true); try { const data = await sendFile({ questionId: currentQuestion.id, body: { file: file, name: file.name }, qid: quizId, }); console.log(data); await sendAnswer({ questionId: currentQuestion.id, body: `https://storage.yandexcloud.net/squizanswer/${quizId}/${currentQuestion.id}/${data.data.fileIDMap[currentQuestion.id]}`, qid: quizId, }); updateAnswer(currentQuestion.id, `${file.name}|${URL.createObjectURL(file)}`, 0); } catch (e) { console.log(e); enqueueSnackbar("ответ не был засчитан"); } setIsSending(false); }; const onDrop = (event: React.DragEvent) => { event.preventDefault(); setIsDropzoneHighlighted(false); const file = event.dataTransfer.files[0]; uploadFile(file); }; return ( {currentQuestion.title} {answer?.split("|")[0] ? ( Вы загрузили: {answer?.split("|")[0]} { if (answer.length > 0) { setIsSending(true); await sendAnswer({ questionId: currentQuestion.id, body: "", qid: quizId, }); } console.log(answer); updateAnswer(currentQuestion.id, "", 0); setIsSending(false); }} > ) : ( {isSending ? : uploadFile(e.target.files?.[0])} hidden accept={ACCEPT_SEND_FILE_TYPES_MAP[currentQuestion.content.type].join(",")} multiple type="file" /> !answer?.split("|")[0] && setIsDropzoneHighlighted(true)} onDragLeave={() => setIsDropzoneHighlighted(false)} onDragOver={(e) => e.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: theme.palette.background.default, border: `1px solid ${isDropzoneHighlighted ? "red" : "#9A9AAF"}`, borderRadius: "8px", }} > {UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type].title} {UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type].description} } setModalWarningType(currentQuestion.content.type)} /> )} {answer && currentQuestion.content.type === "picture" && ( )} {answer && currentQuestion.content.type === "video" && ( setModalWarningType(null)} > ); }; const CurrentModal = ({ status }: { status: ModalWarningType; }) => { switch (status) { case null: return null; case 'errorType': return Выбран некорректный тип файла; case 'errorSize': return Файл слишком большой. Максимальный размер 50 МБ; default: return ( <> Допустимые расширения файлов: { ACCEPT_SEND_FILE_TYPES_MAP[status].join(" ")} ); } };