import React, { useState, useEffect } from 'react'; import { Smile, Frown, Meh, TrendingUp, TrendingDown, Target, Heart, Share2, Send, MessageSquare, Hash, PartyPopper, Calendar } from 'lucide-react'; import { MOCK_BUILDINGS } from '../../constants'; import { backendApi } from '../../services/apiClient'; import type { SMMChannel, PREvent } from '../../types'; const CHANNEL_ICONS: Record = { tg: Send, vk: Share2, wa: MessageSquare, other: Hash }; interface Props { onNavigate: (tab: any) => void; } export const PRSummary: React.FC = ({ onNavigate }) => { const avgNPS = 68; const sentiment = { positive: 72, neutral: 18, negative: 10 }; const [smmChannels, setSmmChannels] = useState([]); const [smmLoading, setSmmLoading] = useState(true); const [events, setEvents] = useState([]); const [eventsLoading, setEventsLoading] = useState(true); useEffect(() => { setSmmLoading(true); backendApi.getSMMChannels() .then((list) => setSmmChannels(Array.isArray(list) ? list : [])) .catch(() => setSmmChannels([])) .finally(() => setSmmLoading(false)); }, []); useEffect(() => { setEventsLoading(true); const now = new Date(); const from = new Date(now.getFullYear(), now.getMonth(), 1).toISOString().slice(0, 10); const to = new Date(now.getFullYear(), now.getMonth() + 2, 0).toISOString().slice(0, 10); backendApi.getPREvents({ from, to, limit: 30 }) .then((list) => setEvents(Array.isArray(list) ? list : [])) .catch(() => setEvents([])) .finally(() => setEventsLoading(false)); }, []); return (
{/* NPS Card */}

Net Promoter Score

Общий индекс лояльности по компании

+{avgNPS}

Тенденция: Рост

{/* Performance Lists */}

Топ лояльных домов

{MOCK_BUILDINGS.filter(b => b.nps > 30).slice(0, 3).map(b => (
{b.passport.address} +{b.nps} NPS
))}

Зоны внимания (Критики)

{MOCK_BUILDINGS.filter(b => b.nps < 10).slice(0, 3).map(b => (
{b.passport.address} {b.nps} NPS
))}
{/* SMM: соцсети и подписчики */}

SMM — соцсети и подписчики

{smmLoading ? (

Загрузка...

) : smmChannels.length === 0 ? (

Каналы не добавлены

) : ( <>
{smmChannels.map(ch => { const Icon = CHANNEL_ICONS[ch.type] || Hash; const count = ch.subscribersCount ?? ch.lastSnapshot?.subscribersCount; const style = ch.type === 'tg' ? 'text-sky-500 bg-sky-50' : ch.type === 'vk' ? 'text-blue-600 bg-blue-50' : ch.type === 'wa' ? 'text-emerald-500 bg-emerald-50' : 'text-slate-600 bg-slate-50'; return (

{ch.name}

{count != null ? `${count.toLocaleString('ru-RU')} подписчиков` : '—'}

); })}

Всего: {smmChannels.reduce((s, c) => s + (c.subscribersCount ?? c.lastSnapshot?.subscribersCount ?? 0), 0).toLocaleString('ru-RU')} подписчиков

)}
{/* Мероприятия */}

Ближайшие мероприятия

{eventsLoading ? (

Загрузка...

) : events.length === 0 ? (

Нет запланированных мероприятий

) : ( <>

Запланировано

{events.filter(e => e.status === 'planned' || e.status === 'in_progress').length}

Проведено

{events.filter(e => e.status === 'completed').length}

{events.filter(e => e.status === 'planned' || e.status === 'in_progress').slice(0, 5).map((ev) => (

{ev.title}

{typeof ev.date === 'string' ? ev.date : String(ev.date)}

))}
)}
); }; const SentimentWidget = ({ icon: Icon, label, value, color }: any) => (
{label}

{value}%

);