@elevasis/ui 2.17.2 → 2.19.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 (63) hide show
  1. package/dist/api/index.js +2 -2
  2. package/dist/app/index.js +5 -5
  3. package/dist/charts/index.js +3 -3
  4. package/dist/chunk-3JCMO7SD.js +14 -0
  5. package/dist/{chunk-TP5NMF6K.js → chunk-46Z2VHY3.js} +4 -4
  6. package/dist/{chunk-FNWWVX5N.js → chunk-5SCVXZPM.js} +358 -188
  7. package/dist/{chunk-TTP62HWW.js → chunk-BHR7IV72.js} +10 -15
  8. package/dist/{chunk-MJ6YV2B5.js → chunk-CTTY6FUT.js} +2 -2
  9. package/dist/{chunk-P3TFNFZS.js → chunk-EUWBY43Z.js} +2 -2
  10. package/dist/{chunk-MDO4UCEJ.js → chunk-IBOX2M24.js} +47 -82
  11. package/dist/{chunk-HH3RNG2O.js → chunk-JEQM67SO.js} +307 -173
  12. package/dist/{chunk-2TDZBYXI.js → chunk-LR5CRY5A.js} +1 -1
  13. package/dist/{chunk-JU6UB4YA.js → chunk-LVCJ2H2T.js} +4 -4
  14. package/dist/{chunk-GRGRBWIO.js → chunk-M7W7CGPL.js} +1 -1
  15. package/dist/{chunk-34NQLV2W.js → chunk-MJAKU2WA.js} +3 -3
  16. package/dist/{chunk-OCCZRPER.js → chunk-Q4QJOSVS.js} +1 -1
  17. package/dist/{chunk-R73EHHPN.js → chunk-Q5HC6ENG.js} +18 -2
  18. package/dist/{chunk-VDM6DQES.js → chunk-R7OJCNL3.js} +1 -1
  19. package/dist/{chunk-6RWMRQN5.js → chunk-TIIPYB2Z.js} +1 -1
  20. package/dist/{chunk-ABUDMATM.js → chunk-TKEKYPZA.js} +6 -6
  21. package/dist/{chunk-R7GKX4HW.js → chunk-UU6PJ4EJ.js} +192 -82
  22. package/dist/{chunk-7L42RRHZ.js → chunk-Y7TDUZEH.js} +221 -514
  23. package/dist/{chunk-7GCWOUFT.js → chunk-YVAXWM3W.js} +73 -121
  24. package/dist/components/index.d.ts +219 -2810
  25. package/dist/components/index.js +41 -27
  26. package/dist/features/crm/index.d.ts +54 -53
  27. package/dist/features/crm/index.js +11 -11
  28. package/dist/features/dashboard/index.js +12 -12
  29. package/dist/features/delivery/index.d.ts +2642 -2605
  30. package/dist/features/delivery/index.js +11 -11
  31. package/dist/features/lead-gen/index.d.ts +152 -16
  32. package/dist/features/lead-gen/index.js +11 -22
  33. package/dist/features/monitoring/index.js +13 -13
  34. package/dist/features/monitoring/requests/index.d.ts +38 -27
  35. package/dist/features/monitoring/requests/index.js +212 -106
  36. package/dist/features/operations/index.d.ts +9 -26
  37. package/dist/features/operations/index.js +15 -15
  38. package/dist/features/settings/index.d.ts +36 -37
  39. package/dist/features/settings/index.js +12 -12
  40. package/dist/hooks/delivery/index.d.ts +2712 -2699
  41. package/dist/hooks/delivery/index.js +2 -2
  42. package/dist/hooks/index.d.ts +1997 -4627
  43. package/dist/hooks/index.js +10 -10
  44. package/dist/hooks/published.d.ts +1997 -4627
  45. package/dist/hooks/published.js +10 -10
  46. package/dist/index.d.ts +1124 -3673
  47. package/dist/index.js +11 -11
  48. package/dist/layout/index.d.ts +14 -2
  49. package/dist/layout/index.js +1 -1
  50. package/dist/provider/index.d.ts +320 -249
  51. package/dist/provider/index.js +8 -8
  52. package/dist/provider/published.d.ts +320 -249
  53. package/dist/provider/published.js +5 -5
  54. package/dist/sse/index.d.ts +1 -6
  55. package/dist/theme/index.js +2 -2
  56. package/dist/types/index.d.ts +1608 -2487
  57. package/dist/utils/index.d.ts +32 -1
  58. package/dist/utils/index.js +1 -1
  59. package/dist/zustand/index.d.ts +4 -8
  60. package/dist/zustand/index.js +2 -2
  61. package/package.json +4 -4
  62. package/dist/chunk-ADSSLKKP.js +0 -10
  63. /package/dist/{chunk-GCBWGGI6.js → chunk-OD7GWIZS.js} +0 -0
@@ -1,22 +1,21 @@
1
- import { ResourceExecuteDialog } from './chunk-HH3RNG2O.js';
2
1
  import { PageContainer } from './chunk-BZZCNLT6.js';
3
2
  import { TableSelectionToolbar, SortableHeader } from './chunk-TUMSNGTX.js';
4
3
  import { SubshellNavItem } from './chunk-CEWTOKE7.js';
5
4
  import { SubshellSidebarSection } from './chunk-IIMU5YAJ.js';
6
5
  import { FilterBar } from './chunk-PDHTXPSF.js';
7
6
  import { CustomModal } from './chunk-GBMNCNHX.js';
8
- import { acquisitionListKeys, useListsTelemetry, useLists, useCreateList, useTableSort, sortData, usePaginationState, useTableSelection, useList, useListProgress, useListExecutions, useResourceDefinition, useCompanies, useDeleteCompanies, useContacts, useDeleteContacts } from './chunk-R7GKX4HW.js';
9
- import { showApiErrorNotification, showSuccessNotification } from './chunk-GRGRBWIO.js';
7
+ import { acquisitionListKeys, useListsTelemetry, useLists, useCreateList, useTableSort, sortData, usePaginationState, useTableSelection, useList, useListProgress, useListExecutions, useContacts, useCompanies, useCompanyFacets, useDeleteCompanies, useDeleteContacts } from './chunk-UU6PJ4EJ.js';
8
+ import { showApiErrorNotification, showSuccessNotification } from './chunk-M7W7CGPL.js';
10
9
  import { SubshellContentContainer } from './chunk-RX4UWZZR.js';
11
- import { PageTitleCaption, CenteredErrorState, StatCard, EmptyState } from './chunk-TTP62HWW.js';
10
+ import { PageTitleCaption, CenteredErrorState, StatCard, CardHeader, EmptyState } from './chunk-BHR7IV72.js';
12
11
  import { useRouterContext } from './chunk-Q7DJKLEN.js';
13
12
  import { useElevasisServices } from './chunk-IRW7JMQ4.js';
14
- import { Stack, Paper, Text, Anchor, Group, Title, ActionIcon, Divider, Box, SimpleGrid, Badge, Card, Button, Center, Loader, Alert, Table, Progress, TextInput, Checkbox, Pagination, Textarea, Select, Code, Modal } from '@mantine/core';
15
- import { IconLayoutGrid, IconList, IconBuilding, IconAddressBook, IconMailCheck, IconTarget, IconExternalLink, IconX, IconAlertCircle, IconPlayerPlay, IconArrowRight, IconQuestionMark, IconChecklist, IconPlus, IconSearch, IconSparkles, IconAlertTriangle, IconArrowLeft, IconClockHour4, IconBuildingFactory2, IconUsers } from '@tabler/icons-react';
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';
16
15
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
17
16
  import { Link, useNavigate } from '@tanstack/react-router';
18
17
  import { useQueryClient, useMutation } from '@tanstack/react-query';
19
- import { useState, useMemo } from 'react';
18
+ import { useState, useMemo, useEffect } from 'react';
20
19
 
