Implementado em: 2026-04-02 Status: Ativo
Resumo
A conversa aberta no chat persiste ao recarregar a página (F5). O ticketId selecionado é salvo na URL como query parameter. Ao recarregar, o sistema lê o parâmetro e reabre a conversa automaticamente.
Como Funciona
Salvar na URL (ao selecionar conversa)
const selectTicket = useCallback((ticketId: number | null) => {
setSelectedTicketId(ticketId)
const url = new URL(window.location.href)
if (ticketId) {
url.searchParams.set("ticket", String(ticketId))
} else {
url.searchParams.delete("ticket")
}
window.history.replaceState({}, "", url.toString())
}, [])
Ler da URL (ao carregar página)
const searchParams = useSearchParams()
const [selectedTicketId, setSelectedTicketId] = useState<number | null>(() => {
const param = searchParams.get("ticket")
return param ? parseInt(param) : null
})
Fluxo completo
1. Usuário clica "João" → URL: /chat?ticket=45
2. F5 (recarregar)
3. useSearchParams lê ?ticket=45
4. selectedTicketId = 45
5. Tickets carregam da API
6. selectedTicket = tickets.find(t => t.id === 45)
7. Chat abre na conversa do "João" automaticamente
Detalhes Técnicos
window.history.replaceState— atualiza URL sem recarregar a página e sem criar entrada no históricouseSearchParams— hook do Next.js App Router para ler query paramsSuspensewrapper — necessário no Next.js parauseSearchParamsfuncionar em Server Components- Zero overhead — nenhuma chamada extra, nenhum storage, apenas leitura de string da URL
Benefícios extras
| Benefício | Descrição |
|---|---|
| Deep link | /chat?ticket=45 abre direto na conversa |
| Compartilhável | Pode enviar link para outro atendente |
| Funciona em incógnito | Não depende de localStorage |
| Histórico limpo | replaceState não cria entradas extras no back/forward |
Arquivo
frontend/src/app/(dashboard)/chat/page.tsx:
useSearchParams+SuspensewrapperselectTicket()comreplaceState- Inicialização do
selectedTicketIda partir do query param