"use client"; // ============================================================================ // Channels Analytics Page // ============================================================================ import { useEffect, useState } from "react"; import { useParams } from "next/navigation"; import { Loader2, Building2, ArrowUpDown, ArrowUp, ArrowDown, } from "lucide-react"; import { DashboardHeader } from "@/components/layout/dashboard-header"; import { useWorkspace } from "@/components/providers/workspace-provider"; import { demoAwareAnalyticsApi } from "@/lib/demo"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import type { ChannelAnalyticsItem } from "@/lib/types/api"; // ============================================================================ // Helpers // ============================================================================ const formatCurrency = (value: number | null) => { if (value === null) return "—"; return new Intl.NumberFormat("ru-RU", { style: "currency", currency: "RUB", minimumFractionDigits: 0, maximumFractionDigits: 0, }).format(value); }; const formatNumber = (value: number | null) => { if (value === null) return "—"; return new Intl.NumberFormat("ru-RU").format(value); }; // ============================================================================ // Types // ============================================================================ type SortField = | "placements" | "cost" | "subscriptions" | "views" | "cps" | "cpm"; type SortOrder = "asc" | "desc" | null; // ============================================================================ // Component // ============================================================================ export default function ChannelsAnalyticsPage() { const params = useParams(); const workspaceId = params?.workspaceId as string; const { getProjectFilterId } = useWorkspace(); const projectFilterId = getProjectFilterId(); const [channels, setChannels] = useState([]); const [loading, setLoading] = useState(true); const [sortField, setSortField] = useState("cost"); const [sortOrder, setSortOrder] = useState("desc"); useEffect(() => { loadData(); }, [workspaceId, projectFilterId]); const loadData = async () => { try { setLoading(true); const response = await demoAwareAnalyticsApi.channels(workspaceId, { project_id: projectFilterId, size: 100, }); setChannels(response.items); } catch (err) { console.error("Failed to load channels analytics:", err); } finally { setLoading(false); } }; // Sort handler const handleSort = (field: SortField) => { if (sortField === field) { if (sortOrder === "asc") setSortOrder("desc"); else if (sortOrder === "desc") { setSortField(null); setSortOrder(null); } else setSortOrder("asc"); } else { setSortField(field); setSortOrder("desc"); } }; const getSortIcon = (field: SortField) => { if (sortField !== field) return ; if (sortOrder === "asc") return ; if (sortOrder === "desc") return ; return ; }; // Sort data const sortedChannels = [...channels].sort((a, b) => { if (!sortField || !sortOrder) return 0; let aVal = 0; let bVal = 0; switch (sortField) { case "placements": aVal = a.placements_count; bVal = b.placements_count; break; case "cost": aVal = a.total_cost; bVal = b.total_cost; break; case "subscriptions": aVal = a.total_subscriptions; bVal = b.total_subscriptions; break; case "views": aVal = a.total_views; bVal = b.total_views; break; case "cps": aVal = a.avg_cps ?? 0; bVal = b.avg_cps ?? 0; break; case "cpm": aVal = a.avg_cpm ?? 0; bVal = b.avg_cpm ?? 0; break; } return sortOrder === "asc" ? aVal - bVal : bVal - aVal; }); return ( <>

Аналитика по каналам

Эффективность каналов размещения

{loading ? (
) : sortedChannels.length === 0 ? (

Нет данных

Создайте размещения для отображения статистики по каналам

) : ( Каналы размещения {sortedChannels.length} каналов Канал {sortedChannels.map((channel) => (
{channel.channel_title}
{channel.channel_username && (
@{channel.channel_username}
)}
{channel.placements_count} {formatCurrency(channel.total_cost)} {formatNumber(channel.total_subscriptions)} {formatNumber(channel.total_views)} {formatCurrency(channel.avg_cps)} {formatCurrency(channel.avg_cpm)}
))}
)}
); }