Initial commit
This commit is contained in:
135
Client-Admin/src/components/Dashboard.jsx
Normal file
135
Client-Admin/src/components/Dashboard.jsx
Normal file
@@ -0,0 +1,135 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import { useAuth } from '../auth/AuthProvider';
|
||||
import { API_BASE_URL } from '../auth/authConfig';
|
||||
import ClientsPanel from './admin/ClientsPanel';
|
||||
import UsersPanel from './admin/UsersPanel';
|
||||
import SessionsPanel from './admin/SessionsPanel';
|
||||
|
||||
export default function Dashboard() {
|
||||
const { session } = useAuth();
|
||||
const [activeTab, setActiveTab] = useState('overview');
|
||||
const [data, setData] = useState(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState(null);
|
||||
const [refreshKey, setRefreshKey] = useState(0);
|
||||
|
||||
const fetchData = useCallback(async (endpoint) => {
|
||||
if (!session?.sessionToken) return null;
|
||||
|
||||
setLoading(true);
|
||||
setError(null);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${API_BASE_URL}${endpoint}`, {
|
||||
headers: { 'X-Session-Token': session.sessionToken }
|
||||
});
|
||||
const result = await response.json();
|
||||
if (!result.ok) throw new Error(result.error || 'Request failed');
|
||||
return result;
|
||||
} catch (err) {
|
||||
setError(err.message);
|
||||
return null;
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
}, [session]);
|
||||
|
||||
const refresh = () => setRefreshKey(k => k + 1);
|
||||
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
let result = null;
|
||||
switch (activeTab) {
|
||||
case 'overview':
|
||||
result = await fetchData('/api/monitoring/health');
|
||||
break;
|
||||
case 'clients':
|
||||
result = await fetchData('/api/admin/clients');
|
||||
break;
|
||||
case 'users':
|
||||
result = await fetchData('/api/admin/users');
|
||||
break;
|
||||
case 'sessions':
|
||||
result = await fetchData('/api/admin/sessions');
|
||||
break;
|
||||
}
|
||||
setData(result);
|
||||
};
|
||||
loadData();
|
||||
}, [activeTab, fetchData, refreshKey]);
|
||||
|
||||
const tabs = [
|
||||
{ id: 'overview', label: 'Overview' },
|
||||
{ id: 'clients', label: 'Clients' },
|
||||
{ id: 'users', label: 'Users' },
|
||||
{ id: 'sessions', label: 'Sessions' },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="dashboard">
|
||||
<div className="dashboard-header">
|
||||
<h1>Management Dashboard</h1>
|
||||
<div className="dashboard-info">
|
||||
<span className="info-item"><strong>Client:</strong> {session?.clientName}</span>
|
||||
<span className="info-item"><strong>Role:</strong> {session?.role}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav className="dashboard-tabs">
|
||||
{tabs.map(tab => (
|
||||
<button
|
||||
key={tab.id}
|
||||
className={`tab-btn ${activeTab === tab.id ? 'active' : ''}`}
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
>
|
||||
{tab.label}
|
||||
</button>
|
||||
))}
|
||||
</nav>
|
||||
|
||||
<div className="dashboard-content">
|
||||
{loading && (
|
||||
<div className="loading-container">
|
||||
<div className="spinner"></div>
|
||||
<p>Loading...</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{error && <div className="error-message">{error}</div>}
|
||||
|
||||
{!loading && !error && data && (
|
||||
<div className="data-panel">
|
||||
{activeTab === 'overview' && <OverviewPanel data={data} />}
|
||||
{activeTab === 'clients' && <ClientsPanel data={data} sessionToken={session?.sessionToken} onRefresh={refresh} />}
|
||||
{activeTab === 'users' && <UsersPanel data={data} sessionToken={session?.sessionToken} onRefresh={refresh} />}
|
||||
{activeTab === 'sessions' && <SessionsPanel data={data} sessionToken={session?.sessionToken} onRefresh={refresh} />}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function OverviewPanel({ data }) {
|
||||
return (
|
||||
<div className="overview-panel">
|
||||
<h2>System Overview</h2>
|
||||
<div className="stats-grid">
|
||||
<StatCard label="Active Clients" value={data.activeClients} />
|
||||
<StatCard label="Active Users" value={data.activeUsers} />
|
||||
<StatCard label="Active Sessions" value={data.activeSessions} />
|
||||
<StatCard label="API Calls (24h)" value={data.apiCalls24h} />
|
||||
</div>
|
||||
<p className="server-time">Server Time: {new Date(data.serverTimeUtc).toLocaleString()}</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function StatCard({ label, value }) {
|
||||
return (
|
||||
<div className="stat-card">
|
||||
<div className="stat-value">{value ?? '-'}</div>
|
||||
<div className="stat-label">{label}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user