@elevasis/ui 2.1.0 → 2.2.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.
@@ -1,25 +1,25 @@
1
1
  import { useBreadcrumbs } from '../chunk-MG3NF7QL.js';
2
2
  import '../chunk-SMJLS23U.js';
3
- import { NotificationList } from '../chunk-QRHLV74B.js';
4
- export { ActivityCard, ActivityFilters as ActivityFiltersBar, ActivityTable, BusinessImpactCard, CostBreakdownCard, CostByModelTable, CostMetricsCard, ErrorAnalysisCard, ErrorBreakdownTable, ExecutionBreakdownTable, ExecutionHealthCard, ExecutionLogsFilters as ExecutionLogsFilterBar, ExecutionLogsTable, NotificationItem, NotificationList, monitoringManifest } from '../chunk-QRHLV74B.js';
5
- export { CreateCredentialModal, CredentialList, CredentialSettings, MembershipFeaturePanel, MembershipStatusBadge, OAuthConnectModal, OrganizationMembershipsList, WebhookUrlDisplayModal, settingsManifest } from '../chunk-MVJ4TSSA.js';
3
+ import { NotificationList } from '../chunk-2JTCPVZX.js';
4
+ export { ActivityCard, ActivityFilters as ActivityFiltersBar, ActivityTable, BusinessImpactCard, CostBreakdownCard, CostByModelTable, CostMetricsCard, ErrorAnalysisCard, ErrorBreakdownTable, ExecutionBreakdownTable, ExecutionHealthCard, ExecutionLogsFilters as ExecutionLogsFilterBar, ExecutionLogsTable, NotificationItem, NotificationList, monitoringManifest } from '../chunk-2JTCPVZX.js';
5
+ export { CreateCredentialModal, CredentialList, CredentialSettings, MembershipFeaturePanel, MembershipStatusBadge, OAuthConnectModal, OrganizationMembershipsList, WebhookUrlDisplayModal, settingsManifest } from '../chunk-MXVA7U2I.js';
6
6
  import { FilterBar } from '../chunk-PDHTXPSF.js';
7
7
  export { FilterBar } from '../chunk-PDHTXPSF.js';
8
- import { ResourceExecuteDialog } from '../chunk-H762MTQ5.js';
9
- export { ActionModal, AgentDefinitionDisplay, AgentExecutionLogs, BaseExecutionLogs, BaseExecutionLogsHeader, BaseExecutionLogsStates, CheckpointGroup, CollapsibleJsonSection, CommandQueueSidebar, CommandQueueSidebarMiddle, CommandQueueSidebarTop, CommandQueueTaskRow, CommandViewEdge, CommandViewGraph, CommandViewNode, ConfigCard, ContentSections, ContextUsageBadge, ContractDisplay, ExecutionErrorSection, FormFieldRenderer, LogEntry, LogGroup, NewKnowledgeMapEdge, NewKnowledgeMapGraph, NewKnowledgeMapNode, OperationsSidebar, OperationsSidebarMiddle, OperationsSidebarTop, ResourceDefinitionSection, ResourceErrorState, ResourceFilter, ResourceHeader, ResourceNotFoundState, SessionMemory, ToolsListDisplay, WorkflowDefinitionDisplay, WorkflowExecutionLogs, getExecutionStatusConfig, getIcon, getLogLevelConfig, iconMap, operationsManifest, useNewKnowledgeMapLayout } from '../chunk-H762MTQ5.js';
8
+ import { ResourceExecuteDialog } from '../chunk-7IE3KXKV.js';
9
+ export { ActionModal, AgentDefinitionDisplay, AgentExecutionLogs, BaseExecutionLogs, BaseExecutionLogsHeader, BaseExecutionLogsStates, CheckpointGroup, CollapsibleJsonSection, CommandQueueSidebar, CommandQueueSidebarMiddle, CommandQueueSidebarTop, CommandQueueTaskRow, CommandViewEdge, CommandViewGraph, CommandViewNode, ConfigCard, ContentSections, ContextUsageBadge, ContractDisplay, ExecutionErrorSection, FormFieldRenderer, LogEntry, LogGroup, NewKnowledgeMapEdge, NewKnowledgeMapGraph, NewKnowledgeMapNode, OperationsSidebar, OperationsSidebarMiddle, OperationsSidebarTop, ResourceDefinitionSection, ResourceErrorState, ResourceFilter, ResourceHeader, ResourceNotFoundState, SessionMemory, ToolsListDisplay, WorkflowDefinitionDisplay, WorkflowExecutionLogs, getExecutionStatusConfig, getIcon, getLogLevelConfig, iconMap, operationsManifest, useNewKnowledgeMapLayout } from '../chunk-7IE3KXKV.js';
10
10
  import '../chunk-ROSMICXG.js';
11
11
  import { SubshellLoader, PageContainer, SubshellSidebarSection, SubshellNavItem, CollapsibleSidebarGroup } from '../chunk-OCP2MBTY.js';
12
- export { ResourceHealthPanel } from '../chunk-OKKGD3S6.js';
12
+ export { ResourceHealthPanel } from '../chunk-PFONCU6C.js';
13
13
  import { CustomModal } from '../chunk-GBMNCNHX.js';
14
14
  export { ConfirmationInputModal, ConfirmationModal, CustomModal } from '../chunk-GBMNCNHX.js';
15
- export { AgentExecutionTimeline, AgentExecutionVisualizer, AgentIterationEdge, AgentIterationNode, BaseEdge, BaseNode, EmptyVisualizer, ExecutionStats, ExecutionStatusBadge, GraphBackground, GraphContainer, GraphFitViewButton, GraphFitViewHandler, GraphLegend, TimelineAxis, TimelineBar, TimelineContainer, TimelineRow, UnifiedWorkflowEdge, UnifiedWorkflowGraph, UnifiedWorkflowNode, VisualizerContainer, WorkflowExecutionTimeline, dashboardManifest, getGraphBackgroundStyles, useGraphBackgroundStyles, useGraphTheme } from '../chunk-PQNEE57X.js';
15
+ export { AgentExecutionTimeline, AgentExecutionVisualizer, AgentIterationEdge, AgentIterationNode, BaseEdge, BaseNode, EmptyVisualizer, ExecutionStats, ExecutionStatusBadge, GraphBackground, GraphContainer, GraphFitViewButton, GraphFitViewHandler, GraphLegend, TimelineAxis, TimelineBar, TimelineContainer, TimelineRow, UnifiedWorkflowEdge, UnifiedWorkflowGraph, UnifiedWorkflowNode, VisualizerContainer, WorkflowExecutionTimeline, dashboardManifest, getGraphBackgroundStyles, useGraphBackgroundStyles, useGraphTheme } from '../chunk-BIZNOFO4.js';
16
16
  export { ResourceHealthChart, getHealthColor } from '../chunk-LGKLC5MG.js';
17
17
  import '../chunk-KFICYU6S.js';
18
18
  import { AppShellLoader } from '../chunk-YEX4MQSY.js';
19
19
  import '../chunk-35QO7M43.js';
