"use client"; // ============================================================================ // Dashboard Home Page // ============================================================================ import React, { useEffect, useState, useRef } from "react"; import { DashboardHeader } from "@/components/layout/dashboard-header"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, } from "@/components/ui/card"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, } from "@/components/ui/dialog"; import { Alert, AlertDescription } from "@/components/ui/alert"; import { analyticsApi, channelsApi } from "@/lib/api"; import { formatCurrency, formatNumber, formatMetric, formatPercent, } from "@/lib/utils/format"; import { BarChart3, TrendingUp, Users, ShoppingCart, Loader2, ExternalLink, CheckCircle2, } from "lucide-react"; import type { SpendingAnalytics } from "@/lib/types/api"; import { useTargetChannel } from "@/components/providers/target-channel-provider"; import { BOT_USERNAME } from "@/lib/utils/constants"; export default function DashboardPage() { const { selectedChannel, channels, isLoading: channelsLoading, } = useTargetChannel(); const [spending, setSpending] = useState(null); const [loading, setLoading] = useState(true); // Для модального окна добавления канала const [showAddChannelDialog, setShowAddChannelDialog] = useState(false); const [isSuccess, setIsSuccess] = useState(false); const [initialChannelCount, setInitialChannelCount] = useState(0); const pollingIntervalRef = useRef(null); // Показываем модальное окно, если нет каналов useEffect(() => { if (!channelsLoading && channels.length === 0) { setShowAddChannelDialog(true); setInitialChannelCount(0); } }, [channelsLoading, channels]); // Автоматический polling при открытом окне useEffect(() => { if (showAddChannelDialog && !isSuccess && initialChannelCount === 0) { pollingIntervalRef.current = setInterval(() => { checkForNewChannels(); }, 1000); return () => { if (pollingIntervalRef.current) { clearInterval(pollingIntervalRef.current); pollingIntervalRef.current = null; } }; } }, [showAddChannelDialog, isSuccess, initialChannelCount]); // Очистка при размонтировании useEffect(() => { return () => { if (pollingIntervalRef.current) { clearInterval(pollingIntervalRef.current); } }; }, []); const checkForNewChannels = async () => { try { const response = await channelsApi.list(); const activeChannels = response.target_channels.filter( (c) => c.is_active ); if (activeChannels.length > initialChannelCount) { setIsSuccess(true); if (pollingIntervalRef.current) { clearInterval(pollingIntervalRef.current); pollingIntervalRef.current = null; } setTimeout(() => { setShowAddChannelDialog(false); setIsSuccess(false); window.location.reload(); }, 2000); } } catch (err) { console.error("Error polling channels:", err); } }; useEffect(() => { if (!selectedChannel) { setLoading(false); return; } const loadData = async () => { try { setLoading(true); const data = await analyticsApi.spending({ grouping: "week", target_channel_id: selectedChannel.id, }); setSpending(data); } catch (error) { console.error("Error loading spending data:", error); } finally { setLoading(false); } }; loadData(); }, [selectedChannel]); return ( <> {/* Модальное окно добавления первого канала */} {}}> e.preventDefault()} onEscapeKeyDown={(e) => e.preventDefault()} > Добро пожаловать! Для начала работы добавьте ваш первый целевой канал {isSuccess ? (

Канал успешно добавлен!

Страница обновится автоматически...

) : (

Шаги для добавления канала:

  1. Откройте свой Telegram канал
  2. Перейдите в настройки канала → Администраторы
  3. Добавьте бота{" "} @{BOT_USERNAME} {" "} как администратора
  4. Предоставьте боту права:{" "} Публикация сообщений, Удаление сообщений

Ждем добавления бота...
Как только вы добавите бота, канал автоматически появится

)}
{!selectedChannel ? (

Выберите целевой канал

Для начала работы выберите целевой канал в верхнем меню

) : (
Всего закупов {loading ? ( ) : ( <>
{formatNumber(spending?.total_cost)}

{formatNumber(0 || 0, true)} за прошлый месяц

)}
Подписчиков привлечено {loading ? ( ) : ( <>
{formatNumber(spending?.total_subscriptions)}

{formatNumber(0 || 0, true)} за прошлый месяц

)}
Средний CPF {loading ? ( ) : ( <>
₽{formatMetric(spending?.avg_cpf)}

{formatPercent(0 || 0, true)} от прошлого месяца

)}
Средний CPM {loading ? ( ) : ( <>
₽{formatMetric(spending?.avg_cpm)}

{formatPercent(0 || 0, true)} от прошлого месяца

)}
Быстрый старт Начните с основных действий → Создать новый закуп → Создать креатив → Импортировать каналы → Посмотреть аналитику
)} ); }