refactor & fix crop modal consumers
This commit is contained in:
parent
a0355eb38b
commit
66b39f63de
@ -4,11 +4,9 @@ import { DragDropContext, Droppable } from "react-beautiful-dnd";
|
||||
|
||||
import { AnswerItem } from "./AnswerItem";
|
||||
|
||||
import { updateVariants } from "@root/questions";
|
||||
import { reorderVariants } from "@root/questions";
|
||||
|
||||
import { reorder } from "./helper";
|
||||
|
||||
import type { ReactNode } from "react";
|
||||
import { type ReactNode } from "react";
|
||||
import type { DropResult } from "react-beautiful-dnd";
|
||||
import type { ImageQuestionVariant, QuestionVariant } from "../../../model/questionTypes/shared";
|
||||
|
||||
@ -29,9 +27,7 @@ export const AnswerDraggableList = ({
|
||||
|
||||
const onDragEnd = ({ destination, source }: DropResult) => {
|
||||
if (destination) {
|
||||
const newItems = reorder(variants, source.index, destination.index);
|
||||
|
||||
updateVariants(quizId, totalIndex, newItems);
|
||||
reorderVariants(quizId, totalIndex, source.index, destination.index);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -21,15 +21,14 @@ import { ImageAddIcons } from "@icons/ImageAddIcons";
|
||||
import { MessageIcon } from "@icons/messagIcon";
|
||||
import { PointsIcon } from "@icons/questionsPage/PointsIcon";
|
||||
import { DeleteIcon } from "@icons/questionsPage/deleteIcon";
|
||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||
import { questionStore, setVariantImageUrl, setVariantOriginalImageUrl, updateQuestionsList } from "@root/questions";
|
||||
import { EnterIcon } from "../../../assets/icons/questionsPage/enterIcon";
|
||||
import ButtonsOptionsAndPict from "../ButtonsOptionsAndPict";
|
||||
import SwitchOptionsAndPict from "./switchOptionsAndPict";
|
||||
|
||||
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
|
||||
import { produce } from "immer";
|
||||
import type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg";
|
||||
import { openCropModal } from "@root/cropModal";
|
||||
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
|
||||
import type { QuizQuestionVarImg } from "../../../model/questionTypes/varimg";
|
||||
|
||||
interface Props {
|
||||
totalIndex: number;
|
||||
@ -50,25 +49,22 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
|
||||
setSwitchState(data);
|
||||
};
|
||||
|
||||
const uploadImage = (files: FileList | null) => {
|
||||
if (files?.length) {
|
||||
const [file] = Array.from(files);
|
||||
const handleImageUpload = (files: FileList | null) => {
|
||||
if (!files?.length) return;
|
||||
|
||||
const clonedContent = { ...question.content };
|
||||
clonedContent.variants[currentIndex].extendedText =
|
||||
URL.createObjectURL(file);
|
||||
updateQuestionsList<QuizQuestionVarImg>(quizId, totalIndex, {
|
||||
content: clonedContent,
|
||||
});
|
||||
const [file] = Array.from(files);
|
||||
const url = URL.createObjectURL(file);
|
||||
|
||||
setIsUploadImageModalOpen(false);
|
||||
openCropModal(
|
||||
question.content.variants[currentIndex]?.extendedText,
|
||||
question.content.variants[currentIndex]?.originalImageUrl
|
||||
);
|
||||
}
|
||||
setVariantImageUrl(quizId, totalIndex, currentIndex, url);
|
||||
setVariantOriginalImageUrl(quizId, totalIndex, currentIndex, url);
|
||||
setIsUploadImageModalOpen(false);
|
||||
openCropModal(url, url);
|
||||
};
|
||||
|
||||
function handleCropModalSaveClick(url: string) {
|
||||
setVariantImageUrl(quizId, totalIndex, currentIndex, url);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box sx={{ pl: "20px", pr: "20px" }}>
|
||||
@ -129,18 +125,9 @@ export default function OptionsAndPicture({ totalIndex }: Props) {
|
||||
<UploadImageModal
|
||||
open={isUploadImageModalOpen}
|
||||
onClose={() => setIsUploadImageModalOpen(false)}
|
||||
imgHC={uploadImage}
|
||||
/>
|
||||
<CropModal
|
||||
onSaveImageClick={url => {
|
||||
const content = produce(question.content, draft => {
|
||||
draft.variants[currentIndex].extendedText = url;
|
||||
});
|
||||
updateQuestionsList<QuizQuestionVarImg>(quizId, totalIndex, {
|
||||
content,
|
||||
});
|
||||
}}
|
||||
imgHC={handleImageUpload}
|
||||
/>
|
||||
<CropModal onSaveImageClick={handleCropModalSaveClick} />
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
|
||||
@ -8,7 +8,7 @@ import {
|
||||
import { useState } from "react";
|
||||
import { useParams } from "react-router-dom";
|
||||
|
||||
import { questionStore, updateQuestionsList } from "@root/questions";
|
||||
import { questionStore, setVariantImageUrl, updateQuestionsList, setVariantOriginalImageUrl } from "@root/questions";
|
||||
import { CropModal } from "@ui_kit/Modal/CropModal";
|
||||
import { AnswerDraggableList } from "../AnswerDraggableList";
|
||||
import ButtonsOptions from "../ButtonsOptions";
|
||||
@ -17,10 +17,9 @@ import { UploadImageModal } from "../UploadImage/UploadImageModal";
|
||||
import { EnterIcon } from "../../../assets/icons/questionsPage/enterIcon";
|
||||
import SwitchAnswerOptionsPict from "./switchOptionsPict";
|
||||
|
||||
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
|
||||
import { produce } from "immer";
|
||||
import type { QuizQuestionImages } from "../../../model/questionTypes/images";
|
||||
import { openCropModal } from "@root/cropModal";
|
||||
import AddOrEditImageButton from "@ui_kit/AddOrEditImageButton";
|
||||
import type { QuizQuestionImages } from "../../../model/questionTypes/images";
|
||||
|
||||
interface Props {
|
||||
totalIndex: number;
|
||||
@ -40,26 +39,16 @@ export default function OptionsPicture({ totalIndex }: Props) {
|
||||
setSwitchState(data);
|
||||
};
|
||||
|
||||
const uploadImage = (files: FileList | null) => {
|
||||
if (files?.length) {
|
||||
const [file] = Array.from(files);
|
||||
const handleImageUpload = (files: FileList | null) => {
|
||||
if (!files?.length) return;
|
||||
|
||||
const clonedContent = { ...question.content };
|
||||
const [file] = Array.from(files);
|
||||
const url = URL.createObjectURL(file);
|
||||
|
||||
const url = URL.createObjectURL(file);
|
||||
clonedContent.variants[currentIndex].extendedText = url;
|
||||
clonedContent.variants[currentIndex].originalImageUrl = url;
|
||||
|
||||
updateQuestionsList<QuizQuestionImages>(quizId, totalIndex, {
|
||||
content: clonedContent,
|
||||
});
|
||||
|
||||
setIsUploadImageModalOpen(false);
|
||||
openCropModal(
|
||||
question.content.variants[currentIndex]?.extendedText,
|
||||
question.content.variants[currentIndex]?.originalImageUrl,
|
||||
);
|
||||
}
|
||||
setVariantImageUrl(quizId, totalIndex, currentIndex, url);
|
||||
setVariantOriginalImageUrl(quizId, totalIndex, currentIndex, url);
|
||||
setIsUploadImageModalOpen(false);
|
||||
openCropModal(url, url);
|
||||
};
|
||||
|
||||
const addNewAnswer = () => {
|
||||
@ -71,6 +60,10 @@ export default function OptionsPicture({ totalIndex }: Props) {
|
||||
});
|
||||
};
|
||||
|
||||
function handleCropModalSaveClick(url: string) {
|
||||
setVariantImageUrl(quizId, totalIndex, currentIndex, url);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box sx={{ padding: "20px" }}>
|
||||
@ -135,18 +128,9 @@ export default function OptionsPicture({ totalIndex }: Props) {
|
||||
<UploadImageModal
|
||||
open={isUploadImageModalOpen}
|
||||
onClose={() => setIsUploadImageModalOpen(false)}
|
||||
imgHC={uploadImage}
|
||||
/>
|
||||
<CropModal
|
||||
onSaveImageClick={url => {
|
||||
const content = produce(question.content, draft => {
|
||||
draft.variants[currentIndex].extendedText = url;
|
||||
});
|
||||
updateQuestionsList<QuizQuestionImages>(quizId, totalIndex, {
|
||||
content,
|
||||
});
|
||||
}}
|
||||
imgHC={handleImageUpload}
|
||||
/>
|
||||
<CropModal onSaveImageClick={handleCropModalSaveClick} />
|
||||
<Box sx={{ display: "flex", alignItems: "center", gap: "10px" }}>
|
||||
<Link
|
||||
component="button"
|
||||
|
||||
@ -3,8 +3,6 @@ import { devtools, persist } from "zustand/middleware";
|
||||
|
||||
import type {
|
||||
AnyQuizQuestion,
|
||||
ImageQuestionVariant,
|
||||
QuestionVariant,
|
||||
QuizQuestionType
|
||||
} from "../model/questionTypes/shared";
|
||||
|
||||
@ -43,6 +41,7 @@ export const questionStore = create<QuestionStore>()(
|
||||
name: "Question",
|
||||
enabled: process.env.NODE_ENV === "development",
|
||||
trace: process.env.NODE_ENV === "development",
|
||||
actionsBlacklist: "ignored",
|
||||
}
|
||||
),
|
||||
{
|
||||
@ -125,6 +124,54 @@ export const removeQuestionsByQuizId = (quizId: number) => setProducedState(stat
|
||||
delete state.listQuestions[quizId];
|
||||
}, "removeQuestionsByQuizId");
|
||||
|
||||
export const setVariantImageUrl = (
|
||||
quizId: number,
|
||||
questionIndex: number,
|
||||
variantIndex: number,
|
||||
url: string,
|
||||
) => setProducedState(state => {
|
||||
const question = state.listQuestions[quizId][questionIndex];
|
||||
if (!("variants" in question.content)) return;
|
||||
|
||||
const variant = question.content.variants[variantIndex];
|
||||
if (!("originalImageUrl" in variant)) return;
|
||||
|
||||
if (variant.extendedText === url) return;
|
||||
|
||||
if (variant.extendedText !== variant.originalImageUrl) URL.revokeObjectURL(variant.extendedText);
|
||||
variant.extendedText = url;
|
||||
}, {
|
||||
type: "setVariantImageUrl",
|
||||
quizId,
|
||||
questionIndex,
|
||||
variantIndex,
|
||||
url,
|
||||
});
|
||||
|
||||
export const setVariantOriginalImageUrl = (
|
||||
quizId: number,
|
||||
questionIndex: number,
|
||||
variantIndex: number,
|
||||
url: string,
|
||||
) => setProducedState(state => {
|
||||
const question = state.listQuestions[quizId][questionIndex];
|
||||
if (!("variants" in question.content)) return;
|
||||
|
||||
const variant = question.content.variants[variantIndex];
|
||||
if (!("originalImageUrl" in variant)) return;
|
||||
|
||||
if (variant.originalImageUrl === url) return;
|
||||
|
||||
URL.revokeObjectURL(variant.originalImageUrl);
|
||||
variant.originalImageUrl = url;
|
||||
}, {
|
||||
type: "setVariantOriginalImageUrl",
|
||||
quizId,
|
||||
questionIndex,
|
||||
variantIndex,
|
||||
url,
|
||||
});
|
||||
|
||||
export const updateQuestionsListDragAndDrop = (
|
||||
quizId: number,
|
||||
updatedQuestions: AnyQuizQuestion[]
|
||||
@ -135,14 +182,26 @@ export const updateQuestionsListDragAndDrop = (
|
||||
});
|
||||
};
|
||||
|
||||
export const updateVariants = (
|
||||
quizId: number,
|
||||
index: number,
|
||||
variants: ImageQuestionVariant[] | QuestionVariant[],
|
||||
) => setProducedState(state => {
|
||||
const question = state.listQuestions[quizId][index];
|
||||
|
||||
if ("variants" in question.content) question.content.variants = variants;
|
||||
export const reorderVariants = (
|
||||
quizId: number,
|
||||
questionIndex: number,
|
||||
sourceIndex: number,
|
||||
destinationIndex: number,
|
||||
) => setProducedState(state => {
|
||||
if (sourceIndex === destinationIndex) return;
|
||||
|
||||
const question = state.listQuestions[quizId][questionIndex];
|
||||
if (!("variants" in question.content)) return;
|
||||
|
||||
const [removed] = question.content.variants.splice(sourceIndex, 1);
|
||||
question.content.variants.splice(destinationIndex, 0, removed);
|
||||
}, {
|
||||
type: sourceIndex === destinationIndex ? "reorderVariants" : "ignored",
|
||||
quizId,
|
||||
questionIndex,
|
||||
sourceIndex,
|
||||
destinationIndex,
|
||||
});
|
||||
|
||||
export const createQuestion = (
|
||||
|
||||
Loading…
Reference in New Issue
Block a user