'use client' /** * ErrorOverviewCard - #41 錯誤統計卡片 * ===================================== * Phase 10: Sentry + OpenClaw + UI 整合 * * Nothing.tech 視覺規範: * - 純白底色 (bg-white) * - 極細淺灰邊框 (border border-gray-200) * - 無圓角或微圓角 (rounded-sm) * - 嚴禁陰影 (shadow-none) * * 建立: 2026-03-26 (台北時區) * 建立者: Claude Code (#41 Error UI) */ import { useTranslations } from 'next-intl' import { cn } from '@/lib/utils' import { AlertTriangle, Bug, Clock, TrendingUp, TrendingDown, Minus } from 'lucide-react' import type { ErrorStatsResponse } from '@/lib/api-client' // ============================================================================= // Component Props // ============================================================================= interface ErrorOverviewCardProps { stats: ErrorStatsResponse | null loading?: boolean error?: string | null changePercent?: number className?: string } // ============================================================================= // Component // ============================================================================= export function ErrorOverviewCard({ stats, loading = false, error = null, changePercent = 0, className, }: ErrorOverviewCardProps) { const t = useTranslations('errors') // Loading state if (loading) { return (
) } // Error state if (error) { return (
{error}
) } // Empty state if (!stats) { return (

{t('noData')}

) } // Trend indicator const TrendIcon = changePercent > 0 ? TrendingUp : changePercent < 0 ? TrendingDown : Minus const trendColor = changePercent > 0 ? 'text-red-500' : changePercent < 0 ? 'text-green-500' : 'text-gray-400' return (
{/* Header */}

{t('overview')}

{changePercent !== 0 && (
{Math.abs(changePercent).toFixed(1)}%
)}
{/* Stats Grid */}
{/* Unresolved Issues */}
{stats.unresolved_issues}
{t('unresolvedIssues')}
{/* 24h Errors */}
{stats.error_count_24h}
{t('errors24h')}
{/* Critical Count */}
{stats.critical_count}
{t('criticalErrors')}
{/* Total Issues */}
{stats.total_issues}
{t('totalIssues')}
{/* Projects */} {stats.projects.length > 0 && (
{t('projects')}: {stats.projects.join(', ')}
)}
) }