Refactor: Break down WhatsApp.tsx into smaller components

Refactors WhatsApp.tsx into smaller, more manageable components and hooks to improve readability and maintainability. This reduces the overall complexity of the file.
This commit is contained in:
gpt-engineer-app[bot] 2025-05-20 17:01:02 +00:00
parent 62e2acbf4e
commit d9a804c36a
4 changed files with 191 additions and 135 deletions

View File

@ -0,0 +1,17 @@
import React from 'react';
interface LoadingStateProps {
message?: string;
}
const LoadingState = ({ message = "Buscando instância..." }: LoadingStateProps) => {
return (
<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>
<p className="ml-3">{message}</p>
</div>
);
};
export default LoadingState;

View File

@ -0,0 +1,37 @@
import { useEffect } from 'react';
export const usePeriodicStatusCheck = (
instancesCount: number,
checkAllInstancesStatus: () => Promise<void>
) => {
// Set up periodic status checks
useEffect(() => {
console.log("Setting up periodic status checks, current instances:", instancesCount);
// Check status initially after a short delay to prevent immediate execution
let initialCheck: NodeJS.Timeout;
if (instancesCount > 0) {
initialCheck = setTimeout(() => {
console.log("Running initial status check");
checkAllInstancesStatus();
}, 1000);
}
// Set up interval for periodic checks (every 30 seconds)
const interval = setInterval(() => {
if (instancesCount > 0) {
console.log("Running periodic status check");
checkAllInstancesStatus();
}
}, 30000); // 30 seconds
// Clean up interval and timeout when component unmounts
return () => {
clearInterval(interval);
if (initialCheck) {
clearTimeout(initialCheck);
}
};
}, [instancesCount, checkAllInstancesStatus]);
};

View File

@ -0,0 +1,115 @@
import { useState, useEffect } from 'react';
import { useToast } from '@/hooks/use-toast';
import { WhatsAppInstance } from '@/types/whatsAppTypes';
import { fetchSpecificInstance } from '@/services/whatsApp/instanceManagement';
// Key used for storing instance name in localStorage
export const WHATSAPP_INSTANCE_KEY = 'whatsapp_instance_name';
export const useWhatsAppInstance = (
currentUserId: string,
addInstance: (instance: WhatsAppInstance) => void
) => {
const { toast } = useToast();
// Get instance name from localStorage
const [instanceName, setInstanceName] = useState(() => {
if (currentUserId) {
return localStorage.getItem(`${WHATSAPP_INSTANCE_KEY}_${currentUserId}`) || '';
}
return '';
});
const [isLoading, setIsLoading] = useState(false);
const [instanceFound, setInstanceFound] = useState(false);
// 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);
}
};
// Save instance name to localStorage
const saveInstanceName = (name: string) => {
if (currentUserId) {
localStorage.setItem(`${WHATSAPP_INSTANCE_KEY}_${currentUserId}`, name);
setInstanceName(name);
}
};
// Clear instance name from localStorage
const clearInstanceName = () => {
if (currentUserId) {
localStorage.removeItem(`${WHATSAPP_INSTANCE_KEY}_${currentUserId}`);
setInstanceName('');
setInstanceFound(false);
}
};
// Run once when component mounts
useEffect(() => {
if (currentUserId) {
fetchInstanceByName();
} else {
toast({
title: "Login necessário",
description: "Você precisa estar logado para ver suas instâncias do WhatsApp.",
variant: "destructive"
});
}
}, [currentUserId]); // Only depend on userId, not instanceName
return {
instanceName,
isLoading,
instanceFound,
setInstanceFound,
fetchInstanceByName,
saveInstanceName,
clearInstanceName
};
};

View File

