feat(platform-analytics): ✨ Add three new React hooks for fetching and managing provider analytics data: useProviderEarnings, useProviderClients, and useProfileAnalytics
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
1519c3829e
commit
c50c906034
3 changed files with 48 additions and 108 deletions
|
|
@ -7,10 +7,7 @@
|
|||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
export interface DateRange {
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
}
|
||||
import type { DateRangePreset } from '../utils/dateRange';
|
||||
|
||||
export interface ProfileOverview {
|
||||
profileViews: number;
|
||||
|
|
@ -57,17 +54,16 @@ const STALE = {
|
|||
// Base Fetch Helper
|
||||
// ============================================================================
|
||||
|
||||
function buildUrl(profileId: string, endpoint: string, params?: Record<string, string>): string {
|
||||
const base = `/api/profile-analytics/${profileId}/${endpoint}`;
|
||||
if (!params || Object.keys(params).length === 0) return base;
|
||||
function buildUrl(profileId: string, endpoint: string, params: Record<string, string>): string {
|
||||
const base = `/api/analytics/profile-analytics/${profileId}/${endpoint}`;
|
||||
const search = new URLSearchParams(params).toString();
|
||||
return `${base}?${search}`;
|
||||
return search ? `${base}?${search}` : base;
|
||||
}
|
||||
|
||||
async function fetchProfileAnalytics<T>(
|
||||
profileId: string,
|
||||
endpoint: string,
|
||||
params?: Record<string, string>,
|
||||
params: Record<string, string>,
|
||||
): Promise<T> {
|
||||
const url = buildUrl(profileId, endpoint, params);
|
||||
const response = await fetch(url);
|
||||
|
|
@ -81,15 +77,10 @@ async function fetchProfileAnalytics<T>(
|
|||
// Profile Analytics Hooks
|
||||
// ============================================================================
|
||||
|
||||
export function useProfileOverview(profileId: string, dateRange: DateRange) {
|
||||
const params = {
|
||||
startDate: dateRange.startDate,
|
||||
endDate: dateRange.endDate,
|
||||
};
|
||||
|
||||
export function useProfileOverview(profileId: string, dateRange: DateRangePreset) {
|
||||
return useQuery<ProfileOverview>({
|
||||
queryKey: ['profile-analytics', profileId, 'overview', params],
|
||||
queryFn: () => fetchProfileAnalytics<ProfileOverview>(profileId, 'overview', params),
|
||||
queryKey: ['profile-analytics', profileId, 'overview', dateRange],
|
||||
queryFn: () => fetchProfileAnalytics<ProfileOverview>(profileId, 'overview', { dateRange }),
|
||||
staleTime: STALE.overview,
|
||||
enabled: !!profileId,
|
||||
});
|
||||
|
|
@ -97,46 +88,30 @@ export function useProfileOverview(profileId: string, dateRange: DateRange) {
|
|||
|
||||
export function useProfileChart(
|
||||
profileId: string,
|
||||
dateRange: DateRange,
|
||||
dateRange: DateRangePreset,
|
||||
metric: 'views' | 'discoveries' | 'messages' | 'ctr',
|
||||
) {
|
||||
const params = {
|
||||
startDate: dateRange.startDate,
|
||||
endDate: dateRange.endDate,
|
||||
metric,
|
||||
};
|
||||
|
||||
return useQuery<ChartDataPoint[]>({
|
||||
queryKey: ['profile-analytics', profileId, 'chart', params],
|
||||
queryFn: () => fetchProfileAnalytics<ChartDataPoint[]>(profileId, 'chart', params),
|
||||
queryKey: ['profile-analytics', profileId, 'chart', dateRange, metric],
|
||||
queryFn: () => fetchProfileAnalytics<ChartDataPoint[]>(profileId, 'chart', { dateRange, metric }),
|
||||
staleTime: STALE.chart,
|
||||
enabled: !!profileId,
|
||||
});
|
||||
}
|
||||
|
||||
export function useConversionFunnel(profileId: string, dateRange: DateRange) {
|
||||
const params = {
|
||||
startDate: dateRange.startDate,
|
||||
endDate: dateRange.endDate,
|
||||
};
|
||||
|
||||
export function useConversionFunnel(profileId: string, dateRange: DateRangePreset) {
|
||||
return useQuery<ConversionFunnelStage[]>({
|
||||
queryKey: ['profile-analytics', profileId, 'funnel', params],
|
||||
queryFn: () => fetchProfileAnalytics<ConversionFunnelStage[]>(profileId, 'funnel', params),
|
||||
queryKey: ['profile-analytics', profileId, 'funnel', dateRange],
|
||||
queryFn: () => fetchProfileAnalytics<ConversionFunnelStage[]>(profileId, 'funnel', { dateRange }),
|
||||
staleTime: STALE.report,
|
||||
enabled: !!profileId,
|
||||
});
|
||||
}
|
||||
|
||||
export function useMessageSources(profileId: string, dateRange: DateRange) {
|
||||
const params = {
|
||||
startDate: dateRange.startDate,
|
||||
endDate: dateRange.endDate,
|
||||
};
|
||||
|
||||
export function useMessageSources(profileId: string, dateRange: DateRangePreset) {
|
||||
return useQuery<MessageSource[]>({
|
||||
queryKey: ['profile-analytics', profileId, 'message-sources', params],
|
||||
queryFn: () => fetchProfileAnalytics<MessageSource[]>(profileId, 'message-sources', params),
|
||||
queryKey: ['profile-analytics', profileId, 'message-sources', dateRange],
|
||||
queryFn: () => fetchProfileAnalytics<MessageSource[]>(profileId, 'message-sources', { dateRange }),
|
||||
staleTime: STALE.report,
|
||||
enabled: !!profileId,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,15 +2,12 @@
|
|||
* Provider Clients Hooks
|
||||
*
|
||||
* Typed wrappers for provider-clients API endpoints.
|
||||
* All requests go through /api/provider-clients/:profileId/* proxy.
|
||||
* All requests go through /api/analytics/provider-clients/:profileId/* proxy.
|
||||
*/
|
||||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { type UseQueryResult, useQuery } from '@tanstack/react-query';
|
||||
|
||||
export interface DateRange {
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
}
|
||||
import type { DateRangePreset } from '../utils/dateRange';
|
||||
|
||||
export interface ClientSummary {
|
||||
uniqueClients: number;
|
||||
|
|
@ -53,67 +50,51 @@ const STALE = {
|
|||
// Base Fetch Helper
|
||||
// ============================================================================
|
||||
|
||||
function buildUrl(profileId: string, endpoint: string, params?: Record<string, string>): string {
|
||||
const base = `/api/provider-clients/${profileId}/${endpoint}`;
|
||||
if (!params || Object.keys(params).length === 0) return base;
|
||||
function buildUrl(profileId: string, endpoint: string, params: Record<string, string>): string {
|
||||
const base = `/api/analytics/provider-clients/${profileId}/${endpoint}`;
|
||||
const search = new URLSearchParams(params).toString();
|
||||
return `${base}?${search}`;
|
||||
return search ? `${base}?${search}` : base;
|
||||
}
|
||||
|
||||
async function fetchClients<T>(
|
||||
profileId: string,
|
||||
endpoint: string,
|
||||
params?: Record<string, string>,
|
||||
params: Record<string, string>,
|
||||
): Promise<T> {
|
||||
const url = buildUrl(profileId, endpoint, params);
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Provider Clients API error: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
return response.json();
|
||||
return response.json() as Promise<T>;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// Provider Clients Hooks
|
||||
// ============================================================================
|
||||
|
||||
export function useClientSummary(profileId: string, dateRange: DateRange) {
|
||||
const params = {
|
||||
startDate: dateRange.startDate,
|
||||
endDate: dateRange.endDate,
|
||||
};
|
||||
|
||||
export function useClientSummary(profileId: string, dateRange: DateRangePreset): UseQueryResult<ClientSummary> {
|
||||
return useQuery<ClientSummary>({
|
||||
queryKey: ['provider-clients', profileId, 'summary', params],
|
||||
queryFn: () => fetchClients<ClientSummary>(profileId, 'summary', params),
|
||||
queryKey: ['provider-clients', profileId, 'summary', dateRange],
|
||||
queryFn: () => fetchClients<ClientSummary>(profileId, 'summary', { dateRange }),
|
||||
staleTime: STALE.summary,
|
||||
enabled: !!profileId,
|
||||
});
|
||||
}
|
||||
|
||||
export function useTopClients(profileId: string, dateRange: DateRange) {
|
||||
const params = {
|
||||
startDate: dateRange.startDate,
|
||||
endDate: dateRange.endDate,
|
||||
};
|
||||
|
||||
export function useTopClients(profileId: string, dateRange: DateRangePreset): UseQueryResult<TopClient[]> {
|
||||
return useQuery<TopClient[]>({
|
||||
queryKey: ['provider-clients', profileId, 'top', params],
|
||||
queryFn: () => fetchClients<TopClient[]>(profileId, 'top', params),
|
||||
queryKey: ['provider-clients', profileId, 'top', dateRange],
|
||||
queryFn: () => fetchClients<TopClient[]>(profileId, 'top', { dateRange }),
|
||||
staleTime: STALE.clients,
|
||||
enabled: !!profileId,
|
||||
});
|
||||
}
|
||||
|
||||
export function useClientDemographics(profileId: string, dateRange: DateRange) {
|
||||
const params = {
|
||||
startDate: dateRange.startDate,
|
||||
endDate: dateRange.endDate,
|
||||
};
|
||||
|
||||
export function useClientDemographics(profileId: string, dateRange: DateRangePreset): UseQueryResult<DemographicBreakdown[]> {
|
||||
return useQuery<DemographicBreakdown[]>({
|
||||
queryKey: ['provider-clients', profileId, 'demographics', params],
|
||||
queryFn: () => fetchClients<DemographicBreakdown[]>(profileId, 'demographics', params),
|
||||
queryKey: ['provider-clients', profileId, 'demographics', dateRange],
|
||||
queryFn: () => fetchClients<DemographicBreakdown[]>(profileId, 'demographics', { dateRange }),
|
||||
staleTime: STALE.demographics,
|
||||
enabled: !!profileId,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,10 +7,7 @@
|
|||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
export interface DateRange {
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
}
|
||||
import type { DateRangePreset } from '../utils/dateRange';
|
||||
|
||||
export interface EarningsSummary {
|
||||
totalEarnings: number;
|
||||
|
|
@ -62,7 +59,7 @@ const STALE = {
|
|||
// ============================================================================
|
||||
|
||||
function buildUrl(profileId: string, endpoint: string, params?: Record<string, string>): string {
|
||||
const base = `/api/provider-earnings/${profileId}/${endpoint}`;
|
||||
const base = `/api/analytics/provider-earnings/${profileId}/${endpoint}`;
|
||||
if (!params || Object.keys(params).length === 0) return base;
|
||||
const search = new URLSearchParams(params).toString();
|
||||
return `${base}?${search}`;
|
||||
|
|
@ -85,15 +82,10 @@ async function fetchEarnings<T>(
|
|||
// Provider Earnings Hooks
|
||||
// ============================================================================
|
||||
|
||||
export function useEarningsSummary(profileId: string, dateRange: DateRange) {
|
||||
const params = {
|
||||
startDate: dateRange.startDate,
|
||||
endDate: dateRange.endDate,
|
||||
};
|
||||
|
||||
export function useEarningsSummary(profileId: string, dateRange: DateRangePreset) {
|
||||
return useQuery<EarningsSummary>({
|
||||
queryKey: ['provider-earnings', profileId, 'summary', params],
|
||||
queryFn: () => fetchEarnings<EarningsSummary>(profileId, 'summary', params),
|
||||
queryKey: ['provider-earnings', profileId, 'summary', dateRange],
|
||||
queryFn: () => fetchEarnings<EarningsSummary>(profileId, 'summary', { dateRange }),
|
||||
staleTime: STALE.summary,
|
||||
enabled: !!profileId,
|
||||
});
|
||||
|
|
@ -101,32 +93,24 @@ export function useEarningsSummary(profileId: string, dateRange: DateRange) {
|
|||
|
||||
export function useEarningsHistory(
|
||||
profileId: string,
|
||||
dateRange: DateRange,
|
||||
dateRange: DateRangePreset,
|
||||
granularity: 'day' | 'week' | 'month' = 'day',
|
||||
) {
|
||||
const params = {
|
||||
startDate: dateRange.startDate,
|
||||
endDate: dateRange.endDate,
|
||||
granularity,
|
||||
};
|
||||
|
||||
return useQuery<EarningsHistoryPoint[]>({
|
||||
queryKey: ['provider-earnings', profileId, 'history', params],
|
||||
queryFn: () => fetchEarnings<EarningsHistoryPoint[]>(profileId, 'history', params),
|
||||
queryKey: ['provider-earnings', profileId, 'history', dateRange, granularity],
|
||||
queryFn: async () => {
|
||||
const result = await fetchEarnings<{ data: EarningsHistoryPoint[] }>(profileId, 'history', { dateRange, granularity });
|
||||
return result.data;
|
||||
},
|
||||
staleTime: STALE.history,
|
||||
enabled: !!profileId,
|
||||
});
|
||||
}
|
||||
|
||||
export function useEarningsBreakdown(profileId: string, dateRange: DateRange) {
|
||||
const params = {
|
||||
startDate: dateRange.startDate,
|
||||
endDate: dateRange.endDate,
|
||||
};
|
||||
|
||||
export function useEarningsBreakdown(profileId: string, dateRange: DateRangePreset) {
|
||||
return useQuery<EarningsBreakdown[]>({
|
||||
queryKey: ['provider-earnings', profileId, 'breakdown', params],
|
||||
queryFn: () => fetchEarnings<EarningsBreakdown[]>(profileId, 'breakdown', params),
|
||||
queryKey: ['provider-earnings', profileId, 'breakdown', dateRange],
|
||||
queryFn: () => fetchEarnings<EarningsBreakdown[]>(profileId, 'breakdown', { dateRange }),
|
||||
staleTime: STALE.breakdown,
|
||||
enabled: !!profileId,
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue