mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-07-28 17:43:47 +00:00
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:
@@ -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;
|
||||
},
|
||||
};
|
||||
|
||||
@@ -27,6 +27,10 @@ export interface PartnerCampaignInfo {
|
||||
subscription_traffic_gb: number | null;
|
||||
deep_link: string | null;
|
||||
web_link: string | null;
|
||||
// Per-campaign statistics
|
||||
registrations_count: number;
|
||||
referrals_count: number;
|
||||
earnings_kopeks: number;
|
||||
}
|
||||
|
||||
export interface PartnerStatusResponse {
|
||||
@@ -45,6 +49,57 @@ export interface PartnerApplicationRequest {
|
||||
desired_commission_percent?: number;
|
||||
}
|
||||
|
||||
// ==================== Campaign detailed stats types ====================
|
||||
|
||||
export interface DailyStatItem {
|
||||
date: string;
|
||||
referrals_count: number;
|
||||
earnings_kopeks: number;
|
||||
}
|
||||
|
||||
export interface PeriodStats {
|
||||
days: number;
|
||||
referrals_count: number;
|
||||
earnings_kopeks: number;
|
||||
}
|
||||
|
||||
export interface PeriodChange {
|
||||
absolute: number;
|
||||
percent: number;
|
||||
trend: 'up' | 'down' | 'stable';
|
||||
}
|
||||
|
||||
export interface PeriodComparison {
|
||||
current: PeriodStats;
|
||||
previous: PeriodStats;
|
||||
referrals_change: PeriodChange;
|
||||
earnings_change: PeriodChange;
|
||||
}
|
||||
|
||||
export interface CampaignReferralItem {
|
||||
id: number;
|
||||
full_name: string;
|
||||
created_at: string;
|
||||
has_paid: boolean;
|
||||
is_active: boolean;
|
||||
total_earnings_kopeks: number;
|
||||
}
|
||||
|
||||
export interface PartnerCampaignDetailedStats {
|
||||
campaign_id: number;
|
||||
campaign_name: string;
|
||||
registrations_count: number;
|
||||
referrals_count: number;
|
||||
earnings_kopeks: number;
|
||||
conversion_rate: number;
|
||||
earnings_today: number;
|
||||
earnings_week: number;
|
||||
earnings_month: number;
|
||||
daily_stats: DailyStatItem[];
|
||||
period_comparison: PeriodComparison;
|
||||
top_referrals: CampaignReferralItem[];
|
||||
}
|
||||
|
||||
// ==================== Admin-facing types ====================
|
||||
|
||||
export interface AdminPartnerApplicationItem {
|
||||
@@ -159,6 +214,13 @@ export const partnerApi = {
|
||||
return response.data;
|
||||
},
|
||||
|
||||
getCampaignStats: async (campaignId: number): Promise<PartnerCampaignDetailedStats> => {
|
||||
const response = await apiClient.get<PartnerCampaignDetailedStats>(
|
||||
`/cabinet/referral/partner/campaigns/${campaignId}/stats`,
|
||||
);
|
||||
return response.data;
|
||||
},
|
||||
|
||||
// Admin endpoints
|
||||
getStats: async (): Promise<PartnerStats> => {
|
||||
const response = await apiClient.get<PartnerStats>('/cabinet/admin/partners/stats');
|
||||
|
||||
Reference in New Issue
Block a user