import { useState, useEffect, useCallback, useRef } from 'react'; import { toast } from 'sonner'; import { Plus, Pencil, Trash2 } from 'lucide-react'; import { api } from '@/api.js'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { InputDialog } from '@/components/ui/input-dialog'; import { AlertDialog, AlertDialogContent, AlertDialogHeader, AlertDialogTitle, AlertDialogDescription, AlertDialogFooter, AlertDialogCancel, AlertDialogAction, } from '@/components/ui/alert-dialog'; import { buttonVariants } from '@/components/ui/button'; import { cn } from '@/lib/utils'; // ─── CategoriesPage ─────────────────────────────────────────────────────────── export default function CategoriesPage() { const [categories, setCategories] = useState([]); const [loading, setLoading] = useState(true); const [newName, setNewName] = useState(''); const [adding, setAdding] = useState(false); const addInputRef = useRef(null); // Rename dialog state const [renameTarget, setRenameTarget] = useState(null); // { id, name } const [renaming, setRenaming] = useState(false); // Delete dialog state const [deleteTarget, setDeleteTarget] = useState(null); // { id, name } const [deleting, setDeleting] = useState(false); const load = useCallback(async () => { try { const cats = await api.categories(); setCategories(cats); } catch (err) { toast.error(err.message); } finally { setLoading(false); } }, []); useEffect(() => { load(); }, [load]); // ── Add ────────────────────────────────────────────────────────────────────── async function handleAdd(e) { e.preventDefault(); const trimmed = newName.trim(); if (!trimmed) { toast.error('Enter a category name'); addInputRef.current?.focus(); return; } setAdding(true); try { await api.createCategory({ name: trimmed }); toast.success(`"${trimmed}" added`); setNewName(''); addInputRef.current?.focus(); load(); } catch (err) { toast.error(err.message); } finally { setAdding(false); } } // ── Rename ─────────────────────────────────────────────────────────────────── function openRename(cat) { setRenameTarget(cat); } async function handleRename(name) { setRenaming(true); try { await api.updateCategory(renameTarget.id, { name }); toast.success('Category renamed'); setRenameTarget(null); load(); } catch (err) { toast.error(err.message); } finally { setRenaming(false); } } // ── Delete ─────────────────────────────────────────────────────────────────── function openDelete(cat) { setDeleteTarget(cat); } async function handleDelete() { setDeleting(true); try { await api.deleteCategory(deleteTarget.id); toast.success(`"${deleteTarget.name}" deleted`); setDeleteTarget(null); load(); } catch (err) { toast.error(err.message); } finally { setDeleting(false); } } // ── Render ─────────────────────────────────────────────────────────────────── return (
{categories.length} categories