/** * Shared types, bot registry and label helpers for the Bot Analytics screen * (split out of the former 1,758-line dashboard-analytics.tsx — P2-2.1). */ import { botLogoUrl, getBotLogos } from '../../lib/bot-logos'; import { __, sprintf } from '../../lib/i18n'; export interface BotVisit { bot_name: string; date: string; visits: number; } export interface BotSummary { bot_name: string; total_visits: number; // Explicitly a number, not a string previous_visits?: number; // Visits in the previous period percentage_change?: number; // Percentage change vs previous period logo: string; } export interface BotStat { bot_name: string; impressions: number; clicks: number; ctr: number; trend: number; } export type TimeRangeType = | '24hours' | '7days' | '14days' | '30days' | '90days' | 'alltime' | 'custom'; // Define all supported bots - centralized list for consistency export const SUPPORTED_BOTS = [ 'ChatGPT', 'Claude', 'Perplexity', 'Gemini', 'Grok', 'DeepSeek', 'Bing', 'Llama', 'Mistral', 'Other LLM', ]; export const BOT_COMPANY_DOMAINS: Record = { 'ChatGPT': 'openai.com', 'Claude': 'claude.com', 'Gemini': 'google.com', 'Bing': 'microsoft.com', 'Perplexity': 'perplexity.ai', 'Llama': 'meta.com', 'Mistral': 'mistral.ai', 'Grok': 'x.ai', 'DeepSeek': 'deepseek.ai', 'Other LLM': 'ai.com', }; export const BOT_LOGOS: Record = new Proxy({} as Record, { get(_target, botName: string) { return botLogoUrl(String(botName)); }, ownKeys() { return Object.keys(getBotLogos()); }, getOwnPropertyDescriptor() { return { enumerable: true, configurable: true }; }, }); // Colors for each bot export const BOT_COLORS: Record = { 'ChatGPT': '#10a37f', // OpenAI green 'Claude': '#6f42c1', // Purple for Claude 'Gemini': '#4285f4', // Google blue 'Bing': '#00a4ef', // Bing blue 'Perplexity': '#5436da', // Perplexity purple 'Grok': '#1d9bf0', 'DeepSeek': '#4d7cfe', 'Llama': '#0668e1', // Meta blue 'Mistral': '#007bff', // Mistral blue 'Other LLM': '#ff9800', // Orange for others }; // Default logo for unknown bots export function getDefaultBotLogo(): string { return botLogoUrl('Other LLM'); } export function getTimeRangeLabel( timeRange: TimeRangeType, startDate: string, endDate: string ): string { switch (timeRange) { case '24hours': return __('Last 24 hours', 'llmagnet-llm-txt-generator'); case '7days': return __('Last 7 days', 'llmagnet-llm-txt-generator'); case '14days': return __('Last 14 days', 'llmagnet-llm-txt-generator'); case '30days': return __('Last 30 days', 'llmagnet-llm-txt-generator'); case '90days': return __('Last 90 days', 'llmagnet-llm-txt-generator'); case 'alltime': return __('All time (charts aggregate up to 365 days)', 'llmagnet-llm-txt-generator'); case 'custom': if (startDate && endDate) { return sprintf( /* translators: 1: start date, 2: end date. */ __('Custom: %1$s – %2$s', 'llmagnet-llm-txt-generator'), new Date(startDate).toLocaleDateString(), new Date(endDate).toLocaleDateString() ); } return __('Custom range', 'llmagnet-llm-txt-generator'); default: return __('Last 30 days', 'llmagnet-llm-txt-generator'); } } export function getChartTrafficWindowLabel(timeRange: TimeRangeType): string { if (timeRange === '7days') return __('Last 7 days', 'llmagnet-llm-txt-generator'); if (timeRange === '90days') return __('Last 90 days', 'llmagnet-llm-txt-generator'); return __('Last 30 days', 'llmagnet-llm-txt-generator'); }