внесён багрепорт
This commit is contained in:
parent
05f2fc33f9
commit
ac692fafd3
@ -6,7 +6,7 @@
|
|||||||
"@craco/craco": "^7.0.0",
|
"@craco/craco": "^7.0.0",
|
||||||
"@emotion/react": "^11.10.5",
|
"@emotion/react": "^11.10.5",
|
||||||
"@emotion/styled": "^11.10.5",
|
"@emotion/styled": "^11.10.5",
|
||||||
"@frontend/kitui": "^1.0.109",
|
"@frontend/kitui": "^1.0.110",
|
||||||
"@frontend/squzanswerer": "^1.0.57",
|
"@frontend/squzanswerer": "^1.0.57",
|
||||||
"@mui/icons-material": "^5.10.14",
|
"@mui/icons-material": "^5.10.14",
|
||||||
"@mui/material": "^5.10.14",
|
"@mui/material": "^5.10.14",
|
||||||
|
56
src/App.tsx
56
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 type { OriginalUserAccount } from "@root/user";
|
||||||
import { clearUserData, setCustomerAccount, setUser, setUserAccount, useUserStore } from "@root/user";
|
import { clearUserData, setCustomerAccount, setUser, setUserAccount, useUserStore } from "@root/user";
|
||||||
import ContactFormModal from "@ui_kit/ContactForm";
|
import ContactFormModal from "@ui_kit/ContactForm";
|
||||||
@ -8,7 +8,7 @@ import { useAfterPay } from "@utils/hooks/useAutoPay";
|
|||||||
import { useUserAccountFetcher } from "@utils/hooks/useUserAccountFetcher";
|
import { useUserAccountFetcher } from "@utils/hooks/useUserAccountFetcher";
|
||||||
import { enqueueSnackbar } from "notistack";
|
import { enqueueSnackbar } from "notistack";
|
||||||
import type { SuspenseProps } from "react";
|
import type { SuspenseProps } from "react";
|
||||||
import { lazy, Suspense } from "react";
|
import { lazy, Suspense, useEffect } from "react";
|
||||||
import { lazily } from "react-lazily";
|
import { lazily } from "react-lazily";
|
||||||
import { Navigate, Route, Routes, useLocation, useNavigate } from "react-router-dom";
|
import { Navigate, Route, Routes, useLocation, useNavigate } from "react-router-dom";
|
||||||
import { useAmoAccount } from "./api/integration";
|
import { useAmoAccount } from "./api/integration";
|
||||||
@ -23,6 +23,9 @@ import { InfoPrivilege } from "./pages/InfoPrivilege";
|
|||||||
import AmoTokenExpiredDialog from "./pages/IntegrationsPage/IntegrationsModal/Amo/AmoTokenExpiredDialog";
|
import AmoTokenExpiredDialog from "./pages/IntegrationsPage/IntegrationsModal/Amo/AmoTokenExpiredDialog";
|
||||||
import Landing from "./pages/Landing/Landing";
|
import Landing from "./pages/Landing/Landing";
|
||||||
import Main from "./pages/main";
|
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";
|
import { ErrorBoundary } from "react-error-boundary";
|
||||||
|
|
||||||
const MyQuizzesFull = lazy(() => import("./pages/createQuize/MyQuizzesFull"));
|
const MyQuizzesFull = lazy(() => import("./pages/createQuize/MyQuizzesFull"));
|
||||||
@ -73,12 +76,16 @@ const LazyLoading = ({ children, fallback }: SuspenseProps) => (
|
|||||||
<Suspense fallback={fallback ?? <></>}>{children}</Suspense>
|
<Suspense fallback={fallback ?? <></>}>{children}</Suspense>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const ApologyPage = () => <div><p>Что-то пошло не так</p></div>
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
window.LoadingObserver = false;
|
window.LoadingObserver = false;
|
||||||
const userId = useUserStore((state) => state.userId);
|
const userId = useUserStore((state) => state.userId);
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { data: amoAccount } = useAmoAccount();
|
const { data: amoAccount } = useAmoAccount();
|
||||||
|
const tickets = useTicketStore(store => store.tickets);
|
||||||
|
|
||||||
|
|
||||||
useUserFetcher({
|
useUserFetcher({
|
||||||
url: `${process.env.REACT_APP_DOMAIN}/user/${userId}`,
|
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();
|
useAfterPay();
|
||||||
|
|
||||||
if (location.state?.redirectTo)
|
if (location.state?.redirectTo)
|
||||||
@ -145,7 +183,10 @@ export default function App() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<ErrorBoundary
|
||||||
|
FallbackComponent={ApologyPage}
|
||||||
|
onError={(error, info) => handleComponentError(error, info, tickets)}
|
||||||
|
>
|
||||||
{amoAccount && <AmoTokenExpiredDialog isAmoTokenExpired={amoAccount.stale} />}
|
{amoAccount && <AmoTokenExpiredDialog isAmoTokenExpired={amoAccount.stale} />}
|
||||||
|
|
||||||
<ContactFormModal />
|
<ContactFormModal />
|
||||||
@ -268,6 +309,10 @@ export default function App() {
|
|||||||
path={"/image/:srcImage"}
|
path={"/image/:srcImage"}
|
||||||
element={<ChatImageNewWindow />}
|
element={<ChatImageNewWindow />}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path={"/debug"}
|
||||||
|
element={<div></div>}
|
||||||
|
/>
|
||||||
<Route element={<PrivateRoute />}>
|
<Route element={<PrivateRoute />}>
|
||||||
{routeslink.map((e, i) => (
|
{routeslink.map((e, i) => (
|
||||||
<Route
|
<Route
|
||||||
@ -289,6 +334,9 @@ export default function App() {
|
|||||||
))}
|
))}
|
||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</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";
|
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 { 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 { parseAxiosError } from "@utils/parse-error";
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { QuestionKeys } from "@/pages/IntegrationsPage/IntegrationsModal/Amo/types";
|
import { QuestionKeys } from "@/pages/IntegrationsPage/IntegrationsModal/Amo/types";
|
||||||
import { makeRequest } from "@api/makeRequest";
|
import { makeRequest } from "@frontend/kitui";
|
||||||
import { useToken } from "@frontend/kitui";
|
import { useToken } from "@frontend/kitui";
|
||||||
import { parseAxiosError } from "@utils/parse-error";
|
import { parseAxiosError } from "@utils/parse-error";
|
||||||
import useSWR from "swr";
|
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";
|
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 { replaceSpacesToEmptyLines } from "@utils/replaceSpacesToEmptyLines";
|
||||||
import { parseAxiosError } from "@utils/parse-error";
|
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 { defaultQuizConfig } from "@model/quizSettings";
|
||||||
|
|
||||||
import { parseAxiosError } from "@utils/parse-error";
|
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 { 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 { 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 { parseAxiosError } from "@utils/parse-error";
|
||||||
import type { GetTariffsResponse } from "@frontend/kitui";
|
import type { GetTariffsResponse } from "@frontend/kitui";
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { createTicket as createTicketRequest } from "@frontend/kitui";
|
import { createTicket as createTicketRequest } from "@frontend/kitui";
|
||||||
|
|
||||||
import { makeRequest } from "@api/makeRequest";
|
import { makeRequest } from "@frontend/kitui";
|
||||||
|
|
||||||
import { parseAxiosError } from "@utils/parse-error";
|
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 { parseAxiosError } from "@utils/parse-error";
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import CloseIcon from "@icons/CloseBold";
|
|||||||
import type { SnackbarKey } from "notistack";
|
import type { SnackbarKey } from "notistack";
|
||||||
import { CheckFastlink } from "@ui_kit/CheckFastlink";
|
import { CheckFastlink } from "@ui_kit/CheckFastlink";
|
||||||
import { ErrorBoundary } from "react-error-boundary";
|
import { ErrorBoundary } from "react-error-boundary";
|
||||||
import { handleComponentError } from "./utils/handleComponentError";
|
import { handleComponentError } from "@frontend/kitui";
|
||||||
|
|
||||||
moment.locale("ru");
|
moment.locale("ru");
|
||||||
polyfillCountryFlagEmojis();
|
polyfillCountryFlagEmojis();
|
||||||
@ -38,7 +38,6 @@ const snackbarAction = (snackbarId: SnackbarKey) => (
|
|||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
|
||||||
const ApologyPage = () => <div><p>Что-то пошло не так</p></div>
|
|
||||||
|
|
||||||
const root = createRoot(document.getElementById("root")!);
|
const root = createRoot(document.getElementById("root")!);
|
||||||
|
|
||||||
@ -65,12 +64,7 @@ root.render(
|
|||||||
>
|
>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
|
|
||||||
<ErrorBoundary
|
|
||||||
FallbackComponent={ApologyPage}
|
|
||||||
onError={handleComponentError}
|
|
||||||
>
|
|
||||||
<App />
|
<App />
|
||||||
</ErrorBoundary>
|
|
||||||
<CheckFastlink />
|
<CheckFastlink />
|
||||||
</SnackbarProvider>
|
</SnackbarProvider>
|
||||||
</BrowserRouter>
|
</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`;
|
const API_URL = `${process.env.REACT_APP_DOMAIN}/squiz/amocrm`;
|
||||||
|
|
||||||
export const resetAmoTagsFields = async () => {
|
export const resetAmoTagsFields = async () => {
|
||||||
|
@ -16,7 +16,7 @@ import { inCart } from "../Tariffs/utils";
|
|||||||
import { isTestServer } from "@/utils/hooks/useDomainDefine";
|
import { isTestServer } from "@/utils/hooks/useDomainDefine";
|
||||||
import { useToken } from "@frontend/kitui";
|
import { useToken } from "@frontend/kitui";
|
||||||
import { useSWRConfig } from "swr";
|
import { useSWRConfig } from "swr";
|
||||||
import { makeRequest } from "@api/makeRequest";
|
import { makeRequest } from "@frontend/kitui";
|
||||||
import { setUserAccount, setCustomerAccount } from "@/stores/user";
|
import { setUserAccount, setCustomerAccount } from "@/stores/user";
|
||||||
import { quizApi } from "@api/quiz";
|
import { quizApi } from "@api/quiz";
|
||||||
import { setQuizes } from "@root/quizes/actions";
|
import { setQuizes } from "@root/quizes/actions";
|
||||||
|
@ -18,7 +18,7 @@ import { object, string } from "yup";
|
|||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useUserStore } from "@root/user";
|
import { useUserStore } from "@root/user";
|
||||||
|
|
||||||
import { makeRequest } from "@api/makeRequest";
|
import { makeRequest } from "@frontend/kitui";
|
||||||
import { setAuthToken } from "@frontend/kitui";
|
import { setAuthToken } from "@frontend/kitui";
|
||||||
import { parseAxiosError } from "@utils/parse-error";
|
import { parseAxiosError } from "@utils/parse-error";
|
||||||
import { recoverUser } from "@api/user";
|
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 { deleteQuiz, setEditQuizId } from "@root/quizes/actions";
|
||||||
import { Link, useNavigate } from "react-router-dom";
|
import { Link, useNavigate } from "react-router-dom";
|
||||||
import { inCart } from "../../pages/Tariffs/utils";
|
import { inCart } from "../../pages/Tariffs/utils";
|
||||||
import { makeRequest } from "@api/makeRequest";
|
import { makeRequest } from "@frontend/kitui";
|
||||||
import { enqueueSnackbar } from "notistack";
|
import { enqueueSnackbar } from "notistack";
|
||||||
import { useDomainDefine } from "@utils/hooks/useDomainDefine";
|
import { useDomainDefine } from "@utils/hooks/useDomainDefine";
|
||||||
import CopyIcon from "@icons/CopyIcon";
|
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 { create } from "zustand";
|
||||||
import { createJSONStorage, devtools, persist } from "zustand/middleware";
|
import { createJSONStorage, devtools, persist } from "zustand/middleware";
|
||||||
import { useUserStore } from "./user";
|
import { useUserStore } from "./user";
|
||||||
@ -21,11 +21,12 @@ interface AuthData {
|
|||||||
interface TicketStore {
|
interface TicketStore {
|
||||||
unauthData: AuthData;
|
unauthData: AuthData;
|
||||||
authData: AuthData;
|
authData: AuthData;
|
||||||
|
tickets: Ticket[];
|
||||||
}
|
}
|
||||||
|
|
||||||
let params = new URLSearchParams(document.location.search);
|
let params = new URLSearchParams(document.location.search);
|
||||||
|
|
||||||
const debug = params.get("debug");
|
|
||||||
const initAuthData = {
|
const initAuthData = {
|
||||||
sessionData: null,
|
sessionData: null,
|
||||||
isMessageSending: false,
|
isMessageSending: false,
|
||||||
@ -35,10 +36,12 @@ const initAuthData = {
|
|||||||
lastMessageId: undefined,
|
lastMessageId: undefined,
|
||||||
isPreventAutoscroll: false,
|
isPreventAutoscroll: false,
|
||||||
unauthTicketMessageFetchState: "idle" as FetchState,
|
unauthTicketMessageFetchState: "idle" as FetchState,
|
||||||
|
tickets: []
|
||||||
};
|
};
|
||||||
const initState = {
|
const initState = {
|
||||||
unauthData: initAuthData,
|
unauthData: initAuthData,
|
||||||
authData: initAuthData,
|
authData: initAuthData,
|
||||||
|
tickets: []
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useTicketStore = create<TicketStore>()(
|
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,
|
recipe: (state: TicketStore) => void,
|
||||||
action?: A,
|
action?: A,
|
||||||
) {
|
) {
|
||||||
useTicketStore.setState((state) => produce(state, recipe), false, action);
|
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 { enqueueSnackbar } from "notistack";
|
||||||
import { mutate } from "swr";
|
import { mutate } from "swr";
|
||||||
|
|
||||||
import { makeRequest } from "@api/makeRequest";
|
import { makeRequest } from "@frontend/kitui";
|
||||||
import { getDiscounts } from "@api/discounts";
|
import { getDiscounts } from "@api/discounts";
|
||||||
|
|
||||||
import { clearUserData, OriginalUserAccount, setUserAccount, useUserStore } from "@root/user";
|
import { clearUserData, OriginalUserAccount, setUserAccount, useUserStore } from "@root/user";
|
||||||
|
@ -72,33 +72,6 @@ export default () => {
|
|||||||
setIsChatOpened((state) => !state);
|
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({
|
useTicketMessages({
|
||||||
url: `${process.env.REACT_APP_DOMAIN}/heruvym/v1.0.0/getMessages`,
|
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 { useEffect, useLayoutEffect, useRef } from "react";
|
||||||
import { createUserAccount, devlog } from "@frontend/kitui";
|
import { createUserAccount, devlog } from "@frontend/kitui";
|
||||||
import { isAxiosError } from "axios";
|
import { isAxiosError } from "axios";
|
||||||
import { makeRequest } from "@api/makeRequest";
|
import { makeRequest } from "@frontend/kitui";
|
||||||
import type { UserAccount } from "@frontend/kitui";
|
import type { UserAccount } from "@frontend/kitui";
|
||||||
import { setUserAccount } from "@/stores/user";
|
import { setUserAccount } from "@/stores/user";
|
||||||
|
|
||||||
|
@ -1443,10 +1443,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429"
|
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429"
|
||||||
integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==
|
integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==
|
||||||
|
|
||||||
"@frontend/kitui@^1.0.109":
|
"@frontend/kitui@^1.0.110":
|
||||||
version "1.0.109"
|
version "1.0.110"
|
||||||
resolved "http://gitea.pena/api/packages/skeris/npm/%40frontend%2Fkitui/-/1.0.109/kitui-1.0.109.tgz#a9611e7b69dbd2bbc46e78c083d0442fc22bdcef"
|
resolved "http://gitea.pena/api/packages/skeris/npm/%40frontend%2Fkitui/-/1.0.110/kitui-1.0.110.tgz#969f70636508e9efd6c8d81e62a6913b18a0c029"
|
||||||
integrity sha512-y6wzLDEWfTXMjL2gDucs/AzAc0fyh80aIbiokGz1ZgaHMR0XQhV2E/VqlUvK95VZRFO7UqnEaJofpY7iwSQjQA==
|
integrity sha512-M+U9a4qylLb9ZOUn57v7lm/Rutqicm04vJsJrxeAY/6G4ma1bC29toOZwTt/uJUlF4gk4ojyWIIjiGTVM1/hKQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
immer "^10.0.2"
|
immer "^10.0.2"
|
||||||
reconnecting-eventsource "^1.6.2"
|
reconnecting-eventsource "^1.6.2"
|
||||||
|
Loading…
Reference in New Issue
Block a user