adminFront/src/pages/dashboard/Content/PromocodeManagement/CreatePromocodeForm.tsx
2024-03-22 13:27:36 +03:00

370 lines
15 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
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";
import { useEffect, useState } from "react";
import { requestPrivileges } from "@root/services/privilegies.service";
import { usePrivilegeStore } from "@root/stores/privilegesStore";
import { SERVICE_LIST } from "@root/model/privilege";
import theme from "@root/theme";
import type { TextFieldProps } from "@mui/material";
import { CreatePromocodeBody } from "@root/model/promocodes";
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;
};
const initialValues: FormValues = {
codeword: "",
description: "",
greetings: "",
dueTo: 0,
activationCount: 0,
privilegeId: "",
amount: 0,
layer: 1,
factor: 0,
target: "",
threshold: 0,
};
type Props = {
createPromocode: (body: CreatePromocodeBody) => Promise<void>;
};
export const CreatePromocodeForm = ({ createPromocode }: Props) => {
const [bonusType, setBonusType] = useState<BonusType>("discount");
const { privileges } = usePrivilegeStore();
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,
},
},
});
};
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>
);
};
type CustomTextFieldProps = {
name: string;
label: string;
required?: boolean;
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
};
const CustomTextField = ({
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 },
}}
/>
);