"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 { Button } from "@/components/ui/button"; 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"; 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: () => toast.success(next === "active" ? "Skill ativada" : "Skill desativada"), onError: (e: unknown) => toast.error(e instanceof Error ? e.message : "Erro ao atualizar"), }); }; const handleArchive = () => { updateStatus.mutate("archived", { onSuccess: () => { toast.success("Skill arquivada"); setConfirmArchive(false); }, onError: (e: unknown) => toast.error(e instanceof Error ? e.message : "Erro ao arquivar"), }); }; const handleRestore = () => { updateStatus.mutate("draft", { onSuccess: () => toast.success("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: () => { toast.success("Skill deletada"); qc.invalidateQueries({ queryKey: ["skills"] }); qc.invalidateQueries({ queryKey: ["user-limits"] }); setConfirmDelete(false); }, onError: (e: unknown) => toast.error(e instanceof Error ? e.message : "Erro ao deletar"), }); return ( <>

{skill.description}

{isArchived ? ( <> Restaurar setConfirmDelete(true)} className="cursor-pointer text-destructive focus:text-destructive" > Deletar ) : ( <> Editar setTestOpen(true)} disabled={!skill.current_version_id} className="cursor-pointer" > Testar {skill.status === "active" ? "Desativar" : "Ativar"} Duplicar setConfirmArchive(true)} className="cursor-pointer text-destructive focus:text-destructive" > Arquivar )}
{formatDistanceToNow(new Date(skill.updated_at), { addSuffix: true, locale: ptBR })}
Arquivar esta skill? A skill {skill.name} ficará invisível para o agente. Você poderá restaurá-la depois sem perder o histórico. Cancelar Arquivar Deletar definitivamente? Esta ação remove {skill.name} e todo o histórico de versões. Não é possível desfazer. Cancelar handleDelete.mutate()} className="bg-destructive text-destructive-foreground hover:bg-destructive/90" > Deletar {testOpen && skill.current_version_id && ( )} ); }