Skip to main content

useAdminCategories

Overview

useAdminCategories is a React hook for managing categories in the admin panel. It provides paginated category listing with sorting, CRUD mutations (including soft and hard delete), and aggregate data. The file also exports several companion hooks: useCategory for single-category access, useCategoryMutations for mutation-only usage, useAllCategories for unpaginated access, and useAllCategoriesFormatted for a formatted variant.

Source: template/hooks/use-admin-categories.ts

Signature / Parameters

useAdminCategories

function useAdminCategories(options?: UseAdminCategoriesOptions): UseAdminCategoriesReturn

UseAdminCategoriesOptions

PropertyTypeDefaultDescription
paramsCategoryListOptions{}Filtering, pagination, sorting
enabledbooleantrueWhether to enable the query

CategoryListOptions

ParameterTypeDescription
includeInactivebooleanInclude inactive categories in results
pagenumberCurrent page number
limitnumberItems per page
sortBystringField to sort by
sortOrder'asc' | 'desc'Sort direction

Return Values

UseAdminCategoriesReturn

Data

PropertyTypeDescription
categoriesCategoryWithCount[]Array of categories with associated item counts
totalnumberTotal categories matching filters
pagenumberCurrent page (defaults to 1)
totalPagesnumberTotal pages (defaults to 1)
limitnumberItems per page (defaults to 10)

Loading States

PropertyTypeDescription
isLoadingbooleantrue on initial load
isSubmittingbooleantrue when any mutation is pending

Actions

MethodSignatureDescription
createCategory(data: CreateCategoryRequest) => Promise<boolean>Create a new category
updateCategory(id: string, data: UpdateCategoryRequest) => Promise<boolean>Update an existing category
deleteCategory(id: string, hard?: boolean) => Promise<boolean>Delete a category. Pass hard=true for permanent deletion.

Utility

MethodSignatureDescription
refetch() => voidRe-execute the categories list query
refreshData() => voidInvalidate all category queries for fresh data

Companion Hooks

useCategory

Fetches a single category by ID.

function useCategory(options: UseCategoryOptions): UseCategoryReturn
OptionTypeDescription
idstringCategory ID to fetch
enabledbooleanWhether to run the query

Returns: { category: CategoryData | null, isLoading: boolean, error: Error | null, refetch: () => void }

useCategoryMutations

Provides create/update/delete mutations without fetching data.

function useCategoryMutations(): UseCategoryMutationsReturn

Returns: { createCategory, updateCategory, deleteCategory, isSubmitting }

useAllCategories

Fetches all categories without pagination from the /api/admin/categories/all endpoint.

function useAllCategories(): UseQueryResult<CategoryData[]>

Returns a standard TanStack useQuery result with data as CategoryData[].

useAllCategoriesFormatted

Wraps useAllCategories with a formatted response.

function useAllCategoriesFormatted(): {
allCategories: CategoryData[];
isLoading: boolean;
error: Error | null;
refetch: () => void;
}

Implementation Details

  • Query caching: 5-minute staleTime, 10-minute gcTime, 3 retries on failure.
  • Soft vs. hard delete: The deleteCategory action supports a hard parameter. When false (default), the category is soft-deleted (deactivated). When true, the ?hard=true query parameter is appended and the category is permanently removed.
  • Cache invalidation: All mutations invalidate the entire ['admin', 'categories'] query key family, which covers the paginated list, all-categories endpoint, and individual category queries.
  • Toast notifications: sonner toasts fire on mutation success and error.

Query Keys

const QUERY_KEYS = {
categories: ['admin', 'categories'],
categoriesList: (params) => ['admin', 'categories', 'list', params],
allCategories: () => ['admin', 'categories', 'all'],
category: (id) => ['admin', 'categories', 'detail', id],
};

Usage Examples

Category management page

import { useAdminCategories } from '@/hooks/use-admin-categories';

function CategoriesPage() {
const {
categories,
total,
isLoading,
createCategory,
deleteCategory,
isSubmitting,
} = useAdminCategories({
params: { includeInactive: true, sortBy: 'name', sortOrder: 'asc' },
});

const handleCreate = async () => {
await createCategory({ name: 'New Category', slug: 'new-category' });
};

const handleSoftDelete = async (id: string) => {
await deleteCategory(id); // soft delete
};

const handleHardDelete = async (id: string) => {
await deleteCategory(id, true); // permanent delete
};

return (
<div>
<p>Total categories: {total}</p>
<CategoryList categories={categories} />
</div>
);
}

Loading all categories for a select dropdown

import { useAllCategoriesFormatted } from '@/hooks/use-admin-categories';

function CategorySelect({ value, onChange }) {
const { allCategories, isLoading } = useAllCategoriesFormatted();

return (
<select value={value} onChange={(e) => onChange(e.target.value)} disabled={isLoading}>
<option value="">All Categories</option>
{allCategories.map((cat) => (
<option key={cat.id} value={cat.id}>{cat.name}</option>
))}
</select>
);
}

Mutation-only usage in a dialog

import { useCategoryMutations } from '@/hooks/use-admin-categories';

function EditCategoryDialog({ category, onClose }) {
const { updateCategory, isSubmitting } = useCategoryMutations();

const handleSave = async (data: UpdateCategoryRequest) => {
const success = await updateCategory(category.id, data);
if (success) onClose();
};

return <CategoryForm onSubmit={handleSave} isLoading={isSubmitting} />;
}
  • useAdminItems -- Item management; items belong to categories.
  • useAdminFilters -- Unified filter state management including multi-select category filters.
  • useAdminStats -- Platform-wide dashboard statistics.