diff --git a/lib/components/ViewPublicationPage/questions/Varimg/OwnVarimgImage.tsx b/lib/components/ViewPublicationPage/questions/Varimg/OwnVarimgImage.tsx index 5c734d8..9446c24 100644 --- a/lib/components/ViewPublicationPage/questions/Varimg/OwnVarimgImage.tsx +++ b/lib/components/ViewPublicationPage/questions/Varimg/OwnVarimgImage.tsx @@ -1,197 +1,33 @@ -import { Box, ButtonBase, IconButton, Typography, useTheme } from "@mui/material"; -import { useState, useRef } from "react"; -import CloseIcon from "@mui/icons-material/Close"; -import { useTranslation } from "react-i18next"; -import { useQuizStore } from "@/stores/useQuizStore"; -import { useQuizViewStore } from "@/stores/quizView"; -import { useSnackbar } from "notistack"; -import { Skeleton } from "@mui/material"; -import UploadIcon from "@/assets/icons/UploadIcon"; -import { sendFile } from "@/api/quizRelase"; -import { ACCEPT_SEND_FILE_TYPES_MAP, MAX_FILE_SIZE } from "../../tools/fileUpload"; +import React, { forwardRef } from "react"; +import { useQuizViewStore } from "@stores/quizView"; -// Пропсы компонента -export type OwnVarimgImageProps = { - imageUrl?: string; +interface OwnVarimgImageProps { questionId: string; variantId: string; - onValidationError: (error: "size" | "type") => void; -}; +} -export const OwnVarimgImage = ({ imageUrl, questionId, variantId, onValidationError }: OwnVarimgImageProps) => { - const theme = useTheme(); - const { t } = useTranslation(); - const { quizId, preview } = useQuizStore(); - const { ownVariants, updateOwnVariant, updateAnswer } = useQuizViewStore((state) => state); - const { enqueueSnackbar } = useSnackbar(); +export const OwnVarimgImage = forwardRef(({ questionId, variantId }, ref) => { + const { updateAnswer, updateOwnVariantWithFile } = useQuizViewStore((state) => state); - const [selectedFile, setSelectedFile] = useState(null); - const [isUploading, setIsUploading] = useState(false); - const fileInputRef = useRef(null); - - // Получаем ownVariant для этого варианта - const ownVariantData = ownVariants.find((v) => v.id === variantId); - - // Загрузка файла - const uploadImage = async (file: File) => { - if (isUploading) return; - if (!file) return; - if (file.size > MAX_FILE_SIZE) { - onValidationError("size"); - return; - } - const isFileTypeAccepted = ACCEPT_SEND_FILE_TYPES_MAP.picture.some((fileType) => - file.name.toLowerCase().endsWith(fileType) - ); - if (!isFileTypeAccepted) { - onValidationError("type"); - return; - } - setIsUploading(true); - try { - const data = await sendFile({ - questionId, - body: { file, name: file.name, preview }, - qid: quizId, - }); - const fileId = data?.data.fileIDMap[questionId]; - const localImageUrl = URL.createObjectURL(file); - // @ts-ignore - updateOwnVariant(variantId, "", "", fileId, localImageUrl, file); - updateAnswer(questionId, variantId, 0); - setSelectedFile(file); - } catch (error) { - console.error("Error uploading image:", error); - enqueueSnackbar(t("The answer was not counted")); - } finally { - setIsUploading(false); - } - }; - - // Обработчик выбора файла const handleFileChange = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (file) { - uploadImage(file); - } - }; - - // Открытие диалога выбора файла - const handleClick = (e: React.MouseEvent) => { - e.stopPropagation(); - if (fileInputRef.current) fileInputRef.current.value = ""; - fileInputRef.current?.click(); - }; - - // Удаление изображения - const handleRemoveImage = (e: React.MouseEvent) => { - e.stopPropagation(); - setSelectedFile(null); - updateOwnVariant(variantId, "", "", "", ""); - }; - - // Определяем, что показывать - let imageToDisplay: string | null = null; - if (selectedFile) { - imageToDisplay = URL.createObjectURL(selectedFile); - } else if (ownVariantData?.variant.localImageUrl) { - // @ts-ignore - if (ownVariantData.variant.file) { // @ts-ignore - imageToDisplay = URL.createObjectURL(ownVariantData.variant.file); - } else { - imageToDisplay = ownVariantData.variant.localImageUrl; + updateOwnVariantWithFile(variantId, file); + updateAnswer(questionId, variantId, 0); + event.target.value = ""; } - } else if (imageUrl) { - imageToDisplay = imageUrl; - } - - if (isUploading) { - return ( - - ); - } + }; return ( - - - {imageToDisplay ? ( - <> - - Preview - - - - - - ) : ( - - - - добавьте свою картинку - - - )} - + ); -}; +}); + +OwnVarimgImage.displayName = "OwnVarimgImage"; diff --git a/lib/components/ViewPublicationPage/questions/Varimg/VarimgVariant.tsx b/lib/components/ViewPublicationPage/questions/Varimg/VarimgVariant.tsx index d1c5cfa..69d8eee 100644 --- a/lib/components/ViewPublicationPage/questions/Varimg/VarimgVariant.tsx +++ b/lib/components/ViewPublicationPage/questions/Varimg/VarimgVariant.tsx @@ -1,23 +1,12 @@ import type { QuestionVariant, QuestionVariantWithEditedImages } from "@/model/questionTypes/shared"; import { useQuizStore } from "@/stores/useQuizStore"; -import { - FormControlLabel, - TextareaAutosize, - Radio, - useTheme, - Box, - Input, - FormControl, - InputLabel, - Typography, -} from "@mui/material"; +import { FormControlLabel, TextareaAutosize, Radio, useTheme, Box, Input, Typography } from "@mui/material"; import { useQuizViewStore } from "@stores/quizView"; import RadioCheck from "@ui_kit/RadioCheck"; import RadioIcon from "@ui_kit/RadioIcon"; import { quizThemes } from "@utils/themes/Publication/themePublication"; import { type MouseEvent } from "react"; import { useTranslation } from "react-i18next"; -import { useDebouncedCallback } from "use-debounce"; type VarimgVariantProps = { questionId: string; @@ -175,16 +164,12 @@ export const VarimgVariant = ({ value={index} onClick={sendVariant} label={ - variant?.isOwn ? ( - - ) : ( - variant.answer - ) + } control={ - ) : ( - variant.answer - ) - } + label={variant.answer} control={ } diff --git a/lib/components/ViewPublicationPage/questions/Varimg/index.tsx b/lib/components/ViewPublicationPage/questions/Varimg/index.tsx index 4f72535..c90a7fc 100644 --- a/lib/components/ViewPublicationPage/questions/Varimg/index.tsx +++ b/lib/components/ViewPublicationPage/questions/Varimg/index.tsx @@ -1,7 +1,8 @@ -import { useEffect, useMemo, useState } from "react"; +import { useEffect, useMemo, useRef, useState } from "react"; import { Box, ButtonBase, RadioGroup, Typography, useTheme } from "@mui/material"; import { VarimgVariant } from "./VarimgVariant"; +import { OwnVarimgImage } from "./OwnVarimgImage"; import { useQuizViewStore } from "@stores/quizView"; import { useRootContainerSize } from "@contexts/RootContainerWidthContext"; @@ -35,9 +36,13 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => { [currentQuestion.content.variants] ); const ownVariantData = ownVariants.find((v) => v.id === answer); - const ownImageUrl = ownVariantData?.variant.file - ? URL.createObjectURL(ownVariantData.variant.file) - : ownVariantData?.variant.localImageUrl; + const ownImageUrl = useMemo(() => { + return ownVariantData?.variant.file + ? URL.createObjectURL(ownVariantData.variant.file) + : ownVariantData?.variant.localImageUrl; + }, [ownVariantData]); + + const inputRef = useRef(null); useEffect(() => { if (!ownVariant) { @@ -67,15 +72,9 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => { } }, [variant]); - const handlePlaceholderClick = () => { - if (ownVariantInQuestion) { - document.getElementById(`own-image-input-${ownVariantInQuestion.id}`)?.click(); - } - }; - const handlePreviewAreaClick = () => { if (ownVariantInQuestion) { - document.getElementById(`own-image-input-${ownVariantInQuestion.id}`)?.click(); + inputRef.current?.click(); } }; @@ -140,6 +139,13 @@ export const Varimg = ({ currentQuestion }: VarimgProps) => { answer={answer} /> ))} + {ownVariantInQuestion && ( + + )} void; + updateOwnVariantWithFile: (variantId: string, file: File) => void; deleteOwnVariant: (id: string) => void; setCurrentQuizStep: (step: QuizStep) => void; } @@ -134,6 +135,35 @@ export const createQuizViewStore = () => } ); }, + updateOwnVariantWithFile(variantId, file) { + set( + (state) => { + const index = state.ownVariants.findIndex((v) => v.id === variantId); + + if (index < 0) { + state.ownVariants.push({ + id: variantId, + variant: { + id: variantId, + answer: "", + extendedText: "", + hints: "", + originalImageUrl: "", + file: file, + }, + }); + } else { + state.ownVariants[index].variant.file = file; + state.ownVariants[index].variant.localImageUrl = undefined; + } + }, + false, + { + type: "updateOwnVariantWithFile", + variantId, + } + ); + }, deleteOwnVariant(id) { set( (state) => {