/**
* @file SmsCampaignStats.jsx
* @description SMS Campaign statistics with charts:
* - KPI cards (sent, delivered, in transit, errors)
* - Daily trend (sent vs delivered, last 14 days)
* - Status donut chart
* - Delivery rate
*/
import React, { useState, useEffect, useCallback } from "react";
import {
BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer,
PieChart, Pie, Cell, LineChart, Line, CartesianGrid, Legend,
} from "recharts";
import { Panel } from "../UI/Panel";
import { supabase } from "../../supabaseClient";
const STATUS_COLORS = {
delivered: "#22c55e",
sent: "#3b82f6",
checking: "#94a3b8",
expired: "#eab308",
send_failed: "#ef4444",
error: "#ef4444",
limit_exceeded: "#f97316",
};
const STATUS_LABELS = {
delivered: "Доставлено",
sent: "Отправлено",
checking: "Проверяется",
expired: "Истёк срок",
send_failed: "Ошибка отправки",
error: "Ошибка доставки",
limit_exceeded: "Лимит",
};
export const SmsCampaignStats = ({ campaignType }) => {
const [stats, setStats] = useState(null);
const [dailyData, setDailyData] = useState([]);
const [statusData, setStatusData] = useState([]);
const [isLoading, setIsLoading] = useState(true);
const [period, setPeriod] = useState("14d");
const loadStats = useCallback(async () => {
setIsLoading(true);
try {
const days = period === "7d" ? 7 : period === "30d" ? 30 : period === "all" ? 90 : 14;
const startDate = new Date();
startDate.setDate(startDate.getDate() - days);
const startDateISO = startDate.toISOString();
const { data, error } = await supabase
.from("sms_campaign_log")
.select("status, sms_code, attempts, created_at, campaign_type")
.eq("campaign_type", campaignType)
.gte("created_at", startDateISO)
.order("created_at", { ascending: true });
if (error) throw error;
// KPI
const total = data.length;
const delivered = data.filter(d => d.status === "delivered").length;
const inTransit = data.filter(d => d.status === "sent" || d.status === "checking").length;
const errors = data.filter(d => ["send_failed", "error", "limit_exceeded"].includes(d.status)).length;
const expired = data.filter(d => d.status === "expired").length;
const deliveryRate = total > 0 ? Math.round((delivered / total) * 100) : 0;
setStats({ total, delivered, inTransit, errors, expired, deliveryRate });
// Daily data
const byDay = {};
data.forEach(d => {
const day = new Date(d.created_at).toLocaleDateString("ru-RU", { day: "2-digit", month: "2-digit" });
if (!byDay[day]) byDay[day] = { date: day, sent: 0, delivered: 0, errors: 0 };
byDay[day].sent++;
if (d.status === "delivered") byDay[day].delivered++;
if (["send_failed", "error", "limit_exceeded"].includes(d.status)) byDay[day].errors++;
});
setDailyData(Object.values(byDay));
// Status pie
const byStatus = {};
data.forEach(d => {
byStatus[d.status] = (byStatus[d.status] || 0) + 1;
});
setStatusData(Object.entries(byStatus).map(([name, value]) => ({
name: STATUS_LABELS[name] || name,
value,
color: STATUS_COLORS[name] || "#94a3b8",
})));
} catch (e) {
console.error("Stats error:", e);
} finally {
setIsLoading(false);
}
}, [campaignType, period]);
useEffect(() => { loadStats(); }, [loadStats]);
if (isLoading) {
return (