/** * Intelligence API — wraps customer-api GET /intelligence?type=… * * Single endpoint, discriminated by `type`. Used by the dashboard statistics * (today_kpis, kpi_timeseries, analytics_overview/_errors/_timeseries) and * the new Intelligence page (product_demand, query_phrase, intent_theme). * * (c) 2026 TWWIM UG. All rights reserved. (www.twwim.com) */ import { apiClient } from '../../ApiClient'; import { INTELLIGENCE_GET } from '@archer/api-interface/endpoints/customer-api'; export type IntelligenceType = | 'analytics_overview' | 'analytics_timeseries' | 'analytics_errors' | 'product_demand' | 'query_phrase' | 'intent_theme' | 'today_kpis' | 'kpi_timeseries'; export type IntelligenceGranularity = 'hour' | 'day' | 'month' | 'year'; export type ProductDemandSortBy = 'demand' | 'oos'; export interface IntelligenceQuery { type: IntelligenceType; tenantId: string; startDate?: Date; endDate?: Date; granularity?: IntelligenceGranularity; limit?: number; gapOnly?: boolean; sortBy?: ProductDemandSortBy; } export interface IntelligenceResponse { type: IntelligenceType; data: T; } export interface AnalyticsOverviewData { totalCommands: number; successCount: number; failureCount: number; successRate: number; activeTenants: number; avgProcessingMs: number } export interface AnalyticsTimeseriesPoint { period: string; total: number; success: number; failure: number; voice: number; text: number } export interface AnalyticsErrorEntry { errorType: string; count: number; percentage: number } export interface ProductDemandEntry { productId: string; productName: string | null; demandHits: number; oosHits: number; lastActiveAt: string | null } export interface QueryPhraseEntry { phraseHash: string; sampleText: string | null; hitCount: number; gapCount: number; lastSeenAt: string | null } export interface IntentThemeEntry { themeUuid: string; themeCode: string; themeLabel: string; hitCount: number; percentage: number } export interface TodayKpisData { commands: number; suggestedProducts: number; visits: number; revenueCents: number } export interface KpiTimeseriesPoint { period: string; visits: number; commands: number; suggestedProducts: number; revenueCents: number } function toParams(q: IntelligenceQuery): Record { const p: Record = { type: q.type, tenantId: q.tenantId }; if (q.startDate) p.startDate = q.startDate.toISOString(); if (q.endDate) p.endDate = q.endDate.toISOString(); if (q.granularity) p.granularity = q.granularity; if (q.limit !== undefined) p.limit = String(q.limit); if (q.gapOnly !== undefined) p.gapOnly = String(q.gapOnly); if (q.sortBy !== undefined) p.sortBy = q.sortBy; return p; } export const intelligenceApi = { fetch(q: IntelligenceQuery): Promise> { return apiClient.get>(INTELLIGENCE_GET.path, { params: toParams(q) }); }, today(tenantId: string, opts?: { startDate?: Date; endDate?: Date }) { return intelligenceApi.fetch({ type: 'today_kpis', tenantId, ...opts }); }, kpiTimeseries(tenantId: string, granularity: IntelligenceGranularity, opts?: { startDate?: Date; endDate?: Date }) { return intelligenceApi.fetch({ type: 'kpi_timeseries', tenantId, granularity, ...opts }); }, analyticsOverview(tenantId: string, opts?: { startDate?: Date; endDate?: Date }) { return intelligenceApi.fetch({ type: 'analytics_overview', tenantId, ...opts }); }, analyticsErrors(tenantId: string, opts?: { startDate?: Date; endDate?: Date }) { return intelligenceApi.fetch({ type: 'analytics_errors', tenantId, ...opts }); }, analyticsTimeseries(tenantId: string, granularity: IntelligenceGranularity, opts?: { startDate?: Date; endDate?: Date }) { return intelligenceApi.fetch({ type: 'analytics_timeseries', tenantId, granularity, ...opts }); }, productDemand(tenantId: string, opts?: { startDate?: Date; endDate?: Date; limit?: number; sortBy?: ProductDemandSortBy }) { return intelligenceApi.fetch({ type: 'product_demand', tenantId, ...opts }); }, queryPhrase(tenantId: string, opts?: { startDate?: Date; endDate?: Date; limit?: number; gapOnly?: boolean }) { return intelligenceApi.fetch({ type: 'query_phrase', tenantId, ...opts }); }, intentTheme(tenantId: string, opts?: { startDate?: Date; endDate?: Date }) { return intelligenceApi.fetch({ type: 'intent_theme', tenantId, ...opts }); }, };