Skip to main content

useAdminClients

Overview

useAdminClients is a React hook for managing client profiles in the admin panel. It provides paginated client listing with rich filtering (by status, plan, account type, provider, and date ranges), CRUD mutations, and aggregated client statistics including growth metrics. The file also exports companion hooks: useClient for single-client fetching, useClientMutations for mutation-only usage, and useClientStats for stats-only access.

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

Signature / Parameters

useAdminClients

function useAdminClients(options?: UseAdminClientsOptions): UseAdminClientsReturn

UseAdminClientsOptions

PropertyTypeDefaultDescription
paramsClientDashboardOptions{}Filtering, pagination, sorting, and date params
enabledbooleantrueWhether to enable the query

ClientDashboardOptions

ParameterTypeDescription
pagenumberCurrent page number
limitnumberItems per page
searchstringSearch term for name/email matching
statusstringFilter by client status
planstringFilter by subscription plan
accountTypestringFilter by account type
providerstringFilter by auth provider
createdAfterstringISO date string -- created after this date
createdBeforestringISO date string -- created before this date
updatedAfterstringISO date string -- updated after this date
updatedBeforestringISO date string -- updated before this date
sortBystringField to sort by
sortOrderstring'asc' or 'desc'

Return Values

UseAdminClientsReturn

Data

PropertyTypeDescription
clientsClientProfileWithAuth[]Array of client profiles for the current page
statsClientStatsAggregated client statistics
totalnumberTotal clients matching filters
pagenumberCurrent page
totalPagesnumberTotal pages
limitnumberItems per page

ClientStats structure

interface ClientStats {
overview: { total: number; active: number; inactive: number; suspended: number; trial: number };
byProvider: Record<string, number>;
byPlan: Record<string, number>;
byAccountType: Record<string, number>;
byStatus: Record<string, number>;
activity: { newThisWeek: number; newThisMonth: number; activeThisWeek: number; activeThisMonth: number };
growth: { weeklyGrowth: number; monthlyGrowth: number };
}

Loading States

PropertyTypeDescription
isLoadingbooleantrue on initial load
isSubmittingbooleantrue when any mutation is pending

Actions

MethodSignatureDescription
createClient(data: CreateClientRequest) => Promise<boolean>Create a new client profile
updateClient(id: string, data: UpdateClientRequest) => Promise<boolean>Update an existing client
deleteClient(id: string) => Promise<boolean>Delete a client

Utility

MethodSignatureDescription
refetch() => voidRe-execute the dashboard query
refreshData() => voidInvalidate all client queries to force fresh data

Companion Hooks

useClient

Fetches a single client by ID.

function useClient(options: UseClientOptions): UseClientReturn
OptionTypeDescription
idstringClient ID to fetch
enabledbooleanWhether to run the query

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

useClientMutations

Provides create/update/delete mutations without fetching data. Useful for modal forms.

function useClientMutations(): UseClientMutationsReturn

Returns: { createClient, updateClient, deleteClient, isSubmitting }

useClientStats

Fetches only the stats portion of the dashboard data (uses limit: 1 to minimize payload).

function useClientStats(options?: UseClientStatsOptions): UseClientStatsReturn

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

Implementation Details

  • Query caching: 5-minute staleTime, 10-minute gcTime, 3 retries on failure.
  • Placeholder data: keepPreviousData is used for smooth pagination transitions.
  • Cache invalidation: All mutations invalidate the entire ['admin', 'clients'] query key family via queryClient.invalidateQueries.
  • Toast notifications: Success and error toasts from sonner are triggered automatically on mutation completion.
  • URL encoding: Client IDs are URI-encoded in API calls via encodeURIComponent for safe handling of special characters.

Query Keys

const QUERY_KEYS = {
clients: ['admin', 'clients'],
clientsDashboard: (params) => ['admin', 'clients', 'dashboard', params],
client: (id) => ['admin', 'clients', 'detail', id],
clientsStats: () => ['admin', 'clients', 'stats'],
};

Usage Examples

Client dashboard with filtering

import { useAdminClients } from '@/hooks/use-admin-clients';

function ClientsPage() {
const [page, setPage] = useState(1);
const [statusFilter, setStatusFilter] = useState('');

const {
clients,
stats,
total,
totalPages,
isLoading,
} = useAdminClients({
params: {
page,
limit: 25,
status: statusFilter || undefined,
sortBy: 'createdAt',
sortOrder: 'desc',
},
});

return (
<div>
<ClientStatsCards stats={stats} />
<ClientTable clients={clients} />
<Pagination current={page} total={totalPages} onChange={setPage} />
</div>
);
}

Fetching a single client

import { useClient } from '@/hooks/use-admin-clients';

function ClientDetail({ clientId }: { clientId: string }) {
const { client, isLoading, error } = useClient({ id: clientId });

if (isLoading) return <Spinner />;
if (error) return <ErrorMessage error={error} />;

return <ClientProfile client={client} />;
}

Mutation-only usage in a modal

import { useClientMutations } from '@/hooks/use-admin-clients';

function CreateClientModal({ onClose }: { onClose: () => void }) {
const { createClient, isSubmitting } = useClientMutations();

const handleSubmit = async (formData: CreateClientRequest) => {
const success = await createClient(formData);
if (success) onClose();
};

return <ClientForm onSubmit={handleSubmit} isLoading={isSubmitting} />;
}