feat: new API requests
This commit is contained in:
parent
258c7caaa8
commit
100d6657da
@ -40,7 +40,7 @@ export const getAccountInfo = async (
|
||||
): Promise<[Account | null, string?]> => {
|
||||
try {
|
||||
const accountInfoResponse = await makeRequest<never, Account>({
|
||||
url: `/account${baseUrl}/${id}`,
|
||||
url: `${baseUrl}/account/${id}`,
|
||||
method: "GET",
|
||||
useToken: true,
|
||||
});
|
||||
|
72
src/api/auth.ts
Normal file
72
src/api/auth.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@root/utils/parse-error";
|
||||
|
||||
import type {
|
||||
LoginRequest,
|
||||
RegisterRequest,
|
||||
RegisterResponse,
|
||||
} from "@frontend/kitui";
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production"
|
||||
? "/auth"
|
||||
: "https://admin.pena.digital/auth";
|
||||
|
||||
export const signin = async (
|
||||
login: string,
|
||||
password: string
|
||||
): Promise<[RegisterResponse | null, string?]> => {
|
||||
try {
|
||||
const signinResponse = await makeRequest<LoginRequest, RegisterResponse>({
|
||||
url: baseUrl + "/login",
|
||||
body: { login, password },
|
||||
useToken: false,
|
||||
});
|
||||
|
||||
return [signinResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка авторизации. ${error}`];
|
||||
}
|
||||
};
|
||||
|
||||
export const register = async (
|
||||
login: string,
|
||||
password: string,
|
||||
phoneNumber: string = "--"
|
||||
): Promise<[RegisterResponse | null, string?]> => {
|
||||
try {
|
||||
const registerResponse = await makeRequest<
|
||||
RegisterRequest,
|
||||
RegisterResponse
|
||||
>({
|
||||
url: baseUrl + "/register",
|
||||
body: { login, password, phoneNumber },
|
||||
useToken: false,
|
||||
});
|
||||
|
||||
return [registerResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка регистрации. ${error}`];
|
||||
}
|
||||
};
|
||||
|
||||
export const logout = async (): Promise<[unknown, string?]> => {
|
||||
try {
|
||||
const logoutResponse = await makeRequest<never, unknown>({
|
||||
url: baseUrl + "/logout",
|
||||
method: "post",
|
||||
contentType: true,
|
||||
});
|
||||
|
||||
return [logoutResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка выхода из аккаунта. ${error}`];
|
||||
}
|
||||
};
|
@ -3,7 +3,11 @@ import { makeRequest } from "@frontend/kitui";
|
||||
import { parseAxiosError } from "@root/utils/parse-error";
|
||||
|
||||
import type { Discount } from "@frontend/kitui";
|
||||
import type { CreateDiscountBody, DiscountType } from "@root/model/discount";
|
||||
import type {
|
||||
CreateDiscountBody,
|
||||
DiscountType,
|
||||
GetDiscountResponse,
|
||||
} from "@root/model/discount";
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production"
|
||||
@ -194,3 +198,21 @@ export const patchDiscount = async (
|
||||
return [null, `Ошибка изменения скидки. ${error}`];
|
||||
}
|
||||
};
|
||||
|
||||
export const requestDiscounts = async (): Promise<
|
||||
[GetDiscountResponse | null, string?]
|
||||
> => {
|
||||
try {
|
||||
const discountsResponse = await makeRequest<never, GetDiscountResponse>({
|
||||
url: baseUrl + "/discounts",
|
||||
method: "get",
|
||||
useToken: true,
|
||||
});
|
||||
|
||||
return [discountsResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка получения скидок. ${error}`];
|
||||
}
|
||||
};
|
||||
|
92
src/api/privilegies.ts
Normal file
92
src/api/privilegies.ts
Normal file
@ -0,0 +1,92 @@
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@root/utils/parse-error";
|
||||
|
||||
import { PrivilegeWithAmount } from "@frontend/kitui";
|
||||
import type { TMockData } from "./roles";
|
||||
|
||||
type SeverPrivilegiesResponse = {
|
||||
templategen: PrivilegeWithAmount[];
|
||||
};
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production"
|
||||
? "/strator"
|
||||
: "https://admin.pena.digital/strator";
|
||||
|
||||
export const getRoles = async (): Promise<[TMockData | null, string?]> => {
|
||||
try {
|
||||
const rolesResponse = await makeRequest<never, TMockData>({
|
||||
method: "get",
|
||||
url: baseUrl + "/role",
|
||||
});
|
||||
|
||||
return [rolesResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка запроса ролей. ${error}`];
|
||||
}
|
||||
};
|
||||
|
||||
export const putPrivilegie = async (
|
||||
body: Omit<PrivilegeWithAmount, "_id" | "updatedAt">
|
||||
): Promise<[unknown, string?]> => {
|
||||
try {
|
||||
const putedPrivilegie = await makeRequest<
|
||||
Omit<PrivilegeWithAmount, "_id" | "updatedAt">,
|
||||
unknown
|
||||
>({
|
||||
url: baseUrl + "/privilege",
|
||||
method: "put",
|
||||
body,
|
||||
});
|
||||
|
||||
return [putedPrivilegie];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка изменения привилегии. ${error}`];
|
||||
}
|
||||
};
|
||||
|
||||
export const requestServicePrivilegies = async (): Promise<
|
||||
[SeverPrivilegiesResponse | null, string?]
|
||||
> => {
|
||||
try {
|
||||
const privilegiesResponse = await makeRequest<
|
||||
never,
|
||||
SeverPrivilegiesResponse
|
||||
>({
|
||||
url: baseUrl + "/privilege/service",
|
||||
method: "get",
|
||||
});
|
||||
|
||||
return [privilegiesResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка запроса привилегий. ${error}`];
|
||||
}
|
||||
};
|
||||
|
||||
export const requestPrivilegies = async (
|
||||
signal: AbortSignal | undefined
|
||||
): Promise<[PrivilegeWithAmount[], string?]> => {
|
||||
try {
|
||||
const privilegiesResponse = await makeRequest<never, PrivilegeWithAmount[]>(
|
||||
{
|
||||
url: baseUrl + "/privilege",
|
||||
method: "get",
|
||||
useToken: true,
|
||||
signal,
|
||||
}
|
||||
);
|
||||
|
||||
return [privilegiesResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [[], `Ошибка запроса привилегий. ${error}`];
|
||||
}
|
||||
};
|
@ -1,3 +1,7 @@
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@root/utils/parse-error";
|
||||
|
||||
export const MOCK_DATA_USERS = [
|
||||
{
|
||||
key: 0,
|
||||
@ -31,6 +35,11 @@ export type UserType = {
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production"
|
||||
? "/role"
|
||||
: "https://admin.pena.digital/role";
|
||||
|
||||
export const getRoles_mock = (): Promise<TMockData> => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
@ -38,3 +47,18 @@ export const getRoles_mock = (): Promise<TMockData> => {
|
||||
}, 1000);
|
||||
});
|
||||
};
|
||||
|
||||
export const deleteRole = async (id: string): Promise<[unknown, string?]> => {
|
||||
try {
|
||||
const deleteRoleResponse = await makeRequest({
|
||||
url: `${baseUrl}/${id}`,
|
||||
method: "delete",
|
||||
});
|
||||
|
||||
return [deleteRoleResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка удаления роли. ${error}`];
|
||||
}
|
||||
};
|
||||
|
@ -2,14 +2,49 @@ import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@root/utils/parse-error";
|
||||
|
||||
import type { PrivilegeWithAmount } from "@frontend/kitui";
|
||||
import type { Tariff } from "@frontend/kitui";
|
||||
import type { EditTariffRequestBody } from "@root/model/tariff";
|
||||
|
||||
type CreateTariffBackendRequest = {
|
||||
name: string;
|
||||
price: number;
|
||||
isCustom: boolean;
|
||||
privilegies: Omit<PrivilegeWithAmount, "_id" | "updatedAt">[];
|
||||
};
|
||||
|
||||
type GetTariffsResponse = {
|
||||
totalPages: number;
|
||||
tariffs: Tariff[];
|
||||
};
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production"
|
||||
? "/strator"
|
||||
: "https://admin.pena.digital/strator";
|
||||
|
||||
export const createTariff = async (
|
||||
body: CreateTariffBackendRequest
|
||||
): Promise<[unknown, string?]> => {
|
||||
try {
|
||||
const createdTariffResponse = await makeRequest<CreateTariffBackendRequest>(
|
||||
{
|
||||
url: baseUrl + "/tariff/",
|
||||
method: "post",
|
||||
body,
|
||||
}
|
||||
);
|
||||
|
||||
debugger;
|
||||
|
||||
return [createdTariffResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка создания тарифа. ${error}`];
|
||||
}
|
||||
};
|
||||
|
||||
export const putTariff = async (tariff: Tariff): Promise<[null, string?]> => {
|
||||
try {
|
||||
const putedTariffResponse = await makeRequest<EditTariffRequestBody, null>({
|
||||
@ -49,22 +84,19 @@ export const deleteTariff = async (
|
||||
}
|
||||
};
|
||||
|
||||
export async function deleteManyTariffs(tariffIds: string[]) {
|
||||
const results = await Promise.allSettled(
|
||||
tariffIds.map((tariffId) => deleteTariff(tariffId))
|
||||
);
|
||||
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",
|
||||
});
|
||||
|
||||
let deletedCount = 0;
|
||||
let errorCount = 0;
|
||||
const errors: unknown[] = [];
|
||||
return [tariffsResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
results.forEach((result) => {
|
||||
if (result.status === "fulfilled") deletedCount++;
|
||||
else {
|
||||
errorCount++;
|
||||
errors.push(result.reason);
|
||||
}
|
||||
});
|
||||
|
||||
return { deletedCount, errorCount, errors };
|
||||
}
|
||||
return [null, `Ошибка запроса тарифов. ${error}`];
|
||||
}
|
||||
};
|
||||
|
@ -4,6 +4,11 @@ import { parseAxiosError } from "@root/utils/parse-error";
|
||||
|
||||
import type { UserType } from "@root/api/roles";
|
||||
|
||||
type RegisteredUsersResponse = {
|
||||
tatalPages: number;
|
||||
users: UserType[];
|
||||
};
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production"
|
||||
? "/user"
|
||||
@ -26,3 +31,43 @@ export const getUserInfo = async (
|
||||
return [null, `Ошибка получения информации о пользователе. ${error}`];
|
||||
}
|
||||
};
|
||||
|
||||
export const getRegisteredUsers = async (): Promise<
|
||||
[RegisteredUsersResponse | null, string?]
|
||||
> => {
|
||||
try {
|
||||
const registeredUsersResponse = await makeRequest<
|
||||
never,
|
||||
RegisteredUsersResponse
|
||||
>({
|
||||
method: "get",
|
||||
url: baseUrl + "/",
|
||||
});
|
||||
|
||||
return [registeredUsersResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка при получении пользователей. ${error}`];
|
||||
}
|
||||
};
|
||||
|
||||
export const getManagersList = async (): Promise<
|
||||
[RegisteredUsersResponse | null, string?]
|
||||
> => {
|
||||
try {
|
||||
const managersListResponse = await makeRequest<
|
||||
never,
|
||||
RegisteredUsersResponse
|
||||
>({
|
||||
method: "get",
|
||||
url: baseUrl + "/",
|
||||
});
|
||||
|
||||
return [managersListResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка при получении менеджеров. ${error}`];
|
||||
}
|
||||
};
|
||||
|
68
src/api/verification.ts
Normal file
68
src/api/verification.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@root/utils/parse-error";
|
||||
|
||||
type File = {
|
||||
name: "inn" | "rule" | "egrule" | "certificate";
|
||||
url: string;
|
||||
};
|
||||
|
||||
export type Verification = {
|
||||
_id: string;
|
||||
accepted: boolean;
|
||||
status: "org" | "nko";
|
||||
updated_at: string;
|
||||
comment: string;
|
||||
files: File[];
|
||||
};
|
||||
|
||||
type PatchVerificationBody = {
|
||||
id: string;
|
||||
status: "org" | "nko";
|
||||
comment: string;
|
||||
accepted: boolean;
|
||||
};
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production"
|
||||
? "/verification"
|
||||
: "https://admin.pena.digital/verification";
|
||||
|
||||
export const verification = async (
|
||||
userId: string
|
||||
): Promise<[Verification | null, string?]> => {
|
||||
try {
|
||||
const verificationResponse = await makeRequest<never, Verification>({
|
||||
method: "get",
|
||||
url: baseUrl + `/verification/${userId}`,
|
||||
});
|
||||
|
||||
return [verificationResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка верификации. ${error}`];
|
||||
}
|
||||
};
|
||||
|
||||
export const patchVerification = async (
|
||||
body: PatchVerificationBody
|
||||
): Promise<[unknown, string?]> => {
|
||||
try {
|
||||
const patchedVerificationResponse = await makeRequest<
|
||||
PatchVerificationBody,
|
||||
unknown
|
||||
>({
|
||||
method: "patch",
|
||||
useToken: true,
|
||||
url: baseUrl + `/verification/verification`,
|
||||
body,
|
||||
});
|
||||
|
||||
return [patchedVerificationResponse];
|
||||
} catch (nativeError) {
|
||||
const [error] = parseAxiosError(nativeError);
|
||||
|
||||
return [null, `Ошибка изменения верификации. ${error}`];
|
||||
}
|
||||
};
|
@ -44,9 +44,7 @@ export default function Cart() {
|
||||
|
||||
async function handleCalcCartClick() {
|
||||
await requestPrivilegies();
|
||||
try {
|
||||
discounts = await requestDiscounts();
|
||||
} catch { }
|
||||
await requestDiscounts();
|
||||
|
||||
const cartTariffs = tariffs.filter(tariff => selectedTariffIds.includes(tariff._id));
|
||||
|
||||
|
@ -3,12 +3,18 @@ import { enqueueSnackbar } from "notistack";
|
||||
import { useTheme } from "@mui/material/styles";
|
||||
import { Formik, Field, Form, FormikHelpers } from "formik";
|
||||
import { Link } from "react-router-dom";
|
||||
import { Box, Checkbox, Typography, FormControlLabel, Button } from "@mui/material";
|
||||
import {
|
||||
Box,
|
||||
Checkbox,
|
||||
Typography,
|
||||
FormControlLabel,
|
||||
Button,
|
||||
} from "@mui/material";
|
||||
import Logo from "@pages/Logo";
|
||||
import OutlinedInput from "@kitUI/outlinedInput";
|
||||
import EmailOutlinedIcon from "@mui/icons-material/EmailOutlined";
|
||||
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import { signin } from "@root/api/auth";
|
||||
|
||||
interface Values {
|
||||
email: string;
|
||||
@ -44,30 +50,29 @@ const SigninForm = () => {
|
||||
password: "",
|
||||
};
|
||||
|
||||
const onSignFormSubmit = (values: Values, formikHelpers: FormikHelpers<Values>) => {
|
||||
const onSignFormSubmit = async (
|
||||
values: Values,
|
||||
formikHelpers: FormikHelpers<Values>
|
||||
) => {
|
||||
formikHelpers.setSubmitting(true);
|
||||
makeRequest({
|
||||
url: "https://admin.pena.digital/auth/login",
|
||||
body: {
|
||||
login: values.email,
|
||||
password: values.password,
|
||||
},
|
||||
useToken: false,
|
||||
})
|
||||
.then((e) => {
|
||||
navigate("/users");
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
enqueueSnackbar(e.message ? e.message : `Unknown error`);
|
||||
})
|
||||
.finally(() => {
|
||||
formikHelpers.setSubmitting(false);
|
||||
});
|
||||
|
||||
const [_, signinError] = await signin(values.email, values.password);
|
||||
|
||||
formikHelpers.setSubmitting(false);
|
||||
|
||||
if (signinError) {
|
||||
return enqueueSnackbar(signinError);
|
||||
}
|
||||
|
||||
navigate("/users");
|
||||
};
|
||||
|
||||
return (
|
||||
<Formik initialValues={initialValues} validate={validate} onSubmit={onSignFormSubmit}>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validate={validate}
|
||||
onSubmit={onSignFormSubmit}
|
||||
>
|
||||
{(props) => (
|
||||
<Form>
|
||||
<Box
|
||||
@ -105,7 +110,14 @@ const SigninForm = () => {
|
||||
Мы рады что вы выбрали нас!
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", marginTop: "15px", "> *": { marginRight: "10px" } }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
marginTop: "15px",
|
||||
"> *": { marginRight: "10px" },
|
||||
}}
|
||||
>
|
||||
<EmailOutlinedIcon htmlColor={theme.palette.golden.main} />
|
||||
<Field
|
||||
as={OutlinedInput}
|
||||
@ -120,7 +132,14 @@ const SigninForm = () => {
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", marginTop: "15px", "> *": { marginRight: "10px" } }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
marginTop: "15px",
|
||||
"> *": { marginRight: "10px" },
|
||||
}}
|
||||
>
|
||||
<LockOutlinedIcon htmlColor={theme.palette.golden.main} />
|
||||
<Field
|
||||
as={OutlinedInput}
|
||||
@ -165,7 +184,9 @@ const SigninForm = () => {
|
||||
/>
|
||||
</Box>
|
||||
<Link to="/restore" style={{ textDecoration: "none" }}>
|
||||
<Typography color={theme.palette.golden.main}>Забыли пароль?</Typography>
|
||||
<Typography color={theme.palette.golden.main}>
|
||||
Забыли пароль?
|
||||
</Typography>
|
||||
</Link>
|
||||
<Button
|
||||
type="submit"
|
||||
@ -184,9 +205,13 @@ const SigninForm = () => {
|
||||
display: "flex",
|
||||
}}
|
||||
>
|
||||
<Typography color={theme.palette.secondary.main}>У вас нет аккаунта? </Typography>
|
||||
<Typography color={theme.palette.secondary.main}>
|
||||
У вас нет аккаунта?
|
||||
</Typography>
|
||||
<Link to="/signup" style={{ textDecoration: "none" }}>
|
||||
<Typography color={theme.palette.golden.main}>Зарегестрируйтесь</Typography>
|
||||
<Typography color={theme.palette.golden.main}>
|
||||
Зарегестрируйтесь
|
||||
</Typography>
|
||||
</Link>
|
||||
</Box>
|
||||
</Box>
|
||||
|
@ -9,7 +9,7 @@ import OutlinedInput from "@kitUI/outlinedInput";
|
||||
import Logo from "@pages/Logo/index";
|
||||
import EmailOutlinedIcon from "@mui/icons-material/EmailOutlined";
|
||||
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import { register } from "@root/api/auth";
|
||||
|
||||
interface Values {
|
||||
email: string;
|
||||
@ -39,8 +39,8 @@ function validate(values: Values) {
|
||||
}
|
||||
|
||||
const SignUp = () => {
|
||||
const navigate = useNavigate();
|
||||
const theme = useTheme();
|
||||
const navigate = useNavigate();
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<Formik
|
||||
@ -50,31 +50,21 @@ const SignUp = () => {
|
||||
repeatPassword: "",
|
||||
}}
|
||||
validate={validate}
|
||||
onSubmit={(values, formikHelpers) => {
|
||||
onSubmit={async (values, formikHelpers) => {
|
||||
formikHelpers.setSubmitting(true);
|
||||
makeRequest({
|
||||
url: "https://admin.pena.digital/auth/register",
|
||||
body: {
|
||||
login: values.email,
|
||||
email: values.email,
|
||||
password: values.repeatPassword,
|
||||
phoneNumber: "--",
|
||||
},
|
||||
useToken: false,
|
||||
})
|
||||
.then((e) => {
|
||||
navigate("/users");
|
||||
})
|
||||
.catch((e) => {
|
||||
console.log(e);
|
||||
enqueueSnackbar(
|
||||
e.response && e.response.data && e.response.data.message ? e.response.data.message : `Unknown error`,
|
||||
{ variant: "error" } // Устанавливаем вариант уведомления на "error"
|
||||
);
|
||||
})
|
||||
.finally(() => {
|
||||
formikHelpers.setSubmitting(false);
|
||||
});
|
||||
|
||||
const [_, registerError] = await register(
|
||||
values.email,
|
||||
values.repeatPassword
|
||||
);
|
||||
|
||||
formikHelpers.setSubmitting(false);
|
||||
|
||||
if (registerError) {
|
||||
return enqueueSnackbar(registerError);
|
||||
}
|
||||
|
||||
navigate("/users");
|
||||
}}
|
||||
>
|
||||
{(props) => (
|
||||
@ -118,7 +108,14 @@ const SignUp = () => {
|
||||
Мы рады что вы выбрали нас!
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", marginTop: "15px", "> *": { marginRight: "10px" } }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
marginTop: "15px",
|
||||
"> *": { marginRight: "10px" },
|
||||
}}
|
||||
>
|
||||
<EmailOutlinedIcon htmlColor={theme.palette.golden.main} />
|
||||
<Field
|
||||
as={OutlinedInput}
|
||||
@ -134,7 +131,14 @@ const SignUp = () => {
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", marginTop: "15px", "> *": { marginRight: "10px" } }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
marginTop: "15px",
|
||||
"> *": { marginRight: "10px" },
|
||||
}}
|
||||
>
|
||||
<LockOutlinedIcon htmlColor={theme.palette.golden.main} />
|
||||
<Field
|
||||
sx={{}}
|
||||
@ -152,7 +156,14 @@ const SignUp = () => {
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{ display: "flex", alignItems: "center", marginTop: "15px", "> *": { marginRight: "10px" } }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
marginTop: "15px",
|
||||
"> *": { marginRight: "10px" },
|
||||
}}
|
||||
>
|
||||
<LockOutlinedIcon htmlColor={theme.palette.golden.main} />
|
||||
<Field
|
||||
as={OutlinedInput}
|
||||
@ -161,10 +172,14 @@ const SignUp = () => {
|
||||
variant="filled"
|
||||
label="Повторите пароль"
|
||||
id="repeatPassword"
|
||||
error={props.touched.repeatPassword && !!props.errors.repeatPassword}
|
||||
error={
|
||||
props.touched.repeatPassword &&
|
||||
!!props.errors.repeatPassword
|
||||
}
|
||||
helperText={
|
||||
<Typography sx={{ fontSize: "12px", width: "200px" }}>
|
||||
{props.touched.repeatPassword && props.errors.repeatPassword}
|
||||
{props.touched.repeatPassword &&
|
||||
props.errors.repeatPassword}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
@ -182,7 +197,9 @@ const SignUp = () => {
|
||||
Войти
|
||||
</Button>
|
||||
<Link to="/signin" style={{ textDecoration: "none" }}>
|
||||
<Typography color={theme.palette.golden.main}>У меня уже есть аккаунт</Typography>
|
||||
<Typography color={theme.palette.golden.main}>
|
||||
У меня уже есть аккаунт
|
||||
</Typography>
|
||||
</Link>
|
||||
</Box>
|
||||
</Box>
|
||||
|
@ -2,163 +2,158 @@ import { useRef, useState } from "react";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
import { Box, IconButton, TextField, Tooltip, Typography } from "@mui/material";
|
||||
import ModeEditOutlineOutlinedIcon from "@mui/icons-material/ModeEditOutlineOutlined";
|
||||
import { PrivilegeWithAmount, makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { PrivilegeWithAmount } from "@frontend/kitui";
|
||||
import { putPrivilegie } from "@root/api/privilegies";
|
||||
|
||||
interface CardPrivilegie {
|
||||
privilege: PrivilegeWithAmount;
|
||||
privilege: PrivilegeWithAmount;
|
||||
}
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production"
|
||||
? "/strator"
|
||||
: "https://admin.pena.digital/strator";
|
||||
|
||||
export const СardPrivilegie = ({ privilege }: CardPrivilegie) => {
|
||||
const [inputOpen, setInputOpen] = useState<boolean>(false);
|
||||
const [inputValue, setInputValue] = useState<string>("");
|
||||
const priceRef = useRef<any>(null);
|
||||
const [inputOpen, setInputOpen] = useState<boolean>(false);
|
||||
const [inputValue, setInputValue] = useState<string>("");
|
||||
const priceRef = useRef<any>(null);
|
||||
|
||||
const translationType = {
|
||||
count: "за единицу",
|
||||
day: "за день",
|
||||
mb: "за МБ",
|
||||
};
|
||||
const translationType = {
|
||||
count: "за единицу",
|
||||
day: "за день",
|
||||
mb: "за МБ",
|
||||
};
|
||||
|
||||
const PutPrivilegies = () => {
|
||||
makeRequest<Omit<PrivilegeWithAmount, "_id" | "updatedAt">>({
|
||||
url: baseUrl + "/privilege/",
|
||||
method: "put",
|
||||
body: {
|
||||
name: privilege.name,
|
||||
privilegeId: privilege.privilegeId,
|
||||
serviceKey: privilege.serviceKey,
|
||||
description: privilege.description,
|
||||
amount: 1,
|
||||
type: privilege.type,
|
||||
value: privilege.value,
|
||||
price: Number(inputValue),
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
priceRef.current.innerText = "price: " + inputValue;
|
||||
setInputValue("");
|
||||
setInputOpen(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
enqueueSnackbar(error.message);
|
||||
});
|
||||
};
|
||||
const putPrivilegies = async () => {
|
||||
const [_, putedPrivilegieError] = await putPrivilegie({
|
||||
name: privilege.name,
|
||||
privilegeId: privilege.privilegeId,
|
||||
serviceKey: privilege.serviceKey,
|
||||
description: privilege.description,
|
||||
amount: 1,
|
||||
type: privilege.type,
|
||||
value: privilege.value,
|
||||
price: Number(inputValue),
|
||||
});
|
||||
|
||||
const requestOnclickEnter = (event: any) => {
|
||||
if (event.key === "Enter" && inputValue !== "") {
|
||||
PutPrivilegies();
|
||||
setInputOpen(false);
|
||||
}
|
||||
};
|
||||
if (putedPrivilegieError) {
|
||||
return enqueueSnackbar(putedPrivilegieError);
|
||||
}
|
||||
|
||||
const onCloseInput = (event: any) => {
|
||||
if (event.key === "Escape") {
|
||||
setInputOpen(false);
|
||||
}
|
||||
};
|
||||
priceRef.current.innerText = "price: " + inputValue;
|
||||
setInputValue("");
|
||||
setInputOpen(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
key={privilege.type}
|
||||
const requestOnclickEnter = (event: any) => {
|
||||
if (event.key === "Enter" && inputValue !== "") {
|
||||
putPrivilegies();
|
||||
setInputOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
const onCloseInput = (event: any) => {
|
||||
if (event.key === "Escape") {
|
||||
setInputOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
key={privilege.type}
|
||||
sx={{
|
||||
px: "20px",
|
||||
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
border: "1px solid gray",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: "flex", borderRight: "1px solid gray" }}>
|
||||
<Box sx={{ width: "200px", py: "25px" }}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
sx={{
|
||||
px: "20px",
|
||||
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
border: "1px solid gray",
|
||||
color: "#fe9903",
|
||||
overflowWrap: "break-word",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: "flex", borderRight: "1px solid gray" }}>
|
||||
<Box sx={{ width: "200px", py: "25px" }}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
sx={{
|
||||
color: "#fe9903",
|
||||
overflowWrap: "break-word",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{privilege.name}
|
||||
</Typography>
|
||||
<Tooltip
|
||||
sx={{
|
||||
span: {
|
||||
fontSize: "1rem",
|
||||
},
|
||||
}}
|
||||
placement="top"
|
||||
title={
|
||||
<Typography sx={{ fontSize: "16px" }}>{privilege.description}</Typography>
|
||||
}
|
||||
>
|
||||
<IconButton disableRipple>
|
||||
<svg
|
||||
width="40"
|
||||
height="40"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.25 9.25H10V14.5H10.75"
|
||||
stroke="#7E2AEA"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M9.8125 7C10.4338 7 10.9375 6.49632 10.9375 5.875C10.9375 5.25368 10.4338 4.75 9.8125 4.75C9.19118 4.75 8.6875 5.25368 8.6875 5.875C8.6875 6.49632 9.19118 7 9.8125 7Z"
|
||||
fill="#7E2AEA"
|
||||
/>
|
||||
</svg>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<IconButton onClick={() => setInputOpen(!inputOpen)}>
|
||||
<ModeEditOutlineOutlinedIcon sx={{ color: "gray" }} />
|
||||
</IconButton>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{ width: "600px", display: "flex", justifyContent: "space-around" }}
|
||||
>
|
||||
{inputOpen ? (
|
||||
<TextField
|
||||
type="number"
|
||||
onKeyDown={onCloseInput}
|
||||
onKeyPress={requestOnclickEnter}
|
||||
placeholder="введите число"
|
||||
fullWidth
|
||||
onChange={(event) => setInputValue(event.target.value)}
|
||||
sx={{
|
||||
alignItems: "center",
|
||||
width: "400px",
|
||||
"& .MuiInputBase-root": {
|
||||
backgroundColor: "#F2F3F7",
|
||||
height: "48px",
|
||||
},
|
||||
}}
|
||||
inputProps={{
|
||||
sx: {
|
||||
borderRadius: "10px",
|
||||
fontSize: "18px",
|
||||
lineHeight: "21px",
|
||||
py: 0,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div ref={priceRef} style={{ color: "white", marginRight: "5px" }}>
|
||||
price: {privilege.price}
|
||||
</div>
|
||||
)}
|
||||
<Typography sx={{ color: "white" }}>{translationType[privilege.type]}</Typography>
|
||||
</Box>
|
||||
>
|
||||
{privilege.name}
|
||||
</Typography>
|
||||
<Tooltip
|
||||
sx={{
|
||||
span: {
|
||||
fontSize: "1rem",
|
||||
},
|
||||
}}
|
||||
placement="top"
|
||||
title={
|
||||
<Typography sx={{ fontSize: "16px" }}>
|
||||
{privilege.description}
|
||||
</Typography>
|
||||
}
|
||||
>
|
||||
<IconButton disableRipple>
|
||||
<svg
|
||||
width="40"
|
||||
height="40"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M9.25 9.25H10V14.5H10.75"
|
||||
stroke="#7E2AEA"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M9.8125 7C10.4338 7 10.9375 6.49632 10.9375 5.875C10.9375 5.25368 10.4338 4.75 9.8125 4.75C9.19118 4.75 8.6875 5.25368 8.6875 5.875C8.6875 6.49632 9.19118 7 9.8125 7Z"
|
||||
fill="#7E2AEA"
|
||||
/>
|
||||
</svg>
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<IconButton onClick={() => setInputOpen(!inputOpen)}>
|
||||
<ModeEditOutlineOutlinedIcon sx={{ color: "gray" }} />
|
||||
</IconButton>
|
||||
</Box>
|
||||
);
|
||||
</Box>
|
||||
<Box
|
||||
sx={{ width: "600px", display: "flex", justifyContent: "space-around" }}
|
||||
>
|
||||
{inputOpen ? (
|
||||
<TextField
|
||||
type="number"
|
||||
onKeyDown={onCloseInput}
|
||||
onKeyPress={requestOnclickEnter}
|
||||
placeholder="введите число"
|
||||
fullWidth
|
||||
onChange={(event) => setInputValue(event.target.value)}
|
||||
sx={{
|
||||
alignItems: "center",
|
||||
width: "400px",
|
||||
"& .MuiInputBase-root": {
|
||||
backgroundColor: "#F2F3F7",
|
||||
height: "48px",
|
||||
},
|
||||
}}
|
||||
inputProps={{
|
||||
sx: {
|
||||
borderRadius: "10px",
|
||||
fontSize: "18px",
|
||||
lineHeight: "21px",
|
||||
py: 0,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div ref={priceRef} style={{ color: "white", marginRight: "5px" }}>
|
||||
price: {privilege.price}
|
||||
</div>
|
||||
)}
|
||||
<Typography sx={{ color: "white" }}>
|
||||
{translationType[privilege.type]}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
@ -10,7 +10,8 @@ import {
|
||||
TextField,
|
||||
} from "@mui/material";
|
||||
import { MOCK_DATA_USERS } from "@root/api/roles";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import { deleteRole } from "@root/api/roles";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
|
||||
const ITEM_HEIGHT = 48;
|
||||
const ITEM_PADDING_TOP = 8;
|
||||
@ -22,9 +23,6 @@ const MenuProps = {
|
||||
},
|
||||
};
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production" ? "" : "https://admin.pena.digital";
|
||||
|
||||
export default function DeleteForm() {
|
||||
const [personName, setPersonName] = useState<string[]>([]);
|
||||
const [roleId, setRoleId] = useState<string>();
|
||||
@ -36,9 +34,14 @@ export default function DeleteForm() {
|
||||
setPersonName(typeof value === "string" ? value.split(",") : value);
|
||||
};
|
||||
|
||||
const rolesDelete = (id = "") => {
|
||||
makeRequest({ url: baseUrl + "/role/" + id, method: "delete" });
|
||||
const rolesDelete = async (id = "") => {
|
||||
const [_, deletedRoleError] = await deleteRole(id);
|
||||
|
||||
if (deletedRoleError) {
|
||||
return enqueueSnackbar(deletedRoleError);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
|
@ -22,11 +22,14 @@ export default function DiscountDataGrid({ selectedRows }: Props) {
|
||||
return enqueueSnackbar("Скидка не найдена");
|
||||
}
|
||||
|
||||
try {
|
||||
await changeDiscount(String(id), { ...discount, Deprecated: isActive });
|
||||
const [_, changedDiscountError] = await changeDiscount(String(id), {
|
||||
...discount,
|
||||
Deprecated: isActive,
|
||||
});
|
||||
|
||||
if (changedDiscountError) {
|
||||
done += 1;
|
||||
} catch {
|
||||
} else {
|
||||
fatal += 1;
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,25 @@
|
||||
import { useState } from "react";
|
||||
import { Typography, Container, Button, Select, MenuItem, FormControl, InputLabel, useTheme, Box } from "@mui/material";
|
||||
import {
|
||||
Typography,
|
||||
Container,
|
||||
Button,
|
||||
Select,
|
||||
MenuItem,
|
||||
FormControl,
|
||||
InputLabel,
|
||||
useTheme,
|
||||
Box,
|
||||
} from "@mui/material";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
|
||||
import { CustomTextField } from "@root/kitUI/CustomTextField";
|
||||
import { requestTariffs } from "@root/services/tariffs.service";
|
||||
import { createTariff } from "@root/api/tariffs";
|
||||
|
||||
import {
|
||||
findPrivilegeById,
|
||||
usePrivilegeStore,
|
||||
} from "@root/stores/privilegesStore";
|
||||
import { PrivilegeWithAmount, makeRequest } from "@frontend/kitui";
|
||||
|
||||
|
||||
type CreateTariffBackendRequest = {
|
||||
name: string;
|
||||
price: number;
|
||||
isCustom: boolean;
|
||||
privilegies: Omit<PrivilegeWithAmount, "_id" | "updatedAt">[];
|
||||
};
|
||||
|
||||
const baseUrl = process.env.NODE_ENV === "production" ? "/strator" : "https://admin.pena.digital/strator";
|
||||
|
||||
export default function CreateTariff() {
|
||||
const theme = useTheme();
|
||||
@ -53,35 +53,31 @@ export default function CreateTariff() {
|
||||
return true;
|
||||
};
|
||||
|
||||
const createTariffBackend = () => {
|
||||
const createTariffBackend = async () => {
|
||||
if (checkFulledFields() && privilege !== null) {
|
||||
makeRequest<CreateTariffBackendRequest>({
|
||||
url: baseUrl + "/tariff/",
|
||||
method: "post",
|
||||
body: {
|
||||
name: nameField,
|
||||
price: Number(customPriceField) * 100,
|
||||
isCustom: false,
|
||||
privilegies: [
|
||||
{
|
||||
name: privilege.name,
|
||||
privilegeId: privilege.privilegeId ?? "",
|
||||
serviceKey: privilege.serviceKey,
|
||||
description: privilege.description,
|
||||
type: privilege.type,
|
||||
value: privilege.value ?? "",
|
||||
price: privilege.price,
|
||||
amount: Number(amountField),
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
requestTariffs();
|
||||
})
|
||||
.catch(() => {
|
||||
enqueueSnackbar("что-то пошло не так");
|
||||
});
|
||||
const [_, createdTariffError] = await createTariff({
|
||||
name: nameField,
|
||||
price: Number(customPriceField) * 100,
|
||||
isCustom: false,
|
||||
privilegies: [
|
||||
{
|
||||
name: privilege.name,
|
||||
privilegeId: privilege.privilegeId ?? "",
|
||||
serviceKey: privilege.serviceKey,
|
||||
description: privilege.description,
|
||||
type: privilege.type,
|
||||
value: privilege.value ?? "",
|
||||
price: privilege.price,
|
||||
amount: Number(amountField),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
if (createdTariffError) {
|
||||
return enqueueSnackbar(createdTariffError);
|
||||
}
|
||||
|
||||
requestTariffs();
|
||||
}
|
||||
};
|
||||
// const createTariffFrontend = () => {
|
||||
|
@ -5,13 +5,33 @@ import Modal from "@mui/material/Modal";
|
||||
import { closeDeleteTariffDialog, useTariffStore } from "@root/stores/tariffs";
|
||||
import { requestTariffs } from "@root/services/tariffs.service";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
import { deleteManyTariffs } from "@root/api/tariffs";
|
||||
import { deleteTariff } from "@root/api/tariffs";
|
||||
import { devlog } from "@frontend/kitui";
|
||||
|
||||
|
||||
export default function DeleteModal() {
|
||||
const deleteTariffIds = useTariffStore(state => state.deleteTariffIds);
|
||||
|
||||
async function deleteManyTariffs(tariffIds: string[]) {
|
||||
const results = await Promise.allSettled(
|
||||
tariffIds.map((tariffId) => deleteTariff(tariffId))
|
||||
);
|
||||
|
||||
let deletedCount = 0;
|
||||
let errorCount = 0;
|
||||
const errors: unknown[] = [];
|
||||
|
||||
results.forEach((result) => {
|
||||
if (result.status === "fulfilled") deletedCount++;
|
||||
else {
|
||||
errorCount++;
|
||||
errors.push(result.reason);
|
||||
}
|
||||
});
|
||||
|
||||
return { deletedCount, errorCount, errors };
|
||||
}
|
||||
|
||||
async function handleTariffDeleteClick() {
|
||||
if (!deleteTariffIds?.length) return;
|
||||
|
||||
|
@ -24,29 +24,16 @@ import ClearIcon from "@mui/icons-material/Clear";
|
||||
import ConditionalRender from "@root/pages/Setting/ConditionalRender";
|
||||
import ModalUser from "@root/pages/dashboard/ModalUser";
|
||||
import ServiceUsersDG from "./ServiceUsersDG";
|
||||
import { getRegisteredUsers, getManagersList } from "@root/api/user";
|
||||
import { getRoles } from "@root/api/privilegies";
|
||||
|
||||
import { getRoles_mock, TMockData } from "../../../api/roles";
|
||||
|
||||
import theme from "../../../theme";
|
||||
|
||||
import type { UserType } from "../../../api/roles";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
type RegisteredUsersResponse = {
|
||||
tatalPages: number;
|
||||
users: UserType[];
|
||||
};
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production" ? "" : "https://admin.pena.digital";
|
||||
|
||||
const Users: React.FC = () => {
|
||||
// makeRequest({
|
||||
// url: "https://admin.pena.digital/strator/account",
|
||||
// method: "get",
|
||||
// bearer: true,
|
||||
// contentType: true,
|
||||
// })
|
||||
const radioboxes = ["admin", "manager", "user"];
|
||||
|
||||
const [selectedValue, setSelectedValue] = React.useState("admin");
|
||||
@ -109,47 +96,23 @@ const Users: React.FC = () => {
|
||||
}, [userId]);
|
||||
|
||||
useEffect(() => {
|
||||
async function axiosRoles() {
|
||||
try {
|
||||
const rolesResponse = await makeRequest<never, TMockData>({
|
||||
method: "get",
|
||||
url: baseUrl + "/strator/role/",
|
||||
});
|
||||
getManagersList().then(([managersListResponse]) => {
|
||||
if (managersListResponse) {
|
||||
setManager(managersListResponse.users);
|
||||
}
|
||||
});
|
||||
|
||||
getRegisteredUsers().then(([registeredUsersResponse]) => {
|
||||
if (registeredUsersResponse) {
|
||||
setUsers(registeredUsersResponse.users);
|
||||
}
|
||||
});
|
||||
|
||||
getRoles().then(([rolesResponse]) => {
|
||||
if (rolesResponse) {
|
||||
setRoles(rolesResponse);
|
||||
} catch (error) {
|
||||
console.error("Ошибка при получении ролей!");
|
||||
}
|
||||
}
|
||||
async function gettingRegisteredUsers() {
|
||||
try {
|
||||
const { users } = await makeRequest<never, RegisteredUsersResponse>({
|
||||
method: "get",
|
||||
url: baseUrl + "/user/",
|
||||
});
|
||||
|
||||
setUsers(users);
|
||||
} catch (error) {
|
||||
console.error("Ошибка при получении пользователей!");
|
||||
}
|
||||
}
|
||||
|
||||
async function gettingListManagers() {
|
||||
try {
|
||||
const { users } = await makeRequest<never, RegisteredUsersResponse>({
|
||||
method: "get",
|
||||
url: baseUrl + "/user/",
|
||||
});
|
||||
|
||||
setManager(users);
|
||||
} catch (error) {
|
||||
console.error("Ошибка при получении менеджеров!");
|
||||
}
|
||||
}
|
||||
|
||||
gettingListManagers();
|
||||
gettingRegisteredUsers();
|
||||
axiosRoles();
|
||||
});
|
||||
}, [selectedValue]);
|
||||
|
||||
const [selectedTariffs, setSelectedTariffs] = useState<GridSelectionModel>(
|
||||
|
@ -3,11 +3,11 @@ import { Box, IconButton, Typography } from "@mui/material";
|
||||
import theme from "../../../theme";
|
||||
import ExitToAppOutlinedIcon from "@mui/icons-material/ExitToAppOutlined";
|
||||
import Logo from "../../Logo";
|
||||
import { clearAuthToken, makeRequest } from "@frontend/kitui";
|
||||
import { clearAuthToken } from "@frontend/kitui";
|
||||
import { logout } from "@root/api/auth";
|
||||
|
||||
const Header: React.FC = () => {
|
||||
|
||||
return (
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Box
|
||||
sx={{
|
||||
@ -52,10 +52,7 @@ const Header: React.FC = () => {
|
||||
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
makeRequest({
|
||||
url: "https://admin.pena.digital/auth/logout",
|
||||
contentType: true,
|
||||
}).then(() => clearAuthToken());
|
||||
logout().then(clearAuthToken);
|
||||
}}
|
||||
sx={{
|
||||
display: "flex",
|
||||
|
@ -1,37 +1,15 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { Box, Typography, TextField, Button } from "@mui/material";
|
||||
import { verification, patchVerification } from "@root/api/verification";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
|
||||
import type { ChangeEvent } from "react";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
type File = {
|
||||
name: "inn" | "rule" | "egrule" | "certificate";
|
||||
url: string;
|
||||
};
|
||||
|
||||
type Verification = {
|
||||
_id: string;
|
||||
accepted: boolean;
|
||||
status: "org" | "nko";
|
||||
updated_at: string;
|
||||
comment: string;
|
||||
files: File[];
|
||||
};
|
||||
|
||||
type PatchVerificationBody = {
|
||||
id: string;
|
||||
status: "org" | "nko";
|
||||
comment: string;
|
||||
accepted: boolean;
|
||||
};
|
||||
import type { Verification } from "@root/api/verification";
|
||||
|
||||
type VerificationTabProps = {
|
||||
userId: string;
|
||||
};
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production" ? "" : "https://hub.pena.digital";
|
||||
|
||||
export const VerificationTab = ({ userId }: VerificationTabProps) => {
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [user, setUser] = useState<Verification | null>(null);
|
||||
@ -39,17 +17,20 @@ export const VerificationTab = ({ userId }: VerificationTabProps) => {
|
||||
|
||||
const requestVefification = async () => {
|
||||
setIsLoading(true);
|
||||
try {
|
||||
const verification = await makeRequest<never, Verification>({
|
||||
method: "get",
|
||||
url: baseUrl + `/verification/verification/${userId}`,
|
||||
});
|
||||
setUser(verification);
|
||||
setComment(verification.comment);
|
||||
} catch (error) {
|
||||
console.error("Error fetching verification:", error);
|
||||
} finally {
|
||||
setIsLoading(false);
|
||||
|
||||
const [verificationResponse, verificationError] = await verification(
|
||||
userId
|
||||
);
|
||||
|
||||
setIsLoading(false);
|
||||
|
||||
if (verificationError) {
|
||||
return console.error("Error verifying:", verificationError);
|
||||
}
|
||||
|
||||
if (verificationResponse) {
|
||||
setUser(verificationResponse);
|
||||
setComment(verificationResponse.comment);
|
||||
}
|
||||
};
|
||||
|
||||
@ -62,23 +43,18 @@ export const VerificationTab = ({ userId }: VerificationTabProps) => {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await makeRequest<PatchVerificationBody, never>({
|
||||
method: "patch",
|
||||
useToken: true,
|
||||
url: baseUrl + `/verification/verification`,
|
||||
body: {
|
||||
accepted,
|
||||
comment,
|
||||
id: user._id,
|
||||
status: user.status,
|
||||
},
|
||||
});
|
||||
const [_, patchVerificationError] = await patchVerification({
|
||||
accepted,
|
||||
comment,
|
||||
id: user._id,
|
||||
status: user.status,
|
||||
});
|
||||
|
||||
await requestVefification();
|
||||
} catch (error) {
|
||||
console.error("Error verifying:", error);
|
||||
if (patchVerificationError) {
|
||||
return console.error("Error verifying:", patchVerificationError);
|
||||
}
|
||||
|
||||
await requestVefification();
|
||||
};
|
||||
|
||||
return (
|
||||
@ -93,7 +69,11 @@ export const VerificationTab = ({ userId }: VerificationTabProps) => {
|
||||
{user?.accepted ? "Верификация пройдена" : "Не верифицирован"}
|
||||
</Typography>
|
||||
{isLoading ? (
|
||||
<Typography sx={{ fontWeight: "bold", fontSize: "18px", marginBottom: "25px" }}>Загрузка данных...</Typography>
|
||||
<Typography
|
||||
sx={{ fontWeight: "bold", fontSize: "18px", marginBottom: "25px" }}
|
||||
>
|
||||
Загрузка данных...
|
||||
</Typography>
|
||||
) : user && user.files.length > 0 ? (
|
||||
user.files.map(({ name, url }, index) => (
|
||||
<Box sx={{ marginBottom: "25px" }} key={name + url}>
|
||||
@ -122,13 +102,18 @@ export const VerificationTab = ({ userId }: VerificationTabProps) => {
|
||||
</Box>
|
||||
))
|
||||
) : (
|
||||
<Typography sx={{ fontWeight: "bold", fontSize: "18px", marginBottom: "25px" }}>
|
||||
<Typography
|
||||
sx={{ fontWeight: "bold", fontSize: "18px", marginBottom: "25px" }}
|
||||
>
|
||||
Пользователь не загружал данные
|
||||
</Typography>
|
||||
)}
|
||||
{user?.comment && (
|
||||
<Box sx={{ marginBottom: "15px" }}>
|
||||
<Typography component="span" sx={{ fontWeight: "bold", marginBottom: "10px" }}>
|
||||
<Typography
|
||||
component="span"
|
||||
sx={{ fontWeight: "bold", marginBottom: "10px" }}
|
||||
>
|
||||
Комментарий:
|
||||
</Typography>
|
||||
<Typography component="span"> {user.comment}</Typography>
|
||||
@ -145,13 +130,23 @@ export const VerificationTab = ({ userId }: VerificationTabProps) => {
|
||||
maxWidth: "500px",
|
||||
marginBottom: "10px",
|
||||
}}
|
||||
onChange={(event: ChangeEvent<HTMLTextAreaElement>) => setComment(event.target.value)}
|
||||
onChange={(event: ChangeEvent<HTMLTextAreaElement>) =>
|
||||
setComment(event.target.value)
|
||||
}
|
||||
/>
|
||||
<Box sx={{ display: "flex", columnGap: "10px" }}>
|
||||
<Button variant="text" sx={{ background: "#9A9AAF" }} onClick={() => verify(false)}>
|
||||
<Button
|
||||
variant="text"
|
||||
sx={{ background: "#9A9AAF" }}
|
||||
onClick={() => verify(false)}
|
||||
>
|
||||
Отклонить
|
||||
</Button>
|
||||
<Button variant="text" sx={{ background: "#9A9AAF" }} onClick={() => verify(true)}>
|
||||
<Button
|
||||
variant="text"
|
||||
sx={{ background: "#9A9AAF" }}
|
||||
onClick={() => verify(true)}
|
||||
>
|
||||
Подтвердить
|
||||
</Button>
|
||||
</Box>
|
||||
|
@ -1,12 +1,7 @@
|
||||
import { setDiscounts } from "@root/stores/discounts";
|
||||
|
||||
import type { GetDiscountResponse } from "@root/model/discount";
|
||||
import { Discount, makeRequest } from "@frontend/kitui";
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production"
|
||||
? "/price"
|
||||
: "https://admin.pena.digital/price";
|
||||
import { requestDiscounts as requestDiscountsRequest } from "@root/api/discounts";
|
||||
import type { Discount } from "@frontend/kitui";
|
||||
|
||||
const filterDiscounts = (discounts: Discount[]) => {
|
||||
const activeDiscounts = discounts.filter((discount) => !discount.Deprecated);
|
||||
@ -15,17 +10,19 @@ const filterDiscounts = (discounts: Discount[]) => {
|
||||
};
|
||||
|
||||
export const requestDiscounts = async (): Promise<Discount[]> => {
|
||||
try {
|
||||
const { Discounts } = await makeRequest<never, GetDiscountResponse>({
|
||||
url: baseUrl + "/discounts",
|
||||
method: "get",
|
||||
useToken: true,
|
||||
});
|
||||
const [discounts, discountsError] = await requestDiscountsRequest();
|
||||
|
||||
filterDiscounts(Discounts);
|
||||
if (discountsError) {
|
||||
console.error(discountsError);
|
||||
|
||||
return Discounts
|
||||
} catch {
|
||||
throw new Error("Ошибка при получении скидок");
|
||||
return [];
|
||||
}
|
||||
|
||||
if (discounts) {
|
||||
filterDiscounts(discounts.Discounts);
|
||||
|
||||
return discounts.Discounts;
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
@ -1,16 +1,8 @@
|
||||
import { resetPrivilegeArray } from "@root/stores/privilegesStore";
|
||||
import { exampleCartValues } from "@stores/mocks/exampleCartValues";
|
||||
import { requestServicePrivilegies } from "@root/api/privilegies";
|
||||
|
||||
import { PrivilegeWithAmount, makeRequest } from "@frontend/kitui";
|
||||
|
||||
type SeverPrivilegiesResponse = {
|
||||
templategen: PrivilegeWithAmount[];
|
||||
};
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production"
|
||||
? "/strator"
|
||||
: "https://admin.pena.digital/strator";
|
||||
import type { PrivilegeWithAmount } from "@frontend/kitui";
|
||||
|
||||
const mutatePrivilegies = (privilegies: PrivilegeWithAmount[]) => {
|
||||
let extracted: PrivilegeWithAmount[] = [];
|
||||
@ -34,12 +26,14 @@ const mutatePrivilegies = (privilegies: PrivilegeWithAmount[]) => {
|
||||
};
|
||||
|
||||
export const requestPrivilegies = async () => {
|
||||
await makeRequest<never, SeverPrivilegiesResponse>({
|
||||
url: baseUrl + "/privilege/service",
|
||||
method: "get",
|
||||
})
|
||||
.then(({ templategen }) => mutatePrivilegies(templategen))
|
||||
.catch(() => {
|
||||
console.log("Ошибка при получении привилегий");
|
||||
});
|
||||
const [privilegiesResponse, privilegiesError] =
|
||||
await requestServicePrivilegies();
|
||||
|
||||
if (privilegiesError) {
|
||||
return console.error(privilegiesError);
|
||||
}
|
||||
|
||||
if (privilegiesResponse) {
|
||||
mutatePrivilegies(privilegiesResponse.templategen);
|
||||
}
|
||||
};
|
||||
|
@ -1,43 +1,36 @@
|
||||
import { Tariff, makeRequest } from "@frontend/kitui";
|
||||
import { updateTariffs } from "@root/stores/tariffs";
|
||||
import { requestTariffs as requestTariffsRequest } from "@root/api/tariffs";
|
||||
|
||||
|
||||
type GetTariffsResponse = {
|
||||
totalPages: number;
|
||||
tariffs: Tariff[];
|
||||
};
|
||||
|
||||
const baseUrl =
|
||||
process.env.NODE_ENV === "production"
|
||||
? "/strator"
|
||||
: "https://admin.pena.digital/strator";
|
||||
import type { Tariff } from "@frontend/kitui";
|
||||
|
||||
const mutateTariffs = (tariffs: Tariff[]) => {
|
||||
const nonDeletedTariffs = tariffs
|
||||
.filter(({ isDeleted }) => !isDeleted);
|
||||
const nonDeletedTariffs = tariffs.filter(({ isDeleted }) => !isDeleted);
|
||||
|
||||
updateTariffs(nonDeletedTariffs);
|
||||
updateTariffs(nonDeletedTariffs);
|
||||
};
|
||||
|
||||
export const requestTariffs = async (
|
||||
page: number = 1,
|
||||
existingTariffs: Tariff[] = []
|
||||
page: number = 1,
|
||||
existingTariffs: Tariff[] = []
|
||||
): Promise<void> => {
|
||||
try {
|
||||
const { tariffs, totalPages } = await makeRequest<
|
||||
never,
|
||||
GetTariffsResponse
|
||||
>({
|
||||
url: baseUrl + `/tariff/?page=${page}&limit=${100}`,
|
||||
method: "get",
|
||||
});
|
||||
const [tariffsResponse, tariffsResponseError] = await requestTariffsRequest(
|
||||
page
|
||||
);
|
||||
|
||||
if (page < totalPages) {
|
||||
return requestTariffs(page + 1, [...existingTariffs, ...tariffs]);
|
||||
}
|
||||
if (tariffsResponseError) {
|
||||
console.error(tariffsResponseError);
|
||||
|
||||
mutateTariffs([...existingTariffs, ...tariffs]);
|
||||
} catch {
|
||||
throw new Error("Ошибка при получении тарифов");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tariffsResponse) {
|
||||
if (page < tariffsResponse.totalPages) {
|
||||
return requestTariffs(page + 1, [
|
||||
...existingTariffs,
|
||||
...tariffsResponse.tariffs,
|
||||
]);
|
||||
}
|
||||
|
||||
mutateTariffs([...existingTariffs, ...tariffsResponse.tariffs]);
|
||||
}
|
||||
};
|
||||
|
@ -1,25 +1,29 @@
|
||||
import { PrivilegeWithAmount, makeRequest } from "@frontend/kitui";
|
||||
import { useEffect } from "react";
|
||||
|
||||
import { requestPrivilegies } from "@root/api/privilegies";
|
||||
|
||||
export default function usePrivileges({ onError, onNewPrivileges }: {
|
||||
onNewPrivileges: (response: PrivilegeWithAmount[]) => void;
|
||||
onError?: (error: any) => void;
|
||||
import type { PrivilegeWithAmount } from "@frontend/kitui";
|
||||
|
||||
export default function usePrivileges({
|
||||
onError,
|
||||
onNewPrivileges,
|
||||
}: {
|
||||
onNewPrivileges: (response: PrivilegeWithAmount[]) => void;
|
||||
onError?: (error: any) => void;
|
||||
}) {
|
||||
useEffect(() => {
|
||||
const controller = new AbortController();
|
||||
useEffect(() => {
|
||||
const controller = new AbortController();
|
||||
|
||||
makeRequest<never, PrivilegeWithAmount[]>({
|
||||
url: "https://admin.pena.digital/strator/privilege",
|
||||
method: "get",
|
||||
useToken: true,
|
||||
signal: controller.signal,
|
||||
}).then(result => {
|
||||
onNewPrivileges(result);
|
||||
}).catch(error => {
|
||||
onError?.(error);
|
||||
});
|
||||
requestPrivilegies(controller.signal).then(
|
||||
([privilegiesResponse, privilegiesError]) => {
|
||||
if (privilegiesError) {
|
||||
return onError?.(privilegiesError);
|
||||
}
|
||||
|
||||
return () => controller.abort();
|
||||
}, [onError, onNewPrivileges]);
|
||||
onNewPrivileges(privilegiesResponse);
|
||||
}
|
||||
);
|
||||
|
||||
return () => controller.abort();
|
||||
}, [onError, onNewPrivileges]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user