From 66b39f63de1ff718d8269b1c4c1f57c96ef4c3a8 Mon Sep 17 00:00:00 2001 From: nflnkr Date: Mon, 23 Oct 2023 18:48:27 +0300 Subject: [PATCH] refactor & fix crop modal consumers --- .../Questions/AnswerDraggableList/index.tsx | 10 +-- .../OptionsAndPicture/OptionsAndPicture.tsx | 47 ++++------- .../OptionsPicture/OptionsPicture.tsx | 50 ++++-------- src/stores/questions.ts | 77 ++++++++++++++++--- 4 files changed, 105 insertions(+), 79 deletions(-) diff --git a/src/pages/Questions/AnswerDraggableList/index.tsx b/src/pages/Questions/AnswerDraggableList/index.tsx index 20173602..4de85766 100644 --- a/src/pages/Questions/AnswerDraggableList/index.tsx +++ b/src/pages/Questions/AnswerDraggableList/index.tsx @@ -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); } }; diff --git a/src/pages/Questions/OptionsAndPicture/OptionsAndPicture.tsx b/src/pages/Questions/OptionsAndPicture/OptionsAndPicture.tsx index b09989c6..3519ef50 100644 --- a/src/pages/Questions/OptionsAndPicture/OptionsAndPicture.tsx +++ b/src/pages/Questions/OptionsAndPicture/OptionsAndPicture.tsx @@ -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(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 ( <> @@ -129,18 +125,9 @@ export default function OptionsAndPicture({ totalIndex }: Props) { setIsUploadImageModalOpen(false)} - imgHC={uploadImage} - /> - { - const content = produce(question.content, draft => { - draft.variants[currentIndex].extendedText = url; - }); - updateQuestionsList(quizId, totalIndex, { - content, - }); - }} + imgHC={handleImageUpload} /> + { - 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(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 ( <> @@ -135,18 +128,9 @@ export default function OptionsPicture({ totalIndex }: Props) { setIsUploadImageModalOpen(false)} - imgHC={uploadImage} - /> - { - const content = produce(question.content, draft => { - draft.variants[currentIndex].extendedText = url; - }); - updateQuestionsList(quizId, totalIndex, { - content, - }); - }} + imgHC={handleImageUpload} /> + ()( 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 = (