Merge branch 'dev' into 'staging'

Dev

See merge request frontend/admin!64
This commit is contained in:
Nastya 2024-04-10 15:01:05 +00:00
commit 5a31cb5fde
2 changed files with 358 additions and 329 deletions

@ -8,6 +8,7 @@ export type CreatePromocodeBody = {
privilege: {
privilegeID: string;
amount: number;
serviceKey: string;
};
discount: {
layer: number;

@ -1,12 +1,12 @@
import {
Button,
FormControlLabel,
MenuItem,
Radio,
RadioGroup,
Select,
TextField,
Typography,
Button,
FormControlLabel,
MenuItem,
Radio,
RadioGroup,
Select,
TextField,
Typography,
} from "@mui/material";
import { DesktopDatePicker } from "@mui/x-date-pickers/DesktopDatePicker";
import { Field, Form, Formik } from "formik";
@ -25,345 +25,373 @@ import type { ChangeEvent } from "react";
type BonusType = "discount" | "privilege";
type FormValues = {
codeword: string;
description: string;
greetings: string;
dueTo: number;
activationCount: number;
privilegeId: string;
amount: number;
layer: 1 | 2;
factor: number;
target: string;
threshold: number;
codeword: string;
description: string;
greetings: string;
dueTo: number;
activationCount: number;
privilegeId: string;
amount: number;
layer: 1 | 2;
factor: number;
target: string;
threshold: number;
serviceKey: string;
};
type SelectChangeProps = {
target: {
name: string;
value: string;
};
};
const initialValues: FormValues = {
codeword: "",
description: "",
greetings: "",
dueTo: 0,
activationCount: 0,
privilegeId: "",
amount: 0,
layer: 1,
factor: 0,
target: "",
threshold: 0,
codeword: "",
description: "",
greetings: "",
dueTo: 0,
activationCount: 0,
privilegeId: "",
amount: 0,
layer: 1,
factor: 0,
target: "",
threshold: 0,
serviceKey: "",
};
type Props = {
createPromocode: (body: CreatePromocodeBody) => Promise<void>;
createPromocode: (body: CreatePromocodeBody) => Promise<void>;
};
export const CreatePromocodeForm = ({ createPromocode }: Props) => {
const [bonusType, setBonusType] = useState<BonusType>("discount");
const { privileges } = usePrivilegeStore();
const [bonusType, setBonusType] = useState<BonusType>("discount");
const { privileges } = usePrivilegeStore();
useEffect(() => {
requestPrivileges();
}, []);
useEffect(() => {
requestPrivileges();
}, []);
const submitForm = (values: FormValues) => {
const body = {
...values,
threshold: values.layer === 1 ? values.threshold : values.threshold * 100,
};
const factorFromDiscountValue = 1 - body.factor / 100;
return createPromocode({
codeword: body.codeword,
description: body.description,
greetings: body.greetings,
dueTo: body.dueTo,
activationCount: body.activationCount,
bonus: {
privilege: { privilegeID: body.privilegeId, amount: body.amount },
discount: {
layer: body.layer,
factor: factorFromDiscountValue,
target: body.target,
threshold: body.threshold,
},
},
});
const submitForm = (values: FormValues) => {
const body = {
...values,
threshold: values.layer === 1 ? values.threshold : values.threshold * 100,
};
return (
<Formik initialValues={initialValues} onSubmit={submitForm}>
{({ values, handleChange, handleBlur, setFieldValue }) => (
<Form
style={{
width: "100%",
maxWidth: "600px",
padding: "0 10px",
}}
>
<CustomTextField
name="codeword"
label="Кодовое слово"
required
onChange={handleChange}
/>
<CustomTextField
name="description"
label="Описание"
required
onChange={handleChange}
/>
<CustomTextField
name="greetings"
label="Приветственное сообщение"
required
onChange={handleChange}
/>
<Typography
variant="h4"
sx={{
height: "40px",
fontWeight: "normal",
marginTop: "15px",
color: theme.palette.secondary.main,
}}
>
Время существования промокода
</Typography>
<Field
name="dueTo"
as={DesktopDatePicker}
inputFormat="DD/MM/YYYY"
value={values.dueTo ? new Date(Number(values.dueTo) * 1000) : null}
onChange={(event: any) => {
setFieldValue("dueTo", event.$d.getTime() / 1000 || null);
}}
renderInput={(params: TextFieldProps) => <TextField {...params} />}
InputProps={{
sx: {
height: "40px",
color: theme.palette.secondary.main,
border: "1px solid",
borderColor: theme.palette.secondary.main,
"& .MuiSvgIcon-root": { color: theme.palette.secondary.main },
},
}}
/>
<CustomTextField
name="activationCount"
label="Количество активаций промокода"
onChange={({ target }) =>
setFieldValue(
"activationCount",
Number(target.value.replace(/\D/g, ""))
)
}
/>
<RadioGroup
row
name="bonusType"
value={bonusType}
sx={{ marginTop: "15px" }}
onChange={({ target }: React.ChangeEvent<HTMLInputElement>) => {
setBonusType(target.value as BonusType);
}}
onBlur={handleBlur}
>
<FormControlLabel
value="discount"
control={<Radio color="secondary" />}
label="Скидка"
/>
<FormControlLabel
value="privilege"
control={<Radio color="secondary" />}
label="Привилегия"
/>
</RadioGroup>
{bonusType === "discount" && (
<>
<RadioGroup
row
name="layer"
value={values.layer}
sx={{ marginTop: "15px" }}
onChange={({ target }: React.ChangeEvent<HTMLInputElement>) => {
setFieldValue("target", "");
setFieldValue("layer", Number(target.value));
}}
onBlur={handleBlur}
>
<FormControlLabel
value="1"
control={<Radio color="secondary" />}
label="Привилегия"
/>
<FormControlLabel
value="2"
control={<Radio color="secondary" />}
label="Сервис"
/>
</RadioGroup>
<CustomTextField
name="factor"
label="Процент скидки"
required
onChange={({ target }) => {
setFieldValue(
"factor",
Number(target.value.replace(/\D/g, ""))
);
}}
/>
<Typography
variant="h4"
sx={{
height: "40px",
fontWeight: "normal",
marginTop: "15px",
padding: "0 12px",
color: theme.palette.secondary.main,
}}
>
{values.layer === 1 ? "Выбор привилегии" : "Выбор сервиса"}
</Typography>
<Field
name="target"
as={Select}
label={values.layer === 1 ? "Привилегия" : "Сервис"}
sx={{
width: "100%",
border: "2px solid",
color: theme.palette.secondary.main,
borderColor: theme.palette.secondary.main,
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
border: "none",
},
".MuiSvgIcon-root ": { fill: theme.palette.secondary.main },
}}
children={
values.layer === 1
? privileges.map(({ name, privilegeId }) => (
<MenuItem key={privilegeId} value={privilegeId}>
{name}
</MenuItem>
))
: SERVICE_LIST.map(({ displayName, serviceKey }) => (
<MenuItem key={serviceKey} value={serviceKey}>
{displayName}
</MenuItem>
))
}
/>
<CustomTextField
name="threshold"
label="При каком значении применяется скидка"
onChange={({ target }) =>
setFieldValue(
"threshold",
Number(target.value.replace(/\D/g, ""))
)
}
/>
</>
)}
{bonusType === "privilege" && (
<>
<Typography
variant="h4"
sx={{
height: "40px",
fontWeight: "normal",
marginTop: "15px",
padding: "0 12px",
color: theme.palette.secondary.main,
}}
>
Выбор привилегии
</Typography>
<Field
name="privilegeId"
as={Select}
label="Привилегия"
sx={{
width: "100%",
border: "2px solid",
color: theme.palette.secondary.main,
borderColor: theme.palette.secondary.main,
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
border: "none",
},
".MuiSvgIcon-root ": { fill: theme.palette.secondary.main },
}}
children={privileges.map(({ name, privilegeId }) => (
<MenuItem key={privilegeId} value={privilegeId}>
{name}
</MenuItem>
))}
/>
<CustomTextField
name="amount"
label="Количество"
required
onChange={({ target }) =>
setFieldValue(
"amount",
Number(target.value.replace(/\D/g, ""))
)
}
/>
</>
)}
<Button
variant="contained"
sx={{
display: "block",
padding: "10px",
margin: "15px auto 0",
fontWeight: "normal",
fontSize: "18px",
backgroundColor: theme.palette.menu.main,
"&:hover": { backgroundColor: theme.palette.grayMedium.main },
}}
type="submit"
>
Cоздать
</Button>
</Form>
)}
</Formik>
);
const factorFromDiscountValue = 1 - body.factor / 100;
return createPromocode({
codeword: body.codeword,
description: body.description,
greetings: body.greetings,
dueTo: body.dueTo,
activationCount: body.activationCount,
bonus: {
privilege: {
privilegeID: body.privilegeId,
amount: body.amount,
serviceKey: body.serviceKey,
},
discount: {
layer: body.layer,
factor: factorFromDiscountValue,
target: body.target,
threshold: body.threshold,
},
},
});
};
return (
<Formik initialValues={initialValues} onSubmit={submitForm}>
{({ values, handleChange, handleBlur, setFieldValue }) => (
<Form
style={{
width: "100%",
maxWidth: "600px",
padding: "0 10px",
}}
>
<CustomTextField
name="codeword"
label="Кодовое слово"
required
onChange={handleChange}
/>
<CustomTextField
name="description"
label="Описание"
required
onChange={handleChange}
/>
<CustomTextField
name="greetings"
label="Приветственное сообщение"
required
onChange={handleChange}
/>
<Typography
variant="h4"
sx={{
height: "40px",
fontWeight: "normal",
marginTop: "15px",
color: theme.palette.secondary.main,
}}
>
Время существования промокода
</Typography>
<Field
name="dueTo"
as={DesktopDatePicker}
inputFormat="DD/MM/YYYY"
value={values.dueTo ? new Date(Number(values.dueTo) * 1000) : null}
onChange={(event: any) => {
setFieldValue("dueTo", event.$d.getTime() / 1000 || null);
}}
renderInput={(params: TextFieldProps) => <TextField {...params} />}
InputProps={{
sx: {
height: "40px",
color: theme.palette.secondary.main,
border: "1px solid",
borderColor: theme.palette.secondary.main,
"& .MuiSvgIcon-root": { color: theme.palette.secondary.main },
},
}}
/>
<CustomTextField
name="activationCount"
label="Количество активаций промокода"
onChange={({ target }) =>
setFieldValue(
"activationCount",
Number(target.value.replace(/\D/g, ""))
)
}
/>
<RadioGroup
row
name="bonusType"
value={bonusType}
sx={{ marginTop: "15px" }}
onChange={({ target }: React.ChangeEvent<HTMLInputElement>) => {
setBonusType(target.value as BonusType);
}}
onBlur={handleBlur}
>
<FormControlLabel
value="discount"
control={<Radio color="secondary" />}
label="Скидка"
/>
<FormControlLabel
value="privilege"
control={<Radio color="secondary" />}
label="Привилегия"
/>
</RadioGroup>
{bonusType === "discount" && (
<>
<RadioGroup
row
name="layer"
value={values.layer}
sx={{ marginTop: "15px" }}
onChange={({ target }: React.ChangeEvent<HTMLInputElement>) => {
setFieldValue("target", "");
setFieldValue("layer", Number(target.value));
}}
onBlur={handleBlur}
>
<FormControlLabel
value="1"
control={<Radio color="secondary" />}
label="Привилегия"
/>
<FormControlLabel
value="2"
control={<Radio color="secondary" />}
label="Сервис"
/>
</RadioGroup>
<CustomTextField
name="factor"
label="Процент скидки"
required
onChange={({ target }) => {
setFieldValue(
"factor",
Number(target.value.replace(/\D/g, ""))
);
}}
/>
<Typography
variant="h4"
sx={{
height: "40px",
fontWeight: "normal",
marginTop: "15px",
padding: "0 12px",
color: theme.palette.secondary.main,
}}
>
{values.layer === 1 ? "Выбор привилегии" : "Выбор сервиса"}
</Typography>
<Field
name="target"
as={Select}
label={values.layer === 1 ? "Привилегия" : "Сервис"}
onChange={({ target }: SelectChangeProps) => {
if (values.layer === 1) {
const currentPrivilege = privileges.find(
(item) => item.privilegeId === target.value
);
setFieldValue("serviceKey", currentPrivilege?.serviceKey);
setFieldValue("privilegeId", currentPrivilege?.privilegeId);
return;
}
setFieldValue("privilegeId", target.value);
}}
sx={{
width: "100%",
border: "2px solid",
color: theme.palette.secondary.main,
borderColor: theme.palette.secondary.main,
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
border: "none",
},
".MuiSvgIcon-root ": { fill: theme.palette.secondary.main },
}}
value={values.privilegeId}
children={
values.layer === 1
? privileges.map(({ name, privilegeId }) => (
<MenuItem key={privilegeId} value={privilegeId}>
{name}
</MenuItem>
))
: SERVICE_LIST.map(({ displayName, serviceKey }) => (
<MenuItem key={serviceKey} value={serviceKey}>
{displayName}
</MenuItem>
))
}
/>
<CustomTextField
name="threshold"
label="При каком значении применяется скидка"
onChange={({ target }) =>
setFieldValue(
"threshold",
Number(target.value.replace(/\D/g, ""))
)
}
/>
</>
)}
{bonusType === "privilege" && (
<>
<Typography
variant="h4"
sx={{
height: "40px",
fontWeight: "normal",
marginTop: "15px",
padding: "0 12px",
color: theme.palette.secondary.main,
}}
>
Выбор привилегии
</Typography>
<Field
name="privilegeId"
as={Select}
label="Привилегия"
sx={{
width: "100%",
border: "2px solid",
color: theme.palette.secondary.main,
borderColor: theme.palette.secondary.main,
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
border: "none",
},
".MuiSvgIcon-root ": { fill: theme.palette.secondary.main },
}}
children={privileges.map(({ name, privilegeId }) => (
<MenuItem key={privilegeId} value={privilegeId}>
{name}
</MenuItem>
))}
/>
<CustomTextField
name="amount"
label="Количество"
required
onChange={({ target }) =>
setFieldValue(
"amount",
Number(target.value.replace(/\D/g, ""))
)
}
/>
</>
)}
<Button
variant="contained"
sx={{
display: "block",
padding: "10px",
margin: "15px auto 0",
fontWeight: "normal",
fontSize: "18px",
backgroundColor: theme.palette.menu.main,
"&:hover": { backgroundColor: theme.palette.grayMedium.main },
}}
type="submit"
>
Cоздать
</Button>
</Form>
)}
</Formik>
);
};
type CustomTextFieldProps = {
name: string;
label: string;
required?: boolean;
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
name: string;
label: string;
required?: boolean;
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
};
const CustomTextField = ({
name,
label,
required = false,
onChange,
name,
label,
required = false,
onChange,
}: CustomTextFieldProps) => (
<Field
name={name}
label={label}
required={required}
variant="filled"
color="secondary"
as={TextField}
onChange={onChange}
sx={{ width: "100%", marginTop: "15px" }}
InputProps={{
style: {
backgroundColor: theme.palette.content.main,
color: theme.palette.secondary.main,
},
}}
InputLabelProps={{
style: { color: theme.palette.secondary.main },
}}
/>
<Field
name={name}
label={label}
required={required}
variant="filled"
color="secondary"
as={TextField}
onChange={onChange}
sx={{ width: "100%", marginTop: "15px" }}
InputProps={{
style: {
backgroundColor: theme.palette.content.main,
color: theme.palette.secondary.main,
},
}}
InputLabelProps={{
style: { color: theme.palette.secondary.main },
}}
/>
);