"use client"; // ============================================================================ // Target Channel Detail Page // ============================================================================ import React, { useEffect, useState } from "react"; import { use } from "react"; import Link from "next/link"; import { useRouter } from "next/navigation"; import { DashboardHeader } from "@/components/layout/dashboard-header"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from "@/components/ui/table"; import { channelsApi } from "@/lib/api"; import { formatNumber, formatMetric, formatCurrency, formatUsername, formatDate, } from "@/lib/utils/format"; import { Target, Users, TrendingUp, ArrowLeft, Loader2, AlertCircle, ExternalLink as ExternalLinkIcon, BarChart3, } from "lucide-react"; import type { TargetChannelDetail } from "@/lib/types/api"; interface PageProps { params: Promise<{ id: string }>; } export default function ChannelDetailPage({ params }: PageProps) { const resolvedParams = use(params); const router = useRouter(); const [channel, setChannel] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const loadChannel = async () => { try { setLoading(true); const data = await channelsApi.get(resolvedParams.id); setChannel(data); } catch (err: any) { setError(err?.error?.message || "Ошибка загрузки канала"); } finally { setLoading(false); } }; loadChannel(); }, [resolvedParams.id]); const handleToggleActive = async () => { if (!channel) return; try { const updated = await channelsApi.update(channel.id, { is_active: !channel.is_active, }); setChannel({ ...channel, is_active: updated.is_active }); } catch (err: any) { alert(err?.error?.message || "Ошибка обновления канала"); } }; const handleDelete = async () => { if (!channel) return; if (!confirm("Вы уверены, что хотите отключить этот канал?")) return; try { await channelsApi.delete(channel.id); router.push("/channels"); } catch (err: any) { alert(err?.error?.message || "Ошибка удаления канала"); } }; if (loading) { return ( <>
); } if (error || !channel) { return ( <>
{error || "Канал не найден"}
); } return ( <>

{channel.title}

{channel.is_active ? "Активен" : "Отключен"}
{channel.username ? ( {formatUsername(channel.username)} ) : ( Приватный канал )} Добавлен {formatDate(channel.created_at)}
{channel.description && ( Описание

{channel.description}

)}
Всего закупов
{formatNumber(channel.total_purchases)}

За весь период

Подписчиков привлечено
{formatNumber(channel.total_subscriptions)}

Всего

Средний CPF
₽{formatMetric(channel.avg_cpf)}

Стоимость подписчика

Статистика по периодам Последние закупы Статистика по периодам Динамика привлечения подписчиков Период Подписчики Затраты CPF {channel.stats_by_period.map((stat, index) => ( {stat.period} {formatNumber(stat.subscriptions)} {formatCurrency(stat.cost)} ₽{formatMetric(stat.cpf)} ))}
Последние закупы 5 последних рекламных размещений {channel.recent_purchases.length === 0 ? (

Закупов пока нет

) : ( Внешний канал Дата Подписчики CPF {channel.recent_purchases.map((purchase) => ( {purchase.external_channel.title} {formatDate( purchase.actual_date || purchase.scheduled_date )} {formatNumber(purchase.subscriptions_count)} ₽{formatMetric(purchase.cpf)} ))}
)}
); }