From d7f8c32b6dec66a9d3b0a7cd5bbe0762ad3a59dc Mon Sep 17 00:00:00 2001 From: nflnkr Date: Thu, 26 Oct 2023 13:39:58 +0300 Subject: [PATCH 01/10] fix adding to cart --- src/stores/user.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stores/user.ts b/src/stores/user.ts index e791c51..8e810db 100644 --- a/src/stores/user.ts +++ b/src/stores/user.ts @@ -278,7 +278,7 @@ export const sendUserData = async () => { export const addTariffToCart = async (tariffId: string) => { const [patchCartResponse, patchCartError] = await patchCart(tariffId); - if (patchCartError !== undefined) { + if (patchCartError === undefined) { setCart(patchCartResponse); } return({patchCartResponse, patchCartError}) From 68c6c864328f4bde4c514c99cdbdde865aa5b754 Mon Sep 17 00:00:00 2001 From: nflnkr Date: Thu, 26 Oct 2023 13:56:40 +0300 Subject: [PATCH 02/10] fix nko discount applying to non-nko user --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d15dabb..9d373f6 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "dependencies": { "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", - "@frontend/kitui": "1.0.53", + "@frontend/kitui": "1.0.54", "@mui/icons-material": "^5.10.14", "@mui/material": "^5.10.14", "@popperjs/core": "^2.11.8", diff --git a/yarn.lock b/yarn.lock index 8217f37..01c6e41 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1532,10 +1532,10 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@frontend/kitui@1.0.53": - version "1.0.53" - resolved "https://penahub.gitlab.yandexcloud.net/api/v4/projects/21/packages/npm/@frontend/kitui/-/@frontend/kitui-1.0.53.tgz#a663052d300b9e3c588346c646f276c9aec7de5d" - integrity sha1-pmMFLTALnjxYg0bGRvJ2ya7H3l0= +"@frontend/kitui@1.0.54": + version "1.0.54" + resolved "https://penahub.gitlab.yandexcloud.net/api/v4/projects/21/packages/npm/@frontend/kitui/-/@frontend/kitui-1.0.54.tgz#0235d5a8effb9b92351471c3c7775f28cb2839f6" + integrity sha1-AjXVqO/7m5I1FHHDx3dfKMsoOfY= dependencies: immer "^10.0.2" reconnecting-eventsource "^1.6.2" From 47059457816561ba29c312b54ea70b16601b11dd Mon Sep 17 00:00:00 2001 From: nflnkr Date: Thu, 26 Oct 2023 14:27:41 +0300 Subject: [PATCH 03/10] fix not enough money number parsing --- src/components/Drawers.tsx | 13 ++++++++----- src/components/TotalPrice.tsx | 13 ++++++++----- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/components/Drawers.tsx b/src/components/Drawers.tsx index 0896626..1a48ad4 100644 --- a/src/components/Drawers.tsx +++ b/src/components/Drawers.tsx @@ -57,12 +57,15 @@ export default function Drawers() { const [payCartResponse, payCartError] = await payCart(); if (payCartError) { - const notEnoughMoneyAmount = parseInt( - payCartError.replace("insufficient funds: ", "") - ); + if (payCartError.includes("insufficient funds: ")) { + const notEnoughMoneyAmount = parseInt( + payCartError.replace(/^.*insufficient\sfunds:\s(?=\d+$)/, "") + ); - setNotEnoughMoneyAmount(notEnoughMoneyAmount); - setLoading(false); + setNotEnoughMoneyAmount(notEnoughMoneyAmount); + } + + setLoading(false); return enqueueSnackbar(payCartError); } diff --git a/src/components/TotalPrice.tsx b/src/components/TotalPrice.tsx index 37977c6..3e1a144 100644 --- a/src/components/TotalPrice.tsx +++ b/src/components/TotalPrice.tsx @@ -38,12 +38,15 @@ export default function TotalPrice({ const [payCartResponse, payCartError] = await payCart(); if (payCartError) { - const notEnoughMoneyAmount = parseInt( - payCartError.replace("insufficient funds: ", "") - ); + if (payCartError.includes("insufficient funds: ")) { + const notEnoughMoneyAmount = parseInt( + payCartError.replace(/^.*insufficient\sfunds:\s(?=\d+$)/, "") + ); - setNotEnoughMoneyAmount(notEnoughMoneyAmount); - setLoading(false); + setNotEnoughMoneyAmount(notEnoughMoneyAmount); + } + + setLoading(false); return enqueueSnackbar(payCartError); } From 35547195c462828cf19fa8a5671abd258c40ac8d Mon Sep 17 00:00:00 2001 From: nflnkr Date: Thu, 26 Oct 2023 14:29:27 +0300 Subject: [PATCH 04/10] fix cart drawer redirect --- src/components/Drawers.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/Drawers.tsx b/src/components/Drawers.tsx index 1a48ad4..3749922 100644 --- a/src/components/Drawers.tsx +++ b/src/components/Drawers.tsx @@ -75,6 +75,7 @@ export default function Drawers() { } setLoading(false); + closeCartDrawer(); } function handleReplenishWallet() { @@ -306,8 +307,6 @@ export default function Drawers() { + + + ); +} + +export default withErrorBoundary(AccountSettings, { + fallback: Ошибка при отображении настроек аккаунта, + onError: handleComponentError, +}) + +const verificationStatusData: Record = { verificated: { text: "Верификация пройдена", color: "#0D9F00" }, waiting: { text: "В ожидании верификации", color: "#F18956" }, notVerificated: { text: "Не верифицирован", color: "#E02C2C" }, - }; +}; - function handleSendDataClick() { - sendUserData() - .then(() => { - enqueueSnackbar("Информация обновлена"); - }) - .catch((error) => { - const message = getMessageFromFetchError(error); - if (message) enqueueSnackbar(message); - }); - } - - function VerificationIndicator({ +function VerificationIndicator({ verificationStatus, sx, - }: { +}: { verificationStatus: VerificationStatus; sx?: SxProps; - }) { +}) { return ( - - {verificationStatusData[verificationStatus].text} - - ); - } - - 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} - /> - - - Статус - - {verificationStatus === VerificationStatus.NOT_VERIFICATED && ( - <> - } - sx={{ mt: "55px" }} - ButtonProps={{ - onClick: () => openDocumentsDialog("juridical"), - }} - > - Загрузить документы для юр лиц - - } - sx={{ mt: "15px" }} - ButtonProps={{ - onClick: () => openDocumentsDialog("nko"), - }} - > - Загрузить документы для НКО - - - )} - {verificationStatus === VerificationStatus.VERIFICATED && ( - } - sx={{ mt: "55px" }} - ButtonProps={{ - onClick: () => openDocumentsDialog(verificationType), - }} - > - Посмотреть свою верификацию - - )} - {comment &&

{comment}

} -
+ {verificationStatusData[verificationStatus].text}
- -
-
- ); + ); } diff --git a/src/pages/Cart/Cart.tsx b/src/pages/Cart/Cart.tsx index 84216c3..fb744bb 100644 --- a/src/pages/Cart/Cart.tsx +++ b/src/pages/Cart/Cart.tsx @@ -6,8 +6,10 @@ 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"; -export default function Cart() { +function Cart() { const theme = useTheme(); const upMd = useMediaQuery(theme.breakpoints.up("md")); const isMobile = useMediaQuery(theme.breakpoints.down(550)); @@ -71,3 +73,8 @@ export default function Cart() { ); } + +export default withErrorBoundary(Cart, { + fallback: Ошибка при отображении корзины, + onError: handleComponentError, +}) diff --git a/src/pages/SavedTariffs/index.tsx b/src/pages/SavedTariffs/index.tsx index 4b37a2b..fada753 100644 --- a/src/pages/SavedTariffs/index.tsx +++ b/src/pages/SavedTariffs/index.tsx @@ -5,8 +5,10 @@ import { useHistoryTracker } from "@root/utils/hooks/useHistoryTracker"; import SaveWrapper from "./SaveWrapper"; import { useTariffStore } from "@root/stores/tariffs"; import { type Tariff } from "@frontend/kitui"; +import { withErrorBoundary } from "react-error-boundary"; +import { handleComponentError } from "@root/utils/handleComponentError"; -export default function SavedTariffs() { +function SavedTariffs() { const theme = useTheme(); const upMd = useMediaQuery(theme.breakpoints.up("md")); const isMobile = useMediaQuery(theme.breakpoints.down(550)); @@ -65,3 +67,8 @@ export default function SavedTariffs() { ); } + +export default withErrorBoundary(SavedTariffs, { + fallback: Ошибка при отображении сохраненных тарифов, + onError: handleComponentError, +}) diff --git a/src/pages/Support/SupportChat.tsx b/src/pages/Support/SupportChat.tsx index d275a7b..88409a9 100644 --- a/src/pages/Support/SupportChat.tsx +++ b/src/pages/Support/SupportChat.tsx @@ -35,8 +35,10 @@ import { useTicketMessages, } from "@frontend/kitui"; import { shownMessage, sendTicketMessage } from "@root/api/ticket"; +import { withErrorBoundary } from "react-error-boundary"; +import { handleComponentError } from "@root/utils/handleComponentError"; -export default function SupportChat() { +function SupportChat() { const theme = useTheme(); const upMd = useMediaQuery(theme.breakpoints.up("md")); const isMobile = useMediaQuery(theme.breakpoints.up(460)); @@ -128,7 +130,7 @@ export default function SupportChat() { async function handleSendMessage() { if (!ticket || !messageField) return; - const [_, sendTicketMessageError] = await sendTicketMessage( + const [, sendTicketMessageError] = await sendTicketMessage( ticket.id, messageField ); @@ -318,3 +320,8 @@ export default function SupportChat() { ); } + +export default withErrorBoundary(SupportChat, { + fallback: Не удалось отобразить чат, + onError: handleComponentError, +}) diff --git a/src/pages/Support/TicketList/TicketList.tsx b/src/pages/Support/TicketList/TicketList.tsx index 22ad915..98035c3 100644 --- a/src/pages/Support/TicketList/TicketList.tsx +++ b/src/pages/Support/TicketList/TicketList.tsx @@ -5,13 +5,16 @@ import { Box, useTheme, Pagination, + Typography, } from "@mui/material"; import TicketCard from "./TicketCard"; import { setTicketApiPage, useTicketStore } from "@root/stores/tickets"; import { Ticket } from "@frontend/kitui"; +import { withErrorBoundary } from "react-error-boundary"; +import { handleComponentError } from "@root/utils/handleComponentError"; -export default function TicketList() { +function TicketList() { const theme = useTheme(); const tickets = useTicketStore((state) => state.tickets); const ticketCount = useTicketStore((state) => state.ticketCount); @@ -87,3 +90,8 @@ function sortTicketsByUpdateTime(ticket1: Ticket, ticket2: Ticket) { const date2 = new Date(ticket2.updated_at).getTime(); return date2 - date1; } + +export default withErrorBoundary(TicketList, { + fallback: Ошибка загрузки тикетов, + onError: handleComponentError, +}); diff --git a/src/pages/TariffConstructor/TariffConstructor.tsx b/src/pages/TariffConstructor/TariffConstructor.tsx index c007bbf..d36c667 100644 --- a/src/pages/TariffConstructor/TariffConstructor.tsx +++ b/src/pages/TariffConstructor/TariffConstructor.tsx @@ -1,4 +1,4 @@ -import { Box, IconButton, useMediaQuery, useTheme } from "@mui/material"; +import { Box, IconButton, Typography, useMediaQuery, useTheme } from "@mui/material"; import { Link } from "react-router-dom"; import SectionWrapper from "@components/SectionWrapper"; import { useCustomTariffsStore } from "@root/stores/customTariffs"; @@ -8,8 +8,10 @@ import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import TotalPrice from "@root/components/TotalPrice"; import { serviceNameByKey } from "@root/utils/serviceKeys"; import { useHistoryTracker } from "@root/utils/hooks/useHistoryTracker"; +import { withErrorBoundary } from "react-error-boundary"; +import { handleComponentError } from "@root/utils/handleComponentError"; -export default function TariffConstructor() { +function TariffConstructor() { const theme = useTheme(); const upMd = useMediaQuery(theme.breakpoints.up("md")); const isTablet = useMediaQuery(theme.breakpoints.down(1000)); @@ -84,3 +86,8 @@ export default function TariffConstructor() { ); } + +export default withErrorBoundary(TariffConstructor, { + fallback: Ошибка при отображении кастомных тарифов, + onError: handleComponentError, +}) diff --git a/src/pages/Tariffs/TariffsPage.tsx b/src/pages/Tariffs/TariffsPage.tsx index 6248ec0..93b6832 100644 --- a/src/pages/Tariffs/TariffsPage.tsx +++ b/src/pages/Tariffs/TariffsPage.tsx @@ -18,6 +18,8 @@ import { Slider } from "./slider"; import { useCartStore } from "@root/stores/cart"; import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import { usePrevLocation } from "@root/utils/hooks/handleCustomBackNavigation"; +import { withErrorBoundary } from "react-error-boundary"; +import { handleComponentError } from "@root/utils/handleComponentError"; const subPages = ["Шаблонизатор", "Опросник", "Сокращатель ссылок"]; @@ -26,7 +28,7 @@ const StepperText: Record = { time: "Тарифы на время", }; -export default function TariffPage() { +function TariffPage() { const theme = useTheme(); const upMd = useMediaQuery(theme.breakpoints.up("md")); const isMobile = useMediaQuery(theme.breakpoints.down(600)); @@ -178,3 +180,8 @@ export default function TariffPage() { ); } + +export default withErrorBoundary(TariffPage, { + fallback: Ошибка загрузки тарифов, + onError: handleComponentError, +}) diff --git a/src/utils/handleComponentError.ts b/src/utils/handleComponentError.ts index e53049a..e6ae5bd 100644 --- a/src/utils/handleComponentError.ts +++ b/src/utils/handleComponentError.ts @@ -39,6 +39,6 @@ async function sendErrorsToServer() { // body: errorsQueue, // useToken: true, // }); - console.log(`Sending ${errorsQueue.length} errors to server`, errorsQueue); + console.log(`Fake-sending ${errorsQueue.length} errors to server`, errorsQueue); errorsQueue = []; } From 9b7be15cf47e7480fade1f13025521c9eeeea786 Mon Sep 17 00:00:00 2001 From: Nastya Date: Sat, 28 Oct 2023 02:13:54 +0300 Subject: [PATCH 10/10] fix verification methods patch && post --- src/api/verification.ts | 4 +- src/components/Menu.tsx | 17 ++- src/index.tsx | 5 +- src/pages/AccountSettings/AccountSettings.tsx | 108 +--------------- .../DocumentsDialog/DocumentsDialog.tsx | 13 +- .../JuridicalDocumentsDialog.tsx | 107 ++++++++++------ .../DocumentsDialog/NkoDocumentsDialog.tsx | 109 +++++++++++----- src/pages/AccountSettings/UserFields.tsx | 121 ++++++++++++++++++ src/stores/user.ts | 9 +- 9 files changed, 306 insertions(+), 187 deletions(-) create mode 100644 src/pages/AccountSettings/UserFields.tsx diff --git a/src/api/verification.ts b/src/api/verification.ts index d607e52..458b085 100644 --- a/src/api/verification.ts +++ b/src/api/verification.ts @@ -35,7 +35,7 @@ export async function verification( export async function sendDocuments( documents: SendDocumentsArgs -): Promise<[Verification | null, string?]> { +): Promise<[Verification | "OK" | null, string?]> { try { const sendDocumentsResponse = await makeRequest({ url: apiUrl + "/verification", @@ -55,7 +55,7 @@ export async function sendDocuments( export async function updateDocuments( documents: UpdateDocumentsArgs -): Promise<[Verification | null, string?]> { +): Promise<[Verification | "OK" | null, string? ]> { try { const updateDocumentsResponse = await makeRequest({ url: apiUrl + "/verification/file", diff --git a/src/components/Menu.tsx b/src/components/Menu.tsx index faf057c..3e0a40c 100644 --- a/src/components/Menu.tsx +++ b/src/components/Menu.tsx @@ -15,11 +15,26 @@ export default function Menu() { const color = location.pathname === "/" ? "white" : "black"; - const arrayMenu: MenuItem[] = [ + 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 ( { + console.log("render app") const location = useLocation(); const userId = useUserStore((state) => state.userId); const navigate = useNavigate(); @@ -101,7 +102,7 @@ const App = () => { const root = ReactDOM.createRoot(document.getElementById("root") as HTMLElement); root.render( - + // @@ -109,7 +110,7 @@ root.render( - + // ); // If you want to start measuring performance in your app, pass a function diff --git a/src/pages/AccountSettings/AccountSettings.tsx b/src/pages/AccountSettings/AccountSettings.tsx index 8d87795..3ecfd0b 100644 --- a/src/pages/AccountSettings/AccountSettings.tsx +++ b/src/pages/AccountSettings/AccountSettings.tsx @@ -1,8 +1,7 @@ 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 SectionWrapper from "@components/SectionWrapper"; +import UserFields from "./UserFields"; import { openDocumentsDialog, sendUserData, setSettingsField, useUserStore } from "@root/stores/user"; import UnderlinedButtonWithIcon from "@root/components/UnderlinedButtonWithIcon"; import UploadIcon from "@root/components/icons/UploadIcon"; @@ -31,11 +30,7 @@ export default function AccountSettings() { verify(userId); }, []); - const textFieldProps = { - gap: upMd ? "16px" : "10px", - color: "#F2F3F7", - bold: true, - }; + const verificationStatusData: Record = { verificated: { text: "Верификация пройдена", color: "#0D9F00" }, @@ -80,6 +75,7 @@ export default function AccountSettings() { ); } + console.log("компонент настройки юзера") 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} - /> - + state.dialogType); - - return type === "juridical" ? : + switch(useUserStore(state => state.dialogType)) { + case 'juridical': + return + + case "nko": + 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 fa683bb..c649436 100644 --- a/src/pages/AccountSettings/DocumentsDialog/JuridicalDocumentsDialog.tsx +++ b/src/pages/AccountSettings/DocumentsDialog/JuridicalDocumentsDialog.tsx @@ -14,6 +14,7 @@ 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%", @@ -26,15 +27,15 @@ const dialogContainerStyle = { 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 documents = useUserStore((state) => state.documents);//загруженные юзером файлы + const documentsUrl = useUserStore((state) => state.documentsUrl);//ссылки с бекенда const userId = useUserStore((state) => state.userId) ?? ""; - const [isLoading, setIsLoading] = useState(false); const sendUploadedDocuments = async () => { - setIsLoading(true); - if (documents["ИНН"].file && documents["Устав"].file) { + if (documents["ИНН"].file && documents["Устав"].file && !documentsUrl["ИНН"] && !documentsUrl["Устав"]) { + closeDocumentsDialog(); + //Пользователь заполнил все поля и на беке пусто const inn = await readFile(documents["ИНН"].file, "binary"); const rule = await readFile(documents["Устав"].file, "binary"); @@ -46,42 +47,64 @@ export default function JuridicalDocumentsDialog() { if (sendDocumentsError) { enqueueSnackbar(sendDocumentsError); - return; } - } else { - 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, - }) - ); - - if (updateDocumentsError) { - enqueueSnackbar(updateDocumentsError); - - return; + if (_ === "OK") { + enqueueSnackbar("Информация доставлена") } + + 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; + + const [_, updateDocumentsError] = await updateDocuments( + deleteEmptyKeys({ + status: "org", + inn, + rule, + }) + ); + + if (updateDocumentsError) { + enqueueSnackbar(updateDocumentsError); + + return; + } + if (_ === "OK") { + enqueueSnackbar("Информация доставлена") + } + + setDocument("ИНН", null); + setDocument("Устав", null); + + await verify(userId); + } } - - setIsLoading(false); - closeDocumentsDialog(); - - setDocument("ИНН", null); - setDocument("Устав", null); - - await verify(userId); - if (!isLoading) closeDocumentsDialog(); }; + 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 = verificationStatus === VerificationStatus.VERIFICATED ? ( <> @@ -163,6 +186,18 @@ export default function JuridicalDocumentsDialog() { > для верификации юридических лиц в формате PDF + {Boolean(!documentsUrl["ИНН"] && !documentsUrl["Устав"]) && + Пожалуйста, заполните все поля! + } + Отправить diff --git a/src/pages/AccountSettings/DocumentsDialog/NkoDocumentsDialog.tsx b/src/pages/AccountSettings/DocumentsDialog/NkoDocumentsDialog.tsx index 8b3f017..98ab7b0 100644 --- a/src/pages/AccountSettings/DocumentsDialog/NkoDocumentsDialog.tsx +++ b/src/pages/AccountSettings/DocumentsDialog/NkoDocumentsDialog.tsx @@ -14,6 +14,7 @@ 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%", @@ -29,15 +30,16 @@ export default function NkoDocumentsDialog() { const documents = useUserStore((state) => state.documents); const documentsUrl = useUserStore((state) => state.documentsUrl); const userId = useUserStore((state) => state.userId) ?? ""; - const [isLoading, setIsLoading] = useState(false); const sendUploadedDocuments = async () => { - setIsLoading(true); 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( @@ -57,46 +59,72 @@ export default function NkoDocumentsDialog() { return; } - } else { - 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; + if (_ === "OK") { + enqueueSnackbar("Информация доставлена") + } - const [_, updateDocumentsError] = await updateDocuments( - deleteEmptyKeys({ - status: "org", - inn, - rule, - certificate, - }) - ); + 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; - if (updateDocumentsError) { - enqueueSnackbar(updateDocumentsError); + const [_, updateDocumentsError] = await updateDocuments( + deleteEmptyKeys({ + status: "org", + inn, + rule, + certificate, + }) + ); - return; + if (updateDocumentsError) { + enqueueSnackbar(updateDocumentsError); + + return; + } + if (_ === "OK") { + enqueueSnackbar("Информация доставлена") + } + + setDocument("ИНН", null); + setDocument("Устав", null); + setDocument("Свидетельство о регистрации НКО", null); + + await verify(userId); } } - setIsLoading(false); - closeDocumentsDialog(); - - setDocument("ИНН", null); - setDocument("Устав", null); - setDocument("Свидетельство о регистрации НКО", null); - - 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 documentElements = verificationStatus === VerificationStatus.VERIFICATED ? ( <> @@ -194,6 +222,17 @@ export default function NkoDocumentsDialog() { > для верификации НКО в формате PDF + {Boolean(!documentsUrl["ИНН"] && !documentsUrl["Устав"] && !documentsUrl["Свидетельство о регистрации НКО"]) && + Пожалуйста, заполните все поля! + } Отправить diff --git a/src/pages/AccountSettings/UserFields.tsx b/src/pages/AccountSettings/UserFields.tsx new file mode 100644 index 0000000..2d29689 --- /dev/null +++ b/src/pages/AccountSettings/UserFields.tsx @@ -0,0 +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"; + + +export default function UserFields () { + const theme = useTheme(); + const upSm = useMediaQuery(theme.breakpoints.up("sm")); + const upMd = useMediaQuery(theme.breakpoints.up("md")); + + const fields = useUserStore((state) => state.settingsFields); + + console.log("fields") + + 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} + /> + + ) +} \ No newline at end of file diff --git a/src/stores/user.ts b/src/stores/user.ts index e791c51..4858db5 100644 --- a/src/stores/user.ts +++ b/src/stores/user.ts @@ -23,7 +23,7 @@ interface UserStore { verificationStatus: VerificationStatus; verificationType: "juridical" | "nko"; isDocumentsDialogOpen: boolean; - dialogType: "juridical" | "nko"; + dialogType: "juridical" | "nko" | ""; documents: UserDocuments; documentsUrl: UserDocumentsUrl; comment: string; @@ -61,7 +61,7 @@ const initialState: UserStore = { verificationStatus: VerificationStatus.NOT_VERIFICATED, verificationType: "juridical", isDocumentsDialogOpen: false, - dialogType: "juridical", + dialogType: "", comment: "", documents: { ИНН: { ...defaultDocument }, @@ -87,7 +87,7 @@ export const useUserStore = create()( version: 2, name: "user", storage: createJSONStorage(() => localStorage), - partialize: (state) => ({ + partialize: (state) => ({ // список полей для хранения в ЛС userId: state.userId, user: state.user, }), @@ -161,6 +161,7 @@ export const closeDocumentsDialog = () => useUserStore.setState( produce((state) => { state.isDocumentsDialogOpen = false; + state.dialogType = ""; }) ); @@ -214,7 +215,7 @@ export const setUploadedDocument = (type: UserDocumentTypes, fileName: string, u }) ); -export const setSettingsField = (fieldName: UserSettingsField | keyof UserName, value: string) => +export const setSettingsField = (fieldName: UserSettingsField | keyof UserName, value: string) => useUserStore.setState( produce((state) => { if (!state.settingsFields) return;