import React from 'react'
import { useQuery } from '@tanstack/react-query'
import { Activity, Users, Terminal, Globe, Database } from 'lucide-react'
import { format } from 'date-fns'
// API functions
const fetchSessions = async () => {
const response = await fetch('/sessions')
if (!response.ok) throw new Error('Failed to fetch sessions')
return response.json()
}
const fetchRecentLogs = async () => {
const response = await fetch('/logs?limit=10')
if (!response.ok) throw new Error('Failed to fetch logs')
return response.json()
}
const fetchTools = async () => {
const response = await fetch('/tools')
if (!response.ok) throw new Error('Failed to fetch tools')
return response.json()
}
export default function Overview() {
const { data: sessionsData } = useQuery({
queryKey: ['sessions'],
queryFn: fetchSessions,
refetchInterval: 5000
})
const { data: logsData } = useQuery({
queryKey: ['logs'],
queryFn: fetchRecentLogs,
refetchInterval: 2000
})
const { data: toolsData } = useQuery({
queryKey: ['tools'],
queryFn: fetchTools
})
const stats = [
{
name: 'Active Sessions',
value: sessionsData?.stats?.active_sessions || 0,
icon: Users,
color: 'text-blue-600',
bgColor: 'bg-blue-100 dark:bg-blue-900/20'
},
{
name: 'Total Tools',
value: toolsData?.tools?.length || 0,
icon: Terminal,
color: 'text-green-600',
bgColor: 'bg-green-100 dark:bg-green-900/20'
},
{
name: 'Static Tools',
value: sessionsData?.stats?.static_tools || 0,
icon: Activity,
color: 'text-purple-600',
bgColor: 'bg-purple-100 dark:bg-purple-900/20'
},
{
name: 'Session Tools',
value: sessionsData?.stats?.session_tools || 0,
icon: Globe,
color: 'text-orange-600',
bgColor: 'bg-orange-100 dark:bg-orange-900/20'
}
]
return (
<div className="px-4 sm:px-6 lg:px-8">
<div className="sm:flex sm:items-center">
<div className="sm:flex-auto">
<h1 className="text-2xl font-semibold text-gray-900 dark:text-white">Overview</h1>
<p className="mt-2 text-sm text-gray-700 dark:text-gray-300">
Monitor your MCP server status, sessions, and tool activity.
</p>
</div>
</div>
{/* Stats Grid */}
<div className="mt-8 grid grid-cols-1 gap-5 sm:grid-cols-2 lg:grid-cols-4">
{stats.map((stat) => (
<div
key={stat.name}
className="bg-white dark:bg-gray-800 overflow-hidden shadow rounded-lg border dark:border-gray-700"
>
<div className="p-5">
<div className="flex items-center">
<div className="flex-shrink-0">
<div className={`w-8 h-8 rounded-md ${stat.bgColor} flex items-center justify-center`}>
<stat.icon className={`w-5 h-5 ${stat.color}`} />
</div>
</div>
<div className="ml-5 w-0 flex-1">
<dl>
<dt className="text-sm font-medium text-gray-500 dark:text-gray-400 truncate">
{stat.name}
</dt>
<dd className="text-lg font-semibold text-gray-900 dark:text-white">
{stat.value}
</dd>
</dl>
</div>
</div>
</div>
</div>
))}
</div>
{/* Recent Activity */}
<div className="mt-8 grid grid-cols-1 lg:grid-cols-2 gap-8">
{/* Recent Tool Calls */}
<div className="bg-white dark:bg-gray-800 shadow rounded-lg border dark:border-gray-700">
<div className="px-6 py-4 border-b dark:border-gray-700">
<h3 className="text-lg font-medium text-gray-900 dark:text-white">Recent Tool Calls</h3>
</div>
<div className="p-6">
{logsData?.logs?.length > 0 ? (
<div className="space-y-4">
{logsData.logs.slice(0, 5).map((log: any, index: number) => (
<div key={log.id || index} className="flex items-start space-x-3">
<div className="flex-shrink-0">
<div className={`w-2 h-2 mt-2 rounded-full ${
log.error ? 'bg-red-500' : 'bg-green-500'
}`} />
</div>
<div className="min-w-0 flex-1">
<div className="text-sm font-medium text-gray-900 dark:text-white">
{log.tool_name}
</div>
<div className="text-xs text-gray-500 dark:text-gray-400">
{format(new Date(log.timestamp), 'MMM d, h:mm:ss a')} • {log.duration_ms}ms
</div>
{log.error && (
<div className="mt-1 text-xs text-red-600 dark:text-red-400">
{log.error.message}
</div>
)}
</div>
</div>
))}
</div>
) : (
<div className="text-center py-4">
<Terminal className="mx-auto h-8 w-8 text-gray-400" />
<p className="mt-2 text-sm text-gray-500 dark:text-gray-400">No recent tool calls</p>
</div>
)}
</div>
</div>
{/* Active Sessions */}
<div className="bg-white dark:bg-gray-800 shadow rounded-lg border dark:border-gray-700">
<div className="px-6 py-4 border-b dark:border-gray-700">
<h3 className="text-lg font-medium text-gray-900 dark:text-white">Active Sessions</h3>
</div>
<div className="p-6">
{sessionsData?.sessions?.length > 0 ? (
<div className="space-y-4">
{sessionsData.sessions.map((session: any) => (
<div key={session.id} className="flex items-start space-x-3">
<div className="flex-shrink-0">
<div className="w-8 h-8 rounded-full bg-indigo-100 dark:bg-indigo-900/20 flex items-center justify-center">
{session.type === 'browser' ? (
<Globe className="w-4 h-4 text-indigo-600" />
) : (
<Database className="w-4 h-4 text-indigo-600" />
)}
</div>
</div>
<div className="min-w-0 flex-1">
<div className="text-sm font-medium text-gray-900 dark:text-white">
{session.type} session
</div>
<div className="text-xs text-gray-500 dark:text-gray-400">
ID: {session.id.slice(0, 8)}...
</div>
<div className="text-xs text-gray-500 dark:text-gray-400">
Created: {format(new Date(session.created_at), 'MMM d, h:mm a')}
</div>
</div>
</div>
))}
</div>
) : (
<div className="text-center py-4">
<Users className="mx-auto h-8 w-8 text-gray-400" />
<p className="mt-2 text-sm text-gray-500 dark:text-gray-400">No active sessions</p>
</div>
)}
</div>
</div>
</div>
</div>
)
}