'use client'; import { useCallback, useEffect, useState } from 'react'; import { Button } from '@/components/ui/button'; import { PageHeader } from '@/components/shared/page-header'; import { Badge } from '@/components/ui/badge'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from '@/components/ui/alert-dialog'; import { apiFetch } from '@/lib/api/client'; import { WebhookForm } from '@/components/admin/webhooks/webhook-form'; import { WebhookDeliveryLog } from '@/components/admin/webhooks/webhook-delivery-log'; import { WebhookSecretDisplay } from '@/components/admin/webhooks/webhook-secret-display'; interface Webhook { id: string; name: string; url: string; events: string[]; isActive: boolean; secretMasked: string; createdAt: string; } export default function WebhooksPage() { const [webhooks, setWebhooks] = useState([]); const [loading, setLoading] = useState(true); const [formOpen, setFormOpen] = useState(false); const [editTarget, setEditTarget] = useState(null); const [deleteTarget, setDeleteTarget] = useState(null); const [expandedId, setExpandedId] = useState(null); const [regenerating, setRegenerating] = useState(null); const [newSecret, setNewSecret] = useState<{ webhookId: string; secret: string; masked: string; } | null>(null); const loadWebhooks = useCallback(async () => { try { const result = await apiFetch<{ data: Webhook[] }>('/api/v1/admin/webhooks'); setWebhooks(result.data); } catch { // ignore } finally { setLoading(false); } }, []); useEffect(() => { void loadWebhooks(); }, [loadWebhooks]); async function handleDelete() { if (!deleteTarget) return; try { await apiFetch(`/api/v1/admin/webhooks/${deleteTarget.id}`, { method: 'DELETE' }); setDeleteTarget(null); void loadWebhooks(); } catch { // ignore } } async function handleRegenerate(webhookId: string) { setRegenerating(webhookId); try { const result = await apiFetch<{ data: { secret: string; secretMasked: string } }>( `/api/v1/admin/webhooks/${webhookId}/regenerate-secret`, { method: 'POST' }, ); setNewSecret({ webhookId, secret: result.data.secret, masked: result.data.secretMasked }); void loadWebhooks(); } catch { // ignore } finally { setRegenerating(null); } } async function handleToggleActive(webhook: Webhook) { try { await apiFetch(`/api/v1/admin/webhooks/${webhook.id}`, { method: 'PATCH', body: { isActive: !webhook.isActive }, }); void loadWebhooks(); } catch { // ignore } } function toggleExpand(id: string) { setExpandedId((prev) => (prev === id ? null : id)); } return (
{ setEditTarget(null); setFormOpen(true); }} > Add Webhook } /> {loading ? (

Loading...

) : webhooks.length === 0 ? (

No webhooks configured

Add a webhook to receive real-time notifications of CRM events.

) : (
{webhooks.map((webhook) => (
{webhook.name} {webhook.isActive ? 'Active' : 'Inactive'}

{webhook.url}

{webhook.events.length} event{webhook.events.length !== 1 ? 's' : ''}

{expandedId === webhook.id && (
{/* Events */}

Subscribed Events

{webhook.events.map((e) => ( {e} ))}
{/* Secret */}

Signing Secret

{newSecret?.webhookId === webhook.id ? ( ) : ( )}
{/* Delivery Log */}

Delivery Log

)}
))}
)} { if (!open) setDeleteTarget(null); }} > Delete Webhook Delete "{deleteTarget?.name}"? This will also delete all delivery history. This action cannot be undone. Cancel Delete
); }