Merge branch 'dev' into 'staging'

Dev

See merge request frontend/admin!94
This commit is contained in:
Nastya 2024-06-02 03:36:38 +00:00
commit fa5dc3a797
30 changed files with 650 additions and 506 deletions

@ -30,13 +30,13 @@ export type Account = {
wallet: Wallet;
};
const baseUrl = process.env.REACT_APP_DOMAIN + "/customer";
const API_URL = `${process.env.REACT_APP_DOMAIN}/customer`;
export const getAccountInfo = async (id: string): Promise<[Account | null, string?]> => {
try {
const accountInfoResponse = await makeRequest<never, Account>({
url: `${baseUrl}/account/${id}`,
method: "GET",
url: `${API_URL}/account/${id}`,
useToken: true,
});
@ -47,3 +47,20 @@ export const getAccountInfo = async (id: string): Promise<[Account | null, strin
return [null, `Не удалось получить информацию об аккаунте. ${error}`];
}
};
export const editAccount = async (userId: string, status: "org" | "nko"): Promise<[Account | null, string?]> => {
try {
const editResponse = await makeRequest<{ status: "org" | "nko" }, Account>({
method: "PATCH",
url: `${API_URL}/account/${userId}`,
body: { status },
useToken: true,
});
return [editResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Не удалось отредактировать информацию. ${error}`];
}
};

@ -4,12 +4,12 @@ import { parseAxiosError } from "@root/utils/parse-error";
import type { LoginRequest, RegisterRequest, RegisterResponse } from "@frontend/kitui";
const baseUrl = process.env.REACT_APP_DOMAIN + "/auth";
const API_URL = `${process.env.REACT_APP_DOMAIN}/auth`;
export const signin = async (login: string, password: string): Promise<[RegisterResponse | null, string?]> => {
try {
const signinResponse = await makeRequest<LoginRequest, RegisterResponse>({
url: baseUrl + "/login",
url: `${API_URL}/login`,
body: { login, password },
useToken: false,
});
@ -17,7 +17,7 @@ export const signin = async (login: string, password: string): Promise<[Register
return [signinResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
console.error(error);
return [null, `Ошибка авторизации. ${error}`];
}
};
@ -29,7 +29,7 @@ export const register = async (
): Promise<[RegisterResponse | null, string?]> => {
try {
const registerResponse = await makeRequest<RegisterRequest, RegisterResponse>({
url: baseUrl + "/register",
url: `${API_URL}/register`,
body: { login, password, phoneNumber },
useToken: false,
});
@ -42,11 +42,11 @@ export const register = async (
}
};
export const logout = async (): Promise<[unknown, string?]> => {
export const logout = async (): Promise<[unknown | null, string?]> => {
try {
const logoutResponse = await makeRequest<never, unknown>({
url: baseUrl + "/logout",
method: "post",
method: "POST",
url: `${API_URL}/logout`,
contentType: true,
});

@ -4,10 +4,8 @@ import { parseAxiosError } from "@root/utils/parse-error";
import type { Discount } from "@frontend/kitui";
import type { CreateDiscountBody, DiscountType, GetDiscountResponse } from "@root/model/discount";
import useSWR from "swr";
import { enqueueSnackbar } from "notistack";
const baseUrl = process.env.REACT_APP_DOMAIN + "/price";
const API_URL = `${process.env.REACT_APP_DOMAIN}/price`;
interface CreateDiscountParams {
purchasesAmount: number;
@ -108,10 +106,10 @@ export function createDiscountObject({
export const changeDiscount = async (discountId: string, discount: Discount): Promise<[unknown, string?]> => {
try {
const changeDiscountResponse = await makeRequest<Discount, unknown>({
url: baseUrl + "/discount/" + discountId,
method: "patch",
useToken: true,
method: "PATCH",
url: `${API_URL}/discount/${discountId}`,
body: discount,
useToken: true,
});
return [changeDiscountResponse];
@ -127,10 +125,10 @@ export const createDiscount = async (discountParams: CreateDiscountParams): Prom
try {
const createdDiscountResponse = await makeRequest<CreateDiscountBody, Discount>({
url: baseUrl + "/discount",
method: "post",
useToken: true,
method: "POST",
url: `${API_URL}/discount`,
body: discount,
useToken: true,
});
return [createdDiscountResponse];
@ -144,8 +142,8 @@ export const createDiscount = async (discountParams: CreateDiscountParams): Prom
export const deleteDiscount = async (discountId: string): Promise<[Discount | null, string?]> => {
try {
const deleteDiscountResponse = await makeRequest<never, Discount>({
url: baseUrl + "/discount/" + discountId,
method: "delete",
method: "DELETE",
url: `${API_URL}/discount/${discountId}`,
useToken: true,
});
@ -165,10 +163,10 @@ export const patchDiscount = async (
try {
const patchDiscountResponse = await makeRequest<CreateDiscountBody, Discount>({
url: baseUrl + "/discount/" + discountId,
method: "patch",
useToken: true,
method: "PATCH",
url: `${API_URL}/discount/${discountId}`,
body: discount,
useToken: true,
});
return [patchDiscountResponse];
@ -182,8 +180,8 @@ export const patchDiscount = async (
export const requestDiscounts = async (): Promise<[GetDiscountResponse | null, string?]> => {
try {
const discountsResponse = await makeRequest<never, GetDiscountResponse>({
url: baseUrl + "/discounts",
method: "get",
method: "GET",
url: `${API_URL}/discounts`,
useToken: true,
});
@ -195,32 +193,18 @@ export const requestDiscounts = async (): Promise<[GetDiscountResponse | null, s
}
};
async function getDiscounts() {
export const getDiscounts = async (): Promise<[Discount[] | null, string?]> => {
try {
const discountsResponse = await makeRequest<never, GetDiscountResponse>({
url: baseUrl + "/discounts",
method: "get",
method: "GET",
url: `${API_URL}/discounts`,
useToken: true,
});
return discountsResponse.Discounts.filter((discount) => !discount.Deprecated);
return [discountsResponse.Discounts.filter((discount) => !discount.Deprecated)];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
throw new Error(`Ошибка получения списка скидок. ${error}`);
return [null, `Ошибка получения списка скидок. ${error}`];
}
}
export function useDiscounts() {
const { data } = useSWR("discounts", getDiscounts, {
keepPreviousData: true,
suspense: true,
onError: (error) => {
if (!(error instanceof Error)) return;
enqueueSnackbar(error.message, { variant: "error" });
},
});
return data;
}
};

30
src/api/discounts/swr.ts Normal file

@ -0,0 +1,30 @@
import useSWR from "swr";
import { enqueueSnackbar } from "notistack";
import { getDiscounts } from "./requests";
export function useDiscounts() {
const { data } = useSWR(
"discounts",
async () => {
const [discounts, discountsError] = await getDiscounts();
if (discountsError || !discounts) {
throw new Error(discountsError);
}
return discounts;
},
{
keepPreviousData: true,
suspense: true,
onError: (error) => {
if (!(error instanceof Error)) return;
enqueueSnackbar(error.message, { variant: "error" });
},
}
);
return data;
}

@ -23,13 +23,13 @@ type HistoryResponse = {
totalPages: number;
};
const baseUrl = process.env.REACT_APP_DOMAIN + "/customer";
const API_URL = `${process.env.REACT_APP_DOMAIN}/customer`;
const getUserHistory = async (accountId: string, page: number): Promise<[HistoryResponse | null, string?]> => {
try {
const historyResponse = await makeRequest<never, HistoryResponse>({
method: "GET",
url: baseUrl + `/history?page=${page}&limit=${100}&accountID=${accountId}&type=payCart`,
url: `${API_URL}/history?page=${page}&limit=${100}&accountID=${accountId}&type=payCart`,
});
return [historyResponse];

@ -11,13 +11,13 @@ type SeverPrivilegesResponse = {
squiz: CustomPrivilege[];
};
const baseUrl = process.env.REACT_APP_DOMAIN + "/strator";
const API_URL = `${process.env.REACT_APP_DOMAIN}/strator`;
export const getRoles = async (): Promise<[TMockData | null, string?]> => {
try {
const rolesResponse = await makeRequest<never, TMockData>({
method: "get",
url: baseUrl + "/role",
method: "GET",
url: `${API_URL}/role`,
});
return [rolesResponse];
@ -28,11 +28,13 @@ export const getRoles = async (): Promise<[TMockData | null, string?]> => {
}
};
export const putPrivilege = async (body: Omit<Privilege, "_id" | "updatedAt">): Promise<[unknown, string?]> => {
export const putPrivilege = async (
body: Omit<Privilege, "_id" | "updatedAt">
): Promise<[CustomPrivilege | null, string?]> => {
try {
const putedPrivilege = await makeRequest<Omit<Privilege, "_id" | "updatedAt">, unknown>({
url: baseUrl + "/privilege",
method: "put",
const putedPrivilege = await makeRequest<Omit<Privilege, "_id" | "updatedAt">, CustomPrivilege>({
method: "PUT",
url: `${API_URL}/privilege`,
body,
});
@ -47,8 +49,8 @@ export const putPrivilege = async (body: Omit<Privilege, "_id" | "updatedAt">):
export const requestServicePrivileges = async (): Promise<[SeverPrivilegesResponse | null, string?]> => {
try {
const privilegesResponse = await makeRequest<never, SeverPrivilegesResponse>({
url: baseUrl + "/privilege/service",
method: "get",
method: "GET",
url: `${API_URL}/privilege/service`,
});
return [privilegesResponse];
@ -62,8 +64,8 @@ export const requestServicePrivileges = async (): Promise<[SeverPrivilegesRespon
export const requestPrivileges = async (signal: AbortSignal | undefined): Promise<[CustomPrivilege[], string?]> => {
try {
const privilegesResponse = await makeRequest<never, CustomPrivilege[]>({
url: baseUrl + "/privilege",
method: "get",
method: "GET",
url: `${API_URL}/privilege`,
useToken: true,
signal,
});

@ -1,54 +1,64 @@
import makeRequest from "@root/api/makeRequest";
import type {
CreatePromocodeBody,
CreatePromocodeBody,
EditPromocodeBody,
GetPromocodeListBody,
Promocode,
PromocodeList,
PromocodeStatistics,
GetPromocodeListBody,
Promocode,
PromocodeList,
PromocodeStatistics,
} from "@root/model/promocodes";
import { parseAxiosError } from "@root/utils/parse-error";
import { isAxiosError } from "axios";
const baseUrl = process.env.REACT_APP_DOMAIN + "/codeword/promocode";
type PromocodeStatisticsBody = {
id: string;
from: number;
to: number;
};
const getPromocodeList = async (body: GetPromocodeListBody) => {
const API_URL = `${process.env.REACT_APP_DOMAIN}/codeword/promocode`;
const getPromocodeList = async (body: GetPromocodeListBody): Promise<[PromocodeList | null, string?]> => {
try {
const promocodeListResponse = await makeRequest<GetPromocodeListBody, PromocodeList>({
url: baseUrl + "/getList",
method: "POST",
url: `${API_URL}/getList`,
body,
useToken: false,
});
return promocodeListResponse;
return [promocodeListResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
throw new Error(`Ошибка при получении списка промокодов. ${error}`);
return [null, `Ошибка при получении списка промокодов. ${error}`];
}
};
const createFastlink = async (id: string) => {
const createFastlink = async (id: string): Promise<[{ fastlink: string } | null, string?]> => {
try {
return await makeRequest<{ id: string }, { fastlink: string }>({
url: baseUrl + "/fastlink",
const createFastLinkResponse = await makeRequest<{ id: string }, { fastlink: string }>({
url: `${API_URL}/fastlink`,
method: "POST",
body: { id },
});
return [createFastLinkResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
throw new Error(`Ошибка при создании фастлинка. ${error}`);
return [null, `Ошибка при создании фастлинка. ${error}`];
}
};
export const getAllPromocodes = async () => {
export const getAllPromocodes = async (): Promise<[Promocode[] | null, string?]> => {
try {
const promocodes: Promocode[] = [];
let page = 0;
while (true) {
const promocodeList = await getPromocodeList({
const [promocodeList] = await getPromocodeList({
limit: 100,
filter: {
active: true,
@ -56,119 +66,133 @@ export const getAllPromocodes = async () => {
page,
});
if (promocodeList.items.length === 0) break;
if (promocodeList) {
if (promocodeList.items.length === 0) break;
promocodes.push(...promocodeList.items);
page++;
promocodes.push(...promocodeList.items);
page++;
}
}
return promocodes;
return [promocodes];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
throw new Error(`Ошибка при получении списка промокодов. ${error}`);
return [null, `Ошибка при получении списка промокодов. ${error}`];
}
};
export const getNotActivePromocodes = async () => {
try {
const promocodes: Promocode[] = [];
export const getNotActivePromocodes = async (): Promise<[Promocode[] | null, string?]> => {
try {
const promocodes: Promocode[] = [];
let page = 0;
while (true) {
const promocodeList = await getPromocodeList({
limit: 100,
filter: {
active: false,
},
page,
});
let page = 0;
while (true) {
const [promocodeList] = await getPromocodeList({
limit: 100,
filter: {
active: false,
},
page,
});
if (promocodeList.items.length === 0) break;
if (promocodeList) {
if (promocodeList.items.length === 0) break;
promocodes.push(...promocodeList.items);
page++;
}
promocodes.push(...promocodeList.items);
page++;
}
}
return promocodes;
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
throw new Error(`Ошибка при получении списка промокодов. ${error}`);
}
return [promocodes];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка при получении списка промокодов. ${error}`];
}
};
const createPromocode = async (body: CreatePromocodeBody) => {
const createPromocode = async (body: CreatePromocodeBody): Promise<[Promocode | null, string?]> => {
try {
const createPromocodeResponse = await makeRequest<CreatePromocodeBody, Promocode>({
url: baseUrl + "/create",
method: "POST",
url: `${API_URL}/create`,
body,
useToken: false,
});
return createPromocodeResponse;
return [createPromocodeResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
if (isAxiosError(nativeError) && nativeError.response?.data.error === "Duplicate Codeword") {
throw new Error(`Промокод уже существует`);
return [null, `Промокод уже существует`];
}
const [error] = parseAxiosError(nativeError);
throw new Error(`Ошибка создания промокода. ${error}`);
return [null, `Ошибка создания промокода. ${error}`];
}
};
const editPromocode = async (body: EditPromocodeBody) => {
try {
const editPromocodeResponse = await makeRequest<unknown, Promocode>({
url: process.env.REACT_APP_DOMAIN + "/codeword/promocode" + "/edit",
method: "PUT",
body,
});
return [editPromocodeResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка редактирования промокода. ${error}`];
}
const editPromocode = async (body: EditPromocodeBody): Promise<[Promocode | null, string?]> => {
try {
const editPromocodeResponse = await makeRequest<EditPromocodeBody, Promocode>({
method: "PUT",
url: `${API_URL}/codeword/promocode/edit`,
body,
});
return [editPromocodeResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка редактирования промокода. ${error}`];
}
};
const deletePromocode = async (id: string): Promise<void> => {
const deletePromocode = async (id: string): Promise<[null, string?]> => {
try {
await makeRequest<never, never>({
url: `${baseUrl}/${id}`,
method: "DELETE",
url: `${API_URL}/${id}`,
useToken: false,
});
return [null];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
throw new Error(`Ошибка удаления промокода. ${error}`);
return [null, `Ошибка удаления промокода. ${error}`];
}
};
const getPromocodeStatistics = async (id: string, from: number, to: number) => {
const getPromocodeStatistics = async (
id: string,
from: number,
to: number
): Promise<[PromocodeStatistics | null, string?]> => {
try {
const promocodeStatisticsResponse = await makeRequest<unknown, PromocodeStatistics>({
url: baseUrl + `/stats`,
body: {
id: id,
from: from,
to: to,
},
const promocodeStatisticsResponse = await makeRequest<PromocodeStatisticsBody, PromocodeStatistics>({
method: "POST",
url: `${API_URL}/stats`,
body: { id, from, to },
useToken: false,
});
return promocodeStatisticsResponse;
return [promocodeStatisticsResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
throw new Error(`Ошибка при получении статистики промокода. ${error}`);
return [null, `Ошибка при получении статистики промокода. ${error}`];
}
};
export const promocodeApi = {
getPromocodeList,
createPromocode,
editPromocode,
deletePromocode,
getAllPromocodes,
getNotActivePromocodes,
getPromocodeStatistics,
createFastlink,
getPromocodeList,
createPromocode,
editPromocode,
deletePromocode,
getAllPromocodes,
getNotActivePromocodes,
getPromocodeStatistics,
createFastlink,
};

@ -3,33 +3,34 @@ import useSwr, { mutate } from "swr";
import { enqueueSnackbar } from "notistack";
import { promocodeApi } from "./requests";
import type {
CreatePromocodeBody, EditPromocodeBody,
PromocodeList,
} from "@root/model/promocodes";
import type { CreatePromocodeBody, EditPromocodeBody, PromocodeList } from "@root/model/promocodes";
export function usePromocodes(
page: number,
pageSize: number,
promocodeId: string,
to: number,
from: number,
active: boolean
page: number,
pageSize: number,
promocodeId: string,
to: number,
from: number,
active: boolean
) {
const promocodesCountRef = useRef<number>(0);
const swrResponse = useSwr(
["promocodes", page, pageSize, active],
async (key) => {
const result = await promocodeApi.getPromocodeList({
limit: key[2],
filter: {
active: key[3],
},
page: key[1],
});
const promocodesCountRef = useRef<number>(0);
const swrResponse = useSwr(
["promocodes", page, pageSize, active],
async (key) => {
const [promocodeList, promocodeListError] = await promocodeApi.getPromocodeList({
limit: key[2],
filter: {
active: key[3],
},
page: key[1],
});
promocodesCountRef.current = result.count;
return result;
if (promocodeListError || !promocodeList) {
throw new Error(promocodeListError);
}
promocodesCountRef.current = promocodeList.count;
return promocodeList;
},
{
onError(err) {
@ -43,49 +44,60 @@ export function usePromocodes(
const createPromocode = useCallback(
async function (body: CreatePromocodeBody) {
try {
await promocodeApi.createPromocode(body);
mutate(["promocodes", page, pageSize]);
} catch (error) {
console.error("Error creating promocode", error);
if (error instanceof Error) enqueueSnackbar(error.message, { variant: "error" });
const [, createError] = await promocodeApi.createPromocode(body);
if (createError) {
enqueueSnackbar(createError, { variant: "error" });
return;
}
mutate(["promocodes", page, pageSize]);
},
[page, pageSize]
);
const editPromocode = useCallback(
async function (body: EditPromocodeBody) {
const [, editError] = await promocodeApi.editPromocode(body);
if (editError) {
enqueueSnackbar(editError, { variant: "error" });
return;
}
mutate<PromocodeList | undefined, void>(["promocodes", page, pageSize, active]);
const [, getPromocodesError] = await promocodeApi.getPromocodeList({
limit: pageSize,
filter: {
active: active,
},
page: page,
});
if (getPromocodesError) {
enqueueSnackbar(getPromocodesError, { variant: "error" });
}
},
[page, pageSize]
);
const editPromocode = useCallback(
async function (body: EditPromocodeBody) {
try {
await promocodeApi.editPromocode(body);
mutate<PromocodeList | undefined, void>(
["promocodes", page, pageSize, active],
);
await promocodeApi.getPromocodeList({
limit: pageSize,
filter: {
active: active,
},
page: page,
});
} catch (error) {
console.error("Error editing promocode", error);
if (error instanceof Error)
enqueueSnackbar(error.message, { variant: "error" });
}
},
[page, pageSize,]
);
const deletePromocode = useCallback(
async function (id: string) {
try {
await mutate<PromocodeList | undefined, void>(
["promocodes", page, pageSize],
async () => {
const [_, deleteError] = await promocodeApi.deletePromocode(id);
const deletePromocode = useCallback(
async function (id: string) {
try {
await mutate<PromocodeList | undefined, void>(
["promocodes", page, pageSize],
promocodeApi.deletePromocode(id),
{
optimisticData(currentData, displayedData) {
if (!displayedData) return;
if (deleteError) {
throw new Error(deleteError);
}
},
{
optimisticData(currentData, displayedData) {
if (!displayedData) return;
return {
count: displayedData.count - 1,
@ -118,7 +130,15 @@ export function usePromocodes(
return null;
}
const promocodeStatisticsResponse = await promocodeApi.getPromocodeStatistics(id, from, to);
const [promocodeStatisticsResponse, promocodeStatisticsError] = await promocodeApi.getPromocodeStatistics(
id,
from,
to
);
if (promocodeStatisticsError) {
throw new Error(promocodeStatisticsError);
}
return promocodeStatisticsResponse;
},
@ -134,50 +154,76 @@ export function usePromocodes(
const createFastLink = useCallback(
async function (id: string) {
try {
await promocodeApi.createFastlink(id);
mutate(["promocodes", page, pageSize]);
} catch (error) {
console.error("Error creating fast link", error);
if (error instanceof Error) enqueueSnackbar(error.message, { variant: "error" });
const [, createError] = await promocodeApi.createFastlink(id);
if (createError) {
enqueueSnackbar(createError, { variant: "error" });
return;
}
mutate(["promocodes", page, pageSize]);
},
[page, pageSize]
);
return {
...swrResponse,
createPromocode,
deletePromocode,
editPromocode,
createFastLink,
promocodeStatistics: promocodeStatistics.data,
promocodesCount: promocodesCountRef.current,
};
return {
...swrResponse,
createPromocode,
deletePromocode,
editPromocode,
createFastLink,
promocodeStatistics: promocodeStatistics.data,
promocodesCount: promocodesCountRef.current,
};
}
export function useAllPromocodes() {
const { data } = useSwr("allPromocodes", promocodeApi.getAllPromocodes, {
keepPreviousData: true,
suspense: true,
onError(err) {
console.error("Error fetching all promocodes", err);
enqueueSnackbar(err.message, { variant: "error" });
const { data } = useSwr(
"allPromocodes",
async () => {
const [promocodes, promocodesError] = await promocodeApi.getAllPromocodes();
if (promocodesError || !promocodes) {
throw new Error(promocodesError);
}
return promocodes;
},
});
{
keepPreviousData: true,
suspense: true,
onError(err) {
console.error("Error fetching all promocodes", err);
enqueueSnackbar(err.message, { variant: "error" });
},
}
);
return data;
}
export function useNotActivePromocodes() {
const { data } = useSwr("notActivePromocodes", promocodeApi.getNotActivePromocodes, {
keepPreviousData: true,
suspense: true,
onError(err) {
console.error("Error fetching all promocodes", err);
enqueueSnackbar(err.message, { variant: "error" });
},
});
const { data } = useSwr(
"notActivePromocodes",
async () => {
const [promocodes, promocodesError] = await promocodeApi.getNotActivePromocodes();
return data;
if (promocodesError || !promocodes) {
throw new Error(promocodesError);
}
return promocodes;
},
{
keepPreviousData: true,
suspense: true,
onError(err) {
console.error("Error fetching all promocodes", err);
enqueueSnackbar(err.message, { variant: "error" });
},
}
);
return data;
}

26
src/api/quiz.ts Normal file

@ -0,0 +1,26 @@
import makeRequest from "@root/api/makeRequest";
import { parseAxiosError } from "@root/utils/parse-error";
const API_URL = `${process.env.REACT_APP_DOMAIN}/squiz/quiz`;
type MoveQuizBody = {
Qid: string;
AccountID: string;
};
export const moveQuiz = async (quizId: string, userId: string): Promise<[string | null, string?]> => {
try {
const moveResponse = await makeRequest<MoveQuizBody, string>({
method: "POST",
url: `${API_URL}/move`,
body: { Qid: quizId, AccountID: userId },
});
return [moveResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Ошибка перемещения квиза. ${error}`];
}
};

@ -1,4 +1,5 @@
import makeRequest from "@root/api/makeRequest";
import { parseAxiosError } from "@root/utils/parse-error";
import type {
GetStatisticSchildBody,
@ -18,60 +19,70 @@ type TRequest = {
from: number;
};
export const getStatistic = async (to: number, from: number): Promise<QuizStatisticResponse> => {
const API_URL = process.env.REACT_APP_DOMAIN;
export const getStatistic = async (to: number, from: number): Promise<[QuizStatisticResponse | null, string?]> => {
try {
const generalResponse = await makeRequest<TRequest, QuizStatisticResponse>({
url: `${process.env.REACT_APP_DOMAIN}/squiz/statistic`,
url: `${API_URL}/squiz/statistic`,
body: { to, from },
});
return generalResponse;
return [generalResponse];
} catch (nativeError) {
return { Registrations: 0, Quizes: 0, Results: 0 };
const [error] = parseAxiosError(nativeError);
return [null, `Не удалось получить статистику ${error}`];
}
};
export const getStatisticSchild = async (from: number, to: number): Promise<QuizStatisticsItem[]> => {
export const getStatisticSchild = async (from: number, to: number): Promise<[QuizStatisticsItem[] | null, string?]> => {
try {
const StatisticResponse = await makeRequest<GetStatisticSchildBody, QuizStatisticsItem[]>({
url: process.env.REACT_APP_DOMAIN + "/customer/quizlogo/stat",
method: "post",
useToken: true,
const statisticResponse = await makeRequest<GetStatisticSchildBody, QuizStatisticsItem[]>({
method: "POST",
url: `${API_URL}/customer/quizlogo/stat`,
body: { to, from, page: 0, limit: 100 },
useToken: true,
});
if (!StatisticResponse) {
throw new Error("Статистика не найдена");
if (!statisticResponse) {
return [null, "Статистика не найдена"];
}
return StatisticResponse;
return [statisticResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [
{
ID: "0",
Regs: 0,
Money: 0,
Quizes: [{ QuizID: "0", Regs: 0, Money: 0 }],
},
[
{
ID: "0",
Regs: 0,
Money: 0,
Quizes: [{ QuizID: "0", Regs: 0, Money: 0 }],
},
],
`Не удалось получить статистику ${error}`,
];
}
};
export const getStatisticPromocode = async (
export const getStatisticsPromocode = async (
from: number,
to: number
): Promise<Record<string, AllPromocodeStatistics>> => {
): Promise<[Record<string, AllPromocodeStatistics> | null, string?]> => {
try {
const StatisticPromo = await makeRequest<GetPromocodeStatisticsBody, Record<string, AllPromocodeStatistics>>({
url: process.env.REACT_APP_DOMAIN + "/customer/promocode/ltv",
method: "post",
useToken: true,
const statisticsPromocode = await makeRequest<GetPromocodeStatisticsBody, Record<string, AllPromocodeStatistics>>({
method: "POST",
url: `${API_URL}/customer/promocode/ltv`,
body: { to, from },
useToken: true,
});
return StatisticPromo;
return [statisticsPromocode];
} catch (nativeError) {
console.log(nativeError);
const error = parseAxiosError(nativeError);
return {};
return [null, `Не удалось получить статистику промокода ${error}`];
}
};

@ -35,7 +35,7 @@ export type UserType = {
updatedAt: string;
};
const baseUrl = process.env.REACT_APP_DOMAIN + "/role";
const API_URL = `${process.env.REACT_APP_DOMAIN}/role`;
export const getRoles_mock = (): Promise<TMockData> => {
return new Promise((resolve) => {
@ -47,9 +47,9 @@ export const getRoles_mock = (): Promise<TMockData> => {
export const deleteRole = async (id: string): Promise<[unknown, string?]> => {
try {
const deleteRoleResponse = await makeRequest({
url: `${baseUrl}/${id}`,
method: "delete",
const deleteRoleResponse = await makeRequest<never, unknown>({
method: "DELETE",
url: `${API_URL}/${id}`,
});
return [deleteRoleResponse];

@ -20,13 +20,13 @@ type GetTariffsResponse = {
tariffs: Tariff[];
};
const baseUrl = process.env.REACT_APP_DOMAIN + "/strator";
const API_URL = `${process.env.REACT_APP_DOMAIN}/strator`;
export const createTariff = async (body: CreateTariffBackendRequest): Promise<[unknown, string?]> => {
export const createTariff = async (body: CreateTariffBackendRequest): Promise<[Tariff | null, string?]> => {
try {
const createdTariffResponse = await makeRequest<CreateTariffBackendRequest>({
url: baseUrl + "/tariff/",
method: "post",
const createdTariffResponse = await makeRequest<CreateTariffBackendRequest, Tariff>({
method: "POST",
url: `${API_URL}/tariff/`,
body,
});
@ -38,11 +38,11 @@ export const createTariff = async (body: CreateTariffBackendRequest): Promise<[u
}
};
export const putTariff = async (tariff: Tariff): Promise<[null, string?]> => {
export const putTariff = async (tariff: Tariff): Promise<[Tariff | null, string?]> => {
try {
const putedTariffResponse = await makeRequest<EditTariffRequestBody, null>({
method: "put",
url: baseUrl + `/tariff/${tariff._id}`,
const putedTariffResponse = await makeRequest<EditTariffRequestBody, Tariff>({
method: "PUT",
url: `${API_URL}/tariff/${tariff._id}`,
body: {
name: tariff.name,
price: tariff.price ?? 0,
@ -64,8 +64,8 @@ export const putTariff = async (tariff: Tariff): Promise<[null, string?]> => {
export const deleteTariff = async (tariffId: string): Promise<[Tariff | null, string?]> => {
try {
const deletedTariffResponse = await makeRequest<{ id: string }, Tariff>({
method: "delete",
url: baseUrl + "/tariff",
method: "DELETE",
url: `${API_URL}/tariff`,
body: { id: tariffId },
});
@ -80,8 +80,8 @@ export const deleteTariff = async (tariffId: string): Promise<[Tariff | null, st
export const requestTariffs = async (page: number): Promise<[GetTariffsResponse | null, string?]> => {
try {
const tariffsResponse = await makeRequest<never, GetTariffsResponse>({
url: baseUrl + `/tariff/?page=${page}&limit=${100}`,
method: "get",
method: "GET",
url: `${API_URL}/tariff/?page=${page}&limit=${100}`,
});
return [tariffsResponse];

@ -4,15 +4,23 @@ import { parseAxiosError } from "@root/utils/parse-error";
import type { SendTicketMessageRequest } from "@root/model/ticket";
const baseUrl = process.env.REACT_APP_DOMAIN + "/heruvym";
const API_URL = `${process.env.REACT_APP_DOMAIN}/heruvym`;
export const sendTicketMessage = async (body: SendTicketMessageRequest): Promise<[unknown, string?]> => {
type CloseTicketBody = {
ticket: string;
};
type SendFileResponse = {
message: string;
};
export const sendTicketMessage = async (body: SendTicketMessageRequest): Promise<[null, string?]> => {
try {
const sendTicketMessageResponse = await makeRequest<SendTicketMessageRequest, unknown>({
url: `${baseUrl}/send`,
const sendTicketMessageResponse = await makeRequest<SendTicketMessageRequest, null>({
method: "POST",
useToken: true,
url: `${API_URL}/send`,
body,
useToken: true,
});
return [sendTicketMessageResponse];
@ -22,3 +30,40 @@ export const sendTicketMessage = async (body: SendTicketMessageRequest): Promise
return [null, `Ошибка отправки сообщения. ${error}`];
}
};
export const closeTicket = async (ticketId: string): Promise<[CloseTicketBody | null, string?]> => {
try {
const ticketCloseResponse = await makeRequest<CloseTicketBody, CloseTicketBody>({
method: "POST",
url: `${API_URL}/close`,
body: { ticket: ticketId },
useToken: true,
});
return [ticketCloseResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Не удалось закрыть тикет. ${error}`];
}
};
export const sendFile = async (file: File, ticketId: string): Promise<[SendFileResponse | null, string?]> => {
try {
const body = new FormData();
body.append(file.name, file);
body.append("ticket", ticketId);
const sendFileRespose = await makeRequest<FormData, SendFileResponse>({
method: "POST",
url: `${API_URL}/sendFiles`,
body,
});
return [sendFileRespose];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Не удалось отправить файл. ${error}`];
}
};

@ -9,13 +9,13 @@ export type UsersListResponse = {
users: UserType[];
};
const baseUrl = process.env.REACT_APP_DOMAIN + "/user";
const API_URL = `${process.env.REACT_APP_DOMAIN}/user`;
const getUserInfo = async (id: string): Promise<[UserType | null, string?]> => {
try {
const userInfoResponse = await makeRequest<never, UserType>({
url: `${baseUrl}/${id}`,
method: "GET",
url: `${API_URL}/${id}`,
useToken: true,
});
@ -30,8 +30,8 @@ const getUserInfo = async (id: string): Promise<[UserType | null, string?]> => {
const getUserList = async (page = 1, limit = 10): Promise<[UsersListResponse | null, string?]> => {
try {
const userResponse = await makeRequest<never, UsersListResponse>({
method: "get",
url: baseUrl + `/?page=${page}&limit=${limit}`,
method: "GET",
url: `${API_URL}/?page=${page}&limit=${limit}`,
});
return [userResponse];
@ -45,8 +45,8 @@ const getUserList = async (page = 1, limit = 10): Promise<[UsersListResponse | n
const getManagerList = async (page = 1, limit = 10): Promise<[UsersListResponse | null, string?]> => {
try {
const managerResponse = await makeRequest<never, UsersListResponse>({
method: "get",
url: baseUrl + `/?page=${page}&limit=${limit}`,
method: "GET",
url: `${API_URL}/?page=${page}&limit=${limit}`,
});
return [managerResponse];
@ -60,8 +60,8 @@ const getManagerList = async (page = 1, limit = 10): Promise<[UsersListResponse
const getAdminList = async (page = 1, limit = 10): Promise<[UsersListResponse | null, string?]> => {
try {
const adminResponse = await makeRequest<never, UsersListResponse>({
method: "get",
url: baseUrl + `/?page=${page}&limit=${limit}`,
method: "GET",
url: `${API_URL}/?page=${page}&limit=${limit}`,
});
return [adminResponse];

@ -25,13 +25,13 @@ type PatchVerificationBody = {
taxnumber?: string;
};
const baseUrl = process.env.REACT_APP_DOMAIN + "/verification/v1.0.0";
const API_URL = `${process.env.REACT_APP_DOMAIN}/verification/v1.0.0`;
export const verification = async (userId: string): Promise<[Verification | null, string?]> => {
try {
const verificationResponse = await makeRequest<never, Verification>({
method: "get",
url: baseUrl + `/verification/${userId}`,
method: "GET",
url: `${API_URL}/verification/${userId}`,
});
return [verificationResponse];
@ -42,13 +42,13 @@ export const verification = async (userId: string): Promise<[Verification | null
}
};
export const patchVerification = async (body: PatchVerificationBody): Promise<[unknown, string?]> => {
export const patchVerification = async (body: PatchVerificationBody): Promise<[string | null, string?]> => {
try {
const patchedVerificationResponse = await makeRequest<PatchVerificationBody, unknown>({
method: "patch",
useToken: true,
url: baseUrl + `/verification`,
const patchedVerificationResponse = await makeRequest<PatchVerificationBody, string>({
method: "PATCH",
url: `${API_URL}/verification`,
body,
useToken: true,
});
return [patchedVerificationResponse];

@ -16,7 +16,7 @@ import {
useMediaQuery,
useTheme,
} from "@mui/material";
import { useDiscounts } from "@root/api/discounts";
import { useDiscounts } from "@root/api/discounts/swr";
import { useAllPromocodes } from "@root/api/promocode/swr";
import { requestDiscounts } from "@root/services/discounts.service";
import { requestPrivileges } from "@root/services/privilegies.service";

@ -2,7 +2,7 @@ import { enqueueSnackbar } from "notistack";
import { GridSelectionModel } from "@mui/x-data-grid";
import { Box, Button, useMediaQuery, useTheme } from "@mui/material";
import { changeDiscount } from "@root/api/discounts";
import { changeDiscount } from "@root/api/discounts/requests";
import { findDiscountsById } from "@root/stores/discounts";
import { requestDiscounts } from "@root/services/discounts.service";

@ -18,7 +18,7 @@ import { resetPrivilegeArray, usePrivilegeStore } from "@root/stores/privilegesS
import { addDiscount } from "@root/stores/discounts";
import { enqueueSnackbar } from "notistack";
import { DiscountType, discountTypes } from "@root/model/discount";
import { createDiscount } from "@root/api/discounts";
import { createDiscount } from "@root/api/discounts/requests";
import usePrivileges from "@root/utils/hooks/usePrivileges";
import { Formik, Field, Form, FormikHelpers } from "formik";
import { mutate } from "swr";

@ -9,7 +9,7 @@ import {
} from "@root/stores/discounts";
import DeleteIcon from "@mui/icons-material/Delete";
import EditIcon from "@mui/icons-material/Edit";
import { deleteDiscount } from "@root/api/discounts";
import { deleteDiscount } from "@root/api/discounts/requests";
import { GridSelectionModel } from "@mui/x-data-grid";
import { requestDiscounts } from "@root/services/discounts.service";
import AutorenewIcon from "@mui/icons-material/Autorenew";

@ -14,7 +14,7 @@ import {
Typography,
useTheme,
} from "@mui/material";
import { patchDiscount } from "@root/api/discounts";
import { patchDiscount } from "@root/api/discounts/requests";
import { CustomTextField } from "@root/kitUI/CustomTextField";
import { DiscountType, discountTypes } from "@root/model/discount";
import { ServiceType, SERVICE_LIST } from "@root/model/tariff";

@ -1,5 +1,5 @@
import { useState } from "react";
import {Box, Button, FormControl, InputLabel, MenuItem, Select, Typography, useTheme} from "@mui/material";
import { Box, Button, FormControl, InputLabel, MenuItem, Select, Typography, useTheme } from "@mui/material";
import { DataGrid, GridLoadingOverlay, GridToolbar } from "@mui/x-data-grid";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
@ -9,9 +9,9 @@ import { CreatePromocodeForm } from "./CreatePromocodeForm";
import { usePromocodeGridColDef } from "./usePromocodeGridColDef";
import { StatisticsModal } from "./StatisticsModal";
import DeleteModal from "./DeleteModal";
import {promocodeApi} from "@root/api/promocode/requests";
import {SelectChangeEvent} from "@mui/material/Select";
import {EditModal} from "@pages/dashboard/Content/PromocodeManagement/EditModal";
import { promocodeApi } from "@root/api/promocode/requests";
import { SelectChangeEvent } from "@mui/material/Select";
import { EditModal } from "@pages/dashboard/Content/PromocodeManagement/EditModal";
export const PromocodeManagement = () => {
const theme = useTheme();
@ -19,135 +19,126 @@ export const PromocodeManagement = () => {
const [deleteModal, setDeleteModal] = useState<string>("");
const deleteModalHC = (id: string) => setDeleteModal(id);
const [showStatisticsModalId, setShowStatisticsModalId] =
useState<string>("");
const [showEditModalId, setShowEditModalId] =
useState<string>("");
const [page, setPage] = useState<number>(0);
const [to, setTo] = useState(0);
const [from, setFrom] = useState(0);
const [pageSize, setPageSize] = useState<number>(10);
const [active, setActive] = useState(true);
const {
data,
error,
isValidating,
promocodesCount,
promocodeStatistics,
deletePromocode,
createPromocode,
editPromocode,
createFastLink,
} = usePromocodes(page, pageSize, showStatisticsModalId, to, from, active);
const columns = usePromocodeGridColDef(
setShowEditModalId,
setShowStatisticsModalId,
deleteModalHC
);
if (error) return <Typography>Ошибка загрузки промокодов</Typography>;
const [showStatisticsModalId, setShowStatisticsModalId] = useState<string>("");
const [showEditModalId, setShowEditModalId] = useState<string>("");
const [page, setPage] = useState<number>(0);
const [to, setTo] = useState(0);
const [from, setFrom] = useState(0);
const [pageSize, setPageSize] = useState<number>(10);
const [active, setActive] = useState(true);
const {
data,
error,
isValidating,
promocodesCount,
promocodeStatistics,
deletePromocode,
createPromocode,
editPromocode,
createFastLink,
} = usePromocodes(page, pageSize, showStatisticsModalId, to, from, active);
const columns = usePromocodeGridColDef(setShowEditModalId, setShowStatisticsModalId, deleteModalHC);
if (error) return <Typography>Ошибка загрузки промокодов</Typography>;
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Typography
variant="subtitle1"
sx={{
width: "90%",
height: "60px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
textTransform: "uppercase",
color: theme.palette.secondary.main,
}}
>
Создание промокода
</Typography>
<CreatePromocodeForm createPromocode={createPromocode} />
<Box sx={{marginTop: "55px", width: "80%", display: "flex"}}>
<FormControl variant="standard" sx={{ m: 1, minWidth: 120 }}>
<Select
labelId="demo-simple-select-standard-label"
id="demo-simple-select-standard"
sx={{color: "white",
backgroundColor: "transparent",
padding: "5px",
border: "1px solid white",
borderRadius: "4px",
".MuiSelect-icon": {
color: "white"
}
}}
value={active? "true" : "false"}
onChange={(event: SelectChangeEvent) => {
setActive((event.target.value) === "true" ? true : false);
}}
label="Age"
>
<MenuItem value={"true"}>Активные</MenuItem>
<MenuItem value={"false"}>Неактивные</MenuItem>
</Select>
</FormControl>
</Box>
<Box style={{ width: "80%", marginTop: "25px" }}>
<DataGrid
disableSelectionOnClick={true}
rows={data?.items ?? []}
columns={columns}
sx={{
color: theme.palette.secondary.main,
"& .MuiDataGrid-iconSeparator": { display: "none" },
"& .css-levciy-MuiTablePagination-displayedRows": {
color: theme.palette.secondary.main,
},
"& .MuiSvgIcon-root": { color: theme.palette.secondary.main },
"& .MuiTablePagination-selectLabel": {
color: theme.palette.secondary.main,
},
"& .MuiInputBase-root": { color: theme.palette.secondary.main },
"& .MuiButton-text": { color: theme.palette.secondary.main },
"& .MuiDataGrid-overlay": {
backgroundColor: "rgba(255, 255, 255, 0.1)",
animation: `${fadeIn} 0.5s ease-out`,
},
}}
components={{
Toolbar: GridToolbar,
LoadingOverlay: GridLoadingOverlay,
}}
loading={isValidating}
paginationMode="server"
page={page}
onPageChange={setPage}
rowCount={promocodesCount}
pageSize={pageSize}
onPageSizeChange={setPageSize}
rowsPerPageOptions={[10, 25, 50, 100]}
autoHeight
/>
</Box>
<EditModal
id={showEditModalId}
setId={setShowEditModalId}
promocodes={data?.items ?? []}
editPromocode={editPromocode}
/>
<StatisticsModal
id={showStatisticsModalId}
setId={setShowStatisticsModalId}
promocodeStatistics={promocodeStatistics}
to={to}
setTo={setTo}
from={from}
setFrom={setFrom}
promocodes={data?.items ?? []}
createFastLink={createFastLink}
/>
<DeleteModal
id={deleteModal}
setModal={setDeleteModal}
deletePromocode={deletePromocode}
/>
</LocalizationProvider>
);
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<Typography
variant="subtitle1"
sx={{
width: "90%",
height: "60px",
display: "flex",
flexDirection: "column",
justifyContent: "center",
alignItems: "center",
textTransform: "uppercase",
color: theme.palette.secondary.main,
}}
>
Создание промокода
</Typography>
<CreatePromocodeForm createPromocode={createPromocode} />
<Box sx={{ marginTop: "55px", width: "80%", display: "flex" }}>
<FormControl variant="standard" sx={{ m: 1, minWidth: 120 }}>
<Select
labelId="demo-simple-select-standard-label"
id="demo-simple-select-standard"
sx={{
color: "white",
backgroundColor: "transparent",
padding: "5px",
border: "1px solid white",
borderRadius: "4px",
".MuiSelect-icon": {
color: "white",
},
}}
value={active ? "true" : "false"}
onChange={(event: SelectChangeEvent) => {
setActive(event.target.value === "true" ? true : false);
}}
label="Age"
>
<MenuItem value={"true"}>Активные</MenuItem>
<MenuItem value={"false"}>Неактивные</MenuItem>
</Select>
</FormControl>
</Box>
<Box style={{ width: "80%", marginTop: "25px" }}>
<DataGrid
disableSelectionOnClick={true}
rows={data?.items ?? []}
columns={columns}
sx={{
color: theme.palette.secondary.main,
"& .MuiDataGrid-iconSeparator": { display: "none" },
"& .css-levciy-MuiTablePagination-displayedRows": {
color: theme.palette.secondary.main,
},
"& .MuiSvgIcon-root": { color: theme.palette.secondary.main },
"& .MuiTablePagination-selectLabel": {
color: theme.palette.secondary.main,
},
"& .MuiInputBase-root": { color: theme.palette.secondary.main },
"& .MuiButton-text": { color: theme.palette.secondary.main },
"& .MuiDataGrid-overlay": {
backgroundColor: "rgba(255, 255, 255, 0.1)",
animation: `${fadeIn} 0.5s ease-out`,
},
}}
components={{
Toolbar: GridToolbar,
LoadingOverlay: GridLoadingOverlay,
}}
loading={isValidating}
paginationMode="server"
page={page}
onPageChange={setPage}
rowCount={promocodesCount}
pageSize={pageSize}
onPageSizeChange={setPageSize}
rowsPerPageOptions={[10, 25, 50, 100]}
autoHeight
/>
</Box>
<EditModal
id={showEditModalId}
setId={setShowEditModalId}
promocodes={data?.items ?? []}
editPromocode={editPromocode}
/>
<StatisticsModal
id={showStatisticsModalId}
setId={setShowStatisticsModalId}
promocodeStatistics={promocodeStatistics}
to={to}
setTo={setTo}
from={from}
setFrom={setFrom}
promocodes={data?.items ?? []}
createFastLink={createFastLink}
/>
<DeleteModal id={deleteModal} setModal={setDeleteModal} deletePromocode={deletePromocode} />
</LocalizationProvider>
);
};

@ -30,6 +30,7 @@ import ChatDocument from "./ChatDocument";
import ChatVideo from "./ChatVideo";
import ChatMessage from "./ChatMessage";
import { ACCEPT_SEND_MEDIA_TYPES_MAP, MAX_FILE_SIZE, MAX_PHOTO_SIZE, MAX_VIDEO_SIZE } from "./fileUpload";
import { sendFile as sendFileRequest } from "@root/api/tickets";
const tooLarge = "Файл слишком большой";
const checkAcceptableMediaType = (file: File) => {
@ -163,24 +164,18 @@ export default function Chat() {
const sendFile = async (file: File) => {
if (file === undefined) return true;
let data;
const ticketId = ticket?.id;
if (ticketId !== undefined) {
try {
const body = new FormData();
const [_, sendFileError] = await sendFileRequest(file, ticketId);
body.append(file.name, file);
body.append("ticket", ticketId);
await makeRequest({
url: process.env.REACT_APP_DOMAIN + "/heruvym/sendFiles",
body: body,
method: "POST",
});
} catch (error: any) {
const errorMessage = getMessageFromFetchError(error);
if (errorMessage) enqueueSnackbar(errorMessage);
if (sendFileError) {
const errorMessage = getMessageFromFetchError(sendFileError);
if (errorMessage) {
enqueueSnackbar(errorMessage);
}
}
return true;
}
};

@ -5,6 +5,7 @@ import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import makeRequest from "@root/api/makeRequest";
import { parseAxiosError } from "@root/utils/parse-error";
import { closeTicket } from "@root/api/tickets";
interface Props {
ticketId: string | undefined;
openModal: boolean;
@ -12,22 +13,10 @@ interface Props {
}
export default function CloseTicketModal({ ticketId, openModal, setOpenModal }: Props) {
const CloseTicket = async () => {
try {
const ticketCloseResponse = await makeRequest<unknown, unknown>({
url: process.env.REACT_APP_DOMAIN + "/heruvym/close",
method: "post",
useToken: true,
body: {
ticket: ticketId,
},
});
return [ticketCloseResponse];
} catch (nativeError) {
const [error] = parseAxiosError(nativeError);
return [null, `Не удалось закрыть тикет. ${error}`];
const onCloseTicket = async () => {
if (ticketId) {
await closeTicket(ticketId);
setOpenModal(false);
}
};
@ -64,13 +53,7 @@ export default function CloseTicketModal({ ticketId, openModal, setOpenModal }:
alignItems: "center",
}}
>
<Button
onClick={async () => {
CloseTicket();
setOpenModal(false);
}}
sx={{ width: "40px", height: "25px" }}
>
<Button onClick={onCloseTicket} sx={{ width: "40px", height: "25px" }}>
Да
</Button>
<Button onClick={() => setOpenModal(false)} sx={{ width: "40px", height: "25px" }}>

@ -51,9 +51,7 @@ const Header: React.FC = () => {
</Typography>
<IconButton
onClick={() => {
logout().then(clearAuthToken);
}}
onClick={() => logout().then(clearAuthToken)}
sx={{
display: "flex",
flexDirection: "column",

@ -1,6 +1,6 @@
import { Box, Button, TextField, Typography } from "@mui/material";
import { ChangeEvent, useState } from "react";
import makeRequest from "@root/api/makeRequest";
import { moveQuiz } from "@root/api/quiz";
type QuizTabProps = {
userId: string;
@ -25,18 +25,7 @@ export default function QuizTab({ userId }: QuizTabProps) {
setQuizId(event.target.value.split("link/")[1]);
}}
/>
<Button
variant="text"
sx={{ background: "#9A9AAF" }}
onClick={async () => {
await makeRequest({
method: "post",
//useToken: true,
url: process.env.REACT_APP_DOMAIN + "/squiz/quiz/move",
body: { Qid: quizId, AccountID: userId },
});
}}
>
<Button variant="text" sx={{ background: "#9A9AAF" }} onClick={() => moveQuiz(quizId, userId)}>
Ок
</Button>
</Box>

@ -6,7 +6,7 @@ import { useDebouncedCallback } from "use-debounce";
import type { ChangeEvent } from "react";
import type { Verification } from "@root/api/verification";
import makeRequest from "@root/api/makeRequest";
import { editAccount } from "@root/api/account";
type VerificationTabProps = {
userId: string;
@ -58,7 +58,7 @@ export const VerificationTab = ({ userId }: VerificationTabProps) => {
return;
}
const [_, patchVerificationError] = await patchVerification({
const [patchResponse, patchVerificationError] = await patchVerification({
accepted,
comment,
id: verificationInfo._id,
@ -66,13 +66,9 @@ export const VerificationTab = ({ userId }: VerificationTabProps) => {
status: verificationInfo.status,
});
if (accepted && _ === "OK")
await makeRequest({
method: "patch",
useToken: true,
url: process.env.REACT_APP_DOMAIN + `/customer/account/${userId}`,
body: { status: verificationInfo.status },
});
if (accepted && patchResponse === "OK") {
await editAccount(userId, verificationInfo.status);
}
if (patchVerificationError) {
return console.error("Error verifying:", patchVerificationError);

@ -1,6 +1,6 @@
import { setDiscounts } from "@root/stores/discounts";
import { requestDiscounts as requestDiscountsRequest } from "@root/api/discounts";
import { requestDiscounts as requestDiscountsRequest } from "@root/api/discounts/requests";
import type { Discount } from "@frontend/kitui";
const filterDiscounts = (discounts: Discount[]) => {

@ -1,5 +1,5 @@
import { useEffect, useState } from "react";
import { getStatisticPromocode } from "@root/api/quizStatistics";
import { getStatisticsPromocode } from "@root/api/quizStatistics";
import type { Moment } from "moment";
import type { AllPromocodeStatistics } from "@root/api/quizStatistics/types";
@ -18,9 +18,11 @@ export function usePromocodeStatistics({ to, from }: useStatisticProps) {
useEffect(() => {
const requestStatistics = async () => {
const gottenData = await getStatisticPromocode(Number(formatFrom), Number(formatTo));
const [gottenData] = await getStatisticsPromocode(Number(formatFrom), Number(formatTo));
setPromocodeStatistics(gottenData);
if (gottenData) {
setPromocodeStatistics(gottenData);
}
};
requestStatistics();

@ -12,7 +12,7 @@ export function useQuizStatistic({ to, from }: useQuizStatisticProps) {
const formatTo = to?.unix();
const formatFrom = from?.unix();
const [data, setData] = useState<QuizStatisticResponse | null>({
const [data, setData] = useState<QuizStatisticResponse>({
Registrations: 0,
Quizes: 0,
Results: 0,
@ -20,8 +20,11 @@ export function useQuizStatistic({ to, from }: useQuizStatisticProps) {
useEffect(() => {
const requestStatistics = async () => {
const gottenData = await getStatistic(Number(formatTo), Number(formatFrom));
setData(gottenData);
const [gottenData] = await getStatistic(Number(formatTo), Number(formatFrom));
if (gottenData) {
setData(gottenData);
}
};
requestStatistics();

@ -13,9 +13,11 @@ export const useSchildStatistics = (from: Moment | null, to: Moment | null) => {
useEffect(() => {
const StatisticsShild = async () => {
const gottenData = await getStatisticSchild(Number(formatFrom), Number(formatTo));
const [gottenData] = await getStatisticSchild(Number(formatFrom), Number(formatTo));
setStatistics(gottenData);
if (gottenData) {
setStatistics(gottenData);
}
};
StatisticsShild();