внесён багрепорт

This commit is contained in:
Nastya 2025-07-23 08:06:30 +03:00
parent 05f2fc33f9
commit ac692fafd3
27 changed files with 240 additions and 167 deletions

@ -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",

@ -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

@ -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"