refactor & fix crop modal consumers

This commit is contained in:
nflnkr 2023-10-23 18:48:27 +03:00
parent a0355eb38b
commit 66b39f63de
4 changed files with 105 additions and 79 deletions

@ -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 = (