import { useState, useEffect, useRef } from 'react' import { categoriesApi } from '../../api/client' import { useToast } from '../shared/Toast' import { Plus, Edit2, Trash2, Pipette } from 'lucide-react' import { CATEGORY_ICON_MAP, ICON_LABELS, getCategoryIcon } from '../shared/categoryIcons' import { useTranslation } from '../../i18n' import { getApiErrorMessage } from '../../types' const PRESET_COLORS = [ '#6366f1', '#8b5cf6', '#ec4899', '#ef4444', '#f97316', '#f59e0b', '#10b981', '#06b6d4', '#3b82f6', '#84cc16', '#6b7280', '#1f2937', ] const ICON_NAMES = Object.keys(CATEGORY_ICON_MAP) export default function CategoryManager() { const [categories, setCategories] = useState([]) const [showForm, setShowForm] = useState(false) const [editingId, setEditingId] = useState(null) const [form, setForm] = useState({ name: '', color: '#6366f1', icon: 'MapPin' }) const [isSaving, setIsSaving] = useState(false) const [isLoading, setIsLoading] = useState(true) const colorInputRef = useRef(null) const toast = useToast() const { t } = useTranslation() useEffect(() => { loadCategories() }, []) const loadCategories = async () => { setIsLoading(true) try { const data = await categoriesApi.list() setCategories(data.categories || []) } catch (err: unknown) { toast.error(t('categories.toast.loadError')) } finally { setIsLoading(false) } } const handleStartEdit = (cat) => { setEditingId(cat.id) setForm({ name: cat.name, color: cat.color || '#6366f1', icon: cat.icon || 'MapPin' }) setShowForm(false) } const handleStartCreate = () => { setEditingId(null) setForm({ name: '', color: '#6366f1', icon: 'MapPin' }) setShowForm(true) } const handleCancel = () => { setShowForm(false) setEditingId(null) } const handleSave = async () => { if (!form.name.trim()) { toast.error(t('categories.toast.nameRequired')); return } setIsSaving(true) try { if (editingId) { const result = await categoriesApi.update(editingId, form) setCategories(prev => prev.map(c => c.id === editingId ? result.category : c)) setEditingId(null) toast.success(t('categories.toast.updated')) } else { const result = await categoriesApi.create(form) setCategories(prev => [...prev, result.category]) setShowForm(false) toast.success(t('categories.toast.created')) } setForm({ name: '', color: '#6366f1', icon: 'MapPin' }) } catch (err: unknown) { toast.error(getApiErrorMessage(err, t('categories.toast.saveError'))) } finally { setIsSaving(false) } } const handleDelete = async (id) => { if (!confirm(t('categories.confirm.delete'))) return try { await categoriesApi.delete(id) setCategories(prev => prev.filter(c => c.id !== id)) toast.success(t('categories.toast.deleted')) } catch (err: unknown) { toast.error(getApiErrorMessage(err, t('categories.toast.deleteError'))) } } const isPresetColor = PRESET_COLORS.includes(form.color) const PreviewIcon = getCategoryIcon(form.icon) const categoryForm = (
{t('categories.subtitle')}
{t('categories.empty')}