"use client"; // ============================================================================ // Analytics Overview Page // ============================================================================ import React, { useEffect, useState } from "react"; import { DashboardHeader } from "@/components/layout/dashboard-header"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { analyticsApi } from "@/lib/api"; import { formatNumber, formatMetric, formatCurrency, formatPercent, } from "@/lib/utils/format"; import { BarChart3, Loader2, AlertCircle, TrendingUp, TrendingDown, Users, ShoppingCart, DollarSign, } from "lucide-react"; import type { AnalyticsOverview } from "@/lib/types/api"; import { LineChart, Line, BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer, } from "recharts"; export default function AnalyticsPage() { const [overview, setOverview] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { loadOverview(); }, []); const loadOverview = async () => { try { setLoading(true); const data = await analyticsApi.overview(); setOverview(data); } catch (err: any) { setError(err?.error?.message || "Ошибка загрузки аналитики"); } finally { setLoading(false); } }; if (loading) { return ( <>
); } if (error || !overview) { return ( <>
{error || "Не удалось загрузить аналитику"}
); } return ( <>

Аналитика

Сводная статистика за последний месяц

Всего закупов
{formatNumber(overview.totalPurchases)}
{overview.purchasesChange >= 0 ? ( ) : ( )} = 0 ? "text-green-600" : "text-red-600" } > {overview.purchasesChange >= 0 ? "+" : ""} {formatNumber(overview.purchasesChange)} за прошлый месяц
Всего подписчиков
{formatNumber(overview.totalFollowers)}
{overview.followersChange >= 0 ? ( ) : ( )} = 0 ? "text-green-600" : "text-red-600" } > {overview.followersChange >= 0 ? "+" : ""} {formatNumber(overview.followersChange)} за прошлый месяц
Средний CPF
₽{formatMetric(overview.averageCpf)}
{overview.cpfChange <= 0 ? ( ) : ( )} {formatPercent(overview.cpfChange, true)} от прошлого месяца
Средний CPM
₽{formatMetric(overview.averageCpm)}
{overview.cpmChange <= 0 ? ( ) : ( )} {formatPercent(overview.cpmChange, true)} от прошлого месяца
Топ каналов по CPF Самые эффективные внешние каналы
{overview.topChannelsByCpf?.length > 0 ? ( overview.topChannelsByCpf.slice(0, 5).map((item, index) => (
{index + 1}

{item.channel_name}

{formatNumber(item.total_purchases)} закупов

₽{formatMetric(item.avg_cpf)}

CPF

)) ) : (

Нет данных

)}
Топ креативов Самые эффективные рекламные креативы
{overview.topCreativesByCpf?.length > 0 ? ( overview.topCreativesByCpf.slice(0, 5).map((item, index) => (
{index + 1}

{item.creative_name}

{formatNumber(item.total_subscriptions)} подписчиков

₽{formatMetric(item.avg_cpf)}

CPF

)) ) : (

Нет данных

)}
); }