@elevasis/ui 2.22.0 → 2.24.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-3HEUGBOT.js → chunk-2WZ635SS.js} +2 -2
  4. package/dist/{chunk-GJ7EIABJ.js → chunk-4NWNS7TX.js} +1 -1
  5. package/dist/{chunk-LKVBEE63.js → chunk-FUEXGRFR.js} +2 -2
  6. package/dist/{chunk-6IA2OMAE.js → chunk-HC2KV6BU.js} +9 -0
  7. package/dist/{chunk-IBUYJXA3.js → chunk-KCJ6VATY.js} +1133 -578
  8. package/dist/{chunk-WWJ6S2HQ.js → chunk-KLFIJDTD.js} +1 -1
  9. package/dist/{chunk-COG4ABRI.js → chunk-M2HWJY6O.js} +704 -375
  10. package/dist/{chunk-LVJGPE6H.js → chunk-MTR6AN2C.js} +3 -12
  11. package/dist/chunk-OWHQ65EQ.js +211 -0
  12. package/dist/{chunk-XOTJNW4Q.js → chunk-QIW6OCEI.js} +18 -1
  13. package/dist/{chunk-B4FHWKEF.js → chunk-QULLZ5PE.js} +193 -10
  14. package/dist/{chunk-QZJM3RYI.js → chunk-SNHGSCKH.js} +1 -1
  15. package/dist/{chunk-LVUCBY7X.js → chunk-UDJE54WN.js} +85 -3
  16. package/dist/{chunk-IOTLB6ND.js → chunk-VGNAV3TH.js} +406 -195
  17. package/dist/{chunk-BSZRKBAW.js → chunk-YBZT7MJR.js} +3 -3
  18. package/dist/{chunk-SQ5JGELM.js → chunk-ZDKQNQ4X.js} +19 -1
  19. package/dist/components/index.d.ts +500 -466
  20. package/dist/components/index.js +75 -32
  21. package/dist/components/navigation/index.js +2 -2
  22. package/dist/features/auth/index.d.ts +472 -389
  23. package/dist/features/crm/index.d.ts +468 -391
  24. package/dist/features/crm/index.js +8 -8
  25. package/dist/features/dashboard/index.js +8 -8
  26. package/dist/features/delivery/index.d.ts +466 -383
  27. package/dist/features/delivery/index.js +8 -8
  28. package/dist/features/lead-gen/index.d.ts +213 -65
  29. package/dist/features/lead-gen/index.js +9 -8
  30. package/dist/features/monitoring/index.js +9 -9
  31. package/dist/features/monitoring/requests/index.js +7 -7
  32. package/dist/features/operations/index.js +11 -10
  33. package/dist/features/settings/index.d.ts +472 -389
  34. package/dist/features/settings/index.js +9 -9
  35. package/dist/hooks/delivery/index.d.ts +466 -383
  36. package/dist/hooks/index.d.ts +967 -744
  37. package/dist/hooks/index.js +7 -7
  38. package/dist/hooks/published.d.ts +967 -744
  39. package/dist/hooks/published.js +7 -7
  40. package/dist/index.d.ts +1360 -1069
  41. package/dist/index.js +8 -8
  42. package/dist/initialization/index.d.ts +472 -389
  43. package/dist/organization/index.d.ts +11 -1
  44. package/dist/organization/index.js +2 -2
  45. package/dist/profile/index.d.ts +472 -389
  46. package/dist/provider/index.d.ts +3132 -169
  47. package/dist/provider/index.js +6 -6
  48. package/dist/provider/published.d.ts +3098 -168
  49. package/dist/provider/published.js +3 -3
  50. package/dist/supabase/index.d.ts +577 -413
  51. package/dist/test-utils/index.d.ts +21 -1
  52. package/dist/test-utils/index.js +13 -4
  53. package/dist/theme/index.js +2 -2
  54. package/dist/types/index.d.ts +472 -389
  55. package/package.json +2 -2
  56. package/src/test-utils/README.md +2 -0
  57. /package/dist/{chunk-ZBCTB5CA.js → chunk-EIOJNUPL.js} +0 -0
@@ -1,19 +1,20 @@
1
+ import { LEAD_GEN_STAGE_CATALOG, LEAD_GEN_PIPELINE_DEFINITIONS, findPipeline } from './chunk-OWHQ65EQ.js';
1
2
  import { PageContainer } from './chunk-BZZCNLT6.js';
2
3
  import { TableSelectionToolbar, SortableHeader } from './chunk-TUMSNGTX.js';
