Merge branch 'cart-calc' into promocode-field
This commit is contained in:
commit
a2ded0d895
24027
package-lock.json
generated
24027
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
148
package.json
148
package.json
@ -1,75 +1,77 @@
|
|||||||
{
|
{
|
||||||
"name": "hub_frontend",
|
"name": "hub_frontend",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "craco start",
|
"start": "craco start",
|
||||||
"build": "craco build",
|
"build": "craco build",
|
||||||
"test": "craco test --env=node --transformIgnorePatterns \"node_modules/(?!@frontend)/\"",
|
"test": "craco test --env=node --transformIgnorePatterns \"node_modules/(?!@frontend)/\"",
|
||||||
"test:cart": "craco test src/utils/calcCart --transformIgnorePatterns \"node_modules/(?!@frontend)/\"",
|
"test:cart": "vitest ./src/utils/calcCart",
|
||||||
"eject": "craco eject",
|
"eject": "craco eject",
|
||||||
"test:cypress": "start-server-and-test start http://localhost:3000 cypress",
|
"test:cypress": "start-server-and-test start http://localhost:3000 cypress",
|
||||||
"cypress": "cypress open",
|
"cypress": "cypress open",
|
||||||
"prepare": "husky install"
|
"prepare": "husky install"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.10.5",
|
"@emotion/react": "^11.10.5",
|
||||||
"@emotion/styled": "^11.10.5",
|
"@emotion/styled": "^11.10.5",
|
||||||
"@frontend/kitui": "1.0.65",
|
"@frontend/kitui": "^1.0.66",
|
||||||
"@mui/icons-material": "^5.10.14",
|
"@mui/icons-material": "^5.10.14",
|
||||||
"@mui/material": "^5.10.14",
|
"@mui/material": "^5.10.14",
|
||||||
"@popperjs/core": "^2.11.8",
|
"@popperjs/core": "^2.11.8",
|
||||||
"axios": "^1.4.0",
|
"axios": "^1.4.0",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"classnames": "^2.3.2",
|
"classnames": "^2.3.2",
|
||||||
"cypress": "^12.17.3",
|
"cypress": "^12.17.3",
|
||||||
"formik": "^2.2.9",
|
"formik": "^2.2.9",
|
||||||
"husky": "^8.0.3",
|
"husky": "^8.0.3",
|
||||||
"immer": "^10.0.2",
|
"immer": "^10.0.2",
|
||||||
"isomorphic-fetch": "^3.0.0",
|
"isomorphic-fetch": "^3.0.0",
|
||||||
"notistack": "^3.0.1",
|
"notistack": "^3.0.1",
|
||||||
"pdfjs-dist": "3.6.172",
|
"pdfjs-dist": "3.6.172",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-error-boundary": "^4.0.11",
|
"react-error-boundary": "^4.0.11",
|
||||||
"react-pdf": "^7.1.2",
|
"react-pdf": "^7.1.2",
|
||||||
"react-router-dom": "^6.15.0",
|
"react-router-dom": "^6.15.0",
|
||||||
"react-slick": "^0.29.0",
|
"react-slick": "^0.29.0",
|
||||||
"slick-carousel": "^1.8.1",
|
"slick-carousel": "^1.8.1",
|
||||||
"use-debounce": "^10.0.0",
|
"swr": "^2.2.5",
|
||||||
"web-vitals": "^2.1.0",
|
"use-debounce": "^10.0.0",
|
||||||
"yup": "^1.1.1",
|
"web-vitals": "^2.1.0",
|
||||||
"zustand": "^4.3.8"
|
"yup": "^1.1.1",
|
||||||
},
|
"zustand": "^4.3.8"
|
||||||
"devDependencies": {
|
},
|
||||||
"@craco/craco": "^7.1.0",
|
"devDependencies": {
|
||||||
"@testing-library/jest-dom": "^5.14.1",
|
"@craco/craco": "^7.1.0",
|
||||||
"@testing-library/react": "^13.0.0",
|
"@testing-library/jest-dom": "^5.14.1",
|
||||||
"@testing-library/user-event": "^13.2.1",
|
"@testing-library/react": "^13.0.0",
|
||||||
"@types/jest": "^27.0.1",
|
"@testing-library/user-event": "^13.2.1",
|
||||||
"@types/node": "^16.7.13",
|
"@types/jest": "^27.0.1",
|
||||||
"@types/react": "^18.0.0",
|
"@types/node": "^16.7.13",
|
||||||
"@types/react-dom": "^18.0.0",
|
"@types/react": "^18.0.0",
|
||||||
"@types/react-slick": "^0.23.10",
|
"@types/react-dom": "^18.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.9.1",
|
"@types/react-slick": "^0.23.10",
|
||||||
"@typescript-eslint/parser": "^6.9.1",
|
"@typescript-eslint/eslint-plugin": "^6.9.1",
|
||||||
"craco-alias": "^3.0.1",
|
"@typescript-eslint/parser": "^6.9.1",
|
||||||
"eslint": "^8.53.0",
|
"craco-alias": "^3.0.1",
|
||||||
"eslint-plugin-react": "^7.33.2",
|
"eslint": "^8.53.0",
|
||||||
"jest": "^29.5.0",
|
"eslint-plugin-react": "^7.33.2",
|
||||||
"react-scripts": "5.0.1",
|
"jest": "^29.5.0",
|
||||||
"typescript": "^5.4.2"
|
"react-scripts": "5.0.1",
|
||||||
},
|
"typescript": "^5.4.2",
|
||||||
"browserslist": {
|
"vitest": "^1.4.0"
|
||||||
"production": [
|
},
|
||||||
">0.2%",
|
"browserslist": {
|
||||||
"not dead",
|
"production": [
|
||||||
"not op_mini all"
|
">0.2%",
|
||||||
],
|
"not dead",
|
||||||
"development": [
|
"not op_mini all"
|
||||||
"last 1 chrome version",
|
],
|
||||||
"last 1 firefox version",
|
"development": [
|
||||||
"last 1 safari version"
|
"last 1 chrome version",
|
||||||
]
|
"last 1 firefox version",
|
||||||
}
|
"last 1 safari version"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,6 @@ export async function getHistory(): Promise<[GetHistoryResponse | GetHistoryResp
|
|||||||
|
|
||||||
|
|
||||||
historyResponse.records = checked || []
|
historyResponse.records = checked || []
|
||||||
console.log("historyResponse ", historyResponse)
|
|
||||||
return [historyResponse]
|
return [historyResponse]
|
||||||
} catch (nativeError) {
|
} catch (nativeError) {
|
||||||
const [error] = parseAxiosError(nativeError)
|
const [error] = parseAxiosError(nativeError)
|
||||||
|
@ -1,88 +1,119 @@
|
|||||||
import { Tariff, makeRequest } from "@frontend/kitui"
|
import { Tariff, makeRequest } from "@frontend/kitui";
|
||||||
import { CreateTariffBody } from "@root/model/customTariffs"
|
import { CreateTariffBody } from "@root/model/customTariffs";
|
||||||
import { parseAxiosError } from "@root/utils/parse-error"
|
import { parseAxiosError } from "@root/utils/parse-error";
|
||||||
|
|
||||||
import type { ServiceKeyToPrivilegesMap } from "@root/model/privilege"
|
import type { ServiceKeyToPrivilegesMap } from "@root/model/privilege";
|
||||||
import type { GetTariffsResponse } from "@root/model/tariff"
|
import type { GetTariffsResponse } from "@root/model/tariff";
|
||||||
|
import { removeTariffFromCart } from "@root/stores/user";
|
||||||
|
|
||||||
const apiUrl = process.env.REACT_APP_DOMAIN + "/strator"
|
const apiUrl = process.env.REACT_APP_DOMAIN + "/strator"
|
||||||
console.log("домен с которого тарифы запрашиваются", process.env.REACT_APP_DOMAIN)
|
console.log("домен с которого тарифы запрашиваются", process.env.REACT_APP_DOMAIN)
|
||||||
console.log("домен с которого тарифы запрашиваются", apiUrl)
|
console.log("домен с которого тарифы запрашиваются", apiUrl)
|
||||||
|
|
||||||
export async function getTariffs(
|
export async function getTariffs(
|
||||||
apiPage: number,
|
apiPage: number,
|
||||||
tariffsPerPage: number,
|
tariffsPerPage: number,
|
||||||
signal: AbortSignal | undefined
|
signal: AbortSignal | undefined
|
||||||
): Promise<[GetTariffsResponse | null, string?]> {
|
): Promise<[GetTariffsResponse | null, string?]> {
|
||||||
try {
|
try {
|
||||||
const tariffsResponse = await makeRequest<never, GetTariffsResponse>({
|
const tariffsResponse = await makeRequest<never, GetTariffsResponse>({
|
||||||
url: apiUrl + `/tariff?page=${apiPage}&limit=${tariffsPerPage}`,
|
url: apiUrl + `/tariff?page=${apiPage}&limit=${tariffsPerPage}`,
|
||||||
method: "get",
|
method: "get",
|
||||||
useToken: true,
|
useToken: true,
|
||||||
signal,
|
signal,
|
||||||
})
|
});
|
||||||
|
|
||||||
return [tariffsResponse]
|
return [tariffsResponse];
|
||||||
} catch (nativeError) {
|
} catch (nativeError) {
|
||||||
const [error] = parseAxiosError(nativeError)
|
const [error] = parseAxiosError(nativeError);
|
||||||
|
|
||||||
return [null, `Не удалось получить список тарифов. ${error}`]
|
return [null, `Не удалось получить список тарифов. ${error}`];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createTariff(tariff: CreateTariffBody): Promise<[Tariff | null, string?]> {
|
export async function createTariff(tariff: CreateTariffBody): Promise<[Tariff | null, string?]> {
|
||||||
try {
|
try {
|
||||||
const createTariffResponse = await makeRequest<CreateTariffBody, Tariff>({
|
const createTariffResponse = await makeRequest<CreateTariffBody, Tariff>({
|
||||||
url: `${apiUrl}/tariff`,
|
url: `${apiUrl}/tariff`,
|
||||||
method: "post",
|
method: "post",
|
||||||
useToken: true,
|
useToken: true,
|
||||||
body: tariff,
|
body: tariff,
|
||||||
})
|
});
|
||||||
|
|
||||||
return [createTariffResponse]
|
return [createTariffResponse];
|
||||||
} catch (nativeError) {
|
} catch (nativeError) {
|
||||||
const [error] = parseAxiosError(nativeError)
|
const [error] = parseAxiosError(nativeError);
|
||||||
|
|
||||||
return [null, `Не удалось создать тариф. ${error}`]
|
return [null, `Не удалось создать тариф. ${error}`];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getTariffById(tariffId: string): Promise<[Tariff | null, string?, number?]> {
|
export async function getTariffById(tariffId: string): Promise<[Tariff | null, string?, number?]> {
|
||||||
try {
|
try {
|
||||||
const getTariffByIdResponse = await makeRequest<never, Tariff>({
|
const getTariffByIdResponse = await makeRequest<never, Tariff>({
|
||||||
url: `${apiUrl}/tariff/${tariffId}`,
|
url: `${apiUrl}/tariff/${tariffId}`,
|
||||||
method: "get",
|
method: "get",
|
||||||
useToken: true,
|
useToken: true,
|
||||||
})
|
});
|
||||||
|
|
||||||
return [getTariffByIdResponse]
|
return [getTariffByIdResponse];
|
||||||
} catch (nativeError) {
|
} catch (nativeError) {
|
||||||
const [error, status] = parseAxiosError(nativeError)
|
const [error, status] = parseAxiosError(nativeError);
|
||||||
|
|
||||||
return [null, `Не удалось получить тарифы. ${error}`, status]
|
return [null, `Не удалось получить тарифы. ${error}`, status];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getCustomTariffs(
|
export async function getCustomTariffs(
|
||||||
signal: AbortSignal | undefined
|
signal: AbortSignal | undefined
|
||||||
): Promise<[ServiceKeyToPrivilegesMap | null, string?]> {
|
): Promise<[ServiceKeyToPrivilegesMap | null, string?]> {
|
||||||
try {
|
try {
|
||||||
const customTariffsResponse = await makeRequest<null, ServiceKeyToPrivilegesMap>({
|
const customTariffsResponse = await makeRequest<null, ServiceKeyToPrivilegesMap>({
|
||||||
url: apiUrl + "/privilege/service",
|
url: apiUrl + "/privilege/service",
|
||||||
signal,
|
signal,
|
||||||
method: "get",
|
method: "get",
|
||||||
useToken: true,
|
useToken: true,
|
||||||
})
|
});
|
||||||
|
|
||||||
const tempCustomTariffsResponse = {
|
const tempCustomTariffsResponse = {
|
||||||
...customTariffsResponse,
|
...customTariffsResponse,
|
||||||
squiz: customTariffsResponse.squiz
|
squiz: customTariffsResponse.squiz
|
||||||
};
|
};
|
||||||
|
|
||||||
return [tempCustomTariffsResponse]
|
return [tempCustomTariffsResponse];
|
||||||
} catch (nativeError) {
|
} catch (nativeError) {
|
||||||
const [error] = parseAxiosError(nativeError)
|
const [error] = parseAxiosError(nativeError);
|
||||||
|
|
||||||
return [null, `Не удалось получить мои тарифы. ${error}`]
|
return [null, `Не удалось получить мои тарифы. ${error}`];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTariffArray(tariffIds: string[] | undefined) {
|
||||||
|
if (!tariffIds) return null;
|
||||||
|
|
||||||
|
const responses = await Promise.allSettled(tariffIds.map(tariffId =>
|
||||||
|
makeRequest<never, Tariff>({
|
||||||
|
url: `${apiUrl}/tariff/${tariffId}`,
|
||||||
|
method: "get",
|
||||||
|
useToken: true,
|
||||||
|
})
|
||||||
|
));
|
||||||
|
|
||||||
|
const tariffs: Tariff[] = [];
|
||||||
|
|
||||||
|
responses.forEach((response, index) => {
|
||||||
|
switch (response.status) {
|
||||||
|
case "fulfilled": {
|
||||||
|
tariffs.push(response.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "rejected": {
|
||||||
|
const [, status] = parseAxiosError(response.reason);
|
||||||
|
if (status === 404) removeTariffFromCart(tariffIds[index]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return tariffs;
|
||||||
}
|
}
|
||||||
|
@ -14,10 +14,9 @@ import type { MouseEvent } from "react"
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tariffCartData: TariffCartData;
|
tariffCartData: TariffCartData;
|
||||||
outsideFactor: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CustomTariffAccordion({ tariffCartData, outsideFactor }: Props) {
|
export default function CustomTariffAccordion({ tariffCartData }: Props) {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const upMd = useMediaQuery(theme.breakpoints.up("md"))
|
const upMd = useMediaQuery(theme.breakpoints.up("md"))
|
||||||
const upSm = useMediaQuery(theme.breakpoints.up("sm"))
|
const upSm = useMediaQuery(theme.breakpoints.up("sm"))
|
||||||
@ -36,7 +35,6 @@ export default function CustomTariffAccordion({ tariffCartData, outsideFactor }:
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('DRAWER', outsideFactor)
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@ -103,7 +101,7 @@ console.log('DRAWER', outsideFactor)
|
|||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{currencyFormatter.format(tariffCartData.price * outsideFactor / 100)}
|
{currencyFormatter.format(tariffCartData.price / 100)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<CloseButton
|
<CloseButton
|
||||||
@ -150,7 +148,7 @@ console.log('DRAWER', outsideFactor)
|
|||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{currencyFormatter.format(privilege.price * outsideFactor / 100)}
|
{currencyFormatter.format(privilege.price / 100)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -13,6 +13,7 @@ import { ReactComponent as CrossIcon } from "@root/assets/Icons/cross.svg";
|
|||||||
|
|
||||||
import type { MouseEvent } from "react";
|
import type { MouseEvent } from "react";
|
||||||
import CustomTariffAccordion from "@root/components/CustomTariffAccordion";
|
import CustomTariffAccordion from "@root/components/CustomTariffAccordion";
|
||||||
|
import { setNotEnoughMoneyAmount } from "@root/stores/cart";
|
||||||
|
|
||||||
const name: Record<string, string> = {
|
const name: Record<string, string> = {
|
||||||
templategen: "Шаблонизатор",
|
templategen: "Шаблонизатор",
|
||||||
@ -23,10 +24,9 @@ const name: Record<string, string> = {
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
serviceData: ServiceCartData;
|
serviceData: ServiceCartData;
|
||||||
outsideFactor: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CustomWrapperDrawer({ serviceData, outsideFactor }: Props) {
|
export default function CustomWrapperDrawer({ serviceData }: Props) {
|
||||||
const [isExpanded, setIsExpanded] = useState<boolean>(false);
|
const [isExpanded, setIsExpanded] = useState<boolean>(false);
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@ -51,6 +51,7 @@ export default function CustomWrapperDrawer({ serviceData, outsideFactor }: Prop
|
|||||||
const errors: string[] = [];
|
const errors: string[] = [];
|
||||||
|
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
setNotEnoughMoneyAmount(0);
|
||||||
|
|
||||||
for (const { id } of serviceData.tariffs) {
|
for (const { id } of serviceData.tariffs) {
|
||||||
const [cartItemsResponse, deleteError] = await deleteCart(id);
|
const [cartItemsResponse, deleteError] = await deleteCart(id);
|
||||||
@ -138,7 +139,7 @@ export default function CustomWrapperDrawer({ serviceData, outsideFactor }: Prop
|
|||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{currencyFormatter.format(serviceData.price * outsideFactor / 100)}
|
{currencyFormatter.format(serviceData.price / 100)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@ -169,9 +170,8 @@ export default function CustomWrapperDrawer({ serviceData, outsideFactor }: Prop
|
|||||||
serviceData.tariffs.map((tariff) => {
|
serviceData.tariffs.map((tariff) => {
|
||||||
const privilege = tariff.privileges[0];
|
const privilege = tariff.privileges[0];
|
||||||
|
|
||||||
console.log('CD', tariff, outsideFactor)
|
|
||||||
return tariff.privileges.length > 1 ? (
|
return tariff.privileges.length > 1 ? (
|
||||||
<CustomTariffAccordion outsideFactor={outsideFactor} key={tariff.id} tariffCartData={tariff} />
|
<CustomTariffAccordion key={tariff.id} tariffCartData={tariff} />
|
||||||
) : (
|
) : (
|
||||||
<Box
|
<Box
|
||||||
key={tariff.id + privilege.privilegeId}
|
key={tariff.id + privilege.privilegeId}
|
||||||
@ -211,7 +211,7 @@ console.log('CD', tariff, outsideFactor)
|
|||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{currencyFormatter.format((tariff.price || privilege.price) * outsideFactor / 100)}
|
{currencyFormatter.format((tariff.price || privilege.price) / 100)}
|
||||||
</Typography>
|
</Typography>
|
||||||
<SvgIcon
|
<SvgIcon
|
||||||
sx={{
|
sx={{
|
||||||
|
@ -6,7 +6,6 @@ import { NotificationsModal } from "./NotificationsModal";
|
|||||||
import { Loader } from "./Loader";
|
import { Loader } from "./Loader";
|
||||||
import { useCart } from "@root/utils/hooks/useCart";
|
import { useCart } from "@root/utils/hooks/useCart";
|
||||||
import { currencyFormatter } from "@root/utils/currencyFormatter";
|
import { currencyFormatter } from "@root/utils/currencyFormatter";
|
||||||
import { closeCartDrawer, openCartDrawer, setNotEnoughMoneyAmount, useCartStore } from "@root/stores/cart";
|
|
||||||
import { setUserAccount, useUserStore } from "@root/stores/user";
|
import { setUserAccount, useUserStore } from "@root/stores/user";
|
||||||
import { useTicketStore } from "@root/stores/tickets";
|
import { useTicketStore } from "@root/stores/tickets";
|
||||||
|
|
||||||
@ -20,6 +19,7 @@ import { Link, useNavigate } from "react-router-dom";
|
|||||||
import { withErrorBoundary } from "react-error-boundary";
|
import { withErrorBoundary } from "react-error-boundary";
|
||||||
import { handleComponentError } from "@root/utils/handleComponentError";
|
import { handleComponentError } from "@root/utils/handleComponentError";
|
||||||
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
|
import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline";
|
||||||
|
import { setNotEnoughMoneyAmount, useCartStore } from "@root/stores/cart";
|
||||||
|
|
||||||
function Drawers() {
|
function Drawers() {
|
||||||
const [openNotificationsModal, setOpenNotificationsModal] = useState<boolean>(false);
|
const [openNotificationsModal, setOpenNotificationsModal] = useState<boolean>(false);
|
||||||
@ -29,7 +29,7 @@ function Drawers() {
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||||
const isDrawerOpen = useCartStore((state) => state.isDrawerOpen);
|
const [isDrawerOpen, setIsDrawerOpen] = useState<boolean>(false);
|
||||||
const cart = useCart();
|
const cart = useCart();
|
||||||
const userAccount = useUserStore((state) => state.userAccount);
|
const userAccount = useUserStore((state) => state.userAccount);
|
||||||
const tickets = useTicketStore((state) => state.tickets);
|
const tickets = useTicketStore((state) => state.tickets);
|
||||||
@ -61,11 +61,11 @@ function Drawers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
closeCartDrawer();
|
setIsDrawerOpen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleReplenishWallet() {
|
function handleReplenishWallet() {
|
||||||
closeCartDrawer();
|
setIsDrawerOpen(false);
|
||||||
navigate("/payment", { state: { notEnoughMoneyAmount } });
|
navigate("/payment", { state: { notEnoughMoneyAmount } });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ function Drawers() {
|
|||||||
}))}
|
}))}
|
||||||
/>
|
/>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={openCartDrawer}
|
onClick={() => setIsDrawerOpen(true)}
|
||||||
component="div"
|
component="div"
|
||||||
sx={{
|
sx={{
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
@ -172,7 +172,7 @@ function Drawers() {
|
|||||||
<CartIcon />
|
<CartIcon />
|
||||||
</Badge>
|
</Badge>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<Drawer anchor={"right"} open={isDrawerOpen} onClose={closeCartDrawer} sx={{ background: "rgba(0, 0, 0, 0.55)" }}>
|
<Drawer anchor={"right"} open={isDrawerOpen} onClose={() => setIsDrawerOpen(false)} sx={{ background: "rgba(0, 0, 0, 0.55)" }}>
|
||||||
<SectionWrapper
|
<SectionWrapper
|
||||||
maxWidth="lg"
|
maxWidth="lg"
|
||||||
sx={{
|
sx={{
|
||||||
@ -204,15 +204,16 @@ function Drawers() {
|
|||||||
>
|
>
|
||||||
Корзина
|
Корзина
|
||||||
</Typography>
|
</Typography>
|
||||||
<IconButton onClick={closeCartDrawer} sx={{ p: 0 }}>
|
<IconButton onClick={() => setIsDrawerOpen(false)} sx={{ p: 0 }}>
|
||||||
<CrossIcon />
|
<CrossIcon />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Box>
|
</Box>
|
||||||
<Box sx={{ pl: "20px", pr: "20px" }}>
|
<Box sx={{ pl: "20px", pr: "20px" }}>
|
||||||
{cart.services.map((serviceData) => {
|
{cart.services.map((serviceData) => {
|
||||||
return (
|
return (
|
||||||
<CustomWrapperDrawer key={serviceData.serviceKey} outsideFactor={(cart.appliedCartPurchasesDiscount?.Target?.Factor || 1)*(cart.appliedLoyaltyDiscount?.Target?.Factor || 1)} serviceData={serviceData} />
|
<CustomWrapperDrawer key={serviceData.serviceKey} serviceData={serviceData} />
|
||||||
)})}
|
);
|
||||||
|
})}
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
mt: "40px",
|
mt: "40px",
|
||||||
@ -256,8 +257,7 @@ function Drawers() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
-
|
-
|
||||||
{`${
|
{`${((cart.priceBeforeDiscounts - cart.priceAfterDiscounts) / (cart.priceBeforeDiscounts / 100)).toFixed(0)
|
||||||
((cart.priceBeforeDiscounts - cart.priceAfterDiscounts) / (cart.priceBeforeDiscounts / 100)).toFixed(0)
|
|
||||||
}%`}
|
}%`}
|
||||||
</span>
|
</span>
|
||||||
) : null
|
) : null
|
||||||
@ -333,7 +333,7 @@ function Drawers() {
|
|||||||
disabled={cart.priceAfterDiscounts === 0}
|
disabled={cart.priceAfterDiscounts === 0}
|
||||||
variant="pena-contained-dark"
|
variant="pena-contained-dark"
|
||||||
onClick={() => (notEnoughMoneyAmount === 0 ? !loading && handlePayClick() : handleReplenishWallet())}
|
onClick={() => (notEnoughMoneyAmount === 0 ? !loading && handlePayClick() : handleReplenishWallet())}
|
||||||
sx={{ display: "block" }}
|
sx={{ display: "block" }}
|
||||||
>
|
>
|
||||||
{loading ? <Loader size={24} /> : notEnoughMoneyAmount === 0 ? "Оплатить" : "Пополнить"}
|
{loading ? <Loader size={24} /> : notEnoughMoneyAmount === 0 ? "Оплатить" : "Пополнить"}
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -2,113 +2,114 @@ import { useState } from "react"
|
|||||||
import { InputAdornment, TextField, Typography, useTheme } from "@mui/material"
|
import { InputAdornment, TextField, Typography, useTheme } from "@mui/material"
|
||||||
|
|
||||||
import type { ChangeEvent } from "react"
|
import type { ChangeEvent } from "react"
|
||||||
import {Privilege} from "@frontend/kitui"
|
import { CustomPrivilege } from "@frontend/kitui"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
id: string;
|
id: string
|
||||||
value: number;
|
value: number
|
||||||
adornmentText: string;
|
adornmentText: string
|
||||||
privilege: Privilege;
|
privilege: CustomPrivilege
|
||||||
onChange: (value: number) => void;
|
onChange: (value: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const sliderSettingsByType = {
|
const sliderSettingsByType = {
|
||||||
день: { max: 365, min: 0 },
|
день: { max: 365, min: 0 },
|
||||||
шаблон: { max: 5000, min: 0 },
|
шаблон: { max: 5000, min: 0 },
|
||||||
МБ: { max: 5000, min: 0 },
|
МБ: { max: 5000, min: 0 },
|
||||||
заявка: { max: 5000, min: 0 }
|
заявка: { max: 5000, min: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function NumberInputWithUnitAdornment({ id, value, adornmentText, privilege, onChange }: Props) {
|
export default function NumberInputWithUnitAdornment({ id, value, adornmentText, privilege, onChange }: Props) {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const [changed, setChanged] = useState<boolean>(false)
|
const [changed, setChanged] = useState<boolean>(false)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TextField
|
<TextField
|
||||||
type="number"
|
type="number"
|
||||||
size="small"
|
size="small"
|
||||||
placeholder="Введите вручную"
|
placeholder="Введите вручную"
|
||||||
id={id}
|
id={id}
|
||||||
onBlur={(e) => {e.target.value = String(Number(String(e.target.value).replace(/^0+(?=\d\.)/, '')))
|
onBlur={(e) => {
|
||||||
console.log("сработало", e.target.value)
|
e.target.value = String(Number(String(e.target.value).replace(/^0+(?=\d\.)/, "")))
|
||||||
}}
|
console.log("сработало", e.target.value)
|
||||||
value={changed ? (value !== sliderSettingsByType[privilege.value]?.min ? parseInt(String(value), 10) : sliderSettingsByType[privilege.value]?.min) : ""}
|
}}
|
||||||
onChange={({ target }: ChangeEvent<HTMLInputElement>) => {
|
value={changed ? (value !== sliderSettingsByType[privilege.value]?.min ? parseInt(String(value), 10) : sliderSettingsByType[privilege.value]?.min) : ""}
|
||||||
if (!changed) {
|
onChange={({ target }: ChangeEvent<HTMLInputElement>) => {
|
||||||
setChanged(true)
|
if (!changed) {
|
||||||
}
|
setChanged(true)
|
||||||
|
}
|
||||||
|
|
||||||
if (Number(target.value) > 999999) {
|
if (Number(target.value) > 999999) {
|
||||||
target.value = "999999"
|
target.value = "999999"
|
||||||
}
|
}
|
||||||
|
|
||||||
const newNumber = parseInt(target.value)
|
const newNumber = parseInt(target.value)
|
||||||
|
|
||||||
|
|
||||||
if (!isFinite(newNumber) || newNumber < 0) {
|
if (!isFinite(newNumber) || newNumber < 0) {
|
||||||
onChange(sliderSettingsByType[privilege.value]?.min)
|
onChange(sliderSettingsByType[privilege.value]?.min)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
onChange(newNumber)
|
onChange(newNumber)
|
||||||
}}
|
}}
|
||||||
sx={{
|
sx={{
|
||||||
maxWidth: "200px",
|
maxWidth: "200px",
|
||||||
minWidth: "200px",
|
minWidth: "200px",
|
||||||
".MuiInputBase-root": {
|
".MuiInputBase-root": {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
pr: 0,
|
pr: 0,
|
||||||
height: "48px",
|
height: "48px",
|
||||||
borderRadius: "8px",
|
borderRadius: "8px",
|
||||||
backgroundColor: "#F2F3F7",
|
backgroundColor: "#F2F3F7",
|
||||||
fieldset: {
|
fieldset: {
|
||||||
border: "1px solid" + theme.palette.gray.main,
|
border: "1px solid" + theme.palette.gray.main,
|
||||||
},
|
},
|
||||||
"&.Mui-focused fieldset": {
|
"&.Mui-focused fieldset": {
|
||||||
borderColor: theme.palette.purple.main,
|
borderColor: theme.palette.purple.main,
|
||||||
},
|
},
|
||||||
input: {
|
input: {
|
||||||
height: "31px",
|
height: "31px",
|
||||||
borderRight: !changed ? "none" : "1px solid #9A9AAF",
|
borderRight: !changed ? "none" : "1px solid #9A9AAF",
|
||||||
},
|
},
|
||||||
"&.Mui-focused input": {
|
"&.Mui-focused input": {
|
||||||
borderRight: "1px solid #9A9AAF",
|
borderRight: "1px solid #9A9AAF",
|
||||||
},
|
},
|
||||||
"&:not(.Mui-focused) .MuiInputAdornment-root": {
|
"&:not(.Mui-focused) .MuiInputAdornment-root": {
|
||||||
display: !changed ? "none" : undefined,
|
display: !changed ? "none" : undefined,
|
||||||
},
|
},
|
||||||
"&.Mui-focused ::-webkit-input-placeholder": {
|
"&.Mui-focused ::-webkit-input-placeholder": {
|
||||||
color: "transparent",
|
color: "transparent",
|
||||||
},
|
},
|
||||||
|
|
||||||
// Hiding arrows
|
// Hiding arrows
|
||||||
"input::-webkit-outer-spin-button, input::-webkit-inner-spin-button": {
|
"input::-webkit-outer-spin-button, input::-webkit-inner-spin-button": {
|
||||||
WebkitAppearance: "none",
|
WebkitAppearance: "none",
|
||||||
margin: 0,
|
margin: 0,
|
||||||
},
|
},
|
||||||
"input[type = number]": {
|
"input[type = number]": {
|
||||||
MozAppearance: "textfield",
|
MozAppearance: "textfield",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
InputProps={{
|
InputProps={{
|
||||||
endAdornment: (
|
endAdornment: (
|
||||||
<InputAdornment
|
<InputAdornment
|
||||||
position="end"
|
position="end"
|
||||||
sx={{
|
sx={{
|
||||||
userSelect: "none",
|
userSelect: "none",
|
||||||
pointerEvents: "none",
|
pointerEvents: "none",
|
||||||
pl: "2px",
|
pl: "2px",
|
||||||
pr: "13px",
|
pr: "13px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography variant="body2" color="#4D4D4D">
|
<Typography variant="body2" color="#4D4D4D">
|
||||||
{adornmentText}
|
{adornmentText}
|
||||||
</Typography>
|
</Typography>
|
||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import { Loader } from "./Loader";
|
|||||||
import { currencyFormatter } from "@root/utils/currencyFormatter";
|
import { currencyFormatter } from "@root/utils/currencyFormatter";
|
||||||
import { payCart } from "@root/api/cart";
|
import { payCart } from "@root/api/cart";
|
||||||
import { setUserAccount } from "@root/stores/user";
|
import { setUserAccount } from "@root/stores/user";
|
||||||
import { useCart } from "@root/utils/hooks/useCart";
|
|
||||||
import { setNotEnoughMoneyAmount, useCartStore } from "@root/stores/cart";
|
import { setNotEnoughMoneyAmount, useCartStore } from "@root/stores/cart";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -20,8 +19,7 @@ interface Props {
|
|||||||
export default function TotalPrice({ priceAfterDiscounts, priceBeforeDiscounts, isConstructor = false }: Props) {
|
export default function TotalPrice({ priceAfterDiscounts, priceBeforeDiscounts, isConstructor = false }: Props) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
||||||
const cart = useCart();
|
const notEnoughMoneyAmount = useCartStore(state => state.notEnoughMoneyAmount);
|
||||||
const notEnoughMoneyAmount = useCartStore(state => state.notEnoughMoneyAmount)
|
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -169,7 +167,7 @@ export default function TotalPrice({ priceAfterDiscounts, priceBeforeDiscounts,
|
|||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant="pena-contained-dark"
|
variant="pena-contained-dark"
|
||||||
disabled = {cart.priceAfterDiscounts === 0}
|
disabled = {priceAfterDiscounts === 0}
|
||||||
onClick={() => (notEnoughMoneyAmount === 0 ? !loading && handlePayClick() : handleReplenishWallet())}
|
onClick={() => (notEnoughMoneyAmount === 0 ? !loading && handlePayClick() : handleReplenishWallet())}
|
||||||
>
|
>
|
||||||
{loading ? <Loader size={24} /> : notEnoughMoneyAmount === 0 ? "Оплатить" : "Пополнить"}
|
{loading ? <Loader size={24} /> : notEnoughMoneyAmount === 0 ? "Оплатить" : "Пополнить"}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { PrivilegeWithAmount } from "@frontend/kitui"
|
|
||||||
import { PrivilegeWithoutPrice } from "./privilege"
|
import { PrivilegeWithoutPrice } from "./privilege"
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Privilege, PrivilegeWithAmount } from "@frontend/kitui"
|
import { CustomPrivilegeWithAmount } from "@frontend/kitui";
|
||||||
|
|
||||||
|
|
||||||
export type ServiceKeyToPrivilegesMap = Record<string, Privilege[]>;
|
export type ServiceKeyToPrivilegesMap = Record<string, CustomPrivilegeWithAmount[]>;
|
||||||
|
|
||||||
export type PrivilegeWithoutPrice = Omit<PrivilegeWithAmount, "price">;
|
export type PrivilegeWithoutPrice = Omit<CustomPrivilegeWithAmount, "price">;
|
||||||
|
@ -4,9 +4,4 @@ import { Tariff } from "@frontend/kitui"
|
|||||||
export interface GetTariffsResponse {
|
export interface GetTariffsResponse {
|
||||||
totalPages: number;
|
totalPages: number;
|
||||||
tariffs: Tariff[];
|
tariffs: Tariff[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FullTariff extends Tariff {
|
|
||||||
description?: string;
|
|
||||||
order?: number;
|
|
||||||
}
|
|
||||||
|
@ -1,82 +1,79 @@
|
|||||||
import { Box, IconButton, Typography, Badge, useMediaQuery, useTheme } from "@mui/material"
|
import { Box, IconButton, Typography, Badge, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import SectionWrapper from "@components/SectionWrapper"
|
import SectionWrapper from "@components/SectionWrapper";
|
||||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack"
|
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||||
import TotalPrice from "@components/TotalPrice"
|
import TotalPrice from "@components/TotalPrice";
|
||||||
import CustomWrapper from "./CustomWrapper"
|
import CustomWrapper from "./CustomWrapper";
|
||||||
import { useCart } from "@root/utils/hooks/useCart"
|
import { useCart } from "@root/utils/hooks/useCart";
|
||||||
import { useLocation } from "react-router-dom"
|
import { useLocation } from "react-router-dom";
|
||||||
import { usePrevLocation } from "@root/utils/hooks/handleCustomBackNavigation"
|
import { usePrevLocation } from "@root/utils/hooks/handleCustomBackNavigation";
|
||||||
import { handleComponentError } from "@root/utils/handleComponentError"
|
import { handleComponentError } from "@root/utils/handleComponentError";
|
||||||
import { withErrorBoundary } from "react-error-boundary"
|
import { withErrorBoundary } from "react-error-boundary";
|
||||||
|
|
||||||
function Cart() {
|
function Cart() {
|
||||||
const theme = useTheme()
|
const theme = useTheme();
|
||||||
const upMd = useMediaQuery(theme.breakpoints.up("md"))
|
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
||||||
const isMobile = useMediaQuery(theme.breakpoints.down(550))
|
const isMobile = useMediaQuery(theme.breakpoints.down(550));
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000))
|
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||||
const cart = useCart()
|
const cart = useCart();
|
||||||
const location = useLocation()
|
const location = useLocation();
|
||||||
|
|
||||||
const totalPriceBeforeDiscounts = cart.priceBeforeDiscounts
|
const totalPriceBeforeDiscounts = cart.priceBeforeDiscounts;
|
||||||
const totalPriceAfterDiscounts = cart.priceAfterDiscounts
|
const totalPriceAfterDiscounts = cart.priceAfterDiscounts;
|
||||||
|
|
||||||
console.log('CART', totalPriceAfterDiscounts, totalPriceBeforeDiscounts, cart)
|
const handleCustomBackNavigation = usePrevLocation(location);
|
||||||
const handleCustomBackNavigation = usePrevLocation(location)
|
|
||||||
|
|
||||||
|
return (
|
||||||
return (
|
<SectionWrapper
|
||||||
<SectionWrapper
|
maxWidth="lg"
|
||||||
maxWidth="lg"
|
sx={{
|
||||||
sx={{
|
mt: upMd ? "25px" : "20px",
|
||||||
mt: upMd ? "25px" : "20px",
|
px: isTablet ? (upMd ? "40px" : "18px") : "20px",
|
||||||
px: isTablet ? (upMd ? "40px" : "18px") : "20px",
|
mb: upMd ? "70px" : "37px",
|
||||||
mb: upMd ? "70px" : "37px",
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<Box
|
||||||
<Box
|
sx={{
|
||||||
sx={{
|
mt: "20px",
|
||||||
mt: "20px",
|
mb: upMd ? "40px" : "20px",
|
||||||
mb: upMd ? "40px" : "20px",
|
display: "flex",
|
||||||
display: "flex",
|
alignItems: "center",
|
||||||
alignItems: "center",
|
gap: "10px",
|
||||||
gap: "10px",
|
}}
|
||||||
}}
|
>
|
||||||
>
|
{isMobile && (
|
||||||
{isMobile && (
|
<IconButton onClick={handleCustomBackNavigation} sx={{ p: 0, height: "28px", width: "28px", color: "black" }}>
|
||||||
<IconButton onClick={handleCustomBackNavigation} sx={{ p: 0, height: "28px", width: "28px", color: "black" }}>
|
<ArrowBackIcon />
|
||||||
<ArrowBackIcon />
|
</IconButton>
|
||||||
</IconButton>
|
)}
|
||||||
)}
|
<Typography
|
||||||
<Typography
|
sx={{
|
||||||
sx={{
|
fontSize: isMobile ? "24px" : "36px",
|
||||||
fontSize: isMobile ? "24px" : "36px",
|
fontWeight: "500",
|
||||||
fontWeight: "500",
|
}}
|
||||||
}}
|
>
|
||||||
>
|
Корзина
|
||||||
Корзина
|
</Typography>
|
||||||
</Typography>
|
</Box>
|
||||||
</Box>
|
<Box
|
||||||
<Box
|
sx={{
|
||||||
sx={{
|
mt: upMd ? "27px" : "10px",
|
||||||
mt: upMd ? "27px" : "10px",
|
}}
|
||||||
}}
|
>
|
||||||
>
|
{cart.services.map((serviceData, index) => (
|
||||||
{cart.services.map((serviceData, index) => (
|
<CustomWrapper
|
||||||
<CustomWrapper
|
key={serviceData.serviceKey}
|
||||||
key={serviceData.serviceKey}
|
serviceData={serviceData}
|
||||||
serviceData={serviceData}
|
first={index === 0}
|
||||||
outsideFactor={(cart.appliedCartPurchasesDiscount?.Target?.Factor || 1)*(cart.appliedLoyaltyDiscount?.Target?.Factor || 1)}
|
last={index === cart.services.length - 1}
|
||||||
first={index === 0}
|
/>
|
||||||
last={index === cart.services.length - 1}
|
))}
|
||||||
/>
|
</Box>
|
||||||
))}
|
<TotalPrice priceBeforeDiscounts={totalPriceBeforeDiscounts} priceAfterDiscounts={totalPriceAfterDiscounts} />
|
||||||
</Box>
|
</SectionWrapper>
|
||||||
<TotalPrice priceBeforeDiscounts={totalPriceBeforeDiscounts} priceAfterDiscounts={totalPriceAfterDiscounts} />
|
);
|
||||||
</SectionWrapper>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withErrorBoundary(Cart, {
|
export default withErrorBoundary(Cart, {
|
||||||
fallback: <Typography mt="8px" textAlign="center">Ошибка при отображении корзины</Typography>,
|
fallback: <Typography mt="8px" textAlign="center">Ошибка при отображении корзины</Typography>,
|
||||||
onError: handleComponentError,
|
onError: handleComponentError,
|
||||||
})
|
});
|
||||||
|
@ -5,7 +5,7 @@ import ClearIcon from "@mui/icons-material/Clear"
|
|||||||
import { currencyFormatter } from "@root/utils/currencyFormatter"
|
import { currencyFormatter } from "@root/utils/currencyFormatter"
|
||||||
import { removeTariffFromCart } from "@root/stores/user"
|
import { removeTariffFromCart } from "@root/stores/user"
|
||||||
import { enqueueSnackbar } from "notistack"
|
import { enqueueSnackbar } from "notistack"
|
||||||
import { CloseButton, ServiceCartData, getMessageFromFetchError } from "@frontend/kitui"
|
import { CloseButton, ServiceCartData, getMessageFromFetchError } from "@frontend/kitui"
|
||||||
|
|
||||||
import type { MouseEvent } from "react"
|
import type { MouseEvent } from "react"
|
||||||
import CustomTariffAccordion from "@root/components/CustomTariffAccordion"
|
import CustomTariffAccordion from "@root/components/CustomTariffAccordion"
|
||||||
@ -19,12 +19,11 @@ const name: Record<string, string> = {
|
|||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
serviceData: ServiceCartData;
|
serviceData: ServiceCartData;
|
||||||
outsideFactor: number;
|
|
||||||
last?: boolean;
|
last?: boolean;
|
||||||
first?: boolean;
|
first?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CustomWrapper({ serviceData, last, first, outsideFactor }: Props) {
|
export default function CustomWrapper({ serviceData, last, first }: Props) {
|
||||||
const theme = useTheme()
|
const theme = useTheme()
|
||||||
const upMd = useMediaQuery(theme.breakpoints.up("md"))
|
const upMd = useMediaQuery(theme.breakpoints.up("md"))
|
||||||
const upSm = useMediaQuery(theme.breakpoints.up("sm"))
|
const upSm = useMediaQuery(theme.breakpoints.up("sm"))
|
||||||
@ -55,7 +54,6 @@ export default function CustomWrapper({ serviceData, last, first, outsideFactor
|
|||||||
enqueueSnackbar("Тарифы удалены")
|
enqueueSnackbar("Тарифы удалены")
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('SDDD', serviceData)
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@ -128,7 +126,7 @@ console.log('SDDD', serviceData)
|
|||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{currencyFormatter.format(serviceData.price * outsideFactor / 100)}
|
{currencyFormatter.format(serviceData.price / 100)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<CloseButton style={{ height: "22 px", width: "22px" }} onClick={deleteService} />
|
<CloseButton style={{ height: "22 px", width: "22px" }} onClick={deleteService} />
|
||||||
@ -139,7 +137,7 @@ console.log('SDDD', serviceData)
|
|||||||
|
|
||||||
|
|
||||||
return tariff.privileges.length > 1 ? (
|
return tariff.privileges.length > 1 ? (
|
||||||
<CustomTariffAccordion outsideFactor={outsideFactor} key={tariff.id} tariffCartData={tariff} />
|
<CustomTariffAccordion key={tariff.id} tariffCartData={tariff} />
|
||||||
) : (
|
) : (
|
||||||
<Box
|
<Box
|
||||||
key={tariff.id + privilege.privilegeId}
|
key={tariff.id + privilege.privilegeId}
|
||||||
@ -178,7 +176,7 @@ console.log('SDDD', serviceData)
|
|||||||
fontWeight: 500,
|
fontWeight: 500,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{currencyFormatter.format(tariff.price * outsideFactor / 100)}
|
{currencyFormatter.format(tariff.price / 100)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
|
@ -4,11 +4,11 @@ import { enqueueSnackbar } from "notistack"
|
|||||||
import { Box, Button, Typography, useMediaQuery, useTheme } from "@mui/material"
|
import { Box, Button, Typography, useMediaQuery, useTheme } from "@mui/material"
|
||||||
|
|
||||||
import { addTariffToCart } from "@root/stores/user"
|
import { addTariffToCart } from "@root/stores/user"
|
||||||
import { PrivilegeWithAmount, getMessageFromFetchError } from "@frontend/kitui"
|
import { Privilege, getMessageFromFetchError } from "@frontend/kitui"
|
||||||
import CustomSaveAccordion from "../../components/CustomSaveAccordion"
|
import CustomSaveAccordion from "../../components/CustomSaveAccordion"
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
privileges: PrivilegeWithAmount[];
|
privileges: Privilege[];
|
||||||
tariffId: string;
|
tariffId: string;
|
||||||
createdAt: string | undefined;
|
createdAt: string | undefined;
|
||||||
first?: boolean;
|
first?: boolean;
|
||||||
|
@ -1,27 +1,27 @@
|
|||||||
|
import { CustomPrivilegeWithAmount } from "@frontend/kitui";
|
||||||
import {
|
import {
|
||||||
Box,
|
Badge,
|
||||||
Button,
|
Box,
|
||||||
Divider,
|
Button,
|
||||||
Badge,
|
Divider,
|
||||||
Typography,
|
Typography,
|
||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
} from "@mui/material"
|
} from "@mui/material";
|
||||||
import TariffPrivilegeSlider from "./TariffItem"
|
|
||||||
import {
|
import {
|
||||||
createAndSendTariff,
|
createAndSendTariff,
|
||||||
useCustomTariffsStore,
|
useCustomTariffsStore,
|
||||||
} from "@root/stores/customTariffs"
|
} from "@root/stores/customTariffs";
|
||||||
import { cardShadow } from "@root/utils/theme"
|
import { updateTariffs } from "@root/stores/tariffs";
|
||||||
import { currencyFormatter } from "@root/utils/currencyFormatter"
|
import { addTariffToCart } from "@root/stores/user";
|
||||||
import { Privilege, getMessageFromFetchError } from "@frontend/kitui"
|
import { currencyFormatter } from "@root/utils/currencyFormatter";
|
||||||
import { enqueueSnackbar } from "notistack"
|
import { cardShadow } from "@root/utils/theme";
|
||||||
import { updateTariffs } from "@root/stores/tariffs"
|
import { enqueueSnackbar } from "notistack";
|
||||||
import { addTariffToCart } from "@root/stores/user"
|
import TariffPrivilegeSlider from "./TariffItem";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
serviceKey: string;
|
serviceKey: string;
|
||||||
privileges: Privilege[];
|
privileges: CustomPrivilegeWithAmount[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CustomTariffCard({ serviceKey, privileges }: Props) {
|
export default function CustomTariffCard({ serviceKey, privileges }: Props) {
|
||||||
|
@ -1,92 +1,94 @@
|
|||||||
import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material"
|
import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import { Link } from "react-router-dom"
|
import { Link } from "react-router-dom";
|
||||||
import SectionWrapper from "@components/SectionWrapper"
|
import SectionWrapper from "@components/SectionWrapper";
|
||||||
import { useCustomTariffsStore } from "@root/stores/customTariffs"
|
import { useCustomTariffsStore } from "@root/stores/customTariffs";
|
||||||
import ComplexHeader from "@root/components/ComplexHeader"
|
import ComplexHeader from "@root/components/ComplexHeader";
|
||||||
import CustomTariffCard from "./CustomTariffCard"
|
import CustomTariffCard from "./CustomTariffCard";
|
||||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack"
|
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||||
import TotalPrice from "@root/components/TotalPrice"
|
import TotalPrice from "@root/components/TotalPrice";
|
||||||
import { serviceNameByKey } from "@root/utils/serviceKeys"
|
import { serviceNameByKey } from "@root/utils/serviceKeys";
|
||||||
import { useHistoryTracker } from "@root/utils/hooks/useHistoryTracker"
|
import { useHistoryTracker } from "@root/utils/hooks/useHistoryTracker";
|
||||||
import { withErrorBoundary } from "react-error-boundary"
|
import { withErrorBoundary } from "react-error-boundary";
|
||||||
import { handleComponentError } from "@root/utils/handleComponentError"
|
import { handleComponentError } from "@root/utils/handleComponentError";
|
||||||
import { useCart } from "@root/utils/hooks/useCart";
|
import { useCart } from "@root/utils/hooks/useCart";
|
||||||
|
|
||||||
function TariffConstructor() {
|
function TariffConstructor() {
|
||||||
const theme = useTheme()
|
const theme = useTheme();
|
||||||
const upMd = useMediaQuery(theme.breakpoints.up("md"))
|
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
||||||
const isTablet = useMediaQuery(theme.breakpoints.down(1000))
|
const isTablet = useMediaQuery(theme.breakpoints.down(1000));
|
||||||
const cart = useCart();
|
const cart = useCart();
|
||||||
const customTariffs = useCustomTariffsStore((state) => state.privilegeByService)
|
const customTariffs = useCustomTariffsStore((state) => state.privilegeByService);
|
||||||
|
|
||||||
const basePrice = cart.priceBeforeDiscounts
|
const basePrice = cart.priceBeforeDiscounts;
|
||||||
const discountedPrice = cart.priceAfterDiscounts
|
const discountedPrice = cart.priceAfterDiscounts;
|
||||||
|
|
||||||
const handleCustomBackNavigation = useHistoryTracker()
|
const handleCustomBackNavigation = useHistoryTracker();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SectionWrapper
|
<SectionWrapper
|
||||||
maxWidth="lg"
|
maxWidth="lg"
|
||||||
sx={{
|
sx={{
|
||||||
mt: upMd ? "25px" : "20px",
|
mt: upMd ? "25px" : "20px",
|
||||||
px: isTablet ? (upMd ? "40px" : "18px") : "20px",
|
px: isTablet ? (upMd ? "40px" : "18px") : "20px",
|
||||||
mb: upMd ? "93px" : "48px",
|
mb: upMd ? "93px" : "48px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
mt: "20px",
|
mt: "20px",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
gap: "80px",
|
gap: "80px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{Object.entries(customTariffs).filter(([serviceKey]) => serviceKey === "squiz").map(([serviceKey, privileges], index) => {
|
{Object.entries(customTariffs).filter(([serviceKey]) => serviceKey === "squiz").map(([serviceKey, privileges], index) => {
|
||||||
return <Box key={index}>
|
return (
|
||||||
<Box
|
<Box key={serviceKey}>
|
||||||
sx={{
|
<Box
|
||||||
mb: "40px",
|
sx={{
|
||||||
display: "flex",
|
mb: "40px",
|
||||||
gap: "10px",
|
display: "flex",
|
||||||
}}
|
gap: "10px",
|
||||||
>
|
}}
|
||||||
{!upMd && index === 0 && (
|
>
|
||||||
<IconButton
|
{!upMd && index === 0 && (
|
||||||
onClick={handleCustomBackNavigation}
|
<IconButton
|
||||||
sx={{
|
onClick={handleCustomBackNavigation}
|
||||||
p: 0,
|
sx={{
|
||||||
height: "28px",
|
p: 0,
|
||||||
width: "28px",
|
height: "28px",
|
||||||
color: "black",
|
width: "28px",
|
||||||
}}
|
color: "black",
|
||||||
>
|
}}
|
||||||
<ArrowBackIcon />
|
>
|
||||||
</IconButton>
|
<ArrowBackIcon />
|
||||||
)}
|
</IconButton>
|
||||||
<ComplexHeader text1="Мой тариф " text2={serviceNameByKey[serviceKey] === "Опросник" ? "PenaQuiz" : serviceNameByKey[serviceKey]} />
|
)}
|
||||||
</Box>
|
<ComplexHeader text1="Мой тариф " text2={serviceNameByKey[serviceKey] === "Опросник" ? "PenaQuiz" : serviceNameByKey[serviceKey]} />
|
||||||
<CustomTariffCard serviceKey={serviceKey} privileges={privileges} />
|
</Box>
|
||||||
</Box>
|
<CustomTariffCard serviceKey={serviceKey} privileges={privileges} />
|
||||||
})}
|
</Box>
|
||||||
</Box>
|
);
|
||||||
<Link
|
})}
|
||||||
to="/tariffconstructor/savedtariffs"
|
</Box>
|
||||||
style={{
|
<Link
|
||||||
display: "block",
|
to="/tariffconstructor/savedtariffs"
|
||||||
marginTop: "50px",
|
style={{
|
||||||
textUnderlinePosition: "under",
|
display: "block",
|
||||||
color: theme.palette.purple.main,
|
marginTop: "50px",
|
||||||
textDecorationColor: theme.palette.purple.main,
|
textUnderlinePosition: "under",
|
||||||
}}
|
color: theme.palette.purple.main,
|
||||||
>
|
textDecorationColor: theme.palette.purple.main,
|
||||||
Ваши сохраненные тарифы
|
}}
|
||||||
</Link>
|
>
|
||||||
<TotalPrice priceBeforeDiscounts={basePrice} priceAfterDiscounts={discountedPrice} isConstructor={true} />
|
Ваши сохраненные тарифы
|
||||||
</SectionWrapper>
|
</Link>
|
||||||
)
|
<TotalPrice priceBeforeDiscounts={basePrice} priceAfterDiscounts={discountedPrice} isConstructor={true} />
|
||||||
|
</SectionWrapper>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withErrorBoundary(TariffConstructor, {
|
export default withErrorBoundary(TariffConstructor, {
|
||||||
fallback: <Typography mt="8px" textAlign="center">Ошибка при отображении моих тарифов</Typography>,
|
fallback: <Typography mt="8px" textAlign="center">Ошибка при отображении моих тарифов</Typography>,
|
||||||
onError: handleComponentError,
|
onError: handleComponentError,
|
||||||
})
|
});
|
||||||
|
@ -1,173 +1,169 @@
|
|||||||
import { Privilege, PrivilegeValueType, useThrottle } from "@frontend/kitui"
|
import { CustomPrivilege, Privilege, useThrottle } from "@frontend/kitui";
|
||||||
import { Box, SliderProps, Typography, useMediaQuery, useTheme } from "@mui/material"
|
import { Box, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import { CustomSlider } from "@root/components/CustomSlider"
|
import { CustomSlider } from "@root/components/CustomSlider";
|
||||||
import NumberInputWithUnitAdornment from "@root/components/NumberInputWithUnitAdornment"
|
import NumberInputWithUnitAdornment from "@root/components/NumberInputWithUnitAdornment";
|
||||||
import CalendarIcon from "@root/components/icons/CalendarIcon"
|
import CalendarIcon from "@root/components/icons/CalendarIcon";
|
||||||
import PieChartIcon from "@root/components/icons/PieChartIcon"
|
import PieChartIcon from "@root/components/icons/PieChartIcon";
|
||||||
import { useCartStore } from "@root/stores/cart"
|
import { setCustomTariffsUserValue, useCustomTariffsStore } from "@root/stores/customTariffs";
|
||||||
import { setCustomTariffsUserValue, useCustomTariffsStore } from "@root/stores/customTariffs"
|
import { useUserStore } from "@root/stores/user";
|
||||||
import { useDiscountStore } from "@root/stores/discounts"
|
import { getDeclension } from "@root/utils/declension";
|
||||||
import { useUserStore } from "@root/stores/user"
|
import { useCartTariffs } from "@root/utils/hooks/useCartTariffs";
|
||||||
import { getDeclension } from "@root/utils/declension"
|
import { useEffect, useState } from "react";
|
||||||
import { useEffect, useState } from "react"
|
import { useDebouncedCallback } from "use-debounce";
|
||||||
import { useDebouncedCallback } from 'use-debounce';
|
|
||||||
|
|
||||||
const sliderSettingsByType = {
|
const sliderSettingsByType = {
|
||||||
день: { max: 365, min: 0 },
|
день: { max: 365, min: 0 },
|
||||||
шаблон: { max: 5000, min: 0 },
|
шаблон: { max: 5000, min: 0 },
|
||||||
МБ: { max: 5000, min: 0 },
|
МБ: { max: 5000, min: 0 },
|
||||||
заявка: { max: 5000, min: 0 }
|
заявка: { max: 5000, min: 0 }
|
||||||
}
|
};
|
||||||
type PrivilegeName = "день" | "шаблон" | "МБ" | "заявка"
|
|
||||||
|
type PrivilegeName = "день" | "шаблон" | "МБ" | "заявка";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
privilege: Privilege;
|
privilege: CustomPrivilege;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function TariffPrivilegeSlider({ privilege }: Props) {
|
export default function TariffPrivilegeSlider({ privilege }: Props) {
|
||||||
const theme = useTheme()
|
const theme = useTheme();
|
||||||
const upMd = useMediaQuery(theme.breakpoints.up("md"))
|
const upMd = useMediaQuery(theme.breakpoints.up("md"));
|
||||||
const userValue = useCustomTariffsStore((state) => state.userValuesMap[privilege.serviceKey]?.[privilege._id]) ?? sliderSettingsByType[privilege.value]?.min
|
const userValue = useCustomTariffsStore((state) => state.userValuesMap[privilege.serviceKey]?.[privilege._id]) ?? sliderSettingsByType[privilege.value]?.min;
|
||||||
const discounts = useDiscountStore((state) => state.discounts)
|
const purchasesAmount = useUserStore((state) => state.userAccount?.wallet.spent) ?? sliderSettingsByType[privilege.value]?.min;
|
||||||
const currentCartTotal = useCartStore((state) => state.cart.priceAfterDiscounts)
|
const cartTariffs = useCartTariffs();
|
||||||
const purchasesAmount = useUserStore((state) => state.userAccount?.wallet.spent) ?? sliderSettingsByType[privilege.value]?.min
|
const [value, setValue] = useState<number>(userValue);
|
||||||
const isUserNko = useUserStore(state => state.userAccount?.status) === "nko"
|
const throttledValue = useThrottle(value, 200);
|
||||||
const [value, setValue] = useState<number>(userValue)
|
|
||||||
const throttledValue = useThrottle(value, 200)
|
|
||||||
|
|
||||||
useEffect(
|
useEffect(
|
||||||
function setStoreValue() {
|
function setStoreValue() {
|
||||||
setCustomTariffsUserValue(
|
setCustomTariffsUserValue(
|
||||||
privilege.serviceKey,
|
cartTariffs ?? [],
|
||||||
privilege._id,
|
privilege.serviceKey,
|
||||||
throttledValue,
|
privilege._id,
|
||||||
discounts,
|
throttledValue,
|
||||||
currentCartTotal,
|
purchasesAmount,
|
||||||
purchasesAmount,
|
);
|
||||||
isUserNko,
|
},
|
||||||
)
|
[cartTariffs, purchasesAmount, privilege._id, privilege.serviceKey, throttledValue]
|
||||||
},
|
);
|
||||||
[currentCartTotal, discounts, purchasesAmount, privilege._id, privilege.serviceKey, throttledValue, isUserNko]
|
|
||||||
)
|
|
||||||
|
|
||||||
function handleSliderChange(measurement: PrivilegeName) {
|
function handleSliderChange(measurement: PrivilegeName) {
|
||||||
return (value: number | number[]) => {
|
return (value: number | number[]) => {
|
||||||
|
|
||||||
if (Number(value) < Number(sliderSettingsByType[measurement]?.min)) {
|
if (Number(value) < Number(sliderSettingsByType[measurement]?.min)) {
|
||||||
setValue(0)
|
setValue(0);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Array.isArray(value)) throw new Error("Slider uses multiple values instead of one")
|
if (Array.isArray(value)) throw new Error("Slider uses multiple values instead of one");
|
||||||
|
|
||||||
setValue(value)
|
setValue(value);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const quantityText = `${value} ${getDeclension(value, privilege.value)}`
|
const quantityText = `${value} ${getDeclension(value, privilege.value)}`;
|
||||||
|
|
||||||
|
|
||||||
const setNotSmallNumber = useDebouncedCallback(() => {
|
|
||||||
if (value === sliderSettingsByType[privilege.value]?.min) return
|
|
||||||
if (Number(value) < Number(sliderSettingsByType[privilege.value]?.min)) {
|
|
||||||
setValue(sliderSettingsByType[privilege.value]?.min)
|
|
||||||
}
|
|
||||||
if (privilege.value === "день" && Number(value) < 30 && Number(value) !== 0) {
|
|
||||||
setValue(30)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (privilege.value !== "день" && Number(value) < 100 && Number(value) !== 0) {
|
const setNotSmallNumber = useDebouncedCallback(() => {
|
||||||
setValue(100)
|
if (value === sliderSettingsByType[privilege.value]?.min) return;
|
||||||
}
|
if (Number(value) < Number(sliderSettingsByType[privilege.value]?.min)) {
|
||||||
}, 600)
|
setValue(sliderSettingsByType[privilege.value]?.min);
|
||||||
|
}
|
||||||
|
if (privilege.value === "день" && Number(value) < 30 && Number(value) !== 0) {
|
||||||
|
setValue(30);
|
||||||
|
}
|
||||||
|
|
||||||
const quantityElement = (
|
if (privilege.value !== "день" && Number(value) < 100 && Number(value) !== 0) {
|
||||||
<Box
|
setValue(100);
|
||||||
sx={{
|
}
|
||||||
display: "flex",
|
}, 600);
|
||||||
gap: "15px",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: upMd ? "end" : undefined,
|
|
||||||
flexWrap: "wrap",
|
|
||||||
mt: upMd ? undefined : "12px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="p1" color={theme.palette.purple.main} textAlign="end">
|
|
||||||
{quantityText}
|
|
||||||
</Typography>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
gap: "15px",
|
|
||||||
alignItems: "center",
|
|
||||||
flexWrap: "wrap",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography sx={{ fontSize: "16px", lineHeight: "19px", mt: "1px" }}>или</Typography>
|
|
||||||
<NumberInputWithUnitAdornment
|
|
||||||
id={"privilege_input_" + privilege._id}
|
|
||||||
value={value}
|
|
||||||
privilege={privilege}
|
|
||||||
adornmentText={getDeclension(0, privilege.value)}
|
|
||||||
onChange={(value) => {
|
|
||||||
setValue(value)
|
|
||||||
setNotSmallNumber()
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
|
|
||||||
const icon =
|
const quantityElement = (
|
||||||
privilege.type === "day" ? (
|
<Box
|
||||||
<CalendarIcon color={theme.palette.orange.main} bgcolor="#FEDFD0" />
|
sx={{
|
||||||
) : (
|
display: "flex",
|
||||||
<PieChartIcon color={theme.palette.orange.main} bgcolor="#FEDFD0" />
|
gap: "15px",
|
||||||
)
|
alignItems: "center",
|
||||||
|
justifyContent: upMd ? "end" : undefined,
|
||||||
|
flexWrap: "wrap",
|
||||||
|
mt: upMd ? undefined : "12px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography variant="p1" color={theme.palette.purple.main} textAlign="end">
|
||||||
|
{quantityText}
|
||||||
|
</Typography>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
gap: "15px",
|
||||||
|
alignItems: "center",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography sx={{ fontSize: "16px", lineHeight: "19px", mt: "1px" }}>или</Typography>
|
||||||
|
<NumberInputWithUnitAdornment
|
||||||
|
id={"privilege_input_" + privilege._id}
|
||||||
|
value={value}
|
||||||
|
privilege={privilege}
|
||||||
|
adornmentText={getDeclension(0, privilege.value)}
|
||||||
|
onChange={(value) => {
|
||||||
|
setValue(value);
|
||||||
|
setNotSmallNumber();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
const icon =
|
||||||
<Box>
|
privilege.type === "day" ? (
|
||||||
<Typography sx={{ color: theme.palette.gray.dark, mb: "auto" }}>{privilege.description}</Typography>
|
<CalendarIcon color={theme.palette.orange.main} bgcolor="#FEDFD0" />
|
||||||
<Box
|
) : (
|
||||||
sx={{
|
<PieChartIcon color={theme.palette.orange.main} bgcolor="#FEDFD0" />
|
||||||
display: "flex",
|
);
|
||||||
flexDirection: "column",
|
|
||||||
mt: "40px",
|
return (
|
||||||
}}
|
<Box>
|
||||||
>
|
<Typography sx={{ color: theme.palette.gray.dark, mb: "auto" }}>{privilege.description}</Typography>
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
// flexWrap: "wrap",
|
flexDirection: "column",
|
||||||
alignItems: "center",
|
mt: "40px",
|
||||||
mb: "8px",
|
}}
|
||||||
justifyContent: "space-between",
|
>
|
||||||
gap: "10px",
|
<Box
|
||||||
}}
|
sx={{
|
||||||
>
|
display: "flex",
|
||||||
<Box
|
// flexWrap: "wrap",
|
||||||
sx={{
|
alignItems: "center",
|
||||||
display: "flex",
|
mb: "8px",
|
||||||
alignItems: "center",
|
justifyContent: "space-between",
|
||||||
gap: "22px",
|
gap: "10px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{icon}
|
<Box
|
||||||
<Typography sx={{ maxWidth: "100px" }} variant="h5">
|
sx={{
|
||||||
{privilege.name}
|
display: "flex",
|
||||||
</Typography>
|
alignItems: "center",
|
||||||
</Box>
|
gap: "22px",
|
||||||
{upMd && quantityElement}
|
}}
|
||||||
</Box>
|
>
|
||||||
<CustomSlider
|
{icon}
|
||||||
value={value}
|
<Typography sx={{ maxWidth: "100px" }} variant="h5">
|
||||||
min={sliderSettingsByType[privilege.value]?.min }
|
{privilege.name}
|
||||||
max={sliderSettingsByType[privilege.value]?.max || 100}
|
</Typography>
|
||||||
onChange={handleSliderChange(privilege.value)}
|
</Box>
|
||||||
firstStep={privilege.value === "день" ? 30 : 100}
|
{upMd && quantityElement}
|
||||||
/>
|
</Box>
|
||||||
{!upMd && quantityElement}
|
<CustomSlider
|
||||||
</Box>
|
value={value}
|
||||||
</Box>
|
min={sliderSettingsByType[privilege.value]?.min}
|
||||||
)
|
max={sliderSettingsByType[privilege.value]?.max || 100}
|
||||||
|
onChange={handleSliderChange(privilege.value)}
|
||||||
|
firstStep={privilege.value === "день" ? 30 : 100}
|
||||||
|
/>
|
||||||
|
{!upMd && quantityElement}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import SectionWrapper from "@components/SectionWrapper";
|
import SectionWrapper from "@components/SectionWrapper";
|
||||||
import { getMessageFromFetchError } from "@frontend/kitui";
|
import { Tariff, getMessageFromFetchError } from "@frontend/kitui";
|
||||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||||
import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material";
|
import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material";
|
||||||
import NumberIcon from "@root/components/NumberIcon";
|
import NumberIcon from "@root/components/NumberIcon";
|
||||||
import { FullTariff } from "@root/model/tariff";
|
|
||||||
import { useCartStore } from "@root/stores/cart";
|
|
||||||
import { useDiscountStore } from "@root/stores/discounts";
|
import { useDiscountStore } from "@root/stores/discounts";
|
||||||
import { useTariffStore } from "@root/stores/tariffs";
|
import { useTariffStore } from "@root/stores/tariffs";
|
||||||
import { addTariffToCart, useUserStore } from "@root/stores/user";
|
import { addTariffToCart, useUserStore } from "@root/stores/user";
|
||||||
@ -12,7 +10,7 @@ import { calcIndividualTariffPrices } from "@root/utils/calcTariffPrices";
|
|||||||
import { currencyFormatter } from "@root/utils/currencyFormatter";
|
import { currencyFormatter } from "@root/utils/currencyFormatter";
|
||||||
import { handleComponentError } from "@root/utils/handleComponentError";
|
import { handleComponentError } from "@root/utils/handleComponentError";
|
||||||
import { usePrevLocation } from "@root/utils/hooks/handleCustomBackNavigation";
|
import { usePrevLocation } from "@root/utils/hooks/handleCustomBackNavigation";
|
||||||
import { useRecentlyPurchasedTariffs } from "@utils/hooks/useRecentlyPurchasedTariffs";
|
import { useCartTariffs } from "@root/utils/hooks/useCartTariffs";
|
||||||
import { enqueueSnackbar } from "notistack";
|
import { enqueueSnackbar } from "notistack";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { withErrorBoundary } from "react-error-boundary";
|
import { withErrorBoundary } from "react-error-boundary";
|
||||||
@ -39,14 +37,12 @@ function TariffPage() {
|
|||||||
const [selectedItem, setSelectedItem] = useState<number>(0);
|
const [selectedItem, setSelectedItem] = useState<number>(0);
|
||||||
const discounts = useDiscountStore((state) => state.discounts);
|
const discounts = useDiscountStore((state) => state.discounts);
|
||||||
const purchasesAmount = useUserStore((state) => state.userAccount?.wallet.spent) ?? 0;
|
const purchasesAmount = useUserStore((state) => state.userAccount?.wallet.spent) ?? 0;
|
||||||
const cartTariffMap = useCartStore((state) => state.cartTariffMap);
|
|
||||||
const isUserNko = useUserStore((state) => state.userAccount?.status) === "nko";
|
const isUserNko = useUserStore((state) => state.userAccount?.status) === "nko";
|
||||||
|
const currentTariffs = useCartTariffs();
|
||||||
|
|
||||||
const { recentlyPurchased } = useRecentlyPurchasedTariffs();
|
|
||||||
const handleCustomBackNavigation = usePrevLocation(location);
|
const handleCustomBackNavigation = usePrevLocation(location);
|
||||||
|
|
||||||
const unit: string = String(location.pathname).slice(9);
|
const unit: string = String(location.pathname).slice(9);
|
||||||
const currentTariffs = Object.values(cartTariffMap).filter((tariff): tariff is FullTariff => typeof tariff === "object");
|
|
||||||
|
|
||||||
function handleTariffItemClick(tariffId: string) {
|
function handleTariffItemClick(tariffId: string) {
|
||||||
addTariffToCart(tariffId)
|
addTariffToCart(tariffId)
|
||||||
@ -72,7 +68,8 @@ function TariffPage() {
|
|||||||
return false
|
return false
|
||||||
});
|
});
|
||||||
|
|
||||||
const createTariffElements = (filteredTariffs: FullTariff[], addFreeTariff = false) => {
|
const createTariffElements = (filteredTariffs: Tariff[], addFreeTariff = false) => {
|
||||||
|
console.log(filteredTariffs)
|
||||||
const tariffElements = filteredTariffs
|
const tariffElements = filteredTariffs
|
||||||
.filter((tariff) => tariff.privileges.length > 0)
|
.filter((tariff) => tariff.privileges.length > 0)
|
||||||
.map((tariff, index) => {
|
.map((tariff, index) => {
|
||||||
@ -80,7 +77,7 @@ function TariffPage() {
|
|||||||
tariff,
|
tariff,
|
||||||
discounts,
|
discounts,
|
||||||
purchasesAmount,
|
purchasesAmount,
|
||||||
currentTariffs,
|
currentTariffs ?? [],
|
||||||
isUserNko
|
isUserNko
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1,95 +1,22 @@
|
|||||||
import { CartData, Discount, Tariff } from "@frontend/kitui"
|
import { create } from "zustand";
|
||||||
import { calcCart } from "@root/utils/calcCart/calcCart"
|
import { devtools } from "zustand/middleware";
|
||||||
import { produce } from "immer"
|
|
||||||
import { create } from "zustand"
|
|
||||||
import { devtools } from "zustand/middleware"
|
|
||||||
|
|
||||||
interface CartStore {
|
interface CartStore {
|
||||||
cartTariffMap: Record<string, Tariff | "loading" | "not found">;
|
notEnoughMoneyAmount: number;
|
||||||
cart: CartData;
|
|
||||||
isDrawerOpen: boolean;
|
|
||||||
notEnoughMoneyAmount: number;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useCartStore = create<CartStore>()(
|
export const useCartStore = create<CartStore>()(
|
||||||
devtools(
|
devtools(
|
||||||
(get, set) => ({
|
(get, set) => ({
|
||||||
cartTariffMap: {},
|
|
||||||
cart: {
|
|
||||||
services: [],
|
|
||||||
priceBeforeDiscounts: 0,
|
|
||||||
priceAfterDiscounts: 0,
|
|
||||||
itemCount: 0,
|
|
||||||
allAppliedDiscounts: [],
|
|
||||||
appliedCartPurchasesDiscount: null,
|
|
||||||
appliedLoyaltyDiscount: null,
|
|
||||||
},
|
|
||||||
isDrawerOpen: false,
|
|
||||||
notEnoughMoneyAmount: 0,
|
notEnoughMoneyAmount: 0,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: "Cart",
|
name: "Cart",
|
||||||
enabled: process.env.NODE_ENV === "development",
|
enabled: process.env.NODE_ENV === "development",
|
||||||
trace: true,
|
trace: true,
|
||||||
actionsBlacklist: "rejected",
|
actionsBlacklist: "rejected",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
);
|
||||||
|
|
||||||
export const setCartTariffStatus = (tariffId: string, status: "loading" | "not found") =>
|
export const setNotEnoughMoneyAmount = (amount: number) => useCartStore.setState({ notEnoughMoneyAmount: amount });
|
||||||
useCartStore.setState(
|
|
||||||
produce<CartStore>((state) => {
|
|
||||||
state.cartTariffMap[tariffId] = status
|
|
||||||
}),
|
|
||||||
false,
|
|
||||||
{
|
|
||||||
type: "setCartTariffStatus",
|
|
||||||
tariffId,
|
|
||||||
status,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
export const addCartTariffs = (tariffs: Tariff[], discounts: Discount[], purchasesAmount: number, isUserNko: boolean) =>
|
|
||||||
useCartStore.setState(
|
|
||||||
produce<CartStore>((state) => {
|
|
||||||
tariffs.forEach((tariff) => {
|
|
||||||
// if (tariff.isCustom && tariff.privileges[0].serviceKey !== "custom") {
|
|
||||||
// tariff.privileges[0].serviceKey = "custom"
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
state.cartTariffMap[tariff._id] = tariff
|
|
||||||
})
|
|
||||||
const cartTariffs = Object.values(state.cartTariffMap).filter(
|
|
||||||
(tariff): tariff is Tariff => typeof tariff === "object"
|
|
||||||
)
|
|
||||||
state.cart = calcCart(cartTariffs, discounts, purchasesAmount, isUserNko)
|
|
||||||
}),
|
|
||||||
false,
|
|
||||||
{
|
|
||||||
type: tariffs.length > 0 ? "addCartTariffs" : "rejected",
|
|
||||||
tariffs,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
export const removeMissingCartTariffs = (tariffIds: string[], discounts: Discount[], purchasesAmount: number, isUserNko: boolean) =>
|
|
||||||
useCartStore.setState(
|
|
||||||
produce<CartStore>((state) => {
|
|
||||||
for (const key in state.cartTariffMap) {
|
|
||||||
if (!tariffIds.includes(key)) delete state.cartTariffMap[key]
|
|
||||||
}
|
|
||||||
const cartTariffs = Object.values(state.cartTariffMap).filter(
|
|
||||||
(tariff): tariff is Tariff => typeof tariff === "object"
|
|
||||||
)
|
|
||||||
state.cart = calcCart(cartTariffs, discounts, purchasesAmount, isUserNko)
|
|
||||||
}),
|
|
||||||
false,
|
|
||||||
{
|
|
||||||
type: "rejected",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
export const openCartDrawer = () => useCartStore.setState({ isDrawerOpen: true })
|
|
||||||
|
|
||||||
export const closeCartDrawer = () => useCartStore.setState({ isDrawerOpen: false })
|
|
||||||
|
|
||||||
export const setNotEnoughMoneyAmount = (amount: number) => useCartStore.setState({ notEnoughMoneyAmount: amount })
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import { createTariff } from "@root/api/tariff"
|
import { CustomPrivilegeWithAmount, Tariff } from "@frontend/kitui";
|
||||||
import { CustomTariffUserValuesMap, ServiceKeyToPriceMap } from "@root/model/customTariffs"
|
import { createTariff } from "@root/api/tariff";
|
||||||
import { ServiceKeyToPrivilegesMap } from "@root/model/privilege"
|
import { CustomTariffUserValuesMap, ServiceKeyToPriceMap } from "@root/model/customTariffs";
|
||||||
import { produce } from "immer"
|
import { ServiceKeyToPrivilegesMap } from "@root/model/privilege";
|
||||||
import { create } from "zustand"
|
import { calcCustomTariffPrice } from "@root/utils/calcCart/calcCustomTariffPrice";
|
||||||
import { devtools, persist } from "zustand/middleware"
|
import { produce } from "immer";
|
||||||
import { Discount, PrivilegeWithAmount/* , findCartDiscount */, findDiscountFactor/* , findLoyaltyDiscount *//* , findPrivilegeDiscount *//* , findServiceDiscount */} from "@frontend/kitui"
|
import { create } from "zustand";
|
||||||
import { findNkoDiscount, calcCart } from "@root/utils/calcCart/calcCart"
|
import { devtools, persist } from "zustand/middleware";
|
||||||
import { useCartStore } from "./cart"
|
import { useDiscountStore } from "./discounts";
|
||||||
import { FullTariff } from "@root/model/tariff"
|
import { useUserStore } from "./user";
|
||||||
|
|
||||||
|
|
||||||
interface CustomTariffsStore {
|
interface CustomTariffsStore {
|
||||||
@ -18,229 +18,90 @@ interface CustomTariffsStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const initialState: CustomTariffsStore = {
|
const initialState: CustomTariffsStore = {
|
||||||
privilegeByService: {},
|
privilegeByService: {},
|
||||||
userValuesMap: {},
|
userValuesMap: {},
|
||||||
summaryPriceBeforeDiscountsMap: {},
|
summaryPriceBeforeDiscountsMap: {},
|
||||||
summaryPriceAfterDiscountsMap: {},
|
summaryPriceAfterDiscountsMap: {},
|
||||||
}
|
};
|
||||||
|
|
||||||
function findLoyaltyDiscount(
|
|
||||||
purchasesAmount: number,
|
|
||||||
discounts: Discount[],
|
|
||||||
): Discount | null {
|
|
||||||
const applicableDiscounts = discounts.filter(discount => {
|
|
||||||
return (
|
|
||||||
discount.Layer === 4 &&
|
|
||||||
discount.Condition.UserType !== "nko" &&
|
|
||||||
purchasesAmount >= Number(discount.Condition.PurchasesAmount)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!applicableDiscounts.length) return null;
|
|
||||||
|
|
||||||
const maxValueDiscount = applicableDiscounts.reduce((prev, current) => {
|
|
||||||
return Number(current.Condition.PurchasesAmount) > Number(prev.Condition.PurchasesAmount) ? current : prev;
|
|
||||||
});
|
|
||||||
|
|
||||||
return maxValueDiscount;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function findServiceDiscount(
|
|
||||||
serviceKey: string,
|
|
||||||
currentPrice: number,
|
|
||||||
discounts: Discount[],
|
|
||||||
): Discount | null {
|
|
||||||
const applicableDiscounts = discounts.filter(discount => {
|
|
||||||
return (
|
|
||||||
discount.Layer === 2 &&
|
|
||||||
discount.Condition.Group === serviceKey &&
|
|
||||||
currentPrice >= Number(discount.Condition.PriceFrom)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!applicableDiscounts.length) return null;
|
|
||||||
|
|
||||||
const maxValueDiscount = applicableDiscounts.reduce((prev, current) => {
|
|
||||||
return Number(current.Condition.PriceFrom) > Number(prev.Condition.PriceFrom) ? current : prev;
|
|
||||||
});
|
|
||||||
|
|
||||||
return maxValueDiscount;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const useCustomTariffsStore = create<CustomTariffsStore>()(
|
export const useCustomTariffsStore = create<CustomTariffsStore>()(
|
||||||
persist(
|
persist(
|
||||||
devtools(
|
devtools(
|
||||||
(set, get) => initialState,
|
(set, get) => initialState,
|
||||||
{
|
{
|
||||||
name: "Custom tariffs",
|
name: "Custom tariffs",
|
||||||
enabled: process.env.NODE_ENV === "development",
|
enabled: process.env.NODE_ENV === "development",
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
name: "customTariffs",
|
name: "customTariffs",
|
||||||
partialize: state => ({
|
partialize: state => ({
|
||||||
userValuesMap: state.userValuesMap,
|
userValuesMap: state.userValuesMap,
|
||||||
summaryPriceBeforeDiscountsMap: state.summaryPriceBeforeDiscountsMap,
|
summaryPriceBeforeDiscountsMap: state.summaryPriceBeforeDiscountsMap,
|
||||||
summaryPriceAfterDiscountsMap: state.summaryPriceAfterDiscountsMap,
|
summaryPriceAfterDiscountsMap: state.summaryPriceAfterDiscountsMap,
|
||||||
}),
|
}),
|
||||||
migrate: () => initialState,
|
migrate: () => initialState,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
);
|
||||||
|
|
||||||
function findPrivilegeDiscount(
|
export const setCustomTariffs = (customTariffs: ServiceKeyToPrivilegesMap) => useCustomTariffsStore.setState({ privilegeByService: customTariffs });
|
||||||
privilegeId: string,
|
|
||||||
privilegePrice: number,
|
|
||||||
discounts: Discount[],
|
|
||||||
): Discount | null {
|
|
||||||
const applicableDiscounts = discounts.filter(discount => {
|
|
||||||
const conditionMinPrice = parseFloat(discount.Condition.Term);
|
|
||||||
if (!isFinite(conditionMinPrice)) throw new Error(`Couldn't parse Discount.Condition.Term: ${discount.Condition.Term}`);
|
|
||||||
|
|
||||||
return (
|
|
||||||
discount.Layer === 1 &&
|
|
||||||
privilegeId === discount.Condition.Product &&
|
|
||||||
privilegePrice >= conditionMinPrice
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!applicableDiscounts.length) return null;
|
|
||||||
|
|
||||||
const maxValueDiscount = applicableDiscounts.reduce((prev, current) =>
|
|
||||||
parseFloat(current.Condition.Term) > parseFloat(prev.Condition.Term) ? current : prev
|
|
||||||
);
|
|
||||||
|
|
||||||
return maxValueDiscount;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const setCustomTariffs = (customTariffs: ServiceKeyToPrivilegesMap) => useCustomTariffsStore.setState({ privilegeByService: customTariffs })
|
|
||||||
function findCartDiscount(
|
|
||||||
cartPurchasesAmount: number,
|
|
||||||
discounts: Discount[],
|
|
||||||
): Discount | null {
|
|
||||||
const applicableDiscounts = discounts.filter(discount => {
|
|
||||||
return (
|
|
||||||
discount.Layer === 3 &&
|
|
||||||
cartPurchasesAmount >= discount.Condition.CartPurchasesAmount
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!applicableDiscounts.length) return null;
|
|
||||||
|
|
||||||
const maxValueDiscount = applicableDiscounts.reduce((prev, current) => {
|
|
||||||
|
|
||||||
return Number(current.Condition.CartPurchasesAmount) > Number(prev.Condition.CartPurchasesAmount) ? current : prev;
|
|
||||||
});
|
|
||||||
|
|
||||||
return maxValueDiscount;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const setCustomTariffsUserValue = (
|
export const setCustomTariffsUserValue = (
|
||||||
serviceKey: string,
|
cartTariffs: Tariff[],
|
||||||
privilegeId: string,
|
serviceKey: string,
|
||||||
value: number,
|
privilegeId: string,
|
||||||
discounts: Discount[],
|
value: number,
|
||||||
currentCartTotal: number,
|
purchasesAmount: number,
|
||||||
purchasesAmount: number,
|
|
||||||
isUserNko: boolean,
|
|
||||||
) => useCustomTariffsStore.setState(
|
) => useCustomTariffsStore.setState(
|
||||||
produce<CustomTariffsStore>(state => {
|
produce<CustomTariffsStore>(state => {
|
||||||
state.userValuesMap[serviceKey] ??= {}
|
state.userValuesMap[serviceKey] ??= {};
|
||||||
state.userValuesMap[serviceKey][privilegeId] = value
|
state.userValuesMap[serviceKey][privilegeId] = value;
|
||||||
|
const isUserNko = useUserStore.getState().userAccount?.status === "nko";
|
||||||
|
const discounts = useDiscountStore.getState().discounts;
|
||||||
|
|
||||||
const privilegeWithoutAmount = state.privilegeByService[serviceKey].find(p => p._id === privilegeId)
|
const { priceBeforeDiscounts, priceAfterDiscounts } = calcCustomTariffPrice(
|
||||||
if (!privilegeWithoutAmount) throw new Error(`Privilege not found: ${privilegeId}`)
|
state.userValuesMap[serviceKey],
|
||||||
let priceWithoutDiscounts = 0
|
state.privilegeByService[serviceKey],
|
||||||
let priceAfterDiscounts = 0
|
cartTariffs,
|
||||||
const privileges = new Array<PrivilegeWithAmount>()
|
discounts,
|
||||||
|
purchasesAmount,
|
||||||
|
isUserNko
|
||||||
|
);
|
||||||
|
|
||||||
Object.keys(state.userValuesMap[serviceKey]).forEach(e => {
|
state.summaryPriceBeforeDiscountsMap[serviceKey] = priceBeforeDiscounts;
|
||||||
const pwa = state.privilegeByService[serviceKey].find(p => p._id === e)
|
state.summaryPriceAfterDiscountsMap[serviceKey] = priceAfterDiscounts;
|
||||||
if (!pwa) return
|
|
||||||
if (state.userValuesMap[serviceKey][e] > 0)
|
|
||||||
privileges.push({
|
|
||||||
...pwa,
|
|
||||||
amount: state.userValuesMap[serviceKey][e]
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
);
|
||||||
let tariff: FullTariff = {
|
|
||||||
_id: "",
|
|
||||||
name: "",
|
|
||||||
price: 0,
|
|
||||||
description: "",
|
|
||||||
isCustom: true,
|
|
||||||
isDeleted: false,
|
|
||||||
privileges: privileges,
|
|
||||||
}
|
|
||||||
const cart = calcCart([...Object.values(useCartStore.getState().cartTariffMap as Record<string, FullTariff>), tariff], discounts, purchasesAmount, isUserNko)
|
|
||||||
|
|
||||||
const nkoDiscount = findNkoDiscount(discounts)
|
|
||||||
|
|
||||||
if (isUserNko && nkoDiscount) {
|
|
||||||
state.privilegeByService[serviceKey].forEach(privilege => {
|
|
||||||
const amount = state.userValuesMap[serviceKey]?.[privilege._id] ?? 0
|
|
||||||
priceWithoutDiscounts += privilege.price * amount
|
|
||||||
})
|
|
||||||
|
|
||||||
priceAfterDiscounts = priceWithoutDiscounts * findDiscountFactor(nkoDiscount)
|
|
||||||
} else {
|
|
||||||
state.privilegeByService[serviceKey].forEach(privilege => {
|
|
||||||
const amount = state.userValuesMap[serviceKey]?.[privilege._id] ?? 0
|
|
||||||
priceWithoutDiscounts += privilege.price * amount
|
|
||||||
|
|
||||||
const discount = cart.allAppliedDiscounts?.find(e => e.Condition.Product === privilege.privilegeId)
|
|
||||||
//const discount = findPrivilegeDiscount(privilege.privilegeId, amount, discounts)
|
|
||||||
priceAfterDiscounts += privilege.price * amount * findDiscountFactor(discount)
|
|
||||||
})
|
|
||||||
|
|
||||||
const serviceDiscount = cart.allAppliedDiscounts?.find(e => e.Condition.Group === serviceKey)
|
|
||||||
priceAfterDiscounts *= findDiscountFactor(serviceDiscount)
|
|
||||||
|
|
||||||
const cartDiscount = findCartDiscount(currentCartTotal+priceAfterDiscounts, discounts)
|
|
||||||
priceAfterDiscounts *= findDiscountFactor(cartDiscount)
|
|
||||||
|
|
||||||
const loyaltyDiscount = findLoyaltyDiscount(purchasesAmount, discounts)
|
|
||||||
priceAfterDiscounts *= findDiscountFactor(loyaltyDiscount)
|
|
||||||
}
|
|
||||||
|
|
||||||
state.summaryPriceBeforeDiscountsMap[serviceKey] = priceWithoutDiscounts
|
|
||||||
state.summaryPriceAfterDiscountsMap[serviceKey] = priceAfterDiscounts
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
export const createAndSendTariff = (serviceKey: string) => {
|
export const createAndSendTariff = (serviceKey: string) => {
|
||||||
const state = useCustomTariffsStore.getState()
|
const state = useCustomTariffsStore.getState();
|
||||||
|
|
||||||
const privileges: PrivilegeWithAmount[] = []
|
const privileges: CustomPrivilegeWithAmount[] = [];
|
||||||
|
|
||||||
Object.entries(state.userValuesMap[serviceKey]).forEach(([privilegeId, userValue]) => {
|
Object.entries(state.userValuesMap[serviceKey]).forEach(([privilegeId, userValue]) => {
|
||||||
if (userValue === 0) return
|
if (userValue === 0) return;
|
||||||
|
|
||||||
const privilegeWithoutAmount = state.privilegeByService[serviceKey].find(p => p._id === privilegeId)
|
const privilegeWithoutAmount = state.privilegeByService[serviceKey].find(p => p._id === privilegeId);
|
||||||
if (!privilegeWithoutAmount) throw new Error(`Privilege not found: ${privilegeId}`)
|
if (!privilegeWithoutAmount) throw new Error(`Privilege not found: ${privilegeId}`);
|
||||||
|
|
||||||
const privilege: PrivilegeWithAmount = {
|
const privilege: CustomPrivilegeWithAmount = {
|
||||||
...privilegeWithoutAmount,
|
...privilegeWithoutAmount,
|
||||||
privilegeId: privilegeWithoutAmount.privilegeId,
|
privilegeId: privilegeWithoutAmount.privilegeId,
|
||||||
amount: userValue,
|
amount: userValue,
|
||||||
}
|
};
|
||||||
|
|
||||||
privileges.push(privilege)
|
privileges.push(privilege);
|
||||||
})
|
});
|
||||||
|
|
||||||
const name = [...privileges.map(p => p.name), new Date().toISOString()].join(", ")
|
const name = [...privileges.map(p => p.name), new Date().toISOString()].join(", ");
|
||||||
|
|
||||||
const tariff = {
|
const tariff = {
|
||||||
name,
|
name,
|
||||||
isCustom: true,
|
isCustom: true,
|
||||||
privileges,
|
privileges,
|
||||||
}
|
};
|
||||||
|
|
||||||
return createTariff(tariff)
|
return createTariff(tariff);
|
||||||
}
|
};
|
||||||
|
|
||||||
export const clearCustomTariffs = () => useCustomTariffsStore.setState({ ...initialState })
|
export const clearCustomTariffs = () => useCustomTariffsStore.setState({ ...initialState });
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { PrivilegeWithAmount } from "@frontend/kitui"
|
import { Privilege } from "@frontend/kitui";
|
||||||
import { create } from "zustand"
|
import { create } from "zustand"
|
||||||
import { devtools } from "zustand/middleware"
|
import { devtools } from "zustand/middleware"
|
||||||
|
|
||||||
|
|
||||||
interface PrivilegeStore {
|
interface PrivilegeStore {
|
||||||
privileges: PrivilegeWithAmount[];
|
privileges: Privilege[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: PrivilegeStore = {
|
const initialState: PrivilegeStore = {
|
||||||
|
@ -108,7 +108,7 @@ export const updateTicket = <T extends AuthData>(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
function setProducedState<A extends string | { type: unknown }>(
|
function setProducedState<A extends string | { type: string }>(
|
||||||
recipe: (state: TicketStore) => void,
|
recipe: (state: TicketStore) => void,
|
||||||
action?: A
|
action?: A
|
||||||
) {
|
) {
|
||||||
|
@ -14,6 +14,7 @@ import { patchUser } from "@root/api/user"
|
|||||||
import { UserAccountSettingsFieldStatus, VerificationStatus } from "@root/model/account"
|
import { UserAccountSettingsFieldStatus, VerificationStatus } from "@root/model/account"
|
||||||
import { patchCurrency, deleteCart, patchCart } from "@root/api/cart"
|
import { patchCurrency, deleteCart, patchCart } from "@root/api/cart"
|
||||||
import { User, UserAccount, UserName, getInitials, patchUserAccount } from "@frontend/kitui"
|
import { User, UserAccount, UserName, getInitials, patchUserAccount } from "@frontend/kitui"
|
||||||
|
import { setNotEnoughMoneyAmount } from "./cart";
|
||||||
|
|
||||||
interface UserStore {
|
interface UserStore {
|
||||||
userId: string | null;
|
userId: string | null;
|
||||||
@ -286,6 +287,7 @@ export const addTariffToCart = async (tariffId: string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const removeTariffFromCart = async (tariffId: string) => {
|
export const removeTariffFromCart = async (tariffId: string) => {
|
||||||
|
setNotEnoughMoneyAmount(0);
|
||||||
const [deleteCartResponse, deleteCartError] = await deleteCart(tariffId)
|
const [deleteCartResponse, deleteCartError] = await deleteCart(tariffId)
|
||||||
|
|
||||||
if (!deleteCartError) {
|
if (!deleteCartError) {
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,149 +1,51 @@
|
|||||||
import { CartData, Discount, PrivilegeCartData, Tariff, TariffCartData, findPrivilegeDiscount, findDiscountFactor, applyLoyaltyDiscount} from "@frontend/kitui";
|
import {
|
||||||
|
CartData,
|
||||||
|
Discount,
|
||||||
|
PrivilegeCartData,
|
||||||
|
Tariff,
|
||||||
|
TariffCartData,
|
||||||
|
findCartDiscount,
|
||||||
|
findDiscountFactor,
|
||||||
|
findLoyaltyDiscount,
|
||||||
|
findNkoDiscount,
|
||||||
|
findPrivilegeDiscount,
|
||||||
|
findServiceDiscount,
|
||||||
|
} from "@frontend/kitui";
|
||||||
|
|
||||||
function applyPrivilegeDiscounts(
|
export function calcCart(tariffs: Tariff[], discounts: Discount[], purchasesAmount: number, isUserNko?: boolean, userId: string = ""): CartData {
|
||||||
cartData: CartData,
|
|
||||||
discounts: Discount[],
|
|
||||||
) {
|
|
||||||
const privMap = new Map()
|
|
||||||
|
|
||||||
cartData.services.forEach(service => service.tariffs.forEach(tariff => tariff.privileges.forEach(p => {
|
|
||||||
privMap.set(p.privilegeId, p.amount + (privMap.get(p.privilegeId)||0))
|
|
||||||
})))
|
|
||||||
cartData.services.forEach(service => {
|
|
||||||
|
|
||||||
service.tariffs.forEach(tariff => {
|
|
||||||
|
|
||||||
tariff.privileges.forEach(privilege => {
|
|
||||||
const privilegeDiscount = findPrivilegeDiscount(privilege.privilegeId, privMap.get(privilege.privilegeId)||0, discounts);
|
|
||||||
if (!privilegeDiscount) return;
|
|
||||||
|
|
||||||
const discountAmount = privilege.price * (1 - findDiscountFactor(privilegeDiscount));
|
|
||||||
privilege.price -= discountAmount;
|
|
||||||
cartData.allAppliedDiscounts.push(privilegeDiscount);
|
|
||||||
privilege.appliedPrivilegeDiscount = privilegeDiscount;
|
|
||||||
|
|
||||||
tariff.price -= discountAmount;
|
|
||||||
service.price -= discountAmount;
|
|
||||||
cartData.priceAfterDiscounts -= discountAmount;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function findServiceDiscount(
|
|
||||||
serviceKey: string,
|
|
||||||
currentPrice: number,
|
|
||||||
discounts: Discount[],
|
|
||||||
): Discount | null {
|
|
||||||
const applicableDiscounts = discounts.filter(discount => {
|
|
||||||
return (
|
|
||||||
discount.Layer === 2 &&
|
|
||||||
discount.Condition.Group === serviceKey &&
|
|
||||||
currentPrice >= Number(discount.Condition.PriceFrom)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!applicableDiscounts.length) return null;
|
|
||||||
|
|
||||||
const maxValueDiscount = applicableDiscounts.reduce((prev, current) => {
|
|
||||||
return Number(current.Condition.PriceFrom) > Number(prev.Condition.PriceFrom) ? current : prev;
|
|
||||||
});
|
|
||||||
|
|
||||||
return maxValueDiscount;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findCartDiscount(
|
|
||||||
cartPurchasesAmount: number,
|
|
||||||
discounts: Discount[],
|
|
||||||
): Discount | null {
|
|
||||||
const applicableDiscounts = discounts.filter(discount => {
|
|
||||||
return (
|
|
||||||
discount.Layer === 3 &&
|
|
||||||
cartPurchasesAmount >= Number(discount.Condition.CartPurchasesAmount)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!applicableDiscounts.length) return null;
|
|
||||||
|
|
||||||
const maxValueDiscount = applicableDiscounts.reduce((prev, current) => {
|
|
||||||
return Number(current.Condition.CartPurchasesAmount) > Number(prev.Condition.CartPurchasesAmount) ? current : prev;
|
|
||||||
});
|
|
||||||
|
|
||||||
return maxValueDiscount;
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyCartDiscount(
|
|
||||||
cartData: CartData,
|
|
||||||
discounts: Discount[],
|
|
||||||
) {
|
|
||||||
const cartDiscount = findCartDiscount(cartData.priceAfterDiscounts, discounts);
|
|
||||||
if (!cartDiscount) return;
|
|
||||||
|
|
||||||
cartData.priceAfterDiscounts *= findDiscountFactor(cartDiscount);
|
|
||||||
cartData.allAppliedDiscounts.push(cartDiscount);
|
|
||||||
cartData.appliedCartPurchasesDiscount = cartDiscount;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function applyServiceDiscounts(
|
|
||||||
cartData: CartData,
|
|
||||||
discounts: Discount[],
|
|
||||||
) {
|
|
||||||
const privMap = new Map()
|
|
||||||
cartData.services.forEach(service => {
|
|
||||||
|
|
||||||
service.tariffs.forEach(tariff => tariff.privileges.forEach(p => {
|
|
||||||
privMap.set(p.serviceKey, p.price + (privMap.get(p.serviceKey)||0))
|
|
||||||
}))
|
|
||||||
})
|
|
||||||
|
|
||||||
cartData.services.forEach(service => {
|
|
||||||
service.tariffs.map(tariff => {
|
|
||||||
tariff.privileges.forEach(privilege => {
|
|
||||||
const privilegeDiscount = findServiceDiscount(privilege.serviceKey, privMap.get(privilege.serviceKey), discounts);
|
|
||||||
if (!privilegeDiscount) return;
|
|
||||||
|
|
||||||
const discountAmount = privilege.price * (1 - findDiscountFactor(privilegeDiscount));
|
|
||||||
privilege.price -= discountAmount;
|
|
||||||
cartData.allAppliedDiscounts.push(privilegeDiscount);
|
|
||||||
service.appliedServiceDiscount = privilegeDiscount;
|
|
||||||
|
|
||||||
tariff.price -= discountAmount;
|
|
||||||
service.price -= discountAmount;
|
|
||||||
cartData.priceAfterDiscounts -= discountAmount;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function calcCart(tariffs: Tariff[], discounts: Discount[], purchasesAmount: number, isUserNko?: boolean): CartData {
|
|
||||||
const cartData: CartData = {
|
const cartData: CartData = {
|
||||||
services: [],
|
services: [],
|
||||||
priceBeforeDiscounts: 0,
|
priceBeforeDiscounts: 0,
|
||||||
priceAfterDiscounts: 0,
|
priceAfterDiscounts: 0,
|
||||||
itemCount: 0,
|
|
||||||
appliedCartPurchasesDiscount: null,
|
appliedCartPurchasesDiscount: null,
|
||||||
appliedLoyaltyDiscount: null,
|
appliedLoyaltyDiscount: null,
|
||||||
allAppliedDiscounts: [],
|
allAppliedDiscounts: [],
|
||||||
}
|
appliedDiscountsByPrivilegeId: new Map(),
|
||||||
|
};
|
||||||
|
const privilegeAmountById = new Map<string, number>();
|
||||||
|
const servicePriceByKey = new Map<string, number>();
|
||||||
|
const allAppliedDiscounts = new Set<Discount>();
|
||||||
|
|
||||||
|
// Формируем корзину
|
||||||
|
|
||||||
tariffs.forEach(tariff => {
|
tariffs.forEach(tariff => {
|
||||||
if (tariff.privileges === undefined) return
|
if (tariff.privileges === undefined) return;
|
||||||
if (
|
if (
|
||||||
(tariff.price || 0) > 0
|
(tariff.price || 0) > 0
|
||||||
&& tariff.privileges.length !== 1
|
&& tariff.privileges.length !== 1
|
||||||
) throw new Error("Price is defined for tariff with several")
|
) throw new Error("Price is defined for tariff with several privileges");
|
||||||
|
|
||||||
let serviceData =cartData.services.find(service => (service.serviceKey === "custom" && tariff.isCustom))
|
let serviceData = cartData.services.find(service => (service.serviceKey === "custom" && tariff.isCustom));
|
||||||
if (!serviceData && !tariff.isCustom) serviceData = cartData.services.find(service => service.serviceKey === tariff.privileges[0]?.serviceKey)
|
if (!serviceData && !tariff.isCustom) serviceData = cartData.services.find(service => service.serviceKey === tariff.privileges[0]?.serviceKey);
|
||||||
|
|
||||||
if (!serviceData) {
|
if (!serviceData) {
|
||||||
serviceData = {
|
serviceData = {
|
||||||
serviceKey: tariff.isCustom ?"custom" :tariff.privileges[0]?.serviceKey,
|
serviceKey: tariff.isCustom ? "custom" : tariff.privileges[0]?.serviceKey,
|
||||||
tariffs: [],
|
tariffs: [],
|
||||||
price: 0,
|
price: 0,
|
||||||
appliedServiceDiscount: null,
|
appliedServiceDiscount: null,
|
||||||
}
|
};
|
||||||
cartData.services.push(serviceData)
|
cartData.services.push(serviceData);
|
||||||
}
|
}
|
||||||
|
|
||||||
const tariffCartData: TariffCartData = {
|
const tariffCartData: TariffCartData = {
|
||||||
@ -152,13 +54,12 @@ export function calcCart(tariffs: Tariff[], discounts: Discount[], purchasesAmou
|
|||||||
privileges: [],
|
privileges: [],
|
||||||
id: tariff._id,
|
id: tariff._id,
|
||||||
name: tariff.name,
|
name: tariff.name,
|
||||||
}
|
};
|
||||||
serviceData.tariffs.push(tariffCartData)
|
serviceData.tariffs.push(tariffCartData);
|
||||||
|
|
||||||
tariff.privileges.forEach(privilege => {
|
tariff.privileges.forEach(privilege => {
|
||||||
let privilegePrice = privilege.amount * privilege.price
|
let privilegePrice = privilege.amount * privilege.price;
|
||||||
if (!tariff.price) tariffCartData.price += privilegePrice
|
if (tariff.price) privilegePrice = tariff.price;
|
||||||
else privilegePrice = tariff.price
|
|
||||||
|
|
||||||
const privilegeCartData: PrivilegeCartData = {
|
const privilegeCartData: PrivilegeCartData = {
|
||||||
serviceKey: privilege.serviceKey,
|
serviceKey: privilege.serviceKey,
|
||||||
@ -166,46 +67,158 @@ export function calcCart(tariffs: Tariff[], discounts: Discount[], purchasesAmou
|
|||||||
description: privilege.description,
|
description: privilege.description,
|
||||||
price: privilegePrice,
|
price: privilegePrice,
|
||||||
amount: privilege.amount,
|
amount: privilege.amount,
|
||||||
appliedPrivilegeDiscount: null,
|
};
|
||||||
}
|
|
||||||
|
|
||||||
tariffCartData.privileges.push(privilegeCartData)
|
privilegeAmountById.set(
|
||||||
cartData.priceAfterDiscounts += privilegePrice
|
privilege.privilegeId,
|
||||||
cartData.itemCount++
|
privilege.amount + (privilegeAmountById.get(privilege.privilegeId) || 0)
|
||||||
})
|
);
|
||||||
|
servicePriceByKey.set(
|
||||||
|
privilege.serviceKey,
|
||||||
|
privilegePrice + (servicePriceByKey.get(privilege.serviceKey) || 0)
|
||||||
|
);
|
||||||
|
cartData.appliedDiscountsByPrivilegeId.set(privilege.privilegeId, new Set());
|
||||||
|
|
||||||
cartData.priceBeforeDiscounts += tariffCartData.price
|
tariffCartData.privileges.push(privilegeCartData);
|
||||||
serviceData.price += tariffCartData.price
|
});
|
||||||
})
|
});
|
||||||
|
|
||||||
const nkoDiscount = findNkoDiscount(discounts)
|
cartData.priceBeforeDiscounts = Array.from(servicePriceByKey.values()).reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
|
const nkoDiscount = findNkoDiscount(discounts);
|
||||||
if (isUserNko && nkoDiscount) {
|
if (isUserNko && nkoDiscount) {
|
||||||
applyNkoDiscount(cartData, nkoDiscount)
|
cartData.priceAfterDiscounts *= nkoDiscount.Target.Factor;
|
||||||
} else {
|
allAppliedDiscounts.add(nkoDiscount);
|
||||||
applyPrivilegeDiscounts(cartData, discounts)
|
|
||||||
applyServiceDiscounts(cartData, discounts)
|
cartData.services.forEach(service => {
|
||||||
applyCartDiscount(cartData, discounts)
|
service.tariffs.forEach(tariff => {
|
||||||
applyLoyaltyDiscount(cartData, discounts, purchasesAmount)
|
tariff.privileges.forEach(privilege => {
|
||||||
|
const privilegeAppliedDiscounts = cartData.appliedDiscountsByPrivilegeId.get(privilege.privilegeId);
|
||||||
|
if (!privilegeAppliedDiscounts) throw new Error(`Privilege id ${privilege.privilegeId} not found in appliedDiscountsByPrivilegeId`);
|
||||||
|
|
||||||
|
privilegeAppliedDiscounts.add(nkoDiscount);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
applyDiscountsToCart(cartData);
|
||||||
|
|
||||||
|
cartData.allAppliedDiscounts = Array.from(allAppliedDiscounts);
|
||||||
|
|
||||||
|
return cartData;
|
||||||
}
|
}
|
||||||
|
|
||||||
cartData.allAppliedDiscounts = Array.from(new Set(cartData.allAppliedDiscounts))
|
// Ищем и собираем скидки в appliedDiscountsByPrivilegeId
|
||||||
|
|
||||||
return cartData
|
cartData.services.forEach(service => {
|
||||||
|
service.tariffs.forEach(tariff => {
|
||||||
|
tariff.privileges.forEach(privilege => {
|
||||||
|
const privilegeDiscount = findPrivilegeDiscount(privilege.privilegeId, privilegeAmountById.get(privilege.privilegeId) || 0, discounts, userId);
|
||||||
|
if (!privilegeDiscount) return;
|
||||||
|
|
||||||
|
allAppliedDiscounts.add(privilegeDiscount);
|
||||||
|
|
||||||
|
const privilegeAppliedDiscounts = cartData.appliedDiscountsByPrivilegeId.get(privilege.privilegeId);
|
||||||
|
if (!privilegeAppliedDiscounts) throw new Error(`Privilege id ${privilege.privilegeId} not found in appliedDiscountsByPrivilegeId`);
|
||||||
|
|
||||||
|
privilegeAppliedDiscounts.add(privilegeDiscount);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
cartData.services.forEach(service => {
|
||||||
|
service.tariffs.map(tariff => {
|
||||||
|
tariff.privileges.forEach(privilege => {
|
||||||
|
const servicePrice = servicePriceByKey.get(privilege.serviceKey);
|
||||||
|
if (!servicePrice) return;
|
||||||
|
|
||||||
|
const serviceDiscount = findServiceDiscount(privilege.serviceKey, servicePrice, discounts, userId);
|
||||||
|
if (!serviceDiscount) return;
|
||||||
|
|
||||||
|
allAppliedDiscounts.add(serviceDiscount);
|
||||||
|
service.appliedServiceDiscount = serviceDiscount;
|
||||||
|
|
||||||
|
const privilegeAppliedDiscounts = cartData.appliedDiscountsByPrivilegeId.get(privilege.privilegeId);
|
||||||
|
if (!privilegeAppliedDiscounts) throw new Error(`Privilege id ${privilege.privilegeId} not found in appliedDiscountsByPrivilegeId`);
|
||||||
|
|
||||||
|
privilegeAppliedDiscounts.add(serviceDiscount);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const intermediateCartData = structuredClone(cartData);
|
||||||
|
applyDiscountsToCart(intermediateCartData);
|
||||||
|
|
||||||
|
const intermediateCartPriceAfterDiscounts = intermediateCartData.priceAfterDiscounts;
|
||||||
|
|
||||||
|
const cartDiscount = findCartDiscount(intermediateCartPriceAfterDiscounts, discounts);
|
||||||
|
if (cartDiscount) {
|
||||||
|
cartData.services.forEach(service => {
|
||||||
|
service.tariffs.forEach(tariff => {
|
||||||
|
tariff.privileges.forEach(privilege => {
|
||||||
|
const privilegeAppliedDiscounts = cartData.appliedDiscountsByPrivilegeId.get(privilege.privilegeId);
|
||||||
|
if (!privilegeAppliedDiscounts) throw new Error(`Privilege id ${privilege.privilegeId} not found in appliedDiscountsByPrivilegeId`);
|
||||||
|
|
||||||
|
if (!Array.from(privilegeAppliedDiscounts)[0]?.Condition.User) privilegeAppliedDiscounts.add(cartDiscount);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
allAppliedDiscounts.add(cartDiscount);
|
||||||
|
cartData.appliedCartPurchasesDiscount = cartDiscount;
|
||||||
|
}
|
||||||
|
|
||||||
|
const loyalDiscount = findLoyaltyDiscount(purchasesAmount, discounts);
|
||||||
|
if (loyalDiscount) {
|
||||||
|
cartData.services.forEach(service => {
|
||||||
|
service.tariffs.forEach(tariff => {
|
||||||
|
tariff.privileges.forEach(privilege => {
|
||||||
|
const privilegeAppliedDiscounts = cartData.appliedDiscountsByPrivilegeId.get(privilege.privilegeId);
|
||||||
|
if (!privilegeAppliedDiscounts) throw new Error(`Privilege id ${privilege.privilegeId} not found in appliedDiscountsByPrivilegeId`);
|
||||||
|
|
||||||
|
if (!Array.from(privilegeAppliedDiscounts)[0]?.Condition.User) privilegeAppliedDiscounts.add(loyalDiscount);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
allAppliedDiscounts.add(loyalDiscount);
|
||||||
|
cartData.appliedLoyaltyDiscount = loyalDiscount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Применяем скидки
|
||||||
|
|
||||||
|
applyDiscountsToCart(cartData);
|
||||||
|
|
||||||
|
cartData.allAppliedDiscounts = Array.from(allAppliedDiscounts);
|
||||||
|
|
||||||
|
return Object.freeze(cartData);
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyNkoDiscount(cartData: CartData, discount: Discount) {
|
function applyDiscountsToCart(cartData: CartData) {
|
||||||
cartData.priceAfterDiscounts *= discount.Target.Factor
|
cartData.services.forEach(service => {
|
||||||
cartData.allAppliedDiscounts.push(discount)
|
let servicePrice = 0;
|
||||||
}
|
|
||||||
|
|
||||||
export function findNkoDiscount(discounts: Discount[]): Discount | null {
|
service.tariffs.forEach(tariff => {
|
||||||
const applicableDiscounts = discounts.filter(discount => discount.Condition.UserType === "nko")
|
let privilegePriceSum = 0;
|
||||||
|
let tariffDiscountFactor = 1;
|
||||||
|
|
||||||
if (!applicableDiscounts.length) return null
|
tariff.privileges.forEach(privilege => {
|
||||||
|
const discounts = cartData.appliedDiscountsByPrivilegeId.get(privilege.privilegeId) ?? [];
|
||||||
|
|
||||||
const maxValueDiscount = applicableDiscounts.reduce((prev, current) => {
|
const discountsFactor = Array.from(discounts).reduce((factor, discount) => factor * findDiscountFactor(discount), 1);
|
||||||
return current.Condition.CartPurchasesAmount > prev.Condition.CartPurchasesAmount ? current : prev
|
privilege.price *= discountsFactor;
|
||||||
})
|
tariffDiscountFactor *= discountsFactor;
|
||||||
|
|
||||||
return maxValueDiscount
|
privilegePriceSum += privilege.price;
|
||||||
}
|
});
|
||||||
|
|
||||||
|
if (tariff.price) tariff.price *= tariffDiscountFactor;
|
||||||
|
else tariff.price = privilegePriceSum;
|
||||||
|
|
||||||
|
servicePrice += tariff.price;
|
||||||
|
});
|
||||||
|
|
||||||
|
service.price = servicePrice;
|
||||||
|
cartData.priceAfterDiscounts += servicePrice;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
49
src/utils/calcCart/calcCustomTariffPrice.ts
Normal file
49
src/utils/calcCart/calcCustomTariffPrice.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { CustomPrivilegeWithAmount, Discount, Tariff } from "@frontend/kitui";
|
||||||
|
import { CustomTariffUserValues } from "@root/model/customTariffs";
|
||||||
|
import { calcCart } from "./calcCart";
|
||||||
|
|
||||||
|
|
||||||
|
export function calcCustomTariffPrice(
|
||||||
|
customTariffUserValues: CustomTariffUserValues,
|
||||||
|
servicePrivileges: CustomPrivilegeWithAmount[],
|
||||||
|
cartTariffs: Tariff[],
|
||||||
|
discounts: Discount[],
|
||||||
|
purchasesAmount: number,
|
||||||
|
isUserNko: boolean,
|
||||||
|
) {
|
||||||
|
const privileges = new Array<CustomPrivilegeWithAmount>();
|
||||||
|
|
||||||
|
const priceBeforeDiscounts = servicePrivileges.reduce((price, privilege) => {
|
||||||
|
const amount = customTariffUserValues?.[privilege._id] ?? 0;
|
||||||
|
return price + privilege.price * amount;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
Object.keys(customTariffUserValues).forEach(privilegeId => {
|
||||||
|
const pwa = servicePrivileges.find(p => p._id === privilegeId);
|
||||||
|
if (!pwa) return;
|
||||||
|
if (customTariffUserValues[privilegeId] > 0) privileges.push({
|
||||||
|
...pwa,
|
||||||
|
amount: customTariffUserValues[privilegeId]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const customTariff: Tariff = {
|
||||||
|
_id: crypto.randomUUID(),
|
||||||
|
name: "",
|
||||||
|
price: 0,
|
||||||
|
description: "",
|
||||||
|
isCustom: true,
|
||||||
|
isDeleted: false,
|
||||||
|
privileges: privileges,
|
||||||
|
};
|
||||||
|
|
||||||
|
const cart = calcCart([...cartTariffs, customTariff], discounts, purchasesAmount, isUserNko);
|
||||||
|
|
||||||
|
const customService = cart.services.flatMap(service => service.tariffs).find(tariff => tariff.id === customTariff._id);
|
||||||
|
if (!customService) throw new Error("Custom service not found in cart");
|
||||||
|
|
||||||
|
return {
|
||||||
|
priceBeforeDiscounts,
|
||||||
|
priceAfterDiscounts: customService.price,
|
||||||
|
};
|
||||||
|
}
|
900
src/utils/calcCart/mockData/discounts.ts
Normal file
900
src/utils/calcCart/mockData/discounts.ts
Normal file
@ -0,0 +1,900 @@
|
|||||||
|
import { Discount } from "@frontend/kitui";
|
||||||
|
|
||||||
|
export const testDiscounts: Discount[] = [
|
||||||
|
{
|
||||||
|
"ID": "6521d98b166f36879928ebbf",
|
||||||
|
"Name": "NKO",
|
||||||
|
"Layer": 4,
|
||||||
|
"Description": "скидка ветеранам НКО",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-10-07T21:00:45.829Z",
|
||||||
|
"To": "2023-11-06T21:00:45.829Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "nko",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "",
|
||||||
|
"Term": "0",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [],
|
||||||
|
"Factor": 0.4,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": true
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-11-10T23:20:32.619Z",
|
||||||
|
"CreatedAt": "2023-09-16T20:10:26.048Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "657b9b73153787e41052c25b",
|
||||||
|
"Name": "1000 шаблонов",
|
||||||
|
"Layer": 1,
|
||||||
|
"Description": "Тариф на 1000 шаблонов",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-15T00:18:57.999Z",
|
||||||
|
"To": "2024-01-14T00:18:58Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "templateCnt",
|
||||||
|
"Term": "1000",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "templateCnt",
|
||||||
|
"Factor": 0.7,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.7,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-15T00:18:59.138Z",
|
||||||
|
"CreatedAt": "2023-12-15T00:18:59.138Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "657b9cb0153787e41052c25c",
|
||||||
|
"Name": "десять тысяч шаблонов",
|
||||||
|
"Layer": 1,
|
||||||
|
"Description": "Тариф 10 000",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-15T00:24:15.555Z",
|
||||||
|
"To": "2024-01-14T00:24:15.555Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "templateCnt",
|
||||||
|
"Term": "10000",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "templateCnt",
|
||||||
|
"Factor": 0.5,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.5,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-15T00:24:16.562Z",
|
||||||
|
"CreatedAt": "2023-12-15T00:24:16.562Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "657b9e67153787e41052c25d",
|
||||||
|
"Name": "3 месяца",
|
||||||
|
"Layer": 1,
|
||||||
|
"Description": "Тариф 3 месяца",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-15T00:31:34.807Z",
|
||||||
|
"To": "2024-01-14T00:31:34.807Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "templateUnlimTime",
|
||||||
|
"Term": "90",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "templateUnlimTime",
|
||||||
|
"Factor": 0.8,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.8,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-15T00:31:35.601Z",
|
||||||
|
"CreatedAt": "2023-12-15T00:31:35.601Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "657b9e8a153787e41052c25e",
|
||||||
|
"Name": "год",
|
||||||
|
"Layer": 1,
|
||||||
|
"Description": "Тариф год",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-15T00:32:09.329Z",
|
||||||
|
"To": "2024-01-14T00:32:09.329Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "templateUnlimTime",
|
||||||
|
"Term": "365",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "templateUnlimTime",
|
||||||
|
"Factor": 0.65,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.65,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-15T00:32:10.123Z",
|
||||||
|
"CreatedAt": "2023-12-15T00:32:10.123Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "657b9eb4153787e41052c25f",
|
||||||
|
"Name": "3 года",
|
||||||
|
"Layer": 1,
|
||||||
|
"Description": "Тариф 3 года",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-15T00:32:51.379Z",
|
||||||
|
"To": "2024-01-14T00:32:51.379Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "templateUnlimTime",
|
||||||
|
"Term": "1095",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "templateUnlimTime",
|
||||||
|
"Factor": 0.5,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.5,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-15T00:32:52.174Z",
|
||||||
|
"CreatedAt": "2023-12-15T00:32:52.174Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "657f5028153787e41052c266",
|
||||||
|
"Name": "10т.р",
|
||||||
|
"Layer": 4,
|
||||||
|
"Description": "купил больше чем на 10 тыров",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-17T19:48:47.466Z",
|
||||||
|
"To": "2024-01-16T19:48:47.466Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "10000",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "",
|
||||||
|
"Term": "0",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "",
|
||||||
|
"Factor": 0,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.98,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-17T19:48:46.072Z",
|
||||||
|
"CreatedAt": "2023-12-17T19:46:48.854Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "657f50c3153787e41052c268",
|
||||||
|
"Name": "1т.р",
|
||||||
|
"Layer": 4,
|
||||||
|
"Description": "купил больше чем на 1 тыр",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-17T19:49:24.782Z",
|
||||||
|
"To": "2024-01-16T19:49:24.782Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "100000",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "",
|
||||||
|
"Term": "0",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "",
|
||||||
|
"Factor": 0,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.99,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-17T19:49:23.384Z",
|
||||||
|
"CreatedAt": "2023-12-17T19:49:23.384Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "657f50e4153787e41052c269",
|
||||||
|
"Name": "100т.р",
|
||||||
|
"Layer": 4,
|
||||||
|
"Description": "купил больше чем на 100 тыров",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-17T19:49:57.462Z",
|
||||||
|
"To": "2024-01-16T19:49:57.462Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "10000000",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "",
|
||||||
|
"Term": "0",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "",
|
||||||
|
"Factor": 0,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.95,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-17T19:49:56.066Z",
|
||||||
|
"CreatedAt": "2023-12-17T19:49:56.066Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "657f511b153787e41052c26a",
|
||||||
|
"Name": "1 т.р",
|
||||||
|
"Layer": 3,
|
||||||
|
"Description": "Больще 1т.р",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-17T19:50:52.764Z",
|
||||||
|
"To": "2024-01-16T19:50:52.764Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "100000",
|
||||||
|
"Product": "",
|
||||||
|
"Term": "0",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "",
|
||||||
|
"Factor": 0,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.95,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-17T19:50:51.408Z",
|
||||||
|
"CreatedAt": "2023-12-17T19:50:51.408Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "657f512d153787e41052c26b",
|
||||||
|
"Name": "5 т.р",
|
||||||
|
"Layer": 3,
|
||||||
|
"Description": "Больще 5т.р",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-17T19:51:11.104Z",
|
||||||
|
"To": "2024-01-16T19:51:11.104Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "500000",
|
||||||
|
"Product": "",
|
||||||
|
"Term": "0",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "",
|
||||||
|
"Factor": 0,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.93,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-17T19:51:09.707Z",
|
||||||
|
"CreatedAt": "2023-12-17T19:51:09.707Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "657f5144153787e41052c26c",
|
||||||
|
"Name": "10 т.р",
|
||||||
|
"Layer": 3,
|
||||||
|
"Description": "Больше 10т.р",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-17T19:51:33.502Z",
|
||||||
|
"To": "2024-01-16T19:51:33.502Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "1000000",
|
||||||
|
"Product": "",
|
||||||
|
"Term": "0",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "",
|
||||||
|
"Factor": 0,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.91,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-17T19:51:32.105Z",
|
||||||
|
"CreatedAt": "2023-12-17T19:51:32.105Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "657f515a153787e41052c26d",
|
||||||
|
"Name": "50 т.р",
|
||||||
|
"Layer": 3,
|
||||||
|
"Description": "Больше 50т.р",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-17T19:51:56.316Z",
|
||||||
|
"To": "2024-01-16T19:51:56.316Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "5000000",
|
||||||
|
"Product": "",
|
||||||
|
"Term": "0",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "",
|
||||||
|
"Factor": 0,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.89,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-17T19:51:54.919Z",
|
||||||
|
"CreatedAt": "2023-12-17T19:51:54.919Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "65872fb4153787e41052c26e",
|
||||||
|
"Name": "Лямчик",
|
||||||
|
"Layer": 4,
|
||||||
|
"Description": "Купил больше чем на миллиона",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-23T19:06:27.521Z",
|
||||||
|
"To": "2024-01-22T19:06:27.521Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "100000000",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "",
|
||||||
|
"Term": "0",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "",
|
||||||
|
"Factor": 0,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.9,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-23T19:06:28.253Z",
|
||||||
|
"CreatedAt": "2023-12-23T19:06:28.253Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "6588c6e9153787e41052c26f",
|
||||||
|
"Name": "больше 5т.р",
|
||||||
|
"Layer": 2,
|
||||||
|
"Description": "Шаблонизатор:Больше 5т.р",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-25T00:03:53.024Z",
|
||||||
|
"To": "2024-01-24T00:03:53.024Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "",
|
||||||
|
"Term": "0",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "500000",
|
||||||
|
"Group": "templategen"
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "",
|
||||||
|
"Factor": 0,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.98,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "templategen",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-25T00:03:53.269Z",
|
||||||
|
"CreatedAt": "2023-12-25T00:03:53.269Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "6588c70c153787e41052c270",
|
||||||
|
"Name": "больше 10 т.р",
|
||||||
|
"Layer": 2,
|
||||||
|
"Description": "Шаблонизатор:Больше 10 т.р",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-25T00:04:28.279Z",
|
||||||
|
"To": "2024-01-24T00:04:28.279Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "",
|
||||||
|
"Term": "0",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "1000000",
|
||||||
|
"Group": "templategen"
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "",
|
||||||
|
"Factor": 0,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.97,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "templategen",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-25T00:04:28.442Z",
|
||||||
|
"CreatedAt": "2023-12-25T00:04:28.442Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "6588c724153787e41052c271",
|
||||||
|
"Name": "больше 100 т.р",
|
||||||
|
"Layer": 2,
|
||||||
|
"Description": "Шаблонизатор:Больше 100 т.р",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2023-12-25T00:04:52.461Z",
|
||||||
|
"To": "2024-01-24T00:04:52.461Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "",
|
||||||
|
"Term": "0",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "10000000",
|
||||||
|
"Group": "templategen"
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "",
|
||||||
|
"Factor": 0,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.95,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "templategen",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2023-12-25T00:04:52.625Z",
|
||||||
|
"CreatedAt": "2023-12-25T00:04:52.625Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "65a49c215389294d1c348511",
|
||||||
|
"Name": "1000 заявок",
|
||||||
|
"Layer": 1,
|
||||||
|
"Description": "Полное прохождение 1000 опросов респондентом",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2024-01-15T02:44:49.156Z",
|
||||||
|
"To": "2024-02-14T02:44:49.156Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "quizCnt",
|
||||||
|
"Term": "1000",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "quizCnt",
|
||||||
|
"Factor": 0.7,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.7,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2024-01-15T02:44:48.995Z",
|
||||||
|
"CreatedAt": "2024-01-15T02:44:48.995Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "65a49c4f5389294d1c348512",
|
||||||
|
"Name": "10000 заявок",
|
||||||
|
"Layer": 1,
|
||||||
|
"Description": "Полное прохождение 10000 опросов респондентом",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2024-01-15T02:45:37.236Z",
|
||||||
|
"To": "2024-02-14T02:45:37.236Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "quizCnt",
|
||||||
|
"Term": "10000",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "quizCnt",
|
||||||
|
"Factor": 0.5,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.5,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2024-01-15T02:45:35.984Z",
|
||||||
|
"CreatedAt": "2024-01-15T02:45:35.984Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "65a49d1a5389294d1c348513",
|
||||||
|
"Name": "3 месяца",
|
||||||
|
"Layer": 1,
|
||||||
|
"Description": "3 Месяца безлимита",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2024-01-15T02:48:59.617Z",
|
||||||
|
"To": "2024-02-14T02:48:59.617Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "quizUnlimTime",
|
||||||
|
"Term": "90",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "quizUnlimTime",
|
||||||
|
"Factor": 0.8,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.8,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2024-01-15T02:48:58.560Z",
|
||||||
|
"CreatedAt": "2024-01-15T02:48:58.560Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "65a49d335389294d1c348514",
|
||||||
|
"Name": "Год",
|
||||||
|
"Layer": 1,
|
||||||
|
"Description": "Год безлимита",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2024-01-15T02:49:24.266Z",
|
||||||
|
"To": "2024-02-14T02:49:24.266Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "quizUnlimTime",
|
||||||
|
"Term": "365",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "quizUnlimTime",
|
||||||
|
"Factor": 0.65,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.65,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2024-01-15T02:49:23.024Z",
|
||||||
|
"CreatedAt": "2024-01-15T02:49:23.024Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ID": "65a49d4f5389294d1c348515",
|
||||||
|
"Name": "3 Года",
|
||||||
|
"Layer": 1,
|
||||||
|
"Description": "3 Года безлимита",
|
||||||
|
"Condition": {
|
||||||
|
"Period": {
|
||||||
|
"From": "2024-01-15T02:49:52.264Z",
|
||||||
|
"To": "2024-02-14T02:49:52.264Z"
|
||||||
|
},
|
||||||
|
"User": "",
|
||||||
|
"UserType": "",
|
||||||
|
"Coupon": "",
|
||||||
|
"PurchasesAmount": "0",
|
||||||
|
"CartPurchasesAmount": "0",
|
||||||
|
"Product": "quizUnlimTime",
|
||||||
|
"Term": "1095",
|
||||||
|
"Usage": "0",
|
||||||
|
"PriceFrom": "0",
|
||||||
|
"Group": ""
|
||||||
|
},
|
||||||
|
"Target": {
|
||||||
|
"Products": [
|
||||||
|
{
|
||||||
|
"ID": "quizUnlimTime",
|
||||||
|
"Factor": 0.5,
|
||||||
|
"Overhelm": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Factor": 0.5,
|
||||||
|
"TargetScope": "Sum",
|
||||||
|
"TargetGroup": "",
|
||||||
|
"Overhelm": false
|
||||||
|
},
|
||||||
|
"Audit": {
|
||||||
|
"UpdatedAt": "2024-01-15T02:49:51.024Z",
|
||||||
|
"CreatedAt": "2024-01-15T02:49:51.024Z",
|
||||||
|
"Deleted": false
|
||||||
|
},
|
||||||
|
"Deprecated": false
|
||||||
|
}
|
||||||
|
];
|
492
src/utils/calcCart/mockData/results.ts
Normal file
492
src/utils/calcCart/mockData/results.ts
Normal file
@ -0,0 +1,492 @@
|
|||||||
|
type CartTestResult = [
|
||||||
|
/** Cart price */
|
||||||
|
number,
|
||||||
|
/** Used tariff mask, last number shows if nko applied */
|
||||||
|
number[],
|
||||||
|
];
|
||||||
|
|
||||||
|
export const cartTestResults: CartTestResult[] = [
|
||||||
|
[
|
||||||
|
750184.5,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 1, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
232560,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
956819.5,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 1, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1274000,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 1, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
96900,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
916051.5,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1, 0, 0, 0, 1, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
508524,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1, 1, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
466860,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1763580,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
963690,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
1, 1, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
848285.55,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
922862.85,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
383158.75,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1101077.25,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 1, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
602756.25,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
469952.25,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
910113.75,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||||
|
1, 1, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
916665.75,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
1, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
116280,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
864016.5,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 1, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
348840,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1068203.5,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 1, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
938255.5,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 1, 0, 0, 1, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
527496,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
489552,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
911092,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1,
|
||||||
|
1, 1, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
935844,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
1, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
479145.765,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
706809.765,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
966429.555,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1, 1, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
925661.555,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
903678.675,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
911544.725,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
637980,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
865644,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
939848,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 1, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
917280,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
|
||||||
|
1, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
973904.9775,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1196672.9775,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
749535.36,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
956184.3200000001,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
915416.3200000001,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1081947.4575,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
468595.57499999995,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1182916.735,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 1, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
686394.405,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
553590.405,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
946453.235,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1, 1, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
998505.235,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
1, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
905167.14,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1108469.18,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
978521.18,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
||||||
|
0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
760745.5800000001,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
967153.4600000001,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
926385.4600000001,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
1, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1092804.6675,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1315572.6675,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
872300.9400000001,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1076309.78,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
946361.78,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1200847.1475,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1423615.1475,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
909407.01,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1112617.87,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
982669.87,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1354679.69,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
907241.9700000001,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1110499.3900000001,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
||||||
|
0, 0, 0, 1, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
980551.39,
|
||||||
|
[
|
||||||
|
0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
|
||||||
|
0, 1, 0, 0, 0, 0, 0, 0,
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
811
src/utils/calcCart/mockData/tariffs.ts
Normal file
811
src/utils/calcCart/mockData/tariffs.ts
Normal file
@ -0,0 +1,811 @@
|
|||||||
|
import { Tariff } from "@frontend/kitui";
|
||||||
|
|
||||||
|
export const testTariffs: Tariff[] = [
|
||||||
|
{
|
||||||
|
"_id": "64f06be63fae7d590bf6426c",
|
||||||
|
"name": "Безлимит, Количество Шаблонов, 2023-08-31T10:31:02.472Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443d",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 10,
|
||||||
|
"amount": 130
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Количество Шаблонов",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443e",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество шаблонов, которые может сделать пользователь сервиса",
|
||||||
|
"type": "count",
|
||||||
|
"value": "шаблон",
|
||||||
|
"price": 5,
|
||||||
|
"amount": 2100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-08-31T10:31:02.570Z",
|
||||||
|
"updatedAt": "2023-08-31T10:31:02.570Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "64f06be93fae7d590bf64271",
|
||||||
|
"name": "Безлимит, Количество Шаблонов, 2023-08-31T10:31:05.703Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443d",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 10,
|
||||||
|
"amount": 130
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Количество Шаблонов",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443e",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество шаблонов, которые может сделать пользователь сервиса",
|
||||||
|
"type": "count",
|
||||||
|
"value": "шаблон",
|
||||||
|
"price": 5,
|
||||||
|
"amount": 2100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-08-31T10:31:05.732Z",
|
||||||
|
"updatedAt": "2023-08-31T10:31:05.732Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "64f06be93fae7d590bf64276",
|
||||||
|
"name": "Безлимит, Количество Шаблонов, 2023-08-31T10:31:05.874Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443d",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 10,
|
||||||
|
"amount": 130
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Количество Шаблонов",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443e",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество шаблонов, которые может сделать пользователь сервиса",
|
||||||
|
"type": "count",
|
||||||
|
"value": "шаблон",
|
||||||
|
"price": 5,
|
||||||
|
"amount": 2100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-08-31T10:31:05.884Z",
|
||||||
|
"updatedAt": "2023-08-31T10:31:05.884Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "64f06c103fae7d590bf6427b",
|
||||||
|
"name": "Безлимит, Количество Шаблонов, 2023-08-31T10:31:44.015Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443d",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 10,
|
||||||
|
"amount": 130
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Количество Шаблонов",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443e",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество шаблонов, которые может сделать пользователь сервиса",
|
||||||
|
"type": "count",
|
||||||
|
"value": "шаблон",
|
||||||
|
"price": 5,
|
||||||
|
"amount": 2100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-08-31T10:31:44.198Z",
|
||||||
|
"updatedAt": "2023-08-31T10:31:44.198Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "64f06c123fae7d590bf64280",
|
||||||
|
"name": "Безлимит, Количество Шаблонов, 2023-08-31T10:31:16.087Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443d",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 10,
|
||||||
|
"amount": 130
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Количество Шаблонов",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443e",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество шаблонов, которые может сделать пользователь сервиса",
|
||||||
|
"type": "count",
|
||||||
|
"value": "шаблон",
|
||||||
|
"price": 5,
|
||||||
|
"amount": 2100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-08-31T10:31:46.954Z",
|
||||||
|
"updatedAt": "2023-08-31T10:31:46.954Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "64f61a713fae7d590bf6494c",
|
||||||
|
"name": "Размер Диска, Безлимит, 2023-09-04T17:57:05.862Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Размер Диска",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443c",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Обьём ПенаДиска для хранения шаблонов и результатов шаблонизации",
|
||||||
|
"type": "count",
|
||||||
|
"value": "МБ",
|
||||||
|
"price": 555,
|
||||||
|
"amount": 1500
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Безлимит",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443d",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 10,
|
||||||
|
"amount": 220
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-09-04T17:57:05.987Z",
|
||||||
|
"updatedAt": "2023-09-04T17:57:05.987Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "64ff6eb75913fc89c5667d85",
|
||||||
|
"name": "Безлимит, 2023-09-11T19:47:03.383Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит",
|
||||||
|
"privilegeId": "64e88d30c4c82e949d5c443d",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 10,
|
||||||
|
"amount": 170
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-09-11T19:47:03.546Z",
|
||||||
|
"updatedAt": "2023-09-11T19:47:03.546Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "657b9b11215b615d2e35741f",
|
||||||
|
"name": "100 шаблонов",
|
||||||
|
"price": 0,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Количество Шаблонов",
|
||||||
|
"privilegeId": "templateCnt",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество шаблонов, которые может сделать пользователь сервиса",
|
||||||
|
"type": "count",
|
||||||
|
"value": "шаблон",
|
||||||
|
"price": 1000,
|
||||||
|
"amount": 100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-12-15T00:17:21.104Z",
|
||||||
|
"updatedAt": "2023-12-15T00:17:21.104Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "657b9b1a215b615d2e357424",
|
||||||
|
"name": "1000 шаблонов",
|
||||||
|
"price": 0,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Количество Шаблонов",
|
||||||
|
"privilegeId": "templateCnt",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество шаблонов, которые может сделать пользователь сервиса",
|
||||||
|
"type": "count",
|
||||||
|
"value": "шаблон",
|
||||||
|
"price": 1000,
|
||||||
|
"amount": 1000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-12-15T00:17:30.813Z",
|
||||||
|
"updatedAt": "2023-12-15T00:17:30.813Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "657b9b98215b615d2e35743a",
|
||||||
|
"name": "10000 шаблонов",
|
||||||
|
"price": 0,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Количество Шаблонов",
|
||||||
|
"privilegeId": "templateCnt",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество шаблонов, которые может сделать пользователь сервиса",
|
||||||
|
"type": "count",
|
||||||
|
"value": "шаблон",
|
||||||
|
"price": 1000,
|
||||||
|
"amount": 10000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-12-15T00:19:36.848Z",
|
||||||
|
"updatedAt": "2023-12-15T00:19:36.848Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "657b9bd0215b615d2e357445",
|
||||||
|
"name": "1 день",
|
||||||
|
"price": 10000,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит",
|
||||||
|
"privilegeId": "templateUnlimTime",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 1700,
|
||||||
|
"amount": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-12-15T00:20:32.586Z",
|
||||||
|
"updatedAt": "2023-12-15T00:20:32.586Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "657b9c15215b615d2e35745f",
|
||||||
|
"name": "Месяц",
|
||||||
|
"price": 0,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит",
|
||||||
|
"privilegeId": "templateUnlimTime",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 1700,
|
||||||
|
"amount": 30
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-12-15T00:21:41.878Z",
|
||||||
|
"updatedAt": "2023-12-15T00:21:41.878Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "657b9c25215b615d2e357464",
|
||||||
|
"name": "3 месяца",
|
||||||
|
"price": 0,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит",
|
||||||
|
"privilegeId": "templateUnlimTime",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 1700,
|
||||||
|
"amount": 90
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-12-15T00:21:57.114Z",
|
||||||
|
"updatedAt": "2023-12-15T00:21:57.114Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "657b9c4d215b615d2e357469",
|
||||||
|
"name": "Год",
|
||||||
|
"price": 0,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит",
|
||||||
|
"privilegeId": "templateUnlimTime",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 1700,
|
||||||
|
"amount": 365
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-12-15T00:22:37.456Z",
|
||||||
|
"updatedAt": "2023-12-15T00:22:37.456Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "657b9c59215b615d2e35746e",
|
||||||
|
"name": "3 года",
|
||||||
|
"price": 0,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит",
|
||||||
|
"privilegeId": "templateUnlimTime",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 1700,
|
||||||
|
"amount": 1095
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2023-12-15T00:22:49.492Z",
|
||||||
|
"updatedAt": "2023-12-15T00:22:49.492Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65af14358507c326f5a2db91",
|
||||||
|
"name": "Безлимит Опросов, Количество Заявок, 2024-01-23T01:19:49.676Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит Опросов",
|
||||||
|
"privilegeId": "quizUnlimTime",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 3400,
|
||||||
|
"amount": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Количество Заявок",
|
||||||
|
"privilegeId": "quizCnt",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество полных прохождений опросов",
|
||||||
|
"type": "count",
|
||||||
|
"value": "заявка",
|
||||||
|
"price": 2000,
|
||||||
|
"amount": 100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-23T01:19:49.897Z",
|
||||||
|
"updatedAt": "2024-01-23T01:19:49.897Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65af1b978507c326f5a2dbaa",
|
||||||
|
"name": "Безлимит Опросов, Количество Заявок, 2024-01-23T01:51:19.622Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит Опросов",
|
||||||
|
"privilegeId": "quizUnlimTime",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 3400,
|
||||||
|
"amount": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Количество Заявок",
|
||||||
|
"privilegeId": "quizCnt",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество полных прохождений опросов",
|
||||||
|
"type": "count",
|
||||||
|
"value": "заявка",
|
||||||
|
"price": 2000,
|
||||||
|
"amount": 100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-23T01:51:19.814Z",
|
||||||
|
"updatedAt": "2024-01-23T01:51:19.814Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65afd0518507c326f5a2e59d",
|
||||||
|
"name": "Безлимит Опросов, Количество Заявок, 2024-01-23T14:42:25.093Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит Опросов",
|
||||||
|
"privilegeId": "quizUnlimTime",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 3400,
|
||||||
|
"amount": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Количество Заявок",
|
||||||
|
"privilegeId": "quizCnt",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество полных прохождений опросов",
|
||||||
|
"type": "count",
|
||||||
|
"value": "заявка",
|
||||||
|
"price": 2000,
|
||||||
|
"amount": 850
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-23T14:42:25.154Z",
|
||||||
|
"updatedAt": "2024-01-23T14:42:25.154Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65afd05e8507c326f5a2e5a2",
|
||||||
|
"name": "Безлимит Опросов, Количество Заявок, 2024-01-23T14:42:38.254Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит Опросов",
|
||||||
|
"privilegeId": "quizUnlimTime",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 3400,
|
||||||
|
"amount": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Количество Заявок",
|
||||||
|
"privilegeId": "quizCnt",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество полных прохождений опросов",
|
||||||
|
"type": "count",
|
||||||
|
"value": "заявка",
|
||||||
|
"price": 2000,
|
||||||
|
"amount": 850
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-23T14:42:38.338Z",
|
||||||
|
"updatedAt": "2024-01-23T14:42:38.339Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65afd0738507c326f5a2e5a7",
|
||||||
|
"name": "Безлимит Опросов, Количество Заявок, 2024-01-23T14:42:58.966Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит Опросов",
|
||||||
|
"privilegeId": "quizUnlimTime",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 3400,
|
||||||
|
"amount": 70
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Количество Заявок",
|
||||||
|
"privilegeId": "quizCnt",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество полных прохождений опросов",
|
||||||
|
"type": "count",
|
||||||
|
"value": "заявка",
|
||||||
|
"price": 2000,
|
||||||
|
"amount": 850
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-23T14:42:59.050Z",
|
||||||
|
"updatedAt": "2024-01-23T14:42:59.050Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65afd08a8507c326f5a2e5ac",
|
||||||
|
"name": "Безлимит Опросов, Количество Заявок, 2024-01-23T14:43:22.214Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит Опросов",
|
||||||
|
"privilegeId": "quizUnlimTime",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 3400,
|
||||||
|
"amount": 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Количество Заявок",
|
||||||
|
"privilegeId": "quizCnt",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество полных прохождений опросов",
|
||||||
|
"type": "count",
|
||||||
|
"value": "заявка",
|
||||||
|
"price": 2000,
|
||||||
|
"amount": 100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-23T14:43:22.284Z",
|
||||||
|
"updatedAt": "2024-01-23T14:43:22.284Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65b2d740c644401f2ff3ad26",
|
||||||
|
"name": "Безлимит Опросов, Количество Заявок, 2024-01-25T21:48:47.933Z",
|
||||||
|
"isCustom": true,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит Опросов",
|
||||||
|
"privilegeId": "quizUnlimTime",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 3400,
|
||||||
|
"amount": 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Количество Заявок",
|
||||||
|
"privilegeId": "quizCnt",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество полных прохождений опросов",
|
||||||
|
"type": "count",
|
||||||
|
"value": "заявка",
|
||||||
|
"price": 2000,
|
||||||
|
"amount": 3480
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-25T21:48:48.015Z",
|
||||||
|
"updatedAt": "2024-01-25T21:48:48.015Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "657b9b06215b615d2e35741a",
|
||||||
|
"name": "10 шаблонов",
|
||||||
|
"price": 20000,
|
||||||
|
"order": 1,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Количество Шаблонов",
|
||||||
|
"privilegeId": "templateCnt",
|
||||||
|
"serviceKey": "templategen",
|
||||||
|
"description": "Количество шаблонов, которые может сделать пользователь сервиса",
|
||||||
|
"type": "count",
|
||||||
|
"value": "шаблон",
|
||||||
|
"price": 1000,
|
||||||
|
"amount": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-14T19:22:07.206Z",
|
||||||
|
"updatedAt": "2024-01-14T19:22:07.206Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65a493550089bcd87ba53d4b",
|
||||||
|
"name": "10 заявок",
|
||||||
|
"description": "Полное прохождение 10 опросов респондентом",
|
||||||
|
"price": 0,
|
||||||
|
"order": 1,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Количество Заявок",
|
||||||
|
"privilegeId": "quizCnt",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество полных прохождений опросов",
|
||||||
|
"type": "count",
|
||||||
|
"value": "заявка",
|
||||||
|
"price": 2000,
|
||||||
|
"amount": 10
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-15T02:07:17.403Z",
|
||||||
|
"updatedAt": "2024-01-15T02:07:17.403Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65a493b60089bcd87ba53d5f",
|
||||||
|
"name": "1 день",
|
||||||
|
"description": "день безлимитного пользования сервисом",
|
||||||
|
"price": 10000,
|
||||||
|
"order": 1,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит Опросов",
|
||||||
|
"privilegeId": "quizUnlimTime",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 3400,
|
||||||
|
"amount": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-15T02:08:54.275Z",
|
||||||
|
"updatedAt": "2024-01-15T02:08:54.275Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65a493640089bcd87ba53d50",
|
||||||
|
"name": "100 заявок",
|
||||||
|
"description": "Полное прохождение 100 опросов респондентом",
|
||||||
|
"price": 0,
|
||||||
|
"order": 2,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Количество Заявок",
|
||||||
|
"privilegeId": "quizCnt",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество полных прохождений опросов",
|
||||||
|
"type": "count",
|
||||||
|
"value": "заявка",
|
||||||
|
"price": 2000,
|
||||||
|
"amount": 100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-15T02:07:32.444Z",
|
||||||
|
"updatedAt": "2024-01-15T02:07:32.444Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65a497890089bcd87ba53d64",
|
||||||
|
"name": "Месяц",
|
||||||
|
"description": "Месяц безлимитного пользования сервисом",
|
||||||
|
"price": 0,
|
||||||
|
"order": 2,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит Опросов",
|
||||||
|
"privilegeId": "quizUnlimTime",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 3400,
|
||||||
|
"amount": 30
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-15T02:25:13.366Z",
|
||||||
|
"updatedAt": "2024-01-15T02:25:13.366Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65a493740089bcd87ba53d55",
|
||||||
|
"name": "1000 заявок",
|
||||||
|
"description": "Полное прохождение 1000 опросов респондентом",
|
||||||
|
"price": 0,
|
||||||
|
"order": 3,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Количество Заявок",
|
||||||
|
"privilegeId": "quizCnt",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество полных прохождений опросов",
|
||||||
|
"type": "count",
|
||||||
|
"value": "заявка",
|
||||||
|
"price": 2000,
|
||||||
|
"amount": 1000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-15T02:07:48.095Z",
|
||||||
|
"updatedAt": "2024-01-15T02:07:48.095Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65a4987e0089bcd87ba53d75",
|
||||||
|
"name": "3 Месяца",
|
||||||
|
"description": "3 Месяца безлимитного пользования сервисом",
|
||||||
|
"price": 0,
|
||||||
|
"order": 3,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит Опросов",
|
||||||
|
"privilegeId": "quizUnlimTime",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 3400,
|
||||||
|
"amount": 90
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-15T02:29:18.577Z",
|
||||||
|
"updatedAt": "2024-01-15T02:29:18.577Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65a498cc0089bcd87ba53d92",
|
||||||
|
"name": "Год",
|
||||||
|
"description": "Год безлимитного пользования сервисом",
|
||||||
|
"price": 0,
|
||||||
|
"order": 3,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит Опросов",
|
||||||
|
"privilegeId": "quizUnlimTime",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 3400,
|
||||||
|
"amount": 365
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-15T02:30:36.131Z",
|
||||||
|
"updatedAt": "2024-01-15T02:30:36.131Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65a493830089bcd87ba53d5a",
|
||||||
|
"name": "10000 заявок",
|
||||||
|
"description": "Полное прохождение 10000 опросов респондентом",
|
||||||
|
"price": 0,
|
||||||
|
"order": 4,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Количество Заявок",
|
||||||
|
"privilegeId": "quizCnt",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество полных прохождений опросов",
|
||||||
|
"type": "count",
|
||||||
|
"value": "заявка",
|
||||||
|
"price": 2000,
|
||||||
|
"amount": 10000
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-15T02:08:03.341Z",
|
||||||
|
"updatedAt": "2024-01-15T02:08:03.341Z"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"_id": "65a498f80089bcd87ba53d97",
|
||||||
|
"name": "3 Года",
|
||||||
|
"description": "3 Года безлимитного пользования сервисом",
|
||||||
|
"price": 0,
|
||||||
|
"order": 4,
|
||||||
|
"isCustom": false,
|
||||||
|
"privileges": [
|
||||||
|
{
|
||||||
|
"name": "Безлимит Опросов",
|
||||||
|
"privilegeId": "quizUnlimTime",
|
||||||
|
"serviceKey": "squiz",
|
||||||
|
"description": "Количество дней, в течении которых пользование сервисом безлимитно",
|
||||||
|
"type": "day",
|
||||||
|
"value": "день",
|
||||||
|
"price": 3400,
|
||||||
|
"amount": 1095
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"isDeleted": false,
|
||||||
|
"createdAt": "2024-01-15T02:31:20.448Z",
|
||||||
|
"updatedAt": "2024-01-15T02:31:20.448Z"
|
||||||
|
}
|
||||||
|
];
|
@ -1,40 +1,33 @@
|
|||||||
import { Discount, Tariff, findDiscountFactor } from "@frontend/kitui"
|
import { Discount, Tariff, findDiscountFactor } from "@frontend/kitui";
|
||||||
import { calcCart } from "./calcCart/calcCart"
|
import { calcCart } from "./calcCart/calcCart";
|
||||||
|
|
||||||
export function calcIndividualTariffPrices(
|
export function calcIndividualTariffPrices(
|
||||||
tariff: Tariff,
|
targetTariff: Tariff,
|
||||||
discounts: Discount[],
|
discounts: Discount[],
|
||||||
purchasesAmount: number,
|
purchasesAmount: number,
|
||||||
currentTariffs: Tariff[],
|
currentTariffs: Tariff[],
|
||||||
isUserNko?: boolean,
|
isUserNko?: boolean,
|
||||||
): {
|
): {
|
||||||
priceBeforeDiscounts: number;
|
priceBeforeDiscounts: number;
|
||||||
priceAfterDiscounts: number;
|
priceAfterDiscounts: number;
|
||||||
} {
|
} {
|
||||||
const priceBeforeDiscounts =
|
const priceBeforeDiscounts = targetTariff.price || targetTariff.privileges.reduce(
|
||||||
tariff.price || tariff.privileges.reduce((sum, privilege) => sum + privilege.amount * privilege.price, 0)
|
(sum, privilege) => sum + privilege.amount * privilege.price,
|
||||||
let priceAfterDiscounts = 0
|
0
|
||||||
|
);
|
||||||
|
|
||||||
const cart = calcCart([...currentTariffs, tariff], discounts, purchasesAmount, isUserNko)
|
const cart = calcCart([...currentTariffs, targetTariff], discounts, purchasesAmount, isUserNko);
|
||||||
if (cart.allAppliedDiscounts[0]?.Target.Overhelm) return {priceBeforeDiscounts: priceBeforeDiscounts, priceAfterDiscounts: priceBeforeDiscounts * cart.allAppliedDiscounts[0].Target.Factor }
|
|
||||||
cart.services.forEach(s => {
|
|
||||||
if (s.serviceKey === tariff.privileges[0].serviceKey) {
|
|
||||||
let processed = false
|
|
||||||
s.tariffs.forEach(t => {
|
|
||||||
if (t.id === tariff._id && !processed) {
|
|
||||||
processed = true
|
|
||||||
t.privileges.forEach(p => priceAfterDiscounts+=p.price)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
priceAfterDiscounts*=findDiscountFactor(cart.appliedLoyaltyDiscount)
|
|
||||||
priceAfterDiscounts*=findDiscountFactor(cart.appliedCartPurchasesDiscount)
|
|
||||||
|
|
||||||
if (priceAfterDiscounts === 0) priceAfterDiscounts = cart.priceAfterDiscounts
|
const tariffCartData = cart.services.flatMap(service => service.tariffs).find(tariff => tariff.id === targetTariff._id);
|
||||||
// cart.allAppliedDiscounts.forEach((discount) => {
|
if (!tariffCartData) throw new Error(`Target tariff ${targetTariff._id} not found in cart`);
|
||||||
// priceAfterDiscounts *= findDiscountFactor(discount)
|
|
||||||
// })
|
if (cart.allAppliedDiscounts[0]?.Target.Overhelm) return {
|
||||||
//priceAfterDiscounts = cart.priceAfterDiscounts
|
priceBeforeDiscounts: priceBeforeDiscounts,
|
||||||
return { priceBeforeDiscounts, priceAfterDiscounts }
|
priceAfterDiscounts: priceBeforeDiscounts * cart.allAppliedDiscounts[0].Target.Factor
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
priceBeforeDiscounts,
|
||||||
|
priceAfterDiscounts: tariffCartData.price,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ interface ComponentError {
|
|||||||
timestamp: number;
|
timestamp: number;
|
||||||
message: string;
|
message: string;
|
||||||
callStack: string | undefined;
|
callStack: string | undefined;
|
||||||
componentStack: string;
|
componentStack: string | null | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleComponentError(error: Error, info: ErrorInfo) {
|
export function handleComponentError(error: Error, info: ErrorInfo) {
|
||||||
|
@ -1,85 +1,20 @@
|
|||||||
import { Tariff, devlog } from "@frontend/kitui"
|
import { useDiscountStore } from "@root/stores/discounts";
|
||||||
import { getTariffById } from "@root/api/tariff"
|
import { useUserStore } from "@root/stores/user";
|
||||||
import {
|
import { useMemo } from "react";
|
||||||
addCartTariffs,
|
import { calcCart } from "../calcCart/calcCart";
|
||||||
removeMissingCartTariffs,
|
import { useCartTariffs } from "./useCartTariffs";
|
||||||
setCartTariffStatus,
|
import { CartData } from "@frontend/kitui";
|
||||||
setNotEnoughMoneyAmount,
|
|
||||||
useCartStore,
|
|
||||||
} from "@root/stores/cart"
|
|
||||||
import { calcCart } from "@root/utils/calcCart/calcCart"
|
|
||||||
import { useDiscountStore } from "@root/stores/discounts"
|
|
||||||
import { useTariffStore } from "@root/stores/tariffs"
|
|
||||||
import { removeTariffFromCart, useUserStore } from "@root/stores/user"
|
|
||||||
import { useEffect } from "react"
|
|
||||||
|
|
||||||
|
|
||||||
export function useCart() {
|
export function useCart(): CartData {
|
||||||
const tariffs = useTariffStore((state) => state.tariffs)
|
const cartTariffs = useCartTariffs();
|
||||||
const cartTariffMap = useCartStore((state) => state.cartTariffMap)
|
const discounts = useDiscountStore((state) => state.discounts);
|
||||||
const cartTariffIds = useUserStore((state) => state.userAccount?.cart)
|
const purchasesAmount = useUserStore((state) => state.userAccount?.wallet.spent) ?? 0;
|
||||||
const cart = useCartStore((state) => state.cart)
|
const isUserNko = useUserStore(state => state.userAccount?.status) === "nko";
|
||||||
const discounts = useDiscountStore((state) => state.discounts)
|
|
||||||
const purchasesAmount =
|
|
||||||
useUserStore((state) => state.userAccount?.wallet.spent) ?? 0
|
|
||||||
const isUserNko = useUserStore(state => state.userAccount?.status) === "nko"
|
|
||||||
|
|
||||||
useEffect(() => {
|
const cart = useMemo(() => {
|
||||||
function addTariffsToCart() {
|
return calcCart(cartTariffs ?? [], discounts, purchasesAmount, isUserNko);
|
||||||
const knownTariffs: Tariff[] = []
|
}, [cartTariffs, discounts, purchasesAmount, isUserNko]);
|
||||||
setNotEnoughMoneyAmount(0);
|
|
||||||
|
|
||||||
cartTariffIds?.forEach(async (tariffId) => {
|
return cart;
|
||||||
if (typeof cartTariffMap[tariffId] === "object") return
|
|
||||||
|
|
||||||
const tariff = tariffs.find((tariff) => tariff._id === tariffId)
|
|
||||||
if (tariff) return knownTariffs.push(tariff)
|
|
||||||
|
|
||||||
if (!cartTariffMap[tariffId]) {
|
|
||||||
setCartTariffStatus(tariffId, "loading")
|
|
||||||
|
|
||||||
const [tariffByIdResponse, tariffByIdError, tariffByIdStatus] =
|
|
||||||
await getTariffById(tariffId)
|
|
||||||
|
|
||||||
if (tariffByIdError) {
|
|
||||||
devlog(tariffByIdError)
|
|
||||||
setCartTariffStatus(tariffId, "not found")
|
|
||||||
|
|
||||||
if (tariffByIdStatus === 404) {
|
|
||||||
try {
|
|
||||||
await removeTariffFromCart(tariffId)
|
|
||||||
|
|
||||||
devlog(
|
|
||||||
`Unexistant tariff with id ${tariffId} deleted from cart`
|
|
||||||
)
|
|
||||||
} catch (error) {
|
|
||||||
devlog("Error deleting unexistant tariff from cart", error)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tariffByIdResponse) {
|
|
||||||
addCartTariffs([tariffByIdResponse], discounts, purchasesAmount, isUserNko)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (knownTariffs.length > 0)
|
|
||||||
addCartTariffs(knownTariffs, discounts, purchasesAmount, isUserNko)
|
|
||||||
}
|
|
||||||
|
|
||||||
addTariffsToCart()
|
|
||||||
}, [cartTariffIds, cartTariffMap, discounts, isUserNko, purchasesAmount, tariffs])
|
|
||||||
|
|
||||||
useEffect(
|
|
||||||
function cleanUpCart() {
|
|
||||||
if (cartTariffIds)
|
|
||||||
removeMissingCartTariffs(cartTariffIds, discounts, purchasesAmount, isUserNko)
|
|
||||||
},
|
|
||||||
[cartTariffIds, discounts, isUserNko, purchasesAmount]
|
|
||||||
)
|
|
||||||
const currentTariffs = Object.values(cartTariffMap).filter((tariff): tariff is Tariff => typeof tariff === "object");
|
|
||||||
return calcCart(currentTariffs, discounts,purchasesAmount,isUserNko)
|
|
||||||
}
|
}
|
||||||
|
17
src/utils/hooks/useCartTariffs.ts
Normal file
17
src/utils/hooks/useCartTariffs.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { getTariffArray } from "@root/api/tariff";
|
||||||
|
import { useUserStore } from "@root/stores/user";
|
||||||
|
import useSWR from "swr";
|
||||||
|
|
||||||
|
|
||||||
|
export function useCartTariffs() {
|
||||||
|
const cartTariffIds = useUserStore((state) => state.userAccount?.cart);
|
||||||
|
const { data } = useSWR(
|
||||||
|
["cartTariffs", cartTariffIds],
|
||||||
|
key => getTariffArray(key[1]),
|
||||||
|
{
|
||||||
|
keepPreviousData: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extends": "./tsconfig.extend.json",
|
"extends": "./tsconfig.extend.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "ESNext",
|
||||||
"lib": ["es5", "dom", "dom.iterable", "esnext"],
|
"lib": ["es5", "dom", "dom.iterable", "esnext"],
|
||||||
"types": ["node"],
|
"types": ["node"],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
|
Loading…
Reference in New Issue
Block a user