крако, привелегии в зустанд, корзина в ките
This commit is contained in:
parent
8a5ff4441b
commit
3741c78391
17
craco.config.js
Normal file
17
craco.config.js
Normal file
@ -0,0 +1,17 @@
|
||||
const CracoAlias = require("craco-alias");
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
{
|
||||
plugin: CracoAlias,
|
||||
options: {
|
||||
source: "tsconfig",
|
||||
// baseUrl SHOULD be specified
|
||||
// plugin does not take it from tsconfig
|
||||
baseUrl: "./src",
|
||||
// tsConfigPath should point to the file where "baseUrl" and "paths" are specified
|
||||
tsConfigPath: "./tsconfig.extend.json"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
6684
package-lock.json
generated
6684
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
12
package.json
12
package.json
@ -21,6 +21,7 @@
|
||||
"@types/node": "^16.11.56",
|
||||
"@types/react": "^18.0.18",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"craco": "^0.0.3",
|
||||
"dayjs": "^1.11.5",
|
||||
"moment": "^2.29.4",
|
||||
"numeral": "^2.0.6",
|
||||
@ -35,10 +36,10 @@
|
||||
"zustand": "^4.1.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
"start": "craco start",
|
||||
"build": "craco build",
|
||||
"test": "craco test",
|
||||
"eject": "craco eject"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
@ -57,5 +58,8 @@
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"craco-alias": "^3.0.1"
|
||||
}
|
||||
}
|
||||
|
12
src/__tests__/test.test.js
Normal file
12
src/__tests__/test.test.js
Normal file
@ -0,0 +1,12 @@
|
||||
const puppeteer = require('puppeteer');
|
||||
|
||||
(async () => {
|
||||
const browser = await puppeteer.launch();
|
||||
const page = await browser.newPage();
|
||||
await page.goto('https://news.ycombinator.com', {
|
||||
waitUntil: 'networkidle2',
|
||||
});
|
||||
await page.pdf({ path: 'hn.pdf', format: 'a4' });
|
||||
|
||||
await browser.close();
|
||||
})();
|
87
src/kitUI/basket/calc.ts
Normal file
87
src/kitUI/basket/calc.ts
Normal file
@ -0,0 +1,87 @@
|
||||
// export const setPromocode = (name: string) => {
|
||||
// let codeNumber = -1;
|
||||
//
|
||||
// promocodeArray.forEach((item, i) => {
|
||||
// if (name != "" && item.name == name) codeNumber = i;
|
||||
// });
|
||||
//
|
||||
// setSelectedPromocode(codeNumber);
|
||||
// }
|
||||
|
||||
export const PositiveInput = (event: any) => {
|
||||
const numberInput = parseInt(event.target.value);
|
||||
if (isNaN(numberInput) || numberInput < 0) {
|
||||
event.target.value = '0'
|
||||
}
|
||||
}
|
||||
|
||||
// export const calcPriseTariff () => {
|
||||
//
|
||||
// // считаем цену в ТАРИФАХ
|
||||
// price = item.price;
|
||||
// percents = 0;
|
||||
// discounts = "";
|
||||
//
|
||||
// // применяем скидки по промокоду
|
||||
// if (selectedPromocode >= 0) {
|
||||
// promocodeArray[selectedPromocode].privileges.forEach((privilege) => {
|
||||
// console.log(item.service)
|
||||
// console.log(privilege.good)
|
||||
// if (item.service == privilege.good) {
|
||||
// appliedDscnts.push(privilege.discount)
|
||||
// price *= (1 - privilege.discount)
|
||||
// }
|
||||
// })
|
||||
// } else {
|
||||
// // применяем активные скидки
|
||||
// if (fitDiscounts.length >= 0) {
|
||||
// fitDiscounts.forEach((activeDiscount) => {
|
||||
// const discount = discountsArray[activeDiscount]
|
||||
// discount.privileges.forEach((p) => {
|
||||
// const svcName = item.service.split(' ')[0]
|
||||
// if (p.good == svcName) {
|
||||
// const summary = cartSummary.get(svcName) || {
|
||||
// mbs: 0,
|
||||
// points: 0,
|
||||
// days: 0
|
||||
// }
|
||||
// if (discount.toCapacity === 0 && discount.toTime === 0 && discount.basketMore === 0 && !(discount.incomeMore) ||
|
||||
// discount.toCapacity > 0 && summary.points > discount.toCapacity && item.points > 0 && discount.toTime == 0
|
||||
// || discount.toTime > 0 && summary.days > discount.toTime * 100 && item.time > 0 && discount.toCapacity == 0 ||
|
||||
// discount.toTime > 0 && discount.toCapacity > 0 && summary.days > discount.toTime * 100 && summary.points > discount.toCapacity) {
|
||||
//
|
||||
// price *= (1 - p.discount)
|
||||
// appliedDscnts.push(p.discount)
|
||||
// }
|
||||
//
|
||||
//
|
||||
// }
|
||||
// })
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// percents = Number(percents.toFixed(2));
|
||||
//
|
||||
// priceBefore = price;
|
||||
// price = price - (price * percents);
|
||||
// prices += price;
|
||||
// }
|
||||
//
|
||||
// // применяем активные скидки за объем корзины
|
||||
// const discountsAfter = (priceBefore: number) => {
|
||||
// const discounts: Array<number> = [];
|
||||
//
|
||||
//
|
||||
// if (fitDiscounts.length >= 0 && !nonCommercial && selectedPromocode < 0) {
|
||||
// fitDiscounts.forEach((activeDiscount) => {
|
||||
// const d = discountsArray[activeDiscount]
|
||||
// console.log(d)
|
||||
// console.log(fieldAddedValue)
|
||||
// if (d.basketMore > 0 && getPrice > d.basketMore && d.basketMore === fitDiscounts.reduce((a, e) => Math.max(a, discountsArray[e].basketMore), 0) ||
|
||||
// d.incomeMore > 0 && parseInt(fieldAddedValue) > d.incomeMore) {
|
||||
// prices *= (1 - d.privileges[0].discount)
|
||||
// discounts.push(d.privileges[0].discount)
|
||||
// }
|
||||
// });
|
||||
// }
|
372
src/kitUI/basket/index.tsx
Normal file
372
src/kitUI/basket/index.tsx
Normal file
@ -0,0 +1,372 @@
|
||||
import * as React from "react";
|
||||
import theme from "@theme";
|
||||
import {Button, Paper, ListItemText, IconButton, FormControlLabel, Box, TextField, Typography, Container, Checkbox, List, ListItem, ListItemAvatar, Avatar} from "@mui/material";
|
||||
import ShoppingCartIcon from "@mui/icons-material/ShoppingCart";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import Input from "@kitUI/input";
|
||||
import useStore, {StoreState} from "../../stores/store";
|
||||
import {useDemoData} from "@mui/x-data-grid-generator";
|
||||
import {GridSelectionModel} from "@mui/x-data-grid";
|
||||
import {ArrayProps} from "../../pages/dashboard/Content/Tariffs/types";
|
||||
import TableHead from "@mui/material/TableHead";
|
||||
import TableRow from "@mui/material/TableRow";
|
||||
import TableCell from "@mui/material/TableCell";
|
||||
import TableBody from "@mui/material/TableBody";
|
||||
import Radio from "@mui/material/Radio";
|
||||
import Skeleton from "@mui/material/Skeleton";
|
||||
import Table from "@mui/material/Table";
|
||||
|
||||
export default (props:any):any => {
|
||||
// const [added, setAdded] = React.useState<number>(0)
|
||||
// const [notCommercial, setNotCommercial] = React.useState<boolean>(false)
|
||||
//
|
||||
// const setPromocode = (name: string) => {
|
||||
// let codeNumber = -1;
|
||||
//
|
||||
// promocodeArray.forEach((item, i) => {
|
||||
// if (name != "" && item.name == name) codeNumber = i;
|
||||
// });
|
||||
//
|
||||
// setSelectedPromocode(codeNumber);
|
||||
// }
|
||||
//
|
||||
// const PositiveInput = (event: any) => {
|
||||
// const numberInput = parseInt(event.target.value);
|
||||
// if (isNaN(numberInput) || numberInput < 0) {
|
||||
// event.target.value = '0'
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // const getData = localStorage.getItem("tariffs");
|
||||
// // const store = useStore( (state) => state );
|
||||
// //
|
||||
// // if( getData && !store.tariffsArray.length ) {
|
||||
// // const rows:Array<ArrayProps> = JSON.parse(getData);
|
||||
// // if( rows.length ) { store.tariffsArraySet( rows ); };
|
||||
// // }
|
||||
// let priceBefore = 0;
|
||||
// let price = 0;
|
||||
// let prices = 0;
|
||||
// let percents = 0;
|
||||
// let discounts = "";
|
||||
// let discountsSum = "";
|
||||
//
|
||||
// const { discountsArray, discountsArraySet } = useStore<StoreState>((state) => state);
|
||||
// const { discountsActiveArray, discountsActiveArraySet } = useStore<StoreState>((state) => state);
|
||||
//
|
||||
// const [nonCommercial, setNonCommercial] = React.useState(false);
|
||||
//
|
||||
// const { data } = useDemoData({
|
||||
// dataSet: "Commodity",
|
||||
// rowLength: 10,
|
||||
// maxColumns: 5,
|
||||
// });
|
||||
//
|
||||
//
|
||||
// const { tariffsArray } = useStore<StoreState>((state) => state);
|
||||
// const tariffsArrayConverted = tariffsArray.map( (item) => {
|
||||
// if( item.type === "package" && item.tariffs ) {
|
||||
// const result = item.tariffs.reduce( (acc, tariff) => {
|
||||
// acc.service = acc.service? `${acc.service}, ${tariff.service}` : tariff.service;
|
||||
// acc.disk = acc.disk+ tariff.disk;
|
||||
// acc.time = acc.time+ tariff.time;
|
||||
// acc.points = acc.points + tariff.points;
|
||||
// acc.price = acc.price + tariff.price;
|
||||
//
|
||||
// return acc;
|
||||
// }, { service: "", disk: "", time: "", points: "", price: 0 } );
|
||||
//
|
||||
// return { id: item.id, name: item.name, type: item.type, ...result }
|
||||
// } else {
|
||||
// return item;
|
||||
// }
|
||||
// } );
|
||||
//
|
||||
// const { tariffsSelectedRowsData, tariffsSelectedRowsDataSet } = useStore<StoreState>((state) => state);
|
||||
// const onRowsSelectionHandler = ( ids:GridSelectionModel ) => {
|
||||
// const result:Array<ArrayProps> = [];
|
||||
// ids.forEach((id) => tariffsArray.forEach( (row) => {
|
||||
// if(row.id === id) result.push(row);
|
||||
// } ) );
|
||||
//
|
||||
// tariffsSelectedRowsDataSet( result );
|
||||
// };
|
||||
//
|
||||
// const { cartRowsData, cartRowsDataSet } = useStore<StoreState>((state) => state);
|
||||
// const handleToBasket = () => {
|
||||
// cartRowsDataSet( tariffsSelectedRowsData );
|
||||
// }
|
||||
//
|
||||
// const handleRemoveBasket = ( id:number ) => {
|
||||
// const cartFiltered = cartRowsData.filter( (row) => row.id != id );
|
||||
// cartRowsDataSet( cartFiltered );
|
||||
// }
|
||||
//
|
||||
// const fieldPromocode = React.useRef<HTMLInputElement | null>(null);
|
||||
// const checkPromocode = () => {
|
||||
// if( fieldPromocode.current != null ) {
|
||||
// setPromocode( fieldPromocode.current.value );
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// let { promocodeArray, promocodeArraySet } = useStore<StoreState>((state) => state);
|
||||
// const [selectedPromocode, setSelectedPromocode] = React.useState( -1 );
|
||||
//
|
||||
// //promocodeArray = [ ...rowz ];
|
||||
//
|
||||
// const setPromocode = ( name:string ) => {
|
||||
// let codeNumber = -1;
|
||||
//
|
||||
// promocodeArray.forEach( (item, i) => {
|
||||
// if( name != "" && item.name == name ) codeNumber = i;
|
||||
// } );
|
||||
//
|
||||
// setSelectedPromocode( codeNumber );
|
||||
// }
|
||||
//
|
||||
// const PositiveInput = (event:any) => {
|
||||
// const numberInput = parseInt(event.target.value);
|
||||
// if(isNaN(numberInput) || numberInput < 0) {event.target.value = '0'}
|
||||
// }
|
||||
//
|
||||
// const fieldAdded = React.useRef<HTMLInputElement | null>(null);
|
||||
// const [ fieldAddedValue, setFieldAddedValue ] = React.useState("");
|
||||
//
|
||||
// const changeAdded = (event:any) => {
|
||||
// if( fieldAdded.current != null ) {
|
||||
// if( fieldAdded.current.value != null ) {
|
||||
// setFieldAddedValue( fieldAdded.current.value );
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// PositiveInput(event)
|
||||
// };
|
||||
//
|
||||
// const separator = (amount: number) => {
|
||||
// console.log(amount)
|
||||
//
|
||||
// if( String(amount).length < 4 ) { return amount; }
|
||||
//
|
||||
// let result:Array<string> = [];
|
||||
// const arrs = String(amount).split('.')
|
||||
// const arr = arrs[0].split('').reverse();
|
||||
//
|
||||
// arr.forEach( (item, i:number) => {
|
||||
// result.push( String( arr[ i ] ) );
|
||||
// if( ((i+1) / 3) - Math.round((i+1) / 3) == 0 ) result.push(" ");
|
||||
// });
|
||||
//
|
||||
// if( arrs.length > 1 ) { return result.reverse().join("") +"." +arrs[1]; }
|
||||
// else { return result.reverse().join(""); }
|
||||
//
|
||||
// }
|
||||
//
|
||||
//
|
||||
// const cartSummary = new Map()
|
||||
// cartRowsData.forEach((row) => {
|
||||
// const svcName = row.service.split(" ")[0]
|
||||
// const prev = cartSummary.get(svcName)
|
||||
// console.log(row)
|
||||
// console.log(prev)
|
||||
// if (!prev) {
|
||||
// cartSummary.set(svcName, {
|
||||
// mbs: row.disk,
|
||||
// points: row.points,
|
||||
// days: row.time,
|
||||
// })
|
||||
// } else {
|
||||
// cartSummary.set(svcName, {
|
||||
// mbs: row.disk+prev.mbs,
|
||||
// points: row.points+prev.points,
|
||||
// days: row.time+prev.days,
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
// console.log(cartSummary)
|
||||
//
|
||||
// const fitDiscounts = discountsActiveArray.filter(e => {
|
||||
// const d = discountsArray[e]
|
||||
// const summary = cartSummary.get(d.privileges[0].good.split(' ')[0])
|
||||
// return d.incomeMore*100 < parseInt(fieldAddedValue) && d.incomeMore > 0 ||
|
||||
// d.toTime < (summary ? summary.days : 0) && d.toTime > 0 && d.toCapacity === 0 ||
|
||||
// d.toCapacity > 0 && d.toCapacity < (summary ? summary.points : 0) && d.toTime === 0 ||
|
||||
// d.toCapacity > 0 && d.toTime > 0 && d.toCapacity < (summary ? summary.points : 0) && d.toTime < (summary ? summary.days : 0) ||
|
||||
// !d.toCapacity && !d.toTime && !d.incomeMore && !d.basketMore ||
|
||||
// d.basketMore
|
||||
// }).filter((e,i,a)=>{
|
||||
// const d = discountsArray[e]
|
||||
// if (d.incomeMore) {
|
||||
// return d.incomeMore === a.reduce((a, e) => Math.max(a, discountsArray[e].incomeMore || 0), 0 )
|
||||
// }
|
||||
// if (d.toTime && d.toCapacity) {
|
||||
// return d.toTime === a.reduce((a, e) => Math.max(a, (discountsArray[e].toTime && discountsArray[e].toCapacity) ? discountsArray[e].toTime:0 ), 0 ) && d.toCapacity === a.reduce((a, e) => Math.max(a, (discountsArray[e].toCapacity && discountsArray[e].toTime) ? discountsArray[e].toCapacity : 0 ), 0 )
|
||||
// }
|
||||
// if (d.toTime && !d.toCapacity) {
|
||||
// return d.toTime === a.reduce((a, e) => Math.max(a, discountsArray[e].toTime && !discountsArray[e].toCapacity ? discountsArray[e].toTime : 0), 0 )
|
||||
// }
|
||||
// if (!d.toTime && d.toCapacity) {
|
||||
// return d.toCapacity === a.reduce((a, e) => Math.max(a, discountsArray[e].toCapacity && !discountsArray[e].toTime ? discountsArray[e].toCapacity : 0), 0 )
|
||||
// }
|
||||
// return true
|
||||
// })
|
||||
// console.log(fitDiscounts)
|
||||
//
|
||||
// const discountsAfter = ( getPrice:number ) => {
|
||||
// const discounts:Array<number> = [];
|
||||
// priceBefore = getPrice;
|
||||
//
|
||||
// prices = getPrice;
|
||||
// console.log(getPrice)
|
||||
//
|
||||
// // применяем активные скидки за объем корзины
|
||||
//
|
||||
// if( fitDiscounts.length >= 0 && !nonCommercial && selectedPromocode < 0 ) {
|
||||
// fitDiscounts.forEach( (activeDiscount) => {
|
||||
// const d = discountsArray[activeDiscount]
|
||||
// console.log(d)
|
||||
// console.log(fieldAddedValue)
|
||||
// if (d.basketMore > 0 && getPrice > d.basketMore && d.basketMore === fitDiscounts.reduce((a,e) => Math.max(a, discountsArray[e].basketMore), 0) ||
|
||||
// d.incomeMore > 0 && parseInt(fieldAddedValue) > d.incomeMore) {
|
||||
// prices *= (1-d.privileges[0].discount)
|
||||
// discounts.push(d.privileges[0].discount)
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// if( nonCommercial ) {
|
||||
// prices *= 0.2
|
||||
// return `80%`;
|
||||
// }
|
||||
//
|
||||
// return discounts.map(e => `${(e*100).toFixed(2)}%`).join(' × ') + ` = ${(100 - discounts.reduce((a : number,cv : number) => a*(1-cv), 100)) .toFixed(2)}%`;
|
||||
// }
|
||||
|
||||
|
||||
return (
|
||||
<Box
|
||||
component="section"
|
||||
sx={{
|
||||
border: "1px solid white",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
width: "100%"
|
||||
}}
|
||||
>
|
||||
<Typography variant="caption">
|
||||
корзина
|
||||
</Typography>
|
||||
<Paper
|
||||
variant="bar"
|
||||
sx={{display:"flex", alignItems:"center", justifyContent: "space-between"}}
|
||||
>
|
||||
<FormControlLabel
|
||||
label="НКО"
|
||||
control={
|
||||
<Checkbox
|
||||
sx={{
|
||||
color: theme.palette.secondary.main,
|
||||
"&.Mui-checked": {
|
||||
color: theme.palette.secondary.main,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
}
|
||||
sx={{
|
||||
color: theme.palette.secondary.main,
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
label="внесено"
|
||||
type="number"
|
||||
size="small"
|
||||
// onChange={(e:React.ChangeEvent<HTMLInputElement>) => setAdded(Number(e.target.value))}
|
||||
/>
|
||||
<Box
|
||||
sx={{
|
||||
border: "1px solid white",
|
||||
padding: "3px",
|
||||
display:"flex",
|
||||
flexDirection:"column"
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
label="промокод"
|
||||
size="small"
|
||||
|
||||
/>
|
||||
<Button sx={{maxWidth:"140px"}}>применить промокод</Button>
|
||||
</Box>
|
||||
<Button>рассчитать</Button>
|
||||
</Paper>
|
||||
|
||||
|
||||
{/*<Table sx={{*/}
|
||||
{/* width: "90%",*/}
|
||||
{/* margin: "5px",*/}
|
||||
{/* border: "2px solid",*/}
|
||||
{/* borderColor: theme.palette.secondary.main,*/}
|
||||
{/*}} aria-label="simple table">*/}
|
||||
{/* <TableHead>*/}
|
||||
{/* <TableRow sx={{*/}
|
||||
{/* borderBottom: "2px solid",*/}
|
||||
{/* borderColor: theme.palette.grayLight.main,*/}
|
||||
{/* height: "100px"*/}
|
||||
{/* }}>*/}
|
||||
{/* <TableCell>*/}
|
||||
{/* <Typography*/}
|
||||
{/* variant="h4"*/}
|
||||
{/* sx={{*/}
|
||||
{/* color: theme.palette.secondary.main,*/}
|
||||
{/* }}>*/}
|
||||
{/* Имя*/}
|
||||
{/* </Typography>*/}
|
||||
{/* </TableCell>*/}
|
||||
{/* <TableCell>*/}
|
||||
{/* <Typography*/}
|
||||
{/* variant="h4"*/}
|
||||
{/* sx={{*/}
|
||||
{/* color: theme.palette.secondary.main,*/}
|
||||
{/* }}>*/}
|
||||
{/* Описание*/}
|
||||
{/* </Typography>*/}
|
||||
{/* </TableCell>*/}
|
||||
{/* <TableCell>*/}
|
||||
{/* <Typography*/}
|
||||
{/* variant="h4"*/}
|
||||
{/* sx={{*/}
|
||||
{/* color: theme.palette.secondary.main,*/}
|
||||
{/* }}>*/}
|
||||
{/* стоимость*/}
|
||||
{/* </Typography>*/}
|
||||
{/* </TableCell>*/}
|
||||
{/* </TableRow>*/}
|
||||
{/* </TableHead>*/}
|
||||
|
||||
{/* <TableBody>*/}
|
||||
|
||||
|
||||
{/* </TableBody>*/}
|
||||
{/*</Table>*/}
|
||||
|
||||
|
||||
<Typography id="transition-modal-title" variant="h6" sx={{
|
||||
fontWeight: "normal",
|
||||
textAlign: "center",
|
||||
marginTop: "15px",
|
||||
fontSize: "16px"
|
||||
}}>
|
||||
Скидки:
|
||||
</Typography>
|
||||
|
||||
<Typography id="transition-modal-title" variant="h6" sx={{
|
||||
fontWeight: "normal",
|
||||
textAlign: "center",
|
||||
marginTop: "10px"
|
||||
}}>
|
||||
ИТОГО:
|
||||
</Typography>
|
||||
|
||||
</Box>
|
||||
)
|
||||
}
|
26
src/kitUI/datagrid.tsx
Normal file
26
src/kitUI/datagrid.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import { DataGrid } from "@mui/x-data-grid";
|
||||
import { styled } from "@mui/material/styles";
|
||||
export default styled(DataGrid)(({ theme }) => ({
|
||||
width: "100%",
|
||||
minHeight: "400px",
|
||||
margin: "10px 0",
|
||||
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
|
||||
},
|
||||
}));
|
16
src/kitUI/input.tsx
Normal file
16
src/kitUI/input.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import {TextField} from "@mui/material";
|
||||
import { styled } from "@mui/material/styles";
|
||||
export default styled(TextField)(({ theme }) => ({
|
||||
variant: "outlined",
|
||||
height: "40px",
|
||||
size: "small",
|
||||
color: theme.palette.secondary.main,
|
||||
width: "140px",
|
||||
backgroundColor: theme.palette.content.main,
|
||||
"& .MuiFormLabel-root": {
|
||||
color: theme.palette.secondary.main,
|
||||
},
|
||||
"& .Mui-focused": {
|
||||
color: theme.palette.secondary.main,
|
||||
}
|
||||
}));
|
11
src/kitUI/types/privileges.ts
Normal file
11
src/kitUI/types/privileges.ts
Normal file
@ -0,0 +1,11 @@
|
||||
export type Privilege = {
|
||||
serviceKey: string;
|
||||
name: string;
|
||||
description: string;
|
||||
type: string;
|
||||
price: number;
|
||||
}
|
||||
export interface State {
|
||||
privileges: { [key: string]: Privilege } | {},
|
||||
tariffsUpdate: (element:Privilege) => void
|
||||
}
|
@ -13,7 +13,7 @@ import { DataGrid, GridColDef, GridSelectionModel, GridToolbar } from "@mui/x-da
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import { PrivilegesProps, DiscountProps } from "./types";
|
||||
import useStore, { StoreState } from "../../../../store";
|
||||
import useStore, { StoreState } from "../../../../stores/store";
|
||||
import theme from "../../../../theme";
|
||||
import {styled} from "@mui/material/styles";
|
||||
|
||||
|
@ -13,7 +13,7 @@ import { DataGrid, GridColDef, GridSelectionModel, GridToolbar } from "@mui/x-da
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import Select, { SelectChangeEvent } from "@mui/material/Select";
|
||||
import { PrivilegesProps, PromocodeProps } from "./types";
|
||||
import useStore, { StoreState } from "../../../../store";
|
||||
import useStore, { StoreState } from "../../../../stores/store";
|
||||
import theme from "../../../../theme";
|
||||
|
||||
|
||||
|
@ -1,81 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { Box, Typography, Button } from "@mui/material";
|
||||
import theme from "../../../../../theme";
|
||||
|
||||
|
||||
export interface MWProps {
|
||||
openModal: (type:number, num: number) => void
|
||||
}
|
||||
|
||||
const Contractor: React.FC<MWProps> = ({ openModal }) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
sx={{
|
||||
width: "90%",
|
||||
height: "60px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
color: theme.palette.secondary.main
|
||||
}}>
|
||||
Сокращатель ссылок
|
||||
</Typography>
|
||||
|
||||
<Box sx={{
|
||||
marginTop: "35px",
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(2, 1fr)",
|
||||
gridGap: "20px",
|
||||
marginBottom: "120px",
|
||||
}}>
|
||||
<Button
|
||||
variant = "contained"
|
||||
onClick={ () => openModal(3, 1) }
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
padding: '11px 65px',
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Создать тариф <br /> на аналитику время
|
||||
</Button>
|
||||
<Button
|
||||
variant = "contained"
|
||||
onClick={ () => openModal(3, 1) }
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
padding: '11px 65px',
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Создать тариф <br /> на a/b тесты время
|
||||
</Button>
|
||||
<Button
|
||||
variant = "contained"
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
padding: '11px 65px',
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Изменить тариф
|
||||
</Button>
|
||||
</Box>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default Contractor;
|
@ -1,807 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { Box, Button, Typography, TextField } from "@mui/material";
|
||||
import { DataGrid, GridColDef, GridSelectionModel, GridToolbar } from "@mui/x-data-grid";
|
||||
import { useDemoData } from "@mui/x-data-grid-generator";
|
||||
import useStore, { StoreState } from "../../../../../store";
|
||||
import { ArrayProps, CartSummary } from "../types";
|
||||
import List from "@mui/material/List";
|
||||
import ListItem from "@mui/material/ListItem";
|
||||
import ListItemAvatar from "@mui/material/ListItemAvatar";
|
||||
import Avatar from "@mui/material/Avatar";
|
||||
import ShoppingCartIcon from "@mui/icons-material/ShoppingCart";
|
||||
import ListItemText from "@mui/material/ListItemText";
|
||||
import IconButton from "@mui/material/IconButton";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||
import Checkbox from "@mui/material/Checkbox";
|
||||
import { PrivilegesProps, PromocodeProps } from "../../Promocode/types";
|
||||
import { DiscountProps } from "../../Discounts/types";
|
||||
import theme from "../../../../../theme";
|
||||
|
||||
export interface MWProps {
|
||||
openModal: () => void
|
||||
}
|
||||
|
||||
const columns: GridColDef[] = [
|
||||
{
|
||||
field: "id",
|
||||
headerName: "ID",
|
||||
width: 30,
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
field: "name",
|
||||
headerName: "Название тарифа",
|
||||
width: 200,
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
field: "service",
|
||||
headerName: "Сервис",
|
||||
width: 210,
|
||||
sortable: false,
|
||||
},{
|
||||
field: "disk",
|
||||
headerName: "Гигабайты",
|
||||
type: "number",
|
||||
width: 110,
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
field: "time",
|
||||
headerName: "Время",
|
||||
type: "number",
|
||||
width: 110,
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
field: "points",
|
||||
headerName: "Объем",
|
||||
width: 110,
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
field: "price",
|
||||
headerName: "Стоимость",
|
||||
width: 160,
|
||||
sortable: false,
|
||||
},
|
||||
{
|
||||
field: "conditions",
|
||||
headerName: "Условия",
|
||||
width: 110,
|
||||
sortable: false,
|
||||
},
|
||||
];
|
||||
|
||||
const rows = [
|
||||
{ id: 1, name: "Тариф 1", type: "tariff", service: "Шаблонизатор", disk: "100 гб", time: "200 дней", points: "300", price: 100500 },
|
||||
{ id: 2, name: "Тариф 2", type: "tariff", service: "Шаблонизатор", disk: "100 гб", time: "200 дней", points: "300", price: 100500 },
|
||||
{ id: 3, name: "Тариф 3", type: "tariff", service: "Шаблонизатор", disk: "100 гб", time: "200 дней", points: "300", price: 100500 },
|
||||
{ id: 4, name: "Пакет 1", type: "package", tariffs: [
|
||||
{ id: 1, name: "Тариф 1", type: "tariff", service: "Шаблонизатор", disk: "100 гб", time: "200 дней", points: "300", price: 100500 },
|
||||
{ id: 2, name: "Тариф 2", type: "tariff", service: "Шаблонизатор", disk: "100 гб", time: "200 дней", points: "300", price: 100500 },
|
||||
] },
|
||||
];
|
||||
|
||||
const rowz:Array<PromocodeProps> = [
|
||||
{ id: 1, name: "Промокод 1", endless: false, from: "", dueTo: "", privileges: [
|
||||
{
|
||||
good: "Шаблонизатор",
|
||||
discount: 0.15
|
||||
},
|
||||
{
|
||||
good: "Опросник",
|
||||
discount: 0.3
|
||||
}
|
||||
] },
|
||||
{ id: 1, name: "Промокод 2", endless: false, from: "", dueTo: "", privileges: [
|
||||
{
|
||||
good: "Шаблонизатор",
|
||||
discount: 0.4
|
||||
},
|
||||
{
|
||||
good: "Опросник",
|
||||
discount: 0.6
|
||||
}
|
||||
] }
|
||||
];
|
||||
|
||||
const DataGridElement: React.FC<MWProps> = ({ openModal }) => {
|
||||
let priceBefore = 0;
|
||||
let price = 0;
|
||||
let prices = 0;
|
||||
let percents = 0;
|
||||
let discounts = "";
|
||||
let discountsSum = "";
|
||||
|
||||
const { discountsArray, discountsArraySet } = useStore<StoreState>((state) => state);
|
||||
const { discountsActiveArray, discountsActiveArraySet } = useStore<StoreState>((state) => state);
|
||||
|
||||
const [nonCommercial, setNonCommercial] = React.useState(false);
|
||||
|
||||
const { data } = useDemoData({
|
||||
dataSet: "Commodity",
|
||||
rowLength: 10,
|
||||
maxColumns: 5,
|
||||
});
|
||||
|
||||
const { tariffsArray } = useStore<StoreState>((state) => state);
|
||||
const tariffsArrayConverted = tariffsArray.map( (item) => {
|
||||
if( item.type === "package" && item.tariffs ) {
|
||||
const result = item.tariffs.reduce( (acc, tariff) => {
|
||||
acc.service = acc.service? `${acc.service}, ${tariff.service}` : tariff.service;
|
||||
acc.disk = acc.disk+ tariff.disk;
|
||||
acc.time = acc.time+ tariff.time;
|
||||
acc.points = acc.points + tariff.points;
|
||||
acc.price = acc.price + tariff.price;
|
||||
|
||||
return acc;
|
||||
}, { service: "", disk: "", time: "", points: "", price: 0 } );
|
||||
|
||||
return { id: item.id, name: item.name, type: item.type, ...result }
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
} );
|
||||
|
||||
const { tariffsSelectedRowsData, tariffsSelectedRowsDataSet } = useStore<StoreState>((state) => state);
|
||||
const onRowsSelectionHandler = ( ids:GridSelectionModel ) => {
|
||||
const result:Array<ArrayProps> = [];
|
||||
ids.forEach((id) => tariffsArray.forEach( (row) => {
|
||||
if(row.id === id) result.push(row);
|
||||
} ) );
|
||||
|
||||
tariffsSelectedRowsDataSet( result );
|
||||
};
|
||||
|
||||
const { cartRowsData, cartRowsDataSet } = useStore<StoreState>((state) => state);
|
||||
const handleToBasket = () => {
|
||||
cartRowsDataSet( tariffsSelectedRowsData );
|
||||
}
|
||||
|
||||
const handleRemoveBasket = ( id:number ) => {
|
||||
const cartFiltered = cartRowsData.filter( (row) => row.id != id );
|
||||
cartRowsDataSet( cartFiltered );
|
||||
}
|
||||
|
||||
const fieldPromocode = React.useRef<HTMLInputElement | null>(null);
|
||||
const checkPromocode = () => {
|
||||
if( fieldPromocode.current != null ) {
|
||||
setPromocode( fieldPromocode.current.value );
|
||||
}
|
||||
}
|
||||
|
||||
let { promocodeArray, promocodeArraySet } = useStore<StoreState>((state) => state);
|
||||
const [selectedPromocode, setSelectedPromocode] = React.useState( -1 );
|
||||
|
||||
//promocodeArray = [ ...rowz ];
|
||||
|
||||
const setPromocode = ( name:string ) => {
|
||||
let codeNumber = -1;
|
||||
|
||||
promocodeArray.forEach( (item, i) => {
|
||||
if( name != "" && item.name == name ) codeNumber = i;
|
||||
} );
|
||||
|
||||
setSelectedPromocode( codeNumber );
|
||||
}
|
||||
|
||||
const PositiveInput = (event:any) => {
|
||||
const numberInput = parseInt(event.target.value);
|
||||
if(isNaN(numberInput) || numberInput < 0) {event.target.value = '0'}
|
||||
}
|
||||
|
||||
const fieldAdded = React.useRef<HTMLInputElement | null>(null);
|
||||
const [ fieldAddedValue, setFieldAddedValue ] = React.useState("");
|
||||
|
||||
const changeAdded = (event:any) => {
|
||||
if( fieldAdded.current != null ) {
|
||||
if( fieldAdded.current.value != null ) {
|
||||
setFieldAddedValue( fieldAdded.current.value );
|
||||
}
|
||||
|
||||
}
|
||||
PositiveInput(event)
|
||||
};
|
||||
|
||||
const separator = (amount: number) => {
|
||||
console.log(amount)
|
||||
|
||||
if( String(amount).length < 4 ) { return amount; }
|
||||
|
||||
let result:Array<string> = [];
|
||||
const arrs = String(amount).split('.')
|
||||
const arr = arrs[0].split('').reverse();
|
||||
|
||||
arr.forEach( (item, i:number) => {
|
||||
result.push( String( arr[ i ] ) );
|
||||
if( ((i+1) / 3) - Math.round((i+1) / 3) == 0 ) result.push(" ");
|
||||
});
|
||||
|
||||
if( arrs.length > 1 ) { return result.reverse().join("") +"." +arrs[1]; }
|
||||
else { return result.reverse().join(""); }
|
||||
|
||||
}
|
||||
|
||||
|
||||
const cartSummary = new Map()
|
||||
cartRowsData.forEach((row) => {
|
||||
const svcName = row.service.split(" ")[0]
|
||||
const prev = cartSummary.get(svcName)
|
||||
console.log(row)
|
||||
console.log(prev)
|
||||
if (!prev) {
|
||||
cartSummary.set(svcName, {
|
||||
mbs: row.disk,
|
||||
points: row.points,
|
||||
days: row.time,
|
||||
})
|
||||
} else {
|
||||
cartSummary.set(svcName, {
|
||||
mbs: row.disk+prev.mbs,
|
||||
points: row.points+prev.points,
|
||||
days: row.time+prev.days,
|
||||
})
|
||||
}
|
||||
})
|
||||
console.log(cartSummary)
|
||||
|
||||
const fitDiscounts = discountsActiveArray.filter(e => {
|
||||
const d = discountsArray[e]
|
||||
const summary = cartSummary.get(d.privileges[0].good.split(' ')[0])
|
||||
return d.incomeMore*100 < parseInt(fieldAddedValue) && d.incomeMore > 0 ||
|
||||
d.toTime < (summary ? summary.days : 0) && d.toTime > 0 && d.toCapacity === 0 ||
|
||||
d.toCapacity > 0 && d.toCapacity < (summary ? summary.points : 0) && d.toTime === 0 ||
|
||||
d.toCapacity > 0 && d.toTime > 0 && d.toCapacity < (summary ? summary.points : 0) && d.toTime < (summary ? summary.days : 0) ||
|
||||
!d.toCapacity && !d.toTime && !d.incomeMore && !d.basketMore ||
|
||||
d.basketMore
|
||||
}).filter((e,i,a)=>{
|
||||
const d = discountsArray[e]
|
||||
if (d.incomeMore) {
|
||||
return d.incomeMore === a.reduce((a, e) => Math.max(a, discountsArray[e].incomeMore || 0), 0 )
|
||||
}
|
||||
if (d.toTime && d.toCapacity) {
|
||||
return d.toTime === a.reduce((a, e) => Math.max(a, (discountsArray[e].toTime && discountsArray[e].toCapacity) ? discountsArray[e].toTime:0 ), 0 ) && d.toCapacity === a.reduce((a, e) => Math.max(a, (discountsArray[e].toCapacity && discountsArray[e].toTime) ? discountsArray[e].toCapacity : 0 ), 0 )
|
||||
}
|
||||
if (d.toTime && !d.toCapacity) {
|
||||
return d.toTime === a.reduce((a, e) => Math.max(a, discountsArray[e].toTime && !discountsArray[e].toCapacity ? discountsArray[e].toTime : 0), 0 )
|
||||
}
|
||||
if (!d.toTime && d.toCapacity) {
|
||||
return d.toCapacity === a.reduce((a, e) => Math.max(a, discountsArray[e].toCapacity && !discountsArray[e].toTime ? discountsArray[e].toCapacity : 0), 0 )
|
||||
}
|
||||
return true
|
||||
})
|
||||
console.log(fitDiscounts)
|
||||
|
||||
const discountsAfter = ( getPrice:number ) => {
|
||||
const discounts:Array<number> = [];
|
||||
priceBefore = getPrice;
|
||||
|
||||
prices = getPrice;
|
||||
console.log(getPrice)
|
||||
|
||||
// применяем активные скидки за объем корзины
|
||||
|
||||
if( fitDiscounts.length >= 0 && !nonCommercial && selectedPromocode < 0 ) {
|
||||
fitDiscounts.forEach( (activeDiscount) => {
|
||||
const d = discountsArray[activeDiscount]
|
||||
console.log(d)
|
||||
console.log(fieldAddedValue)
|
||||
if (d.basketMore > 0 && getPrice > d.basketMore && d.basketMore === fitDiscounts.reduce((a,e) => Math.max(a, discountsArray[e].basketMore), 0) ||
|
||||
d.incomeMore > 0 && parseInt(fieldAddedValue) > d.incomeMore) {
|
||||
prices *= (1-d.privileges[0].discount)
|
||||
discounts.push(d.privileges[0].discount)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if( nonCommercial ) {
|
||||
prices *= 0.2
|
||||
return `80%`;
|
||||
}
|
||||
|
||||
return discounts.map(e => `${(e*100).toFixed(2)}%`).join(' × ') + ` = ${(100 - discounts.reduce((a : number,cv : number) => a*(1-cv), 100)) .toFixed(2)}%`;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box style={{ width: "93%" }}>
|
||||
<Box style={{ height: 400 }}>
|
||||
<DataGrid
|
||||
checkboxSelection={true}
|
||||
rows={ tariffsArrayConverted }
|
||||
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 sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center"
|
||||
}}>
|
||||
<Button
|
||||
variant = "contained"
|
||||
onClick={ () => openModal() }
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
padding: "6px 30px",
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
marginTop: "45px",
|
||||
marginBottom: "15px",
|
||||
maxWidth: '320px',
|
||||
width: '100%',
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Пакетизировать
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant = "contained"
|
||||
onClick={ () => handleToBasket() }
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
padding: "6px 69px",
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
marginBottom: "95px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Сложить в корзину
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
<Box sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
marginBottom: "45px",
|
||||
}}>
|
||||
<Box sx={{
|
||||
maxWidth: "480px",
|
||||
width: '100%',
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
}}>
|
||||
<TextField
|
||||
id = "standard-basic"
|
||||
label = { "Ввести промокод" }
|
||||
variant = "filled"
|
||||
size="small"
|
||||
color = "secondary"
|
||||
sx={{
|
||||
width: "200px",
|
||||
height: "30px",
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
backgroundColor: theme.palette.content.main,
|
||||
color: theme.palette.secondary.main,
|
||||
} }}
|
||||
InputLabelProps={{
|
||||
style: {
|
||||
color: theme.palette.secondary.main
|
||||
} }}
|
||||
inputRef={ fieldPromocode }
|
||||
/>
|
||||
|
||||
<Button
|
||||
variant = "contained"
|
||||
onClick={ () => checkPromocode() }
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
width: "200px",
|
||||
height: "48px",
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Готово
|
||||
</Button>
|
||||
</Box>
|
||||
|
||||
{
|
||||
selectedPromocode >= 0
|
||||
? (
|
||||
<Box>
|
||||
<Box sx={{ marginTop: "35px", display: "flex" }}>
|
||||
<Typography sx={{ color: theme.palette.grayDisabled.main, minWidth: "150px" }}>
|
||||
Введен промокод:
|
||||
</Typography>
|
||||
<Typography sx={{ width: "100%", textAlign: "center" }}>
|
||||
{ promocodeArray[ selectedPromocode ].name }
|
||||
</Typography>
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: "flex" }}>
|
||||
<Typography sx={{ color: theme.palette.grayDisabled.main, minWidth: "150px" }}>
|
||||
Привилегии:  
|
||||
</Typography>
|
||||
|
||||
<Typography sx={{ width: "100%", textAlign: "center" }}>
|
||||
{
|
||||
promocodeArray[ selectedPromocode ].privileges.map( (item, i) => {
|
||||
let period;
|
||||
|
||||
i < promocodeArray[ selectedPromocode ].privileges.length - 1
|
||||
? period = ", "
|
||||
: period = ""
|
||||
|
||||
return(
|
||||
<>
|
||||
{
|
||||
`${item.good} - ${ Math.round(item.discount * 100) }%${period}`
|
||||
}
|
||||
</>
|
||||
)
|
||||
} )
|
||||
}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
) : null
|
||||
}
|
||||
</Box>
|
||||
|
||||
<Box sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
paddingBottom: "45px"
|
||||
}}>
|
||||
<Typography id="transition-modal-title" variant="caption">
|
||||
Корзина
|
||||
</Typography>
|
||||
|
||||
<Box sx={{
|
||||
display: "flex",
|
||||
marginTop: "15px",
|
||||
marginBottom: "15px",
|
||||
maxWidth: "350px",
|
||||
width: '100%',
|
||||
justifyContent: "space-between"
|
||||
}}>
|
||||
<FormControlLabel control={
|
||||
<Checkbox sx={{
|
||||
color: theme.palette.secondary.main,
|
||||
"&.Mui-checked": {
|
||||
color: theme.palette.secondary.main,
|
||||
},
|
||||
}} onClick={ () => setNonCommercial(!nonCommercial) } />
|
||||
} label="НКО" />
|
||||
|
||||
<TextField
|
||||
id = "standard-basic"
|
||||
label = { "Внесено" }
|
||||
variant = "filled"
|
||||
size="small"
|
||||
color = "secondary"
|
||||
type="number"
|
||||
sx={{
|
||||
width: "200px"
|
||||
}}
|
||||
InputProps={{
|
||||
style: {
|
||||
backgroundColor: theme.palette.content.main,
|
||||
color: theme.palette.secondary.main,
|
||||
} }}
|
||||
InputLabelProps={{
|
||||
style: {
|
||||
color: theme.palette.secondary.main
|
||||
} }}
|
||||
inputRef={ fieldAdded }
|
||||
onChange={ changeAdded }
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<List sx={{
|
||||
border: "1px solid",
|
||||
borderColor: theme.palette.secondary.main,
|
||||
maxWidth: '745px',
|
||||
width: '100%',
|
||||
}}>
|
||||
<ListItem>
|
||||
<ListItemAvatar>
|
||||
<Avatar sx={{ backgroundColor: theme.palette.content.main }}>
|
||||
<ShoppingCartIcon sx={{
|
||||
color: theme.palette.content.main,
|
||||
display: "none"
|
||||
}} />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary="Название"
|
||||
sx={{
|
||||
textAlign: "center",
|
||||
// minWidth: "250px",
|
||||
maxWidth: "250px",
|
||||
padding: '0 10px'
|
||||
}}
|
||||
/>
|
||||
<ListItemText
|
||||
primary="Цена"
|
||||
sx={{
|
||||
textAlign: "center",
|
||||
// minWidth: "200px",
|
||||
padding: '0 10px',
|
||||
maxWidth: "200px" }}
|
||||
/>
|
||||
<ListItemText
|
||||
primary="Скидки"
|
||||
sx={{
|
||||
textAlign: "center",
|
||||
// minWidth: "200px",
|
||||
padding: '0 10px',
|
||||
maxWidth: "400px" }}
|
||||
/>
|
||||
<IconButton edge="end" aria-label="delete">
|
||||
<DeleteIcon sx={{
|
||||
color: theme.palette.grayDisabled.main,
|
||||
display: "none"
|
||||
}} />
|
||||
</IconButton>
|
||||
</ListItem>
|
||||
|
||||
{ cartRowsData.map( (item) => {
|
||||
price = item.price
|
||||
const appliedDscnts: number[] = [];
|
||||
if (!nonCommercial) {
|
||||
|
||||
if( item.type == "package" ) {
|
||||
// считаем цену в ПАКЕТАХ
|
||||
price = 0;
|
||||
discounts = "";
|
||||
priceBefore = 0;
|
||||
|
||||
if( item.tariffs ) {
|
||||
item.tariffs.forEach( (tariff) => {
|
||||
let tariffPrice = tariff.price;
|
||||
percents = 0;
|
||||
|
||||
// применяем скидки по промокоду
|
||||
if( selectedPromocode >= 0 ) {
|
||||
promocodeArray[ selectedPromocode ].privileges.forEach( (privilege) => {
|
||||
if( tariff.service == privilege.good ) {
|
||||
percents = percents + privilege.discount;
|
||||
|
||||
if( discounts ) { discounts += " × "; }
|
||||
discounts += `${ Math.round(privilege.discount * 100) }%`;
|
||||
}
|
||||
} )
|
||||
}
|
||||
|
||||
// применяем активные скидки
|
||||
if( discountsActiveArray.length >= 0 && selectedPromocode < 0 ) {
|
||||
discountsActiveArray.forEach( (activeDiscount) => {
|
||||
discountsArray.forEach( (discount, i) => {
|
||||
if( i == activeDiscount ) {
|
||||
discount.privileges.forEach( (privilege) => {
|
||||
if( privilege.discount != 0 ) {
|
||||
|
||||
if( fieldAddedValue ) { // внесено
|
||||
const f = Number(fieldAddedValue);
|
||||
let minDiscount = 100;
|
||||
let minI = -1;
|
||||
|
||||
discountsArray.forEach( (x, ii) => {
|
||||
x.privileges.forEach( (y) => {
|
||||
if( x.active && f - y.discount * 100 < minDiscount
|
||||
&& f - y.discount * 100 > 0 ) {
|
||||
minDiscount = f - y.discount * 100;
|
||||
minI = ii;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if( minI >= 0 ) {
|
||||
discountsArray[ minI ].privileges.forEach( (y) => {
|
||||
percents = percents + y.discount / discountsActiveArray.length; // костыль
|
||||
|
||||
if( discounts ) { discounts += " × "; }
|
||||
discounts += `${y.discount / discountsActiveArray.length * 100}%`;
|
||||
});
|
||||
}
|
||||
|
||||
} else { // не внесено
|
||||
if( tariff.service == privilege.good ) {
|
||||
percents = percents + privilege.discount;
|
||||
|
||||
if( discounts ) { discounts += " × "; }
|
||||
discounts += `${ Math.round(privilege.discount * 100) }% `;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// применяем активные скидки по времени объему
|
||||
if( discountsActiveArray.length >= 0 && selectedPromocode < 0 ) {
|
||||
discountsActiveArray.forEach( (activeDiscount) => {
|
||||
discountsArray.forEach( (discount, i) => {
|
||||
if( i == activeDiscount ) {
|
||||
if( tariff.time ) {
|
||||
const dTime = 0.1;
|
||||
percents = percents + dTime;
|
||||
|
||||
if( discounts ) discounts += " × ";
|
||||
//if( dTime != 0.0 ) discounts += `${ Math.round(dTime * 100) }%`;
|
||||
}
|
||||
|
||||
if( tariff.points ) {
|
||||
//const cTime = discountCapacity( tariff.points );
|
||||
//percents = percents + cTime;
|
||||
|
||||
//if( discounts ) discounts += " × ";
|
||||
//if( cTime != 0 ) discounts += `${ Math.round(cTime * 100) }%`;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// применяем активные скидки на продукт
|
||||
if( discountsActiveArray.length >= 0 && selectedPromocode < 0 ) {
|
||||
discountsActiveArray.forEach( (activeDiscount) => {
|
||||
discountsArray.forEach( (discount, i) => {
|
||||
if( i == activeDiscount ) {
|
||||
if( tariff.time && tariff.points ) {
|
||||
//const dProduct = discountProduct( tariff.time, tariff.points );
|
||||
//percents = percents + dProduct;
|
||||
|
||||
//if( discounts ) discounts += " × ";
|
||||
//if( dProduct != 0 ) discounts += `${ Math.round(dProduct * 100) }%`;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
percents = Number( percents.toFixed(2) );
|
||||
|
||||
priceBefore += tariffPrice;
|
||||
tariffPrice = tariffPrice - (tariffPrice * percents);
|
||||
|
||||
price += tariffPrice;
|
||||
} );
|
||||
}
|
||||
} else {
|
||||
// считаем цену в ТАРИФАХ
|
||||
price = item.price;
|
||||
percents = 0;
|
||||
discounts = "";
|
||||
|
||||
// применяем скидки по промокоду
|
||||
if( selectedPromocode >= 0 ) {
|
||||
promocodeArray[ selectedPromocode ].privileges.forEach( (privilege) => {
|
||||
console.log(item.service)
|
||||
console.log(privilege.good)
|
||||
if( item.service == privilege.good ) {
|
||||
appliedDscnts.push(privilege.discount)
|
||||
price *= (1 - privilege.discount)
|
||||
}
|
||||
} )
|
||||
} else {
|
||||
// применяем активные скидки
|
||||
if( fitDiscounts.length >= 0 ) {
|
||||
fitDiscounts.forEach( (activeDiscount) => {
|
||||
const discount = discountsArray[activeDiscount]
|
||||
discount.privileges.forEach((p) => {
|
||||
const svcName = item.service.split(' ')[0]
|
||||
if (p.good == svcName) {
|
||||
const summary = cartSummary.get(svcName) || {mbs:0,points:0,days:0}
|
||||
if (discount.toCapacity === 0 && discount.toTime === 0 && discount.basketMore === 0 && !(discount.incomeMore) ||
|
||||
discount.toCapacity > 0 && summary.points > discount.toCapacity && item.points > 0 && discount.toTime == 0
|
||||
|| discount.toTime >0 && summary.days > discount.toTime*100 && item.time > 0 && discount.toCapacity == 0 ||
|
||||
discount.toTime > 0 && discount.toCapacity > 0 && summary.days > discount.toTime*100 && summary.points > discount.toCapacity ){
|
||||
|
||||
price *= (1-p.discount)
|
||||
appliedDscnts.push(p.discount)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
percents = Number( percents.toFixed(2) );
|
||||
|
||||
priceBefore = price;
|
||||
price = price - (price * percents);
|
||||
}
|
||||
}
|
||||
prices += price;
|
||||
|
||||
return(
|
||||
<ListItem key={ item.id }>
|
||||
<ListItemAvatar>
|
||||
<Avatar sx={{ backgroundColor: theme.palette.secondary.main }}>
|
||||
<ShoppingCartIcon sx={{
|
||||
color: theme.palette.content.main,
|
||||
}} />
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={ item.name }
|
||||
sx={{ minWidth: "250px", maxWidth: "250px" }}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={ `${separator(price)} ₽` }
|
||||
sx={{ textAlign: "center", minWidth: "200px", maxWidth: "200px" }}
|
||||
/>
|
||||
<ListItemText
|
||||
primary={ `${(appliedDscnts.map(e=>(e*100).toFixed(2)).join(' × '))} = ${(100 - appliedDscnts.reduce((a : number,cv : number) => a*(1-cv), 100)).toFixed(2)}%` }
|
||||
sx={{ textAlign: "center", minWidth: "400px", maxWidth: "400px" }}
|
||||
/>
|
||||
<IconButton edge="end" aria-label="delete" onClick={ () => handleRemoveBasket( item.id ) }>
|
||||
<DeleteIcon sx={{
|
||||
color: theme.palette.secondary.main,
|
||||
}} />
|
||||
</IconButton>
|
||||
</ListItem>
|
||||
)
|
||||
} ) }
|
||||
|
||||
<Typography id="transition-modal-title" variant="h6" sx={{
|
||||
fontWeight: "normal",
|
||||
textAlign: "center",
|
||||
marginTop: "15px",
|
||||
fontSize: "16px"
|
||||
}}>
|
||||
Скидки:   { discountsAfter(prices) }
|
||||
</Typography>
|
||||
|
||||
<Typography id="transition-modal-title" variant="h6" sx={{
|
||||
fontWeight: "normal",
|
||||
textAlign: "center",
|
||||
marginTop: "10px"
|
||||
}}>
|
||||
ИТОГО:   { separator( prices ) } ₽
|
||||
</Typography>
|
||||
|
||||
</List>
|
||||
</Box>
|
||||
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
export default DataGridElement;
|
@ -1,185 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { Box, Modal, Fade, Backdrop, Typography, Button, TextField } from "@mui/material";
|
||||
import { ArrayProps } from "../types";
|
||||
import useStore, { StoreState } from "../../../../../store";
|
||||
import theme from "../../../../../theme";
|
||||
|
||||
|
||||
export interface MWProps {
|
||||
open: boolean
|
||||
type: number
|
||||
variant: number
|
||||
close: () => void
|
||||
}
|
||||
|
||||
const ModalMini = ({open, type, variant, close}: MWProps ) => {
|
||||
let tariffsArray:Array<ArrayProps> = useStore((state) => state.tariffsArray);
|
||||
const { tariffsArraySet } = useStore<StoreState>((state) => state);
|
||||
|
||||
const types = [ "", "Шаблонизатор документов", "Опросник", "Сокращатель ссылок" ];
|
||||
const variants = [ "Количество", "Срок (дней)", "Количество (гб)" ];
|
||||
|
||||
const fieldName = React.useRef<HTMLInputElement | null>(null);
|
||||
const fieldTime = React.useRef<HTMLInputElement | null>(null);
|
||||
const fieldPrice = React.useRef<HTMLInputElement | null>(null);
|
||||
|
||||
const checkTariff = () => {
|
||||
if( fieldName.current != null && fieldTime.current != null && fieldPrice.current != null ) {
|
||||
if( fieldName.current.value && fieldTime.current.value && fieldPrice.current.value ) {
|
||||
const getData = localStorage.getItem("tariffs");
|
||||
|
||||
if( getData != null ) { tariffsArray = JSON.parse(getData); }
|
||||
|
||||
const data = [ 0, 0, 0 ];
|
||||
|
||||
if( variant == 0 ) { data[ 0 ] = parseInt(fieldTime.current.value); }
|
||||
if( variant == 1 ) { data[ 1 ] = parseInt(fieldTime.current.value); }
|
||||
if( variant == 2 ) { data[ 2 ] = parseInt(fieldTime.current.value); }
|
||||
|
||||
const tariffsArrayNew = [...tariffsArray, {
|
||||
"id": new Date().getTime(),
|
||||
"name": fieldName.current.value,
|
||||
"type": "tariff",
|
||||
"service": types[ type ],
|
||||
"disk": data[ 2 ],
|
||||
"time": data[ 1 ],
|
||||
"points": data[ 0 ],
|
||||
"price": +fieldPrice.current.value
|
||||
} ];
|
||||
|
||||
tariffsArraySet( tariffsArrayNew );
|
||||
|
||||
localStorage.setItem( "tariffs", JSON.stringify( tariffsArrayNew ) );
|
||||
close();
|
||||
|
||||
console.log( tariffsArrayNew );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Modal
|
||||
aria-labelledby="transition-modal-title"
|
||||
aria-describedby="transition-modal-description"
|
||||
open={ open }
|
||||
onClose={ () => close() }
|
||||
closeAfterTransition
|
||||
BackdropComponent={Backdrop}
|
||||
BackdropProps={{
|
||||
timeout: 500,
|
||||
}}
|
||||
>
|
||||
<Fade in={open}>
|
||||
<Box sx={{
|
||||
position: "absolute" as "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: "350px",
|
||||
height: "350px",
|
||||
bgcolor: theme.palette.menu.main,
|
||||
boxShadow: 24,
|
||||
color: theme.palette.secondary.main,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}>
|
||||
<TextField
|
||||
id = "standard-basic"
|
||||
label = { types[ type ] }
|
||||
disabled={ true }
|
||||
variant = "filled"
|
||||
color = "secondary"
|
||||
sx = {{ width: "80%", marginTop: theme.spacing(1) }}
|
||||
InputProps={{
|
||||
style: {
|
||||
backgroundColor: theme.palette.content.main,
|
||||
color: theme.palette.secondary.main,
|
||||
} }}
|
||||
InputLabelProps={{
|
||||
style: {
|
||||
color: theme.palette.secondary.main
|
||||
} }}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
id = "standard-basic"
|
||||
label = { "Название тарифа" }
|
||||
variant = "filled"
|
||||
color = "secondary"
|
||||
sx = {{ width: "80%", marginTop: theme.spacing(1) }}
|
||||
InputProps={{
|
||||
style: {
|
||||
backgroundColor: theme.palette.content.main,
|
||||
color: theme.palette.secondary.main,
|
||||
} }}
|
||||
InputLabelProps={{
|
||||
style: {
|
||||
color: theme.palette.secondary.main
|
||||
} }}
|
||||
inputRef={ fieldName }
|
||||
/>
|
||||
|
||||
<TextField
|
||||
id = "standard-basic"
|
||||
label = { variants[ variant ] }
|
||||
variant = "filled"
|
||||
color = "secondary"
|
||||
sx = {{ width: "80%", marginTop: theme.spacing(1) }}
|
||||
InputProps={{
|
||||
style: {
|
||||
backgroundColor: theme.palette.content.main,
|
||||
color: theme.palette.secondary.main,
|
||||
} }}
|
||||
InputLabelProps={{
|
||||
style: {
|
||||
color: theme.palette.secondary.main
|
||||
} }}
|
||||
inputRef={ fieldTime }
|
||||
/>
|
||||
|
||||
<TextField
|
||||
id = "standard-basic"
|
||||
label = "Цена"
|
||||
variant = "filled"
|
||||
color = "secondary"
|
||||
sx = {{ width: "80%", marginTop: theme.spacing(1) }}
|
||||
InputProps={{
|
||||
style: {
|
||||
backgroundColor: theme.palette.content.main,
|
||||
color: theme.palette.secondary.main,
|
||||
} }}
|
||||
InputLabelProps={{
|
||||
style: {
|
||||
color: theme.palette.secondary.main
|
||||
} }}
|
||||
inputRef={ fieldPrice }
|
||||
/>
|
||||
|
||||
|
||||
<Button
|
||||
variant = "contained"
|
||||
onClick={ () => checkTariff() }
|
||||
sx={{
|
||||
backgroundColor: theme.palette.grayDark.main,
|
||||
marginTop: "30px",
|
||||
height: "42px",
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Применить
|
||||
</Button>
|
||||
</Box>
|
||||
</Fade>
|
||||
</Modal>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default ModalMini;
|
@ -1,92 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { Box, Modal, Fade, Backdrop, Button, TextField } from "@mui/material";
|
||||
import theme from "../../../../../theme";
|
||||
|
||||
|
||||
export interface MWProps {
|
||||
open: boolean
|
||||
newPackage: (name: string) => void
|
||||
close: () => void
|
||||
}
|
||||
|
||||
const ModalPackage = ({open, newPackage, close}: MWProps ) => {
|
||||
const fieldName = React.useRef<HTMLInputElement | null>(null);
|
||||
|
||||
const checkName = () => {
|
||||
if( fieldName.current != null ) {
|
||||
newPackage( fieldName.current.value );
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Modal
|
||||
aria-labelledby="transition-modal-title"
|
||||
aria-describedby="transition-modal-description"
|
||||
open={ open }
|
||||
onClose={ () => close() }
|
||||
closeAfterTransition
|
||||
BackdropComponent={Backdrop}
|
||||
BackdropProps={{
|
||||
timeout: 500,
|
||||
}}
|
||||
>
|
||||
<Fade in={open}>
|
||||
<Box sx={{
|
||||
position: "absolute" as "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
width: "350px",
|
||||
height: "170px",
|
||||
bgcolor: theme.palette.menu.main,
|
||||
boxShadow: 24,
|
||||
color: theme.palette.secondary.main,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
}}>
|
||||
<TextField
|
||||
id = "standard-basic"
|
||||
label = { "Название пакета" }
|
||||
variant = "filled"
|
||||
color = "secondary"
|
||||
sx = {{ width: "80%", marginTop: theme.spacing(1) }}
|
||||
InputProps={{
|
||||
style: {
|
||||
backgroundColor: theme.palette.content.main,
|
||||
color: theme.palette.secondary.main,
|
||||
} }}
|
||||
InputLabelProps={{
|
||||
style: {
|
||||
color: theme.palette.secondary.main
|
||||
} }}
|
||||
inputRef={ fieldName }
|
||||
/>
|
||||
|
||||
<Button
|
||||
variant = "contained"
|
||||
onClick={ () => checkName() }
|
||||
sx={{
|
||||
backgroundColor: theme.palette.grayDark.main,
|
||||
marginTop: "30px",
|
||||
height: "42px",
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Применить
|
||||
</Button>
|
||||
|
||||
</Box>
|
||||
</Fade>
|
||||
</Modal>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default ModalPackage;
|
@ -1,81 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { Box, Typography, Button } from "@mui/material";
|
||||
import theme from "../../../../../theme";
|
||||
|
||||
|
||||
export interface MWProps {
|
||||
openModal: (type:number, num: number) => void
|
||||
}
|
||||
|
||||
const Quiz: React.FC<MWProps> = ({ openModal }) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
sx={{
|
||||
width: "90%",
|
||||
height: "60px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
color: theme.palette.secondary.main
|
||||
}}>
|
||||
Опросник
|
||||
</Typography>
|
||||
|
||||
<Box sx={{
|
||||
marginTop: "35px",
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(2, 1fr)",
|
||||
gridGap: "20px",
|
||||
marginBottom: "120px",
|
||||
}}>
|
||||
<Button
|
||||
variant = "contained"
|
||||
onClick={ () => openModal(2, 1) }
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
padding: "11px 43px",
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Создать тариф на время
|
||||
</Button>
|
||||
<Button
|
||||
variant = "contained"
|
||||
onClick={ () => openModal(2, 0) }
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
padding: '11px 43px',
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Создать тариф на объем
|
||||
</Button>
|
||||
<Button
|
||||
variant = "contained"
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
padding: '11px 43px',
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Изменить тариф
|
||||
</Button>
|
||||
</Box>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default Quiz;
|
@ -1,95 +0,0 @@
|
||||
import * as React from "react";
|
||||
import { Box, Typography, Button } from "@mui/material";
|
||||
import theme from "../../../../../theme";
|
||||
|
||||
|
||||
export interface MWProps {
|
||||
openModal: (type:number, num: number) => void
|
||||
}
|
||||
|
||||
const Templater: React.FC<MWProps> = ({ openModal }) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Typography
|
||||
variant="subtitle1"
|
||||
sx={{
|
||||
width: "90%",
|
||||
height: "60px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
color: theme.palette.secondary.main
|
||||
}}>
|
||||
Шаблонизатор документов
|
||||
</Typography>
|
||||
|
||||
<Box sx={{
|
||||
marginTop: "35px",
|
||||
display: "grid",
|
||||
gridTemplateColumns: "repeat(2, 1fr)",
|
||||
gridGap: "20px",
|
||||
marginBottom: "120px",
|
||||
}}>
|
||||
<Button
|
||||
variant = "contained"
|
||||
onClick={ () => openModal(1, 1) }
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
padding: '11px 25px',
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Создать тариф на время
|
||||
</Button>
|
||||
<Button
|
||||
variant = "contained"
|
||||
onClick={ () => openModal(1, 0) }
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
padding: '11px 25px',
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Создать тариф на объем
|
||||
</Button>
|
||||
<Button
|
||||
variant = "contained"
|
||||
onClick={ () => openModal(1, 2) }
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
padding: '11px 25px',
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Создать тариф на гигабайты
|
||||
</Button>
|
||||
<Button
|
||||
variant = "contained"
|
||||
sx={{
|
||||
backgroundColor: theme.palette.menu.main,
|
||||
padding: '11px 25px',
|
||||
fontWeight: "normal",
|
||||
fontSize: "17px",
|
||||
"&:hover": {
|
||||
backgroundColor: theme.palette.grayMedium.main
|
||||
}
|
||||
}}>
|
||||
Изменить тариф
|
||||
</Button>
|
||||
</Box>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export default Templater;
|
File diff suppressed because it is too large
Load Diff
29
src/pages/dashboard/Content/Tariffs/privilegesDG.tsx
Normal file
29
src/pages/dashboard/Content/Tariffs/privilegesDG.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import * as React from "react";
|
||||
import { GridColDef } from "@mui/x-data-grid";
|
||||
import DataGrid from "@kitUI/datagrid";
|
||||
import privilegesStore from "@stores/privileges";
|
||||
|
||||
const columns: GridColDef[] = [
|
||||
{ field: 'name', headerName: 'Привелегия', width: 150 },
|
||||
{ field: 'description', headerName: 'Описание', width: 550 },//инфо из гитлаба.
|
||||
{ field: 'type', headerName: 'Тип', width: 150 },
|
||||
{ field: 'price', headerName: 'Стоимость', width: 50 }
|
||||
]
|
||||
export default () => {
|
||||
const {privileges} = privilegesStore()
|
||||
let rows = []
|
||||
if (Object.keys(privileges).length !== 0) {
|
||||
for (let [id, value] of Object.entries(privileges)) {
|
||||
rows.push({id:id,name:value.name,description:value.description,type:value.type,price:value.price})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<DataGrid
|
||||
checkboxSelection={true}
|
||||
rows={ rows }
|
||||
columns={columns}
|
||||
/>
|
||||
);
|
||||
}
|
27
src/pages/dashboard/Content/Tariffs/tariffsDG.tsx
Normal file
27
src/pages/dashboard/Content/Tariffs/tariffsDG.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import * as React from "react";
|
||||
import { GridColDef, GridSelectionModel, GridToolbar } from "@mui/x-data-grid";
|
||||
import DataGrid from "@kitUI/datagrid";
|
||||
|
||||
|
||||
const columns: GridColDef[] = [
|
||||
{ field: 'id', headerName: 'ID', width: 150 },
|
||||
{ field: 'id', headerName: 'Название тарифа', width: 150 },
|
||||
{ field: 'id', headerName: 'Сервис', width: 150 },//инфо из гитлаба.
|
||||
{ field: 'id', headerName: 'Гигабайты', width: 150 },
|
||||
{ field: 'id', headerName: 'Привелегия', width: 150 },
|
||||
{ field: 'id', headerName: 'Количество привелегии', width: 150 },
|
||||
{ field: 'id', headerName: 'Условия', width: 150 },
|
||||
]
|
||||
|
||||
export default () => {
|
||||
|
||||
return (
|
||||
<DataGrid
|
||||
checkboxSelection={true}
|
||||
rows={ [] }
|
||||
columns={columns}
|
||||
components={{ Toolbar: GridToolbar }}
|
||||
// onSelectionModelChange={ (ids) => onRowsSelectionHandler( ids ) }
|
||||
/>
|
||||
);
|
||||
}
|
60
src/stores/privileges.ts
Normal file
60
src/stores/privileges.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import create from "zustand";
|
||||
import {Privilege, State} from "@kitUI/types/privileges";
|
||||
|
||||
const useStore = create<State>()(
|
||||
(set, get) => ({
|
||||
privileges: {
|
||||
p1: {
|
||||
"serviceKey": "templategen",
|
||||
"name": "unlim",
|
||||
"description":"привилегия безлимитного доступа к шаблонизатору на время. в днях",
|
||||
"type":"day",
|
||||
"price": 0.5
|
||||
},
|
||||
p2: {
|
||||
"serviceKey": "templategen",
|
||||
"name": "gencount",
|
||||
"description":"привилегия на определённое количество генераций",
|
||||
"type":"count",
|
||||
"price": 0.1
|
||||
},
|
||||
p3: {
|
||||
"serviceKey": "squiz",
|
||||
"name": "unlim",
|
||||
"description":"привилегия безлимитного доступа к опроснику. в днях",
|
||||
"type":"day",
|
||||
"price": 3.0
|
||||
},
|
||||
p4: {
|
||||
"serviceKey": "squiz",
|
||||
"name": "activequiz",
|
||||
"description":"привилегия создания ограниченного количества опросов",
|
||||
"type":"count",
|
||||
"price": 1.0
|
||||
},
|
||||
p5: {
|
||||
"serviceKey": "dwarfener",
|
||||
"name": "unlim",
|
||||
"description":"привилегия безлимитного доступа к сокращателю на время. в днях",
|
||||
"type":"day",
|
||||
"price": 0.1
|
||||
},
|
||||
p6: {
|
||||
"serviceKey": "dwarfener",
|
||||
"name": "abcount",
|
||||
"description":"привилегия на количество активных ссылок в абтестах",
|
||||
"type":"count",
|
||||
"price": 0.7
|
||||
},
|
||||
p7: {
|
||||
"serviceKey": "dwarfener",
|
||||
"name": "extended",
|
||||
"description":"привилегия расширенной статистики, в днях",
|
||||
"type":"day",
|
||||
"price": 2
|
||||
},
|
||||
},
|
||||
tariffsUpdate: (element:Privilege) => {set((state:State) => ({ privileges: {...state.privileges, ...element} }))}
|
||||
})
|
||||
);
|
||||
export default useStore;
|
@ -1,8 +1,8 @@
|
||||
import create from "zustand";
|
||||
import { persist } from "zustand/middleware"
|
||||
import { ArrayProps } from "./pages/dashboard/Content/Tariffs/types";
|
||||
import { PromocodeProps } from "./pages/dashboard/Content/Promocode/types";
|
||||
import { DiscountProps } from "./pages/dashboard/Content/Discounts/types";
|
||||
import { ArrayProps } from "../pages/dashboard/Content/Tariffs/types";
|
||||
import { PromocodeProps } from "../pages/dashboard/Content/Promocode/types";
|
||||
import { DiscountProps } from "../pages/dashboard/Content/Discounts/types";
|
||||
|
||||
|
||||
const useStore = create<StoreState>()(
|
18
src/stores/tariffs.ts
Normal file
18
src/stores/tariffs.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import create from "zustand";
|
||||
import { persist } from "zustand/middleware"
|
||||
|
||||
|
||||
const useStore = create<any>()(
|
||||
persist((set, get) => ({
|
||||
tariffs: {},
|
||||
tariffsUpdate: (element:any) => {set((state:any) => ({ tariffs: {...state.tariffs, ...element} }))},
|
||||
tariffsClear: () => set({tariffs: {}}),
|
||||
}),
|
||||
{
|
||||
name: "tariffs",
|
||||
getStorage: () => localStorage,
|
||||
}
|
||||
));
|
||||
|
||||
|
||||
export default useStore;
|
181
src/theme.ts
181
src/theme.ts
@ -1,4 +1,6 @@
|
||||
import { Theme } from '@mui/material/styles';
|
||||
import {createTheme, PaletteColorOptions} from "@mui/material";
|
||||
import { deepmerge } from '@mui/utils';
|
||||
//import { createTheme } from "./types";
|
||||
|
||||
declare module '@mui/material/Button' {
|
||||
@ -6,17 +8,88 @@ declare module '@mui/material/Button' {
|
||||
enter: true;
|
||||
}
|
||||
}
|
||||
declare module '@mui/material/Paper' {
|
||||
interface PaperPropsVariantOverrides {
|
||||
bar: true;
|
||||
}
|
||||
}
|
||||
declare module '@mui/material/styles' {
|
||||
interface Theme {
|
||||
palette: {
|
||||
primary: {
|
||||
main: string
|
||||
},
|
||||
secondary: {
|
||||
main: string;
|
||||
},
|
||||
menu: {
|
||||
main: string;
|
||||
},
|
||||
content: {
|
||||
main: string;
|
||||
},
|
||||
grayLight: {
|
||||
main: string;
|
||||
},
|
||||
grayDark: {
|
||||
main: string;
|
||||
},
|
||||
grayMedium: {
|
||||
main: string;
|
||||
},
|
||||
grayDisabled: {
|
||||
main: string;
|
||||
},
|
||||
golden: {
|
||||
main: string;
|
||||
},
|
||||
goldenDark: {
|
||||
main: string;
|
||||
},
|
||||
goldenMedium: {
|
||||
main: string;
|
||||
},
|
||||
caption: {
|
||||
main: string;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface PaletteOptions {
|
||||
menu?: PaletteColorOptions;
|
||||
content?: PaletteColorOptions;
|
||||
grayLight?: PaletteColorOptions;
|
||||
grayDark?: PaletteColorOptions;
|
||||
grayMedium?: PaletteColorOptions;
|
||||
grayDisabled?: PaletteColorOptions;
|
||||
golden?: PaletteColorOptions;
|
||||
goldenDark?: PaletteColorOptions;
|
||||
goldenMedium?: PaletteColorOptions;
|
||||
hover?: PaletteColorOptions;
|
||||
}
|
||||
|
||||
// allow configuration using `createTheme`
|
||||
interface TypographyVariants {
|
||||
body1: React.CSSProperties;
|
||||
subtitle1: React.CSSProperties;
|
||||
subtitle2: React.CSSProperties;
|
||||
caption: React.CSSProperties;
|
||||
h5: React.CSSProperties;
|
||||
h6: React.CSSProperties;
|
||||
button: React.CSSProperties;
|
||||
}
|
||||
}
|
||||
|
||||
const fontFamily: string = "GilroyRegular";
|
||||
const fontWeight: string = "600";
|
||||
|
||||
const theme = createTheme({
|
||||
const options1 = {
|
||||
palette: {
|
||||
primary: {
|
||||
main: "#111217"
|
||||
},
|
||||
secondary: {
|
||||
main: "#ffffff"
|
||||
main: "#e6e8ec"
|
||||
},
|
||||
menu: {
|
||||
main: "#2f3339"
|
||||
@ -24,6 +97,9 @@ const theme = createTheme({
|
||||
content: {
|
||||
main: "#26272c"
|
||||
},
|
||||
hover: {
|
||||
main: "#191a1e"
|
||||
},
|
||||
grayLight: {
|
||||
main: "#707070"
|
||||
},
|
||||
@ -46,7 +122,8 @@ const theme = createTheme({
|
||||
main: "#2a2b1d"
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
const options2 = {
|
||||
typography: {
|
||||
body1: {
|
||||
fontFamily: fontFamily
|
||||
@ -90,91 +167,51 @@ const theme = createTheme({
|
||||
|
||||
components: {
|
||||
MuiButton: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
color: options1.palette.secondary.main,
|
||||
backgroundColor: options1.palette.menu.main,
|
||||
padding: "12px",
|
||||
fontSize: "13px",
|
||||
"&:hover": {
|
||||
backgroundColor: options1.palette.hover.main,
|
||||
}
|
||||
}
|
||||
},
|
||||
variants: [
|
||||
{
|
||||
props: {
|
||||
variant: 'enter' },
|
||||
variant: 'enter'
|
||||
},
|
||||
style: {
|
||||
backgroundColor: "#26272c",
|
||||
color: options1.palette.secondary.main,
|
||||
backgroundColor: options1.palette.content.main,
|
||||
padding: '12px 48px',
|
||||
"&:hover": {
|
||||
backgroundColor: "#2f3339"
|
||||
backgroundColor: options1.palette.hover.main,
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
MuiPaper: {
|
||||
variants: [
|
||||
{
|
||||
props: {
|
||||
variant: "bar"
|
||||
},
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
declare module '@mui/material/styles' {
|
||||
interface Theme {
|
||||
palette: {
|
||||
primary: {
|
||||
main: string
|
||||
},
|
||||
secondary: {
|
||||
main: string;
|
||||
},
|
||||
menu: {
|
||||
main: string;
|
||||
},
|
||||
content: {
|
||||
main: string;
|
||||
},
|
||||
grayLight: {
|
||||
main: string;
|
||||
},
|
||||
grayDark: {
|
||||
main: string;
|
||||
},
|
||||
grayMedium: {
|
||||
main: string;
|
||||
},
|
||||
grayDisabled: {
|
||||
main: string;
|
||||
},
|
||||
golden: {
|
||||
main: string;
|
||||
},
|
||||
goldenDark: {
|
||||
main: string;
|
||||
},
|
||||
goldenMedium: {
|
||||
main: string;
|
||||
},
|
||||
caption: {
|
||||
main: string;
|
||||
style: {
|
||||
backgroundColor: options1.palette.grayMedium.main,
|
||||
padding: "15px",
|
||||
width: "100%"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
interface PaletteOptions {
|
||||
menu?: PaletteColorOptions;
|
||||
content?: PaletteColorOptions;
|
||||
grayLight?: PaletteColorOptions;
|
||||
grayDark?: PaletteColorOptions;
|
||||
grayMedium?: PaletteColorOptions;
|
||||
grayDisabled?: PaletteColorOptions;
|
||||
golden?: PaletteColorOptions;
|
||||
goldenDark?: PaletteColorOptions;
|
||||
goldenMedium?: PaletteColorOptions;
|
||||
}
|
||||
// allow configuration using `createTheme`
|
||||
interface TypographyVariants {
|
||||
body1: React.CSSProperties;
|
||||
subtitle1: React.CSSProperties;
|
||||
subtitle2: React.CSSProperties;
|
||||
caption: React.CSSProperties;
|
||||
h5: React.CSSProperties;
|
||||
h6: React.CSSProperties;
|
||||
button: React.CSSProperties;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
};
|
||||
const theme = createTheme(deepmerge(options1, options2));
|
||||
export default theme;
|
11
tsconfig.extend.json
Normal file
11
tsconfig.extend.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./src",
|
||||
"paths": {
|
||||
"@theme": ["./theme.ts"],
|
||||
"@root/*": ["./*"],
|
||||
"@kitUI/*": ["./kitUI/*"],
|
||||
"@stores/*": ["./stores/*"]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"extends": "./tsconfig.extend.json",
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"lib": [
|
||||
|
Loading…
Reference in New Issue
Block a user