feat: Implement "Atualizar Lista" button

The "Connect WhatsApp" menu now loads instances only on clicking the "Atualizar Lista" button. The button fetches instances from the API, filters by the user's instance name, and displays the results. It also shows an appropriate message if no instances are found and addresses potential rendering errors.
This commit is contained in:
gpt-engineer-app[bot] 2025-05-20 19:26:10 +00:00
parent 66e18c3988
commit a9ee70ccb6
5 changed files with 73 additions and 55 deletions

View File

@ -26,13 +26,26 @@ const InstanceList = ({
onRefreshInstances, onRefreshInstances,
isRefreshing isRefreshing
}: InstanceListProps) => { }: InstanceListProps) => {
if (instances.length === 0) { // Safely check if instances is an array and has elements
const hasInstances = Array.isArray(instances) && instances.length > 0;
if (!hasInstances) {
return ( return (
<Card> <Card>
<CardContent className="py-6"> <CardContent className="py-6">
<div className="text-center text-muted-foreground"> <div className="text-center text-muted-foreground">
<p>Nenhuma instância criada ainda.</p> <p>Nenhuma instância criada ainda.</p>
<p className="mt-1">Crie uma instância usando o formulário acima.</p> <p className="mt-1">Clique em 'Atualizar Lista' para buscar novamente.</p>
<Button
variant="outline"
size="sm"
onClick={onRefreshInstances}
disabled={isRefreshing}
className="mt-4"
>
<RefreshCw className={`h-4 w-4 mr-2 ${isRefreshing ? 'animate-spin' : ''}`} />
{isRefreshing ? 'Atualizando...' : 'Atualizar Lista'}
</Button>
</div> </div>
</CardContent> </CardContent>
</Card> </Card>
@ -43,15 +56,6 @@ const InstanceList = ({
<div className="space-y-4"> <div className="space-y-4">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<h2 className="text-xl font-semibold">Instâncias Criadas</h2> <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>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{instances.map((instance) => ( {instances.map((instance) => (

View File

@ -28,9 +28,18 @@ export const useInstanceRefresh = (
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 && response.instances && Array.isArray(response.instances)) {
// Busca o nome da instância salvo para o usuário atual
const savedInstanceName = localStorage.getItem(`whatsapp_instance_name_${currentUserId}`);
console.log("Saved instance name for current user:", savedInstanceName);
// Filtra as instâncias pelo nome criado pelo usuário
const filteredInstances = savedInstanceName
? response.instances.filter(instance => instance.instanceName === savedInstanceName)
: response.instances;
// Mapeia as instâncias do servidor para o formato correto com userId // Mapeia as instâncias do servidor para o formato correto com userId
const serverInstances: WhatsAppInstance[] = response.instances const serverInstances: WhatsAppInstance[] = filteredInstances
.map(serverInstance => { .map(serverInstance => {
// Ensure we convert server state to valid connectionState // Ensure we convert server state to valid connectionState
let connectionState: 'open' | 'closed' | 'connecting'; let connectionState: 'open' | 'closed' | 'connecting';
@ -53,36 +62,28 @@ export const useInstanceRefresh = (
}; };
}); });
console.log("Mapped server instances:", serverInstances); console.log("Filtered server instances for this user:", serverInstances);
// Identifica instâncias novas que não existem localmente if (serverInstances.length > 0) {
const localInstanceIds = new Set(instances.map(i => i.instanceId)); setInstances(serverInstances);
const newServerInstances = serverInstances.filter(i => !localInstanceIds.has(i.instanceId));
toast({
// Atualiza instâncias existentes com dados do servidor title: "Sucesso",
const updatedExistingInstances = instances.map(localInstance => { description: `${serverInstances.length} instância(s) encontrada(s) para este usuário`,
const serverMatch = serverInstances.find(si => si.instanceId === localInstance.instanceId); });
if (serverMatch) { } else {
return { // Clear instances if none found for this user
...localInstance, setInstances([]);
connectionState: serverMatch.connectionState,
status: serverMatch.status toast({
}; title: "Aviso",
} description: "Nenhuma instância encontrada para este usuário",
return localInstance; });
}); }
// Combina tudo
const allInstances = [...updatedExistingInstances, ...newServerInstances];
console.log("Combined instances after refresh:", allInstances);
setInstances(allInstances);
toast({
title: "Sucesso",
description: `${serverInstances.length} instâncias encontradas no servidor`,
});
} else { } else {
// Handle empty or invalid response
setInstances([]);
toast({ toast({
title: "Aviso", title: "Aviso",
description: "Nenhuma instância encontrada no servidor", description: "Nenhuma instância encontrada no servidor",
@ -90,6 +91,9 @@ export const useInstanceRefresh = (
} }
} catch (error) { } catch (error) {
console.error("Erro ao buscar instâncias:", error); console.error("Erro ao buscar instâncias:", error);
// Ensure we don't leave instances in an undefined state
setInstances([]);
toast({ toast({
title: "Erro", title: "Erro",
description: "Falha ao buscar instâncias do servidor", description: "Falha ao buscar instâncias do servidor",

View File

@ -117,12 +117,7 @@ export const useWhatsAppInstance = (
} }
}; };
// Run once when component mounts or currentUserId changes // Don't automatically load the instance - removed the useEffect that called fetchInstanceByName
useEffect(() => {
if (instanceName && currentUserId) {
fetchInstanceByName();
}
}, [currentUserId]); // Only depend on userId changes
return { return {
instanceName, instanceName,

View File

@ -10,6 +10,8 @@ import { useWhatsAppInstances } from '@/hooks/useWhatsAppInstances';
import { useWhatsAppActions } from '@/hooks/useWhatsAppActions'; import { useWhatsAppActions } from '@/hooks/useWhatsAppActions';
import { useWhatsAppInstance, WHATSAPP_INSTANCE_KEY } from '@/hooks/whatsApp/useWhatsAppInstance'; import { useWhatsAppInstance, WHATSAPP_INSTANCE_KEY } from '@/hooks/whatsApp/useWhatsAppInstance';
import { usePeriodicStatusCheck } from '@/hooks/whatsApp/usePeriodicStatusCheck'; import { usePeriodicStatusCheck } from '@/hooks/whatsApp/usePeriodicStatusCheck';
import { Button } from '@/components/ui/button';
import { RefreshCw } from 'lucide-react';
const WhatsApp = () => { const WhatsApp = () => {
const { const {
@ -40,11 +42,12 @@ const WhatsApp = () => {
isLoading, isLoading,
instanceFound, instanceFound,
setInstanceFound, setInstanceFound,
fetchInstanceByName,
saveInstanceName, saveInstanceName,
clearInstanceName clearInstanceName
} = useWhatsAppInstance(currentUserId, addInstance); } = useWhatsAppInstance(currentUserId, addInstance);
// Set up periodic status checking // Set up periodic status checking only after instances are loaded
usePeriodicStatusCheck(instances.length, checkAllInstancesStatus); usePeriodicStatusCheck(instances.length, checkAllInstancesStatus);
// Handler para quando o usuário cria uma nova instância // Handler para quando o usuário cria uma nova instância
@ -87,29 +90,40 @@ const WhatsApp = () => {
} }
}; };
console.log('Current instances in WhatsApp component:', instances); // Check if we have any instances to show
console.log('Instance found status:', instanceFound); const hasInstances = Array.isArray(instances) && instances.length > 0;
return ( return (
<Layout> <Layout>
<div className="space-y-6"> <div className="space-y-6">
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<h1 className="text-2xl font-bold tracking-tight">Conectar WhatsApp</h1> <h1 className="text-2xl font-bold tracking-tight">Conectar WhatsApp</h1>
{/* Update List Button - Always visible */}
<Button
variant="outline"
onClick={refreshInstances}
disabled={isRefreshing}
className="flex items-center gap-2"
>
<RefreshCw className={`h-4 w-4 ${isRefreshing ? 'animate-spin' : ''}`} />
{isRefreshing ? 'Atualizando...' : 'Atualizar Lista'}
</Button>
</div> </div>
{isLoading ? ( {isLoading ? (
<LoadingState /> <LoadingState />
) : !instanceFound ? ( ) : !instanceFound && !hasInstances ? (
// Show create form if no instance found // Show create form if no instance found and no instances loaded
<CreateInstanceForm <CreateInstanceForm
onInstanceCreated={handleInstanceCreated} onInstanceCreated={handleInstanceCreated}
initialInstanceName={instanceName} initialInstanceName={instanceName}
/> />
) : ( ) : (
// Only show stats and instance list if instance found // Only show stats and instance list if instances are available
<> <>
{/* Stats component */} {/* Stats component */}
<InstanceStats instances={instances} /> {hasInstances && <InstanceStats instances={instances} />}
{/* List of created instances */} {/* List of created instances */}
<InstanceList <InstanceList

View File

@ -69,7 +69,8 @@ export const fetchAllInstances = async (): Promise<any> => {
try { try {
console.log('Fetching all instances'); console.log('Fetching all instances');
const data = await makeRequest('/fetch-instances', 'GET'); // Using the /instance/fetchInstances endpoint as specified in the requirements
const data = await makeRequest('/instance/fetchInstances', 'GET');
console.log('All instances response:', data); console.log('All instances response:', data);
return data; return data;