ожидание загрузки файла

This commit is contained in:
Nastya 2024-02-15 12:13:14 +03:00
parent 051e9ee4ac
commit 8e1ec4b30b
7 changed files with 237 additions and 172 deletions

@ -87,6 +87,7 @@ export function sendAnswer({ questionId, body, qid }: any) {
}, },
]; ];
formData.append("answers", JSON.stringify(answers)); formData.append("answers", JSON.stringify(answers));
console.log("QID", qid)
formData.append("qid", qid); formData.append("qid", qid);
return publicationMakeRequest({ return publicationMakeRequest({
@ -109,6 +110,7 @@ export function sendFile({ questionId, body, qid }: any) {
formData.append("answers", JSON.stringify(answers)); formData.append("answers", JSON.stringify(answers));
formData.append(body.name, body.file); formData.append(body.name, body.file);
console.log("QID", qid)
formData.append("qid", qid); formData.append("qid", qid);
return publicationMakeRequest({ return publicationMakeRequest({

@ -11,6 +11,7 @@ import { sendAnswer } from "@api/quizRelase";
import { quizThemes } from "@utils/themes/Publication/themePublication"; import { quizThemes } from "@utils/themes/Publication/themePublication";
import { useQuizData } from "@contexts/QuizDataContext"; import { useQuizData } from "@contexts/QuizDataContext";
import { useState } from "react";
type DateProps = { type DateProps = {
currentQuestion: QuizQuestionDate; currentQuestion: QuizQuestionDate;
@ -24,10 +25,11 @@ export const Date = ({ currentQuestion }: DateProps) => {
({ questionId }) => questionId === currentQuestion.id ({ questionId }) => questionId === currentQuestion.id
)?.answer as string; )?.answer as string;
const currentAnswer = moment(answer) || moment(); const currentAnswer = moment(answer) || moment();
const [readySend, setReadySend] = useState(true)
return ( return (
<Box> <Box>
<Typography variant="h5" color={theme.palette.text.primary} sx={{wordBreak: "break-word"}}> <Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>
{currentQuestion.title} {currentQuestion.title}
</Typography> </Typography>
<Box <Box
@ -51,25 +53,28 @@ export const Date = ({ currentQuestion }: DateProps) => {
}} }}
value={currentAnswer} value={currentAnswer}
onChange={async (date) => { onChange={async (date) => {
console.log(date); if (readySend) {
if (!date) { setReadySend(false)
return; if (!date) {
} return;
}
try { try {
await sendAnswer({ await sendAnswer({
questionId: currentQuestion.id, questionId: currentQuestion.id,
body: moment(date).format("YYYY.MM.DD"), body: moment(date).format("YYYY.MM.DD"),
qid: quizId, qid: quizId,
}); });
updateAnswer( updateAnswer(
currentQuestion.id, currentQuestion.id,
date, date,
0 0
); );
} catch (e) { } catch (e) {
enqueueSnackbar("ответ не был засчитан"); enqueueSnackbar("ответ не был засчитан");
}
setReadySend(true)
} }
}} }}
slotProps={{ slotProps={{

@ -18,6 +18,7 @@ import { sendAnswer } from "@api/quizRelase";
import { enqueueSnackbar } from "notistack"; import { enqueueSnackbar } from "notistack";
import type { QuizQuestionEmoji } from "../../../model/questionTypes/emoji"; import type { QuizQuestionEmoji } from "../../../model/questionTypes/emoji";
import { useQuizData } from "@contexts/QuizDataContext"; import { useQuizData } from "@contexts/QuizDataContext";
import { useState } from "react";
type EmojiProps = { type EmojiProps = {
currentQuestion: QuizQuestionEmoji; currentQuestion: QuizQuestionEmoji;
@ -25,16 +26,17 @@ type EmojiProps = {
export const Emoji = ({ currentQuestion }: EmojiProps) => { export const Emoji = ({ currentQuestion }: EmojiProps) => {
const theme = useTheme(); const theme = useTheme();
const quizId = useQuizData(); const { quizId } = useQuizData();
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const { answer } = const { answer } =
answers.find( answers.find(
({ questionId }) => questionId === currentQuestion.id ({ questionId }) => questionId === currentQuestion.id
) ?? {}; ) ?? {};
const [readySend, setReadySend] = useState(true)
return ( return (
<Box> <Box>
<Typography variant="h5" color={theme.palette.text.primary} sx={{wordBreak: "break-word"}}>{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
<RadioGroup <RadioGroup
name={currentQuestion.id} name={currentQuestion.id}
value={currentQuestion.content.variants.findIndex( value={currentQuestion.content.variants.findIndex(
@ -114,7 +116,8 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
value={index} value={index}
onClick={async (event) => { onClick={async (event) => {
event.preventDefault(); event.preventDefault();
if (readySend) {
setReadySend(false)
try { try {
await sendAnswer({ await sendAnswer({
@ -149,6 +152,9 @@ export const Emoji = ({ currentQuestion }: EmojiProps) => {
enqueueSnackbar("ответ не был засчитан"); enqueueSnackbar("ответ не был засчитан");
} }
} }
setReadySend(true)
}
}} }}
control={ control={

@ -3,6 +3,7 @@ import {
ButtonBase, ButtonBase,
IconButton, IconButton,
Modal, Modal,
Skeleton,
Typography, Typography,
useTheme useTheme
} from "@mui/material"; } from "@mui/material";
@ -118,73 +119,78 @@ const UPLOAD_FILE_DESCRIPTIONS_MAP: Record<
export const File = ({ currentQuestion }: FileProps) => { export const File = ({ currentQuestion }: FileProps) => {
const theme = useTheme(); const theme = useTheme();
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const quizId = useQuizData(); const { quizId } = useQuizData();
const [statusModal, setStatusModal] = useState<"errorType" | "errorSize" | "picture" | "video" | "audio" | "document" | "">(""); const [statusModal, setStatusModal] = useState<"errorType" | "errorSize" | "picture" | "video" | "audio" | "document" | "">("");
const [readySend, setReadySend] = useState(true)
const answer = answers.find( const answer = answers.find(
({ questionId }) => questionId === currentQuestion.id ({ questionId }) => questionId === currentQuestion.id
)?.answer as string; )?.answer as string;
const isMobile = useRootContainerSize() < 500; const isMobile = useRootContainerSize() < 500;
const uploadFile = async ({ target }: ChangeEvent<HTMLInputElement>) => { const uploadFile = async ({ target }: ChangeEvent<HTMLInputElement>) => {
const file = target.files?.[0]; if (readySend) {
if (file) { setReadySend(false)
if (file.size <= 52428800) { const file = target.files?.[0];
//проверяем на соответствие if (file) {
console.log(file.name.toLowerCase()); if (file.size <= 52428800) {
if (ACCEPT_SEND_FILE_TYPES_MAP[currentQuestion.content.type].find((ednding => { //проверяем на соответствие
console.log(ednding); console.log(file.name.toLowerCase());
console.log(file.name.toLowerCase().endsWith(ednding)); if (ACCEPT_SEND_FILE_TYPES_MAP[currentQuestion.content.type].find((ednding => {
return file.name.toLowerCase().endsWith(ednding); console.log(ednding);
}))) { console.log(file.name.toLowerCase().endsWith(ednding));
return file.name.toLowerCase().endsWith(ednding);
}))) {
//Нужный формат //Нужный формат
console.log(file); console.log(file);
try { try {
const data = await sendFile({ const data = await sendFile({
questionId: currentQuestion.id, questionId: currentQuestion.id,
body: { body: {
file: file, file: file,
name: file.name name: file.name
}, },
qid: quizId, qid: quizId,
}); });
console.log(data); console.log(data);
await sendAnswer({ await sendAnswer({
questionId: currentQuestion.id, questionId: currentQuestion.id,
body: `https://storage.yandexcloud.net/squizanswer/${quizId}/${currentQuestion.id}/${data.data.fileIDMap[currentQuestion.id]}`, body: `https://storage.yandexcloud.net/squizanswer/${quizId}/${currentQuestion.id}/${data.data.fileIDMap[currentQuestion.id]}`,
qid: quizId, qid: quizId,
}); });
updateAnswer( updateAnswer(
currentQuestion.id, currentQuestion.id,
`${file.name}|${URL.createObjectURL(file)}`, `${file.name}|${URL.createObjectURL(file)}`,
0 0
); );
} catch (e) { } catch (e) {
console.log(e); console.log(e);
enqueueSnackbar("ответ не был засчитан"); enqueueSnackbar("ответ не был засчитан");
}
} else {
//неподходящий формат
setStatusModal("errorType");
} }
} else { } else {
//неподходящий формат setStatusModal("errorSize");
setStatusModal("errorType");
} }
} else {
setStatusModal("errorSize");
} }
setReadySend(true)
} }
}; };
return ( return (
<> <>
<Box> <Box>
<Typography variant="h5" color={theme.palette.text.primary} sx={{wordBreak: "break-word"}}>{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
@ -219,8 +225,18 @@ export const File = ({ currentQuestion }: FileProps) => {
{answer?.split("|")[0]}</Typography> {answer?.split("|")[0]}</Typography>
<IconButton <IconButton
sx={{ p: 0 }} sx={{ p: 0 }}
onClick={() => { onClick={async () => {
if (answer.length > 0) {
setReadySend(false)
await sendAnswer({
questionId: currentQuestion.id,
body: "",
qid: quizId,
})
}
console.log(answer)
updateAnswer(currentQuestion.id, "", 0); updateAnswer(currentQuestion.id, "", 0);
setReadySend(true)
}} }}
> >
<CloseBold /> <CloseBold />
@ -234,62 +250,77 @@ export const File = ({ currentQuestion }: FileProps) => {
display: "flex", display: "flex",
alignItems: "center" alignItems: "center"
}}> }}>
<ButtonBase component="label" sx={{ justifyContent: "flex-start", width: "100%" }}> {
<input
onChange={uploadFile} !readySend ? <>
hidden <ButtonBase component="label" sx={{ justifyContent: "flex-start", width: "100%" }}>
accept={ACCEPT_SEND_FILE_TYPES_MAP[currentQuestion.content.type].join(",")} <input
multiple onChange={uploadFile}
type="file" hidden
/> accept={ACCEPT_SEND_FILE_TYPES_MAP[currentQuestion.content.type].join(",")}
<Box multiple
onDragOver={(event: DragEvent<HTMLDivElement>) => type="file"
event.preventDefault() />
} <Box
sx={{ onDragOver={(event: DragEvent<HTMLDivElement>) =>
width: "100%", event.preventDefault()
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={{ sx={{
color: "#9A9AAF", width: "100%",
// color: theme.palette.grey2.main, height: isMobile ? undefined : "120px",
fontWeight: 500, 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 />
UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type] <Box>
.title <Typography
} sx={{
</Typography> color: "#9A9AAF",
<Typography // color: theme.palette.grey2.main,
sx={{ fontWeight: 500,
color: "#9A9AAF", }}
// color: theme.palette.grey2.main, >
fontSize: "16px", {
lineHeight: "19px", UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type]
}} .title
> }
{ </Typography>
UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type] <Typography
.description sx={{
} color: "#9A9AAF",
</Typography> // color: theme.palette.grey2.main,
</Box> fontSize: "16px",
</Box> lineHeight: "19px",
</ButtonBase> }}
>
{
UPLOAD_FILE_DESCRIPTIONS_MAP[currentQuestion.content.type]
.description
}
</Typography>
</Box>
</Box>
</ButtonBase>
</> :
<Skeleton
variant="rounded"
sx={{
width: "100%",
height: "120px",
maxWidth: "560px",
}}
/>
}
<Info sx={{ width: "40px", height: "40px" }} color={theme.palette.primary.main} onClick={() => setStatusModal(currentQuestion.content.type)} /> <Info sx={{ width: "40px", height: "40px" }} color={theme.palette.primary.main} onClick={() => setStatusModal(currentQuestion.content.type)} />
</Box> </Box>
)} )}

@ -22,7 +22,7 @@ type ImagesProps = {
}; };
export const Images = ({ currentQuestion }: ImagesProps) => { export const Images = ({ currentQuestion }: ImagesProps) => {
const quizId =useQuizData(); const { quizId } =useQuizData();
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const theme = useTheme(); const theme = useTheme();
const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer; const answer = answers.find(({ questionId }) => questionId === currentQuestion.id)?.answer;
@ -69,6 +69,8 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
onClick={async (event) => { onClick={async (event) => {
event.preventDefault(); event.preventDefault();
console.log("пытаюсь передать qid")
console.log(quizId)
try { try {
await sendAnswer({ await sendAnswer({
@ -92,6 +94,8 @@ export const Images = ({ currentQuestion }: ImagesProps) => {
deleteAnswer(currentQuestion.id); deleteAnswer(currentQuestion.id);
try { try {
console.log("пытаюсь передать qid")
console.log(quizId)
await sendAnswer({ await sendAnswer({
questionId: currentQuestion.id, questionId: currentQuestion.id,
body: "", body: "",

@ -57,7 +57,7 @@ const buttonRatingForm = [
]; ];
export const Rating = ({ currentQuestion }: RatingProps) => { export const Rating = ({ currentQuestion }: RatingProps) => {
const quizId = useQuizData(); const { quizId } = useQuizData();
const { answers } = useQuizViewStore(); const { answers } = useQuizViewStore();
const theme = useTheme(); const theme = useTheme();
const isMobile = useRootContainerSize() < 650; const isMobile = useRootContainerSize() < 650;

@ -10,7 +10,7 @@ import {
Typography, Typography,
useTheme useTheme
} from "@mui/material"; } from "@mui/material";
import { FC, useEffect } from "react"; import { FC, useEffect, useState } from "react";
import { import {
deleteAnswer, deleteAnswer,
@ -44,6 +44,8 @@ type VariantItemProps = {
answer: string | string[] | undefined; answer: string | string[] | undefined;
index: number; index: number;
own?: boolean; own?: boolean;
readySend: boolean;
setReadySend: (a: boolean) => void
}; };
export const Variant = ({ currentQuestion }: VariantProps) => { export const Variant = ({ currentQuestion }: VariantProps) => {
@ -58,6 +60,8 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
(variant) => variant.id === currentQuestion.id (variant) => variant.id === currentQuestion.id
); );
const [readySend, setReadySend] = useState(true)
const Group = currentQuestion.content.multi ? FormGroup : RadioGroup; const Group = currentQuestion.content.multi ? FormGroup : RadioGroup;
useEffect(() => { useEffect(() => {
@ -68,9 +72,11 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
return ( return (
<Box> <Box>
<Typography variant="h5" color={theme.palette.text.primary} sx={{wordBreak: "break-word"}}>{currentQuestion.title}</Typography> <Typography variant="h5" color={theme.palette.text.primary} sx={{ wordBreak: "break-word" }}>{currentQuestion.title}</Typography>
<Box sx={{ display: "flex", gap: "20px", <Box sx={{
flexDirection: isMobile ? "column-reverse" : undefined, alignItems: isMobile ? "center" : undefined}}> display: "flex", gap: "20px",
flexDirection: isMobile ? "column-reverse" : undefined, alignItems: isMobile ? "center" : undefined
}}>
<Group <Group
name={currentQuestion.id.toString()} name={currentQuestion.id.toString()}
value={currentQuestion.content.variants.findIndex( value={currentQuestion.content.variants.findIndex(
@ -102,6 +108,8 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
// @ts-ignore // @ts-ignore
answer={answer} answer={answer}
index={index} index={index}
readySend={readySend}
setReadySend={setReadySend}
/> />
))} ))}
{currentQuestion.content.own && ownVariant && ( {currentQuestion.content.own && ownVariant && (
@ -112,6 +120,8 @@ export const Variant = ({ currentQuestion }: VariantProps) => {
// @ts-ignore // @ts-ignore
answer={answer} answer={answer}
index={currentQuestion.content.variants.length + 2} index={currentQuestion.content.variants.length + 2}
readySend={readySend}
setReadySend={setReadySend}
/> />
)} )}
</Box> </Box>
@ -137,6 +147,8 @@ const VariantItem = ({
answer, answer,
index, index,
own = false, own = false,
readySend,
setReadySend
}: VariantItemProps) => { }: VariantItemProps) => {
const theme = useTheme(); const theme = useTheme();
const { settings, quizId } = useQuizData(); const { settings, quizId } = useQuizData();
@ -185,69 +197,74 @@ const VariantItem = ({
label={own ? <TextField label="Другое..." /> : variant.answer} label={own ? <TextField label="Другое..." /> : variant.answer}
onClick={async (event) => { onClick={async (event) => {
event.preventDefault(); event.preventDefault();
const variantId = currentQuestion.content.variants[index].id; if (readySend) {
console.log(answer); setReadySend(false)
const variantId = currentQuestion.content.variants[index].id;
console.log(answer);
if (currentQuestion.content.multi) { if (currentQuestion.content.multi) {
const currentAnswer = typeof answer !== "string" ? answer || [] : []; const currentAnswer = typeof answer !== "string" ? answer || [] : [];
try {
await sendAnswer({
questionId: currentQuestion.id,
body: currentAnswer.includes(variantId)
? currentAnswer?.filter((item) => item !== variantId)
: [...currentAnswer, variantId],
qid: quizId,
});
updateAnswer(
currentQuestion.id,
currentAnswer.includes(variantId)
? currentAnswer?.filter((item) => item !== variantId)
: [...currentAnswer, variantId],
currentQuestion.content.variants[index].points || 0
);
} catch (e) {
console.log(e);
enqueueSnackbar("ответ не был засчитан");
}
return;
}
try { try {
await sendAnswer({ await sendAnswer({
questionId: currentQuestion.id, questionId: currentQuestion.id,
body: currentAnswer.includes(variantId) body: currentQuestion.content.variants[index].answer,
? currentAnswer?.filter((item) => item !== variantId)
: [...currentAnswer, variantId],
qid: quizId, qid: quizId,
}); });
updateAnswer( updateAnswer(currentQuestion.id, variantId,
currentQuestion.id, answer === variantId ? 0
currentAnswer.includes(variantId) :
? currentAnswer?.filter((item) => item !== variantId) currentQuestion.content.variants[index].points || 0
: [...currentAnswer, variantId],
currentQuestion.content.variants[index].points || 0
); );
} catch (e) {
console.log(e);
enqueueSnackbar("ответ не был засчитан");
}
return;
}
try {
await sendAnswer({
questionId: currentQuestion.id,
body: currentQuestion.content.variants[index].answer,
qid: quizId,
});
updateAnswer(currentQuestion.id, variantId,
answer === variantId ? 0
:
currentQuestion.content.variants[index].points || 0
);
} catch (e) {
console.log(e);
enqueueSnackbar("ответ не был засчитан");
}
if (answer === variantId) {
try {
await sendAnswer({
questionId: currentQuestion.id,
body: "",
qid: quizId,
});
} catch (e) { } catch (e) {
console.log(e); console.log(e);
enqueueSnackbar("ответ не был засчитан"); enqueueSnackbar("ответ не был засчитан");
} }
deleteAnswer(currentQuestion.id);
if (answer === variantId) {
try {
await sendAnswer({
questionId: currentQuestion.id,
body: "",
qid: quizId,
});
} catch (e) {
console.log(e);
enqueueSnackbar("ответ не был засчитан");
}
deleteAnswer(currentQuestion.id);
}
setReadySend(true)
} }
}} }}
/> />
); );