Approve database migration

This commit is contained in:
gpt-engineer-app[bot]
2025-11-03 15:18:06 +00:00
parent 5612d19d07
commit a86da6e833
17 changed files with 1189 additions and 36 deletions

View File

@@ -0,0 +1,173 @@
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { Copy, ExternalLink } from 'lucide-react';
import { format } from 'date-fns';
import { toast } from 'sonner';
interface ErrorDetailsModalProps {
error: any;
onClose: () => void;
}
export function ErrorDetailsModal({ error, onClose }: ErrorDetailsModalProps) {
const copyErrorId = () => {
navigator.clipboard.writeText(error.request_id);
toast.success('Error ID copied to clipboard');
};
const copyErrorReport = () => {
const report = `
Error Report
============
Request ID: ${error.request_id}
Timestamp: ${format(new Date(error.created_at), 'PPpp')}
Type: ${error.error_type}
Endpoint: ${error.endpoint}
Method: ${error.method}
Status: ${error.status_code}
Duration: ${error.duration_ms}ms
Error Message:
${error.error_message}
${error.error_stack ? `Stack Trace:\n${error.error_stack}` : ''}
`.trim();
navigator.clipboard.writeText(report);
toast.success('Error report copied to clipboard');
};
return (
<Dialog open onOpenChange={onClose}>
<DialogContent className="max-w-4xl max-h-[80vh] overflow-y-auto">
<DialogHeader>
<DialogTitle className="flex items-center gap-2">
Error Details
<Badge variant="destructive">{error.error_type}</Badge>
</DialogTitle>
</DialogHeader>
<Tabs defaultValue="overview" className="w-full">
<TabsList>
<TabsTrigger value="overview">Overview</TabsTrigger>
<TabsTrigger value="stack">Stack Trace</TabsTrigger>
<TabsTrigger value="breadcrumbs">Breadcrumbs</TabsTrigger>
<TabsTrigger value="environment">Environment</TabsTrigger>
</TabsList>
<TabsContent value="overview" className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-sm font-medium">Request ID</label>
<div className="flex items-center gap-2">
<code className="text-sm bg-muted px-2 py-1 rounded">
{error.request_id}
</code>
<Button size="sm" variant="ghost" onClick={copyErrorId}>
<Copy className="w-4 h-4" />
</Button>
</div>
</div>
<div>
<label className="text-sm font-medium">Timestamp</label>
<p className="text-sm">{format(new Date(error.created_at), 'PPpp')}</p>
</div>
<div>
<label className="text-sm font-medium">Endpoint</label>
<p className="text-sm font-mono">{error.endpoint}</p>
</div>
<div>
<label className="text-sm font-medium">Method</label>
<Badge variant="outline">{error.method}</Badge>
</div>
<div>
<label className="text-sm font-medium">Status Code</label>
<p className="text-sm">{error.status_code}</p>
</div>
<div>
<label className="text-sm font-medium">Duration</label>
<p className="text-sm">{error.duration_ms}ms</p>
</div>
{error.user_id && (
<div>
<label className="text-sm font-medium">User ID</label>
<a
href={`/admin/users?search=${error.user_id}`}
className="text-sm text-primary hover:underline flex items-center gap-1"
>
{error.user_id.slice(0, 8)}...
<ExternalLink className="w-3 h-3" />
</a>
</div>
)}
</div>
<div>
<label className="text-sm font-medium">Error Message</label>
<div className="bg-muted p-4 rounded-lg mt-2">
<p className="text-sm font-mono">{error.error_message}</p>
</div>
</div>
</TabsContent>
<TabsContent value="stack">
{error.error_stack ? (
<pre className="bg-muted p-4 rounded-lg overflow-x-auto text-xs">
{error.error_stack}
</pre>
) : (
<p className="text-muted-foreground">No stack trace available</p>
)}
</TabsContent>
<TabsContent value="breadcrumbs">
{error.breadcrumbs && error.breadcrumbs.length > 0 ? (
<div className="space-y-2">
{error.breadcrumbs.map((crumb: any, index: number) => (
<div key={index} className="border-l-2 border-primary pl-4 py-2">
<div className="flex items-center gap-2 mb-1">
<Badge variant="outline" className="text-xs">
{crumb.category}
</Badge>
<span className="text-xs text-muted-foreground">
{format(new Date(crumb.timestamp), 'HH:mm:ss.SSS')}
</span>
</div>
<p className="text-sm">{crumb.message}</p>
{crumb.data && (
<pre className="text-xs text-muted-foreground mt-1">
{JSON.stringify(crumb.data, null, 2)}
</pre>
)}
</div>
))}
</div>
) : (
<p className="text-muted-foreground">No breadcrumbs recorded</p>
)}
</TabsContent>
<TabsContent value="environment">
{error.environment_context ? (
<pre className="bg-muted p-4 rounded-lg overflow-x-auto text-xs">
{JSON.stringify(error.environment_context, null, 2)}
</pre>
) : (
<p className="text-muted-foreground">No environment context available</p>
)}
</TabsContent>
</Tabs>
<div className="flex justify-end gap-2">
<Button variant="outline" onClick={copyErrorReport}>
<Copy className="w-4 h-4 mr-2" />
Copy Report
</Button>
<Button onClick={onClose}>Close</Button>
</div>
</DialogContent>
</Dialog>
);
}