import { useT } from "@agent-native/core/client/i18n";
import {
IconLoader2,
IconMessage2,
IconPencil,
IconPlus,
IconTrash,
} from "@tabler/icons-react";
import { useEffect, useRef, useState } from "react";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Skeleton } from "@/components/ui/skeleton";
import { Textarea } from "@/components/ui/textarea";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import {
useCreateSnippet,
useDeleteSnippet,
useSnippets,
useUpdateSnippet,
type Snippet,
} from "@/hooks/use-snippets";
function SnippetEditRow({
snippet,
onSave,
onCancel,
isPending,
}: {
snippet?: Snippet;
onSave: (name: string, body: string) => void;
onCancel: () => void;
isPending?: boolean;
}) {
const t = useT();
const [name, setName] = useState(snippet?.name ?? "");
const [body, setBody] = useState(snippet?.body ?? "");
const handleSave = () => {
if (!name.trim() || !body.trim()) return;
onSave(name.trim(), body);
};
return (
setName(e.target.value)}
placeholder={t("settings.snippetNamePlaceholder")}
className="px-3 py-1.5 text-[13px] placeholder:text-muted-foreground/40"
/>
);
}
function SnippetRow({
snippet,
isEditing,
onEdit,
onCancelEdit,
}: {
snippet: Snippet;
isEditing: boolean;
onEdit: () => void;
onCancelEdit: () => void;
}) {
const t = useT();
const updateSnippet = useUpdateSnippet();
const deleteSnippet = useDeleteSnippet();
const rowRef = useRef(null);
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
useEffect(() => {
if (isEditing && rowRef.current) {
rowRef.current.scrollIntoView({ behavior: "smooth", block: "nearest" });
}
}, [isEditing]);
const handleSave = (name: string, body: string) => {
updateSnippet.mutate(
{ id: snippet.id, name, body },
{ onSuccess: onCancelEdit },
);
};
const confirmDelete = () => {
deleteSnippet.mutate(snippet.id);
setShowDeleteConfirm(false);
};
if (isEditing) {
return (
);
}
return (
<>
{snippet.name}
{snippet.body}
{t("settings.editSnippet")}
{t("settings.deleteSnippet")}
{t("settings.deleteSnippet")}
{t("settings.deleteSnippetDescription", { name: snippet.name })}
{t("settings.cancel")}
{t("settings.delete")}
>
);
}
export function SnippetsSection() {
const t = useT();
const { data, isLoading } = useSnippets();
const snippets = data?.snippets ?? [];
const createSnippet = useCreateSnippet();
const [editingId, setEditingId] = useState(null);
const [showNewForm, setShowNewForm] = useState(false);
const handleCreate = (name: string, body: string) => {
createSnippet.mutate(
{ name, body },
{ onSuccess: () => setShowNewForm(false) },
);
};
return (
{t("settings.snippets")}
{t("settings.snippetsDescription")}
{showNewForm && (
setShowNewForm(false)}
isPending={createSnippet.isPending}
/>
)}
{isLoading &&
Array.from({ length: 3 }).map((_, i) => (
))}
{!isLoading && snippets.length === 0 && !showNewForm && (
{t("settings.noSnippets")}
)}
{snippets.map((snippet) => (
{
setEditingId(snippet.id);
setShowNewForm(false);
}}
onCancelEdit={() => setEditingId(null)}
/>
))}
);
}