@elevasis/ui 2.23.0 → 2.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/app/index.d.ts +2915 -0
  2. package/dist/app/index.js +5 -4
  3. package/dist/{chunk-7PGEGSUM.js → chunk-7D2HSSIW.js} +2 -2
  4. package/dist/{chunk-YU6MBDVO.js → chunk-ABV5LDDC.js} +4 -68
  5. package/dist/chunk-AZXSFDG2.js +474 -0
  6. package/dist/{chunk-6IA2OMAE.js → chunk-HC2KV6BU.js} +9 -0
  7. package/dist/{chunk-PXGSJNBH.js → chunk-HVC2BTFO.js} +783 -374
  8. package/dist/{chunk-3HEUGBOT.js → chunk-LK4MPIMK.js} +2 -2
  9. package/dist/{chunk-XOTJNW4Q.js → chunk-QIW6OCEI.js} +18 -1
  10. package/dist/{chunk-GUJUK6EH.js → chunk-QJLRDTYS.js} +198 -2
  11. package/dist/{chunk-QZJM3RYI.js → chunk-SNHGSCKH.js} +1 -1
  12. package/dist/{chunk-FXWETLEB.js → chunk-V3UOW2HG.js} +1 -1
  13. package/dist/{chunk-N6WLOWOD.js → chunk-WSC5LU3U.js} +3 -12
  14. package/dist/{chunk-EPV7NU2E.js → chunk-WWVSPOJY.js} +385 -188
  15. package/dist/{chunk-SQ5JGELM.js → chunk-ZDKQNQ4X.js} +19 -1
  16. package/dist/{chunk-PTUOINQ2.js → chunk-ZGZZIR6K.js} +3 -3
  17. package/dist/{chunk-D3KQAABP.js → chunk-ZMXZ476Y.js} +1 -1
  18. package/dist/components/index.d.ts +488 -452
  19. package/dist/components/index.js +127 -22
  20. package/dist/components/navigation/index.js +2 -2
  21. package/dist/features/auth/index.d.ts +463 -377
  22. package/dist/features/crm/index.d.ts +459 -379
  23. package/dist/features/crm/index.js +8 -8
  24. package/dist/features/dashboard/index.js +8 -8
  25. package/dist/features/delivery/index.d.ts +457 -371
  26. package/dist/features/delivery/index.js +8 -8
  27. package/dist/features/lead-gen/index.d.ts +225 -65
  28. package/dist/features/lead-gen/index.js +8 -8
  29. package/dist/features/monitoring/index.js +9 -9
  30. package/dist/features/monitoring/requests/index.js +7 -7
  31. package/dist/features/operations/index.js +10 -10
  32. package/dist/features/settings/index.d.ts +463 -377
  33. package/dist/features/settings/index.js +9 -9
  34. package/dist/hooks/delivery/index.d.ts +457 -371
  35. package/dist/hooks/index.d.ts +957 -718
  36. package/dist/hooks/index.js +7 -7
  37. package/dist/hooks/published.d.ts +957 -718
  38. package/dist/hooks/published.js +7 -7
  39. package/dist/index.d.ts +1327 -1020
  40. package/dist/index.js +8 -8
  41. package/dist/initialization/index.d.ts +463 -377
  42. package/dist/organization/index.d.ts +11 -1
  43. package/dist/organization/index.js +2 -2
  44. package/dist/profile/index.d.ts +463 -377
  45. package/dist/provider/index.d.ts +3132 -169
  46. package/dist/provider/index.js +6 -6
  47. package/dist/provider/published.d.ts +3098 -168
  48. package/dist/provider/published.js +3 -3
  49. package/dist/supabase/index.d.ts +559 -389
  50. package/dist/test-utils/index.d.ts +21 -1
  51. package/dist/test-utils/index.js +13 -4
  52. package/dist/theme/index.js +2 -2
  53. package/dist/types/index.d.ts +463 -377
  54. package/package.json +2 -2
  55. package/src/test-utils/README.md +2 -0
  56. package/dist/chunk-LVUCBY7X.js +0 -127
  57. /package/dist/{chunk-ZBCTB5CA.js → chunk-EIOJNUPL.js} +0 -0
@@ -4,16 +4,17 @@ import { SubshellNavItem } from './chunk-CEWTOKE7.js';
4
4
  import { SubshellSidebarSection } from './chunk-IIMU5YAJ.js';
5
5
  import { FilterBar } from './chunk-PDHTXPSF.js';
6
6
  import { CustomModal } from './chunk-KVJ3LFH2.js';
7
- import { acquisitionListKeys, useListsTelemetry, useLists, useCreateList, useTableSort, sortData, usePaginationState, useTableSelection, useList, useListProgress, useListExecutions, useContacts, useCompanies, useCompanyFacets, useDeleteCompanies, useDeleteContacts } from './chunk-GUJUK6EH.js';
7
+ import { acquisitionListKeys, useListsTelemetry, useLists, useCreateList, useTableSort, sortData, usePaginationState, useTableSelection, useList, useListProgress, useListExecutions, useDeleteList, useCompanyFacets, useCompanies, useDeleteCompanies, useContacts, useDeleteContacts, useArtifacts, useListMembers, useListMember, useTransitionListMember, useDeriveActions } from './chunk-QJLRDTYS.js';
8
8
  import { showApiErrorNotification, showSuccessNotification } from './chunk-Z6FAH4XV.js';
9
+ import { LEAD_GEN_STAGE_CATALOG, LEAD_GEN_PIPELINE_DEFINITIONS, findPipeline } from './chunk-AZXSFDG2.js';
9
10
  import { SubshellContentContainer } from './chunk-TKAYX2SP.js';
10
- import { PageTitleCaption, CenteredErrorState, StatCard, CardHeader, EmptyState } from './chunk-XUYBOO32.js';
11
+ import { PageTitleCaption, CenteredErrorState, StatCard, CardHeader, EmptyState, JsonViewer } from './chunk-XUYBOO32.js';
11
12
  import { useRouterContext } from './chunk-Q7DJKLEN.js';
12
13
  import { useElevasisServices } from './chunk-IRW7JMQ4.js';
13
- import { Stack, Paper, Text, Anchor, Group, Title, ActionIcon, Divider, Box, SimpleGrid, Badge, Card, Button, Center, Loader, Alert, Table, TextInput, Checkbox, Pagination, Textarea, Select, SegmentedControl } from '@mantine/core';
14
- import { IconLayoutGrid, IconList, IconBuilding, IconAddressBook, IconTarget, IconExternalLink, IconX, IconAlertCircle, IconPlayerPlay, IconArrowRight, IconSparkles, IconListDetails, IconPlus, IconSearch, IconAlertTriangle, IconArrowLeft, IconUsers, IconBuildingFactory2 } from '@tabler/icons-react';
14
+ import { Stack, Paper, Text, Anchor, Group, Title, ActionIcon, Divider, Box, SimpleGrid, Badge, Card, Button, Center, Loader, Alert, Table, TextInput, Select, Checkbox, Pagination, Textarea, Tooltip, Tabs, SegmentedControl, Drawer } from '@mantine/core';
15
+ import { IconLayoutGrid, IconList, IconBuilding, IconAddressBook, IconTarget, IconExternalLink, IconX, IconAlertCircle, IconPlayerPlay, IconArrowRight, IconSparkles, IconListDetails, IconPlus, IconSearch, IconAlertTriangle, IconCopy, IconTrash, IconUsers, IconDatabase, IconBuildingFactory2, IconArrowLeft, IconChevronRight, IconMail, IconUser } from '@tabler/icons-react';
15
16
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
16
- import { Link, useNavigate } from '@tanstack/react-router';
17
+ import { Link, useNavigate, useSearch } from '@tanstack/react-router';
17
18
  import { useQueryClient, useMutation } from '@tanstack/react-query';
18
19
  import { useState, useMemo, useEffect } from 'react';
19
20
 
@@ -89,6 +90,22 @@ function formatDate(dateValue) {
89
90
  function getStatusColor(status) {
90
91
  return status === "active" ? "green" : status === "invalid" ? "red" : "gray";
91
92
  }
93
+ function getStateKeyColor(stateKey) {
94
+ switch (stateKey) {
95
+ case "draft":
96
+ return "gray";
97
+ case "enriching":
98
+ return "blue";
99
+ case "launched":
100
+ return "green";
101
+ case "closing":
102
+ return "yellow";
103
+ case "archived":
104
+ return "dimmed";
105
+ default:
106
+ return "gray";
107
+ }
108
+ }
92
109
  function getEnrichmentColor(status) {
93
110
  switch (status) {
94
111
  case "complete":
@@ -236,184 +253,6 @@ function ContactDetailModal({
236
253
  ] })
237
254
  ] }) : null });
238
255
  }
