feat(realtime): implement SSE realtime notifications; publish events from resolvers; remove polling in chat/sidebar/supplies/warehouse and wire realtime refetch

This commit is contained in:
Bivekich
2025-08-11 22:13:33 +03:00
parent 52107e793e
commit 3a56092385
14 changed files with 562 additions and 40 deletions

View File

@ -23,12 +23,12 @@ import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Button } from '@/components/ui/button'
import { GET_CONVERSATIONS, GET_INCOMING_REQUESTS, GET_PENDING_SUPPLIES_COUNT } from '@/graphql/queries'
import { useAuth } from '@/hooks/useAuth'
import { useRealtime } from '@/hooks/useRealtime'
import { useSidebar } from '@/hooks/useSidebar'
// Компонент для отображения логистических заявок (только для логистики)
function LogisticsOrdersNotification() {
const { data: pendingData } = useQuery(GET_PENDING_SUPPLIES_COUNT, {
pollInterval: 30000, // Обновляем каждые 30 секунд
const { data: pendingData, refetch: refetchPending } = useQuery(GET_PENDING_SUPPLIES_COUNT, {
fetchPolicy: 'cache-first',
errorPolicy: 'ignore',
})
@ -46,8 +46,7 @@ function LogisticsOrdersNotification() {
// Компонент для отображения поставок фулфилмента (только поставки, не заявки на партнерство)
function FulfillmentSuppliesNotification() {
const { data: pendingData } = useQuery(GET_PENDING_SUPPLIES_COUNT, {
pollInterval: 30000, // Обновляем каждые 30 секунд
const { data: pendingData, refetch: refetchPending } = useQuery(GET_PENDING_SUPPLIES_COUNT, {
fetchPolicy: 'cache-first',
errorPolicy: 'ignore',
})
@ -65,8 +64,7 @@ function FulfillmentSuppliesNotification() {
// Компонент для отображения входящих заказов поставщика (только входящие заказы, не заявки на партнерство)
function WholesaleOrdersNotification() {
const { data: pendingData } = useQuery(GET_PENDING_SUPPLIES_COUNT, {
pollInterval: 30000, // Обновляем каждые 30 секунд
const { data: pendingData, refetch: refetchPending } = useQuery(GET_PENDING_SUPPLIES_COUNT, {
fetchPolicy: 'cache-first',
errorPolicy: 'ignore',
})
@ -95,21 +93,38 @@ export function Sidebar({ isRootInstance = false }: { isRootInstance?: boolean }
const { isCollapsed, toggleSidebar } = useSidebar()
// Загружаем список чатов для подсчета непрочитанных сообщений
const { data: conversationsData } = useQuery(GET_CONVERSATIONS, {
pollInterval: 60000, // Обновляем каждую минуту в сайдбаре - этого достаточно
const { data: conversationsData, refetch: refetchConversations } = useQuery(GET_CONVERSATIONS, {
fetchPolicy: 'cache-first',
errorPolicy: 'ignore', // Игнорируем ошибки чтобы не ломать сайдбар
notifyOnNetworkStatusChange: false, // Плавные обновления без мерцания
})
// Загружаем входящие заявки для подсчета новых запросов
const { data: incomingRequestsData } = useQuery(GET_INCOMING_REQUESTS, {
pollInterval: 60000, // Обновляем каждую минуту
const { data: incomingRequestsData, refetch: refetchIncoming } = useQuery(GET_INCOMING_REQUESTS, {
fetchPolicy: 'cache-first',
errorPolicy: 'ignore',
notifyOnNetworkStatusChange: false,
})
// Реалтайм обновления бейджей
useRealtime({
onEvent: (evt) => {
switch (evt.type) {
case 'message:new':
refetchConversations()
break
case 'counterparty:request:new':
case 'counterparty:request:updated':
refetchIncoming()
break
case 'supply-order:new':
case 'supply-order:updated':
refetchPending()
break
}
},
})
// Если уже есть корневой сайдбар и это не корневой экземпляр — не рендерим дубликат
if (
typeof window !== 'undefined' &&