"use client"; import { useState } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { X, Save, Tag, FolderOpen, Clock, BarChart3, Globe, Lock, Info } from "lucide-react"; import { useMutation } from "convex/react"; import { api } from "@/convex/_generated/api"; import { toast } from "sonner"; import { useUser } from "@clerk/nextjs"; interface SaveAsTemplateModalProps { isOpen: boolean; onClose: () => void; workflowId: string; workflowName: string; } const categories = [ "User Templates", "AI & Automation", "Data Processing", "Web Scraping", "Business Logic", "Integration", "Utility", "Custom", ]; const difficultyLevels = [ { value: "beginner", label: "Beginner", color: "text-green-600" }, { value: "intermediate", label: "Intermediate", color: "text-yellow-600" }, { value: "advanced", label: "Advanced", color: "text-orange-600" }, { value: "expert", label: "Expert", color: "text-red-600" }, ]; export default function SaveAsTemplateModal({ isOpen, onClose, workflowId, workflowName, }: SaveAsTemplateModalProps) { const { user } = useUser(); const saveAsTemplate = useMutation(api.templates.saveAsTemplate); const [formData, setFormData] = useState({ name: `${workflowName} Template`, description: "", category: "User Templates", tags: [] as string[], difficulty: "intermediate", estimatedTime: "", isPublic: false, }); const [currentTag, setCurrentTag] = useState(""); const [isSaving, setIsSaving] = useState(false); const handleAddTag = () => { if (currentTag.trim() && !formData.tags.includes(currentTag.trim())) { setFormData({ ...formData, tags: [...formData.tags, currentTag.trim()], }); setCurrentTag(""); } }; const handleRemoveTag = (tag: string) => { setFormData({ ...formData, tags: formData.tags.filter((t) => t !== tag), }); }; const handleSave = async () => { if (!formData.name.trim()) { toast.error("Template name is required"); return; } if (!workflowId) { toast.error("Invalid workflow"); return; } setIsSaving(true); try { await saveAsTemplate({ workflowId: workflowId as any, name: formData.name, description: formData.description || undefined, category: formData.category, tags: formData.tags.length > 0 ? formData.tags : undefined, difficulty: formData.difficulty || undefined, estimatedTime: formData.estimatedTime || undefined, isPublic: formData.isPublic, }); toast.success("Template saved successfully!", { description: formData.isPublic ? "Your template is now available to other users" : "Your template has been saved to your private collection", }); onClose(); } catch (error) { console.error("Failed to save template:", error); toast.error("Failed to save template", { description: error instanceof Error ? error.message : "Please try again", }); } finally { setIsSaving(false); } }; if (!isOpen) return null; return ( e.stopPropagation()} > {/* Header */}

Save as Template

Save this workflow as a reusable template

{/* Content */}
{/* Template Name */}
setFormData({ ...formData, name: e.target.value })} placeholder="Enter template name" className="w-full px-12 py-10 bg-background-base border border-border-faint rounded-8 text-body-medium text-accent-black placeholder:text-black-alpha-32 focus:outline-none focus:ring-2 focus:ring-heat-100" />
{/* Description */}