239
- var LIST_TEMPLATE_OPTIONS = [
240
- {
241
- value: "blank",
242
- label: "Blank",
243
- description: "Create an empty draft list with qualification defaults and no pipeline steps."
244
- },
245
- {
246
- value: "full_pipeline",
247
- label: "Full 6-Stage",
248
- description: "Create a complete lead-gen pipeline from scrape through personalization."
249
- },
250
- {
251
- value: "personalize_only",
252
- label: "Personalize Only",
253
- description: "Start with personalization and upload-focused steps for already-prepared contacts."
254
- },
255
- {
256
- value: "email_refresh",
257
- label: "Email Refresh",
258
- description: "Run discovery, verification, and personalization for an existing company set."
259
- }
260
- ];
261
- function buildListConfig(template, targetDescription) {
262
- const qualification = {
263
- targetDescription,
264
- minReviewCount: 5,
265
- minRating: 4,
266
- excludeFranchises: true,
267
- customRules: ""
268
- };
269
- const personalization = {
270
- industryContext: targetDescription,
271
- emailBody: "",
272
- creativeDirection: "",
273
- exclusionRules: []
274
- };
275
- switch (template) {
276
- case "full_pipeline":
277
- return {
278
- qualification,
279
- enrichment: {
280
- emailDiscovery: { primary: "tomba" },
281
- emailVerification: { provider: "millionverifier", threshold: "ok" }
282
- },
283
- personalization,
284
- pipeline: {
285
- steps: [
286
- {
287
- key: "scrape",
288
- label: "Scrape Companies",
289
- resourceId: "lgn-01a-google-maps-scrape-workflow",
290
- inputTemplate: {},
291
- enabled: true,
292
- order: 1
293
- },
294
- {
295
- key: "acquire",
296
- label: "Import Companies",
297
- resourceId: "lgn-01b-apify-acquire-workflow",
298
- inputTemplate: {},
299
- enabled: true,
300
- order: 2
301
- },
302
- {
303
- key: "extract",
304
- label: "Extract Website Data",
305
- resourceId: "lgn-02-website-extract-workflow",
306
- inputTemplate: {},
307
- enabled: true,
308
- order: 3
309
- },
310
- {
311
- key: "qualify",
312
- label: "Qualify Companies",
313
- resourceId: "lgn-03-company-qualification-workflow",
314
- inputTemplate: {},
315
- enabled: true,
316
- order: 4
317
- },
318
- {
319
- key: "discover",
320
- label: "Discover Emails",
321
- resourceId: "lgn-04-email-discovery-workflow",
322
- inputTemplate: {},
323
- enabled: true,
324
- order: 5
325
- },
326
- {
327
- key: "verify",
328
- label: "Verify Emails",
329
- resourceId: "lgn-05-email-verification-workflow",
330
- inputTemplate: {},
331
- enabled: true,
332
- order: 6
333
- },
334
- {
335
- key: "personalize",
336
- label: "Personalize Outreach",
337
- resourceId: "ist-personalization-workflow",
338
- inputTemplate: {},
339
- enabled: true,
340
- order: 7
341
- }
342
- ]
343
- }
344
- };
345
- case "personalize_only":
346
- return {
347
- qualification,
348
- personalization,
349
- pipeline: {
350
- steps: [
351
- {
352
- key: "personalize",
353
- label: "Personalize Outreach",
354
- resourceId: "ist-personalization-workflow",
355
- inputTemplate: {},
356
- enabled: true,
357
- order: 1
358
- },
359
- {
360
- key: "upload",
361
- label: "Upload Contacts",
362
- resourceId: "ist-upload-contacts-workflow",
363
- inputTemplate: { requireOpeningLine: true },
364
- enabled: true,
365
- order: 2
366
- }
367
- ]
368
- }
369
- };
370
- case "email_refresh":
371
- return {
372
- qualification,
373
- enrichment: {
374
- emailDiscovery: { primary: "tomba" },
375
- emailVerification: { provider: "millionverifier", threshold: "ok" }
376
- },
377
- personalization,
378
- pipeline: {
379
- steps: [
380
- {
381
- key: "discover",
382
- label: "Discover Emails",
383
- resourceId: "lgn-04-email-discovery-workflow",
384
- inputTemplate: {},
385
- enabled: true,
386
- order: 1
387
- },
388
- {
389
- key: "verify",
390
- label: "Verify Emails",
391
- resourceId: "lgn-05-email-verification-workflow",
392
- inputTemplate: {},
393
- enabled: true,
394
- order: 2
395
- },
396
- {
397
- key: "personalize",
398
- label: "Personalize Outreach",
399
- resourceId: "ist-personalization-workflow",
400
- inputTemplate: {},
401
- enabled: true,
402
- order: 3
403
- }
404
- ]
405
- }
406
- };
407
- case "blank":
408
- default:
409
- return {
410
- qualification,
411
- pipeline: {
412
- steps: []
413
- }
414
- };
415
- }
416
- }
417
256
  function useDeleteLists() {
418
257
  const { apiRequest, organizationId } = useElevasisServices();
419
258
  const queryClient = useQueryClient();
@@ -710,13 +549,22 @@ function LeadGenOverviewPage() {
710
549
  ] }) }) });
711
550
  }
712
551
  var PAGE_SIZE_DEFAULT = 20;
552
+ var STATUS_FILTER_OPTIONS = [
553
+ { value: "", label: "All statuses" },
554
+ { value: "draft", label: "Draft" },
555
+ { value: "enriching", label: "Enriching" },
556
+ { value: "launched", label: "Launched" },
557
+ { value: "closing", label: "Closing" },
558
+ { value: "archived", label: "Archived" }
559
+ ];
713
560
  function LeadGenListsPage() {
714
561
  const navigate = useNavigate();
715
562
  const [searchQuery, setSearchQuery] = useState("");
563
+ const [statusFilter, setStatusFilter] = useState("");
716
564
  const [showCreateList, setShowCreateList] = useState(false);
717
565
  const [newListName, setNewListName] = useState("");
718
566
  const [newListDescription, setNewListDescription] = useState("");
719
- const [selectedTemplate, setSelectedTemplate] = useState("full_pipeline");
567
+ const [newRubricKey, setNewRubricKey] = useState("");
720
568
  const [showBatchDelete, setShowBatchDelete] = useState(false);
721
569
  const { data: lists, isLoading: listsLoading } = useLists();
722
570
  const { data: telemetry, isLoading: telemetryLoading } = useListsTelemetry();
@@ -732,38 +580,46 @@ function LeadGenListsPage() {
732
580
  name: (list) => list.name,
733
581
  description: (list) => list.description || "",
734
582
  contacts: (list) => contactCountByListId.get(list.id) ?? 0,
735
- created: (list) => list.createdAt
583
+ batches: (list) => list.batchIds.length,
584
+ created: (list) => list.createdAt,
585
+ status: (list) => list.status
736
586
  }),
737
587
  [contactCountByListId]
738
588
  );
739
589
  const filteredLists = useMemo(() => {
740
590
  if (!lists) return [];
741
- if (!searchQuery.trim()) return lists;
742
- const query = searchQuery.toLowerCase();
743
- return lists.filter((list) => list.name.toLowerCase().includes(query));
744
- }, [lists, searchQuery]);
591
+ let result = lists;
592
+ if (searchQuery.trim()) {
593
+ const query = searchQuery.toLowerCase();
594
+ result = result.filter((list) => list.name.toLowerCase().includes(query));
595
+ }
596
+ if (statusFilter) {
597
+ result = result.filter((list) => list.status === statusFilter);
598
+ }
599
+ return result;
600
+ }, [lists, searchQuery, statusFilter]);
745
601
  const sortedLists = useMemo(() => sortData(filteredLists, sort, sortAccessors), [filteredLists, sort, sortAccessors]);
746
- const pagination = usePaginationState(PAGE_SIZE_DEFAULT, [searchQuery], sortedLists.length);
602
+ const pagination = usePaginationState(PAGE_SIZE_DEFAULT, [searchQuery, statusFilter], sortedLists.length);
747
603
  const paginatedLists = useMemo(
748
604
  () => sortedLists.slice(pagination.offset, pagination.offset + PAGE_SIZE_DEFAULT),
749
605
  [sortedLists, pagination.offset]
750
606
  );
751
607
  const selection = useTableSelection(paginatedLists, sortedLists);
752
- const selectedTemplateMeta = LIST_TEMPLATE_OPTIONS.find((option) => option.value === selectedTemplate);
753
608
  function resetCreateListModal() {
754
609
  setNewListName("");
755
610
  setNewListDescription("");
756
- setSelectedTemplate("full_pipeline");
611
+ setNewRubricKey("");
757
612
  setShowCreateList(false);
758
613
  }
