дизабл кнопки при некорректных условиях
This commit is contained in:
parent
f5a4bdc36f
commit
f0a977031d
@ -18,9 +18,10 @@ import ArrowDownIcon from "@/assets/icons/ArrowDownIcon";
|
|||||||
interface AgeInputWithSelectProps {
|
interface AgeInputWithSelectProps {
|
||||||
value: string;
|
value: string;
|
||||||
onChange: (value: string) => void;
|
onChange: (value: string) => void;
|
||||||
|
onErrorChange?: (isError: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AgeInputWithSelect = ({ value, onChange }: AgeInputWithSelectProps) => {
|
const AgeInputWithSelect = ({ value, onChange, onErrorChange }: AgeInputWithSelectProps) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const anchorRef = useRef<HTMLDivElement>(null);
|
const anchorRef = useRef<HTMLDivElement>(null);
|
||||||
@ -30,36 +31,36 @@ const AgeInputWithSelect = ({ value, onChange }: AgeInputWithSelectProps) => {
|
|||||||
const validate = (val: string) => {
|
const validate = (val: string) => {
|
||||||
if (!val) return false;
|
if (!val) return false;
|
||||||
// Число (только положительное)
|
// Число (только положительное)
|
||||||
if (/^\d+$/.test(val)) {
|
if (/^-?\d+$/.test(val)) {
|
||||||
const num = Number(val);
|
const num = Number(val);
|
||||||
if (num < 0 || num > 150) return 'range';
|
if (num < 0 || num > 150) return 'range';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Диапазон (только положительные числа)
|
// Диапазон (только положительные числа)
|
||||||
const rangeMatch = val.match(/^(\d+)-(\d+)$/);
|
const rangeMatch = val.match(/^(-?\d+)-(-?\d+)$/);
|
||||||
if (rangeMatch) {
|
if (rangeMatch) {
|
||||||
const left = Number(rangeMatch[1]);
|
const left = Number(rangeMatch[1]);
|
||||||
const right = Number(rangeMatch[2]);
|
const right = Number(rangeMatch[2]);
|
||||||
if (left < 0 || left > 150 || right < 0 || right > 150 || left > right) return 'range';
|
if (left < 0 || left > 150 || right < 0 || right > 150 || left > right) return 'range';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Если есть минус не в начале диапазона — это ошибка диапазона
|
|
||||||
if (/^-?\d+-\d+$/.test(val) || /^\d+-\d+-\d+$/.test(val)) {
|
|
||||||
return 'range';
|
|
||||||
}
|
|
||||||
return 'format';
|
return 'format';
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
const filtered = e.target.value.replace(/[^\d-]/g, '');
|
const filtered = e.target.value.replace(/[^\d-]/g, '');
|
||||||
onChange(filtered);
|
onChange(filtered);
|
||||||
setErrorType(false);
|
const err = validate(filtered);
|
||||||
|
setErrorType(err);
|
||||||
|
if (onErrorChange) onErrorChange(!!err);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleInputBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
const handleInputBlur = (e: React.FocusEvent<HTMLInputElement>) => {
|
||||||
const trimmed = e.target.value.replace(/\s+/g, '');
|
const trimmed = e.target.value.replace(/\s+/g, '');
|
||||||
onChange(trimmed);
|
onChange(trimmed);
|
||||||
setErrorType(validate(trimmed));
|
const err = validate(trimmed);
|
||||||
|
setErrorType(err);
|
||||||
|
if (onErrorChange) onErrorChange(!!err);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectItemClick = (selectedValue: string) => {
|
const handleSelectItemClick = (selectedValue: string) => {
|
||||||
|
@ -19,9 +19,8 @@ export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelector
|
|||||||
const [selectOpen, setSelectOpen] = useState<boolean>(false);
|
const [selectOpen, setSelectOpen] = useState<boolean>(false);
|
||||||
const quiz = useCurrentQuiz();
|
const quiz = useCurrentQuiz();
|
||||||
const { enqueueSnackbar } = useSnackbar();
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(800));
|
const isMobile = useMediaQuery(theme.breakpoints.down(845));
|
||||||
|
const [ageError, setAgeError] = useState(false);
|
||||||
const isFormValid = gender && age;
|
|
||||||
|
|
||||||
const addItem = async () => {
|
const addItem = async () => {
|
||||||
if (!quiz?.backendId) {
|
if (!quiz?.backendId) {
|
||||||
@ -172,14 +171,14 @@ export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelector
|
|||||||
}}>Возраст</FormLabel>
|
}}>Возраст</FormLabel>
|
||||||
<InfoPopover />
|
<InfoPopover />
|
||||||
</Box>
|
</Box>
|
||||||
<AgeInputWithSelect value={age} onChange={setAge} />
|
<AgeInputWithSelect value={age} onChange={setAge} onErrorChange={setAgeError} />
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
onClick={addItem}
|
onClick={addItem}
|
||||||
variant="contained"
|
variant="contained"
|
||||||
disabled={!isFormValid}
|
disabled={!gender || !age || ageError}
|
||||||
sx={{
|
sx={{
|
||||||
bgcolor: theme.palette.brightPurple.main,
|
bgcolor: theme.palette.brightPurple.main,
|
||||||
borderRadius: "8px",
|
borderRadius: "8px",
|
||||||
|
Loading…
Reference in New Issue
Block a user