21
20
  var LeadGenSidebarTop = () => {
22
21
  return /* @__PURE__ */ jsx(SubshellSidebarSection, { icon: IconTarget, label: "Lead Gen" });
@@ -25,8 +24,7 @@ var LEAD_GEN_ITEMS = [
25
24
  { label: "Overview", to: "/lead-gen", icon: IconLayoutGrid, exact: true },
26
25
  { label: "Lists", to: "/lead-gen/lists", icon: IconList, exact: false },
27
26
  { label: "Companies", to: "/lead-gen/companies", icon: IconBuilding, exact: false },
28
- { label: "Contacts", to: "/lead-gen/contacts", icon: IconAddressBook, exact: false },
29
- { label: "Deliverability", to: "/lead-gen/deliverability", icon: IconMailCheck, exact: false }
27
+ { label: "Contacts", to: "/lead-gen/contacts", icon: IconAddressBook, exact: false }
30
28
  ];
31
29
  var LeadGenSidebarMiddle = ({ items = LEAD_GEN_ITEMS } = {}) => {
32
30
  const { currentPath, navigate } = useRouterContext();
@@ -66,8 +64,7 @@ var LEAD_GEN_ROUTE_LINKS = [
66
64
  { label: "Overview", to: "/lead-gen" },
67
65
  { label: "Lists", to: "/lead-gen/lists" },
68
66
  { label: "Companies", to: "/lead-gen/companies" },
69
- { label: "Contacts", to: "/lead-gen/contacts" },
70
- { label: "Deliverability", to: "/lead-gen/deliverability" }
67
+ { label: "Contacts", to: "/lead-gen/contacts" }
71
68
  ];
72
69
  function LeadGenRouteShell({
73
70
  title,
@@ -121,7 +118,10 @@ function formatName(parts, fallback) {
121
118
  const name = parts.filter(Boolean).join(" ").trim();
122
119
  return name || fallback;
123
120
  }
124
- function CompanyDetailModal({ company, onClose }) {
121
+ function CompanyDetailModal({
122
+ company,
123
+ onClose
124
+ }) {
125
125
  return /* @__PURE__ */ jsx(CustomModal, { opened: !!company, onClose, size: "xl", children: company ? /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
126
126
  /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-start", children: [
127
127
  /* @__PURE__ */ jsxs("div", { children: [
@@ -185,7 +185,10 @@ function CompanyDetailModal({ company, onClose }) {
185
185
  ] })
186
186
  ] }) : null });
187
187
  }
188
- function ContactDetailModal({ contact, onClose }) {
188
+ function ContactDetailModal({
189
+ contact,
190
+ onClose
191
+ }) {
189
192
  return /* @__PURE__ */ jsx(CustomModal, { opened: !!contact, onClose, size: "xl", children: contact ? /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
190
193
  /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-start", children: [
191
194
  /* @__PURE__ */ jsxs("div", { children: [
@@ -441,23 +444,6 @@ function useDeleteLists() {
441
444
  }
442
445
  });
443
446
  }
444
- var EM_DASH = "\u2014";
445
- function computeCompletionRatio(populated, personalized) {
446
- if (populated === 0) return null;
447
- return personalized / populated;
448
- }
449
- function formatPercentage(ratio, fractionDigits = 0) {
450
- if (ratio == null) return EM_DASH;
451
- return `${(ratio * 100).toFixed(fractionDigits)}%`;
452
- }
453
- function computeCompletionPercentage(populated, personalized) {
454
- return formatPercentage(computeCompletionRatio(populated, personalized));
455
- }
456
- function computeBounceRate(d) {
457
- const denominator = d.valid + d.risky + d.invalid + d.bounced;
458
- if (denominator === 0) return EM_DASH;
459
- return `${(d.bounced / denominator * 100).toFixed(1)}%`;
460
- }
461
447
  function computeBacklog(current, completed) {
462
448
  return Math.max(current - completed, 0);
463
449
  }
@@ -545,8 +531,8 @@ function getPrimaryAction({
545
531
  return {
546
532
  title: `Resolve ${formatCountLabel(deliverabilityRiskCount, "deliverability risk")}`,
547
533
  detail: "Risky, invalid, or bounced records are the main campaign health issue right now.",
548
- buttonLabel: "View deliverability",
549
- buttonTo: "/lead-gen/deliverability",
534
+ buttonLabel: "Review lists",
535
+ buttonTo: "/lead-gen/lists",
550
536
  tone: "orange"
551
537
  };
552
538
  }
@@ -576,24 +562,12 @@ function getPrimaryAction({
576
562
  tone: "gray"
577
563
  };
578
564
  }
579
- function CompactPipelineStage({ label, value, ratio }) {
580
- return /* @__PURE__ */ jsx(Card, { withBorder: true, p: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: 6, children: [
581
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", wrap: "nowrap", children: [
582
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", tt: "uppercase", fw: 600, children: label }),
583
- /* @__PURE__ */ jsx(Badge, { size: "xs", variant: "light", color: "blue", children: formatPercentage(ratio) })
584
- ] }),
585
- /* @__PURE__ */ jsx(Title, { order: 4, children: value }),
586
- /* @__PURE__ */ jsx(Progress, { value: ratio == null ? 0 : ratio * 100, size: "sm", radius: "xl", color: "blue" })
587
- ] }) });
588
- }
589
565
  function LeadGenOverviewPage() {
590
566
  const navigate = useNavigate();
591
567
  const telemetryQuery = useListsTelemetry();
592
568
  const listsQuery = useLists();
593
569
  const data = telemetryQuery.data;
594
570
  const listMetaById = new Map((listsQuery.data ?? []).map((list) => [list.id, list]));
595
- const totalCompanies = data?.reduce((sum, list) => sum + list.totalCompanies, 0) ?? 0;
596
- const totalContacts = data?.reduce((sum, list) => sum + list.totalContacts, 0) ?? 0;
597
571
  const stageTotals = data?.reduce(
598
572
  (acc, list) => ({
599
573
  populated: acc.populated + list.stageCounts.populated,
@@ -605,7 +579,7 @@ function LeadGenOverviewPage() {
605
579
  uploaded: acc.uploaded + list.stageCounts.uploaded
606
580
  }),
607
581
  { populated: 0, extracted: 0, qualified: 0, discovered: 0, verified: 0, personalized: 0, uploaded: 0 }
608
- ) ?? { populated: 0, extracted: 0, qualified: 0, discovered: 0, verified: 0, personalized: 0, uploaded: 0 };
582
+ ) ?? { discovered: 0, verified: 0, personalized: 0, uploaded: 0 };
609
583
  const deliverabilityTotals = data?.reduce(
610
584
  (acc, list) => ({
611
585
  valid: acc.valid + list.deliverability.valid,
@@ -623,10 +597,10 @@ function LeadGenOverviewPage() {
623
597
  const deliverabilityRiskCount = deliverabilityTotals.risky + deliverabilityTotals.invalid + deliverabilityTotals.bounced;
624
598
  const totalLists = data?.length ?? 0;
625
599
  const summaryLine = [
626
- `${totalLists} ${totalLists === 1 ? "list" : "lists"} active`,
600
+ `${totalLists} total ${totalLists === 1 ? "list" : "lists"}`,
627
601
  `${formatCountLabel(uploadBacklog, "contact")} ready for upload`,
628
602
  deliverabilityRiskCount === 0 ? "no risks" : `${formatCountLabel(deliverabilityRiskCount, "risk")}`
629
- ].join(" \u2022 ");
603
+ ].join(" | ");
630
604
  const primaryAction = getPrimaryAction({
631
605
  uploadBacklog,
632
606
  personalizationBacklog,
@@ -635,41 +609,12 @@ function LeadGenOverviewPage() {
635
609
  activeListCount,
636
610
  totalLists
637
611
  });
638
- const pipelineStages = [
639
- {
640
- label: "Populated",
641
- value: stageTotals.populated,
642
- ratio: totalCompanies === 0 ? null : stageTotals.populated / totalCompanies
643
- },
644
- {
645
- label: "Qualified",
646
- value: stageTotals.qualified,
647
- ratio: totalCompanies === 0 ? null : stageTotals.qualified / totalCompanies
648
- },
649
- {
650
- label: "Verified",
651
- value: stageTotals.verified,
652
- ratio: totalContacts === 0 ? null : stageTotals.verified / totalContacts
653
- },
654
- {
655
- label: "Personalized",
656
- value: stageTotals.personalized,
657
- ratio: totalContacts === 0 ? null : stageTotals.personalized / totalContacts
658
- },
659
- {
660
- label: "Uploaded",
661
- value: stageTotals.uploaded,
662
- ratio: totalContacts === 0 ? null : stageTotals.uploaded / totalContacts
663
- }
664
- ];
665
612
  const overviewRows = data?.map((list) => {
666
613
  const listMeta = listMetaById.get(list.listId);
667
- const completionRatio = computeCompletionRatio(list.stageCounts.populated, list.stageCounts.personalized);
668
614
  const nextFocus = getNextFocus(list);
669
615
  return {
670
616
  ...list,
671
617
  name: listMeta?.name ?? `List ${list.listId.slice(0, 8)}`,
672
- completionRatio,
673
618
  nextFocus,
674
619
  status: getOverviewStatus(list)
675
620
  };
@@ -688,28 +633,27 @@ function LeadGenOverviewPage() {
688
633
  {
689
634
  title: "Lead Gen Overview",
690
635
  caption: summaryLine,
691
- rightSection: /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
692
- /* @__PURE__ */ jsx(Button, { component: Link, to: "/lead-gen/lists", size: "sm", variant: "light", children: "Lists" }),
693
- /* @__PURE__ */ jsx(Button, { component: Link, to: "/lead-gen/deliverability", size: "sm", variant: "light", children: "Deliverability" })
694
- ] })
636
+ rightSection: /* @__PURE__ */ jsx(Button, { component: Link, to: "/lead-gen/lists", size: "xs", variant: "light", children: "Lists" })
695
637
  }
696
638
  ),
697
639
  telemetryQuery.isLoading ? /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) }) : telemetryQuery.isError ? /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(CenteredErrorState, { error: telemetryQuery.error, title: "Failed to load list telemetry" }) }) : !data?.length ? /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { h: 300, children: /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), color: "gray", variant: "light", children: "No lists yet." }) }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