3
4
  import { SubshellNavItem } from './chunk-CEWTOKE7.js';
4
5
  import { SubshellSidebarSection } from './chunk-IIMU5YAJ.js';
5
6
  import { FilterBar } from './chunk-PDHTXPSF.js';
6
7
  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-B4FHWKEF.js';
8
+ import { acquisitionListKeys, useListsTelemetry, useLists, useCreateList, useTableSort, sortData, usePaginationState, useTableSelection, useList, useListProgress, useListExecutions, useCompanyFacets, useCompanies, useDeleteCompanies, useContacts, useDeleteContacts, useArtifacts, useListMembers, useListMember, useTransitionListMember, useDeriveActions } from './chunk-QULLZ5PE.js';
8
9
  import { showApiErrorNotification, showSuccessNotification } from './chunk-Z6FAH4XV.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, Tabs, SegmentedControl, Drawer, Progress } from '@mantine/core';
15
+ import { IconLayoutGrid, IconList, IconBuilding, IconAddressBook, IconTarget, IconExternalLink, IconX, IconAlertCircle, IconPlayerPlay, IconArrowRight, IconSparkles, IconListDetails, IconPlus, IconSearch, IconAlertTriangle, IconCopy, 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,554 @@ 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 done = entry?.done ?? 0;
1115
+ const total = entry?.total ?? 0;
1116
+ const percent = total > 0 ? Math.round(done / total * 100) : 0;
1117
+ const label = LEAD_GEN_STAGE_CATALOG[key]?.label ?? key;
1118
+ return /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
1119
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", children: [
1120
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: label }),
1121
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1122
+ done,
1123
+ " / ",
1124
+ total,
1125
+ " (",
1126
+ percent,
1127
+ "%)"
1128
+ ] })
1129
+ ] }),
1130
+ /* @__PURE__ */ jsx(Progress, { value: percent, size: "sm", color: getMemberStateColor2(key) })
1131
+ ] }, key);
1132
+ }) })
1133
+ ] });
1134
+ }
1135
+ function PipelineStagesCard({ list, progress }) {
1136
+ const hasAnyActivity = Object.keys(progress.byCompanyStage).length > 0 || Object.keys(progress.byContactStage).length > 0;
1137
+ return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
1138
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "center", children: [
1139
+ /* @__PURE__ */ jsx(Title, { order: 5, children: "Pipeline Stages" }),
1140
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1141
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getStatusColor2(list.status), children: list.status }),
1142
+ list.launchedAt && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1143
+ "Launched ",
1144
+ formatDateTime2(list.launchedAt)
1145
+ ] }),
1146
+ list.completedAt && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1147
+ "Completed ",
1148
+ formatDateTime2(list.completedAt)
1149
+ ] })
1150
+ ] })
1151
+ ] }),
1152
+ !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: [
1153
+ /* @__PURE__ */ jsx(
1154
+ PipelineSection,
1155
+ {
1156
+ title: `Company Pipeline (${progress.totalCompanies})`,
1157
+ byStage: progress.byCompanyStage,
1158
+ emptyText: "No company-stage flags recorded yet."
1159
+ }
1160
+ ),
1161
+ /* @__PURE__ */ jsx(
1162
+ PipelineSection,
1163
+ {
1164
+ title: `Contact Pipeline (${progress.totalMembers})`,
1165
+ byStage: progress.byContactStage,
1166
+ emptyText: "No contact-stage flags recorded yet."
1167
+ }
1168
+ )
1169
+ ] })
1170
+ ] }) });
1171
+ }
1172
+ function ListConfigCard({ list }) {
1173
+ const icp = list.icp ?? {};
1174
+ const scraping = list.scrapingConfig ?? {};
1175
+ const hasIcp = Object.values(icp).some((v) => v !== void 0 && v !== null && v !== "");
1176
+ const hasScraping = Object.values(scraping).some((v) => v !== void 0 && v !== null && v !== "");
1177
+ if (!hasIcp && !hasScraping) {
1178
+ return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1179
+ /* @__PURE__ */ jsx(Title, { order: 5, children: "List Config" }),
1180
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No ICP rubric or scraping criteria configured for this list." })
1181
+ ] }) });
1182
+ }
1183
+ return /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "sm", children: [
1184
+ /* @__PURE__ */ jsx(Title, { order: 5, children: "List Config" }),
1185
+ /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, md: 2 }, spacing: "md", children: [
1186
+ hasIcp && /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
1187
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "ICP Rubric" }),
1188
+ icp.qualificationRubricKey && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1189
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Rubric Key" }),
1190
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", children: icp.qualificationRubricKey })
1191
+ ] }),
1192
+ icp.targetDescription && /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
1193
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Target" }),
1194
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: icp.targetDescription })
1195
+ ] }),
1196
+ (icp.minReviewCount !== void 0 || icp.minRating !== void 0) && /* @__PURE__ */ jsxs(Group, { gap: "md", children: [
1197
+ icp.minReviewCount !== void 0 && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1198
+ "Min reviews:",
1199
+ " ",
1200
+ /* @__PURE__ */ jsx(Text, { span: true, size: "xs", c: "bright", children: icp.minReviewCount })
1201
+ ] }),
1202
+ icp.minRating !== void 0 && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1203
+ "Min rating:",
1204
+ " ",
1205
+ /* @__PURE__ */ jsx(Text, { span: true, size: "xs", c: "bright", children: icp.minRating })
1206
+ ] })
1207
+ ] }),
1208
+ icp.excludeFranchises !== void 0 && /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1209
+ "Exclude franchises:",
1210
+ " ",
1211
+ /* @__PURE__ */ jsx(Text, { span: true, size: "xs", c: "bright", children: String(icp.excludeFranchises) })
1212
+ ] }),
1213
+ icp.customRules && /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
1214
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Custom rules" }),
1215
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: icp.customRules })
1216
+ ] })
1217
+ ] }),
1218
+ hasScraping && /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
1219
+ /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "Scraping Criteria" }),
1220
+ scraping.vertical && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1221
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Vertical" }),
1222
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: scraping.vertical })
1223
+ ] }),
1224
+ scraping.geography && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1225
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Geography" }),
1226
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: scraping.geography })
1227
+ ] }),
1228
+ scraping.size && /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1229
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Size" }),
1230
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: scraping.size })
1231
+ ] }),
1232
+ scraping.apifyInput && Object.keys(scraping.apifyInput).length > 0 && /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
1233
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Apify input" }),
1234
+ /* @__PURE__ */ jsx(JsonViewer, { data: scraping.apifyInput, maxHeight: 160, fontSize: "0.75rem" })
1235
+ ] })
1236
+ ] })
1237
+ ] })
1238
+ ] }) });
1239
+ }
1240
+ function OverviewTab({ list, progress }) {
1241
+ const hasMetadata = list.metadata && Object.keys(list.metadata).length > 0;
1242
+ return /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
1243
+ /* @__PURE__ */ jsx(PipelineStagesCard, { list, progress }),
1244
+ /* @__PURE__ */ jsx(ListConfigCard, { list }),
1245
+ /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 2 }, children: [
1246
+ /* @__PURE__ */ jsx(StatCard, { label: "Companies", value: progress.totalCompanies, icon: IconBuilding }),
1247
+ /* @__PURE__ */ jsx(StatCard, { label: "Members", value: progress.totalMembers, icon: IconUsers })
1248
+ ] }),
1249
+ hasMetadata && /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1250
+ /* @__PURE__ */ jsx(Title, { order: 5, children: "Metadata / Qualification Signals" }),
1251
+ /* @__PURE__ */ jsx(JsonViewer, { data: list.metadata, maxHeight: 320 })
1252
+ ] }) })
1253
+ ] });
1254
+ }
1255
+ function MembersTab({
1256
+ listId,
1257
+ progress,
1258
+ onMemberClick
1259
+ }) {
1260
+ const [memberTab, setMemberTab] = useState("contacts");
1261
+ const contactsQuery = useContacts({ listId, limit: 100, offset: 0 });
1262
+ const companiesQuery = useCompanies({ listId, limit: 100, offset: 0 });
1263
+ const contacts = contactsQuery.data?.data ?? [];
1264
+ const companies = companiesQuery.data?.data ?? [];
1265
+ return /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
1266
+ /* @__PURE__ */ jsx(
1267
+ CardHeader,
1268
+ {
1269
+ icon: /* @__PURE__ */ jsx(IconAddressBook, { size: 16 }),
1270
+ title: "Members",
1271
+ rightSection: /* @__PURE__ */ jsx(
1272
+ SegmentedControl,
1273
+ {
1274
+ value: memberTab,
1275
+ onChange: (value) => setMemberTab(value),
1276
+ size: "xs",
1277
+ data: [
1278
+ { label: `Members (${progress.totalMembers})`, value: "contacts" },
1279
+ { label: `Companies (${progress.totalCompanies})`, value: "companies" }
1280
+ ]
1281
+ }
1282
+ )
1283
+ }
1284
+ ),
1285
+ 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: [
1286
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1287
+ /* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
1288
+ /* @__PURE__ */ jsx(Table.Th, { children: "Email" }),
1289
+ /* @__PURE__ */ jsx(Table.Th, { children: "Title" }),
1290
+ /* @__PURE__ */ jsx(Table.Th, { children: "Company" }),
1291
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1292
+ /* @__PURE__ */ jsx(Table.Th, { children: "State" }),
1293
+ /* @__PURE__ */ jsx(Table.Th, { children: "Created" })
1294
+ ] }) }),
1295
+ /* @__PURE__ */ jsx(Table.Tbody, { children: contacts.map((contact) => {
1296
+ const handleRowClick = () => onMemberClick?.(contact.id, "contact");
1297
+ const memberState = contact.stateKey ?? null;
1298
+ return /* @__PURE__ */ jsxs(Table.Tr, { onClick: handleRowClick, style: { cursor: "pointer" }, children: [
1299
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: contactDisplayName(contact.firstName, contact.lastName) }) }),
1300
+ /* @__PURE__ */ jsx(Table.Td, { children: contact.email }),
1301
+ /* @__PURE__ */ jsx(Table.Td, { children: contact.title ?? "\u2014" }),
1302
+ /* @__PURE__ */ jsx(Table.Td, { children: contact.company?.name ?? "\u2014" }),
1303
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor2(contact.status), children: contact.status }) }),
1304
+ /* @__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" }) }),
1305
+ /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime2(contact.createdAt) })
1306
+ ] }, contact.id);
1307
+ }) })
1308
+ ] }) }),
1309
+ 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: [
1310
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1311
+ /* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
1312
+ /* @__PURE__ */ jsx(Table.Th, { children: "Domain" }),
1313
+ /* @__PURE__ */ jsx(Table.Th, { children: "Segment" }),
1314
+ /* @__PURE__ */ jsx(Table.Th, { children: "Contacts" }),
1315
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1316
+ /* @__PURE__ */ jsx(Table.Th, { children: "State" }),
1317
+ /* @__PURE__ */ jsx(Table.Th, { children: "Created" })
1318
+ ] }) }),
1319
+ /* @__PURE__ */ jsx(Table.Tbody, { children: companies.map((company) => {
1320
+ const handleRowClick = () => onMemberClick?.(company.id, "company");
1321
+ const memberState = company.stateKey ?? null;
1322
+ return /* @__PURE__ */ jsxs(Table.Tr, { onClick: handleRowClick, style: { cursor: "pointer" }, children: [
1323
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: company.name }) }),
1324
+ /* @__PURE__ */ jsx(Table.Td, { children: company.domain ?? "\u2014" }),
1325
+ /* @__PURE__ */ jsx(Table.Td, { children: company.segment ?? "\u2014" }),
1326
+ /* @__PURE__ */ jsx(Table.Td, { children: company.contactCount }),
1327
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor2(company.status), children: company.status }) }),
1328
+ /* @__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" }) }),
1329
+ /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime2(company.createdAt) })
1330
+ ] }, company.id);
1331
+ }) })
1332
+ ] }) })
1333
+ ] });
1334
+ }
1335
+ function ArtifactsTab({ listId }) {
1336
+ const { data, isLoading, error } = useArtifacts({ ownerKind: "list", ownerId: listId });
1337
+ const artifacts = data?.artifacts ?? [];
1338
+ if (isLoading) {
1339
+ return /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) });
1340
+ }
1341
+ if (error) {
1342
+ return /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load artifacts" });
1343
+ }
1344
+ if (!artifacts.length) {
1345
+ return /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconDatabase, { size: 16 }), color: "gray", variant: "light", children: "No artifacts recorded for this list yet." });
1346
+ }
1347
+ return /* @__PURE__ */ jsx(Stack, { gap: "sm", children: artifacts.map((artifact) => /* @__PURE__ */ jsx(Card, { withBorder: true, children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1348
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", children: [
1349
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1350
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: "blue", children: artifact.kind }),
1351
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
1352
+ "v",
1353
+ artifact.version
1354
+ ] })
1355
+ ] }),
1356
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: formatDateTime2(artifact.createdAt) })
1357
+ ] }),
1358
+ /* @__PURE__ */ jsx(JsonViewer, { data: artifact.content, maxHeight: 240 })
1359
+ ] }) }, artifact.id)) });
1360
+ }
1361
+ function ExecutionHistorySection({
1362
+ executions
1363
+ }) {
1364
+ if (!executions.length) {
1365
+ return /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No executions recorded for this list yet." });
1366
+ }
1367
+ return /* @__PURE__ */ jsxs(Table, { children: [
1368
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1369
+ /* @__PURE__ */ jsx(Table.Th, { children: "Resource" }),
1370
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1371
+ /* @__PURE__ */ jsx(Table.Th, { children: "Started" }),
1372
+ /* @__PURE__ */ jsx(Table.Th, { children: "Completed" }),
1373
+ /* @__PURE__ */ jsx(Table.Th, { children: "Duration" })
1374
+ ] }) }),
1375
+ /* @__PURE__ */ jsx(Table.Tbody, { children: executions.map((execution) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
1376
+ /* @__PURE__ */ jsxs(Table.Td, { children: [
1377
+ /* @__PURE__ */ jsx(Text, { fw: 500, children: execution.resourceId }),
1378
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: execution.executionId })
1379
+ ] }),
1380
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor2(execution.status), children: execution.status }) }),
1381
+ /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime2(execution.createdAt) }),
1382
+ /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime2(execution.completedAt) }),
1383
+ /* @__PURE__ */ jsx(Table.Td, { children: execution.durationMs == null ? "n/a" : `${execution.durationMs} ms` })
1384
+ ] }, execution.executionId)) })
1385
+ ] });
1386
+ }
1387
+ function ListDetailHeader({
1388
+ title,
1389
+ caption,
1390
+ rightSection
1391
+ }) {
1392
+ return /* @__PURE__ */ jsx(PageTitleCaption, { title, caption, rightSection });
1393
+ }
996
1394
  function LeadGenListDetailPage({ listId }) {
997
1395
  const navigate = useNavigate();
1396
+ const rawSearch = useSearch({ strict: false });
1397
+ const memberId = rawSearch.member ?? null;
1398
+ const memberKind = rawSearch.memberKind ?? null;
1399
+ const handleMemberClick = (id, kind) => {
1400
+ const params = new URLSearchParams(window.location.search);
1401
+ params.set("member", id);
1402
+ params.set("memberKind", kind);
1403
+ window.history.pushState(null, "", `${window.location.pathname}?${params.toString()}`);
1404
+ };
1405
+ const handleDrawerClose = () => {
1406
+ const params = new URLSearchParams(window.location.search);
1407
+ params.delete("member");
1408
+ params.delete("memberKind");
1409
+ const qs = params.toString();
1410
+ window.history.pushState(null, "", qs ? `${window.location.pathname}?${qs}` : window.location.pathname);
1411
+ };
998
1412
  const listQuery = useList(listId);
999
1413
  const progressQuery = useListProgress(listId);
1000
1414
  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");
1004
1415
  const isLoading = listQuery.isLoading || progressQuery.isLoading || executionsQuery.isLoading;
1005
1416
  const error = listQuery.error ?? progressQuery.error ?? executionsQuery.error;
1417
+ const backButton = /* @__PURE__ */ jsx(
1418
+ Button,
1419
+ {
1420
+ variant: "light",
1421
+ size: "xs",
1422
+ leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
1423
+ onClick: () => navigate({ to: "/lead-gen/lists" }),
1424
+ children: "Lists"
1425
+ }
1426
+ );
1006
1427
  if (isLoading) {
1007
1428
  return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1008
1429
  /* @__PURE__ */ jsx(
1009
- PageTitleCaption,
1430
+ ListDetailHeader,
1010
1431
  {
1011
1432
  title: "List Detail",
1012
1433
  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
- )
1434
+ rightSection: backButton
1023
1435
  }
1024
1436
  ),
1025
1437
  /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) })
