Add advanced instance management features
Implement instance listing, restart, disconnect, delete, and presence setting functionalities with confirmation dialogs and UI updates.
This commit is contained in:
parent
686b682c19
commit
b0d6e88a76
@ -1,63 +1,261 @@
|
||||
|
||||
import { useState } from 'react';
|
||||
import { Card, CardHeader, CardTitle, CardContent, CardFooter } from '@/components/ui/card';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Badge } from '@/components/ui/badge';
|
||||
import { QrCode, Smartphone } from 'lucide-react';
|
||||
import {
|
||||
QrCode,
|
||||
Smartphone,
|
||||
RefreshCw,
|
||||
X,
|
||||
PowerOff,
|
||||
CircleDot,
|
||||
CircleOff
|
||||
} from 'lucide-react';
|
||||
import { WhatsAppInstance } from '@/types/whatsAppTypes';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
|
||||
interface InstanceCardProps {
|
||||
instance: WhatsAppInstance;
|
||||
onViewQrCode: (instance: WhatsAppInstance) => void;
|
||||
onDelete: (instanceId: string) => void;
|
||||
onRestart: (instance: WhatsAppInstance) => Promise<void>;
|
||||
onLogout: (instance: WhatsAppInstance) => Promise<void>;
|
||||
onSetPresence: (instance: WhatsAppInstance, presence: 'online' | 'offline') => Promise<void>;
|
||||
}
|
||||
|
||||
const InstanceCard = ({ instance, onViewQrCode, onDelete }: InstanceCardProps) => {
|
||||
const InstanceCard = ({
|
||||
instance,
|
||||
onViewQrCode,
|
||||
onDelete,
|
||||
onRestart,
|
||||
onLogout,
|
||||
onSetPresence
|
||||
}: InstanceCardProps) => {
|
||||
const [loading, setLoading] = useState<string | null>(null);
|
||||
const [confirmAction, setConfirmAction] = useState<{
|
||||
open: boolean;
|
||||
title: string;
|
||||
description: string;
|
||||
action: () => Promise<void>;
|
||||
actionLabel: string;
|
||||
} | null>(null);
|
||||
|
||||
// Função para processar uma ação com confirmação
|
||||
const handleConfirmAction = (
|
||||
title: string,
|
||||
description: string,
|
||||
action: () => Promise<void>,
|
||||
actionLabel: string = "Confirmar"
|
||||
) => {
|
||||
setConfirmAction({
|
||||
open: true,
|
||||
title,
|
||||
description,
|
||||
action,
|
||||
actionLabel
|
||||
});
|
||||
};
|
||||
|
||||
// Executa a ação após confirmação
|
||||
const executeAction = async () => {
|
||||
if (!confirmAction) return;
|
||||
|
||||
try {
|
||||
setLoading(confirmAction.title);
|
||||
await confirmAction.action();
|
||||
} catch (error) {
|
||||
console.error("Error executing action:", error);
|
||||
} finally {
|
||||
setLoading(null);
|
||||
setConfirmAction(null);
|
||||
}
|
||||
};
|
||||
|
||||
// Handler para reiniciar instância
|
||||
const handleRestart = () => {
|
||||
handleConfirmAction(
|
||||
"Reiniciar Instância",
|
||||
`Deseja realmente reiniciar a instância "${instance.instanceName}"? A conexão atual será fechada e restabelecida.`,
|
||||
async () => {
|
||||
await onRestart(instance);
|
||||
},
|
||||
"Reiniciar"
|
||||
);
|
||||
};
|
||||
|
||||
// Handler para deslogar instância
|
||||
const handleLogout = () => {
|
||||
handleConfirmAction(
|
||||
"Desconectar Instância",
|
||||
`Deseja realmente desconectar a instância "${instance.instanceName}"? Você precisará escanear o QR Code novamente para reconectar.`,
|
||||
async () => {
|
||||
await onLogout(instance);
|
||||
},
|
||||
"Desconectar"
|
||||
);
|
||||
};
|
||||
|
||||
// Handler para apagar instância
|
||||
const handleDelete = () => {
|
||||
handleConfirmAction(
|
||||
"Excluir Instância",
|
||||
`Deseja realmente excluir a instância "${instance.instanceName}"? Esta ação não pode ser desfeita.`,
|
||||
async () => {
|
||||
onDelete(instance.instanceId);
|
||||
},
|
||||
"Excluir"
|
||||
);
|
||||
};
|
||||
|
||||
// Handler para definir presença online
|
||||
const handleSetOnline = () => {
|
||||
handleConfirmAction(
|
||||
"Definir Presença Online",
|
||||
`Deseja alterar o status da instância "${instance.instanceName}" para Online?`,
|
||||
async () => {
|
||||
await onSetPresence(instance, 'online');
|
||||
},
|
||||
"Definir Online"
|
||||
);
|
||||
};
|
||||
|
||||
// Handler para definir presença offline
|
||||
const handleSetOffline = () => {
|
||||
handleConfirmAction(
|
||||
"Definir Presença Offline",
|
||||
`Deseja alterar o status da instância "${instance.instanceName}" para Offline?`,
|
||||
async () => {
|
||||
await onSetPresence(instance, 'offline');
|
||||
},
|
||||
"Definir Offline"
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<Card className="h-full">
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-lg">{instance.instanceName}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pb-2">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center text-sm">
|
||||
<Smartphone className="h-4 w-4 mr-2 text-gray-500" />
|
||||
<span>{instance.phoneNumber}</span>
|
||||
<>
|
||||
<Card className="h-full">
|
||||
<CardHeader className="pb-2">
|
||||
<CardTitle className="text-lg">{instance.instanceName}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="pb-2">
|
||||
<div className="space-y-2">
|
||||
<div className="flex items-center text-sm">
|
||||
<Smartphone className="h-4 w-4 mr-2 text-gray-500" />
|
||||
<span>{instance.phoneNumber}</span>
|
||||
</div>
|
||||
<div className="flex items-center text-sm">
|
||||
{instance.connectionState === 'open' ? (
|
||||
<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>
|
||||
Status: Conectado
|
||||
</Badge>
|
||||
) : (
|
||||
<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>
|
||||
Status: Desconectado
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center text-sm">
|
||||
{instance.connectionState === 'open' ? (
|
||||
<Badge variant="success" className="flex items-center gap-1">
|
||||
<span className="inline-block w-2 h-2 rounded-full bg-green-500"></span>
|
||||
Status: Conectado
|
||||
</Badge>
|
||||
) : (
|
||||
<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>
|
||||
Status: Desconectado
|
||||
</Badge>
|
||||
)}
|
||||
</CardContent>
|
||||
<CardFooter className="flex flex-col gap-2">
|
||||
<div className="flex justify-between w-full">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => onViewQrCode(instance)}
|
||||
className="flex items-center"
|
||||
>
|
||||
<QrCode className="h-4 w-4 mr-2" />
|
||||
Ver QR Code
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-red-500 hover:text-red-700 hover:bg-red-50"
|
||||
onClick={handleDelete}
|
||||
disabled={loading !== null}
|
||||
>
|
||||
<X className="h-4 w-4 mr-2" />
|
||||
Excluir
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
<CardFooter className="flex justify-between">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={() => onViewQrCode(instance)}
|
||||
className="flex items-center"
|
||||
>
|
||||
<QrCode className="h-4 w-4 mr-2" />
|
||||
Ver QR Code
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="text-red-500 hover:text-red-700 hover:bg-red-50"
|
||||
onClick={() => onDelete(instance.instanceId)}
|
||||
>
|
||||
Remover
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
<div className="grid grid-cols-2 gap-2 w-full">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleRestart}
|
||||
disabled={loading !== null}
|
||||
>
|
||||
<RefreshCw className="h-4 w-4 mr-1" />
|
||||
Reiniciar
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleLogout}
|
||||
disabled={loading !== null}
|
||||
>
|
||||
<PowerOff className="h-4 w-4 mr-1" />
|
||||
Desconectar
|
||||
</Button>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-2 w-full">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleSetOnline}
|
||||
disabled={loading !== null}
|
||||
className="bg-green-50 hover:bg-green-100 text-green-700"
|
||||
>
|
||||
<CircleDot className="h-4 w-4 mr-1" />
|
||||
Definir Online
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleSetOffline}
|
||||
disabled={loading !== null}
|
||||
className="bg-red-50 hover:bg-red-100 text-red-700"
|
||||
>
|
||||
<CircleOff className="h-4 w-4 mr-1" />
|
||||
Definir Offline
|
||||
</Button>
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
|
||||
<AlertDialog open={confirmAction?.open} onOpenChange={(open) => !open && setConfirmAction(null)}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>{confirmAction?.title}</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
{confirmAction?.description}
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel disabled={loading !== null}>Cancelar</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={executeAction}
|
||||
disabled={loading !== null}
|
||||
className={loading === confirmAction?.title ? "opacity-50 cursor-not-allowed" : ""}
|
||||
>
|
||||
{loading === confirmAction?.title ? "Processando..." : confirmAction?.actionLabel}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,15 +1,31 @@
|
||||
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import InstanceCard from './InstanceCard';
|
||||
import { WhatsAppInstance } from '@/types/whatsAppTypes';
|
||||
import { RefreshCw } from 'lucide-react';
|
||||
|
||||
interface InstanceListProps {
|
||||
instances: WhatsAppInstance[];
|
||||
onViewQrCode: (instance: WhatsAppInstance) => void;
|
||||
onDelete: (instanceId: string) => void;
|
||||
onRestart: (instance: WhatsAppInstance) => Promise<void>;
|
||||
onLogout: (instance: WhatsAppInstance) => Promise<void>;
|
||||
onSetPresence: (instance: WhatsAppInstance, presence: 'online' | 'offline') => Promise<void>;
|
||||
onRefreshInstances: () => Promise<void>;
|
||||
isRefreshing: boolean;
|
||||
}
|
||||
|
||||
const InstanceList = ({ instances, onViewQrCode, onDelete }: InstanceListProps) => {
|
||||
const InstanceList = ({
|
||||
instances,
|
||||
onViewQrCode,
|
||||
onDelete,
|
||||
onRestart,
|
||||
onLogout,
|
||||
onSetPresence,
|
||||
onRefreshInstances,
|
||||
isRefreshing
|
||||
}: InstanceListProps) => {
|
||||
if (instances.length === 0) {
|
||||
return (
|
||||
<Card>
|
||||
@ -25,7 +41,18 @@ const InstanceList = ({ instances, onViewQrCode, onDelete }: InstanceListProps)
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-xl font-semibold">Instâncias Criadas</h2>
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className="text-xl font-semibold">Instâncias Criadas</h2>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={onRefreshInstances}
|
||||
disabled={isRefreshing}
|
||||
>
|
||||
<RefreshCw className={`h-4 w-4 mr-2 ${isRefreshing ? 'animate-spin' : ''}`} />
|
||||
{isRefreshing ? 'Atualizando...' : 'Atualizar Lista'}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
{instances.map((instance) => (
|
||||
<InstanceCard
|
||||
@ -33,6 +60,9 @@ const InstanceList = ({ instances, onViewQrCode, onDelete }: InstanceListProps)
|
||||
instance={instance}
|
||||
onViewQrCode={onViewQrCode}
|
||||
onDelete={onDelete}
|
||||
onRestart={onRestart}
|
||||
onLogout={onLogout}
|
||||
onSetPresence={onSetPresence}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@ -7,7 +7,12 @@ import {
|
||||
fetchQrCode,
|
||||
fetchConnectionState,
|
||||
saveInstancesToLocalStorage,
|
||||
loadInstancesFromLocalStorage
|
||||
loadInstancesFromLocalStorage,
|
||||
fetchAllInstances,
|
||||
restartInstance,
|
||||
logoutInstance,
|
||||
deleteInstance,
|
||||
setInstancePresence
|
||||
} from '@/services/whatsAppService';
|
||||
import CreateInstanceForm from '@/components/whatsapp/CreateInstanceForm';
|
||||
import InstanceList from '@/components/whatsapp/InstanceList';
|
||||
@ -20,6 +25,7 @@ const WhatsApp = () => {
|
||||
const [qrDialogOpen, setQrDialogOpen] = useState(false);
|
||||
const [statusCheckInterval, setStatusCheckInterval] = useState<NodeJS.Timeout | null>(null);
|
||||
const [currentUserId, setCurrentUserId] = useState<string>('');
|
||||
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||
|
||||
// Get current user ID and load instances on component mount
|
||||
useEffect(() => {
|
||||
@ -113,6 +119,155 @@ const WhatsApp = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// Handler para atualizar a lista de instâncias do servidor
|
||||
const handleRefreshInstances = async () => {
|
||||
if (!currentUserId) {
|
||||
toast({
|
||||
title: "Erro de autenticação",
|
||||
description: "Você precisa estar logado para atualizar as instâncias",
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setIsRefreshing(true);
|
||||
try {
|
||||
const response = await fetchAllInstances();
|
||||
console.log("Fetched instances from server:", response);
|
||||
|
||||
if (response.instances && Array.isArray(response.instances)) {
|
||||
// Filtra instâncias para mostrar apenas as do usuário atual
|
||||
// E mapeia para o formato correto com userId
|
||||
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 => ({
|
||||
instanceName: serverInstance.instanceName,
|
||||
instanceId: serverInstance.instanceName,
|
||||
phoneNumber: serverInstance.number || 'Desconhecido',
|
||||
userId: currentUserId,
|
||||
connectionState: serverInstance.state || 'closed',
|
||||
status: serverInstance.status || 'unknown'
|
||||
}));
|
||||
|
||||
// Mesclando instâncias do servidor com as locais (para não perder dados locais)
|
||||
const localInstanceIds = new Set(instances.map(i => i.instanceId));
|
||||
const newInstances = [
|
||||
...instances,
|
||||
...serverInstances.filter(i => !localInstanceIds.has(i.instanceId))
|
||||
];
|
||||
|
||||
setInstances(newInstances);
|
||||
toast({
|
||||
title: "Sucesso",
|
||||
description: `${serverInstances.length} instâncias encontradas no servidor`,
|
||||
});
|
||||
} else {
|
||||
toast({
|
||||
title: "Aviso",
|
||||
description: "Nenhuma instância encontrada no servidor",
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Erro ao buscar instâncias:", error);
|
||||
toast({
|
||||
title: "Erro",
|
||||
description: "Falha ao buscar instâncias do servidor",
|
||||
variant: "destructive",
|
||||
});
|
||||
} finally {
|
||||
setIsRefreshing(false);
|
||||
// Verificar status após atualizar a lista
|
||||
checkAllInstancesStatus();
|
||||
}
|
||||
};
|
||||
|
||||
// Handler for quando uma instância é reiniciada
|
||||
const handleRestartInstance = async (instance: WhatsAppInstance) => {
|
||||
try {
|
||||
await restartInstance(instance.instanceName);
|
||||
|
||||
// Atualiza o estado da instância para "connecting"
|
||||
setInstances(prev =>
|
||||
prev.map(i =>
|
||||
i.instanceId === instance.instanceId
|
||||
? { ...i, connectionState: 'connecting' as const }
|
||||
: i
|
||||
)
|
||||
);
|
||||
|
||||
toast({
|
||||
title: "Sucesso",
|
||||
description: `Instância ${instance.instanceName} reiniciada com sucesso`
|
||||
});
|
||||
|
||||
// Verifica o status após um breve delay para dar tempo de atualizar
|
||||
setTimeout(() => checkAllInstancesStatus(), 3000);
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error restarting instance ${instance.instanceName}:`, error);
|
||||
toast({
|
||||
title: "Erro",
|
||||
description: `Falha ao reiniciar a instância ${instance.instanceName}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Handler for quando uma instância é desconectada
|
||||
const handleLogoutInstance = async (instance: WhatsAppInstance) => {
|
||||
try {
|
||||
await logoutInstance(instance.instanceName);
|
||||
|
||||
// Atualiza o estado da instância para "closed"
|
||||
setInstances(prev =>
|
||||
prev.map(i =>
|
||||
i.instanceId === instance.instanceId
|
||||
? { ...i, connectionState: 'closed' as const }
|
||||
: i
|
||||
)
|
||||
);
|
||||
|
||||
toast({
|
||||
title: "Sucesso",
|
||||
description: `Instância ${instance.instanceName} desconectada com sucesso`
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error logging out instance ${instance.instanceName}:`, error);
|
||||
toast({
|
||||
title: "Erro",
|
||||
description: `Falha ao desconectar a instância ${instance.instanceName}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Handler for quando a presença é alterada
|
||||
const handleSetPresence = async (instance: WhatsAppInstance, presence: 'online' | 'offline') => {
|
||||
try {
|
||||
await setInstancePresence(instance.instanceName, presence);
|
||||
|
||||
toast({
|
||||
title: "Sucesso",
|
||||
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) {
|
||||
console.error(`Error setting presence to ${presence} for instance ${instance.instanceName}:`, error);
|
||||
toast({
|
||||
title: "Erro",
|
||||
description: `Falha ao definir presença ${presence} para ${instance.instanceName}`,
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Handler for when a new instance is created
|
||||
const handleInstanceCreated = async (newInstance: WhatsAppInstance) => {
|
||||
console.log("New instance created, adding to instances list:", newInstance);
|
||||
@ -152,23 +307,49 @@ const WhatsApp = () => {
|
||||
};
|
||||
|
||||
// Handler for when an instance is deleted
|
||||
const handleDeleteInstance = (instanceId: string) => {
|
||||
const handleDeleteInstance = async (instanceId: string) => {
|
||||
console.log(`Deleting instance with ID: ${instanceId}`);
|
||||
setInstances(prevInstances => {
|
||||
const filtered = prevInstances.filter(instance => instance.instanceId !== instanceId);
|
||||
console.log("Updated instances after deletion:", filtered);
|
||||
return filtered;
|
||||
});
|
||||
|
||||
// If we're viewing QR code for this instance, close the dialog
|
||||
if (activeInstance?.instanceId === instanceId) {
|
||||
setQrDialogOpen(false);
|
||||
// Find the instance before deleting it
|
||||
const instanceToDelete = instances.find(i => i.instanceId === instanceId);
|
||||
|
||||
if (!instanceToDelete) {
|
||||
toast({
|
||||
title: "Erro",
|
||||
description: "Instância não encontrada",
|
||||
variant: "destructive",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
toast({
|
||||
title: "Instância removida",
|
||||
description: "A instância do WhatsApp foi removida com sucesso.",
|
||||
});
|
||||
try {
|
||||
// Call API to delete instance
|
||||
await deleteInstance(instanceToDelete.instanceName);
|
||||
|
||||
// Remove from local state if API call was successful
|
||||
setInstances(prevInstances => {
|
||||
const filtered = prevInstances.filter(instance => instance.instanceId !== instanceId);
|
||||
console.log("Updated instances after deletion:", filtered);
|
||||
return filtered;
|
||||
});
|
||||
|
||||
// If we're viewing QR code for this instance, close the dialog
|
||||
if (activeInstance?.instanceId === instanceId) {
|
||||
setQrDialogOpen(false);
|
||||
}
|
||||
|
||||
toast({
|
||||
title: "Instância removida",
|
||||
description: "A instância do WhatsApp foi removida com sucesso.",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`Error deleting instance with ID ${instanceId}:`, error);
|
||||
toast({
|
||||
title: "Erro",
|
||||
description: "Falha ao excluir a instância. Tente novamente.",
|
||||
variant: "destructive",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@ -185,7 +366,12 @@ const WhatsApp = () => {
|
||||
<InstanceList
|
||||
instances={instances}
|
||||
onViewQrCode={handleViewQrCode}
|
||||
onDelete={handleDeleteInstance}
|
||||
onDelete={handleDeleteInstance}
|
||||
onRestart={handleRestartInstance}
|
||||
onLogout={handleLogoutInstance}
|
||||
onSetPresence={handleSetPresence}
|
||||
onRefreshInstances={handleRefreshInstances}
|
||||
isRefreshing={isRefreshing}
|
||||
/>
|
||||
|
||||
{/* QR Code Dialog */}
|
||||
|
||||
@ -69,6 +69,121 @@ export const fetchConnectionState = async (instanceName: string): Promise<'open'
|
||||
}
|
||||
};
|
||||
|
||||
// Nova função para listar todas as instâncias
|
||||
export const fetchAllInstances = async (): Promise<any> => {
|
||||
try {
|
||||
const response = await fetch(`https://${SERVER_URL}/fetch-instances`, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'apikey': API_KEY
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Erro ao buscar instâncias');
|
||||
}
|
||||
|
||||
return response.json();
|
||||
} catch (error) {
|
||||
console.error("Error fetching all instances:", error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Função para reiniciar uma instância
|
||||
export const restartInstance = async (instanceName: string): Promise<any> => {
|
||||
try {
|
||||
const response = await fetch(`https://${SERVER_URL}/instance/restart/${encodeURIComponent(instanceName)}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'apikey': API_KEY
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
throw new Error(errorData.message || 'Erro ao reiniciar instância');
|
||||
}
|
||||
|
||||
return response.json();
|
||||
} catch (error) {
|
||||
console.error(`Error restarting instance ${instanceName}:`, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Função para desconectar (logout) uma instância
|
||||
export const logoutInstance = async (instanceName: string): Promise<any> => {
|
||||
try {
|
||||
const response = await fetch(`https://${SERVER_URL}/instance/logout/${encodeURIComponent(instanceName)}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'apikey': API_KEY
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
throw new Error(errorData.message || 'Erro ao desconectar instância');
|
||||
}
|
||||
|
||||
return response.json();
|
||||
} catch (error) {
|
||||
console.error(`Error logging out instance ${instanceName}:`, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Função para excluir uma instância
|
||||
export const deleteInstance = async (instanceName: string): Promise<any> => {
|
||||
try {
|
||||
const response = await fetch(`https://${SERVER_URL}/instance/${encodeURIComponent(instanceName)}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'apikey': API_KEY
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
throw new Error(errorData.message || 'Erro ao excluir instância');
|
||||
}
|
||||
|
||||
return response.json();
|
||||
} catch (error) {
|
||||
console.error(`Error deleting instance ${instanceName}:`, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Função para definir presença online/offline
|
||||
export const setInstancePresence = async (instanceName: string, presence: 'online' | 'offline'): Promise<any> => {
|
||||
try {
|
||||
const response = await fetch(`https://${SERVER_URL}/instance/setPresence/${encodeURIComponent(instanceName)}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'apikey': API_KEY
|
||||
},
|
||||
body: JSON.stringify({ presence })
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json();
|
||||
throw new Error(errorData.message || `Erro ao definir presença para ${presence}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
} catch (error) {
|
||||
console.error(`Error setting presence to ${presence} for instance ${instanceName}:`, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
export const saveInstancesToLocalStorage = (
|
||||
instances: WhatsAppInstance[],
|
||||
currentUserId: string
|
||||
|
||||
@ -5,6 +5,7 @@ export interface WhatsAppInstance {
|
||||
phoneNumber: string;
|
||||
userId: string;
|
||||
status?: string;
|
||||
qrcode?: string;
|
||||
qrcode?: string | null;
|
||||
connectionState?: 'open' | 'closed' | 'connecting';
|
||||
presence?: 'online' | 'offline';
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user