refactor(web): ErrorsPanel 抽取 — /observability 3 個 Tab 已無雙重 Layout
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled

This commit is contained in:
OG T
2026-04-09 10:51:59 +08:00
parent 22fa6ea413
commit 11fc2860cf
4 changed files with 66 additions and 154 deletions

View File

@@ -0,0 +1,58 @@
'use client'
/**
* ErrorsPanel — 錯誤追蹤面板 (不含 AppLayout)
* Sprint 5: 從 /errors/page.tsx 抽取
*/
import { useTranslations } from 'next-intl'
import { useErrors } from '@/hooks/useErrors'
import { useUXAudit } from '@/hooks/useUXAudit'
import {
ErrorOverviewCard,
RecentIssuesList,
ErrorTrendChart,
UXAuditCard,
} from '@/components/errors'
import { Bug, RefreshCw } from 'lucide-react'
import type { SentryIssue } from '@/lib/api-client'
export function ErrorsPanel() {
const t = useTranslations('errors')
const { stats, issues, trends, loading, error, activePeriod, refetch, setPeriod } = useErrors()
const { data: uxAuditData, loading: uxAuditLoading, error: uxAuditError } = useUXAudit()
const handleIssueClick = (issue: SentryIssue) => {
if (issue.permalink) window.open(issue.permalink, '_blank', 'noopener,noreferrer')
}
return (
<div className="p-6 max-w-7xl mx-auto">
<div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-3">
<Bug className="h-6 w-6 text-gray-700" />
<div>
<h1 className="text-xl font-semibold text-gray-900">{t('title')}</h1>
<p className="text-sm text-gray-500">{t('subtitle')}</p>
</div>
</div>
<button onClick={refetch} disabled={loading} className="flex items-center gap-1.5 px-3 py-1.5 text-sm bg-gray-100 hover:bg-gray-200 rounded transition-colors disabled:opacity-50 disabled:cursor-not-allowed">
<RefreshCw className={`h-4 w-4 ${loading ? 'animate-spin' : ''}`} />
{loading ? t('loading') : t('refresh')}
</button>
</div>
{error && <div className="mb-6 p-4 bg-red-50 border border-red-200 rounded-sm"><p className="text-sm text-red-700">{error}</p></div>}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
<div className="lg:col-span-1 space-y-6">
<ErrorOverviewCard stats={stats} loading={loading} changePercent={trends?.change_percent} />
<ErrorTrendChart data={trends} loading={loading} activePeriod={activePeriod} onPeriodChange={setPeriod} />
<UXAuditCard data={uxAuditData} loading={uxAuditLoading} error={uxAuditError} />
</div>
<div className="lg:col-span-2">
<RecentIssuesList issues={issues} loading={loading} onIssueClick={handleIssueClick} />
</div>
</div>
<div className="mt-6 pt-4 border-t border-gray-100"><p className="text-xs text-gray-400 text-center">{t('footerInfo')}</p></div>
</div>
)
}

View File

@@ -14,3 +14,4 @@
export { MonitoringPanel } from './MonitoringPanel'
export { ApmPanel } from './ApmPanel'
export { ErrorsPanel } from './ErrorsPanel'