'use client'; import React, { useState, useEffect } from 'react'; import { createPortal } from 'react-dom'; import { motion, AnimatePresence } from 'framer-motion'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Textarea } from '@/components/ui/textarea'; import { Label } from '@/components/ui/label'; import { X, Edit, Trash2, Save, Plus } from 'lucide-react'; import { cn } from '@/lib/utils'; import { CustomCategory, getCustomCategories, saveCustomCategories } from '@/services/user'; interface CategoryManagerProps { isOpen: boolean; onClose: () => void; onCategoriesUpdated?: () => void; } export function CategoryManager({ isOpen, onClose, onCategoriesUpdated }: CategoryManagerProps) { const [categories, setCategories] = useState([]); const [editingIndex, setEditingIndex] = useState(null); const [editName, setEditName] = useState(''); const [editDescription, setEditDescription] = useState(''); const [isSaving, setIsSaving] = useState(false); const [isLoading, setIsLoading] = useState(false); // Load categories when modal opens useEffect(() => { if (isOpen) { loadCategories(); } }, [isOpen]); const loadCategories = async () => { setIsLoading(true); try { const response = await getCustomCategories(); if (response.data?.categories) { setCategories(response.data.categories); } } catch (error) { console.error('Failed to load custom categories:', error); alert('Failed to load categories. Please try again.'); } finally { setIsLoading(false); } }; const handleSave = async () => { setIsSaving(true); try { await saveCustomCategories(categories); onCategoriesUpdated?.(); onClose(); } catch (error) { console.error('Failed to save categories:', error); alert('Failed to save categories. Please try again.'); } finally { setIsSaving(false); } }; const handleEdit = (index: number) => { setEditingIndex(index); setEditName(categories[index].name); setEditDescription(categories[index].description); }; const handleSaveEdit = () => { if (!editName.trim()) { alert('Category name cannot be empty'); return; } const trimmedName = editName.trim(); // Keep user's exact casing // Check for duplicates (case-insensitive, excluding current item) const isDuplicate = categories.some((cat, idx) => idx !== editingIndex && cat.name.toLowerCase() === trimmedName.toLowerCase() ); if (isDuplicate) { alert('A category with this name already exists'); return; } const updated = [...categories]; updated[editingIndex!] = { name: trimmedName, description: editDescription.trim(), created_at: categories[editingIndex!].created_at }; setCategories(updated); setEditingIndex(null); setEditName(''); setEditDescription(''); }; const handleCancelEdit = () => { setEditingIndex(null); setEditName(''); setEditDescription(''); }; const handleDelete = (index: number) => { if (confirm(`Are you sure you want to delete the "${categories[index].name}" category?`)) { const updated = categories.filter((_, idx) => idx !== index); setCategories(updated); } }; if (!isOpen) return null; if (typeof window === 'undefined') return null; return createPortal( {/* Header */}

Manage Categories

Edit or delete your custom agent categories

{/* Content */}
{isLoading ? (
Loading categories...
) : categories.length === 0 ? (
No custom categories yet. Create one in the agent configuration panel.
) : (
{categories.map((category, index) => (
{editingIndex === index ? ( // Edit mode
setEditName(e.target.value)} placeholder="Enter category name..." autoFocus />