feat: Use user-provided group name and display created groups

- Modified the WhatsApp group creation to use the user-entered group name instead of the default.
- Implemented the display of created group cards in the "Seus grupos cadastrados" section, including a delete option.
This commit is contained in:
gpt-engineer-app[bot] 2025-06-16 21:05:35 +00:00
parent 57e016a3fb
commit 7970b1b99f
6 changed files with 131 additions and 60 deletions

View File

@ -117,9 +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 com os parâmetros corretos
// 2. Criar grupo no WhatsApp via API com o nome escolhido pelo usuário
try {
const groupResponse = await createWhatsAppGroup(userEmail);
const groupResponse = await createWhatsAppGroup(userEmail, nomeGrupo.trim());
console.log('Resposta da criação do grupo:', groupResponse);
@ -129,7 +129,7 @@ const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
toast({
title: 'Sucesso!',
description: `Grupo "${groupResponse.subject}" criado com sucesso no seu WhatsApp!`,
description: `Grupo "${nomeGrupo}" criado com sucesso no seu WhatsApp!`,
variant: 'default',
});
} else {
@ -260,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: finance{userEmail.split('@')[0]}</li>
<li>O grupo terá o nome que você escolheu: {nomeGrupo || 'Digite um nome acima'}</li>
</ul>
</div>
</CardContent>

View File

@ -0,0 +1,58 @@
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { MessageSquare, Trash2 } from 'lucide-react';
import { WhatsAppGroup } from '@/types/financialTypes';
interface GroupCardProps {
group: WhatsAppGroup;
onDelete: (groupId: number) => void;
}
const GroupCard = ({ group, onDelete }: GroupCardProps) => {
return (
<Card className="w-full">
<CardHeader className="pb-3">
<div className="flex justify-between items-start">
<div className="flex items-center gap-2">
<MessageSquare className="h-5 w-5 text-green-600" />
<CardTitle className="text-lg">{group.nome_grupo}</CardTitle>
</div>
<Button
variant="ghost"
size="sm"
onClick={() => onDelete(group.id)}
className="text-red-500 hover:text-red-700 hover:bg-red-50"
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
</CardHeader>
<CardContent className="pt-0">
<div className="space-y-2">
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">Status:</span>
<Badge variant={group.remote_jid ? "success" : "outline"}>
{group.remote_jid ? 'Ativo' : 'Pendente'}
</Badge>
</div>
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">Workflow:</span>
<Badge variant={group.workflow_id ? "secondary" : "outline"}>
{group.workflow_id ? 'Configurado' : 'Não configurado'}
</Badge>
</div>
<div className="flex justify-between items-center">
<span className="text-sm text-muted-foreground">Criado em:</span>
<span className="text-sm">{new Date(group.created_at).toLocaleDateString()}</span>
</div>
</div>
</CardContent>
</Card>
);
};
export default GroupCard;

View File

@ -1,16 +1,19 @@
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';
import GroupCard from './GroupCard';
interface GroupsListProps {
grupos: WhatsAppGroup[];
carregando: boolean;
onDeleteGroup: (groupId: number) => void;
}
const GroupsList = ({ grupos, carregando }: GroupsListProps) => {
const GroupsList = ({ grupos, carregando, onDeleteGroup }: GroupsListProps) => {
// Filtrar apenas grupos que têm nome_grupo preenchido
const gruposComNome = grupos.filter(grupo => grupo.nome_grupo && grupo.nome_grupo.trim() !== '');
return (
<Card>
<CardHeader>
@ -24,49 +27,16 @@ const GroupsList = ({ grupos, carregando }: GroupsListProps) => {
<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>
) : gruposComNome.length > 0 ? (
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{gruposComNome.map((grupo) => (
<GroupCard
key={grupo.id}
group={grupo}
onDelete={onDeleteGroup}
/>
))}
</div>
) : (
<div className="text-center py-8">
<MessageSquare className="h-12 w-12 text-muted-foreground opacity-20 mx-auto mb-4" />

View File

@ -4,6 +4,7 @@ import Layout from '@/components/layout/Layout';
import { Button } from '@/components/ui/button';
import { RefreshCw } from 'lucide-react';
import { listarGruposWhatsApp } from '@/services/gruposWhatsAppService';
import { deleteWhatsAppGroup } from '@/services/whatsAppGroupsService';
import { WhatsAppGroup } from '@/types/financialTypes';
import { useToast } from '@/hooks/use-toast';
import CreateGroupForm from '@/components/whatsappGroups/CreateGroupForm';
@ -33,6 +34,26 @@ const GruposWhatsApp = () => {
}
};
// Deletar grupo
const handleDeleteGroup = async (groupId: number) => {
try {
await deleteWhatsAppGroup(groupId);
toast({
title: 'Sucesso',
description: 'Grupo deletado com sucesso',
});
// Atualizar a lista após deletar
buscarGrupos();
} catch (error) {
console.error('Erro ao deletar grupo:', error);
toast({
title: 'Erro',
description: 'Não foi possível deletar o grupo',
variant: 'destructive',
});
}
};
useEffect(() => {
// Obter o email do usuário do localStorage
const email = localStorage.getItem('userEmail');
@ -62,7 +83,11 @@ const GruposWhatsApp = () => {
</div>
<CreateGroupForm userEmail={userEmail} onSuccess={buscarGrupos} />
<GroupsList grupos={grupos} carregando={carregando} />
<GroupsList
grupos={grupos}
carregando={carregando}
onDeleteGroup={handleDeleteGroup}
/>
</div>
</Layout>
);

View File

@ -1,4 +1,3 @@
import { supabase } from "@/integrations/supabase/client";
interface CreateGroupResponse {
@ -9,20 +8,17 @@ interface CreateGroupResponse {
}
/**
* Cria um grupo WhatsApp via API da Evolution usando o padrão correto
* Cria um grupo WhatsApp via API da Evolution usando o nome escolhido pelo usuário
*/
export async function createWhatsAppGroup(
userEmail: string
userEmail: string,
groupName: string
): Promise<CreateGroupResponse> {
try {
// 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/${userEmail}`;
const requestBody = {
subject: groupSubject,
subject: groupName,
description: "Finance Home seu controle sem complicação",
participants: ["5561992444275"]
};

View File

@ -1,4 +1,3 @@
// Service dedicated to WhatsApp groups database operations
import { supabase } from "@/integrations/supabase/client";
import { WhatsAppGroup } from "@/types/financialTypes";
@ -114,6 +113,29 @@ export async function findOrCreateWhatsAppGroup(nomeGrupo?: string): Promise<Wha
}
}
/**
* Deletes a WhatsApp group from the database
* @param groupId The ID of the group to delete
*/
export async function deleteWhatsAppGroup(groupId: number): Promise<void> {
try {
const { error } = await supabase
.from('grupos_whatsapp')
.delete()
.eq('id', groupId);
if (error) {
console.error('Erro ao deletar grupo:', error);
throw error;
}
console.log(`Grupo ${groupId} deletado com sucesso`);
} catch (error) {
console.error('Erro ao deletar grupo do WhatsApp:', error);
throw error;
}
}
/**
* Lists all WhatsApp groups for the current user
* @returns Array of WhatsApp groups