Можно выбрать оба пола
Some checks are pending
Deploy / CreateImage (push) Waiting to run
Deploy / DeployService (push) Blocked by required conditions

This commit is contained in:
Nastya 2025-06-06 16:06:50 +03:00
parent 2efdd0b422
commit 595f4b041b
3 changed files with 151 additions and 16 deletions

@ -1,4 +1,4 @@
import { Box, FormControl, FormLabel, RadioGroup, FormControlLabel, Radio, Select, MenuItem, useTheme, Button, useMediaQuery, IconButton } from "@mui/material"; import { Box, FormControl, FormLabel, FormGroup, FormControlLabel, Checkbox, Select, MenuItem, useTheme, Button, useMediaQuery, IconButton } from "@mui/material";
import { InfoPopover } from '@ui_kit/InfoPopover'; import { InfoPopover } from '@ui_kit/InfoPopover';
import CheckboxIcon from "@icons/Checkbox"; import CheckboxIcon from "@icons/Checkbox";
import { useState } from "react"; import { useState } from "react";
@ -15,7 +15,7 @@ interface GenderAndAgeSelectorProps {
export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelectorProps) { export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelectorProps) {
const theme = useTheme(); const theme = useTheme();
const [age, setAge] = useState<string>(''); const [age, setAge] = useState<string>('');
const [gender, setGender] = useState<string>(''); const [gender, setGender] = useState<string[]>([]);
const [selectOpen, setSelectOpen] = useState<boolean>(false); const [selectOpen, setSelectOpen] = useState<boolean>(false);
const quiz = useCurrentQuiz(); const quiz = useCurrentQuiz();
const { enqueueSnackbar } = useSnackbar(); const { enqueueSnackbar } = useSnackbar();
@ -32,7 +32,7 @@ export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelector
const [result, error] = await auditoryAdd({ const [result, error] = await auditoryAdd({
quizId: quiz.backendId, quizId: quiz.backendId,
body: { body: {
sex: gender === "male", sex: gender.includes("male"),
age age
} }
}); });
@ -46,13 +46,13 @@ export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelector
handleAdd({ handleAdd({
id: result.ID, id: result.ID,
quiz_id: quiz.backendId, quiz_id: quiz.backendId,
sex: gender === "male", sex: gender.includes("male"),
age, age,
deleted: false, deleted: false,
}); });
enqueueSnackbar('Ссылка успешно добавлена', { variant: 'success' }); enqueueSnackbar('Ссылка успешно добавлена', { variant: 'success' });
// Очищаем форму // Очищаем форму
setGender(''); setGender([]);
setAge(''); setAge('');
} }
} catch (error) { } catch (error) {
@ -81,7 +81,7 @@ export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelector
component="legend">Пол</FormLabel> component="legend">Пол</FormLabel>
<InfoPopover /> <InfoPopover />
</Box> </Box>
<RadioGroup <FormGroup
sx={{ sx={{
width: "155px", width: "155px",
justifyContent: "space-between", justifyContent: "space-between",
@ -89,10 +89,6 @@ export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelector
ml: "-9px" ml: "-9px"
}} }}
row row
aria-label="gender"
name="row-radio-buttons-group"
value={gender}
onChange={(e) => setGender(e.target.value)}
> >
<FormControlLabel <FormControlLabel
sx={{ sx={{
@ -119,8 +115,20 @@ export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelector
}, },
m: 0, m: 0,
}} }}
value="male" control={
control={<Radio icon={<CheckboxIcon />} checkedIcon={<CheckboxIcon checked />} />} <Checkbox
checked={gender.includes('male')}
onChange={(e) => {
if (e.target.checked) {
setGender([...gender, 'male']);
} else {
setGender(gender.filter(g => g !== 'male'));
}
}}
icon={<CheckboxIcon />}
checkedIcon={<CheckboxIcon checked />}
/>
}
label="М" label="М"
/> />
<FormControlLabel <FormControlLabel
@ -147,11 +155,23 @@ export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelector
}, },
m: 0, m: 0,
}} }}
value="female" control={
control={<Radio icon={<CheckboxIcon />} checkedIcon={<CheckboxIcon checked />} />} <Checkbox
checked={gender.includes('female')}
onChange={(e) => {
if (e.target.checked) {
setGender([...gender, 'female']);
} else {
setGender(gender.filter(g => g !== 'female'));
}
}}
icon={<CheckboxIcon />}
checkedIcon={<CheckboxIcon checked />}
/>
}
label="Ж" label="Ж"
/> />
</RadioGroup> </FormGroup>
</FormControl> </FormControl>
<FormControl sx={{ maxWidth: "420px", width: "100%", marginLeft: isMobile ? "0" : "120px", minWidth: "265px" }} variant="filled"> <FormControl sx={{ maxWidth: "420px", width: "100%", marginLeft: isMobile ? "0" : "120px", minWidth: "265px" }} variant="filled">
@ -178,7 +198,7 @@ export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelector
<Button <Button
onClick={addItem} onClick={addItem}
variant="contained" variant="contained"
disabled={!gender || !age || ageError} disabled={gender.length === 0 || !age || ageError}
sx={{ sx={{
bgcolor: theme.palette.brightPurple.main, bgcolor: theme.palette.brightPurple.main,
borderRadius: "8px", borderRadius: "8px",

@ -0,0 +1,61 @@
import React from 'react';
import { Box, Typography, useTheme } from '@mui/material';
import { useMediaQuery } from '@mui/material';
import MaleIcon from '@mui/icons-material/Male';
import FemaleIcon from '@mui/icons-material/Female';
import PeopleIcon from '@mui/icons-material/People';
interface GenderButtonProps {
selected: boolean;
onClick: () => void;
icon: 'male' | 'female' | 'both';
label: string;
}
export const GenderButton: React.FC<GenderButtonProps> = ({ selected, onClick, icon, label }) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const getIcon = () => {
switch (icon) {
case 'male':
return <MaleIcon sx={{ fontSize: isMobile ? '20px' : '24px' }} />;
case 'female':
return <FemaleIcon sx={{ fontSize: isMobile ? '20px' : '24px' }} />;
case 'both':
return <PeopleIcon sx={{ fontSize: isMobile ? '20px' : '24px' }} />;
default:
return null;
}
};
return (
<Box
onClick={onClick}
sx={{
display: 'flex',
alignItems: 'center',
gap: '8px',
padding: isMobile ? '8px 12px' : '10px 16px',
borderRadius: '8px',
cursor: 'pointer',
bgcolor: selected ? theme.palette.brightPurple.main : 'transparent',
border: `1px solid ${selected ? theme.palette.brightPurple.main : theme.palette.grey[300]}`,
'&:hover': {
bgcolor: selected ? theme.palette.brightPurple.main : theme.palette.grey[100],
},
}}
>
{getIcon()}
<Typography
sx={{
fontSize: isMobile ? '14px' : '16px',
fontWeight: 500,
color: selected ? theme.palette.common.white : theme.palette.text.primary,
}}
>
{label}
</Typography>
</Box>
);
};

@ -0,0 +1,54 @@
import React from 'react';
import { Box, Typography, useTheme } from '@mui/material';
import { useMediaQuery } from '@mui/material';
import { InfoPopover } from './InfoPopover';
import { GenderButton } from './GenderButton';
interface GenderSelectorProps {
value: string[];
onChange: (value: string[]) => void;
}
export const GenderSelector: React.FC<GenderSelectorProps> = ({ value, onChange }) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
const handleGenderClick = (gender: string) => {
if (value.includes(gender)) {
onChange(value.filter(g => g !== gender));
} else {
onChange([...value, gender]);
}
};
return (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '8px' }}>
<Box sx={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
<Typography
sx={{
fontSize: isMobile ? '14px' : '16px',
fontWeight: 500,
color: theme.palette.text.primary,
}}
>
Пол
</Typography>
<InfoPopover />
</Box>
<Box sx={{ display: 'flex', gap: '8px' }}>
<GenderButton
selected={value.includes('male')}
onClick={() => handleGenderClick('male')}
icon="male"
label="Мужской"
/>
<GenderButton
selected={value.includes('female')}
onClick={() => handleGenderClick('female')}
icon="female"
label="Женский"
/>
</Box>
</Box>
);
};