698
640
  /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 3 }, children: [
699
- /* @__PURE__ */ jsx(StatCard, { variant: "hero", icon: IconPlayerPlay, value: activeListCount, label: "Active Lists" }),
641
+ /* @__PURE__ */ jsx(StatCard, { variant: "hero", icon: IconPlayerPlay, value: totalLists, label: "Total Lists" }),
700
642
  /* @__PURE__ */ jsx(StatCard, { variant: "hero", icon: IconArrowRight, value: uploadBacklog, label: "Ready Contacts" }),
701
643
  /* @__PURE__ */ jsx(StatCard, { variant: "hero", icon: IconAlertCircle, value: deliverabilityRiskCount, label: "At Risk" })
702
644
  ] }),
703
645
  /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
704
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-start", gap: "md", children: [
705
- /* @__PURE__ */ jsxs(Stack, { gap: 4, children: [
706
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", tt: "uppercase", fw: 700, children: "Next Action" }),
707
- /* @__PURE__ */ jsx(Title, { order: 3, children: primaryAction.title }),
708
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", maw: 620, children: primaryAction.detail })
709
- ] }),
710
- /* @__PURE__ */ jsx(Button, { component: Link, to: primaryAction.buttonTo, size: "sm", variant: "light", children: primaryAction.buttonLabel })
711
- ] }),
712
- /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, md: 3 }, children: [
646
+ /* @__PURE__ */ jsx(
647
+ CardHeader,
648
+ {
649
+ icon: /* @__PURE__ */ jsx(IconSparkles, { size: 18 }),
650
+ title: "Next Action",
651
+ subtitle: primaryAction.title,
652
+ rightSection: /* @__PURE__ */ jsx(Button, { component: Link, to: primaryAction.buttonTo, size: "xs", variant: "light", children: primaryAction.buttonLabel })
653
+ }
654
+ ),
655
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", maw: 620, children: primaryAction.detail }),
656
+ /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, md: 2 }, children: [
713
657
  /* @__PURE__ */ jsxs(Card, { withBorder: true, p: "sm", children: [
714
658
  /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", tt: "uppercase", fw: 600, children: "Verification" }),
715
659
  /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-end", mt: 6, children: [
@@ -723,54 +667,25 @@ function LeadGenOverviewPage() {
723
667
  /* @__PURE__ */ jsx(Title, { order: 4, children: personalizationBacklog }),
724
668
  /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "ready" })
725
669
  ] })
726
- ] }),
727
- /* @__PURE__ */ jsxs(Card, { withBorder: true, p: "sm", children: [
728
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", tt: "uppercase", fw: 600, children: "Completion" }),
729
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-end", mt: 6, children: [
730
- /* @__PURE__ */ jsx(Title, { order: 4, children: computeCompletionPercentage(stageTotals.populated, stageTotals.personalized) }),
731
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "personalized" })
732
- ] })
733
670
  ] })
734
671
  ] })
735
672
  ] }) }),
736
673
  /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
737
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-end", children: [
738
- /* @__PURE__ */ jsxs("div", { children: [
739
- /* @__PURE__ */ jsx(Title, { order: 3, children: "Pipeline" }),
740
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Keep the funnel visible without giving every zero state its own section." })
741
- ] }),
742
- /* @__PURE__ */ jsxs(Badge, { variant: "light", color: "blue", children: [
743
- stageTotals.extracted,
744
- " extracted \u2022 ",
745
- stageTotals.discovered,
746
- " discovered"
747
- ] })
748
- ] }),
749
- /* @__PURE__ */ jsx(SimpleGrid, { cols: { base: 1, sm: 2, xl: 5 }, children: pipelineStages.map((stage) => /* @__PURE__ */ jsx(
750
- CompactPipelineStage,
674
+ /* @__PURE__ */ jsx(
675
+ CardHeader,
751
676
  {
752
- label: stage.label,
753
- value: stage.value,
754
- ratio: stage.ratio
755
- },
756
- stage.label
757
- )) })
758
- ] }) }),
759
- /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
760
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-end", children: [
761
- /* @__PURE__ */ jsxs("div", { children: [
762
- /* @__PURE__ */ jsx(Title, { order: 3, children: "List Snapshot" }),
763
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Ranked to surface active work first, then the largest unresolved backlogs." })
764
- ] }),
765
- /* @__PURE__ */ jsx(Button, { component: Link, to: "/lead-gen/lists", size: "sm", variant: "subtle", children: "Open lists" })
766
- ] }),
677
+ icon: /* @__PURE__ */ jsx(IconListDetails, { size: 18 }),
678
+ title: "List Snapshot",
679
+ subtitle: "Ranked to surface active work first, then the largest unresolved backlogs.",
680
+ rightSection: /* @__PURE__ */ jsx(Button, { component: Link, to: "/lead-gen/lists", size: "xs", variant: "subtle", children: "Open lists" })
681
+ }
682
+ ),
767
683
  /* @__PURE__ */ jsxs(Table, { children: [
768
684
  /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
769
685
  /* @__PURE__ */ jsx(Table.Th, { children: "List" }),
770
686
  /* @__PURE__ */ jsx(Table.Th, { children: "Companies" }),
771
687
  /* @__PURE__ */ jsx(Table.Th, { children: "Contacts" }),
772
688
  /* @__PURE__ */ jsx(Table.Th, { children: "Next Focus" }),
773
- /* @__PURE__ */ jsx(Table.Th, { children: "Progress" }),
774
689
  /* @__PURE__ */ jsx(Table.Th, { children: "Status" })
775
690
  ] }) }),
776
691
  /* @__PURE__ */ jsx(Table.Tbody, { children: overviewRows.map((list) => /* @__PURE__ */ jsxs(
@@ -789,25 +704,6 @@ function LeadGenOverviewPage() {
789
704
  /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: list.nextFocus.label }),
790
705
  /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: list.nextFocus.count == null ? "No outstanding count" : `${list.nextFocus.count} item${list.nextFocus.count === 1 ? "" : "s"} queued` })
791
706
  ] }) }),
792
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", miw: 150, children: [
793
- /* @__PURE__ */ jsxs(Group, { justify: "space-between", gap: "xs", children: [
794
- /* @__PURE__ */ jsx(Text, { size: "sm", children: formatPercentage(list.completionRatio) }),
795
- /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
796
- list.stageCounts.personalized,
797
- "/",
798
- list.stageCounts.populated || 0
799
- ] })
800
- ] }),
801
- /* @__PURE__ */ jsx(
802
- Progress,
803
- {
804
- value: list.completionRatio == null ? 0 : list.completionRatio * 100,
805
- size: "sm",
806
- radius: "xl",
807
- color: "blue"
808
- }
809
- )
810
- ] }) }),
811
707
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: list.status.color, children: list.status.label }) })
812
708
  ]
813
709
  },
@@ -818,88 +714,6 @@ function LeadGenOverviewPage() {
818
714
  ] })
819
715
  ] }) }) });
820
716
  }
