test (access && tariffs) create
This commit is contained in:
parent
3920ccebfd
commit
ec148d261e
11
cypress.config.ts
Normal file
11
cypress.config.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { defineConfig } from "cypress";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
e2e: {
|
||||||
|
viewportWidth: 1200,
|
||||||
|
viewportHeight: 800,
|
||||||
|
fixturesFolder: "tests/e2e/fixtures",
|
||||||
|
supportFile: false,
|
||||||
|
defaultCommandTimeout: 100,
|
||||||
|
},
|
||||||
|
});
|
110
cypress/e2e/access.cy.ts
Normal file
110
cypress/e2e/access.cy.ts
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
describe("Форма Входа", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit("http://localhost:3000");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("должна успешно входить с правильными учетными данными", () => {
|
||||||
|
const email = "valid_user@example.com";
|
||||||
|
const password = "valid_password";
|
||||||
|
|
||||||
|
cy.get('input[name="email"]').type(email);
|
||||||
|
cy.get('input[name="password"]').type(password);
|
||||||
|
cy.get('button[type="submit"]').click();
|
||||||
|
|
||||||
|
cy.url().should("include", "http://localhost:3000/users");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("должна отображать сообщение об ошибке при неверном формате электронной почты", () => {
|
||||||
|
const invalidEmail = "invalid_email";
|
||||||
|
|
||||||
|
cy.get('input[name="email"]').type(invalidEmail);
|
||||||
|
cy.get('input[name="password"]').type("valid_password");
|
||||||
|
cy.get('button[type="submit"]').click();
|
||||||
|
|
||||||
|
cy.contains("Неверный формат эл. почты");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("должна отображать сообщение об ошибке при отсутствии пароля", () => {
|
||||||
|
cy.get('input[name="email"]').type("valid_email@example.com");
|
||||||
|
cy.get('button[type="submit"]').click();
|
||||||
|
|
||||||
|
cy.contains("Введите пароль");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("должна отображать сообщение об ошибке для недопустимого пароля", () => {
|
||||||
|
const invalidPassword = "short";
|
||||||
|
|
||||||
|
cy.get('input[name="email"]').type("valid_email@example.com");
|
||||||
|
cy.get('input[name="password"]').type(invalidPassword);
|
||||||
|
cy.get('button[type="submit"]').click();
|
||||||
|
|
||||||
|
cy.contains("Invalid password");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Форма регистрации", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit("http://localhost:3000/signup");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("должна регистрировать нового пользователя с правильными данными", () => {
|
||||||
|
const email = Cypress._.random(1000) + "@example.com";
|
||||||
|
const password = "valid_password";
|
||||||
|
|
||||||
|
cy.get('input[name="email"]').type(email);
|
||||||
|
cy.get('input[name="password"]').type(password);
|
||||||
|
cy.get('input[name="repeatPassword"]').type(password);
|
||||||
|
|
||||||
|
cy.get('button[type="submit"]').click();
|
||||||
|
cy.wait(5000);
|
||||||
|
|
||||||
|
cy.url().should("include", "http://localhost:3000/users");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("должна отображать ошибку при неверном формате электронной почты", () => {
|
||||||
|
const invalidEmail = "invalid_email";
|
||||||
|
|
||||||
|
cy.get('input[name="email"]').type(invalidEmail);
|
||||||
|
cy.get('input[name="password"]').type("valid_password");
|
||||||
|
cy.get('input[name="repeatPassword"]').type("valid_password");
|
||||||
|
|
||||||
|
cy.get('button[type="submit"]').click();
|
||||||
|
|
||||||
|
cy.contains("Неверный формат эл. почты");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("должна отображать ошибку при отсутствии пароля", () => {
|
||||||
|
cy.get('input[name="email"]').type("valid_email@example.com");
|
||||||
|
cy.get('input[name="repeatPassword"]').type("valid_password");
|
||||||
|
|
||||||
|
cy.get('button[type="submit"]').click();
|
||||||
|
|
||||||
|
cy.contains("Обязательное поле").should("have.length", 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("должна отображать ошибку при несовпадении паролей", () => {
|
||||||
|
cy.get('input[name="email"]').type("valid_email@example.com");
|
||||||
|
cy.get('input[name="password"]').type("valid_password");
|
||||||
|
cy.get('input[name="repeatPassword"]').type("different_password");
|
||||||
|
|
||||||
|
cy.get('button[type="submit"]').click();
|
||||||
|
|
||||||
|
cy.contains("Пароли не совпадают");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("попытка отправки запроса при уже зарегистрированном пользователе", () => {
|
||||||
|
const email = "users@gmail.com";
|
||||||
|
const password = "12344321";
|
||||||
|
|
||||||
|
cy.get('input[name="email"]').type(email);
|
||||||
|
cy.get('input[name="password"]').type(password);
|
||||||
|
cy.get('input[name="repeatPassword"]').type(password);
|
||||||
|
|
||||||
|
cy.intercept("POST", "https://admin.pena.digital/auth/register").as("registerRequest");
|
||||||
|
cy.get('button[type="submit"]').click();
|
||||||
|
cy.wait("@registerRequest");
|
||||||
|
|
||||||
|
cy.wait(5000);
|
||||||
|
cy.contains("user with this login is exist");
|
||||||
|
});
|
||||||
|
});
|
195
cypress/e2e/tariffs.cy.ts
Normal file
195
cypress/e2e/tariffs.cy.ts
Normal file
@ -0,0 +1,195 @@
|
|||||||
|
describe("Форма Создания Тарифа", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit("http://localhost:3000");
|
||||||
|
cy.get('input[name="email"]').type("valid_user@example.com");
|
||||||
|
cy.get('input[name="password"]').type("valid_password");
|
||||||
|
cy.get('button[type="submit"]').click();
|
||||||
|
cy.wait(3000);
|
||||||
|
cy.url().should("include", "http://localhost:3000/users");
|
||||||
|
cy.visit("http://localhost:3000/tariffs");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("должна отображать сообщение об ошибке при пустом названии тарифа", () => {
|
||||||
|
cy.get('input[id="tariff-amount"]').type("10");
|
||||||
|
|
||||||
|
// Выбрать первую привилегию с нужным текстом из выпадающего списка
|
||||||
|
cy.get("#privilege-select").click();
|
||||||
|
|
||||||
|
cy.get(`[data-cy = "select-option-Количество шаблонов, которые может сделать пользователь сервиса"]`).click();
|
||||||
|
|
||||||
|
cy.get(".btn_createTariffBackend").click({ force: true });
|
||||||
|
|
||||||
|
cy.contains("Пустое название тарифа");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("должна отображать сообщение об ошибке при отсутствии выбора привилегии", () => {
|
||||||
|
cy.get('input[id="tariff-name"]').type("Тестовый Тариф");
|
||||||
|
cy.get('input[id="tariff-amount"]').type("10");
|
||||||
|
|
||||||
|
cy.get(".btn_createTariffBackend").click({ force: true });
|
||||||
|
|
||||||
|
cy.contains("Не выбрана привилегия");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Создание трех тарифов", () => {
|
||||||
|
cy.get('input[id="tariff-name"]').type("Тестовый Тариф 1");
|
||||||
|
cy.get('input[id="tariff-amount"]').type("10");
|
||||||
|
cy.get("#privilege-select").click();
|
||||||
|
cy.get(`[data-cy="select-option-Количество шаблонов, которые может сделать пользователь сервиса"]`).click();
|
||||||
|
cy.get(".btn_createTariffBackend").click({ force: true });
|
||||||
|
|
||||||
|
cy.get('input[id="tariff-name"]').scrollIntoView().clear({ force: true }).type("Тестовый Тариф 2");
|
||||||
|
cy.get('input[id="tariff-amount"]').scrollIntoView().clear({ force: true }).type("15");
|
||||||
|
cy.get("#privilege-select").click();
|
||||||
|
cy.wait(800);
|
||||||
|
cy.get(`[data-cy="select-option-Количество дней, в течении которых пользование сервисом безлимитно"]`).click();
|
||||||
|
cy.get(".btn_createTariffBackend").click({ force: true });
|
||||||
|
|
||||||
|
cy.get('input[id="tariff-name"]').scrollIntoView().clear({ force: true }).type("Тестовый Тариф 3");
|
||||||
|
cy.get('input[id="tariff-amount"]').scrollIntoView().clear({ force: true }).type("20");
|
||||||
|
cy.get("#privilege-select").click();
|
||||||
|
cy.wait(800);
|
||||||
|
cy.get(`[data-cy="select-option-Обьём ПенаДиска для хранения шаблонов и результатов шаблонизации"]`).click();
|
||||||
|
cy.get(".btn_createTariffBackend").click({ force: true });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Форма Создания Тарифа", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.visit("http://localhost:3000");
|
||||||
|
cy.get('input[name="email"]').type("valid_user@example.com");
|
||||||
|
cy.get('input[name="password"]').type("valid_password");
|
||||||
|
cy.get('button[type="submit"]').click();
|
||||||
|
cy.wait(3000);
|
||||||
|
cy.url().should("include", "http://localhost:3000/users");
|
||||||
|
cy.visit("http://localhost:3000/tariffs");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Удаление тарифа единично, одного за другим ", () => {
|
||||||
|
const tariffNamesToFind = ["Тестовый Тариф 1", "Тестовый Тариф 2", "Тестовый Тариф 3"];
|
||||||
|
|
||||||
|
// Поиск каждого тарифа в DataGrid
|
||||||
|
cy.wait(3000);
|
||||||
|
tariffNamesToFind.forEach((tariffName) => {
|
||||||
|
cy.get(".tariffs-data-grid").scrollIntoView().contains(tariffName).should("be.visible");
|
||||||
|
});
|
||||||
|
|
||||||
|
const deleteTariffs = () => {
|
||||||
|
let tariffsFound = true;
|
||||||
|
|
||||||
|
cy.get(".tariffs-data-grid .MuiDataGrid-row").then(($rows) => {
|
||||||
|
const rowCount = $rows.length;
|
||||||
|
|
||||||
|
if (rowCount === 1) {
|
||||||
|
cy.log("Тарифы не найдены. Тест завершен.");
|
||||||
|
tariffsFound = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.wrap($rows).each(($row) => {
|
||||||
|
// Шаг 2: В каждом элементе найдите все дивы вложенные внутрь и выберите последний див
|
||||||
|
cy.wrap($row).find("div").last().scrollIntoView().get(".delete-tariff-button").last().click({ force: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.wait(2000);
|
||||||
|
cy.contains("Да")
|
||||||
|
.click()
|
||||||
|
.then(() => {
|
||||||
|
if (!tariffsFound) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.wait(5000);
|
||||||
|
deleteTariffs();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
deleteTariffs();
|
||||||
|
|
||||||
|
// Проверяем что Дата грид тарифов пустой
|
||||||
|
cy.wait(2000);
|
||||||
|
cy.get(".tariffs-data-grid .MuiDataGrid-row").should("not.exist");
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Форма Создания Тарифа", () => {});
|
||||||
|
|
||||||
|
it("Удаление тарифов массово через DataGrid", () => {
|
||||||
|
// Добавляем 3 тариффа
|
||||||
|
cy.get('input[id="tariff-name"]').type("Тестовый Тариф 1");
|
||||||
|
cy.get('input[id="tariff-amount"]').type("10");
|
||||||
|
cy.get("#privilege-select").click();
|
||||||
|
cy.get(`[data-cy="select-option-Количество шаблонов, которые может сделать пользователь сервиса"]`).click();
|
||||||
|
cy.get(".btn_createTariffBackend").click({ force: true });
|
||||||
|
|
||||||
|
cy.get('input[id="tariff-name"]').scrollIntoView().clear({ force: true }).type("Тестовый Тариф 2");
|
||||||
|
cy.get('input[id="tariff-amount"]').scrollIntoView().clear({ force: true }).type("15");
|
||||||
|
cy.get("#privilege-select").click();
|
||||||
|
cy.wait(800);
|
||||||
|
cy.get(`[data-cy="select-option-Количество дней, в течении которых пользование сервисом безлимитно"]`).click();
|
||||||
|
cy.get(".btn_createTariffBackend").click({ force: true });
|
||||||
|
|
||||||
|
cy.get('input[id="tariff-name"]').scrollIntoView().clear({ force: true }).type("Тестовый Тариф 3");
|
||||||
|
cy.get('input[id="tariff-amount"]').scrollIntoView().clear({ force: true }).type("20");
|
||||||
|
cy.get("#privilege-select").click();
|
||||||
|
cy.wait(800);
|
||||||
|
cy.get(`[data-cy="select-option-Обьём ПенаДиска для хранения шаблонов и результатов шаблонизации"]`).click();
|
||||||
|
cy.get(".btn_createTariffBackend").click({ force: true });
|
||||||
|
// Добавляем 3 тариффа
|
||||||
|
|
||||||
|
cy.wait(3000);
|
||||||
|
cy.get(".tariffs-data-grid .PrivateSwitchBase-input").first().click({ multiple: true });
|
||||||
|
|
||||||
|
// Проверить, что кнопка "Удалить" появилась
|
||||||
|
cy.wait(2000);
|
||||||
|
cy.contains("Удаление").should("be.visible");
|
||||||
|
|
||||||
|
// Нажать на кнопку "Удалить"
|
||||||
|
cy.contains("Удаление").click();
|
||||||
|
|
||||||
|
// Подтверждение удаления (если нужно)
|
||||||
|
cy.contains("Да").click();
|
||||||
|
|
||||||
|
// Проверяем что Дата грид тарифов пустой
|
||||||
|
cy.wait(2000);
|
||||||
|
cy.get(".tariffs-data-grid .MuiDataGrid-row").should("not.exist");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Добавление тарифом в корзину", () => {
|
||||||
|
// Добавляем 3 тариффа
|
||||||
|
|
||||||
|
cy.get('input[id="tariff-name"]').type("Тестовый Тариф 1");
|
||||||
|
cy.get('input[id="tariff-amount"]').type("10");
|
||||||
|
cy.get("#privilege-select").click();
|
||||||
|
cy.get(`[data-cy="select-option-Количество шаблонов, которые может сделать пользователь сервиса"]`).click();
|
||||||
|
cy.get(".btn_createTariffBackend").click({ force: true });
|
||||||
|
|
||||||
|
cy.get('input[id="tariff-name"]').scrollIntoView().clear({ force: true }).type("Тестовый Тариф 2");
|
||||||
|
cy.get('input[id="tariff-amount"]').scrollIntoView().clear({ force: true }).type("15");
|
||||||
|
cy.get("#privilege-select").click();
|
||||||
|
cy.wait(800);
|
||||||
|
cy.get(`[data-cy="select-option-Количество дней, в течении которых пользование сервисом безлимитно"]`).click();
|
||||||
|
cy.get(".btn_createTariffBackend").click({ force: true });
|
||||||
|
|
||||||
|
cy.get('input[id="tariff-name"]').scrollIntoView().clear({ force: true }).type("Тестовый Тариф 3");
|
||||||
|
cy.get('input[id="tariff-amount"]').scrollIntoView().clear({ force: true }).type("20");
|
||||||
|
cy.get("#privilege-select").click();
|
||||||
|
cy.wait(800);
|
||||||
|
cy.get(`[data-cy="select-option-Обьём ПенаДиска для хранения шаблонов и результатов шаблонизации"]`).click();
|
||||||
|
cy.get(".btn_createTariffBackend").click({ force: true });
|
||||||
|
// Добавляем 3 тариффа
|
||||||
|
|
||||||
|
cy.wait(3000);
|
||||||
|
cy.get(".tariffs-data-grid .PrivateSwitchBase-input").first().click({ multiple: true });
|
||||||
|
|
||||||
|
// Проверить, что кнопка "Удалить" появилась
|
||||||
|
cy.wait(2000);
|
||||||
|
cy.contains("рассчитать").should("be.visible");
|
||||||
|
|
||||||
|
// Нажать на кнопку "Удалить"
|
||||||
|
cy.contains("рассчитать").click();
|
||||||
|
|
||||||
|
// смотрим что в корзине ровно столько тарифом, сколько мы добовляли
|
||||||
|
cy.wait(5000);
|
||||||
|
cy.get(".MuiTable-root tbody tr").its("length").should("eq", 3);
|
||||||
|
});
|
||||||
|
});
|
@ -24,6 +24,7 @@
|
|||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"axios": "^1.3.4",
|
"axios": "^1.3.4",
|
||||||
"craco": "^0.0.3",
|
"craco": "^0.0.3",
|
||||||
|
"cypress": "^12.17.2",
|
||||||
"dayjs": "^1.11.5",
|
"dayjs": "^1.11.5",
|
||||||
"formik": "^2.2.9",
|
"formik": "^2.2.9",
|
||||||
"immer": "^10.0.2",
|
"immer": "^10.0.2",
|
||||||
@ -37,6 +38,7 @@
|
|||||||
"react-router-dom": "^6.3.0",
|
"react-router-dom": "^6.3.0",
|
||||||
"react-scripts": "^5.0.1",
|
"react-scripts": "^5.0.1",
|
||||||
"reconnecting-eventsource": "^1.6.2",
|
"reconnecting-eventsource": "^1.6.2",
|
||||||
|
"start-server-and-test": "^2.0.0",
|
||||||
"styled-components": "^5.3.5",
|
"styled-components": "^5.3.5",
|
||||||
"typescript": "^4.8.2",
|
"typescript": "^4.8.2",
|
||||||
"web-vitals": "^2.1.4",
|
"web-vitals": "^2.1.4",
|
||||||
@ -47,6 +49,8 @@
|
|||||||
"build": "craco build",
|
"build": "craco build",
|
||||||
"test": "craco test",
|
"test": "craco test",
|
||||||
"test:cart": "craco test src/kitUI/Cart --watchAll=false",
|
"test:cart": "craco test src/kitUI/Cart --watchAll=false",
|
||||||
|
"test:cypress": "start-server-and-test start http://localhost:3000 cypress",
|
||||||
|
"cypress": "cypress open",
|
||||||
"eject": "craco eject"
|
"eject": "craco eject"
|
||||||
},
|
},
|
||||||
"eslintConfig": {
|
"eslintConfig": {
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
import { styled } from "@mui/material/styles";
|
import { styled } from "@mui/material/styles";
|
||||||
import { TextField} from "@mui/material";
|
import { TextField } from "@mui/material";
|
||||||
export default styled(TextField)(({ theme }) => ({
|
export default styled(TextField)(({ theme }) => ({
|
||||||
|
color: theme.palette.grayLight.main,
|
||||||
|
"& .MuiInputLabel-root": {
|
||||||
color: theme.palette.grayLight.main,
|
color: theme.palette.grayLight.main,
|
||||||
"& .MuiInputLabel-root": {
|
},
|
||||||
color: theme.palette.grayLight.main,
|
"& .MuiFilledInput-root": {
|
||||||
},
|
border: theme.palette.grayLight.main + " 1px solid",
|
||||||
"& .MuiFilledInput-root": {
|
borderRadius: "0",
|
||||||
border: theme.palette.grayLight.main+" 1px solid",
|
backgroundColor: theme.palette.hover.main,
|
||||||
borderRadius: "0",
|
color: theme.palette.grayLight.main,
|
||||||
backgroundColor: theme.palette.hover.main,
|
},
|
||||||
color: theme.palette.grayLight.main,
|
|
||||||
}
|
|
||||||
|
|
||||||
}));
|
"& .MuiFilledInput-root.Mui-error": {
|
||||||
|
fontSize: "8px",
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
@ -19,11 +19,13 @@ function validate(values: Values) {
|
|||||||
const errors = {} as any;
|
const errors = {} as any;
|
||||||
|
|
||||||
if (!values.email) {
|
if (!values.email) {
|
||||||
errors.email = "Required";
|
errors.email = "Обязательное поле";
|
||||||
|
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(values.email)) {
|
||||||
|
errors.email = "Неверный формат эл. почты";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!values.password) {
|
if (!values.password) {
|
||||||
errors.password = "Required";
|
errors.password = "Введите пароль";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.password && !/^[\S]{8,25}$/i.test(values.password)) {
|
if (values.password && !/^[\S]{8,25}$/i.test(values.password)) {
|
||||||
@ -107,11 +109,34 @@ const SigninForm = () => {
|
|||||||
</Box>
|
</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} />
|
<EmailOutlinedIcon htmlColor={theme.palette.golden.main} />
|
||||||
<Field as={OutlinedInput} name="email" variant="filled" label="Эл. почта" />
|
<Field
|
||||||
|
as={OutlinedInput}
|
||||||
|
name="email"
|
||||||
|
variant="filled"
|
||||||
|
label="Эл. почта"
|
||||||
|
error={props.touched.email && !!props.errors.email}
|
||||||
|
helperText={
|
||||||
|
<Typography sx={{ fontSize: "12px", width: "200px" }}>
|
||||||
|
{props.touched.email && props.errors.email}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</Box>
|
</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} />
|
<LockOutlinedIcon htmlColor={theme.palette.golden.main} />
|
||||||
<Field as={OutlinedInput} type="password" name="password" variant="filled" label="Пароль" />
|
<Field
|
||||||
|
as={OutlinedInput}
|
||||||
|
type="password"
|
||||||
|
name="password"
|
||||||
|
variant="filled"
|
||||||
|
label="Пароль"
|
||||||
|
error={props.touched.password && !!props.errors.password}
|
||||||
|
helperText={
|
||||||
|
<Typography sx={{ fontSize: "12px", width: "200px" }}>
|
||||||
|
{props.touched.password && props.errors.password}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
component="article"
|
component="article"
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { enqueueSnackbar } from "notistack";
|
import { enqueueSnackbar, useSnackbar } from "notistack";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useTheme } from "@mui/material/styles";
|
import { useTheme } from "@mui/material/styles";
|
||||||
import { Formik, Field, Form } from "formik";
|
import { Formik, Field, Form } from "formik";
|
||||||
@ -10,142 +10,188 @@ import Logo from "@pages/Logo/index";
|
|||||||
import EmailOutlinedIcon from "@mui/icons-material/EmailOutlined";
|
import EmailOutlinedIcon from "@mui/icons-material/EmailOutlined";
|
||||||
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
|
import LockOutlinedIcon from "@mui/icons-material/LockOutlined";
|
||||||
import { authStore } from "@root/stores/auth";
|
import { authStore } from "@root/stores/auth";
|
||||||
|
|
||||||
interface Values {
|
interface Values {
|
||||||
email: string;
|
email: string;
|
||||||
password: string;
|
password: string;
|
||||||
repeatPassword: string;
|
repeatPassword: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function validate(values: Values) {
|
function validate(values: Values) {
|
||||||
const errors = {} as any;
|
const errors: Partial<Values> = {};
|
||||||
if (!values.email) {
|
|
||||||
errors.login = "Required";
|
if (!values.email) {
|
||||||
}
|
errors.email = "Обязательное поле";
|
||||||
if (!values.password) {
|
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(values.email)) {
|
||||||
errors.password = "Required";
|
errors.email = "Неверный формат эл. почты";
|
||||||
} else if (!/^[\S]{8,25}$/i.test(values.password)) {
|
}
|
||||||
errors.password = "Invalid password";
|
|
||||||
}
|
if (!values.password) {
|
||||||
if (values.password !== values.repeatPassword) {
|
errors.password = "Обязательное поле";
|
||||||
errors.repeatPassword = "Passwords do not match";
|
} else if (!/^[\S]{8,25}$/i.test(values.password)) {
|
||||||
}
|
errors.password = "Неверный пароль";
|
||||||
return errors;
|
}
|
||||||
|
if (values.password !== values.repeatPassword) {
|
||||||
|
errors.repeatPassword = "Пароли не совпадают";
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SignUp = () => {
|
const SignUp = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { makeRequest } = authStore();
|
const { makeRequest } = authStore();
|
||||||
|
const { enqueueSnackbar } = useSnackbar();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Formik
|
<Formik
|
||||||
initialValues={{
|
initialValues={{
|
||||||
email: "",
|
email: "",
|
||||||
password: "",
|
password: "",
|
||||||
repeatPassword: "",
|
repeatPassword: "",
|
||||||
|
}}
|
||||||
|
validate={validate}
|
||||||
|
onSubmit={(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);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{(props) => (
|
||||||
|
<Form>
|
||||||
|
<Box
|
||||||
|
component="section"
|
||||||
|
sx={{
|
||||||
|
minHeight: "100vh",
|
||||||
|
height: "100%",
|
||||||
|
width: "100%",
|
||||||
|
backgroundColor: theme.palette.content.main,
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: "15px 0",
|
||||||
}}
|
}}
|
||||||
validate={validate}
|
>
|
||||||
onSubmit={(values, formikHelpers) => {
|
<Box
|
||||||
formikHelpers.setSubmitting(true);
|
component="article"
|
||||||
makeRequest({
|
sx={{
|
||||||
url: "https://admin.pena.digital/auth/register",
|
width: "350px",
|
||||||
body: {
|
backgroundColor: theme.palette.content.main,
|
||||||
login: values.email,
|
display: "flex",
|
||||||
email: values.email,
|
flexDirection: "column",
|
||||||
password: values.repeatPassword,
|
justifyContent: "center",
|
||||||
phoneNumber: "--",
|
"> *": {
|
||||||
},
|
marginTop: "15px",
|
||||||
useToken: false,
|
},
|
||||||
})
|
}}
|
||||||
.then((e) => {
|
>
|
||||||
navigate("/users");
|
<Typography variant="h6" color={theme.palette.secondary.main}>
|
||||||
})
|
Новый аккаунт
|
||||||
.catch((e) => {
|
</Typography>
|
||||||
console.log(e);
|
<Logo />
|
||||||
enqueueSnackbar(
|
|
||||||
e.response && e.response.data && e.response.data.message ? e.response.data.message : `Unknown error`
|
|
||||||
);
|
|
||||||
}).finally(() => {
|
|
||||||
formikHelpers.setSubmitting(false);
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{props =>
|
|
||||||
<Form>
|
|
||||||
<Box
|
|
||||||
component="section"
|
|
||||||
sx={{
|
|
||||||
minHeight: "100vh",
|
|
||||||
height: "100%",
|
|
||||||
width: "100%",
|
|
||||||
backgroundColor: theme.palette.content.main,
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
padding: "15px 0",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
component="article"
|
|
||||||
sx={{
|
|
||||||
width: "350px",
|
|
||||||
backgroundColor: theme.palette.content.main,
|
|
||||||
display: "flex",
|
|
||||||
flexDirection: "column",
|
|
||||||
justifyContent: "center",
|
|
||||||
"> *": {
|
|
||||||
marginTop: "15px",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography variant="h6" color={theme.palette.secondary.main}>
|
|
||||||
Новый аккаунт
|
|
||||||
</Typography>
|
|
||||||
<Logo />
|
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Typography variant="h5" color={theme.palette.secondary.main}>
|
<Typography variant="h5" color={theme.palette.secondary.main}>
|
||||||
Добро пожаловать
|
Добро пожаловать
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography variant="h6" color={theme.palette.secondary.main}>
|
<Typography variant="h6" color={theme.palette.secondary.main}>
|
||||||
Мы рады что вы выбрали нас!
|
Мы рады что вы выбрали нас!
|
||||||
</Typography>
|
</Typography>
|
||||||
</Box>
|
</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} />
|
<EmailOutlinedIcon htmlColor={theme.palette.golden.main} />
|
||||||
<Field as={OutlinedInput} name="email" variant="filled" label="Эл. почта" />
|
<Field
|
||||||
</Box>
|
as={OutlinedInput}
|
||||||
<Box sx={{ display: "flex", alignItems: "center", marginTop: "15px", "> *": { marginRight: "10px" } }}>
|
name="email"
|
||||||
<LockOutlinedIcon htmlColor={theme.palette.golden.main} />
|
variant="filled"
|
||||||
<Field as={OutlinedInput} type="password" name="password" variant="filled" label="Пароль" />
|
label="Эл. почта"
|
||||||
</Box>
|
id="email"
|
||||||
<Box sx={{ display: "flex", alignItems: "center", marginTop: "15px", "> *": { marginRight: "10px" } }}>
|
error={props.touched.email && !!props.errors.email}
|
||||||
<LockOutlinedIcon htmlColor={theme.palette.golden.main} />
|
helperText={
|
||||||
<Field
|
<Typography sx={{ fontSize: "12px", width: "200px" }}>
|
||||||
as={OutlinedInput}
|
{props.touched.email && props.errors.email}
|
||||||
type="password"
|
</Typography>
|
||||||
name="repeatPassword"
|
}
|
||||||
variant="filled"
|
/>
|
||||||
label="Повторите пароль"
|
</Box>
|
||||||
/>
|
<Box sx={{ display: "flex", alignItems: "center", marginTop: "15px", "> *": { marginRight: "10px" } }}>
|
||||||
</Box>
|
<LockOutlinedIcon htmlColor={theme.palette.golden.main} />
|
||||||
<Button
|
<Field
|
||||||
type="submit"
|
sx={{}}
|
||||||
disabled={props.isSubmitting}
|
as={OutlinedInput}
|
||||||
sx={{
|
type="password"
|
||||||
width: "250px",
|
name="password"
|
||||||
margin: "15px auto",
|
variant="filled"
|
||||||
padding: "20px 30px",
|
label="Пароль"
|
||||||
fontSize: 18,
|
id="password"
|
||||||
}}
|
error={props.touched.password && !!props.errors.password}
|
||||||
>Войти</Button>
|
helperText={
|
||||||
<Link to="/signin" style={{ textDecoration: "none" }}>
|
<Typography sx={{ fontSize: "12px", width: "200px" }}>
|
||||||
<Typography color={theme.palette.golden.main}>У меня уже есть аккаунт</Typography>
|
{props.touched.password && props.errors.password}
|
||||||
</Link>
|
</Typography>
|
||||||
</Box>
|
}
|
||||||
</Box>
|
/>
|
||||||
</Form>
|
</Box>
|
||||||
}
|
<Box sx={{ display: "flex", alignItems: "center", marginTop: "15px", "> *": { marginRight: "10px" } }}>
|
||||||
</Formik>
|
<LockOutlinedIcon htmlColor={theme.palette.golden.main} />
|
||||||
);
|
<Field
|
||||||
|
as={OutlinedInput}
|
||||||
|
type="password"
|
||||||
|
name="repeatPassword"
|
||||||
|
variant="filled"
|
||||||
|
label="Повторите пароль"
|
||||||
|
id="repeatPassword"
|
||||||
|
error={props.touched.repeatPassword && !!props.errors.repeatPassword}
|
||||||
|
helperText={
|
||||||
|
<Typography sx={{ fontSize: "12px", width: "200px" }}>
|
||||||
|
{props.touched.repeatPassword && props.errors.repeatPassword}
|
||||||
|
</Typography>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
disabled={props.isSubmitting}
|
||||||
|
sx={{
|
||||||
|
width: "250px",
|
||||||
|
margin: "15px auto",
|
||||||
|
padding: "20px 30px",
|
||||||
|
fontSize: 18,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Войти
|
||||||
|
</Button>
|
||||||
|
<Link to="/signin" style={{ textDecoration: "none" }}>
|
||||||
|
<Typography color={theme.palette.golden.main}>У меня уже есть аккаунт</Typography>
|
||||||
|
</Link>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Form>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default SignUp;
|
export default SignUp;
|
||||||
|
@ -1,25 +1,12 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import {
|
import { Typography, Container, Button, Select, MenuItem, FormControl, InputLabel, useTheme, Box } from "@mui/material";
|
||||||
Typography,
|
|
||||||
Container,
|
|
||||||
Button,
|
|
||||||
Select,
|
|
||||||
MenuItem,
|
|
||||||
FormControl,
|
|
||||||
InputLabel,
|
|
||||||
useTheme,
|
|
||||||
Box,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { enqueueSnackbar } from "notistack";
|
import { enqueueSnackbar } from "notistack";
|
||||||
|
|
||||||
import { CustomTextField } from "@root/kitUI/CustomTextField";
|
import { CustomTextField } from "@root/kitUI/CustomTextField";
|
||||||
import { requestTariffs } from "@root/services/tariffs.service";
|
import { requestTariffs } from "@root/services/tariffs.service";
|
||||||
|
|
||||||
import { authStore } from "@root/stores/auth";
|
import { authStore } from "@root/stores/auth";
|
||||||
import {
|
import { findPrivilegeById, usePrivilegeStore } from "@root/stores/privilegesStore";
|
||||||
findPrivilegeById,
|
|
||||||
usePrivilegeStore,
|
|
||||||
} from "@root/stores/privilegesStore";
|
|
||||||
|
|
||||||
import type { Privilege_BACKEND } from "@root/model/tariff";
|
import type { Privilege_BACKEND } from "@root/model/tariff";
|
||||||
|
|
||||||
@ -30,10 +17,7 @@ type CreateTariffBackendRequest = {
|
|||||||
privilegies: Omit<Privilege_BACKEND, "_id" | "updatedAt">[];
|
privilegies: Omit<Privilege_BACKEND, "_id" | "updatedAt">[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseUrl =
|
const baseUrl = process.env.NODE_ENV === "production" ? "/strator" : "https://admin.pena.digital/strator";
|
||||||
process.env.NODE_ENV === "production"
|
|
||||||
? "/strator"
|
|
||||||
: "https://admin.pena.digital/strator";
|
|
||||||
|
|
||||||
export default function CreateTariff() {
|
export default function CreateTariff() {
|
||||||
const { makeRequest } = authStore();
|
const { makeRequest } = authStore();
|
||||||
@ -170,7 +154,11 @@ export default function CreateTariff() {
|
|||||||
inputProps={{ sx: { pt: "12px" } }}
|
inputProps={{ sx: { pt: "12px" } }}
|
||||||
>
|
>
|
||||||
{privileges.map((privilege) => (
|
{privileges.map((privilege) => (
|
||||||
<MenuItem key={privilege.description} value={privilege.id}>
|
<MenuItem
|
||||||
|
data-cy={`select-option-${privilege.description}`}
|
||||||
|
key={privilege.description}
|
||||||
|
value={privilege.id}
|
||||||
|
>
|
||||||
{privilege.description}
|
{privilege.description}
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
@ -218,6 +206,8 @@ export default function CreateTariff() {
|
|||||||
type="number"
|
type="number"
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
|
className="btn_createTariffBackend"
|
||||||
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
createTariffBackend();
|
createTariffBackend();
|
||||||
}}
|
}}
|
||||||
|
@ -26,17 +26,9 @@ type EditTariffBackendRequest = {
|
|||||||
privilegies: Omit<Privilege_BACKEND, "_id" | "updatedAt">[];
|
privilegies: Omit<Privilege_BACKEND, "_id" | "updatedAt">[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const baseUrl =
|
const baseUrl = process.env.NODE_ENV === "production" ? "/strator" : "https://admin.pena.digital/strator";
|
||||||
process.env.NODE_ENV === "production"
|
|
||||||
? "/strator"
|
|
||||||
: "https://admin.pena.digital/strator";
|
|
||||||
|
|
||||||
const editTariff = ({
|
const editTariff = ({ tarifIid, tariffName, tariffPrice, privilege }: EditProps): Promise<unknown> => {
|
||||||
tarifIid,
|
|
||||||
tariffName,
|
|
||||||
tariffPrice,
|
|
||||||
privilege,
|
|
||||||
}: EditProps): Promise<unknown> => {
|
|
||||||
const { makeRequest } = authStore.getState();
|
const { makeRequest } = authStore.getState();
|
||||||
|
|
||||||
return makeRequest<EditTariffBackendRequest>({
|
return makeRequest<EditTariffBackendRequest>({
|
||||||
@ -87,12 +79,7 @@ export default function EditModal({ tariff = undefined }: Props) {
|
|||||||
p: 4,
|
p: 4,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Typography
|
<Typography id="modal-modal-title" variant="h6" component="h2" sx={{ whiteSpace: "nowrap" }}>
|
||||||
id="modal-modal-title"
|
|
||||||
variant="h6"
|
|
||||||
component="h2"
|
|
||||||
sx={{ whiteSpace: "nowrap" }}
|
|
||||||
>
|
|
||||||
Редактирование тариффа
|
Редактирование тариффа
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
@ -106,9 +93,7 @@ export default function EditModal({ tariff = undefined }: Props) {
|
|||||||
value={name}
|
value={name}
|
||||||
sx={{ marginBottom: "10px" }}
|
sx={{ marginBottom: "10px" }}
|
||||||
/>
|
/>
|
||||||
<Typography>
|
<Typography>Цена за единицу: {currentTariff.pricePerUnit}</Typography>
|
||||||
Цена за единицу: {currentTariff.pricePerUnit}
|
|
||||||
</Typography>
|
|
||||||
<TextField
|
<TextField
|
||||||
onChange={(event) => setPrice(event.target.value)}
|
onChange={(event) => setPrice(event.target.value)}
|
||||||
label="Цена за единицу"
|
label="Цена за единицу"
|
||||||
@ -119,9 +104,7 @@ export default function EditModal({ tariff = undefined }: Props) {
|
|||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (!currentTariff.isFront) {
|
if (!currentTariff.isFront) {
|
||||||
const privilege = findPrivilegeById(
|
const privilege = findPrivilegeById(currentTariff.privilegeId);
|
||||||
currentTariff.privilegeId
|
|
||||||
);
|
|
||||||
privilege.privilegeId = privilege.id;
|
privilege.privilegeId = privilege.id;
|
||||||
console.log(privilege);
|
console.log(privilege);
|
||||||
|
|
||||||
@ -136,11 +119,7 @@ export default function EditModal({ tariff = undefined }: Props) {
|
|||||||
editTariff({
|
editTariff({
|
||||||
tarifIid: currentTariff.id,
|
tarifIid: currentTariff.id,
|
||||||
tariffName: name ? name : currentTariff.name,
|
tariffName: name ? name : currentTariff.name,
|
||||||
tariffPrice: price
|
tariffPrice: price ? Number(price) : currentTariff.price ? currentTariff.price : privilege.price,
|
||||||
? Number(price)
|
|
||||||
: currentTariff.price
|
|
||||||
? currentTariff.price
|
|
||||||
: privilege.price,
|
|
||||||
isDeleted: currentTariff.isDeleted,
|
isDeleted: currentTariff.isDeleted,
|
||||||
customPricePerUnit: currentTariff.price,
|
customPricePerUnit: currentTariff.price,
|
||||||
privilege: privilege,
|
privilege: privilege,
|
||||||
|
@ -22,10 +22,7 @@ interface Props {
|
|||||||
handleSelectionChange: (selectionModel: GridSelectionModel) => void;
|
handleSelectionChange: (selectionModel: GridSelectionModel) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function TariffsDG({
|
export default function TariffsDG({ selectedTariffs, handleSelectionChange }: Props) {
|
||||||
selectedTariffs,
|
|
||||||
handleSelectionChange,
|
|
||||||
}: Props) {
|
|
||||||
const tariffs = useTariffStore((state) => state.tariffs);
|
const tariffs = useTariffStore((state) => state.tariffs);
|
||||||
const [openDeleteModal, setOpenDeleteModal] = useState(false);
|
const [openDeleteModal, setOpenDeleteModal] = useState(false);
|
||||||
const [changingTariff, setChangingTariff] = useState<Tariff | undefined>();
|
const [changingTariff, setChangingTariff] = useState<Tariff | undefined>();
|
||||||
@ -39,15 +36,10 @@ export default function TariffsDG({
|
|||||||
return {
|
return {
|
||||||
id: tariff.id,
|
id: tariff.id,
|
||||||
name: tariff.name,
|
name: tariff.name,
|
||||||
serviceName:
|
serviceName: privilege?.serviceKey == "templategen" ? "Шаблонизатор" : privilege?.serviceKey,
|
||||||
privilege?.serviceKey == "templategen"
|
|
||||||
? "Шаблонизатор"
|
|
||||||
: privilege?.serviceKey,
|
|
||||||
privilegeName: privilege?.name,
|
privilegeName: privilege?.name,
|
||||||
amount: tariff.amount,
|
amount: tariff.amount,
|
||||||
pricePerUnit: tariff.isCustom
|
pricePerUnit: tariff.isCustom ? (tariff.customPricePerUnit || 0) / 100 : (tariff?.price || 0) / 100,
|
||||||
? (tariff.customPricePerUnit || 0) / 100
|
|
||||||
: (tariff?.price || 0) / 100,
|
|
||||||
type:
|
type:
|
||||||
findPrivilegeById(tariff.privilegeId)?.value === "шаблон"
|
findPrivilegeById(tariff.privilegeId)?.value === "шаблон"
|
||||||
? "штука"
|
? "штука"
|
||||||
@ -67,8 +59,6 @@ export default function TariffsDG({
|
|||||||
setGridData(data);
|
setGridData(data);
|
||||||
}, [tariffs]);
|
}, [tariffs]);
|
||||||
|
|
||||||
console.log(selectedTariffs);
|
|
||||||
|
|
||||||
const closeDeleteModal = () => {
|
const closeDeleteModal = () => {
|
||||||
setOpenDeleteModal(false);
|
setOpenDeleteModal(false);
|
||||||
};
|
};
|
||||||
@ -102,6 +92,7 @@ export default function TariffsDG({
|
|||||||
renderCell: ({ row }) => {
|
renderCell: ({ row }) => {
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
|
className="delete-tariff-button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setOpenDeleteModal(row.id);
|
setOpenDeleteModal(row.id);
|
||||||
}}
|
}}
|
||||||
@ -113,8 +104,6 @@ export default function TariffsDG({
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// console.log(gridData)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Tooltip title="обновить список тарифов">
|
<Tooltip title="обновить список тарифов">
|
||||||
@ -123,6 +112,7 @@ export default function TariffsDG({
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<DataGrid
|
<DataGrid
|
||||||
|
className="tariffs-data-grid"
|
||||||
disableSelectionOnClick={true}
|
disableSelectionOnClick={true}
|
||||||
checkboxSelection={true}
|
checkboxSelection={true}
|
||||||
rows={gridData}
|
rows={gridData}
|
||||||
@ -141,10 +131,7 @@ export default function TariffsDG({
|
|||||||
mb: "30px",
|
mb: "30px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button onClick={() => setOpenDeleteModal(true)} sx={{ mr: "20px", zIndex: "10000" }}>
|
||||||
onClick={() => setOpenDeleteModal(true)}
|
|
||||||
sx={{ mr: "20px", zIndex: "10000" }}
|
|
||||||
>
|
|
||||||
Удаление
|
Удаление
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -2,11 +2,7 @@
|
|||||||
"extends": "./tsconfig.extend.json",
|
"extends": "./tsconfig.extend.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "es5",
|
||||||
"lib": [
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
"dom",
|
|
||||||
"dom.iterable",
|
|
||||||
"esnext"
|
|
||||||
],
|
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
@ -19,9 +15,10 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"jsx": "react-jsx"
|
"jsx": "react-jsx",
|
||||||
|
"types": ["node"],
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src", "**/*.ts"]
|
||||||
"src"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user