20
- import { useUpdateApiKey, useDeleteApiKey, useCreateApiKey, useListApiKeys, useActivateDeployment, useDeactivateDeployment, useDeleteDeployment, useListDeployments, useProjects } from '../chunk-PRLXFMNP.js';
21
- import { usePaginationState, useDeploymentDocs, useResources, useCreateSchedule, useListSchedules, usePauseSchedule, useResumeSchedule, useCancelSchedule, useDeleteSchedule, useDealNotes, useCreateDealNote, useDeals, useSyncDealStage, dealKeys, useDealTasksDue, useCreateDealTask, useDeleteDeal, useTableSort, sortData, useTableSelection, useDealDetail, showApiErrorNotification, acquisitionListKeys, showSuccessNotification, useListsTelemetry, useLists, useCreateList, useList, useListProgress, useListExecutions, useResourceDefinition, useDeleteProject, useMarkAllAsRead, useNotifications, showErrorNotification } from '../chunk-TZOGB3X4.js';
22
- export { showApiErrorNotification, showErrorNotification, showInfoNotification, showSuccessNotification, showWarningNotification } from '../chunk-TZOGB3X4.js';
20
+ import { useUpdateApiKey, useDeleteApiKey, useCreateApiKey, useListApiKeys, useActivateDeployment, useDeactivateDeployment, useDeleteDeployment, useListDeployments, useProjects } from '../chunk-JT3FN6TE.js';
21
+ import { usePaginationState, useDeploymentDocs, useResources, useCreateSchedule, useListSchedules, usePauseSchedule, useResumeSchedule, useCancelSchedule, useDeleteSchedule, useDealNotes, useCreateDealNote, useDeals, useSyncDealStage, dealKeys, useDealTasksDue, useCreateDealTask, useDeleteDeal, useTableSort, sortData, useTableSelection, useDealDetail, showApiErrorNotification, acquisitionListKeys, showSuccessNotification, useListsTelemetry, useLists, useCreateList, useList, useListProgress, useListExecutions, useResourceDefinition, useCompanies, useDeleteCompanies, useContacts, useDeleteContacts, useDeleteProject, useMarkAllAsRead, useNotifications, showErrorNotification } from '../chunk-J5TBNCMD.js';
22
+ export { showApiErrorNotification, showErrorNotification, showInfoNotification, showSuccessNotification, showWarningNotification } from '../chunk-J5TBNCMD.js';
23
23
  import '../chunk-LXHZYSMQ.js';
24
24
  export { Graph_module_css_default as graphStyles } from '../chunk-F6RBK7NJ.js';
25
25
  export { CONTAINER_CONSTANTS, SHARED_VIZ_CONSTANTS } from '../chunk-XA34RETF.js';
@@ -48,7 +48,7 @@ import { useElevasisServices } from '../chunk-QEPXAWE2.js';
48
48
  import '../chunk-BRJ3QZ4E.js';
49
49
  import { useRouterContext } from '../chunk-Q7DJKLEN.js';
50
50
  import { Table, Group, Text, Button, Stack, Title, TextInput, Alert, Tooltip, ActionIcon, Paper, Code, CopyButton, SimpleGrid, Badge, Loader, Pagination, useMantineTheme, Box, ScrollArea, Select, Center, Card, SegmentedControl, Switch, Textarea, Divider, Menu, Timeline, ThemeIcon, Tabs, Anchor, Breadcrumbs as Breadcrumbs$1, Drawer, UnstyledButton, Modal, Checkbox, RingProgress, Collapse, Popover, Indicator } from '@mantine/core';
51
- import { IconAddressBook, IconBriefcase, IconTarget, IconChevronUp, IconChevronDown, IconSelector, IconTrash, IconPencil, IconAlertCircle, IconKey, IconCalendar, IconClock, IconAlertTriangle, IconExclamationMark, IconShieldLock, IconCheck, IconCopy, IconPlus, IconRocket, IconRefresh, IconPower, IconPlayerPlay, IconCircleCheck, IconTag, IconBook2, IconFileOff, IconList, IconCalendarRepeat, IconCalendarEvent, IconCalendarTime, IconRobot, IconGitBranch, IconSettings, IconExternalLink, IconDotsVertical, IconPlayerPause, IconPlayerStop, IconCalendarDue, IconCalendarStats, IconCalendarOff, IconListCheck, IconTrophy, IconClockExclamation, IconUser, IconLayoutGrid, IconColumns, IconFileInvoice, IconChecklist, IconHistory, IconSearch, IconTargetArrow, IconArrowLeft, IconFileText, IconX, IconBuilding, IconMailCheck, IconChartBar, IconBuildingFactory2, IconUsers, IconSparkles, IconClockHour4, IconTrendingUp, IconHeartbeat, IconFlag, IconInbox, IconLock, IconChevronRight, IconDownload, IconMessageCircle, IconBell, IconNotes, IconFolderOpen, IconFolder, IconCheckbox, IconMail, IconPhone, IconArrowRight, IconNote } from '@tabler/icons-react';
51
+ import { IconAddressBook, IconBriefcase, IconTarget, IconChevronUp, IconChevronDown, IconSelector, IconTrash, IconPencil, IconAlertCircle, IconKey, IconCalendar, IconClock, IconAlertTriangle, IconExclamationMark, IconShieldLock, IconCheck, IconCopy, IconPlus, IconRocket, IconRefresh, IconPower, IconPlayerPlay, IconCircleCheck, IconTag, IconBook2, IconFileOff, IconList, IconCalendarRepeat, IconCalendarEvent, IconCalendarTime, IconRobot, IconGitBranch, IconSettings, IconExternalLink, IconDotsVertical, IconPlayerPause, IconPlayerStop, IconCalendarDue, IconCalendarStats, IconCalendarOff, IconListCheck, IconTrophy, IconClockExclamation, IconUser, IconLayoutGrid, IconColumns, IconFileInvoice, IconChecklist, IconHistory, IconSearch, IconTargetArrow, IconArrowLeft, IconFileText, IconX, IconBuilding, IconMailCheck, IconChartBar, IconBuildingFactory2, IconUsers, IconQuestionMark, IconSparkles, IconClockHour4, IconTrendingUp, IconHeartbeat, IconFlag, IconInbox, IconLock, IconChevronRight, IconDownload, IconMessageCircle, IconBell, IconNotes, IconFolderOpen, IconFolder, IconCheckbox, IconMail, IconPhone, IconArrowRight, IconNote } from '@tabler/icons-react';
52
52
  import * as runtime from 'react/jsx-runtime';
53
53
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
54
54
  import { useDisclosure } from '@mantine/hooks';
@@ -4546,8 +4546,9 @@ function LeadGenRouteShell({
4546
4546
  ] }) })
4547
4547
  ] }) }) });
4548
4548
  }
