698 lines
21 KiB
TypeScript
698 lines
21 KiB
TypeScript
import * as React from "react";
|
||
import { Box, Typography, TextField, Checkbox, Button } from "@mui/material";
|
||
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
|
||
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
|
||
import { DesktopDatePicker } from "@mui/x-date-pickers/DesktopDatePicker";
|
||
import Table from "@mui/material/Table";
|
||
import TableBody from "@mui/material/TableBody";
|
||
import TableCell from "@mui/material/TableCell";
|
||
import TableRow from "@mui/material/TableRow";
|
||
import TableContainer from "@mui/material/TableContainer";
|
||
import Paper from "@mui/material/Paper";
|
||
import { DataGrid, GridColDef, GridSelectionModel, GridToolbar } from "@mui/x-data-grid";
|
||
import MenuItem from "@mui/material/MenuItem";
|
||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||
import theme from "../../../../theme";
|
||
import { styled } from "@mui/material/styles";
|
||
import { Discount } from "../../../../model/cart";
|
||
import { useDiscountStore } from "../../../../stores/discounts";
|
||
|
||
|
||
const BoxButton = styled('div')(({ theme }) => ({
|
||
[theme.breakpoints.down(400)]: {
|
||
justifyContent: 'center'
|
||
},
|
||
}));
|
||
|
||
|
||
const columns: GridColDef[] = [
|
||
{
|
||
field: "id",
|
||
headerName: "ID",
|
||
width: 30,
|
||
sortable: false,
|
||
},
|
||
{
|
||
field: "name",
|
||
headerName: "Название скидки",
|
||
width: 200,
|
||
sortable: false,
|
||
},
|
||
{
|
||
field: "endless",
|
||
headerName: "Бесконечная",
|
||
width: 120,
|
||
sortable: false,
|
||
},
|
||
{
|
||
field: "from",
|
||
headerName: "От",
|
||
width: 120,
|
||
sortable: false,
|
||
},
|
||
{
|
||
field: "dueTo",
|
||
headerName: "До",
|
||
width: 120,
|
||
sortable: false,
|
||
},
|
||
{
|
||
field: "privileges",
|
||
headerName: "Привилегии",
|
||
width: 210,
|
||
sortable: false,
|
||
},
|
||
{
|
||
field: "active",
|
||
headerName: "Активна",
|
||
width: 100,
|
||
sortable: false,
|
||
},
|
||
{
|
||
field: "basketMore",
|
||
headerName: "Корзина больше",
|
||
width: 140,
|
||
sortable: false,
|
||
}
|
||
,
|
||
{
|
||
field: "toTime",
|
||
headerName: "На время",
|
||
width: 140,
|
||
sortable: false,
|
||
}
|
||
,
|
||
{
|
||
field: "toCapacity",
|
||
headerName: "На объем",
|
||
width: 140,
|
||
sortable: false,
|
||
}
|
||
];
|
||
|
||
|
||
const Discounts: React.FC = () => {
|
||
const [checkboxState, setCheckboxState] = React.useState<boolean>(false);
|
||
const toggleCheckbox = () => { setCheckboxState(!checkboxState); };
|
||
|
||
const [value1, setValue1] = React.useState<Date>(new Date());
|
||
const [value2, setValue2] = React.useState<Date>(new Date());
|
||
|
||
const [service, setService] = React.useState("Шаблонизатор");
|
||
const handleChange = (event: SelectChangeEvent) => {
|
||
setService(event.target.value as string);
|
||
};
|
||
|
||
const discountsArray = useDiscountStore(state => state.discountsArray);
|
||
const discountsArraySet = useDiscountStore(state => state.setDiscountsArray);
|
||
|
||
const discountsActiveArray = useDiscountStore(state => state.discountsActiveArray);
|
||
const discountsActiveArraySet = useDiscountStore(state => state.setDiscountsActiveArray);
|
||
let discountsActiveArrayUpdated: Array<number>;
|
||
|
||
const findActiveDiscounts = () => {
|
||
const actives: Array<number> = [];
|
||
|
||
discountsArray.forEach((item, i) => {
|
||
if (item.active == true) { actives.push(i); }
|
||
});
|
||
|
||
discountsActiveArrayUpdated = [...actives];
|
||
|
||
if (JSON.stringify(discountsActiveArray) != JSON.stringify(discountsActiveArrayUpdated)) {
|
||
discountsActiveArraySet(discountsActiveArrayUpdated);
|
||
}
|
||
};
|
||
|
||
findActiveDiscounts();
|
||
|
||
const discountsArrayConverted = discountsArray.map((item) => {
|
||
const basketMorePerc = Math.round(Number(item.basketMore) * 100) + "%";
|
||
const toTimePerc = Math.round(Number(item.toTime) * 100) + "%";
|
||
const toCapacityPerc = Math.round(Number(item.toCapacity) * 100) + "%";
|
||
|
||
const dateFrom = item.from ? new Date(Number(item.from)) : "";
|
||
const dateDueTo = item.from ? new Date(Number(item.dueTo)) : "";
|
||
|
||
const strFrom = dateFrom
|
||
? `${dateFrom.getDate()}.${dateFrom.getMonth()}.${dateFrom.getFullYear()}`
|
||
: "-";
|
||
|
||
const strDueTo = dateDueTo
|
||
? `${dateDueTo.getDate()}.${dateDueTo.getMonth()}.${dateDueTo.getFullYear()}`
|
||
: "-";
|
||
|
||
if (item.privileges.length) {
|
||
const result = item.privileges.reduce((acc, privilege) => {
|
||
acc = acc
|
||
? `${acc}, ${privilege.good} - ${privilege.discount}%`
|
||
: `${privilege.good} - ${Math.round(privilege.discount * 100)}%`;
|
||
|
||
return acc;
|
||
}, "");
|
||
|
||
return {
|
||
...item, privileges: result, from: strFrom, dueTo: strDueTo,
|
||
basketMore: basketMorePerc, toTime: toTimePerc, toCapacity: toCapacityPerc
|
||
};
|
||
} else {
|
||
return {
|
||
...item, from: strFrom, dueTo: strDueTo,
|
||
basketMore: basketMorePerc, toTime: toTimePerc, toCapacity: toCapacityPerc
|
||
};
|
||
}
|
||
});
|
||
|
||
const createDiscount = (name: string,
|
||
discount: number,
|
||
addedMore: number,
|
||
basketMore: number,
|
||
toTime: number,
|
||
toCapacity: number,) => {
|
||
const newDiscount = {
|
||
id: new Date().getTime(),
|
||
name,
|
||
endless: checkboxState,
|
||
incomeMore: addedMore,
|
||
from: checkboxState ? "" : new Date(value1).getTime() + "",
|
||
dueTo: checkboxState ? "" : new Date(value2).getTime() + "",
|
||
privileges: [{
|
||
good: service,
|
||
discount: discount / 100
|
||
}],
|
||
active: false,
|
||
basketMore: basketMore / 100,
|
||
toTime: toTime / 100,
|
||
toCapacity: toCapacity / 100
|
||
} as Discount;
|
||
|
||
const discountsArrayUpdated = [...discountsArray, newDiscount];
|
||
discountsArraySet(discountsArrayUpdated);
|
||
};
|
||
|
||
const fieldName = React.useRef<HTMLInputElement | null>(null);
|
||
const fieldDiscount = React.useRef<HTMLInputElement | null>(null);
|
||
const fieldAddedMore = React.useRef<HTMLInputElement | null>(null);
|
||
const basketMore = React.useRef<HTMLInputElement | null>(null);
|
||
const toTime = React.useRef<HTMLInputElement | null>(null);
|
||
const toCapacity = React.useRef<HTMLInputElement | null>(null);
|
||
|
||
// const cleraAddedMore = () => {
|
||
// if (fieldAddedMore.current) {
|
||
// fieldAddedMore.current.value = "";
|
||
// }
|
||
// }
|
||
|
||
const checkFields = () => {
|
||
if (fieldName.current != null
|
||
&& fieldDiscount.current != null
|
||
&& fieldAddedMore.current != null
|
||
&& basketMore.current != null
|
||
&& toTime.current != null
|
||
&& toCapacity.current != null) {
|
||
|
||
createDiscount(fieldName.current.value,
|
||
Number(fieldDiscount.current.value),
|
||
Number(fieldAddedMore.current.value),
|
||
Number(basketMore.current.value),
|
||
Number(toTime.current.value),
|
||
Number(toCapacity.current.value));
|
||
|
||
}
|
||
};
|
||
|
||
const discountsSelectedRowsData = useDiscountStore(state => state.discountsSelectedRowsData);
|
||
const discountsSelectedRowsDataSet = useDiscountStore(state => state.setDiscountsSelectedRowsData);
|
||
|
||
const onRowsSelectionHandler = (ids: GridSelectionModel) => {
|
||
const result: Array<Discount> = [];
|
||
ids.forEach((id) => discountsArray.forEach((row) => {
|
||
if (row.id === id) result.push(row);
|
||
}));
|
||
|
||
discountsSelectedRowsDataSet([...result]);
|
||
};
|
||
|
||
const activation = (value: boolean) => {
|
||
discountsArray.forEach((item, i) => {
|
||
discountsSelectedRowsData.forEach((selected) => {
|
||
if (item.id == selected.id) {
|
||
if (value) {
|
||
discountsArray[i].active = true;
|
||
} else {
|
||
discountsArray[i].active = false;
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
discountsArraySet(discountsArray);
|
||
};
|
||
|
||
const PositiveInput = (event: any) => {
|
||
const numberInput = parseInt(event.target.value);
|
||
if (isNaN(numberInput) || numberInput < 0) { event.target.value = '0'; }
|
||
};
|
||
|
||
|
||
return (
|
||
<React.Fragment>
|
||
<LocalizationProvider dateAdapter={AdapterDayjs}>
|
||
<Typography
|
||
variant="subtitle1"
|
||
sx={{
|
||
width: "90%",
|
||
height: "60px",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
color: theme.palette.secondary.main
|
||
}}>
|
||
СКИДКИ
|
||
</Typography>
|
||
|
||
<Box
|
||
sx={{
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "left",
|
||
alignItems: "left",
|
||
marginTop: "15px",
|
||
}}
|
||
>
|
||
<TextField
|
||
id="standard-basic"
|
||
label={"Название"}
|
||
variant="filled"
|
||
color="secondary"
|
||
sx={{
|
||
height: "30px",
|
||
}}
|
||
InputProps={{
|
||
style: {
|
||
backgroundColor: theme.palette.content.main,
|
||
color: theme.palette.secondary.main,
|
||
}
|
||
}}
|
||
InputLabelProps={{
|
||
style: {
|
||
color: theme.palette.secondary.main
|
||
}
|
||
}}
|
||
inputRef={fieldName}
|
||
/>
|
||
|
||
<Typography
|
||
variant="h4"
|
||
sx={{
|
||
width: "90%",
|
||
height: "40px",
|
||
fontWeight: "normal",
|
||
color: theme.palette.grayDisabled.main,
|
||
marginTop: "75px",
|
||
paddingLeft: '10px',
|
||
}}>
|
||
Условия:
|
||
</Typography>
|
||
|
||
<Select
|
||
labelId="demo-simple-select-label"
|
||
id="demo-simple-select"
|
||
value={service}
|
||
label="Age"
|
||
onChange={handleChange}
|
||
sx={{
|
||
color: theme.palette.secondary.main,
|
||
border: "1px solid",
|
||
borderColor: theme.palette.secondary.main,
|
||
"&.Mui-focused .MuiOutlinedInput-notchedOutline": {
|
||
borderColor: theme.palette.secondary.main
|
||
},
|
||
".MuiSvgIcon-root ": {
|
||
fill: theme.palette.secondary.main,
|
||
}
|
||
}}
|
||
>
|
||
<MenuItem value={"Шаблонизатор"}>Шаблонизатор</MenuItem>
|
||
<MenuItem value={"Опросник"}>Опросник</MenuItem>
|
||
<MenuItem value={"Аналитика сокращателя"}>Аналитика сокращателя</MenuItem>
|
||
<MenuItem value={"АБ тесты"}>АБ тесты</MenuItem>
|
||
</Select>
|
||
|
||
<TextField
|
||
id="standard-basic"
|
||
label={"Процент скидки"}
|
||
variant="filled"
|
||
color="secondary"
|
||
sx={{
|
||
marginTop: "15px"
|
||
}}
|
||
InputProps={{
|
||
style: {
|
||
backgroundColor: theme.palette.content.main,
|
||
color: theme.palette.secondary.main,
|
||
}
|
||
}}
|
||
InputLabelProps={{
|
||
style: {
|
||
color: theme.palette.secondary.main
|
||
}
|
||
}}
|
||
inputRef={fieldDiscount}
|
||
/>
|
||
|
||
<TextField
|
||
id="standard-basic"
|
||
label={"Внесено больше"}
|
||
variant="filled"
|
||
color="secondary"
|
||
type="number"
|
||
sx={{
|
||
marginTop: "15px"
|
||
}}
|
||
InputProps={{
|
||
style: {
|
||
backgroundColor: theme.palette.content.main,
|
||
color: theme.palette.secondary.main,
|
||
}
|
||
}}
|
||
InputLabelProps={{
|
||
style: {
|
||
color: theme.palette.secondary.main
|
||
}
|
||
}}
|
||
inputRef={fieldAddedMore}
|
||
onChange={PositiveInput}
|
||
/>
|
||
|
||
<TextField
|
||
id="standard-basic"
|
||
label={"Объем в корзине"}
|
||
variant="filled"
|
||
color="secondary"
|
||
type="number"
|
||
sx={{
|
||
marginTop: "15px"
|
||
}}
|
||
InputProps={{
|
||
style: {
|
||
backgroundColor: theme.palette.content.main,
|
||
color: theme.palette.secondary.main,
|
||
}
|
||
}}
|
||
InputLabelProps={{
|
||
style: {
|
||
color: theme.palette.secondary.main
|
||
}
|
||
}}
|
||
inputRef={basketMore}
|
||
onChange={PositiveInput}
|
||
/>
|
||
|
||
<TextField
|
||
id="standard-basic"
|
||
label={"На время"}
|
||
variant="filled"
|
||
color="secondary"
|
||
type="number"
|
||
sx={{
|
||
marginTop: "15px"
|
||
}}
|
||
InputProps={{
|
||
style: {
|
||
backgroundColor: theme.palette.content.main,
|
||
color: theme.palette.secondary.main,
|
||
}
|
||
}}
|
||
InputLabelProps={{
|
||
style: {
|
||
color: theme.palette.secondary.main
|
||
}
|
||
}}
|
||
inputRef={toTime}
|
||
onChange={PositiveInput}
|
||
/>
|
||
|
||
<TextField
|
||
id="standard-basic"
|
||
label={"На объем"}
|
||
variant="filled"
|
||
color="secondary"
|
||
type="number"
|
||
sx={{
|
||
marginTop: "15px"
|
||
}}
|
||
InputProps={{
|
||
style: {
|
||
backgroundColor: theme.palette.content.main,
|
||
color: theme.palette.secondary.main,
|
||
}
|
||
}}
|
||
InputLabelProps={{
|
||
style: {
|
||
color: theme.palette.secondary.main
|
||
}
|
||
}}
|
||
inputRef={toCapacity}
|
||
onChange={PositiveInput}
|
||
/>
|
||
|
||
<TableContainer component={Paper} sx={{
|
||
width: "100%",
|
||
marginTop: "35px",
|
||
backgroundColor: theme.palette.content.main
|
||
}}>
|
||
<Table aria-label="simple table">
|
||
<TableBody>
|
||
<TableRow sx={{ border: "1px solid white" }} >
|
||
<TableCell component="th" scope="row" sx={{ color: theme.palette.secondary.main }}>
|
||
Работает, если заплатите 100500 денег
|
||
</TableCell>
|
||
</TableRow>
|
||
<TableRow sx={{ border: "1px solid white" }} >
|
||
<TableCell component="th" scope="row" sx={{ color: theme.palette.secondary.main }}>
|
||
Вы должны будете продать душу дьяволу
|
||
</TableCell>
|
||
</TableRow>
|
||
</TableBody>
|
||
</Table>
|
||
</TableContainer>
|
||
|
||
<Typography
|
||
variant="h4"
|
||
sx={{
|
||
width: "90%",
|
||
height: "40px",
|
||
fontWeight: "normal",
|
||
color: theme.palette.grayDisabled.main,
|
||
marginTop: "55px"
|
||
}}>
|
||
Дата действия:
|
||
</Typography>
|
||
|
||
<Box
|
||
sx={{
|
||
width: "100%",
|
||
display: "flex",
|
||
flexWrap: 'wrap'
|
||
}}
|
||
>
|
||
<Typography sx={{
|
||
width: "35px",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "center",
|
||
alignItems: "left",
|
||
}}>С</Typography>
|
||
|
||
<DesktopDatePicker
|
||
inputFormat="DD/MM/YYYY"
|
||
value={value1}
|
||
onChange={(e) => { if (e) { setValue1(e); } }}
|
||
renderInput={(params) => <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 }
|
||
}
|
||
}}
|
||
/>
|
||
|
||
<Typography sx={{
|
||
width: "65px",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
}}>по</Typography>
|
||
|
||
<DesktopDatePicker
|
||
inputFormat="DD/MM/YYYY"
|
||
value={value2}
|
||
onChange={(e) => { if (e) { setValue2(e); } }}
|
||
renderInput={(params) => <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 }
|
||
}
|
||
}}
|
||
/>
|
||
</Box>
|
||
|
||
|
||
<Box sx={{
|
||
display: "flex",
|
||
width: "90%",
|
||
marginTop: theme.spacing(2),
|
||
}}>
|
||
<Box sx={{
|
||
width: "20px",
|
||
height: "42px",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "left",
|
||
alignItems: "left",
|
||
marginRight: theme.spacing(1)
|
||
}}>
|
||
<Checkbox sx={{
|
||
color: theme.palette.secondary.main,
|
||
"&.Mui-checked": {
|
||
color: theme.palette.secondary.main,
|
||
},
|
||
}} onClick={() => toggleCheckbox()} />
|
||
</Box>
|
||
<Box sx={{
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "center",
|
||
alignItems: "center"
|
||
}}>
|
||
Бессрочно
|
||
</Box>
|
||
</Box>
|
||
|
||
<Box sx={{
|
||
width: "90%",
|
||
marginTop: "55px",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "center",
|
||
alignItems: "center"
|
||
}}>
|
||
<Button
|
||
variant="contained"
|
||
sx={{
|
||
backgroundColor: theme.palette.menu.main,
|
||
height: "52px",
|
||
fontWeight: "normal",
|
||
fontSize: "17px",
|
||
"&:hover": {
|
||
backgroundColor: theme.palette.grayMedium.main
|
||
}
|
||
}}
|
||
onClick={() => checkFields()} >
|
||
Cоздать
|
||
</Button>
|
||
</Box>
|
||
|
||
</Box>
|
||
|
||
<Box style={{ width: "80%", marginTop: "55px" }}>
|
||
<Box style={{ height: 400 }}>
|
||
<DataGrid
|
||
checkboxSelection={true}
|
||
rows={discountsArrayConverted}
|
||
columns={columns}
|
||
sx={{
|
||
color: theme.palette.secondary.main,
|
||
"& .MuiDataGrid-iconSeparator": {
|
||
display: "none"
|
||
},
|
||
"& .css-levciy-MuiTablePagination-displayedRows": {
|
||
color: theme.palette.secondary.main
|
||
},
|
||
"& .MuiSvgIcon-root": {
|
||
color: theme.palette.secondary.main
|
||
},
|
||
"& .MuiTablePagination-selectLabel": {
|
||
color: theme.palette.secondary.main
|
||
},
|
||
"& .MuiInputBase-root": {
|
||
color: theme.palette.secondary.main
|
||
},
|
||
"& .MuiButton-text": {
|
||
color: theme.palette.secondary.main
|
||
},
|
||
}}
|
||
components={{ Toolbar: GridToolbar }}
|
||
onSelectionModelChange={(ids) => onRowsSelectionHandler(ids)}
|
||
/>
|
||
</Box>
|
||
</Box>
|
||
|
||
<Box sx={{
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
width: '100%',
|
||
marginTop: "45px"
|
||
}}>
|
||
<BoxButton sx={{
|
||
maxWidth: "420px",
|
||
width: '100%',
|
||
display: "flex",
|
||
justifyContent: "space-between",
|
||
flexWrap: 'wrap',
|
||
}}>
|
||
<Button
|
||
variant="contained"
|
||
onClick={() => activation(false)}
|
||
sx={{
|
||
backgroundColor: theme.palette.menu.main,
|
||
width: "200px",
|
||
height: "48px",
|
||
fontWeight: "normal",
|
||
fontSize: "17px",
|
||
marginBottom: '10px',
|
||
"&:hover": {
|
||
backgroundColor: theme.palette.grayMedium.main
|
||
}
|
||
}}>
|
||
Деактивировать
|
||
</Button>
|
||
|
||
<Button
|
||
variant="contained"
|
||
onClick={() => activation(true)}
|
||
sx={{
|
||
backgroundColor: theme.palette.menu.main,
|
||
width: "200px",
|
||
height: "48px",
|
||
fontWeight: "normal",
|
||
fontSize: "17px",
|
||
"&:hover": {
|
||
backgroundColor: theme.palette.grayMedium.main
|
||
}
|
||
}}>
|
||
Применить
|
||
</Button>
|
||
</BoxButton>
|
||
</Box>
|
||
|
||
</LocalizationProvider>
|
||
</React.Fragment>
|
||
);
|
||
};
|
||
|
||
|
||
export default Discounts;
|