Files
instrucoes_gerais/clube67/newwhats.local/frontend/hooks/useProtocolPanel.ts
T

174 lines
6.2 KiB
TypeScript

import { useState, useCallback, useEffect } from 'react'
import { protocolApi, sectorApi, type Sector, type Team } from '../services/chatApiService'
// ─── Types ────────────────────────────────────────────────────────────────────
export type ProtocolStatus =
| 'OPEN'
| 'IN_PROGRESS'
| 'WAITING_CLIENT'
| 'WAITING_AGENT'
| 'RESOLVED'
| 'CANCELLED'
export interface Protocol {
id: string
number: string
chatId: string
contactId: string
sectorId: string | null
teamId: string | null
agentId: string | null
status: ProtocolStatus
summary: string | null
deadline: string | null
resolvedAt: string | null
createdAt: string
updatedAt: string
sector?: { name: string } | null
team?: { name: string } | null
}
// ─── Hook ─────────────────────────────────────────────────────────────────────
export function useProtocolPanel(chatId: string | null) {
const [protocols, setProtocols] = useState<Protocol[]>([])
const [loading, setLoading] = useState(false)
// Sectors & teams for the "open protocol" form
const [sectors, setSectors] = useState<Sector[]>([])
const [teams, setTeams] = useState<Team[]>([])
const [selectedSectorId, setSelectedSectorId] = useState<string>('')
const [selectedTeamId, setSelectedTeamId] = useState<string>('')
const [loadingSectors, setLoadingSectors] = useState(false)
const [loadingTeams, setLoadingTeams] = useState(false)
// Opening a new protocol
const [isOpening, setIsOpening] = useState(false)
const [showOpenForm, setShowOpenForm] = useState(false)
// Updating status
const [updatingId, setUpdatingId] = useState<string | null>(null)
// Toast
const [toast, setToast] = useState<{ message: string; type: 'success' | 'error' } | null>(null)
const showToast = useCallback((message: string, type: 'success' | 'error') => {
setToast({ message, type })
setTimeout(() => setToast(null), 3000)
}, [])
// ── Load protocols ────────────────────────────────────────────────────────
const load = useCallback(async () => {
if (!chatId) { setProtocols([]); return }
setLoading(true)
try {
const data = await protocolApi.list(chatId)
setProtocols(data as Protocol[])
} catch {
// silently ignore
} finally {
setLoading(false)
}
}, [chatId])
useEffect(() => { load() }, [chatId])
// ── Load sectors (lazy, once) ─────────────────────────────────────────────
const loadSectors = useCallback(async () => {
if (sectors.length > 0) return
setLoadingSectors(true)
try {
const data = await sectorApi.list()
setSectors(data.filter((s) => s.isActive))
} catch {
// ignore
} finally {
setLoadingSectors(false)
}
}, [sectors.length])
// ── Load teams when sector changes ────────────────────────────────────────
useEffect(() => {
if (!selectedSectorId) { setTeams([]); setSelectedTeamId(''); return }
setLoadingTeams(true)
sectorApi.listTeams(selectedSectorId)
.then((data) => { setTeams(data.filter((t) => t.isActive)); setSelectedTeamId('') })
.catch(() => {})
.finally(() => setLoadingTeams(false))
}, [selectedSectorId])
const openForm = useCallback(() => {
setShowOpenForm(true)
setSelectedSectorId('')
setSelectedTeamId('')
loadSectors()
}, [loadSectors])
// ── Open new protocol ─────────────────────────────────────────────────────
const openProtocol = useCallback(async () => {
if (!chatId) return
setIsOpening(true)
try {
const protocol = await protocolApi.open(chatId, {
sectorId: selectedSectorId || undefined,
teamId: selectedTeamId || undefined,
})
setProtocols((prev) => [protocol as Protocol, ...prev])
setShowOpenForm(false)
showToast('Protocolo aberto.', 'success')
} catch (err: any) {
showToast(err?.response?.data?.error ?? 'Erro ao abrir protocolo.', 'error')
} finally {
setIsOpening(false)
}
}, [chatId, selectedSectorId, selectedTeamId, showToast])
// ── Update status ─────────────────────────────────────────────────────────
const updateStatus = useCallback(async (protocol: Protocol, status: ProtocolStatus) => {
if (!chatId) return
setUpdatingId(protocol.id)
try {
await protocolApi.update(chatId, protocol.id, { status })
setProtocols((prev) =>
prev.map((p) =>
p.id === protocol.id
? { ...p, status, resolvedAt: status === 'RESOLVED' ? new Date().toISOString() : p.resolvedAt }
: p
)
)
showToast('Status atualizado.', 'success')
} catch {
showToast('Erro ao atualizar status.', 'error')
} finally {
setUpdatingId(null)
}
}, [chatId, showToast])
// ── Derived ───────────────────────────────────────────────────────────────
const activeProtocol = protocols.find(
(p) => p.status !== 'RESOLVED' && p.status !== 'CANCELLED'
) ?? null
const hasActive = activeProtocol !== null
return {
protocols, loading, load,
activeProtocol, hasActive,
// open form
showOpenForm, setShowOpenForm,
openForm,
sectors, teams,
selectedSectorId, setSelectedSectorId,
selectedTeamId, setSelectedTeamId,
loadingSectors, loadingTeams,
isOpening, openProtocol,
// update
updatingId, updateStatus,
toast,
}
}