"use client"; import { useState } from "react"; import { Link, useNavigate } from "@tanstack/react-router"; import { useMutation, useQueryClient } from "@tanstack/react-query"; import { MoreVertical, Edit, Play, Power, Copy, Archive, RotateCcw, Trash2 } from "lucide-react"; import { formatDistanceToNow } from "date-fns"; import { ptBR } from "date-fns/locale"; import { toast } from "sonner"; import { supabase } from "@/integrations/supabase/client"; import { syncAgentSkills } from "@/lib/sync-agent-skills"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alert-dialog"; import { SkillStatusBadge } from "./SkillStatusBadge"; import type { Skill } from "@/hooks/use-skills"; import { SkillTestPanel } from "./SkillTestPanel"; export function SkillCard({ skill }: { skill: Skill }) { const navigate = useNavigate(); const qc = useQueryClient(); const [confirmArchive, setConfirmArchive] = useState(false); const [confirmDelete, setConfirmDelete] = useState(false); const [testOpen, setTestOpen] = useState(false); const isArchived = skill.status === "archived"; async function syncRuntimeAfterMutation(actionLabel: string) { const { error } = await syncAgentSkills(skill.agent_instance_id); if (error) { toast.warning(`${actionLabel}, mas o sync com o container falhou.`, { description: error.message, }); } } const updateStatus = useMutation({ mutationFn: async (newStatus: string) => { const { error } = await supabase .from("skills") .update({ status: newStatus, updated_at: new Date().toISOString() }) .eq("id", skill.id); if (error) throw error; }, onSuccess: () => { qc.invalidateQueries({ queryKey: ["skills"] }); qc.invalidateQueries({ queryKey: ["user-limits"] }); }, }); const handleToggleActive = () => { const next = skill.status === "active" ? "disabled" : "active"; updateStatus.mutate(next, { onSuccess: async () => { const actionLabel = next === "active" ? "Skill ativada" : "Skill desativada"; toast.success(actionLabel); await syncRuntimeAfterMutation(actionLabel); }, onError: (e: unknown) => toast.error(e instanceof Error ? e.message : "Erro ao atualizar"), }); }; const handleArchive = () => { updateStatus.mutate("archived", { onSuccess: async () => { toast.success("Skill arquivada"); setConfirmArchive(false); await syncRuntimeAfterMutation("Skill arquivada"); }, onError: (e: unknown) => toast.error(e instanceof Error ? e.message : "Erro ao arquivar"), }); }; const handleRestore = () => { updateStatus.mutate("draft", { onSuccess: async () => { toast.success("Skill restaurada como rascunho"); await syncRuntimeAfterMutation("Skill restaurada como rascunho"); }, onError: (e: unknown) => { if ((e as { code?: string })?.code === "23505") { toast.error("Já existe outra skill ativa com esse nome. Renomeie antes de restaurar."); } else { toast.error(e instanceof Error ? e.message : "Erro ao restaurar"); } }, }); }; const handleDelete = useMutation({ mutationFn: async () => { const { error } = await supabase.from("skills").delete().eq("id", skill.id); if (error) throw error; }, onSuccess: async () => { toast.success("Skill deletada"); qc.invalidateQueries({ queryKey: ["skills"] }); qc.invalidateQueries({ queryKey: ["user-limits"] }); setConfirmDelete(false); await syncRuntimeAfterMutation("Skill deletada"); }, onError: (e: unknown) => toast.error(e instanceof Error ? e.message : "Erro ao deletar"), }); return ( <>
{skill.description}