"use client"; import { useEffect, useState } from "react"; import { signOut, useSession } from "next-auth/react"; import { SessionsLineChart, CategoriesBarChart, SentimentChart, LanguagePieChart, TokenUsageChart, } from "../../components/Charts"; import DashboardSettings from "./settings"; import UserManagement from "./users"; import { Company, MetricsResult } from "../../lib/types"; interface MetricsCardProps { label: string; value: string | number | null | undefined; className?: string; } interface StatCardProps { label: string; value: string | number | null | undefined; description?: string; icon?: string; trend?: number; trendLabel?: string; } function MetricsCard({ label, value, className = "" }: MetricsCardProps) { return (
{value ?? "-"} {label}
); } function StatCard({ label, value, description, icon, trend, trendLabel, }: StatCardProps) { return (

{label}

{value ?? "-"}

{description && (

{description}

)}
{icon &&
{icon}
}
{trend !== undefined && (
= 0 ? "text-green-500" : "text-red-500"}`} > {trend >= 0 ? "↑" : "↓"} {Math.abs(trend).toFixed(1)}% {trendLabel && ( {trendLabel} )}
)}
); } // Safely wrapped component with useSession function DashboardContent() { const { data: session } = useSession(); const [metrics, setMetrics] = useState(null); const [company, setCompany] = useState(null); const [, setLoading] = useState(false); // Remove unused csvUrl state variable const [refreshing, setRefreshing] = useState(false); const isAdmin = session?.user?.role === "admin"; const isAuditor = session?.user?.role === "auditor"; useEffect(() => { // Fetch metrics and company on mount const fetchData = async () => { setLoading(true); const res = await fetch("/api/dashboard/metrics"); const data = await res.json(); setMetrics(data.metrics); setCompany(data.company); // Removed unused csvUrl assignment setLoading(false); }; fetchData(); }, []); 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) { console.error("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(); console.error("Failed to refresh sessions:", errorData.error); } } finally { setRefreshing(false); } } // Calculate sentiment distribution const getSentimentData = () => { if (!metrics) return { positive: 0, neutral: 0, negative: 0 }; // If we have the new sentiment count fields, use those if ( metrics.sentimentPositiveCount !== undefined && metrics.sentimentNeutralCount !== undefined && metrics.sentimentNegativeCount !== undefined ) { return { positive: metrics.sentimentPositiveCount, neutral: metrics.sentimentNeutralCount, negative: metrics.sentimentNegativeCount, }; } // Fallback to estimating based on total const total = metrics.totalSessions || 1; return { positive: Math.round(total * 0.6), // 60% positive as fallback neutral: Math.round(total * 0.3), // 30% neutral as fallback negative: Math.round(total * 0.1), // 10% negative as fallback }; }; // Prepare token usage data const getTokenData = () => { if (!metrics || !metrics.tokensByDay) { return { labels: [], values: [], costs: [] }; } const days = Object.keys(metrics.tokensByDay).sort(); // Get the last 7 days if available 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 }; }; if (!metrics || !company) { return
Loading dashboard...
; } return (
{/* Header with company info */}

{company.name}

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

{/* Key Performance Metrics */}
{/* Sentiment & Escalation Metrics */}

Sentiment Distribution

Case Handling

{/* Charts Row */}

Sessions by Day

Categories

{/* Language & Token Usage */}

Languages

Token Usage & Costs

Total Tokens:{" "} {metrics.totalTokens?.toLocaleString() || 0} Total Cost:{" "} €{metrics.totalTokensEur?.toFixed(4) || 0}
{/* Admin Controls */} {isAdmin && ( <> )}
); } // Our exported component export default function DashboardPage() { // We don't use useSession here to avoid the error outside the provider return ; }