feat: Implement WhatsApp group creation and instance management
- Implemented POST request to Evolution API for WhatsApp group creation on "Cadastrar Grupo" button click. - Added "Desconectar Instância" button with disconnection logic and Supabase update. - Hid debug information in the "Grupos" menu. - Changed app name to "Finance Home". - Added hover color to sidebar menu items.
This commit is contained in:
parent
a097f05a74
commit
7f202972b2
@ -1,3 +1,4 @@
|
||||
|
||||
import { Link, NavLink, useLocation } from 'react-router-dom';
|
||||
import { useIsMobile } from '@/hooks/use-mobile';
|
||||
import {
|
||||
@ -23,8 +24,8 @@ interface SidebarProps {
|
||||
|
||||
const getNavLinkClass = (isActive: boolean) => {
|
||||
return cn(
|
||||
"group flex items-center rounded-md px-3 py-2 text-sm font-medium hover:bg-secondary hover:text-foreground",
|
||||
isActive ? "bg-secondary text-foreground" : "text-muted-foreground"
|
||||
"group flex items-center rounded-md px-3 py-2 text-sm font-medium transition-all duration-200 hover:bg-gradient-to-r hover:from-blue-50 hover:to-indigo-50 hover:text-blue-700 hover:scale-105 hover:shadow-sm",
|
||||
isActive ? "bg-gradient-to-r from-blue-100 to-indigo-100 text-blue-700 shadow-sm" : "text-muted-foreground"
|
||||
);
|
||||
};
|
||||
|
||||
@ -38,8 +39,8 @@ export default function Sidebar({ isOpen, onClose }: SidebarProps) {
|
||||
isMobile ? 'fixed left-0 top-0 z-50 w-full transition-all duration-300' : 'relative'
|
||||
)}>
|
||||
<div className="flex items-center justify-between px-4 py-2">
|
||||
<Link to="/" className="flex items-center space-x-2 font-semibold">
|
||||
<span>FinDash</span>
|
||||
<Link to="/" className="flex items-center space-x-2 font-semibold text-blue-700 hover:text-blue-800 transition-colors">
|
||||
<span className="text-lg">Finance Home</span>
|
||||
</Link>
|
||||
{isMobile && (
|
||||
<Button variant="ghost" size="icon" onClick={onClose}>
|
||||
@ -56,7 +57,7 @@ export default function Sidebar({ isOpen, onClose }: SidebarProps) {
|
||||
className={({ isActive }) => getNavLinkClass(isActive)}
|
||||
onClick={isMobile ? onClose : undefined}
|
||||
>
|
||||
<Home className="mr-2 h-4 w-4" />
|
||||
<Home className="mr-2 h-4 w-4 transition-transform group-hover:scale-110" />
|
||||
<span>Dashboard</span>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
@ -64,7 +65,7 @@ export default function Sidebar({ isOpen, onClose }: SidebarProps) {
|
||||
className={({ isActive }) => getNavLinkClass(isActive)}
|
||||
onClick={isMobile ? onClose : undefined}
|
||||
>
|
||||
<Receipt className="mr-2 h-4 w-4" />
|
||||
<Receipt className="mr-2 h-4 w-4 transition-transform group-hover:scale-110" />
|
||||
<span>Transações</span>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
@ -72,7 +73,7 @@ export default function Sidebar({ isOpen, onClose }: SidebarProps) {
|
||||
className={({ isActive }) => getNavLinkClass(isActive)}
|
||||
onClick={isMobile ? onClose : undefined}
|
||||
>
|
||||
<CreditCard className="mr-2 h-4 w-4" />
|
||||
<CreditCard className="mr-2 h-4 w-4 transition-transform group-hover:scale-110" />
|
||||
<span>Cartões de Crédito</span>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
@ -80,7 +81,7 @@ export default function Sidebar({ isOpen, onClose }: SidebarProps) {
|
||||
className={({ isActive }) => getNavLinkClass(isActive)}
|
||||
onClick={isMobile ? onClose : undefined}
|
||||
>
|
||||
<ListFilter className="mr-2 h-4 w-4" />
|
||||
<ListFilter className="mr-2 h-4 w-4 transition-transform group-hover:scale-110" />
|
||||
<span>Categorias</span>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
@ -88,7 +89,7 @@ export default function Sidebar({ isOpen, onClose }: SidebarProps) {
|
||||
className={({ isActive }) => getNavLinkClass(isActive)}
|
||||
onClick={isMobile ? onClose : undefined}
|
||||
>
|
||||
<Target className="mr-2 h-4 w-4" />
|
||||
<Target className="mr-2 h-4 w-4 transition-transform group-hover:scale-110" />
|
||||
<span>Metas</span>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
@ -96,14 +97,14 @@ export default function Sidebar({ isOpen, onClose }: SidebarProps) {
|
||||
className={({ isActive }) => getNavLinkClass(isActive)}
|
||||
onClick={isMobile ? onClose : undefined}
|
||||
>
|
||||
<Calendar className="mr-2 h-4 w-4" />
|
||||
<Calendar className="mr-2 h-4 w-4 transition-transform group-hover:scale-110" />
|
||||
<span>Calendário</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="px-3 py-2">
|
||||
<h2 className="mb-2 px-3 text-sm font-semibold tracking-tight">
|
||||
<h2 className="mb-2 px-3 text-sm font-semibold tracking-tight text-gray-600">
|
||||
WhatsApp
|
||||
</h2>
|
||||
<div className="space-y-1">
|
||||
@ -112,7 +113,7 @@ export default function Sidebar({ isOpen, onClose }: SidebarProps) {
|
||||
className={({ isActive }) => getNavLinkClass(isActive)}
|
||||
onClick={isMobile ? onClose : undefined}
|
||||
>
|
||||
<MessageSquareText className="mr-2 h-4 w-4" />
|
||||
<MessageSquareText className="mr-2 h-4 w-4 transition-transform group-hover:scale-110" />
|
||||
<span>Conectar WhatsApp</span>
|
||||
</NavLink>
|
||||
<NavLink
|
||||
@ -120,13 +121,13 @@ export default function Sidebar({ isOpen, onClose }: SidebarProps) {
|
||||
className={({ isActive }) => getNavLinkClass(isActive)}
|
||||
onClick={isMobile ? onClose : undefined}
|
||||
>
|
||||
<Users className="mr-2 h-4 w-4" />
|
||||
<Users className="mr-2 h-4 w-4 transition-transform group-hover:scale-110" />
|
||||
<span>Grupos</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
</div>
|
||||
<div className="px-3 py-2">
|
||||
<h2 className="mb-2 px-3 text-sm font-semibold tracking-tight">
|
||||
<h2 className="mb-2 px-3 text-sm font-semibold tracking-tight text-gray-600">
|
||||
Configurações
|
||||
</h2>
|
||||
<div className="space-y-1">
|
||||
@ -135,7 +136,7 @@ export default function Sidebar({ isOpen, onClose }: SidebarProps) {
|
||||
className={({ isActive }) => getNavLinkClass(isActive)}
|
||||
onClick={isMobile ? onClose : undefined}
|
||||
>
|
||||
<Settings className="mr-2 h-4 w-4" />
|
||||
<Settings className="mr-2 h-4 w-4 transition-transform group-hover:scale-110" />
|
||||
<span>Configurações</span>
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
@ -7,7 +7,8 @@ import {
|
||||
PowerOff,
|
||||
CircleDot,
|
||||
CircleOff,
|
||||
X
|
||||
X,
|
||||
Unplug
|
||||
} from "lucide-react";
|
||||
import { WhatsAppInstance } from "@/types/whatsAppTypes";
|
||||
|
||||
@ -17,6 +18,7 @@ interface InstanceActionsProps {
|
||||
onViewQrCode: (instance: WhatsAppInstance) => void;
|
||||
onRestart: () => void;
|
||||
onLogout: () => void;
|
||||
onDisconnect?: () => void;
|
||||
onDelete: () => void;
|
||||
onSetOnline: () => void;
|
||||
onSetOffline: () => void;
|
||||
@ -28,10 +30,13 @@ const InstanceActions = ({
|
||||
onViewQrCode,
|
||||
onRestart,
|
||||
onLogout,
|
||||
onDisconnect,
|
||||
onDelete,
|
||||
onSetOnline,
|
||||
onSetOffline,
|
||||
}: InstanceActionsProps) => {
|
||||
const isConnected = instance.connectionState === 'open' || instance.status === 'connected';
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex justify-between w-full">
|
||||
@ -55,6 +60,7 @@ const InstanceActions = ({
|
||||
Excluir
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-2 w-full">
|
||||
<Button
|
||||
variant="outline"
|
||||
@ -75,6 +81,21 @@ const InstanceActions = ({
|
||||
Desconectar
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Botão de desconectar instância - apenas quando conectada */}
|
||||
{isConnected && onDisconnect && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={onDisconnect}
|
||||
disabled={loading !== null}
|
||||
className="w-full bg-orange-50 hover:bg-orange-100 text-orange-700 border-orange-200"
|
||||
>
|
||||
<Unplug className="h-4 w-4 mr-1" />
|
||||
Desconectar Instância
|
||||
</Button>
|
||||
)}
|
||||
|
||||
<div className="grid grid-cols-2 gap-2 w-full">
|
||||
<Button
|
||||
variant="outline"
|
||||
|
||||
@ -13,6 +13,7 @@ interface InstanceCardProps {
|
||||
onDelete: (instanceId: string) => void;
|
||||
onRestart: (instance: WhatsAppInstance) => Promise<void>;
|
||||
onLogout: (instance: WhatsAppInstance) => Promise<void>;
|
||||
onDisconnect?: (instance: WhatsAppInstance) => Promise<void>;
|
||||
onSetPresence: (instance: WhatsAppInstance, presence: 'online' | 'offline') => Promise<void>;
|
||||
}
|
||||
|
||||
@ -22,6 +23,7 @@ const InstanceCard = ({
|
||||
onDelete,
|
||||
onRestart,
|
||||
onLogout,
|
||||
onDisconnect,
|
||||
onSetPresence
|
||||
}: InstanceCardProps) => {
|
||||
const [loading, setLoading] = useState<string | null>(null);
|
||||
@ -88,6 +90,22 @@ const InstanceCard = ({
|
||||
);
|
||||
};
|
||||
|
||||
// Handler para desconectar instância permanentemente
|
||||
const handleDisconnect = () => {
|
||||
if (!onDisconnect) return;
|
||||
|
||||
handleConfirmAction(
|
||||
"Desconectar Instância",
|
||||
`Deseja realmente desconectar a instância "${instance.instanceName}" permanentemente? Esta ação atualizará seu status no banco de dados para "desconectado".`,
|
||||
async () => {
|
||||
if (onDisconnect) {
|
||||
await onDisconnect(instance);
|
||||
}
|
||||
},
|
||||
"Desconectar"
|
||||
);
|
||||
};
|
||||
|
||||
// Handler para apagar instância
|
||||
const handleDelete = () => {
|
||||
handleConfirmAction(
|
||||
@ -169,6 +187,7 @@ const InstanceCard = ({
|
||||
onViewQrCode={onViewQrCode}
|
||||
onRestart={handleRestart}
|
||||
onLogout={handleLogout}
|
||||
onDisconnect={onDisconnect ? handleDisconnect : undefined}
|
||||
onDelete={handleDelete}
|
||||
onSetOnline={handleSetOnline}
|
||||
onSetOffline={handleSetOffline}
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
|
||||
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';
|
||||
import InstanceCard from './InstanceCard';
|
||||
import { Card, CardContent } from '@/components/ui/card';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
|
||||
interface InstanceListProps {
|
||||
instances: WhatsAppInstance[];
|
||||
@ -11,41 +10,42 @@ interface InstanceListProps {
|
||||
onDelete: (instanceId: string) => void;
|
||||
onRestart: (instance: WhatsAppInstance) => Promise<void>;
|
||||
onLogout: (instance: WhatsAppInstance) => Promise<void>;
|
||||
onDisconnect?: (instance: WhatsAppInstance) => Promise<void>;
|
||||
onSetPresence: (instance: WhatsAppInstance, presence: 'online' | 'offline') => Promise<void>;
|
||||
onRefreshInstances: () => Promise<void>;
|
||||
onRefreshInstances: () => void;
|
||||
isRefreshing: boolean;
|
||||
}
|
||||
|
||||
const InstanceList = ({
|
||||
instances,
|
||||
onViewQrCode,
|
||||
instances,
|
||||
onViewQrCode,
|
||||
onDelete,
|
||||
onRestart,
|
||||
onLogout,
|
||||
onDisconnect,
|
||||
onSetPresence,
|
||||
onRefreshInstances,
|
||||
isRefreshing
|
||||
}: InstanceListProps) => {
|
||||
// Safely check if instances is an array and has elements
|
||||
const hasInstances = Array.isArray(instances) && instances.length > 0;
|
||||
|
||||
if (!hasInstances) {
|
||||
|
||||
if (isRefreshing && instances.length === 0) {
|
||||
return (
|
||||
<Card>
|
||||
<CardContent className="py-6">
|
||||
<CardContent className="flex items-center justify-center py-8">
|
||||
<Loader2 className="h-6 w-6 animate-spin mr-2" />
|
||||
<span>Carregando instâncias...</span>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
if (instances.length === 0) {
|
||||
return (
|
||||
<Card>
|
||||
<CardContent className="flex items-center justify-center py-8">
|
||||
<div className="text-center text-muted-foreground">
|
||||
<p>Nenhuma instância criada ainda.</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>
|
||||
<p className="text-lg mb-2">Nenhuma instância encontrada</p>
|
||||
<p className="text-sm">Crie uma nova instância para começar</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@ -54,27 +54,23 @@ const InstanceList = ({
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<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 className="flex items-center justify-between">
|
||||
<h2 className="text-xl font-semibold">Suas Instâncias do WhatsApp</h2>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{instances.length} instância{instances.length !== 1 ? 's' : ''} encontrada{instances.length !== 1 ? 's' : ''}
|
||||
</span>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
||||
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||
{instances.map((instance) => (
|
||||
<InstanceCard
|
||||
key={instance.instanceId}
|
||||
instance={instance}
|
||||
onViewQrCode={onViewQrCode}
|
||||
<InstanceCard
|
||||
key={instance.instanceId}
|
||||
instance={instance}
|
||||
onViewQrCode={onViewQrCode}
|
||||
onDelete={onDelete}
|
||||
onRestart={onRestart}
|
||||
onLogout={onLogout}
|
||||
onDisconnect={onDisconnect}
|
||||
onSetPresence={onSetPresence}
|
||||
/>
|
||||
))}
|
||||
|
||||
@ -32,66 +32,41 @@ const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
|
||||
useEffect(() => {
|
||||
const checkUserInstance = async () => {
|
||||
if (!userEmail) {
|
||||
console.log('🔍 Email do usuário não fornecido');
|
||||
console.log('Email do usuário não fornecido');
|
||||
setCheckingInstance(false);
|
||||
return;
|
||||
}
|
||||
|
||||
setCheckingInstance(true);
|
||||
try {
|
||||
console.log('🔍 === VERIFICAÇÃO DE INSTÂNCIA INICIADA ===');
|
||||
console.log('🔍 Email fornecido:', userEmail);
|
||||
console.log('🔍 Tipo do email:', typeof userEmail);
|
||||
console.log('🔍 Email length:', userEmail.length);
|
||||
|
||||
// TESTE: Verificar se o email está sendo usado corretamente
|
||||
const emailTrimmed = userEmail.trim().toLowerCase();
|
||||
console.log('📧 Email após trim/lower:', emailTrimmed);
|
||||
console.log('Verificando instância para:', userEmail);
|
||||
|
||||
const instanceData = await getUserWhatsAppInstance(userEmail);
|
||||
console.log('📊 === DADOS RETORNADOS DA FUNÇÃO ===');
|
||||
console.log('📊 instanceData completo:', JSON.stringify(instanceData, null, 2));
|
||||
console.log('Dados da instância:', instanceData);
|
||||
|
||||
if (instanceData) {
|
||||
console.log('🔍 === ANÁLISE DETALHADA DOS DADOS ===');
|
||||
console.log('✅ instanceData existe:', !!instanceData);
|
||||
console.log('📝 instancia_zap valor:', instanceData.instancia_zap);
|
||||
console.log('📝 instancia_zap tipo:', typeof instanceData.instancia_zap);
|
||||
console.log('✅ instancia_zap não é null:', instanceData.instancia_zap !== null);
|
||||
console.log('✅ instancia_zap não é vazio após trim:', instanceData.instancia_zap?.trim() !== '');
|
||||
console.log('📝 status_instancia valor:', instanceData.status_instancia);
|
||||
console.log('📝 status_instancia tipo:', typeof instanceData.status_instancia);
|
||||
console.log('✅ status_instancia é "conectado":', instanceData.status_instancia === 'conectado');
|
||||
} else {
|
||||
console.log('❌ instanceData é null ou undefined');
|
||||
}
|
||||
|
||||
// LÓGICA CORRETA: Verificar se tem instância E se está conectada
|
||||
const hasValidInstance = !!(
|
||||
instanceData &&
|
||||
instanceData.instancia_zap &&
|
||||
instanceData.instancia_zap.trim() !== '' &&
|
||||
instanceData.status_instancia === 'conectado'
|
||||
);
|
||||
|
||||
console.log('🎯 === RESULTADO FINAL DA VALIDAÇÃO ===');
|
||||
console.log('🎯 hasValidInstance:', hasValidInstance);
|
||||
|
||||
if (hasValidInstance) {
|
||||
setHasWhatsAppInstance(true);
|
||||
setUserInstance(instanceData);
|
||||
console.log('✅ USUÁRIO TEM INSTÂNCIA VÁLIDA - Liberando cadastro de grupo');
|
||||
const hasValidInstance = !!(
|
||||
instanceData &&
|
||||
instanceData.instancia_zap &&
|
||||
instanceData.instancia_zap.trim() !== '' &&
|
||||
instanceData.status_instancia === 'conectado'
|
||||
);
|
||||
|
||||
console.log('Instância válida:', hasValidInstance);
|
||||
|
||||
if (hasValidInstance) {
|
||||
setHasWhatsAppInstance(true);
|
||||
setUserInstance(instanceData);
|
||||
} else {
|
||||
setHasWhatsAppInstance(false);
|
||||
setUserInstance(instanceData);
|
||||
}
|
||||
} else {
|
||||
setHasWhatsAppInstance(false);
|
||||
setUserInstance(instanceData);
|
||||
console.log('❌ USUÁRIO NÃO TEM INSTÂNCIA VÁLIDA:', {
|
||||
temInstanceData: !!instanceData,
|
||||
instancia_zap: instanceData?.instancia_zap || 'NULL',
|
||||
status_instancia: instanceData?.status_instancia || 'NULL'
|
||||
});
|
||||
setUserInstance(null);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('💥 ERRO CRÍTICO ao verificar instância do usuário:', error);
|
||||
console.error('Erro ao verificar instância do usuário:', error);
|
||||
setHasWhatsAppInstance(false);
|
||||
setUserInstance(null);
|
||||
} finally {
|
||||
@ -142,13 +117,9 @@ const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
|
||||
throw new Error('Não foi possível cadastrar o grupo no banco de dados');
|
||||
}
|
||||
|
||||
// 2. Criar grupo no WhatsApp via API
|
||||
// 2. Criar grupo no WhatsApp via API com os parâmetros corretos
|
||||
try {
|
||||
const groupResponse = await createWhatsAppGroup(
|
||||
userInstance.instancia_zap,
|
||||
userEmail,
|
||||
userInstance.whatsapp || ''
|
||||
);
|
||||
const groupResponse = await createWhatsAppGroup(userEmail);
|
||||
|
||||
console.log('Resposta da criação do grupo:', groupResponse);
|
||||
|
||||
@ -229,53 +200,6 @@ const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
|
||||
Acesse o menu "Conectar WhatsApp" e realize a conexão primeiro.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
{/* Informações de debug SUPER DETALHADAS */}
|
||||
<div className="mt-4 p-4 bg-gray-100 rounded text-sm">
|
||||
<p><strong>🔧 DEBUG COMPLETO - CONEXÃO COM BANCO:</strong></p>
|
||||
<div className="mt-2 space-y-1">
|
||||
<p><strong>Email original:</strong> {userEmail || 'Não definido'}</p>
|
||||
<p><strong>Email processado:</strong> {userEmail?.trim().toLowerCase() || 'Não processado'}</p>
|
||||
|
||||
<div className="mt-3 p-2 bg-blue-100 rounded">
|
||||
<p><strong>📊 DADOS DO BANCO DE DADOS:</strong></p>
|
||||
{userInstance ? (
|
||||
<>
|
||||
<p><strong>instancia_zap:</strong>
|
||||
<span className={userInstance.instancia_zap ? 'text-green-600' : 'text-red-600'}>
|
||||
"{userInstance.instancia_zap || 'NULL'}" (tipo: {typeof userInstance.instancia_zap})
|
||||
</span>
|
||||
</p>
|
||||
<p><strong>status_instancia:</strong>
|
||||
<span className={userInstance.status_instancia === 'conectado' ? 'text-green-600' : 'text-red-600'}>
|
||||
"{userInstance.status_instancia || 'NULL'}" (tipo: {typeof userInstance.status_instancia})
|
||||
</span>
|
||||
</p>
|
||||
<p><strong>whatsapp:</strong> "{userInstance.whatsapp || 'NULL'}"</p>
|
||||
</>
|
||||
) : (
|
||||
<p className="text-red-600">❌ Nenhum dado retornado do banco de dados!</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="mt-3 p-2 bg-yellow-100 rounded">
|
||||
<p><strong>🔍 VALIDAÇÕES STEP-BY-STEP:</strong></p>
|
||||
<p>1. Dados existem? {userInstance ? '✅ SIM' : '❌ NÃO'}</p>
|
||||
<p>2. instancia_zap preenchida? {(userInstance?.instancia_zap && userInstance.instancia_zap.trim() !== '') ? '✅ SIM' : '❌ NÃO'}</p>
|
||||
<p>3. Status é "conectado"? {userInstance?.status_instancia === 'conectado' ? '✅ SIM' : '❌ NÃO'}</p>
|
||||
|
||||
{userInstance?.instancia_zap && userInstance?.status_instancia !== 'conectado' && (
|
||||
<p className="text-red-600 font-medium mt-2">
|
||||
⚠️ Instância encontrada mas status incorreto: "{userInstance.status_instancia}"
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-3 text-xs text-gray-600">
|
||||
<p>💡 Abra o Console do navegador (F12) para ver logs detalhados da consulta ao banco de dados</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
@ -336,7 +260,7 @@ const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
|
||||
<ul className="list-disc list-inside space-y-1 text-sm text-muted-foreground">
|
||||
<li>O grupo será criado automaticamente no seu WhatsApp</li>
|
||||
<li>Você será adicionado como participante do grupo</li>
|
||||
<li>O grupo terá o nome: FinDash - {userEmail.split('@')[0]}</li>
|
||||
<li>O grupo terá o nome: finance{userEmail.split('@')[0]}</li>
|
||||
</ul>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
@ -7,6 +7,7 @@ import {
|
||||
logoutInstance,
|
||||
deleteInstance,
|
||||
setInstancePresence,
|
||||
disconnectInstance,
|
||||
fetchQrCode
|
||||
} from '@/services/whatsAppService';
|
||||
|
||||
@ -80,6 +81,43 @@ export const useWhatsAppActions = (
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Handler for quando uma instância é desconectada permanentemente
|
||||
const handleDisconnectInstance = async (instance: WhatsAppInstance) => {
|
||||
try {
|
||||
console.log(`Attempting to disconnect instance ${instance.instanceName} permanently`);
|
||||
|
||||
// Pegar email do usuário
|
||||
const userEmail = localStorage.getItem('userEmail');
|
||||
if (!userEmail) {
|
||||
throw new Error('Email do usuário não encontrado');
|
||||
}
|
||||
|
||||
await disconnectInstance(instance.instanceName, userEmail);
|
||||
|
||||
// Atualiza o estado da instância para "closed"
|
||||
const updatedInstance = {
|
||||
...instance,
|
||||
connectionState: 'closed' as const,
|
||||
status: 'disconnected'
|
||||
};
|
||||
console.log(`Instance ${instance.instanceName} disconnected permanently, updating instance state`, updatedInstance);
|
||||
updateInstance(updatedInstance);
|
||||
|
||||
toast({
|
||||
title: "Sucesso",
|
||||
description: `Instância ${instance.instanceName} desconectada permanentemente`
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error disconnecting 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') => {
|
||||
@ -179,6 +217,7 @@ export const useWhatsAppActions = (
|
||||
setQrDialogOpen,
|
||||
handleRestartInstance,
|
||||
handleLogoutInstance,
|
||||
handleDisconnectInstance,
|
||||
handleSetPresence,
|
||||
handleDeleteInstance,
|
||||
handleViewQrCode
|
||||
|
||||
@ -32,6 +32,7 @@ const WhatsApp = () => {
|
||||
setQrDialogOpen,
|
||||
handleRestartInstance,
|
||||
handleLogoutInstance,
|
||||
handleDisconnectInstance,
|
||||
handleSetPresence,
|
||||
handleDeleteInstance,
|
||||
handleViewQrCode
|
||||
@ -149,6 +150,7 @@ const WhatsApp = () => {
|
||||
onDelete={handleDeleteInstanceWrapper}
|
||||
onRestart={handleRestartInstance}
|
||||
onLogout={handleLogoutInstance}
|
||||
onDisconnect={handleDisconnectInstance}
|
||||
onSetPresence={handleSetPresence}
|
||||
onRefreshInstances={refreshInstances}
|
||||
isRefreshing={isRefreshing}
|
||||
|
||||
@ -3,3 +3,6 @@
|
||||
export * from './instanceManagement';
|
||||
export * from './instanceActions';
|
||||
export * from './localStorage';
|
||||
|
||||
// Import and re-export the disconnect function specifically
|
||||
export { disconnectInstance } from './instanceActions';
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
|
||||
import { makeRequest } from './apiHelpers';
|
||||
import { supabase } from '@/integrations/supabase/client';
|
||||
|
||||
/**
|
||||
* Restarts a WhatsApp instance
|
||||
@ -35,6 +36,38 @@ export const logoutInstance = async (instanceName: string): Promise<any> => {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Disconnects a WhatsApp instance and updates database
|
||||
*/
|
||||
export const disconnectInstance = async (instanceName: string, userEmail: string): Promise<any> => {
|
||||
try {
|
||||
console.log(`Disconnecting instance: ${instanceName}`);
|
||||
|
||||
// Primeiro desconecta via API
|
||||
const data = await makeRequest(`/instance/logout/${encodeURIComponent(instanceName)}`, 'DELETE');
|
||||
|
||||
// Depois atualiza o banco de dados
|
||||
const { error } = await supabase
|
||||
.from('usuarios')
|
||||
.update({
|
||||
status_instancia: 'desconectado',
|
||||
instancia_zap: null
|
||||
})
|
||||
.eq('email', userEmail.trim().toLowerCase());
|
||||
|
||||
if (error) {
|
||||
console.error('Erro ao atualizar status no banco:', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
console.log(`Instance ${instanceName} disconnected and database updated`);
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error(`Error disconnecting instance ${instanceName}:`, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Deletes a WhatsApp instance
|
||||
*/
|
||||
|
||||
@ -9,24 +9,22 @@ interface CreateGroupResponse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cria um grupo WhatsApp via API da Evolution
|
||||
* Cria um grupo WhatsApp via API da Evolution usando o padrão correto
|
||||
*/
|
||||
export async function createWhatsAppGroup(
|
||||
instanceName: string,
|
||||
userEmail: string,
|
||||
userPhone: string
|
||||
userEmail: string
|
||||
): Promise<CreateGroupResponse> {
|
||||
try {
|
||||
// Extrair a parte antes do @ do email
|
||||
const emailPrefix = userEmail.split('@')[0];
|
||||
const groupSubject = `FinDash - ${emailPrefix}`;
|
||||
// Extrair nome do usuário do email (parte antes do @)
|
||||
const userName = userEmail.split('@')[0];
|
||||
const groupSubject = `finance${userName}`;
|
||||
|
||||
const url = `https://evolutionapi2.innova1001.com.br/group/create/${instanceName}`;
|
||||
const url = `https://evolutionapi2.innova1001.com.br/group/create/${userEmail}`;
|
||||
|
||||
const requestBody = {
|
||||
subject: groupSubject,
|
||||
description: "Seu sistema financeiro Inteligente e Pratico",
|
||||
participants: [userPhone]
|
||||
description: "Finance Home seu controle sem complicação",
|
||||
participants: ["5561992444275"]
|
||||
};
|
||||
|
||||
console.log('Criando grupo WhatsApp:', { url, requestBody });
|
||||
@ -35,6 +33,7 @@ export async function createWhatsAppGroup(
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'beeb77fbd7f48f91db2cd539a573c130'
|
||||
},
|
||||
body: JSON.stringify(requestBody)
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user