'use client' import { useState, useEffect, useCallback } from 'react' import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Badge } from '@/components/ui/badge' import { Checkbox } from '@/components/ui/checkbox' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '@/components/ui/dropdown-menu' import { Search, Plus, Edit, Trash2, MoreHorizontal, Download } from 'lucide-react' import { toast } from 'sonner' import Link from 'next/link' import Image from 'next/image' import { CategoryFormDialog } from '@/components/admin/CategoryFormDialog' interface Category { id: string name: string description: string image: string | null isActive: boolean createdAt: string _count: { products: number } } export default function AdminCategoriesPage() { const [categories, setCategories] = useState([]) const [loading, setLoading] = useState(true) const [search, setSearch] = useState('') const [selectedCategories, setSelectedCategories] = useState([]) const [bulkActionLoading, setBulkActionLoading] = useState(false) const fetchCategories = useCallback(async () => { try { setLoading(true) const params = new URLSearchParams() if (search) params.append('search', search) const response = await fetch(`/api/admin/categories?${params}`) const data = await response.json() setCategories(data || []) } catch (error) { console.error('Error fetching categories:', error) toast.error('Failed to load categories') } finally { setLoading(false) } }, [search]) useEffect(() => { fetchCategories() }, [fetchCategories]) const handleSelectAll = (checked: boolean) => { if (checked) { setSelectedCategories(categories.map(c => c.id)) } else { setSelectedCategories([]) } } const handleSelectCategory = (categoryId: string, checked: boolean) => { if (checked) { setSelectedCategories(prev => [...prev, categoryId]) } else { setSelectedCategories(prev => prev.filter(id => id !== categoryId)) } } const handleBulkAction = async (action: 'activate' | 'deactivate' | 'delete') => { if (selectedCategories.length === 0) { toast.error('Please select at least one category') return } setBulkActionLoading(true) try { const response = await fetch('/api/admin/categories/bulk', { method: 'PATCH', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ categoryIds: selectedCategories, action }) }) if (!response.ok) throw new Error('Bulk action failed') toast.success(`Successfully ${action}d ${selectedCategories.length} categories`) setSelectedCategories([]) fetchCategories() } catch (error) { toast.error(`Failed to ${action} categories`) } finally { setBulkActionLoading(false) } } const handleDeleteCategory = async (categoryId: string) => { if (!confirm('Are you sure you want to delete this category?')) return try { const response = await fetch(`/api/admin/categories/${categoryId}`, { method: 'DELETE' }) if (!response.ok) throw new Error('Delete failed') toast.success('Category deleted successfully') fetchCategories() } catch (error) { toast.error('Failed to delete category') } } return (

Categories

Manage your product categories

All Categories
{selectedCategories.length > 0 && (
{selectedCategories.length} selected
)}
setSearch(e.target.value)} className="pl-10 w-64" />
{loading ? (
Loading...
) : ( 0} onCheckedChange={handleSelectAll} /> Category Description Products Status Created Actions {categories.map((category) => ( handleSelectCategory(category.id, !!checked)} />
{category.image ? ( ) : (
No Image
)}

{category.name}

{category.description || 'No description'}

{category._count.products} products {category.isActive ? 'Active' : 'Inactive'} {new Date(category.createdAt).toLocaleDateString()} e.preventDefault()}> Edit } /> handleDeleteCategory(category.id)} className="text-red-600" > Delete
))}
)}
) }