держится контекст о выбранной картинке у Images
This commit is contained in:
parent
9f32bd9c9d
commit
38bd30ce35
@ -10,7 +10,8 @@ import UploadIcon from "@/assets/icons/UploadIcon";
|
|||||||
import { sendFile } from "@/api/quizRelase";
|
import { sendFile } from "@/api/quizRelase";
|
||||||
import { ACCEPT_SEND_FILE_TYPES_MAP, MAX_FILE_SIZE } from "../../tools/fileUpload";
|
import { ACCEPT_SEND_FILE_TYPES_MAP, MAX_FILE_SIZE } from "../../tools/fileUpload";
|
||||||
|
|
||||||
type OwnImageProps = {
|
// Пропсы компонента
|
||||||
|
export type OwnImageProps = {
|
||||||
imageUrl?: string;
|
imageUrl?: string;
|
||||||
questionId: string;
|
questionId: string;
|
||||||
variantId: string;
|
variantId: string;
|
||||||
@ -21,24 +22,24 @@ export const OwnImage = ({ imageUrl, questionId, variantId, onValidationError }:
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { quizId, preview } = useQuizStore();
|
const { quizId, preview } = useQuizStore();
|
||||||
const { answers, updateAnswer, ownVariants, updateOwnVariant } = useQuizViewStore((state) => state);
|
const { ownVariants, updateOwnVariant } = useQuizViewStore((state) => state);
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
const [selectedFile, setSelectedFile] = useState<File | null>(null);
|
const [selectedFile, setSelectedFile] = useState<File | null>(null);
|
||||||
const [isUploading, setIsUploading] = useState(false);
|
const [isUploading, setIsUploading] = useState(false);
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
// Получаем ownVariant для этого варианта
|
||||||
const ownVariantData = ownVariants.find((v) => v.id === variantId);
|
const ownVariantData = ownVariants.find((v) => v.id === variantId);
|
||||||
|
|
||||||
|
// Загрузка файла
|
||||||
const uploadImage = async (file: File) => {
|
const uploadImage = async (file: File) => {
|
||||||
if (isUploading) return;
|
if (isUploading) return;
|
||||||
if (!file) return;
|
if (!file) return;
|
||||||
|
|
||||||
if (file.size > MAX_FILE_SIZE) {
|
if (file.size > MAX_FILE_SIZE) {
|
||||||
onValidationError("size");
|
onValidationError("size");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isFileTypeAccepted = ACCEPT_SEND_FILE_TYPES_MAP.picture.some((fileType) =>
|
const isFileTypeAccepted = ACCEPT_SEND_FILE_TYPES_MAP.picture.some((fileType) =>
|
||||||
file.name.toLowerCase().endsWith(fileType)
|
file.name.toLowerCase().endsWith(fileType)
|
||||||
);
|
);
|
||||||
@ -46,28 +47,16 @@ export const OwnImage = ({ imageUrl, questionId, variantId, onValidationError }:
|
|||||||
onValidationError("type");
|
onValidationError("type");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsUploading(true);
|
setIsUploading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = await sendFile({
|
const data = await sendFile({
|
||||||
questionId,
|
questionId,
|
||||||
body: {
|
body: { file, name: file.name, preview },
|
||||||
file: file,
|
|
||||||
name: file.name,
|
|
||||||
preview,
|
|
||||||
},
|
|
||||||
qid: quizId,
|
qid: quizId,
|
||||||
});
|
});
|
||||||
|
const fileId = data?.data.fileIDMap[questionId];
|
||||||
const fileId = data!.data.fileIDMap[questionId];
|
|
||||||
|
|
||||||
// Сохраняем fileId в originalImageUrl
|
|
||||||
updateOwnVariant(variantId, "", "", fileId);
|
|
||||||
|
|
||||||
// Для UI — локальный preview
|
|
||||||
const localImageUrl = URL.createObjectURL(file);
|
const localImageUrl = URL.createObjectURL(file);
|
||||||
updateAnswer(questionId, `${file.name}|${localImageUrl}`, 0);
|
updateOwnVariant(variantId, "", "", fileId, localImageUrl);
|
||||||
setSelectedFile(file);
|
setSelectedFile(file);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error uploading image:", error);
|
console.error("Error uploading image:", error);
|
||||||
@ -77,6 +66,7 @@ export const OwnImage = ({ imageUrl, questionId, variantId, onValidationError }:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Обработчик выбора файла
|
||||||
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const file = event.target.files?.[0];
|
const file = event.target.files?.[0];
|
||||||
if (file) {
|
if (file) {
|
||||||
@ -84,24 +74,29 @@ export const OwnImage = ({ imageUrl, questionId, variantId, onValidationError }:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Открытие диалога выбора файла
|
||||||
const handleClick = (e: React.MouseEvent) => {
|
const handleClick = (e: React.MouseEvent) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
if (fileInputRef.current) {
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
||||||
fileInputRef.current.value = "";
|
|
||||||
}
|
|
||||||
fileInputRef.current?.click();
|
fileInputRef.current?.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Удаление изображения
|
||||||
const handleRemoveImage = (e: React.MouseEvent) => {
|
const handleRemoveImage = (e: React.MouseEvent) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setSelectedFile(null);
|
setSelectedFile(null);
|
||||||
updateAnswer(questionId, "", 0);
|
updateOwnVariant(variantId, "", "", "", "");
|
||||||
updateOwnVariant(variantId, "", "", "");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const imageToDisplay = selectedFile
|
// Определяем, что показывать
|
||||||
? URL.createObjectURL(selectedFile)
|
let imageToDisplay: string | null = null;
|
||||||
: ownVariantData?.variant.originalImageUrl || imageUrl;
|
if (selectedFile) {
|
||||||
|
imageToDisplay = URL.createObjectURL(selectedFile);
|
||||||
|
} else if (ownVariantData?.variant.localImageUrl) {
|
||||||
|
imageToDisplay = ownVariantData.variant.localImageUrl;
|
||||||
|
} else if (imageUrl) {
|
||||||
|
imageToDisplay = imageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
if (isUploading) {
|
if (isUploading) {
|
||||||
return (
|
return (
|
||||||
@ -137,7 +132,6 @@ export const OwnImage = ({ imageUrl, questionId, variantId, onValidationError }:
|
|||||||
accept={ACCEPT_SEND_FILE_TYPES_MAP.picture.join(",")}
|
accept={ACCEPT_SEND_FILE_TYPES_MAP.picture.join(",")}
|
||||||
hidden
|
hidden
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{imageToDisplay ? (
|
{imageToDisplay ? (
|
||||||
<>
|
<>
|
||||||
<Box sx={{ width: "100%", height: "100%", position: "relative" }}>
|
<Box sx={{ width: "100%", height: "100%", position: "relative" }}>
|
||||||
@ -147,26 +141,24 @@ export const OwnImage = ({ imageUrl, questionId, variantId, onValidationError }:
|
|||||||
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
style={{ width: "100%", height: "100%", objectFit: "cover" }}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
{(selectedFile || ownVariantData?.variant.originalImageUrl) && (
|
<IconButton
|
||||||
<IconButton
|
onClick={handleRemoveImage}
|
||||||
onClick={handleRemoveImage}
|
sx={{
|
||||||
sx={{
|
position: "absolute",
|
||||||
position: "absolute",
|
top: 8,
|
||||||
top: 8,
|
right: 8,
|
||||||
right: 8,
|
zIndex: 1,
|
||||||
zIndex: 1,
|
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
||||||
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
color: "white",
|
||||||
color: "white",
|
height: "25px",
|
||||||
height: "25px",
|
width: "25px",
|
||||||
width: "25px",
|
"&:hover": {
|
||||||
"&:hover": {
|
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
||||||
backgroundColor: "rgba(0, 0, 0, 0.7)",
|
},
|
||||||
},
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<CloseIcon />
|
||||||
<CloseIcon />
|
</IconButton>
|
||||||
</IconButton>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Box
|
<Box
|
||||||
|
@ -51,6 +51,8 @@ export type QuestionVariant = {
|
|||||||
isMulti?: boolean;
|
isMulti?: boolean;
|
||||||
/** Оригинал изображения (до кропа) */
|
/** Оригинал изображения (до кропа) */
|
||||||
originalImageUrl: string;
|
originalImageUrl: string;
|
||||||
|
/** Локальный URL для предпросмотра */
|
||||||
|
localImageUrl?: string;
|
||||||
points?: number;
|
points?: number;
|
||||||
};
|
};
|
||||||
export interface QuestionVariantWithEditedImages extends QuestionVariant {
|
export interface QuestionVariantWithEditedImages extends QuestionVariant {
|
||||||
|
@ -30,7 +30,13 @@ interface QuizViewStore {
|
|||||||
interface QuizViewActions {
|
interface QuizViewActions {
|
||||||
updateAnswer: (questionId: string, answer: string | string[] | Moment, points: number) => void;
|
updateAnswer: (questionId: string, answer: string | string[] | Moment, points: number) => void;
|
||||||
deleteAnswer: (questionId: string) => void;
|
deleteAnswer: (questionId: string) => void;
|
||||||
updateOwnVariant: (id: string, answer: string, extendedText?: string, originalImageUrl?: string) => void;
|
updateOwnVariant: (
|
||||||
|
id: string,
|
||||||
|
answer: string,
|
||||||
|
extendedText?: string,
|
||||||
|
originalImageUrl?: string,
|
||||||
|
localImageUrl?: string
|
||||||
|
) => void;
|
||||||
deleteOwnVariant: (id: string) => void;
|
deleteOwnVariant: (id: string) => void;
|
||||||
setCurrentQuizStep: (step: QuizStep) => void;
|
setCurrentQuizStep: (step: QuizStep) => void;
|
||||||
}
|
}
|
||||||
@ -90,7 +96,7 @@ export const createQuizViewStore = () =>
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
updateOwnVariant(id, answer, extendedText, originalImageUrl) {
|
updateOwnVariant(id, answer, extendedText, originalImageUrl, localImageUrl) {
|
||||||
set(
|
set(
|
||||||
(state) => {
|
(state) => {
|
||||||
const index = state.ownVariants.findIndex((variant) => variant.id === id);
|
const index = state.ownVariants.findIndex((variant) => variant.id === id);
|
||||||
@ -104,6 +110,7 @@ export const createQuizViewStore = () =>
|
|||||||
extendedText: extendedText || "",
|
extendedText: extendedText || "",
|
||||||
hints: "",
|
hints: "",
|
||||||
originalImageUrl: originalImageUrl || "",
|
originalImageUrl: originalImageUrl || "",
|
||||||
|
localImageUrl: localImageUrl || "",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -114,6 +121,9 @@ export const createQuizViewStore = () =>
|
|||||||
if (originalImageUrl) {
|
if (originalImageUrl) {
|
||||||
state.ownVariants[index].variant.originalImageUrl = originalImageUrl;
|
state.ownVariants[index].variant.originalImageUrl = originalImageUrl;
|
||||||
}
|
}
|
||||||
|
if (localImageUrl) {
|
||||||
|
state.ownVariants[index].variant.localImageUrl = localImageUrl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
|
Loading…
Reference in New Issue
Block a user