821
- function LeadGenDeliverabilityPage() {
822
- const { data, isLoading, error } = useListsTelemetry();
823
- if (isLoading) {
824
- return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
825
- /* @__PURE__ */ jsx(
826
- PageTitleCaption,
827
- {
828
- title: "Deliverability",
829
- caption: "Email validity breakdown and bounce health across lists"
830
- }
831
- ),
832
- /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) })
833
- ] }) }) });
834
- }
835
- if (error) {
836
- return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
837
- /* @__PURE__ */ jsx(
838
- PageTitleCaption,
839
- {
840
- title: "Deliverability",
841
- caption: "Email validity breakdown and bounce health across lists"
842
- }
843
- ),
844
- /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(CenteredErrorState, { error, title: "Failed to load deliverability data" }) })
845
- ] }) }) });
846
- }
847
- if (data?.length === 0) {
848
- return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
849
- /* @__PURE__ */ jsx(
850
- PageTitleCaption,
851
- {
852
- title: "Deliverability",
853
- caption: "Email validity breakdown and bounce health across lists"
854
- }
855
- ),
856
- /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsx(Center, { h: 300, children: /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconMailCheck, { size: 16 }), color: "gray", variant: "light", children: "No lists yet. Deliverability will populate once contacts are validated." }) }) })
857
- ] }) }) });
858
- }
859
- const lists = data ?? [];
860
- const totals = lists.reduce(
861
- (acc, list) => ({
862
- valid: acc.valid + list.deliverability.valid,
863
- risky: acc.risky + list.deliverability.risky,
864
- invalid: acc.invalid + list.deliverability.invalid,
865
- unknown: acc.unknown + list.deliverability.unknown,
866
- bounced: acc.bounced + list.deliverability.bounced
867
- }),
868
- { valid: 0, risky: 0, invalid: 0, unknown: 0, bounced: 0 }
869
- );
870
- const summaryTiles = [
871
- { label: "Valid", value: totals.valid, icon: IconMailCheck },
872
- { label: "Risky", value: totals.risky, icon: IconAlertCircle },
873
- { label: "Invalid", value: totals.invalid, icon: IconX },
874
- { label: "Unknown", value: totals.unknown, icon: IconQuestionMark },
875
- { label: "Bounced", value: totals.bounced, icon: IconAlertCircle },
876
- { label: "Bounce Rate", value: computeBounceRate(totals), icon: IconChecklist }
877
- ];
878
- return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
879
- /* @__PURE__ */ jsx(PageTitleCaption, { title: "Deliverability", caption: "Email validity breakdown and bounce health across lists" }),
880
- /* @__PURE__ */ jsx(SimpleGrid, { cols: { base: 2, sm: 3, lg: 6 }, children: summaryTiles.map((tile) => /* @__PURE__ */ jsx(StatCard, { variant: "hero", icon: tile.icon, value: tile.value, label: tile.label }, tile.label)) }),
881
- /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsxs(Table, { children: [
882
- /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
883
- /* @__PURE__ */ jsx(Table.Th, { children: "List ID" }),
884
- /* @__PURE__ */ jsx(Table.Th, { children: "Valid" }),
885
- /* @__PURE__ */ jsx(Table.Th, { children: "Risky" }),
886
- /* @__PURE__ */ jsx(Table.Th, { children: "Invalid" }),
887
- /* @__PURE__ */ jsx(Table.Th, { children: "Unknown" }),
888
- /* @__PURE__ */ jsx(Table.Th, { children: "Bounced" }),
889
- /* @__PURE__ */ jsx(Table.Th, { children: "Bounce Rate" })
890
- ] }) }),
891
- /* @__PURE__ */ jsx(Table.Tbody, { children: lists.map((list) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
892
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: list.listId }) }),
893
- /* @__PURE__ */ jsx(Table.Td, { children: list.deliverability.valid }),
894
- /* @__PURE__ */ jsx(Table.Td, { children: list.deliverability.risky }),
895
- /* @__PURE__ */ jsx(Table.Td, { children: list.deliverability.invalid }),
896
- /* @__PURE__ */ jsx(Table.Td, { children: list.deliverability.unknown }),
897
- /* @__PURE__ */ jsx(Table.Td, { children: list.deliverability.bounced }),
898
- /* @__PURE__ */ jsx(Table.Td, { children: computeBounceRate(list.deliverability) })
899
- ] }, list.listId)) })
900
- ] }) })
901
- ] }) }) });
902
- }
903
717
  var PAGE_SIZE_DEFAULT = 20;
904
718
  function LeadGenListsPage() {
905
719
  const navigate = useNavigate();
@@ -969,7 +783,16 @@ function LeadGenListsPage() {
969
783
  {
970
784
  title: "Lists",
971
785
  caption: "Lead lists and contact organization",
972
- rightSection: /* @__PURE__ */ jsx(Button, { leftSection: /* @__PURE__ */ jsx(IconPlus, { size: 16 }), onClick: () => setShowCreateList(true), children: "New List" })
786
+ rightSection: /* @__PURE__ */ jsx(
787
+ Button,
788
+ {
789
+ leftSection: /* @__PURE__ */ jsx(IconPlus, { size: 16 }),
790
+ onClick: () => setShowCreateList(true),
791
+ variant: "light",
792
+ size: "xs",
793
+ children: "New List"
794
+ }
795
+ )
973
796
  }
974
797
  ) }),
975
798
  /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
@@ -1171,17 +994,18 @@ function formatDateTime(value) {
1171
994
  minute: "2-digit"
1172
995
  });
1173
996
  }
