Refactor: Split GruposWhatsApp.tsx into smaller components

Split the large GruposWhatsApp.tsx file into smaller, more manageable components to improve readability and maintainability. This refactoring aims to improve code organization without altering existing functionality.
This commit is contained in:
gpt-engineer-app[bot] 2025-05-20 20:15:21 +00:00
parent c5f3a3d161
commit 6d6734c17d
4 changed files with 295 additions and 233 deletions

View File

@ -0,0 +1,171 @@
import { useState } from 'react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Loader2, Plus } from 'lucide-react';
import { cadastrarGrupoWhatsApp } from '@/services/gruposWhatsAppService';
import { useToast } from '@/hooks/use-toast';
interface CreateGroupFormProps {
userEmail: string;
onSuccess: () => void;
}
const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
const { toast } = useToast();
const [cadastrando, setCadastrando] = useState<boolean>(false);
const [nomeGrupo, setNomeGrupo] = useState<string>('');
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const [debugInfo, setDebugInfo] = useState<string | null>(null);
// Cadastrar novo grupo ou atualizar workflow se necessário
const handleCadastrarGrupo = async () => {
setErrorMessage(null);
setDebugInfo(null);
if (!userEmail) {
toast({
title: 'Erro',
description: 'Você precisa estar logado para cadastrar um grupo',
variant: 'destructive',
});
return;
}
if (!nomeGrupo.trim()) {
toast({
title: 'Atenção',
description: 'Digite um nome para o grupo',
variant: 'destructive',
});
return;
}
setCadastrando(true);
try {
console.log("Iniciando processo de cadastro de grupo...");
const grupo = await cadastrarGrupoWhatsApp(nomeGrupo.trim());
if (grupo) {
let successMessage = 'Grupo registrado com sucesso';
let variant: 'default' | 'destructive' = 'default';
if (grupo.workflow_id) {
successMessage = 'Grupo cadastrado e workflow criado com sucesso!';
} else {
successMessage = 'Grupo cadastrado, mas falha ao criar workflow de automação.';
setDebugInfo('O grupo foi criado no Supabase, mas houve um problema ao criar o workflow no n8n. Verifique os logs do console para mais detalhes.');
variant = 'destructive';
}
toast({
title: grupo.workflow_id ? 'Sucesso' : 'Atenção',
description: successMessage,
variant: variant,
});
// Resetar o campo de nome
setNomeGrupo('');
// Atualizar a lista de grupos
onSuccess();
} else {
setErrorMessage('Não foi possível registrar o grupo. Verifique a conexão com o Supabase.');
toast({
title: 'Erro',
description: 'Não foi possível registrar o grupo',
variant: 'destructive',
});
}
} catch (error) {
console.error('Erro ao cadastrar grupo:', error);
let errorMsg = 'Erro desconhecido';
if (error instanceof Error) {
errorMsg = error.message;
// Tentar extrair detalhes específicos do erro se existirem
if (errorMsg.includes('Status')) {
const statusMatch = errorMsg.match(/Status (\d+)/);
if (statusMatch && statusMatch[1]) {
setDebugInfo(`Código de status HTTP da API: ${statusMatch[1]}`);
}
}
}
setErrorMessage('Erro ao cadastrar grupo: ' + errorMsg);
toast({
title: 'Erro',
description: 'Não foi possível registrar o grupo',
variant: 'destructive',
});
} finally {
setCadastrando(false);
}
};
return (
<Card>
<CardHeader>
<CardTitle>Cadastrar novo grupo</CardTitle>
<CardDescription>
Preencha as informações abaixo para cadastrar um novo grupo do WhatsApp
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label htmlFor="nomeGrupo">Nome do grupo</Label>
<Input
id="nomeGrupo"
placeholder="Ex: Controle de Gastos da Família"
value={nomeGrupo}
onChange={(e) => setNomeGrupo(e.target.value)}
/>
<p className="text-sm text-muted-foreground">
Digite um nome descritivo para o grupo que você irá criar
</p>
</div>
<Button
onClick={handleCadastrarGrupo}
disabled={cadastrando || !userEmail || !nomeGrupo.trim()}
className="w-full"
>
{cadastrando ? (
<>
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
Cadastrando...
</>
) : (
<>
<Plus className="h-4 w-4 mr-2" />
Cadastrar Grupo
</>
)}
</Button>
<div className="mt-4 border-t pt-4">
<h3 className="font-medium mb-2">Após cadastrar:</h3>
<ol className="list-decimal list-inside space-y-2">
<li>Adicione o número (61)99244-4275 ao grupo do WhatsApp que deseja automatizar</li>
<li>Envie uma mensagem neste grupo com o seguinte texto:</li>
</ol>
<div className="bg-muted p-3 rounded-md font-mono mt-2">
{userEmail}
</div>
<p className="text-sm text-muted-foreground mt-2">
Copie e cole o email exatamente como aparece acima
</p>
</div>
{errorMessage && <p className="text-destructive text-sm mt-4">{errorMessage}</p>}
{debugInfo && <p className="text-amber-800 text-sm mt-2 bg-amber-50 p-3 rounded-md">{debugInfo}</p>}
</CardContent>
</Card>
);
};
export default CreateGroupForm;

