diff --git a/client/src/pages/webhooks.tsx b/client/src/pages/webhooks.tsx index a26ef2b..318c816 100644 --- a/client/src/pages/webhooks.tsx +++ b/client/src/pages/webhooks.tsx @@ -76,8 +76,11 @@ export default function WebhooksPage() { const [isDeleteOpen, setIsDeleteOpen] = useState(false); const [isTestResultOpen, setIsTestResultOpen] = useState(false); const [isHistorySheetOpen, setIsHistorySheetOpen] = useState(false); + const [isLogsDialogOpen, setIsLogsDialogOpen] = useState(false); const [currentWebhook, setCurrentWebhook] = useState(null); + const [currentWebhookId, setCurrentWebhookId] = useState(null); const [testResult, setTestResult] = useState(null); + const [selectedLog, setSelectedLog] = useState(null); // Form state for create/edit const [formData, setFormData] = useState({ @@ -229,6 +232,21 @@ export default function WebhooksPage() { }); }, }); + + // Fetch webhook delivery logs + const { + data: webhookLogs = [], + isLoading: isLogsLoading, + error: logsError, + } = useQuery({ + queryKey: ["/api/webhooks", currentWebhookId, "logs"], + queryFn: async () => { + if (!currentWebhookId) return []; + const res = await apiRequest("GET", `/api/webhooks/${currentWebhookId}/logs`); + return await res.json(); + }, + enabled: !!currentWebhookId && isLogsDialogOpen, + }); const handleCreateSubmit = (e: React.FormEvent) => { e.preventDefault(); @@ -271,6 +289,15 @@ export default function WebhooksPage() { setCurrentWebhook(webhook); setIsDeleteOpen(true); }; + + const handleViewLogs = (webhookId: string) => { + setCurrentWebhookId(webhookId); + const webhook = webhooks.find((w: Webhook) => w.id === webhookId); + if (webhook) { + setCurrentWebhook(webhook); + } + setIsLogsDialogOpen(true); + }; // Event options for the select component const eventOptions = [ @@ -281,8 +308,11 @@ export default function WebhooksPage() { ]; // Helper to format the date - const formatDate = (dateString: string | null | undefined) => { + const formatDate = (dateString: string | Date | null | undefined) => { if (!dateString) return "Never"; + if (dateString instanceof Date) { + return dateString.toLocaleString(); + } return new Date(dateString).toLocaleString(); }; @@ -387,6 +417,14 @@ export default function WebhooksPage() {
+ +
+ ) : ( +
+
+ + + + Event + Status + Time + Actions + + + + {webhookLogs.map((log: WebhookDeliveryLog) => ( + + {log.event} + + {log.status ? ( + Success + ) : ( + Failed + )} + + + {formatDate(log.createdAt)} + + + + + + ))} + +
+
+ + {selectedLog && ( +
+
+

Delivery Details

+ +
+ +
+
+

Status

+
+ {selectedLog.status ? ( + + Success ({selectedLog.statusCode || 200}) + + ) : ( + + Failed {selectedLog.statusCode && `(${selectedLog.statusCode})`} + + )} + {selectedLog.retryCount > 0 && ( + + Retry {selectedLog.retryCount} + + )} +
+
+ + {selectedLog.message && ( +
+

Message

+
+ {selectedLog.message} +
+
+ )} + +
+

Payload

+
+
+                          {JSON.stringify(selectedLog.payload, null, 2)}
+                        
+
+
+ + {selectedLog.responseBody && ( +
+

Response

+
+
+                            {selectedLog.responseBody}
+                          
+
+
+ )} + + {selectedLog.signature && ( +
+

Signature

+
+ {selectedLog.signature} +
+
+ )} +
+
+ )} +
+ )} + + + + + + ); } \ No newline at end of file