diff --git a/src/App.tsx b/src/App.tsx index 059ccfd3..f1e5ae16 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -195,7 +195,7 @@ export default function App() { onError={(error, info) => handleComponentError(error, info, () => useTicketStore.getState().tickets)} > {amoAccount && } - + {!isTest && } {location.state?.backgroundLocation && ( diff --git a/src/ui_kit/FloatingSupportChat/FloatingSupportChat.tsx b/src/ui_kit/FloatingSupportChat/FloatingSupportChat.tsx index 2c7f7419..e133464f 100644 --- a/src/ui_kit/FloatingSupportChat/FloatingSupportChat.tsx +++ b/src/ui_kit/FloatingSupportChat/FloatingSupportChat.tsx @@ -1,5 +1,5 @@ import type { ReactNode, Ref } from "react"; -import { forwardRef, useEffect, useState } from "react"; +import { forwardRef, useEffect, useState, useMemo } from "react"; import { Badge, Box, @@ -70,6 +70,48 @@ export default function FloatingSupportChat({ (state) => state[user ? "authData" : "unauthData"], ); + const ticket = useTicketStore( + (state) => state[user ? "authData" : "unauthData"], + ); + + // Функция для подсчёта непрочитанных сообщений согласно новой логике + const unreadCount = useMemo(() => { + if (messages.length === 0) return 0; + + const currentUserId = user || ticket?.sessionData?.sessionId; + if (!currentUserId) return 0; + + // Если последнее сообщение моё - не показываем количество + const lastMessage = messages[messages.length - 1]; + if (lastMessage.user_id === currentUserId) { + return 0; + } + + // Если последнее сообщение не моё и оно не прочитано - считаем его как +1 + if (lastMessage.shown?.me !== 1) { + let count = 1; + + // Считаем все последующие сообщения до тех пор пока не воткнёмся в моё сообщение + for (let i = messages.length - 2; i >= 0; i--) { + const message = messages[i]; + + // Если встретили моё сообщение - останавливаемся + if (message.user_id === currentUserId) { + break; + } + + // Если сообщение не прочитано - добавляем к счётчику + if (message.shown?.me !== 1) { + count++; + } + } + + return count; + } + + return 0; + }, [messages, user, ticket?.sessionData?.sessionId]); + useEffect(() => { const onResize = () => { if (document.fullscreenElement) { @@ -158,9 +200,7 @@ export default function FloatingSupportChat({ /> )} shown?.me !== 1).length || 0 - } + badgeContent={unreadCount} sx={{ "& .MuiBadge-badge": { display: isChatOpened ? "none" : "flex", diff --git a/src/utils/handleComponentError.ts b/src/utils/handleComponentError.ts index fd08857a..2687d868 100644 --- a/src/utils/handleComponentError.ts +++ b/src/utils/handleComponentError.ts @@ -5,10 +5,10 @@ let errorsQueue: ComponentError[] = []; let timeoutId: ReturnType; interface ComponentError { - timestamp: number; - message: string; - callStack: string | undefined; - componentStack: string | null | undefined; + timestamp: number; + message: string; + callStack: string | undefined; + componentStack: string | null | undefined; } function isErrorReportingAllowed(error?: Error): boolean { @@ -31,22 +31,22 @@ export function handleComponentError(error: Error, info: ErrorInfo, getTickets: console.log(`✅ Обработка ошибки: ${error.message}`); // Копируем __forceSend если есть const componentError: ComponentError & { __forceSend?: boolean } = { - timestamp: Math.floor(Date.now() / 1000), - message: error.message, - callStack: error.stack, - componentStack: info.componentStack, + timestamp: Math.floor(Date.now() / 1000), + message: error.message, + callStack: error.stack, + componentStack: info.componentStack, ...(error && (error as any).__forceSend ? { __forceSend: true } : {}) - }; + }; queueErrorRequest(componentError, getTickets); } // Ставит ошибку в очередь для отправки, через 1 секунду вызывает sendErrorsToServer export function queueErrorRequest(error: ComponentError, getTickets: () => Ticket[]) { - errorsQueue.push(error); - clearTimeout(timeoutId); - timeoutId = setTimeout(() => { + errorsQueue.push(error); + clearTimeout(timeoutId); + timeoutId = setTimeout(() => { sendErrorsToServer(getTickets); - }, 1000); + }, 1000); } // Отправляет накопленные ошибки в тикеты, ищет существующий тикет с system: true или создает новый