Merge branch 'discounts' into 'dev'

add discount creating

See merge request frontend/admin!23
This commit is contained in:
Mikhail 2023-06-30 19:41:33 +00:00
commit a815229da0
16 changed files with 653 additions and 423 deletions

@ -6,16 +6,6 @@
"src": "favicon.ico", "src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16", "sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon" "type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
} }
], ],
"start_url": ".", "start_url": ".",

106
src/api/discounts.ts Normal file

@ -0,0 +1,106 @@
import { CreateDiscountBody, Discount, DiscountType } from "@root/model/discount";
import { ServiceType } from "@root/model/tariff";
import { authStore } from "@root/stores/auth";
const makeRequest = authStore.getState().makeRequest;
type CreateDiscount = (props: {
purchasesAmount: number;
cartPurchasesAmount: number;
discountMinValue: number;
discountFactor: number;
discountDescription: string;
discountName: string;
/** ISO string */
startDate: string;
/** ISO string */
endDate: string;
serviceType: ServiceType;
discountType: DiscountType;
privilegeId: string;
}) => Promise<Discount>;
export const createDiscountJSON: CreateDiscount = ({
endDate,
startDate,
discountName,
cartPurchasesAmount,
discountDescription,
discountFactor,
discountMinValue,
purchasesAmount,
serviceType,
discountType,
privilegeId,
}) => {
const discount: CreateDiscountBody = {
Name: discountName,
Layer: 1,
Description: discountDescription,
Condition: {
Period: {
From: startDate,
To: endDate,
},
User: "",
UserType: "",
Coupon: "",
Usage: 0,
PurchasesAmount: 0,
CartPurchasesAmount: 0,
Product: "",
Term: 0,
PriceFrom: 0,
Group: "",
},
Target: {
Factor: discountFactor,
TargetScope: "Sum",
Overhelm: false,
TargetGroup: "",
Products: [{
ID: "",
Factor: 0,
Overhelm: false,
}],
},
};
switch (discountType) {
case "privilege":
discount.Layer = 1;
discount.Condition.Product = privilegeId;
discount.Condition.Term = discountMinValue;
discount.Target.Products = [{
Factor: discountFactor,
ID: privilegeId,
Overhelm: false,
}];
break;
case "service":
discount.Layer = 2;
discount.Condition.PriceFrom = discountMinValue;
discount.Condition.Group = serviceType;
discount.Target.TargetGroup = serviceType;
break;
case "cartPurchasesAmount":
discount.Layer = 3;
discount.Condition.CartPurchasesAmount = cartPurchasesAmount;
break;
case "purchasesAmount":
discount.Layer = 4;
discount.Condition.PurchasesAmount = purchasesAmount;
break;
}
console.log("Constructed discount", discount);
return makeRequest<CreateDiscountBody, Discount>({
url: "https://admin.pena.digital/price/discount",
method: "post",
useToken: true,
bearer: true,
body: discount,
});
};

