import React, { useState } from 'react'; import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'; import { Plus, Edit2, Trash2, Loader2 } from 'lucide-react'; import { toast } from 'react-toastify'; import { useTranslation } from 'react-i18next'; import { categoriesService, type PhotoCategory } from '../../services/categories.service'; import { Button } from '../common'; export const CategoryManager: React.FC = () => { const { t } = useTranslation(); const queryClient = useQueryClient(); const [isAdding, setIsAdding] = useState(false); const [editingId, setEditingId] = useState(null); const [newCategoryName, setNewCategoryName] = useState(''); const [editingName, setEditingName] = useState(''); // Fetch global categories const { data: categories = [], isLoading } = useQuery({ queryKey: ['global-categories'], queryFn: categoriesService.getGlobalCategories, }); // Create category mutation const createMutation = useMutation({ mutationFn: (name: string) => categoriesService.createCategory({ name, is_global: true }), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['global-categories'] }); toast.success(t('categories.categoryCreatedSuccess')); setNewCategoryName(''); setIsAdding(false); }, onError: (error: any) => { toast.error(error.response?.data?.error || t('categories.failedToCreateCategory')); }, }); // Update category mutation const updateMutation = useMutation({ mutationFn: ({ id, name }: { id: number; name: string }) => categoriesService.updateCategory(id, name), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['global-categories'] }); toast.success(t('toast.categoryUpdated')); setEditingId(null); setEditingName(''); }, onError: (error: any) => { toast.error(error.response?.data?.error || t('toast.saveError')); }, }); // Delete category mutation const deleteMutation = useMutation({ mutationFn: categoriesService.deleteCategory, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['global-categories'] }); toast.success(t('categories.categoryDeletedSuccess')); }, onError: (error: any) => { toast.error(error.response?.data?.error || t('categories.failedToDeleteCategory')); }, }); const handleCreate = () => { if (newCategoryName.trim()) { createMutation.mutate(newCategoryName.trim()); } }; const handleUpdate = (id: number) => { if (editingName.trim()) { updateMutation.mutate({ id, name: editingName.trim() }); } }; const handleDelete = (category: PhotoCategory) => { if (window.confirm(t('categories.deleteConfirm', { name: category.name }))) { deleteMutation.mutate(category.id); } }; const startEdit = (category: PhotoCategory) => { setEditingId(category.id); setEditingName(category.name); }; const cancelEdit = () => { setEditingId(null); setEditingName(''); }; if (isLoading) { return (
); } return (

{t('categories.title')}

{!isAdding && ( )}
{/* Add new category form */} {isAdding && (
setNewCategoryName(e.target.value)} onKeyPress={(e) => e.key === 'Enter' && handleCreate()} placeholder={t('categories.categoryName')} className="flex-1 px-3 py-2 border border-neutral-300 rounded-md focus:ring-2 focus:ring-primary-500" autoFocus />
)} {/* Categories list */}
{categories.length === 0 ? (

{t('categories.noCategoriesYet')}

) : ( categories.map((category) => (
{editingId === category.id ? (
setEditingName(e.target.value)} onKeyPress={(e) => { if (e.key === 'Enter') handleUpdate(category.id); if (e.key === 'Escape') cancelEdit(); }} className="flex-1 px-3 py-1 border border-neutral-300 rounded-md focus:ring-2 focus:ring-primary-500" autoFocus />
) : ( <>

{category.name}

/{category.slug}

)}
)) )}
); }; CategoryManager.displayName = 'CategoryManager';