759
614
  function handleCreateList() {
760
615
  const trimmedName = newListName.trim();
761
616
  if (!trimmedName) return;
617
+ const trimmedRubric = newRubricKey.trim();
618
+ const icp = trimmedRubric ? { qualificationRubricKey: trimmedRubric } : void 0;
762
619
  const body = {
763
620
  name: trimmedName,
764
621
  description: newListDescription.trim() || null,
765
- type: selectedTemplate,
766
- config: buildListConfig(selectedTemplate, trimmedName)
622
+ ...icp ? { icp } : {}
767
623
  };
768
624
  createListMutation.mutate(body, {
769
625
  onSuccess: (list) => {
@@ -791,7 +647,7 @@ function LeadGenListsPage() {
791
647
  }
792
648
  ) }),
793
649
  /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
794
- /* @__PURE__ */ jsx(
650
+ /* @__PURE__ */ jsxs(
795
651
  FilterBar,
796
652
  {
797
653
  actions: /* @__PURE__ */ jsx(
@@ -802,24 +658,38 @@ function LeadGenListsPage() {
802
658
  isDeleting: deleteListsMutation.isPending
803
659
  }
804
660
  ),
805
- children: /* @__PURE__ */ jsx(
806
- TextInput,
807
- {
808
- placeholder: "Search by name...",
809
- leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
810
- value: searchQuery,
811
- onChange: (e) => setSearchQuery(e.currentTarget.value)
812
- }
813
- )
661
+ children: [
662
+ /* @__PURE__ */ jsx(
663
+ TextInput,
664
+ {
665
+ placeholder: "Search by name...",
666
+ leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
667
+ value: searchQuery,
668
+ onChange: (e) => setSearchQuery(e.currentTarget.value)
669
+ }
670
+ ),
671
+ /* @__PURE__ */ jsx(
672
+ Select,
673
+ {
674
+ placeholder: "All statuses",
675
+ data: STATUS_FILTER_OPTIONS,
676
+ value: statusFilter,
677
+ onChange: (value) => setStatusFilter(value ?? ""),
678
+ clearable: true,
679
+ size: "sm",
680
+ w: 160
681
+ }
682
+ )
683
+ ]
814
684
  }
815
685
  ),
816
686
  listsLoading || telemetryLoading ? /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) : !filteredLists.length ? /* @__PURE__ */ jsx(
817
687
  EmptyState,
818
688
  {
819
689
  icon: IconList,
820
- title: searchQuery.trim() ? "No lists match your search" : "No lists yet",
821
- description: searchQuery.trim() ? void 0 : "Create one to get started.",
822
- action: searchQuery.trim() ? void 0 : {
690
+ title: searchQuery.trim() || statusFilter ? "No lists match your filters" : "No lists yet",
691
+ description: searchQuery.trim() || statusFilter ? void 0 : "Create one to get started.",
692
+ action: searchQuery.trim() || statusFilter ? void 0 : {
823
693
  label: "Create List",
824
694
  onClick: () => setShowCreateList(true),
825
695
  icon: /* @__PURE__ */ jsx(IconPlus, { size: 16 })
@@ -837,24 +707,53 @@ function LeadGenListsPage() {
837
707
  ) }),
838
708
  /* @__PURE__ */ jsx(SortableHeader, { column: "name", sort, onToggle: toggleSort, children: "Name" }),
839
709
  /* @__PURE__ */ jsx(SortableHeader, { column: "description", sort, onToggle: toggleSort, children: "Description" }),
710
+ /* @__PURE__ */ jsx(SortableHeader, { column: "status", sort, onToggle: toggleSort, children: "Status" }),
711
+ /* @__PURE__ */ jsx(Table.Th, { children: "ICP Rubric" }),
840
712
  /* @__PURE__ */ jsx(SortableHeader, { column: "contacts", sort, onToggle: toggleSort, children: "Contacts" }),
713
+ /* @__PURE__ */ jsx(SortableHeader, { column: "batches", sort, onToggle: toggleSort, children: "Batches" }),
841
714
  /* @__PURE__ */ jsx(SortableHeader, { column: "created", sort, onToggle: toggleSort, children: "Created" })
842
715
  ] }) }),
843
- /* @__PURE__ */ jsx(Table.Tbody, { children: paginatedLists.map((list) => /* @__PURE__ */ jsxs(
844
- Table.Tr,
845
- {
846
- style: { cursor: "pointer" },
847
- onClick: () => navigate({ to: "/lead-gen/lists/$listId", params: { listId: list.id } }),
848
- children: [
849
- /* @__PURE__ */ jsx(Table.Td, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(Checkbox, { checked: selection.isSelected(list.id), onChange: () => selection.toggle(list.id) }) }),
850
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: list.name }) }),
851
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: list.description || "-" }) }),
852
- /* @__PURE__ */ jsx(Table.Td, { children: contactCountByListId.get(list.id) ?? 0 }),
853
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: formatDate(list.createdAt) }) })
854
- ]
855
- },
856
- list.id
857
- )) })
716
+ /* @__PURE__ */ jsx(Table.Tbody, { children: paginatedLists.map((list) => {
717
+ const rubricKey = list.icp?.qualificationRubricKey;
718
+ return /* @__PURE__ */ jsxs(
719
+ Table.Tr,
720
+ {
721
+ style: { cursor: "pointer" },
722
+ onClick: () => navigate({ to: "/lead-gen/lists/$listId", params: { listId: list.id } }),
723
+ children: [
724
+ /* @__PURE__ */ jsx(Table.Td, { onClick: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx(
725
+ Checkbox,
726
+ {
727
+ checked: selection.isSelected(list.id),
728
+ onChange: () => selection.toggle(list.id)
729
+ }
730
+ ) }),
731
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Group, { gap: 6, wrap: "nowrap", children: [
732
+ /* @__PURE__ */ jsx(Text, { fw: 500, children: list.name }),
733
+ list.instantlyCampaignId ? /* @__PURE__ */ jsx(
734
+ Anchor,
735
+ {
736
+ href: `https://app.instantly.ai/app/campaign/${list.instantlyCampaignId}/analytics`,
737
+ target: "_blank",
738
+ rel: "noreferrer",
739
+ onClick: (e) => e.stopPropagation(),
740
+ c: "dimmed",
741
+ lh: 1,
742
+ children: /* @__PURE__ */ jsx(IconExternalLink, { size: 16 })
743
+ }
744
+ ) : null
745
+ ] }) }),
746
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: list.description || "-" }) }),
747
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", color: getStateKeyColor(list.status), variant: "light", children: list.status }) }),
748
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: rubricKey || "\u2014" }) }),
749
+ /* @__PURE__ */ jsx(Table.Td, { children: contactCountByListId.get(list.id) ?? 0 }),
750
+ /* @__PURE__ */ jsx(Table.Td, { children: list.batchIds.length }),
751
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: formatDate(list.createdAt) }) })
752
+ ]
753
+ },
754
+ list.id
755
+ );
756
+ }) })
858
757
  ] }),
859
758
  sortedLists.length > PAGE_SIZE_DEFAULT && /* @__PURE__ */ jsx(Group, { justify: "center", children: /* @__PURE__ */ jsx(
860
759
  Pagination,
@@ -901,20 +800,16 @@ function LeadGenListsPage() {
901
800
  }
902
801
  ),
903
802
  /* @__PURE__ */ jsx(
904
- Select,
803
+ TextInput,
905
804
  {
906
- label: "Pipeline Template",
907
- data: LIST_TEMPLATE_OPTIONS.map((option) => ({
908
- value: option.value,
909
- label: option.label
910
- })),
911
- value: selectedTemplate,
912
- onChange: (value) => setSelectedTemplate(value ?? "full_pipeline"),
913
- disabled: createListMutation.isPending,
914
- allowDeselect: false
805
+ label: "ICP Rubric Key",
806
+ description: "Optional free-form text key identifying the qualification rubric for this list.",
807
+ placeholder: "e.g. smb-veterinary-us",
808
+ value: newRubricKey,
809
+ onChange: (event) => setNewRubricKey(event.currentTarget.value),
810
+ disabled: createListMutation.isPending
915
811
  }
916
812
  ),
917
- selectedTemplateMeta ? /* @__PURE__ */ jsx(Alert, { variant: "light", color: "blue", children: /* @__PURE__ */ jsx(Text, { size: "sm", children: selectedTemplateMeta.description }) }) : null,
918
813
  /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "The list will open in draft mode after creation so you can review configuration, edit pipeline steps, and run workflows from the detail page." }),
