фикс подсчёта кол-ва непрочитанных
All checks were successful
Deploy / CreateImage (push) Successful in 5m58s
Deploy / DeployService (push) Successful in 30s

This commit is contained in:
Nastya 2025-07-24 02:41:58 +03:00
parent 2fecf6ca14
commit e9b7f1b0a9
3 changed files with 58 additions and 18 deletions

@ -195,7 +195,7 @@ export default function App() {
onError={(error, info) => handleComponentError(error, info, () => useTicketStore.getState().tickets)} onError={(error, info) => handleComponentError(error, info, () => useTicketStore.getState().tickets)}
> >
{amoAccount && <AmoTokenExpiredDialog isAmoTokenExpired={amoAccount.stale} />} {amoAccount && <AmoTokenExpiredDialog isAmoTokenExpired={amoAccount.stale} />}
<ContactFormModal /> <ContactFormModal />
{!isTest && <FloatingSupportChat />} {!isTest && <FloatingSupportChat />}
{location.state?.backgroundLocation && ( {location.state?.backgroundLocation && (

@ -1,5 +1,5 @@
import type { ReactNode, Ref } from "react"; import type { ReactNode, Ref } from "react";
import { forwardRef, useEffect, useState } from "react"; import { forwardRef, useEffect, useState, useMemo } from "react";
import { import {
Badge, Badge,
Box, Box,
@ -70,6 +70,48 @@ export default function FloatingSupportChat({
(state) => state[user ? "authData" : "unauthData"], (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(() => { useEffect(() => {
const onResize = () => { const onResize = () => {
if (document.fullscreenElement) { if (document.fullscreenElement) {
@ -158,9 +200,7 @@ export default function FloatingSupportChat({
/> />
)} )}
<Badge <Badge
badgeContent={ badgeContent={unreadCount}
messages.filter(({ shown }) => shown?.me !== 1).length || 0
}
sx={{ sx={{
"& .MuiBadge-badge": { "& .MuiBadge-badge": {
display: isChatOpened ? "none" : "flex", display: isChatOpened ? "none" : "flex",

@ -5,10 +5,10 @@ let errorsQueue: ComponentError[] = [];
let timeoutId: ReturnType<typeof setTimeout>; let timeoutId: ReturnType<typeof setTimeout>;
interface ComponentError { interface ComponentError {
timestamp: number; timestamp: number;
message: string; message: string;
callStack: string | undefined; callStack: string | undefined;
componentStack: string | null | undefined; componentStack: string | null | undefined;
} }
function isErrorReportingAllowed(error?: Error): boolean { function isErrorReportingAllowed(error?: Error): boolean {
@ -31,22 +31,22 @@ export function handleComponentError(error: Error, info: ErrorInfo, getTickets:
console.log(`✅ Обработка ошибки: ${error.message}`); console.log(`✅ Обработка ошибки: ${error.message}`);
// Копируем __forceSend если есть // Копируем __forceSend если есть
const componentError: ComponentError & { __forceSend?: boolean } = { const componentError: ComponentError & { __forceSend?: boolean } = {
timestamp: Math.floor(Date.now() / 1000), timestamp: Math.floor(Date.now() / 1000),
message: error.message, message: error.message,
callStack: error.stack, callStack: error.stack,
componentStack: info.componentStack, componentStack: info.componentStack,
...(error && (error as any).__forceSend ? { __forceSend: true } : {}) ...(error && (error as any).__forceSend ? { __forceSend: true } : {})
}; };
queueErrorRequest(componentError, getTickets); queueErrorRequest(componentError, getTickets);
} }
// Ставит ошибку в очередь для отправки, через 1 секунду вызывает sendErrorsToServer // Ставит ошибку в очередь для отправки, через 1 секунду вызывает sendErrorsToServer
export function queueErrorRequest(error: ComponentError, getTickets: () => Ticket[]) { export function queueErrorRequest(error: ComponentError, getTickets: () => Ticket[]) {
errorsQueue.push(error); errorsQueue.push(error);
clearTimeout(timeoutId); clearTimeout(timeoutId);
timeoutId = setTimeout(() => { timeoutId = setTimeout(() => {
sendErrorsToServer(getTickets); sendErrorsToServer(getTickets);
}, 1000); }, 1000);
} }
// Отправляет накопленные ошибки в тикеты, ищет существующий тикет с system: true или создает новый // Отправляет накопленные ошибки в тикеты, ищет существующий тикет с system: true или создает новый