Seth commited on
Commit
d9926cf
·
1 Parent(s): 5e70d64
Files changed (1) hide show
  1. frontend/src/pages/Leads.jsx +50 -4
frontend/src/pages/Leads.jsx CHANGED
@@ -11,6 +11,7 @@ import {
11
  Trash2,
12
  Handshake,
13
  Pencil,
 
14
  } from 'lucide-react';
15
  import { Button } from '@/components/ui/button';
16
  import { Select, SelectTrigger, SelectContent, SelectItem } from '@/components/ui/select';
@@ -72,6 +73,26 @@ export default function Leads() {
72
  const [rowSelection, setRowSelection] = useState({});
73
  const [bulkBusy, setBulkBusy] = useState(null);
74
  const [tableEditRowId, setTableEditRowId] = useState(null);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
 
76
  const selectedIds = useMemo(
77
  () => Object.keys(rowSelection).filter((id) => rowSelection[id]).map(Number),
@@ -82,8 +103,12 @@ export default function Leads() {
82
 
83
  const webhookUrl = useMemo(() => {
84
  if (typeof window === 'undefined') return '';
85
- return `${window.location.origin}/api/webhooks/smartlead`;
86
- }, []);
 
 
 
 
87
 
88
  const fetchLeads = useCallback(async () => {
89
  setLoading(true);
@@ -380,8 +405,29 @@ export default function Leads() {
380
  title="Leads"
381
  subtitle={
382
  <>
383
- Replies from Smartlead campaigns appear here. Webhook URL:{' '}
384
- <code className="text-xs bg-slate-100 px-1.5 py-0.5 rounded">{webhookUrl}</code>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
385
  </>
386
  }
387
  >
 
11
  Trash2,
12
  Handshake,
13
  Pencil,
14
+ ClipboardCopy,
15
  } from 'lucide-react';
16
  import { Button } from '@/components/ui/button';
17
  import { Select, SelectTrigger, SelectContent, SelectItem } from '@/components/ui/select';
 
73
  const [rowSelection, setRowSelection] = useState({});
74
  const [bulkBusy, setBulkBusy] = useState(null);
75
  const [tableEditRowId, setTableEditRowId] = useState(null);
76
+ /** undefined = loading /auth/me; null = signed out or no tenant; number = workspace id for webhook */
77
+ const [webhookTenantId, setWebhookTenantId] = useState(undefined);
78
+
79
+ useEffect(() => {
80
+ let cancelled = false;
81
+ apiFetch('/api/auth/me').then(async (r) => {
82
+ if (cancelled) return;
83
+ if (!r.ok) {
84
+ setWebhookTenantId(null);
85
+ return;
86
+ }
87
+ const u = await r.json().catch(() => null);
88
+ if (cancelled) return;
89
+ const tid = u?.current_tenant_id;
90
+ setWebhookTenantId(tid != null ? Number(tid) : null);
91
+ });
92
+ return () => {
93
+ cancelled = true;
94
+ };
95
+ }, []);
96
 
97
  const selectedIds = useMemo(
98
  () => Object.keys(rowSelection).filter((id) => rowSelection[id]).map(Number),
 
103
 
104
  const webhookUrl = useMemo(() => {
105
  if (typeof window === 'undefined') return '';
106
+ const base = `${window.location.origin}/api/webhooks/smartlead`;
107
+ if (typeof webhookTenantId === 'number' && !Number.isNaN(webhookTenantId)) {
108
+ return `${base}?tenant_id=${webhookTenantId}`;
109
+ }
110
+ return base;
111
+ }, [webhookTenantId]);
112
 
113
  const fetchLeads = useCallback(async () => {
114
  setLoading(true);
 
405
  title="Leads"
406
  subtitle={
407
  <>
408
+ Replies from Smartlead campaigns appear here. Webhook URL (this workspace):{' '}
409
+ {webhookTenantId === undefined ? (
410
+ <Loader2 className="inline h-3.5 w-3.5 animate-spin align-middle text-slate-400" />
411
+ ) : (
412
+ <span className="inline-flex max-w-full flex-wrap items-center gap-1 align-middle">
413
+ <code className="text-xs bg-slate-100 px-1.5 py-0.5 rounded break-all">
414
+ {webhookUrl}
415
+ </code>
416
+ <Button
417
+ type="button"
418
+ variant="outline"
419
+ size="sm"
420
+ className="h-7 shrink-0 gap-1 px-2 text-xs"
421
+ title="Copy webhook URL"
422
+ onClick={() => {
423
+ if (webhookUrl) navigator.clipboard.writeText(webhookUrl);
424
+ }}
425
+ >
426
+ <ClipboardCopy className="h-3.5 w-3.5" />
427
+ Copy
428
+ </Button>
429
+ </span>
430
+ )}
431
  </>
432
  }
433
  >