"use client"; import { useEffect, useState } from "react"; import { signOut, useSession } from "next-auth/react"; import { useRouter } from "next/navigation"; // Import useRouter import { SessionsLineChart, CategoriesBarChart, LanguagePieChart, TokenUsageChart, } from "../../components/Charts"; import DashboardSettings from "./settings"; import UserManagement from "./users"; import { Company, MetricsResult, WordCloudWord } from "../../lib/types"; // Added WordCloudWord import MetricCard from "../../components/MetricCard"; import DonutChart from "../../components/DonutChart"; import WordCloud from "../../components/WordCloud"; import GeographicMap from "../../components/GeographicMap"; import ResponseTimeDistribution from "../../components/ResponseTimeDistribution"; import WelcomeBanner from "../../components/WelcomeBanner"; // Safely wrapped component with useSession function DashboardContent() { const { data: session, status } = useSession(); // Add status from useSession const router = useRouter(); // Initialize useRouter const [metrics, setMetrics] = useState(null); const [company, setCompany] = useState(null); const [, setLoading] = useState(false); const [refreshing, setRefreshing] = useState(false); const isAdmin = session?.user?.role === "admin"; const isAuditor = session?.user?.role === "auditor"; useEffect(() => { // Redirect if not authenticated if (status === "unauthenticated") { router.push("/login"); return; // Stop further execution in this effect } // Fetch metrics and company on mount if authenticated if (status === "authenticated") { const fetchData = async () => { setLoading(true); const res = await fetch("/api/dashboard/metrics"); const data = await res.json(); setMetrics(data.metrics); setCompany(data.company); setLoading(false); }; fetchData(); } }, [status, router]); // Add status and router to dependency array async function handleRefresh() { if (isAuditor) return; // Prevent auditors from refreshing try { setRefreshing(true); // Make sure we have a company ID to send if (!company?.id) { setRefreshing(false); alert("Cannot refresh: Company ID is missing"); return; } const res = await fetch("/api/admin/refresh-sessions", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ companyId: company.id }), }); if (res.ok) { // Refetch metrics const metricsRes = await fetch("/api/dashboard/metrics"); const data = await metricsRes.json(); setMetrics(data.metrics); } else { const errorData = await res.json(); alert(`Failed to refresh sessions: ${errorData.error}`); } } finally { setRefreshing(false); } } // Calculate sentiment distribution const getSentimentData = () => { if (!metrics) return { positive: 0, neutral: 0, negative: 0 }; if ( metrics.sentimentPositiveCount !== undefined && metrics.sentimentNeutralCount !== undefined && metrics.sentimentNegativeCount !== undefined ) { return { positive: metrics.sentimentPositiveCount, neutral: metrics.sentimentNeutralCount, negative: metrics.sentimentNegativeCount, }; } const total = metrics.totalSessions || 1; return { positive: Math.round(total * 0.6), neutral: Math.round(total * 0.3), negative: Math.round(total * 0.1), }; }; // Prepare token usage data const getTokenData = () => { if (!metrics || !metrics.tokensByDay) { return { labels: [], values: [], costs: [] }; } const days = Object.keys(metrics.tokensByDay).sort(); const labels = days.slice(-7); const values = labels.map((day) => metrics.tokensByDay?.[day] || 0); const costs = labels.map((day) => metrics.tokensCostByDay?.[day] || 0); return { labels, values, costs }; }; // Show loading state while session status is being determined if (status === "loading") { return
Loading session...
; } // If unauthenticated and not redirected yet (should be handled by useEffect, but as a fallback) if (status === "unauthenticated") { return
Redirecting to login...
; } if (!metrics || !company) { return
Loading dashboard...
; } // Function to prepare word cloud data from metrics.wordCloudData const getWordCloudData = (): WordCloudWord[] => { if (!metrics || !metrics.wordCloudData) return []; return metrics.wordCloudData; }; // Function to prepare country data for the map - using simulated/dummy data const getCountryData = () => { return { US: 42, GB: 25, DE: 18, FR: 15, CA: 12, AU: 10, JP: 8, BR: 6, IN: 5, ZA: 3, ES: 7, NL: 9, IT: 6, SE: 4, }; }; // Function to prepare response time distribution data const getResponseTimeData = () => { const avgTime = metrics.avgResponseTime || 1.5; const simulatedData: number[] = []; for (let i = 0; i < 50; i++) { const randomFactor = 0.5 + Math.random(); simulatedData.push(avgTime * randomFactor); } return simulatedData; }; return (

{company.name}

Dashboard updated{" "} {new Date(metrics.lastUpdated || Date.now()).toLocaleString()}

Sentiment Distribution

Case Handling Statistics

metrics.totalSessions * 0.1 ? "warning" : "success" } /> metrics.totalSessions * 0.05 ? "warning" : "default" } />

Sessions by Day

Top Categories

Transcript Word Cloud

Geographic Distribution

Response Time Distribution

Languages

Token Usage & Costs

Total Tokens: {metrics.totalTokens?.toLocaleString() || 0}
Total Cost:€ {metrics.totalTokensEur?.toFixed(4) || 0}
{isAdmin && ( <> )}
); } // Our exported component export default function DashboardPage() { return (
); }