919
814
  /* @__PURE__ */ jsxs(Group, { justify: "flex-end", children: [
920
815
  /* @__PURE__ */ jsx(Button, { variant: "light", onClick: resetCreateListModal, disabled: createListMutation.isPending, children: "Cancel" }),
@@ -989,37 +884,588 @@ function formatDateTime(value) {
989
884
  minute: "2-digit"
990
885
  });
991
886
  }
887
+ function resolveMemberStateLabel(member) {
888
+ const defs = LEAD_GEN_PIPELINE_DEFINITIONS["acq.list-member"];
889
+ if (!defs) return null;
890
+ const pipeline = findPipeline(defs, member.pipelineKey);
891
+ if (!pipeline) return null;
892
+ const stage = pipeline.stages.find((s) => s.stageKey === member.stageKey);
893
+ if (!stage) return null;
894
+ const state = stage.states.find((s) => s.stateKey === member.stateKey);
895
+ return {
896
+ stageLabel: stage.label,
897
+ stateLabel: state?.label ?? member.stateKey
898
+ };
899
+ }
900
+ function getMemberStateColor(stateKey) {
901
+ switch (stateKey) {
902
+ case "personalized":
903
+ case "verified":
904
+ case "qualified":
905
+ case "interested":
906
+ return "green";
907
+ case "uploaded":
908
+ case "discovered":
909
+ case "extracted":
910
+ case "populated":
911
+ return "blue";
912
+ case "pending":
913
+ return "gray";
914
+ default:
915
+ return "gray";
916
+ }
917
+ }
918
+ function ArtifactsPanel({ listMemberId }) {
919
+ const { data, isLoading, error } = useArtifacts({ ownerKind: "list_member", ownerId: listMemberId });
920
+ const artifacts = data?.artifacts ?? [];
921
+ if (isLoading) {
922
+ return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) });
923
+ }
924
+ if (error) {
925
+ return /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load artifacts" });
926
+ }
927
+ if (!artifacts.length) {
928
+ return /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconDatabase, { size: 16 }), color: "gray", variant: "light", children: "No artifacts recorded for this member yet." });
929
+ }
930
+ return /* @__PURE__ */ jsx(Stack, { gap: "sm", children: artifacts.map((artifact) => /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
931
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
932
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
933
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: "blue", children: artifact.kind }),
934
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
935
+ "v",
936
+ artifact.version
937
+ ] })
938
+ ] }),
939
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: formatDateTime(artifact.createdAt) })
940
+ ] }),
941
+ /* @__PURE__ */ jsx(JsonViewer, { data: artifact.content, maxHeight: 240 })
942
+ ] }) }, artifact.id)) });
943
+ }
944
+ function ListMemberDrawerContent({ member, listId }) {
945
+ const transitionMember = useTransitionListMember();
946
+ const statefulItem = useMemo(
947
+ () => ({
948
+ id: member.id,
949
+ pipeline_key: member.pipelineKey,
950
+ stage_key: member.stageKey,
951
+ state_key: member.stateKey,
952
+ activity_log: member.activityLog
953
+ }),
954
+ [member]
955
+ );
956
+ const derivedActions = useDeriveActions(statefulItem);
957
+ const resolved = resolveMemberStateLabel(member);
958
+ const contactName = [member.contact?.firstName, member.contact?.lastName].filter(Boolean).join(" ").trim() || member.contact?.email || "\u2014";
959
+ return /* @__PURE__ */ jsxs(Stack, { gap: "md", p: "md", children: [
960
+ /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
961
+ /* @__PURE__ */ jsx(Group, { gap: "xs", align: "center", children: resolved ? /* @__PURE__ */ jsxs(Fragment, { children: [
962
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: "blue", children: resolved.stageLabel }),
963
+ /* @__PURE__ */ jsx(IconChevronRight, { size: 14, style: { color: "var(--color-text-dimmed)" } }),
964
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getMemberStateColor(member.stateKey), children: resolved.stateLabel })
965
+ ] }) : /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getMemberStateColor(member.stateKey), children: member.stateKey }) }),
966
+ /* @__PURE__ */ jsx(Title, { order: 4, children: contactName }),
967
+ member.contact?.email && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
968
+ /* @__PURE__ */ jsx(IconMail, { size: 14, style: { color: "var(--color-text-dimmed)" } }),
969
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: member.contact.email })
970
+ ] }),
971
+ member.contact?.title && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
972
+ /* @__PURE__ */ jsx(IconUser, { size: 14, style: { color: "var(--color-text-dimmed)" } }),
973
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: member.contact.title })
974
+ ] })
975
+ ] }),
976
+ derivedActions.length > 0 && /* @__PURE__ */ jsx(Group, { gap: "xs", children: derivedActions.map((action) => /* @__PURE__ */ jsx(
977
+ Button,
978
+ {
979
+ variant: "light",
980
+ size: "xs",
981
+ loading: transitionMember.isPending,
982
+ onClick: () => {
983
+ transitionMember.mutate({
984
+ memberId: member.id,
985
+ listId,
986
+ pipelineKey: member.pipelineKey,
987
+ // Lead-gen action dispatch targets are resolved server-side via the action key.
988
+ // Stage/state keys are no longer embedded in the client-side Action shape.
989
+ stageKey: action.key,
990
+ stateKey: null
991
+ });
992
+ },
993
+ children: action.label
994
+ },
995
+ action.key
996
+ )) }),
997
+ /* @__PURE__ */ jsx(ArtifactsPanel, { listMemberId: member.id })
998
+ ] });
999
+ }
1000
+ function CompanyMemberDrawerContent({ companyId: _companyId }) {
1001
+ return /* @__PURE__ */ jsxs(Stack, { gap: "md", p: "md", children: [
1002
+ /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
1003
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: "gray", children: "company member" }),
1004
+ /* @__PURE__ */ jsx(Title, { order: 4, children: "Company" })
1005
+ ] }),
1006
+ /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), color: "blue", variant: "light", children: "Company-level pipeline transitions are not yet available in this view." })
1007
+ ] });
1008
+ }
1009
+ function ContactMemberDrawerShell({ contactId, listId }) {
1010
+ const { data: membersData, isLoading, error } = useListMembers({ listId });
1011
+ const listMember = useMemo(() => {
1012
+ if (!membersData?.members) return null;
1013
+ return membersData.members.find((m) => m.contactId === contactId) ?? null;
1014
+ }, [membersData, contactId]);
1015
+ const directQuery = useListMember(listMember === null && !isLoading ? contactId : "");
1016
+ const resolvedMember = listMember ?? directQuery.data ?? null;
1017
+ if (isLoading) {
1018
+ return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) });
1019
+ }
1020
+ if (error) {
1021
+ return /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load member detail" });
1022
+ }
1023
+ if (!resolvedMember) {
1024
+ return /* @__PURE__ */ jsx(Stack, { gap: "md", p: "md", children: /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), color: "gray", variant: "light", children: "Member detail not found. The member may have been removed from this list." }) });
1025
+ }
1026
+ return /* @__PURE__ */ jsx(ListMemberDrawerContent, { member: resolvedMember, listId });
1027
+ }
1028
+ function ListMemberDrawer({ memberId, memberKind, listId, onClose }) {
1029
+ const opened = !!memberId && !!memberKind;
1030
+ return /* @__PURE__ */ jsxs(
1031
+ Drawer,
1032
+ {
1033
+ opened,
1034
+ onClose,
1035
+ position: "right",
1036
+ size: "lg",
1037
+ title: "Member Detail",
1038
+ styles: {
1039
+ body: { padding: 0 }
1040
+ },
1041
+ children: [
1042
+ opened && memberId && memberKind === "contact" && /* @__PURE__ */ jsx(ContactMemberDrawerShell, { contactId: memberId, listId }),
1043
+ opened && memberId && memberKind === "company" && /* @__PURE__ */ jsx(CompanyMemberDrawerContent, { companyId: memberId })
1044
+ ]
1045
+ }
1046
+ );
1047
+ }
1048
+ function formatDateTime2(value) {
1049
+ if (!value) return "Not yet";
1050
+ return new Date(value).toLocaleString("en-US", {
1051
+ month: "short",
1052
+ day: "numeric",
1053
+ year: "numeric",
1054
+ hour: "numeric",
1055
+ minute: "2-digit"
1056
+ });
1057
+ }
992
1058
  function contactDisplayName(firstName, lastName) {
993
1059
  const full = [firstName, lastName].filter(Boolean).join(" ").trim();
994
1060
  return full || "\u2014";
995
1061
  }