997
+ function contactDisplayName(firstName, lastName) {
998
+ const full = [firstName, lastName].filter(Boolean).join(" ").trim();
999
+ return full || "\u2014";
1000
+ }
1174
1001
  function LeadGenListDetailPage({ listId }) {
1175
1002
  const navigate = useNavigate();
1176
- const [selectedStepKey, setSelectedStepKey] = useState(null);
1177
1003
  const listQuery = useList(listId);
1178
1004
  const progressQuery = useListProgress(listId);
1179
1005
  const executionsQuery = useListExecutions(listId);
1180
- const selectedStep = useMemo(
1181
- () => listQuery.data?.config.pipeline?.steps?.slice().sort((a, b) => a.order - b.order).find((step) => step.key === selectedStepKey) ?? null,
1182
- [listQuery.data?.config.pipeline?.steps, selectedStepKey]
1183
- );
1184
- const resourceDefinitionQuery = useResourceDefinition(selectedStep?.resourceId ?? "", !!selectedStep?.resourceId);
1006
+ const contactsQuery = useContacts({ listId, limit: 100, offset: 0 });
1007
+ const companiesQuery = useCompanies({ listId, limit: 100, offset: 0 });
1008
+ const [memberTab, setMemberTab] = useState("contacts");
1185
1009
  const isLoading = listQuery.isLoading || progressQuery.isLoading || executionsQuery.isLoading;
1186
1010
  const error = listQuery.error ?? progressQuery.error ?? executionsQuery.error;
1187
1011
  if (isLoading) {
@@ -1195,7 +1019,7 @@ function LeadGenListDetailPage({ listId }) {
1195
1019
  Button,
1196
1020
  {
1197
1021
  variant: "light",
1198
- size: "sm",
1022
+ size: "xs",
1199
1023
  leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
1200
1024
  onClick: () => navigate({ to: "/lead-gen/lists" }),
1201
1025
  children: "Lists"
@@ -1217,7 +1041,7 @@ function LeadGenListDetailPage({ listId }) {
1217
1041
  Button,
1218
1042
  {
1219
1043
  variant: "light",
1220
- size: "sm",
1044
+ size: "xs",
1221
1045
  leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
1222
1046
  onClick: () => navigate({ to: "/lead-gen/lists" }),
1223
1047
  children: "Lists"
@@ -1239,7 +1063,7 @@ function LeadGenListDetailPage({ listId }) {
1239
1063
  Button,
1240
1064
  {
1241
1065
  variant: "light",
1242
- size: "sm",
1066
+ size: "xs",
1243
1067
  leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
1244
1068
  onClick: () => navigate({ to: "/lead-gen/lists" }),
1245
1069
  children: "Lists"
@@ -1253,210 +1077,117 @@ function LeadGenListDetailPage({ listId }) {
1253
1077
  const list = listQuery.data;
1254
1078
  const progress = progressQuery.data;
1255
1079
  const executions = executionsQuery.data ?? [];
1256
- const qualification = list.config.qualification;
1257
- const pipelineSteps = list.config.pipeline?.steps?.slice().sort((a, b) => a.order - b.order) ?? [];
1258
- const stageTiles = [
1259
- { label: "Populated", value: progress.stageCounts.populated },
1260
- { label: "Extracted", value: progress.stageCounts.extracted },
1261
- { label: "Qualified", value: progress.stageCounts.qualified },
1262
- { label: "Discovered", value: progress.stageCounts.discovered },
1263
- { label: "Verified", value: progress.stageCounts.verified },
1264
- { label: "Personalized", value: progress.stageCounts.personalized },
1265
- { label: "Uploaded", value: progress.stageCounts.uploaded }
1266
- ];
1267
- const deliverabilityTiles = [
1268
- { label: "Valid", value: progress.deliverability.valid },
1269
- { label: "Risky", value: progress.deliverability.risky },
1270
- { label: "Invalid", value: progress.deliverability.invalid },
1271
- { label: "Unknown", value: progress.deliverability.unknown },
1272
- { label: "Bounced", value: progress.deliverability.bounced }
1273
- ];
1274
- return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsxs(PageContainer, { children: [
1275
- /* @__PURE__ */ jsxs(Stack, { children: [
1080
+ const contacts = contactsQuery.data?.data ?? [];
1081
+ const companies = companiesQuery.data?.data ?? [];
1082
+ return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
1083
+ /* @__PURE__ */ jsx(
1084
+ PageTitleCaption,
1085
+ {
1086
+ title: list.name,
1087
+ caption: list.description ?? "Configuration, progress, and execution history for this list",
1088
+ rightSection: /* @__PURE__ */ jsx(
1089
+ Button,
1090
+ {
1091
+ variant: "light",
1092
+ size: "xs",
1093
+ leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
1094
+ onClick: () => navigate({ to: "/lead-gen/lists" }),
1095
+ children: "Lists"
1096
+ }
1097
+ )
1098
+ }
1099
+ ),
1100
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
1101
+ /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor(list.status), children: list.status }),
1102
+ /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
1103
+ "Created ",
1104
+ formatDateTime(list.createdAt)
1105
+ ] })
1106
+ ] }),
1107
+ /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 2 }, children: [
1108
+ /* @__PURE__ */ jsx(StatCard, { label: "Companies", value: progress.totalCompanies, icon: IconBuilding }),
1109
+ /* @__PURE__ */ jsx(StatCard, { label: "Contacts", value: progress.totalContacts, icon: IconUsers })
1110
+ ] }),
1111
+ /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
1276
1112
  /* @__PURE__ */ jsx(
1277
- PageTitleCaption,
1113
+ CardHeader,
1278
1114
  {
1279
- title: list.name,
1280
- caption: list.description ?? "Configuration, progress, and execution history for this list",
1115
+ icon: /* @__PURE__ */ jsx(IconAddressBook, { size: 16 }),
1116
+ title: "Members",
1281
1117
  rightSection: /* @__PURE__ */ jsx(
1282
- Button,
1118
+ SegmentedControl,
1283
1119
  {
1284
- variant: "light",
1285
- size: "sm",
1286
- leftSection: /* @__PURE__ */ jsx(IconArrowLeft, { size: 16 }),
1287
- onClick: () => navigate({ to: "/lead-gen/lists" }),
1288
- children: "Lists"
1120
+ value: memberTab,
1121
+ onChange: (value) => setMemberTab(value),
1122
+ size: "xs",
1123
+ data: [
1124
+ { label: `Contacts (${progress.totalContacts})`, value: "contacts" },
1125
+ { label: `Companies (${progress.totalCompanies})`, value: "companies" }
1126
+ ]
1289
1127
  }
1290
1128
  )
1291
1129
  }
1292
1130
  ),
1293
- /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1294
- /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor(list.status), children: list.status }),
1295
- /* @__PURE__ */ jsxs(Text, { size: "sm", c: "dimmed", children: [
1296
- "Created ",
1297
- formatDateTime(list.createdAt)
1298
- ] })
1299
- ] }),
1300
- /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, sm: 2, lg: 4 }, children: [
1301
- /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
1302
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", mb: "xs", children: "Companies" }),
1303
- /* @__PURE__ */ jsx(Title, { order: 3, children: progress.totalCompanies })
1304
- ] }),
1305
- /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
1306
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", mb: "xs", children: "Contacts" }),
1307
- /* @__PURE__ */ jsx(Title, { order: 3, children: progress.totalContacts })
1308
- ] }),
1309
- /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
1310
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", mb: "xs", children: "Pipeline Steps" }),
1311
- /* @__PURE__ */ jsx(Title, { order: 3, children: pipelineSteps.length })
1312
- ] }),
1313
- /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
1314
- /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", mb: "xs", children: "Executions" }),
1315
- /* @__PURE__ */ jsx(Title, { order: 3, children: executions.length })
1316
- ] })
1317
- ] }),
1318
- /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
1319
- /* @__PURE__ */ jsx(Title, { order: 3, children: "Pipeline Progress" }),
1320
- /* @__PURE__ */ jsx(SimpleGrid, { cols: { base: 2, sm: 3, lg: 7 }, children: stageTiles.map((tile) => /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "sm", children: [
1321
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: tile.label }),
1322
- /* @__PURE__ */ jsx(Title, { order: 4, children: tile.value })
1323
- ] }, tile.label)) })
1324
- ] }) }),
1325
- /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
1326
- /* @__PURE__ */ jsx(Title, { order: 3, children: "Deliverability" }),
1327
- /* @__PURE__ */ jsx(SimpleGrid, { cols: { base: 2, sm: 3, lg: 5 }, children: deliverabilityTiles.map((tile) => /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "sm", children: [
1328
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: tile.label }),
1329
- /* @__PURE__ */ jsx(Title, { order: 4, children: tile.value })
1330
- ] }, tile.label)) })
1331
- ] }) }),
1332
- /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
1333
- /* @__PURE__ */ jsx(Title, { order: 3, children: "Configuration" }),
1334
- /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, lg: 2 }, children: [
1335
- /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1336
- /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "Qualification" }),
1337
- qualification ? /* @__PURE__ */ jsxs(Fragment, { children: [
1338
- /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
1339
- "Target: ",
1340
- qualification.targetDescription
1341
- ] }),
1342
- /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
1343
- "Minimum reviews: ",
1344
- qualification.minReviewCount
1345
- ] }),
1346
- /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
1347
- "Minimum rating: ",
1348
- qualification.minRating
1349
- ] }),
1350
- /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
1351
- "Exclude franchises: ",
1352
- qualification.excludeFranchises ? "Yes" : "No"
1353
- ] })
1354
- ] }) : /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Qualification settings are not configured for this list." })
1355
- ] }) }),
1356
- /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
1357
- /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "Enrichment + Personalization" }),
1358
- /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
1359
- "Discovery provider: ",
1360
- list.config.enrichment?.emailDiscovery?.primary ?? "Inherited default"
1361
- ] }),
1362
- /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
1363
- "Verification provider: ",
1364
- list.config.enrichment?.emailVerification?.provider ?? "Inherited default"
1365
- ] }),
1366
- /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
1367
- "Industry context: ",
1368
- list.config.personalization?.industryContext ?? "Inherited default"
1369
- ] }),
1370
- /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
1371
- "Creative direction: ",
1372
- list.config.personalization?.creativeDirection ?? "Inherited default"
1373
- ] })
1374
- ] }) })
1375
- ] }),
1376
- list.config.personalization?.emailBody ? /* @__PURE__ */ jsxs(Box, { children: [
1377
- /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, mb: "xs", children: "Email Body Template" }),
1378
- /* @__PURE__ */ jsx(Code, { block: true, children: list.config.personalization.emailBody })
1379
- ] }) : null
1380
- ] }) }),
1381
- /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
1382
- /* @__PURE__ */ jsx(Title, { order: 3, children: "Pipeline Steps" }),
1383
- !pipelineSteps.length ? /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconAlertCircle, { size: 16 }), color: "gray", variant: "light", children: "This list does not have any configured pipeline steps yet." }) : /* @__PURE__ */ jsxs(Table, { children: [
1384
- /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1385
- /* @__PURE__ */ jsx(Table.Th, { children: "Order" }),
1386
- /* @__PURE__ */ jsx(Table.Th, { children: "Step" }),
1387
- /* @__PURE__ */ jsx(Table.Th, { children: "Resource" }),
1388
- /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1389
- /* @__PURE__ */ jsx(Table.Th, { children: "Action" })
1390
- ] }) }),
1391
- /* @__PURE__ */ jsx(Table.Tbody, { children: pipelineSteps.map((step) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
1392
- /* @__PURE__ */ jsx(Table.Td, { children: step.order }),
1393
- /* @__PURE__ */ jsxs(Table.Td, { children: [
1394
- /* @__PURE__ */ jsx(Text, { fw: 500, children: step.label }),
1395
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: step.key })
1396
- ] }),
1397
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Code, { children: step.resourceId }) }),
1398
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: step.enabled ? "light" : "outline", color: step.enabled ? "green" : "gray", children: step.enabled ? "Enabled" : "Disabled" }) }),
1399
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(
1400
- Button,
1401
- {
1402
- size: "xs",
1403
- variant: "light",
1404
- leftSection: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 14 }),
1405
- disabled: !step.enabled,
1406
- onClick: () => setSelectedStepKey(step.key),
1407
- children: "Run"
1408
- }
1409
- ) })
1410
- ] }, step.key)) })
1411
- ] })
1131
+ 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: [
1132
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1133
+ /* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
1134
+ /* @__PURE__ */ jsx(Table.Th, { children: "Email" }),
1135
+ /* @__PURE__ */ jsx(Table.Th, { children: "Title" }),
1136
+ /* @__PURE__ */ jsx(Table.Th, { children: "Company" }),
1137
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1138
+ /* @__PURE__ */ jsx(Table.Th, { children: "Created" })
1139
+ ] }) }),
1140
+ /* @__PURE__ */ jsx(Table.Tbody, { children: contacts.map((contact) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
1141
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: contactDisplayName(contact.firstName, contact.lastName) }) }),
1142
+ /* @__PURE__ */ jsx(Table.Td, { children: contact.email }),
1143
+ /* @__PURE__ */ jsx(Table.Td, { children: contact.title ?? "\u2014" }),
1144
+ /* @__PURE__ */ jsx(Table.Td, { children: contact.company?.name ?? "\u2014" }),
1145
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor(contact.status), children: contact.status }) }),
1146
+ /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime(contact.createdAt) })
1147
+ ] }, contact.id)) })
1412
1148
  ] }) }),
