import React, { useState, useEffect } from 'react'; import { ArrowLeft, BarChart3, Users, TrendingUp, MessageSquare, Calendar, Building2, Eye, Key, Copy, CheckCircle2, X } from 'lucide-react'; import { apiClient } from '../../services/apiClient'; import { NPSSurvey, NPSSurveyStats, NPSResponse } from '../../types'; interface NPSSurveyStatsPageProps { surveyId: string | number; onBack?: () => void; } export const NPSSurveyStatsPage: React.FC = ({ surveyId, onBack }) => { const [survey, setSurvey] = useState(null); const [stats, setStats] = useState(null); const [responses, setResponses] = useState([]); const [isLoading, setIsLoading] = useState(true); const [showAccessKeyModal, setShowAccessKeyModal] = useState(false); const [copied, setCopied] = useState(false); const [selectedMonth, setSelectedMonth] = useState<{ month: number; year: number }>(() => { const now = new Date(); return { month: now.getMonth() + 1, year: now.getFullYear() }; }); useEffect(() => { loadData(); }, [surveyId, selectedMonth]); const loadData = async () => { try { setIsLoading(true); const params = new URLSearchParams(); params.append('month', selectedMonth.month.toString()); params.append('year', selectedMonth.year.toString()); const [surveyData, statsData, responsesData] = await Promise.all([ apiClient.get(`/pr/nps-surveys/${surveyId}`), apiClient.get(`/pr/nps-surveys/${surveyId}/stats?${params.toString()}`), apiClient.get(`/pr/nps-surveys/${surveyId}/responses?${params.toString()}`) ]); setSurvey(surveyData); setStats(statsData); setResponses(responsesData); } catch (err) { console.error('Error loading survey data:', err); setSurvey(null); setStats(null); setResponses([]); } finally { setIsLoading(false); } }; const getSurveyLink = () => { if (!survey) return ''; return `${window.location.origin}/nps/${survey.id}?key=${survey.accessKey}`; }; const handleCopyLink = () => { const link = getSurveyLink(); navigator.clipboard.writeText(link); setCopied(true); setTimeout(() => setCopied(false), 2000); }; const getNPSColor = (nps: number) => { if (nps >= 50) return 'text-emerald-600'; if (nps >= 0) return 'text-amber-600'; return 'text-red-600'; }; const getScoreColor = (score: number) => { if (score >= 9) return 'bg-emerald-100 text-emerald-700 border-emerald-200'; if (score >= 7) return 'bg-amber-100 text-amber-700 border-amber-200'; return 'bg-red-100 text-red-700 border-red-200'; }; if (isLoading) { return (

Загрузка статистики...

); } if (!survey) { return (

Не удалось загрузить данные опроса NPS

{onBack && ( )}
); } return (
{/* Header */} {onBack && (
)}
{/* Заголовок */}

{survey.title}

{survey.address && (

{survey.address}

)}
{/* Выбор месяца */}
{/* Основная статистика */} {stats && (
{/* NPS Score */}

Индекс NPS

{stats.nps > 0 ? '+' : ''}{stats.nps}
NPS

{stats.nps >= 50 ? 'Отличный показатель' : stats.nps >= 0 ? 'Хороший показатель' : 'Требует внимания'}

Средняя оценка:{' '} {(stats.avgScore ?? 0).toFixed(1)} {' '} из 10

{/* Общая статистика */}

Общая статистика

Всего ответов

{stats.totalResponses ?? 0}

Распределение

Промоутеры {stats.promoters ?? 0} ({(stats.promoterPercent ?? 0).toFixed(1)}%)
Нейтральные {stats.passives ?? 0} ( {stats.totalResponses ? ((stats.passives / stats.totalResponses) * 100).toFixed(1) : '0.0' }%)
Критики {stats.detractors ?? 0} ({(stats.detractorPercent ?? 0).toFixed(1)}%)
)} {/* Список ответов */}

Ответы жителей за {new Date(selectedMonth.year, selectedMonth.month - 1).toLocaleDateString('ru-RU', { month: 'long', year: 'numeric' })}

Всего: {responses.length}
{responses.length === 0 ? (

Пока нет ответов

) : (
{responses.map(response => (
{response.score}
{response.respondentName && (

{response.respondentName}

)} {response.apartment && (

Квартира №{response.apartment}

)}
{response.comment && (

{response.comment}

)}

{new Date(response.createdAt).toLocaleDateString('ru-RU', { day: 'numeric', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit' })}

))}
)}
{/* Модальное окно с ключом доступа */} {showAccessKeyModal && survey && (

Ссылка на опрос

Важно: Ссылка содержит ключ доступа. Отправляйте её только жителям выбранного дома.

)}
); };