1062
+ function getStatusColor2(status) {
1063
+ switch (status) {
1064
+ case "draft":
1065
+ return "gray";
1066
+ case "enriching":
1067
+ return "blue";
1068
+ case "launched":
1069
+ return "green";
1070
+ case "closing":
1071
+ return "yellow";
1072
+ case "archived":
1073
+ return "red";
1074
+ default:
1075
+ return "gray";
1076
+ }
1077
+ }
1078
+ function getMemberStateColor2(stateKey) {
1079
+ switch (stateKey) {
1080
+ case "personalized":
1081
+ case "verified":
1082
+ case "qualified":
1083
+ case "interested":
1084
+ return "green";
1085
+ case "uploaded":
1086
+ case "discovered":
1087
+ case "extracted":
1088
+ case "populated":
1089
+ return "blue";
1090
+ case "pending":
1091
+ return "gray";
1092
+ default:
1093
+ return "gray";
1094
+ }
1095
+ }
1096
+ var ORPHAN_STAGE_ORDER = 9999;
1097
+ function sortStageKeys(keys) {
1098
+ return keys.slice().sort((a, b) => {
1099
+ const oa = LEAD_GEN_STAGE_CATALOG[a]?.order ?? ORPHAN_STAGE_ORDER;
1100
+ const ob = LEAD_GEN_STAGE_CATALOG[b]?.order ?? ORPHAN_STAGE_ORDER;
1101
+ return oa - ob || a.localeCompare(b);
1102
+ });
1103
+ }
1104
+ function PipelineSection({
1105
+ title,
1106
+ byStage,
1107
+ emptyText
1108
+ }) {
1109
+ const orderedKeys = sortStageKeys(Object.keys(byStage));
1110
+ return /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1111
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: title }),
1112
+ orderedKeys.length === 0 ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: emptyText }) : /* @__PURE__ */ jsx(Stack, { gap: "xs", children: orderedKeys.map((key) => {
1113
+ const entry = byStage[key];
1114
+ const total = entry?.total ?? 0;
1115
+ const attempted = entry?.attempted ?? 0;
1116
+ const percent = total > 0 ? Math.round(attempted / total * 100) : 0;
1117
+ const label = LEAD_GEN_STAGE_CATALOG[key]?.label ?? key;
1118
+ const segments = [
1119
+ { key: "success", value: entry?.success ?? 0, color: "var(--mantine-color-green-6)" },
1120
+ { key: "noResult", value: entry?.noResult ?? 0, color: "var(--mantine-color-gray-6)" },
1121
+ { key: "skipped", value: entry?.skipped ?? 0, color: "var(--mantine-color-yellow-6)" },
1122
+ { key: "error", value: entry?.error ?? 0, color: "var(--mantine-color-red-6)" },
1123
+ { key: "other", value: entry?.other ?? 0, color: "var(--mantine-color-blue-6)" }
1124
+ ].filter((segment) => segment.value > 0);
1125
+ const statusSummary = [
1126
+ `${entry?.success ?? 0} success`,
1127
+ `${entry?.noResult ?? 0} no result`,
1128
+ `${entry?.skipped ?? 0} skipped`,
1129
+ `${entry?.error ?? 0} errors`,
1130
+ (entry?.other ?? 0) > 0 ? `${entry?.other ?? 0} other` : null,
1131
+ (entry?.notAttempted ?? 0) > 0 ? `${entry?.notAttempted ?? 0} not attempted` : null
1132
+ ].filter(Boolean);
1133
+ return /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
1134
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", children: [
1135
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: label }),
1136
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1137
+ attempted,
1138
+ " / ",
1139
+ total,
1140
+ " attempted (",
1141
+ percent,
1142
+ "%)"
1143
+ ] })
1144
+ ] }),
1145
+ /* @__PURE__ */ jsx(
1146
+ Box,
1147
+ {
1148
+ h: 8,
1149
+ bg: "var(--mantine-color-dark-4)",
1150
+ style: { borderRadius: 999, display: "flex", overflow: "hidden" },
1151
+ children: segments.map((segment) => /* @__PURE__ */ jsx(
1152
+ Box,
1153
+ {
1154
+ h: "100%",
1155
+ w: `${total > 0 ? segment.value / total * 100 : 0}%`,
1156
+ bg: segment.color
1157
+ },
1158
+ segment.key
1159
+ ))
1160
+ }
1161
+ ),
1162
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: statusSummary.join(" \xB7 ") })
1163
+ ] }, key);
1164
+ }) })
1165
+ ] });
1166
+ }
1167
+ function PipelineStagesCard({ list, progress }) {
1168
+ const hasAnyActivity = Object.keys(progress.byCompanyStage).length > 0 || Object.keys(progress.byContactStage).length > 0;
1169
+ return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
1170
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", children: [
1171
+ /* @__PURE__ */ jsx(Title, { order: 5, children: "Pipeline Stages" }),
1172
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1173
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getStatusColor2(list.status), children: list.status }),
1174
+ list.launchedAt && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1175
+ "Launched ",
1176
+ formatDateTime2(list.launchedAt)
1177
+ ] }),
1178
+ list.completedAt && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1179
+ "Completed ",
1180
+ formatDateTime2(list.completedAt)
1181
+ ] })
1182
+ ] })
1183
+ ] }),
1184
+ !hasAnyActivity ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No pipeline activity yet \u2014 stages appear here as workflows write processing_state flags." }) : /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, md: 2 }, spacing: "md", children: [
1185
+ /* @__PURE__ */ jsx(
1186
+ PipelineSection,
1187
+ {
1188
+ title: `Company Pipeline (${progress.totalCompanies})`,
1189
+ byStage: progress.byCompanyStage,
1190
+ emptyText: "No company-stage flags recorded yet."
1191
+ }
1192
+ ),
1193
+ /* @__PURE__ */ jsx(
1194
+ PipelineSection,
1195
+ {
1196
+ title: `Contact Pipeline (${progress.totalMembers})`,
1197
+ byStage: progress.byContactStage,
1198
+ emptyText: "No contact-stage flags recorded yet."
1199
+ }
1200
+ )
1201
+ ] })
1202
+ ] }) });
1203
+ }
1204
+ function ListConfigCard({ list }) {
1205
+ const icp = list.icp ?? {};
1206
+ const scraping = list.scrapingConfig ?? {};
1207
+ const hasIcp = Object.values(icp).some((v) => v !== void 0 && v !== null && v !== "");
1208
+ const hasScraping = Object.values(scraping).some((v) => v !== void 0 && v !== null && v !== "");
1209
+ if (!hasIcp && !hasScraping) {
1210
+ return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1211
+ /* @__PURE__ */ jsx(Title, { order: 5, children: "List Config" }),
1212
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No ICP rubric or scraping criteria configured for this list." })
1213
+ ] }) });
1214
+ }
1215
+ return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
1216
+ /* @__PURE__ */ jsx(Title, { order: 5, children: "List Config" }),
1217
+ /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, md: 2 }, spacing: "md", children: [
1218
+ hasIcp && /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
1219
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "ICP Rubric" }),
1220
+ icp.qualificationRubricKey && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1221
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Rubric Key" }),
1222
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", children: icp.qualificationRubricKey })
1223
+ ] }),
1224
+ icp.targetDescription && /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
1225
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Target" }),
1226
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: icp.targetDescription })
1227
+ ] }),
1228
+ (icp.minReviewCount !== void 0 || icp.minRating !== void 0) && /* @__PURE__ */ jsxs(Group, { gap: "md", children: [
1229
+ icp.minReviewCount !== void 0 && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1230
+ "Min reviews:",
1231
+ " ",
1232
+ /* @__PURE__ */ jsx(Text, { span: true, size: "xs", c: "bright", children: icp.minReviewCount })
1233
+ ] }),
1234
+ icp.minRating !== void 0 && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1235
+ "Min rating:",
1236
+ " ",
1237
+ /* @__PURE__ */ jsx(Text, { span: true, size: "xs", c: "bright", children: icp.minRating })
1238
+ ] })
1239
+ ] }),
1240
+ icp.excludeFranchises !== void 0 && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1241
+ "Exclude franchises:",
1242
+ " ",
1243
+ /* @__PURE__ */ jsx(Text, { span: true, size: "xs", c: "bright", children: String(icp.excludeFranchises) })
1244
+ ] }),
1245
+ icp.customRules && /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
1246
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Custom rules" }),
1247
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: icp.customRules })
1248
+ ] })
1249
+ ] }),
1250
+ hasScraping && /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
1251
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "Scraping Criteria" }),
1252
+ scraping.vertical && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1253
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Vertical" }),
1254
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: scraping.vertical })
1255
+ ] }),
1256
+ scraping.geography && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1257
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Geography" }),
1258
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: scraping.geography })
1259
+ ] }),
1260
+ scraping.size && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1261
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Size" }),
1262
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: scraping.size })
1263
+ ] }),
1264
+ scraping.apifyInput && Object.keys(scraping.apifyInput).length > 0 && /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
1265
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Apify input" }),
1266
+ /* @__PURE__ */ jsx(JsonViewer, { data: scraping.apifyInput, maxHeight: 160, fontSize: "0.75rem" })
1267
+ ] })
1268
+ ] })
1269
+ ] })
1270
+ ] }) });
1271
+ }
1272
+ function OverviewTab({ list, progress }) {
1273
+ const hasMetadata = list.metadata && Object.keys(list.metadata).length > 0;
1274
+ return /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
1275
+ /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 2 }, children: [
1276
+ /* @__PURE__ */ jsx(StatCard, { label: "Companies", value: progress.totalCompanies, icon: IconBuilding }),
1277
+ /* @__PURE__ */ jsx(StatCard, { label: "Members", value: progress.totalMembers, icon: IconUsers })
1278
+ ] }),
1279
+ /* @__PURE__ */ jsx(PipelineStagesCard, { list, progress }),
1280
+ /* @__PURE__ */ jsx(ListConfigCard, { list }),
1281
+ hasMetadata && /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1282
+ /* @__PURE__ */ jsx(Title, { order: 5, children: "Metadata / Qualification Signals" }),
1283
+ /* @__PURE__ */ jsx(JsonViewer, { data: list.metadata, maxHeight: 320 })
1284
+ ] }) })
1285
+ ] });
1286
+ }
1287
+ function MembersTab({
1288
+ listId,
1289
+ progress,
1290
+ onMemberClick
1291
+ }) {
1292
+ const [memberTab, setMemberTab] = useState("contacts");
1293
+ const contactsQuery = useContacts({ listId, limit: 100, offset: 0 });
1294
+ const companiesQuery = useCompanies({ listId, limit: 100, offset: 0 });
1295
+ const contacts = contactsQuery.data?.data ?? [];
1296
+ const companies = companiesQuery.data?.data ?? [];
1297
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
1298
+ /* @__PURE__ */ jsx(
1299
+ CardHeader,
1300
+ {
1301
+ icon: /* @__PURE__ */ jsx(IconAddressBook, { size: 16 }),
1302
+ title: "Members",
1303
+ rightSection: /* @__PURE__ */ jsx(
1304
+ SegmentedControl,
1305
+ {
1306
+ value: memberTab,
1307
+ onChange: (value) => setMemberTab(value),
1308
+ size: "xs",
1309
+ data: [
1310
+ { label: `Members (${progress.totalMembers})`, value: "contacts" },
1311
+ { label: `Companies (${progress.totalCompanies})`, value: "companies" }
1312
+ ]
1313
+ }
1314
+ )
1315
+ }
1316
+ ),
1317
+ memberTab === "contacts" && /* @__PURE__ */ jsx(Fragment, { children: contactsQuery.isLoading ? /* @__PURE__ */ jsx(Center, { p: "md", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) }) : !contacts.length ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No contacts attached to this list yet." }) : /* @__PURE__ */ jsxs(Table, { highlightOnHover: true, children: [
1318
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1319
+ /* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
1320
+ /* @__PURE__ */ jsx(Table.Th, { children: "Email" }),
1321
+ /* @__PURE__ */ jsx(Table.Th, { children: "Title" }),
1322
+ /* @__PURE__ */ jsx(Table.Th, { children: "Company" }),
1323
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1324
+ /* @__PURE__ */ jsx(Table.Th, { children: "State" }),
1325
+ /* @__PURE__ */ jsx(Table.Th, { children: "Created" })
1326
+ ] }) }),
1327
+ /* @__PURE__ */ jsx(Table.Tbody, { children: contacts.map((contact) => {
1328
+ const handleRowClick = () => onMemberClick?.(contact.id, "contact");
1329
+ const memberState = contact.stateKey ?? null;
1330
+ return /* @__PURE__ */ jsxs(Table.Tr, { onClick: handleRowClick, style: { cursor: "pointer" }, children: [
1331
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: contactDisplayName(contact.firstName, contact.lastName) }) }),
1332
+ /* @__PURE__ */ jsx(Table.Td, { children: contact.email }),
1333
+ /* @__PURE__ */ jsx(Table.Td, { children: contact.title ?? "\u2014" }),
1334
+ /* @__PURE__ */ jsx(Table.Td, { children: contact.company?.name ?? "\u2014" }),
1335
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor2(contact.status), children: contact.status }) }),
1336
+ /* @__PURE__ */ jsx(Table.Td, { children: memberState ? /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "dot", color: getMemberStateColor2(memberState), children: memberState }) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "\u2014" }) }),
1337
+ /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime2(contact.createdAt) })
1338
+ ] }, contact.id);
1339
+ }) })
1340
+ ] }) }),
1341
+ memberTab === "companies" && /* @__PURE__ */ jsx(Fragment, { children: companiesQuery.isLoading ? /* @__PURE__ */ jsx(Center, { p: "md", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) }) : !companies.length ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No companies attached to this list yet." }) : /* @__PURE__ */ jsxs(Table, { highlightOnHover: true, children: [
1342
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1343
+ /* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
1344
+ /* @__PURE__ */ jsx(Table.Th, { children: "Domain" }),
1345
+ /* @__PURE__ */ jsx(Table.Th, { children: "Segment" }),
1346
+ /* @__PURE__ */ jsx(Table.Th, { children: "Contacts" }),
1347
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1348
+ /* @__PURE__ */ jsx(Table.Th, { children: "State" }),
1349
+ /* @__PURE__ */ jsx(Table.Th, { children: "Created" })
1350
+ ] }) }),
1351
+ /* @__PURE__ */ jsx(Table.Tbody, { children: companies.map((company) => {
1352
+ const handleRowClick = () => onMemberClick?.(company.id, "company");
1353
+ const memberState = company.stateKey ?? null;
1354
+ return /* @__PURE__ */ jsxs(Table.Tr, { onClick: handleRowClick, style: { cursor: "pointer" }, children: [
1355
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: company.name }) }),
1356
+ /* @__PURE__ */ jsx(Table.Td, { children: company.domain ?? "\u2014" }),
1357
+ /* @__PURE__ */ jsx(Table.Td, { children: company.segment ?? "\u2014" }),
1358
+ /* @__PURE__ */ jsx(Table.Td, { children: company.contactCount }),
1359
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor2(company.status), children: company.status }) }),
1360
+ /* @__PURE__ */ jsx(Table.Td, { children: memberState ? /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "dot", color: getMemberStateColor2(memberState), children: memberState }) : /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "\u2014" }) }),
1361
+ /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime2(company.createdAt) })
1362
+ ] }, company.id);
1363
+ }) })
1364
+ ] }) })
1365
+ ] });
1366
+ }
1367
+ function ArtifactsTab({ listId }) {
1368
+ const { data, isLoading, error } = useArtifacts({ ownerKind: "list", ownerId: listId });
1369
+ const artifacts = data?.artifacts ?? [];
1370
+ if (isLoading) {
1371
+ return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) });
1372
+ }
1373
+ if (error) {
1374
+ return /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load artifacts" });
1375
+ }
1376
+ if (!artifacts.length) {
1377
+ return /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconDatabase, { size: 16 }), color: "gray", variant: "light", children: "No artifacts recorded for this list yet." });
1378
+ }
1379
+ return /* @__PURE__ */ jsx(Stack, { gap: "sm", children: artifacts.map((artifact) => /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1380
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
1381
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1382
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: "blue", children: artifact.kind }),
1383
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1384
+ "v",
1385
+ artifact.version
1386
+ ] })
1387
+ ] }),
1388
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: formatDateTime2(artifact.createdAt) })
1389
+ ] }),
1390
+ /* @__PURE__ */ jsx(JsonViewer, { data: artifact.content, maxHeight: 240 })
1391
+ ] }) }, artifact.id)) });
1392
+ }
1393
+ function ExecutionHistorySection({
1394
+ executions
1395
+ }) {
1396
+ if (!executions.length) {
1397
+ return /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No executions recorded for this list yet." });
1398
+ }
1399
+ return /* @__PURE__ */ jsxs(Table, { children: [
1400
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1401
+ /* @__PURE__ */ jsx(Table.Th, { children: "Resource" }),
1402
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1403
+ /* @__PURE__ */ jsx(Table.Th, { children: "Started" }),
1404
+ /* @__PURE__ */ jsx(Table.Th, { children: "Completed" }),
1405
+ /* @__PURE__ */ jsx(Table.Th, { children: "Duration" })
1406
+ ] }) }),
1407
+ /* @__PURE__ */ jsx(Table.Tbody, { children: executions.map((execution) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
1408
+ /* @__PURE__ */ jsxs(Table.Td, { children: [
1409
+ /* @__PURE__ */ jsx(Text, { fw: 500, children: execution.resourceId }),
1410
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: execution.executionId })
1411
+ ] }),
1412
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor2(execution.status), children: execution.status }) }),
1413
+ /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime2(execution.createdAt) }),
1414
+ /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime2(execution.completedAt) }),
1415
+ /* @__PURE__ */ jsx(Table.Td, { children: execution.durationMs == null ? "n/a" : `${execution.durationMs} ms` })
1416
+ ] }, execution.executionId)) })
1417
+ ] });
1418
+ }
1419
+ function ListDetailHeader({
1420
+ title,
1421
+ caption,
1422
+ rightSection
1423
+ }) {
1424
+ return /* @__PURE__ */ jsx(PageTitleCaption, { title, caption, rightSection });
1425
+ }
996
1426
  function LeadGenListDetailPage({ listId }) {
997
1427
  const navigate = useNavigate();
1428
+ const rawSearch = useSearch({ strict: false });
1429
+ const memberId = rawSearch.member ?? null;
1430
+ const memberKind = rawSearch.memberKind ?? null;
1431
+ const handleMemberClick = (id, kind) => {
1432
+ const params = new URLSearchParams(window.location.search);
1433
+ params.set("member", id);
1434
+ params.set("memberKind", kind);
1435
+ window.history.pushState(null, "", `${window.location.pathname}?${params.toString()}`);
1436
+ };
1437
+ const handleDrawerClose = () => {
1438
+ const params = new URLSearchParams(window.location.search);
1439
+ params.delete("member");
1440
+ params.delete("memberKind");
1441
+ const qs = params.toString();
1442
+ window.history.pushState(null, "", qs ? `${window.location.pathname}?${qs}` : window.location.pathname);
1443
+ };
998
1444
  const listQuery = useList(listId);
999
1445
  const progressQuery = useListProgress(listId);
1000
1446
  const executionsQuery = useListExecutions(listId);
1001
- const contactsQuery = useContacts({ listId, limit: 100, offset: 0 });
1002
- const companiesQuery = useCompanies({ listId, limit: 100, offset: 0 });
1003
- const [memberTab, setMemberTab] = useState("contacts");
1447
+ const deleteListMutation = useDeleteList();
1448
+ const [deleteModalOpen, setDeleteModalOpen] = useState(false);
1004
1449
  const isLoading = listQuery.isLoading || progressQuery.isLoading || executionsQuery.isLoading;
1005
1450
  const error = listQuery.error ?? progressQuery.error ?? executionsQuery.error;
1451
+ const backButton = /* @__PURE__ */ jsx(
1452
+ Button,
1453
+ {
1454
+ variant: "light",
1455
+ size: "xs",
1456
+ leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
1457
+ onClick: () => navigate({ to: "/lead-gen/lists" }),
1458
+ children: "Lists"
1459
+ }
1460
+ );
1006
1461
  if (isLoading) {
1007
1462
  return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1008
1463
  /* @__PURE__ */ jsx(
1009
- PageTitleCaption,
1464
+ ListDetailHeader,
1010
1465
  {
1011
1466
  title: "List Detail",
1012
1467
  caption: "Configuration, progress, and execution history for a single lead-gen list",
1013
- rightSection: /* @__PURE__ */ jsx(
1014
- Button,
1015
- {
1016
- variant: "light",
1017
- size: "xs",
1018
- leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
1019
- onClick: () => navigate({ to: "/lead-gen/lists" }),
1020
- children: "Lists"
1021
- }
1022
- )
1468
+ rightSection: backButton
1023
1469
  }
1024
1470
  ),
1025
1471
  /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) })
