Files
thrilltrack-explorer/src/components/admin/data-completeness/DataCompletenessDashboard.tsx
gpt-engineer-app[bot] 69db3c7743 Integrate Data Completeness Dashboard
Adds comprehensive data completeness dashboard UI and hooks:
- Introduces data completeness types and hook (useDataCompleteness) to fetch and subscribe to updates
- Builds dashboard components (summary, filters, table) and integrates into Admin Settings
- Wireframes for real-time updates and filtering across parks, rides, companies, and ride models
- Integrates into AdminSettings with a new Data Quality tab and route
- Adds data types and scaffolding for analytics, including completeness analysis structure
2025-11-11 16:38:26 +00:00

146 lines
4.8 KiB
TypeScript

/**
* Data Completeness Dashboard
*
* Main dashboard component combining summary, filters, and table
* Provides comprehensive view of data quality across all entity types
*/
import { useState, useMemo } from 'react';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Alert, AlertDescription } from '@/components/ui/alert';
import { Loader2, AlertCircle, RefreshCw } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useDataCompleteness } from '@/hooks/useDataCompleteness';
import { CompletenessSummary } from './CompletenesSummary';
import { CompletenessFilters } from './CompletenessFilters';
import { CompletenessTable } from './CompletenessTable';
import type { CompletenessFilters as Filters, EntityType } from '@/types/data-completeness';
export function DataCompletenessDashboard() {
const [filters, setFilters] = useState<Filters>({});
const { data, isLoading, error, refetch, isRefetching } = useDataCompleteness(filters);
// Combine all entities for the "All" tab
const allEntities = useMemo(() => {
if (!data) return [];
return [
...data.entities.parks,
...data.entities.rides,
...data.entities.companies,
...data.entities.ride_models,
];
}, [data]);
if (isLoading) {
return (
<div className="flex items-center justify-center py-12">
<Loader2 className="h-8 w-8 animate-spin text-muted-foreground" />
<span className="ml-2 text-muted-foreground">Analyzing data completeness...</span>
</div>
);
}
if (error) {
return (
<Alert variant="destructive">
<AlertCircle className="h-4 w-4" />
<AlertDescription>
Failed to load data completeness analysis. Please try again.
</AlertDescription>
</Alert>
);
}
if (!data) return null;
return (
<div className="space-y-6">
<div className="flex items-center justify-between">
<div>
<h1 className="text-3xl font-bold">Data Completeness Dashboard</h1>
<p className="text-muted-foreground">
Monitor and improve data quality across all entities
</p>
</div>
<Button
onClick={() => refetch()}
disabled={isRefetching}
variant="outline"
>
{isRefetching ? (
<Loader2 className="h-4 w-4 animate-spin mr-2" />
) : (
<RefreshCw className="h-4 w-4 mr-2" />
)}
Refresh
</Button>
</div>
<CompletenessSummary summary={data.summary} />
<Card>
<CardHeader>
<CardTitle>Filter Entities</CardTitle>
<CardDescription>
Filter by entity type, completeness score, and missing field categories
</CardDescription>
</CardHeader>
<CardContent>
<CompletenessFilters filters={filters} onFiltersChange={setFilters} />
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Entity Details</CardTitle>
<CardDescription>
Entities sorted by completeness (most incomplete first)
</CardDescription>
</CardHeader>
<CardContent>
<Tabs defaultValue="all" className="space-y-4">
<TabsList>
<TabsTrigger value="all">
All ({allEntities.length})
</TabsTrigger>
<TabsTrigger value="parks">
Parks ({data.entities.parks.length})
</TabsTrigger>
<TabsTrigger value="rides">
Rides ({data.entities.rides.length})
</TabsTrigger>
<TabsTrigger value="companies">
Companies ({data.entities.companies.length})
</TabsTrigger>
<TabsTrigger value="ride_models">
Ride Models ({data.entities.ride_models.length})
</TabsTrigger>
</TabsList>
<TabsContent value="all">
<CompletenessTable entities={allEntities} filters={filters} />
</TabsContent>
<TabsContent value="parks">
<CompletenessTable entities={data.entities.parks} filters={filters} />
</TabsContent>
<TabsContent value="rides">
<CompletenessTable entities={data.entities.rides} filters={filters} />
</TabsContent>
<TabsContent value="companies">
<CompletenessTable entities={data.entities.companies} filters={filters} />
</TabsContent>
<TabsContent value="ride_models">
<CompletenessTable entities={data.entities.ride_models} filters={filters} />
</TabsContent>
</Tabs>
</CardContent>
</Card>
</div>
);
}