fix: frontend error handling — ErrorBoundary, type-safe errors, stable keys

- React ErrorBoundary wrapping entire app for graceful crash recovery
- fetchJSON error handling uses try/catch instead of .catch() chain
- CertificateDetailPage: instanceof checks replace unsafe type casts
- DataTable: keyField prop replaces array index keys

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
shankar0123
2026-03-20 01:20:32 -04:00
parent 7618c5a734
commit bb7a78352e
5 changed files with 91 additions and 31 deletions
+3 -2
View File
@@ -11,9 +11,10 @@ interface DataTableProps<T> {
onRowClick?: (item: T) => void;
emptyMessage?: string;
isLoading?: boolean;
keyField?: string;
}
export default function DataTable<T>({ columns, data, onRowClick, emptyMessage, isLoading }: DataTableProps<T>) {
export default function DataTable<T>({ columns, data, onRowClick, emptyMessage, isLoading, keyField = 'id' }: DataTableProps<T>) {
if (isLoading) {
return (
<div className="flex items-center justify-center py-16 text-slate-400">
@@ -49,7 +50,7 @@ export default function DataTable<T>({ columns, data, onRowClick, emptyMessage,
<tbody>
{data.map((item, i) => (
<tr
key={i}
key={(item as Record<string, unknown>)[keyField] as string ?? `row-${i}`}
onClick={() => onRowClick?.(item)}
className={`border-b border-slate-700/50 transition-colors hover:bg-blue-500/5 ${onRowClick ? 'cursor-pointer' : ''}`}
>