@ -19,11 +19,12 @@ import { useCartStore } from "@root/stores/cart";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { GridSelectionModel } from "@mui/x-data-grid"; import { GridSelectionModel } from "@mui/x-data-grid";
import { testUser } from "@root/stores/mocks/user"; import { testUser } from "@root/stores/mocks/user";
import { useDiscountStore } from "@root/stores/discounts"; import { useMockDiscountStore } from "@root/stores/discounts";
import { calcCartData, createCartItem, findDiscountFactor, formatDiscountFactor } from "./calc"; import { calcCartData, createCartItem, findDiscountFactor, formatDiscountFactor } from "./calc";
import { useTariffStore } from "@root/stores/tariffs"; import { useTariffStore } from "@root/stores/tariffs";
import { AnyDiscount, CartItemTotal } from "@root/model/cart"; import { AnyDiscount, CartItemTotal } from "@root/model/cart";
import { findPrivilegeById } from "@root/stores/privileges"; import { findPrivilegeById } from "@root/stores/privileges";
import { Privilege } from "@root/model/tariff";
interface Props { interface Props {
selectedTariffs: GridSelectionModel; selectedTariffs: GridSelectionModel;
@ -46,7 +47,7 @@ interface MergedTariff {
} }
export default function Cart({ selectedTariffs }: Props) { export default function Cart({ selectedTariffs }: Props) {
const discounts = useDiscountStore((store) => store.discounts); const discounts = useMockDiscountStore((store) => store.discounts);
const cartTotal = useCartStore((state) => state.cartTotal); const cartTotal = useCartStore((state) => state.cartTotal);
const setCartTotal = useCartStore((store) => store.setCartTotal); const setCartTotal = useCartStore((store) => store.setCartTotal);
const [couponField, setCouponField] = useState<string>(""); const [couponField, setCouponField] = useState<string>("");

@ -10,9 +10,9 @@ import {
ServiceDiscount, ServiceDiscount,
UserDiscount, UserDiscount,
} from "@root/model/cart"; } from "@root/model/cart";
import { Tariff_BACKEND } from "@root/model/tariff";
import { User } from "../../model/user"; import { User } from "../../model/user";
import { findPrivilegeById } from "@root/stores/privileges"; import { findPrivilegeById } from "@root/stores/privileges";
import { SERVICE_LIST, ServiceType, Tariff } from "@root/model/tariff";
export function calcCartData({ export function calcCartData({
user, user,

@ -1,3 +1,6 @@
import { ServiceType } from "./tariff";
export type Discount = { export type Discount = {
ID: string; ID: string;
Name: string; Name: string;
@ -39,6 +42,50 @@ export type Discount = {
Deprecated: boolean; Deprecated: boolean;
}; };
export type DiscountData = { export type GetDiscountResponse = {
Discounts: Discount[]; Discounts: Discount[];
}; };
export const discountTypes = {
"purchasesAmount": "Лояльность",
"cartPurchasesAmount": "Корзина",
"service": "Сервис",
"privilege": "Товар",
} as const;
export type DiscountType = keyof typeof discountTypes;
export type CreateDiscountBody = {
Name: string;
Layer: 1 | 2 | 3 | 4;
Description: string;
Condition: {
Period: {
/** ISO string */
From: string;
/** ISO string */
To: string;
};
User: string;
UserType: string;
Coupon: string;
PurchasesAmount: number;
CartPurchasesAmount: number;
Product: string;
Term: number;
Usage: number;
PriceFrom: number;
Group: ServiceType | "";
};
Target: {
Factor: number;
TargetScope: "Sum" | "Group" | "Each";
Overhelm: boolean;
TargetGroup: ServiceType | "";
Products: [{
ID: string;
Factor: number;
Overhelm: false;
}];
};
};

21
src/model/privilege.ts Normal file

@ -0,0 +1,21 @@
export interface RealPrivilege {
_id: string;
name: string;
privilegeId: string;
serviceKey: string;
description: string;
type: "day" | "count";
value: PrivilegeValueType;
price: number;
updatedAt?: string;
isDeleted?: boolean;
createdAt?: string;
};
export type PrivilegeMap = Record<string, RealPrivilege[]>;
export type PrivilegeValueType = "шаблон" | "день" | "МБ";
export type PrivilegeWithAmount = Omit<RealPrivilege, "_id"> & { amount: number; };
export type PrivilegeWithoutPrice = Omit<PrivilegeWithAmount, "price">;

@ -38,13 +38,36 @@ export type Tariff_BACKEND = {
privilegies: Privilege_BACKEND[], privilegies: Privilege_BACKEND[],
isDeleted: boolean, isDeleted: boolean,
createdAt: string, createdAt: string,
updatedAt: string updatedAt: string;
} };
export type Tariff_FRONTEND = { export type Tariff_FRONTEND = {
id: string, id: string,
name: string, name: string,
amount:number, amount: number,
isFront: boolean,
privilegeId: string, privilegeId: string,
customPricePerUnit: number customPricePerUnit?: number;
};
/** @deprecated */
export interface Privilege {
serviceKey: ServiceType;
name: PrivilegeType;
privilegeId: string;
description: string;
/** Единица измерения привелегии: время в днях/кол-во */
type: "day" | "count";
/** Стоимость одной единицы привелегии */
price: number;
}
/** @deprecated */
export interface Tariff {
id: string;
name: string;
privilegeId: string;
/** Количество единиц привелегии */
amount: number;
/** Кастомная цена, если есть, то используется вместо privilege.price */
customPricePerUnit?: number;
isFront?: boolean;
} }

@ -4,34 +4,29 @@ import Select, { SelectChangeEvent } from "@mui/material/Select";
import { useState } from "react"; import { useState } from "react";
import { SERVICE_LIST, ServiceType } from "@root/model/tariff"; import { SERVICE_LIST, ServiceType } from "@root/model/tariff";
import { CustomTextField } from "@root/kitUI/CustomTextField"; import { CustomTextField } from "@root/kitUI/CustomTextField";
import { usePrivilegeStore } from "@root/stores/privileges"; import { addRealPrivileges, useRealPrivilegeStore } from "@root/stores/privileges";
import { AnyDiscount } from "@root/model/cart";
import { nanoid } from "nanoid";
import { addDiscounts } from "@root/stores/discounts"; import { addDiscounts } from "@root/stores/discounts";
import { enqueueSnackbar } from "notistack"; import { enqueueSnackbar } from "notistack";
import { DiscountType, discountTypes } from "@root/model/discount";
import { createDiscountJSON } from "@root/api/discounts";
import usePrivileges from "@root/utils/hooks/usePrivileges";
const discountTypes = {
"Лояльность": "purchasesAmount",
"Корзина": "cartPurchasesAmount",
"Сервис": "service",
"Товар": "privilege",
} as const;
type DiscountType = keyof typeof discountTypes;
export default function CreateDiscount() { export default function CreateDiscount() {
const theme = useTheme(); const theme = useTheme();
const privileges = usePrivilegeStore(state => state.privileges); const privileges = useRealPrivilegeStore(state => state.privileges);
const [serviceType, setServiceType] = useState<ServiceType>("templategen"); const [serviceType, setServiceType] = useState<ServiceType>("templategen");
const [discountType, setDiscountType] = useState<DiscountType>("Лояльность"); const [discountType, setDiscountType] = useState<DiscountType>("purchasesAmount");
const [discountNameField, setDiscountNameField] = useState<string>(""); const [discountNameField, setDiscountNameField] = useState<string>("");
const [discountDescription, setDiscountDescription] = useState<string>(""); const [discountDescriptionField, setDiscountDescriptionField] = useState<string>("");
const [privilegeIdField, setPrivilegeIdField] = useState<string | "">(""); const [privilegeIdField, setPrivilegeIdField] = useState<string | "">("");
const [discountFactorField, setDiscountFactorField] = useState<string>("0"); const [discountFactorField, setDiscountFactorField] = useState<string>("0");
const [purchasesAmountField, setPurchasesAmountField] = useState<string>("0"); const [purchasesAmountField, setPurchasesAmountField] = useState<string>("0");
const [cartPurchasesAmountField, setCartPurchasesAmountField] = useState<string>("0"); const [cartPurchasesAmountField, setCartPurchasesAmountField] = useState<string>("0");
const [discountMinValueField, setDiscountMinValueField] = useState<string>("0"); const [discountMinValueField, setDiscountMinValueField] = useState<string>("0");
usePrivileges({ onNewPrivileges: addRealPrivileges });
const handleDiscountTypeChange = (event: React.ChangeEvent<HTMLInputElement>) => { const handleDiscountTypeChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setDiscountType(event.target.value as DiscountType); setDiscountType(event.target.value as DiscountType);
}; };
@ -40,9 +35,9 @@ export default function CreateDiscount() {
setServiceType(event.target.value as ServiceType); setServiceType(event.target.value as ServiceType);
}; };
function handleCreateDiscount() { async function handleCreateDiscount() {
const purchasesAmount = parseFloat(purchasesAmountField.replace(",", ".")); const purchasesAmount = parseFloat(purchasesAmountField.replace(",", "."));
const discountFactor = 1 - parseFloat(discountFactorField.replace(",", ".")) / 100; const discountFactor = (100 - parseFloat(discountFactorField.replace(",", "."))) / 100;
const cartPurchasesAmount = parseFloat(cartPurchasesAmountField.replace(",", ".")); const cartPurchasesAmount = parseFloat(cartPurchasesAmountField.replace(",", "."));
const discountMinValue = parseFloat(discountMinValueField.replace(",", ".")); const discountMinValue = parseFloat(discountMinValueField.replace(",", "."));
@ -50,82 +45,28 @@ export default function CreateDiscount() {
if (!isFinite(discountFactor)) return enqueueSnackbar("Поле discountFactor не число"); if (!isFinite(discountFactor)) return enqueueSnackbar("Поле discountFactor не число");
if (!isFinite(cartPurchasesAmount)) return enqueueSnackbar("Поле cartPurchasesAmount не число"); if (!isFinite(cartPurchasesAmount)) return enqueueSnackbar("Поле cartPurchasesAmount не число");
if (!isFinite(discountMinValue)) return enqueueSnackbar("Поле discountMinValue не число"); if (!isFinite(discountMinValue)) return enqueueSnackbar("Поле discountMinValue не число");
if (discountType === "privilege" && !privilegeIdField) return enqueueSnackbar("Привилегия не выбрана");
let discount: AnyDiscount; try {
switch (discountType) { const createdDiscount = await createDiscountJSON({
case "Лояльность": { cartPurchasesAmount,
discount = { discountFactor,
_id: nanoid(6), discountMinValue,
name: discountNameField, purchasesAmount,
description: discountDescription, discountDescription: discountDescriptionField,
disabled: false, discountName: discountNameField,
conditionType: "purchasesAmount", startDate: new Date().toISOString(),
condition: { endDate: new Date(Date.now() + 1000 * 3600 * 24 * 30).toISOString(),
purchasesAmount: purchasesAmount, serviceType,
}, discountType,
factor: discountFactor,
};
break;
}
case "Корзина": {
discount = {
_id: nanoid(6),
name: discountNameField,
description: discountDescription,
disabled: false,
conditionType: "cartPurchasesAmount",
condition: {
cartPurchasesAmount: cartPurchasesAmount,
},
factor: discountFactor,
};
break;
}
case "Сервис": {
discount = {
_id: nanoid(6),
name: discountNameField,
description: discountDescription,
disabled: false,
conditionType: "service",
condition: {
service: {
id: serviceType,
value: discountMinValue,
},
},
target: {
service: serviceType,
factor: discountFactor,
},
};
break;
}
case "Товар": {
discount = {
_id: nanoid(6),
name: discountNameField,
description: discountDescription,
disabled: false,
conditionType: "privilege",
condition: {
privilege: {
id: privilegeIdField,
value: discountMinValue,
},
},
target: {
products: [{
privilegeId: privilegeIdField, privilegeId: privilegeIdField,
factor: discountFactor, });
}],
},
};
break;
}
}
addDiscounts([discount]); addDiscounts([createdDiscount]);
} catch (error) {
console.log("Error creating discount", error);
enqueueSnackbar("Ошибка при создании скидки");
}
} }
return ( return (
@ -149,8 +90,8 @@ export default function CreateDiscount() {
<CustomTextField <CustomTextField
id="discount-desc" id="discount-desc"
label="Описание" label="Описание"
value={discountDescription} value={discountDescriptionField}
onChange={e => setDiscountDescription(e.target.value)} onChange={e => setDiscountDescriptionField(e.target.value)}
/> />
<Typography <Typography
variant="h4" variant="h4"
@ -187,11 +128,16 @@ export default function CreateDiscount() {
onChange={handleDiscountTypeChange} onChange={handleDiscountTypeChange}
> >
{Object.keys(discountTypes).map(type => {Object.keys(discountTypes).map(type =>
<FormControlLabel key={type} value={type} control={<Radio color="secondary" />} label={type} /> <FormControlLabel
key={type}
value={type}
control={<Radio color="secondary" />}
label={discountTypes[type as DiscountType]}
/>
)} )}
</RadioGroup> </RadioGroup>
</FormControl> </FormControl>
{discountType === "Лояльность" && {discountType === "purchasesAmount" &&
<CustomTextField <CustomTextField
id="discount-purchases" id="discount-purchases"
label="Внесено больше" label="Внесено больше"
@ -203,7 +149,7 @@ export default function CreateDiscount() {
onChange={e => setPurchasesAmountField(e.target.value)} onChange={e => setPurchasesAmountField(e.target.value)}
/> />
} }
{discountType === "Корзина" && {discountType === "cartPurchasesAmount" &&
<CustomTextField <CustomTextField
id="discount-cart-purchases" id="discount-cart-purchases"
label="Объем в корзине" label="Объем в корзине"
@ -215,7 +161,7 @@ export default function CreateDiscount() {
onChange={e => setCartPurchasesAmountField(e.target.value)} onChange={e => setCartPurchasesAmountField(e.target.value)}
/> />
} }
{discountType === "Сервис" && {discountType === "service" &&
<> <>
<Select <Select
labelId="discount-service-label" labelId="discount-service-label"
@ -249,7 +195,7 @@ export default function CreateDiscount() {
/> />
</> </>
} }
{discountType === "Товар" && {discountType === "privilege" &&
<> <>
<FormControl <FormControl
fullWidth fullWidth
@ -330,6 +276,6 @@ export default function CreateDiscount() {
onClick={handleCreateDiscount} onClick={handleCreateDiscount}
>Cоздать</Button> >Cоздать</Button>
</Box> </Box>
</Box > </Box>
); );
} }

@ -1,17 +1,9 @@
import { useEffect, useState } from "react";
import { enqueueSnackbar } from "notistack";
import { Box, Button, styled, useTheme } from "@mui/material"; import { Box, Button, styled, useTheme } from "@mui/material";
import { DataGrid, GridColDef, GridRowsProp, GridToolbar } from "@mui/x-data-grid"; import { DataGrid, GridColDef, GridRowsProp, GridToolbar } from "@mui/x-data-grid";
import { findDiscountFactor, formatDiscountFactor } from "@root/kitUI/Cart/calc"; import { findDiscountFactor, formatDiscountFactor } from "@root/kitUI/Cart/calc";
import { import { activateMockDiscounts, addDiscounts, deactivateMockDiscounts, setMockSelectedDiscountIds, useDiscountStore, useMockDiscountStore, } from "@root/stores/discounts";
activateDiscounts, import useDiscounts from "@root/utils/hooks/useDiscounts";
deactivateDiscounts,
setSelectedDiscountIds,
useDiscountStore,
} from "@root/stores/discounts";
import axios from "axios";
import type { DiscountData } from "@root/model/discount";
const BoxButton = styled("div")(({ theme }) => ({ const BoxButton = styled("div")(({ theme }) => ({
[theme.breakpoints.down(400)]: { [theme.breakpoints.down(400)]: {
@ -66,31 +58,11 @@ const columns: GridColDef[] = [
export default function DiscountDataGrid() { export default function DiscountDataGrid() {
const theme = useTheme(); const theme = useTheme();
const exampleDiscounts = useDiscountStore((state) => state.discounts); const exampleDiscounts = useMockDiscountStore((state) => state.discounts);
const selectedDiscountIds = useDiscountStore((state) => state.selectedDiscountIds); const selectedDiscountIds = useMockDiscountStore((state) => state.selectedDiscountIds);
const realDiscounts = useDiscountStore(state => state.discounts);
const [discount, setDiscount] = useState<DiscountData>(); useDiscounts({ onNewDiscounts: addDiscounts });
const mergeDiscount = [...(discount?.Discounts ?? []), ...exampleDiscounts];
console.log(mergeDiscount);
useEffect(() => {
const axiosDiscount = async () => {
try {
const { data } = await axios({
method: "get",
url: "https://admin.pena.digital/price/discounts",
});
setDiscount(data);
console.log(data);
} catch (error) {
enqueueSnackbar("Ошибка получения скидок");
}
};
axiosDiscount();
}, []);
const discountsGridData: GridRowsProp = exampleDiscounts.map((discount) => { const discountsGridData: GridRowsProp = exampleDiscounts.map((discount) => {
const value = const value =
@ -119,7 +91,7 @@ export default function DiscountDataGrid() {
rows={discountsGridData} rows={discountsGridData}
columns={columns} columns={columns}
selectionModel={selectedDiscountIds} selectionModel={selectedDiscountIds}
onSelectionModelChange={setSelectedDiscountIds} onSelectionModelChange={setMockSelectedDiscountIds}
sx={{ sx={{
color: theme.palette.secondary.main, color: theme.palette.secondary.main,
"& .MuiDataGrid-iconSeparator": { "& .MuiDataGrid-iconSeparator": {
@ -165,7 +137,7 @@ export default function DiscountDataGrid() {
> >
<Button <Button
variant="contained" variant="contained"
onClick={deactivateDiscounts} onClick={deactivateMockDiscounts}
sx={{ sx={{
backgroundColor: theme.palette.menu.main, backgroundColor: theme.palette.menu.main,
width: "200px", width: "200px",
@ -182,7 +154,7 @@ export default function DiscountDataGrid() {
</Button> </Button>
<Button <Button
variant="contained" variant="contained"
onClick={activateDiscounts} onClick={activateMockDiscounts}
sx={{ sx={{
backgroundColor: theme.palette.menu.main, backgroundColor: theme.palette.menu.main,
width: "200px", width: "200px",

@ -1,3 +1,4 @@
// @ts-nocheck
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
@ -48,6 +49,7 @@ interface Props {
getTariffs: () => void getTariffs: () => void
} }
/** @deprecated */
export default function EditModal({tariff, getTariffs}:Props) { export default function EditModal({tariff, getTariffs}:Props) {
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);

@ -1,3 +1,4 @@
// @ts-nocheck
import React from "react"; import React from "react";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { GridColDef, GridSelectionModel, GridToolbar } from "@mui/x-data-grid"; import { GridColDef, GridSelectionModel, GridToolbar } from "@mui/x-data-grid";
@ -24,6 +25,7 @@ interface Props {
getTariffs: () => void; getTariffs: () => void;
} }
/** @deprecated */
export default function TariffsDG({ selectedTariffs, handleSelectionChange, getTariffs }: Props) { export default function TariffsDG({ selectedTariffs, handleSelectionChange, getTariffs }: Props) {
const { token } = authStore(); const { token } = authStore();

1
src/react-app-env.d.ts vendored Normal file

@ -0,0 +1 @@
/// <reference types="react-scripts" />

@ -3,14 +3,40 @@ import { AnyDiscount } from "@root/model/cart";
import { create } from "zustand"; import { create } from "zustand";
import { devtools } from "zustand/middleware"; import { devtools } from "zustand/middleware";
import { exampleCartValues } from "./mocks/exampleCartValues"; import { exampleCartValues } from "./mocks/exampleCartValues";
import { Discount } from "@root/model/discount";
interface DiscountStore { interface DiscountStore {
discounts: AnyDiscount[]; discounts: Discount[];
selectedDiscountIds: GridSelectionModel, selectedDiscountIds: GridSelectionModel,
} }
export const useDiscountStore = create<DiscountStore>()( export const useDiscountStore = create<DiscountStore>()(
devtools(
(set, get) => ({
discounts: [],
selectedDiscountIds: [],
}),
{
name: "Real discount store",
enabled: process.env.NODE_ENV === "development"
}
)
);
export const addDiscounts = (newDiscounts: DiscountStore["discounts"]) => useDiscountStore.setState(state => ({ discounts: [...state.discounts, ...newDiscounts] }));
export const setSelectedDiscountIds = (selectedDiscountIds: DiscountStore["selectedDiscountIds"]) => useDiscountStore.setState({ selectedDiscountIds });
/** @deprecated */
interface MockDiscountStore {
discounts: AnyDiscount[];
selectedDiscountIds: GridSelectionModel,
}
/** @deprecated */
export const useMockDiscountStore = create<MockDiscountStore>()(
devtools( devtools(
(set, get) => ({ (set, get) => ({
discounts: exampleCartValues.discounts, discounts: exampleCartValues.discounts,
@ -22,11 +48,14 @@ export const useDiscountStore = create<DiscountStore>()(
) )
); );
export const addDiscounts = (newDiscounts: AnyDiscount[]) => useDiscountStore.setState(state => ({ discounts: [...state.discounts, ...newDiscounts] })); /** @deprecated */
export const addMockDiscounts = (newDiscounts: AnyDiscount[]) => useMockDiscountStore.setState(state => ({ discounts: [...state.discounts, ...newDiscounts] }));
export const setSelectedDiscountIds = (selectedDiscountIds: DiscountStore["selectedDiscountIds"]) => useDiscountStore.setState({ selectedDiscountIds }); /** @deprecated */
export const setMockSelectedDiscountIds = (selectedDiscountIds: MockDiscountStore["selectedDiscountIds"]) => useMockDiscountStore.setState({ selectedDiscountIds });
export const activateDiscounts = () => useDiscountStore.setState(state => { /** @deprecated */
export const activateMockDiscounts = () => useMockDiscountStore.setState(state => {
const discounts: AnyDiscount[] = []; const discounts: AnyDiscount[] = [];
state.discounts.forEach(discount => { state.discounts.forEach(discount => {
if (!state.selectedDiscountIds.includes(discount._id)) return discounts.push(discount); if (!state.selectedDiscountIds.includes(discount._id)) return discounts.push(discount);
@ -40,7 +69,8 @@ export const activateDiscounts = () => useDiscountStore.setState(state => {
return { discounts }; return { discounts };
}); });
export const deactivateDiscounts = () => useDiscountStore.setState(state => { /** @deprecated */
export const deactivateMockDiscounts = () => useMockDiscountStore.setState(state => {
const discounts: AnyDiscount[] = []; const discounts: AnyDiscount[] = [];
state.discounts.forEach(discount => { state.discounts.forEach(discount => {
if (!state.selectedDiscountIds.includes(discount._id)) return discounts.push(discount); if (!state.selectedDiscountIds.includes(discount._id)) return discounts.push(discount);

@ -2,7 +2,27 @@ import { Privilege } from "@root/model/tariff";
import { create } from "zustand"; import { create } from "zustand";
import { devtools } from "zustand/middleware"; import { devtools } from "zustand/middleware";
import { exampleCartValues } from "./mocks/exampleCartValues"; import { exampleCartValues } from "./mocks/exampleCartValues";
import { RealPrivilege } from "@root/model/privilege";
interface RealPrivilegeStore {
privileges: RealPrivilege[];
}
export const useRealPrivilegeStore = create<RealPrivilegeStore>()(
devtools(
(set, get) => ({
privileges: [],
}),
{
name: "Privilege store",
}
)
);
export const addRealPrivileges = (privileges: RealPrivilegeStore["privileges"]) => useRealPrivilegeStore.setState({ privileges });
/** @deprecated */
interface PrivilegeStore { interface PrivilegeStore {
privileges: Privilege[]; privileges: Privilege[];
isModalOpen: boolean; isModalOpen: boolean;
@ -11,6 +31,7 @@ interface PrivilegeStore {
addPrivileges: (newPrivileges: Privilege[]) => void; addPrivileges: (newPrivileges: Privilege[]) => void;
} }
/** @deprecated */
export const usePrivilegeStore = create<PrivilegeStore>()( export const usePrivilegeStore = create<PrivilegeStore>()(
devtools( devtools(
(set, get) => ({ (set, get) => ({
@ -21,12 +42,15 @@ export const usePrivilegeStore = create<PrivilegeStore>()(
addPrivileges: (newPrivileges) => set((state) => ({ privileges: [...state.privileges, ...newPrivileges] })), addPrivileges: (newPrivileges) => set((state) => ({ privileges: [...state.privileges, ...newPrivileges] })),
}), }),
{ {
name: "Privilege store", name: "Mock Privilege store",
} }
) )
); );
/** @deprecated */
export const closePrivilegePriceModal = () => usePrivilegeStore.setState({ isModalOpen: false }); export const closePrivilegePriceModal = () => usePrivilegeStore.setState({ isModalOpen: false });
/** @deprecated */
export const openPrivilegePriceModal = (modalPrivilegeId: string | null, defaultPrice: number) => export const openPrivilegePriceModal = (modalPrivilegeId: string | null, defaultPrice: number) =>
usePrivilegeStore.setState({ usePrivilegeStore.setState({
isModalOpen: true, isModalOpen: true,
@ -34,8 +58,10 @@ export const openPrivilegePriceModal = (modalPrivilegeId: string | null, default
modalPrivilegeId, modalPrivilegeId,
}); });
/** @deprecated */
export const changeModalPriceField = (modalPriceField: string) => usePrivilegeStore.setState({ modalPriceField }); export const changeModalPriceField = (modalPriceField: string) => usePrivilegeStore.setState({ modalPriceField });
/** @deprecated */
export const changePrivilegePrice = () => { export const changePrivilegePrice = () => {
const { privileges, modalPrivilegeId, modalPriceField } = usePrivilegeStore.getState(); const { privileges, modalPrivilegeId, modalPriceField } = usePrivilegeStore.getState();
@ -59,6 +85,7 @@ export const changePrivilegePrice = () => {
}); });
}; };
/** @deprecated */
export const findPrivilegeById = (privilegeId: string) => { export const findPrivilegeById = (privilegeId: string) => {
return usePrivilegeStore.getState().privileges.find((privilege) => privilege.privilegeId === privilegeId) ?? null; return usePrivilegeStore.getState().privileges.find((privilege) => privilege.privilegeId === privilegeId) ?? null;
}; };

@ -0,0 +1,31 @@
import { Discount, GetDiscountResponse } from "@root/model/discount";
import { authStore } from "@root/stores/auth";
import { useEffect } from "react";
const makeRequest = authStore.getState().makeRequest;
export default function useDiscounts({ onError, onNewDiscounts }: {
onNewDiscounts: (response: Discount[]) => void;
onError?: (error: any) => void;
}) {
useEffect(() => {
const controller = new AbortController();
makeRequest<never, GetDiscountResponse>({
url: "https://admin.pena.digital/price/discounts",
method: "get",
useToken: true,
bearer: true,
signal: controller.signal,
}).then(result => {
console.log("New discounts", result);
onNewDiscounts(result.Discounts);
}).catch(error => {
console.log("Error fetching discounts", error);
onError?.(error);
});
return () => controller.abort();
}, [onError, onNewDiscounts]);
}

@ -0,0 +1,31 @@
import { RealPrivilege } from "@root/model/privilege";
import { authStore } from "@root/stores/auth";
import { useEffect } from "react";
const makeRequest = authStore.getState().makeRequest;
export default function usePrivileges({ onError, onNewPrivileges }: {
onNewPrivileges: (response: RealPrivilege[]) => void;
onError?: (error: any) => void;
}) {
useEffect(() => {
const controller = new AbortController();
makeRequest<never, RealPrivilege[]>({
url: "https://admin.pena.digital/strator/privilege",
method: "get",
useToken: true,
bearer: true,
signal: controller.signal,
}).then(result => {
console.log("New privileges", result);
onNewPrivileges(result);
}).catch(error => {
console.log("Error fetching privileges", error);
onError?.(error);
});
return () => controller.abort();
}, [onError, onNewPrivileges]);
}