Files
awoooi/apps/web/src/components/genui/SentryErrorCard.tsx
OG T 4d46e6b9a7
Some checks failed
E2E Health Check / e2e-health (push) Successful in 17s
CD Pipeline / build-and-deploy (push) Has been cancelled
style(web): 全站 font-mono → font-body (DM Mono 設計系統套用)
45 個 component + 6 個 page 統一從舊 font-mono 遷移到
font-body (DM Mono),確保設計系統一致性。

font-body = DM Mono (等寬),視覺效果相同但走新設計 token。
保留: font-heading (Syne)、font-dot-matrix (VT323/DSEG7)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 09:37:03 +08:00

88 lines
2.6 KiB
TypeScript

/**
* SentryErrorCard - Sentry Error Display
* =======================================
* Phase 19.4a - GenUI 錯誤追蹤卡
*
* @see ADR-032 GenUI Dynamic Rendering
* @author Claude Code (首席架構師)
* @version 1.0.0
* @date 2026-03-28 (台北時間)
*/
import React from 'react'
import { Bug, ExternalLink } from 'lucide-react'
interface SentryErrorCardProps {
data: {
errorId: string
title: string
count?: number
lastSeen?: string
level?: 'error' | 'warning' | 'info'
url?: string
}
}
export const SentryErrorCard: React.FC<SentryErrorCardProps> = ({ data }) => {
const level = data.level || 'error'
const levelColors = {
error: 'border-red-500 text-red-600',
warning: 'border-yellow-500 text-yellow-600',
info: 'border-blue-500 text-blue-600',
}
return (
<div className="w-full max-w-2xl bg-white border-2 border-nothing-black shadow-lg rounded-sm overflow-hidden mt-4 mb-2">
<div className="flex border-b-2 border-nothing-black bg-nothing-gray-50 p-3 items-center justify-between">
<div className="flex items-center gap-2">
<Bug className={levelColors[level]} size={20} />
<span className="font-['VT323'] text-xl font-bold uppercase tracking-wider text-nothing-black">
Sentry // {data.errorId}
</span>
</div>
<div className={`px-2 py-1 text-xs font-body font-bold border-2 ${levelColors[level]} uppercase`}>
{level}
</div>
</div>
<div className="p-4 space-y-3">
<div>
<span className="text-xs uppercase font-body font-bold text-gray-500 tracking-wider">
Error
</span>
<div className="mt-1 font-['VT323'] text-xl text-nothing-black">
{data.title}
</div>
</div>
<div className="flex gap-4 text-sm font-body">
{data.count !== undefined && (
<div>
<span className="text-gray-500">Count:</span>{' '}
<span className="font-bold">{data.count}</span>
</div>
)}
{data.lastSeen && (
<div>
<span className="text-gray-500">Last seen:</span>{' '}
<span className="font-bold">{data.lastSeen}</span>
</div>
)}
</div>
{data.url && (
<a
href={data.url}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 text-sm font-body text-[#4A90D9] hover:underline"
>
View in Sentry <ExternalLink size={14} />
</a>
)}
</div>
</div>
)
}