Skip to main content

Item Management Hooks

Hooks for managing directory items: company associations, audit history, deleted item recovery, featured item sections, and sponsor ad management.

useItemCompany

Manages the association between items and companies. Provides fetching, assigning, and removing company assignments with optimistic updates and toast notifications.

useItemCompany(options: UseItemCompanyOptions): UseItemCompanyReturn

Options

OptionTypeDefaultDescription
itemSlugstring--The item slug to manage (required)
enabledbooleantrueWhether to fetch the current assignment

Return Values

PropertyTypeDescription
companyCompany | nullCurrently assigned company
isLoadingbooleanWhether the company assignment is loading
isAssigningbooleanWhether an assign operation is in progress
isRemovingbooleanWhether a remove operation is in progress
assignCompany(companyId: string) => Promise<boolean>Assign a company; returns success status
removeCompany() => Promise<boolean>Remove the company assignment
refetch() => voidRe-fetch the current assignment

Query Configuration

SettingValue
Query key['item-company', itemSlug]
Stale time5 minutes
GC time10 minutes
Retry2 times
import { useItemCompany } from '@/hooks/use-item-company';

function CompanyAssignment({ itemSlug }) {
const { company, isLoading, assignCompany, removeCompany, isAssigning } =
useItemCompany({ itemSlug });

if (isLoading) return <Spinner />;

return (
<div>
{company ? (
<div>
<p>Company: {company.name}</p>
<button onClick={removeCompany}>Remove</button>
</div>
) : (
<CompanySelector
onSelect={(id) => assignCompany(id)}
disabled={isAssigning}
/>
)}
</div>
);
}

useItemHistory

Fetches paginated audit history for an item, including status changes, field modifications, and performer information.

useItemHistory(params: UseItemHistoryParams): UseQueryResult<ItemHistoryData>

Parameters

ParamTypeDefaultDescription
itemIdstring--Item ID to fetch history for (required)
pagenumber1Page number
limitnumber20Items per page
actionFilterItemAuditActionValues[]--Filter by specific action types
enabledbooleantrueWhether to enable the query

ItemAuditLogEntry Shape

FieldTypeDescription
idstringLog entry ID
itemIdstringAssociated item ID
itemNamestringItem name at time of action
actionItemAuditActionValuesAction type (create, update, approve, reject, etc.)
previousStatusstring | nullStatus before the action
newStatusstring | nullStatus after the action
changesRecord<string, { old, new }>Field-level change details
performedBystring | nullUser ID who performed the action
performedByNamestring | nullDisplay name of the performer
notesstring | nullOptional notes about the action
createdAtstringISO timestamp of the action
performer{ id, email } | nullPerformer user data

Query Configuration

SettingValue
Query key['admin', 'items', 'history', itemId, { page, actionFilter }]
Stale time30 seconds
Placeholder dataPrevious page data (smooth pagination)
import { useItemHistory } from '@/hooks/use-item-history';

function ItemAuditLog({ itemId }) {
const [page, setPage] = useState(1);
const { data, isLoading } = useItemHistory({ itemId, page, limit: 10 });

if (isLoading) return <Spinner />;

return (
<div>
{data?.logs.map((entry) => (
<div key={entry.id}>
<span>{entry.action}</span>
<span>{entry.performedByName}</span>
<time>{new Date(entry.createdAt).toLocaleString()}</time>
</div>
))}
<Pagination
page={page}
totalPages={data?.totalPages ?? 1}
onChange={setPage}
/>
</div>
);
}

useDeletedClientItems

Manages deleted (trashed) client items with pagination and restore functionality.

useDeletedClientItems(params?: UseDeletedClientItemsParams): UseDeletedClientItemsReturn

Parameters

ParamTypeDefaultDescription
pagenumber1Page number
limitnumber10Items per page

Return Values

PropertyTypeDescription
itemsClientSubmissionData[]Deleted items for the current page
totalnumberTotal number of deleted items
pagenumberCurrent page
totalPagesnumberTotal pages available
isLoadingbooleanInitial loading state
isFetchingbooleanBackground refetch state
restoringItemIdstring | nullID of item currently being restored
errorError | nullFetch error
restoreItem(id: string) => Promise<boolean>Restore a deleted item
refetch() => voidRe-fetch deleted items
refreshData() => voidInvalidate all deleted item caches
import { useDeletedClientItems } from '@/hooks/use-deleted-client-items';