@@ -1028,20 +1440,11 @@ function LeadGenListDetailPage({ listId }) {
1028
1440
  if (error) {
1029
1441
  return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1030
1442
  /* @__PURE__ */ jsx(
1031
- PageTitleCaption,
1443
+ ListDetailHeader,
1032
1444
  {
1033
1445
  title: "List Detail",
1034
1446
  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
- )
1447
+ rightSection: backButton
1045
1448
  }
1046
1449
  ),
1047
1450
  /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load list detail" }) })
@@ -1050,20 +1453,11 @@ function LeadGenListDetailPage({ listId }) {
1050
1453
  if (!listQuery.data || !progressQuery.data) {
1051
1454
  return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1052
1455
  /* @__PURE__ */ jsx(
1053
- PageTitleCaption,
1456
+ ListDetailHeader,
1054
1457
  {
1055
1458
  title: "List Not Found",
1056
1459
  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
- )
1460
+ rightSection: backButton
1067
1461
  }
1068
1462
  ),
1069
1463
  /* @__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 +1466,52 @@ function LeadGenListDetailPage({ listId }) {
1072
1466
  const list = listQuery.data;
1073
1467
  const progress = progressQuery.data;
1074
1468
  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
- )
1093
- }
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: [
1469
+ const handleCopyListCommand = () => {
1470
+ void navigator.clipboard.writeText(`/acquisition --lead-gen list ${list.id}`);
1471
+ showSuccessNotification("Copied list command to clipboard");
1472
+ };
1473
+ return /* @__PURE__ */ jsxs(SubshellContentContainer, { children: [
1474
+ /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1107
1475
  /* @__PURE__ */ jsx(
1108
- CardHeader,
1476
+ ListDetailHeader,
1109
1477
  {
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
- )
1478
+ title: list.name,
1479
+ caption: list.description ?? "Configuration, progress, and execution history for this list"
1124
1480
  }
1125
1481
  ),
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 })
1482
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", wrap: "nowrap", children: [
1483
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1484
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "filled", color: getStatusColor2(list.status), children: list.status }),
1485
+ /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
1486
+ "Created ",
1487
+ formatDateTime2(list.createdAt)
1488
+ ] })
1489
+ ] }),
1490
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1491
+ /* @__PURE__ */ jsxs(Group, { gap: 4, wrap: "nowrap", onClick: handleCopyListCommand, style: { cursor: "pointer" }, children: [
1492
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", ff: "monospace", children: list.id }),
1493
+ /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", size: "sm", "aria-label": "Copy list command", children: /* @__PURE__ */ jsx(IconCopy, { size: 14 }) })
1177
1494
  ] }),
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)) })
1495
+ backButton
1496
+ ] })
1497
+ ] }),
1498
+ /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsxs(Tabs, { defaultValue: "overview", children: [
1499
+ /* @__PURE__ */ jsxs(Tabs.List, { children: [
1500
+ /* @__PURE__ */ jsx(Tabs.Tab, { value: "overview", leftSection: /* @__PURE__ */ jsx(IconBuilding, { size: 14 }), children: "Overview" }),
1501
+ /* @__PURE__ */ jsx(Tabs.Tab, { value: "members", leftSection: /* @__PURE__ */ jsx(IconUsers, { size: 14 }), children: "Members" }),
1502
+ /* @__PURE__ */ jsx(Tabs.Tab, { value: "artifacts", leftSection: /* @__PURE__ */ jsx(IconDatabase, { size: 14 }), children: "Artifacts" })
1503
+ ] }),
1504
+ /* @__PURE__ */ jsx(Tabs.Panel, { value: "overview", pt: "sm", children: /* @__PURE__ */ jsx(OverviewTab, { list, progress }) }),
1505
+ /* @__PURE__ */ jsx(Tabs.Panel, { value: "members", pt: "sm", children: /* @__PURE__ */ jsx(MembersTab, { listId, progress, onMemberClick: handleMemberClick }) }),
1506
+ /* @__PURE__ */ jsx(Tabs.Panel, { value: "artifacts", pt: "sm", children: /* @__PURE__ */ jsx(ArtifactsTab, { listId }) })
1507
+ ] }) }),
1508
+ /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
1509
+ /* @__PURE__ */ jsx(CardHeader, { icon: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 16 }), title: "Execution History" }),
1510
+ /* @__PURE__ */ jsx(ExecutionHistorySection, { executions })
1183
1511
  ] })
1184
- ] })
1185
- ] }) }) });
1512
+ ] }) }),
1513
+ /* @__PURE__ */ jsx(ListMemberDrawer, { memberId, memberKind, listId, onClose: handleDrawerClose })
1514
+ ] });
1186
1515
  }
1187
1516
  var PAGE_SIZE_DEFAULT2 = 20;
1188
1517
  function LeadGenCompaniesPage() {
@@ -1542,4 +1871,4 @@ function LeadGenContactsPage() {
1542
1871
  ] }) });
1543
1872
  }
1544
1873
 
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 };
1874
+ 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 };