feat: rating autosize inputs
This commit is contained in:
parent
123a26a436
commit
0c1279b37d
@ -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<string>("");
|
||||
const [positiveText, setPositiveText] = useState<string>("");
|
||||
const [negativeTextWidth, setNegativeTextWidth] = useState<number>(0);
|
||||
const [positiveTextWidth, setPositiveTextWidth] = useState<number>(0);
|
||||
const quizId = Number(useParams().quizId);
|
||||
const { listQuestions } = questionStore();
|
||||
const theme = useTheme();
|
||||
const isMobile = useMediaQuery(theme.breakpoints.down(790));
|
||||
const negativeRef = useRef<HTMLDivElement>(null);
|
||||
const positiveRef = useRef<HTMLDivElement>(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: <StarIconMini color={theme.palette.grey2.main} /> },
|
||||
@ -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",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: "flex", gap: isMobile ? "10px" : "15px" }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
padding: "0 10px",
|
||||
gap: isMobile ? "10px" : "15px",
|
||||
}}
|
||||
>
|
||||
{Array.from(
|
||||
{ length: listQuestions[quizId][totalIndex].content.steps },
|
||||
(_, index) => index
|
||||
).map((itemNumber) => (
|
||||
<Box
|
||||
key={itemNumber}
|
||||
{...(itemNumber === 0 ||
|
||||
itemNumber === listQuestions[quizId][totalIndex].content.steps - 1
|
||||
? {
|
||||
onClick: () => {
|
||||
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)" } })}
|
||||
>
|
||||
<Box key={itemNumber} sx={{ transform: "scale(1.5)" }}>
|
||||
{
|
||||
buttonRatingForm.find(
|
||||
({ name }) =>
|
||||
@ -100,65 +129,124 @@ export default function RatingOptions({ totalIndex }: Props) {
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
{!listQuestions[quizId][totalIndex].content.ratingDescription && (
|
||||
<Box
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
ref={negativeRef}
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
position: "absolute",
|
||||
opacity: 0,
|
||||
zIndex: "-100",
|
||||
whiteSpace: "nowrap",
|
||||
fontSize: "16px",
|
||||
}}
|
||||
>
|
||||
<Typography
|
||||
sx={{
|
||||
color: theme.palette.grey2.main,
|
||||
fontSize: "16px",
|
||||
fontWeight: 400,
|
||||
}}
|
||||
>
|
||||
Негативно
|
||||
</Typography>
|
||||
<Typography
|
||||
sx={{
|
||||
color: theme.palette.grey2.main,
|
||||
fontSize: "16px",
|
||||
fontWeight: 400,
|
||||
}}
|
||||
>
|
||||
Позитивно
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
{listQuestions[quizId][totalIndex].content.ratingExpanded &&
|
||||
(listQuestions[quizId][totalIndex].content.ratingDescription ? (
|
||||
<Typography>
|
||||
{listQuestions[quizId][totalIndex].content.ratingDescription}
|
||||
</Typography>
|
||||
) : (
|
||||
<CustomTextField
|
||||
placeholder={"Описание"}
|
||||
text={listQuestions[quizId][totalIndex].content.ratingDescription}
|
||||
onKeyDown={({ target, key }) => {
|
||||
if (key === "Enter") {
|
||||
const currentTarget = target as HTMLInputElement;
|
||||
{negativeText}
|
||||
</Typography>
|
||||
<TextField
|
||||
defaultValue={
|
||||
listQuestions[quizId][totalIndex].content
|
||||
.ratingNegativeDescription
|
||||
}
|
||||
value={negativeText}
|
||||
placeholder="Негативно"
|
||||
onChange={({ target }) => {
|
||||
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",
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<Typography
|
||||
ref={positiveRef}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
opacity: 0,
|
||||
zIndex: "-100",
|
||||
whiteSpace: "nowrap",
|
||||
fontSize: "16px",
|
||||
}}
|
||||
>
|
||||
{positiveText}
|
||||
</Typography>
|
||||
<TextField
|
||||
value={positiveText}
|
||||
placeholder="Позитивно"
|
||||
onChange={({ target }) => {
|
||||
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",
|
||||
},
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
<ButtonsOptions
|
||||
switchState={switchState}
|
||||
|
@ -64,8 +64,8 @@ export interface Question {
|
||||
chooseRange: boolean;
|
||||
required: boolean;
|
||||
replText: string;
|
||||
ratingExpanded: boolean;
|
||||
ratingDescription: string;
|
||||
ratingNegativeDescription: string;
|
||||
ratingPositiveDescription: string;
|
||||
};
|
||||
version: number;
|
||||
parent_ids: number[];
|
||||
@ -116,8 +116,8 @@ export const DEFAULT_QUESTION: Omit<Question, "id"> = {
|
||||
chooseRange: false,
|
||||
required: false,
|
||||
replText: "",
|
||||
ratingExpanded: false,
|
||||
ratingDescription: "",
|
||||
ratingNegativeDescription: "",
|
||||
ratingPositiveDescription: "",
|
||||
variants: [
|
||||
{
|
||||
answer: "",
|
||||
|
Loading…
Reference in New Issue
Block a user