4549
- function formatDate2(dateString) {
4550
- return new Date(dateString).toLocaleDateString("en-US", {
4549
+ function formatDate2(dateValue) {
4550
+ const date = typeof dateValue === "string" ? new Date(dateValue) : dateValue;
4551
+ return date.toLocaleDateString("en-US", {
4551
4552
  month: "short",
4552
4553
  day: "numeric",
4553
4554
  year: "numeric"
@@ -4568,6 +4569,135 @@ function getEnrichmentColor(status) {
4568
4569
  return "gray";
4569
4570
  }
4570
4571
  }
4572
+ function getEnrichmentStatus(enrichmentData) {
4573
+ if (!enrichmentData || typeof enrichmentData !== "object") return "pending";
4574
+ const website = enrichmentData.website;
4575
+ const linkedin = enrichmentData.linkedin;
4576
+ if (website === "complete" && linkedin === "complete") return "complete";
4577
+ if (website === "failed" || linkedin === "failed") return "failed";
4578
+ return "pending";
4579
+ }
4580
+ function formatName(parts, fallback) {
4581
+ const name = parts.filter(Boolean).join(" ").trim();
4582
+ return name || fallback;
4583
+ }
4584
+ function CompanyDetailModal({ company, onClose }) {
4585
+ return /* @__PURE__ */ jsx(CustomModal, { opened: !!company, onClose, size: "xl", children: company ? /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
4586
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-start", children: [
4587
+ /* @__PURE__ */ jsxs("div", { children: [
4588
+ /* @__PURE__ */ jsx(Title, { order: 3, children: company.name }),
4589
+ company.domain ? /* @__PURE__ */ jsxs(Anchor, { href: `https://${company.domain}`, target: "_blank", size: "sm", c: "dimmed", children: [
4590
+ company.domain,
4591
+ " ",
4592
+ /* @__PURE__ */ jsx(IconExternalLink, { size: 12, style: { verticalAlign: "middle" } })
4593
+ ] }) : null
4594
+ ] }),
4595
+ /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", onClick: onClose, children: /* @__PURE__ */ jsx(IconX, { size: 18 }) })
4596
+ ] }),
4597
+ /* @__PURE__ */ jsx(Divider, {}),
4598
+ /* @__PURE__ */ jsxs(Box, { children: [
4599
+ /* @__PURE__ */ jsx(Title, { order: 4, mb: "xs", children: "Firmographics" }),
4600
+ /* @__PURE__ */ jsxs(SimpleGrid, { cols: 3, children: [
4601
+ /* @__PURE__ */ jsxs("div", { children: [
4602
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Segment" }),
4603
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: company.segment || "-" })
4604
+ ] }),
4605
+ /* @__PURE__ */ jsxs("div", { children: [
4606
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Category" }),
4607
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: company.category || "-" })
4608
+ ] }),
4609
+ /* @__PURE__ */ jsxs("div", { children: [
4610
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Employees" }),
4611
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: company.numEmployees || "-" })
4612
+ ] }),
4613
+ /* @__PURE__ */ jsxs("div", { children: [
4614
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Founded" }),
4615
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: company.foundedYear || "-" })
4616
+ ] }),
4617
+ /* @__PURE__ */ jsxs("div", { children: [
4618
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Location" }),
4619
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: [company.locationCity, company.locationState].filter(Boolean).join(", ") || "-" })
4620
+ ] }),
4621
+ /* @__PURE__ */ jsxs("div", { children: [
4622
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Contacts" }),
4623
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: company.contactCount })
4624
+ ] })
4625
+ ] })
4626
+ ] }),
4627
+ company.enrichmentData ? /* @__PURE__ */ jsxs(Box, { children: [
4628
+ /* @__PURE__ */ jsx(Title, { order: 4, mb: "xs", children: "Enrichment Data" }),
4629
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", style: { whiteSpace: "pre-wrap" }, children: JSON.stringify(company.enrichmentData, null, 2) })
4630
+ ] }) : null,
4631
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
4632
+ company.linkedinUrl ? /* @__PURE__ */ jsxs(Anchor, { href: company.linkedinUrl, target: "_blank", size: "sm", children: [
4633
+ "LinkedIn ",
4634
+ /* @__PURE__ */ jsx(IconExternalLink, { size: 12 })
4635
+ ] }) : null,
4636
+ company.website ? /* @__PURE__ */ jsxs(Anchor, { href: company.website, target: "_blank", size: "sm", children: [
4637
+ "Website ",
4638
+ /* @__PURE__ */ jsx(IconExternalLink, { size: 12 })
4639
+ ] }) : null
4640
+ ] }),
4641
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
4642
+ "Created: ",
4643
+ formatDate2(company.createdAt),
4644
+ company.updatedAt && ` | Updated: ${formatDate2(company.updatedAt)}`
4645
+ ] })
4646
+ ] }) : null });
4647
+ }
4648
+ function ContactDetailModal({ contact, onClose }) {
4649
+ return /* @__PURE__ */ jsx(CustomModal, { opened: !!contact, onClose, size: "xl", children: contact ? /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
4650
+ /* @__PURE__ */ jsxs(Group, { justify: "space-between", align: "flex-start", children: [
4651
+ /* @__PURE__ */ jsxs("div", { children: [
4652
+ /* @__PURE__ */ jsx(Title, { order: 3, children: formatName([contact.firstName, contact.lastName], contact.email) }),
4653
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: contact.email }),
4654
+ contact.title ? /* @__PURE__ */ jsx(Text, { size: "sm", children: contact.title }) : null
4655
+ ] }),
4656
+ /* @__PURE__ */ jsx(ActionIcon, { variant: "subtle", onClick: onClose, children: /* @__PURE__ */ jsx(IconX, { size: 18 }) })
4657
+ ] }),
4658
+ /* @__PURE__ */ jsx(Divider, {}),
4659
+ /* @__PURE__ */ jsxs(Group, { gap: "xs", children: [
4660
+ /* @__PURE__ */ jsx(Badge, { color: getStatusColor3(contact.status), children: contact.status }),
4661
+ contact.openingLine ? /* @__PURE__ */ jsx(Badge, { color: "green", children: "Personalized" }) : null
4662
+ ] }),
4663
+ contact.company ? /* @__PURE__ */ jsxs(Box, { children: [
4664
+ /* @__PURE__ */ jsx(Title, { order: 4, mb: "xs", children: "Company" }),
4665
+ /* @__PURE__ */ jsxs(Card, { withBorder: true, children: [
4666
+ /* @__PURE__ */ jsx(Text, { fw: 500, children: contact.company.name }),
4667
+ contact.company.domain ? /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: contact.company.domain }) : null
4668
+ ] })
4669
+ ] }) : null,
4670
+ /* @__PURE__ */ jsxs(Box, { children: [
4671
+ /* @__PURE__ */ jsx(Title, { order: 4, mb: "xs", children: "Contact Information" }),
4672
+ /* @__PURE__ */ jsxs(SimpleGrid, { cols: 2, children: [
4673
+ /* @__PURE__ */ jsxs("div", { children: [
4674
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "Headline" }),
4675
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: contact.headline || "-" })
4676
+ ] }),
4677
+ /* @__PURE__ */ jsxs("div", { children: [
4678
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: "LinkedIn" }),
4679
+ contact.linkedinUrl ? /* @__PURE__ */ jsxs(Anchor, { href: contact.linkedinUrl, target: "_blank", size: "sm", children: [
4680
+ "View Profile ",
4681
+ /* @__PURE__ */ jsx(IconExternalLink, { size: 12 })
4682
+ ] }) : /* @__PURE__ */ jsx(Text, { size: "sm", children: "-" })
4683
+ ] })
4684
+ ] })
4685
+ ] }),
4686
+ contact.filterReason ? /* @__PURE__ */ jsxs(Box, { children: [
4687
+ /* @__PURE__ */ jsx(Title, { order: 4, mb: "xs", children: "Qualification" }),
4688
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "red", children: contact.filterReason })
4689
+ ] }) : null,
4690
+ contact.openingLine ? /* @__PURE__ */ jsxs(Box, { children: [
4691
+ /* @__PURE__ */ jsx(Title, { order: 4, mb: "xs", children: "Personalization" }),
4692
+ /* @__PURE__ */ jsx(Text, { size: "sm", children: contact.openingLine })
4693
+ ] }) : null,
4694
+ /* @__PURE__ */ jsxs(Text, { size: "xs", c: "dimmed", children: [
4695
+ "Created: ",
4696
+ formatDate2(contact.createdAt),
4697
+ contact.updatedAt && ` | Updated: ${formatDate2(contact.updatedAt)}`
4698
+ ] })
4699
+ ] }) : null });
4700
+ }
4571
4701
  var LIST_TEMPLATE_OPTIONS = [
4572
4702
  {
4573
4703
  value: "blank",
@@ -4772,16 +4902,39 @@ function useDeleteLists() {
4772
4902
  });
4773
4903
  }