1413
- /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
1414
- /* @__PURE__ */ jsx(Title, { order: 3, children: "Execution History" }),
1415
- !executions.length ? /* @__PURE__ */ jsx(Alert, { icon: /* @__PURE__ */ jsx(IconClockHour4, { size: 16 }), color: "gray", variant: "light", children: "No executions recorded for this list yet." }) : /* @__PURE__ */ jsxs(Table, { children: [
1416
- /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1417
- /* @__PURE__ */ jsx(Table.Th, { children: "Resource" }),
1418
- /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1419
- /* @__PURE__ */ jsx(Table.Th, { children: "Started" }),
1420
- /* @__PURE__ */ jsx(Table.Th, { children: "Completed" }),
1421
- /* @__PURE__ */ jsx(Table.Th, { children: "Duration" })
1422
- ] }) }),
1423
- /* @__PURE__ */ jsx(Table.Tbody, { children: executions.map((execution) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
1424
- /* @__PURE__ */ jsxs(Table.Td, { children: [
1425
- /* @__PURE__ */ jsx(Text, { fw: 500, children: execution.resourceId }),
1426
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: execution.executionId })
1427
- ] }),
1428
- /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor(execution.status), children: execution.status }) }),
1429
- /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime(execution.createdAt) }),
1430
- /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime(execution.completedAt) }),
1431
- /* @__PURE__ */ jsx(Table.Td, { children: execution.durationMs == null ? "n/a" : `${execution.durationMs} ms` })
1432
- ] }, execution.executionId)) })
1433
- ] })
1149
+ 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: [
1150
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1151
+ /* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
1152
+ /* @__PURE__ */ jsx(Table.Th, { children: "Domain" }),
1153
+ /* @__PURE__ */ jsx(Table.Th, { children: "Segment" }),
1154
+ /* @__PURE__ */ jsx(Table.Th, { children: "Contacts" }),
1155
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1156
+ /* @__PURE__ */ jsx(Table.Th, { children: "Created" })
1157
+ ] }) }),
1158
+ /* @__PURE__ */ jsx(Table.Tbody, { children: companies.map((company) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
1159
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: company.name }) }),
1160
+ /* @__PURE__ */ jsx(Table.Td, { children: company.domain ?? "\u2014" }),
1161
+ /* @__PURE__ */ jsx(Table.Td, { children: company.segment ?? "\u2014" }),
1162
+ /* @__PURE__ */ jsx(Table.Td, { children: company.contactCount }),
1163
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor(company.status), children: company.status }) }),
1164
+ /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime(company.createdAt) })
1165
+ ] }, company.id)) })
1434
1166
  ] }) })
1435
1167
  ] }),
1436
- selectedStep ? /* @__PURE__ */ jsx(
1437
- ResourceExecuteDialog,
1438
- {
1439
- opened: !!selectedStep && !resourceDefinitionQuery.isLoading,
1440
- onClose: () => setSelectedStepKey(null),
1441
- resource: {
1442
- resourceId: selectedStep.resourceId,
1443
- resourceType: "workflow",
1444
- name: selectedStep.label,
1445
- formSchema: resourceDefinitionQuery.data?.interface?.form
1446
- }
1447
- }
1448
- ) : null,
1449
- /* @__PURE__ */ jsx(
1450
- Modal,
1451
- {
1452
- opened: resourceDefinitionQuery.isLoading && !!selectedStep,
1453
- onClose: () => setSelectedStepKey(null),
1454
- withCloseButton: false,
1455
- centered: true,
1456
- children: /* @__PURE__ */ jsx(Center, { p: "md", children: /* @__PURE__ */ jsx(Loader, {}) })
1457
- }
1458
- )
1459
- ] }) });
1168
+ /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
1169
+ /* @__PURE__ */ jsx(CardHeader, { icon: /* @__PURE__ */ jsx(IconPlayerPlay, { size: 16 }), title: "Execution History" }),
1170
+ !executions.length ? /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "No executions recorded for this list yet." }) : /* @__PURE__ */ jsxs(Table, { children: [
1171
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1172
+ /* @__PURE__ */ jsx(Table.Th, { children: "Resource" }),
1173
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1174
+ /* @__PURE__ */ jsx(Table.Th, { children: "Started" }),
1175
+ /* @__PURE__ */ jsx(Table.Th, { children: "Completed" }),
1176
+ /* @__PURE__ */ jsx(Table.Th, { children: "Duration" })
1177
+ ] }) }),
1178
+ /* @__PURE__ */ jsx(Table.Tbody, { children: executions.map((execution) => /* @__PURE__ */ jsxs(Table.Tr, { children: [
1179
+ /* @__PURE__ */ jsxs(Table.Td, { children: [
1180
+ /* @__PURE__ */ jsx(Text, { fw: 500, children: execution.resourceId }),
1181
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: execution.executionId })
1182
+ ] }),
1183
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: "light", color: getStatusColor(execution.status), children: execution.status }) }),
1184
+ /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime(execution.createdAt) }),
1185
+ /* @__PURE__ */ jsx(Table.Td, { children: formatDateTime(execution.completedAt) }),
1186
+ /* @__PURE__ */ jsx(Table.Td, { children: execution.durationMs == null ? "n/a" : `${execution.durationMs} ms` })
1187
+ ] }, execution.executionId)) })
1188
+ ] })
1189
+ ] })
1190
+ ] }) }) });
1460
1191
  }
1461
1192
  var PAGE_SIZE_DEFAULT2 = 20;
