frontPanel/src/ui_kit/MediaSelectionAndDisplay.tsx

296 lines
8.4 KiB
TypeScript
Raw Normal View History

import { FC, useState } from "react";
import {
Box,
Button,
ButtonBase,
Skeleton,
Tooltip,
Typography,
useTheme,
} from "@mui/material";
2023-12-20 20:25:58 +00:00
import { updateQuestion, uploadQuestionImage } from "@root/questions/actions";
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
2024-11-17 10:21:28 +00:00
import { UploadImageModal } from "@/pages/Questions/UploadImage/UploadImageModal";
import { VideoElement } from "@/pages/startPage/VideoElement";
import { useCurrentQuiz } from "@/stores/quizes/hooks";
import { useDisclosure } from "@/utils/useDisclosure";
2024-01-04 21:42:05 +00:00
import UploadBox from "@ui_kit/UploadBox";
import UploadIcon from "@icons/UploadIcon";
import InfoIcon from "@icons/InfoIcon";
2023-12-20 20:25:58 +00:00
import { CropModalInit } from "./Modal/CropModal";
2024-11-17 10:21:28 +00:00
import { AnyTypedQuizQuestion } from "@frontend/squzanswerer";
import UploadVideoModal from "@/pages/Questions/UploadVideoModal";
2023-12-20 20:25:58 +00:00
interface Iprops {
2024-11-17 10:21:28 +00:00
question: AnyTypedQuizQuestion;
2024-04-01 17:09:54 +00:00
cropAspectRatio: {
width: number;
height: number;
};
2023-12-20 20:25:58 +00:00
}
2024-04-01 17:09:54 +00:00
export const MediaSelectionAndDisplay: FC<Iprops> = ({
2024-11-17 10:21:28 +00:00
question,
2024-04-01 17:09:54 +00:00
cropAspectRatio,
}) => {
const theme = useTheme();
const [isVideoUploadDialogOpen, setIsVideoUploadDialogOpen] = useState<boolean>(false);
2024-01-18 14:21:09 +00:00
const [pictureUploding, setPictureUploading] = useState<boolean>(false);
const [backgroundUploding, setBackgroundUploading] = useState<boolean>(false);
const [openCropModal, setOpenCropModal] = useState(false);
2023-12-20 20:25:58 +00:00
const quizQid = useCurrentQuiz()?.qid;
2023-12-31 02:53:25 +00:00
const [isImageUploadOpen, openImageUploadModal, closeImageUploadModal] =
useDisclosure();
2023-12-20 20:25:58 +00:00
async function handleImageUpload(file: File) {
2024-01-18 14:21:09 +00:00
setPictureUploading(true);
2024-01-19 11:22:48 +00:00
closeImageUploadModal();
const url = await uploadQuestionImage(
2024-11-17 10:21:28 +00:00
question.id,
2024-01-19 11:22:48 +00:00
quizQid,
file,
(question, url) => {
question.content.back = url;
question.content.originalBack = url;
},
);
2024-11-15 22:42:19 +00:00
setOpenCropModal(true)
2024-01-18 14:21:09 +00:00
setPictureUploading(false);
2023-12-20 20:25:58 +00:00
}
function handleCropModalSaveClick(imageBlob: Blob) {
2024-06-17 14:28:24 +00:00
uploadQuestionImage(question.id, quizQid, imageBlob, (question, url) => {
2023-12-20 20:25:58 +00:00
question.content.back = url;
});
}
2024-06-17 14:28:24 +00:00
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);
}
2023-12-20 20:25:58 +00:00
return (
<Box
sx={{
mt: "20px",
display: "flex",
gap: "10px",
flexDirection: "column",
}}
>
<Box
sx={{
display: "flex",
}}
>
<Button
sx={{
2024-06-17 14:28:24 +00:00
color: question.content.useImage ? "#7E2AEA" : "#9A9AAF",
2023-12-20 20:25:58 +00:00
fontSize: "16px",
"&:hover": {
background: "none",
},
}}
variant="text"
2023-12-31 02:53:25 +00:00
onClick={() =>
updateQuestion(
2024-11-17 10:21:28 +00:00
question.id,
2023-12-31 02:53:25 +00:00
(question) => (question.content.useImage = true),
)
}
2023-12-20 20:25:58 +00:00
>
Изображение
</Button>
<Button
sx={{
2024-06-17 14:28:24 +00:00
color: question.content.useImage ? "#9A9AAF" : "#7E2AEA",
2023-12-20 20:25:58 +00:00
fontSize: "16px",
"&:hover": {
background: "none",
},
}}
variant="text"
2023-12-31 02:53:25 +00:00
onClick={() =>
2024-06-17 14:28:24 +00:00
updateQuestion(question.id, (question) => {
if (!("useImage" in question.content)) return;
question.content.useImage = false;
})
2023-12-31 02:53:25 +00:00
}
2023-12-20 20:25:58 +00:00
>
Видео
</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
2024-11-17 10:21:28 +00:00
originalImageUrl={question.content.originalBack}
editedUrlImagesList={question.content?.editedUrlImagesList}
questionId={question.id}
questionType={question.type}
quizId={quizQid}
open={openCropModal}
selfClose={() => setOpenCropModal(false)}
setPictureUploading={setPictureUploading}
2023-12-20 20:25:58 +00:00
/>
</Box>
2024-06-17 14:28:24 +00:00
{question.content.useImage && (
2023-12-20 20:25:58 +00:00
<Box
sx={{
cursor: "pointer",
display: "flex",
alignItems: "center",
gap: "20px",
mb: "30px",
}}
>
<AddOrEditImageButton
2024-11-17 10:21:28 +00:00
imageSrc={question.content.back}
2024-01-18 14:21:09 +00:00
uploading={pictureUploding}
2023-12-20 20:25:58 +00:00
onImageClick={() => {
2024-06-17 14:28:24 +00:00
if (question.content.back) {
setOpenCropModal(true)
} else {
openImageUploadModal();
2023-12-20 20:25:58 +00:00
}
}}
onPlusClick={() => {
openImageUploadModal();
}}
/>
</Box>
)}
2024-06-17 14:28:24 +00:00
{!question.content.useImage && (
2024-01-04 21:42:05 +00:00
<>
2024-06-17 14:28:24 +00:00
{!question.content.video ? (
<>
<Box
sx={{
display: "flex",
alignItems: "center",
gap: "7px",
mt: "20px",
mb: "14px",
}}
>
2024-06-17 14:28:24 +00:00
<Typography sx={{ fontWeight: 500, color: theme.palette.grey3.main }}>Добавить видео</Typography>
<Tooltip
title="Можно загрузить видео."
placement="top"
>
<Box>
<InfoIcon />
</Box>
</Tooltip>
2024-01-04 21:42:05 +00:00
</Box>
{backgroundUploding ? (
<Skeleton
sx={{
width: "48px",
height: "48px",
transform: "none",
margin: "20px 0",
}}
/>
) : (
<>
<ButtonBase
2024-06-17 14:28:24 +00:00
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(
2024-11-17 10:21:28 +00:00
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
2024-06-17 14:28:24 +00:00
videoSrc={question.content.video}
theme={theme}
onDeleteClick={() => {
2024-06-17 14:28:24 +00:00
updateQuestion(question.id, (question) => {
if (!("video" in question.content)) return;
question.content.video = null;
});
2024-01-04 21:42:05 +00:00
}}
/>
)}
2024-01-04 21:42:05 +00:00
</>
2024-11-17 10:21:28 +00:00
)
}
</Box >
2023-12-20 20:25:58 +00:00
);
};