mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-25 20:51:11 -05:00
Enhance admin stats dashboard
Add data quality metrics, growth trends visualization, entity comparison views, and automated health checks to the AdminDatabaseStats dashboard, including new TS types, hooks, UI components, and integrated tabbed layout.
This commit is contained in:
@@ -1,11 +1,16 @@
|
||||
import { Building2, Bike, Factory, Users, FileText, TrendingUp, Box, MapPin, Calendar, Image as ImageIcon } from 'lucide-react';
|
||||
import { Building2, Bike, Factory, Users, FileText, TrendingUp, Box, Image as ImageIcon, Activity, BarChart3, Shield } from 'lucide-react';
|
||||
import { AdminLayout } from '@/components/layout/AdminLayout';
|
||||
import { useAdminGuard } from '@/hooks/useAdminGuard';
|
||||
import { DatabaseStatsCard } from '@/components/admin/database-stats/DatabaseStatsCard';
|
||||
import { RecentAdditionsTable } from '@/components/admin/database-stats/RecentAdditionsTable';
|
||||
import { DataQualityOverview } from '@/components/admin/database-stats/DataQualityOverview';
|
||||
import { GrowthTrendsChart } from '@/components/admin/database-stats/GrowthTrendsChart';
|
||||
import { EntityComparisonDashboard } from '@/components/admin/database-stats/EntityComparisonDashboard';
|
||||
import { DatabaseHealthDashboard } from '@/components/admin/database-stats/DatabaseHealthDashboard';
|
||||
import { useAdminDatabaseStats } from '@/hooks/useAdminDatabaseStats';
|
||||
import { useRecentAdditions } from '@/hooks/useRecentAdditions';
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert';
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { AlertCircle } from 'lucide-react';
|
||||
|
||||
export default function AdminDatabaseStats() {
|
||||
@@ -58,103 +63,166 @@ export default function AdminDatabaseStats() {
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold tracking-tight">Database Statistics</h1>
|
||||
<p className="text-muted-foreground mt-2">
|
||||
Complete overview of database content and activity
|
||||
Comprehensive analytics, quality metrics, and health monitoring
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Stats Grid */}
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<DatabaseStatsCard
|
||||
title="Total Entities"
|
||||
icon={Box}
|
||||
iconClassName="text-blue-500"
|
||||
stats={[
|
||||
{ label: 'All Entities', value: totalEntities },
|
||||
{ label: 'Parks', value: stats?.parks.total || 0 },
|
||||
{ label: 'Rides', value: stats?.rides.total || 0 },
|
||||
{ label: 'Companies', value: stats?.companies.total || 0 },
|
||||
{ label: 'Ride Models', value: stats?.ride_models.total || 0 },
|
||||
]}
|
||||
/>
|
||||
<Tabs defaultValue="overview" className="space-y-6">
|
||||
<TabsList className="grid w-full grid-cols-5">
|
||||
<TabsTrigger value="overview" className="flex items-center gap-2">
|
||||
<Box className="h-4 w-4" />
|
||||
Overview
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="growth" className="flex items-center gap-2">
|
||||
<TrendingUp className="h-4 w-4" />
|
||||
Growth Trends
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="comparisons" className="flex items-center gap-2">
|
||||
<BarChart3 className="h-4 w-4" />
|
||||
Comparisons
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="quality" className="flex items-center gap-2">
|
||||
<Activity className="h-4 w-4" />
|
||||
Data Quality
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="health" className="flex items-center gap-2">
|
||||
<Shield className="h-4 w-4" />
|
||||
Health Checks
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<DatabaseStatsCard
|
||||
title="Recent Activity"
|
||||
icon={TrendingUp}
|
||||
iconClassName="text-green-500"
|
||||
stats={[
|
||||
{
|
||||
label: 'Added (7 days)',
|
||||
value: recentAdditions7d,
|
||||
},
|
||||
{
|
||||
label: 'Added (30 days)',
|
||||
value: recentAdditions30d,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
{/* Overview Tab */}
|
||||
<TabsContent value="overview" className="space-y-6">
|
||||
{/* Stats Grid */}
|
||||
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
|
||||
<DatabaseStatsCard
|
||||
title="Total Entities"
|
||||
icon={Box}
|
||||
iconClassName="text-blue-500"
|
||||
stats={[
|
||||
{ label: 'All Entities', value: totalEntities },
|
||||
{ label: 'Parks', value: stats?.parks.total || 0 },
|
||||
{ label: 'Rides', value: stats?.rides.total || 0 },
|
||||
{ label: 'Companies', value: stats?.companies.total || 0 },
|
||||
{ label: 'Ride Models', value: stats?.ride_models.total || 0 },
|
||||
]}
|
||||
/>
|
||||
|
||||
<DatabaseStatsCard
|
||||
title="Parks & Rides"
|
||||
icon={Building2}
|
||||
iconClassName="text-purple-500"
|
||||
stats={[
|
||||
{ label: 'Active Parks', value: stats?.parks.active || 0 },
|
||||
{ label: 'Historical Parks', value: stats?.parks.historical || 0 },
|
||||
{ label: 'Active Rides', value: stats?.rides.active || 0 },
|
||||
{ label: 'Historical Rides', value: stats?.rides.historical || 0 },
|
||||
]}
|
||||
/>
|
||||
<DatabaseStatsCard
|
||||
title="Recent Activity"
|
||||
icon={TrendingUp}
|
||||
iconClassName="text-green-500"
|
||||
stats={[
|
||||
{
|
||||
label: 'Added (7 days)',
|
||||
value: recentAdditions7d,
|
||||
},
|
||||
{
|
||||
label: 'Added (30 days)',
|
||||
value: recentAdditions30d,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
|
||||
<DatabaseStatsCard
|
||||
title="Content"
|
||||
icon={ImageIcon}
|
||||
iconClassName="text-orange-500"
|
||||
stats={[
|
||||
{ label: 'Photos', value: stats?.photos.total || 0 },
|
||||
{ label: 'Locations', value: stats?.locations.total || 0 },
|
||||
{ label: 'Timeline Events', value: stats?.timeline_events.total || 0 },
|
||||
]}
|
||||
/>
|
||||
<DatabaseStatsCard
|
||||
title="Parks & Rides"
|
||||
icon={Building2}
|
||||
iconClassName="text-purple-500"
|
||||
stats={[
|
||||
{ label: 'Active Parks', value: stats?.parks.active || 0 },
|
||||
{ label: 'Historical Parks', value: stats?.parks.historical || 0 },
|
||||
{ label: 'Active Rides', value: stats?.rides.active || 0 },
|
||||
{ label: 'Historical Rides', value: stats?.rides.historical || 0 },
|
||||
]}
|
||||
/>
|
||||
|
||||
<DatabaseStatsCard
|
||||
title="Companies"
|
||||
icon={Factory}
|
||||
iconClassName="text-amber-500"
|
||||
stats={[
|
||||
{ label: 'Total', value: stats?.companies.total || 0 },
|
||||
{ label: 'Manufacturers', value: stats?.companies.manufacturers || 0 },
|
||||
{ label: 'Operators', value: stats?.companies.operators || 0 },
|
||||
{ label: 'Designers', value: stats?.companies.designers || 0 },
|
||||
]}
|
||||
/>
|
||||
<DatabaseStatsCard
|
||||
title="Content"
|
||||
icon={ImageIcon}
|
||||
iconClassName="text-orange-500"
|
||||
stats={[
|
||||
{ label: 'Photos', value: stats?.photos.total || 0 },
|
||||
{ label: 'Locations', value: stats?.locations.total || 0 },
|
||||
{ label: 'Timeline Events', value: stats?.timeline_events.total || 0 },
|
||||
]}
|
||||
/>
|
||||
|
||||
<DatabaseStatsCard
|
||||
title="User Activity"
|
||||
icon={Users}
|
||||
iconClassName="text-teal-500"
|
||||
stats={[
|
||||
{ label: 'Total Users', value: stats?.users.total || 0 },
|
||||
{ label: 'Active (30 days)', value: stats?.users.active_30d || 0 },
|
||||
]}
|
||||
/>
|
||||
<DatabaseStatsCard
|
||||
title="Companies"
|
||||
icon={Factory}
|
||||
iconClassName="text-amber-500"
|
||||
stats={[
|
||||
{ label: 'Total', value: stats?.companies.total || 0 },
|
||||
{ label: 'Manufacturers', value: stats?.companies.manufacturers || 0 },
|
||||
{ label: 'Operators', value: stats?.companies.operators || 0 },
|
||||
{ label: 'Designers', value: stats?.companies.designers || 0 },
|
||||
]}
|
||||
/>
|
||||
|
||||
<DatabaseStatsCard
|
||||
title="Submissions"
|
||||
icon={FileText}
|
||||
iconClassName="text-pink-500"
|
||||
stats={[
|
||||
{ label: 'Pending', value: stats?.submissions.pending || 0 },
|
||||
{ label: 'Approved', value: stats?.submissions.approved || 0 },
|
||||
{ label: 'Rejected', value: stats?.submissions.rejected || 0 },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
<DatabaseStatsCard
|
||||
title="User Activity"
|
||||
icon={Users}
|
||||
iconClassName="text-teal-500"
|
||||
stats={[
|
||||
{ label: 'Total Users', value: stats?.users.total || 0 },
|
||||
{ label: 'Active (30 days)', value: stats?.users.active_30d || 0 },
|
||||
]}
|
||||
/>
|
||||
|
||||
{/* Recent Additions Table */}
|
||||
<RecentAdditionsTable
|
||||
additions={recentAdditions || []}
|
||||
isLoading={additionsLoading}
|
||||
/>
|
||||
<DatabaseStatsCard
|
||||
title="Submissions"
|
||||
icon={FileText}
|
||||
iconClassName="text-pink-500"
|
||||
stats={[
|
||||
{ label: 'Pending', value: stats?.submissions.pending || 0 },
|
||||
{ label: 'Approved', value: stats?.submissions.approved || 0 },
|
||||
{ label: 'Rejected', value: stats?.submissions.rejected || 0 },
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Data Quality Overview */}
|
||||
<DataQualityOverview />
|
||||
|
||||
{/* Recent Additions Table */}
|
||||
<RecentAdditionsTable
|
||||
additions={recentAdditions || []}
|
||||
isLoading={additionsLoading}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
{/* Growth Trends Tab */}
|
||||
<TabsContent value="growth" className="space-y-6">
|
||||
<GrowthTrendsChart />
|
||||
</TabsContent>
|
||||
|
||||
{/* Entity Comparisons Tab */}
|
||||
<TabsContent value="comparisons" className="space-y-6">
|
||||
<EntityComparisonDashboard />
|
||||
</TabsContent>
|
||||
|
||||
{/* Data Quality Tab */}
|
||||
<TabsContent value="quality" className="space-y-6">
|
||||
<DataQualityOverview />
|
||||
<div className="p-6 border rounded-lg bg-muted/50">
|
||||
<h3 className="text-lg font-semibold mb-2">Full Data Completeness Dashboard</h3>
|
||||
<p className="text-sm text-muted-foreground mb-4">
|
||||
For detailed analysis of data completeness by entity, missing fields, and improvement opportunities.
|
||||
</p>
|
||||
<a
|
||||
href="/admin/data-completeness"
|
||||
className="inline-flex items-center gap-2 text-primary hover:underline"
|
||||
>
|
||||
View Full Dashboard →
|
||||
</a>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
{/* Database Health Tab */}
|
||||
<TabsContent value="health" className="space-y-6">
|
||||
<DatabaseHealthDashboard />
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
</AdminLayout>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user