@@ -1028,20 +1474,11 @@ function LeadGenListDetailPage({ listId }) {
1028
1474
  if (error) {
1029
1475
  return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1030
1476
  /* @__PURE__ */ jsx(
1031
- PageTitleCaption,
1477
+ ListDetailHeader,
1032
1478
  {
1033
1479
  title: "List Detail",
1034
1480
  caption: "Configuration, progress, and execution history for a single lead-gen list",
1035
- rightSection: /* @__PURE__ */ jsx(
1036
- Button,
1037
- {
1038
- variant: "light",
1039
- size: "xs",
1040
- leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
1041
- onClick: () => navigate({ to: "/lead-gen/lists" }),
1042
- children: "Lists"
1043
- }
1044
- )
1481
+ rightSection: backButton
1045
1482
  }
1046
1483
  ),
1047
1484
  /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load list detail" }) })
@@ -1050,20 +1487,11 @@ function LeadGenListDetailPage({ listId }) {
1050
1487
  if (!listQuery.data || !progressQuery.data) {
1051
1488
  return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1052
1489
  /* @__PURE__ */ jsx(
1053
- PageTitleCaption,
1490
+ ListDetailHeader,
1054
1491
  {
1055
1492
  title: "List Not Found",
1056
1493
  caption: "The requested lead-gen list is unavailable.",
1057
- rightSection: /* @__PURE__ */ jsx(
1058
- Button,
1059
- {
1060
- variant: "light",
1061
- size: "xs",
1062
- leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
1063
- onClick: () => navigate({ to: "/lead-gen/lists" }),
1064
- children: "Lists"
1065
- }
1066
- )
1494
+ rightSection: backButton
1067
1495
  }
1068
1496
  ),
1069
1497
  /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { h: 240, children: /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), color: "gray", variant: "light", children: "The requested list could not be found." }) }) })