View File

@ -0,0 +1,35 @@
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
interface DebugInfoProps {
errorMessage: string | null;
debugInfo: string | null;
}
const DebugInfo = ({ errorMessage, debugInfo }: DebugInfoProps) => {
if (!errorMessage && !debugInfo) return null;
return (
<>
{errorMessage && (
<Alert variant="destructive">
<AlertTitle>Erro ao cadastrar grupo</AlertTitle>
<AlertDescription>
{errorMessage}
</AlertDescription>
</Alert>
)}
{debugInfo && (
<Alert variant="default" className="bg-amber-50 border-amber-200">
<AlertTitle>Informações de depuração</AlertTitle>
<AlertDescription className="text-amber-800">
{debugInfo}
</AlertDescription>
</Alert>
)}
</>
);
};
export default DebugInfo;

View File

@ -0,0 +1,81 @@
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Loader2, MessageSquare } from 'lucide-react';
import { WhatsAppGroup } from '@/types/financialTypes';
interface GroupsListProps {
grupos: WhatsAppGroup[];
carregando: boolean;
}
const GroupsList = ({ grupos, carregando }: GroupsListProps) => {
return (
<Card>
<CardHeader>
<CardTitle>Seus grupos cadastrados</CardTitle>
<CardDescription>
Lista de grupos do WhatsApp que você cadastrou
</CardDescription>
</CardHeader>
<CardContent>
{carregando ? (
<div className="flex justify-center py-8">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
</div>
) : grupos.length > 0 ? (
<Table>
<TableHeader>
<TableRow>
<TableHead>ID</TableHead>
<TableHead>Nome do grupo</TableHead>
<TableHead>Status</TableHead>
<TableHead>Workflow</TableHead>
<TableHead>Cadastro</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{grupos.map((grupo) => (
<TableRow key={grupo.id}>
<TableCell className="font-medium">{grupo.id}</TableCell>
<TableCell>
{grupo.nome_grupo || (
<span className="text-muted-foreground italic">
{grupo.remote_jid ? 'Sem nome definido' : 'Aguardando vínculo...'}
</span>
)}
</TableCell>
<TableCell>
<Badge variant={grupo.remote_jid ? "success" : "outline"}>
{grupo.remote_jid ? 'Ativo' : 'Pendente'}
</Badge>
</TableCell>
<TableCell>
{grupo.workflow_id ? (
<Badge variant="secondary" className="bg-green-100 text-green-800">
Configurado
</Badge>
) : (
<Badge variant="outline" className="text-gray-500">
Não configurado
</Badge>
)}
</TableCell>
<TableCell>{new Date(grupo.created_at).toLocaleDateString()}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
) : (
<div className="text-center py-8">
<MessageSquare className="h-12 w-12 text-muted-foreground opacity-20 mx-auto mb-4" />
<p className="text-muted-foreground">Você ainda não cadastrou nenhum grupo</p>
</div>
)}
</CardContent>
</Card>
);
};
export default GroupsList;

View File

@ -2,26 +2,21 @@
import { useState, useEffect } from 'react';
import Layout from '@/components/layout/Layout';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
import { Badge } from '@/components/ui/badge';
import { Loader2, Plus, RefreshCw, MessageSquare, Edit } from 'lucide-react';
import { cadastrarGrupoWhatsApp, listarGruposWhatsApp } from '@/services/gruposWhatsAppService';
import { RefreshCw } from 'lucide-react';
import { listarGruposWhatsApp } from '@/services/gruposWhatsAppService';
import { WhatsAppGroup } from '@/types/financialTypes';
import { useToast } from '@/hooks/use-toast';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import CreateGroupForm from '@/components/whatsappGroups/CreateGroupForm';
import GroupsList from '@/components/whatsappGroups/GroupsList';
import DebugInfo from '@/components/whatsappGroups/DebugInfo';
const GruposWhatsApp = () => {
const { toast } = useToast();
const [grupos, setGrupos] = useState<WhatsAppGroup[]>([]);
const [carregando, setCarregando] = useState<boolean>(true);
const [cadastrando, setCadastrando] = useState<boolean>(false);
const [userEmail, setUserEmail] = useState<string>('');
const [errorMessage, setErrorMessage] = useState<string | null>(null);
const [debugInfo, setDebugInfo] = useState<string | null>(null);
const [nomeGrupo, setNomeGrupo] = useState<string>('');
// Buscar os grupos do usuário ao carregar a página
const buscarGrupos = async () => {
@ -53,91 +48,6 @@ const GruposWhatsApp = () => {
buscarGrupos();
}, []);
// Cadastrar novo grupo ou atualizar workflow se necessário
const handleCadastrarGrupo = async () => {
setErrorMessage(null);
setDebugInfo(null);
if (!userEmail) {
toast({
title: 'Erro',
description: 'Você precisa estar logado para cadastrar um grupo',
variant: 'destructive',
});
return;
}
if (!nomeGrupo.trim()) {
toast({
title: 'Atenção',
description: 'Digite um nome para o grupo',
variant: 'destructive',
});
return;
}
setCadastrando(true);
try {
console.log("Iniciando processo de cadastro de grupo...");
const grupo = await cadastrarGrupoWhatsApp(nomeGrupo.trim());
if (grupo) {
let successMessage = 'Grupo registrado com sucesso';
let variant: 'default' | 'destructive' = 'default';
if (grupo.workflow_id) {
successMessage = 'Grupo cadastrado e workflow criado com sucesso!';
} else {
successMessage = 'Grupo cadastrado, mas falha ao criar workflow de automação.';
setDebugInfo('O grupo foi criado no Supabase, mas houve um problema ao criar o workflow no n8n. Verifique os logs do console para mais detalhes.');
variant = 'destructive';
}
toast({
title: grupo.workflow_id ? 'Sucesso' : 'Atenção',
description: successMessage,
variant: variant,
});
// Resetar o campo de nome
setNomeGrupo('');
// Atualizar a lista de grupos
buscarGrupos();
} else {
setErrorMessage('Não foi possível registrar o grupo. Verifique a conexão com o Supabase.');
toast({
title: 'Erro',
description: 'Não foi possível registrar o grupo',
variant: 'destructive',
});
}
} catch (error) {
console.error('Erro ao cadastrar grupo:', error);
let errorMsg = 'Erro desconhecido';
if (error instanceof Error) {
errorMsg = error.message;
// Tentar extrair detalhes específicos do erro se existirem
if (errorMsg.includes('Status')) {
const statusMatch = errorMsg.match(/Status (\d+)/);
if (statusMatch && statusMatch[1]) {
setDebugInfo(`Código de status HTTP da API: ${statusMatch[1]}`);
}
}
}
setErrorMessage('Erro ao cadastrar grupo: ' + errorMsg);
toast({
title: 'Erro',
description: 'Não foi possível registrar o grupo',
variant: 'destructive',
});
} finally {
setCadastrando(false);
}
};
return (
<Layout>
<div className="space-y-6">
@ -156,144 +66,9 @@ const GruposWhatsApp = () => {
</div>
</div>
{errorMessage && (
<Alert variant="destructive">
<AlertTitle>Erro ao cadastrar grupo</AlertTitle>
<AlertDescription>
{errorMessage}
</AlertDescription>
</Alert>
)}
{debugInfo && (
<Alert variant="default" className="bg-amber-50 border-amber-200">
<AlertTitle>Informações de depuração</AlertTitle>
<AlertDescription className="text-amber-800">
{debugInfo}
</AlertDescription>
</Alert>
)}
<Card>
<CardHeader>
<CardTitle>Cadastrar novo grupo</CardTitle>
<CardDescription>
Preencha as informações abaixo para cadastrar um novo grupo do WhatsApp
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-2">
<Label htmlFor="nomeGrupo">Nome do grupo</Label>
<Input
id="nomeGrupo"
placeholder="Ex: Controle de Gastos da Família"
value={nomeGrupo}
onChange={(e) => setNomeGrupo(e.target.value)}
/>
<p className="text-sm text-muted-foreground">
Digite um nome descritivo para o grupo que você irá criar
</p>
</div>
<Button
onClick={handleCadastrarGrupo}
disabled={cadastrando || !userEmail || !nomeGrupo.trim()}
className="w-full"
>
{cadastrando ? (
<>
<Loader2 className="h-4 w-4 mr-2 animate-spin" />
Cadastrando...
</>
) : (
<>
<Plus className="h-4 w-4 mr-2" />
Cadastrar Grupo
</>
)}
</Button>
<div className="mt-4 border-t pt-4">
<h3 className="font-medium mb-2">Após cadastrar:</h3>
<ol className="list-decimal list-inside space-y-2">
<li>Adicione o número (61)99244-4275 ao grupo do WhatsApp que deseja automatizar</li>
<li>Envie uma mensagem neste grupo com o seguinte texto:</li>
</ol>
<div className="bg-muted p-3 rounded-md font-mono mt-2">
{userEmail}
</div>
<p className="text-sm text-muted-foreground mt-2">
Copie e cole o email exatamente como aparece acima
</p>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Seus grupos cadastrados</CardTitle>
<CardDescription>
Lista de grupos do WhatsApp que você cadastrou
</CardDescription>
</CardHeader>
<CardContent>
{carregando ? (
<div className="flex justify-center py-8">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
</div>
) : grupos.length > 0 ? (
<Table>
<TableHeader>
<TableRow>
<TableHead>ID</TableHead>
<TableHead>Nome do grupo</TableHead>
<TableHead>Status</TableHead>
<TableHead>Workflow</TableHead>
<TableHead>Cadastro</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{grupos.map((grupo) => (
<TableRow key={grupo.id}>
<TableCell className="font-medium">{grupo.id}</TableCell>
<TableCell>
{grupo.nome_grupo || (
<span className="text-muted-foreground italic">
{grupo.remote_jid ? 'Sem nome definido' : 'Aguardando vínculo...'}
</span>
)}
</TableCell>
<TableCell>
<Badge variant={grupo.remote_jid ? "success" : "outline"}>
{grupo.remote_jid ? 'Ativo' : 'Pendente'}
</Badge>
</TableCell>
<TableCell>
{grupo.workflow_id ? (
<Badge variant="secondary" className="bg-green-100 text-green-800">
Configurado
</Badge>
) : (
<Badge variant="outline" className="text-gray-500">
Não configurado
</Badge>
)}
</TableCell>
<TableCell>{new Date(grupo.created_at).toLocaleDateString()}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
) : (
<div className="text-center py-8">
<MessageSquare className="h-12 w-12 text-muted-foreground opacity-20 mx-auto mb-4" />
<p className="text-muted-foreground">Você ainda não cadastrou nenhum grupo</p>
</div>
)}
</CardContent>
</Card>
<DebugInfo errorMessage={errorMessage} debugInfo={debugInfo} />
<CreateGroupForm userEmail={userEmail} onSuccess={buscarGrupos} />
<GroupsList grupos={grupos} carregando={carregando} />
</div>
</Layout>
);