4774
4904
  var EM_DASH = "\u2014";
4905
+ function computeCompletionPercentage(populated, personalized) {
4906
+ if (populated === 0) return EM_DASH;
4907
+ return `${Math.round(personalized / populated * 100)}%`;
4908
+ }
4775
4909
  function LeadGenOverviewPage() {
4776
4910
  const { data, isLoading, isError, error } = useListsTelemetry();
4777
4911
  const totalCompanies = data?.reduce((sum, list) => sum + list.totalCompanies, 0) ?? 0;
4778
4912
  const totalContacts = data?.reduce((sum, list) => sum + list.totalContacts, 0) ?? 0;
4913
+ const stageTotals = data?.reduce(
4914
+ (acc, list) => ({
4915
+ populated: acc.populated + list.stageCounts.populated,
4916
+ extracted: acc.extracted + list.stageCounts.extracted,
4917
+ qualified: acc.qualified + list.stageCounts.qualified,
4918
+ discovered: acc.discovered + list.stageCounts.discovered,
4919
+ verified: acc.verified + list.stageCounts.verified,
4920
+ personalized: acc.personalized + list.stageCounts.personalized,
4921
+ uploaded: acc.uploaded + list.stageCounts.uploaded
4922
+ }),
4923
+ { populated: 0, extracted: 0, qualified: 0, discovered: 0, verified: 0, personalized: 0, uploaded: 0 }
4924
+ ) ?? { populated: 0, extracted: 0, qualified: 0, discovered: 0, verified: 0, personalized: 0, uploaded: 0 };
4779
4925
  const completionLabel = (() => {
4780
4926
  if (!data?.length) return EM_DASH;
4781
- const populated = data.reduce((sum, list) => sum + list.stageCounts.populated, 0);
4782
- const personalized = data.reduce((sum, list) => sum + list.stageCounts.personalized, 0);
4783
- return populated === 0 ? EM_DASH : `${Math.round(personalized / populated * 100)}%`;
4927
+ return computeCompletionPercentage(stageTotals.populated, stageTotals.personalized);
4784
4928
  })();
4929
+ const stageTiles = [
4930
+ { label: "Populated", value: stageTotals.populated },
4931
+ { label: "Extracted", value: stageTotals.extracted },
4932
+ { label: "Qualified", value: stageTotals.qualified },
4933
+ { label: "Discovered", value: stageTotals.discovered },
4934
+ { label: "Verified", value: stageTotals.verified },
4935
+ { label: "Personalized", value: stageTotals.personalized },
4936
+ { label: "Uploaded", value: stageTotals.uploaded }
4937
+ ];
4785
4938
  return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
4786
4939
  /* @__PURE__ */ jsx(
4787
4940
  PageTitleCaption,
@@ -4803,7 +4956,40 @@ function LeadGenOverviewPage() {
4803
4956
  /* @__PURE__ */ jsx(Anchor, { component: Link$1, to: "/lead-gen/lists", size: "sm", children: "Lists" }),
4804
4957
  " ",
4805
4958
  "page."
4806
- ] })
4959
+ ] }),
4960
+ /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
4961
+ /* @__PURE__ */ jsx(Title, { order: 3, children: "Pipeline Roll-Up" }),
4962
+ /* @__PURE__ */ jsx(SimpleGrid, { cols: { base: 2, sm: 3, lg: 7 }, children: stageTiles.map((tile) => /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "sm", children: [
4963
+ /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", children: tile.label }),
4964
+ /* @__PURE__ */ jsx(Title, { order: 4, children: tile.value })
4965
+ ] }, tile.label)) })
4966
+ ] }) }),
4967
+ /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
4968
+ /* @__PURE__ */ jsx(Title, { order: 3, children: "List Snapshot" }),
4969
+ /* @__PURE__ */ jsxs(Table, { children: [
4970
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
4971
+ /* @__PURE__ */ jsx(Table.Th, { children: "List" }),
4972
+ /* @__PURE__ */ jsx(Table.Th, { children: "Companies" }),
4973
+ /* @__PURE__ */ jsx(Table.Th, { children: "Contacts" }),
4974
+ /* @__PURE__ */ jsx(Table.Th, { children: "Completion" }),
4975
+ /* @__PURE__ */ jsx(Table.Th, { children: "Status" })
4976
+ ] }) }),
4977
+ /* @__PURE__ */ jsx(Table.Tbody, { children: data.map((list) => {
4978
+ const completion = computeCompletionPercentage(
4979
+ list.stageCounts.populated,
4980
+ list.stageCounts.personalized
4981
+ );
4982
+ const isActive = (list.activeWorkflows?.length ?? 0) > 0;
4983
+ return /* @__PURE__ */ jsxs(Table.Tr, { children: [
4984
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", fw: 500, children: list.listId }) }),
4985
+ /* @__PURE__ */ jsx(Table.Td, { children: list.totalCompanies }),
4986
+ /* @__PURE__ */ jsx(Table.Td, { children: list.totalContacts }),
4987
+ /* @__PURE__ */ jsx(Table.Td, { children: completion }),
4988
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { size: "sm", variant: isActive ? "light" : "outline", color: isActive ? "green" : "gray", children: isActive ? "Active Work" : "Idle" }) })
4989
+ ] }, list.listId);
4990
+ }) })
4991
+ ] })
4992
+ ] }) })
4807
4993
  ] })
4808
4994
  ] }) }) });
4809
4995
  }