@@ -1072,117 +1500,98 @@ function LeadGenListDetailPage({ listId }) {
1072
1500
  const list = listQuery.data;
1073
1501
  const progress = progressQuery.data;
1074
1502
  const executions = executionsQuery.data ?? [];
1075
- const contacts = contactsQuery.data?.data ?? [];
1076
- const companies = companiesQuery.data?.data ?? [];
1077
- return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1078
- /* @__PURE__ */ jsx(
1079
- PageTitleCaption,
1080
- {
1081
- title: list.name,
1082
- caption: list.description ?? "Configuration, progress, and execution history for this list",
1083
- rightSection: /* @__PURE__ */ jsx(
1084
- Button,
1085
- {
1086
- variant: "light",
1087
- size: "xs",
1088
- leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
1089
- onClick: () => navigate({ to: "/lead-gen/lists" }),
1090
- children: "Lists"
1091
- }
1092
- )
1503
+ const handleCopyListCommand = () => {
1504
+ void navigator.clipboard.writeText(`/acquisition --lead-gen list ${list.id}`);
1505
+ showSuccessNotification("Copied list command to clipboard");
1506
+ };
1507
+ const handleDeleteList = () => {
1508
+ deleteListMutation.mutate(list.id, {
1509
+ onSuccess: () => {
1510
+ setDeleteModalOpen(false);
1511
+ void navigate({ to: "/lead-gen/lists" });
1093
1512
  }
1094
- ),
1095
- /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1096
- /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor(list.status), children: list.status }),
1097
- /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
1098
- "Created ",
1099
- formatDateTime(list.createdAt)
1100
- ] })
1101
- ] }),
1102
- /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 2 }, children: [
1103
- /* @__PURE__ */ jsx(StatCard, { label: "Companies", value: progress.totalCompanies, icon: IconBuilding }),
1104
- /* @__PURE__ */ jsx(StatCard, { label: "Contacts", value: progress.totalContacts, icon: IconUsers })
1105
- ] }),
1106
- /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
1513
+ });
1514
+ };
1515
+ return /* @__PURE__ */ jsxs(SubshellContentContainer, { children: [
1516
+ /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1107
1517
  /* @__PURE__ */ jsx(
1108
- CardHeader,
1518
+ ListDetailHeader,
1109
1519
  {
1110
- icon: /* @__PURE__ */ jsx(IconAddressBook, { size: 16 }),
1111
- title: "Members",
1112
- rightSection: /* @__PURE__ */ jsx(
1113
- SegmentedControl,
1114
- {
1115
- value: memberTab,
1116
- onChange: (value) => setMemberTab(value),
1117
- size: "xs",
1118
- data: [
1119
- { label: `Contacts (${progress.totalContacts})`, value: "contacts" },
1120
- { label: `Companies (${progress.totalCompanies})`, value: "companies" }
1121
- ]
1122
- }
1123
- )
1520
+ title: list.name,
1521
+ caption: list.description ?? "Configuration, progress, and execution history for this list"
1124
1522
  }
1125
1523
  ),
1126
- memberTab === "contacts" && /* @__PURE__ */ jsx(Fragment, { children: contactsQuery.isLoading ? /* @__PURE__ */ jsx(Center, { p: "md", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) }) : !contacts.length ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No contacts attached to this list yet." }) : /* @__PURE__ */ jsxs(Table, { children: [
1127
- /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1128
- /* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
1129
- /* @__PURE__ */ jsx(Table.Th, { children: "Email" }),
1130
- /* @__PURE__ */ jsx(Table.Th, { children: "Title" }),
1131
- /* @__PURE__ */ jsx(Table.Th, { children: "Company" }),
1132
- /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1133
- /* @__PURE__ */ jsx(Table.Th, { children: "Created" })
1134
- ] }) }),
1135
- /* @__PURE__ */ jsx(Table.Tbody, { children: contacts.map((contact) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
1136
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: contactDisplayName(contact.firstName, contact.lastName) }) }),
1137
- /* @__PURE__ */ jsx(Table.Td, { children: contact.email }),
1138
- /* @__PURE__ */ jsx(Table.Td, { children: contact.title ?? "\u2014" }),
1139
- /* @__PURE__ */ jsx(Table.Td, { children: contact.company?.name ?? "\u2014" }),
1140
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor(contact.status), children: contact.status }) }),
1141
- /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime(contact.createdAt) })
1142
- ] }, contact.id)) })
1143
- ] }) }),
1144
- memberTab === "companies" && /* @__PURE__ */ jsx(Fragment, { children: companiesQuery.isLoading ? /* @__PURE__ */ jsx(Center, { p: "md", children: /* @__PURE__ */ jsx(Loader, { size: "sm" }) }) : !companies.length ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No companies attached to this list yet." }) : /* @__PURE__ */ jsxs(Table, { children: [
1145
- /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1146
- /* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
1147
- /* @__PURE__ */ jsx(Table.Th, { children: "Domain" }),
1148
- /* @__PURE__ */ jsx(Table.Th, { children: "Segment" }),
1149
- /* @__PURE__ */ jsx(Table.Th, { children: "Contacts" }),
1150
- /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1151
- /* @__PURE__ */ jsx(Table.Th, { children: "Created" })
1152
- ] }) }),
1153
- /* @__PURE__ */ jsx(Table.Tbody, { children: companies.map((company) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
1154
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: company.name }) }),
1155
- /* @__PURE__ */ jsx(Table.Td, { children: company.domain ?? "\u2014" }),
1156
- /* @__PURE__ */ jsx(Table.Td, { children: company.segment ?? "\u2014" }),
1157
- /* @__PURE__ */ jsx(Table.Td, { children: company.contactCount }),
1158
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor(company.status), children: company.status }) }),
1159
- /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime(company.createdAt) })
1160
- ] }, company.id)) })
1161
- ] }) })
1162
- ] }),
1163
- /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
1164
- /* @__PURE__ */ jsx(CardHeader, { icon: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 16 }), title: "Execution History" }),
1165
- !executions.length ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No executions recorded for this list yet." }) : /* @__PURE__ */ jsxs(Table, { children: [
1166
- /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1167
- /* @__PURE__ */ jsx(Table.Th, { children: "Resource" }),
1168
- /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1169
- /* @__PURE__ */ jsx(Table.Th, { children: "Started" }),
1170
- /* @__PURE__ */ jsx(Table.Th, { children: "Completed" }),
1171
- /* @__PURE__ */ jsx(Table.Th, { children: "Duration" })
1172
- ] }) }),
1173
- /* @__PURE__ */ jsx(Table.Tbody, { children: executions.map((execution) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
1174
- /* @__PURE__ */ jsxs(Table.Td, { children: [
1175
- /* @__PURE__ */ jsx(Text, { fw: 500, children: execution.resourceId }),
1176
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: execution.executionId })
1524
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", wrap: "nowrap", children: [
1525
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1526
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getStatusColor2(list.status), children: list.status }),
1527
+ /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
1528
+ "Created ",
1529
+ formatDateTime2(list.createdAt)
1530
+ ] })
1531
+ ] }),
1532
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1533
+ /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", onClick: handleCopyListCommand, style: { cursor: "pointer" }, children: [
1534
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", ff: "monospace", children: list.id }),
1535
+ /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", "aria-label": "Copy list command", children: /* @__PURE__ */ jsx(IconCopy, { size: 14 }) })
1177
1536
  ] }),
