Skip to main content

useAdminCompanies

Overview

useAdminCompanies is a React hook for managing company records in the admin panel. It provides paginated listing with search, status filtering, and sorting, along with full CRUD mutations and aggregate statistics (total, active, inactive). The file also exports a useCompany companion hook for fetching a single company by ID.

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

Signature / Parameters

useAdminCompanies

function useAdminCompanies(options?: UseAdminCompaniesOptions): UseAdminCompaniesReturn

UseAdminCompaniesOptions

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

CompaniesListOptions

ParameterTypeDescription
pagenumberCurrent page number
limitnumberItems per page
searchstringSearch term
status'active' | 'inactive'Filter by company status
sortBy'name' | 'createdAt' | 'updatedAt'Field to sort by
sortOrder'asc' | 'desc'Sort direction

Return Values

UseAdminCompaniesReturn

Data

PropertyTypeDescription
companiesCompany[]Array of companies for the current page
statsCompanyStatsAggregate counts
totalnumberTotal companies matching filters
pagenumberCurrent page (defaults to 1)
totalPagesnumberTotal pages (defaults to 1)
limitnumberItems per page (defaults to 10)

CompanyStats

interface CompanyStats {
total: number;
active: number;
inactive: number;
}

Loading States

PropertyTypeDescription
isLoadingbooleantrue on initial load
isSubmittingbooleantrue when any mutation is pending

Actions

MethodSignatureDescription
createCompany(data: CreateCompanyRequest) => Promise<boolean>Create a new company
updateCompany(id: string, data: UpdateCompanyRequest) => Promise<boolean>Update an existing company
deleteCompany(id: string) => Promise<boolean>Delete a company

Request Types

interface CreateCompanyRequest {
name: string;
website?: string;
domain?: string;
slug?: string;
status?: 'active' | 'inactive';
}

interface UpdateCompanyRequest extends Partial<CreateCompanyRequest> {
id: string;
}

Utility

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

Companion Hook: useCompany

Fetches a single company by ID.

function useCompany(options: UseCompanyOptions): UseCompanyReturn
OptionTypeDescription
idstringCompany ID to fetch
enabledbooleanWhether to run the query

Returns:

{
company: Company | null;
isLoading: boolean;
error: Error | null;
refetch: () => void;
}

Implementation Details

  • Query caching: 5-minute staleTime, 10-minute gcTime, 3 retries on failure.
  • Placeholder data: keepPreviousData ensures smooth pagination transitions.
  • URL building: Uses apiUtils.buildUrl to construct query strings, mapping search to the q query parameter.
  • Stats derivation: Stats are derived from the API response meta object (meta.total, meta.activeCount, meta.inactiveCount) rather than from a separate endpoint.
  • Cache invalidation: Mutations invalidate the entire ['admin', 'companies'] query key family.
  • Toast notifications: sonner toasts fire on mutation success and error.
  • URL encoding: Company IDs are URI-encoded in API paths via encodeURIComponent.

Query Keys

const QUERY_KEYS = {
companies: ['admin', 'companies'],
companiesList: (params) => ['admin', 'companies', 'list', params],
company: (id) => ['admin', 'companies', 'detail', id],
};

Usage Examples

Company listing page

import { useAdminCompanies } from '@/hooks/use-admin-companies';

function CompaniesPage() {
const [page, setPage] = useState(1);
const [search, setSearch] = useState('');

const {
companies,
stats,
totalPages,
isLoading,
} = useAdminCompanies({
params: {
page,
limit: 20,
search: search || undefined,
sortBy: 'name',
sortOrder: 'asc',
},
});

return (
<div>
<SearchInput value={search} onChange={setSearch} />
<p>Total: {stats.total} | Active: {stats.active} | Inactive: {stats.inactive}</p>
<CompanyTable companies={companies} />
<Pagination current={page} total={totalPages} onChange={setPage} />
</div>
);
}

Creating a company

const { createCompany, isSubmitting } = useAdminCompanies();

const handleCreate = async () => {
const success = await createCompany({
name: 'Acme Corp',
website: 'https://acme.com',
domain: 'acme.com',
status: 'active',
});
};

Fetching a single company

import { useCompany } from '@/hooks/use-admin-companies';

function CompanyDetail({ companyId }: { companyId: string }) {
const { company, isLoading } = useCompany({ id: companyId });

if (isLoading) return <Spinner />;
return <CompanyCard company={company} />;
}