frontAnswerer/src/pages/ViewPublicationPage/questions/File.tsx
2024-01-28 01:44:48 +03:00

332 lines
9.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
Box,
Typography,
ButtonBase,
useTheme,
IconButton, useMediaQuery, Modal,
} from "@mui/material";
import { useQuizViewStore, updateAnswer } from "@stores/quizView/store";
import { UPLOAD_FILE_TYPES_MAP } from "../tools/File";
import UploadIcon from "@icons/UploadIcon";
import CloseBold from "@icons/CloseBold";
import { useState, type ChangeEvent } from "react";
import type { QuizQuestionFile } from "../../../model/questionTypes/file";
import type { DragEvent } from "react";
import type { UploadFileType } from "@model/questionTypes/file";
import { enqueueSnackbar } from "notistack";
import { sendAnswer, sendFile } from "@api/quizRelase";
import { useQuestionsStore } from "@stores/quizData/store"
import Info from "@icons/Info";
type FileProps = {
currentQuestion: QuizQuestionFile;
};
const CurrentModal = ({status}:{status:"error" | "picture" | "video" | "audio" | "document" | ""}) => {
switch (status) {
case 'error':
return (<>
<Typography>Выбран некорректный тип файла</Typography>
</>)
default :
return (<>
<Typography>Допустимые расширения файлов:</Typography>
<Typography>{
//@ts-ignore
ACCEPT_SEND_FILE_TYPES_MAP[status].join(" ")}</Typography>
</>)
}
}
const ACCEPT_SEND_FILE_TYPES_MAP = {
picture: [
".jpeg",
".jpg",
".png",
".ico",
".gif",
".tiff",
".webp",
".eps",
".svg"
],
video: [
".mp4",
".mov",
".wmv",
".avi",
".avchd",
".flv",
".f4v",
".swf",
".mkv",
".webm",
".mpeg-2"
],
audio: [
".aac",
".aiff",
".dsd",
".flac",
".MP3",
".MQA",
".OGG",
".WAV",
".WMA"
],
document: [
".doc",
".docx",
".dotx",
".rtf",
".odt",
".pdf",
".txt",
".xls",
".ppt",
".xlsx",
".pptx",
".pages",
],
}
export const UPLOAD_FILE_DESCRIPTIONS_MAP: Record<
UploadFileType,
{ title: string; description: string }
> = {
picture: {
title: "Добавить изображение",
description: "Принимает изображения",
},
video: {
title: "Добавить видео",
description: "Принимает .mp4 и .mov формат — максимум 100мб",
},
audio: { title: "Добавить аудиофайл", description: "Принимает аудиофайлы" },
document: { title: "Добавить документ", description: "Принимает документы" },
} as const;
export const File = ({ currentQuestion }: FileProps) => {
const theme = useTheme();
const { settings } = useQuestionsStore()
const { answers } = useQuizViewStore();
const [statusModal, setStatusModal] = useState<"error" | "picture" | "video" | "audio" | "document" | "">("")
const answer = answers.find(
({ questionId }) => questionId === currentQuestion.id
)?.answer as string;
const isMobile = useMediaQuery(theme.breakpoints.down(500));
const uploadFile = async ({ target }: ChangeEvent<HTMLInputElement>) => {
const file = target.files?.[0];
if (file) {
//проверяем на соответствие
if (ACCEPT_SEND_FILE_TYPES_MAP[currentQuestion.content.type].find((ednding => (
file.name.endsWith(ednding)
)))) {
//Нужный формат
console.log(file)
try {
const data = await sendFile({
questionId: currentQuestion.id,
body: {
file: file,
name: file.name
},
//@ts-ignore
qid: settings.qid
})
console.log(data)
await sendAnswer({
questionId: currentQuestion.id,
//@ts-ignore
body: `https://storage.yandexcloud.net/squizanswer/${settings.qid}/${currentQuestion.id}/${data.data.fileIDMap[currentQuestion.id]}`,
//@ts-ignore
qid: settings.qid
})
updateAnswer(
currentQuestion.id,
`${file.name}|${URL.createObjectURL(file)}`
);
} catch (e) {
console.log(e)
enqueueSnackbar("ответ не был засчитан")
}
} else {
//неподходящий формат
setStatusModal("error")
}
}
};
return (
<>
<Box>
<Typography variant="h5" color={theme.palette.text.primary}>{currentQuestion.title}</Typography>
<Box
sx={{
display: "flex",
flexDirection: "column",
width: "100%",
marginTop: "20px",
maxWidth: answer?.split("|")[0] ? "640px" : "550px",
}}
>
{answer?.split("|")[0] && (
<Box sx={{ display: "flex", alignItems: "center", gap: "15px" }}>
<Typography color={theme.palette.text.primary}>Вы загрузили:</Typography>
<Box
sx={{
padding: "5px 5px 5px 16px",
backgroundColor: theme.palette.primary.main,
borderRadius: "8px",
color: "#FFFFFF",
display: "flex",
alignItems: "center",
overflow: "hidden",
gap: "15px",
}}
>
<Typography
sx={{
whiteSpace: "nowrap",
textOverflow: "ellipsis",
overflow: "hidden",
}}
>
{answer?.split("|")[0]}</Typography>
<IconButton
sx={{ p: 0 }}
onClick={() => {
updateAnswer(currentQuestion.id, "");
}}
>
<CloseBold />
</IconButton>
</Box>
</Box>
)}
{!answer?.split("|")[0] && (
<Box sx={{
display: "flex",
alignItems: "center"
}}>
<ButtonBase component="label" sx={{ justifyContent: "flex-start" }}>
<input
onChange={uploadFile}
hidden
accept={UPLOAD_FILE_TYPES_MAP[currentQuestion.content.type]}
multiple
type="file"
/>
<Box
onDragOver={(event: DragEvent<HTMLDivElement>) =>
event.preventDefault()
}
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 #9A9AAF`,
// border: `1px solid ${theme.palette.grey2.main}`,
borderRadius: "8px",
}}
>
<UploadIcon />
<Box>
<Typography
sx={{
color: "#9A9AAF",
// color: theme.palette.grey2.main,
fontWeight: 500,
}}
>
{
UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type]
.title
}
</Typography>
<Typography
sx={{
color: "#9A9AAF",
// color: theme.palette.grey2.main,
fontSize: "16px",
lineHeight: "19px",
}}
>
{
UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type]
.description
}
</Typography>
</Box>
</Box>
</ButtonBase>
<Info sx={{ width: "40px", height: "40px" }} onClick={() => setStatusModal(currentQuestion.content.type)} />
</Box>
)}
{answer && currentQuestion.content.type === "picture" && (
<img
src={answer.split("|")[1]}
alt=""
style={{
marginTop: "15px",
maxWidth: "300px",
maxHeight: "300px",
}}
/>
)}
{answer && currentQuestion.content.type === "video" && (
<video
src={answer.split("|")[1]}
style={{
marginTop: "15px",
maxWidth: "300px",
maxHeight: "300px",
objectFit: "cover",
}}
/>
)}
</Box>
</Box>
<Modal
open={Boolean(statusModal)}
onClose={() =>setStatusModal("")}
>
<Box sx={{
position: 'absolute' as 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
borderRadius: 3,
boxShadow: 24,
p: 4,
}}>
<CurrentModal status={statusModal}/>
</Box>
</Modal>
</>
);
};