Files
scoreodonto.com/frontend/hooks/useDashboardLogic.ts
T

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) },
}
}