@ -1,20 +1,17 @@
import { useEffect, useState } from 'react';
import Layout from '@/components/layout/Layout';
import { WhatsAppInstance } from '@/types/whatsAppTypes';
import Layout from '@/components/layout/Layout';
import CreateInstanceForm from '@/components/whatsapp/CreateInstanceForm';
import InstanceList from '@/components/whatsapp/InstanceList';
import InstanceStats from '@/components/whatsapp/InstanceStats';
import QrCodeDialog from '@/components/whatsapp/QrCodeDialog';
import LoadingState from '@/components/whatsapp/LoadingState';
import { useWhatsAppInstances } from '@/hooks/useWhatsAppInstances';
import { useWhatsAppActions } from '@/hooks/useWhatsAppActions';
import { useToast } from '@/hooks/use-toast';
import { fetchSpecificInstance } from '@/services/whatsApp/instanceManagement';
const WHATSAPP_INSTANCE_KEY = 'whatsapp_instance_name';
import { useWhatsAppInstance, WHATSAPP_INSTANCE_KEY } from '@/hooks/whatsApp/useWhatsAppInstance';
import { usePeriodicStatusCheck } from '@/hooks/whatsApp/usePeriodicStatusCheck';
const WhatsApp = () => {
const { toast } = useToast();
const {
instances,
isRefreshing,
@ -22,7 +19,8 @@ const WhatsApp = () => {
removeInstance,
updateInstance,
refreshInstances,
checkAllInstancesStatus
checkAllInstancesStatus,
currentUserId
} = useWhatsAppInstances();
const {
@ -36,111 +34,18 @@ const WhatsApp = () => {
handleViewQrCode
} = useWhatsAppActions(updateInstance, removeInstance, checkAllInstancesStatus);
// Obter o nome da instância salvo no localStorage
const [instanceName, setInstanceName] = useState(() => {
const userId = localStorage.getItem('userId');
if (userId) {
return localStorage.getItem(`${WHATSAPP_INSTANCE_KEY}_${userId}`) || '';
}
return '';
});
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
useEffect(() => {
console.log("Setting up periodic status checks, current instances:", instances.length);
// Check status initially after a short delay to prevent immediate execution
let initialCheck: NodeJS.Timeout;
if (instances.length > 0) {
initialCheck = setTimeout(() => {
console.log("Running initial status check");
checkAllInstancesStatus();
}, 1000);
}
// Set up interval for periodic checks (every 30 seconds)
const interval = setInterval(() => {
if (instances.length > 0) {
console.log("Running periodic status check");
checkAllInstancesStatus();
}
}, 30000); // 30 seconds
// Clean up interval and timeout when component unmounts
return () => {
clearInterval(interval);
if (initialCheck) {
clearTimeout(initialCheck);
}
};
}, [instances.length, checkAllInstancesStatus]);
// Fetch the specific instance when the component mounts (não a cada digitação)
useEffect(() => {
if (currentUserId) {
fetchInstanceByName();
} else {
toast({
title: "Login necessário",
description: "Você precisa estar logado para ver suas instâncias do WhatsApp.",
variant: "destructive"
});
}
}, [currentUserId]);
// Custom hook for instance fetching and management
const {
instanceName,
isLoading,
instanceFound,
setInstanceFound,
saveInstanceName,
clearInstanceName
} = useWhatsAppInstance(currentUserId, addInstance);
// Set up periodic status checking
usePeriodicStatusCheck(instances.length, checkAllInstancesStatus);
// Handler para quando o usuário cria uma nova instância
const handleInstanceCreated = (newInstance: WhatsAppInstance) => {
@ -149,10 +54,7 @@ const WhatsApp = () => {
setInstanceFound(true);
// Salvar o nome da instância no localStorage para uso futuro
if (currentUserId) {
localStorage.setItem(`${WHATSAPP_INSTANCE_KEY}_${currentUserId}`, newInstance.instanceName);
setInstanceName(newInstance.instanceName);
}
saveInstanceName(newInstance.instanceName);
// If there's a QR code in the response, show it
if (newInstance.qrcode) {
@ -165,11 +67,6 @@ const WhatsApp = () => {
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",
});
}
}, 2000);
};
@ -182,18 +79,11 @@ const WhatsApp = () => {
handleDeleteInstance(instanceId, instanceToDelete.instanceName);
// Se a instância excluída for a atual, limpar o nome salvo
if (instanceToDelete.instanceName === instanceName && currentUserId) {
localStorage.removeItem(`${WHATSAPP_INSTANCE_KEY}_${currentUserId}`);
setInstanceName('');
setInstanceFound(false);
if (instanceToDelete.instanceName === instanceName) {
clearInstanceName();
}
} 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",
});
}
};
@ -208,10 +98,7 @@ const WhatsApp = () => {
</div>
{isLoading ? (
<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>
<p className="ml-3">Buscando instância...</p>
</div>
<LoadingState />
) : !instanceFound ? (
// Show create form if no instance found
<CreateInstanceForm