From d69d27acb4dc8321246bc7a7c30302e51366dc53 Mon Sep 17 00:00:00 2001 From: Nastya Date: Mon, 6 Nov 2023 02:33:40 +0300 Subject: [PATCH] add husky && eslinter --- .eslintrc.json | 34 + .husky/pre-commit | 4 + babel.config.js | 10 +- craco.config.js | 30 +- cypress.config.ts | 18 +- cypress/e2e/access.cy.ts | 178 +- package.json | 14 +- src/__mocks__/CustomRadioButtonsMocks.ts | 8 +- src/__mocks__/showCaseObject.ts | 12 +- src/__mocks__/showCaseTime.ts | 102 +- src/__mocks__/showCaseVolume.ts | 102 +- src/api/auth.ts | 100 +- src/api/cart.ts | 112 +- src/api/history.ts | 26 +- src/api/price.ts | 32 +- src/api/tariff.ts | 114 +- src/api/ticket.ts | 62 +- src/api/user.ts | 40 +- src/api/verification.ts | 104 +- src/api/wallet.ts | 68 +- src/components/CardWithLink.tsx | 100 +- src/components/ChatMessage.tsx | 150 +- src/components/ComplexHeader.tsx | 34 +- src/components/CustomAccordion.tsx | 178 +- src/components/CustomSaveAccordion.tsx | 128 +- src/components/CustomSlider.tsx | 116 +- src/components/CustomTab.tsx | 32 +- src/components/CustomTariffAccordion.tsx | 288 +-- src/components/CustomWrapperDrawer.tsx | 440 ++-- src/components/Drawers.tsx | 624 ++--- src/components/FloatingSupportChat/Chat.tsx | 572 ++--- .../CircleDoubleDownIcon.tsx | 36 +- .../FloatingSupportChat.tsx | 176 +- .../FloatingSupportChat/UserCircleIcon.tsx | 34 +- src/components/Footer.tsx | 146 +- src/components/InputTextfield.tsx | 152 +- src/components/Loader.tsx | 46 +- src/components/Menu.tsx | 232 +- src/components/NavbarLanding/Avatar.tsx | 68 +- src/components/NavbarLanding/DialogMenu.tsx | 274 +-- src/components/NavbarLanding/Navbar.tsx | 12 +- .../NavbarLanding/NavbarCollapsed.tsx | 70 +- src/components/NavbarLanding/NavbarFull.tsx | 296 +-- src/components/NavbarSite/DialogMenu.tsx | 346 +-- src/components/NavbarSite/Navbar.tsx | 40 +- src/components/NavbarSite/NavbarCollapsed.tsx | 456 ++-- src/components/NavbarSite/NavbarFull.tsx | 160 +- src/components/NavbarSite/NavbarPanel.tsx | 162 +- src/components/NotificationsModal.tsx | 248 +- src/components/NumberIcon.tsx | 154 +- .../NumberInputWithUnitAdornment.tsx | 166 +- src/components/PenaLogo.tsx | 50 +- src/components/ProtectedLayout.tsx | 148 +- src/components/SectionWrapper.tsx | 38 +- src/components/Select/index.tsx | 150 +- src/components/Tabs.tsx | 28 +- src/components/TotalPrice.tsx | 246 +- src/components/UnderlinedButtonWithIcon.tsx | 64 +- src/components/icons/CalendarIcon.tsx | 120 +- src/components/icons/CloseIcons.tsx | 40 +- src/components/icons/CloseSmallIcon.tsx | 32 +- src/components/icons/CustomIcon.tsx | 104 +- src/components/icons/ExpandIcon.tsx | 34 +- src/components/icons/EyeIcon.tsx | 32 +- src/components/icons/File.tsx | 38 +- src/components/icons/LogoutIcon.tsx | 18 +- src/components/icons/PaperClipIcon.tsx | 30 +- src/components/icons/PieChartIcon.tsx | 44 +- src/components/icons/SendIcon.tsx | 16 +- src/components/icons/UploadIcon.tsx | 34 +- src/components/icons/WalletIcon.tsx | 58 +- src/components/passwordInput.tsx | 212 +- src/components/templCardPhoneLight.tsx | 100 +- src/components/templCardPhonePink.tsx | 52 +- src/components/wideTemplCard.tsx | 90 +- src/constants/documentTypeMap.tsx | 12 +- src/index.tsx | 212 +- src/model/account.ts | 2 +- src/model/auth.ts | 2 +- src/model/customTariffs.ts | 4 +- src/model/discount.ts | 2 +- src/model/privilege.ts | 2 +- src/model/tariff.ts | 2 +- src/pages/AccountSettings/AccountSettings.tsx | 310 +-- .../DocumentsDialog/DocumentItem.tsx | 116 +- .../DocumentsDialog/DocumentUploadItem.tsx | 168 +- .../DocumentsDialog/DocumentsDialog.tsx | 22 +- .../JuridicalDocumentsDialog.tsx | 402 +-- .../DocumentsDialog/NkoDocumentsDialog.tsx | 468 ++-- src/pages/AccountSettings/UserFields.tsx | 226 +- src/pages/AccountSettings/helper.ts | 92 +- src/pages/Cart/Cart.tsx | 138 +- src/pages/Cart/CustomWrapper.tsx | 354 +-- src/pages/Faq/AccordionWrapper.tsx | 32 +- src/pages/Faq/Faq.tsx | 330 +-- src/pages/History/AccordionWrapper.tsx | 412 ++-- src/pages/History/historyMocks.ts | 244 +- src/pages/History/index.tsx | 174 +- src/pages/Landing/Infographics.tsx | 48 +- src/pages/Landing/Landing.tsx | 66 +- src/pages/Landing/PromoCard.tsx | 146 +- src/pages/Landing/Section1.tsx | 148 +- src/pages/Landing/Section2.tsx | 112 +- src/pages/Landing/Section3.tsx | 240 +- src/pages/Landing/Section4.tsx | 64 +- src/pages/Landing/Section5.tsx | 98 +- src/pages/Payment/Payment.tsx | 424 ++-- src/pages/Payment/PaymentMethodCard.tsx | 64 +- src/pages/SavedTariffs/AccordionWrapper.tsx | 196 +- src/pages/SavedTariffs/SaveWrapper.tsx | 268 +- src/pages/SavedTariffs/index.tsx | 126 +- src/pages/Support/CreateTicket.tsx | 248 +- src/pages/Support/Support.tsx | 116 +- src/pages/Support/SupportChat.tsx | 582 ++--- src/pages/Support/TicketList/TicketCard.tsx | 178 +- src/pages/Support/TicketList/TicketList.tsx | 170 +- .../TariffConstructor/CustomTariffCard.tsx | 248 +- .../TariffConstructor/TariffConstructor.tsx | 164 +- src/pages/TariffConstructor/TariffItem.tsx | 248 +- src/pages/Tariffs/FreeTariffCard.tsx | 56 +- src/pages/Tariffs/TariffCard.tsx | 176 +- src/pages/Tariffs/Tariffs.tsx | 184 +- src/pages/Tariffs/TariffsPage.tsx | 326 +-- src/pages/Tariffs/slider/index.tsx | 2 +- src/pages/Tariffs/slider/slider.tsx | 220 +- src/pages/Wallet.tsx | 268 +- src/pages/auth/AmoButton.tsx | 78 +- src/pages/auth/Signin.tsx | 392 +-- src/pages/auth/Signup.tsx | 412 ++-- src/react-app-env.d.ts | 4 +- src/reportWebVitals.ts | 24 +- src/setupTests.ts | 2 +- src/stores/cart.ts | 148 +- src/stores/customTariffs.ts | 182 +- src/stores/discounts.ts | 28 +- src/stores/messages.ts | 76 +- src/stores/privileges.ts | 28 +- src/stores/tariffs.ts | 60 +- src/stores/tickets.ts | 50 +- src/stores/unauthTicket.ts | 96 +- src/stores/user.ts | 460 ++-- src/utils/calcCart/calcCart.test.ts | 2180 ++++++++--------- src/utils/calcCart/calcCart.ts | 130 +- src/utils/calcTariffPrices.ts | 30 +- src/utils/currencyFormatter.ts | 16 +- src/utils/date.ts | 28 +- src/utils/declension.ts | 42 +- src/utils/deleteEmptyKeys.ts | 16 +- src/utils/downloadFileToDevice.ts | 14 +- src/utils/handleComponentError.ts | 48 +- src/utils/hooks/handleCustomBackNavigation.ts | 36 +- src/utils/hooks/useCart.ts | 126 +- src/utils/hooks/useCustomTariffs.ts | 52 +- src/utils/hooks/useDiscounts.ts | 50 +- src/utils/hooks/useHistoryData.ts | 44 +- src/utils/hooks/useHistoryTracker.ts | 48 +- src/utils/hooks/useTariffFetcher.ts | 60 +- src/utils/jsonToFormdata.ts | 48 +- src/utils/parse-error.ts | 68 +- src/utils/readFile.ts | 72 +- src/utils/routes/ProtectedRoute.tsx | 8 +- src/utils/serviceKeys.ts | 10 +- src/utils/theme.ts | 14 +- yarn.lock | 777 +++++- 164 files changed, 12282 insertions(+), 11471 deletions(-) create mode 100644 .eslintrc.json create mode 100755 .husky/pre-commit diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..b510487 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,34 @@ +{ + "env": { + "browser": true, + "es2021": true + }, + "extends": [], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": [ + "@typescript-eslint", + "react" + ], + "rules": { + "indent": [ + "error", + "tab" + ], + "linebreak-style": [ + "error", + "unix" + ], + "quotes": [ + "error", + "double" + ], + "semi": [ + "error", + "never" + ] + } +} diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 0000000..3e48a61 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,4 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" + +yarn eslint . --fix diff --git a/babel.config.js b/babel.config.js index dd242dc..606618f 100644 --- a/babel.config.js +++ b/babel.config.js @@ -1,6 +1,6 @@ module.exports = { - presets: [ - ["@babel/preset-env", { targets: { node: "current" } }], - "@babel/preset-typescript", - ], -}; + presets: [ + ["@babel/preset-env", { targets: { node: "current" } }], + "@babel/preset-typescript", + ], +} diff --git a/craco.config.js b/craco.config.js index fa1bc01..7a845ad 100644 --- a/craco.config.js +++ b/craco.config.js @@ -1,17 +1,17 @@ -const CracoAlias = require("craco-alias"); +const CracoAlias = require("craco-alias") module.exports = { - plugins: [ - { - plugin: CracoAlias, - options: { - source: "tsconfig", - // baseUrl SHOULD be specified - // plugin does not take it from tsconfig - baseUrl: "./src", - // tsConfigPath should point to the file where "baseUrl" and "paths" are specified - tsConfigPath: "./tsconfig.extend.json" - } - } - ] -}; \ No newline at end of file + plugins: [ + { + plugin: CracoAlias, + options: { + source: "tsconfig", + // baseUrl SHOULD be specified + // plugin does not take it from tsconfig + baseUrl: "./src", + // tsConfigPath should point to the file where "baseUrl" and "paths" are specified + tsConfigPath: "./tsconfig.extend.json" + } + } + ] +} \ No newline at end of file diff --git a/cypress.config.ts b/cypress.config.ts index a43fe1b..1b2b0b6 100644 --- a/cypress.config.ts +++ b/cypress.config.ts @@ -1,11 +1,11 @@ -import { defineConfig } from "cypress"; +import { defineConfig } from "cypress" export default defineConfig({ - e2e: { - viewportWidth: 1200, - viewportHeight: 800, - fixturesFolder: "tests/e2e/fixtures", - supportFile: false, - defaultCommandTimeout: 100, - }, -}); + e2e: { + viewportWidth: 1200, + viewportHeight: 800, + fixturesFolder: "tests/e2e/fixtures", + supportFile: false, + defaultCommandTimeout: 100, + }, +}) diff --git a/cypress/e2e/access.cy.ts b/cypress/e2e/access.cy.ts index b065432..22a3cec 100644 --- a/cypress/e2e/access.cy.ts +++ b/cypress/e2e/access.cy.ts @@ -1,125 +1,125 @@ describe("Форма Входа", () => { - beforeEach(() => { - cy.visit("http://localhost:3000"); - cy.wait(1000); - cy.contains("Личный кабинет").click(); - }); + beforeEach(() => { + cy.visit("http://localhost:3000") + cy.wait(1000) + cy.contains("Личный кабинет").click() + }) - it("должна успешно входить с правильными учетными данными", () => { - const login = "valid_user@example.com"; - const password = "valid_password"; + it("должна успешно входить с правильными учетными данными", () => { + const login = "valid_user@example.com" + const password = "valid_password" - cy.get("#login").type(login); - cy.get("#password").type(password); - cy.get('button[type="submit"]').click(); + cy.get("#login").type(login) + cy.get("#password").type(password) + cy.get("button[type=\"submit\"]").click() - cy.wait(2000); - cy.url().should("include", "http://localhost:3000/tariffs"); - }); + cy.wait(2000) + cy.url().should("include", "http://localhost:3000/tariffs") + }) - it("должна отображать два сообщение об ошибке при отсутствии полей", () => { - cy.get('button[type="submit"]').click(); + it("должна отображать два сообщение об ошибке при отсутствии полей", () => { + cy.get("button[type=\"submit\"]").click() - cy.wait(2000); - cy.get("#password-helper-text").should("contain", "Поле обязательно"); - cy.get("#login-helper-text").should("contain", "Поле обязательно"); - }); + cy.wait(2000) + cy.get("#password-helper-text").should("contain", "Поле обязательно") + cy.get("#login-helper-text").should("contain", "Поле обязательно") + }) - it("должна отображать сообщение об ошибке при отсутствии пароля", () => { - cy.get("#login").type("valid_email@example.com"); - cy.get('button[type="submit"]').click(); + it("должна отображать сообщение об ошибке при отсутствии пароля", () => { + cy.get("#login").type("valid_email@example.com") + cy.get("button[type=\"submit\"]").click() - cy.get("#password-helper-text").should("contain", "Поле обязательно"); - }); + cy.get("#password-helper-text").should("contain", "Поле обязательно") + }) - it("должна отображать сообщение об ошибке при отсутствии Логина", () => { - cy.get("#password").type("valid_password"); - cy.get('button[type="submit"]').click(); + it("должна отображать сообщение об ошибке при отсутствии Логина", () => { + cy.get("#password").type("valid_password") + cy.get("button[type=\"submit\"]").click() - cy.get("#login-helper-text").should("contain", "Поле обязательно"); - }); -}); + cy.get("#login-helper-text").should("contain", "Поле обязательно") + }) +}) describe("Форма регистрации", () => { - beforeEach(() => { - cy.visit("http://localhost:3000"); - cy.wait(1000); - cy.contains("Личный кабинет").click(); - cy.contains("Регистрация").click(); - }); + beforeEach(() => { + cy.visit("http://localhost:3000") + cy.wait(1000) + cy.contains("Личный кабинет").click() + cy.contains("Регистрация").click() + }) - it("должна регистрировать нового пользователя с правильными данными", () => { - const login = Cypress._.random(1000) + "@example.com"; - const password = "valid_password"; + it("должна регистрировать нового пользователя с правильными данными", () => { + const login = Cypress._.random(1000) + "@example.com" + const password = "valid_password" - cy.get("#login").type(login); - cy.get("#password").type(password); - cy.get("#repeatPassword").type(password); + cy.get("#login").type(login) + cy.get("#password").type(password) + cy.get("#repeatPassword").type(password) - cy.get('button[type="submit"]').click(); - cy.wait(5000); + cy.get("button[type=\"submit\"]").click() + cy.wait(5000) - cy.url().should("include", "http://localhost:3000/tariffs"); - }); + cy.url().should("include", "http://localhost:3000/tariffs") + }) - it("должна отображать ошибку при отсутсвии логина", () => { - cy.get("#password").type("valid_password"); - cy.get("#repeatPassword").type("valid_password"); + it("должна отображать ошибку при отсутсвии логина", () => { + cy.get("#password").type("valid_password") + cy.get("#repeatPassword").type("valid_password") - cy.get('button[type="submit"]').click(); + cy.get("button[type=\"submit\"]").click() - cy.get("#login-helper-text").should("contain", "Поле обязательно"); - }); + cy.get("#login-helper-text").should("contain", "Поле обязательно") + }) - it("должна отображать ошибку при отсутствии пароля", () => { - cy.get("#login").type("valid_login"); + it("должна отображать ошибку при отсутствии пароля", () => { + cy.get("#login").type("valid_login") - cy.get('button[type="submit"]').click(); + cy.get("button[type=\"submit\"]").click() - cy.get("#password-helper-text").should("contain", "Поле обязательно"); - }); + cy.get("#password-helper-text").should("contain", "Поле обязательно") + }) - it("должна отображать ошибку при отсутствии поля Повторения пароля", () => { - cy.get("#login").type("valid_login"); - cy.get("#password").type("valid_password"); + it("должна отображать ошибку при отсутствии поля Повторения пароля", () => { + cy.get("#login").type("valid_login") + cy.get("#password").type("valid_password") - cy.get('button[type="submit"]').click(); + cy.get("button[type=\"submit\"]").click() - cy.get("#repeatPassword-helper-text").should("contain", "Повторите пароль"); - }); + cy.get("#repeatPassword-helper-text").should("contain", "Повторите пароль") + }) - it("должна отображать ошибку при некоректном пароле", () => { - cy.get("#login").type("valid_log"); - cy.get("#password").type("valid@12_-_@@password"); + it("должна отображать ошибку при некоректном пароле", () => { + cy.get("#login").type("valid_log") + cy.get("#password").type("valid@12_-_@@password") - cy.get('button[type="submit"]').click(); + cy.get("button[type=\"submit\"]").click() - cy.get("#password-helper-text").should("contain", "Некорректные символы"); + cy.get("#password-helper-text").should("contain", "Некорректные символы") - cy.get("#repeatPassword-helper-text").should("contain", "Повторите пароль"); - }); + cy.get("#repeatPassword-helper-text").should("contain", "Повторите пароль") + }) - it("должна отображать ошибку при несовпадении паролей", () => { - cy.get("#login").type("valid_login"); - cy.get("#password").type("valid_password"); - cy.get("#repeatPassword").type("invalidPassword"); + it("должна отображать ошибку при несовпадении паролей", () => { + cy.get("#login").type("valid_login") + cy.get("#password").type("valid_password") + cy.get("#repeatPassword").type("invalidPassword") - cy.get('button[type="submit"]').click(); + cy.get("button[type=\"submit\"]").click() - cy.get("#repeatPassword-helper-text").should("contain", "Пароли не совпадают"); - }); + cy.get("#repeatPassword-helper-text").should("contain", "Пароли не совпадают") + }) - it("попытка отправки запроса при уже зарегистрированном пользователе", () => { - const login = "valid_user@example.com"; - const password = "valid_password"; + it("попытка отправки запроса при уже зарегистрированном пользователе", () => { + const login = "valid_user@example.com" + const password = "valid_password" - cy.get("#login").type(login); - cy.get("#password").type(password); - cy.get("#repeatPassword").type(password); + cy.get("#login").type(login) + cy.get("#password").type(password) + cy.get("#repeatPassword").type(password) - cy.get('button[type="submit"]').click(); + cy.get("button[type=\"submit\"]").click() - cy.wait(5000); - cy.contains("user with this login is exist"); - }); -}); + cy.wait(5000) + cy.contains("user with this login is exist") + }) +}) diff --git a/package.json b/package.json index 14b55cd..293cb45 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "test:cart": "craco test src/utils/calcCart --transformIgnorePatterns \"node_modules/(?!@frontend)/\"", "eject": "craco eject", "test:cypress": "start-server-and-test start http://localhost:3000 cypress", - "cypress": "cypress open" + "cypress": "cypress open", + "prepare": "husky install" }, "dependencies": { "@emotion/react": "^11.10.5", @@ -23,6 +24,7 @@ "classnames": "^2.3.2", "cypress": "^12.17.3", "formik": "^2.2.9", + "husky": "^8.0.3", "immer": "^10.0.2", "isomorphic-fetch": "^3.0.0", "notistack": "^3.0.1", @@ -48,17 +50,15 @@ "@types/react": "^18.0.0", "@types/react-dom": "^18.0.0", "@types/react-slick": "^0.23.10", + "@typescript-eslint/eslint-plugin": "^6.9.1", + "@typescript-eslint/parser": "^6.9.1", "craco-alias": "^3.0.1", + "eslint": "^8.53.0", + "eslint-plugin-react": "^7.33.2", "jest": "^29.5.0", "react-scripts": "5.0.1", "typescript": "^4.9.3" }, - "eslintConfig": { - "extends": [ - "react-app", - "react-app/jest" - ] - }, "browserslist": { "production": [ ">0.2%", diff --git a/src/__mocks__/CustomRadioButtonsMocks.ts b/src/__mocks__/CustomRadioButtonsMocks.ts index fdd33c0..957ea2d 100644 --- a/src/__mocks__/CustomRadioButtonsMocks.ts +++ b/src/__mocks__/CustomRadioButtonsMocks.ts @@ -1,5 +1,5 @@ export const _mocsk_: { name: string; type: "templ" | "squiz" | "reducer" }[] = [ - { name: "Шаблонизатор", type: "templ" }, - { name: "Опросник", type: "squiz" }, - { name: "Сокращатель ссылок", type: "reducer" }, -]; + { name: "Шаблонизатор", type: "templ" }, + { name: "Опросник", type: "squiz" }, + { name: "Сокращатель ссылок", type: "reducer" }, +] diff --git a/src/__mocks__/showCaseObject.ts b/src/__mocks__/showCaseObject.ts index c8a17d1..f01cb5c 100644 --- a/src/__mocks__/showCaseObject.ts +++ b/src/__mocks__/showCaseObject.ts @@ -1,5 +1,5 @@ -import { showCaseTime } from "./showCaseTime"; -import { showCaseVolume } from "./showCaseVolume"; +import { showCaseTime } from "./showCaseTime" +import { showCaseVolume } from "./showCaseVolume" export const showCaseObject: Record< string, @@ -20,7 +20,7 @@ export const showCaseObject: Record< }[] > > = { - templ: { volume: showCaseVolume, time: showCaseTime }, - squiz: { volume: showCaseVolume, time: showCaseTime }, - reducer: { volume: showCaseVolume, time: showCaseTime }, -}; + templ: { volume: showCaseVolume, time: showCaseTime }, + squiz: { volume: showCaseVolume, time: showCaseTime }, + reducer: { volume: showCaseVolume, time: showCaseTime }, +} diff --git a/src/__mocks__/showCaseTime.ts b/src/__mocks__/showCaseTime.ts index db03846..fdc8ee3 100644 --- a/src/__mocks__/showCaseTime.ts +++ b/src/__mocks__/showCaseTime.ts @@ -1,53 +1,53 @@ -import Infinity from "../assets/Icons/tariffs-time/Infinity.svg"; -import OneIcons from "../assets/Icons/tariffs-time/OneIcons.svg"; -import ThreeIcons from "../assets/Icons/tariffs-time/ThreeIcons.svg"; -import SixIcons from "../assets/Icons/tariffs-time/SixIcons.svg"; -import NineIcons from "../assets/Icons/tariffs-time/NineIcons.svg"; +import Infinity from "../assets/Icons/tariffs-time/Infinity.svg" +import OneIcons from "../assets/Icons/tariffs-time/OneIcons.svg" +import ThreeIcons from "../assets/Icons/tariffs-time/ThreeIcons.svg" +import SixIcons from "../assets/Icons/tariffs-time/SixIcons.svg" +import NineIcons from "../assets/Icons/tariffs-time/NineIcons.svg" export const showCaseTime = [ - { - name: "Безлимит", - desc: "Текст-заполнитель — это текст, который имеет", - style: { icon: Infinity, bgcolor: "#D6F3E9" }, - id: "id1", - privelegeid: "1", - amount: 10, - price: 100, - }, - { - name: "1 месяц", - desc: "Текст-заполнитель — это текст, который имеет", - style: { icon: OneIcons, bgcolor: "#EEE4FC" }, - id: "id2", - privelegeid: "2", - amount: 10, - price: 1000, - }, - { - name: "3 месяц", - desc: "Текст-заполнитель — это текст, который имеет", - style: { icon: ThreeIcons, bgcolor: "#EEE4FC" }, - id: "id3", - privelegeid: "3", - amount: 10, - price: 1000, - }, - { - name: "6 месяц", - desc: "Текст-заполнитель — это текст, который имеет", - style: { icon: SixIcons, bgcolor: "#EEE4FC" }, - id: "id4", - privelegeid: "4", - amount: 10, - price: 1000, - }, - { - name: "9 месяц", - desc: "Текст-заполнитель — это текст, который имеет", - style: { icon: NineIcons, bgcolor: "#EEE4FC" }, - id: "id5", - privelegeid: "5", - amount: 10, - price: 1000, - }, -]; + { + name: "Безлимит", + desc: "Текст-заполнитель — это текст, который имеет", + style: { icon: Infinity, bgcolor: "#D6F3E9" }, + id: "id1", + privelegeid: "1", + amount: 10, + price: 100, + }, + { + name: "1 месяц", + desc: "Текст-заполнитель — это текст, который имеет", + style: { icon: OneIcons, bgcolor: "#EEE4FC" }, + id: "id2", + privelegeid: "2", + amount: 10, + price: 1000, + }, + { + name: "3 месяц", + desc: "Текст-заполнитель — это текст, который имеет", + style: { icon: ThreeIcons, bgcolor: "#EEE4FC" }, + id: "id3", + privelegeid: "3", + amount: 10, + price: 1000, + }, + { + name: "6 месяц", + desc: "Текст-заполнитель — это текст, который имеет", + style: { icon: SixIcons, bgcolor: "#EEE4FC" }, + id: "id4", + privelegeid: "4", + amount: 10, + price: 1000, + }, + { + name: "9 месяц", + desc: "Текст-заполнитель — это текст, который имеет", + style: { icon: NineIcons, bgcolor: "#EEE4FC" }, + id: "id5", + privelegeid: "5", + amount: 10, + price: 1000, + }, +] diff --git a/src/__mocks__/showCaseVolume.ts b/src/__mocks__/showCaseVolume.ts index f463c92..bca8978 100644 --- a/src/__mocks__/showCaseVolume.ts +++ b/src/__mocks__/showCaseVolume.ts @@ -1,53 +1,53 @@ -import OneIcons from "../assets/Icons/tariffs-volume/OneIcons.svg"; -import TwoIcons from "../assets/Icons/tariffs-volume/TwoIcons.svg"; -import ThreeIcons from "../assets/Icons/tariffs-volume/ThreeIcons.svg"; -import FourIcons from "../assets/Icons/tariffs-volume/FourIcons.svg"; -import FiveIcons from "../assets/Icons/tariffs-volume/FiveIcons.svg"; +import OneIcons from "../assets/Icons/tariffs-volume/OneIcons.svg" +import TwoIcons from "../assets/Icons/tariffs-volume/TwoIcons.svg" +import ThreeIcons from "../assets/Icons/tariffs-volume/ThreeIcons.svg" +import FourIcons from "../assets/Icons/tariffs-volume/FourIcons.svg" +import FiveIcons from "../assets/Icons/tariffs-volume/FiveIcons.svg" export const showCaseVolume = [ - { - name: "Безлимит", - desc: "Текст-заполнитель — это текст, который имеет", - style: { icon: OneIcons, bgcolor: "#FEDFD0" }, - id: "id1", - privelegeid: "1", - amount: 10, - price: 100, - }, - { - name: "1 месяц", - desc: "Текст-заполнитель — это текст, который имеет", - style: { icon: TwoIcons, bgcolor: "#FEDFD0" }, - id: "id2", - privelegeid: "2", - amount: 10, - price: 1000, - }, - { - name: "3 месяц", - desc: "Текст-заполнитель — это текст, который имеет", - style: { icon: ThreeIcons, bgcolor: "#FEDFD0" }, - id: "id3", - privelegeid: "3", - amount: 10, - price: 1000, - }, - { - name: "6 месяц", - desc: "Текст-заполнитель — это текст, который имеет", - style: { icon: FourIcons, bgcolor: "#FEDFD0" }, - id: "id4", - privelegeid: "4", - amount: 10, - price: 1000, - }, - { - name: "9 месяц", - desc: "Текст-заполнитель — это текст, который имеет", - style: { icon: FiveIcons, bgcolor: "#FEDFD0" }, - id: "id5", - privelegeid: "5", - amount: 10, - price: 1000, - }, -]; + { + name: "Безлимит", + desc: "Текст-заполнитель — это текст, который имеет", + style: { icon: OneIcons, bgcolor: "#FEDFD0" }, + id: "id1", + privelegeid: "1", + amount: 10, + price: 100, + }, + { + name: "1 месяц", + desc: "Текст-заполнитель — это текст, который имеет", + style: { icon: TwoIcons, bgcolor: "#FEDFD0" }, + id: "id2", + privelegeid: "2", + amount: 10, + price: 1000, + }, + { + name: "3 месяц", + desc: "Текст-заполнитель — это текст, который имеет", + style: { icon: ThreeIcons, bgcolor: "#FEDFD0" }, + id: "id3", + privelegeid: "3", + amount: 10, + price: 1000, + }, + { + name: "6 месяц", + desc: "Текст-заполнитель — это текст, который имеет", + style: { icon: FourIcons, bgcolor: "#FEDFD0" }, + id: "id4", + privelegeid: "4", + amount: 10, + price: 1000, + }, + { + name: "9 месяц", + desc: "Текст-заполнитель — это текст, который имеет", + style: { icon: FiveIcons, bgcolor: "#FEDFD0" }, + id: "id5", + privelegeid: "5", + amount: 10, + price: 1000, + }, +] diff --git a/src/api/auth.ts b/src/api/auth.ts index eabe5c5..526fe66 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -1,76 +1,76 @@ -import { makeRequest } from "@frontend/kitui"; +import { makeRequest } from "@frontend/kitui" -import { parseAxiosError } from "@root/utils/parse-error"; +import { parseAxiosError } from "@root/utils/parse-error" import type { - LoginRequest, - LoginResponse, - RegisterRequest, - RegisterResponse, -} from "@frontend/kitui"; + LoginRequest, + LoginResponse, + RegisterRequest, + RegisterResponse, +} from "@frontend/kitui" const apiUrl = process.env.NODE_ENV === "production" - ? "/auth" - : "https://hub.pena.digital/auth"; + ? "/auth" + : "https://hub.pena.digital/auth" export async function register( - login: string, - password: string, - phoneNumber: string + login: string, + password: string, + phoneNumber: string ): Promise<[RegisterResponse | null, string?]> { - try { - const registerResponse = await makeRequest< + try { + const registerResponse = await makeRequest< RegisterRequest, RegisterResponse >({ - url: apiUrl + "/register", - body: { login, password, phoneNumber }, - useToken: false, - withCredentials: true, - }); + url: apiUrl + "/register", + body: { login, password, phoneNumber }, + useToken: false, + withCredentials: true, + }) - return [registerResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [registerResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Не удалось зарегестрировать аккаунт. ${error}`]; - } + return [null, `Не удалось зарегестрировать аккаунт. ${error}`] + } } export async function login( - login: string, - password: string + login: string, + password: string ): Promise<[LoginResponse | null, string?]> { - try { - const loginResponse = await makeRequest({ - url: apiUrl + "/login", - body: { login, password }, - useToken: false, - withCredentials: true, - }); + try { + const loginResponse = await makeRequest({ + url: apiUrl + "/login", + body: { login, password }, + useToken: false, + withCredentials: true, + }) - return [loginResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [loginResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Не удалось войти. ${error}`]; - } + return [null, `Не удалось войти. ${error}`] + } } export async function logout(): Promise<[unknown, string?]> { - try { - const logoutResponse = await makeRequest({ - url: apiUrl + "/logout", - method: "POST", - useToken: true, - withCredentials: true, - }); + try { + const logoutResponse = await makeRequest({ + url: apiUrl + "/logout", + method: "POST", + useToken: true, + withCredentials: true, + }) - return [logoutResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [logoutResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Не удалось выйти. ${error}`]; - } + return [null, `Не удалось выйти. ${error}`] + } } diff --git a/src/api/cart.ts b/src/api/cart.ts index 5c2cc22..e7dd9bb 100644 --- a/src/api/cart.ts +++ b/src/api/cart.ts @@ -1,86 +1,86 @@ -import { UserAccount, makeRequest } from "@frontend/kitui"; -import { AxiosError } from 'axios'; +import { UserAccount, makeRequest } from "@frontend/kitui" +import { AxiosError } from "axios" -import { parseAxiosError } from "@root/utils/parse-error"; +import { parseAxiosError } from "@root/utils/parse-error" const apiUrl = process.env.NODE_ENV === "production" - ? "/customer" - : "https://hub.pena.digital/customer"; + ? "/customer" + : "https://hub.pena.digital/customer" export async function patchCart( - tariffId: string + tariffId: string ): Promise<[string[], string?]> { - try { - const patchCartResponse = await makeRequest({ - url: apiUrl + `/cart?id=${tariffId}`, - method: "PATCH", - useToken: true, - }); + try { + const patchCartResponse = await makeRequest({ + url: apiUrl + `/cart?id=${tariffId}`, + method: "PATCH", + useToken: true, + }) - return [patchCartResponse.cart]; - } catch (nativeError) { - let [error, status] = parseAxiosError(nativeError); - if (status === 400 && error.indexOf("invalid id") !== -1) error = "Данный тариф более недоступен" + return [patchCartResponse.cart] + } catch (nativeError) { + let [error, status] = parseAxiosError(nativeError) + if (status === 400 && error.indexOf("invalid id") !== -1) error = "Данный тариф более недоступен" - return [[], `Не удалось добавить товар в корзину. ${error}`]; - } + return [[], `Не удалось добавить товар в корзину. ${error}`] + } } export async function deleteCart( - tariffId: string + tariffId: string ): Promise<[string[], string?]> { - try { - const deleteCartResponse = await makeRequest({ - url: apiUrl + `/cart?id=${tariffId}`, - method: "DELETE", - useToken: true, - }); + try { + const deleteCartResponse = await makeRequest({ + url: apiUrl + `/cart?id=${tariffId}`, + method: "DELETE", + useToken: true, + }) - return [deleteCartResponse.cart]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [deleteCartResponse.cart] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [[], `Не удалось удалить товар из корзины. ${error}`]; - } + return [[], `Не удалось удалить товар из корзины. ${error}`] + } } export async function payCart(): Promise<[UserAccount | null, string?]> { - try { - const payCartResponse = await makeRequest({ - url: apiUrl + "/cart/pay", - method: "POST", - useToken: true, - }); + try { + const payCartResponse = await makeRequest({ + url: apiUrl + "/cart/pay", + method: "POST", + useToken: true, + }) - return [payCartResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [payCartResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Не удалось оплатить товар из корзины. ${error}`]; - } + return [null, `Не удалось оплатить товар из корзины. ${error}`] + } } export async function patchCurrency( - currency: string + currency: string ): Promise<[UserAccount | null, string?]> { - try { - const patchCurrencyResponse = await makeRequest< + try { + const patchCurrencyResponse = await makeRequest< { currency: string }, UserAccount >({ - url: apiUrl + "/wallet", - method: "PATCH", - useToken: true, - body: { - currency, - }, - }); + url: apiUrl + "/wallet", + method: "PATCH", + useToken: true, + body: { + currency, + }, + }) - return [patchCurrencyResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [patchCurrencyResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Не удалось изменить валюту. ${error}`]; - } + return [null, `Не удалось изменить валюту. ${error}`] + } } \ No newline at end of file diff --git a/src/api/history.ts b/src/api/history.ts index 23820b6..ee4273f 100644 --- a/src/api/history.ts +++ b/src/api/history.ts @@ -1,5 +1,5 @@ -import { Tariff, makeRequest } from "@frontend/kitui"; -import { parseAxiosError } from "@root/utils/parse-error"; +import { Tariff, makeRequest } from "@frontend/kitui" +import { parseAxiosError } from "@root/utils/parse-error" export interface GetHistoryResponse { totalPages: number; @@ -21,17 +21,17 @@ type RawDetails = { Key: string; Value: KeyValue[][] } type KeyValue = { Key: string; Value: string | number }; export async function getHistory(): Promise<[GetHistoryResponse | null, string?]> { - try { - const historyResponse = await makeRequest({ - url: "https://hub.pena.digital/customer/history?page=1&limit=100&type=payCart", - method: "get", - useToken: true, - }); + try { + const historyResponse = await makeRequest({ + url: "https://hub.pena.digital/customer/history?page=1&limit=100&type=payCart", + method: "get", + useToken: true, + }) - return [historyResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [historyResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Не удалось получить историю. ${error}`]; - } + return [null, `Не удалось получить историю. ${error}`] + } } diff --git a/src/api/price.ts b/src/api/price.ts index 01849cd..a8a3b41 100644 --- a/src/api/price.ts +++ b/src/api/price.ts @@ -1,24 +1,24 @@ -import { makeRequest } from "@frontend/kitui"; +import { makeRequest } from "@frontend/kitui" -import { parseAxiosError } from "@root/utils/parse-error"; +import { parseAxiosError } from "@root/utils/parse-error" -import type { GetDiscountsResponse } from "@root/model/discount"; +import type { GetDiscountsResponse } from "@root/model/discount" -const apiUrl = process.env.NODE_ENV === "production" ? "/price" : "https://hub.pena.digital/price"; +const apiUrl = process.env.NODE_ENV === "production" ? "/price" : "https://hub.pena.digital/price" export async function getDiscounts(signal: AbortSignal | undefined): Promise<[GetDiscountsResponse | null, string?]> { - try { - const discountsResponse = await makeRequest({ - url: apiUrl + "/discounts", - method: "get", - useToken: true, - signal, - }); + try { + const discountsResponse = await makeRequest({ + url: apiUrl + "/discounts", + method: "get", + useToken: true, + signal, + }) - return [discountsResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [discountsResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Ошибка получения списка скидок. ${error}`]; - } + return [null, `Ошибка получения списка скидок. ${error}`] + } } diff --git a/src/api/tariff.ts b/src/api/tariff.ts index 1ffc993..cf8b415 100644 --- a/src/api/tariff.ts +++ b/src/api/tariff.ts @@ -1,81 +1,81 @@ -import { Tariff, makeRequest } from "@frontend/kitui"; -import { CreateTariffBody } from "@root/model/customTariffs"; -import { parseAxiosError } from "@root/utils/parse-error"; +import { Tariff, makeRequest } from "@frontend/kitui" +import { CreateTariffBody } from "@root/model/customTariffs" +import { parseAxiosError } from "@root/utils/parse-error" -import type { ServiceKeyToPrivilegesMap } from "@root/model/privilege"; -import type { GetTariffsResponse } from "@root/model/tariff"; +import type { ServiceKeyToPrivilegesMap } from "@root/model/privilege" +import type { GetTariffsResponse } from "@root/model/tariff" -const apiUrl = process.env.NODE_ENV === "production" ? "/strator" : "https://hub.pena.digital/strator"; +const apiUrl = process.env.NODE_ENV === "production" ? "/strator" : "https://hub.pena.digital/strator" export async function getTariffs( - apiPage: number, - tariffsPerPage: number, - signal: AbortSignal | undefined + apiPage: number, + tariffsPerPage: number, + signal: AbortSignal | undefined ): Promise<[GetTariffsResponse | null, string?]> { - try { - const tariffsResponse = await makeRequest({ - url: apiUrl + `/tariff?page=${apiPage}&limit=${tariffsPerPage}`, - method: "get", - useToken: true, - signal, - }); + try { + const tariffsResponse = await makeRequest({ + url: apiUrl + `/tariff?page=${apiPage}&limit=${tariffsPerPage}`, + method: "get", + useToken: true, + signal, + }) - return [tariffsResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [tariffsResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Не удалось получить список тарифов. ${error}`]; - } + return [null, `Не удалось получить список тарифов. ${error}`] + } } export async function createTariff(tariff: CreateTariffBody): Promise<[Tariff | null, string?]> { - try { - const createTariffResponse = await makeRequest({ - url: `${apiUrl}/tariff`, - method: "post", - useToken: true, - body: tariff, - }); + try { + const createTariffResponse = await makeRequest({ + url: `${apiUrl}/tariff`, + method: "post", + useToken: true, + body: tariff, + }) - return [createTariffResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [createTariffResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Не удалось создать тариф. ${error}`]; - } + return [null, `Не удалось создать тариф. ${error}`] + } } export async function getTariffById(tariffId: string): Promise<[Tariff | null, string?, number?]> { - try { - const getTariffByIdResponse = await makeRequest({ - url: `${apiUrl}/tariff/${tariffId}`, - method: "get", - useToken: true, - }); + try { + const getTariffByIdResponse = await makeRequest({ + url: `${apiUrl}/tariff/${tariffId}`, + method: "get", + useToken: true, + }) - return [getTariffByIdResponse]; - } catch (nativeError) { - const [error, status] = parseAxiosError(nativeError); + return [getTariffByIdResponse] + } catch (nativeError) { + const [error, status] = parseAxiosError(nativeError) - return [null, `Не удалось получить тарифы. ${error}`, status]; - } + return [null, `Не удалось получить тарифы. ${error}`, status] + } } export async function getCustomTariffs( - signal: AbortSignal | undefined + signal: AbortSignal | undefined ): Promise<[ServiceKeyToPrivilegesMap | null, string?]> { - try { - const getCustomTariffsResponse = await makeRequest({ - url: apiUrl + "/privilege/service", - signal, - method: "get", - useToken: true, - }); + try { + const getCustomTariffsResponse = await makeRequest({ + url: apiUrl + "/privilege/service", + signal, + method: "get", + useToken: true, + }) - return [getCustomTariffsResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [getCustomTariffsResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Не удалось получить кастомные тарифы. ${error}`]; - } + return [null, `Не удалось получить кастомные тарифы. ${error}`] + } } diff --git a/src/api/ticket.ts b/src/api/ticket.ts index 0d1263c..6fbffef 100644 --- a/src/api/ticket.ts +++ b/src/api/ticket.ts @@ -1,49 +1,49 @@ -import { makeRequest } from "@frontend/kitui"; -import { parseAxiosError } from "@root/utils/parse-error"; +import { makeRequest } from "@frontend/kitui" +import { parseAxiosError } from "@root/utils/parse-error" -import { SendTicketMessageRequest } from "@frontend/kitui"; +import { SendTicketMessageRequest } from "@frontend/kitui" const apiUrl = process.env.NODE_ENV === "production" - ? "/heruvym" - : "https://hub.pena.digital/heruvym"; + ? "/heruvym" + : "https://hub.pena.digital/heruvym" export async function sendTicketMessage( - ticketId: string, - message: string + ticketId: string, + message: string ): Promise<[null, string?]> { - try { - const sendTicketMessageResponse = await makeRequest< + try { + const sendTicketMessageResponse = await makeRequest< SendTicketMessageRequest, null >({ - url: `${apiUrl}/send`, - method: "POST", - useToken: true, - body: { ticket: ticketId, message: message, lang: "ru", files: [] }, - }); + url: `${apiUrl}/send`, + method: "POST", + useToken: true, + body: { ticket: ticketId, message: message, lang: "ru", files: [] }, + }) - return [sendTicketMessageResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [sendTicketMessageResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Не удалось отправить сообщение. ${error}`]; - } + return [null, `Не удалось отправить сообщение. ${error}`] + } } export async function shownMessage(id: string): Promise<[null, string?]> { - try { - const shownMessageResponse = await makeRequest<{ id: string }, null>({ - url: apiUrl + "/shown", - method: "POST", - useToken: true, - body: { id }, - }); + try { + const shownMessageResponse = await makeRequest<{ id: string }, null>({ + url: apiUrl + "/shown", + method: "POST", + useToken: true, + body: { id }, + }) - return [shownMessageResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [shownMessageResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Не удалось прочесть сообщение. ${error}`]; - } + return [null, `Не удалось прочесть сообщение. ${error}`] + } } diff --git a/src/api/user.ts b/src/api/user.ts index b000856..ed0e8ba 100644 --- a/src/api/user.ts +++ b/src/api/user.ts @@ -1,29 +1,29 @@ -import { User, makeRequest } from "@frontend/kitui"; -import { PatchUserRequest } from "@root/model/user"; -import { parseAxiosError } from "@root/utils/parse-error"; +import { User, makeRequest } from "@frontend/kitui" +import { PatchUserRequest } from "@root/model/user" +import { parseAxiosError } from "@root/utils/parse-error" const apiUrl = process.env.NODE_ENV === "production" - ? "/user" - : "https://hub.pena.digital/user"; + ? "/user" + : "https://hub.pena.digital/user" export async function patchUser( - user: PatchUserRequest + user: PatchUserRequest ): Promise<[User | null, string?]> { - try { - const patchUserResponse = await makeRequest({ - url: apiUrl, - contentType: true, - method: "PATCH", - useToken: true, - withCredentials: false, - body: user, - }); + try { + const patchUserResponse = await makeRequest({ + url: apiUrl, + contentType: true, + method: "PATCH", + useToken: true, + withCredentials: false, + body: user, + }) - return [patchUserResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [patchUserResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Не удалось изменить пользователя. ${error}`]; - } + return [null, `Не удалось изменить пользователя. ${error}`] + } } diff --git a/src/api/verification.ts b/src/api/verification.ts index 458b085..5873415 100644 --- a/src/api/verification.ts +++ b/src/api/verification.ts @@ -1,76 +1,76 @@ -import { makeRequest } from "@frontend/kitui"; +import { makeRequest } from "@frontend/kitui" -import { jsonToFormdata } from "@root/utils/jsonToFormdata"; -import { parseAxiosError } from "@root/utils/parse-error"; +import { jsonToFormdata } from "@root/utils/jsonToFormdata" +import { parseAxiosError } from "@root/utils/parse-error" import type { - Verification, - SendDocumentsArgs, - UpdateDocumentsArgs, -} from "@root/model/auth"; + Verification, + SendDocumentsArgs, + UpdateDocumentsArgs, +} from "@root/model/auth" const apiUrl = process.env.NODE_ENV === "production" - ? "/verification" - : "https://hub.pena.digital/verification"; + ? "/verification" + : "https://hub.pena.digital/verification" export async function verification( - userId: string + userId: string ): Promise<[Verification | null, string?]> { - try { - const verificationResponse = await makeRequest({ - url: apiUrl + "/verification/" + userId, - method: "GET", - useToken: true, - withCredentials: true, - }); + try { + const verificationResponse = await makeRequest({ + url: apiUrl + "/verification/" + userId, + method: "GET", + useToken: true, + withCredentials: true, + }) - return [verificationResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [verificationResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Ошибка запроса верификации. ${error}`]; - } + return [null, `Ошибка запроса верификации. ${error}`] + } } export async function sendDocuments( - documents: SendDocumentsArgs + documents: SendDocumentsArgs ): Promise<[Verification | "OK" | null, string?]> { - try { - const sendDocumentsResponse = await makeRequest({ - url: apiUrl + "/verification", - method: "POST", - useToken: true, - withCredentials: true, - body: jsonToFormdata({ ...documents, egrule: documents.inn }), - }); + try { + const sendDocumentsResponse = await makeRequest({ + url: apiUrl + "/verification", + method: "POST", + useToken: true, + withCredentials: true, + body: jsonToFormdata({ ...documents, egrule: documents.inn }), + }) - return [sendDocumentsResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [sendDocumentsResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Ошибка отправки документов. ${error}`]; - } + return [null, `Ошибка отправки документов. ${error}`] + } } export async function updateDocuments( - documents: UpdateDocumentsArgs + documents: UpdateDocumentsArgs ): Promise<[Verification | "OK" | null, string? ]> { - try { - const updateDocumentsResponse = await makeRequest({ - url: apiUrl + "/verification/file", - method: "PATCH", - useToken: true, - withCredentials: true, - body: jsonToFormdata( - documents.inn ? { ...documents, egrule: documents.inn } : documents - ), - }); + try { + const updateDocumentsResponse = await makeRequest({ + url: apiUrl + "/verification/file", + method: "PATCH", + useToken: true, + withCredentials: true, + body: jsonToFormdata( + documents.inn ? { ...documents, egrule: documents.inn } : documents + ), + }) - return [updateDocumentsResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [updateDocumentsResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Ошибка обновления документов. ${error}`]; - } + return [null, `Ошибка обновления документов. ${error}`] + } } diff --git a/src/api/wallet.ts b/src/api/wallet.ts index eb84258..ba7d5cb 100644 --- a/src/api/wallet.ts +++ b/src/api/wallet.ts @@ -1,48 +1,48 @@ -import { makeRequest } from "@frontend/kitui"; -import { SendPaymentRequest, SendPaymentResponse } from "@root/model/wallet"; -import { parseAxiosError } from "@root/utils/parse-error"; +import { makeRequest } from "@frontend/kitui" +import { SendPaymentRequest, SendPaymentResponse } from "@root/model/wallet" +import { parseAxiosError } from "@root/utils/parse-error" const apiUrl = process.env.NODE_ENV === "production" - ? "/customer" - : "https://hub.pena.digital/customer"; + ? "/customer" + : "https://hub.pena.digital/customer" const testPaymentBody: SendPaymentRequest = { - type: "bankCard", - amount: 15020, - currency: "RUB", - bankCard: { - number: "RUB", - expiryYear: "2021", - expiryMonth: "05", - csc: "05", - cardholder: "IVAN IVANOV", - }, - phoneNumber: "79000000000", - login: "login_test", - returnUrl: window.location.origin + "/wallet", -}; + type: "bankCard", + amount: 15020, + currency: "RUB", + bankCard: { + number: "RUB", + expiryYear: "2021", + expiryMonth: "05", + csc: "05", + cardholder: "IVAN IVANOV", + }, + phoneNumber: "79000000000", + login: "login_test", + returnUrl: window.location.origin + "/wallet", +} export async function sendPayment( - body: SendPaymentRequest = testPaymentBody + body: SendPaymentRequest = testPaymentBody ): Promise<[SendPaymentResponse | null, string?]> { - try { - const sendPaymentResponse = await makeRequest< + try { + const sendPaymentResponse = await makeRequest< SendPaymentRequest, SendPaymentResponse >({ - url: apiUrl + "/wallet", - contentType: true, - method: "POST", - useToken: true, - withCredentials: false, - body, - }); + url: apiUrl + "/wallet", + contentType: true, + method: "POST", + useToken: true, + withCredentials: false, + body, + }) - return [sendPaymentResponse]; - } catch (nativeError) { - const [error] = parseAxiosError(nativeError); + return [sendPaymentResponse] + } catch (nativeError) { + const [error] = parseAxiosError(nativeError) - return [null, `Ошибка оплаты. ${error}`]; - } + return [null, `Ошибка оплаты. ${error}`] + } } diff --git a/src/components/CardWithLink.tsx b/src/components/CardWithLink.tsx index 17c5f95..abc530b 100644 --- a/src/components/CardWithLink.tsx +++ b/src/components/CardWithLink.tsx @@ -1,6 +1,6 @@ -import { Box, SxProps, Theme, Typography, useMediaQuery, useTheme } from "@mui/material"; -import { PenaLink } from "@frontend/kitui"; -import { Link as RouterLink } from "react-router-dom"; +import { Box, SxProps, Theme, Typography, useMediaQuery, useTheme } from "@mui/material" +import { PenaLink } from "@frontend/kitui" +import { Link as RouterLink } from "react-router-dom" interface Props { image?: string; @@ -12,21 +12,21 @@ interface Props { } export default function CardWithLink({ image, headerText, text, linkHref, isHighlighted = false, sx }: Props) { - const theme = useTheme(); + const theme = useTheme() - return ( - - {image && ( - - )} - {headerText} - - {text} - - + ...sx, + }} + > + {image && ( + + )} + {headerText} + + {text} + + Подробнее - - - ); + + + ) } diff --git a/src/components/ChatMessage.tsx b/src/components/ChatMessage.tsx index cfd8150..06f1ab3 100644 --- a/src/components/ChatMessage.tsx +++ b/src/components/ChatMessage.tsx @@ -1,5 +1,5 @@ -import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; -import { isDateToday } from "@root/utils/date"; +import { Box, Typography, useMediaQuery, useTheme } from "@mui/material" +import { isDateToday } from "@root/utils/date" interface Props { @@ -10,81 +10,81 @@ interface Props { } export default function ChatMessage({ unAuthenticated = false, isSelf, text, createdAt }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) - const messageBackgroundColor = isSelf ? "white" : unAuthenticated ? "#EFF0F5" : theme.palette.gray.main; + const messageBackgroundColor = isSelf ? "white" : unAuthenticated ? "#EFF0F5" : theme.palette.gray.main - const date = new Date(createdAt); - const time = date.toLocaleString([], { - hour: "2-digit", - minute: "2-digit", - ...(!isDateToday(date) && { year: "2-digit", month: "2-digit", day: "2-digit" }) - }); + const date = new Date(createdAt) + const time = date.toLocaleString([], { + hour: "2-digit", + minute: "2-digit", + ...(!isDateToday(date) && { year: "2-digit", month: "2-digit", day: "2-digit" }) + }) - return ( - - {time} - - - + {time} + + + - - - {text} - - - ); + fill={messageBackgroundColor} + stroke={unAuthenticated ? "#E3E3E3" : theme.palette.gray.main} + /> + + + {text} + + + ) } diff --git a/src/components/ComplexHeader.tsx b/src/components/ComplexHeader.tsx index c1be264..6fdbaca 100644 --- a/src/components/ComplexHeader.tsx +++ b/src/components/ComplexHeader.tsx @@ -1,4 +1,4 @@ -import { SxProps, Theme, Typography, useTheme } from "@mui/material"; +import { SxProps, Theme, Typography, useTheme } from "@mui/material" interface Props { @@ -8,24 +8,24 @@ interface Props { } export default function ComplexHeader({ text1, text2, sx }: Props) { - const theme = useTheme(); + const theme = useTheme() - return ( - - {text1} - {text2 && + return ( + + {text1} + {text2 && - {text2} + {text2} - } - - ); + } + + ) } diff --git a/src/components/CustomAccordion.tsx b/src/components/CustomAccordion.tsx index be1659a..66a9420 100644 --- a/src/components/CustomAccordion.tsx +++ b/src/components/CustomAccordion.tsx @@ -1,7 +1,7 @@ -import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; -import { useState } from "react"; -import ExpandIcon from "./icons/ExpandIcon"; -import type { ReactNode } from "react"; +import { Box, Typography, useMediaQuery, useTheme } from "@mui/material" +import { useState } from "react" +import ExpandIcon from "./icons/ExpandIcon" +import type { ReactNode } from "react" interface Props { header: ReactNode; @@ -13,91 +13,91 @@ interface Props { } export default function CustomAccordion({ header, text, divide = false, price, last, first }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const upXs = useMediaQuery(theme.breakpoints.up("xs")); - const [isExpanded, setIsExpanded] = useState(false); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const upXs = useMediaQuery(theme.breakpoints.up("xs")) + const [isExpanded, setIsExpanded] = useState(false) - return ( - - setIsExpanded((prev) => !prev)} - sx={{ - minHeight: "72px", - px: "20px", - display: "flex", - alignItems: "stretch", - justifyContent: "space-between", - cursor: "pointer", - userSelect: "none", - rowGap: "10px", - flexDirection: upXs ? undefined : "column", - }} - > - - {header} - - - - - - {isExpanded && ( - - - {text} - - - {price} руб. - - - )} - - ); + ...(last && { borderBottom: "none" }), + }} + > + setIsExpanded((prev) => !prev)} + sx={{ + minHeight: "72px", + px: "20px", + display: "flex", + alignItems: "stretch", + justifyContent: "space-between", + cursor: "pointer", + userSelect: "none", + rowGap: "10px", + flexDirection: upXs ? undefined : "column", + }} + > + + {header} + + + + + + {isExpanded && ( + + + {text} + + + {price} руб. + + + )} + + ) } diff --git a/src/components/CustomSaveAccordion.tsx b/src/components/CustomSaveAccordion.tsx index d75db59..a921bb1 100644 --- a/src/components/CustomSaveAccordion.tsx +++ b/src/components/CustomSaveAccordion.tsx @@ -1,7 +1,7 @@ -import { Box, useMediaQuery, useTheme } from "@mui/material"; -import { useState } from "react"; -import ExpandIcon from "./icons/ExpandIcon"; -import type { ReactNode } from "react"; +import { Box, useMediaQuery, useTheme } from "@mui/material" +import { useState } from "react" +import ExpandIcon from "./icons/ExpandIcon" +import type { ReactNode } from "react" interface Props { header: ReactNode; @@ -12,66 +12,66 @@ interface Props { } export default function CustomSaveAccordion({ header, divide = false, privilege, last, first }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const upXs = useMediaQuery(theme.breakpoints.up("xs")); - const [isExpanded, setIsExpanded] = useState(false); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const upXs = useMediaQuery(theme.breakpoints.up("xs")) + const [isExpanded, setIsExpanded] = useState(false) - return ( - - setIsExpanded((prev) => !prev)} - sx={{ - minHeight: "72px", - px: "20px", - display: "flex", - alignItems: "stretch", - justifyContent: "space-between", - cursor: "pointer", - userSelect: "none", - rowGap: "10px", - flexDirection: upXs ? undefined : "column", - }} - > - - {header} - - - - - - {isExpanded && privilege} - - ); + ...(last && { borderBottom: "none" }), + }} + > + setIsExpanded((prev) => !prev)} + sx={{ + minHeight: "72px", + px: "20px", + display: "flex", + alignItems: "stretch", + justifyContent: "space-between", + cursor: "pointer", + userSelect: "none", + rowGap: "10px", + flexDirection: upXs ? undefined : "column", + }} + > + + {header} + + + + + + {isExpanded && privilege} + + ) } diff --git a/src/components/CustomSlider.tsx b/src/components/CustomSlider.tsx index 5a0eee8..f232382 100644 --- a/src/components/CustomSlider.tsx +++ b/src/components/CustomSlider.tsx @@ -1,5 +1,5 @@ -import { useState, useEffect } from "react"; -import { Slider, useTheme } from "@mui/material"; +import { useState, useEffect } from "react" +import { Slider, useTheme } from "@mui/material" type CustomSliderProps = { value: number; @@ -9,68 +9,68 @@ type CustomSliderProps = { }; export const CustomSlider = ({ - value, - min = 0, - max = 100, - onChange, + value, + min = 0, + max = 100, + onChange, }: CustomSliderProps) => { - const theme = useTheme(); - const [step, setStep] = useState(1); + const theme = useTheme() + const [step, setStep] = useState(1) - useEffect(() => { - if (value < 100) { - return setStep(10); - } + useEffect(() => { + if (value < 100) { + return setStep(10) + } - if (value < 500) { - return setStep(20); - } + if (value < 500) { + return setStep(20) + } - if (value < 2000) { - return setStep(50); - } + if (value < 2000) { + return setStep(50) + } - setStep(150); - }, [value]); + setStep(150) + }, [value]) - const handleChange = ({ type }: Event, newValue: number | number[]) => { - // Для корректной работы слайдера в FireFox - if (type !== "change") { - onChange(newValue); - } - }; + const handleChange = ({ type }: Event, newValue: number | number[]) => { + // Для корректной работы слайдера в FireFox + if (type !== "change") { + onChange(newValue) + } + } - return ( - - ); -}; + }, + }, + }} + /> + ) +} diff --git a/src/components/CustomTab.tsx b/src/components/CustomTab.tsx index fc4f314..1109542 100644 --- a/src/components/CustomTab.tsx +++ b/src/components/CustomTab.tsx @@ -1,19 +1,19 @@ -import { Tab } from "@mui/material"; -import { styled } from "@mui/material"; +import { Tab } from "@mui/material" +import { styled } from "@mui/material" export const CustomTab = styled(Tab)(({ theme }) => ({ - ...theme.typography.body2, - color: theme.palette.primary.main, - padding: "15px", - minWidth: 0, - "&.Mui-selected": { - color: theme.palette.purple.main, - textUnderlinePosition: "under", - textDecoration: "underline", - textUnderlineOffset: "3px", - }, - "&:first-of-type": { - paddingLeft: 0, - } -})); + ...theme.typography.body2, + color: theme.palette.primary.main, + padding: "15px", + minWidth: 0, + "&.Mui-selected": { + color: theme.palette.purple.main, + textUnderlinePosition: "under", + textDecoration: "underline", + textUnderlineOffset: "3px", + }, + "&:first-of-type": { + paddingLeft: 0, + } +})) diff --git a/src/components/CustomTariffAccordion.tsx b/src/components/CustomTariffAccordion.tsx index df84130..2241455 100644 --- a/src/components/CustomTariffAccordion.tsx +++ b/src/components/CustomTariffAccordion.tsx @@ -1,159 +1,159 @@ -import { useState } from "react"; -import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; -import ExpandIcon from "@components/icons/ExpandIcon"; -import { currencyFormatter } from "@root/utils/currencyFormatter"; -import { removeTariffFromCart } from "@root/stores/user"; -import { enqueueSnackbar } from "notistack"; +import { useState } from "react" +import { Box, Typography, useMediaQuery, useTheme } from "@mui/material" +import ExpandIcon from "@components/icons/ExpandIcon" +import { currencyFormatter } from "@root/utils/currencyFormatter" +import { removeTariffFromCart } from "@root/stores/user" +import { enqueueSnackbar } from "notistack" import { - CloseButton, - TariffCartData, - getMessageFromFetchError, -} from "@frontend/kitui"; + CloseButton, + TariffCartData, + getMessageFromFetchError, +} from "@frontend/kitui" -import type { MouseEvent } from "react"; +import type { MouseEvent } from "react" interface Props { tariffCartData: TariffCartData; } export default function CustomTariffAccordion({ tariffCartData }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const upSm = useMediaQuery(theme.breakpoints.up("sm")); - const [isExpanded, setIsExpanded] = useState(false); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const upSm = useMediaQuery(theme.breakpoints.up("sm")) + const [isExpanded, setIsExpanded] = useState(false) - function handleDeleteClick(event: MouseEvent) { - event.stopPropagation(); + function handleDeleteClick(event: MouseEvent) { + event.stopPropagation() - removeTariffFromCart(tariffCartData.id) - .then(() => { - enqueueSnackbar("Тариф удален"); - }) - .catch((error) => { - const message = getMessageFromFetchError(error); - if (message) enqueueSnackbar(message); - }); - } + removeTariffFromCart(tariffCartData.id) + .then(() => { + enqueueSnackbar("Тариф удален") + }) + .catch((error) => { + const message = getMessageFromFetchError(error) + if (message) enqueueSnackbar(message) + }) + } - return ( - - - setIsExpanded((prev) => !prev)} - sx={{ - height: "72px", - pr: "20px", - pl: "30px", - display: "flex", - gap: "15px", - alignItems: "center", - justifyContent: "space-between", - cursor: "pointer", - userSelect: "none", - }} - > - - - - + return ( + + + setIsExpanded((prev) => !prev)} + sx={{ + height: "72px", + pr: "20px", + pl: "30px", + display: "flex", + gap: "15px", + alignItems: "center", + justifyContent: "space-between", + cursor: "pointer", + userSelect: "none", + }} + > + + + + Кастомный тариф - - - - {currencyFormatter.format(tariffCartData.price / 100)} - - - - - {isExpanded && + + + + {currencyFormatter.format(tariffCartData.price / 100)} + + + + + {isExpanded && tariffCartData.privileges.map((privilege) => ( - - - {privilege.description} - - - - {currencyFormatter.format(privilege.price / 100)} - - - + + + {privilege.description} + + + + {currencyFormatter.format(privilege.price / 100)} + + + ))} - - - ); + + + ) } diff --git a/src/components/CustomWrapperDrawer.tsx b/src/components/CustomWrapperDrawer.tsx index 9397888..1392240 100644 --- a/src/components/CustomWrapperDrawer.tsx +++ b/src/components/CustomWrapperDrawer.tsx @@ -1,244 +1,244 @@ -import { useState } from "react"; +import { useState } from "react" import { - Box, - SvgIcon, - IconButton, - Typography, - CircularProgress, - useMediaQuery, - useTheme, -} from "@mui/material"; + Box, + SvgIcon, + IconButton, + Typography, + CircularProgress, + useMediaQuery, + useTheme, +} from "@mui/material" -import ClearIcon from "@mui/icons-material/Clear"; -import { currencyFormatter } from "@root/utils/currencyFormatter"; -import { useUserStore, removeTariffFromCart, setCart } from "@root/stores/user"; -import { enqueueSnackbar } from "notistack"; -import { ServiceCartData, getMessageFromFetchError } from "@frontend/kitui"; -import ExpandIcon from "@components/icons/ExpandIcon"; -import { deleteCart } from "@root/api/cart"; +import ClearIcon from "@mui/icons-material/Clear" +import { currencyFormatter } from "@root/utils/currencyFormatter" +import { useUserStore, removeTariffFromCart, setCart } from "@root/stores/user" +import { enqueueSnackbar } from "notistack" +import { ServiceCartData, getMessageFromFetchError } from "@frontend/kitui" +import ExpandIcon from "@components/icons/ExpandIcon" +import { deleteCart } from "@root/api/cart" -import { ReactComponent as CrossIcon } from "@root/assets/Icons/cross.svg"; +import { ReactComponent as CrossIcon } from "@root/assets/Icons/cross.svg" -import type { MouseEvent } from "react"; -import CustomTariffAccordion from "@root/components/CustomTariffAccordion"; +import type { MouseEvent } from "react" +import CustomTariffAccordion from "@root/components/CustomTariffAccordion" const name: Record = { - templategen: "Шаблонизатор", - squiz: "Опросник", - reducer: "Скоращатель ссылок", - custom: "Кастомные тарифы", -}; + templategen: "Шаблонизатор", + squiz: "Опросник", + reducer: "Скоращатель ссылок", + custom: "Кастомные тарифы", +} interface Props { serviceData: ServiceCartData; } export default function CustomWrapperDrawer({ serviceData }: Props) { - const [isExpanded, setIsExpanded] = useState(false); - const [isLoading, setIsLoading] = useState(false); - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const upSm = useMediaQuery(theme.breakpoints.up("sm")); - const userAccount = useUserStore((state) => state.userAccount); + const [isExpanded, setIsExpanded] = useState(false) + const [isLoading, setIsLoading] = useState(false) + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const upSm = useMediaQuery(theme.breakpoints.up("sm")) + const userAccount = useUserStore((state) => state.userAccount) - function handleItemDeleteClick(tariffId: string) { - removeTariffFromCart(tariffId) - .then(() => { - enqueueSnackbar("Тариф удален"); - }) - .catch((error) => { - const message = getMessageFromFetchError(error); - if (message) enqueueSnackbar(message); - }); - } + function handleItemDeleteClick(tariffId: string) { + removeTariffFromCart(tariffId) + .then(() => { + enqueueSnackbar("Тариф удален") + }) + .catch((error) => { + const message = getMessageFromFetchError(error) + if (message) enqueueSnackbar(message) + }) + } - const deleteService = async (event: MouseEvent) => { - event.stopPropagation(); - let cartItems: string[] = userAccount?.cart || []; - const errors: string[] = []; + const deleteService = async (event: MouseEvent) => { + event.stopPropagation() + let cartItems: string[] = userAccount?.cart || [] + const errors: string[] = [] - setIsLoading(true); + setIsLoading(true) - for (const { id } of serviceData.tariffs) { - const [cartItemsResponse, deleteError] = await deleteCart(id); + for (const { id } of serviceData.tariffs) { + const [cartItemsResponse, deleteError] = await deleteCart(id) - if (deleteError) { - errors.push(deleteError); - } else { - cartItems = cartItemsResponse; - } - } + if (deleteError) { + errors.push(deleteError) + } else { + cartItems = cartItemsResponse + } + } - setCart(cartItems); - setIsLoading(false); - errors.forEach(enqueueSnackbar); - }; + setCart(cartItems) + setIsLoading(false) + errors.forEach(enqueueSnackbar) + } - return ( - - - - setIsExpanded((prev) => !prev)} - sx={{ - height: "72px", - display: "flex", - gap: "10px", - alignItems: "center", - justifyContent: "space-between", - cursor: "pointer", - userSelect: "none", - }} - > - - - - {name[serviceData.serviceKey]} - - - - {currencyFormatter.format(serviceData.price / 100)} - - - - {isLoading ? ( - - - - ) : ( - - - - )} - - {isExpanded && + return ( + + + + setIsExpanded((prev) => !prev)} + sx={{ + height: "72px", + display: "flex", + gap: "10px", + alignItems: "center", + justifyContent: "space-between", + cursor: "pointer", + userSelect: "none", + }} + > + + + + {name[serviceData.serviceKey]} + + + + {currencyFormatter.format(serviceData.price / 100)} + + + + {isLoading ? ( + + + + ) : ( + + + + )} + + {isExpanded && serviceData.tariffs.map((tariff) => { - const privilege = tariff.privileges[0]; + const privilege = tariff.privileges[0] - return tariff.privileges.length > 1 ? ( - - ) : ( - 1 ? ( + + ) : ( + - - {privilege.description} - - - - {currencyFormatter.format( - (tariff.price || privilege.price) / 100 - )} - - handleItemDeleteClick(tariff.id)} - component={ClearIcon} - /> - - - ); + display: "flex", + justifyContent: "space-between", + alignItems: "center", + gap: "15px", + }} + > + + {privilege.description} + + + + {currencyFormatter.format( + (tariff.price || privilege.price) / 100 + )} + + handleItemDeleteClick(tariff.id)} + component={ClearIcon} + /> + + + ) })} - - - - ); + + + + ) } diff --git a/src/components/Drawers.tsx b/src/components/Drawers.tsx index 66ca6e0..4f7a13d 100644 --- a/src/components/Drawers.tsx +++ b/src/components/Drawers.tsx @@ -1,341 +1,341 @@ -import { useState, useRef } from "react"; +import { useState, useRef } from "react" import { - Typography, - Drawer, - useMediaQuery, - useTheme, - Box, - IconButton, - Badge, - Button, -} from "@mui/material"; -import SectionWrapper from "./SectionWrapper"; -import CustomWrapperDrawer from "./CustomWrapperDrawer"; -import { NotificationsModal } from "./NotificationsModal"; -import { Loader } from "./Loader"; -import { useCart } from "@root/utils/hooks/useCart"; -import { currencyFormatter } from "@root/utils/currencyFormatter"; + Typography, + Drawer, + useMediaQuery, + useTheme, + Box, + IconButton, + Badge, + Button, +} from "@mui/material" +import SectionWrapper from "./SectionWrapper" +import CustomWrapperDrawer from "./CustomWrapperDrawer" +import { NotificationsModal } from "./NotificationsModal" +import { Loader } from "./Loader" +import { useCart } from "@root/utils/hooks/useCart" +import { currencyFormatter } from "@root/utils/currencyFormatter" import { - closeCartDrawer, - openCartDrawer, - useCartStore, -} from "@root/stores/cart"; -import { setUserAccount, useUserStore } from "@root/stores/user"; -import { useTicketStore } from "@root/stores/tickets"; + closeCartDrawer, + openCartDrawer, + useCartStore, +} from "@root/stores/cart" +import { setUserAccount, useUserStore } from "@root/stores/user" +import { useTicketStore } from "@root/stores/tickets" -import { ReactComponent as BellIcon } from "@root/assets/Icons/bell.svg"; -import { ReactComponent as CartIcon } from "@root/assets/Icons/cart.svg"; -import { ReactComponent as CrossIcon } from "@root/assets/Icons/cross.svg"; +import { ReactComponent as BellIcon } from "@root/assets/Icons/bell.svg" +import { ReactComponent as CartIcon } from "@root/assets/Icons/cart.svg" +import { ReactComponent as CrossIcon } from "@root/assets/Icons/cross.svg" -import { payCart } from "@root/api/cart"; -import { enqueueSnackbar } from "notistack"; -import { Link, useNavigate } from "react-router-dom"; -import { withErrorBoundary } from "react-error-boundary"; -import { handleComponentError } from "@root/utils/handleComponentError"; -import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline'; +import { payCart } from "@root/api/cart" +import { enqueueSnackbar } from "notistack" +import { Link, useNavigate } from "react-router-dom" +import { withErrorBoundary } from "react-error-boundary" +import { handleComponentError } from "@root/utils/handleComponentError" +import ErrorOutlineIcon from "@mui/icons-material/ErrorOutline" function Drawers() { - const [openNotificationsModal, setOpenNotificationsModal] = - useState(false); - const [loading, setLoading] = useState(false); - const bellRef = useRef(null); - const navigate = useNavigate(); - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); - const isDrawerOpen = useCartStore((state) => state.isDrawerOpen); - const cart = useCart(); - const userAccount = useUserStore((state) => state.userAccount); - const tickets = useTicketStore((state) => state.tickets); - const [notEnoughMoneyAmount, setNotEnoughMoneyAmount] = useState(0); + const [openNotificationsModal, setOpenNotificationsModal] = + useState(false) + const [loading, setLoading] = useState(false) + const bellRef = useRef(null) + const navigate = useNavigate() + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const isTablet = useMediaQuery(theme.breakpoints.down(1000)) + const isDrawerOpen = useCartStore((state) => state.isDrawerOpen) + const cart = useCart() + const userAccount = useUserStore((state) => state.userAccount) + const tickets = useTicketStore((state) => state.tickets) + const [notEnoughMoneyAmount, setNotEnoughMoneyAmount] = useState(0) - const notificationsCount = tickets.filter( - ({ user, top_message }) => - user !== top_message.user_id && top_message.shown.me !== 1 - ).length; + const notificationsCount = tickets.filter( + ({ user, top_message }) => + user !== top_message.user_id && top_message.shown.me !== 1 + ).length - async function handlePayClick() { - setLoading(true); + async function handlePayClick() { + setLoading(true) - const [payCartResponse, payCartError] = await payCart(); + const [payCartResponse, payCartError] = await payCart() - if (payCartError) { - if (payCartError.includes("insufficient funds: ")) { - const notEnoughMoneyAmount = parseInt( - payCartError.replace(/^.*insufficient\sfunds:\s(?=\d+$)/, "") - ); + if (payCartError) { + if (payCartError.includes("insufficient funds: ")) { + const notEnoughMoneyAmount = parseInt( + payCartError.replace(/^.*insufficient\sfunds:\s(?=\d+$)/, "") + ) - setNotEnoughMoneyAmount(notEnoughMoneyAmount); - } + setNotEnoughMoneyAmount(notEnoughMoneyAmount) + } - setLoading(false); + setLoading(false) - return enqueueSnackbar(payCartError); - } + return enqueueSnackbar(payCartError) + } - if (payCartResponse) { - setUserAccount(payCartResponse); - } + if (payCartResponse) { + setUserAccount(payCartResponse) + } - setLoading(false); - closeCartDrawer(); - } + setLoading(false) + closeCartDrawer() + } - function handleReplenishWallet() { - navigate("/payment", { state: { notEnoughMoneyAmount } }); - } + function handleReplenishWallet() { + navigate("/payment", { state: { notEnoughMoneyAmount } }) + } - return ( - - setOpenNotificationsModal((isOpened) => !isOpened)} - sx={{ - cursor: "pointer", - borderRadius: "6px", - background: openNotificationsModal - ? theme.palette.purple.main - : theme.palette.background.default, - "& .MuiBadge-badge": { - background: openNotificationsModal - ? theme.palette.background.default - : theme.palette.purple.main, - color: openNotificationsModal - ? theme.palette.purple.main - : theme.palette.background.default, - }, - "& svg > path:first-of-type": { - fill: openNotificationsModal ? "#FFFFFF" : "#9A9AAF", - }, - "& svg > path:last-child": { - stroke: openNotificationsModal ? "#FFFFFF" : "#9A9AAF", - }, - "&:hover": { - background: theme.palette.purple.main, - "& .MuiBox-root": { - background: theme.palette.purple.main, - }, - "& .MuiBadge-badge": { - background: theme.palette.background.default, - color: theme.palette.purple.main, - }, - "& svg > path:first-of-type": { fill: "#FFFFFF" }, - "& svg > path:last-child": { stroke: "#FFFFFF" }, - }, - }} - > - - - - - user !== top_message.user_id) - .map((ticket) => ({ - text: "У вас новое сообщение от техподдержки", - date: new Date(ticket.updated_at).toLocaleDateString(), - url: `/support/${ticket.id}`, - watched: + return ( + + setOpenNotificationsModal((isOpened) => !isOpened)} + sx={{ + cursor: "pointer", + borderRadius: "6px", + background: openNotificationsModal + ? theme.palette.purple.main + : theme.palette.background.default, + "& .MuiBadge-badge": { + background: openNotificationsModal + ? theme.palette.background.default + : theme.palette.purple.main, + color: openNotificationsModal + ? theme.palette.purple.main + : theme.palette.background.default, + }, + "& svg > path:first-of-type": { + fill: openNotificationsModal ? "#FFFFFF" : "#9A9AAF", + }, + "& svg > path:last-child": { + stroke: openNotificationsModal ? "#FFFFFF" : "#9A9AAF", + }, + "&:hover": { + background: theme.palette.purple.main, + "& .MuiBox-root": { + background: theme.palette.purple.main, + }, + "& .MuiBadge-badge": { + background: theme.palette.background.default, + color: theme.palette.purple.main, + }, + "& svg > path:first-of-type": { fill: "#FFFFFF" }, + "& svg > path:last-child": { stroke: "#FFFFFF" }, + }, + }} + > + + + + + user !== top_message.user_id) + .map((ticket) => ({ + text: "У вас новое сообщение от техподдержки", + date: new Date(ticket.updated_at).toLocaleDateString(), + url: `/support/${ticket.id}`, + watched: ticket.user === ticket.top_message.user_id || ticket.top_message.shown.me === 1, - }))} - /> - path:nth-of-type(1)": { fill: "#FFFFFF" }, - "& svg > path:nth-of-type(2)": { fill: "#FFFFFF" }, - "& svg > path:nth-of-type(3)": { stroke: "#FFFFFF" }, - }, - }} - > - - - - - - - - + }))} + /> + path:nth-of-type(1)": { fill: "#FFFFFF" }, + "& svg > path:nth-of-type(2)": { fill: "#FFFFFF" }, + "& svg > path:nth-of-type(3)": { stroke: "#FFFFFF" }, + }, + }} + > + + + + + + + + Корзина - - - - - - - {cart.services.map((serviceData) => ( - - ))} - - - + + + + + + + {cart.services.map((serviceData) => ( + + ))} + + + Итоговая цена - - + + Текст-заполнитель — это текст, который имеет Текст-заполнитель — это текст, который имеет Текст-заполнитель — это текст, который имеет Текст-заполнитель — это текст, который имеет Текст-заполнитель - - - - - - {currencyFormatter.format(cart.priceBeforeDiscounts / 100)} - - - {currencyFormatter.format(cart.priceAfterDiscounts / 100)} - - - - - - - - - - ); + + + + + + {currencyFormatter.format(cart.priceBeforeDiscounts / 100)} + + + {currencyFormatter.format(cart.priceAfterDiscounts / 100)} + + + + + + + + + + ) } export default withErrorBoundary(Drawers, { - fallback: ( - - - - ), - onError: handleComponentError, + fallback: ( + + + + ), + onError: handleComponentError, }) diff --git a/src/components/FloatingSupportChat/Chat.tsx b/src/components/FloatingSupportChat/Chat.tsx index 0cc3b53..126de87 100644 --- a/src/components/FloatingSupportChat/Chat.tsx +++ b/src/components/FloatingSupportChat/Chat.tsx @@ -1,319 +1,319 @@ import { - Box, - FormControl, - IconButton, - InputAdornment, - InputBase, - SxProps, - Theme, - Typography, - useMediaQuery, - useTheme, -} from "@mui/material"; -import { TicketMessage } from "@frontend/kitui"; + Box, + FormControl, + IconButton, + InputAdornment, + InputBase, + SxProps, + Theme, + Typography, + useMediaQuery, + useTheme, +} from "@mui/material" +import { TicketMessage } from "@frontend/kitui" import { - addOrUpdateUnauthMessages, - useUnauthTicketStore, - incrementUnauthMessageApiPage, - setUnauthIsPreventAutoscroll, - setUnauthSessionData, - setIsMessageSending, - setUnauthTicketMessageFetchState, -} from "@root/stores/unauthTicket"; -import { enqueueSnackbar } from "notistack"; -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import ChatMessage from "../ChatMessage"; -import SendIcon from "../icons/SendIcon"; -import UserCircleIcon from "./UserCircleIcon"; -import { throttle } from "@frontend/kitui"; + addOrUpdateUnauthMessages, + useUnauthTicketStore, + incrementUnauthMessageApiPage, + setUnauthIsPreventAutoscroll, + setUnauthSessionData, + setIsMessageSending, + setUnauthTicketMessageFetchState, +} from "@root/stores/unauthTicket" +import { enqueueSnackbar } from "notistack" +import { useCallback, useEffect, useMemo, useRef, useState } from "react" +import ChatMessage from "../ChatMessage" +import SendIcon from "../icons/SendIcon" +import UserCircleIcon from "./UserCircleIcon" +import { throttle } from "@frontend/kitui" import { - useTicketMessages, - getMessageFromFetchError, - useSSESubscription, - useEventListener, - createTicket, -} from "@frontend/kitui"; -import { sendTicketMessage } from "@root/api/ticket"; + useTicketMessages, + getMessageFromFetchError, + useSSESubscription, + useEventListener, + createTicket, +} from "@frontend/kitui" +import { sendTicketMessage } from "@root/api/ticket" interface Props { sx?: SxProps; } export default function Chat({ sx }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const [messageField, setMessageField] = useState(""); - const sessionData = useUnauthTicketStore((state) => state.sessionData); - const messages = useUnauthTicketStore((state) => state.messages); - const messageApiPage = useUnauthTicketStore((state) => state.apiPage); - const messagesPerPage = useUnauthTicketStore( - (state) => state.messagesPerPage - ); - const isMessageSending = useUnauthTicketStore( - (state) => state.isMessageSending - ); - const isPreventAutoscroll = useUnauthTicketStore( - (state) => state.isPreventAutoscroll - ); - const lastMessageId = useUnauthTicketStore((state) => state.lastMessageId); - const fetchState = useUnauthTicketStore( - (state) => state.unauthTicketMessageFetchState - ); - const chatBoxRef = useRef(null); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const [messageField, setMessageField] = useState("") + const sessionData = useUnauthTicketStore((state) => state.sessionData) + const messages = useUnauthTicketStore((state) => state.messages) + const messageApiPage = useUnauthTicketStore((state) => state.apiPage) + const messagesPerPage = useUnauthTicketStore( + (state) => state.messagesPerPage + ) + const isMessageSending = useUnauthTicketStore( + (state) => state.isMessageSending + ) + const isPreventAutoscroll = useUnauthTicketStore( + (state) => state.isPreventAutoscroll + ) + const lastMessageId = useUnauthTicketStore((state) => state.lastMessageId) + const fetchState = useUnauthTicketStore( + (state) => state.unauthTicketMessageFetchState + ) + const chatBoxRef = useRef(null) - useTicketMessages({ - url: "https://hub.pena.digital/heruvym/getMessages", - isUnauth: true, - ticketId: sessionData?.ticketId, - messagesPerPage, - messageApiPage, - onSuccess: useCallback((messages) => { - if (chatBoxRef.current && chatBoxRef.current.scrollTop < 1) - chatBoxRef.current.scrollTop = 1; - addOrUpdateUnauthMessages(messages); - }, []), - onError: useCallback((error: Error) => { - const message = getMessageFromFetchError(error); - if (message) enqueueSnackbar(message); - }, []), - onFetchStateChange: setUnauthTicketMessageFetchState, - }); + useTicketMessages({ + url: "https://hub.pena.digital/heruvym/getMessages", + isUnauth: true, + ticketId: sessionData?.ticketId, + messagesPerPage, + messageApiPage, + onSuccess: useCallback((messages) => { + if (chatBoxRef.current && chatBoxRef.current.scrollTop < 1) + chatBoxRef.current.scrollTop = 1 + addOrUpdateUnauthMessages(messages) + }, []), + onError: useCallback((error: Error) => { + const message = getMessageFromFetchError(error) + if (message) enqueueSnackbar(message) + }, []), + onFetchStateChange: setUnauthTicketMessageFetchState, + }) - useSSESubscription({ - enabled: Boolean(sessionData), - url: `https://hub.pena.digital/heruvym/ticket?ticket=${sessionData?.ticketId}&s=${sessionData?.sessionId}`, - onNewData: addOrUpdateUnauthMessages, - onDisconnect: useCallback(() => { - setUnauthIsPreventAutoscroll(false); - }, []), - marker: "ticket", - }); + useSSESubscription({ + enabled: Boolean(sessionData), + url: `https://hub.pena.digital/heruvym/ticket?ticket=${sessionData?.ticketId}&s=${sessionData?.sessionId}`, + onNewData: addOrUpdateUnauthMessages, + onDisconnect: useCallback(() => { + setUnauthIsPreventAutoscroll(false) + }, []), + marker: "ticket", + }) - const throttledScrollHandler = useMemo( - () => - throttle(() => { - const chatBox = chatBoxRef.current; - if (!chatBox) return; + const throttledScrollHandler = useMemo( + () => + throttle(() => { + const chatBox = chatBoxRef.current + if (!chatBox) return - const scrollBottom = - chatBox.scrollHeight - chatBox.scrollTop - chatBox.clientHeight; - const isPreventAutoscroll = scrollBottom > chatBox.clientHeight; - setUnauthIsPreventAutoscroll(isPreventAutoscroll); + const scrollBottom = + chatBox.scrollHeight - chatBox.scrollTop - chatBox.clientHeight + const isPreventAutoscroll = scrollBottom > chatBox.clientHeight + setUnauthIsPreventAutoscroll(isPreventAutoscroll) - if (fetchState !== "idle") return; + if (fetchState !== "idle") return - if (chatBox.scrollTop < chatBox.clientHeight) { - incrementUnauthMessageApiPage(); - } - }, 200), - [fetchState] - ); + if (chatBox.scrollTop < chatBox.clientHeight) { + incrementUnauthMessageApiPage() + } + }, 200), + [fetchState] + ) - useEventListener("scroll", throttledScrollHandler, chatBoxRef); + useEventListener("scroll", throttledScrollHandler, chatBoxRef) - useEffect( - function scrollOnNewMessage() { - if (!chatBoxRef.current) return; + useEffect( + function scrollOnNewMessage() { + if (!chatBoxRef.current) return - if (!isPreventAutoscroll) { - setTimeout(() => { - scrollToBottom(); - }, 50); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, - [lastMessageId] - ); + if (!isPreventAutoscroll) { + setTimeout(() => { + scrollToBottom() + }, 50) + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, + [lastMessageId] + ) - async function handleSendMessage() { - if (!messageField || isMessageSending) return; + async function handleSendMessage() { + if (!messageField || isMessageSending) return - if (!sessionData) { - setIsMessageSending(true); - createTicket({ - url: "https://hub.pena.digital/heruvym/create", - body: { - Title: "Unauth title", - Message: messageField, - }, - useToken: false, - }) - .then((response) => { - setUnauthSessionData({ - ticketId: response.Ticket, - sessionId: response.sess, - }); - }) - .catch((error) => { - const errorMessage = getMessageFromFetchError(error); - if (errorMessage) enqueueSnackbar(errorMessage); - }) - .finally(() => { - setMessageField(""); - setIsMessageSending(false); - }); - } else { - setIsMessageSending(true); + if (!sessionData) { + setIsMessageSending(true) + createTicket({ + url: "https://hub.pena.digital/heruvym/create", + body: { + Title: "Unauth title", + Message: messageField, + }, + useToken: false, + }) + .then((response) => { + setUnauthSessionData({ + ticketId: response.Ticket, + sessionId: response.sess, + }) + }) + .catch((error) => { + const errorMessage = getMessageFromFetchError(error) + if (errorMessage) enqueueSnackbar(errorMessage) + }) + .finally(() => { + setMessageField("") + setIsMessageSending(false) + }) + } else { + setIsMessageSending(true) - const [_, sendTicketMessageError] = await sendTicketMessage( - sessionData.ticketId, - messageField - ); + const [_, sendTicketMessageError] = await sendTicketMessage( + sessionData.ticketId, + messageField + ) - if (sendTicketMessageError) { - enqueueSnackbar(sendTicketMessageError); - } + if (sendTicketMessageError) { + enqueueSnackbar(sendTicketMessageError) + } - setMessageField(""); - setIsMessageSending(false); - } - } + setMessageField("") + setIsMessageSending(false) + } + } - function scrollToBottom(behavior?: ScrollBehavior) { - if (!chatBoxRef.current) return; + function scrollToBottom(behavior?: ScrollBehavior) { + if (!chatBoxRef.current) return - const chatBox = chatBoxRef.current; - chatBox.scroll({ - left: 0, - top: chatBox.scrollHeight, - behavior, - }); - } + const chatBox = chatBoxRef.current + chatBox.scroll({ + left: 0, + top: chatBox.scrollHeight, + behavior, + }) + } - const handleTextfieldKeyPress: React.KeyboardEventHandler< + const handleTextfieldKeyPress: React.KeyboardEventHandler< HTMLInputElement | HTMLTextAreaElement > = (e) => { - if (e.key === "Enter" && !e.shiftKey) { - e.preventDefault(); - handleSendMessage(); - } - }; + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault() + handleSendMessage() + } + } - return ( - - - - - Мария - + return ( + + + + + Мария + онлайн-консультант - - - - - - {sessionData && + + + + + + {sessionData && messages.map((message) => ( - + ))} - - - setMessageField(e.target.value)} - endAdornment={ - - - - - - } - /> - - - - ); + + + setMessageField(e.target.value)} + endAdornment={ + + + + + + } + /> + + + + ) } diff --git a/src/components/FloatingSupportChat/CircleDoubleDownIcon.tsx b/src/components/FloatingSupportChat/CircleDoubleDownIcon.tsx index 86e88e1..cbdafea 100644 --- a/src/components/FloatingSupportChat/CircleDoubleDownIcon.tsx +++ b/src/components/FloatingSupportChat/CircleDoubleDownIcon.tsx @@ -1,4 +1,4 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" interface Props { @@ -6,21 +6,21 @@ interface Props { } export default function CircleDoubleDown({ isUp = false }: Props) { - return ( - - - - - - - - ); + return ( + + + + + + + + ) } \ No newline at end of file diff --git a/src/components/FloatingSupportChat/FloatingSupportChat.tsx b/src/components/FloatingSupportChat/FloatingSupportChat.tsx index 88a55dd..53471d7 100644 --- a/src/components/FloatingSupportChat/FloatingSupportChat.tsx +++ b/src/components/FloatingSupportChat/FloatingSupportChat.tsx @@ -1,94 +1,94 @@ -import { Box, Fab, Typography } from "@mui/material"; -import { useState } from "react"; -import CircleDoubleDown from "./CircleDoubleDownIcon"; -import Chat from "./Chat"; +import { Box, Fab, Typography } from "@mui/material" +import { useState } from "react" +import CircleDoubleDown from "./CircleDoubleDownIcon" +import Chat from "./Chat" export default function FloatingSupportChat() { - const [isChatOpened, setIsChatOpened] = useState(false); + const [isChatOpened, setIsChatOpened] = useState(false) - const animation = { - "@keyframes runningStripe": { - "0%": { - left: "10%", - backgroundColor: "transparent", - }, - "10%": { - backgroundColor: "#ffffff", - }, - "50%": { - backgroundColor: "#ffffff", - transform: "translate(400px, 0)", - }, - "80%": { - backgroundColor: "#ffffff", - }, + const animation = { + "@keyframes runningStripe": { + "0%": { + left: "10%", + backgroundColor: "transparent", + }, + "10%": { + backgroundColor: "#ffffff", + }, + "50%": { + backgroundColor: "#ffffff", + transform: "translate(400px, 0)", + }, + "80%": { + backgroundColor: "#ffffff", + }, - "100%": { - backgroundColor: "transparent", - boxShadow: "none", - left: "100%", - }, - }, - }; - return ( - - {isChatOpened && ( - - )} - setIsChatOpened((prev) => !prev)} - > - {!isChatOpened && ( - - )} + "100%": { + backgroundColor: "transparent", + boxShadow: "none", + left: "100%", + }, + }, + } + return ( + + {isChatOpened && ( + + )} + setIsChatOpened((prev) => !prev)} + > + {!isChatOpened && ( + + )} - - {!isChatOpened && Задайте нам вопрос} - - - ); + + {!isChatOpened && Задайте нам вопрос} + + + ) } diff --git a/src/components/FloatingSupportChat/UserCircleIcon.tsx b/src/components/FloatingSupportChat/UserCircleIcon.tsx index 51b4032..5fa3283 100644 --- a/src/components/FloatingSupportChat/UserCircleIcon.tsx +++ b/src/components/FloatingSupportChat/UserCircleIcon.tsx @@ -1,22 +1,22 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" export default function UserCircleIcon() { - return ( - - - - - - - - ); + return ( + + + + + + + + ) } \ No newline at end of file diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 71e7f9e..bd7572a 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -1,66 +1,66 @@ -import { Box, Button, Divider, Typography, useMediaQuery, useTheme } from "@mui/material"; -import PenaLogo from "./PenaLogo"; -import SectionWrapper from "./SectionWrapper"; -import { Link } from "react-router-dom"; +import { Box, Button, Divider, Typography, useMediaQuery, useTheme } from "@mui/material" +import PenaLogo from "./PenaLogo" +import SectionWrapper from "./SectionWrapper" +import { Link } from "react-router-dom" export default function Footer() { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) - return ( - - - - - - *": { - width: upMd ? "33%" : undefined, - }, - }} - > - - - - {/* + return ( + + + + + + *": { + width: upMd ? "33%" : undefined, + }, + }} + > + + + + {/* @@ -68,18 +68,18 @@ export default function Footer() { */} - - + + ООО Пена© 2023 {new Date().getFullYear() === 2023 ? "" : " - " + new Date().getFullYear()} - - - - ); + + + + ) } diff --git a/src/components/InputTextfield.tsx b/src/components/InputTextfield.tsx index 97f1629..1df9cf4 100644 --- a/src/components/InputTextfield.tsx +++ b/src/components/InputTextfield.tsx @@ -1,15 +1,15 @@ import { - FormControl, - InputLabel, - SxProps, - TextField, - TextFieldProps, - Theme, - useMediaQuery, - useTheme, -} from "@mui/material"; + FormControl, + InputLabel, + SxProps, + TextField, + TextFieldProps, + Theme, + useMediaQuery, + useTheme, +} from "@mui/material" -import "./text-input.css"; +import "./text-input.css" interface Props { id: string; @@ -23,74 +23,74 @@ interface Props { } export default function InputTextfield({ - id, - label, - bold = false, - gap = "10px", - onChange, - TextfieldProps, - color, - FormInputSx, + id, + label, + bold = false, + gap = "10px", + onChange, + TextfieldProps, + color, + FormInputSx, }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) - const labelFont = upMd - ? bold - ? theme.typography.p1 - : { ...theme.typography.body1, fontWeight: 500 } - : theme.typography.body2; + const labelFont = upMd + ? bold + ? theme.typography.p1 + : { ...theme.typography.body1, fontWeight: 500 } + : theme.typography.body2 - const placeholderFont = upMd ? undefined : { fontWeight: 400, fontSize: "16px", lineHeight: "19px" }; + const placeholderFont = upMd ? undefined : { fontWeight: 400, fontSize: "16px", lineHeight: "19px" } - return ( - - {label && ( - - {label} - - )} - - - ); + return ( + + {label && ( + + {label} + + )} + + + ) } diff --git a/src/components/Loader.tsx b/src/components/Loader.tsx index f288687..699f510 100644 --- a/src/components/Loader.tsx +++ b/src/components/Loader.tsx @@ -1,30 +1,30 @@ -import { Box, useTheme } from "@mui/material"; +import { Box, useTheme } from "@mui/material" type LoaderProps = { size?: number; }; export const Loader = ({ size = 40 }: LoaderProps) => { - const theme = useTheme(); + const theme = useTheme() - return ( - - ); -}; + return ( + + ) +} diff --git a/src/components/Menu.tsx b/src/components/Menu.tsx index 3e0a40c..d177640 100644 --- a/src/components/Menu.tsx +++ b/src/components/Menu.tsx @@ -1,6 +1,6 @@ -import { useState } from "react"; -import { Box, Typography, useTheme } from "@mui/material"; -import { Link, useLocation } from "react-router-dom"; +import { useState } from "react" +import { Box, Typography, useTheme } from "@mui/material" +import { Link, useLocation } from "react-router-dom" type MenuItem = { name: string; @@ -9,123 +9,123 @@ type MenuItem = { }; export default function Menu() { - const [activeSubMenu, setActiveSubMenu] = useState([]); - const theme = useTheme(); - const location = useLocation(); + const [activeSubMenu, setActiveSubMenu] = useState([]) + const theme = useTheme() + const location = useLocation() - const color = location.pathname === "/" ? "white" : "black"; + const color = location.pathname === "/" ? "white" : "black" - const arrayMenu: MenuItem[] = location.pathname === "/" ? [ - { name: "Наши продукты", url: "/faq" }, - { name: "Наши услуги", url: "/cart" } - ] : [ - { - name: "Тарифы", - url: "/tariffs", - subMenu: [ - { name: "Тарифы на время", url: "/tariffs/time" }, - { name: "Тарифы на объём", url: "/tariffs/volume" }, - { name: "Кастомный тариф", url: "/tariffconstructor" }, - ], - }, - { name: "Вопросы и ответы", url: "/faq" }, - { name: "Корзина", url: "/cart" }, - { name: "Поддержка", url: "/support" }, - { name: "История", url: "/history" }, - ]; + const arrayMenu: MenuItem[] = location.pathname === "/" ? [ + { name: "Наши продукты", url: "/faq" }, + { name: "Наши услуги", url: "/cart" } + ] : [ + { + name: "Тарифы", + url: "/tariffs", + subMenu: [ + { name: "Тарифы на время", url: "/tariffs/time" }, + { name: "Тарифы на объём", url: "/tariffs/volume" }, + { name: "Кастомный тариф", url: "/tariffconstructor" }, + ], + }, + { name: "Вопросы и ответы", url: "/faq" }, + { name: "Корзина", url: "/cart" }, + { name: "Поддержка", url: "/support" }, + { name: "История", url: "/history" }, + ] - return ( - - {location.pathname !== "/" - ? arrayMenu.map(({ name, url, subMenu = [] }) => ( - setActiveSubMenu(subMenu)} - state={{ previousUrl: location.pathname }} - > - - {name} - - - )) - : arrayMenu.map(({ name, url, subMenu = [] }, index) => ( - - {name} - - ))} - setActiveSubMenu([])} - > - {location.pathname !== "/" && + return ( + + {location.pathname !== "/" + ? arrayMenu.map(({ name, url, subMenu = [] }) => ( + setActiveSubMenu(subMenu)} + state={{ previousUrl: location.pathname }} + > + + {name} + + + )) + : arrayMenu.map(({ name, url, subMenu = [] }, index) => ( + + {name} + + ))} + setActiveSubMenu([])} + > + {location.pathname !== "/" && activeSubMenu.map(({ name, url }) => ( - - - {name} - - + + + {name} + + ))} - - - ); + + + ) } diff --git a/src/components/NavbarLanding/Avatar.tsx b/src/components/NavbarLanding/Avatar.tsx index d47875a..cd767a6 100644 --- a/src/components/NavbarLanding/Avatar.tsx +++ b/src/components/NavbarLanding/Avatar.tsx @@ -1,42 +1,42 @@ -import { Avatar, Box, IconButton, SxProps, Theme, Typography, useTheme } from "@mui/material"; -import { useNavigate } from "react-router-dom"; +import { Avatar, Box, IconButton, SxProps, Theme, Typography, useTheme } from "@mui/material" +import { useNavigate } from "react-router-dom" interface Props { sx?: SxProps; } export default function CustomAvatar({ sx }: Props) { - const theme = useTheme(); - const navigate = useNavigate() + const theme = useTheme() + const navigate = useNavigate() - return ( - navigate("/settings")} - sx={{ - ml: "27px", - height: "36px", width: "36px", - ...sx, - }} - > - - AA - - - - - - - - - - ); + return ( + navigate("/settings")} + sx={{ + ml: "27px", + height: "36px", width: "36px", + ...sx, + }} + > + + AA + + + + + + + + + + ) } \ No newline at end of file diff --git a/src/components/NavbarLanding/DialogMenu.tsx b/src/components/NavbarLanding/DialogMenu.tsx index 002b1e1..e93c74b 100644 --- a/src/components/NavbarLanding/DialogMenu.tsx +++ b/src/components/NavbarLanding/DialogMenu.tsx @@ -1,28 +1,28 @@ -import { TransitionProps } from "@mui/material/transitions"; -import logotip from "../../assets/Icons/logoPenaHab.svg"; -import logotipBlack from "../../assets/Icons/black_logo_PenaHab.svg"; -import CustomAvatar from "./Avatar"; -import React from "react"; -import { Box, Button, Dialog, List, ListItem, Slide, Typography, useMediaQuery, useTheme } from "@mui/material"; -import { Link, useLocation } from "react-router-dom"; -import { useUserStore } from "@root/stores/user"; -import { currencyFormatter } from "@root/utils/currencyFormatter"; +import { TransitionProps } from "@mui/material/transitions" +import logotip from "../../assets/Icons/logoPenaHab.svg" +import logotipBlack from "../../assets/Icons/black_logo_PenaHab.svg" +import CustomAvatar from "./Avatar" +import React from "react" +import { Box, Button, Dialog, List, ListItem, Slide, Typography, useMediaQuery, useTheme } from "@mui/material" +import { Link, useLocation } from "react-router-dom" +import { useUserStore } from "@root/stores/user" +import { currencyFormatter } from "@root/utils/currencyFormatter" const arrayMenu = [ - { name: "Наши продукты", url: "/" }, - { name: "Наши услуги", url: "/" }, -]; + { name: "Наши продукты", url: "/" }, + { name: "Наши услуги", url: "/" }, +] const Transition = React.forwardRef(function Transition( - props: TransitionProps & { + props: TransitionProps & { children: React.ReactElement; }, - ref: React.Ref + ref: React.Ref ) { - return ; -}); + return +}) interface DialogMenuProps { open: boolean; @@ -30,129 +30,129 @@ interface DialogMenuProps { } export default function DialogMenu({ open, handleClose }: DialogMenuProps) { - const theme = useTheme(); - const location = useLocation(); - const isTablet = useMediaQuery(theme.breakpoints.down(900)); - const user = useUserStore((state) => state.user); - const cash = useUserStore((state) => state.userAccount?.wallet.cash) ?? 0; + const theme = useTheme() + const location = useLocation() + const isTablet = useMediaQuery(theme.breakpoints.down(900)) + const user = useUserStore((state) => state.user) + const cash = useUserStore((state) => state.userAccount?.wallet.cash) ?? 0 - const isMobileHeight = useMediaQuery("(max-height: 400px)"); + const isMobileHeight = useMediaQuery("(max-height: 400px)") - return ( - - - - {arrayMenu.map(({ name, url }, index) => ( - - ))} - - - {isTablet ? ( - location.pathname === "/" ? ( - + ))} + + + {isTablet ? ( + location.pathname === "/" ? ( + - ) : ( - - - - + + ) : ( + + + + Мой баланс - - - {currencyFormatter.format(cash / 100)} - - - - ) - ) : ( - <> - - icon - - - )} - - ); + + + {currencyFormatter.format(cash / 100)} + + + + ) + ) : ( + <> + + icon + + + )} + + ) } diff --git a/src/components/NavbarLanding/Navbar.tsx b/src/components/NavbarLanding/Navbar.tsx index a191c67..d0422e2 100644 --- a/src/components/NavbarLanding/Navbar.tsx +++ b/src/components/NavbarLanding/Navbar.tsx @@ -1,6 +1,6 @@ -import { useMediaQuery, useTheme } from "@mui/material"; -import NavbarCollapsed from "./NavbarCollapsed"; -import NavbarFull from "./NavbarFull"; +import { useMediaQuery, useTheme } from "@mui/material" +import NavbarCollapsed from "./NavbarCollapsed" +import NavbarFull from "./NavbarFull" interface Props { isCollapsed?: boolean; @@ -8,8 +8,8 @@ interface Props { } export default function Navbar({ isLoggedIn, isCollapsed = false }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) - return upMd ? : ; + return upMd ? : } diff --git a/src/components/NavbarLanding/NavbarCollapsed.tsx b/src/components/NavbarLanding/NavbarCollapsed.tsx index dac4bef..3040ccc 100644 --- a/src/components/NavbarLanding/NavbarCollapsed.tsx +++ b/src/components/NavbarLanding/NavbarCollapsed.tsx @@ -1,46 +1,46 @@ -import { useState } from "react"; -import { Button, useMediaQuery, useTheme } from "@mui/material"; -import { Link, useLocation } from "react-router-dom"; +import { useState } from "react" +import { Button, useMediaQuery, useTheme } from "@mui/material" +import { Link, useLocation } from "react-router-dom" -import SectionWrapper from "../SectionWrapper"; +import SectionWrapper from "../SectionWrapper" -import PenaLogo from "../PenaLogo"; -import DialogMenu from "./DialogMenu"; -import { BurgerButton } from "@frontend/kitui"; +import PenaLogo from "../PenaLogo" +import DialogMenu from "./DialogMenu" +import { BurgerButton } from "@frontend/kitui" interface Props { isLoggedIn: boolean; } export default function NavbarCollapsed({ isLoggedIn }: Props) { - const [open, setOpen] = useState(false); - const theme = useTheme(); + const [open, setOpen] = useState(false) + const theme = useTheme() - return ( - - - - + return ( + + + + - setOpen(!open)} sx={{ color: "white" }} /> - setOpen(false)} /> - - ); + setOpen(!open)} sx={{ color: "white" }} /> + setOpen(false)} /> + + ) } diff --git a/src/components/NavbarLanding/NavbarFull.tsx b/src/components/NavbarLanding/NavbarFull.tsx index 9b434ad..402e440 100644 --- a/src/components/NavbarLanding/NavbarFull.tsx +++ b/src/components/NavbarLanding/NavbarFull.tsx @@ -1,164 +1,164 @@ -import { useState } from "react"; -import { Link, useLocation, useNavigate } from "react-router-dom"; +import { useState } from "react" +import { Link, useLocation, useNavigate } from "react-router-dom" import { - Box, - Button, - Container, - IconButton, - Typography, - useMediaQuery, - useTheme, -} from "@mui/material"; -import SectionWrapper from "../SectionWrapper"; -import LogoutIcon from "../icons/LogoutIcon"; -import DialogMenu from "./DialogMenu"; -import WalletIcon from "../icons/WalletIcon"; -import CustomAvatar from "./Avatar"; -import Drawers from "../Drawers"; -import PenaLogo from "../PenaLogo"; -import Menu from "../Menu"; -import { logout } from "@root/api/auth"; -import { enqueueSnackbar } from "notistack"; -import { clearUserData, useUserStore } from "@root/stores/user"; + Box, + Button, + Container, + IconButton, + Typography, + useMediaQuery, + useTheme, +} from "@mui/material" +import SectionWrapper from "../SectionWrapper" +import LogoutIcon from "../icons/LogoutIcon" +import DialogMenu from "./DialogMenu" +import WalletIcon from "../icons/WalletIcon" +import CustomAvatar from "./Avatar" +import Drawers from "../Drawers" +import PenaLogo from "../PenaLogo" +import Menu from "../Menu" +import { logout } from "@root/api/auth" +import { enqueueSnackbar } from "notistack" +import { clearUserData, useUserStore } from "@root/stores/user" import { - BurgerButton, - clearAuthToken, - getMessageFromFetchError, -} from "@frontend/kitui"; -import { currencyFormatter } from "@root/utils/currencyFormatter"; -import { clearCustomTariffs } from "@root/stores/customTariffs"; -import { clearTickets } from "@root/stores/tickets"; + BurgerButton, + clearAuthToken, + getMessageFromFetchError, +} from "@frontend/kitui" +import { currencyFormatter } from "@root/utils/currencyFormatter" +import { clearCustomTariffs } from "@root/stores/customTariffs" +import { clearTickets } from "@root/stores/tickets" interface Props { isLoggedIn: boolean; } export default function NavbarFull({ isLoggedIn }: Props) { - const theme = useTheme(); - const location = useLocation(); - const navigate = useNavigate(); - const user = useUserStore((state) => state.user); - const cash = useUserStore((state) => state.userAccount?.wallet.cash) ?? 0; - const isTablet = useMediaQuery(theme.breakpoints.up(1000)); - const [open, setOpen] = useState(false); + const theme = useTheme() + const location = useLocation() + const navigate = useNavigate() + const user = useUserStore((state) => state.user) + const cash = useUserStore((state) => state.userAccount?.wallet.cash) ?? 0 + const isTablet = useMediaQuery(theme.breakpoints.up(1000)) + const [open, setOpen] = useState(false) - async function handleLogoutClick() { - const [_, logoutError] = await logout(); + async function handleLogoutClick() { + const [_, logoutError] = await logout() - if (logoutError) { - return enqueueSnackbar(logoutError); - } + if (logoutError) { + return enqueueSnackbar(logoutError) + } - clearAuthToken(); - clearUserData(); - clearCustomTariffs(); - clearTickets(); - navigate("/"); - } + clearAuthToken() + clearUserData() + clearCustomTariffs() + clearTickets() + navigate("/") + } - return isLoggedIn ? ( - - - - - - - - navigate("/wallet")} - > - - - - + return isLoggedIn ? ( + + + + + + + + navigate("/wallet")} + > + + + + Мой баланс - - - {currencyFormatter.format(cash / 100)} - - - - - - - - - ) : ( - <> - - - - {!isTablet ? null : } + + + {currencyFormatter.format(cash / 100)} + + + + + + + + + ) : ( + <> + + + + {!isTablet ? null : } - - - setOpen(!open)} - sx={{ color: "white", display: !isTablet ? "block" : "none" }} - /> - - setOpen(false)} /> - - ); + + setOpen(!open)} + sx={{ color: "white", display: !isTablet ? "block" : "none" }} + /> + + setOpen(false)} /> + + ) } diff --git a/src/components/NavbarSite/DialogMenu.tsx b/src/components/NavbarSite/DialogMenu.tsx index a1df782..85302bc 100644 --- a/src/components/NavbarSite/DialogMenu.tsx +++ b/src/components/NavbarSite/DialogMenu.tsx @@ -1,10 +1,10 @@ -import { useState } from "react"; -import { Link, useLocation } from "react-router-dom"; -import { Box, Button, List, ListItem, Typography, useMediaQuery, useTheme } from "@mui/material"; -import { useUserStore } from "@root/stores/user"; -import { currencyFormatter } from "@root/utils/currencyFormatter"; -import { cardShadow } from "@root/utils/theme"; -import { AvatarButton } from "@frontend/kitui"; +import { useState } from "react" +import { Link, useLocation } from "react-router-dom" +import { Box, Button, List, ListItem, Typography, useMediaQuery, useTheme } from "@mui/material" +import { useUserStore } from "@root/stores/user" +import { currencyFormatter } from "@root/utils/currencyFormatter" +import { cardShadow } from "@root/utils/theme" +import { AvatarButton } from "@frontend/kitui" type MenuItem = { @@ -14,186 +14,186 @@ type MenuItem = { }; const arrayMenu: MenuItem[] = [ - { - name: "Тарифы", - url: "/tariffs", - subMenu: [ - { name: "Тарифы на время", url: "/tariffs/time" }, - { name: "Тарифы на объём", url: "/tariffs/volume" }, - { name: "Кастомный тариф", url: "/tariffconstructor" }, - ], - }, - { name: "Профиль", url: "/settings" }, - { name: "Вопросы и ответы", url: "/faq" }, - { name: "Корзина", url: "/cart" }, - { name: "Поддержка", url: "/support" }, - { name: "История", url: "/history" }, -]; + { + name: "Тарифы", + url: "/tariffs", + subMenu: [ + { name: "Тарифы на время", url: "/tariffs/time" }, + { name: "Тарифы на объём", url: "/tariffs/volume" }, + { name: "Кастомный тариф", url: "/tariffconstructor" }, + ], + }, + { name: "Профиль", url: "/settings" }, + { name: "Вопросы и ответы", url: "/faq" }, + { name: "Корзина", url: "/cart" }, + { name: "Поддержка", url: "/support" }, + { name: "История", url: "/history" }, +] interface DialogMenuProps { handleClose: () => void; } export default function DialogMenu({ handleClose }: DialogMenuProps) { - const [activeSubMenuIndex, setActiveSubMenuIndex] = useState(-1); - const theme = useTheme(); - const location = useLocation(); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); - const isMobile = useMediaQuery(theme.breakpoints.down(600)); - const user = useUserStore((state) => state.user); - const cash = useUserStore((state) => state.userAccount?.wallet.cash) ?? 0; - const initials = useUserStore(state => state.initials); + const [activeSubMenuIndex, setActiveSubMenuIndex] = useState(-1) + const theme = useTheme() + const location = useLocation() + const isTablet = useMediaQuery(theme.breakpoints.down(1000)) + const isMobile = useMediaQuery(theme.breakpoints.down(600)) + const user = useUserStore((state) => state.user) + const cash = useUserStore((state) => state.userAccount?.wallet.cash) ?? 0 + const initials = useUserStore(state => state.initials) - const closeDialogMenu = () => { - setActiveSubMenuIndex(-1); + const closeDialogMenu = () => { + setActiveSubMenuIndex(-1) - handleClose(); - }; + handleClose() + } - const handleSubMenu = (index: number) => setActiveSubMenuIndex((activeIndex) => (activeIndex !== index ? index : -1)); + const handleSubMenu = (index: number) => setActiveSubMenuIndex((activeIndex) => (activeIndex !== index ? index : -1)) - return ( - - - - {arrayMenu.map(({ name, url, subMenu = [] }, index) => ( - - - {subMenu.length ? ( - - {index === activeSubMenuIndex && + return ( + + + + {arrayMenu.map(({ name, url, subMenu = [] }, index) => ( + + + {subMenu.length ? ( + + {index === activeSubMenuIndex && subMenu.map(({ name, url }) => ( - - + - {name} - - + }} + > + {name} + + ))} - - ) : ( - <> - )} - - ))} - - {location.pathname === "/" ? ( - - ) : ( - - {initials} - - + + ) : ( + + {initials} + + Мой баланс - - - {currencyFormatter.format(cash / 100)} - - - - )} - - - ); + + + {currencyFormatter.format(cash / 100)} + + + + )} + + + ) } diff --git a/src/components/NavbarSite/Navbar.tsx b/src/components/NavbarSite/Navbar.tsx index d49997d..72c93fe 100644 --- a/src/components/NavbarSite/Navbar.tsx +++ b/src/components/NavbarSite/Navbar.tsx @@ -1,28 +1,28 @@ -import { Box, useMediaQuery, useTheme } from "@mui/material"; -import NavbarCollapsed from "./NavbarCollapsed"; -import NavbarFull from "./NavbarFull"; +import { Box, useMediaQuery, useTheme } from "@mui/material" +import NavbarCollapsed from "./NavbarCollapsed" +import NavbarFull from "./NavbarFull" -import type { ReactNode } from "react"; +import type { ReactNode } from "react" interface Props { children: ReactNode; } export default function Navbar({ children }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up(1000)); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up(1000)) - return ( - - {upMd ? ( - {children} - ) : ( - {children} - )} - - ); + return ( + + {upMd ? ( + {children} + ) : ( + {children} + )} + + ) } diff --git a/src/components/NavbarSite/NavbarCollapsed.tsx b/src/components/NavbarSite/NavbarCollapsed.tsx index dfd74cc..8461096 100644 --- a/src/components/NavbarSite/NavbarCollapsed.tsx +++ b/src/components/NavbarSite/NavbarCollapsed.tsx @@ -1,248 +1,248 @@ -import { useState, useRef, useEffect } from "react"; +import { useState, useRef, useEffect } from "react" import { - Box, - Badge, - Drawer, - IconButton, - useTheme, - useMediaQuery, -} from "@mui/material"; -import { Link } from "react-router-dom"; + Box, + Badge, + Drawer, + IconButton, + useTheme, + useMediaQuery, +} from "@mui/material" +import { Link } from "react-router-dom" -import SectionWrapper from "../SectionWrapper"; -import { NotificationsModal } from "../NotificationsModal"; -import { NavbarPanel } from "./NavbarPanel"; +import SectionWrapper from "../SectionWrapper" +import { NotificationsModal } from "../NotificationsModal" +import { NavbarPanel } from "./NavbarPanel" -import { useUserStore } from "@root/stores/user"; +import { useUserStore } from "@root/stores/user" import { - useTicketStore -} from "@root/stores/tickets"; + useTicketStore +} from "@root/stores/tickets" -import { ReactComponent as CartIcon } from "@root/assets/Icons/cart.svg"; -import { ReactComponent as BellIcon } from "@root/assets/Icons/bell.svg"; +import { ReactComponent as CartIcon } from "@root/assets/Icons/cart.svg" +import { ReactComponent as BellIcon } from "@root/assets/Icons/bell.svg" -import DialogMenu from "./DialogMenu"; -import PenaLogo from "../PenaLogo"; -import CloseIcon from "../icons/CloseIcons"; -import MenuIcon from "@mui/icons-material/Menu"; +import DialogMenu from "./DialogMenu" +import PenaLogo from "../PenaLogo" +import CloseIcon from "../icons/CloseIcons" +import MenuIcon from "@mui/icons-material/Menu" -import type { ReactNode } from "react"; +import type { ReactNode } from "react" interface Props { children: ReactNode; } export default function NavbarCollapsed({ children }: Props) { - const [open, setOpen] = useState(false); - const [openNotificationsModal, setOpenNotificationsModal] = - useState(false); - const bellRef = useRef(null); - const userAccount = useUserStore((state) => state.userAccount); - const tickets = useTicketStore((state) => state.tickets); - const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down(550)); + const [open, setOpen] = useState(false) + const [openNotificationsModal, setOpenNotificationsModal] = + useState(false) + const bellRef = useRef(null) + const userAccount = useUserStore((state) => state.userAccount) + const tickets = useTicketStore((state) => state.tickets) + const theme = useTheme() + const isMobile = useMediaQuery(theme.breakpoints.down(550)) - const handleClose = () => { - setOpen(false); - }; + const handleClose = () => { + setOpen(false) + } - const notificationsCount = tickets.filter( - ({ user, top_message }) => - user !== top_message.user_id && top_message.shown.me !== 1 - ).length; + const notificationsCount = tickets.filter( + ({ user, top_message }) => + user !== top_message.user_id && top_message.shown.me !== 1 + ).length - useEffect(() => { - if (open) { - document.body.style.overflow = "hidden"; + useEffect(() => { + if (open) { + document.body.style.overflow = "hidden" - return; - } + return + } - document.body.style.overflow = "unset"; - }, [open]); + document.body.style.overflow = "unset" + }, [open]) - return ( - - - - setOpen((isOpened) => !isOpened)} - sx={{ - p: 0, - width: "30px", - color: theme.palette.primary.main, - }} - > - {open ? ( - - ) : ( - - )} - - {isMobile && ( - <> - - path:nth-of-type(1)": { fill: "#FFFFFF" }, - "& svg > path:nth-of-type(2)": { fill: "#FFFFFF" }, - "& svg > path:nth-of-type(3)": { stroke: "#FFFFFF" }, - }, - }} - > - - - - - - - setOpenNotificationsModal((isOpened) => !isOpened) - } - aria-label="cart" - sx={{ - width: "30px", - height: "30px", - background: theme.palette.background.default, - borderRadius: "6px", - "&:hover": { - background: theme.palette.purple.main, - "& .MuiBadge-badge": { - background: theme.palette.background.default, - color: theme.palette.purple.main, - }, - "& svg > path:first-of-type": { fill: "#FFFFFF" }, - "& svg > path:last-child": { stroke: "#FFFFFF" }, - }, - }} - > - - - - - - )} - user !== top_message.user_id) - .map((ticket) => ({ - text: "У вас новое сообщение от техподдержки", - date: new Date(ticket.updated_at).toLocaleDateString(), - url: `/support/${ticket.id}`, - watched: ticket.top_message.shown.me === 1, - }))} - /> - - - - {!isMobile && } - - - - - - - - {children} - - - - ); + return ( + + + + setOpen((isOpened) => !isOpened)} + sx={{ + p: 0, + width: "30px", + color: theme.palette.primary.main, + }} + > + {open ? ( + + ) : ( + + )} + + {isMobile && ( + <> + + path:nth-of-type(1)": { fill: "#FFFFFF" }, + "& svg > path:nth-of-type(2)": { fill: "#FFFFFF" }, + "& svg > path:nth-of-type(3)": { stroke: "#FFFFFF" }, + }, + }} + > + + + + + + + setOpenNotificationsModal((isOpened) => !isOpened) + } + aria-label="cart" + sx={{ + width: "30px", + height: "30px", + background: theme.palette.background.default, + borderRadius: "6px", + "&:hover": { + background: theme.palette.purple.main, + "& .MuiBadge-badge": { + background: theme.palette.background.default, + color: theme.palette.purple.main, + }, + "& svg > path:first-of-type": { fill: "#FFFFFF" }, + "& svg > path:last-child": { stroke: "#FFFFFF" }, + }, + }} + > + + + + + + )} + user !== top_message.user_id) + .map((ticket) => ({ + text: "У вас новое сообщение от техподдержки", + date: new Date(ticket.updated_at).toLocaleDateString(), + url: `/support/${ticket.id}`, + watched: ticket.top_message.shown.me === 1, + }))} + /> + + + + {!isMobile && } + + + + + + + + {children} + + + + ) } diff --git a/src/components/NavbarSite/NavbarFull.tsx b/src/components/NavbarSite/NavbarFull.tsx index 785a125..bf26211 100644 --- a/src/components/NavbarSite/NavbarFull.tsx +++ b/src/components/NavbarSite/NavbarFull.tsx @@ -1,94 +1,94 @@ -import { Link, useNavigate } from "react-router-dom"; -import { Box, Container, Typography, useTheme } from "@mui/material"; -import Drawers from "../Drawers"; -import PenaLogo from "../PenaLogo"; -import Menu from "../Menu"; -import { logout } from "@root/api/auth"; -import { enqueueSnackbar } from "notistack"; -import { clearUserData, useUserStore } from "@root/stores/user"; +import { Link, useNavigate } from "react-router-dom" +import { Box, Container, Typography, useTheme } from "@mui/material" +import Drawers from "../Drawers" +import PenaLogo from "../PenaLogo" +import Menu from "../Menu" +import { logout } from "@root/api/auth" +import { enqueueSnackbar } from "notistack" +import { clearUserData, useUserStore } from "@root/stores/user" import { - AvatarButton, - LogoutButton, - WalletButton, - clearAuthToken, -} from "@frontend/kitui"; -import { clearCustomTariffs } from "@root/stores/customTariffs"; -import { currencyFormatter } from "@root/utils/currencyFormatter"; -import { clearTickets } from "@root/stores/tickets"; + AvatarButton, + LogoutButton, + WalletButton, + clearAuthToken, +} from "@frontend/kitui" +import { clearCustomTariffs } from "@root/stores/customTariffs" +import { currencyFormatter } from "@root/utils/currencyFormatter" +import { clearTickets } from "@root/stores/tickets" -import type { ReactNode } from "react"; +import type { ReactNode } from "react" interface Props { children: ReactNode; } export default function NavbarFull({ children }: Props) { - const theme = useTheme(); - const navigate = useNavigate(); - const cash = useUserStore((state) => state.userAccount?.wallet.cash) ?? 0; - const initials = useUserStore((state) => state.initials); + const theme = useTheme() + const navigate = useNavigate() + const cash = useUserStore((state) => state.userAccount?.wallet.cash) ?? 0 + const initials = useUserStore((state) => state.initials) - async function handleLogoutClick() { - const [_, logoutError] = await logout(); + async function handleLogoutClick() { + const [_, logoutError] = await logout() - if (logoutError) { - return enqueueSnackbar(logoutError); - } + if (logoutError) { + return enqueueSnackbar(logoutError) + } - clearAuthToken(); - clearUserData(); - clearCustomTariffs(); - clearTickets(); - navigate("/"); - } + clearAuthToken() + clearUserData() + clearCustomTariffs() + clearTickets() + navigate("/") + } - return ( - - - - - - - - - - - + return ( + + + + + + + + + + + Мой баланс - - - {currencyFormatter.format(cash / 100)} - - - - {initials} - - - - - {children} - - ); + + + {currencyFormatter.format(cash / 100)} + + + + {initials} + + + + + {children} + + ) } diff --git a/src/components/NavbarSite/NavbarPanel.tsx b/src/components/NavbarSite/NavbarPanel.tsx index e4926d6..4d839e4 100644 --- a/src/components/NavbarSite/NavbarPanel.tsx +++ b/src/components/NavbarSite/NavbarPanel.tsx @@ -1,91 +1,91 @@ -import { Link, useNavigate } from "react-router-dom"; +import { Link, useNavigate } from "react-router-dom" import { - Box, - IconButton, - Typography, - useTheme, - useMediaQuery, -} from "@mui/material"; -import LogoutIcon from "../icons/LogoutIcon"; -import Drawers from "../Drawers"; -import { logout } from "@root/api/auth"; -import { enqueueSnackbar } from "notistack"; -import { clearUserData, useUserStore } from "@root/stores/user"; -import { AvatarButton, clearAuthToken } from "@frontend/kitui"; -import { clearCustomTariffs } from "@root/stores/customTariffs"; -import { clearTickets } from "@root/stores/tickets"; + Box, + IconButton, + Typography, + useTheme, + useMediaQuery, +} from "@mui/material" +import LogoutIcon from "../icons/LogoutIcon" +import Drawers from "../Drawers" +import { logout } from "@root/api/auth" +import { enqueueSnackbar } from "notistack" +import { clearUserData, useUserStore } from "@root/stores/user" +import { AvatarButton, clearAuthToken } from "@frontend/kitui" +import { clearCustomTariffs } from "@root/stores/customTariffs" +import { clearTickets } from "@root/stores/tickets" -import { currencyFormatter } from "@root/utils/currencyFormatter"; +import { currencyFormatter } from "@root/utils/currencyFormatter" -import walletIcon from "@root/assets/Icons/wallet_icon.svg"; +import walletIcon from "@root/assets/Icons/wallet_icon.svg" export const NavbarPanel = () => { - const navigate = useNavigate(); - const theme = useTheme(); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); - const cash = useUserStore((state) => state.userAccount?.wallet.cash) ?? 0; - const initials = useUserStore((state) => state.initials); + const navigate = useNavigate() + const theme = useTheme() + const isTablet = useMediaQuery(theme.breakpoints.down(1000)) + const cash = useUserStore((state) => state.userAccount?.wallet.cash) ?? 0 + const initials = useUserStore((state) => state.initials) - async function handleLogoutClick() { - const [_, logoutError] = await logout(); + async function handleLogoutClick() { + const [_, logoutError] = await logout() - if (logoutError) { - return enqueueSnackbar(logoutError); - } + if (logoutError) { + return enqueueSnackbar(logoutError) + } - clearAuthToken(); - clearUserData(); - clearCustomTariffs(); - clearTickets(); - navigate("/"); - } + clearAuthToken() + clearUserData() + clearCustomTariffs() + clearTickets() + navigate("/") + } - return ( - - - navigate("/wallet")} - > - wallet - - - + return ( + + + navigate("/wallet")} + > + wallet + + + Мой баланс - - - {currencyFormatter.format(cash / 100)} - - - - {initials} - - - - - - ); -}; + + + {currencyFormatter.format(cash / 100)} + + + + {initials} + + + + + + ) +} diff --git a/src/components/NotificationsModal.tsx b/src/components/NotificationsModal.tsx index d4b97ab..f150d75 100644 --- a/src/components/NotificationsModal.tsx +++ b/src/components/NotificationsModal.tsx @@ -1,12 +1,12 @@ import { - Popover, - List, - ListItem, - Typography, - useTheme, - useMediaQuery, -} from "@mui/material"; -import { Link } from "react-router-dom"; + Popover, + List, + ListItem, + Typography, + useTheme, + useMediaQuery, +} from "@mui/material" +import { Link } from "react-router-dom" type Notification = { text: string; @@ -23,123 +23,123 @@ type NotificationsModalProps = { }; export const NotificationsModal = ({ - open, - setOpen, - anchorElement, - notifications, + open, + setOpen, + anchorElement, + notifications, }: NotificationsModalProps) => { - const theme = useTheme(); - const isMobile = useMediaQuery(theme.breakpoints.down(650)); + const theme = useTheme() + const isMobile = useMediaQuery(theme.breakpoints.down(650)) - return ( - setOpen(false)} - anchorOrigin={{ vertical: "bottom", horizontal: "left" }} - transformOrigin={{ vertical: "top", horizontal: "right" }} - sx={{ - "& .MuiPopover-paper": { - maxWidth: isMobile ? "calc(100vw - 30px)" : 600, - width: "100%", - maxHeight: "310px", - borderRadius: "8px", - boxShadow: + return ( + setOpen(false)} + anchorOrigin={{ vertical: "bottom", horizontal: "left" }} + transformOrigin={{ vertical: "top", horizontal: "right" }} + sx={{ + "& .MuiPopover-paper": { + maxWidth: isMobile ? "calc(100vw - 30px)" : 600, + width: "100%", + maxHeight: "310px", + borderRadius: "8px", + boxShadow: "0px 3px 18px rgba(49, 28, 77, 0.1), 0px 3px 34px rgba(49, 28, 77, 0.15)", - "&::-webkit-scrollbar": { width: "6px" }, - "&::-webkit-scrollbar-track": { - background: "#F0F0F6", - margin: "5px", - borderRadius: "5px", - }, - "&::-webkit-scrollbar-thumb": { - width: "4px", - background: "#9A9AAF", - borderRadius: "5px", - }, - }, - }} - > - - {notifications.length ? ( - <> - {notifications.map(({ text, date, url, watched = true }) => ( - setOpen(false)} - style={{ - textDecoration: "none", - color: "inherit", - }} - > - - - {text} - - - {date} - - - - ))} - - ) : ( - + "&::-webkit-scrollbar": { width: "6px" }, + "&::-webkit-scrollbar-track": { + background: "#F0F0F6", + margin: "5px", + borderRadius: "5px", + }, + "&::-webkit-scrollbar-thumb": { + width: "4px", + background: "#9A9AAF", + borderRadius: "5px", + }, + }, + }} + > + + {notifications.length ? ( + <> + {notifications.map(({ text, date, url, watched = true }) => ( + setOpen(false)} + style={{ + textDecoration: "none", + color: "inherit", + }} + > + + + {text} + + + {date} + + + + ))} + + ) : ( + Нет оповещений - - )} - - - ); -}; + + )} + + + ) +} diff --git a/src/components/NumberIcon.tsx b/src/components/NumberIcon.tsx index 6f4cf01..ae27b96 100644 --- a/src/components/NumberIcon.tsx +++ b/src/components/NumberIcon.tsx @@ -1,5 +1,5 @@ -import { Box, SxProps, Theme } from "@mui/material"; -import { ReactElement } from "react"; +import { Box, SxProps, Theme } from "@mui/material" +import { ReactElement } from "react" interface Props { @@ -10,86 +10,86 @@ interface Props { } export default function NumberIcon({ number, backgroundColor = "rgb(0 0 0 / 0)", color, sx }: Props) { - number = number % 100; + number = number % 100 - const firstDigit = Math.floor(number / 10); - const secondDigit = number % 10; + const firstDigit = Math.floor(number / 10) + const secondDigit = number % 10 - const firstDigitTranslateX = 6; - const secondDigitTranslateX = number < 10 - ? 9 - : number < 20 - ? 11 - : 12; + const firstDigitTranslateX = 6 + const secondDigitTranslateX = number < 10 + ? 9 + : number < 20 + ? 11 + : 12 - const firstDigitElement = digitSvgs[firstDigit](firstDigitTranslateX); - const secondDigitElement = digitSvgs[secondDigit](secondDigitTranslateX); + const firstDigitElement = digitSvgs[firstDigit](firstDigitTranslateX) + const secondDigitElement = digitSvgs[secondDigit](secondDigitTranslateX) - return ( - - - {circleSvg} - {number > 9 && firstDigitElement} - {secondDigitElement} - - - ); + return ( + + + {circleSvg} + {number > 9 && firstDigitElement} + {secondDigitElement} + + + ) } -const circleSvg = ; +const circleSvg = const digitSvgs: Record ReactElement> = { - 0: (translateX: number) => ( - - ), - 1: (translateX: number) => ( - - ), - 2: (translateX: number) => ( - - ), - 3: (translateX: number) => ( - - ), - 4: (translateX: number) => ( - <> - - - - ), - 5: (translateX: number) => ( - - ), - 6: (translateX: number) => ( - <> - - - - ), - 7: (translateX: number) => ( - - ), - 8: (translateX: number) => ( - <> - - - - ), - 9: (translateX: number) => ( - <> - - - - ), -}; + 0: (translateX: number) => ( + + ), + 1: (translateX: number) => ( + + ), + 2: (translateX: number) => ( + + ), + 3: (translateX: number) => ( + + ), + 4: (translateX: number) => ( + <> + + + + ), + 5: (translateX: number) => ( + + ), + 6: (translateX: number) => ( + <> + + + + ), + 7: (translateX: number) => ( + + ), + 8: (translateX: number) => ( + <> + + + + ), + 9: (translateX: number) => ( + <> + + + + ), +} diff --git a/src/components/NumberInputWithUnitAdornment.tsx b/src/components/NumberInputWithUnitAdornment.tsx index ebd16d3..397a124 100644 --- a/src/components/NumberInputWithUnitAdornment.tsx +++ b/src/components/NumberInputWithUnitAdornment.tsx @@ -1,7 +1,7 @@ -import { useState } from "react"; -import { InputAdornment, TextField, Typography, useTheme } from "@mui/material"; +import { useState } from "react" +import { InputAdornment, TextField, Typography, useTheme } from "@mui/material" -import type { ChangeEvent } from "react"; +import type { ChangeEvent } from "react" interface Props { id: string; @@ -11,92 +11,92 @@ interface Props { } export default function NumberInputWithUnitAdornment({ id, value, adornmentText, onChange }: Props) { - const theme = useTheme(); - const [changed, setChanged] = useState(false); + const theme = useTheme() + const [changed, setChanged] = useState(false) - return ( - ) => { - if (!changed) { - setChanged(true); - } + return ( + ) => { + if (!changed) { + setChanged(true) + } - if (Number(target.value) > 999999) { - target.value = "999999"; - } + if (Number(target.value) > 999999) { + target.value = "999999" + } - const newNumber = parseInt(target.value); + const newNumber = parseInt(target.value) - if (!isFinite(newNumber) || newNumber < 0) { - onChange(0); + if (!isFinite(newNumber) || newNumber < 0) { + onChange(0) - return; - } + return + } - onChange(newNumber); - }} - sx={{ - maxWidth: "200px", - minWidth: "200px", - ".MuiInputBase-root": { - display: "flex", - pr: 0, - height: "48px", - borderRadius: "8px", - backgroundColor: "#F2F3F7", - fieldset: { - border: "1px solid" + theme.palette.gray.main, - }, - "&.Mui-focused fieldset": { - borderColor: theme.palette.purple.main, - }, - input: { - height: "31px", - borderRight: !changed ? "none" : "1px solid #9A9AAF", - }, - "&.Mui-focused input": { - borderRight: "1px solid #9A9AAF", - }, - "&:not(.Mui-focused) .MuiInputAdornment-root": { - display: !changed ? "none" : undefined, - }, - "&.Mui-focused ::-webkit-input-placeholder": { - color: "transparent", - }, + onChange(newNumber) + }} + sx={{ + maxWidth: "200px", + minWidth: "200px", + ".MuiInputBase-root": { + display: "flex", + pr: 0, + height: "48px", + borderRadius: "8px", + backgroundColor: "#F2F3F7", + fieldset: { + border: "1px solid" + theme.palette.gray.main, + }, + "&.Mui-focused fieldset": { + borderColor: theme.palette.purple.main, + }, + input: { + height: "31px", + borderRight: !changed ? "none" : "1px solid #9A9AAF", + }, + "&.Mui-focused input": { + borderRight: "1px solid #9A9AAF", + }, + "&:not(.Mui-focused) .MuiInputAdornment-root": { + display: !changed ? "none" : undefined, + }, + "&.Mui-focused ::-webkit-input-placeholder": { + color: "transparent", + }, - // Hiding arrows - "input::-webkit-outer-spin-button, input::-webkit-inner-spin-button": { - WebkitAppearance: "none", - margin: 0, - }, - "input[type = number]": { - MozAppearance: "textfield", - }, - }, - }} - InputProps={{ - endAdornment: ( - - - {adornmentText} - - - ), - }} - /> - ); + // Hiding arrows + "input::-webkit-outer-spin-button, input::-webkit-inner-spin-button": { + WebkitAppearance: "none", + margin: 0, + }, + "input[type = number]": { + MozAppearance: "textfield", + }, + }, + }} + InputProps={{ + endAdornment: ( + + + {adornmentText} + + + ), + }} + /> + ) } diff --git a/src/components/PenaLogo.tsx b/src/components/PenaLogo.tsx index f4fbdd9..07110ef 100644 --- a/src/components/PenaLogo.tsx +++ b/src/components/PenaLogo.tsx @@ -1,4 +1,4 @@ -import { useTheme } from "@mui/material"; +import { useTheme } from "@mui/material" interface Props { @@ -7,29 +7,29 @@ interface Props { } export default function PenaLogo({ width, color }: Props) { - const theme = useTheme(); + const theme = useTheme() - return ( - - - - - - - - - - - - - - - - - - - - - - ); + return ( + + + + + + + + + + + + + + + + + + + + + + ) } diff --git a/src/components/ProtectedLayout.tsx b/src/components/ProtectedLayout.tsx index 4378f00..342c27c 100644 --- a/src/components/ProtectedLayout.tsx +++ b/src/components/ProtectedLayout.tsx @@ -1,85 +1,85 @@ -import { Outlet } from "react-router-dom"; -import Navbar from "./NavbarSite/Navbar"; +import { Outlet } from "react-router-dom" +import Navbar from "./NavbarSite/Navbar" import { - Ticket, - getMessageFromFetchError, - useAllTariffsFetcher, - usePrivilegeFetcher, - useSSESubscription, - useTicketsFetcher, - useToken, -} from "@frontend/kitui"; -import { updateTickets, setTicketCount, useTicketStore, setTicketsFetchState } from "@root/stores/tickets"; -import { enqueueSnackbar } from "notistack"; -import { updateTariffs } from "@root/stores/tariffs"; -import { useCustomTariffs } from "@root/utils/hooks/useCustomTariffs"; -import { setCustomTariffs } from "@root/stores/customTariffs"; -import { useDiscounts } from "@root/utils/hooks/useDiscounts"; -import { setDiscounts } from "@root/stores/discounts"; -import { setPrivileges } from "@root/stores/privileges"; + Ticket, + getMessageFromFetchError, + useAllTariffsFetcher, + usePrivilegeFetcher, + useSSESubscription, + useTicketsFetcher, + useToken, +} from "@frontend/kitui" +import { updateTickets, setTicketCount, useTicketStore, setTicketsFetchState } from "@root/stores/tickets" +import { enqueueSnackbar } from "notistack" +import { updateTariffs } from "@root/stores/tariffs" +import { useCustomTariffs } from "@root/utils/hooks/useCustomTariffs" +import { setCustomTariffs } from "@root/stores/customTariffs" +import { useDiscounts } from "@root/utils/hooks/useDiscounts" +import { setDiscounts } from "@root/stores/discounts" +import { setPrivileges } from "@root/stores/privileges" export default function ProtectedLayout() { - const token = useToken(); - const ticketApiPage = useTicketStore((state) => state.apiPage); - const ticketsPerPage = useTicketStore((state) => state.ticketsPerPage); + const token = useToken() + const ticketApiPage = useTicketStore((state) => state.apiPage) + const ticketsPerPage = useTicketStore((state) => state.ticketsPerPage) - useSSESubscription({ - url: `https://hub.pena.digital/heruvym/subscribe?Authorization=${token}`, - onNewData: (data) => { - updateTickets(data.filter((d) => Boolean(d.id))); - setTicketCount(data.length); - }, - marker: "ticket", - }); + useSSESubscription({ + url: `https://hub.pena.digital/heruvym/subscribe?Authorization=${token}`, + onNewData: (data) => { + updateTickets(data.filter((d) => Boolean(d.id))) + setTicketCount(data.length) + }, + marker: "ticket", + }) - useTicketsFetcher({ - url: "https://hub.pena.digital/heruvym/getTickets", - ticketsPerPage, - ticketApiPage, - onSuccess: (result) => { - if (result.data) updateTickets(result.data); - setTicketCount(result.count); - }, - onError: (error: Error) => { - const message = getMessageFromFetchError(error); - if (message) enqueueSnackbar(message); - }, - onFetchStateChange: setTicketsFetchState, - }); + useTicketsFetcher({ + url: "https://hub.pena.digital/heruvym/getTickets", + ticketsPerPage, + ticketApiPage, + onSuccess: (result) => { + if (result.data) updateTickets(result.data) + setTicketCount(result.count) + }, + onError: (error: Error) => { + const message = getMessageFromFetchError(error) + if (message) enqueueSnackbar(message) + }, + onFetchStateChange: setTicketsFetchState, + }) - useAllTariffsFetcher({ - onSuccess: updateTariffs, - onError: (error) => { - const errorMessage = getMessageFromFetchError(error); - if (errorMessage) enqueueSnackbar(errorMessage); - }, - }); + useAllTariffsFetcher({ + onSuccess: updateTariffs, + onError: (error) => { + const errorMessage = getMessageFromFetchError(error) + if (errorMessage) enqueueSnackbar(errorMessage) + }, + }) - useCustomTariffs({ - onNewUser: setCustomTariffs, - onError: (error) => { - if (error) enqueueSnackbar(error); - }, - }); + useCustomTariffs({ + onNewUser: setCustomTariffs, + onError: (error) => { + if (error) enqueueSnackbar(error) + }, + }) - useDiscounts({ - onNewDiscounts: setDiscounts, - onError: (error) => { - const message = getMessageFromFetchError(error); - if (message) enqueueSnackbar(message); - }, - }); + useDiscounts({ + onNewDiscounts: setDiscounts, + onError: (error) => { + const message = getMessageFromFetchError(error) + if (message) enqueueSnackbar(message) + }, + }) - usePrivilegeFetcher({ - onSuccess: setPrivileges, - onError: (error) => { - console.log("usePrivilegeFetcher error :>> ", error); - }, - }); + usePrivilegeFetcher({ + onSuccess: setPrivileges, + onError: (error) => { + console.log("usePrivilegeFetcher error :>> ", error) + }, + }) - return ( - - - - ); + return ( + + + + ) } diff --git a/src/components/SectionWrapper.tsx b/src/components/SectionWrapper.tsx index 0c83c1f..4a459d4 100644 --- a/src/components/SectionWrapper.tsx +++ b/src/components/SectionWrapper.tsx @@ -1,5 +1,5 @@ -import { Breakpoint, Container, SxProps, Theme, useMediaQuery, useTheme } from "@mui/material"; -import React, { ElementType } from "react"; +import { Breakpoint, Container, SxProps, Theme, useMediaQuery, useTheme } from "@mui/material" +import React, { ElementType } from "react" interface Props { component?: ElementType; @@ -11,23 +11,23 @@ interface Props { } export default function SectionWrapper({ component, outerContainerSx: sx, sx: innerSx, children, maxWidth }: Props) { - const theme = useTheme(); - const matchMd = useMediaQuery(theme.breakpoints.up("md")); + const theme = useTheme() + const matchMd = useMediaQuery(theme.breakpoints.up("md")) - const isMobile = useMediaQuery(theme.breakpoints.down(380)); + const isMobile = useMediaQuery(theme.breakpoints.down(380)) - return ( - - - {children} - - - ); + return ( + + + {children} + + + ) } diff --git a/src/components/Select/index.tsx b/src/components/Select/index.tsx index bebe600..1cbb0f6 100644 --- a/src/components/Select/index.tsx +++ b/src/components/Select/index.tsx @@ -1,12 +1,12 @@ -import { useState, useRef } from "react"; -import { Select as MuiSelect, MenuItem, Box, Typography, useTheme } from "@mui/material"; -import classnames from "classnames"; +import { useState, useRef } from "react" +import { Select as MuiSelect, MenuItem, Box, Typography, useTheme } from "@mui/material" +import classnames from "classnames" -import checkIcon from "@root/assets/Icons/check.svg"; +import checkIcon from "@root/assets/Icons/check.svg" -import "./select.css"; +import "./select.css" -import type { SelectChangeEvent } from "@mui/material"; +import type { SelectChangeEvent } from "@mui/material" type SelectProps = { items: string[]; @@ -15,74 +15,74 @@ type SelectProps = { }; export const Select = ({ items, selectedItem, setSelectedItem }: SelectProps) => { - const [opened, setOpened] = useState(false); - const [currentValue, setCurrentValue] = useState(items[selectedItem]); - const ref = useRef(null); - const theme = useTheme(); + const [opened, setOpened] = useState(false) + const [currentValue, setCurrentValue] = useState(items[selectedItem]) + const ref = useRef(null) + const theme = useTheme() - const selectItem = (event: SelectChangeEvent) => { - setCurrentValue(items[Number(event.target.value)]); - setSelectedItem(Number(event.target.value)); - }; + const selectItem = (event: SelectChangeEvent) => { + setCurrentValue(items[Number(event.target.value)]) + setSelectedItem(Number(event.target.value)) + } - return ( - - ref.current?.click()} - > - - {currentValue} - - check - - setOpened((isOpened) => !isOpened)} - > - {items.map((item, index) => ( - - {item} - - ))} - - - ); -}; + return ( + + ref.current?.click()} + > + + {currentValue} + + check + + setOpened((isOpened) => !isOpened)} + > + {items.map((item, index) => ( + + {item} + + ))} + + + ) +} diff --git a/src/components/Tabs.tsx b/src/components/Tabs.tsx index c7ed07d..f2d8a6c 100644 --- a/src/components/Tabs.tsx +++ b/src/components/Tabs.tsx @@ -1,5 +1,5 @@ -import { Tabs as MuiTabs } from "@mui/material"; -import { CustomTab } from "@root/components/CustomTab"; +import { Tabs as MuiTabs } from "@mui/material" +import { CustomTab } from "@root/components/CustomTab" type TabsProps = { items: string[]; @@ -8,15 +8,15 @@ type TabsProps = { }; export const Tabs = ({ items, selectedItem, setSelectedItem }: TabsProps) => ( - setSelectedItem(newValue)} - variant="scrollable" - scrollButtons={false} - > - {items.map((item, index) => ( - - ))} - -); + setSelectedItem(newValue)} + variant="scrollable" + scrollButtons={false} + > + {items.map((item, index) => ( + + ))} + +) diff --git a/src/components/TotalPrice.tsx b/src/components/TotalPrice.tsx index 3e1a144..a6b35b1 100644 --- a/src/components/TotalPrice.tsx +++ b/src/components/TotalPrice.tsx @@ -1,20 +1,20 @@ -import { useState } from "react"; -import { useNavigate } from "react-router-dom"; -import { enqueueSnackbar } from "notistack"; +import { useState } from "react" +import { useNavigate } from "react-router-dom" +import { enqueueSnackbar } from "notistack" import { - Alert, - Box, - Button, - Typography, - useMediaQuery, - useTheme, -} from "@mui/material"; + Alert, + Box, + Button, + Typography, + useMediaQuery, + useTheme, +} from "@mui/material" -import { Loader } from "./Loader"; +import { Loader } from "./Loader" -import { currencyFormatter } from "@root/utils/currencyFormatter"; -import { payCart } from "@root/api/cart"; -import { setUserAccount } from "@root/stores/user"; +import { currencyFormatter } from "@root/utils/currencyFormatter" +import { payCart } from "@root/api/cart" +import { setUserAccount } from "@root/stores/user" interface Props { priceBeforeDiscounts: number; @@ -22,129 +22,129 @@ interface Props { } export default function TotalPrice({ - priceAfterDiscounts, - priceBeforeDiscounts, + priceAfterDiscounts, + priceBeforeDiscounts, }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const isMobile = useMediaQuery(theme.breakpoints.down(550)); - const [notEnoughMoneyAmount, setNotEnoughMoneyAmount] = useState(0); - const [loading, setLoading] = useState(false); - const navigate = useNavigate(); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const isMobile = useMediaQuery(theme.breakpoints.down(550)) + const [notEnoughMoneyAmount, setNotEnoughMoneyAmount] = useState(0) + const [loading, setLoading] = useState(false) + const navigate = useNavigate() - async function handlePayClick() { - setLoading(true); + async function handlePayClick() { + setLoading(true) - const [payCartResponse, payCartError] = await payCart(); + const [payCartResponse, payCartError] = await payCart() - if (payCartError) { - if (payCartError.includes("insufficient funds: ")) { - const notEnoughMoneyAmount = parseInt( - payCartError.replace(/^.*insufficient\sfunds:\s(?=\d+$)/, "") - ); + if (payCartError) { + if (payCartError.includes("insufficient funds: ")) { + const notEnoughMoneyAmount = parseInt( + payCartError.replace(/^.*insufficient\sfunds:\s(?=\d+$)/, "") + ) - setNotEnoughMoneyAmount(notEnoughMoneyAmount); - } + setNotEnoughMoneyAmount(notEnoughMoneyAmount) + } - setLoading(false); + setLoading(false) - return enqueueSnackbar(payCartError); - } + return enqueueSnackbar(payCartError) + } - if (payCartResponse) { - setUserAccount(payCartResponse); - } + if (payCartResponse) { + setUserAccount(payCartResponse) + } - setLoading(false); - } + setLoading(false) + } - function handleReplenishWallet() { - navigate("/payment", { state: { notEnoughMoneyAmount } }); - } + function handleReplenishWallet() { + navigate("/payment", { state: { notEnoughMoneyAmount } }) + } - return ( - - - + return ( + + + Итоговая цена - - + + Текст-заполнитель — это текст, который имеет Текст-заполнитель — это текст, который имеет Текст-заполнитель — это текст, который имеет Текст-заполнитель — это текст, который имеет Текст-заполнитель - - - - - - {currencyFormatter.format(priceBeforeDiscounts / 100)} - - - {currencyFormatter.format(priceAfterDiscounts / 100)} - - - {notEnoughMoneyAmount > 0 && ( - + + + + + + {currencyFormatter.format(priceBeforeDiscounts / 100)} + + + {currencyFormatter.format(priceAfterDiscounts / 100)} + + + {notEnoughMoneyAmount > 0 && ( + Нехватает {currencyFormatter.format(notEnoughMoneyAmount / 100)} - - )} - - - - ); + + )} + + + + ) } diff --git a/src/components/UnderlinedButtonWithIcon.tsx b/src/components/UnderlinedButtonWithIcon.tsx index 727b89c..a8bbc0d 100644 --- a/src/components/UnderlinedButtonWithIcon.tsx +++ b/src/components/UnderlinedButtonWithIcon.tsx @@ -1,5 +1,5 @@ -import { Button, ButtonProps, SxProps, Theme, useMediaQuery, useTheme } from "@mui/material"; -import { MouseEventHandler, ReactNode } from "react"; +import { Button, ButtonProps, SxProps, Theme, useMediaQuery, useTheme } from "@mui/material" +import { MouseEventHandler, ReactNode } from "react" interface Props { @@ -11,35 +11,35 @@ interface Props { } export default function UnderlinedButtonWithIcon({ ButtonProps, icon, children, sx, onClick }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) - return ( - - ); + return ( + + ) } diff --git a/src/components/icons/CalendarIcon.tsx b/src/components/icons/CalendarIcon.tsx index 917e1ec..f7f1770 100644 --- a/src/components/icons/CalendarIcon.tsx +++ b/src/components/icons/CalendarIcon.tsx @@ -1,4 +1,4 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" interface Props { color: string; @@ -6,63 +6,63 @@ interface Props { } export default function CalendarIcon({ color, bgcolor }: Props) { - return ( - - - - - - - - - - - ); + return ( + + + + + + + + + + + ) } diff --git a/src/components/icons/CloseIcons.tsx b/src/components/icons/CloseIcons.tsx index fe34cc0..c8cb063 100644 --- a/src/components/icons/CloseIcons.tsx +++ b/src/components/icons/CloseIcons.tsx @@ -1,23 +1,23 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" export default function CloseIcon() { - return ( - - - - - - ); + return ( + + + + + + ) } diff --git a/src/components/icons/CloseSmallIcon.tsx b/src/components/icons/CloseSmallIcon.tsx index a043fba..09d8a25 100644 --- a/src/components/icons/CloseSmallIcon.tsx +++ b/src/components/icons/CloseSmallIcon.tsx @@ -1,21 +1,21 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" export default function CloseSmallIcon() { - return ( - - - - - - - ); + return ( + + + + + + + ) } \ No newline at end of file diff --git a/src/components/icons/CustomIcon.tsx b/src/components/icons/CustomIcon.tsx index 1d60803..23aeed6 100644 --- a/src/components/icons/CustomIcon.tsx +++ b/src/components/icons/CustomIcon.tsx @@ -1,4 +1,4 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" interface Props { color: string; @@ -6,55 +6,55 @@ interface Props { } export default function CustomIcon({ color, bgcolor }: Props) { - return ( - - - - - - - - - - ); + return ( + + + + + + + + + + ) } diff --git a/src/components/icons/ExpandIcon.tsx b/src/components/icons/ExpandIcon.tsx index 0f7c734..5f07de1 100644 --- a/src/components/icons/ExpandIcon.tsx +++ b/src/components/icons/ExpandIcon.tsx @@ -1,4 +1,4 @@ -import { useTheme , Box} from "@mui/material"; +import { useTheme , Box} from "@mui/material" interface Props { @@ -6,21 +6,21 @@ interface Props { } export default function ExpandIcon({ isExpanded }: Props) { - const theme = useTheme(); + const theme = useTheme() - return ( - - - - - - - ) + return ( + + + + + + + ) } diff --git a/src/components/icons/EyeIcon.tsx b/src/components/icons/EyeIcon.tsx index 6785638..ac73778 100644 --- a/src/components/icons/EyeIcon.tsx +++ b/src/components/icons/EyeIcon.tsx @@ -1,21 +1,21 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" export default function EyeIcon() { - return ( - - - - - - - ); + return ( + + + + + + + ) } \ No newline at end of file diff --git a/src/components/icons/File.tsx b/src/components/icons/File.tsx index 8895d10..c201c6b 100644 --- a/src/components/icons/File.tsx +++ b/src/components/icons/File.tsx @@ -1,4 +1,4 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" interface Props { color?: string; @@ -8,23 +8,23 @@ interface Props { } export default function CustomIcon() { - return ( - - - - - - - - - ); + > + + + + + + + + ) } diff --git a/src/components/icons/LogoutIcon.tsx b/src/components/icons/LogoutIcon.tsx index 719619e..8dcaab6 100644 --- a/src/components/icons/LogoutIcon.tsx +++ b/src/components/icons/LogoutIcon.tsx @@ -1,14 +1,14 @@ -import { useTheme } from "@mui/material"; +import { useTheme } from "@mui/material" export default function LogoutIcon() { - const theme = useTheme(); + const theme = useTheme() - return ( - - - - - - ); + return ( + + + + + + ) } diff --git a/src/components/icons/PaperClipIcon.tsx b/src/components/icons/PaperClipIcon.tsx index 178151d..79d4cf2 100644 --- a/src/components/icons/PaperClipIcon.tsx +++ b/src/components/icons/PaperClipIcon.tsx @@ -1,4 +1,4 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" interface Props { @@ -7,18 +7,18 @@ interface Props { export default function PaperClipIcon({ color = "#7E2AEA" }: Props) { - return ( - - - - - - ); + return ( + + + + + + ) } \ No newline at end of file diff --git a/src/components/icons/PieChartIcon.tsx b/src/components/icons/PieChartIcon.tsx index 2410782..603b058 100644 --- a/src/components/icons/PieChartIcon.tsx +++ b/src/components/icons/PieChartIcon.tsx @@ -1,4 +1,4 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" interface Props { @@ -8,25 +8,25 @@ interface Props { export default function PieChartIcon({ color, bgcolor }: Props) { - return ( - - - - - - - - - ); + return ( + + + + + + + + + ) } diff --git a/src/components/icons/SendIcon.tsx b/src/components/icons/SendIcon.tsx index cf6b345..6548d53 100644 --- a/src/components/icons/SendIcon.tsx +++ b/src/components/icons/SendIcon.tsx @@ -1,4 +1,4 @@ -import { CSSProperties } from "react"; +import { CSSProperties } from "react" interface Props { @@ -7,11 +7,11 @@ interface Props { export default function SendIcon({ style }: Props) { - return ( - - - - - - ); + return ( + + + + + + ) } \ No newline at end of file diff --git a/src/components/icons/UploadIcon.tsx b/src/components/icons/UploadIcon.tsx index 4adbbfa..286c916 100644 --- a/src/components/icons/UploadIcon.tsx +++ b/src/components/icons/UploadIcon.tsx @@ -1,22 +1,22 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" export default function SendIcon() { - return ( - - - - - - - - ); + return ( + + + + + + + + ) } \ No newline at end of file diff --git a/src/components/icons/WalletIcon.tsx b/src/components/icons/WalletIcon.tsx index 33981d3..fc7ea81 100644 --- a/src/components/icons/WalletIcon.tsx +++ b/src/components/icons/WalletIcon.tsx @@ -1,4 +1,4 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" interface Props { color: string; @@ -6,32 +6,32 @@ interface Props { } export default function SendIcon({ color, bgcolor }: Props) { - return ( - - - - - - ); + return ( + + + + + + ) } diff --git a/src/components/passwordInput.tsx b/src/components/passwordInput.tsx index a5d6c59..5161165 100644 --- a/src/components/passwordInput.tsx +++ b/src/components/passwordInput.tsx @@ -1,18 +1,18 @@ import { - FormControl, - IconButton, - InputLabel, - SxProps, - TextField, - TextFieldProps, - Theme, - useMediaQuery, - useTheme, -} from "@mui/material"; -import * as React from "react"; -import InputAdornment from "@mui/material/InputAdornment"; -import Visibility from "@mui/icons-material/Visibility"; -import VisibilityOff from "@mui/icons-material/VisibilityOff"; + FormControl, + IconButton, + InputLabel, + SxProps, + TextField, + TextFieldProps, + Theme, + useMediaQuery, + useTheme, +} from "@mui/material" +import * as React from "react" +import InputAdornment from "@mui/material/InputAdornment" +import Visibility from "@mui/icons-material/Visibility" +import VisibilityOff from "@mui/icons-material/VisibilityOff" interface Props { id: string; @@ -26,103 +26,103 @@ interface Props { } export default function PasswordInput({ - id, - label, - bold = false, - gap = "10px", - onChange, - TextfieldProps, - color, - FormInputSx, + id, + label, + bold = false, + gap = "10px", + onChange, + TextfieldProps, + color, + FormInputSx, }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) - const labelFont = upMd - ? bold - ? theme.typography.p1 - : { ...theme.typography.body1, fontWeight: 500 } - : theme.typography.body2; + const labelFont = upMd + ? bold + ? theme.typography.p1 + : { ...theme.typography.body1, fontWeight: 500 } + : theme.typography.body2 - const placeholderFont = upMd ? undefined : { fontWeight: 400, fontSize: "16px", lineHeight: "19px" }; + const placeholderFont = upMd ? undefined : { fontWeight: 400, fontSize: "16px", lineHeight: "19px" } - const [showPassword, setShowPassword] = React.useState(false); + const [showPassword, setShowPassword] = React.useState(false) - const handleClickShowPassword = () => setShowPassword((show) => !show); + const handleClickShowPassword = () => setShowPassword((show) => !show) - const handleMouseDownPassword = (event: React.MouseEvent) => { - event.preventDefault(); - }; + const handleMouseDownPassword = (event: React.MouseEvent) => { + event.preventDefault() + } - return ( - - - {label} - - - - {showPassword ? : } - - - ), - sx: { - padding: "0px", - border: "1px solid" + theme.palette.gray.main, - backgroundColor: color, - borderRadius: "8px", - height: "48px", - color: "black", - ...placeholderFont, - "& .MuiInputBase-input": { - boxSizing: "border-box", - height: "100%", - padding: "14px", - }, - }, - }} - onChange={onChange} - type={showPassword ? "text" : "password"} - /> - - ); + return ( + + + {label} + + + + {showPassword ? : } + + + ), + sx: { + padding: "0px", + border: "1px solid" + theme.palette.gray.main, + backgroundColor: color, + borderRadius: "8px", + height: "48px", + color: "black", + ...placeholderFont, + "& .MuiInputBase-input": { + boxSizing: "border-box", + height: "100%", + padding: "14px", + }, + }, + }} + onChange={onChange} + type={showPassword ? "text" : "password"} + /> + + ) } diff --git a/src/components/templCardPhoneLight.tsx b/src/components/templCardPhoneLight.tsx index 7257abf..a3d0164 100644 --- a/src/components/templCardPhoneLight.tsx +++ b/src/components/templCardPhoneLight.tsx @@ -1,56 +1,56 @@ -import { Box, Button, Typography, useMediaQuery, useTheme } from "@mui/material"; -import card1Image from "@root/assets/landing/card1.png"; +import { Box, Button, Typography, useMediaQuery, useTheme } from "@mui/material" +import card1Image from "@root/assets/landing/card1.png" export default function TemplCardPhoneLight() { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const isMobile = useMediaQuery(theme.breakpoints.down(600)); - return ( - - - - Шаблонизатор - + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const isMobile = useMediaQuery(theme.breakpoints.down(600)) + return ( + + + + Шаблонизатор + Текст-заполнитель — {isMobile &&
} это текст, который имеет некоторые характеристики реального письменного текста, но является -
+
- -
-
- ); + + + + ) } diff --git a/src/components/templCardPhonePink.tsx b/src/components/templCardPhonePink.tsx index 68e7e67..7889e8c 100644 --- a/src/components/templCardPhonePink.tsx +++ b/src/components/templCardPhonePink.tsx @@ -1,30 +1,30 @@ -import { Box, useMediaQuery, useTheme } from "@mui/material"; -import CardWithLink from "@components/CardWithLink"; -import card1Image from "@root/assets/landing/card1.png"; +import { Box, useMediaQuery, useTheme } from "@mui/material" +import CardWithLink from "@components/CardWithLink" +import card1Image from "@root/assets/landing/card1.png" export default function () { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) - return ( - - - - ); + return ( + + + + ) } diff --git a/src/components/wideTemplCard.tsx b/src/components/wideTemplCard.tsx index 65875bb..3011f22 100644 --- a/src/components/wideTemplCard.tsx +++ b/src/components/wideTemplCard.tsx @@ -1,7 +1,7 @@ -import { Box, Typography, SxProps, Theme, Button, useTheme, useMediaQuery } from "@mui/material"; -import cardImageBig from "@root/assets/landing/card1big.png"; -import { PenaLink } from "@frontend/kitui"; -import { Link as RouterLink } from "react-router-dom"; +import { Box, Typography, SxProps, Theme, Button, useTheme, useMediaQuery } from "@mui/material" +import cardImageBig from "@root/assets/landing/card1big.png" +import { PenaLink } from "@frontend/kitui" +import { Link as RouterLink } from "react-router-dom" interface Props { light?: boolean; @@ -11,46 +11,46 @@ interface Props { } export default function WideTemplCard({ light = true, sx, name="Шаблонизатор", desc="тект заполнитель это текст который имеет" }: Props) { - const theme = useTheme(); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); + const theme = useTheme() + const isTablet = useMediaQuery(theme.breakpoints.down(1000)) - return ( - - - {name} - - {desc} - - - - - ); + return ( + + + {name} + + {desc} + + + + + ) } diff --git a/src/constants/documentTypeMap.tsx b/src/constants/documentTypeMap.tsx index 4d9eeb0..6e93d8a 100644 --- a/src/constants/documentTypeMap.tsx +++ b/src/constants/documentTypeMap.tsx @@ -1,11 +1,11 @@ -import type { UserDocumentTypes } from "@root/model/user"; +import type { UserDocumentTypes } from "@root/model/user" export const DOCUMENT_TYPE_MAP: Record< "inn" | "rule" | "egrule" | "certificate", UserDocumentTypes > = { - inn: "ИНН", - rule: "Устав", - certificate: "Свидетельство о регистрации НКО", - egrule: "ИНН", -}; + inn: "ИНН", + rule: "Устав", + certificate: "Свидетельство о регистрации НКО", + egrule: "ИНН", +} diff --git a/src/index.tsx b/src/index.tsx index 4926aaa..b5bf5b6 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,119 +1,119 @@ -import React from "react"; -import ReactDOM from "react-dom/client"; -import { BrowserRouter, Navigate, Route, Routes, useLocation, useNavigate } from "react-router-dom"; -import { CssBaseline, ThemeProvider } from "@mui/material"; -import Faq from "./pages/Faq/Faq"; -import Wallet from "./pages/Wallet"; -import Payment from "./pages/Payment/Payment"; -import Support from "./pages/Support/Support"; -import AccountSettings from "./pages/AccountSettings/AccountSettings"; -import Landing from "./pages/Landing/Landing"; -import Tariffs from "./pages/Tariffs/Tariffs"; -import SigninDialog from "./pages/auth/Signin"; -import SignupDialog from "./pages/auth/Signup"; -import History from "./pages/History"; -import Cart from "./pages/Cart/Cart"; -import TariffPage from "./pages/Tariffs/TariffsPage"; -import SavedTariffs from "./pages/SavedTariffs"; -import PrivateRoute from "@root/utils/routes/ProtectedRoute"; -import reportWebVitals from "./reportWebVitals"; -import { SnackbarProvider, enqueueSnackbar } from "notistack"; -import "./index.css"; -import ProtectedLayout from "./components/ProtectedLayout"; -import { clearUserData, setUser, setUserAccount, useUserStore } from "./stores/user"; -import TariffConstructor from "./pages/TariffConstructor/TariffConstructor"; -import { clearAuthToken, getMessageFromFetchError, useUserAccountFetcher, useUserFetcher } from "@frontend/kitui"; -import { pdfjs } from "react-pdf"; -import { theme } from "./utils/theme"; +import React from "react" +import ReactDOM from "react-dom/client" +import { BrowserRouter, Navigate, Route, Routes, useLocation, useNavigate } from "react-router-dom" +import { CssBaseline, ThemeProvider } from "@mui/material" +import Faq from "./pages/Faq/Faq" +import Wallet from "./pages/Wallet" +import Payment from "./pages/Payment/Payment" +import Support from "./pages/Support/Support" +import AccountSettings from "./pages/AccountSettings/AccountSettings" +import Landing from "./pages/Landing/Landing" +import Tariffs from "./pages/Tariffs/Tariffs" +import SigninDialog from "./pages/auth/Signin" +import SignupDialog from "./pages/auth/Signup" +import History from "./pages/History" +import Cart from "./pages/Cart/Cart" +import TariffPage from "./pages/Tariffs/TariffsPage" +import SavedTariffs from "./pages/SavedTariffs" +import PrivateRoute from "@root/utils/routes/ProtectedRoute" +import reportWebVitals from "./reportWebVitals" +import { SnackbarProvider, enqueueSnackbar } from "notistack" +import "./index.css" +import ProtectedLayout from "./components/ProtectedLayout" +import { clearUserData, setUser, setUserAccount, useUserStore } from "./stores/user" +import TariffConstructor from "./pages/TariffConstructor/TariffConstructor" +import { clearAuthToken, getMessageFromFetchError, useUserAccountFetcher, useUserFetcher } from "@frontend/kitui" +import { pdfjs } from "react-pdf" +import { theme } from "./utils/theme" -pdfjs.GlobalWorkerOptions.workerSrc = new URL("pdfjs-dist/build/pdf.worker.min.js", import.meta.url).toString(); +pdfjs.GlobalWorkerOptions.workerSrc = new URL("pdfjs-dist/build/pdf.worker.min.js", import.meta.url).toString() const App = () => { - console.log("render app") - const location = useLocation(); - const userId = useUserStore((state) => state.userId); - const navigate = useNavigate(); + console.log("render app") + const location = useLocation() + const userId = useUserStore((state) => state.userId) + const navigate = useNavigate() - useUserFetcher({ - url: `https://hub.pena.digital/user/${userId}`, - userId, - onNewUser: setUser, - onError: (error) => { - const errorMessage = getMessageFromFetchError(error); - if (errorMessage) { - enqueueSnackbar(errorMessage); - clearUserData(); - clearAuthToken(); - } - }, - }); + useUserFetcher({ + url: `https://hub.pena.digital/user/${userId}`, + userId, + onNewUser: setUser, + onError: (error) => { + const errorMessage = getMessageFromFetchError(error) + if (errorMessage) { + enqueueSnackbar(errorMessage) + clearUserData() + clearAuthToken() + } + }, + }) - useUserAccountFetcher({ - url: "https://hub.pena.digital/customer/account", - userId, - onNewUserAccount: setUserAccount, - onError: (error) => { - const errorMessage = getMessageFromFetchError(error); - if (errorMessage) { - enqueueSnackbar(errorMessage); - clearUserData(); - clearAuthToken(); - navigate("/signin"); - } - }, - }); + useUserAccountFetcher({ + url: "https://hub.pena.digital/customer/account", + userId, + onNewUserAccount: setUserAccount, + onError: (error) => { + const errorMessage = getMessageFromFetchError(error) + if (errorMessage) { + enqueueSnackbar(errorMessage) + clearUserData() + clearAuthToken() + navigate("/signin") + } + }, + }) - if (location.state?.redirectTo) - return ; + if (location.state?.redirectTo) + return - return ( - <> - {location.state?.backgroundLocation && ( - - } /> - } /> - - )} - - } /> - } /> - } /> - }> - }> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - } /> - - - - - ); -}; + return ( + <> + {location.state?.backgroundLocation && ( + + } /> + } /> + + )} + + } /> + } /> + } /> + }> + }> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> + + + + + ) +} -const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement); +const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement) root.render( - // - - - - - - - - // -); + // + + + + + + + + // +) // If you want to start measuring performance in your app, pass a function // to log results (for example: reportWebVitals(console.log)) // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals -reportWebVitals(); +reportWebVitals() diff --git a/src/model/account.ts b/src/model/account.ts index f607534..07f7ee7 100644 --- a/src/model/account.ts +++ b/src/model/account.ts @@ -1,4 +1,4 @@ -import { UserName } from "@frontend/kitui"; +import { UserName } from "@frontend/kitui" export enum VerificationStatus { diff --git a/src/model/auth.ts b/src/model/auth.ts index 5918547..0050435 100644 --- a/src/model/auth.ts +++ b/src/model/auth.ts @@ -1,4 +1,4 @@ -import type { Attachment } from "@root/model/attachment"; +import type { Attachment } from "@root/model/attachment" export type File = { name: "inn" | "rule" | "egrule" | "certificate"; diff --git a/src/model/customTariffs.ts b/src/model/customTariffs.ts index 16265fe..cc054ab 100644 --- a/src/model/customTariffs.ts +++ b/src/model/customTariffs.ts @@ -1,5 +1,5 @@ -import { PrivilegeWithAmount } from "@frontend/kitui"; -import { PrivilegeWithoutPrice } from "./privilege"; +import { PrivilegeWithAmount } from "@frontend/kitui" +import { PrivilegeWithoutPrice } from "./privilege" type ServiceKey = string; diff --git a/src/model/discount.ts b/src/model/discount.ts index 0042d38..d3e386c 100644 --- a/src/model/discount.ts +++ b/src/model/discount.ts @@ -1,4 +1,4 @@ -import { Discount } from "@frontend/kitui"; +import { Discount } from "@frontend/kitui" export interface GetDiscountsResponse { diff --git a/src/model/privilege.ts b/src/model/privilege.ts index 47aa509..9f4aa27 100644 --- a/src/model/privilege.ts +++ b/src/model/privilege.ts @@ -1,4 +1,4 @@ -import { Privilege, PrivilegeWithAmount } from "@frontend/kitui"; +import { Privilege, PrivilegeWithAmount } from "@frontend/kitui" export type ServiceKeyToPrivilegesMap = Record; diff --git a/src/model/tariff.ts b/src/model/tariff.ts index 3085dad..e234108 100644 --- a/src/model/tariff.ts +++ b/src/model/tariff.ts @@ -1,4 +1,4 @@ -import { Tariff } from "@frontend/kitui"; +import { Tariff } from "@frontend/kitui" export interface GetTariffsResponse { diff --git a/src/pages/AccountSettings/AccountSettings.tsx b/src/pages/AccountSettings/AccountSettings.tsx index 3d7e1c6..4558df4 100644 --- a/src/pages/AccountSettings/AccountSettings.tsx +++ b/src/pages/AccountSettings/AccountSettings.tsx @@ -1,180 +1,180 @@ -import { useEffect } from "react"; -import { Box, Button, SxProps, Theme, Typography, useMediaQuery, useTheme } from "@mui/material"; -import InputTextfield from "@components/InputTextfield"; -import PasswordInput from "@components/passwordInput"; -import UserFields from "./UserFields"; -import SectionWrapper from "@components/SectionWrapper"; -import { openDocumentsDialog, sendUserData, setSettingsField, useUserStore } from "@root/stores/user"; -import UnderlinedButtonWithIcon from "@root/components/UnderlinedButtonWithIcon"; -import UploadIcon from "@root/components/icons/UploadIcon"; -import DocumentsDialog from "./DocumentsDialog/DocumentsDialog"; -import EyeIcon from "@root/components/icons/EyeIcon"; -import { cardShadow } from "@root/utils/theme"; -import { getMessageFromFetchError } from "@frontend/kitui"; -import { enqueueSnackbar } from "notistack"; -import { VerificationStatus } from "@root/model/account"; -import { verify } from "./helper"; -import { withErrorBoundary } from "react-error-boundary"; -import { handleComponentError } from "@root/utils/handleComponentError"; +import { useEffect } from "react" +import { Box, Button, SxProps, Theme, Typography, useMediaQuery, useTheme } from "@mui/material" +import InputTextfield from "@components/InputTextfield" +import PasswordInput from "@components/passwordInput" +import UserFields from "./UserFields" +import SectionWrapper from "@components/SectionWrapper" +import { openDocumentsDialog, sendUserData, setSettingsField, useUserStore } from "@root/stores/user" +import UnderlinedButtonWithIcon from "@root/components/UnderlinedButtonWithIcon" +import UploadIcon from "@root/components/icons/UploadIcon" +import DocumentsDialog from "./DocumentsDialog/DocumentsDialog" +import EyeIcon from "@root/components/icons/EyeIcon" +import { cardShadow } from "@root/utils/theme" +import { getMessageFromFetchError } from "@frontend/kitui" +import { enqueueSnackbar } from "notistack" +import { VerificationStatus } from "@root/model/account" +import { verify } from "./helper" +import { withErrorBoundary } from "react-error-boundary" +import { handleComponentError } from "@root/utils/handleComponentError" function AccountSettings() { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const upSm = useMediaQuery(theme.breakpoints.up("sm")); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); - const isMobile = useMediaQuery(theme.breakpoints.down(600)); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const upSm = useMediaQuery(theme.breakpoints.up("sm")) + const isTablet = useMediaQuery(theme.breakpoints.down(1000)) + const isMobile = useMediaQuery(theme.breakpoints.down(600)) - const fields = useUserStore((state) => state.settingsFields); - const verificationStatus = useUserStore((state) => state.verificationStatus); - const verificationType = useUserStore((state) => state.verificationType); - const comment = useUserStore((state) => state.comment); - const userId = useUserStore((state) => state.userId) ?? ""; + const fields = useUserStore((state) => state.settingsFields) + const verificationStatus = useUserStore((state) => state.verificationStatus) + const verificationType = useUserStore((state) => state.verificationType) + const comment = useUserStore((state) => state.comment) + const userId = useUserStore((state) => state.userId) ?? "" - useEffect(() => { - verify(userId); - }, []); + useEffect(() => { + verify(userId) + }, []) - const textFieldProps = { - gap: upMd ? "16px" : "10px", - color: "#F2F3F7", - bold: true, - }; + const textFieldProps = { + gap: upMd ? "16px" : "10px", + color: "#F2F3F7", + bold: true, + } - function handleSendDataClick() { - sendUserData() - .then(() => { - enqueueSnackbar("Информация обновлена"); - }) - .catch((error) => { - const message = getMessageFromFetchError(error); - if (message) enqueueSnackbar(message); - }); - } + function handleSendDataClick() { + sendUserData() + .then(() => { + enqueueSnackbar("Информация обновлена") + }) + .catch((error) => { + const message = getMessageFromFetchError(error) + if (message) enqueueSnackbar(message) + }) + } - return ( - - - + return ( + + + Настройки аккаунта - - - - - - Статус - - {verificationStatus === VerificationStatus.NOT_VERIFICATED && ( - <> - } - sx={{ mt: "55px" }} - ButtonProps={{ - onClick: () => openDocumentsDialog("juridical"), - }} - > + + + + + + Статус + + {verificationStatus === VerificationStatus.NOT_VERIFICATED && ( + <> + } + sx={{ mt: "55px" }} + ButtonProps={{ + onClick: () => openDocumentsDialog("juridical"), + }} + > Загрузить документы для юр лиц - - } - sx={{ mt: "15px" }} - ButtonProps={{ - onClick: () => openDocumentsDialog("nko"), - }} - > + + } + sx={{ mt: "15px" }} + ButtonProps={{ + onClick: () => openDocumentsDialog("nko"), + }} + > Загрузить документы для НКО - - - )} - {verificationStatus === VerificationStatus.VERIFICATED && ( - } - sx={{ mt: "55px" }} - ButtonProps={{ - onClick: () => openDocumentsDialog(verificationType), - }} - > + + + )} + {verificationStatus === VerificationStatus.VERIFICATED && ( + } + sx={{ mt: "55px" }} + ButtonProps={{ + onClick: () => openDocumentsDialog(verificationType), + }} + > Посмотреть свою верификацию - - )} - {comment &&

{comment}

} -
-
- -
-
- ); + + + + ) } export default withErrorBoundary(AccountSettings, { - fallback: Ошибка при отображении настроек аккаунта, - onError: handleComponentError, + fallback: Ошибка при отображении настроек аккаунта, + onError: handleComponentError, }) const verificationStatusData: Record = { - verificated: { text: "Верификация пройдена", color: "#0D9F00" }, - waiting: { text: "В ожидании верификации", color: "#F18956" }, - notVerificated: { text: "Не верифицирован", color: "#E02C2C" }, -}; + verificated: { text: "Верификация пройдена", color: "#0D9F00" }, + waiting: { text: "В ожидании верификации", color: "#F18956" }, + notVerificated: { text: "Не верифицирован", color: "#E02C2C" }, +} function VerificationIndicator({ - verificationStatus, - sx, + verificationStatus, + sx, }: { verificationStatus: VerificationStatus; sx?: SxProps; }) { - return ( - - {verificationStatusData[verificationStatus].text} - - ); + return ( + + {verificationStatusData[verificationStatus].text} + + ) } \ No newline at end of file diff --git a/src/pages/AccountSettings/DocumentsDialog/DocumentItem.tsx b/src/pages/AccountSettings/DocumentsDialog/DocumentItem.tsx index f8fd344..191aae6 100644 --- a/src/pages/AccountSettings/DocumentsDialog/DocumentItem.tsx +++ b/src/pages/AccountSettings/DocumentsDialog/DocumentItem.tsx @@ -1,8 +1,8 @@ -import axios from "axios"; -import { Box, SxProps, Theme, Typography, useTheme } from "@mui/material"; -import { Document, Page } from "react-pdf"; -import { Buffer } from "buffer"; -import { downloadFileToDevice } from "@root/utils/downloadFileToDevice"; +import axios from "axios" +import { Box, SxProps, Theme, Typography, useTheme } from "@mui/material" +import { Document, Page } from "react-pdf" +import { Buffer } from "buffer" +import { downloadFileToDevice } from "@root/utils/downloadFileToDevice" interface Props { text: string; @@ -11,62 +11,62 @@ interface Props { } export default function DocumentItem({ text, documentUrl = "", sx }: Props) { - const theme = useTheme(); + const theme = useTheme() - const downloadFile = async () => { - const { data } = await axios.get(documentUrl, { - responseType: "arraybuffer", - }); + const downloadFile = async () => { + const { data } = await axios.get(documentUrl, { + responseType: "arraybuffer", + }) - if (!data) { - return; - } + if (!data) { + return + } - downloadFileToDevice( - `${documentUrl.split("/").pop()?.split(".")?.[0] || "document"}.pdf`, - Buffer.from(data) - ); + downloadFileToDevice( + `${documentUrl.split("/").pop()?.split(".")?.[0] || "document"}.pdf`, + Buffer.from(data) + ) - return; - }; + return + } - return ( - - - {text} - - {documentUrl && ( - <> - - {documentUrl.split("/").pop()?.split(".")?.[0]} - - - - - - )} - - ); + return ( + + + {text} + + {documentUrl && ( + <> + + {documentUrl.split("/").pop()?.split(".")?.[0]} + + + + + + )} + + ) } diff --git a/src/pages/AccountSettings/DocumentsDialog/DocumentUploadItem.tsx b/src/pages/AccountSettings/DocumentsDialog/DocumentUploadItem.tsx index 7796321..bf39d91 100644 --- a/src/pages/AccountSettings/DocumentsDialog/DocumentUploadItem.tsx +++ b/src/pages/AccountSettings/DocumentsDialog/DocumentUploadItem.tsx @@ -1,16 +1,16 @@ -import { ChangeEvent, useRef } from "react"; -import axios from "axios"; -import { Document, Page, pdfjs } from "react-pdf"; -import { Box, SxProps, Theme, Typography } from "@mui/material"; -import { Buffer } from "buffer"; +import { ChangeEvent, useRef } from "react" +import axios from "axios" +import { Document, Page, pdfjs } from "react-pdf" +import { Box, SxProps, Theme, Typography } from "@mui/material" +import { Buffer } from "buffer" -import UnderlinedButtonWithIcon from "@root/components/UnderlinedButtonWithIcon"; -import PaperClipIcon from "@root/components/icons/PaperClipIcon"; +import UnderlinedButtonWithIcon from "@root/components/UnderlinedButtonWithIcon" +import PaperClipIcon from "@root/components/icons/PaperClipIcon" -import { UserDocument } from "@root/model/user"; +import { UserDocument } from "@root/model/user" -import { readFile } from "@root/utils/readFile"; -import { downloadFileToDevice } from "@root/utils/downloadFileToDevice"; +import { readFile } from "@root/utils/readFile" +import { downloadFileToDevice } from "@root/utils/downloadFileToDevice" interface Props { text: string; @@ -22,89 +22,89 @@ interface Props { } pdfjs.GlobalWorkerOptions.workerSrc = new URL( - "pdfjs-dist/build/pdf.worker.min.js", - import.meta.url -).toString(); + "pdfjs-dist/build/pdf.worker.min.js", + import.meta.url +).toString() export default function DocumentUploadItem({ - text, - document, - documentUrl = "", - onFileChange, - sx, - accept = "image/*", + text, + document, + documentUrl = "", + onFileChange, + sx, + accept = "image/*", }: Props) { - const fileInputRef = useRef(null); + const fileInputRef = useRef(null) - function handleChooseFileClick() { - fileInputRef.current?.click(); - } + function handleChooseFileClick() { + fileInputRef.current?.click() + } - const downloadFile = async () => { - if (!document.file && documentUrl) { - const { data } = await axios.get(documentUrl, { - responseType: "arraybuffer", - }); + const downloadFile = async () => { + if (!document.file && documentUrl) { + const { data } = await axios.get(documentUrl, { + responseType: "arraybuffer", + }) - if (!data) { - return; - } + if (!data) { + return + } - downloadFileToDevice("document.pdf", Buffer.from(data)); + downloadFileToDevice("document.pdf", Buffer.from(data)) - return; - } + return + } - if (document.file) { - const fileArrayBuffer = await readFile(document.file, "array"); + if (document.file) { + const fileArrayBuffer = await readFile(document.file, "array") - downloadFileToDevice(document.file.name, Buffer.from(fileArrayBuffer)); - } - }; + downloadFileToDevice(document.file.name, Buffer.from(fileArrayBuffer)) + } + } - return ( - - - {text} - - } - onClick={handleChooseFileClick} - > - {document.file ? document.file.name : "Выберите файл"} - - - - - - - ); + return ( + + + {text} + + } + onClick={handleChooseFileClick} + > + {document.file ? document.file.name : "Выберите файл"} + + + + + + + ) } diff --git a/src/pages/AccountSettings/DocumentsDialog/DocumentsDialog.tsx b/src/pages/AccountSettings/DocumentsDialog/DocumentsDialog.tsx index 6ada2f0..8e2eada 100644 --- a/src/pages/AccountSettings/DocumentsDialog/DocumentsDialog.tsx +++ b/src/pages/AccountSettings/DocumentsDialog/DocumentsDialog.tsx @@ -1,17 +1,17 @@ -import { useUserStore } from "@root/stores/user"; -import NkoDocumentsDialog from "./NkoDocumentsDialog"; -import JuridicalDocumentsDialog from "./JuridicalDocumentsDialog"; +import { useUserStore } from "@root/stores/user" +import NkoDocumentsDialog from "./NkoDocumentsDialog" +import JuridicalDocumentsDialog from "./JuridicalDocumentsDialog" export default function DocumentsDialog() { - switch(useUserStore(state => state.dialogType)) { - case 'juridical': - return + switch(useUserStore(state => state.dialogType)) { + case "juridical": + return - case "nko": - return + case "nko": + return - default: - return <> - } + default: + return <> + } } \ No newline at end of file diff --git a/src/pages/AccountSettings/DocumentsDialog/JuridicalDocumentsDialog.tsx b/src/pages/AccountSettings/DocumentsDialog/JuridicalDocumentsDialog.tsx index c649436..0d6046e 100644 --- a/src/pages/AccountSettings/DocumentsDialog/JuridicalDocumentsDialog.tsx +++ b/src/pages/AccountSettings/DocumentsDialog/JuridicalDocumentsDialog.tsx @@ -1,227 +1,227 @@ -import { Box, Button, Dialog, IconButton, Typography } from "@mui/material"; -import { enqueueSnackbar } from "notistack"; -import CloseSmallIcon from "@root/components/icons/CloseSmallIcon"; +import { Box, Button, Dialog, IconButton, Typography } from "@mui/material" +import { enqueueSnackbar } from "notistack" +import CloseSmallIcon from "@root/components/icons/CloseSmallIcon" import { - closeDocumentsDialog, - setDocument, - useUserStore, -} from "@root/stores/user"; -import DocumentUploadItem from "./DocumentUploadItem"; -import DocumentItem from "./DocumentItem"; -import { VerificationStatus } from "@root/model/account"; -import { sendDocuments, updateDocuments } from "@root/api/verification"; -import { readFile } from "@root/utils/readFile"; -import { deleteEmptyKeys } from "@root/utils/deleteEmptyKeys"; -import { verify } from "../helper"; -import { useState } from "react"; -import { theme } from "@root/utils/theme"; + closeDocumentsDialog, + setDocument, + useUserStore, +} from "@root/stores/user" +import DocumentUploadItem from "./DocumentUploadItem" +import DocumentItem from "./DocumentItem" +import { VerificationStatus } from "@root/model/account" +import { sendDocuments, updateDocuments } from "@root/api/verification" +import { readFile } from "@root/utils/readFile" +import { deleteEmptyKeys } from "@root/utils/deleteEmptyKeys" +import { verify } from "../helper" +import { useState } from "react" +import { theme } from "@root/utils/theme" const dialogContainerStyle = { - height: "100%", - overflowY: "scroll", - "::-webkit-scrollbar": { - display: "none", - }, -}; + height: "100%", + overflowY: "scroll", + "::-webkit-scrollbar": { + display: "none", + }, +} export default function JuridicalDocumentsDialog() { - const isOpen = useUserStore((state) => state.isDocumentsDialogOpen); - const verificationStatus = useUserStore((state) => state.verificationStatus); - const documents = useUserStore((state) => state.documents);//загруженные юзером файлы - const documentsUrl = useUserStore((state) => state.documentsUrl);//ссылки с бекенда - const userId = useUserStore((state) => state.userId) ?? ""; + const isOpen = useUserStore((state) => state.isDocumentsDialogOpen) + const verificationStatus = useUserStore((state) => state.verificationStatus) + const documents = useUserStore((state) => state.documents)//загруженные юзером файлы + const documentsUrl = useUserStore((state) => state.documentsUrl)//ссылки с бекенда + const userId = useUserStore((state) => state.userId) ?? "" - const sendUploadedDocuments = async () => { + const sendUploadedDocuments = async () => { - if (documents["ИНН"].file && documents["Устав"].file && !documentsUrl["ИНН"] && !documentsUrl["Устав"]) { - closeDocumentsDialog(); - //Пользователь заполнил все поля и на беке пусто - const inn = await readFile(documents["ИНН"].file, "binary"); - const rule = await readFile(documents["Устав"].file, "binary"); + if (documents["ИНН"].file && documents["Устав"].file && !documentsUrl["ИНН"] && !documentsUrl["Устав"]) { + closeDocumentsDialog() + //Пользователь заполнил все поля и на беке пусто + const inn = await readFile(documents["ИНН"].file, "binary") + const rule = await readFile(documents["Устав"].file, "binary") - const [_, sendDocumentsError] = await sendDocuments({ - status: "org", - inn, - rule, - }); + const [_, sendDocumentsError] = await sendDocuments({ + status: "org", + inn, + rule, + }) - if (sendDocumentsError) { - enqueueSnackbar(sendDocumentsError); - return; - } - if (_ === "OK") { - enqueueSnackbar("Информация доставлена") - } + if (sendDocumentsError) { + enqueueSnackbar(sendDocumentsError) + return + } + if (_ === "OK") { + enqueueSnackbar("Информация доставлена") + } - setDocument("ИНН", null); - setDocument("Устав", null); + setDocument("ИНН", null) + setDocument("Устав", null) - await verify(userId); - } else { //Пользователь заполнил не все, или на беке что-то есть - if ((documents["ИНН"].file || documents["Устав"].file) && (documentsUrl["ИНН"] || documentsUrl["Устав"])) { //минимум 1 поле заполнено на фронте и минимум 1 поле на беке записано - closeDocumentsDialog(); - const inn = documents["ИНН"].file - ? await readFile(documents["ИНН"].file, "binary") - : undefined; - const rule = documents["Устав"].file - ? await readFile(documents["Устав"].file, "binary") - : undefined; + await verify(userId) + } else { //Пользователь заполнил не все, или на беке что-то есть + if ((documents["ИНН"].file || documents["Устав"].file) && (documentsUrl["ИНН"] || documentsUrl["Устав"])) { //минимум 1 поле заполнено на фронте и минимум 1 поле на беке записано + closeDocumentsDialog() + const inn = documents["ИНН"].file + ? await readFile(documents["ИНН"].file, "binary") + : undefined + const rule = documents["Устав"].file + ? await readFile(documents["Устав"].file, "binary") + : undefined - const [_, updateDocumentsError] = await updateDocuments( - deleteEmptyKeys({ - status: "org", - inn, - rule, - }) - ); + const [_, updateDocumentsError] = await updateDocuments( + deleteEmptyKeys({ + status: "org", + inn, + rule, + }) + ) - if (updateDocumentsError) { - enqueueSnackbar(updateDocumentsError); + if (updateDocumentsError) { + enqueueSnackbar(updateDocumentsError) - return; - } - if (_ === "OK") { - enqueueSnackbar("Информация доставлена") - } + return + } + if (_ === "OK") { + enqueueSnackbar("Информация доставлена") + } - setDocument("ИНН", null); - setDocument("Устав", null); + setDocument("ИНН", null) + setDocument("Устав", null) - await verify(userId); - } - } - }; + await verify(userId) + } + } + } - const disbutt = () => { - if (documents["ИНН"].file && documents["Устав"].file && !documentsUrl["ИНН"] && !documentsUrl["Устав"]) { //post - //все поля заполнены и на беке пусто - return false - } else {//patch - if (documents["ИНН"].file || documents["Устав"].file) { - //минимум одно поле заполнено - return false - } - return true - } - } + const disbutt = () => { + if (documents["ИНН"].file && documents["Устав"].file && !documentsUrl["ИНН"] && !documentsUrl["Устав"]) { //post + //все поля заполнены и на беке пусто + return false + } else {//patch + if (documents["ИНН"].file || documents["Устав"].file) { + //минимум одно поле заполнено + return false + } + return true + } + } - const documentElements = + const documentElements = verificationStatus === VerificationStatus.VERIFICATED ? ( - <> - - - + <> + + + ) : ( - <> - setDocument("ИНН", e.target?.files?.[0] || null)} - /> - - setDocument("Устав", e.target?.files?.[0] || null) - } - /> - - ); + <> + setDocument("ИНН", e.target?.files?.[0] || null)} + /> + + setDocument("Устав", e.target?.files?.[0] || null) + } + /> + + ) - return ( - - - - - - - {verificationStatus === VerificationStatus.VERIFICATED - ? "Ваши документы" - : "Загрузите документы"} - - + return ( + + + + + + + {verificationStatus === VerificationStatus.VERIFICATED + ? "Ваши документы" + : "Загрузите документы"} + + для верификации юридических лиц в формате PDF - - {Boolean(!documentsUrl["ИНН"] && !documentsUrl["Устав"]) && + + {Boolean(!documentsUrl["ИНН"] && !documentsUrl["Устав"]) && Пожалуйста, заполните все поля! - } + } - - - {documentElements} - - - - {verificationStatus === VerificationStatus.NOT_VERIFICATED && ( - - )} - - ); + + )} + + ) } diff --git a/src/pages/AccountSettings/DocumentsDialog/NkoDocumentsDialog.tsx b/src/pages/AccountSettings/DocumentsDialog/NkoDocumentsDialog.tsx index 98ab7b0..810f68f 100644 --- a/src/pages/AccountSettings/DocumentsDialog/NkoDocumentsDialog.tsx +++ b/src/pages/AccountSettings/DocumentsDialog/NkoDocumentsDialog.tsx @@ -1,263 +1,263 @@ -import { Box, Button, Dialog, IconButton, Typography } from "@mui/material"; -import { enqueueSnackbar } from "notistack"; -import CloseSmallIcon from "@root/components/icons/CloseSmallIcon"; +import { Box, Button, Dialog, IconButton, Typography } from "@mui/material" +import { enqueueSnackbar } from "notistack" +import CloseSmallIcon from "@root/components/icons/CloseSmallIcon" import { - closeDocumentsDialog, - setDocument, - useUserStore, -} from "@root/stores/user"; -import DocumentUploadItem from "./DocumentUploadItem"; -import DocumentItem from "./DocumentItem"; -import { verify } from "../helper"; -import { VerificationStatus } from "@root/model/account"; -import { sendDocuments, updateDocuments } from "@root/api/verification"; -import { readFile } from "@root/utils/readFile"; -import { deleteEmptyKeys } from "@root/utils/deleteEmptyKeys"; -import { useState } from "react"; -import { theme } from "@root/utils/theme"; + closeDocumentsDialog, + setDocument, + useUserStore, +} from "@root/stores/user" +import DocumentUploadItem from "./DocumentUploadItem" +import DocumentItem from "./DocumentItem" +import { verify } from "../helper" +import { VerificationStatus } from "@root/model/account" +import { sendDocuments, updateDocuments } from "@root/api/verification" +import { readFile } from "@root/utils/readFile" +import { deleteEmptyKeys } from "@root/utils/deleteEmptyKeys" +import { useState } from "react" +import { theme } from "@root/utils/theme" const dialogContainerStyle = { - height: "100%", - overflowY: "scroll", - "::-webkit-scrollbar": { - display: "none", - }, -}; + height: "100%", + overflowY: "scroll", + "::-webkit-scrollbar": { + display: "none", + }, +} export default function NkoDocumentsDialog() { - const isOpen = useUserStore((state) => state.isDocumentsDialogOpen); - const verificationStatus = useUserStore((state) => state.verificationStatus); - const documents = useUserStore((state) => state.documents); - const documentsUrl = useUserStore((state) => state.documentsUrl); - const userId = useUserStore((state) => state.userId) ?? ""; + const isOpen = useUserStore((state) => state.isDocumentsDialogOpen) + const verificationStatus = useUserStore((state) => state.verificationStatus) + const documents = useUserStore((state) => state.documents) + const documentsUrl = useUserStore((state) => state.documentsUrl) + const userId = useUserStore((state) => state.userId) ?? "" - const sendUploadedDocuments = async () => { - if ( - documents["ИНН"].file && + const sendUploadedDocuments = async () => { + if ( + documents["ИНН"].file && documents["Устав"].file && documents["Свидетельство о регистрации НКО"].file && !documentsUrl["ИНН"] && !documentsUrl["Устав"] && !documentsUrl["Свидетельство о регистрации НКО"] - ) { - closeDocumentsDialog(); - //Пользователь заполнил все поля и на беке пусто - const inn = await readFile(documents["ИНН"].file, "binary"); - const rule = await readFile(documents["Устав"].file, "binary"); - const certificate = await readFile( - documents["Свидетельство о регистрации НКО"].file, - "binary" - ); + ) { + closeDocumentsDialog() + //Пользователь заполнил все поля и на беке пусто + const inn = await readFile(documents["ИНН"].file, "binary") + const rule = await readFile(documents["Устав"].file, "binary") + const certificate = await readFile( + documents["Свидетельство о регистрации НКО"].file, + "binary" + ) - const [_, sendDocumentsError] = await sendDocuments({ - status: "nko", - inn, - rule, - certificate, - }); + const [_, sendDocumentsError] = await sendDocuments({ + status: "nko", + inn, + rule, + certificate, + }) - if (sendDocumentsError) { - enqueueSnackbar(sendDocumentsError); + if (sendDocumentsError) { + enqueueSnackbar(sendDocumentsError) - return; - } - if (_ === "OK") { - enqueueSnackbar("Информация доставлена") - } + return + } + if (_ === "OK") { + enqueueSnackbar("Информация доставлена") + } - setDocument("ИНН", null); - setDocument("Устав", null); - setDocument("Свидетельство о регистрации НКО", null); + setDocument("ИНН", null) + setDocument("Устав", null) + setDocument("Свидетельство о регистрации НКО", null) - await verify(userId); - } else { //Пользователь заполнил не все, или на беке что-то есть - if ((documents["ИНН"].file || documents["Устав"].file || documents["Свидетельство о регистрации НКО"].file) && (documentsUrl["ИНН"] || documentsUrl["Устав"] || documentsUrl["Свидетельство о регистрации НКО"])) { //минимум 1 поле заполнено на фронте и минимум 1 поле на беке записано - closeDocumentsDialog(); - const inn = documents["ИНН"].file - ? await readFile(documents["ИНН"].file, "binary") - : undefined; - const rule = documents["Устав"].file - ? await readFile(documents["Устав"].file, "binary") - : undefined; - const certificate = documents["Свидетельство о регистрации НКО"].file - ? await readFile( - documents["Свидетельство о регистрации НКО"].file, - "binary" - ) - : undefined; + await verify(userId) + } else { //Пользователь заполнил не все, или на беке что-то есть + if ((documents["ИНН"].file || documents["Устав"].file || documents["Свидетельство о регистрации НКО"].file) && (documentsUrl["ИНН"] || documentsUrl["Устав"] || documentsUrl["Свидетельство о регистрации НКО"])) { //минимум 1 поле заполнено на фронте и минимум 1 поле на беке записано + closeDocumentsDialog() + const inn = documents["ИНН"].file + ? await readFile(documents["ИНН"].file, "binary") + : undefined + const rule = documents["Устав"].file + ? await readFile(documents["Устав"].file, "binary") + : undefined + const certificate = documents["Свидетельство о регистрации НКО"].file + ? await readFile( + documents["Свидетельство о регистрации НКО"].file, + "binary" + ) + : undefined - const [_, updateDocumentsError] = await updateDocuments( - deleteEmptyKeys({ - status: "org", - inn, - rule, - certificate, - }) - ); + const [_, updateDocumentsError] = await updateDocuments( + deleteEmptyKeys({ + status: "org", + inn, + rule, + certificate, + }) + ) - if (updateDocumentsError) { - enqueueSnackbar(updateDocumentsError); + if (updateDocumentsError) { + enqueueSnackbar(updateDocumentsError) - return; - } - if (_ === "OK") { - enqueueSnackbar("Информация доставлена") - } + return + } + if (_ === "OK") { + enqueueSnackbar("Информация доставлена") + } - setDocument("ИНН", null); - setDocument("Устав", null); - setDocument("Свидетельство о регистрации НКО", null); + setDocument("ИНН", null) + setDocument("Устав", null) + setDocument("Свидетельство о регистрации НКО", null) - await verify(userId); - } - } + await verify(userId) + } + } - }; + } - const disbutt = () => { - if (documents["ИНН"].file && documents["Устав"].file && documents["Свидетельство о регистрации НКО"].file && !documentsUrl["ИНН"] && !documentsUrl["Устав"] && !documentsUrl["Свидетельство о регистрации НКО"]) { //post - //все поля заполнены и на беке пусто - return false - } else {//patch - if (documents["ИНН"].file || documents["Устав"].file || documents["Свидетельство о регистрации НКО"].file ) { - //минимум одно поле заполнено - return false - } - return true - } - } + const disbutt = () => { + if (documents["ИНН"].file && documents["Устав"].file && documents["Свидетельство о регистрации НКО"].file && !documentsUrl["ИНН"] && !documentsUrl["Устав"] && !documentsUrl["Свидетельство о регистрации НКО"]) { //post + //все поля заполнены и на беке пусто + return false + } else {//patch + if (documents["ИНН"].file || documents["Устав"].file || documents["Свидетельство о регистрации НКО"].file ) { + //минимум одно поле заполнено + return false + } + return true + } + } - const documentElements = + const documentElements = verificationStatus === VerificationStatus.VERIFICATED ? ( - <> - - - - + <> + + + + ) : ( - <> - - setDocument( - "Свидетельство о регистрации НКО", - e.target?.files?.[0] || null - ) - } - /> - setDocument("ИНН", e.target?.files?.[0] || null)} - /> - - setDocument("Устав", e.target?.files?.[0] || null) - } - /> - - ); + <> + + setDocument( + "Свидетельство о регистрации НКО", + e.target?.files?.[0] || null + ) + } + /> + setDocument("ИНН", e.target?.files?.[0] || null)} + /> + + setDocument("Устав", e.target?.files?.[0] || null) + } + /> + + ) - return ( - - - - - - - {verificationStatus === VerificationStatus.VERIFICATED - ? "Ваши документы" - : "Загрузите документы"} - - + return ( + + + + + + + {verificationStatus === VerificationStatus.VERIFICATED + ? "Ваши документы" + : "Загрузите документы"} + + для верификации НКО в формате PDF - - {Boolean(!documentsUrl["ИНН"] && !documentsUrl["Устав"] && !documentsUrl["Свидетельство о регистрации НКО"]) && + + {Boolean(!documentsUrl["ИНН"] && !documentsUrl["Устав"] && !documentsUrl["Свидетельство о регистрации НКО"]) && Пожалуйста, заполните все поля! - } - - - {documentElements} - - - - {verificationStatus === VerificationStatus.NOT_VERIFICATED && ( - - )} - <> - - ); + + )} + <> + + ) } \ No newline at end of file diff --git a/src/pages/AccountSettings/UserFields.tsx b/src/pages/AccountSettings/UserFields.tsx index 2d29689..08f8ba0 100644 --- a/src/pages/AccountSettings/UserFields.tsx +++ b/src/pages/AccountSettings/UserFields.tsx @@ -1,121 +1,121 @@ -import { Box, useMediaQuery, useTheme } from "@mui/material"; -import InputTextfield from "@components/InputTextfield"; -import PasswordInput from "@components/passwordInput"; -import { setSettingsField, useUserStore } from "@root/stores/user"; +import { Box, useMediaQuery, useTheme } from "@mui/material" +import InputTextfield from "@components/InputTextfield" +import PasswordInput from "@components/passwordInput" +import { setSettingsField, useUserStore } from "@root/stores/user" export default function UserFields () { - const theme = useTheme(); - const upSm = useMediaQuery(theme.breakpoints.up("sm")); - const upMd = useMediaQuery(theme.breakpoints.up("md")); + const theme = useTheme() + const upSm = useMediaQuery(theme.breakpoints.up("sm")) + const upMd = useMediaQuery(theme.breakpoints.up("md")) - const fields = useUserStore((state) => state.settingsFields); + const fields = useUserStore((state) => state.settingsFields) - console.log("fields") + console.log("fields") - const textFieldProps = { - gap: upMd ? "16px" : "10px", - color: "#F2F3F7", - bold: true, - }; + const textFieldProps = { + gap: upMd ? "16px" : "10px", + color: "#F2F3F7", + bold: true, + } - return( - - setSettingsField("firstname", e.target.value)} - id="firstname" - label="Имя" - {...textFieldProps} - /> - setSettingsField("secondname", e.target.value)} - id="secondname" - label="Фамилия" - {...textFieldProps} - /> - setSettingsField("middlename", e.target.value)} - id="middlename" - label="Отчество" - {...textFieldProps} - /> - setSettingsField("orgname", e.target.value)} - id="orgname" - label="Название компании" - {...textFieldProps} - /> - setSettingsField("email", e.target.value)} - id="email" - label="E-mail" - {...textFieldProps} - /> - setSettingsField("phoneNumber", e.target.value)} - id="phoneNumber" - label="Телефон" - {...textFieldProps} - /> - setSettingsField("password", e.target.value)} - id="password" - label="Пароль" - {...textFieldProps} - /> - - ) + return( + + setSettingsField("firstname", e.target.value)} + id="firstname" + label="Имя" + {...textFieldProps} + /> + setSettingsField("secondname", e.target.value)} + id="secondname" + label="Фамилия" + {...textFieldProps} + /> + setSettingsField("middlename", e.target.value)} + id="middlename" + label="Отчество" + {...textFieldProps} + /> + setSettingsField("orgname", e.target.value)} + id="orgname" + label="Название компании" + {...textFieldProps} + /> + setSettingsField("email", e.target.value)} + id="email" + label="E-mail" + {...textFieldProps} + /> + setSettingsField("phoneNumber", e.target.value)} + id="phoneNumber" + label="Телефон" + {...textFieldProps} + /> + setSettingsField("password", e.target.value)} + id="password" + label="Пароль" + {...textFieldProps} + /> + + ) } \ No newline at end of file diff --git a/src/pages/AccountSettings/helper.ts b/src/pages/AccountSettings/helper.ts index 2c238f0..8781e54 100644 --- a/src/pages/AccountSettings/helper.ts +++ b/src/pages/AccountSettings/helper.ts @@ -1,68 +1,68 @@ -import { devlog } from "@frontend/kitui"; +import { devlog } from "@frontend/kitui" -import { verification } from "@root/api/verification"; +import { verification } from "@root/api/verification" import { - setVerificationStatus, - setVerificationType, - setComment, - setDocumentUrl, -} from "@root/stores/user"; -import { VerificationStatus } from "@root/model/account"; + setVerificationStatus, + setVerificationType, + setComment, + setDocumentUrl, +} from "@root/stores/user" +import { VerificationStatus } from "@root/model/account" -import { DOCUMENT_TYPE_MAP } from "@root/constants/documentTypeMap"; +import { DOCUMENT_TYPE_MAP } from "@root/constants/documentTypeMap" -import type { Verification } from "@root/model/auth"; +import type { Verification } from "@root/model/auth" const updateVerificationStatus = (verification: Verification) => { - if (!verification) { - setVerificationStatus(VerificationStatus.NOT_VERIFICATED); + if (!verification) { + setVerificationStatus(VerificationStatus.NOT_VERIFICATED) - return; - } + return + } - if (verification.accepted) { - setVerificationStatus(VerificationStatus.VERIFICATED); + if (verification.accepted) { + setVerificationStatus(VerificationStatus.VERIFICATED) - return; - } + return + } - if ( - (!verification.accepted && !verification.files?.length) || + if ( + (!verification.accepted && !verification.files?.length) || (!verification.accepted && !verification.comment) - ) { - setVerificationStatus(VerificationStatus.NOT_VERIFICATED); + ) { + setVerificationStatus(VerificationStatus.NOT_VERIFICATED) - return; - } + return + } - if (verification.files?.length && !verification.comment) { - setVerificationStatus(VerificationStatus.WAITING); + if (verification.files?.length && !verification.comment) { + setVerificationStatus(VerificationStatus.WAITING) - return; - } + return + } - setVerificationStatus(VerificationStatus.NOT_VERIFICATED); -}; + setVerificationStatus(VerificationStatus.NOT_VERIFICATED) +} export const verify = async (id: string) => { - const [verificationResult, verificationError] = await verification(id); + const [verificationResult, verificationError] = await verification(id) - if (verificationError) { - setVerificationStatus(VerificationStatus.NOT_VERIFICATED); + if (verificationError) { + setVerificationStatus(VerificationStatus.NOT_VERIFICATED) - devlog("Error fetching user", verificationError); + devlog("Error fetching user", verificationError) - return; - } + return + } - if (verificationResult) { - updateVerificationStatus(verificationResult); - setVerificationType(verificationResult.status); - setComment(verificationResult.comment); - verificationResult.files.forEach((file) => - setDocumentUrl(DOCUMENT_TYPE_MAP[file.name], file.url) - ); + if (verificationResult) { + updateVerificationStatus(verificationResult) + setVerificationType(verificationResult.status) + setComment(verificationResult.comment) + verificationResult.files.forEach((file) => + setDocumentUrl(DOCUMENT_TYPE_MAP[file.name], file.url) + ) - devlog("User", verificationResult); - } -}; + devlog("User", verificationResult) + } +} diff --git a/src/pages/Cart/Cart.tsx b/src/pages/Cart/Cart.tsx index fb744bb..0a00351 100644 --- a/src/pages/Cart/Cart.tsx +++ b/src/pages/Cart/Cart.tsx @@ -1,80 +1,80 @@ -import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material"; -import SectionWrapper from "@components/SectionWrapper"; -import ArrowBackIcon from "@mui/icons-material/ArrowBack"; -import TotalPrice from "@components/TotalPrice"; -import CustomWrapper from "./CustomWrapper"; -import { useCart } from "@root/utils/hooks/useCart"; -import { useLocation } from "react-router-dom"; -import { usePrevLocation } from "@root/utils/hooks/handleCustomBackNavigation"; -import { handleComponentError } from "@root/utils/handleComponentError"; -import { withErrorBoundary } from "react-error-boundary"; +import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material" +import SectionWrapper from "@components/SectionWrapper" +import ArrowBackIcon from "@mui/icons-material/ArrowBack" +import TotalPrice from "@components/TotalPrice" +import CustomWrapper from "./CustomWrapper" +import { useCart } from "@root/utils/hooks/useCart" +import { useLocation } from "react-router-dom" +import { usePrevLocation } from "@root/utils/hooks/handleCustomBackNavigation" +import { handleComponentError } from "@root/utils/handleComponentError" +import { withErrorBoundary } from "react-error-boundary" function Cart() { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const isMobile = useMediaQuery(theme.breakpoints.down(550)); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); - const cart = useCart(); - const location = useLocation(); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const isMobile = useMediaQuery(theme.breakpoints.down(550)) + const isTablet = useMediaQuery(theme.breakpoints.down(1000)) + const cart = useCart() + const location = useLocation() - const totalPriceBeforeDiscounts = cart.priceBeforeDiscounts; - const totalPriceAfterDiscounts = cart.priceAfterDiscounts; + const totalPriceBeforeDiscounts = cart.priceBeforeDiscounts + const totalPriceAfterDiscounts = cart.priceAfterDiscounts - const handleCustomBackNavigation = usePrevLocation(location); + const handleCustomBackNavigation = usePrevLocation(location) - return ( - - - {isMobile && ( - - - - )} - + return ( + + + {isMobile && ( + + + + )} + Корзина - - - - {cart.services.map((serviceData, index) => ( - - ))} - - - - ); + + + + {cart.services.map((serviceData, index) => ( + + ))} + + + + ) } export default withErrorBoundary(Cart, { - fallback: Ошибка при отображении корзины, - onError: handleComponentError, + fallback: Ошибка при отображении корзины, + onError: handleComponentError, }) diff --git a/src/pages/Cart/CustomWrapper.tsx b/src/pages/Cart/CustomWrapper.tsx index b8339d6..431a778 100644 --- a/src/pages/Cart/CustomWrapper.tsx +++ b/src/pages/Cart/CustomWrapper.tsx @@ -1,21 +1,21 @@ -import { useState } from "react"; -import { Box, SvgIcon, Typography, useMediaQuery, useTheme } from "@mui/material"; -import ExpandIcon from "@components/icons/ExpandIcon"; -import ClearIcon from "@mui/icons-material/Clear"; -import { currencyFormatter } from "@root/utils/currencyFormatter"; -import { removeTariffFromCart } from "@root/stores/user"; -import { enqueueSnackbar } from "notistack"; -import { CloseButton, ServiceCartData, getMessageFromFetchError } from "@frontend/kitui"; +import { useState } from "react" +import { Box, SvgIcon, Typography, useMediaQuery, useTheme } from "@mui/material" +import ExpandIcon from "@components/icons/ExpandIcon" +import ClearIcon from "@mui/icons-material/Clear" +import { currencyFormatter } from "@root/utils/currencyFormatter" +import { removeTariffFromCart } from "@root/stores/user" +import { enqueueSnackbar } from "notistack" +import { CloseButton, ServiceCartData, getMessageFromFetchError } from "@frontend/kitui" -import type { MouseEvent } from "react"; -import CustomTariffAccordion from "@root/components/CustomTariffAccordion"; +import type { MouseEvent } from "react" +import CustomTariffAccordion from "@root/components/CustomTariffAccordion" const name: Record = { - templategen: "Шаблонизатор", - squiz: "Опросник", - reducer: "Сокращатель ссылок", - custom: "Кастомные тарифы", -}; + templategen: "Шаблонизатор", + squiz: "Опросник", + reducer: "Сокращатель ссылок", + custom: "Кастомные тарифы", +} interface Props { serviceData: ServiceCartData; @@ -24,177 +24,177 @@ interface Props { } export default function CustomWrapper({ serviceData, last, first }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const upSm = useMediaQuery(theme.breakpoints.up("sm")); - const [isExpanded, setIsExpanded] = useState(false); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const upSm = useMediaQuery(theme.breakpoints.up("sm")) + const [isExpanded, setIsExpanded] = useState(false) - function handleItemDeleteClick(tariffId: string) { - removeTariffFromCart(tariffId) - .then(() => { - enqueueSnackbar("Тариф удален"); - }) - .catch((error) => { - const message = getMessageFromFetchError(error); - if (message) enqueueSnackbar(message); - }); - } + function handleItemDeleteClick(tariffId: string) { + removeTariffFromCart(tariffId) + .then(() => { + enqueueSnackbar("Тариф удален") + }) + .catch((error) => { + const message = getMessageFromFetchError(error) + if (message) enqueueSnackbar(message) + }) + } - const deleteService = async (event: MouseEvent) => { - event.stopPropagation(); + const deleteService = async (event: MouseEvent) => { + event.stopPropagation() - setIsExpanded(false); + setIsExpanded(false) - for (const { id } of serviceData.tariffs) { - try { - await removeTariffFromCart(id); - } catch {} - } + for (const { id } of serviceData.tariffs) { + try { + await removeTariffFromCart(id) + } catch {} + } - enqueueSnackbar("Тарифы удалены"); - }; + enqueueSnackbar("Тарифы удалены") + } - return ( - - + - setIsExpanded((prev) => !prev)} - sx={{ - height: "72px", - px: "20px", - display: "flex", - gap: "15px", - alignItems: "center", - justifyContent: "space-between", - cursor: "pointer", - userSelect: "none", - }} - > - - - - - {name[serviceData.serviceKey]} - - - - {currencyFormatter.format(serviceData.price / 100)} - - - - - {isExpanded && + ...(last && { borderBottom: "none" }), + }} + > + setIsExpanded((prev) => !prev)} + sx={{ + height: "72px", + px: "20px", + display: "flex", + gap: "15px", + alignItems: "center", + justifyContent: "space-between", + cursor: "pointer", + userSelect: "none", + }} + > + + + + + {name[serviceData.serviceKey]} + + + + {currencyFormatter.format(serviceData.price / 100)} + + + + + {isExpanded && serviceData.tariffs.map((tariff) => { - const privilege = tariff.privileges[0]; + const privilege = tariff.privileges[0] - return tariff.privileges.length > 1 ? ( - - ) : ( - - - {privilege.description} - - - - {currencyFormatter.format(tariff.price / 100)} - - - handleItemDeleteClick(tariff.id)} - > - - - - ); + return tariff.privileges.length > 1 ? ( + + ) : ( + + + {privilege.description} + + + + {currencyFormatter.format(tariff.price / 100)} + + + handleItemDeleteClick(tariff.id)} + > + + + + ) })} - - - ); + + + ) } diff --git a/src/pages/Faq/AccordionWrapper.tsx b/src/pages/Faq/AccordionWrapper.tsx index 439f469..ab17f28 100644 --- a/src/pages/Faq/AccordionWrapper.tsx +++ b/src/pages/Faq/AccordionWrapper.tsx @@ -1,24 +1,24 @@ -import { Box } from "@mui/material"; +import { Box } from "@mui/material" -import CustomAccordion from "@components/CustomAccordion"; -import { cardShadow } from "@root/utils/theme"; +import CustomAccordion from "@components/CustomAccordion" +import { cardShadow } from "@root/utils/theme" interface Props { content: [string, string][]; } export default function AccordionWrapper({ content }: Props) { - return ( - - {content.map((accordionItem, index) => ( - - ))} - - ); + return ( + + {content.map((accordionItem, index) => ( + + ))} + + ) } diff --git a/src/pages/Faq/Faq.tsx b/src/pages/Faq/Faq.tsx index e318e30..a798781 100644 --- a/src/pages/Faq/Faq.tsx +++ b/src/pages/Faq/Faq.tsx @@ -1,170 +1,170 @@ -import { IconButton, useMediaQuery, useTheme } from "@mui/material"; -import { Select } from "@root/components/Select"; -import { Box } from "@mui/material"; -import { Typography } from "@mui/material"; -import { useState } from "react"; -import SectionWrapper from "../../components/SectionWrapper"; -import AccordionWrapper from "./AccordionWrapper"; -import ArrowBackIcon from "@mui/icons-material/ArrowBack"; -import { Tabs } from "@root/components/Tabs"; -import { useHistoryTracker } from "@root/utils/hooks/useHistoryTracker"; +import { IconButton, useMediaQuery, useTheme } from "@mui/material" +import { Select } from "@root/components/Select" +import { Box } from "@mui/material" +import { Typography } from "@mui/material" +import { useState } from "react" +import SectionWrapper from "../../components/SectionWrapper" +import AccordionWrapper from "./AccordionWrapper" +import ArrowBackIcon from "@mui/icons-material/ArrowBack" +import { Tabs } from "@root/components/Tabs" +import { useHistoryTracker } from "@root/utils/hooks/useHistoryTracker" -const subPages = ["Pena hub", "Шаблоны", "Опросы", "Ссылки", "Финансовые", "Юридические", "Юридические лица"]; +const subPages = ["Pena hub", "Шаблоны", "Опросы", "Ссылки", "Финансовые", "Юридические", "Юридические лица"] export default function Faq() { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const isMobile = useMediaQuery(theme.breakpoints.down(550)); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); - const [tabIndex, setTabIndex] = useState(0); - const [selectedItem, setSelectedItem] = useState(0); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const isMobile = useMediaQuery(theme.breakpoints.down(550)) + const isTablet = useMediaQuery(theme.breakpoints.down(1000)) + const [tabIndex, setTabIndex] = useState(0) + const [selectedItem, setSelectedItem] = useState(0) - const handleCustomBackNavigation = useHistoryTracker(); + const handleCustomBackNavigation = useHistoryTracker() - return ( - - - {isMobile && ( - - - - )} - + return ( + + + {isMobile && ( + + + + )} + Вопросы и ответы - - - - {isMobile ? ( - + ) : ( + + )} + - - - - - - - - - - - - - - - - - - - - - - - ); + + + + + + + + + + + + + + + + + + + + + + + ) } interface TabPanelProps { @@ -175,9 +175,9 @@ interface TabPanelProps { } function TabPanel({ index, value, children, mt }: TabPanelProps) { - return ( - - ); + return ( + + ) } diff --git a/src/pages/History/AccordionWrapper.tsx b/src/pages/History/AccordionWrapper.tsx index 271a74a..2ad72c2 100644 --- a/src/pages/History/AccordionWrapper.tsx +++ b/src/pages/History/AccordionWrapper.tsx @@ -1,10 +1,10 @@ -import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material"; -import CustomAccordion from "@components/CustomAccordion"; +import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material" +import CustomAccordion from "@components/CustomAccordion" import File from "@components/icons/File" import { getDeclension } from "@utils/declension" -import { enqueueSnackbar } from "notistack"; -import { addTariffToCart } from "@root/stores/user"; -import { getMessageFromFetchError } from "@frontend/kitui"; +import { enqueueSnackbar } from "notistack" +import { addTariffToCart } from "@root/stores/user" +import { getMessageFromFetchError } from "@frontend/kitui" export type History = { title: string; @@ -25,216 +25,216 @@ interface AccordionWrapperProps { } export default function AccordionWrapper({ content, last, first, createdAt }: AccordionWrapperProps) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const upSm = useMediaQuery(theme.breakpoints.up("sm")); - const isTablet = useMediaQuery(theme.breakpoints.down(900)); - const isMobile = useMediaQuery(theme.breakpoints.down(560)); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const upSm = useMediaQuery(theme.breakpoints.up("sm")) + const isTablet = useMediaQuery(theme.breakpoints.down(900)) + const isMobile = useMediaQuery(theme.breakpoints.down(560)) - const valuesByKey: any = {}; - content[0].Value[0].forEach((item) => { - valuesByKey[item.Key] = item.Value; - }); - console.log(content) - console.log(content[0]) - console.log(content[0].Value) - console.log(valuesByKey) - const extractDateFromString = (tariffName: string) => { - const dateMatch = tariffName.match(/\d{4}-\d{2}-\d{2}/); - return dateMatch ? dateMatch[0] : null; - }; + const valuesByKey: any = {} + content[0].Value[0].forEach((item) => { + valuesByKey[item.Key] = item.Value + }) + console.log(content) + console.log(content[0]) + console.log(content[0].Value) + console.log(valuesByKey) + const extractDateFromString = (tariffName: string) => { + const dateMatch = tariffName.match(/\d{4}-\d{2}-\d{2}/) + return dateMatch ? dateMatch[0] : null + } - async function handleTariffItemClick(tariffId: string) { - const { patchCartError } = await addTariffToCart(tariffId) - if (patchCartError) { - enqueueSnackbar(patchCartError); - } else { - enqueueSnackbar("Тариф добавлен в корзину"); - } - } + async function handleTariffItemClick(tariffId: string) { + const { patchCartError } = await addTariffToCart(tariffId) + if (patchCartError) { + enqueueSnackbar(patchCartError) + } else { + enqueueSnackbar("Тариф добавлен в корзину") + } + } - return ( - - ( - - {e[1].Value} - {e[5].Value} {getDeclension(Number(e[5].Value), e[7].Value.toString())} - ) - )} - header={ - <> - - - - {createdAt} - + return ( + + ( + + {e[1].Value} - {e[5].Value} {getDeclension(Number(e[5].Value), e[7].Value.toString())} + ) + )} + header={ + <> + + + + {createdAt} + - - {valuesByKey.iscustom ? "Кастомный тариф" : valuesByKey.name} - - - - - Способ оплаты: ${valuesByKey.payMethod}}`} - > - {valuesByKey.payMethod && Способ оплаты: {valuesByKey.payMethod}} - - - - {Number(content[1].Value) / 100 ? Number(content[1].Value) / 100 : "nodata"} руб. - - - - {!isMobile && + + {valuesByKey.iscustom ? "Кастомный тариф" : valuesByKey.name} + + + + + Способ оплаты: ${valuesByKey.payMethod}}`} + > + {valuesByKey.payMethod && Способ оплаты: {valuesByKey.payMethod}} + + + + {Number(content[1].Value) / 100 ? Number(content[1].Value) / 100 : "nodata"} руб. + + + + {!isMobile && { - e.stopPropagation() - handleTariffItemClick(valuesByKey.id) - }} - sx={{ - ml: "20px", - bgcolor:"#EEE4FC", - stroke: "#7E2AEA", - borderRadius: 2, - "&:hover": { - bgcolor:"#7E2AEA", - stroke: "white", - }, - "&:active": { - bgcolor:"black", - stroke: "white", - } - }} + title="Добавить в корзину тариф" + onClick={(e) => { + e.stopPropagation() + handleTariffItemClick(valuesByKey.id) + }} + sx={{ + ml: "20px", + bgcolor:"#EEE4FC", + stroke: "#7E2AEA", + borderRadius: 2, + "&:hover": { + bgcolor:"#7E2AEA", + stroke: "white", + }, + "&:active": { + bgcolor:"black", + stroke: "white", + } + }} > - + - } - - - {isMobile && + } + + + {isMobile && { - e.stopPropagation() - handleTariffItemClick(valuesByKey.id) - }} - sx={{ - mr: "10px", - bgcolor:"#EEE4FC", - stroke: "#7E2AEA", - borderRadius: 2, - "&:hover": { - bgcolor:"#7E2AEA", - stroke: "white", - }, - "&:active": { - bgcolor:"black", - stroke: "white", - } - }} + title="Добавить в корзину тариф" + onClick={(e) => { + e.stopPropagation() + handleTariffItemClick(valuesByKey.id) + }} + sx={{ + mr: "10px", + bgcolor:"#EEE4FC", + stroke: "#7E2AEA", + borderRadius: 2, + "&:hover": { + bgcolor:"#7E2AEA", + stroke: "white", + }, + "&:active": { + bgcolor:"black", + stroke: "white", + } + }} > - + - } - - } - /> - - ); + } + + } + /> + + ) } diff --git a/src/pages/History/historyMocks.ts b/src/pages/History/historyMocks.ts index b1938ef..74818a7 100644 --- a/src/pages/History/historyMocks.ts +++ b/src/pages/History/historyMocks.ts @@ -1,129 +1,129 @@ -import type { History } from "./AccordionWrapper"; +import type { History } from "./AccordionWrapper" const PAYMENT_HISTORY: History[] = [ - { - date: "28.05.2022", - title: "Шаблонизатор", - payMethod: "QIWI Кошелек", - info: "3 190 руб.", - description: "Дата действия приобретенной лицензии (в формате дд.мм.гггг-дд.мм.гггг) Или же объем", - }, - { - date: "28.05.2022", - title: "Сокращатель ссылок", - payMethod: "Юмани", - info: "2 190 руб.", - description: "Дата действия приобретенной лицензии (в формате дд.мм.гггг-дд.мм.гггг) Или же объем", - }, - { - date: "28.05.2022", - title: "Шаблонизатор", - payMethod: "QIWI Кошелек", - info: "1 190 руб.", - description: "Дата действия приобретенной лицензии (в формате дд.мм.гггг-дд.мм.гггг) Или же объем", - }, - { - date: "08.04.2022", - title: "Шаблонизатор", - payMethod: "QIWI Кошелек", - info: "3 190 руб.", - description: "Дата действия приобретенной лицензии (в формате дд.мм.гггг-дд.мм.гггг) Или же объем", - }, - { - date: "28.05.2022", - title: "Сокращатель ссылок", - payMethod: "Юмани", - info: "5 190 руб.", - description: "Дата действия приобретенной лицензии (в формате дд.мм.гггг-дд.мм.гггг) Или же объем", - }, - { - date: "18.03.2022", - title: "Шаблонизатор", - payMethod: "Юмани", - info: "6 190 руб.", - description: "Дата действия приобретенной лицензии (в формате дд.мм.гггг-дд.мм.гггг) Или же объем", - }, -]; + { + date: "28.05.2022", + title: "Шаблонизатор", + payMethod: "QIWI Кошелек", + info: "3 190 руб.", + description: "Дата действия приобретенной лицензии (в формате дд.мм.гггг-дд.мм.гггг) Или же объем", + }, + { + date: "28.05.2022", + title: "Сокращатель ссылок", + payMethod: "Юмани", + info: "2 190 руб.", + description: "Дата действия приобретенной лицензии (в формате дд.мм.гггг-дд.мм.гггг) Или же объем", + }, + { + date: "28.05.2022", + title: "Шаблонизатор", + payMethod: "QIWI Кошелек", + info: "1 190 руб.", + description: "Дата действия приобретенной лицензии (в формате дд.мм.гггг-дд.мм.гггг) Или же объем", + }, + { + date: "08.04.2022", + title: "Шаблонизатор", + payMethod: "QIWI Кошелек", + info: "3 190 руб.", + description: "Дата действия приобретенной лицензии (в формате дд.мм.гггг-дд.мм.гггг) Или же объем", + }, + { + date: "28.05.2022", + title: "Сокращатель ссылок", + payMethod: "Юмани", + info: "5 190 руб.", + description: "Дата действия приобретенной лицензии (в формате дд.мм.гггг-дд.мм.гггг) Или же объем", + }, + { + date: "18.03.2022", + title: "Шаблонизатор", + payMethod: "Юмани", + info: "6 190 руб.", + description: "Дата действия приобретенной лицензии (в формате дд.мм.гггг-дд.мм.гггг) Или же объем", + }, +] const PURCHASED_TARIFFS_HISTORY: History[] = [ - { - date: "28.05.2022", - title: "Шаблонизатор", - info: "5 000 шаблонов", - description: "Тариф на время/ объем/ кастомный или другая информация", - }, - { - date: "27.05.2022", - title: "Опросник", - info: "9 месяцев 1 000 шаблонов", - description: "Тариф на время/ объем/ кастомный или другая информация", - }, - { - date: "20.05.2022", - title: "Шаблонизатор", - info: "Безлимит", - description: "Тариф на время/ объем/ кастомный или другая информация", - }, - { - date: "08.04.2022", - title: "Опросник", - info: "10 000 шаблонов", - description: "Тариф на время/ объем/ кастомный или другая информация", - }, - { - date: "28.05.2022", - title: "Сокращатель ссылок", - info: "3 дня", - description: "Тариф на время/ объем/ кастомный или другая информация", - }, - { - date: "18.03.2022", - title: "Шаблонизатор", - info: "9 месяцев 1 000 шаблонов", - description: "Тариф на время/ объем/ кастомный или другая информация", - }, -]; + { + date: "28.05.2022", + title: "Шаблонизатор", + info: "5 000 шаблонов", + description: "Тариф на время/ объем/ кастомный или другая информация", + }, + { + date: "27.05.2022", + title: "Опросник", + info: "9 месяцев 1 000 шаблонов", + description: "Тариф на время/ объем/ кастомный или другая информация", + }, + { + date: "20.05.2022", + title: "Шаблонизатор", + info: "Безлимит", + description: "Тариф на время/ объем/ кастомный или другая информация", + }, + { + date: "08.04.2022", + title: "Опросник", + info: "10 000 шаблонов", + description: "Тариф на время/ объем/ кастомный или другая информация", + }, + { + date: "28.05.2022", + title: "Сокращатель ссылок", + info: "3 дня", + description: "Тариф на время/ объем/ кастомный или другая информация", + }, + { + date: "18.03.2022", + title: "Шаблонизатор", + info: "9 месяцев 1 000 шаблонов", + description: "Тариф на время/ объем/ кастомный или другая информация", + }, +] const FINISHED_TARIFFS_HISTORY: History[] = [ - { - date: "28.05.2022", - title: "Шаблонизатор", - info: "5 000 шаблонов", - description: "Тариф на время/ объем/ кастомный или другая информация", - }, - { - date: "28.05.2022", - title: "Сокращатель ссылок", - info: "10 месяцев", - description: "Тариф на время/ объем/ кастомный или другая информация", - }, - { - date: "20.05.2022", - title: "Шаблонизатор", - info: "Безлимит", - description: "Тариф на время/ объем/ кастомный или другая информация", - }, - { - date: "08.04.2022", - title: "Опросник", - info: "5 000 шаблонов", - expired: true, - description: "Тариф на время/ объем/ кастомный или другая информация", - }, - { - date: "01.03.2022", - title: "Шаблонизатор", - info: "3 дня", - expired: true, - description: "Тариф на время/ объем/ кастомный или другая информация", - }, - { - date: "19.02.2022", - title: "Сокращатель ссылок", - info: "9 месяцев 1 000 шаблонов", - expired: true, - description: "Тариф на время/ объем/ кастомный или другая информация", - }, -]; + { + date: "28.05.2022", + title: "Шаблонизатор", + info: "5 000 шаблонов", + description: "Тариф на время/ объем/ кастомный или другая информация", + }, + { + date: "28.05.2022", + title: "Сокращатель ссылок", + info: "10 месяцев", + description: "Тариф на время/ объем/ кастомный или другая информация", + }, + { + date: "20.05.2022", + title: "Шаблонизатор", + info: "Безлимит", + description: "Тариф на время/ объем/ кастомный или другая информация", + }, + { + date: "08.04.2022", + title: "Опросник", + info: "5 000 шаблонов", + expired: true, + description: "Тариф на время/ объем/ кастомный или другая информация", + }, + { + date: "01.03.2022", + title: "Шаблонизатор", + info: "3 дня", + expired: true, + description: "Тариф на время/ объем/ кастомный или другая информация", + }, + { + date: "19.02.2022", + title: "Сокращатель ссылок", + info: "9 месяцев 1 000 шаблонов", + expired: true, + description: "Тариф на время/ объем/ кастомный или другая информация", + }, +] -export const HISTORY: History[][] = [PAYMENT_HISTORY, PURCHASED_TARIFFS_HISTORY, FINISHED_TARIFFS_HISTORY]; +export const HISTORY: History[][] = [PAYMENT_HISTORY, PURCHASED_TARIFFS_HISTORY, FINISHED_TARIFFS_HISTORY] diff --git a/src/pages/History/index.tsx b/src/pages/History/index.tsx index 2f9f428..181c5b7 100644 --- a/src/pages/History/index.tsx +++ b/src/pages/History/index.tsx @@ -1,98 +1,98 @@ -import { useEffect, useState } from "react"; -import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material"; -import ArrowBackIcon from "@mui/icons-material/ArrowBack"; +import { useEffect, useState } from "react" +import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material" +import ArrowBackIcon from "@mui/icons-material/ArrowBack" -import SectionWrapper from "@root/components/SectionWrapper"; -import { Select } from "@root/components/Select"; -import { Tabs } from "@root/components/Tabs"; +import SectionWrapper from "@root/components/SectionWrapper" +import { Select } from "@root/components/Select" +import { Tabs } from "@root/components/Tabs" -import AccordionWrapper from "./AccordionWrapper"; -import { HISTORY } from "./historyMocks"; -import { useHistoryTracker } from "@root/utils/hooks/useHistoryTracker"; -import { useHistoryData } from "@root/utils/hooks/useHistoryData"; -import { isArray } from "cypress/types/lodash"; -import { ErrorBoundary } from "react-error-boundary"; -import { handleComponentError } from "@root/utils/handleComponentError"; +import AccordionWrapper from "./AccordionWrapper" +import { HISTORY } from "./historyMocks" +import { useHistoryTracker } from "@root/utils/hooks/useHistoryTracker" +import { useHistoryData } from "@root/utils/hooks/useHistoryData" +import { isArray } from "cypress/types/lodash" +import { ErrorBoundary } from "react-error-boundary" +import { handleComponentError } from "@root/utils/handleComponentError" -const subPages = ["Платежи", "Покупки тарифов", "Окончания тарифов"]; +const subPages = ["Платежи", "Покупки тарифов", "Окончания тарифов"] export default function History() { - const [selectedItem, setSelectedItem] = useState(0); + const [selectedItem, setSelectedItem] = useState(0) - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); - const isMobile = useMediaQuery(theme.breakpoints.down(600)); - const isTablet = useMediaQuery(theme.breakpoints.down(1000)); - const { historyData, error } = useHistoryData(); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) + const isMobile = useMediaQuery(theme.breakpoints.down(600)) + const isTablet = useMediaQuery(theme.breakpoints.down(1000)) + const { historyData, error } = useHistoryData() - const handleCustomBackNavigation = useHistoryTracker(); + const handleCustomBackNavigation = useHistoryTracker() - const extractDateFromString = (tariffName: string) => { - const dateMatch = tariffName.match(/\d{4}-\d{2}-\d{2}/); - return dateMatch ? dateMatch[0] : ""; - }; + const extractDateFromString = (tariffName: string) => { + const dateMatch = tariffName.match(/\d{4}-\d{2}-\d{2}/) + return dateMatch ? dateMatch[0] : "" + } - return ( - - - {isMobile && ( - - - - )} - + return ( + + + {isMobile && ( + + + + )} + История - - - {isMobile ? ( - + ) : ( + + )} + Ошибка загрузки истории + } + onError={handleComponentError} + > + {historyData?.records + .filter((e) => { + e.createdAt = extractDateFromString(e.createdAt) + return(!e.isDeleted && e.key === "payCart" && Array.isArray(e.rawDetails[0].Value) + )}) + .map(( e, index) => { + return ( + + + + )})} + + + ) } diff --git a/src/pages/Landing/Infographics.tsx b/src/pages/Landing/Infographics.tsx index d0f09bd..22a18cd 100644 --- a/src/pages/Landing/Infographics.tsx +++ b/src/pages/Landing/Infographics.tsx @@ -1,4 +1,4 @@ -import { Box, Typography, useMediaQuery, useTheme } from "@mui/material"; +import { Box, Typography, useMediaQuery, useTheme } from "@mui/material" interface Props { bigText: string; @@ -7,28 +7,28 @@ interface Props { } export default function Infographics({ bigText, text, flex }: Props) { - const theme = useTheme(); - const upMd = useMediaQuery(theme.breakpoints.up("md")); + const theme = useTheme() + const upMd = useMediaQuery(theme.breakpoints.up("md")) - return ( - - - {bigText} - - - {text} - - - ); + return ( + + + {bigText} + + + {text} + + + ) } diff --git a/src/pages/Landing/Landing.tsx b/src/pages/Landing/Landing.tsx index eb488f1..dde3d1b 100644 --- a/src/pages/Landing/Landing.tsx +++ b/src/pages/Landing/Landing.tsx @@ -1,37 +1,37 @@ -import { Box, CssBaseline, ThemeProvider, useTheme, useMediaQuery } from "@mui/material"; -import Section1 from "./Section1"; -import Section2 from "./Section2"; -import Section3 from "./Section3"; -import Section4 from "./Section4"; -import Section5 from "./Section5"; -import FloatingSupportChat from "@root/components/FloatingSupportChat/FloatingSupportChat"; -import Footer from "@root/components/Footer"; -import Navbar from "@root/components/NavbarLanding/Navbar"; -import { theme } from "@root/utils/theme"; +import { Box, CssBaseline, ThemeProvider, useTheme, useMediaQuery } from "@mui/material" +import Section1 from "./Section1" +import Section2 from "./Section2" +import Section3 from "./Section3" +import Section4 from "./Section4" +import Section5 from "./Section5" +import FloatingSupportChat from "@root/components/FloatingSupportChat/FloatingSupportChat" +import Footer from "@root/components/Footer" +import Navbar from "@root/components/NavbarLanding/Navbar" +import { theme } from "@root/utils/theme" export default function Landing() { - const muiTheme = useTheme(); - const isTablet = useMediaQuery(muiTheme.breakpoints.down(900)); + const muiTheme = useTheme() + const isTablet = useMediaQuery(muiTheme.breakpoints.down(900)) - return ( - - - - - - - - - -