import React, { useState, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Separator } from "@/components/ui/separator"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import { Plus, Play, Edit, Trash2, Copy } from "lucide-react"; import { toast } from "sonner"; import { useTranslation } from "react-i18next"; import { useConfirmation } from "@/hooks/use-confirmation.ts"; import { getSnippets, createSnippet, updateSnippet, deleteSnippet, } from "@/ui/main-axios"; import type { Snippet, SnippetData } from "../../../../types/index.js"; interface SnippetsSidebarProps { isOpen: boolean; onClose: () => void; onExecute: (content: string) => void; } export function SnippetsSidebar({ isOpen, onClose, onExecute, }: SnippetsSidebarProps) { const { t } = useTranslation(); const { confirmWithToast } = useConfirmation(); const [snippets, setSnippets] = useState([]); const [loading, setLoading] = useState(true); const [showDialog, setShowDialog] = useState(false); const [editingSnippet, setEditingSnippet] = useState(null); const [formData, setFormData] = useState({ name: "", content: "", description: "", }); const [formErrors, setFormErrors] = useState({ name: false, content: false, }); useEffect(() => { if (isOpen) { fetchSnippets(); } }, [isOpen]); const fetchSnippets = async () => { try { setLoading(true); const data = await getSnippets(); // Defensive: ensure data is an array setSnippets(Array.isArray(data) ? data : []); } catch (err) { toast.error(t("snippets.failedToFetch")); setSnippets([]); } finally { setLoading(false); } }; const handleCreate = () => { setEditingSnippet(null); setFormData({ name: "", content: "", description: "" }); setFormErrors({ name: false, content: false }); setShowDialog(true); }; const handleEdit = (snippet: Snippet) => { setEditingSnippet(snippet); setFormData({ name: snippet.name, content: snippet.content, description: snippet.description || "", }); setFormErrors({ name: false, content: false }); setShowDialog(true); }; const handleDelete = (snippet: Snippet) => { confirmWithToast( t("snippets.deleteConfirmDescription", { name: snippet.name }), async () => { try { await deleteSnippet(snippet.id); toast.success(t("snippets.deleteSuccess")); fetchSnippets(); } catch (err) { toast.error(t("snippets.deleteFailed")); } }, "destructive", ); }; const handleSubmit = async () => { // Validate required fields const errors = { name: !formData.name.trim(), content: !formData.content.trim(), }; setFormErrors(errors); if (errors.name || errors.content) { return; } try { if (editingSnippet) { await updateSnippet(editingSnippet.id, formData); toast.success(t("snippets.updateSuccess")); } else { await createSnippet(formData); toast.success(t("snippets.createSuccess")); } setShowDialog(false); fetchSnippets(); } catch (err) { toast.error( editingSnippet ? t("snippets.updateFailed") : t("snippets.createFailed"), ); } }; const handleExecute = (snippet: Snippet) => { onExecute(snippet.content); toast.success(t("snippets.executeSuccess", { name: snippet.name })); }; const handleCopy = (snippet: Snippet) => { navigator.clipboard.writeText(snippet.content); toast.success(t("snippets.copySuccess", { name: snippet.name })); }; if (!isOpen) return null; return ( <> {/* Overlay and Sidebar */}
e.stopPropagation()} > {/* Header */}

{t("snippets.title")}

{/* Content */}
{loading ? (

{t("common.loading")}

) : snippets.length === 0 ? (

{t("snippets.empty")}

{t("snippets.emptyHint")}

) : (
{snippets.map((snippet) => (

{snippet.name}

{snippet.description && (

{snippet.description}

)}
{snippet.content}

{t("snippets.runTooltip")}

{t("snippets.copyTooltip")}

{t("snippets.editTooltip")}

{t("snippets.deleteTooltip")}

))}
)}
{/* Create/Edit Dialog - centered modal */} {showDialog && (
setShowDialog(false)} >
e.stopPropagation()} >

{editingSnippet ? t("snippets.edit") : t("snippets.create")}

{editingSnippet ? t("snippets.editDescription") : t("snippets.createDescription")}

setFormData({ ...formData, name: e.target.value }) } placeholder={t("snippets.namePlaceholder")} className={`${formErrors.name ? "border-destructive focus-visible:ring-destructive" : ""}`} autoFocus /> {formErrors.name && (

{t("snippets.nameRequired")}

)}
setFormData({ ...formData, description: e.target.value }) } placeholder={t("snippets.descriptionPlaceholder")} />