From a23181e7dbb4ab3f3f25a06c61b0eba74b770707 Mon Sep 17 00:00:00 2001 From: IlyaDoronin Date: Mon, 13 May 2024 16:24:41 +0300 Subject: [PATCH 1/2] style: requests --- src/App.tsx | 2 +- src/api/auth.ts | 36 +-- src/api/cart.ts | 10 +- src/api/contactForm.ts | 39 +++- src/api/discounts.ts | 11 +- src/api/makeRequest.ts | 30 ++- src/api/promocode.ts | 20 +- src/api/question.ts | 177 +++++++++----- src/api/quiz.ts | 198 +++++++++++----- src/api/result.ts | 42 ++-- src/api/statistic.ts | 12 +- src/api/ticket.ts | 18 +- src/pages/Analytics/Analytics.tsx | 23 +- src/pages/QuizAnswersPage/useGetData.ts | 47 ++-- src/pages/Tariffs/Tariffs.tsx | 7 +- src/pages/ViewPublicationPage.tsx | 6 +- src/pages/auth/RecoverPassword.tsx | 2 +- src/pages/createQuize/QuizCard.tsx | 2 +- src/pages/main.tsx | 4 +- src/stores/contactForm.ts | 6 +- src/stores/questions/actions.ts | 280 ++++++++++++----------- src/stores/questions/hooks.ts | 2 +- src/stores/quizes/actions.ts | 150 ++++++------ src/stores/quizes/hooks.ts | 2 +- src/ui_kit/CheckFastlink.tsx | 44 ++-- src/ui_kit/FloatingSupportChat/index.tsx | 4 +- 26 files changed, 704 insertions(+), 470 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 1ce92906..72daabc1 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -24,7 +24,7 @@ import { UserAccount, useUserFetcher, } from "@frontend/kitui"; -import makeRequest from "@api/makeRequest"; +import { makeRequest } from "@api/makeRequest"; import type { OriginalUserAccount } from "@root/user"; import { clearUserData, diff --git a/src/api/auth.ts b/src/api/auth.ts index d15cc3d4..67b19907 100644 --- a/src/api/auth.ts +++ b/src/api/auth.ts @@ -1,4 +1,4 @@ -import makeRequest from "@api/makeRequest"; +import { makeRequest } from "@api/makeRequest"; import type { LoginRequest, @@ -8,19 +8,19 @@ import type { } from "@frontend/kitui"; import { parseAxiosError } from "../utils/parse-error"; -const apiUrl = process.env.REACT_APP_DOMAIN + "/auth"; +const API_URL = process.env.REACT_APP_DOMAIN + "/auth"; -export async function register( +export const register = async ( login: string, password: string, phoneNumber: string, -): Promise<[RegisterResponse | null, string?]> { +): Promise<[RegisterResponse | null, string?]> => { try { const registerResponse = await makeRequest< RegisterRequest, RegisterResponse >({ - url: apiUrl + "/register", + url: `${API_URL}/register`, body: { login, password, phoneNumber }, useToken: false, withCredentials: true, @@ -32,15 +32,15 @@ export async function register( return [null, `Не удалось зарегестрировать аккаунт. ${error}`]; } -} +}; -export async function login( +export const login = async ( login: string, password: string, -): Promise<[LoginResponse | null, string?]> { +): Promise<[LoginResponse | null, string?]> => { try { const loginResponse = await makeRequest({ - url: apiUrl + "/login", + url: `${API_URL}/login`, body: { login, password }, useToken: false, withCredentials: true, @@ -52,13 +52,13 @@ export async function login( return [null, `Не удалось войти. ${error}`]; } -} +}; -export async function logout(): Promise<[unknown, string?]> { +export const logout = async (): Promise<[unknown, string?]> => { try { const logoutResponse = await makeRequest({ - url: apiUrl + "/logout", method: "POST", + url: `${API_URL}/logout`, useToken: true, withCredentials: true, }); @@ -67,13 +67,13 @@ export async function logout(): Promise<[unknown, string?]> { } catch (nativeError) { const [error] = parseAxiosError(nativeError); - return [null]; + return [null, error]; } -} +}; -export async function recover( +export const recover = async ( email: string, -): Promise<[unknown | null, string?]> { +): Promise<[unknown | null, string?]> => { try { const formData = new FormData(); formData.append("email", email); @@ -81,16 +81,18 @@ export async function recover( "RedirectionURL", process.env.REACT_APP_DOMAIN + "/changepwd", ); + const recoverResponse = await makeRequest({ url: process.env.REACT_APP_DOMAIN + "/codeword/recover", body: formData, useToken: false, withCredentials: true, }); + return [recoverResponse]; } catch (nativeError) { const [error] = parseAxiosError(nativeError); return [null, `Не удалось восстановить пароль. ${error}`]; } -} +}; diff --git a/src/api/cart.ts b/src/api/cart.ts index bfa17da0..80d46f27 100644 --- a/src/api/cart.ts +++ b/src/api/cart.ts @@ -1,15 +1,15 @@ import { UserAccount } from "@frontend/kitui"; -import makeRequest from "@api/makeRequest"; +import { makeRequest } from "@api/makeRequest"; import { parseAxiosError } from "@utils/parse-error"; -const apiUrl = process.env.REACT_APP_DOMAIN + "/customer"; +const API_URL = process.env.REACT_APP_DOMAIN + "/customer"; -export async function payCart(): Promise<[UserAccount | null, string?]> { +export const payCart = async (): Promise<[UserAccount | null, string?]> => { try { const payCartResponse = await makeRequest({ - url: apiUrl + "/cart/pay", method: "POST", + url: `${API_URL}/cart/pay`, useToken: true, }); @@ -19,4 +19,4 @@ export async function payCart(): Promise<[UserAccount | null, string?]> { return [null, `Не удалось оплатить товар из корзины. ${error}`]; } -} +}; diff --git a/src/api/contactForm.ts b/src/api/contactForm.ts index 00e9face..00ac2b77 100644 --- a/src/api/contactForm.ts +++ b/src/api/contactForm.ts @@ -1,16 +1,31 @@ -import axios from "axios"; +import { makeRequest } from "@api/makeRequest"; -const domen = process.env.REACT_APP_DOMAIN; +import { parseAxiosError } from "@utils/parse-error"; -export function sendContactFormRequest(body: { +const API_URL = process.env.REACT_APP_DOMAIN + "/feedback"; + +type SendContactFormBody = { contact: string; whoami: string; -}) { - return axios(`${domen}/feedback/callme`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - data: body, - }); -} +}; + +export const sendContactFormRequest = async ( + body: SendContactFormBody, +): Promise<[unknown | null, string?, number?]> => { + try { + const sendContactFormResponse = await makeRequest< + SendContactFormBody, + unknown + >({ + method: "POST", + url: `${API_URL}/callme`, + body, + }); + + return [sendContactFormResponse]; + } catch (nativeError) { + const [error, status] = parseAxiosError(nativeError); + + return [null, `Не удалось отправить контакты. ${error}`, status]; + } +}; diff --git a/src/api/discounts.ts b/src/api/discounts.ts index 025021b1..2cd1fdf1 100644 --- a/src/api/discounts.ts +++ b/src/api/discounts.ts @@ -5,12 +5,15 @@ import type { Discount } from "@model/discounts"; const API_URL = process.env.REACT_APP_DOMAIN + "/price/discount"; -export async function getDiscounts( +export const getDiscounts = async ( userId: string, -): Promise<[Discount[] | null, string?]> { +): Promise<[Discount[] | null, string?]> => { try { const { Discounts } = await makeRequest( - { method: "GET", url: `${API_URL}/user/${userId}` }, + { + method: "GET", + url: `${API_URL}/user/${userId}`, + }, ); return [Discounts]; @@ -19,4 +22,4 @@ export async function getDiscounts( return [null, `Не удалось получить скидки. ${error}`]; } -} +}; diff --git a/src/api/makeRequest.ts b/src/api/makeRequest.ts index b9b4c436..8ec3d2e3 100644 --- a/src/api/makeRequest.ts +++ b/src/api/makeRequest.ts @@ -6,6 +6,8 @@ import { clearUserData } from "@root/user"; import { clearQuizData } from "@root/quizes/store"; import { redirect } from "react-router-dom"; +import type { AxiosResponse } from "axios"; + interface MakeRequest { method?: Method | undefined; url: string; @@ -17,18 +19,22 @@ interface MakeRequest { withCredentials?: boolean | undefined; } -async function makeRequest( - data: MakeRequest, -): Promise { - try { - const response = await KIT.makeRequest(data); +type ExtendedAxiosResponse = AxiosResponse & { message: string }; + +export const makeRequest = async ( + data: MakeRequest, +): Promise => { + try { + const response = await KIT.makeRequest(data); + + return response; + } catch (nativeError) { + const error = nativeError as AxiosError; - return response as TResponse; - } catch (e) { - const error = e as AxiosError; if ( error.response?.status === 400 && - error.response?.data?.message === "refreshToken is empty" + (error.response?.data as ExtendedAxiosResponse)?.message === + "refreshToken is empty" ) { cleanAuthTicketData(); clearAuthToken(); @@ -36,7 +42,7 @@ async function makeRequest( clearQuizData(); redirect("/"); } - throw e; + + throw nativeError; } -} -export default makeRequest; +}; diff --git a/src/api/promocode.ts b/src/api/promocode.ts index 0f409653..2da8fd5b 100644 --- a/src/api/promocode.ts +++ b/src/api/promocode.ts @@ -1,25 +1,27 @@ -import makeRequest from "@api/makeRequest"; +import { makeRequest } from "@api/makeRequest"; import { parseAxiosError } from "@utils/parse-error"; -const apiUrl = process.env.REACT_APP_DOMAIN + "/codeword/promocode"; +type ActivatePromocodeRequest = { codeword: string } | { fastLink: string }; +type ActivatePromocodeResponse = { greetings: string }; -export async function activatePromocode(promocode: string) { +const API_URL = process.env.REACT_APP_DOMAIN + "/codeword/promocode"; + +export const activatePromocode = async (promocode: string) => { try { const response = await makeRequest< - { codeword: string } | { fastLink: string }, - { greetings: string } + ActivatePromocodeRequest, + ActivatePromocodeResponse >({ - url: apiUrl + "/activate", method: "POST", - contentType: true, + url: API_URL + "/activate", body: { codeword: promocode }, + contentType: true, }); return response.greetings; } catch (nativeError) { const [error] = parseAxiosError(nativeError); throw new Error(error); - } -} +}; diff --git a/src/api/question.ts b/src/api/question.ts index 3990299d..fb5fecf1 100644 --- a/src/api/question.ts +++ b/src/api/question.ts @@ -1,4 +1,4 @@ -import makeRequest from "@api/makeRequest"; +import { makeRequest } from "@api/makeRequest"; import { CreateQuestionRequest } from "model/question/create"; import { RawQuestion } from "model/question/question"; import { @@ -18,67 +18,136 @@ import { CopyQuestionResponse, } from "@model/question/copy"; import { replaceSpacesToEmptyLines } from "../utils/replaceSpacesToEmptyLines"; +import { parseAxiosError } from "@utils/parse-error"; -const baseUrl = process.env.REACT_APP_DOMAIN + "/squiz"; +const API_URL = process.env.REACT_APP_DOMAIN + "/squiz"; -function createQuestion(body: CreateQuestionRequest) { - return makeRequest({ - url: `${baseUrl}/question/create`, - body, - method: "POST", - }); -} +export const createQuestion = async ( + body: CreateQuestionRequest, +): Promise<[RawQuestion | null, string?]> => { + try { + const createdQuestion = await makeRequest< + CreateQuestionRequest, + RawQuestion + >({ + method: "POST", + url: `${API_URL}/question/create`, + body, + }); -async function getQuestionList(body?: Partial) { - if (!body?.quiz_id) return null; + return [createdQuestion]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); - const response = await makeRequest< - GetQuestionListRequest, - GetQuestionListResponse - >({ - url: `${baseUrl}/question/getList`, - body: { ...defaultGetQuestionListBody, ...body }, - method: "POST", - }); - const clearArrayFromEmptySpaceBlaBlaValue = response.items?.map( - (question) => { - let data = question; - for (let key in question) { - const k = key as keyof RawQuestion; - //@ts-ignore - if (question[key] === " ") data[key] = ""; - } - return data; - }, - ); + return [null, error]; + } +}; - return replaceSpacesToEmptyLines(clearArrayFromEmptySpaceBlaBlaValue); -} +const getQuestionList = async ( + body?: Partial, +): Promise<[RawQuestion[] | null, string?]> => { + try { + if (!body?.quiz_id) return [null, "Квиз не найден"]; -function editQuestion(body: EditQuestionRequest, signal?: AbortSignal) { - return makeRequest({ - url: `${baseUrl}/question/edit`, - body, - method: "PATCH", - signal, - }); -} + const response = await makeRequest< + GetQuestionListRequest, + GetQuestionListResponse + >({ + method: "POST", + url: `${API_URL}/question/getList`, + body: { ...defaultGetQuestionListBody, ...body }, + }); -function copyQuestion(questionId: number, quizId: number) { - return makeRequest({ - url: `${baseUrl}/question/copy`, - body: { id: questionId, quiz_id: quizId }, - method: "POST", - }); -} + const clearArrayFromEmptySpaceBlaBlaValue = response.items?.map( + (question) => { + let data = question; -function deleteQuestion(id: number) { - return makeRequest({ - url: `${baseUrl}/question/delete`, - body: { id }, - method: "DELETE", - }); -} + for (let key in question) { + if (question[key as keyof RawQuestion] === " ") { + //@ts-ignore + data[key] = ""; + } + } + + return data; + }, + ); + + return [ + replaceSpacesToEmptyLines(clearArrayFromEmptySpaceBlaBlaValue) ?? null, + ]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); + + return [null, error]; + } +}; + +export const editQuestion = async ( + body: EditQuestionRequest, + signal?: AbortSignal, +): Promise<[EditQuestionResponse | null, string?]> => { + try { + const editedQuestion = await makeRequest< + EditQuestionRequest, + EditQuestionResponse + >({ + method: "PATCH", + url: `${API_URL}/question/edit`, + body, + signal, + }); + + return [editedQuestion]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); + + return [null, error]; + } +}; + +export const copyQuestion = async ( + questionId: number, + quizId: number, +): Promise<[CopyQuestionResponse | null, string?]> => { + try { + const copiedQuestion = await makeRequest< + CopyQuestionRequest, + CopyQuestionResponse + >({ + method: "POST", + url: `${API_URL}/question/copy`, + body: { id: questionId, quiz_id: quizId }, + }); + + return [copiedQuestion]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); + + return [null, error]; + } +}; + +export const deleteQuestion = async ( + id: number, +): Promise<[DeleteQuestionResponse | null, string?]> => { + try { + const deletedQuestion = await makeRequest< + DeleteQuestionRequest, + DeleteQuestionResponse + >({ + url: `${API_URL}/question/delete`, + body: { id }, + method: "DELETE", + }); + + return [deletedQuestion]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); + + return [null, error]; + } +}; export const questionApi = { create: createQuestion, diff --git a/src/api/quiz.ts b/src/api/quiz.ts index a876b68f..f4dc5637 100644 --- a/src/api/quiz.ts +++ b/src/api/quiz.ts @@ -1,4 +1,4 @@ -import makeRequest from "@api/makeRequest"; +import { makeRequest } from "@api/makeRequest"; import { defaultQuizConfig } from "@model/quizSettings"; import { CopyQuizRequest, CopyQuizResponse } from "model/quiz/copy"; import { CreateQuizRequest } from "model/quiz/create"; @@ -7,73 +7,157 @@ import { EditQuizRequest, EditQuizResponse } from "model/quiz/edit"; import { GetQuizRequest, GetQuizResponse } from "model/quiz/get"; import { GetQuizListRequest, GetQuizListResponse } from "model/quiz/getList"; import { RawQuiz } from "model/quiz/quiz"; +import { parseAxiosError } from "@utils/parse-error"; -const baseUrl = process.env.REACT_APP_DOMAIN + "/squiz"; -const imagesUrl = process.env.REACT_APP_DOMAIN + "/squizstorer"; +type AddedQuizImagesResponse = { + [key: string]: string; +}; -function createQuiz(body?: Partial) { - return makeRequest({ - url: `${baseUrl}/quiz/create`, - body: { ...defaultCreateQuizBody, ...body }, - method: "POST", - }); -} +const API_URL = process.env.REACT_APP_DOMAIN + "/squiz"; +const IMAGES_URL = process.env.REACT_APP_DOMAIN + "/squizstorer"; -async function getQuizList(body?: Partial) { - const response = await makeRequest({ - url: `${baseUrl}/quiz/getList`, - body: { ...defaultGetQuizListBody, ...body }, - method: "POST", - }); +export const createQuiz = async ( + body?: Partial, +): Promise<[RawQuiz | null, string?]> => { + try { + const createdQuiz = await makeRequest({ + method: "POST", + url: `${API_URL}/quiz/create`, + body: { ...defaultCreateQuizBody, ...body }, + }); - return response.items; -} + return [createdQuiz]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); -function getQuiz(body?: Partial) { - return makeRequest({ - url: `${baseUrl}/quiz/get`, - body: { ...defaultGetQuizBody, ...body }, - method: "GET", - }); -} + return [null, error]; + } +}; -async function editQuiz(body: EditQuizRequest, signal?: AbortSignal) { - return makeRequest({ - url: `${baseUrl}/quiz/edit`, - body, - method: "PATCH", - signal, - }); -} +export const getQuizList = async ( + body?: Partial, +): Promise<[RawQuiz[] | null, string?]> => { + try { + const { items } = await makeRequest< + GetQuizListRequest, + GetQuizListResponse + >({ + method: "POST", + url: `${API_URL}/quiz/getList`, + body: { ...defaultGetQuizListBody, ...body }, + }); -function copyQuiz(id: number) { - return makeRequest({ - url: `${baseUrl}/quiz/copy`, - body: { id }, - method: "POST", - }); -} + return [items]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); -function deleteQuiz(id: number) { - return makeRequest({ - url: `${baseUrl}/quiz/delete`, - body: { id }, - method: "DELETE", - }); -} + return [null, error]; + } +}; -function addQuizImages(quizId: number, image: Blob) { - const formData = new FormData(); +export const getQuiz = async ( + body?: Partial, +): Promise<[GetQuizResponse | null, string?]> => { + try { + const quiz = await makeRequest({ + method: "GET", + url: `${API_URL}/quiz/get`, + body: { ...defaultGetQuizBody, ...body }, + }); - formData.append("quiz", quizId.toString()); - formData.append("image", image); + return [quiz]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); - return makeRequest({ - url: `${imagesUrl}/quiz/putImages`, - body: formData, - method: "PUT", - }); -} + return [null, error]; + } +}; + +export const editQuiz = async ( + body: EditQuizRequest, + signal?: AbortSignal, +): Promise<[EditQuizResponse | null, string?]> => { + try { + const editedQuiz = await makeRequest({ + method: "PATCH", + url: `${API_URL}/quiz/edit`, + body, + signal, + }); + + return [editedQuiz]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); + + return [null, error]; + } +}; + +export const copyQuiz = async ( + id: number, +): Promise<[EditQuizResponse | null, string?]> => { + try { + const copiedQuiz = await makeRequest({ + method: "POST", + url: `${API_URL}/quiz/copy`, + body: { id }, + }); + + return [copiedQuiz]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); + + return [null, error]; + } +}; + +export const deleteQuiz = async ( + id: number, +): Promise<[DeleteQuizResponse | null, string?]> => { + try { + const deletedQuiz = await makeRequest< + DeleteQuizRequest, + DeleteQuizResponse + >({ + method: "DELETE", + url: `${API_URL}/quiz/delete`, + body: { id }, + }); + + return [deletedQuiz]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); + + return [null, error]; + } +}; + +export const addQuizImages = async ( + quizId: number, + image: Blob, +): Promise<[AddedQuizImagesResponse | null, string?]> => { + try { + const formData = new FormData(); + + formData.append("quiz", quizId.toString()); + formData.append("image", image); + + const addedQuizImages = await makeRequest< + FormData, + AddedQuizImagesResponse + >({ + url: `${IMAGES_URL}/quiz/putImages`, + body: formData, + method: "PUT", + }); + + return [addedQuizImages]; + } catch (nativeError) { + const [error] = parseAxiosError(nativeError); + + return [null, error]; + } +}; export const quizApi = { create: createQuiz, diff --git a/src/api/result.ts b/src/api/result.ts index 8d6dab82..edada028 100644 --- a/src/api/result.ts +++ b/src/api/result.ts @@ -1,4 +1,4 @@ -import makeRequest from "@api/makeRequest"; +import { makeRequest } from "@api/makeRequest"; import { RawResult } from "@model/result/result"; interface IResultListBody { @@ -29,47 +29,47 @@ export interface IAnswerResult { question_id: number; } -async function getResultList(quizId: number, page: number, body: any) { +const API_URL = process.env.REACT_APP_DOMAIN + `/squiz`; + +const getResultList = async (quizId: number, page: number, body: any) => { return makeRequest({ - url: process.env.REACT_APP_DOMAIN + `/squiz/results/getResults/${quizId}`, method: "POST", + url: `${API_URL}/results/getResults/${quizId}`, body: { page: page, limit: 10, ...body }, }); -} +}; -function deleteResult(resultId: number) { +const deleteResult = async (resultId: number) => { return makeRequest({ - url: process.env.REACT_APP_DOMAIN + `/squiz/results/delete/${resultId}`, - body: {}, method: "DELETE", + url: `${API_URL}/results/delete/${resultId}`, + body: {}, }); -} +}; -function obsolescenceResult(idResultArray: number[]) { +const obsolescenceResult = (idResultArray: number[]) => { return makeRequest({ - url: process.env.REACT_APP_DOMAIN + `/squiz/result/seen`, - body: { - answers: idResultArray, - }, method: "PATCH", + url: `${API_URL}/result/seen`, + body: { answers: idResultArray }, }); -} +}; -function getAnswerResultList(resultId: number) { +const getAnswerResultList = (resultId: number) => { return makeRequest({ - url: process.env.REACT_APP_DOMAIN + `/squiz/result/${resultId}`, method: "GET", + url: `${API_URL}/result/${resultId}`, }); -} +}; -function AnswerResultListEx(quizId: number, body: any) { +const AnswerResultListEx = (quizId: number, body: any) => { return makeRequest({ - responseType: "blob", - url: process.env.REACT_APP_DOMAIN + `/squiz/results/${quizId}/export`, method: "POST", + url: `${API_URL}/results/${quizId}/export`, body: body, + responseType: "blob", }); -} +}; export const resultApi = { getList: getResultList, diff --git a/src/api/statistic.ts b/src/api/statistic.ts index f9ac1e6b..110d637f 100644 --- a/src/api/statistic.ts +++ b/src/api/statistic.ts @@ -1,9 +1,7 @@ -import makeRequest from "@api/makeRequest"; +import { makeRequest } from "@api/makeRequest"; import { parseAxiosError } from "@utils/parse-error"; -const apiUrl = process.env.REACT_APP_DOMAIN + "/squiz/statistic"; - export type DevicesResponse = { Device: Record; OS: Record; @@ -29,6 +27,8 @@ type TRequest = { from: number; }; +const API_URL = process.env.REACT_APP_DOMAIN + "/squiz/statistic"; + export const getDevices = async ( quizId: string, to: number, @@ -37,7 +37,7 @@ export const getDevices = async ( try { const devicesResponse = await makeRequest({ method: "POST", - url: `${apiUrl}/${quizId}/devices`, + url: `${API_URL}/${quizId}/devices`, withCredentials: true, body: { to, from }, }); @@ -58,7 +58,7 @@ export const getGeneral = async ( try { const generalResponse = await makeRequest({ method: "POST", - url: `${apiUrl}/${quizId}/general`, + url: `${API_URL}/${quizId}/general`, withCredentials: true, body: { to, from }, }); @@ -79,7 +79,7 @@ export const getQuestions = async ( try { const questionsResponse = await makeRequest({ method: "POST", - url: `${apiUrl}/${quizId}/questions`, + url: `${API_URL}/${quizId}/questions`, withCredentials: true, body: { to, from }, }); diff --git a/src/api/ticket.ts b/src/api/ticket.ts index 6d00beed..bdbe2f83 100644 --- a/src/api/ticket.ts +++ b/src/api/ticket.ts @@ -1,20 +1,20 @@ -import makeRequest from "@api/makeRequest"; +import { makeRequest } from "@api/makeRequest"; import { parseAxiosError } from "../utils/parse-error"; import { SendTicketMessageRequest } from "@frontend/kitui"; -const apiUrl = process.env.REACT_APP_DOMAIN + "/heruvym"; +const API_URL = process.env.REACT_APP_DOMAIN + "/heruvym"; -export async function sendTicketMessage( +export const sendTicketMessage = async ( ticketId: string, message: string, -): Promise<[null, string?]> { +): Promise<[null, string?]> => { try { const sendTicketMessageResponse = await makeRequest< SendTicketMessageRequest, null >({ - url: `${apiUrl}/send`, + url: `${API_URL}/send`, method: "POST", useToken: true, body: { ticket: ticketId, message: message, lang: "ru", files: [] }, @@ -26,12 +26,12 @@ export async function sendTicketMessage( return [null, `Не удалось отправить сообщение. ${error}`]; } -} +}; -export async function shownMessage(id: string): Promise<[null, string?]> { +export const shownMessage = async (id: string): Promise<[null, string?]> => { try { const shownMessageResponse = await makeRequest<{ id: string }, null>({ - url: apiUrl + "/shown", + url: `${API_URL}/shown`, method: "POST", useToken: true, body: { id }, @@ -43,4 +43,4 @@ export async function shownMessage(id: string): Promise<[null, string?]> { return [null, `Не удалось прочесть сообщение. ${error}`]; } -} +}; diff --git a/src/pages/Analytics/Analytics.tsx b/src/pages/Analytics/Analytics.tsx index 437ea06b..a1141d23 100644 --- a/src/pages/Analytics/Analytics.tsx +++ b/src/pages/Analytics/Analytics.tsx @@ -68,13 +68,16 @@ export default function Analytics() { useEffect(() => { const getData = async (): Promise => { - try { - if (editQuizId !== null) { - const gottenQuizes = await quizApi.getList(); - setQuizes(gottenQuizes); + if (editQuizId !== null) { + const [gottenQuizes, gottenQuizesError] = await quizApi.getList(); + + if (gottenQuizesError) { + console.error("Не удалось получить квизы", gottenQuizesError); + + return; } - } catch (error) { - console.error("Не удалось получить квизы", error); + + setQuizes(gottenQuizes); } }; @@ -179,7 +182,9 @@ export default function Analytics() { }, }} value={from} - onChange={(date) => {setFrom(date ? date.startOf("day") : moment())}} + onChange={(date) => { + setFrom(date ? date.startOf("day") : moment()); + }} /> @@ -222,7 +227,9 @@ export default function Analytics() { }, }} value={to} - onChange={(date) => {setTo(date ? date.endOf("day") : moment())}} + onChange={(date) => { + setTo(date ? date.endOf("day") : moment()); + }} /> diff --git a/src/pages/QuizAnswersPage/useGetData.ts b/src/pages/QuizAnswersPage/useGetData.ts index 515f111d..4fbbcfac 100644 --- a/src/pages/QuizAnswersPage/useGetData.ts +++ b/src/pages/QuizAnswersPage/useGetData.ts @@ -13,26 +13,39 @@ export const useGetData = (filterNew: string, filterDate: string): void => { useEffect(() => { const getData = async (): Promise => { - try { - if (editQuizId !== null) { - const quizes = await quizApi.getList(); - setQuizes(quizes); + if (editQuizId !== null) { + const [quizes, quizesError] = await quizApi.getList(); - const questions = await questionApi.getList({ quiz_id: editQuizId }); - setQuestions(questions); - - const result = await resultApi.getList( - editQuizId, - 0, - parseFilters(filterNew, filterDate), + if (quizesError) { + console.error( + "An error occurred while receiving data: ", + quizesError, ); - if (result.total_count === 0) { - console.error("No results found"); - } - setResults(result); + + return; } - } catch (error) { - console.error("An error occurred while receiving data: ", error); + + setQuizes(quizes); + + const [questions, questionsError] = await questionApi.getList({ + quiz_id: editQuizId, + }); + + if (questionsError) { + return console.error(questionsError); + } + + setQuestions(questions); + + const result = await resultApi.getList( + editQuizId, + 0, + parseFilters(filterNew, filterDate), + ); + if (result.total_count === 0) { + console.error("No results found"); + } + setResults(result); } }; diff --git a/src/pages/Tariffs/Tariffs.tsx b/src/pages/Tariffs/Tariffs.tsx index e9fd7c91..b5676b2d 100644 --- a/src/pages/Tariffs/Tariffs.tsx +++ b/src/pages/Tariffs/Tariffs.tsx @@ -2,7 +2,7 @@ import { logout } from "@api/auth"; import { activatePromocode } from "@api/promocode"; import type { Tariff } from "@frontend/kitui"; import { useToken } from "@frontend/kitui"; -import makeRequest from "@api/makeRequest"; +import { makeRequest } from "@api/makeRequest"; import ArrowLeft from "@icons/questionsPage/arrowLeft"; import type { GetTariffsResponse } from "@model/tariff"; import { @@ -200,7 +200,10 @@ function TariffPage() { setDiscounts(discounts); } }) - .catch((error) => {if (error.message !== "" && typeof(error.message)==="string") enqueueSnackbar(error.message)}) + .catch((error) => { + if (error.message !== "" && typeof error.message === "string") + enqueueSnackbar(error.message); + }); } return ( diff --git a/src/pages/ViewPublicationPage.tsx b/src/pages/ViewPublicationPage.tsx index b1a8cec1..4ba1c532 100644 --- a/src/pages/ViewPublicationPage.tsx +++ b/src/pages/ViewPublicationPage.tsx @@ -57,9 +57,9 @@ export default function ViewPublicationPage() { if (questionsIsLoading) return null; if (!quiz) throw new Error("Quiz not found"); - if (!rawQuestions) throw new Error("Questions not found"); + if (!rawQuestions?.[0]) throw new Error("Questions not found"); - const questions = rawQuestions.map(rawQuestionToQuestion); + const questions = rawQuestions[0].map(rawQuestionToQuestion); return ( { const getData = async () => { - const quizes = await quizApi.getList(); + const [quizes] = await quizApi.getList(); setQuizes(quizes); if (editQuizId) { - const questions = await questionApi.getList({ quiz_id: editQuizId }); + const [questions] = await questionApi.getList({ quiz_id: editQuizId }); setQuestions(questions); //Всегда должен существовать хоть 1 резулт - "line" diff --git a/src/stores/contactForm.ts b/src/stores/contactForm.ts index da97723c..fcbe0fd4 100644 --- a/src/stores/contactForm.ts +++ b/src/stores/contactForm.ts @@ -58,12 +58,14 @@ export const sendContactForm = async (): Promise => { try { useContactFormStore.setState({ isSubmitDisabled: true }); - const response = await sendContactFormRequest({ + const [_, error, status] = await sendContactFormRequest({ contact, whoami: mail, }); - if (response.status !== 200) throw new Error(response.statusText); + if (status !== 200) { + throw new Error(error); + } useContactFormStore.setState({ ...initialState }); diff --git a/src/stores/questions/actions.ts b/src/stores/questions/actions.ts index cd9dbb26..2ad2d64f 100644 --- a/src/stores/questions/actions.ts +++ b/src/stores/questions/actions.ts @@ -296,35 +296,36 @@ export const updateQuestion = async ( if (!q) return; if (q.type === null) throw new Error("Cannot send update request for untyped question"); - try { - const response = await questionApi.edit( - questionToEditQuestionRequest(replaceEmptyLinesToSpace(q)), - ); - rollbackQuestions = useQuestionsStore.getState(); - - //Если мы делаем листочек веточкой - удаляем созданный к нему результ - const questionResult = useQuestionsStore - .getState() - .questions.find( - (questionResult) => - questionResult.type === "result" && - questionResult.content.rule.parentId === q.content.id, - ); - if (questionResult && q.content.rule.default.length !== 0) - deleteQuestion(questionResult.quizId); - - if (q.backendId !== response.updated) { - console.warn( - `Question backend id has changed from ${q.backendId} to ${response.updated}`, - ); - } - } catch (error) { - if (isAxiosCanceledError(error)) return; + const [response, editError] = await questionApi.edit( + questionToEditQuestionRequest(replaceEmptyLinesToSpace(q)), + ); + if (editError) { useQuestionsStore.setState(rollbackQuestions); - devlog("Error editing question", { error, questionId }); - enqueueSnackbar("Не удалось сохранить вопрос"); + devlog("Error editing question", { editError, questionId }); + enqueueSnackbar(editError); + } + + rollbackQuestions = useQuestionsStore.getState(); + + //Если мы делаем листочек веточкой - удаляем созданный к нему результ + const questionResult = useQuestionsStore + .getState() + .questions.find( + (questionResult) => + questionResult.type === "result" && + questionResult.content.rule.parentId === q.content.id, + ); + + if (questionResult && q.content.rule.default.length !== 0) { + deleteQuestion(String(questionResult.quizId)); + } + + if (q.backendId !== response?.updated) { + console.warn( + `Question backend id has changed from ${q.backendId} to ${response?.updated}`, + ); } }; @@ -430,28 +431,32 @@ export const uploadQuestionImage = async ( .questions.find((q) => q.id === questionId); if (!question || !quizQid) return; - try { - const response = await quizApi.addImages(question.quizId, blob); - - const values = Object.values(response); - if (values.length !== 1) { - console.warn("Error uploading image"); - return; - } - - const imageId = values[0]; - const imageUrl = `https://storage.yandexcloud.net/squizimages/${quizQid}/${imageId}`; - - updateQuestion(questionId, (question) => { - updateFn(question, imageUrl); - }); - - return imageUrl; - } catch (error) { - devlog("Error uploading question image", error); + const [images, addImagesError] = await quizApi.addImages( + question.quizId, + blob, + ); + if (addImagesError || !images) { + devlog("Error uploading question image", addImagesError); enqueueSnackbar("Не удалось загрузить изображение"); + + return; } + + const values = Object.values(images); + if (values.length !== 1) { + console.warn("Error uploading image"); + return; + } + + const imageId = values[0]; + const imageUrl = `https://storage.yandexcloud.net/squizimages/${quizQid}/${imageId}`; + + updateQuestion(questionId, (question) => { + updateFn(question, imageUrl); + }); + + return imageUrl; }; export const setQuestionInnerName = (questionId: string, name: string) => { @@ -489,40 +494,42 @@ export const createTypedQuestion = async ( (q) => q.type === "result" || q.type === null, ).length; - try { - const createdQuestion = await questionApi.create({ - quiz_id: question.quizId, - type, - title: question.title, - description: question.description, - page: questions.length - untypedOrResultQuestionsLength, - required: false, - content: JSON.stringify(defaultQuestionByType[type].content), - }); + const [createdQuestion, createdQuestionError] = await questionApi.create({ + quiz_id: question.quizId, + type, + title: question.title, + description: question.description, + page: questions.length - untypedOrResultQuestionsLength, + required: false, + content: JSON.stringify(defaultQuestionByType[type].content), + }); - setProducedState( - (state) => { - const questionIndex = state.questions.findIndex( - (q) => q.id === questionId, - ); - if (questionIndex !== -1) - state.questions.splice( - questionIndex, - 1, - rawQuestionToQuestion(createdQuestion), - ); - }, - { - type: "createTypedQuestion", - question, - }, - ); + if (createdQuestionError || !createdQuestion) { + devlog("Error creating question", createdQuestionError); + enqueueSnackbar(createdQuestionError); - updateQuestionOrders(); - } catch (error) { - devlog("Error creating question", error); - enqueueSnackbar("Не удалось создать вопрос"); + return; } + + setProducedState( + (state) => { + const questionIndex = state.questions.findIndex( + (q) => q.id === questionId, + ); + if (questionIndex !== -1) + state.questions.splice( + questionIndex, + 1, + rawQuestionToQuestion(createdQuestion), + ); + }, + { + type: "createTypedQuestion", + question, + }, + ); + + updateQuestionOrders(); }); export const deleteQuestion = async (questionId: string) => @@ -537,16 +544,17 @@ export const deleteQuestion = async (questionId: string) => return; } - try { - await questionApi.delete(question.backendId); + const [_, deleteError] = await questionApi.delete(question.backendId); - removeQuestion(questionId); - - updateQuestionOrders(); - } catch (error) { - devlog("Error deleting question", error); + if (deleteError) { + devlog("Error deleting question", deleteError); enqueueSnackbar("Не удалось удалить вопрос"); + return; } + + removeQuestion(questionId); + + updateQuestionOrders(); }); export const copyQuestion = async (questionId: string, quizId: number) => { @@ -587,39 +595,39 @@ export const copyQuestion = async (questionId: string, quizId: number) => { return; } - try { - const { updated: newQuestionId } = await questionApi.copy( - question.backendId, - quizId, - ); + const [copiedQuestionResult, copiedQuestionError] = + await questionApi.copy(question.backendId, quizId); - const copiedQuestion = structuredClone(question); - copiedQuestion.backendId = newQuestionId; - copiedQuestion.id = frontId; - copiedQuestion.content.id = frontId; - copiedQuestion.content.rule = { - main: [], - parentId: "", - default: "", - children: [], - }; + if (copiedQuestionError || !copiedQuestionResult) { + devlog("Error copying question", copiedQuestionError); + enqueueSnackbar(copiedQuestionError); - setProducedState( - (state) => { - state.questions.push(copiedQuestion); - }, - { - type: "copyQuestion", - questionId, - quizId, - }, - ); - - updateQuestionOrders(); - } catch (error) { - devlog("Error copying question", error); - enqueueSnackbar("Не удалось скопировать вопрос"); + return; } + + const copiedQuestion = structuredClone(question); + copiedQuestion.backendId = copiedQuestionResult.updated; + copiedQuestion.id = frontId; + copiedQuestion.content.id = frontId; + copiedQuestion.content.rule = { + main: [], + parentId: "", + default: "", + children: [], + }; + + setProducedState( + (state) => { + state.questions.push(copiedQuestion); + }, + { + type: "copyQuestion", + questionId, + quizId, + }, + ); + + updateQuestionOrders(); }, ); }; @@ -704,30 +712,30 @@ export const createResult = async ( ); content.rule.parentId = parentContentId; - try { - const createdQuestion: RawQuestion = await questionApi.create({ - quiz_id: quizId, - type: "result", - title: "", - description: "", - page: 101, - required: true, - content: JSON.stringify(content), - }); + const [createdQuestion, createdQuestionError] = await questionApi.create({ + quiz_id: quizId, + type: "result", + title: "", + description: "", + page: 101, + required: true, + content: JSON.stringify(content), + }); - setProducedState( - (state) => { - state.questions.push(rawQuestionToQuestion(createdQuestion)); - }, - { - type: "createBackResult", - createdQuestion, - }, - ); - return createdQuestion; - } catch (error) { - devlog("Error creating question", error); - enqueueSnackbar("Не удалось создать вопрос"); + if (createdQuestionError || !createdQuestion) { + throw new Error(createdQuestionError); + + devlog("Error creating question", createdQuestionError); + enqueueSnackbar(createdQuestionError); } + + setProducedState( + (state) => { + state.questions.push(rawQuestionToQuestion(createdQuestion)); + }, + { type: "createBackResult", createdQuestion }, + ); + + return createdQuestion; } }); diff --git a/src/stores/questions/hooks.ts b/src/stores/questions/hooks.ts index 49708b8b..ed7a0f8b 100644 --- a/src/stores/questions/hooks.ts +++ b/src/stores/questions/hooks.ts @@ -14,7 +14,7 @@ export function useQuestions() { ["questions", quiz?.backendId], ([, id]) => questionApi.getList({ quiz_id: id }), { - onSuccess: setQuestions, + onSuccess: ([questions]) => setQuestions(questions), onError: (error) => { const message = isAxiosError(error) ? error.response?.data ?? "" diff --git a/src/stores/quizes/actions.ts b/src/stores/quizes/actions.ts index ea864f6a..d7f5a8a0 100644 --- a/src/stores/quizes/actions.ts +++ b/src/stores/quizes/actions.ts @@ -155,43 +155,44 @@ export const updateQuiz = ( clearTimeout(requestTimeoutId); requestTimeoutId = setTimeout(async () => { - requestQueue - .enqueue(`updateQuiz-${quizId}`, async () => { - const quiz = useQuizStore - .getState() - .quizes.find((q) => q.id === quizId); - if (!quiz) return; + requestQueue.enqueue(`updateQuiz-${quizId}`, async () => { + const quiz = useQuizStore.getState().quizes.find((q) => q.id === quizId); + if (!quiz) return; - const response = await quizApi.edit(quizToEditQuizRequest(quiz)); + const [editedQuiz, editedQuizError] = await quizApi.edit( + quizToEditQuizRequest(quiz), + ); - setQuizBackendId(quizId, response.updated); - setEditQuizId(response.updated); - }) - .catch((error) => { - if (isAxiosCanceledError(error)) return; + if (editedQuizError || !editedQuiz) { + devlog("Error editing quiz", editedQuizError, quizId); + enqueueSnackbar(editedQuizError); - devlog("Error editing quiz", error, quizId); - enqueueSnackbar("Не удалось сохранить настройки quiz"); - }); + return; + } + + setQuizBackendId(quizId, editedQuiz.updated); + setEditQuizId(editedQuiz.updated); + }); }, REQUEST_DEBOUNCE); }; export const createQuiz = async (navigate: NavigateFunction) => requestQueue.enqueue("createQuiz", async () => { - try { - const rawQuiz = await quizApi.create(); - const quiz = rawQuizToQuiz(rawQuiz); + const [rawQuiz, createQuizError] = await quizApi.create(); - addQuiz(quiz); - setEditQuizId(quiz.backendId); - navigate("/edit"); - createUntypedQuestion(rawQuiz.id); - } catch (error) { - devlog("Error creating quiz", error); + if (createQuizError || !rawQuiz) { + devlog("Error creating quiz", createQuizError); + enqueueSnackbar(createQuizError); - const message = getMessageFromFetchError(error) ?? ""; - enqueueSnackbar(`Не удалось создать quiz. ${message}`); + return; } + + const quiz = rawQuizToQuiz(rawQuiz); + + addQuiz(quiz); + setEditQuizId(quiz.backendId); + navigate("/edit"); + createUntypedQuestion(rawQuiz.id); }); export const deleteQuiz = async (quizId: string) => @@ -199,16 +200,17 @@ export const deleteQuiz = async (quizId: string) => const quiz = useQuizStore.getState().quizes.find((q) => q.id === quizId); if (!quiz) return; - try { - await quizApi.delete(quiz.backendId); + const [_, deleteQuizError] = await quizApi.delete(quiz.backendId); - removeQuiz(quizId); - } catch (error) { - devlog("Error deleting quiz", error); + if (deleteQuizError) { + devlog("Error deleting quiz", deleteQuizError); - const message = getMessageFromFetchError(error) ?? ""; - enqueueSnackbar(`Не удалось удалить quiz. ${message}`); + enqueueSnackbar(deleteQuizError); + + return; } + + removeQuiz(quizId); }); export const updateRootContentId = (quizId: string, id: string) => { if (id.length === 0) { @@ -248,30 +250,28 @@ export const copyQuiz = async (quizId: string) => const quiz = useQuizStore.getState().quizes.find((q) => q.id === quizId); if (!quiz) return; - try { - const { updated } = await quizApi.copy(quiz.backendId); - let newQuiz: Quiz = { - ...quiz, - id: String(updated), - session_count: 0, - passed_count: 0, - }; + const [copiedQuiz, copyError] = await quizApi.copy(quiz.backendId); - setProducedState( - (state) => { - state.quizes.unshift(newQuiz); - }, - { - type: "addQuiz", - quiz, - }, - ); - } catch (error) { - devlog("Error copying quiz", error); + if (copyError || !copiedQuiz) { + devlog("Error copying quiz", copyError); + enqueueSnackbar(copyError); - const message = getMessageFromFetchError(error) ?? ""; - enqueueSnackbar(`Не удалось скопировать quiz. ${message}`); + return; } + + let newQuiz: Quiz = { + ...quiz, + id: String(copiedQuiz.updated), + session_count: 0, + passed_count: 0, + }; + + setProducedState( + (state) => { + state.quizes.unshift(newQuiz); + }, + { type: "addQuiz", quiz }, + ); }); export const uploadQuizImage = async ( @@ -282,28 +282,32 @@ export const uploadQuizImage = async ( const quiz = useQuizStore.getState().quizes.find((q) => q.id === quizId); if (!quiz) return; - try { - const response = await quizApi.addImages(quiz.backendId, blob); + const [addedImages, addImagesError] = await quizApi.addImages( + quiz.backendId, + blob, + ); - const values = Object.values(response); - if (values.length !== 1) { - console.warn("Error uploading image"); - return; - } + if (addImagesError || !addedImages) { + devlog("Error uploading quiz image", addImagesError); + enqueueSnackbar(addImagesError); - const imageId = values[0]; - - updateQuiz(quizId, (quiz) => { - updateFn( - quiz, - `https://storage.yandexcloud.net/squizimages/${quiz.qid}/${imageId}`, - ); - }); - } catch (error) { - devlog("Error uploading quiz image", error); - - enqueueSnackbar("Не удалось загрузить изображение"); + return; } + + const values = Object.values(addedImages); + if (values.length !== 1) { + console.warn("Error uploading image"); + return; + } + + const imageId = values[0]; + + updateQuiz(quizId, (quiz) => { + updateFn( + quiz, + `https://storage.yandexcloud.net/squizimages/${quiz.qid}/${imageId}`, + ); + }); }; function setProducedState( diff --git a/src/stores/quizes/hooks.ts b/src/stores/quizes/hooks.ts index b95ec60d..8d286212 100644 --- a/src/stores/quizes/hooks.ts +++ b/src/stores/quizes/hooks.ts @@ -11,7 +11,7 @@ export function useQuizes() { "quizes", () => quizApi.getList(), { - onSuccess: setQuizes, + onSuccess: ([quizes]) => setQuizes(quizes), onError: (error: unknown) => { const message = isAxiosError(error) ? error.response?.data ?? "" diff --git a/src/ui_kit/CheckFastlink.tsx b/src/ui_kit/CheckFastlink.tsx index dfa8bab3..f646cba9 100644 --- a/src/ui_kit/CheckFastlink.tsx +++ b/src/ui_kit/CheckFastlink.tsx @@ -1,18 +1,28 @@ -import {useEffect, useLayoutEffect, useRef, useState} from "react"; +import { useEffect, useLayoutEffect, useRef, useState } from "react"; import { Box, Button, Modal, Typography } from "@mui/material"; import { enqueueSnackbar } from "notistack"; import { mutate } from "swr"; -import makeRequest from "@api/makeRequest"; +import { makeRequest } from "@api/makeRequest"; import { getDiscounts } from "@api/discounts"; -import {clearUserData, OriginalUserAccount, setUserAccount, useUserStore} from "@root/user"; +import { + clearUserData, + OriginalUserAccount, + setUserAccount, + useUserStore, +} from "@root/user"; import { parseAxiosError } from "@utils/parse-error"; import { useUserAccountFetcher } from "../App"; import type { Discount } from "@model/discounts"; -import {clearAuthToken, createUserAccount, devlog, getMessageFromFetchError} from "@frontend/kitui"; -import {useNavigate} from "react-router-dom"; -import {isAxiosError} from "axios"; +import { + clearAuthToken, + createUserAccount, + devlog, + getMessageFromFetchError, +} from "@frontend/kitui"; +import { useNavigate } from "react-router-dom"; +import { isAxiosError } from "axios"; export function CheckFastlink() { const user = useUserStore(); @@ -21,9 +31,7 @@ export function CheckFastlink() { const [discounts, setDiscounts] = useState([]); const [askToChange, setAskToChange] = useState(false); const [promocode, setPromocode] = useState(""); - console.log( - user.userAccount, - user.customerAccount) + console.log(user.userAccount, user.customerAccount); useEffect(() => { const get = async () => { if (!user.userId) { @@ -53,7 +61,11 @@ export function CheckFastlink() { contentType: true, body: { fastLink: promocode }, }); - enqueueSnackbar(response.greetings !== "" ? response.greetings : "Промокод успешно активирован"); + enqueueSnackbar( + response.greetings !== "" + ? response.greetings + : "Промокод успешно активирован", + ); localStorage.setItem("fl", ""); const controller = new AbortController(); const responseAccount = await makeRequest({ @@ -63,8 +75,8 @@ export function CheckFastlink() { useToken: true, withCredentials: false, signal: controller.signal, - }) - setUserAccount(responseAccount) + }); + setUserAccount(responseAccount); mutate("discounts"); return response.greetings; } catch (nativeError) { @@ -104,8 +116,12 @@ export function CheckFastlink() { } } } - }, [user.userId, discounts, user.customerAccount?.createdAt, user.userAccount?.created_at]); - + }, [ + user.userId, + discounts, + user.customerAccount?.createdAt, + user.userAccount?.created_at, + ]); return ( { const message = getMessageFromFetchError(error); if (message) enqueueSnackbar(message); }, - onFetchStateChange: () => { }, + onFetchStateChange: () => {}, enabled: Boolean(user), }); From 7dc71b91e1b2487d490084ca2c38516cd83e3164 Mon Sep 17 00:00:00 2001 From: IlyaDoronin Date: Tue, 14 May 2024 17:27:14 +0300 Subject: [PATCH 2/2] fix: requests --- src/assets/icons/CopyIcon.tsx | 9 +- src/pages/DesignPage/DesignFilling.tsx | 2 +- .../QuizInstallationCard.tsx | 11 +- .../Instructions/VKInstruction.tsx | 6 +- .../Instructions/YandexInstruction.tsx | 6 +- src/pages/Landing/HowItWorks.tsx | 5 +- .../DraggableList/QuestionPageCardTitle.tsx | 541 +++++++++--------- src/pages/ResultPage/cards/ResultCard.tsx | 68 +-- .../tariffsUtils/createTariffElements.tsx | 8 +- src/stores/results/actions.ts | 8 +- 10 files changed, 343 insertions(+), 321 deletions(-) diff --git a/src/assets/icons/CopyIcon.tsx b/src/assets/icons/CopyIcon.tsx index 16409e1e..2079ab74 100644 --- a/src/assets/icons/CopyIcon.tsx +++ b/src/assets/icons/CopyIcon.tsx @@ -4,10 +4,15 @@ interface Props { color?: string; bgcolor?: string; marL?: string; - width?: string + width?: string; } -export default function CopyIcon({ color, bgcolor, marL, width = "36px" }: Props) { +export default function CopyIcon({ + color, + bgcolor, + marL, + width = "36px", +}: Props) { const theme = useTheme(); return ( diff --git a/src/pages/DesignPage/DesignFilling.tsx b/src/pages/DesignPage/DesignFilling.tsx index 74e744be..c6cbfd42 100644 --- a/src/pages/DesignPage/DesignFilling.tsx +++ b/src/pages/DesignPage/DesignFilling.tsx @@ -122,7 +122,7 @@ export const DesignFilling = ({ width: "100%", borderRadius: "12px", height: "calc(100vh - 300px)", - mb: "76px" + mb: "76px", }} > navigator.clipboard.writeText( // TODO + onClick={() => + navigator.clipboard.writeText( + // TODO document.getElementById( - "outlined-multiline-static" - ).value - )} + "outlined-multiline-static", + ).value, + ) + } > { • Посетитель отправил заявку с заполненным полем Х: - penaquiz-formfield-X, где X — одно из полей. - Например, + penaquiz-formfield-X, где X — одно из полей. Например, @@ -163,7 +162,8 @@ export const VKPixelInstruction = () => { - penaquiz-formfield-text (это будет кастомное поле, которое вы настроили сами) + penaquiz-formfield-text (это будет кастомное поле, + которое вы настроили сами) diff --git a/src/pages/IntegrationsPage/PartnersBoard/AnalyticsModal/IntsructionsBlock/Instructions/YandexInstruction.tsx b/src/pages/IntegrationsPage/PartnersBoard/AnalyticsModal/IntsructionsBlock/Instructions/YandexInstruction.tsx index b7ba8d52..310e520f 100644 --- a/src/pages/IntegrationsPage/PartnersBoard/AnalyticsModal/IntsructionsBlock/Instructions/YandexInstruction.tsx +++ b/src/pages/IntegrationsPage/PartnersBoard/AnalyticsModal/IntsructionsBlock/Instructions/YandexInstruction.tsx @@ -132,8 +132,7 @@ export const YandexInstruction = () => { • Посетитель отправил заявку с заполненным полем Х: - penaquiz-formfield-X, где X — одно из полей. - Например, + penaquiz-formfield-X, где X — одно из полей. Например, @@ -159,7 +158,8 @@ export const YandexInstruction = () => { - penaquiz-formfield-text (это будет кастомное поле, которое вы настроили сами) + penaquiz-formfield-text (это будет кастомное поле, + которое вы настроили сами) diff --git a/src/pages/Landing/HowItWorks.tsx b/src/pages/Landing/HowItWorks.tsx index 34accaba..55b1b05b 100644 --- a/src/pages/Landing/HowItWorks.tsx +++ b/src/pages/Landing/HowItWorks.tsx @@ -168,10 +168,7 @@ export default function HowItWorks() { }} > - - {" "} - на сайте - + на сайте (function ({ return ( <> - + + setTitle(target.value || " ")} + onFocus={handleInputFocus} + onBlur={handleInputBlur} + inputProps={{ + maxLength: maxLengthTextField, + }} + InputProps={{ + startAdornment: ( + + setOpen((isOpened) => !isOpened)} + > + {IconAndrom(isExpanded, questionType)} + + setOpen(false)} + anchorRef={anchorRef} + questionId={questionId} + questionContentId={questionContentId} + questionType={questionType} + /> + + ), + endAdornment: isTextFieldtActive && + title.length >= maxLengthTextField - 7 && ( + + {title.length} + / + + {maxLengthTextField} + + + ), + }} sx={{ + flexGrow: 1, + margin: isMobile ? "10px 0" : 0, + "& .MuiInputBase-root": { + color: "#000000", + backgroundColor: isExpanded + ? theme.palette.background.default + : "transparent", + height: "48px", + borderRadius: "10px", + ".MuiOutlinedInput-notchedOutline": { + borderWidth: "1px !important", + border: !isExpanded ? "none" : null, + }, + "& .MuiInputBase-input::placeholder": { + color: "#4D4D4D", + opacity: 0.8, + }, + }, + }} + /> + + + + + + toggleExpandQuestion(questionId)} + > + {isExpanded ? ( + + ) : ( + + )} + + {isExpanded ? ( + <> + ) : ( + + copyQuestion(questionId, quizId)} + > + + + { + if (questionType === null) { + deleteQuestion(questionId); + return; + } + if (questionHasParent) { + setOpenDelete(true); + } else { + deleteQuestionWithTimeout(questionId, () => + DeleteFunction(questionId), + ); + } + }} + data-cy="delete-question" + > + + + setOpenDelete(false)}> + + + Вы удаляете вопрос, участвующий в ветвлении. Все его потомки + потеряют данные ветвления. Вы уверены, что хотите удалить + вопрос? + + + + + + + + + )} + {page !== null && ( + - - setTitle(target.value || " ")} - onFocus={handleInputFocus} - onBlur={handleInputBlur} - inputProps={{ - maxLength: maxLengthTextField, - }} - InputProps={{ - startAdornment: ( - - setOpen((isOpened) => !isOpened)} - > - {IconAndrom(isExpanded, questionType)} - - setOpen(false)} - anchorRef={anchorRef} - questionId={questionId} - questionContentId={questionContentId} - questionType={questionType} - /> - - ), - endAdornment: isTextFieldtActive && - title.length >= maxLengthTextField - 7 && ( - - {title.length} - / - {maxLengthTextField} - - ), - }} - sx={{ - flexGrow: 1, - margin: isMobile ? "10px 0" : 0, - "& .MuiInputBase-root": { - color: "#000000", - backgroundColor: isExpanded - ? theme.palette.background.default - : "transparent", - height: "48px", - borderRadius: "10px", - ".MuiOutlinedInput-notchedOutline": { - borderWidth: "1px !important", - border: !isExpanded ? "none" : null, - }, - "& .MuiInputBase-input::placeholder": { - color: "#4D4D4D", - opacity: 0.8, - }, - }, - }} - /> - - - - - - toggleExpandQuestion(questionId)} - > - {isExpanded ? ( - - ) : ( - - )} - - {isExpanded ? ( - <> - ) : ( - - copyQuestion(questionId, quizId)} - > - - - { - if (questionType === null) { - deleteQuestion(questionId); - return; - } - if (questionHasParent) { - setOpenDelete(true); - } else { - deleteQuestionWithTimeout(questionId, () => - DeleteFunction(questionId), - ); - } - }} - data-cy="delete-question" - > - - - setOpenDelete(false)}> - - - Вы удаляете вопрос, участвующий в ветвлении. Все его потомки - потеряют данные ветвления. Вы уверены, что хотите удалить - вопрос? - - - - - - - - - )} - {page !== null && ( - - {page + 1} - - )} + {page + 1} - + )} - {questionType !== null && - + {questionType !== null && ( + - ID Вопроса - {questionBackendId} - navigator.clipboard.writeText(document.querySelector("#id-copy").innerText) - } - > - - - } + padding: "0 20px 20px 20px", + }} + > + ID Вопроса + {questionBackendId} + + navigator.clipboard.writeText( + document.querySelector("#id-copy").innerText, + ) + } + > + + + + )} ); }); diff --git a/src/pages/ResultPage/cards/ResultCard.tsx b/src/pages/ResultPage/cards/ResultCard.tsx index 7fdc033a..0a3b2758 100644 --- a/src/pages/ResultPage/cards/ResultCard.tsx +++ b/src/pages/ResultPage/cards/ResultCard.tsx @@ -9,16 +9,17 @@ import { useCurrentQuiz } from "@root/quizes/hooks"; import CustomTextField from "@ui_kit/CustomTextField"; import { - Box, - IconButton, - Paper, - Button, - Typography, - TextField, - useMediaQuery, - useTheme, - FormControl, - Popover, InputAdornment, + Box, + IconButton, + Paper, + Button, + Typography, + TextField, + useMediaQuery, + useTheme, + FormControl, + Popover, + InputAdornment, } from "@mui/material"; import MiniButtonSetting from "@ui_kit/MiniButtonSetting"; @@ -260,28 +261,31 @@ export const ResultCard = ({ resultContract, resultData }: Props) => { }} > - - ID результата - {resultData.backendId} - navigator.clipboard.writeText(document.querySelector("#id-copy").innerText) - } - > - - - + + ID результата + {resultData.backendId} + + navigator.clipboard.writeText( + document.querySelector("#id-copy").innerText, + ) + } + > + + + - {currencyFormatter.format(Math.trunc(priceBeforeDiscounts) / 100)} + {currencyFormatter.format( + Math.trunc(priceBeforeDiscounts) / 100, + )} )} - {currencyFormatter.format(Math.trunc(priceAfterDiscounts) / 100)} + {currencyFormatter.format( + Math.trunc(priceAfterDiscounts) / 100, + )} } diff --git a/src/stores/results/actions.ts b/src/stores/results/actions.ts index aa6eb4e4..d1d09ef9 100644 --- a/src/stores/results/actions.ts +++ b/src/stores/results/actions.ts @@ -96,13 +96,15 @@ export const ExportResults = async ( parseFilters(filterNew, filterDate), ); - console.log(typeof data) + console.log(typeof data); - const blob = new Blob([data as BlobPart], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8" }); + const blob = new Blob([data as BlobPart], { + type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8", + }); const link = document.createElement("a"); link.href = window.URL.createObjectURL(data as Blob); - console.log(link) + console.log(link); link.download = `report_${new Date().getTime()}.xlsx`; link.click(); } catch (nativeError) {