1178
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor(execution.status), children: execution.status }) }),
1179
- /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime(execution.createdAt) }),
1180
- /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime(execution.completedAt) }),
1181
- /* @__PURE__ */ jsx(Table.Td, { children: execution.durationMs == null ? "n/a" : `${execution.durationMs} ms` })
1182
- ] }, execution.executionId)) })
1537
+ /* @__PURE__ */ jsx(Tooltip, { label: "Delete list", children: /* @__PURE__ */ jsx(
1538
+ ActionIcon,
1539
+ {
1540
+ variant: "subtle",
1541
+ color: "red",
1542
+ size: "sm",
1543
+ "aria-label": "Delete list",
1544
+ loading: deleteListMutation.isPending,
1545
+ onClick: () => setDeleteModalOpen(true),
1546
+ children: /* @__PURE__ */ jsx(IconTrash, { size: 14 })
1547
+ }
1548
+ ) }),
1549
+ backButton
1550
+ ] })
1551
+ ] }),
1552
+ /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsxs(Tabs, { defaultValue: "overview", children: [
1553
+ /* @__PURE__ */ jsxs(Tabs.List, { children: [
1554
+ /* @__PURE__ */ jsx(Tabs.Tab, { value: "overview", leftSection: /* @__PURE__ */ jsx(IconBuilding, { size: 14 }), children: "Overview" }),
1555
+ /* @__PURE__ */ jsx(Tabs.Tab, { value: "members", leftSection: /* @__PURE__ */ jsx(IconUsers, { size: 14 }), children: "Members" }),
1556
+ /* @__PURE__ */ jsx(Tabs.Tab, { value: "artifacts", leftSection: /* @__PURE__ */ jsx(IconDatabase, { size: 14 }), children: "Artifacts" })
1557
+ ] }),
1558
+ /* @__PURE__ */ jsx(Tabs.Panel, { value: "overview", pt: "sm", children: /* @__PURE__ */ jsx(OverviewTab, { list, progress }) }),
1559
+ /* @__PURE__ */ jsx(Tabs.Panel, { value: "members", pt: "sm", children: /* @__PURE__ */ jsx(MembersTab, { listId, progress, onMemberClick: handleMemberClick }) }),
1560
+ /* @__PURE__ */ jsx(Tabs.Panel, { value: "artifacts", pt: "sm", children: /* @__PURE__ */ jsx(ArtifactsTab, { listId }) })
1561
+ ] }) }),
1562
+ /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
1563
+ /* @__PURE__ */ jsx(CardHeader, { icon: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 16 }), title: "Execution History" }),
1564
+ /* @__PURE__ */ jsx(ExecutionHistorySection, { executions })
1183
1565
  ] })
1184
- ] })
1185
- ] }) }) });
1566
+ ] }) }),
1567
+ /* @__PURE__ */ jsx(ListMemberDrawer, { memberId, memberKind, listId, onClose: handleDrawerClose }),
1568
+ /* @__PURE__ */ jsx(
1569
+ CustomModal,
1570
+ {
1571
+ opened: deleteModalOpen,
1572
+ onClose: () => !deleteListMutation.isPending && setDeleteModalOpen(false),
1573
+ size: "sm",
1574
+ loading: deleteListMutation.isPending,
1575
+ children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
1576
+ /* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
1577
+ /* @__PURE__ */ jsx(IconTrash, { size: 22, color: "var(--color-error)" }),
1578
+ /* @__PURE__ */ jsx(Title, { order: 4, children: "Delete list" })
1579
+ ] }),
1580
+ /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
1581
+ "Are you sure you want to delete",
1582
+ " ",
1583
+ /* @__PURE__ */ jsx(Text, { span: true, fw: 600, children: list.name }),
1584
+ "?"
1585
+ ] }),
1586
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "This removes the list and its list membership links. Companies and contacts remain in the shared lead-gen database." }),
1587
+ /* @__PURE__ */ jsxs(Group, { justify: "flex-end", mt: "md", children: [
1588
+ /* @__PURE__ */ jsx(Button, { variant: "light", onClick: () => setDeleteModalOpen(false), disabled: deleteListMutation.isPending, children: "Cancel" }),
1589
+ /* @__PURE__ */ jsx(Button, { color: "red", loading: deleteListMutation.isPending, onClick: handleDeleteList, children: "Delete" })
1590
+ ] })
1591
+ ] })
1592
+ }
1593
+ )
1594
+ ] });
1186
1595
  }
1187
1596
  var PAGE_SIZE_DEFAULT2 = 20;
1188
1597
  function LeadGenCompaniesPage() {
@@ -1542,4 +1951,4 @@ function LeadGenContactsPage() {
1542
1951
  ] }) });
1543
1952
  }
1544
1953
 
1545
- export { CompanyDetailModal, ContactDetailModal, LEAD_GEN_ITEMS, LEAD_GEN_ROUTE_LINKS, LIST_TEMPLATE_OPTIONS, LeadGenCompaniesPage, LeadGenContactsPage, LeadGenListDetailPage, LeadGenListsPage, LeadGenOverviewPage, LeadGenRouteShell, LeadGenSidebar, LeadGenSidebarMiddle, LeadGenSidebarTop, buildListConfig, formatDate, getEnrichmentColor, getEnrichmentStatus, getStatusColor, leadGenManifest, useDeleteLists };
1954
+ export { CompanyDetailModal, ContactDetailModal, LEAD_GEN_ITEMS, LEAD_GEN_ROUTE_LINKS, LeadGenCompaniesPage, LeadGenContactsPage, LeadGenListDetailPage, LeadGenListsPage, LeadGenOverviewPage, LeadGenRouteShell, LeadGenSidebar, LeadGenSidebarMiddle, LeadGenSidebarTop, formatDate, getEnrichmentColor, getEnrichmentStatus, getStateKeyColor, getStatusColor, leadGenManifest, useDeleteLists };