109 lines
3.7 KiB
TypeScript
109 lines
3.7 KiB
TypeScript
/**
|
|
* useDashboardLogic — dados e estado da página /dashboard.
|
|
*/
|
|
import { useState, useEffect, useCallback, useRef } from 'react'
|
|
import { useInstanceStore } from '../store/instanceStore'
|
|
import { useChatStore } from '../store/chatStore'
|
|
import { socketService } from '../services/socketService'
|
|
import { chatApi } from '../services/chatApiService'
|
|
import type { Chat } from '../store/chatStore'
|
|
|
|
export type Period = 'hoje' | '7d' | '30d'
|
|
|
|
export interface DashStats {
|
|
totalChats: number
|
|
totalUnread: number
|
|
openProtocols: number
|
|
}
|
|
|
|
export function useDashboardLogic() {
|
|
const instances = useInstanceStore((s) => s.instances)
|
|
const loadInst = useInstanceStore((s) => s.loadInstances)
|
|
const instLoading = useInstanceStore((s) => s.loading)
|
|
const activeId = useInstanceStore((s) => s.activeInstanceId)
|
|
const setActiveId = useInstanceStore((s) => s.setActiveInstance)
|
|
const initSocket = useInstanceStore((s) => s.initSocketListeners)
|
|
const resetChats = useChatStore((s) => s.setChats)
|
|
|
|
const [period, setPeriod] = useState<Period>('hoje')
|
|
const [statsLoading, setStatsLoading] = useState(true)
|
|
const [stats, setStats] = useState<DashStats | null>(null)
|
|
const [recentChats, setRecentChats] = useState<Chat[]>([])
|
|
const fetchedFor = useRef<string | null>(null)
|
|
|
|
// ── Boot ──────────────────────────────────────────────────────────────────
|
|
|
|
useEffect(() => {
|
|
loadInst()
|
|
initSocket()
|
|
}, [])
|
|
|
|
// Auto-seleciona primeira instância se nenhuma ativa
|
|
useEffect(() => {
|
|
if (!activeId && instances.length > 0) {
|
|
const first = instances[0]
|
|
setActiveId(first.id)
|
|
socketService.joinInstance(first.id)
|
|
}
|
|
}, [instances, activeId])
|
|
|
|
// ── Fetch dados reais quando activeId muda ────────────────────────────────
|
|
|
|
const fetchDashboardData = useCallback(async (instanceId: string) => {
|
|
setStatsLoading(true)
|
|
try {
|
|
const [statsRes, chatsRes] = await Promise.all([
|
|
chatApi.stats(instanceId),
|
|
chatApi.list(instanceId, { limit: 5 }),
|
|
])
|
|
setStats(statsRes)
|
|
// list pode retornar array direto ou { chats: [...] }
|
|
const list: Chat[] = Array.isArray(chatsRes)
|
|
? chatsRes
|
|
: (chatsRes as any).chats ?? chatsRes
|
|
setRecentChats(list.slice(0, 5))
|
|
} catch {
|
|
setStats(null)
|
|
setRecentChats([])
|
|
} finally {
|
|
setStatsLoading(false)
|
|
}
|
|
}, [])
|
|
|
|
useEffect(() => {
|
|
if (!activeId || fetchedFor.current === activeId) return
|
|
fetchedFor.current = activeId
|
|
fetchDashboardData(activeId)
|
|
}, [activeId, fetchDashboardData])
|
|
|
|
// ── Seleção de instância ──────────────────────────────────────────────────
|
|
|
|
const activeInstance = instances.find((i) => i.id === activeId) ?? instances[0] ?? null
|
|
|
|
const selectInstance = useCallback((id: string) => {
|
|
if (id === activeId) return
|
|
fetchedFor.current = null
|
|
resetChats([])
|
|
setActiveId(id)
|
|
socketService.joinInstance(id)
|
|
}, [activeId, setActiveId, resetChats])
|
|
|
|
const connectedCount = instances.filter((i) => i.status === 'CONNECTED').length
|
|
const disconnectedCount = instances.length - connectedCount
|
|
|
|
return {
|
|
period, setPeriod,
|
|
statsLoading,
|
|
stats,
|
|
recentChats,
|
|
instances,
|
|
instLoading,
|
|
activeInstance,
|
|
activeId,
|
|
selectInstance,
|
|
connectedCount,
|
|
disconnectedCount,
|
|
refetch: () => { fetchedFor.current = null; if (activeId) fetchDashboardData(activeId) },
|
|
}
|
|
}
|