feat: Revamp Dashboard component with new icons, improved layout, and quick action links for enhanced user navigation and experience
Publish Fast Tabler Docker image / build-and-push-fast (push) Successful in 6m14s

This commit is contained in:
2025-08-08 10:39:50 +07:00
parent 64dbe621be
commit 3c185509b2
+40 -74
View File
@@ -1,21 +1,22 @@
import { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import axios from 'axios';
import {
IconWorld,
IconNetwork,
IconServer,
IconDatabase,
IconActivity,
IconTrendingUp,
IconTrendingDown,
IconClock,
IconMapPin,
IconCloud,
IconShield,
IconAlertTriangle
IconAlertTriangle,
IconRefresh,
IconFilter,
IconDownload,
IconCreditCard
} from '@tabler/icons-react';
function StatCard({ icon: Icon, color, value, title, subtitle, trend, trendValue }) {
function StatCard({ icon: Icon, color, value, title, subtitle }) {
return (
<div className="card h-100">
<div className="card-body d-flex align-items-center">
@@ -25,12 +26,6 @@ function StatCard({ icon: Icon, color, value, title, subtitle, trend, trendValue
<div className="flex-grow-1">
<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>
{trend && (
<div className={`mt-2 d-flex align-items-center ${trend === 'up' ? 'text-success' : 'text-danger'}`}>
{trend === 'up' ? <IconTrendingUp size={16} /> : <IconTrendingDown size={16} />}
<span className="ms-1 small">{trendValue}</span>
</div>
)}
</div>
</div>
</div>
@@ -158,16 +153,13 @@ function Dashboard() {
<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>
<h2 className="page-title">Панель</h2>
<div className="page-pretitle">Краткая сводка по данным</div>
</div>
<div className="col-auto ms-auto d-print-none">
<div className="btn-list">
<button className="btn btn-primary">
<IconActivity className="icon" />
Обновить данные
</button>
</div>
<button className="btn btn-outline-primary" onClick={() => window.location.reload()}>
<IconRefresh className="me-2" /> Обновить
</button>
</div>
</div>
</div>
@@ -181,8 +173,6 @@ function Dashboard() {
value={loading ? '...' : stats.domainsCount ?? '—'}
title="Доменов"
subtitle="Всего доменов в системе"
trend="up"
trendValue="+12% за неделю"
/>
</div>
<div className="col-md-3">
@@ -192,8 +182,6 @@ function Dashboard() {
value={loading ? '...' : stats.ipRangesCount ?? '—'}
title="IP-диапазонов"
subtitle="Всего IP диапазонов"
trend="up"
trendValue="+5% за неделю"
/>
</div>
<div className="col-md-3">
@@ -203,8 +191,6 @@ function Dashboard() {
value={loading ? '...' : stats.asnsCount ?? '—'}
title="AS"
subtitle="Всего Autonomous Systems"
trend="down"
trendValue="-2% за неделю"
/>
</div>
<div className="col-md-3">
@@ -214,8 +200,6 @@ function Dashboard() {
value={loading ? '...' : stats.serversCount ?? '—'}
title="Серверов"
subtitle="Всего серверов"
trend="up"
trendValue="+8% за неделю"
/>
</div>
</div>
@@ -252,60 +236,42 @@ function Dashboard() {
<div className="col-md-2">
<MetricCard
title="Последнее обновление"
value={loading ? '...' : (stats.lastModified ? new Date(stats.lastModified).toLocaleString() : '—')}
value={loading ? '...' : (stats.lastModified ? stats.lastModified : '—')}
icon={IconClock}
color="orange"
description="S3 синхронизация"
/>
</div>
<div className="col-md-2">
<MetricCard
title="Активность"
value="98%"
icon={IconActivity}
color="purple"
description="Система работает"
/>
</div>
<div className="col-md-2">
<MetricCard
title="API статус"
value={loading ? '...' : (error ? 'Ошибка' : 'ОК')}
icon={IconDatabase}
color={loading ? 'secondary' : (error ? 'danger' : 'success')}
description={error ? 'Проблемы с подключением' : 'Все API работают'}
/>
</div>
</div>
{/* Графики и диаграммы (заглушки для будущего) */}
<div className="row g-3">
<div className="col-md-6">
<div className="card">
<div className="card-header">
<h3 className="card-title">Распределение по странам</h3>
</div>
<div className="card-body">
<div className="text-center text-muted py-4">
<IconMapPin size={48} className="mb-3" />
<p>График распределения серверов по странам</p>
<small>Будет добавлен в следующем обновлении</small>
</div>
</div>
</div>
{/* Быстрые действия */}
<div className="card">
<div className="card-header">
<h3 className="card-title">Быстрые действия</h3>
</div>
<div className="col-md-6">
<div className="card">
<div className="card-header">
<h3 className="card-title">Активность обновлений</h3>
</div>
<div className="card-body">
<div className="text-center text-muted py-4">
<IconActivity size={48} className="mb-3" />
<p>График активности обновлений данных</p>
<small>Будет добавлен в следующем обновлении</small>
</div>
</div>
<div className="card-body">
<div className="btn-list">
<Link to="/domains" className="btn btn-outline-primary">
<IconWorld className="me-2" /> Домены
</Link>
<Link to="/ip-ranges" className="btn btn-outline-primary">
<IconNetwork className="me-2" /> IP-диапазоны
</Link>
<Link to="/asns" className="btn btn-outline-primary">
<IconNetwork className="me-2" /> AS
</Link>
<Link to="/servers" className="btn btn-outline-primary">
<IconServer className="me-2" /> Серверы
</Link>
<Link to="/filters" className="btn btn-outline-primary">
<IconFilter className="me-2" /> Фильтры
</Link>
<Link to="/auto-urls" className="btn btn-outline-primary">
<IconDownload className="me-2" /> Авто URL
</Link>
<Link to="/billing" className="btn btn-outline-primary">
<IconCreditCard className="me-2" /> Биллинг
</Link>
</div>
</div>
</div>