diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx
index 65570c5..bff9601 100644
--- a/app/dashboard/page.tsx
+++ b/app/dashboard/page.tsx
@@ -11,7 +11,7 @@ import {
} from "../../components/Charts";
import DashboardSettings from "./settings";
import UserManagement from "./users";
-import { Company, MetricsResult } from "../../lib/types";
+import { Company, MetricsResult, WordCloudWord } from "../../lib/types"; // Added WordCloudWord
import MetricCard from "../../components/MetricCard";
import DonutChart from "../../components/DonutChart";
import WordCloud from "../../components/WordCloud";
@@ -136,14 +136,10 @@ function DashboardContent() {
return
Loading dashboard...
;
}
- // Function to prepare word cloud data from categories
- const getWordCloudData = () => {
- if (!metrics || !metrics.categories) return [];
- return Object.entries(metrics.categories)
- .map(([text, value]) => ({ text, value }))
- .filter((item) => item.text.trim() !== "")
- .sort((a, b) => b.value - a.value)
- .slice(0, 30);
+ // 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
@@ -380,7 +376,7 @@ function DashboardContent() {
- Categories Word Cloud
+ Transcript Word Cloud
diff --git a/lib/metrics.ts b/lib/metrics.ts
index a283caf..8cbc199 100644
--- a/lib/metrics.ts
+++ b/lib/metrics.ts
@@ -4,13 +4,308 @@ import {
DayMetrics,
CategoryMetrics,
LanguageMetrics,
+ CountryMetrics, // Added CountryMetrics
MetricsResult,
+ WordCloudWord, // Added WordCloudWord
} from "./types";
interface CompanyConfig {
sentimentAlert?: number;
}
+// List of common stop words - this can be expanded
+const stopWords = new Set([
+ "assistant",
+ "user",
+ // Web
+ "com",
+ "www",
+ "http",
+ "https",
+ "www2",
+ "href",
+ "html",
+ "php",
+ "js",
+ "css",
+ "xml",
+ "json",
+ "txt",
+ "jpg",
+ "jpeg",
+ "png",
+ "gif",
+ "bmp",
+ "svg",
+ "org",
+ "net",
+ "co",
+ "io",
+ // English stop words
+ "a",
+ "an",
+ "the",
+ "is",
+ "are",
+ "was",
+ "were",
+ "be",
+ "been",
+ "being",
+ "have",
+ "has",
+ "had",
+ "do",
+ "does",
+ "did",
+ "will",
+ "would",
+ "should",
+ "can",
+ "could",
+ "may",
+ "might",
+ "must",
+ "am",
+ "i",
+ "you",
+ "he",
+ "she",
+ "it",
+ "we",
+ "they",
+ "me",
+ "him",
+ "her",
+ "us",
+ "them",
+ "my",
+ "your",
+ "his",
+ "its",
+ "our",
+ "their",
+ "mine",
+ "yours",
+ "hers",
+ "ours",
+ "theirs",
+ "to",
+ "of",
+ "in",
+ "on",
+ "at",
+ "by",
+ "for",
+ "with",
+ "about",
+ "against",
+ "between",
+ "into",
+ "through",
+ "during",
+ "before",
+ "after",
+ "above",
+ "below",
+ "from",
+ "up",
+ "down",
+ "out",
+ "off",
+ "over",
+ "under",
+ "again",
+ "further",
+ "then",
+ "once",
+ "here",
+ "there",
+ "when",
+ "where",
+ "why",
+ "how",
+ "all",
+ "any",
+ "both",
+ "each",
+ "few",
+ "more",
+ "most",
+ "other",
+ "some",
+ "such",
+ "no",
+ "nor",
+ "not",
+ "only",
+ "own",
+ "same",
+ "so",
+ "than",
+ "too",
+ "very",
+ "s",
+ "t",
+ "just",
+ "don",
+ "shouldve",
+ "now",
+ "d",
+ "ll",
+ "m",
+ "o",
+ "re",
+ "ve",
+ "y",
+ "ain",
+ "aren",
+ "couldn",
+ "didn",
+ "doesn",
+ "hadn",
+ "hasn",
+ "haven",
+ "isn",
+ "ma",
+ "mightn",
+ "mustn",
+ "needn",
+ "shan",
+ "shouldn",
+ "wasn",
+ "weren",
+ "won",
+ "wouldn",
+ "hi",
+ "hello",
+ "thanks",
+ "thank",
+ "please",
+ "ok",
+ "okay",
+ "yes",
+ "yeah",
+ "bye",
+ "goodbye",
+ // French stop words
+ "la",
+ "le",
+ "les",
+ "un",
+ "une",
+ "des",
+ "et",
+ "ou",
+ "mais",
+ "donc",
+ // Dutch stop words
+ "dit",
+ "ben",
+ "de",
+ "het",
+ "ik",
+ "jij",
+ "hij",
+ "zij",
+ "wij",
+ "jullie",
+ "deze",
+ "dit",
+ "dat",
+ "die",
+ "een",
+ "en",
+ "of",
+ "maar",
+ "want",
+ "omdat",
+ "dus",
+ "als",
+ "ook",
+ "dan",
+ "nu",
+ "nog",
+ "al",
+ "naar",
+ "voor",
+ "van",
+ "door",
+ "met",
+ "bij",
+ "tot",
+ "om",
+ "over",
+ "tussen",
+ "onder",
+ "boven",
+ "tegen",
+ "aan",
+ "uit",
+ "sinds",
+ "tijdens",
+ "binnen",
+ "buiten",
+ "zonder",
+ "volgens",
+ "dankzij",
+ "ondanks",
+ "behalve",
+ "mits",
+ "tenzij",
+ "hoewel",
+ "alhoewel",
+ "toch",
+ "anders",
+ "echter",
+ "wel",
+ "niet",
+ "geen",
+ "iets",
+ "niets",
+ "veel",
+ "weinig",
+ "meer",
+ "meest",
+ "elk",
+ "ieder",
+ "sommige",
+ "hoe",
+ "wat",
+ "waar",
+ "wie",
+ "wanneer",
+ "waarom",
+ "welke",
+ "wordt",
+ "worden",
+ "werd",
+ "werden",
+ "geworden",
+ "zijn",
+ "ben",
+ "bent",
+ "was",
+ "waren",
+ "geweest",
+ "hebben",
+ "heb",
+ "hebt",
+ "heeft",
+ "had",
+ "hadden",
+ "gehad",
+ "kunnen",
+ "kan",
+ "kunt",
+ "kon",
+ "konden",
+ "zullen",
+ "zal",
+ "zult",
+ // Add more domain-specific stop words if necessary
+]);
+
export function sessionMetrics(
sessions: ChatSession[],
companyConfig: CompanyConfig = {}
@@ -19,6 +314,7 @@ export function sessionMetrics(
const byDay: DayMetrics = {};
const byCategory: CategoryMetrics = {};
const byLanguage: LanguageMetrics = {};
+ const byCountry: CountryMetrics = {}; // Added for country data
const tokensByDay: DayMetrics = {};
const tokensCostByDay: DayMetrics = {};
@@ -40,12 +336,15 @@ export function sessionMetrics(
let totalDuration = 0;
let durationCount = 0;
+ const wordCounts: { [key: string]: number } = {}; // For WordCloud
+
sessions.forEach((s) => {
const day = s.startTime.toISOString().slice(0, 10);
byDay[day] = (byDay[day] || 0) + 1;
if (s.category) byCategory[s.category] = (byCategory[s.category] || 0) + 1;
if (s.language) byLanguage[s.language] = (byLanguage[s.language] || 0) + 1;
+ if (s.country) byCountry[s.country] = (byCountry[s.country] || 0) + 1; // Populate byCountry
// Process token usage by day
if (s.tokens) {
@@ -88,6 +387,24 @@ export function sessionMetrics(
totalTokens += s.tokens || 0;
totalTokensEur += s.tokensEur || 0;
+
+ // Process transcript for WordCloud
+ if (s.transcriptContent) {
+ const words = s.transcriptContent.toLowerCase().match(/\b\w+\b/g); // Split into words, lowercase
+ if (words) {
+ words.forEach((word) => {
+ const cleanedWord = word.replace(/[^a-z0-9]/gi, ""); // Remove punctuation
+ if (
+ cleanedWord &&
+ !stopWords.has(cleanedWord) &&
+ cleanedWord.length > 2
+ ) {
+ // Check if not a stop word and length > 2
+ wordCounts[cleanedWord] = (wordCounts[cleanedWord] || 0) + 1;
+ }
+ });
+ }
+ }
});
// Now add sentiment alert logic:
@@ -107,13 +424,20 @@ export function sessionMetrics(
const avgSessionLength =
durationCount > 0 ? totalDuration / durationCount : null;
+ // Prepare wordCloudData
+ const wordCloudData: WordCloudWord[] = Object.entries(wordCounts)
+ .map(([text, value]) => ({ text, value }))
+ .sort((a, b) => b.value - a.value)
+ .slice(0, 500); // Take top 500 words
+
return {
totalSessions: total,
avgSessionsPerDay,
avgSessionLength,
days: byDay,
languages: byLanguage,
- categories: byCategory,
+ categories: byCategory, // This will be empty if we are not using categories for word cloud
+ countries: byCountry, // Added countries to the result
belowThresholdCount: belowThreshold,
// Additional metrics not in the interface - using type assertion
escalatedCount: escalated,
@@ -131,5 +455,6 @@ export function sessionMetrics(
sentimentNegativeCount: sentimentNegative,
tokensByDay,
tokensCostByDay,
+ wordCloudData, // Added word cloud data
};
}
diff --git a/lib/types.ts b/lib/types.ts
index cc92b0d..32d444c 100644
--- a/lib/types.ts
+++ b/lib/types.ts
@@ -74,6 +74,15 @@ export interface LanguageMetrics {
[language: string]: number;
}
+export interface CountryMetrics {
+ [country: string]: number;
+}
+
+export interface WordCloudWord {
+ text: string;
+ value: number;
+}
+
export interface MetricsResult {
totalSessions: number;
avgSessionsPerDay: number;
@@ -81,6 +90,7 @@ export interface MetricsResult {
days: DayMetrics;
languages: LanguageMetrics;
categories: CategoryMetrics;
+ countries: CountryMetrics; // Added for geographic distribution
belowThresholdCount: number;
// Additional properties for dashboard
escalatedCount?: number;
@@ -98,6 +108,7 @@ export interface MetricsResult {
sentimentNegativeCount?: number;
tokensByDay?: DayMetrics;
tokensCostByDay?: DayMetrics;
+ wordCloudData?: WordCloudWord[]; // Added for transcript-based word cloud
}
export interface ApiResponse
{
diff --git a/pages/api/dashboard/metrics.ts b/pages/api/dashboard/metrics.ts
index 0c3986c..c34a84c 100644
--- a/pages/api/dashboard/metrics.ts
+++ b/pages/api/dashboard/metrics.ts
@@ -4,6 +4,7 @@ import { getServerSession } from "next-auth";
import { prisma } from "../../../lib/prisma";
import { sessionMetrics } from "../../../lib/metrics";
import { authOptions } from "../auth/[...nextauth]";
+import { ChatSession } from "../../../lib/types"; // Import ChatSession
interface SessionUser {
email: string;
@@ -32,13 +33,47 @@ export default async function handler(
if (!user) return res.status(401).json({ error: "No user" });
- const sessions = await prisma.session.findMany({
+ const prismaSessions = await prisma.session.findMany({
where: { companyId: user.companyId },
});
+ // Convert Prisma sessions to ChatSession[] type for sessionMetrics
+ const chatSessions: ChatSession[] = prismaSessions.map((ps) => ({
+ id: ps.id, // Map Prisma's id to ChatSession.id
+ sessionId: ps.id, // Map Prisma's id to ChatSession.sessionId
+ companyId: ps.companyId,
+ startTime: new Date(ps.startTime), // Ensure startTime is a Date object
+ endTime: ps.endTime ? new Date(ps.endTime) : null, // Ensure endTime is a Date object or null
+ transcriptContent: ps.transcriptContent || "", // Ensure transcriptContent is a string
+ createdAt: new Date(ps.createdAt), // Map Prisma's createdAt
+ updatedAt: new Date(ps.createdAt), // Use createdAt for updatedAt as Session model doesn't have updatedAt
+ category: ps.category || undefined,
+ language: ps.language || undefined,
+ country: ps.country || undefined,
+ ipAddress: ps.ipAddress || undefined,
+ sentiment: ps.sentiment === null ? undefined : ps.sentiment,
+ messagesSent: ps.messagesSent === null ? undefined : ps.messagesSent, // Handle null messagesSent
+ avgResponseTime:
+ ps.avgResponseTime === null ? undefined : ps.avgResponseTime,
+ tokens: ps.tokens === null ? undefined : ps.tokens,
+ tokensEur: ps.tokensEur === null ? undefined : ps.tokensEur,
+ escalated: ps.escalated || false,
+ forwardedHr: ps.forwardedHr || false,
+ initialMsg: ps.initialMsg || undefined,
+ fullTranscriptUrl: ps.fullTranscriptUrl || undefined,
+ // userId is missing in Prisma Session model, assuming it's not strictly needed for metrics or can be null
+ userId: undefined, // Or some other default/mapping if available
+ }));
+
// Pass company config to metrics
- // @ts-expect-error - Type conversion is needed between prisma session and ChatSession
- const metrics = sessionMetrics(sessions, user.company);
+ const companyConfigForMetrics = {
+ sentimentAlert:
+ user.company.sentimentAlert === null
+ ? undefined
+ : user.company.sentimentAlert,
+ };
+
+ const metrics = sessionMetrics(chatSessions, companyConfigForMetrics);
res.json({
metrics,
diff --git a/pages/api/dashboard/session/[id].ts b/pages/api/dashboard/session/[id].ts
index a9ed1f4..8e2eb73 100644
--- a/pages/api/dashboard/session/[id].ts
+++ b/pages/api/dashboard/session/[id].ts
@@ -3,60 +3,66 @@ import { prisma } from "../../../../lib/prisma";
import { ChatSession } from "../../../../lib/types";
export default async function handler(
- req: NextApiRequest,
- res: NextApiResponse
+ req: NextApiRequest,
+ res: NextApiResponse
) {
- if (req.method !== "GET") {
- return res.status(405).json({ error: "Method not allowed" });
+ if (req.method !== "GET") {
+ return res.status(405).json({ error: "Method not allowed" });
+ }
+
+ const { id } = req.query;
+
+ if (!id || typeof id !== "string") {
+ return res.status(400).json({ error: "Session ID is required" });
+ }
+
+ try {
+ const prismaSession = await prisma.session.findUnique({
+ where: { id },
+ });
+
+ if (!prismaSession) {
+ return res.status(404).json({ error: "Session not found" });
}
- const { id } = req.query;
+ // Map Prisma session object to ChatSession type
+ const session: ChatSession = {
+ // Spread prismaSession to include all its properties
+ ...prismaSession,
+ // Override properties that need conversion or specific mapping
+ id: prismaSession.id, // ChatSession.id from Prisma.Session.id
+ sessionId: prismaSession.id, // ChatSession.sessionId from Prisma.Session.id
+ startTime: new Date(prismaSession.startTime),
+ endTime: prismaSession.endTime ? new Date(prismaSession.endTime) : null,
+ createdAt: new Date(prismaSession.createdAt),
+ // Prisma.Session does not have an `updatedAt` field. We'll use `createdAt` as a fallback.
+ // Or, if your business logic implies an update timestamp elsewhere, use that.
+ updatedAt: new Date(prismaSession.createdAt), // Fallback to createdAt
+ // Prisma.Session does not have a `userId` field.
+ userId: null, // Explicitly set to null or map if available from another source
+ // Ensure nullable fields from Prisma are correctly mapped to ChatSession's optional or nullable fields
+ category: prismaSession.category ?? null,
+ language: prismaSession.language ?? null,
+ country: prismaSession.country ?? null,
+ ipAddress: prismaSession.ipAddress ?? null,
+ sentiment: prismaSession.sentiment ?? null,
+ messagesSent: prismaSession.messagesSent ?? undefined, // Use undefined if ChatSession expects number | undefined
+ avgResponseTime: prismaSession.avgResponseTime ?? null,
+ escalated: prismaSession.escalated ?? undefined,
+ forwardedHr: prismaSession.forwardedHr ?? undefined,
+ tokens: prismaSession.tokens ?? undefined,
+ tokensEur: prismaSession.tokensEur ?? undefined,
+ initialMsg: prismaSession.initialMsg ?? undefined,
+ fullTranscriptUrl: prismaSession.fullTranscriptUrl ?? null,
+ transcriptContent: prismaSession.transcriptContent ?? null,
+ };
- if (!id || typeof id !== "string") {
- return res.status(400).json({ error: "Session ID is required" });
- }
-
- try {
- const prismaSession = await prisma.session.findUnique({
- where: { id },
- });
-
- if (!prismaSession) {
- return res.status(404).json({ error: "Session not found" });
- }
-
- // Map Prisma session object to ChatSession type
- const session: ChatSession = {
- ...prismaSession,
- sessionId: prismaSession.id, // Assuming ChatSession's sessionId is Prisma's id
- startTime: new Date(prismaSession.startTime),
- endTime: prismaSession.endTime ? new Date(prismaSession.endTime) : null,
- createdAt: new Date(prismaSession.createdAt),
- updatedAt: new Date(prismaSession.updatedAt),
- userId: prismaSession.userId === undefined ? null : prismaSession.userId,
- category: prismaSession.category === undefined ? null : prismaSession.category,
- language: prismaSession.language === undefined ? null : prismaSession.language,
- country: prismaSession.country === undefined ? null : prismaSession.country,
- ipAddress: prismaSession.ipAddress === undefined ? null : prismaSession.ipAddress,
- sentiment: prismaSession.sentiment === undefined ? null : prismaSession.sentiment,
- messagesSent: prismaSession.messagesSent === undefined ? undefined : prismaSession.messagesSent,
- avgResponseTime: prismaSession.avgResponseTime === undefined ? null : prismaSession.avgResponseTime,
- escalated: prismaSession.escalated === undefined ? undefined : prismaSession.escalated,
- forwardedHr: prismaSession.forwardedHr === undefined ? undefined : prismaSession.forwardedHr,
- tokens: prismaSession.tokens === undefined ? undefined : prismaSession.tokens,
- tokensEur: prismaSession.tokensEur === undefined ? undefined : prismaSession.tokensEur,
- initialMsg: prismaSession.initialMsg === undefined ? null : prismaSession.initialMsg,
- fullTranscriptUrl: prismaSession.fullTranscriptUrl === undefined ? null : prismaSession.fullTranscriptUrl,
- transcriptContent: prismaSession.transcriptContent === undefined ? null : prismaSession.transcriptContent,
- };
-
- return res.status(200).json({ session });
- } catch (error) {
- console.error(`Failed to fetch session ${id}:`, error);
- const errorMessage =
- error instanceof Error ? error.message : "An unknown error occurred";
- return res
- .status(500)
- .json({ error: "Failed to fetch session", details: errorMessage });
- }
+ return res.status(200).json({ session });
+ } catch (error) {
+ const errorMessage =
+ error instanceof Error ? error.message : "An unknown error occurred";
+ return res
+ .status(500)
+ .json({ error: "Failed to fetch session", details: errorMessage });
+ }
}
diff --git a/pages/api/dashboard/sessions.ts b/pages/api/dashboard/sessions.ts
index 1b069a8..d62e7f7 100644
--- a/pages/api/dashboard/sessions.ts
+++ b/pages/api/dashboard/sessions.ts
@@ -1,73 +1,81 @@
import { NextApiRequest, NextApiResponse } from "next";
+import { getServerSession } from "next-auth/next";
+import { authOptions } from "../auth/[...nextauth]";
import { prisma } from "../../../lib/prisma";
import { ChatSession } from "../../../lib/types";
export default async function handler(
- req: NextApiRequest,
- res: NextApiResponse
+ req: NextApiRequest,
+ res: NextApiResponse
) {
- if (req.method !== "GET") {
- return res.status(405).json({ error: "Method not allowed" });
+ if (req.method !== "GET") {
+ return res.status(405).json({ error: "Method not allowed" });
+ }
+
+ const authSession = await getServerSession(req, res, authOptions);
+
+ if (!authSession || !authSession.user?.companyId) {
+ return res.status(401).json({ error: "Unauthorized" });
+ }
+
+ const companyId = authSession.user.companyId;
+ const { searchTerm } = req.query;
+
+ try {
+ const whereClause: any = { companyId };
+
+ if (
+ searchTerm &&
+ typeof searchTerm === "string" &&
+ searchTerm.trim() !== ""
+ ) {
+ const searchConditions = [
+ { id: { contains: searchTerm, mode: "insensitive" } },
+ { category: { contains: searchTerm, mode: "insensitive" } },
+ { initialMsg: { contains: searchTerm, mode: "insensitive" } },
+ { transcriptContent: { contains: searchTerm, mode: "insensitive" } },
+ ];
+ whereClause.OR = searchConditions;
}
- const { searchTerm } = req.query;
+ const prismaSessions = await prisma.session.findMany({
+ where: whereClause,
+ orderBy: {
+ startTime: "desc",
+ },
+ });
- try {
- let prismaSessions;
+ const sessions: ChatSession[] = prismaSessions.map((ps) => ({
+ id: ps.id,
+ sessionId: ps.id,
+ companyId: ps.companyId,
+ startTime: new Date(ps.startTime),
+ endTime: ps.endTime ? new Date(ps.endTime) : null,
+ createdAt: new Date(ps.createdAt),
+ updatedAt: new Date(ps.createdAt),
+ userId: null,
+ category: ps.category ?? null,
+ language: ps.language ?? null,
+ country: ps.country ?? null,
+ ipAddress: ps.ipAddress ?? null,
+ sentiment: ps.sentiment ?? null,
+ messagesSent: ps.messagesSent ?? undefined,
+ avgResponseTime: ps.avgResponseTime ?? null,
+ escalated: ps.escalated ?? undefined,
+ forwardedHr: ps.forwardedHr ?? undefined,
+ tokens: ps.tokens ?? undefined,
+ tokensEur: ps.tokensEur ?? undefined,
+ initialMsg: ps.initialMsg ?? undefined,
+ fullTranscriptUrl: ps.fullTranscriptUrl ?? null,
+ transcriptContent: ps.transcriptContent ?? null,
+ }));
- if (searchTerm && typeof searchTerm === "string" && searchTerm.trim() !== "") {
- const searchConditions = [
- { id: { contains: searchTerm, mode: "insensitive" } },
- { category: { contains: searchTerm, mode: "insensitive" } },
- { initialMsg: { contains: searchTerm, mode: "insensitive" } },
- { transcriptContent: { contains: searchTerm, mode: "insensitive" } },
- ];
-
- prismaSessions = await prisma.session.findMany({
- where: {
- OR: searchConditions,
- },
- orderBy: {
- startTime: "desc",
- },
- });
- } else {
- prismaSessions = await prisma.session.findMany({
- orderBy: {
- startTime: "desc",
- },
- });
- }
-
- const sessions: ChatSession[] = prismaSessions.map(ps => ({
- ...ps,
- sessionId: ps.id,
- startTime: new Date(ps.startTime),
- endTime: ps.endTime ? new Date(ps.endTime) : null,
- createdAt: new Date(ps.createdAt),
- updatedAt: new Date(ps.updatedAt),
- userId: ps.userId === undefined ? null : ps.userId,
- category: ps.category === undefined ? null : ps.category,
- language: ps.language === undefined ? null : ps.language,
- country: ps.country === undefined ? null : ps.country,
- ipAddress: ps.ipAddress === undefined ? null : ps.ipAddress,
- sentiment: ps.sentiment === undefined ? null : ps.sentiment,
- messagesSent: ps.messagesSent === undefined ? undefined : ps.messagesSent,
- avgResponseTime: ps.avgResponseTime === undefined ? null : ps.avgResponseTime,
- escalated: ps.escalated === undefined ? undefined : ps.escalated,
- forwardedHr: ps.forwardedHr === undefined ? undefined : ps.forwardedHr,
- tokens: ps.tokens === undefined ? undefined : ps.tokens,
- tokensEur: ps.tokensEur === undefined ? undefined : ps.tokensEur,
- initialMsg: ps.initialMsg === undefined ? null : ps.initialMsg,
- fullTranscriptUrl: ps.fullTranscriptUrl === undefined ? null : ps.fullTranscriptUrl,
- transcriptContent: ps.transcriptContent === undefined ? null : ps.transcriptContent,
- }));
-
- return res.status(200).json({ sessions });
- } catch (error) {
- console.error("Failed to fetch sessions:", error);
- const errorMessage =
- error instanceof Error ? error.message : "An unknown error occurred";
- return res.status(500).json({ error: "Failed to fetch sessions", details: errorMessage });
- }
+ return res.status(200).json({ sessions });
+ } catch (error) {
+ const errorMessage =
+ error instanceof Error ? error.message : "An unknown error occurred";
+ return res
+ .status(500)
+ .json({ error: "Failed to fetch sessions", details: errorMessage });
+ }
}