import { useState } from 'react';
import { useParams, useNavigate, Link } from 'react-router-dom';
import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'react-i18next';
import { campaignsApi, CampaignBonusType } from '../api/campaigns';
import { AdminBackButton } from '../components/admin';
// Icons
const CopyIcon = () => (
);
const LinkIcon = () => (
);
const UsersIcon = () => (
);
const ChartIcon = () => (
);
// Bonus type config
const bonusTypeConfig: Record<
CampaignBonusType,
{ labelKey: string; color: string; bgColor: string }
> = {
balance: {
labelKey: 'admin.campaigns.bonusType.balance',
color: 'text-success-400',
bgColor: 'bg-success-500/20',
},
subscription: {
labelKey: 'admin.campaigns.bonusType.subscription',
color: 'text-accent-400',
bgColor: 'bg-accent-500/20',
},
tariff: {
labelKey: 'admin.campaigns.bonusType.tariff',
color: 'text-purple-400',
bgColor: 'bg-purple-500/20',
},
none: {
labelKey: 'admin.campaigns.bonusType.none',
color: 'text-dark-400',
bgColor: 'bg-dark-600',
},
};
// Helper functions
const formatRubles = (kopeks: number): string => {
const rubles = kopeks / 100;
return `${rubles.toLocaleString('ru-RU')} ₽`;
};
const formatDate = (date: string | null): string => {
if (!date) return '-';
return new Date(date).toLocaleDateString('ru-RU', {
day: '2-digit',
month: '2-digit',
year: 'numeric',
hour: '2-digit',
minute: '2-digit',
});
};
export default function AdminCampaignStats() {
const { t } = useTranslation();
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const [copied, setCopied] = useState(false);
const [showUsers, setShowUsers] = useState(false);
// Fetch stats
const {
data: stats,
isLoading,
error,
} = useQuery({
queryKey: ['campaign-stats', id],
queryFn: () => campaignsApi.getCampaignStats(Number(id)),
enabled: !!id,
});
// Fetch registrations when users section is open
const { data: registrationsData, isLoading: usersLoading } = useQuery({
queryKey: ['campaign-registrations', id],
queryFn: () => campaignsApi.getCampaignRegistrations(Number(id), 1, 50),
enabled: !!id && showUsers,
});
const copyLink = () => {
if (stats?.deep_link) {
navigator.clipboard.writeText(stats.deep_link);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
};
if (isLoading) {
return (
);
}
if (error || !stats) {
return (
{t('admin.campaigns.stats.title')}
{t('admin.campaigns.stats.loadError')}
);
}
return (
{/* Header */}
{stats.name}
{t(bonusTypeConfig[stats.bonus_type].labelKey)}
{stats.is_active ? (
{t('admin.campaigns.stats.active')}
) : (
{t('admin.campaigns.stats.inactive')}
)}
{/* Deep Link */}
{stats.deep_link && (
{stats.deep_link}
)}
{/* Main Stats */}
{stats.registrations}
{t('admin.campaigns.stats.registrations')}
{formatRubles(stats.total_revenue_kopeks)}
{t('admin.campaigns.stats.revenue')}
{stats.paid_users_count}
{t('admin.campaigns.stats.paidUsers')}
{stats.conversion_rate}%
{t('admin.campaigns.stats.conversion')}
{/* Detailed Stats */}
{t('admin.campaigns.stats.detailedStats')}
{t('admin.campaigns.stats.bonusesIssued')}
{stats.bonus_type === 'balance' && (
{formatRubles(stats.balance_issued_kopeks)}
)}
{stats.bonus_type === 'subscription' && (
{t('admin.campaigns.stats.subscriptionsIssued', {
count: stats.subscription_issued,
})}
)}
{stats.bonus_type === 'tariff' && (
{t('admin.campaigns.stats.tariffsIssued', { count: stats.subscription_issued })}
)}
{stats.bonus_type === 'none' && (
-
)}
{t('admin.campaigns.stats.avgRevenuePerUser')}
{formatRubles(stats.avg_revenue_per_user_kopeks)}
{t('admin.campaigns.stats.avgFirstPayment')}
{formatRubles(stats.avg_first_payment_kopeks)}
{t('admin.campaigns.stats.trialSubscriptions')}
{t('admin.campaigns.stats.trialCount', {
total: stats.trial_users_count,
active: stats.active_trials_count,
})}
{t('admin.campaigns.stats.trialConversion')}
{stats.trial_conversion_rate}%
{t('admin.campaigns.stats.lastRegistration')}
{formatDate(stats.last_registration)}
{/* Users Section */}
{showUsers && (
{usersLoading ? (
) : registrationsData?.registrations.length === 0 ? (
{t('admin.campaigns.stats.noUsers')}
) : (
{registrationsData?.registrations.map((reg) => (
{reg.first_name || reg.username || `User #${reg.user_id}`}
{reg.telegram_id}
{reg.has_paid && (
{t('admin.campaigns.stats.paid')}
)}
{reg.has_subscription && (
{t('admin.campaigns.stats.hasSub')}
)}
{formatDate(reg.created_at)}
))}
)}
)}
);
}