frontPanel/src/ui_kit/MediaSelectionAndDisplay.tsx

296 lines
8.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 { FC, useState } from "react";
import {
Box,
Button,
ButtonBase,
Skeleton,
Tooltip,
Typography,
useTheme,
} from "@mui/material";
import { updateQuestion, uploadQuestionImage } from "@root/questions/actions";
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
import { UploadImageModal } from "@/pages/Questions/UploadImage/UploadImageModal";
import { VideoElement } from "@/pages/startPage/VideoElement";
import { useCurrentQuiz } from "@/stores/quizes/hooks";
import { useDisclosure } from "@/utils/useDisclosure";
import UploadBox from "@ui_kit/UploadBox";
import UploadIcon from "@icons/UploadIcon";
import InfoIcon from "@icons/InfoIcon";
import { CropModalInit } from "./Modal/CropModal";
import { AnyTypedQuizQuestion } from "@frontend/squzanswerer";
import UploadVideoModal from "@/pages/Questions/UploadVideoModal";
interface Iprops {
question: AnyTypedQuizQuestion;
cropAspectRatio: {
width: number;
height: number;
};
}
export const MediaSelectionAndDisplay: FC<Iprops> = ({
question,
cropAspectRatio,
}) => {
const theme = useTheme();
const [isVideoUploadDialogOpen, setIsVideoUploadDialogOpen] = useState<boolean>(false);
const [pictureUploding, setPictureUploading] = useState<boolean>(false);
const [backgroundUploding, setBackgroundUploading] = useState<boolean>(false);
const [openCropModal, setOpenCropModal] = useState(false);
const quizQid = useCurrentQuiz()?.qid;
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] =
useDisclosure();
async function handleImageUpload(file: File) {
setPictureUploading(true);
closeImageUploadModal();
const url = await uploadQuestionImage(
question.id,
quizQid,
file,
(question, url) => {
question.content.back = url;
question.content.originalBack = url;
},
);
setOpenCropModal(true)
setPictureUploading(false);
}
function handleCropModalSaveClick(imageBlob: Blob) {
uploadQuestionImage(question.id, quizQid, imageBlob, (question, url) => {
question.content.back = url;
});
}
async function handleVideoUpload(videoUrl: string) {
setBackgroundUploading(true);
if (videoUrl.startsWith("blob:")) {
const videoBlob = await (await fetch(videoUrl)).blob();
uploadQuestionImage(question.id, quizQid, videoBlob, (question, url) => {
if (!("video" in question.content)) return;
question.content.video = url;
});
} else {
updateQuestion(question.id, (question) => {
if (!("video" in question.content)) return;
question.content.video = videoUrl;
});
}
setBackgroundUploading(false);
}
return (
<Box
sx={{
mt: "20px",
display: "flex",
gap: "10px",
flexDirection: "column",
}}
>
<Box
sx={{
display: "flex",
}}
>
<Button
sx={{
color: question.content.useImage ? "#7E2AEA" : "#9A9AAF",
fontSize: "16px",
"&:hover": {
background: "none",
},
}}
variant="text"
onClick={() =>
updateQuestion(
question.id,
(question) => (question.content.useImage = true),
)
}
>
Изображение
</Button>
<Button
sx={{
color: question.content.useImage ? "#9A9AAF" : "#7E2AEA",
fontSize: "16px",
"&:hover": {
background: "none",
},
}}
variant="text"
onClick={() =>
updateQuestion(question.id, (question) => {
if (!("useImage" in question.content)) return;
question.content.useImage = false;
})
}
>
Видео
</Button>
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
}}
>
<UploadImageModal
isOpen={isImageUploadOpen}
onClose={closeImageUploadModal}
handleImageChange={handleImageUpload}
/>
<UploadVideoModal
open={isVideoUploadDialogOpen}
onClose={() => setIsVideoUploadDialogOpen(false)}
onUpload={handleVideoUpload}
video={question.content.video}
/>
<CropModalInit
originalImageUrl={question.content.originalBack}
editedUrlImagesList={question.content?.editedUrlImagesList}
questionId={question.id}
questionType={question.type}
quizId={quizQid}
open={openCropModal}
selfClose={() => setOpenCropModal(false)}
setPictureUploading={setPictureUploading}
/>
</Box>
{question.content.useImage && (
<Box
sx={{
cursor: "pointer",
display: "flex",
alignItems: "center",
gap: "20px",
mb: "30px",
}}
>
<AddOrEditImageButton
imageSrc={question.content.back}
uploading={pictureUploding}
onImageClick={() => {
if (question.content.back) {
setOpenCropModal(true)
} else {
openImageUploadModal();
}
}}
onPlusClick={() => {
openImageUploadModal();
}}
/>
</Box>
)}
{!question.content.useImage && (
<>
{!question.content.video ? (
<>
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "7px",
mt: "20px",
mb: "14px",
}}
>
<Typography sx={{ fontWeight: 500, color: theme.palette.grey3.main }}>Добавить видео</Typography>
<Tooltip
title="Можно загрузить видео."
placement="top"
>
<Box>
<InfoIcon />
</Box>
</Tooltip>
</Box>
{backgroundUploding ? (
<Skeleton
sx={{
width: "48px",
height: "48px",
transform: "none",
margin: "20px 0",
}}
/>
) : (
<>
<ButtonBase
onClick={() => setIsVideoUploadDialogOpen(true)}
sx={{
justifyContent: "center",
height: "48px",
width: "48px",
display: "flex",
alignItems: "center",
my: "20px",
}}
>
<input
onChange={async (event) => {
setBackgroundUploading(true);
const file = event.target.files?.[0];
if (file) {
await uploadQuestionImage(
question.id,
quizQid,
file,
(question, url) => {
question.content.video = url;
},
);
}
setBackgroundUploading(false);
}}
hidden
accept=".mp4"
multiple
type="file"
/>
<UploadBox
icon={<UploadIcon />}
sx={{
height: "48px",
width: "48px",
}}
/>
</ButtonBase>
</>
)}
</>
) : (
<VideoElement
videoSrc={question.content.video}
theme={theme}
onDeleteClick={() => {
updateQuestion(question.id, (question) => {
if (!("video" in question.content)) return;
question.content.video = null;
});
}}
/>
)}
</>
)
}
</Box >
);
};