From 0c1279b37d98e7def2594bf6482600b43d9dec6f Mon Sep 17 00:00:00 2001 From: IlyaDoronin Date: Wed, 27 Sep 2023 10:55:11 +0300 Subject: [PATCH] feat: rating autosize inputs --- .../Questions/RatingOptions/RatingOptions.tsx | 256 ++++++++++++------ src/stores/questions.ts | 8 +- 2 files changed, 176 insertions(+), 88 deletions(-) diff --git a/src/pages/Questions/RatingOptions/RatingOptions.tsx b/src/pages/Questions/RatingOptions/RatingOptions.tsx index bbe907fa..3e5887d9 100644 --- a/src/pages/Questions/RatingOptions/RatingOptions.tsx +++ b/src/pages/Questions/RatingOptions/RatingOptions.tsx @@ -1,10 +1,16 @@ -import { useState } from "react"; +import { useState, useEffect, useRef } from "react"; import { useParams } from "react-router-dom"; -import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; +import { + Box, + Typography, + TextField, + useMediaQuery, + useTheme, +} from "@mui/material"; +import { useDebouncedCallback } from "use-debounce"; +import { questionStore, updateQuestionsList } from "@root/questions"; import ButtonsOptions from "../ButtonsOptions"; import SwitchRating from "./switchRating"; -import { questionStore, updateQuestionsList } from "@root/questions"; -import CustomTextField from "@ui_kit/CustomTextField"; import TropfyIcon from "../../../assets/icons/questionsPage/tropfyIcon"; import FlagIcon from "../../../assets/icons/questionsPage/FlagIcon"; @@ -25,10 +31,49 @@ export type ButtonRatingFrom = { export default function RatingOptions({ totalIndex }: Props) { const [switchState, setSwitchState] = useState("setting"); + const [negativeText, setNegativeText] = useState(""); + const [positiveText, setPositiveText] = useState(""); + const [negativeTextWidth, setNegativeTextWidth] = useState(0); + const [positiveTextWidth, setPositiveTextWidth] = useState(0); const quizId = Number(useParams().quizId); const { listQuestions } = questionStore(); const theme = useTheme(); const isMobile = useMediaQuery(theme.breakpoints.down(790)); + const negativeRef = useRef(null); + const positiveRef = useRef(null); + const debounceNegativeDescription = useDebouncedCallback((value) => { + updateQuestionsList(quizId, totalIndex, { + content: { + ...listQuestions[quizId][totalIndex].content, + ratingNegativeDescription: value.substring(0, 15), + }, + }); + }, 500); + const debouncePositiveDescription = useDebouncedCallback((value) => { + updateQuestionsList(quizId, totalIndex, { + content: { + ...listQuestions[quizId][totalIndex].content, + ratingPositiveDescription: value.substring(0, 15), + }, + }); + }, 500); + + useEffect(() => { + setNegativeText( + listQuestions[quizId][totalIndex].content.ratingNegativeDescription + ); + setPositiveText( + listQuestions[quizId][totalIndex].content.ratingPositiveDescription + ); + }, []); + + useEffect(() => { + setNegativeTextWidth(negativeRef.current?.offsetWidth || 0); + }, [negativeText]); + + useEffect(() => { + setPositiveTextWidth(positiveRef.current?.offsetWidth || 0); + }, [positiveText]); const buttonRatingForm: ButtonRatingFrom[] = [ { name: "star", icon: }, @@ -54,7 +99,7 @@ export default function RatingOptions({ totalIndex }: Props) { width: isMobile ? "auto" : `${listQuestions[quizId][totalIndex].content.steps * 44}px`, - minWidth: "200px", + minWidth: "300px", maxWidth: "440px", display: "flex", padding: "20px", @@ -62,35 +107,19 @@ export default function RatingOptions({ totalIndex }: Props) { gap: "20px", }} > - + {Array.from( { length: listQuestions[quizId][totalIndex].content.steps }, (_, index) => index ).map((itemNumber) => ( - { - updateQuestionsList(quizId, totalIndex, { - content: { - ...listQuestions[quizId][totalIndex].content, - ratingExpanded: true, - }, - }); - }, - sx: { - cursor: "pointer", - transform: "scale(1.5)", - ":hover": { - transform: "scale(1.7)", - transition: "0.2s", - }, - }, - } - : { sx: { transform: "scale(1.5)" } })} - > + { buttonRatingForm.find( ({ name }) => @@ -100,65 +129,124 @@ export default function RatingOptions({ totalIndex }: Props) { ))} - {!listQuestions[quizId][totalIndex].content.ratingDescription && ( - + - - Негативно - - - Позитивно - - - )} - {listQuestions[quizId][totalIndex].content.ratingExpanded && - (listQuestions[quizId][totalIndex].content.ratingDescription ? ( - - {listQuestions[quizId][totalIndex].content.ratingDescription} - - ) : ( - { - if (key === "Enter") { - const currentTarget = target as HTMLInputElement; + {negativeText} + + { + if (positiveText) { + setPositiveText(""); + debouncePositiveDescription(""); + } - updateQuestionsList(quizId, totalIndex, { - content: { - ...listQuestions[quizId][totalIndex].content, - ratingDescription: currentTarget.value.substring(0, 20), - }, - }); - } - }} - onBlur={({ target }) => { - updateQuestionsList(quizId, totalIndex, { - content: { - ...listQuestions[quizId][totalIndex].content, - ratingDescription: target.value.substring(0, 20), + if (target.value.length <= 15) { + setNegativeText(target.value); + debounceNegativeDescription(target.value); + } + }} + onBlur={({ target }) => debounceNegativeDescription(target.value)} + sx={{ + width: negativeTextWidth + 10 + "px", + background: "transparent", + fontSize: "18px", + minWidth: "95px", + maxWidth: "230px", + transition: "0.2s", + "& .MuiInputBase-root": { + "& .MuiInputBase-input": { + color: theme.palette.grey2.main, + fontSize: "16px", + padding: "0 3px", + borderRadius: "3px", + border: "1px solid", + borderColor: "transparent", + "&:hover, &:focus": { + borderColor: theme.palette.grey2.main, }, - }); - }} - /> - ))} + }, + "& .MuiOutlinedInput-notchedOutline": { + outline: "none", + border: "none", + }, + }, + }} + /> + + {positiveText} + + { + if (negativeText) { + setNegativeText(""); + debounceNegativeDescription(""); + } + + if (target.value.length <= 15) { + setPositiveText(target.value); + debouncePositiveDescription(target.value); + } + }} + onBlur={({ target }) => debouncePositiveDescription(target.value)} + sx={{ + width: positiveTextWidth + 10 + "px", + background: "transparent", + fontSize: "18px", + minWidth: "95px", + maxWidth: "230px", + transition: "0.2s", + "& .MuiInputBase-root": { + "& .MuiInputBase-input": { + color: theme.palette.grey2.main, + fontSize: "16px", + padding: "0 3px", + borderRadius: "3px", + border: "1px solid", + borderColor: "transparent", + "&:hover, &:focus": { + borderColor: theme.palette.grey2.main, + }, + }, + "& .MuiOutlinedInput-notchedOutline": { + outline: "none", + border: "none", + }, + }, + }} + /> + = { chooseRange: false, required: false, replText: "", - ratingExpanded: false, - ratingDescription: "", + ratingNegativeDescription: "", + ratingPositiveDescription: "", variants: [ { answer: "",