покупка при ок
Some checks failed
Deploy / CreateImage (push) Failing after 1m27s
Deploy / DeployService (push) Has been skipped

This commit is contained in:
Nastya 2025-06-08 20:52:55 +03:00
parent 5ea6d6638a
commit 61c0357adc
3 changed files with 142 additions and 93 deletions

@ -1,69 +1,32 @@
import { Box, FormControl, FormLabel, RadioGroup, FormControlLabel, Radio, Select, MenuItem, useTheme, Button, useMediaQuery, IconButton } from "@mui/material";
import { InfoPopover } from '@ui_kit/InfoPopover';
import { Box, FormControl, FormLabel, RadioGroup, FormControlLabel, Radio, useTheme, Button, useMediaQuery } from "@mui/material";
import CheckboxIcon from "@icons/Checkbox";
import { useState } from "react";
import { useCurrentQuiz } from "@/stores/quizes/hooks";
import { auditoryAdd } from "@/api/auditory";
import { useSnackbar } from "notistack";
import ArrowDownIcon from "@/assets/icons/ArrowDownIcon";
import AgeInputWithSelect from "./AgeInputWithSelect";
interface GenderAndAgeSelectorProps {
handleAdd: (item: any) => void;
gender: string;
age: string;
ageError: boolean;
onGenderChange: (gender: string) => void;
onAgeChange: (age: string) => void;
onAgeErrorChange: (error: boolean) => void;
onStartCreate: () => void;
}
export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelectorProps) {
const theme = useTheme();
const [age, setAge] = useState<string>('');
const [gender, setGender] = useState<string>('');
const [selectOpen, setSelectOpen] = useState<boolean>(false);
const quiz = useCurrentQuiz();
const { enqueueSnackbar } = useSnackbar();
const isMobile = useMediaQuery(theme.breakpoints.down(845));
const [ageError, setAgeError] = useState(false);
const addItem = async () => {
if (!quiz?.backendId) {
enqueueSnackbar('Ошибка: не выбран квиз', { variant: 'error' });
return;
}
try {
const [result, error] = await auditoryAdd({
quizId: quiz.backendId,
body: {
sex: gender === "male",
age
}
});
if (error) {
enqueueSnackbar('Не удалось добавить ссылку', { variant: 'error' });
return;
}
if (result) {
handleAdd({
id: result.ID,
quiz_id: quiz.backendId,
sex: gender === "male",
export default function GenderAndAgeSelector({
gender,
age,
deleted: false,
});
enqueueSnackbar('Ссылка успешно добавлена', { variant: 'success' });
// Очищаем форму
setGender('');
setAge('');
}
} catch (error) {
enqueueSnackbar('Произошла ошибка при добавлении', { variant: 'error' });
}
};
ageError,
onGenderChange,
onAgeChange,
onAgeErrorChange,
onStartCreate
}: GenderAndAgeSelectorProps) {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down(845));
return (
<Box sx={{ display: 'flex', gap: 4, alignItems: "end", flexWrap: "wrap" }}>
<Box sx={{ display: "inline-flex", flexWrap: isMobile ? "wrap" : "initial" }}>
<FormControl component="fieldset" variant="standard">
<Box sx={{ display: 'flex', alignItems: "end", gap: '4px' }}>
<FormLabel
@ -79,7 +42,6 @@ export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelector
mr: '3px',
}}
component="legend">Пол</FormLabel>
{/* <InfoPopover /> */}
</Box>
<RadioGroup
sx={{
@ -92,7 +54,7 @@ export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelector
aria-label="gender"
name="row-radio-buttons-group"
value={gender}
onChange={(e) => setGender(e.target.value)}
onChange={(e) => onGenderChange(e.target.value)}
>
<FormControlLabel
sx={{
@ -169,14 +131,13 @@ export default function GenderAndAgeSelector({ handleAdd }: GenderAndAgeSelector
color: '#4D4D4D',
},
}}>Возраст</FormLabel>
{/* <InfoPopover /> */}
</Box>
<AgeInputWithSelect value={age} onChange={setAge} onErrorChange={setAgeError} />
<AgeInputWithSelect value={age} onChange={onAgeChange} onErrorChange={onAgeErrorChange} />
</FormControl>
</Box>
<Button
onClick={addItem}
onClick={onStartCreate}
variant="contained"
disabled={!gender || !age || ageError}
sx={{

@ -1,33 +1,21 @@
import { useUserStore } from "@/stores/user";
import { Box, Button, Modal, Typography } from "@mui/material"
interface Props {
isOpen: boolean;
openCloseHC: (b: boolean) => void;
open: boolean;
onClose: () => void;
onCreate: () => void;
}
export const PayModal = ({
isOpen,
openCloseHC
open,
onClose,
onCreate
}: Props) => {
const privilegesOfUser = useUserStore((state) => state.userAccount?.privileges);
const user = useUserStore((state) => state.customerAccount); //у него есть wallet
return (
<Modal
open={Boolean(isOpen)}
onClose={() => openCloseHC(false)}
open={open}
onClose={onClose}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
@ -37,23 +25,30 @@ export const PayModal = ({
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
maxWidth: "620px",
maxWidth: "550px",
width: "100%",
bgcolor: "background.paper",
borderRadius: "12px",
boxShadow: 24,
p: "20px",
p: "30px",
display: "flex",
flexDirection: "column",
alignItems: "center"
alignItems: "center",
gap: 2
}}
>
<Typography sx={{ width: "100%", textAlign: "center", mb: "25px" }}>Данная услуга предоставляется за 500 рублей/опрос. Готовы оплатить?</Typography>
<Button variant="contained" onClick={() => openCloseHC(false)} >Нет</Button>
<Button sx={{ mb: "20px" }} onClick={handleDelete}>Да</Button>
<Typography sx={{ width: "100%", textAlign: "center", mb: "25px" }}>
Данная услуга предоставляется за 500 рублей/опрос. Готовы оплатить?
</Typography>
<Box sx={{ display: 'flex', gap: 2 }}>
<Button sx={{width: "100px"}} variant="outlined" onClick={onClose}>
Нет
</Button>
<Button sx={{width: "100px"}} variant="contained" onClick={onCreate}>
Да
</Button>
</Box>
</Box>
</Modal>
)
);
}

@ -8,8 +8,11 @@ import { AuditoryItem, auditoryAdd, auditoryDelete, auditoryGet } from "@/api/au
import { useCurrentQuiz } from "@/stores/quizes/hooks";
import { AuditoryList } from "./AuditoryList";
import { useSnackbar } from "notistack";
import { PayModal } from "./PayModal";
import { useUserStore } from "@/stores/user";
import { cartApi } from "@/api/cart";
const tariff = "6844b8858258f5cc35791ef7";
export default function PersonalizationAI() {
const theme = useTheme();
const [auditory, setAuditory] = useState<AuditoryItem[]>([]);
@ -18,6 +21,70 @@ export default function PersonalizationAI() {
const [utmParams, setUtmParams] = useState<string>('');
const quiz = useCurrentQuiz();
const { enqueueSnackbar } = useSnackbar();
const privilegesOfUser = useUserStore((state) => state.userAccount?.privileges);
const [isStartCreate, setStartCreate] = useState(false);
const [gender, setGender] = useState<string>('');
const [age, setAge] = useState<string>('');
const [ageError, setAgeError] = useState(false);
const [isModalOpen, setIsModalOpen] = useState(false);
const resetForm = () => {
setGender('');
setAge('');
setAgeError(false);
};
const checkPrivileges = async () => {
// TODO: Здесь будет проверка прав пользователя
console.log("______________privilegesOfUser");
console.log(privilegesOfUser);
const [_, addError] = await cartApi.add(tariff);
if (addError) return;
//Если нам хватает денежек - покупаем тариф
const [data, payError] = await cartApi.pay();
};
const createNewLink = async () => {
if (!quiz?.backendId) {
enqueueSnackbar('Ошибка: не выбран квиз', { variant: 'error' });
return;
}
try {
const [result, error] = await auditoryAdd({
quizId: quiz.backendId,
body: {
sex: gender === "male",
age
}
});
if (error) {
enqueueSnackbar('Не удалось добавить ссылку', { variant: 'error' });
return;
}
if (result) {
handleAdd({
id: result.ID,
quiz_id: quiz.backendId,
sex: gender === "male",
age,
deleted: false,
});
enqueueSnackbar('Ссылка успешно добавлена', { variant: 'success' });
resetForm();
setIsModalOpen(false);
setStartCreate(false);
}
} catch (error) {
enqueueSnackbar('Произошла ошибка при добавлении', { variant: 'error' });
}
};
useEffect(() => {
(async () => {
@ -74,7 +141,10 @@ export default function PersonalizationAI() {
}
const handleAdd = (item: AuditoryItem) => {
setAuditory(old => ([...old, item]))
setAuditory(old => ([...old, item]));
// Очищаем форму после успешного добавления
setGender('');
setAge('');
}
const handleLinkChange = (e: React.ChangeEvent<HTMLInputElement>) => {
@ -101,6 +171,13 @@ export default function PersonalizationAI() {
setUtmParams(paramString ? `&${paramString}` : "");
};
const startCreate = () => {
setStartCreate(true);
if (checkPrivileges()) {
setIsModalOpen(true);
}
};
return (
<>
<Container id="PersonalizationAI" maxWidth={false} sx={{ minHeight: "100%", p: "20px", height: " calc(100vh - 80px)", overflow: "auto", pt: "55px" }}>
@ -124,7 +201,15 @@ export default function PersonalizationAI() {
boxShadow: "none",
maxWidth: "796px"
}}>
<GenderAndAgeSelector handleAdd={handleAdd} />
<GenderAndAgeSelector
gender={gender}
age={age}
ageError={ageError}
onGenderChange={setGender}
onAgeChange={setAge}
onAgeErrorChange={setAgeError}
onStartCreate={startCreate}
/>
{/* Ссылка */}
<Box sx={{ mt: "34px" }}>
@ -188,6 +273,14 @@ export default function PersonalizationAI() {
<Button variant="contained" onClick={() => setDeleteModal(0)} >Отмена</Button>
</Box>
</Modal>
<PayModal
open={isModalOpen}
onClose={() => {
setIsModalOpen(false);
setStartCreate(false);
}}
onCreate={createNewLink}
/>
</>
);
}