mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 17:31:13 -05:00
178 lines
7.4 KiB
TypeScript
178 lines
7.4 KiB
TypeScript
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { BarChart, Bar, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';
|
|
import { AlertCircle, TrendingUp, Users, Zap, CheckCircle, XCircle } from 'lucide-react';
|
|
|
|
interface ErrorSummary {
|
|
error_type: string | null;
|
|
occurrence_count: number | null;
|
|
affected_users: number | null;
|
|
avg_duration_ms: number | null;
|
|
}
|
|
|
|
interface ApprovalMetric {
|
|
id: string;
|
|
success: boolean;
|
|
duration_ms: number | null;
|
|
created_at: string | null;
|
|
}
|
|
|
|
interface ErrorAnalyticsProps {
|
|
errorSummary: ErrorSummary[] | undefined;
|
|
approvalMetrics: ApprovalMetric[] | undefined;
|
|
}
|
|
|
|
export function ErrorAnalytics({ errorSummary, approvalMetrics }: ErrorAnalyticsProps) {
|
|
// Calculate error metrics
|
|
const totalErrors = errorSummary?.reduce((sum, item) => sum + (item.occurrence_count || 0), 0) || 0;
|
|
const totalAffectedUsers = errorSummary?.reduce((sum, item) => sum + (item.affected_users || 0), 0) || 0;
|
|
const avgErrorDuration = errorSummary?.length
|
|
? errorSummary.reduce((sum, item) => sum + (item.avg_duration_ms || 0), 0) / errorSummary.length
|
|
: 0;
|
|
const topErrors = errorSummary?.slice(0, 5) || [];
|
|
|
|
// Calculate approval metrics
|
|
const totalApprovals = approvalMetrics?.length || 0;
|
|
const failedApprovals = approvalMetrics?.filter(m => !m.success).length || 0;
|
|
const successRate = totalApprovals > 0 ? ((totalApprovals - failedApprovals) / totalApprovals) * 100 : 0;
|
|
const avgApprovalDuration = approvalMetrics?.length
|
|
? approvalMetrics.reduce((sum, m) => sum + (m.duration_ms || 0), 0) / approvalMetrics.length
|
|
: 0;
|
|
|
|
// Show message if no data available
|
|
if ((!errorSummary || errorSummary.length === 0) && (!approvalMetrics || approvalMetrics.length === 0)) {
|
|
return (
|
|
<Card>
|
|
<CardContent className="pt-6">
|
|
<p className="text-center text-muted-foreground">No analytics data available</p>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
{/* Error Metrics */}
|
|
{errorSummary && errorSummary.length > 0 && (
|
|
<>
|
|
<div>
|
|
<h3 className="text-lg font-semibold mb-3">Error Metrics</h3>
|
|
<div className="grid gap-4 md:grid-cols-4">
|
|
<Card>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">Total Errors</CardTitle>
|
|
<AlertCircle className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">{totalErrors}</div>
|
|
<p className="text-xs text-muted-foreground">Last 30 days</p>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">Error Types</CardTitle>
|
|
<TrendingUp className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">{errorSummary.length}</div>
|
|
<p className="text-xs text-muted-foreground">Unique error types</p>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">Affected Users</CardTitle>
|
|
<Users className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">{totalAffectedUsers}</div>
|
|
<p className="text-xs text-muted-foreground">Users impacted</p>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">Avg Duration</CardTitle>
|
|
<Zap className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">{Math.round(avgErrorDuration)}ms</div>
|
|
<p className="text-xs text-muted-foreground">Before error occurs</p>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
|
|
<Card>
|
|
<CardHeader>
|
|
<CardTitle>Top 5 Errors</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<ResponsiveContainer width="100%" height={300}>
|
|
<BarChart data={topErrors}>
|
|
<XAxis dataKey="error_type" />
|
|
<YAxis />
|
|
<Tooltip />
|
|
<Bar dataKey="occurrence_count" fill="hsl(var(--destructive))" />
|
|
</BarChart>
|
|
</ResponsiveContainer>
|
|
</CardContent>
|
|
</Card>
|
|
</>
|
|
)}
|
|
|
|
{/* Approval Metrics */}
|
|
{approvalMetrics && approvalMetrics.length > 0 && (
|
|
<div>
|
|
<h3 className="text-lg font-semibold mb-3">Approval Metrics</h3>
|
|
<div className="grid gap-4 md:grid-cols-4">
|
|
<Card>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">Total Approvals</CardTitle>
|
|
<CheckCircle className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">{totalApprovals}</div>
|
|
<p className="text-xs text-muted-foreground">Last 24 hours</p>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">Failures</CardTitle>
|
|
<XCircle className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold text-destructive">{failedApprovals}</div>
|
|
<p className="text-xs text-muted-foreground">Failed approvals</p>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">Success Rate</CardTitle>
|
|
<TrendingUp className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">{successRate.toFixed(1)}%</div>
|
|
<p className="text-xs text-muted-foreground">Overall success rate</p>
|
|
</CardContent>
|
|
</Card>
|
|
|
|
<Card>
|
|
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
|
|
<CardTitle className="text-sm font-medium">Avg Duration</CardTitle>
|
|
<Zap className="h-4 w-4 text-muted-foreground" />
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="text-2xl font-bold">{Math.round(avgApprovalDuration)}ms</div>
|
|
<p className="text-xs text-muted-foreground">Approval time</p>
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|