@@ -4862,12 +5048,12 @@ function LeadGenDeliverabilityPage() {
4862
5048
  { valid: 0, risky: 0, invalid: 0, unknown: 0, bounced: 0 }
4863
5049
  );
4864
5050
  const summaryTiles = [
4865
- { label: "Valid", value: totals.valid },
4866
- { label: "Risky", value: totals.risky },
4867
- { label: "Invalid", value: totals.invalid },
4868
- { label: "Unknown", value: totals.unknown },
4869
- { label: "Bounced", value: totals.bounced },
4870
- { label: "Bounce Rate", value: computeBounceRate(totals) }
5051
+ { label: "Valid", value: totals.valid, icon: IconMailCheck },
5052
+ { label: "Risky", value: totals.risky, icon: IconAlertCircle },
5053
+ { label: "Invalid", value: totals.invalid, icon: IconX },
5054
+ { label: "Unknown", value: totals.unknown, icon: IconQuestionMark },
5055
+ { label: "Bounced", value: totals.bounced, icon: IconAlertCircle },
5056
+ { label: "Bounce Rate", value: computeBounceRate(totals), icon: IconChecklist }
4871
5057
  ];
4872
5058
  return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsx(PageContainer, { children: /* @__PURE__ */ jsxs(Stack, { children: [
4873
5059
  /* @__PURE__ */ jsx(
@@ -4877,10 +5063,7 @@ function LeadGenDeliverabilityPage() {
4877
5063
  caption: "Email validity breakdown and bounce health across lists"
4878
5064
  }
4879
5065
  ),
4880
- /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "md", children: /* @__PURE__ */ jsx(SimpleGrid, { cols: 6, children: summaryTiles.map((tile) => /* @__PURE__ */ jsxs(Paper, { withBorder: true, p: "md", children: [
4881
- /* @__PURE__ */ jsx(Text, { size: "xs", c: "dimmed", mb: 4, children: tile.label }),
4882
- /* @__PURE__ */ jsx(Text, { fw: 600, size: "lg", children: tile.value })
4883
- ] }, tile.label)) }) }),
5066
+ /* @__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)) }),
4884
5067
  /* @__PURE__ */ jsx(Paper, { withBorder: true, children: /* @__PURE__ */ jsxs(Table, { children: [
4885
5068
  /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
4886
5069
  /* @__PURE__ */ jsx(Table.Th, { children: "List ID" }),
@@ -5256,6 +5439,7 @@ function LeadGenListDetailPage({ listId }) {
5256
5439
  const list = listQuery.data;
5257
5440
  const progress = progressQuery.data;
5258
5441
  const executions = executionsQuery.data ?? [];
5442
+ const qualification = list.config.qualification;
5259
5443
  const pipelineSteps = list.config.pipeline?.steps?.slice().sort((a, b) => a.order - b.order) ?? [];
5260
5444
  const stageTiles = [
5261
5445
  { label: "Populated", value: progress.stageCounts.populated },
@@ -5336,22 +5520,24 @@ function LeadGenListDetailPage({ listId }) {
5336
5520
  /* @__PURE__ */ jsxs(SimpleGrid, { cols: { base: 1, lg: 2 }, children: [
5337
5521
  /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
5338
5522
  /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "Qualification" }),
5339
- /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
5340
- "Target: ",
5341
- list.config.qualification.targetDescription
5342
- ] }),
5343
- /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
5344
- "Minimum reviews: ",
5345
- list.config.qualification.minReviewCount
5346
- ] }),
5347
- /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
5348
- "Minimum rating: ",
5349
- list.config.qualification.minRating
5350
- ] }),
5351
- /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
5352
- "Exclude franchises: ",
5353
- list.config.qualification.excludeFranchises ? "Yes" : "No"
5354
- ] })
5523
+ qualification ? /* @__PURE__ */ jsxs(Fragment, { children: [
5524
+ /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
5525
+ "Target: ",
5526
+ qualification.targetDescription
5527
+ ] }),
5528
+ /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
5529
+ "Minimum reviews: ",
5530
+ qualification.minReviewCount
5531
+ ] }),
5532
+ /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
5533
+ "Minimum rating: ",
5534
+ qualification.minRating
5535
+ ] }),
5536
+ /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
5537
+ "Exclude franchises: ",
5538
+ qualification.excludeFranchises ? "Yes" : "No"
5539
+ ] })
5540
+ ] }) : /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "Qualification settings are not configured for this list." })
5355
5541
  ] }) }),
5356
5542
  /* @__PURE__ */ jsx(Paper, { withBorder: true, p: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: "xs", children: [
5357
5543
  /* @__PURE__ */ jsx(Text, { size: "sm", fw: 600, children: "Enrichment + Personalization" }),
@@ -5458,31 +5644,386 @@ function LeadGenListDetailPage({ listId }) {
5458
5644
  )
5459
5645
  ] }) });
5460
5646
  }
5647
+ var PAGE_SIZE_DEFAULT3 = 20;
5461
5648
  function LeadGenCompaniesPage() {
5462
- return /* @__PURE__ */ jsx(
5463
- LeadGenRouteShell,
5464
- {
5465
- title: "Companies",
5466
- caption: "Shared lead-gen navigation shell",
5467
- body: /* @__PURE__ */ jsxs(Fragment, { children: [
5468
- /* @__PURE__ */ jsx(Text, { fw: 500, children: "Company records and enrichment workflows stay app-owned here." }),
5469
- /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "The shared Lead Gen package keeps this route reachable so the navigation stays aligned across the template and derived workspaces without pretending to own the data-heavy company table." })
5470
- ] })
5471
- }
5649
+ const [companySearch, setCompanySearch] = useState("");
5650
+ const [segmentFilter, setSegmentFilter] = useState(null);
5651
+ const [categoryFilter, setCategoryFilter] = useState(null);
5652
+ const [statusFilter, setStatusFilter] = useState(null);
5653
+ const [selectedCompany, setSelectedCompany] = useState(null);
5654
+ const [showBatchDelete, setShowBatchDelete] = useState(false);
5655
+ const { data: companies, isLoading: companiesLoading } = useCompanies({
5656
+ search: companySearch || void 0,
5657
+ segment: segmentFilter || void 0,
5658
+ category: categoryFilter || void 0,
5659
+ status: statusFilter === "active" || statusFilter === "invalid" ? statusFilter : void 0
5660
+ });
5661
+ const deleteCompaniesMutation = useDeleteCompanies();
5662
+ const { sort, toggleSort } = useTableSort("company", "asc");
5663
+ const sortAccessors2 = useMemo(
5664
+ () => ({
5665
+ company: (company) => company.name,
5666
+ domain: (company) => company.domain || "",
5667
+ segment: (company) => company.segment || "",
5668
+ category: (company) => company.category || "",
5669
+ employees: (company) => company.numEmployees ?? 0,
5670
+ enrichment: (company) => getEnrichmentStatus(company.enrichmentData),
5671
+ contacts: (company) => company.contactCount
5672
+ }),
5673
+ []
5674
+ );
5675
+ const sortedCompanies = useMemo(
5676
+ () => sortData(companies ?? [], sort, sortAccessors2),
5677
+ [companies, sort, sortAccessors2]
5472
5678
  );