function TrashBin() {
const { items, isLoading, restoreItem, restoringItemId } =
useDeletedClientItems({ page: 1, limit: 20 });

return (
<div>
{items.map((item) => (
<div key={item.id}>
<span>{item.name}</span>
<button
onClick={() => restoreItem(item.id)}
disabled={restoringItemId === item.id}
>
{restoringItemId === item.id ? 'Restoring...' : 'Restore'}
</button>
</div>
))}
</div>
);
}

useFeaturedItemsSection

Fetches and filters featured items for display sections. Sorts by featured order and filters by active status.

useFeaturedItemsSection(props?: UseFeaturedItemsSectionProps): UseFeaturedItemsSectionReturn

Parameters

ParamTypeDefaultDescription
limitnumber6Maximum number of items to display
enabledbooleantrueWhether to enable fetching

Return Values

PropertyTypeDescription
featuredItemsFeaturedItem[]Active featured items sorted by order, limited
isLoadingbooleanLoading state
isErrorbooleanWhether an error occurred
errorstring | nullError message
refetch() => voidRe-fetch featured items
invalidateFeaturedItems() => voidInvalidate cache
import { useFeaturedItemsSection } from '@/hooks/use-feature-items-section';

function FeaturedSection() {
const { featuredItems, isLoading } = useFeaturedItemsSection({ limit: 8 });

if (isLoading) return <FeaturedSkeleton />;
if (!featuredItems.length) return null;

return (
<section>
<h2>Featured</h2>
<div className="grid grid-cols-4 gap-4">
{featuredItems.map((item) => (
<FeaturedCard key={item.slug} item={item} />
))}
</div>
</section>
);
}

useUserSponsorAds

Full-featured hook for managing user sponsor ads with CRUD operations, filtering, pagination, and statistics.

useUserSponsorAds(options?: UseUserSponsorAdsOptions): UseUserSponsorAdsReturn

Options

OptionTypeDefaultDescription
pagenumber1Initial page
limitnumber10Items per page
statusSponsorAdStatus--Filter by status
interval'weekly' | 'monthly'--Filter by billing interval
searchstring""Search query (debounced)

Return Values

CategoryPropertyTypeDescription
DatasponsorAdsSponsorAd[]Current page of sponsor ads
DatastatsSponsorAdStatsOverview, interval, and revenue stats
LoadingisLoadingbooleanInitial load
LoadingisCreatingbooleanCreating a new ad
LoadingisCancellingbooleanCancelling an ad
LoadingisPayingNowbooleanProcessing payment
LoadingisRenewingbooleanProcessing renewal
PaginationcurrentPagenumberCurrent page
PaginationtotalPagesnumberTotal pages
PaginationnextPage / prevPage() => voidPage navigation
ActionscreateSponsorAd(input) => Promise<SponsorAd | null>Create new sponsor ad
ActionscancelSponsorAd(id, reason?) => Promise<boolean>Cancel a sponsor ad
ActionspayNow(id) => Promise<{ checkoutUrl } | null>Get checkout URL
ActionsrenewSponsorship(id) => Promise<{ checkoutUrl } | null>Get renewal URL
FilterssetStatusFilter(status) => voidUpdate status filter
FilterssetIntervalFilter(interval) => voidUpdate interval filter
FilterssetSearch(search) => voidUpdate search (debounced)
import { useUserSponsorAds } from '@/hooks/use-user-sponsor-ads';

function SponsorAdManager() {
const {
sponsorAds,
stats,
isLoading,
createSponsorAd,
cancelSponsorAd,
setStatusFilter,
currentPage,
nextPage,
} = useUserSponsorAds({ limit: 10 });

return (
<div>
<p>Active ads: {stats.overview.active}</p>
<select onChange={(e) => setStatusFilter(e.target.value)}>
<option value="">All</option>
<option value="active">Active</option>
<option value="pending">Pending</option>
</select>
{sponsorAds.map((ad) => (
<SponsorAdCard key={ad.id} ad={ad} onCancel={cancelSponsorAd} />
))}
</div>
);
}

Summary Table

HookPurposeSource File
useItemCompanyItem-company association CRUDuse-item-company.ts
useItemHistoryItem audit log with paginationuse-item-history.ts
useDeletedClientItemsTrashed item management and restoreuse-deleted-client-items.ts
useFeaturedItemsSectionFeatured items display sectionuse-feature-items-section.ts
useUserSponsorAdsSponsor ad CRUD, filtering, statsuse-user-sponsor-ads.ts