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:
parent
57e016a3fb
commit
7970b1b99f
@ -117,9 +117,9 @@ const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
|
|||||||
throw new Error('Não foi possível cadastrar o grupo no banco de dados');
|
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 {
|
try {
|
||||||
const groupResponse = await createWhatsAppGroup(userEmail);
|
const groupResponse = await createWhatsAppGroup(userEmail, nomeGrupo.trim());
|
||||||
|
|
||||||
console.log('Resposta da criação do grupo:', groupResponse);
|
console.log('Resposta da criação do grupo:', groupResponse);
|
||||||
|
|
||||||
@ -129,7 +129,7 @@ const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
|
|||||||
|
|
||||||
toast({
|
toast({
|
||||||
title: 'Sucesso!',
|
title: 'Sucesso!',
|
||||||
description: `Grupo "${groupResponse.subject}" criado com sucesso no seu WhatsApp!`,
|
description: `Grupo "${nomeGrupo}" criado com sucesso no seu WhatsApp!`,
|
||||||
variant: 'default',
|
variant: 'default',
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -260,7 +260,7 @@ const CreateGroupForm = ({ userEmail, onSuccess }: CreateGroupFormProps) => {
|
|||||||
<ul className="list-disc list-inside space-y-1 text-sm text-muted-foreground">
|
<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>O grupo será criado automaticamente no seu WhatsApp</li>
|
||||||
<li>Você será adicionado como participante do grupo</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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
58
src/components/whatsappGroups/GroupCard.tsx
Normal file
58
src/components/whatsappGroups/GroupCard.tsx
Normal 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;
|
||||||
@ -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 { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
|
||||||
import { Badge } from '@/components/ui/badge';
|
|
||||||
import { Loader2, MessageSquare } from 'lucide-react';
|
import { Loader2, MessageSquare } from 'lucide-react';
|
||||||
import { WhatsAppGroup } from '@/types/financialTypes';
|
import { WhatsAppGroup } from '@/types/financialTypes';
|
||||||
|
import GroupCard from './GroupCard';
|
||||||
|
|
||||||
interface GroupsListProps {
|
interface GroupsListProps {
|
||||||
grupos: WhatsAppGroup[];
|
grupos: WhatsAppGroup[];
|
||||||
carregando: boolean;
|
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 (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
@ -24,49 +27,16 @@ const GroupsList = ({ grupos, carregando }: GroupsListProps) => {
|
|||||||
<div className="flex justify-center py-8">
|
<div className="flex justify-center py-8">
|
||||||
<Loader2 className="h-8 w-8 animate-spin text-primary" />
|
<Loader2 className="h-8 w-8 animate-spin text-primary" />
|
||||||
</div>
|
</div>
|
||||||
) : grupos.length > 0 ? (
|
) : gruposComNome.length > 0 ? (
|
||||||
<Table>
|
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
|
||||||
<TableHeader>
|
{gruposComNome.map((grupo) => (
|
||||||
<TableRow>
|
<GroupCard
|
||||||
<TableHead>ID</TableHead>
|
key={grupo.id}
|
||||||
<TableHead>Nome do grupo</TableHead>
|
group={grupo}
|
||||||
<TableHead>Status</TableHead>
|
onDelete={onDeleteGroup}
|
||||||
<TableHead>Workflow</TableHead>
|
/>
|
||||||
<TableHead>Cadastro</TableHead>
|
))}
|
||||||
</TableRow>
|
</div>
|
||||||
</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">
|
<div className="text-center py-8">
|
||||||
<MessageSquare className="h-12 w-12 text-muted-foreground opacity-20 mx-auto mb-4" />
|
<MessageSquare className="h-12 w-12 text-muted-foreground opacity-20 mx-auto mb-4" />
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import Layout from '@/components/layout/Layout';
|
|||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { RefreshCw } from 'lucide-react';
|
import { RefreshCw } from 'lucide-react';
|
||||||
import { listarGruposWhatsApp } from '@/services/gruposWhatsAppService';
|
import { listarGruposWhatsApp } from '@/services/gruposWhatsAppService';
|
||||||
|
import { deleteWhatsAppGroup } from '@/services/whatsAppGroupsService';
|
||||||
import { WhatsAppGroup } from '@/types/financialTypes';
|
import { WhatsAppGroup } from '@/types/financialTypes';
|
||||||
import { useToast } from '@/hooks/use-toast';
|
import { useToast } from '@/hooks/use-toast';
|
||||||
import CreateGroupForm from '@/components/whatsappGroups/CreateGroupForm';
|
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(() => {
|
useEffect(() => {
|
||||||
// Obter o email do usuário do localStorage
|
// Obter o email do usuário do localStorage
|
||||||
const email = localStorage.getItem('userEmail');
|
const email = localStorage.getItem('userEmail');
|
||||||
@ -62,7 +83,11 @@ const GruposWhatsApp = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CreateGroupForm userEmail={userEmail} onSuccess={buscarGrupos} />
|
<CreateGroupForm userEmail={userEmail} onSuccess={buscarGrupos} />
|
||||||
<GroupsList grupos={grupos} carregando={carregando} />
|
<GroupsList
|
||||||
|
grupos={grupos}
|
||||||
|
carregando={carregando}
|
||||||
|
onDeleteGroup={handleDeleteGroup}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import { supabase } from "@/integrations/supabase/client";
|
import { supabase } from "@/integrations/supabase/client";
|
||||||
|
|
||||||
interface CreateGroupResponse {
|
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(
|
export async function createWhatsAppGroup(
|
||||||
userEmail: string
|
userEmail: string,
|
||||||
|
groupName: string
|
||||||
): Promise<CreateGroupResponse> {
|
): Promise<CreateGroupResponse> {
|
||||||
try {
|
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 url = `https://evolutionapi2.innova1001.com.br/group/create/${userEmail}`;
|
||||||
|
|
||||||
const requestBody = {
|
const requestBody = {
|
||||||
subject: groupSubject,
|
subject: groupName,
|
||||||
description: "Finance Home seu controle sem complicação",
|
description: "Finance Home seu controle sem complicação",
|
||||||
participants: ["5561992444275"]
|
participants: ["5561992444275"]
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
// Service dedicated to WhatsApp groups database operations
|
// Service dedicated to WhatsApp groups database operations
|
||||||
import { supabase } from "@/integrations/supabase/client";
|
import { supabase } from "@/integrations/supabase/client";
|
||||||
import { WhatsAppGroup } from "@/types/financialTypes";
|
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
|
* Lists all WhatsApp groups for the current user
|
||||||
* @returns Array of WhatsApp groups
|
* @returns Array of WhatsApp groups
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user