5679
+ const pagination = usePaginationState(PAGE_SIZE_DEFAULT3, [companySearch, segmentFilter, categoryFilter, statusFilter], sortedCompanies.length);
5680
+ const paginatedCompanies = useMemo(
5681
+ () => sortedCompanies.slice(pagination.offset, pagination.offset + PAGE_SIZE_DEFAULT3),
5682
+ [sortedCompanies, pagination.offset]
5683
+ );
5684
+ const selection = useTableSelection(paginatedCompanies, sortedCompanies);
5685
+ function handleBatchDelete() {
5686
+ deleteCompaniesMutation.mutate([...selection.selectedIds], {
5687
+ onSuccess: () => {
5688
+ selection.clear();
5689
+ setShowBatchDelete(false);
5690
+ }
5691
+ });
5692
+ }
5693
+ return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsxs(PageContainer, { children: [
5694
+ /* @__PURE__ */ jsx(Stack, { children: /* @__PURE__ */ jsx(PageTitleCaption, { title: "Companies", caption: "Company records and enrichment tracking" }) }),
5695
+ /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
5696
+ /* @__PURE__ */ jsxs(
5697
+ FilterBar,
5698
+ {
5699
+ actions: /* @__PURE__ */ jsx(
5700
+ TableSelectionToolbar,
5701
+ {
5702
+ selectedCount: selection.selectedCount,
5703
+ onDelete: () => setShowBatchDelete(true),
5704
+ isDeleting: deleteCompaniesMutation.isPending
5705
+ }
5706
+ ),
5707
+ children: [
5708
+ /* @__PURE__ */ jsx(
5709
+ Select,
5710
+ {
5711
+ placeholder: "All Segments",
5712
+ data: ["Technology", "Marketing", "Finance", "Healthcare"],
5713
+ value: segmentFilter,
5714
+ onChange: setSegmentFilter,
5715
+ style: { minWidth: 180 },
5716
+ size: "sm",
5717
+ clearable: true
5718
+ }
5719
+ ),
5720
+ /* @__PURE__ */ jsx(
5721
+ Select,
5722
+ {
5723
+ placeholder: "All Categories",
5724
+ data: ["SaaS", "Service Agency", "Software"],
5725
+ value: categoryFilter,
5726
+ onChange: setCategoryFilter,
5727
+ style: { minWidth: 160 },
5728
+ size: "sm",
5729
+ clearable: true
5730
+ }
5731
+ ),
5732
+ /* @__PURE__ */ jsx(
5733
+ Select,
5734
+ {
5735
+ placeholder: "All Statuses",
5736
+ data: [
5737
+ { value: "active", label: "Active" },
5738
+ { value: "invalid", label: "Invalid" }
5739
+ ],
5740
+ value: statusFilter,
5741
+ onChange: setStatusFilter,
5742
+ style: { minWidth: 160 },
5743
+ size: "sm",
5744
+ clearable: true
5745
+ }
5746
+ ),
5747
+ /* @__PURE__ */ jsx(
5748
+ TextInput,
5749
+ {
5750
+ placeholder: "Search by name or domain...",
5751
+ leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
5752
+ style: { minWidth: 250 },
5753
+ size: "sm",
5754
+ value: companySearch,
5755
+ onChange: (e) => setCompanySearch(e.target.value)
5756
+ }
5757
+ )
5758
+ ]
5759
+ }
5760
+ ),
5761
+ 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: [
5762
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
5763
+ /* @__PURE__ */ jsx(Table.Th, { w: 40, children: /* @__PURE__ */ jsx(
5764
+ Checkbox,
5765
+ {
5766
+ checked: selection.isPageAllSelected,
5767
+ indeterminate: selection.isPagePartiallySelected,
5768
+ onChange: selection.togglePage
5769
+ }
5770
+ ) }),
5771
+ /* @__PURE__ */ jsx(SortableHeader, { column: "company", sort, onToggle: toggleSort, children: "Company" }),
5772
+ /* @__PURE__ */ jsx(SortableHeader, { column: "domain", sort, onToggle: toggleSort, children: "Domain" }),
5773
+ /* @__PURE__ */ jsx(SortableHeader, { column: "segment", sort, onToggle: toggleSort, children: "Segment" }),
5774
+ /* @__PURE__ */ jsx(SortableHeader, { column: "category", sort, onToggle: toggleSort, children: "Category" }),
5775
+ /* @__PURE__ */ jsx(SortableHeader, { column: "employees", sort, onToggle: toggleSort, children: "Employees" }),
5776
+ /* @__PURE__ */ jsx(SortableHeader, { column: "enrichment", sort, onToggle: toggleSort, children: "Enrichment" }),
5777
+ /* @__PURE__ */ jsx(SortableHeader, { column: "contacts", sort, onToggle: toggleSort, children: "Contacts" })
5778
+ ] }) }),
5779
+ /* @__PURE__ */ jsx(Table.Tbody, { children: paginatedCompanies.map((company) => {
5780
+ const enrichStatus = getEnrichmentStatus(company.enrichmentData);
5781
+ return /* @__PURE__ */ jsxs(
5782
+ Table.Tr,
5783
+ {
5784
+ style: { cursor: "pointer" },
5785
+ onClick: () => setSelectedCompany(company),
5786
+ children: [
5787
+ /* @__PURE__ */ jsx(
5788
+ Table.Td,
5789
+ {
5790
+ onClick: (e) => {
5791
+ e.stopPropagation();
5792
+ selection.toggle(company.id);
5793
+ },
5794
+ children: /* @__PURE__ */ jsx(
5795
+ Checkbox,
5796
+ {
5797
+ checked: selection.isSelected(company.id),
5798
+ onChange: () => selection.toggle(company.id),
5799
+ onClick: (e) => e.stopPropagation()
5800
+ }
5801
+ )
5802
+ }
5803
+ ),
5804
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: company.name }) }),
5805
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: company.domain || "-" }) }),
5806
+ /* @__PURE__ */ jsx(Table.Td, { children: company.segment || "-" }),
5807
+ /* @__PURE__ */ jsx(Table.Td, { children: company.category || "-" }),
5808
+ /* @__PURE__ */ jsx(Table.Td, { children: company.numEmployees || "-" }),
5809
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { variant: "light", color: getEnrichmentColor(enrichStatus), size: "sm", children: enrichStatus }) }),
5810
+ /* @__PURE__ */ jsx(Table.Td, { children: company.contactCount })
5811
+ ]
5812
+ },
5813
+ company.id
5814
+ );
5815
+ }) })
5816
+ ] }),
5817
+ sortedCompanies.length > PAGE_SIZE_DEFAULT3 ? /* @__PURE__ */ jsx(Group, { justify: "center", children: /* @__PURE__ */ jsx(
5818
+ Pagination,
5819
+ {
5820
+ value: pagination.page,
5821
+ onChange: pagination.setPage,
5822
+ total: pagination.totalPages(sortedCompanies.length),
5823
+ size: "sm"
5824
+ }
5825
+ ) }) : null
5826
+ ] }) }),
5827
+ /* @__PURE__ */ jsx(CompanyDetailModal, { company: selectedCompany, onClose: () => setSelectedCompany(null) }),
5828
+ /* @__PURE__ */ jsx(CustomModal, { opened: showBatchDelete, onClose: () => setShowBatchDelete(false), size: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
5829
+ /* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
5830
+ /* @__PURE__ */ jsx(IconAlertTriangle, { size: 20, color: "var(--mantine-color-red-6)" }),
5831
+ /* @__PURE__ */ jsxs(Title, { order: 5, children: [
5832
+ "Delete ",
5833
+ selection.selectedCount,
5834
+ " companies?"
5835
+ ] })
5836
+ ] }),
5837
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "This will permanently delete the selected companies and cannot be undone." }),
5838
+ /* @__PURE__ */ jsxs(Group, { justify: "flex-end", gap: "sm", children: [
5839
+ /* @__PURE__ */ jsx(Button, { variant: "default", size: "sm", onClick: () => setShowBatchDelete(false), children: "Cancel" }),
5840
+ /* @__PURE__ */ jsx(Button, { color: "red", size: "sm", loading: deleteCompaniesMutation.isPending, onClick: handleBatchDelete, children: "Delete" })
5841
+ ] })
5842
+ ] }) })
5843
+ ] }) });
5473
5844
  }