1462
1193
  function LeadGenCompaniesPage() {
@@ -1466,36 +1197,24 @@ function LeadGenCompaniesPage() {
1466
1197
  const [statusFilter, setStatusFilter] = useState(null);
1467
1198
  const [selectedCompany, setSelectedCompany] = useState(null);
1468
1199
  const [showBatchDelete, setShowBatchDelete] = useState(false);
1469
- const { data: companies, isLoading: companiesLoading } = useCompanies({
1200
+ const pagination = usePaginationState(PAGE_SIZE_DEFAULT2, [companySearch, segmentFilter, categoryFilter, statusFilter]);
1201
+ const { data: companyFacets } = useCompanyFacets();
1202
+ const { data: pagedCompanies, isLoading: pagedCompaniesLoading, error: pagedCompaniesError } = useCompanies({
1470
1203
  search: companySearch || void 0,
1471
1204
  segment: segmentFilter || void 0,
1472
1205
  category: categoryFilter || void 0,
1473
- status: statusFilter === "active" || statusFilter === "invalid" ? statusFilter : void 0
1206
+ status: statusFilter || void 0,
1207
+ limit: PAGE_SIZE_DEFAULT2,
1208
+ offset: pagination.offset
1474
1209
  });
1475
1210
  const deleteCompaniesMutation = useDeleteCompanies();
1476
- const { sort, toggleSort } = useTableSort("company", "asc");
1477
- const sortAccessors = useMemo(
1478
- () => ({
1479
- company: (company) => company.name,
1480
- domain: (company) => company.domain || "",
1481
- segment: (company) => company.segment || "",
1482
- category: (company) => company.category || "",
1483
- employees: (company) => company.numEmployees ?? 0,
1484
- enrichment: (company) => getEnrichmentStatus(company.enrichmentData),
1485
- contacts: (company) => company.contactCount
1486
- }),
1487
- []
1488
- );
1489
- const sortedCompanies = useMemo(
1490
- () => sortData(companies ?? [], sort, sortAccessors),
1491
- [companies, sort, sortAccessors]
1492
- );
1493
- const pagination = usePaginationState(PAGE_SIZE_DEFAULT2, [companySearch, segmentFilter, categoryFilter, statusFilter], sortedCompanies.length);
1494
- const paginatedCompanies = useMemo(
1495
- () => sortedCompanies.slice(pagination.offset, pagination.offset + PAGE_SIZE_DEFAULT2),
1496
- [sortedCompanies, pagination.offset]
1497
- );
1498
- const selection = useTableSelection(paginatedCompanies, sortedCompanies);
1211
+ const companyRows = pagedCompanies?.data ?? [];
1212
+ const selection = useTableSelection(companyRows);
1213
+ useEffect(() => {
1214
+ if ((pagedCompanies?.total ?? 0) === 0) return;
1215
+ if (companyRows.length > 0 || pagination.page === 1) return;
1216
+ pagination.setPage(pagination.page - 1);
1217
+ }, [companyRows.length, pagedCompanies?.total, pagination.page, pagination.setPage]);
1499
1218
  function handleBatchDelete() {
1500
1219
  deleteCompaniesMutation.mutate([...selection.selectedIds], {
1501
1220
  onSuccess: () => {
@@ -1523,9 +1242,9 @@ function LeadGenCompaniesPage() {
1523
1242
  Select,
1524
1243
  {
1525
1244
  placeholder: "All Segments",
1526
- data: ["Technology", "Marketing", "Finance", "Healthcare"],
1245
+ data: companyFacets?.segments ?? [],
1527
1246
  value: segmentFilter,
1528
- onChange: setSegmentFilter,
1247
+ onChange: (value) => setSegmentFilter(value),
1529
1248
  style: { minWidth: 180 },
1530
1249
  size: "sm",
1531
1250
  clearable: true
@@ -1535,9 +1254,9 @@ function LeadGenCompaniesPage() {
1535
1254
  Select,
1536
1255
  {
1537
1256
  placeholder: "All Categories",
1538
- data: ["SaaS", "Service Agency", "Software"],
1257
+ data: companyFacets?.categories ?? [],
1539
1258
  value: categoryFilter,
1540
- onChange: setCategoryFilter,
1259
+ onChange: (value) => setCategoryFilter(value),
1541
1260
  style: { minWidth: 160 },
1542
1261
  size: "sm",
1543
1262
  clearable: true
@@ -1547,12 +1266,12 @@ function LeadGenCompaniesPage() {
1547
1266
  Select,
1548
1267
  {
1549
1268
  placeholder: "All Statuses",
1550
- data: [
1551
- { value: "active", label: "Active" },
1552
- { value: "invalid", label: "Invalid" }
1553
- ],
1269
+ data: (companyFacets?.statuses ?? []).map((status) => ({
1270
+ value: status,
1271
+ label: status[0].toUpperCase() + status.slice(1)
1272
+ })),
1554
1273
  value: statusFilter,
1555
- onChange: setStatusFilter,
1274
+ onChange: (value) => setStatusFilter(value),
1556
1275
  style: { minWidth: 160 },
1557
1276
  size: "sm",
1558
1277
  clearable: true
@@ -1572,7 +1291,7 @@ function LeadGenCompaniesPage() {
1572
1291
  ]
1573
1292
  }
1574
1293
  ),
1575
- companiesLoading ? /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) : !sortedCompanies.length ? /* @__PURE__ */ jsx(EmptyState, { icon: IconBuildingFactory2, title: "No companies yet", description: "Add one to get started." }) : /* @__PURE__ */ jsxs(Table, { children: [
1294
+ pagedCompaniesLoading ? /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) : pagedCompaniesError ? /* @__PURE__ */ jsx(CenteredErrorState, { error: pagedCompaniesError, title: "Failed to load companies" }) : !companyRows.length ? /* @__PURE__ */ jsx(EmptyState, { icon: IconBuildingFactory2, title: "No companies yet", description: "Add one to get started." }) : /* @__PURE__ */ jsxs(Table, { children: [
1576
1295
  /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1577
1296
  /* @__PURE__ */ jsx(Table.Th, { w: 40, children: /* @__PURE__ */ jsx(
1578
1297
  Checkbox,
@@ -1582,15 +1301,15 @@ function LeadGenCompaniesPage() {
1582
1301
  onChange: selection.togglePage
1583
1302
  }
1584
1303
  ) }),
1585
- /* @__PURE__ */ jsx(SortableHeader, { column: "company", sort, onToggle: toggleSort, children: "Company" }),
1586
- /* @__PURE__ */ jsx(SortableHeader, { column: "domain", sort, onToggle: toggleSort, children: "Domain" }),
1587
- /* @__PURE__ */ jsx(SortableHeader, { column: "segment", sort, onToggle: toggleSort, children: "Segment" }),
1588
- /* @__PURE__ */ jsx(SortableHeader, { column: "category", sort, onToggle: toggleSort, children: "Category" }),
1589
- /* @__PURE__ */ jsx(SortableHeader, { column: "employees", sort, onToggle: toggleSort, children: "Employees" }),
1590
- /* @__PURE__ */ jsx(SortableHeader, { column: "enrichment", sort, onToggle: toggleSort, children: "Enrichment" }),
1591
- /* @__PURE__ */ jsx(SortableHeader, { column: "contacts", sort, onToggle: toggleSort, children: "Contacts" })
1304
+ /* @__PURE__ */ jsx(Table.Th, { children: "Company" }),
1305
+ /* @__PURE__ */ jsx(Table.Th, { children: "Domain" }),
1306
+ /* @__PURE__ */ jsx(Table.Th, { children: "Segment" }),
1307
+ /* @__PURE__ */ jsx(Table.Th, { children: "Category" }),
1308
+ /* @__PURE__ */ jsx(Table.Th, { children: "Employees" }),
1309
+ /* @__PURE__ */ jsx(Table.Th, { children: "Enrichment" }),
1310
+ /* @__PURE__ */ jsx(Table.Th, { children: "Contacts" })
1592
1311
  ] }) }),
1593
- /* @__PURE__ */ jsx(Table.Tbody, { children: paginatedCompanies.map((company) => {
1312
+ /* @__PURE__ */ jsx(Table.Tbody, { children: companyRows.map((company) => {
1594
1313
  const enrichStatus = getEnrichmentStatus(company.enrichmentData);
1595
1314
  return /* @__PURE__ */ jsxs(
1596
1315
  Table.Tr,
@@ -1628,12 +1347,12 @@ function LeadGenCompaniesPage() {
1628
1347
  );
1629
1348
  }) })
1630
1349
  ] }),
1631
- sortedCompanies.length > PAGE_SIZE_DEFAULT2 ? /* @__PURE__ */ jsx(Group, { justify: "center", children: /* @__PURE__ */ jsx(
1350
+ (pagedCompanies?.total ?? 0) > PAGE_SIZE_DEFAULT2 ? /* @__PURE__ */ jsx(Group, { justify: "center", children: /* @__PURE__ */ jsx(
1632
1351
  Pagination,
1633
1352
  {
1634
1353
  value: pagination.page,
1635
1354
  onChange: pagination.setPage,
1636
- total: pagination.totalPages(sortedCompanies.length),
1355
+ total: pagination.totalPages(pagedCompanies?.total ?? 0),
1637
1356
  size: "sm"
1638
1357
  }
1639
1358
  ) }) : null
@@ -1663,35 +1382,23 @@ function LeadGenContactsPage() {
1663
1382
  const [listFilter, setListFilter] = useState(null);
1664
1383
  const [selectedContact, setSelectedContact] = useState(null);
1665
1384
  const [showBatchDelete, setShowBatchDelete] = useState(false);
1385
+ const pagination = usePaginationState(PAGE_SIZE_DEFAULT3, [contactSearch, statusFilter, listFilter]);
1666
1386
  const { data: lists } = useLists();
1667
- const { data: contacts, isLoading: contactsLoading } = useContacts({
1387
+ const { data: contacts, isLoading: contactsLoading, error: contactsError } = useContacts({
1668
1388
  search: contactSearch || void 0,
1669
- contactStatus: statusFilter === "active" || statusFilter === "invalid" ? statusFilter : void 0,
1670
- listId: listFilter || void 0
1389
+ contactStatus: statusFilter || void 0,
1390
+ listId: listFilter || void 0,
1391
+ limit: PAGE_SIZE_DEFAULT3,
1392
+ offset: pagination.offset
1671
1393
  });
1672
1394
  const deleteContactsMutation = useDeleteContacts();
1673
- const { sort, toggleSort } = useTableSort("name", "asc");
1674
- const sortAccessors = useMemo(
1675
- () => ({
1676
- name: (contact) => [contact.firstName, contact.lastName].filter(Boolean).join(" ") || contact.email,
1677
- email: (contact) => contact.email,
1678
- company: (contact) => contact.company?.name || "",
1679
- title: (contact) => contact.title || "",
1680
- status: (contact) => contact.status || "",
1681
- personalized: (contact) => contact.openingLine ? "yes" : "no"
1682
- }),
1683
- []
1684
- );
1685
- const sortedContacts = useMemo(
1686
- () => sortData(contacts ?? [], sort, sortAccessors),
1687
- [contacts, sort, sortAccessors]
1688
- );
1689
- const pagination = usePaginationState(PAGE_SIZE_DEFAULT3, [contactSearch, statusFilter, listFilter], sortedContacts.length);
1690
- const paginatedContacts = useMemo(
1691
- () => sortedContacts.slice(pagination.offset, pagination.offset + PAGE_SIZE_DEFAULT3),
1692
- [sortedContacts, pagination.offset]
1693
- );
1694
- const selection = useTableSelection(paginatedContacts, sortedContacts);
1395
+ const contactRows = contacts?.data ?? [];
1396
+ const selection = useTableSelection(contactRows);
1397
+ useEffect(() => {
1398
+ if ((contacts?.total ?? 0) === 0) return;
1399
+ if (contactRows.length > 0 || pagination.page === 1) return;
1400
+ pagination.setPage(pagination.page - 1);
1401
+ }, [contactRows.length, contacts?.total, pagination.page, pagination.setPage]);
1695
1402
  function handleBatchDelete() {
1696
1403
  deleteContactsMutation.mutate([...selection.selectedIds], {
1697
1404
  onSuccess: () => {
@@ -1724,7 +1431,7 @@ function LeadGenContactsPage() {
1724
1431
  { value: "invalid", label: "Invalid" }
1725
1432
  ],
1726
1433
  value: statusFilter,
1727
- onChange: setStatusFilter,
1434
+ onChange: (value) => setStatusFilter(value),
1728
1435
  style: { minWidth: 160 },
1729
1436
  size: "sm",
1730
1437
  clearable: true
@@ -1736,7 +1443,7 @@ function LeadGenContactsPage() {
1736
1443
  placeholder: "All Lists",
1737
1444
  data: (lists ?? []).map((list) => ({ value: list.id, label: list.name })),
1738
1445
  value: listFilter,
1739
- onChange: setListFilter,
1446
+ onChange: (value) => setListFilter(value),
1740
1447
  style: { minWidth: 200 },
1741
1448
  size: "sm",
1742
1449
  clearable: true
@@ -1756,7 +1463,7 @@ function LeadGenContactsPage() {
1756
1463
  ]
1757
1464
  }
1758
1465
  ),
1759
- contactsLoading ? /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) : !sortedContacts.length ? /* @__PURE__ */ jsx(EmptyState, { icon: IconUsers, title: "No contacts yet", description: "Add one to get started." }) : /* @__PURE__ */ jsxs(Table, { children: [
1466
+ contactsLoading ? /* @__PURE__ */ jsx(Center, { p: "xl", children: /* @__PURE__ */ jsx(Loader, {}) }) : contactsError ? /* @__PURE__ */ jsx(CenteredErrorState, { error: contactsError, title: "Failed to load contacts" }) : !contactRows.length ? /* @__PURE__ */ jsx(EmptyState, { icon: IconUsers, title: "No contacts yet", description: "Add one to get started." }) : /* @__PURE__ */ jsxs(Table, { children: [
1760
1467
  /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
1761
1468
  /* @__PURE__ */ jsx(Table.Th, { w: 40, children: /* @__PURE__ */ jsx(
1762
1469
  Checkbox,
@@ -1766,14 +1473,14 @@ function LeadGenContactsPage() {
1766
1473
  onChange: selection.togglePage
1767
1474
  }
1768
1475
  ) }),
1769
- /* @__PURE__ */ jsx(SortableHeader, { column: "name", sort, onToggle: toggleSort, children: "Name" }),
1770
- /* @__PURE__ */ jsx(SortableHeader, { column: "email", sort, onToggle: toggleSort, children: "Email" }),
1771
- /* @__PURE__ */ jsx(SortableHeader, { column: "company", sort, onToggle: toggleSort, children: "Company" }),
1772
- /* @__PURE__ */ jsx(SortableHeader, { column: "title", sort, onToggle: toggleSort, children: "Title" }),
1773
- /* @__PURE__ */ jsx(SortableHeader, { column: "status", sort, onToggle: toggleSort, children: "Status" }),
1774
- /* @__PURE__ */ jsx(SortableHeader, { column: "personalized", sort, onToggle: toggleSort, children: "Personalized" })
1476
+ /* @__PURE__ */ jsx(Table.Th, { children: "Name" }),
1477
+ /* @__PURE__ */ jsx(Table.Th, { children: "Email" }),
1478
+ /* @__PURE__ */ jsx(Table.Th, { children: "Company" }),
1479
+ /* @__PURE__ */ jsx(Table.Th, { children: "Title" }),
1480
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" }),
1481
+ /* @__PURE__ */ jsx(Table.Th, { children: "Personalized" })
1775
1482
  ] }) }),
1776
- /* @__PURE__ */ jsx(Table.Tbody, { children: paginatedContacts.map((contact) => {
1483
+ /* @__PURE__ */ jsx(Table.Tbody, { children: contactRows.map((contact) => {
1777
1484
  const fullName = [contact.firstName, contact.lastName].filter(Boolean).join(" ") || contact.email;
1778
1485
  const hasPersonalization = !!contact.openingLine;
1779
1486
  return /* @__PURE__ */ jsxs(
@@ -1811,12 +1518,12 @@ function LeadGenContactsPage() {
1811
1518
  );
1812
1519
  }) })
1813
1520
  ] }),
1814
- sortedContacts.length > PAGE_SIZE_DEFAULT3 ? /* @__PURE__ */ jsx(Group, { justify: "center", children: /* @__PURE__ */ jsx(
1521
+ (contacts?.total ?? 0) > PAGE_SIZE_DEFAULT3 ? /* @__PURE__ */ jsx(Group, { justify: "center", children: /* @__PURE__ */ jsx(
1815
1522
  Pagination,
1816
1523
  {
1817
1524
  value: pagination.page,
1818
1525
  onChange: pagination.setPage,
1819
- total: pagination.totalPages(sortedContacts.length),
1526
+ total: pagination.totalPages(contacts?.total ?? 0),
1820
1527
  size: "sm"
1821
1528
  }
1822
1529
  ) }) : null
@@ -1840,4 +1547,4 @@ function LeadGenContactsPage() {
1840
1547
  ] }) });
1841
1548
  }
1842
1549
 
1843
- export { CompanyDetailModal, ContactDetailModal, LEAD_GEN_ITEMS, LEAD_GEN_ROUTE_LINKS, LIST_TEMPLATE_OPTIONS, LeadGenCompaniesPage, LeadGenContactsPage, LeadGenDeliverabilityPage, LeadGenListDetailPage, LeadGenListsPage, LeadGenOverviewPage, LeadGenRouteShell, LeadGenSidebar, LeadGenSidebarMiddle, LeadGenSidebarTop, buildListConfig, formatDate, getEnrichmentColor, getEnrichmentStatus, getStatusColor, leadGenManifest, useDeleteLists };
1550
+ 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 };