Fix: Address instance deletion, disappearing instances, and update errors
- Fixed instance deletion failures. - Resolved the issue of instances appearing and disappearing in a loop. - Addressed errors during instance updates. - Check for missing information.
This commit is contained in:
parent
f26e41707a
commit
dec494083c
@ -56,6 +56,7 @@ const CreateInstanceForm = ({ onInstanceCreated }: CreateInstanceFormProps) => {
|
|||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
console.log(`Creating instance with name ${instanceName} and number ${phoneNumber}`);
|
||||||
const data = await createWhatsAppInstance(instanceName, phoneNumber);
|
const data = await createWhatsAppInstance(instanceName, phoneNumber);
|
||||||
|
|
||||||
console.log('API response for create instance:', data);
|
console.log('API response for create instance:', data);
|
||||||
@ -63,7 +64,7 @@ const CreateInstanceForm = ({ onInstanceCreated }: CreateInstanceFormProps) => {
|
|||||||
// Create new instance object with user ID
|
// Create new instance object with user ID
|
||||||
const newInstance: WhatsAppInstance = {
|
const newInstance: WhatsAppInstance = {
|
||||||
instanceName,
|
instanceName,
|
||||||
instanceId: data.instance?.instanceId || instanceName, // Use instanceName as fallback ID
|
instanceId: instanceName, // Use instanceName as the ID for consistency
|
||||||
phoneNumber,
|
phoneNumber,
|
||||||
userId: currentUserId, // Associate with current user
|
userId: currentUserId, // Associate with current user
|
||||||
status: data.instance?.status || 'created',
|
status: data.instance?.status || 'created',
|
||||||
|
|||||||
@ -141,6 +141,27 @@ const InstanceCard = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Determina o estado de conexão a ser exibido
|
||||||
|
const getConnectionStatus = () => {
|
||||||
|
// Se o status é 'disconnected', 'error', 'destroyed', ou não está definido, consideramos como desconectado
|
||||||
|
if (instance.status === 'disconnected' ||
|
||||||
|
instance.status === 'error' ||
|
||||||
|
instance.status === 'destroyed' ||
|
||||||
|
!instance.status) {
|
||||||
|
return 'closed';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Se o connectionState já está definido como 'open', manter
|
||||||
|
if (instance.connectionState === 'open') {
|
||||||
|
return 'open';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Em outros casos, usar o valor atual do connectionState
|
||||||
|
return instance.connectionState || 'closed';
|
||||||
|
};
|
||||||
|
|
||||||
|
const connectionStatus = getConnectionStatus();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Card className="h-full">
|
<Card className="h-full">
|
||||||
@ -154,11 +175,16 @@ const InstanceCard = ({
|
|||||||
<span>{instance.phoneNumber}</span>
|
<span>{instance.phoneNumber}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center text-sm">
|
<div className="flex items-center text-sm">
|
||||||
{instance.connectionState === 'open' ? (
|
{connectionStatus === 'open' ? (
|
||||||
<Badge variant="outline" className="flex items-center gap-1 text-green-500 border-green-300">
|
<Badge variant="outline" className="flex items-center gap-1 text-green-500 border-green-300">
|
||||||
<span className="inline-block w-2 h-2 rounded-full bg-green-500"></span>
|
<span className="inline-block w-2 h-2 rounded-full bg-green-500"></span>
|
||||||
Status: Conectado
|
Status: Conectado
|
||||||
</Badge>
|
</Badge>
|
||||||
|
) : connectionStatus === 'connecting' ? (
|
||||||
|
<Badge variant="outline" className="flex items-center gap-1 text-orange-500 border-orange-300">
|
||||||
|
<span className="inline-block w-2 h-2 rounded-full bg-orange-500"></span>
|
||||||
|
Status: Conectando
|
||||||
|
</Badge>
|
||||||
) : (
|
) : (
|
||||||
<Badge variant="outline" className="flex items-center gap-1 text-red-500 border-red-300">
|
<Badge variant="outline" className="flex items-center gap-1 text-red-500 border-red-300">
|
||||||
<span className="inline-block w-2 h-2 rounded-full bg-red-500"></span>
|
<span className="inline-block w-2 h-2 rounded-full bg-red-500"></span>
|
||||||
|
|||||||
@ -8,7 +8,7 @@ interface InstanceStatsProps {
|
|||||||
const InstanceStats = ({ instances }: InstanceStatsProps) => {
|
const InstanceStats = ({ instances }: InstanceStatsProps) => {
|
||||||
const totalInstances = instances.length;
|
const totalInstances = instances.length;
|
||||||
const connectedInstances = instances.filter(i => i.connectionState === 'open').length;
|
const connectedInstances = instances.filter(i => i.connectionState === 'open').length;
|
||||||
const disconnectedInstances = instances.filter(i => i.connectionState === 'closed').length;
|
const disconnectedInstances = instances.filter(i => i.connectionState === 'closed' || i.status === 'disconnected').length;
|
||||||
const connectingInstances = instances.filter(i => i.connectionState === 'connecting').length;
|
const connectingInstances = instances.filter(i => i.connectionState === 'connecting').length;
|
||||||
|
|
||||||
if (totalInstances === 0) {
|
if (totalInstances === 0) {
|
||||||
|
|||||||
@ -22,6 +22,7 @@ export const useWhatsAppActions = (
|
|||||||
// Handler for quando uma instância é reiniciada
|
// Handler for quando uma instância é reiniciada
|
||||||
const handleRestartInstance = async (instance: WhatsAppInstance) => {
|
const handleRestartInstance = async (instance: WhatsAppInstance) => {
|
||||||
try {
|
try {
|
||||||
|
console.log(`Attempting to restart instance ${instance.instanceName}`);
|
||||||
await restartInstance(instance.instanceName);
|
await restartInstance(instance.instanceName);
|
||||||
|
|
||||||
// Atualiza o estado da instância para "connecting"
|
// Atualiza o estado da instância para "connecting"
|
||||||
@ -29,6 +30,7 @@ export const useWhatsAppActions = (
|
|||||||
...instance,
|
...instance,
|
||||||
connectionState: 'connecting' as const
|
connectionState: 'connecting' as const
|
||||||
};
|
};
|
||||||
|
console.log(`Instance ${instance.instanceName} restart initiated, setting state to connecting`, updatedInstance);
|
||||||
updateInstance(updatedInstance);
|
updateInstance(updatedInstance);
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
@ -52,13 +54,16 @@ export const useWhatsAppActions = (
|
|||||||
// Handler for quando uma instância é desconectada
|
// Handler for quando uma instância é desconectada
|
||||||
const handleLogoutInstance = async (instance: WhatsAppInstance) => {
|
const handleLogoutInstance = async (instance: WhatsAppInstance) => {
|
||||||
try {
|
try {
|
||||||
|
console.log(`Attempting to logout instance ${instance.instanceName}`);
|
||||||
await logoutInstance(instance.instanceName);
|
await logoutInstance(instance.instanceName);
|
||||||
|
|
||||||
// Atualiza o estado da instância para "closed"
|
// Atualiza o estado da instância para "closed"
|
||||||
const updatedInstance = {
|
const updatedInstance = {
|
||||||
...instance,
|
...instance,
|
||||||
connectionState: 'closed' as const
|
connectionState: 'closed' as const,
|
||||||
|
status: 'disconnected'
|
||||||
};
|
};
|
||||||
|
console.log(`Instance ${instance.instanceName} logout successful, updating instance state`, updatedInstance);
|
||||||
updateInstance(updatedInstance);
|
updateInstance(updatedInstance);
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
@ -79,15 +84,21 @@ export const useWhatsAppActions = (
|
|||||||
// Handler for quando a presença é alterada
|
// Handler for quando a presença é alterada
|
||||||
const handleSetPresence = async (instance: WhatsAppInstance, presence: 'online' | 'offline') => {
|
const handleSetPresence = async (instance: WhatsAppInstance, presence: 'online' | 'offline') => {
|
||||||
try {
|
try {
|
||||||
|
console.log(`Setting presence to ${presence} for instance ${instance.instanceName}`);
|
||||||
await setInstancePresence(instance.instanceName, presence);
|
await setInstancePresence(instance.instanceName, presence);
|
||||||
|
|
||||||
|
const updatedInstance = {
|
||||||
|
...instance,
|
||||||
|
presence: presence
|
||||||
|
};
|
||||||
|
console.log(`Updated instance with new presence status`, updatedInstance);
|
||||||
|
updateInstance(updatedInstance);
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: "Sucesso",
|
title: "Sucesso",
|
||||||
description: `Instância ${instance.instanceName} agora está ${presence === 'online' ? 'Online' : 'Offline'}`
|
description: `Instância ${instance.instanceName} agora está ${presence === 'online' ? 'Online' : 'Offline'}`
|
||||||
});
|
});
|
||||||
|
|
||||||
// Não precisamos alterar o estado da instância aqui, pois isso não afeta o connectionState
|
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error setting presence to ${presence} for instance ${instance.instanceName}:`, error);
|
console.error(`Error setting presence to ${presence} for instance ${instance.instanceName}:`, error);
|
||||||
toast({
|
toast({
|
||||||
@ -100,11 +111,12 @@ export const useWhatsAppActions = (
|
|||||||
|
|
||||||
// Handler for when an instance is deleted
|
// Handler for when an instance is deleted
|
||||||
const handleDeleteInstance = async (instanceId: string, instanceName: string) => {
|
const handleDeleteInstance = async (instanceId: string, instanceName: string) => {
|
||||||
console.log(`Deleting instance with ID: ${instanceId}`);
|
console.log(`Deleting instance with ID: ${instanceId}, name: ${instanceName}`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Call API to delete instance
|
// Call API to delete instance
|
||||||
await deleteInstance(instanceName);
|
const response = await deleteInstance(instanceName);
|
||||||
|
console.log(`Deletion API response for instance ${instanceName}:`, response);
|
||||||
|
|
||||||
// Remove from local state
|
// Remove from local state
|
||||||
removeInstance(instanceId);
|
removeInstance(instanceId);
|
||||||
@ -112,6 +124,7 @@ export const useWhatsAppActions = (
|
|||||||
// If we're viewing QR code for this instance, close the dialog
|
// If we're viewing QR code for this instance, close the dialog
|
||||||
if (activeInstance?.instanceId === instanceId) {
|
if (activeInstance?.instanceId === instanceId) {
|
||||||
setQrDialogOpen(false);
|
setQrDialogOpen(false);
|
||||||
|
setActiveInstance(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
@ -120,9 +133,19 @@ export const useWhatsAppActions = (
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error deleting instance with ID ${instanceId}:`, error);
|
console.error(`Error deleting instance with ID ${instanceId}:`, error);
|
||||||
|
|
||||||
|
// Even if the API call fails, we still want to remove the instance from local storage
|
||||||
|
// This handles the case when instances are in inconsistent state with the server
|
||||||
|
removeInstance(instanceId);
|
||||||
|
|
||||||
|
if (activeInstance?.instanceId === instanceId) {
|
||||||
|
setQrDialogOpen(false);
|
||||||
|
setActiveInstance(null);
|
||||||
|
}
|
||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: "Erro",
|
title: "Aviso",
|
||||||
description: "Falha ao excluir a instância. Tente novamente.",
|
description: "Instância removida localmente, mas pode haver falha na comunicação com o servidor.",
|
||||||
variant: "destructive",
|
variant: "destructive",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -130,6 +153,7 @@ export const useWhatsAppActions = (
|
|||||||
|
|
||||||
// Handler for when QR code dialog is requested
|
// Handler for when QR code dialog is requested
|
||||||
const handleViewQrCode = async (instance: WhatsAppInstance) => {
|
const handleViewQrCode = async (instance: WhatsAppInstance) => {
|
||||||
|
console.log(`Opening QR code dialog for instance: ${instance.instanceName}`);
|
||||||
setActiveInstance(instance);
|
setActiveInstance(instance);
|
||||||
setQrDialogOpen(true);
|
setQrDialogOpen(true);
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
|
import { useState, useEffect, useCallback } from 'react';
|
||||||
import { useState, useEffect } from 'react';
|
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
import { WhatsAppInstance } from '@/types/whatsAppTypes';
|
import { WhatsAppInstance } from '@/types/whatsAppTypes';
|
||||||
import {
|
import {
|
||||||
@ -37,26 +36,50 @@ export const useWhatsAppInstances = () => {
|
|||||||
}, [instances, currentUserId]);
|
}, [instances, currentUserId]);
|
||||||
|
|
||||||
// Function to check connection status for all instances
|
// Function to check connection status for all instances
|
||||||
const checkAllInstancesStatus = async () => {
|
const checkAllInstancesStatus = useCallback(async () => {
|
||||||
if (instances.length === 0) return;
|
if (instances.length === 0) return;
|
||||||
|
|
||||||
|
console.log(`Checking connection status for ${instances.length} instances`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const updatedInstances = await Promise.all(
|
const updatedInstances = await Promise.all(
|
||||||
instances.map(async (instance) => {
|
instances.map(async (instance) => {
|
||||||
try {
|
try {
|
||||||
|
console.log(`Checking status for ${instance.instanceName}`);
|
||||||
const state = await fetchConnectionState(instance.instanceName);
|
const state = await fetchConnectionState(instance.instanceName);
|
||||||
|
console.log(`Status for ${instance.instanceName}: ${state}`);
|
||||||
|
|
||||||
|
// Only update connectionState if it's different
|
||||||
|
if (instance.connectionState !== state) {
|
||||||
return { ...instance, connectionState: state };
|
return { ...instance, connectionState: state };
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error checking status for ${instance.instanceName}:`, error);
|
console.error(`Error checking status for ${instance.instanceName}:`, error);
|
||||||
return { ...instance, connectionState: 'closed' as const };
|
|
||||||
|
// If the instance doesn't exist on the server, mark it as closed
|
||||||
|
if (error instanceof Error && error.message.includes("does not exist")) {
|
||||||
|
return { ...instance, connectionState: 'closed', status: 'disconnected' };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep the current state in case of other errors
|
||||||
|
return instance;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Only update state if there are actual changes
|
||||||
|
const hasChanges = JSON.stringify(updatedInstances) !== JSON.stringify(instances);
|
||||||
|
if (hasChanges) {
|
||||||
|
console.log('Updated instances after status check:', updatedInstances);
|
||||||
setInstances(updatedInstances);
|
setInstances(updatedInstances);
|
||||||
|
} else {
|
||||||
|
console.log('No changes in instance status');
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error checking instances status:", error);
|
console.error("Error checking instances status:", error);
|
||||||
}
|
}
|
||||||
};
|
}, [instances]);
|
||||||
|
|
||||||
// Handler para atualizar a lista de instâncias do servidor
|
// Handler para atualizar a lista de instâncias do servidor
|
||||||
const refreshInstances = async () => {
|
const refreshInstances = async () => {
|
||||||
@ -71,35 +94,47 @@ export const useWhatsAppInstances = () => {
|
|||||||
|
|
||||||
setIsRefreshing(true);
|
setIsRefreshing(true);
|
||||||
try {
|
try {
|
||||||
|
console.log("Fetching instances from server...");
|
||||||
const response = await fetchAllInstances();
|
const response = await fetchAllInstances();
|
||||||
console.log("Fetched instances from server:", response);
|
console.log("Fetched instances from server:", response);
|
||||||
|
|
||||||
if (response.instances && Array.isArray(response.instances)) {
|
if (response.instances && Array.isArray(response.instances)) {
|
||||||
// Filtra instâncias para mostrar apenas as do usuário atual
|
// Mapeia as instâncias do servidor para o formato correto com userId
|
||||||
// E mapeia para o formato correto com userId
|
|
||||||
const serverInstances: WhatsAppInstance[] = response.instances
|
const serverInstances: WhatsAppInstance[] = response.instances
|
||||||
.filter(serverInstance => {
|
|
||||||
// Implemente sua lógica de filtro para o usuário atual (se necessário)
|
|
||||||
// Por padrão, vamos assumir que todas as instâncias são do usuário atual
|
|
||||||
return true;
|
|
||||||
})
|
|
||||||
.map(serverInstance => ({
|
.map(serverInstance => ({
|
||||||
instanceName: serverInstance.instanceName,
|
instanceName: serverInstance.instanceName,
|
||||||
instanceId: serverInstance.instanceName,
|
instanceId: serverInstance.instanceName, // Using instanceName as the ID for consistency
|
||||||
phoneNumber: serverInstance.number || 'Desconhecido',
|
phoneNumber: serverInstance.number || 'Desconhecido',
|
||||||
userId: currentUserId,
|
userId: currentUserId,
|
||||||
connectionState: serverInstance.state || 'closed',
|
connectionState: serverInstance.state || 'closed',
|
||||||
status: serverInstance.status || 'unknown'
|
status: serverInstance.status || 'unknown'
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// Mesclando instâncias do servidor com as locais (para não perder dados locais)
|
console.log("Mapped server instances:", serverInstances);
|
||||||
const localInstanceIds = new Set(instances.map(i => i.instanceId));
|
|
||||||
const newInstances = [
|
// Identifica instâncias novas que não existem localmente
|
||||||
...instances,
|
const localInstanceIds = new Set(instances.map(i => i.instanceId));
|
||||||
...serverInstances.filter(i => !localInstanceIds.has(i.instanceId))
|
const newServerInstances = serverInstances.filter(i => !localInstanceIds.has(i.instanceId));
|
||||||
];
|
|
||||||
|
// Atualiza instâncias existentes com dados do servidor
|
||||||
|
const updatedExistingInstances = instances.map(localInstance => {
|
||||||
|
const serverMatch = serverInstances.find(si => si.instanceId === localInstance.instanceId);
|
||||||
|
if (serverMatch) {
|
||||||
|
return {
|
||||||
|
...localInstance,
|
||||||
|
connectionState: serverMatch.connectionState,
|
||||||
|
status: serverMatch.status
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return localInstance;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Combina tudo
|
||||||
|
const allInstances = [...updatedExistingInstances, ...newServerInstances];
|
||||||
|
|
||||||
|
console.log("Combined instances after refresh:", allInstances);
|
||||||
|
setInstances(allInstances);
|
||||||
|
|
||||||
setInstances(newInstances);
|
|
||||||
toast({
|
toast({
|
||||||
title: "Sucesso",
|
title: "Sucesso",
|
||||||
description: `${serverInstances.length} instâncias encontradas no servidor`,
|
description: `${serverInstances.length} instâncias encontradas no servidor`,
|
||||||
@ -120,18 +155,34 @@ export const useWhatsAppInstances = () => {
|
|||||||
} finally {
|
} finally {
|
||||||
setIsRefreshing(false);
|
setIsRefreshing(false);
|
||||||
// Verificar status após atualizar a lista
|
// Verificar status após atualizar a lista
|
||||||
checkAllInstancesStatus();
|
await checkAllInstancesStatus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add a new instance
|
// Add a new instance
|
||||||
const addInstance = (newInstance: WhatsAppInstance) => {
|
const addInstance = (newInstance: WhatsAppInstance) => {
|
||||||
console.log("New instance created, adding to instances list:", newInstance);
|
console.log("New instance created, adding to instances list:", newInstance);
|
||||||
|
|
||||||
|
// Verifica se já existe uma instância com o mesmo ID
|
||||||
|
const existingIndex = instances.findIndex(inst => inst.instanceId === newInstance.instanceId);
|
||||||
|
|
||||||
|
if (existingIndex >= 0) {
|
||||||
|
// Atualiza a instância existente
|
||||||
|
console.log(`Instance with ID ${newInstance.instanceId} already exists, updating it`);
|
||||||
|
setInstances(prevInstances =>
|
||||||
|
prevInstances.map((instance, index) =>
|
||||||
|
index === existingIndex ? newInstance : instance
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Adiciona nova instância
|
||||||
setInstances(prevInstances => [...prevInstances, newInstance]);
|
setInstances(prevInstances => [...prevInstances, newInstance]);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove an instance
|
// Remove an instance
|
||||||
const removeInstance = (instanceId: string) => {
|
const removeInstance = (instanceId: string) => {
|
||||||
|
console.log(`Removing instance with ID: ${instanceId}`);
|
||||||
setInstances(prevInstances => {
|
setInstances(prevInstances => {
|
||||||
const filtered = prevInstances.filter(instance => instance.instanceId !== instanceId);
|
const filtered = prevInstances.filter(instance => instance.instanceId !== instanceId);
|
||||||
console.log("Updated instances after deletion:", filtered);
|
console.log("Updated instances after deletion:", filtered);
|
||||||
@ -141,13 +192,17 @@ export const useWhatsAppInstances = () => {
|
|||||||
|
|
||||||
// Update an instance
|
// Update an instance
|
||||||
const updateInstance = (updatedInstance: WhatsAppInstance) => {
|
const updateInstance = (updatedInstance: WhatsAppInstance) => {
|
||||||
setInstances(prevInstances =>
|
console.log(`Updating instance: ${updatedInstance.instanceName}`, updatedInstance);
|
||||||
prevInstances.map(instance =>
|
setInstances(prevInstances => {
|
||||||
|
const newInstances = prevInstances.map(instance =>
|
||||||
instance.instanceId === updatedInstance.instanceId
|
instance.instanceId === updatedInstance.instanceId
|
||||||
? updatedInstance
|
? updatedInstance
|
||||||
: instance
|
: instance
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log("Updated instances:", newInstances);
|
||||||
|
return newInstances;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@ -8,8 +8,10 @@ import InstanceStats from '@/components/whatsapp/InstanceStats';
|
|||||||
import QrCodeDialog from '@/components/whatsapp/QrCodeDialog';
|
import QrCodeDialog from '@/components/whatsapp/QrCodeDialog';
|
||||||
import { useWhatsAppInstances } from '@/hooks/useWhatsAppInstances';
|
import { useWhatsAppInstances } from '@/hooks/useWhatsAppInstances';
|
||||||
import { useWhatsAppActions } from '@/hooks/useWhatsAppActions';
|
import { useWhatsAppActions } from '@/hooks/useWhatsAppActions';
|
||||||
|
import { useToast } from '@/hooks/use-toast';
|
||||||
|
|
||||||
const WhatsApp = () => {
|
const WhatsApp = () => {
|
||||||
|
const { toast } = useToast();
|
||||||
const {
|
const {
|
||||||
instances,
|
instances,
|
||||||
isRefreshing,
|
isRefreshing,
|
||||||
@ -33,17 +35,20 @@ const WhatsApp = () => {
|
|||||||
|
|
||||||
// Set up periodic status checks
|
// Set up periodic status checks
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log("Setting up periodic status checks, current instances:", instances.length);
|
||||||
|
|
||||||
// Check status initially
|
// Check status initially
|
||||||
if (instances.length > 0) {
|
if (instances.length > 0) {
|
||||||
checkAllInstancesStatus();
|
checkAllInstancesStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up interval for periodic checks (every 60 seconds)
|
// Set up interval for periodic checks (every 30 seconds)
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
if (instances.length > 0) {
|
if (instances.length > 0) {
|
||||||
|
console.log("Running periodic status check");
|
||||||
checkAllInstancesStatus();
|
checkAllInstancesStatus();
|
||||||
}
|
}
|
||||||
}, 60000); // 60 seconds
|
}, 30000); // 30 seconds
|
||||||
|
|
||||||
// Clean up interval when component unmounts
|
// Clean up interval when component unmounts
|
||||||
return () => {
|
return () => {
|
||||||
@ -53,6 +58,21 @@ const WhatsApp = () => {
|
|||||||
};
|
};
|
||||||
}, [instances.length, checkAllInstancesStatus]);
|
}, [instances.length, checkAllInstancesStatus]);
|
||||||
|
|
||||||
|
// Run refresh instances on initial load to get server instances
|
||||||
|
useEffect(() => {
|
||||||
|
const initialLoad = async () => {
|
||||||
|
if (instances.length === 0) {
|
||||||
|
try {
|
||||||
|
await refreshInstances();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error on initial instance refresh:", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
initialLoad();
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Handler for when a new instance is created
|
// Handler for when a new instance is created
|
||||||
const handleInstanceCreated = async (newInstance: WhatsAppInstance) => {
|
const handleInstanceCreated = async (newInstance: WhatsAppInstance) => {
|
||||||
console.log('New instance to be added:', newInstance);
|
console.log('New instance to be added:', newInstance);
|
||||||
@ -64,14 +84,31 @@ const WhatsApp = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Trigger a status check for all instances
|
// Trigger a status check for all instances
|
||||||
|
try {
|
||||||
await checkAllInstancesStatus();
|
await checkAllInstancesStatus();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error checking status after instance creation:", error);
|
||||||
|
toast({
|
||||||
|
title: "Aviso",
|
||||||
|
description: "Instância criada, mas não foi possível verificar o status. Tente atualizar a lista manualmente.",
|
||||||
|
variant: "default",
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handler for when an instance is deleted
|
// Handler for when an instance is deleted
|
||||||
const handleDeleteInstanceWrapper = (instanceId: string) => {
|
const handleDeleteInstanceWrapper = (instanceId: string) => {
|
||||||
|
console.log(`Instance deletion requested for ID: ${instanceId}`);
|
||||||
const instanceToDelete = instances.find(i => i.instanceId === instanceId);
|
const instanceToDelete = instances.find(i => i.instanceId === instanceId);
|
||||||
if (instanceToDelete) {
|
if (instanceToDelete) {
|
||||||
handleDeleteInstance(instanceId, instanceToDelete.instanceName);
|
handleDeleteInstance(instanceId, instanceToDelete.instanceName);
|
||||||
|
} else {
|
||||||
|
console.error(`Instance with ID ${instanceId} not found for deletion`);
|
||||||
|
toast({
|
||||||
|
title: "Erro",
|
||||||
|
description: "Instância não encontrada para exclusão",
|
||||||
|
variant: "destructive",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -11,6 +11,7 @@ export const createWhatsAppInstance = async (
|
|||||||
instanceName: string,
|
instanceName: string,
|
||||||
phoneNumber: string
|
phoneNumber: string
|
||||||
): Promise<any> => {
|
): Promise<any> => {
|
||||||
|
console.log(`Creating new WhatsApp instance: ${instanceName}, ${phoneNumber}`);
|
||||||
const response = await fetch(`https://${SERVER_URL}/instance/create`, {
|
const response = await fetch(`https://${SERVER_URL}/instance/create`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -27,13 +28,17 @@ export const createWhatsAppInstance = async (
|
|||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json();
|
const errorData = await response.json();
|
||||||
|
console.error('Error creating instance:', errorData);
|
||||||
throw new Error(errorData.message || 'Erro ao criar instância');
|
throw new Error(errorData.message || 'Erro ao criar instância');
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.json();
|
const data = await response.json();
|
||||||
|
console.log('Create instance API response:', data);
|
||||||
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchQrCode = async (instanceName: string): Promise<any> => {
|
export const fetchQrCode = async (instanceName: string): Promise<any> => {
|
||||||
|
console.log(`Fetching QR code for instance: ${instanceName}`);
|
||||||
const response = await fetch(`https://${SERVER_URL}/instance/connect/${encodeURIComponent(instanceName)}`, {
|
const response = await fetch(`https://${SERVER_URL}/instance/connect/${encodeURIComponent(instanceName)}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
@ -44,14 +49,18 @@ export const fetchQrCode = async (instanceName: string): Promise<any> => {
|
|||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json();
|
const errorData = await response.json();
|
||||||
|
console.error('Error fetching QR code:', errorData);
|
||||||
throw new Error(errorData.message || 'Erro ao obter QR Code');
|
throw new Error(errorData.message || 'Erro ao obter QR Code');
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.json();
|
const data = await response.json();
|
||||||
|
console.log('QR code fetch response:', data);
|
||||||
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const fetchConnectionState = async (instanceName: string): Promise<'open' | 'closed' | 'connecting'> => {
|
export const fetchConnectionState = async (instanceName: string): Promise<'open' | 'closed' | 'connecting'> => {
|
||||||
try {
|
try {
|
||||||
|
console.log(`Fetching connection state for: ${instanceName}`);
|
||||||
const response = await fetch(`https://${SERVER_URL}/instance/connectionState/${encodeURIComponent(instanceName)}`, {
|
const response = await fetch(`https://${SERVER_URL}/instance/connectionState/${encodeURIComponent(instanceName)}`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
@ -61,13 +70,25 @@ export const fetchConnectionState = async (instanceName: string): Promise<'open'
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
|
const errorData = await response.json();
|
||||||
|
console.error(`Connection state error for ${instanceName}:`, errorData);
|
||||||
|
|
||||||
|
// If instance doesn't exist, throw a specific error
|
||||||
|
if (response.status === 404) {
|
||||||
|
throw new Error(`The "${instanceName}" instance does not exist`);
|
||||||
|
}
|
||||||
|
|
||||||
return 'closed';
|
return 'closed';
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
console.log(`Connection state for ${instanceName}:`, data);
|
||||||
return data.instance?.state || 'closed';
|
return data.instance?.state || 'closed';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching connection state:", error);
|
console.error(`Error fetching connection state for ${instanceName}:`, error);
|
||||||
|
if (error instanceof Error && error.message.includes("does not exist")) {
|
||||||
|
throw error; // Rethrow specific "does not exist" errors
|
||||||
|
}
|
||||||
return 'closed';
|
return 'closed';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -75,6 +96,7 @@ export const fetchConnectionState = async (instanceName: string): Promise<'open'
|
|||||||
// Nova função para listar todas as instâncias
|
// Nova função para listar todas as instâncias
|
||||||
export const fetchAllInstances = async (): Promise<any> => {
|
export const fetchAllInstances = async (): Promise<any> => {
|
||||||
try {
|
try {
|
||||||
|
console.log('Fetching all instances');
|
||||||
const response = await fetch(`https://${SERVER_URL}/fetch-instances`, {
|
const response = await fetch(`https://${SERVER_URL}/fetch-instances`, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
@ -84,10 +106,14 @@ export const fetchAllInstances = async (): Promise<any> => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Erro ao buscar instâncias');
|
const errorData = await response.json();
|
||||||
|
console.error('Error fetching instances:', errorData);
|
||||||
|
throw new Error(errorData.message || 'Erro ao buscar instâncias');
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.json();
|
const data = await response.json();
|
||||||
|
console.log('All instances response:', data);
|
||||||
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching all instances:", error);
|
console.error("Error fetching all instances:", error);
|
||||||
throw error;
|
throw error;
|
||||||
@ -97,6 +123,7 @@ export const fetchAllInstances = async (): Promise<any> => {
|
|||||||
// Função para reiniciar uma instância
|
// Função para reiniciar uma instância
|
||||||
export const restartInstance = async (instanceName: string): Promise<any> => {
|
export const restartInstance = async (instanceName: string): Promise<any> => {
|
||||||
try {
|
try {
|
||||||
|
console.log(`Restarting instance: ${instanceName}`);
|
||||||
const response = await fetch(`https://${SERVER_URL}/instance/restart/${encodeURIComponent(instanceName)}`, {
|
const response = await fetch(`https://${SERVER_URL}/instance/restart/${encodeURIComponent(instanceName)}`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: {
|
headers: {
|
||||||
@ -107,10 +134,13 @@ export const restartInstance = async (instanceName: string): Promise<any> => {
|
|||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json();
|
const errorData = await response.json();
|
||||||
|
console.error(`Error restarting instance ${instanceName}:`, errorData);
|
||||||
throw new Error(errorData.message || 'Erro ao reiniciar instância');
|
throw new Error(errorData.message || 'Erro ao reiniciar instância');
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.json();
|
const data = await response.json();
|
||||||
|
console.log(`Restart response for ${instanceName}:`, data);
|
||||||
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error restarting instance ${instanceName}:`, error);
|
console.error(`Error restarting instance ${instanceName}:`, error);
|
||||||
throw error;
|
throw error;
|
||||||
@ -120,6 +150,7 @@ export const restartInstance = async (instanceName: string): Promise<any> => {
|
|||||||
// Função para desconectar (logout) uma instância
|
// Função para desconectar (logout) uma instância
|
||||||
export const logoutInstance = async (instanceName: string): Promise<any> => {
|
export const logoutInstance = async (instanceName: string): Promise<any> => {
|
||||||
try {
|
try {
|
||||||
|
console.log(`Logging out instance: ${instanceName}`);
|
||||||
const response = await fetch(`https://${SERVER_URL}/instance/logout/${encodeURIComponent(instanceName)}`, {
|
const response = await fetch(`https://${SERVER_URL}/instance/logout/${encodeURIComponent(instanceName)}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: {
|
||||||
@ -130,10 +161,13 @@ export const logoutInstance = async (instanceName: string): Promise<any> => {
|
|||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json();
|
const errorData = await response.json();
|
||||||
|
console.error(`Error logging out instance ${instanceName}:`, errorData);
|
||||||
throw new Error(errorData.message || 'Erro ao desconectar instância');
|
throw new Error(errorData.message || 'Erro ao desconectar instância');
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.json();
|
const data = await response.json();
|
||||||
|
console.log(`Logout response for ${instanceName}:`, data);
|
||||||
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error logging out instance ${instanceName}:`, error);
|
console.error(`Error logging out instance ${instanceName}:`, error);
|
||||||
throw error;
|
throw error;
|
||||||
@ -143,6 +177,7 @@ export const logoutInstance = async (instanceName: string): Promise<any> => {
|
|||||||
// Função para excluir uma instância
|
// Função para excluir uma instância
|
||||||
export const deleteInstance = async (instanceName: string): Promise<any> => {
|
export const deleteInstance = async (instanceName: string): Promise<any> => {
|
||||||
try {
|
try {
|
||||||
|
console.log(`Deleting instance: ${instanceName}`);
|
||||||
const response = await fetch(`https://${SERVER_URL}/instance/${encodeURIComponent(instanceName)}`, {
|
const response = await fetch(`https://${SERVER_URL}/instance/${encodeURIComponent(instanceName)}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: {
|
||||||
@ -153,10 +188,13 @@ export const deleteInstance = async (instanceName: string): Promise<any> => {
|
|||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json();
|
const errorData = await response.json();
|
||||||
|
console.error(`Error deleting instance ${instanceName}:`, errorData);
|
||||||
throw new Error(errorData.message || 'Erro ao excluir instância');
|
throw new Error(errorData.message || 'Erro ao excluir instância');
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.json();
|
const data = await response.json();
|
||||||
|
console.log(`Delete response for ${instanceName}:`, data);
|
||||||
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error deleting instance ${instanceName}:`, error);
|
console.error(`Error deleting instance ${instanceName}:`, error);
|
||||||
throw error;
|
throw error;
|
||||||
@ -166,6 +204,7 @@ export const deleteInstance = async (instanceName: string): Promise<any> => {
|
|||||||
// Função para definir presença online/offline
|
// Função para definir presença online/offline
|
||||||
export const setInstancePresence = async (instanceName: string, presence: 'online' | 'offline'): Promise<any> => {
|
export const setInstancePresence = async (instanceName: string, presence: 'online' | 'offline'): Promise<any> => {
|
||||||
try {
|
try {
|
||||||
|
console.log(`Setting presence to ${presence} for: ${instanceName}`);
|
||||||
const response = await fetch(`https://${SERVER_URL}/instance/setPresence/${encodeURIComponent(instanceName)}`, {
|
const response = await fetch(`https://${SERVER_URL}/instance/setPresence/${encodeURIComponent(instanceName)}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
@ -177,10 +216,13 @@ export const setInstancePresence = async (instanceName: string, presence: 'onlin
|
|||||||
|
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const errorData = await response.json();
|
const errorData = await response.json();
|
||||||
|
console.error(`Error setting presence for ${instanceName}:`, errorData);
|
||||||
throw new Error(errorData.message || `Erro ao definir presença para ${presence}`);
|
throw new Error(errorData.message || `Erro ao definir presença para ${presence}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return response.json();
|
const data = await response.json();
|
||||||
|
console.log(`Set presence response for ${instanceName}:`, data);
|
||||||
|
return data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error setting presence to ${presence} for instance ${instanceName}:`, error);
|
console.error(`Error setting presence to ${presence} for instance ${instanceName}:`, error);
|
||||||
throw error;
|
throw error;
|
||||||
@ -192,11 +234,13 @@ export const saveInstancesToLocalStorage = (
|
|||||||
currentUserId: string
|
currentUserId: string
|
||||||
): void => {
|
): void => {
|
||||||
try {
|
try {
|
||||||
|
console.log(`Saving ${instances.length} instances for user ${currentUserId}`);
|
||||||
// Get existing instances from localStorage
|
// Get existing instances from localStorage
|
||||||
const savedInstancesStr = localStorage.getItem(STORAGE_KEY);
|
const savedInstancesStr = localStorage.getItem(STORAGE_KEY);
|
||||||
let allInstances: WhatsAppInstance[] = [];
|
let allInstances: WhatsAppInstance[] = [];
|
||||||
|
|
||||||
if (savedInstancesStr) {
|
if (savedInstancesStr) {
|
||||||
|
try {
|
||||||
// Parse saved instances
|
// Parse saved instances
|
||||||
const savedInstances = JSON.parse(savedInstancesStr);
|
const savedInstances = JSON.parse(savedInstancesStr);
|
||||||
|
|
||||||
@ -206,6 +250,9 @@ export const saveInstancesToLocalStorage = (
|
|||||||
(instance: WhatsAppInstance) => instance.userId !== currentUserId
|
(instance: WhatsAppInstance) => instance.userId !== currentUserId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} catch (parseError) {
|
||||||
|
console.error('Error parsing stored instances, resetting:', parseError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add current user's instances to the array
|
// Add current user's instances to the array
|
||||||
@ -223,10 +270,12 @@ export const loadInstancesFromLocalStorage = (
|
|||||||
userId: string
|
userId: string
|
||||||
): WhatsAppInstance[] => {
|
): WhatsAppInstance[] => {
|
||||||
try {
|
try {
|
||||||
|
console.log(`Loading instances for user: ${userId}`);
|
||||||
const savedInstancesStr = localStorage.getItem(STORAGE_KEY);
|
const savedInstancesStr = localStorage.getItem(STORAGE_KEY);
|
||||||
console.log('Raw saved instances from localStorage:', savedInstancesStr);
|
console.log('Raw saved instances from localStorage:', savedInstancesStr);
|
||||||
|
|
||||||
if (savedInstancesStr && userId) {
|
if (savedInstancesStr && userId) {
|
||||||
|
try {
|
||||||
// Parse saved instances
|
// Parse saved instances
|
||||||
const allInstances = JSON.parse(savedInstancesStr);
|
const allInstances = JSON.parse(savedInstancesStr);
|
||||||
|
|
||||||
@ -239,6 +288,9 @@ export const loadInstancesFromLocalStorage = (
|
|||||||
console.log(`Found ${userInstances.length} instances for user ${userId}:`, userInstances);
|
console.log(`Found ${userInstances.length} instances for user ${userId}:`, userInstances);
|
||||||
return userInstances;
|
return userInstances;
|
||||||
}
|
}
|
||||||
|
} catch (parseError) {
|
||||||
|
console.error('Error parsing stored instances:', parseError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
console.log(`No instances found for user ${userId}`);
|
console.log(`No instances found for user ${userId}`);
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user