5845
+ var PAGE_SIZE_DEFAULT4 = 20;
5474
5846
  function LeadGenContactsPage() {
5475
- return /* @__PURE__ */ jsx(
5476
- LeadGenRouteShell,
5477
- {
5478
- title: "Contacts",
5479
- caption: "Shared lead-gen navigation shell",
5480
- body: /* @__PURE__ */ jsxs(Fragment, { children: [
5481
- /* @__PURE__ */ jsx(Text, { fw: 500, children: "Contact management stays app-owned here." }),
5482
- /* @__PURE__ */ jsx(Text, { c: "dimmed", children: "The shared package preserves the route and sibling links so every workspace keeps the same lead-gen surface, even when the detailed contact experience remains local." })
5483
- ] })
5484
- }
5847
+ const [contactSearch, setContactSearch] = useState("");
5848
+ const [statusFilter, setStatusFilter] = useState(null);
5849
+ const [listFilter, setListFilter] = useState(null);
5850
+ const [selectedContact, setSelectedContact] = useState(null);
5851
+ const [showBatchDelete, setShowBatchDelete] = useState(false);
5852
+ const { data: lists } = useLists();
5853
+ const { data: contacts, isLoading: contactsLoading } = useContacts({
5854
+ search: contactSearch || void 0,
5855
+ contactStatus: statusFilter === "active" || statusFilter === "invalid" ? statusFilter : void 0,
5856
+ listId: listFilter || void 0
5857
+ });
5858
+ const deleteContactsMutation = useDeleteContacts();
5859
+ const { sort, toggleSort } = useTableSort("name", "asc");
5860
+ const sortAccessors2 = useMemo(
5861
+ () => ({
5862
+ name: (contact) => [contact.firstName, contact.lastName].filter(Boolean).join(" ") || contact.email,
5863
+ email: (contact) => contact.email,
5864
+ company: (contact) => contact.company?.name || "",
5865
+ title: (contact) => contact.title || "",
5866
+ status: (contact) => contact.status || "",
5867
+ personalized: (contact) => contact.openingLine ? "yes" : "no"
5868
+ }),
5869
+ []
5485
5870
  );
5871
+ const sortedContacts = useMemo(
5872
+ () => sortData(contacts ?? [], sort, sortAccessors2),
5873
+ [contacts, sort, sortAccessors2]
5874
+ );
5875
+ const pagination = usePaginationState(PAGE_SIZE_DEFAULT4, [contactSearch, statusFilter, listFilter], sortedContacts.length);
5876
+ const paginatedContacts = useMemo(
5877
+ () => sortedContacts.slice(pagination.offset, pagination.offset + PAGE_SIZE_DEFAULT4),
5878
+ [sortedContacts, pagination.offset]
5879
+ );
5880
+ const selection = useTableSelection(paginatedContacts, sortedContacts);
5881
+ function handleBatchDelete() {
5882
+ deleteContactsMutation.mutate([...selection.selectedIds], {
5883
+ onSuccess: () => {
5884
+ selection.clear();
5885
+ setShowBatchDelete(false);
5886
+ }
5887
+ });
5888
+ }
5889
+ return /* @__PURE__ */ jsx(SubshellContentContainer, { children: /* @__PURE__ */ jsxs(PageContainer, { children: [
5890
+ /* @__PURE__ */ jsx(Stack, { children: /* @__PURE__ */ jsx(PageTitleCaption, { title: "Contacts", caption: "Contact records and outreach tracking" }) }),
5891
+ /* @__PURE__ */ jsx(Paper, { children: /* @__PURE__ */ jsxs(Stack, { children: [
5892
+ /* @__PURE__ */ jsxs(
5893
+ FilterBar,
5894
+ {
5895
+ actions: /* @__PURE__ */ jsx(
5896
+ TableSelectionToolbar,
5897
+ {
5898
+ selectedCount: selection.selectedCount,
5899
+ onDelete: () => setShowBatchDelete(true),
5900
+ isDeleting: deleteContactsMutation.isPending
5901
+ }
5902
+ ),
5903
+ children: [
5904
+ /* @__PURE__ */ jsx(
5905
+ Select,
5906
+ {
5907
+ placeholder: "All Statuses",
5908
+ data: [
5909
+ { value: "active", label: "Active" },
5910
+ { value: "invalid", label: "Invalid" }
5911
+ ],
5912
+ value: statusFilter,
5913
+ onChange: setStatusFilter,
5914
+ style: { minWidth: 160 },
5915
+ size: "sm",
5916
+ clearable: true
5917
+ }
5918
+ ),
5919
+ /* @__PURE__ */ jsx(
5920
+ Select,
5921
+ {
5922
+ placeholder: "All Lists",
5923
+ data: (lists ?? []).map((list) => ({ value: list.id, label: list.name })),
5924
+ value: listFilter,
5925
+ onChange: setListFilter,
5926
+ style: { minWidth: 200 },
5927
+ size: "sm",
5928
+ clearable: true
5929
+ }
5930
+ ),
5931
+ /* @__PURE__ */ jsx(
5932
+ TextInput,
5933
+ {
5934
+ placeholder: "Search by name or email...",
5935
+ leftSection: /* @__PURE__ */ jsx(IconSearch, { size: 16 }),
5936
+ style: { minWidth: 250 },
5937
+ size: "sm",
5938
+ value: contactSearch,
5939
+ onChange: (e) => setContactSearch(e.target.value)
5940
+ }
5941
+ )
5942
+ ]
5943
+ }
5944
+ ),
5945
+ 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: [
5946
+ /* @__PURE__ */ jsx(Table.Thead, { children: /* @__PURE__ */ jsxs(Table.Tr, { children: [
5947
+ /* @__PURE__ */ jsx(Table.Th, { w: 40, children: /* @__PURE__ */ jsx(
5948
+ Checkbox,
5949
+ {
5950
+ checked: selection.isPageAllSelected,
5951
+ indeterminate: selection.isPagePartiallySelected,
5952
+ onChange: selection.togglePage
5953
+ }
5954
+ ) }),
5955
+ /* @__PURE__ */ jsx(SortableHeader, { column: "name", sort, onToggle: toggleSort, children: "Name" }),
5956
+ /* @__PURE__ */ jsx(SortableHeader, { column: "email", sort, onToggle: toggleSort, children: "Email" }),
5957
+ /* @__PURE__ */ jsx(SortableHeader, { column: "company", sort, onToggle: toggleSort, children: "Company" }),
5958
+ /* @__PURE__ */ jsx(SortableHeader, { column: "title", sort, onToggle: toggleSort, children: "Title" }),
5959
+ /* @__PURE__ */ jsx(SortableHeader, { column: "status", sort, onToggle: toggleSort, children: "Status" }),
5960
+ /* @__PURE__ */ jsx(SortableHeader, { column: "personalized", sort, onToggle: toggleSort, children: "Personalized" })
5961
+ ] }) }),
5962
+ /* @__PURE__ */ jsx(Table.Tbody, { children: paginatedContacts.map((contact) => {
5963
+ const fullName = [contact.firstName, contact.lastName].filter(Boolean).join(" ") || contact.email;
5964
+ const hasPersonalization = !!contact.openingLine;
5965
+ return /* @__PURE__ */ jsxs(
5966
+ Table.Tr,
5967
+ {
5968
+ style: { cursor: "pointer" },
5969
+ onClick: () => setSelectedContact(contact),
5970
+ children: [
5971
+ /* @__PURE__ */ jsx(
5972
+ Table.Td,
5973
+ {
5974
+ onClick: (e) => {
5975
+ e.stopPropagation();
5976
+ selection.toggle(contact.id);
5977
+ },
5978
+ children: /* @__PURE__ */ jsx(
5979
+ Checkbox,
5980
+ {
5981
+ checked: selection.isSelected(contact.id),
5982
+ onChange: () => selection.toggle(contact.id),
5983
+ onClick: (e) => e.stopPropagation()
5984
+ }
5985
+ )
5986
+ }
5987
+ ),
5988
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: fullName }) }),
5989
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: contact.email }) }),
5990
+ /* @__PURE__ */ jsx(Table.Td, { children: contact.company?.name || "-" }),
5991
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: contact.title || "-" }) }),
5992
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { variant: "light", color: getStatusColor3(contact.status), size: "sm", children: contact.status || "unknown" }) }),
5993
+ /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { variant: "light", color: hasPersonalization ? "green" : "gray", size: "sm", children: hasPersonalization ? "Yes" : "No" }) })
5994
+ ]
5995
+ },
5996
+ contact.id
5997
+ );
5998
+ }) })
5999
+ ] }),
6000
+ sortedContacts.length > PAGE_SIZE_DEFAULT4 ? /* @__PURE__ */ jsx(Group, { justify: "center", children: /* @__PURE__ */ jsx(
6001
+ Pagination,
6002
+ {
6003
+ value: pagination.page,
6004
+ onChange: pagination.setPage,
6005
+ total: pagination.totalPages(sortedContacts.length),
6006
+ size: "sm"
6007
+ }
6008
+ ) }) : null
6009
+ ] }) }),
6010
+ /* @__PURE__ */ jsx(ContactDetailModal, { contact: selectedContact, onClose: () => setSelectedContact(null) }),
6011
+ /* @__PURE__ */ jsx(CustomModal, { opened: showBatchDelete, onClose: () => setShowBatchDelete(false), size: "sm", children: /* @__PURE__ */ jsxs(Stack, { gap: "md", children: [
6012
+ /* @__PURE__ */ jsxs(Group, { gap: "sm", children: [
6013
+ /* @__PURE__ */ jsx(IconAlertTriangle, { size: 20, color: "var(--mantine-color-red-6)" }),
6014
+ /* @__PURE__ */ jsxs(Title, { order: 5, children: [
6015
+ "Delete ",
6016
+ selection.selectedCount,
6017
+ " contacts?"
6018
+ ] })
6019
+ ] }),
6020
+ /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: "This will permanently delete the selected contacts and cannot be undone." }),
6021
+ /* @__PURE__ */ jsxs(Group, { justify: "flex-end", gap: "sm", children: [
6022
+ /* @__PURE__ */ jsx(Button, { variant: "default", size: "sm", onClick: () => setShowBatchDelete(false), children: "Cancel" }),
6023
+ /* @__PURE__ */ jsx(Button, { color: "red", size: "sm", loading: deleteContactsMutation.isPending, onClick: handleBatchDelete, children: "Delete" })
6024
+ ] })
6025
+ ] }) })
6026
+ ] }) });
5486
6027
  }
