REFACTOR: Preparação para novos tipos de chat

This commit is contained in:
Rafael Alves Lopes 2026-06-01 17:45:13 -03:00
parent 8b85971371
commit 9ba7d0fb84
2 changed files with 128 additions and 96 deletions

View File

@ -1,6 +1,5 @@
import { useEffect, useMemo, useRef, useState } from 'react';
import { useWhatsappSocket } from '../../../shared/hooks/useWhatsappSocket';
import { API_BASE_URL } from '../../../shared/services/apiConfig';
import { getAccessOptions, getAccessUsers } from '../../management/services/adminAccessService';
import { getCurrentUser, getCurrentUserProfile } from '../../auth/services/sessionService';
import { transferAreas as fallbackTransferAreas } from '../services/chatMocks';
@ -10,6 +9,16 @@ import {
pauseAgent,
resumeAgent,
} from '../services/agentPresenceService';
import {
assignWhatsappChat,
closeWhatsappChat,
getWhatsappMessageMedia,
listWhatsappChats,
listWhatsappMessages,
releaseWhatsappChat,
sendWhatsappMessage,
transferWhatsappChat,
} from '../services/whatsappChatService';
const MAX_ATTACHMENT_SIZE_BYTES = 15 * 1024 * 1024;
@ -412,9 +421,7 @@ export function useChat() {
setIsLoadingChats(true);
}
try {
const response = await fetch(`${API_BASE_URL}/whatsapp/chats`);
if (!response.ok) throw new Error('Falha ao carregar chats do WhatsApp.');
const data = await response.json();
const data = await listWhatsappChats();
if (!Array.isArray(data)) return;
const nextContacts = data.map(normalizeChat).filter(canSeeContact);
@ -454,9 +461,7 @@ export function useChat() {
if (!activeContactId.includes('@')) return;
setIsLoadingMessages(true);
try {
const response = await fetch(`${API_BASE_URL}/whatsapp/messages/${encodeURIComponent(activeContactId)}`);
if (!response.ok) throw new Error('Falha ao carregar mensagens do WhatsApp.');
const data = await response.json();
const data = await listWhatsappMessages(activeContactId);
if (!isMounted || !Array.isArray(data)) return;
const normalizedMessages = dedupeMessages(
data
@ -601,11 +606,7 @@ export function useChat() {
}));
try {
const response = await fetch(
`${API_BASE_URL}/whatsapp/media/${encodeURIComponent(contactId)}/${encodeURIComponent(messageId)}`,
);
if (!response.ok) throw new Error('Falha ao carregar mídia.');
const media = await response.json();
const media = await getWhatsappMessageMedia(contactId, messageId);
setMessagesByContact((current) => ({
...current,
[contactId]: (current[contactId] || []).map((message) =>
@ -630,18 +631,11 @@ export function useChat() {
const targetAssignment = targetContact?.assignment || null;
const areaId = targetContact?.areaId || targetAssignment?.area_id || areaOptions.find((area) => currentUserAreas.includes(area.nome))?.id;
try {
const response = await fetch(`${API_BASE_URL}/whatsapp/assign`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
const assignment = await assignWhatsappChat({
chatId: contactId,
userId: String(currentUserId),
areaId,
}),
});
if (!response.ok) throw new Error('Não foi possível assumir o atendimento.');
const assignment = await response.json();
updateContact(contactId, (contact) => ({
...contact,
assignment,
@ -658,18 +652,19 @@ export function useChat() {
async function releaseChat() {
if (!activeContactId?.includes('@')) return;
const response = await fetch(`${API_BASE_URL}/whatsapp/release/${encodeURIComponent(activeContactId)}`, {
method: 'DELETE',
});
if (!response.ok) throw new Error('Não foi possível sair do atendimento.');
const assignment = await response.json();
try {
const assignment = await releaseWhatsappChat(activeContactId);
updateContact(activeContactId, (contact) => ({
...contact,
assignment,
area: assignment?.area_nome || contact.area,
areaId: assignment?.area_id || contact.areaId,
}));
setApiError(null);
} catch (error) {
setApiError(error.message);
}
}
async function closeChat() {
@ -679,17 +674,11 @@ export function useChat() {
if (!confirmed) return;
try {
const response = await fetch(`${API_BASE_URL}/whatsapp/close`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
await closeWhatsappChat({
chatId: activeContactId,
userId: currentUserId,
}),
});
if (!response.ok) throw new Error('Não foi possível encerrar o atendimento.');
setContacts((current) => current.filter((contact) => contact.id !== activeContactId));
setMessagesByContact((current) => {
const next = { ...current };
@ -798,25 +787,13 @@ export function useChat() {
if (!contactId.includes('@')) return;
try {
const response = await fetch(`${API_BASE_URL}/whatsapp/send`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
await sendWhatsappMessage({
to: contactId,
message: trimmed,
senderName: getUserDisplayName(currentUser),
media,
}),
});
if (!response.ok) {
const message =
response.status === 413
? 'Arquivo muito grande para envio. Tente uma mídia menor.'
: 'Não foi possível enviar a mensagem.';
throw new Error(message);
}
setApiError(null);
updateContact(contactId, (contact) => ({
...contact,
@ -825,7 +802,11 @@ export function useChat() {
: contact.assignment,
}));
} catch (error) {
setApiError(error.message);
setApiError(
error.status === 413
? 'Arquivo muito grande para envio. Tente uma midia menor.'
: error.message,
);
}
}
@ -834,7 +815,7 @@ export function useChat() {
const areaId = selectedTransferArea?.id;
if (!areaId) {
setApiError('Selecione uma especialidade válida para transferência.');
setApiError('Selecione uma especialidade valida para transferencia.');
return;
}
@ -844,26 +825,17 @@ export function useChat() {
}
const targetUserId = isSameUserArea && transferAttendant ? Number(transferAttendant) : null;
const response = await fetch(`${API_BASE_URL}/whatsapp/transfer`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
try {
const assignment = await transferWhatsappChat({
chatId: activeContactId,
areaId,
userId: targetUserId,
note,
}),
});
if (!response.ok) {
setApiError('Não foi possível transferir o atendimento.');
return;
}
const assignment = await response.json();
const transferMessage = targetUserId
? `Transferência solicitada para ${transferArea}. Obs: ${note || 'Sem observação.'}`
: `Transferência enviada para a fila de ${transferArea}. Obs: ${note || 'Sem observação.'}`;
? `Transferencia solicitada para ${transferArea}. Obs: ${note || 'Sem observacao.'}`
: `Transferencia enviada para a fila de ${transferArea}. Obs: ${note || 'Sem observacao.'}`;
setMessagesByContact((current) => ({
...current,
@ -883,8 +855,10 @@ export function useChat() {
setIsTransferOpen(false);
setTransferNote('');
setApiError(null);
} catch (error) {
setApiError(error.message);
}
}
return {
currentUserId,
contacts,

View File

@ -0,0 +1,58 @@
import { apiRequest } from '../../../shared/services/apiClient';
export function listWhatsappChats() {
return apiRequest('/whatsapp/chats', {
fallbackMessage: 'Falha ao carregar chats do WhatsApp.',
});
}
export function listWhatsappMessages(chatId) {
return apiRequest(`/whatsapp/messages/${encodeURIComponent(chatId)}`, {
fallbackMessage: 'Falha ao carregar mensagens do WhatsApp.',
});
}
export function getWhatsappMessageMedia(chatId, messageId) {
return apiRequest(`/whatsapp/media/${encodeURIComponent(chatId)}/${encodeURIComponent(messageId)}`, {
fallbackMessage: 'Falha ao carregar midia.',
});
}
export function assignWhatsappChat(payload) {
return apiRequest('/whatsapp/assign', {
method: 'POST',
body: JSON.stringify(payload),
fallbackMessage: 'Nao foi possivel assumir o atendimento.',
});
}
export function releaseWhatsappChat(chatId) {
return apiRequest(`/whatsapp/release/${encodeURIComponent(chatId)}`, {
method: 'DELETE',
fallbackMessage: 'Nao foi possivel sair do atendimento.',
});
}
export function closeWhatsappChat(payload) {
return apiRequest('/whatsapp/close', {
method: 'POST',
body: JSON.stringify(payload),
fallbackMessage: 'Nao foi possivel encerrar o atendimento.',
});
}
export function sendWhatsappMessage(payload) {
return apiRequest('/whatsapp/send', {
method: 'POST',
body: JSON.stringify(payload),
fallbackMessage: 'Nao foi possivel enviar a mensagem.',
});
}
export function transferWhatsappChat(payload) {
return apiRequest('/whatsapp/transfer', {
method: 'POST',
body: JSON.stringify(payload),
fallbackMessage: 'Nao foi possivel transferir o atendimento.',
});
}