Feat: Fetch WhatsApp instance on mount

Adds functionality to fetch a WhatsApp instance from the Evolution API when the "Conectar WhatsApp" menu is accessed. The request uses the instance name entered in the form, includes the necessary headers, and displays the instance information. It also handles cases where the user is not logged in and when the instance is not found.
This commit is contained in:
gpt-engineer-app[bot] 2025-05-20 16:01:08 +00:00
parent 002103e676
commit 12e6cda1df
3 changed files with 155 additions and 41 deletions

View File

@ -1,5 +1,5 @@
import { useState } from 'react'; import { useState, useEffect } from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
@ -11,17 +11,35 @@ import { WhatsAppInstance } from '@/types/whatsAppTypes';
interface CreateInstanceFormProps { interface CreateInstanceFormProps {
onInstanceCreated: (instance: WhatsAppInstance) => void; onInstanceCreated: (instance: WhatsAppInstance) => void;
initialInstanceName?: string;
onInstanceNameChange?: (name: string) => void;
} }
const CreateInstanceForm = ({ onInstanceCreated }: CreateInstanceFormProps) => { const CreateInstanceForm = ({
onInstanceCreated,
initialInstanceName = '',
onInstanceNameChange
}: CreateInstanceFormProps) => {
const { toast } = useToast(); const { toast } = useToast();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [instanceName, setInstanceName] = useState(() => { const [instanceName, setInstanceName] = useState(initialInstanceName || '');
// Get user's name from localStorage as default value
return localStorage.getItem('userName') || '';
});
const [phoneNumber, setPhoneNumber] = useState(''); const [phoneNumber, setPhoneNumber] = useState('');
const currentUserId = localStorage.getItem('userId') || ''; const currentUserId = localStorage.getItem('userId') || '';
// Update instance name if initial value changes
useEffect(() => {
if (initialInstanceName) {
setInstanceName(initialInstanceName);
}
}, [initialInstanceName]);
const handleInstanceNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newName = e.target.value;
setInstanceName(newName);
if (onInstanceNameChange) {
onInstanceNameChange(newName);
}
};
const handleCreateInstance = async () => { const handleCreateInstance = async () => {
// Validate form fields // Validate form fields
@ -115,7 +133,7 @@ const CreateInstanceForm = ({ onInstanceCreated }: CreateInstanceFormProps) => {
<Input <Input
id="instanceName" id="instanceName"
value={instanceName} value={instanceName}
onChange={(e) => setInstanceName(e.target.value)} onChange={handleInstanceNameChange}
placeholder="Digite um nome para a instância" placeholder="Digite um nome para a instância"
required required
/> />

View File

@ -1,5 +1,5 @@
import { useEffect } from 'react'; import { useEffect, useState } from 'react';
import Layout from '@/components/layout/Layout'; import Layout from '@/components/layout/Layout';
import { WhatsAppInstance } from '@/types/whatsAppTypes'; import { WhatsAppInstance } from '@/types/whatsAppTypes';
import CreateInstanceForm from '@/components/whatsapp/CreateInstanceForm'; import CreateInstanceForm from '@/components/whatsapp/CreateInstanceForm';
@ -9,6 +9,7 @@ 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'; import { useToast } from '@/hooks/use-toast';
import { fetchSpecificInstance } from '@/services/whatsApp/instanceManagement';
const WhatsApp = () => { const WhatsApp = () => {
const { toast } = useToast(); const { toast } = useToast();
@ -32,6 +33,64 @@ const WhatsApp = () => {
handleDeleteInstance, handleDeleteInstance,
handleViewQrCode handleViewQrCode
} = useWhatsAppActions(updateInstance, removeInstance, checkAllInstancesStatus); } = useWhatsAppActions(updateInstance, removeInstance, checkAllInstancesStatus);
const [instanceName, setInstanceName] = useState(() => {
// Get user's name from localStorage as default instance name
return localStorage.getItem('userName') || '';
});
const [isLoading, setIsLoading] = useState(false);
const [instanceFound, setInstanceFound] = useState(false);
const currentUserId = localStorage.getItem('userId') || '';
// Function to fetch specific instance by name
const fetchInstanceByName = async () => {
// Skip if user not logged in or no instance name
if (!currentUserId || !instanceName.trim()) {
return;
}
setIsLoading(true);
try {
console.log(`Fetching specific instance: ${instanceName}`);
const data = await fetchSpecificInstance(instanceName);
console.log('Fetch specific instance response:', data);
if (data && data.instance) {
// Instance found, create or update instance object
const foundInstance: WhatsAppInstance = {
instanceName,
instanceId: instanceName,
phoneNumber: data.instance.number || '',
userId: currentUserId,
status: data.instance.status || 'unknown',
connectionState: data.instance.state || 'closed',
qrcode: data.qrcode?.base64 || null
};
console.log('Found instance:', foundInstance);
addInstance(foundInstance);
setInstanceFound(true);
toast({
title: "Instância encontrada",
description: `A instância ${instanceName} foi localizada no servidor.`
});
} else {
setInstanceFound(false);
console.log(`Instance ${instanceName} not found`);
}
} catch (error) {
console.error('Error fetching specific instance:', error);
setInstanceFound(false);
toast({
title: "Instância não encontrada",
description: "Não foi possível encontrar a instância com este nome.",
variant: "destructive"
});
} finally {
setIsLoading(false);
}
};
// Set up periodic status checks // Set up periodic status checks
useEffect(() => { useEffect(() => {
@ -63,28 +122,29 @@ const WhatsApp = () => {
}; };
}, [instances.length, checkAllInstancesStatus]); }, [instances.length, checkAllInstancesStatus]);
// Run refresh instances on initial load to get server instances // Fetch the specific instance when the component mounts
useEffect(() => { useEffect(() => {
// Only run on first render if (currentUserId) {
const initialLoad = async () => { fetchInstanceByName();
if (instances.length === 0) { } else {
try { toast({
await refreshInstances(); title: "Login necessário",
} catch (error) { description: "Você precisa estar logado para ver suas instâncias do WhatsApp.",
console.error("Error on initial instance refresh:", error); variant: "destructive"
} });
} }
}; }, [currentUserId, instanceName]);
initialLoad(); // Handler for when the user changes the instance name
// This effect should only run once when the component mounts const handleInstanceNameChange = (name: string) => {
// eslint-disable-next-line react-hooks/exhaustive-deps setInstanceName(name);
}, []); };
// 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);
addInstance(newInstance); addInstance(newInstance);
setInstanceFound(true);
// If there's a QR code in the response, show it // If there's a QR code in the response, show it
if (newInstance.qrcode) { if (newInstance.qrcode) {
@ -123,6 +183,7 @@ const WhatsApp = () => {
}; };
console.log('Current instances in WhatsApp component:', instances); console.log('Current instances in WhatsApp component:', instances);
console.log('Instance found status:', instanceFound);
return ( return (
<Layout> <Layout>
@ -131,23 +192,37 @@ const WhatsApp = () => {
<h1 className="text-2xl font-bold tracking-tight">Conectar WhatsApp</h1> <h1 className="text-2xl font-bold tracking-tight">Conectar WhatsApp</h1>
</div> </div>
{/* Form to create a new instance */} {isLoading ? (
<CreateInstanceForm onInstanceCreated={handleInstanceCreated} /> <div className="flex justify-center items-center p-10">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-primary"></div>
{/* Stats component */} <p className="ml-3">Buscando instância...</p>
<InstanceStats instances={instances} /> </div>
) : !instanceFound ? (
{/* List of created instances */} // Show create form if no instance found
<InstanceList <CreateInstanceForm
instances={instances} onInstanceCreated={handleInstanceCreated}
onViewQrCode={handleViewQrCode} initialInstanceName={instanceName}
onDelete={handleDeleteInstanceWrapper} onInstanceNameChange={handleInstanceNameChange}
onRestart={handleRestartInstance} />
onLogout={handleLogoutInstance} ) : (
onSetPresence={handleSetPresence} // Only show stats and instance list if instance found
onRefreshInstances={refreshInstances} <>
isRefreshing={isRefreshing} {/* Stats component */}
/> <InstanceStats instances={instances} />
{/* List of created instances */}
<InstanceList
instances={instances}
onViewQrCode={handleViewQrCode}
onDelete={handleDeleteInstanceWrapper}
onRestart={handleRestartInstance}
onLogout={handleLogoutInstance}
onSetPresence={handleSetPresence}
onRefreshInstances={refreshInstances}
isRefreshing={isRefreshing}
/>
</>
)}
{/* QR Code Dialog */} {/* QR Code Dialog */}
<QrCodeDialog <QrCodeDialog

View File

@ -78,3 +78,24 @@ export const fetchAllInstances = async (): Promise<any> => {
throw error; throw error;
} }
}; };
/**
* Fetches a specific WhatsApp instance by name
*/
export const fetchSpecificInstance = async (instanceName: string): Promise<any> => {
try {
console.log(`Fetching specific instance: ${instanceName}`);
if (!instanceName) {
throw new Error("Instance name cannot be empty");
}
const data = await makeRequest(`/instance/fetchInstances/${encodeURIComponent(instanceName)}`, 'GET');
console.log(`Specific instance response for ${instanceName}:`, data);
return data;
} catch (error) {
console.error(`Error fetching specific instance ${instanceName}:`, error);
throw error;
}
};