veza/apps/web/src/components/admin/admin-dashboard-view/AdminDashboardView.tsx
senke 503e6f00b6 feat(a11y): comprehensive accessibility & view states improvements
Sprint 1 — Quick A11y wins:
- progress.tsx: role=progressbar + aria-value* + aria-label
- switch.tsx: role=switch + aria-checked
- skeleton.tsx: aria-hidden=true
- alert.tsx, Toast.tsx, SelectTrigger.tsx: aria-labels on close buttons
- PostCard.tsx: alt on images + aria-labels on icon buttons
- ProductCard.tsx: aria-labels on play/view buttons
- modal.tsx: role=dialog + aria-modal + aria-labelledby
- input.tsx: error state + aria-invalid + aria-describedby
- FAB.tsx: forward aria-label from label prop

Sprint 2 — Structural A11y + View States:
- tabs/: full ARIA tablist/tab/tabpanel + arrow key navigation
- radio-group.tsx: role=radio + arrow key navigation
- select/: aria-activedescendant + full keyboard navigation
- List.tsx + card.tsx: focus-visible states on interactive elements
- DashboardPage, LibraryPage, LiveView, QueueView: error states
- WishlistView, AdminDashboard, AnalyticsView, SellerDashboard: loading/empty states

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 23:04:35 +01:00

94 lines
3.4 KiB
TypeScript

import React from 'react';
import { motion } from 'framer-motion';
import { Users, DollarSign, Activity, ShieldAlert } from 'lucide-react';
import { useAdminDashboardView } from './useAdminDashboardView';
import { AdminDashboardHeader } from './AdminDashboardHeader';
import { AdminDashboardStatCard } from './AdminDashboardStatCard';
import { AdminDashboardTrafficCard } from './AdminDashboardTrafficCard';
import { AdminDashboardProtocolsCard } from './AdminDashboardProtocolsCard';
import { AdminDashboardNodeHealthCard } from './AdminDashboardNodeHealthCard';
import { AdminDashboardTabs } from './AdminDashboardTabs';
import { AdminDashboardSkeleton } from './AdminDashboardSkeleton';
import { ErrorDisplay } from '@/components/ui/ErrorDisplay';
export function AdminDashboardView() {
const {
stats,
reports,
uploads,
auditLogs,
loading,
error,
protocolActive,
handleAction,
triggerProtocol,
retry,
} = useAdminDashboardView();
if (loading) {
return <AdminDashboardSkeleton />;
}
if (error) {
return (
<div className="container mx-auto px-4 py-8 max-w-layout-content">
<ErrorDisplay
error={error}
onRetry={retry}
title="Failed to load admin dashboard"
context={{ action: 'loading', resource: 'admin dashboard' }}
variant="card"
/>
</div>
);
}
return (
<div className="space-y-8 pb-24 animate-fadeIn container mx-auto px-4 py-8 max-w-layout-content">
<AdminDashboardHeader
protocolActive={protocolActive}
onRescan={() => triggerProtocol('RESCAN', 'success')}
onLockdown={() => triggerProtocol('LOCKDOWN', 'error')}
/>
<motion.div
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8"
initial="hidden"
animate="visible"
variants={{ visible: { transition: { staggerChildren: 0.05 } }, hidden: {} }}
>
{[
{ label: 'Total Nodes', value: stats.totalUsers?.toLocaleString(), icon: Users, trend: stats.trends?.users, color: 'cyan' as const },
{ label: 'Credit Volume', value: `$${stats.monthlyRevenue?.toLocaleString()}`, icon: DollarSign, trend: stats.trends?.revenue, color: 'gold' as const },
{ label: 'Active Uplinks', value: stats.activeSessions?.toLocaleString(), icon: Activity, trend: stats.trends?.sessions, color: 'lime' as const },
{ label: 'Threat Reports', value: stats.pendingReports, icon: ShieldAlert, trend: stats.trends?.reports, color: 'red' as const },
].map((item, i) => (
<motion.div key={item.label} variants={{ hidden: { opacity: 0, y: 8 }, visible: { opacity: 1, y: 0 } }}>
<AdminDashboardStatCard
label={item.label}
value={item.value}
icon={<item.icon className="w-5 h-5" />}
trend={item.trend}
color={item.color}
/>
</motion.div>
))}
</motion.div>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<AdminDashboardTrafficCard />
<div className="space-y-6">
<AdminDashboardProtocolsCard onTrigger={triggerProtocol} />
<AdminDashboardNodeHealthCard />
</div>
</div>
<AdminDashboardTabs
reports={reports}
uploads={uploads}
auditLogs={auditLogs}
onReportAction={handleAction}
/>
</div>
);
}