внесён багрепорт
This commit is contained in:
parent
05f2fc33f9
commit
ac692fafd3
@ -6,7 +6,7 @@
|
||||
"@craco/craco": "^7.0.0",
|
||||
"@emotion/react": "^11.10.5",
|
||||
"@emotion/styled": "^11.10.5",
|
||||
"@frontend/kitui": "^1.0.109",
|
||||
"@frontend/kitui": "^1.0.110",
|
||||
"@frontend/squzanswerer": "^1.0.57",
|
||||
"@mui/icons-material": "^5.10.14",
|
||||
"@mui/material": "^5.10.14",
|
||||
|
58
src/App.tsx
58
src/App.tsx
@ -1,4 +1,4 @@
|
||||
import { clearAuthToken, getMessageFromFetchError, UserAccount, useUserFetcher } from "@frontend/kitui";
|
||||
import { clearAuthToken, getMessageFromFetchError, handleComponentError, UserAccount, useTicketsFetcher, useUserFetcher } from "@frontend/kitui";
|
||||
import type { OriginalUserAccount } from "@root/user";
|
||||
import { clearUserData, setCustomerAccount, setUser, setUserAccount, useUserStore } from "@root/user";
|
||||
import ContactFormModal from "@ui_kit/ContactForm";
|
||||
@ -8,7 +8,7 @@ import { useAfterPay } from "@utils/hooks/useAutoPay";
|
||||
import { useUserAccountFetcher } from "@utils/hooks/useUserAccountFetcher";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
import type { SuspenseProps } from "react";
|
||||
import { lazy, Suspense } from "react";
|
||||
import { lazy, Suspense, useEffect } from "react";
|
||||
import { lazily } from "react-lazily";
|
||||
import { Navigate, Route, Routes, useLocation, useNavigate } from "react-router-dom";
|
||||
import { useAmoAccount } from "./api/integration";
|
||||
@ -23,6 +23,9 @@ import { InfoPrivilege } from "./pages/InfoPrivilege";
|
||||
import AmoTokenExpiredDialog from "./pages/IntegrationsPage/IntegrationsModal/Amo/AmoTokenExpiredDialog";
|
||||
import Landing from "./pages/Landing/Landing";
|
||||
import Main from "./pages/main";
|
||||
import Debug from "./pages/Debug";
|
||||
import { setTicketData, setTickets, useTicketStore } from "./stores/ticket";
|
||||
import { parseAxiosError } from "./utils/parse-error";
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
|
||||
const MyQuizzesFull = lazy(() => import("./pages/createQuize/MyQuizzesFull"));
|
||||
@ -73,12 +76,16 @@ const LazyLoading = ({ children, fallback }: SuspenseProps) => (
|
||||
<Suspense fallback={fallback ?? <></>}>{children}</Suspense>
|
||||
);
|
||||
|
||||
const ApologyPage = () => <div><p>Что-то пошло не так</p></div>
|
||||
|
||||
export default function App() {
|
||||
window.LoadingObserver = false;
|
||||
const userId = useUserStore((state) => state.userId);
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const { data: amoAccount } = useAmoAccount();
|
||||
const tickets = useTicketStore(store => store.tickets);
|
||||
|
||||
|
||||
useUserFetcher({
|
||||
url: `${process.env.REACT_APP_DOMAIN}/user/${userId}`,
|
||||
@ -133,6 +140,37 @@ export default function App() {
|
||||
},
|
||||
});
|
||||
|
||||
useTicketsFetcher({
|
||||
url: `${process.env.REACT_APP_DOMAIN}/heruvym/v1.0.0/getTickets`,
|
||||
ticketsPerPage: 10,
|
||||
ticketApiPage: 0,
|
||||
onSuccess: (result) => {
|
||||
if (result.data?.length) {
|
||||
// Записываем все тикеты в стор
|
||||
setTickets(result.data);
|
||||
|
||||
const currentTicket = result.data.find(
|
||||
({ origin }) => !origin.includes("/support"),
|
||||
);
|
||||
|
||||
if (!currentTicket) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTicketData({
|
||||
ticketId: currentTicket.id,
|
||||
sessionId: currentTicket.sess,
|
||||
});
|
||||
}
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
const message = parseAxiosError(error);
|
||||
if (message) enqueueSnackbar(message);
|
||||
},
|
||||
onFetchStateChange: () => { },
|
||||
enabled: Boolean(userId),
|
||||
});
|
||||
|
||||
useAfterPay();
|
||||
|
||||
if (location.state?.redirectTo)
|
||||
@ -145,9 +183,12 @@ export default function App() {
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ErrorBoundary
|
||||
FallbackComponent={ApologyPage}
|
||||
onError={(error, info) => handleComponentError(error, info, tickets)}
|
||||
>
|
||||
{amoAccount && <AmoTokenExpiredDialog isAmoTokenExpired={amoAccount.stale} />}
|
||||
|
||||
|
||||
<ContactFormModal />
|
||||
{!isTest && <FloatingSupportChat />}
|
||||
{location.state?.backgroundLocation && (
|
||||
@ -268,6 +309,10 @@ export default function App() {
|
||||
path={"/image/:srcImage"}
|
||||
element={<ChatImageNewWindow />}
|
||||
/>
|
||||
<Route
|
||||
path={"/debug"}
|
||||
element={<div></div>}
|
||||
/>
|
||||
<Route element={<PrivateRoute />}>
|
||||
{routeslink.map((e, i) => (
|
||||
<Route
|
||||
@ -289,6 +334,9 @@ export default function App() {
|
||||
))}
|
||||
</Route>
|
||||
</Routes>
|
||||
</>
|
||||
|
||||
{/* Компонент отладки ошибок - доступен по Ctrl+Shift+D */}
|
||||
<Debug />
|
||||
</ErrorBoundary>
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { QuestionKeys } from "@/pages/IntegrationsPage/IntegrationsModal/Amo/types";
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import { useToken } from "@frontend/kitui";
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
import useSWR from "swr";
|
||||
|
@ -1,55 +0,0 @@
|
||||
import * as KIT from "@frontend/kitui";
|
||||
import { Method, ResponseType, AxiosError } from "axios";
|
||||
import { redirect } from "react-router-dom";
|
||||
import { clearAuthToken } from "@frontend/kitui";
|
||||
|
||||
import { cleanAuthTicketData } from "@root/ticket";
|
||||
import { clearUserData } from "@root/user";
|
||||
import { clearQuizData } from "@root/quizes/store";
|
||||
|
||||
import type { AxiosResponse } from "axios";
|
||||
import { selectSendingMethod } from "@/ui_kit/FloatingSupportChat/utils";
|
||||
|
||||
interface MakeRequest {
|
||||
method?: Method | undefined;
|
||||
url: string;
|
||||
body?: unknown;
|
||||
useToken?: boolean | undefined;
|
||||
contentType?: boolean | undefined;
|
||||
responseType?: ResponseType | undefined;
|
||||
signal?: AbortSignal | undefined;
|
||||
withCredentials?: boolean | undefined;
|
||||
}
|
||||
|
||||
type ExtendedAxiosResponse = AxiosResponse & { message: string };
|
||||
|
||||
export const makeRequest = async <TRequest = unknown, TResponse = unknown>(
|
||||
data: MakeRequest,
|
||||
): Promise<TResponse> => {
|
||||
try {
|
||||
const response = await KIT.makeRequest<unknown, TResponse>(data);
|
||||
|
||||
return response;
|
||||
} catch (nativeError) {
|
||||
const error = nativeError as AxiosError;
|
||||
|
||||
// if (window.location.hostname !== 'localhost') selectSendingMethod({
|
||||
// messageField: `status: ${error.response?.status}. Message ${(error.response?.data as ExtendedAxiosResponse)?.message}`,
|
||||
// isSnackbar: false,
|
||||
// systemError: true
|
||||
// });
|
||||
if (
|
||||
error.response?.status === 400 &&
|
||||
(error.response?.data as ExtendedAxiosResponse)?.message ===
|
||||
"refreshToken is empty"
|
||||
) {
|
||||
cleanAuthTicketData();
|
||||
clearAuthToken();
|
||||
clearUserData();
|
||||
clearQuizData();
|
||||
redirect("/");
|
||||
}
|
||||
|
||||
throw nativeError;
|
||||
}
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { replaceSpacesToEmptyLines } from "@utils/replaceSpacesToEmptyLines";
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import { defaultQuizConfig } from "@model/quizSettings";
|
||||
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
import type { GetTariffsResponse } from "@frontend/kitui";
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { createTicket as createTicketRequest } from "@frontend/kitui";
|
||||
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
|
||||
|
@ -18,7 +18,7 @@ import CloseIcon from "@icons/CloseBold";
|
||||
import type { SnackbarKey } from "notistack";
|
||||
import { CheckFastlink } from "@ui_kit/CheckFastlink";
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
import { handleComponentError } from "./utils/handleComponentError";
|
||||
import { handleComponentError } from "@frontend/kitui";
|
||||
|
||||
moment.locale("ru");
|
||||
polyfillCountryFlagEmojis();
|
||||
@ -38,7 +38,6 @@ const snackbarAction = (snackbarId: SnackbarKey) => (
|
||||
</Button>
|
||||
);
|
||||
|
||||
const ApologyPage = () => <div><p>Что-то пошло не так</p></div>
|
||||
|
||||
const root = createRoot(document.getElementById("root")!);
|
||||
|
||||
@ -65,12 +64,7 @@ root.render(
|
||||
>
|
||||
<CssBaseline />
|
||||
|
||||
<ErrorBoundary
|
||||
FallbackComponent={ApologyPage}
|
||||
onError={handleComponentError}
|
||||
>
|
||||
<App />
|
||||
</ErrorBoundary>
|
||||
<CheckFastlink />
|
||||
</SnackbarProvider>
|
||||
</BrowserRouter>
|
||||
|
149
src/pages/Debug.tsx
Normal file
149
src/pages/Debug.tsx
Normal file
@ -0,0 +1,149 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Typography,
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableContainer,
|
||||
TableHead,
|
||||
TableRow,
|
||||
Paper
|
||||
} from '@mui/material';
|
||||
|
||||
// Функции для создания тестовых ошибок
|
||||
const createTestError = (message: string) => {
|
||||
const error = new Error(message);
|
||||
(error as any).__forceSend = true;
|
||||
throw error;
|
||||
};
|
||||
|
||||
const createReactComponentError = (message: string) => {
|
||||
const error = new Error(message);
|
||||
(error as any).__forceSend = true;
|
||||
throw error;
|
||||
};
|
||||
|
||||
/**
|
||||
* Простая страница отладки системы обработки ошибок
|
||||
* Активируется по Ctrl+Shift+F
|
||||
*/
|
||||
const Debug: React.FC = () => {
|
||||
const [isVisible, setIsVisible] = useState(false);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.ctrlKey && event.shiftKey && event.code === 'KeyF') {
|
||||
event.preventDefault();
|
||||
setIsVisible(!isVisible);
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return () => window.removeEventListener('keydown', handleKeyDown);
|
||||
}, [isVisible]);
|
||||
|
||||
if (!isVisible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const errorTests = [
|
||||
{
|
||||
description: 'Простая ошибка',
|
||||
action: () => {
|
||||
createTestError('Тестовая ошибка отладки');
|
||||
}
|
||||
},
|
||||
{
|
||||
description: 'React ошибка компонента',
|
||||
action: () => {
|
||||
createReactComponentError('Тестовая ошибка React компонента');
|
||||
}
|
||||
},
|
||||
{
|
||||
description: 'Прямая ошибка в обработчике',
|
||||
action: () => {
|
||||
const error = new Error('Прямая ошибка в компоненте');
|
||||
(error as any).__forceSend = true;
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
{
|
||||
description: 'Ошибка с длинным стеком',
|
||||
action: () => {
|
||||
const deepError = new Error('Глубокая ошибка с длинным стеком');
|
||||
deepError.stack = 'Error: Глубокая ошибка\n at level1 (debug.ts:10)\n at level2 (debug.ts:15)\n at level3 (debug.ts:20)\n at level4 (debug.ts:25)';
|
||||
(deepError as any).__forceSend = true;
|
||||
throw deepError;
|
||||
}
|
||||
},
|
||||
{
|
||||
description: 'Ошибка с undefined',
|
||||
action: () => {
|
||||
const obj: any = null;
|
||||
try {
|
||||
obj.nonExistentMethod();
|
||||
} catch (error) {
|
||||
(error as any).__forceSend = true;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
return (
|
||||
<Box sx={{
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
bgcolor: 'rgba(0,0,0,0.9)',
|
||||
zIndex: 9999,
|
||||
p: 4,
|
||||
overflow: 'auto'
|
||||
}}>
|
||||
<Box sx={{ maxWidth: 800, mx: 'auto', bgcolor: 'background.paper', p: 3, borderRadius: 2 }}>
|
||||
<Typography variant="h4" gutterBottom>
|
||||
🛠️ Отладка ошибок
|
||||
</Typography>
|
||||
|
||||
<Typography variant="body2" sx={{ mb: 3, color: 'text.secondary' }}>
|
||||
Ctrl+Shift+F для закрытия
|
||||
</Typography>
|
||||
|
||||
<TableContainer component={Paper}>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<TableCell>Описание ошибки</TableCell>
|
||||
<TableCell align="right">Действие</TableCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{errorTests.map((test, index) => (
|
||||
<TableRow key={index}>
|
||||
<TableCell>{test.description}</TableCell>
|
||||
<TableCell align="right">
|
||||
<Button
|
||||
variant="contained"
|
||||
color="error"
|
||||
size="small"
|
||||
onClick={test.action}
|
||||
>
|
||||
Вызвать
|
||||
</Button>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Debug;
|
@ -353,7 +353,7 @@ export const useAmoIntegration = ({ isModalOpen, isTryRemoveAccount, quizID, que
|
||||
};
|
||||
};
|
||||
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
const API_URL = `${process.env.REACT_APP_DOMAIN}/squiz/amocrm`;
|
||||
|
||||
export const resetAmoTagsFields = async () => {
|
||||
|
@ -16,7 +16,7 @@ import { inCart } from "../Tariffs/utils";
|
||||
import { isTestServer } from "@/utils/hooks/useDomainDefine";
|
||||
import { useToken } from "@frontend/kitui";
|
||||
import { useSWRConfig } from "swr";
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import { setUserAccount, setCustomerAccount } from "@/stores/user";
|
||||
import { quizApi } from "@api/quiz";
|
||||
import { setQuizes } from "@root/quizes/actions";
|
||||
|
@ -18,7 +18,7 @@ import { object, string } from "yup";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useUserStore } from "@root/user";
|
||||
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import { setAuthToken } from "@frontend/kitui";
|
||||
import { parseAxiosError } from "@utils/parse-error";
|
||||
import { recoverUser } from "@api/user";
|
||||
|
@ -7,7 +7,7 @@ import { Box, Button, IconButton, Popover, Typography, useMediaQuery, useTheme }
|
||||
import { deleteQuiz, setEditQuizId } from "@root/quizes/actions";
|
||||
import { Link, useNavigate } from "react-router-dom";
|
||||
import { inCart } from "../../pages/Tariffs/utils";
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
import { useDomainDefine } from "@utils/hooks/useDomainDefine";
|
||||
import CopyIcon from "@icons/CopyIcon";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { FetchState, TicketMessage } from "@frontend/kitui";
|
||||
import { FetchState, Ticket, TicketMessage } from "@frontend/kitui";
|
||||
import { create } from "zustand";
|
||||
import { createJSONStorage, devtools, persist } from "zustand/middleware";
|
||||
import { useUserStore } from "./user";
|
||||
@ -21,11 +21,12 @@ interface AuthData {
|
||||
interface TicketStore {
|
||||
unauthData: AuthData;
|
||||
authData: AuthData;
|
||||
tickets: Ticket[];
|
||||
}
|
||||
|
||||
let params = new URLSearchParams(document.location.search);
|
||||
|
||||
const debug = params.get("debug");
|
||||
|
||||
const initAuthData = {
|
||||
sessionData: null,
|
||||
isMessageSending: false,
|
||||
@ -35,10 +36,12 @@ const initAuthData = {
|
||||
lastMessageId: undefined,
|
||||
isPreventAutoscroll: false,
|
||||
unauthTicketMessageFetchState: "idle" as FetchState,
|
||||
tickets: []
|
||||
};
|
||||
const initState = {
|
||||
unauthData: initAuthData,
|
||||
authData: initAuthData,
|
||||
tickets: []
|
||||
};
|
||||
|
||||
export const useTicketStore = create<TicketStore>()(
|
||||
@ -156,9 +159,17 @@ export const updateTicket = <T extends AuthData>(
|
||||
},
|
||||
);
|
||||
|
||||
function setProducedState<A extends string | { type: unknown }>(
|
||||
function setProducedState<A extends string | { type: string }>(
|
||||
recipe: (state: TicketStore) => void,
|
||||
action?: A,
|
||||
) {
|
||||
useTicketStore.setState((state) => produce(state, recipe), false, action);
|
||||
}
|
||||
|
||||
// Функция для записи тикетов в стор
|
||||
export const setTickets = (tickets: Ticket[] | null) => {
|
||||
useTicketStore.setState((state) => ({
|
||||
...state,
|
||||
tickets: tickets || []
|
||||
}), false);
|
||||
};
|
||||
|
@ -3,7 +3,7 @@ import { Box, Button, Modal, Typography } from "@mui/material";
|
||||
import { enqueueSnackbar } from "notistack";
|
||||
import { mutate } from "swr";
|
||||
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import { getDiscounts } from "@api/discounts";
|
||||
|
||||
import { clearUserData, OriginalUserAccount, setUserAccount, useUserStore } from "@root/user";
|
||||
|
@ -72,33 +72,6 @@ export default () => {
|
||||
setIsChatOpened((state) => !state);
|
||||
};
|
||||
|
||||
useTicketsFetcher({
|
||||
url: `${process.env.REACT_APP_DOMAIN}/heruvym/v1.0.0/getTickets`,
|
||||
ticketsPerPage: 10,
|
||||
ticketApiPage: 0,
|
||||
onSuccess: (result) => {
|
||||
if (result.data?.length) {
|
||||
const currentTicket = result.data.find(
|
||||
({ origin }) => !origin.includes("/support"),
|
||||
);
|
||||
|
||||
if (!currentTicket) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTicketData({
|
||||
ticketId: currentTicket.id,
|
||||
sessionId: currentTicket.sess,
|
||||
});
|
||||
}
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
const message = parseAxiosError(error);
|
||||
if (message) enqueueSnackbar(message);
|
||||
},
|
||||
onFetchStateChange: () => { },
|
||||
enabled: Boolean(user),
|
||||
});
|
||||
|
||||
useTicketMessages({
|
||||
url: `${process.env.REACT_APP_DOMAIN}/heruvym/v1.0.0/getMessages`,
|
||||
|
@ -1,47 +0,0 @@
|
||||
import { selectSendingMethod } from "@/ui_kit/FloatingSupportChat/utils";
|
||||
import { ErrorInfo } from "react";
|
||||
|
||||
interface ComponentError {
|
||||
timestamp: number;
|
||||
message: string;
|
||||
callStack: string | undefined;
|
||||
componentStack: string | null | undefined;
|
||||
}
|
||||
|
||||
export function handleComponentError(error: Error, info: ErrorInfo) {
|
||||
const componentError: ComponentError = {
|
||||
timestamp: Math.floor(Date.now() / 1000),
|
||||
message: error.message,
|
||||
callStack: error.stack,
|
||||
componentStack: info.componentStack,
|
||||
};
|
||||
|
||||
queueErrorRequest(componentError);
|
||||
}
|
||||
|
||||
let errorsQueue: ComponentError[] = [];
|
||||
let timeoutId: ReturnType<typeof setTimeout>;
|
||||
|
||||
function queueErrorRequest(error: ComponentError) {
|
||||
errorsQueue.push(error);
|
||||
|
||||
clearTimeout(timeoutId);
|
||||
timeoutId = setTimeout(() => {
|
||||
sendErrorsToServer();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
async function sendErrorsToServer() {
|
||||
// makeRequest({
|
||||
// url: "",
|
||||
// method: "POST",
|
||||
// body: errorsQueue,
|
||||
// useToken: true,
|
||||
// });
|
||||
// selectSendingMethod({
|
||||
// messageField: `Fake-sending ${errorsQueue.length} errors to server ${JSON.stringify(errorsQueue)}`,
|
||||
// isSnackbar: false,
|
||||
// systemError: true
|
||||
// });
|
||||
// errorsQueue = [];
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { useEffect, useLayoutEffect, useRef } from "react";
|
||||
import { createUserAccount, devlog } from "@frontend/kitui";
|
||||
import { isAxiosError } from "axios";
|
||||
import { makeRequest } from "@api/makeRequest";
|
||||
import { makeRequest } from "@frontend/kitui";
|
||||
import type { UserAccount } from "@frontend/kitui";
|
||||
import { setUserAccount } from "@/stores/user";
|
||||
|
||||
|
@ -1443,10 +1443,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429"
|
||||
integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==
|
||||
|
||||
"@frontend/kitui@^1.0.109":
|
||||
version "1.0.109"
|
||||
resolved "http://gitea.pena/api/packages/skeris/npm/%40frontend%2Fkitui/-/1.0.109/kitui-1.0.109.tgz#a9611e7b69dbd2bbc46e78c083d0442fc22bdcef"
|
||||
integrity sha512-y6wzLDEWfTXMjL2gDucs/AzAc0fyh80aIbiokGz1ZgaHMR0XQhV2E/VqlUvK95VZRFO7UqnEaJofpY7iwSQjQA==
|
||||
"@frontend/kitui@^1.0.110":
|
||||
version "1.0.110"
|
||||
resolved "http://gitea.pena/api/packages/skeris/npm/%40frontend%2Fkitui/-/1.0.110/kitui-1.0.110.tgz#969f70636508e9efd6c8d81e62a6913b18a0c029"
|
||||
integrity sha512-M+U9a4qylLb9ZOUn57v7lm/Rutqicm04vJsJrxeAY/6G4ma1bC29toOZwTt/uJUlF4gk4ojyWIIjiGTVM1/hKQ==
|
||||
dependencies:
|
||||
immer "^10.0.2"
|
||||
reconnecting-eventsource "^1.6.2"
|
||||
|
Loading…
Reference in New Issue
Block a user