REFACTOR: Preparação para novos tipos de chat
This commit is contained in:
parent
8b85971371
commit
9ba7d0fb84
@ -1,6 +1,5 @@
|
|||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||||
import { useWhatsappSocket } from '../../../shared/hooks/useWhatsappSocket';
|
import { useWhatsappSocket } from '../../../shared/hooks/useWhatsappSocket';
|
||||||
import { API_BASE_URL } from '../../../shared/services/apiConfig';
|
|
||||||
import { getAccessOptions, getAccessUsers } from '../../management/services/adminAccessService';
|
import { getAccessOptions, getAccessUsers } from '../../management/services/adminAccessService';
|
||||||
import { getCurrentUser, getCurrentUserProfile } from '../../auth/services/sessionService';
|
import { getCurrentUser, getCurrentUserProfile } from '../../auth/services/sessionService';
|
||||||
import { transferAreas as fallbackTransferAreas } from '../services/chatMocks';
|
import { transferAreas as fallbackTransferAreas } from '../services/chatMocks';
|
||||||
@ -10,6 +9,16 @@ import {
|
|||||||
pauseAgent,
|
pauseAgent,
|
||||||
resumeAgent,
|
resumeAgent,
|
||||||
} from '../services/agentPresenceService';
|
} from '../services/agentPresenceService';
|
||||||
|
import {
|
||||||
|
assignWhatsappChat,
|
||||||
|
closeWhatsappChat,
|
||||||
|
getWhatsappMessageMedia,
|
||||||
|
listWhatsappChats,
|
||||||
|
listWhatsappMessages,
|
||||||
|
releaseWhatsappChat,
|
||||||
|
sendWhatsappMessage,
|
||||||
|
transferWhatsappChat,
|
||||||
|
} from '../services/whatsappChatService';
|
||||||
|
|
||||||
const MAX_ATTACHMENT_SIZE_BYTES = 15 * 1024 * 1024;
|
const MAX_ATTACHMENT_SIZE_BYTES = 15 * 1024 * 1024;
|
||||||
|
|
||||||
@ -412,9 +421,7 @@ export function useChat() {
|
|||||||
setIsLoadingChats(true);
|
setIsLoadingChats(true);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/whatsapp/chats`);
|
const data = await listWhatsappChats();
|
||||||
if (!response.ok) throw new Error('Falha ao carregar chats do WhatsApp.');
|
|
||||||
const data = await response.json();
|
|
||||||
if (!Array.isArray(data)) return;
|
if (!Array.isArray(data)) return;
|
||||||
|
|
||||||
const nextContacts = data.map(normalizeChat).filter(canSeeContact);
|
const nextContacts = data.map(normalizeChat).filter(canSeeContact);
|
||||||
@ -454,9 +461,7 @@ export function useChat() {
|
|||||||
if (!activeContactId.includes('@')) return;
|
if (!activeContactId.includes('@')) return;
|
||||||
setIsLoadingMessages(true);
|
setIsLoadingMessages(true);
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/whatsapp/messages/${encodeURIComponent(activeContactId)}`);
|
const data = await listWhatsappMessages(activeContactId);
|
||||||
if (!response.ok) throw new Error('Falha ao carregar mensagens do WhatsApp.');
|
|
||||||
const data = await response.json();
|
|
||||||
if (!isMounted || !Array.isArray(data)) return;
|
if (!isMounted || !Array.isArray(data)) return;
|
||||||
const normalizedMessages = dedupeMessages(
|
const normalizedMessages = dedupeMessages(
|
||||||
data
|
data
|
||||||
@ -601,11 +606,7 @@ export function useChat() {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(
|
const media = await getWhatsappMessageMedia(contactId, messageId);
|
||||||
`${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();
|
|
||||||
setMessagesByContact((current) => ({
|
setMessagesByContact((current) => ({
|
||||||
...current,
|
...current,
|
||||||
[contactId]: (current[contactId] || []).map((message) =>
|
[contactId]: (current[contactId] || []).map((message) =>
|
||||||
@ -630,18 +631,11 @@ export function useChat() {
|
|||||||
const targetAssignment = targetContact?.assignment || null;
|
const targetAssignment = targetContact?.assignment || null;
|
||||||
const areaId = targetContact?.areaId || targetAssignment?.area_id || areaOptions.find((area) => currentUserAreas.includes(area.nome))?.id;
|
const areaId = targetContact?.areaId || targetAssignment?.area_id || areaOptions.find((area) => currentUserAreas.includes(area.nome))?.id;
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/whatsapp/assign`, {
|
const assignment = await assignWhatsappChat({
|
||||||
method: 'POST',
|
chatId: contactId,
|
||||||
headers: { 'Content-Type': 'application/json' },
|
userId: String(currentUserId),
|
||||||
body: JSON.stringify({
|
areaId,
|
||||||
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) => ({
|
updateContact(contactId, (contact) => ({
|
||||||
...contact,
|
...contact,
|
||||||
assignment,
|
assignment,
|
||||||
@ -658,18 +652,19 @@ export function useChat() {
|
|||||||
|
|
||||||
async function releaseChat() {
|
async function releaseChat() {
|
||||||
if (!activeContactId?.includes('@')) return;
|
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.');
|
try {
|
||||||
const assignment = await response.json();
|
const assignment = await releaseWhatsappChat(activeContactId);
|
||||||
updateContact(activeContactId, (contact) => ({
|
updateContact(activeContactId, (contact) => ({
|
||||||
...contact,
|
...contact,
|
||||||
assignment,
|
assignment,
|
||||||
area: assignment?.area_nome || contact.area,
|
area: assignment?.area_nome || contact.area,
|
||||||
areaId: assignment?.area_id || contact.areaId,
|
areaId: assignment?.area_id || contact.areaId,
|
||||||
}));
|
}));
|
||||||
|
setApiError(null);
|
||||||
|
} catch (error) {
|
||||||
|
setApiError(error.message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function closeChat() {
|
async function closeChat() {
|
||||||
@ -679,17 +674,11 @@ export function useChat() {
|
|||||||
if (!confirmed) return;
|
if (!confirmed) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/whatsapp/close`, {
|
await closeWhatsappChat({
|
||||||
method: 'POST',
|
chatId: activeContactId,
|
||||||
headers: { 'Content-Type': 'application/json' },
|
userId: currentUserId,
|
||||||
body: JSON.stringify({
|
|
||||||
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));
|
setContacts((current) => current.filter((contact) => contact.id !== activeContactId));
|
||||||
setMessagesByContact((current) => {
|
setMessagesByContact((current) => {
|
||||||
const next = { ...current };
|
const next = { ...current };
|
||||||
@ -798,25 +787,13 @@ export function useChat() {
|
|||||||
if (!contactId.includes('@')) return;
|
if (!contactId.includes('@')) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/whatsapp/send`, {
|
await sendWhatsappMessage({
|
||||||
method: 'POST',
|
to: contactId,
|
||||||
headers: { 'Content-Type': 'application/json' },
|
message: trimmed,
|
||||||
body: JSON.stringify({
|
senderName: getUserDisplayName(currentUser),
|
||||||
to: contactId,
|
media,
|
||||||
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);
|
setApiError(null);
|
||||||
updateContact(contactId, (contact) => ({
|
updateContact(contactId, (contact) => ({
|
||||||
...contact,
|
...contact,
|
||||||
@ -825,7 +802,11 @@ export function useChat() {
|
|||||||
: contact.assignment,
|
: contact.assignment,
|
||||||
}));
|
}));
|
||||||
} catch (error) {
|
} 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;
|
const areaId = selectedTransferArea?.id;
|
||||||
|
|
||||||
if (!areaId) {
|
if (!areaId) {
|
||||||
setApiError('Selecione uma especialidade válida para transferência.');
|
setApiError('Selecione uma especialidade valida para transferencia.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -844,47 +825,40 @@ export function useChat() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const targetUserId = isSameUserArea && transferAttendant ? Number(transferAttendant) : null;
|
const targetUserId = isSameUserArea && transferAttendant ? Number(transferAttendant) : null;
|
||||||
const response = await fetch(`${API_BASE_URL}/whatsapp/transfer`, {
|
|
||||||
method: 'POST',
|
try {
|
||||||
headers: { 'Content-Type': 'application/json' },
|
const assignment = await transferWhatsappChat({
|
||||||
body: JSON.stringify({
|
|
||||||
chatId: activeContactId,
|
chatId: activeContactId,
|
||||||
areaId,
|
areaId,
|
||||||
userId: targetUserId,
|
userId: targetUserId,
|
||||||
note,
|
note,
|
||||||
}),
|
});
|
||||||
});
|
const transferMessage = targetUserId
|
||||||
|
? `Transferencia solicitada para ${transferArea}. Obs: ${note || 'Sem observacao.'}`
|
||||||
|
: `Transferencia enviada para a fila de ${transferArea}. Obs: ${note || 'Sem observacao.'}`;
|
||||||
|
|
||||||
if (!response.ok) {
|
setMessagesByContact((current) => ({
|
||||||
setApiError('Não foi possível transferir o atendimento.');
|
...current,
|
||||||
return;
|
[activeContactId]: [
|
||||||
|
...(current[activeContactId] || []),
|
||||||
|
{ id: Date.now() + 2, sender: 'system', text: transferMessage },
|
||||||
|
],
|
||||||
|
}));
|
||||||
|
|
||||||
|
updateContact(activeContactId, (contact) => ({
|
||||||
|
...contact,
|
||||||
|
area: assignment.area_nome || transferArea,
|
||||||
|
areaId: assignment.area_id || areaId,
|
||||||
|
assignment,
|
||||||
|
}));
|
||||||
|
setSelectedArea(transferArea);
|
||||||
|
setIsTransferOpen(false);
|
||||||
|
setTransferNote('');
|
||||||
|
setApiError(null);
|
||||||
|
} catch (error) {
|
||||||
|
setApiError(error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
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.'}`;
|
|
||||||
|
|
||||||
setMessagesByContact((current) => ({
|
|
||||||
...current,
|
|
||||||
[activeContactId]: [
|
|
||||||
...(current[activeContactId] || []),
|
|
||||||
{ id: Date.now() + 2, sender: 'system', text: transferMessage },
|
|
||||||
],
|
|
||||||
}));
|
|
||||||
|
|
||||||
updateContact(activeContactId, (contact) => ({
|
|
||||||
...contact,
|
|
||||||
area: assignment.area_nome || transferArea,
|
|
||||||
areaId: assignment.area_id || areaId,
|
|
||||||
assignment,
|
|
||||||
}));
|
|
||||||
setSelectedArea(transferArea);
|
|
||||||
setIsTransferOpen(false);
|
|
||||||
setTransferNote('');
|
|
||||||
setApiError(null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentUserId,
|
currentUserId,
|
||||||
contacts,
|
contacts,
|
||||||
|
|||||||
58
src/modules/chat/services/whatsappChatService.js
Normal file
58
src/modules/chat/services/whatsappChatService.js
Normal 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.',
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user