feat: add recharts analytics to admin campaign stats page

- Move shared chart components (DailyChart, PeriodComparison, StatCard) to src/components/stats/ with configurable label props
- Create shared types for chart data decoupled from partner API
- Add campaign chart data API client with deposits/spending split
- Enhance AdminCampaignStats with daily trends chart, period comparison, top registrations, and deposit/spending stat cards
- Add useChartColors hook with SSR guard and theme-aware CSS variable parsing
- Add cross-platform clipboard utility with execCommand fallback for Telegram WebView
- Add i18n keys for chart analytics across all 4 locales (en, ru, zh, fa)
- Responsive fixes: truncation for long names/values, responsive text sizing, touch-friendly copy buttons
This commit is contained in:
Fringg
2026-03-02 06:10:20 +03:00
parent 60f16e64e8
commit c7d05c4809
21 changed files with 1577 additions and 158 deletions

View File

@@ -149,6 +149,49 @@ export interface CampaignsOverview {
total_tariff_issued: number;
}
export interface AdminDailyStatItem {
date: string;
referrals_count: number;
earnings_kopeks: number;
}
export interface AdminPeriodStats {
days: number;
referrals_count: number;
earnings_kopeks: number;
}
export interface AdminPeriodChange {
absolute: number;
percent: number;
trend: 'up' | 'down' | 'stable';
}
export interface AdminPeriodComparison {
current: AdminPeriodStats;
previous: AdminPeriodStats;
referrals_change: AdminPeriodChange;
earnings_change: AdminPeriodChange;
}
export interface AdminTopRegistrationItem {
id: number;
full_name: string;
created_at: string;
has_paid: boolean;
is_active: boolean;
total_earnings_kopeks: number;
}
export interface AdminCampaignChartData {
campaign_id: number;
total_deposits_kopeks: number;
total_spending_kopeks: number;
daily_stats: AdminDailyStatItem[];
period_comparison: AdminPeriodComparison;
top_registrations: AdminTopRegistrationItem[];
}
export interface ServerSquadInfo {
id: number;
squad_uuid: string;
@@ -258,4 +301,10 @@ export const campaignsApi = {
const response = await apiClient.get('/cabinet/admin/campaigns/available-partners');
return response.data;
},
// Get campaign chart data for analytics
getChartData: async (campaignId: number): Promise<AdminCampaignChartData> => {
const response = await apiClient.get(`/cabinet/admin/campaigns/${campaignId}/chart-data`);
return response.data;
},
};