feat: Integrate Dashboard component into MainLayout and update routing to redirect home path to /dashboard
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 7m6s

This commit is contained in:
2025-08-05 21:26:23 +07:00
parent f5d86d9e1b
commit 7c6ceb66bc
2 changed files with 302 additions and 102 deletions
+5 -102
View File
@@ -32,6 +32,7 @@ import IPRangesManager from './IPRangesManager';
import ASNsNewManager from './ASNsNewManager';
import AutoUrlManager from './AutoUrlManager';
import BillingManager from './BillingManager';
import Dashboard from './Dashboard';
import './App.css';
import axios from 'axios';
import {
@@ -107,7 +108,7 @@ function MainLayout() {
id: 'home',
title: 'Главная',
icon: IconHome,
path: '/',
path: '/dashboard',
single: true
},
{
@@ -136,11 +137,7 @@ function MainLayout() {
title: 'Инструменты',
icon: IconSettings,
items: [
{ id: 'auto-urls', title: 'Авто URL', path: '/auto-urls', icon: IconDownload },
{ id: 'files', title: 'Файлы', path: '/files', icon: IconFileText },
{ id: 'cloud', title: 'Облако', path: '/cloud', icon: IconCloud },
{ id: 'security', title: 'Безопасность', path: '/security', icon: IconShield },
{ id: 'activity', title: 'Активность', path: '/activity', icon: IconActivity }
{ id: 'auto-urls', title: 'Авто URL', path: '/auto-urls', icon: IconDownload }
]
},
{
@@ -288,6 +285,7 @@ function MainLayout() {
</header>
<div className="container-xl mt-4">
<Routes>
<Route path="/dashboard" element={<Dashboard />} />
<Route path="/domains" element={
<DataManager
entityName="домен"
@@ -302,108 +300,13 @@ function MainLayout() {
<Route path="/servers" element={<ServerManager />} />
<Route path="/billing" element={<BillingManager />} />
<Route path="/filters" element={<FilterManager />} />
<Route path="/" element={<Navigate to="/domains" replace />} />
<Route path="/" element={<Navigate to="/dashboard" replace />} />
</Routes>
</div>
</div>
);
}
function StatCard({ icon: Icon, color, value, title, subtitle }) {
return (
<div className="card h-100">
<div className="card-body d-flex align-items-center">
<span className={`avatar avatar-lg me-3 bg-${color}-lt text-${color} border-0`}>
<Icon size={32} />
</span>
<div>
<div className="h3 mb-0 fw-bold">{value} <span className="fs-5 fw-normal">{title}</span></div>
<div className="text-muted lh-1">{subtitle}</div>
</div>
</div>
</div>
);
}
function Dashboard() {
const [stats, setStats] = useState({ domainsCount: null, asnsCount: null, serversCount: null, lastModified: null });
const [loading, setLoading] = useState(true);
useEffect(() => {
async function fetchStats() {
setLoading(true);
try {
const [domainsRes, asnsRes, serversRes, s3Res] = await Promise.all([
axios.get('/api/domains'),
axios.get('/api/asns'),
axios.get('/api/servers'),
axios.get('/api/s3/last-modified')
]);
setStats({
domainsCount: domainsRes.data.length,
asnsCount: asnsRes.data.length,
serversCount: serversRes.data.length,
lastModified: s3Res.data.domainsLastModified
});
} catch (e) {
setStats({ domainsCount: null, asnsCount: null, serversCount: null, lastModified: null });
} finally {
setLoading(false);
}
}
fetchStats();
}, []);
return (
<div>
<div className="row g-3 mb-4">
<div className="col-md-3">
<StatCard
icon={IconWorld}
color="blue"
value={loading ? '...' : stats.domainsCount ?? '—'}
title="Доменов"
subtitle="Всего доменов"
/>
</div>
<div className="col-md-3">
<StatCard
icon={IconNetwork}
color="green"
value={loading ? '...' : stats.asnsCount ?? '—'}
title="AS"
subtitle="Всего AS"
/>
</div>
<div className="col-md-3">
<StatCard
icon={IconServer}
color="purple"
value={loading ? '...' : stats.serversCount ?? '—'}
title="Серверов"
subtitle="Всего серверов"
/>
</div>
<div className="col-md-3">
<StatCard
icon={IconDatabase}
color="orange"
value={loading ? '...' : (stats.lastModified ? new Date(stats.lastModified).toLocaleString() : '—')}
title="Обновление"
subtitle="Последнее изменение S3"
/>
</div>
</div>
<div className="page-header d-print-none mb-4">
<div className="row align-items-center">
<div className="col">
<h2 className="page-title">Dashboard</h2>
<div className="page-pretitle">Главная / Dashboard</div>
</div>
</div>
</div>
</div>
);
}
export default App;