5487
6028
  var SEOSidebarTop = () => {
5488
6029
  return /* @__PURE__ */ jsx(SubshellSidebarSection, { icon: IconSearch, label: "SEO" });
@@ -5940,6 +6481,10 @@ function ProjectsListPage({ onProjectClick } = {}) {
5940
6481
  /* @__PURE__ */ jsx(SortableHeader, { column: "updated", sort, onToggle: toggleSort, children: "Updated" })
5941
6482
  ] }) }),
5942
6483
  /* @__PURE__ */ jsx(Table.Tbody, { children: paginatedProjects.map((project) => {
6484
+ const completedMilestones = project.completedMilestones ?? 0;
6485
+ const milestoneCount = project.milestoneCount ?? 0;
6486
+ const completedTasks = project.completedTasks ?? 0;
6487
+ const taskCount = project.taskCount ?? 0;
5943
6488
  const rowProps = onProjectClick ? {
5944
6489
  style: { cursor: "pointer" },
5945
6490
  onClick: () => onProjectClick(project.id)
@@ -5955,14 +6500,14 @@ function ProjectsListPage({ onProjectClick } = {}) {
5955
6500
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { fw: 500, children: project.name }) }),
5956
6501
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Badge, { variant: "light", color: projectStatusColors[project.status || ""] || "gray", size: "sm", children: formatStatusLabel(project.status || "unknown") }) }),
5957
6502
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
5958
- project.completedMilestones ?? 0,
6503
+ completedMilestones,
5959
6504
  "/",
5960
- project.milestoneCount
6505
+ milestoneCount
5961
6506
  ] }) }),
5962
6507
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsxs(Text, { size: "sm", children: [
5963
- project.completedTasks ?? 0,
6508
+ completedTasks,
5964
6509
  "/",
5965
- project.taskCount
6510
+ taskCount
5966
6511
  ] }) }),
5967
6512
  /* @__PURE__ */ jsx(Table.Td, { children: /* @__PURE__ */ jsx(Text, { size: "sm", c: "dimmed", children: formatTimeAgo(project.updated_at) }) })
5968
6513
  ] }, project.id);