diff --git a/src/assets/icons/questionsPage/deleteIcon.tsx b/src/assets/icons/questionsPage/deleteIcon.tsx index 6c5dc503..b6fcbcc6 100755 --- a/src/assets/icons/questionsPage/deleteIcon.tsx +++ b/src/assets/icons/questionsPage/deleteIcon.tsx @@ -1,29 +1,63 @@ import { Box } from "@mui/material"; - interface Props { - color: string; + color: string; } -export default function DeleteIcon({color}: Props) { - - return ( - - - - - - - - - - ); -} \ No newline at end of file +export default function DeleteIcon({ color = "#4D4D4D" }: Props) { + return ( + + + + + + + + + + ); +} diff --git a/src/assets/icons/questionsPage/ratingStar.tsx b/src/assets/icons/questionsPage/ratingStar.tsx index 41ac6de3..9c38fccc 100644 --- a/src/assets/icons/questionsPage/ratingStar.tsx +++ b/src/assets/icons/questionsPage/ratingStar.tsx @@ -1,25 +1,37 @@ import { Box } from "@mui/material"; +import type { SxProps } from "@mui/material"; interface Props { - color: string; + sx?: SxProps; + onClick?: () => void; } -export default function RatingStar({color}: Props) { - - return ( - - - - - - ); -} \ No newline at end of file +export default function RatingStar({ sx, onClick }: Props) { + return ( + + + + + + ); +} diff --git a/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx b/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx index a7debc03..d0dfc028 100644 --- a/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx +++ b/src/pages/Questions/AnswerDraggableList/AnswerItem.tsx @@ -109,7 +109,7 @@ export const AnswerItem = ({ key={index} fullWidth variant="standard" - sx={{ p: "0 0 20px 0" }} + sx={{ padding: "0 0 20px 0" }} > void; - totalIndex: number + totalIndex: number; } -export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props) { +export default function ButtonsOptions({ + SSHC, + switchState, + totalIndex, +}: Props) { const quizId = Number(useParams().quizId); - const {openedModalSettings} = questionStore() + const { openedModalSettings } = questionStore(); const openedModal = () => { - resetSomeField({openedModalSettings: "open"}) - console.log(openedModalSettings) - } + resetSomeField({ openedModalSettings: "open" }); + console.log(openedModalSettings); + }; const theme = useTheme(); - const buttonSetting: { icon: JSX.Element; title: string; value: string; myFunc?: any }[] = [ + const buttonSetting: { + icon: JSX.Element; + title: string; + value: string; + myFunc?: any; + }[] = [ { - icon: , + icon: ( + + ), title: "Настройки", value: "setting", }, { - icon: , + icon: ( + + ), title: "Подсказка", value: "help", }, { - icon: , + icon: ( + + ), title: "Ветвление", value: "branching", - myFunc: openedModal + myFunc: openedModal, }, ]; @@ -59,21 +89,86 @@ export default function ButtonsOptions({ SSHC, switchState, totalIndex }: Props) gap: "10px", }} > - {buttonSetting.map(({ icon, title, value, myFunc}) => ( - { - SSHC(value); - myFunc() - }} - sx={{ - backgroundColor: switchState === value ? theme.palette.brightPurple.main : "transparent", - color: switchState === value ? "#ffffff" : theme.palette.grey3.main, - }} - > - {icon} - {title} - + {buttonSetting.map(({ icon, title, value, myFunc }) => ( + <> + {value === "branching" ? ( + + + Будет показан при условии + + + Название + + + Условие 1, Условие 2 + + + Все условия обязательны + + + } + > + { + SSHC(value); + myFunc(); + }} + sx={{ + backgroundColor: + switchState === value + ? theme.palette.brightPurple.main + : "transparent", + color: + switchState === value + ? "#ffffff" + : theme.palette.grey3.main, + }} + > + {icon} + {title} + + + ) : ( + { + SSHC(value); + myFunc(); + }} + sx={{ + backgroundColor: + switchState === value + ? theme.palette.brightPurple.main + : "transparent", + color: + switchState === value + ? "#ffffff" + : theme.palette.grey3.main, + }} + > + {icon} + {title} + + )} + ))} - + - - + copyQuestion(quizId, totalIndex)} + > + - removeQuestion(quizId, totalIndex)}> - + removeQuestion(quizId, totalIndex)} + > + diff --git a/src/pages/Questions/ButtonsOptionsAndPict.tsx b/src/pages/Questions/ButtonsOptionsAndPict.tsx index 1e638c4a..43fd1812 100644 --- a/src/pages/Questions/ButtonsOptionsAndPict.tsx +++ b/src/pages/Questions/ButtonsOptionsAndPict.tsx @@ -9,7 +9,12 @@ import CopyIcon from "../../assets/icons/questionsPage/CopyIcon"; import DeleteIcon from "../../assets/icons/questionsPage/deleteIcon"; import ImgIcon from "../../assets/icons/questionsPage/imgIcon"; import { useParams } from "react-router-dom"; -import { questionStore, removeQuestion, resetSomeField } from "@root/questions"; +import { + questionStore, + copyQuestion, + removeQuestion, + resetSomeField, +} from "@root/questions"; import "./ButtonsOptionsAndPict.css"; @@ -176,7 +181,10 @@ export default function ButtonsOptionsAndPict({ - + copyQuestion(quizId, totalIndex)} + > Настройки календаря { const clonContent = listQuestions[quizId][totalIndex].content; @@ -35,10 +36,45 @@ export default function SettingsData({ totalIndex }: SettingsDataProps) { }} /> - + Настройки вопросов - - + { + updateQuestionsList(quizId, totalIndex, { + required: !e.target.checked, + }); + }} + /> + + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerNameCheck = e.target.checked; + + if (!e.target.checked) { + clonContent.innerName = ""; + } + + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + />{" "} + + + {listQuestions[quizId][totalIndex].content.innerNameCheck && ( + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerName = target.value; + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + /> + )} ); diff --git a/src/pages/Questions/DropDown/settingDropDown.tsx b/src/pages/Questions/DropDown/settingDropDown.tsx index a6d5dc4b..ae121649 100644 --- a/src/pages/Questions/DropDown/settingDropDown.tsx +++ b/src/pages/Questions/DropDown/settingDropDown.tsx @@ -24,7 +24,18 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) { Настройки ответов - + + updateQuestionsList(quizId, totalIndex, { + content: { + ...listQuestions[quizId][totalIndex].content, + multi: target.checked, + }, + }) + } + /> Текст в выпадающем списке @@ -38,12 +49,51 @@ export default function SettingDropDown({ totalIndex }: SettingDropDownProps) { }} /> - + Настройки вопросов - - + { + updateQuestionsList(quizId, totalIndex, { + required: !e.target.checked, + }); + }} + /> + + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerNameCheck = e.target.checked; + + if (!e.target.checked) { + clonContent.innerName = ""; + } + + updateQuestionsList(quizId, totalIndex, { + content: clonContent, + }); + }} + />{" "} + + + {listQuestions[quizId][totalIndex].content.innerNameCheck && ( + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerName = target.value; + updateQuestionsList(quizId, totalIndex, { + content: clonContent, + }); + }} + /> + )} diff --git a/src/pages/Questions/Emoji/settingEmoji.tsx b/src/pages/Questions/Emoji/settingEmoji.tsx index 06c77635..847931ed 100644 --- a/src/pages/Questions/Emoji/settingEmoji.tsx +++ b/src/pages/Questions/Emoji/settingEmoji.tsx @@ -1,6 +1,7 @@ import { useParams } from "react-router-dom"; import { Box, Typography } from "@mui/material"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; +import CustomTextField from "@ui_kit/CustomTextField"; import InfoIcon from "../../../assets/icons/InfoIcon"; import { questionStore, updateQuestionsList } from "@root/questions"; @@ -13,7 +14,7 @@ export default function SettingEmoji({ totalIndex }: SettingEmojiProps) { const { listQuestions } = questionStore(); return ( - + Настройки ответов - + Настройки вопросов - - + { + updateQuestionsList(quizId, totalIndex, { + required: !e.target.checked, + }); + }} + /> + + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerNameCheck = e.target.checked; + + if (!e.target.checked) { + clonContent.innerName = ""; + } + + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + />{" "} + + + {listQuestions[quizId][totalIndex].content.innerNameCheck && ( + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerName = target.value; + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + /> + )} ); diff --git a/src/pages/Questions/OptionsPicture/settingOpytionsPict.tsx b/src/pages/Questions/OptionsPicture/settingOpytionsPict.tsx index b0f35e86..b843daf2 100644 --- a/src/pages/Questions/OptionsPicture/settingOpytionsPict.tsx +++ b/src/pages/Questions/OptionsPicture/settingOpytionsPict.tsx @@ -89,7 +89,13 @@ export default function SettingOpytionsPict({ return ( <> - + Пропорции - + Форма - + + Настройки ответов @@ -62,20 +71,68 @@ export default function SettingTextField({ {ANSWER_TYPES.map(({ name }, index) => ( } + control={ + } checkedIcon={} /> + } label={name} /> ))} - + Настройки вопросов - - - + { + const clonContent = listQuestions[quizId][totalIndex].content; + clonContent.autofill = target.checked; + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + /> + { + updateQuestionsList(quizId, totalIndex, { + required: !e.target.checked, + }); + }} + /> + + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerNameCheck = e.target.checked; + + if (!e.target.checked) { + clonContent.innerName = ""; + } + + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + />{" "} + + + {listQuestions[quizId][totalIndex].content.innerNameCheck && ( + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerName = target.value; + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + /> + )} ); diff --git a/src/pages/Questions/PageOptions/SettingPageOptions.tsx b/src/pages/Questions/PageOptions/SettingPageOptions.tsx index 763617cf..034a00ee 100644 --- a/src/pages/Questions/PageOptions/SettingPageOptions.tsx +++ b/src/pages/Questions/PageOptions/SettingPageOptions.tsx @@ -1,15 +1,54 @@ +import { useParams } from "react-router-dom"; import { Box, Typography } from "@mui/material"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; +import CustomTextField from "@ui_kit/CustomTextField"; + +import { questionStore, updateQuestionsList } from "@root/questions"; + import InfoIcon from "../../../assets/icons/InfoIcon"; -export default function SettingPageOptions() { +type SettingPageOptionsProps = { + totalIndex: number; +}; + +export default function SettingPageOptions({ + totalIndex, +}: SettingPageOptionsProps) { + const quizId = Number(useParams().quizId); + const { listQuestions } = questionStore(); + return ( Настройки вопроса - + + updateQuestionsList(quizId, totalIndex, { + content: { + ...listQuestions[quizId][totalIndex].content, + innerNameCheck: target.checked, + innerName: "", + }, + }) + } + /> + {listQuestions[quizId][totalIndex].content.innerNameCheck && ( + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerName = target.value; + updateQuestionsList(quizId, totalIndex, { + content: clonContent, + }); + }} + /> + )} ); } diff --git a/src/pages/Questions/PageOptions/switchPageOptions.tsx b/src/pages/Questions/PageOptions/switchPageOptions.tsx index 52f3c9a0..5eba5a89 100644 --- a/src/pages/Questions/PageOptions/switchPageOptions.tsx +++ b/src/pages/Questions/PageOptions/switchPageOptions.tsx @@ -13,13 +13,13 @@ export default function SwitchPageOptions({ }: Props) { switch (switchState) { case "setting": - return ; + return ; break; case "help": return ; break; case "branching": - return ; + return ; break; default: return <>; diff --git a/src/pages/Questions/RatingOptions/RatingOptions.tsx b/src/pages/Questions/RatingOptions/RatingOptions.tsx index 5a70dfae..e3a46a7a 100644 --- a/src/pages/Questions/RatingOptions/RatingOptions.tsx +++ b/src/pages/Questions/RatingOptions/RatingOptions.tsx @@ -2,10 +2,10 @@ import { useState } from "react"; import { useParams } from "react-router-dom"; import { Box, Typography, useTheme } from "@mui/material"; import ButtonsOptions from "../ButtonsOptions"; -import Rating from "@mui/material/Rating"; import RatingStar from "../../../assets/icons/questionsPage/ratingStar"; import SwitchRating from "./switchRating"; import { questionStore, updateQuestionsList } from "@root/questions"; +import CustomTextField from "@ui_kit/CustomTextField"; interface Props { totalIndex: number; @@ -33,22 +33,45 @@ export default function RatingOptions({ totalIndex }: Props) { gap: "20px", }} > - - `${value} Heart${value !== 1 ? "s" : ""}` - } - precision={1} - icon={} - emptyIcon={} - sx={{ display: "flex", gap: "15px" }} - onChange={(_, value) => { - const clonContent = listQuestions[quizId][totalIndex].content; - clonContent.starts = value || 0; - updateQuestionsList(quizId, totalIndex, { content: clonContent }); - }} - /> + + { + updateQuestionsList(quizId, totalIndex, { + content: { + ...listQuestions[quizId][totalIndex].content, + ratingExpanded: true, + }, + }); + }} + sx={{ + cursor: "pointer", + ":hover": { + transform: "scale(1.1)", + transition: "0.2s", + }, + }} + /> + + + + { + updateQuestionsList(quizId, totalIndex, { + content: { + ...listQuestions[quizId][totalIndex].content, + ratingExpanded: true, + }, + }); + }} + sx={{ + cursor: "pointer", + ":hover": { + transform: "scale(1.1)", + transition: "0.2s", + }, + }} + /> + + {listQuestions[quizId][totalIndex].content.ratingExpanded && + (listQuestions[quizId][totalIndex].content.ratingDescription ? ( + + {listQuestions[quizId][totalIndex].content.ratingDescription} + + ) : ( + { + if (key === "Enter") { + const currentTarget = target as HTMLInputElement; + + 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), + }, + }); + }} + /> + ))} Настройки вопросов - - + { + updateQuestionsList(quizId, totalIndex, { + required: !e.target.checked, + }); + }} + /> + + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerNameCheck = e.target.checked; + + if (!e.target.checked) { + clonContent.innerName = ""; + } + + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + />{" "} + + + {listQuestions[quizId][totalIndex].content.innerNameCheck && ( + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerName = target.value; + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + /> + )} ); diff --git a/src/pages/Questions/SliderOptions/SliderOptions.tsx b/src/pages/Questions/SliderOptions/SliderOptions.tsx index ff3fe54f..c1ae6e54 100644 --- a/src/pages/Questions/SliderOptions/SliderOptions.tsx +++ b/src/pages/Questions/SliderOptions/SliderOptions.tsx @@ -1,8 +1,8 @@ +import { useState } from "react"; import { useParams } from "react-router-dom"; import { Box, Typography } from "@mui/material"; import ButtonsOptions from "../ButtonsOptions"; -import React from "react"; -import CustomTextField from "@ui_kit/CustomTextField"; +import CustomNumberField from "@ui_kit/CustomNumberField"; import SwitchSlider from "./switchSlider"; import { questionStore, updateQuestionsList } from "@root/questions"; @@ -11,7 +11,8 @@ interface Props { } export default function SliderOptions({ totalIndex }: Props) { - const [switchState, setSwitchState] = React.useState("setting"); + const [switchState, setSwitchState] = useState("setting"); + const [stepError, setStepError] = useState(""); const quizId = Number(useParams().quizId); const { listQuestions } = questionStore(); @@ -34,9 +35,11 @@ export default function SliderOptions({ totalIndex }: Props) { Выбор значения из диапазона - { @@ -48,11 +51,31 @@ export default function SliderOptions({ totalIndex }: Props) { content: clonContent, }); }} + onBlur={({ target }) => { + const min = Number(target.value); + const max = Number( + listQuestions[quizId][totalIndex].content.range.split("—")[1] + ); + + if (min >= max) { + const clonContent = listQuestions[quizId][totalIndex].content; + clonContent.range = `${max - 1 >= 0 ? max - 1 : 0}—${ + listQuestions[quizId][totalIndex].content.range.split( + "—" + )[1] + }`; + updateQuestionsList(quizId, totalIndex, { + content: clonContent, + }); + } + }} /> - { @@ -64,6 +87,24 @@ export default function SliderOptions({ totalIndex }: Props) { content: clonContent, }); }} + onBlur={({ target }) => { + const min = Number( + listQuestions[quizId][totalIndex].content.range.split("—")[0] + ); + const max = Number(target.value); + + if (max <= min) { + const clonContent = listQuestions[quizId][totalIndex].content; + clonContent.range = `${ + listQuestions[quizId][totalIndex].content.range.split( + "—" + )[0] + }—${min + 1 >= 100 ? 100 : min + 1}`; + updateQuestionsList(quizId, totalIndex, { + content: clonContent, + }); + } + }} /> @@ -72,13 +113,15 @@ export default function SliderOptions({ totalIndex }: Props) { display: "flex", alignItems: "center", justifyContent: "space-between", + gap: "50px", }} > - + Начальное значение - { const clonContent = listQuestions[quizId][totalIndex].content; clonContent.start = Number(target.value); @@ -86,13 +129,31 @@ export default function SliderOptions({ totalIndex }: Props) { content: clonContent, }); }} + onBlur={({ target }) => { + const start = Number(target.value); + const min = Number( + listQuestions[quizId][totalIndex].content.range.split("—")[0] + ); + + if (start < min) { + updateQuestionsList(quizId, totalIndex, { + content: { + ...listQuestions[quizId][totalIndex].content, + start: min, + }, + }); + } + }} /> - + Шаг - { const clonContent = listQuestions[quizId][totalIndex].content; clonContent.step = Number(target.value); @@ -100,6 +161,35 @@ export default function SliderOptions({ totalIndex }: Props) { content: clonContent, }); }} + onBlur={({ target }) => { + const min = Number( + listQuestions[quizId][totalIndex].content.range.split("—")[0] + ); + const max = Number( + listQuestions[quizId][totalIndex].content.range.split("—")[1] + ); + const range = max - min; + const step = Number(target.value); + + if (step > range) { + updateQuestionsList(quizId, totalIndex, { + content: { + ...listQuestions[quizId][totalIndex].content, + step: range, + }, + }); + } + + if (range % step) { + setStepError( + `Шаг должен делить без остатка диапазон ${max} - ${min} = ${ + max - min + }` + ); + } else { + setStepError(""); + } + }} /> diff --git a/src/pages/Questions/SliderOptions/settingSlider.tsx b/src/pages/Questions/SliderOptions/settingSlider.tsx index 4047816c..eec96052 100644 --- a/src/pages/Questions/SliderOptions/settingSlider.tsx +++ b/src/pages/Questions/SliderOptions/settingSlider.tsx @@ -1,6 +1,7 @@ import { useParams } from "react-router-dom"; import { Box, Typography } from "@mui/material"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; +import CustomTextField from "@ui_kit/CustomTextField"; import InfoIcon from "../../../assets/icons/InfoIcon"; import { questionStore, updateQuestionsList } from "@root/questions"; @@ -28,8 +29,43 @@ export default function SettingSlider({ totalIndex }: SettingSliderProps) { Настройки вопросов - - + { + updateQuestionsList(quizId, totalIndex, { + required: !e.target.checked, + }); + }} + /> + + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerNameCheck = e.target.checked; + + if (!e.target.checked) { + clonContent.innerName = ""; + } + + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + />{" "} + + + {listQuestions[quizId][totalIndex].content.innerNameCheck && ( + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerName = target.value; + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + /> + )} ); diff --git a/src/pages/Questions/UploadFile/settingUpload.tsx b/src/pages/Questions/UploadFile/settingUpload.tsx index 9f94c89c..58bf0820 100644 --- a/src/pages/Questions/UploadFile/settingUpload.tsx +++ b/src/pages/Questions/UploadFile/settingUpload.tsx @@ -1,6 +1,7 @@ import { useParams } from "react-router-dom"; import { Box, Typography } from "@mui/material"; import CustomCheckbox from "@ui_kit/CustomCheckbox"; +import CustomTextField from "@ui_kit/CustomTextField"; import { questionStore, updateQuestionsList } from "@root/questions"; @@ -26,8 +27,43 @@ export default function SettingsUpload({ totalIndex }: SettingsUploadProps) { updateQuestionsList(quizId, totalIndex, { content: clonContent }); }} /> - - + { + updateQuestionsList(quizId, totalIndex, { + required: !e.target.checked, + }); + }} + /> + + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerNameCheck = e.target.checked; + + if (!e.target.checked) { + clonContent.innerName = ""; + } + + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + />{" "} + + + {listQuestions[quizId][totalIndex].content.innerNameCheck && ( + { + let clonContent = listQuestions[quizId][totalIndex].content; + clonContent.innerName = target.value; + updateQuestionsList(quizId, totalIndex, { content: clonContent }); + }} + /> + )} ); } diff --git a/src/pages/Questions/answerOptions/responseSettings.tsx b/src/pages/Questions/answerOptions/responseSettings.tsx index ead6d60f..e2084b6b 100644 --- a/src/pages/Questions/answerOptions/responseSettings.tsx +++ b/src/pages/Questions/answerOptions/responseSettings.tsx @@ -14,7 +14,13 @@ export default function ResponseSettings({ totalIndex }: Props) { const { listQuestions } = questionStore(); return ( - + Настройки ответов - + { video: "", dateRange: false, time: false, - starts: 0, form: "star", steps: 5, range: "0—100", @@ -170,6 +170,8 @@ export const createQuestion = (quizId: number) => { chooseRange: false, required: false, replText: "", + ratingExpanded: false, + ratingDescription: "", variants: [ { answer: "", @@ -204,9 +206,11 @@ export const createQuestion = (quizId: number) => { export const copyQuestion = (quizId: number, copiedQuestionIndex: number) => { const listQuestions = { ...questionStore.getState()["listQuestions"] }; - listQuestions[quizId].push({ - ...listQuestions[quizId][copiedQuestionIndex], - }); + listQuestions[quizId].splice( + copiedQuestionIndex, + 0, + listQuestions[quizId][copiedQuestionIndex] + ); questionStore.setState({ listQuestions }); }; diff --git a/src/ui_kit/CustomNumberField.tsx b/src/ui_kit/CustomNumberField.tsx new file mode 100644 index 00000000..37fab7c2 --- /dev/null +++ b/src/ui_kit/CustomNumberField.tsx @@ -0,0 +1,54 @@ +import CustomTextField from "./CustomTextField"; + +import type { ChangeEvent, KeyboardEvent, FocusEvent } from "react"; +import type { SxProps, Theme } from "@mui/material"; + +interface CustomNumberFieldProps { + placeholder: string; + onChange?: (event: ChangeEvent) => void; + onKeyDown?: (event: KeyboardEvent) => void; + onBlur?: (event: FocusEvent) => void; + error?: string; + value: string; + sx?: SxProps; + min?: number; + max?: number; +} + +export default function CustomNumberField({ + placeholder, + value, + sx, + error, + onChange, + onKeyDown, + onBlur, + min = -999999999, + max = 999999999, +}: CustomNumberFieldProps) { + const onInputChange = (event: ChangeEvent) => { + const inputValue = event.target.value; + + if ( + Number(inputValue) >= min && + Number(inputValue) <= max && + (inputValue === "" || + inputValue.match(/^\d*$/) || + (inputValue[0] === "-" && inputValue.slice(1).match(/^\d*$/))) + ) { + onChange?.({ ...event, target: { ...event.target, value: inputValue } }); + } + }; + + return ( + + ); +} diff --git a/src/ui_kit/CustomTextField.tsx b/src/ui_kit/CustomTextField.tsx index e36b4998..a35fadbc 100755 --- a/src/ui_kit/CustomTextField.tsx +++ b/src/ui_kit/CustomTextField.tsx @@ -1,46 +1,69 @@ -import {FormControl, TextField, useTheme, SxProps, Theme} from "@mui/material"; -import {ChangeEvent} from "react"; +import { + FormControl, + TextField, + useTheme, + SxProps, + Theme, +} from "@mui/material"; + +import type { ChangeEvent, KeyboardEvent, FocusEvent } from "react"; interface CustomTextFieldProps { - placeholder: string; - onChange?: (event: ChangeEvent) => void; - text?: string; - sx?: SxProps; + placeholder: string; + value?: string; + error?: string; + onChange?: (event: ChangeEvent) => void; + onKeyDown?: (event: KeyboardEvent) => void; + onBlur?: (event: FocusEvent) => void; + text?: string; + sx?: SxProps; } -export default function CustomTextField({ placeholder, text, sx, onChange}: CustomTextFieldProps) { - const theme = useTheme(); +export default function CustomTextField({ + placeholder, + value, + text, + sx, + error, + onChange, + onKeyDown, + onBlur, +}: CustomTextFieldProps) { + const theme = useTheme(); - return ( - - - - ); -} \ No newline at end of file + return ( + + + + ); +}