@contractspec/example.crm-pipeline 3.7.7 → 3.7.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/.turbo/turbo-build.log +45 -42
  2. package/CHANGELOG.md +72 -0
  3. package/README.md +2 -1
  4. package/dist/browser/docs/crm-pipeline.docblock.js +1 -1
  5. package/dist/browser/docs/index.js +1 -1
  6. package/dist/browser/handlers/crm.handlers.js +13 -2
  7. package/dist/browser/handlers/index.js +13 -2
  8. package/dist/browser/index.js +392 -159
  9. package/dist/browser/ui/CrmDashboard.js +366 -144
  10. package/dist/browser/ui/hooks/index.js +19 -8
  11. package/dist/browser/ui/hooks/useDealList.js +19 -8
  12. package/dist/browser/ui/index.js +391 -158
  13. package/dist/browser/ui/renderers/index.js +32 -10
  14. package/dist/browser/ui/renderers/pipeline.markdown.js +13 -2
  15. package/dist/browser/ui/renderers/pipeline.renderer.js +19 -8
  16. package/dist/browser/ui/tables/DealListTab.js +390 -0
  17. package/dist/docs/crm-pipeline.docblock.js +1 -1
  18. package/dist/docs/index.js +1 -1
  19. package/dist/handlers/crm.handlers.d.ts +2 -0
  20. package/dist/handlers/crm.handlers.js +13 -2
  21. package/dist/handlers/index.js +13 -2
  22. package/dist/index.js +392 -159
  23. package/dist/node/docs/crm-pipeline.docblock.js +1 -1
  24. package/dist/node/docs/index.js +1 -1
  25. package/dist/node/handlers/crm.handlers.js +13 -2
  26. package/dist/node/handlers/index.js +13 -2
  27. package/dist/node/index.js +392 -159
  28. package/dist/node/ui/CrmDashboard.js +366 -144
  29. package/dist/node/ui/hooks/index.js +19 -8
  30. package/dist/node/ui/hooks/useDealList.js +19 -8
  31. package/dist/node/ui/index.js +391 -158
  32. package/dist/node/ui/renderers/index.js +32 -10
  33. package/dist/node/ui/renderers/pipeline.markdown.js +13 -2
  34. package/dist/node/ui/renderers/pipeline.renderer.js +19 -8
  35. package/dist/node/ui/tables/DealListTab.js +390 -0
  36. package/dist/ui/CrmDashboard.js +366 -144
  37. package/dist/ui/hooks/index.js +19 -8
  38. package/dist/ui/hooks/useDealList.d.ts +8 -2
  39. package/dist/ui/hooks/useDealList.js +19 -8
  40. package/dist/ui/index.js +391 -158
  41. package/dist/ui/renderers/index.js +32 -10
  42. package/dist/ui/renderers/pipeline.markdown.d.ts +1 -1
  43. package/dist/ui/renderers/pipeline.markdown.js +13 -2
  44. package/dist/ui/renderers/pipeline.renderer.d.ts +1 -1
  45. package/dist/ui/renderers/pipeline.renderer.js +19 -8
  46. package/dist/ui/tables/DealListTab.d.ts +20 -0
  47. package/dist/ui/tables/DealListTab.js +391 -0
  48. package/dist/ui/tables/DealListTab.smoke.test.d.ts +1 -0
  49. package/package.json +29 -13
  50. package/src/docs/crm-pipeline.docblock.ts +1 -1
  51. package/src/handlers/crm.handlers.ts +18 -1
  52. package/src/ui/CrmDashboard.tsx +2 -71
  53. package/src/ui/hooks/useDealList.ts +36 -8
  54. package/src/ui/renderers/pipeline.markdown.ts +1 -1
  55. package/src/ui/renderers/pipeline.renderer.tsx +1 -1
  56. package/src/ui/tables/DealListTab.smoke.test.tsx +149 -0
  57. package/src/ui/tables/DealListTab.tsx +276 -0
@@ -22,6 +22,13 @@ function rowToDeal(row) {
22
22
  updatedAt: new Date(row.updatedAt)
23
23
  };
24
24
  }
25
+ var DEAL_SORT_COLUMNS = {
26
+ name: "name",
27
+ value: "value",
28
+ status: "status",
29
+ expectedCloseDate: "expectedCloseDate",
30
+ updatedAt: "updatedAt"
31
+ };
25
32
  function createCrmHandlers(db) {
26
33
  async function listDeals(input) {
27
34
  const {
@@ -32,7 +39,9 @@ function createCrmHandlers(db) {
32
39
  ownerId,
33
40
  search,
34
41
  limit = 20,
35
- offset = 0
42
+ offset = 0,
43
+ sortBy = "value",
44
+ sortDirection = "desc"
36
45
  } = input;
37
46
  let whereClause = "WHERE projectId = ?";
38
47
  const params = [projectId];
@@ -60,7 +69,9 @@ function createCrmHandlers(db) {
60
69
  const total = countResult[0]?.count ?? 0;
61
70
  const valueResult = (await db.query(`SELECT COALESCE(SUM(value), 0) as total FROM crm_deal ${whereClause}`, params)).rows;
62
71
  const totalValue = valueResult[0]?.total ?? 0;
63
- const dealRows = (await db.query(`SELECT * FROM crm_deal ${whereClause} ORDER BY value DESC LIMIT ? OFFSET ?`, [...params, limit, offset])).rows;
72
+ const orderByColumn = DEAL_SORT_COLUMNS[sortBy] ?? DEAL_SORT_COLUMNS.value;
73
+ const orderByDirection = sortDirection === "asc" ? "ASC" : "DESC";
74
+ const dealRows = (await db.query(`SELECT * FROM crm_deal ${whereClause} ORDER BY ${orderByColumn} ${orderByDirection} LIMIT ? OFFSET ?`, [...params, limit, offset])).rows;
64
75
  return {
65
76
  deals: dealRows.map(rowToDeal),
66
77
  total,
@@ -610,8 +621,13 @@ function useDealList(options = {}) {
610
621
  const [stages, setStages] = useState2([]);
611
622
  const [loading, setLoading] = useState2(true);
612
623
  const [error, setError] = useState2(null);
613
- const [page, setPage] = useState2(1);
624
+ const [internalPage, setInternalPage] = useState2(0);
614
625
  const pipelineId = options.pipelineId ?? "pipeline-1";
626
+ const pageIndex = options.pageIndex ?? internalPage;
627
+ const pageSize = options.pageSize ?? options.limit ?? 50;
628
+ const [sort] = options.sorting ?? [];
629
+ const sortBy = sort?.id;
630
+ const sortDirection = sort ? sort.desc ? "desc" : "asc" : undefined;
615
631
  const fetchData = useCallback(async () => {
616
632
  setLoading(true);
617
633
  setError(null);
@@ -623,8 +639,10 @@ function useDealList(options = {}) {
623
639
  stageId: options.stageId,
624
640
  status: options.status === "all" ? undefined : options.status,
625
641
  search: options.search,
626
- limit: options.limit ?? 50,
627
- offset: (page - 1) * (options.limit ?? 50)
642
+ limit: pageSize,
643
+ offset: pageIndex * pageSize,
644
+ sortBy: sortBy === "name" || sortBy === "value" || sortBy === "status" || sortBy === "expectedCloseDate" || sortBy === "updatedAt" ? sortBy : undefined,
645
+ sortDirection
628
646
  }),
629
647
  crm2.getDealsByStage({ projectId, pipelineId }),
630
648
  crm2.getPipelineStages({ pipelineId })
@@ -644,8 +662,10 @@ function useDealList(options = {}) {
644
662
  options.stageId,
645
663
  options.status,
646
664
  options.search,
647
- options.limit,
648
- page
665
+ pageIndex,
666
+ pageSize,
667
+ sortBy,
668
+ sortDirection
649
669
  ]);
650
670
  useEffect(() => {
651
671
  fetchData();
@@ -673,10 +693,12 @@ function useDealList(options = {}) {
673
693
  loading,
674
694
  error,
675
695
  stats,
676
- page,
696
+ page: pageIndex + 1,
697
+ pageIndex,
698
+ pageSize,
677
699
  refetch: fetchData,
678
- nextPage: () => setPage((p) => p + 1),
679
- prevPage: () => page > 1 && setPage((p) => p - 1)
700
+ nextPage: options.pageIndex === undefined ? () => setInternalPage((page) => page + 1) : undefined,
701
+ prevPage: options.pageIndex === undefined ? () => pageIndex > 0 && setInternalPage((page) => page - 1) : undefined
680
702
  };
681
703
  }
682
704
 
@@ -1413,11 +1435,305 @@ function DealActionsModal({
1413
1435
  }, undefined, true, undefined, this);
1414
1436
  }
1415
1437
 
1416
- // src/ui/CrmDashboard.tsx
1438
+ // src/ui/tables/DealListTab.tsx
1417
1439
  import {
1418
1440
  Button as Button3,
1441
+ DataTable,
1442
+ LoaderBlock
1443
+ } from "@contractspec/lib.design-system";
1444
+ import { useContractTable } from "@contractspec/lib.presentation-runtime-react";
1445
+ import { Badge } from "@contractspec/lib.ui-kit-web/ui/badge";
1446
+ import { HStack, VStack } from "@contractspec/lib.ui-kit-web/ui/stack";
1447
+ import { Text } from "@contractspec/lib.ui-kit-web/ui/text";
1448
+ import * as React from "react";
1449
+ import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
1450
+ "use client";
1451
+ function formatCurrency4(value, currency = "USD") {
1452
+ return new Intl.NumberFormat("en-US", {
1453
+ style: "currency",
1454
+ currency,
1455
+ minimumFractionDigits: 0,
1456
+ maximumFractionDigits: 0
1457
+ }).format(value);
1458
+ }
1459
+ function statusVariant(status) {
1460
+ switch (status) {
1461
+ case "WON":
1462
+ return "default";
1463
+ case "LOST":
1464
+ return "destructive";
1465
+ case "STALE":
1466
+ return "outline";
1467
+ default:
1468
+ return "secondary";
1469
+ }
1470
+ }
1471
+ function DealListDataTable({
1472
+ deals,
1473
+ totalItems,
1474
+ pageIndex,
1475
+ pageSize,
1476
+ sorting,
1477
+ loading,
1478
+ onSortingChange,
1479
+ onPaginationChange,
1480
+ onDealClick
1481
+ }) {
1482
+ const controller = useContractTable({
1483
+ data: deals,
1484
+ columns: [
1485
+ {
1486
+ id: "deal",
1487
+ header: "Deal",
1488
+ label: "Deal",
1489
+ accessor: (deal) => deal.name,
1490
+ cell: ({ item }) => /* @__PURE__ */ jsxDEV5(VStack, {
1491
+ gap: "xs",
1492
+ children: [
1493
+ /* @__PURE__ */ jsxDEV5(Text, {
1494
+ className: "font-medium text-sm",
1495
+ children: item.name
1496
+ }, undefined, false, undefined, this),
1497
+ /* @__PURE__ */ jsxDEV5(Text, {
1498
+ className: "text-muted-foreground text-xs",
1499
+ children: item.companyId ?? "Unassigned company"
1500
+ }, undefined, false, undefined, this)
1501
+ ]
1502
+ }, undefined, true, undefined, this),
1503
+ size: 240,
1504
+ minSize: 180,
1505
+ canSort: true,
1506
+ canPin: true,
1507
+ canResize: true
1508
+ },
1509
+ {
1510
+ id: "value",
1511
+ header: "Value",
1512
+ label: "Value",
1513
+ accessorKey: "value",
1514
+ cell: ({ item }) => formatCurrency4(item.value, item.currency),
1515
+ align: "right",
1516
+ size: 140,
1517
+ canSort: true,
1518
+ canResize: true
1519
+ },
1520
+ {
1521
+ id: "status",
1522
+ header: "Status",
1523
+ label: "Status",
1524
+ accessorKey: "status",
1525
+ cell: ({ value }) => /* @__PURE__ */ jsxDEV5(Badge, {
1526
+ variant: statusVariant(value),
1527
+ children: String(value)
1528
+ }, undefined, false, undefined, this),
1529
+ size: 130,
1530
+ canSort: true,
1531
+ canHide: true,
1532
+ canPin: true,
1533
+ canResize: true
1534
+ },
1535
+ {
1536
+ id: "expectedCloseDate",
1537
+ header: "Expected Close",
1538
+ label: "Expected Close",
1539
+ accessor: (deal) => deal.expectedCloseDate?.toISOString() ?? "",
1540
+ cell: ({ item }) => item.expectedCloseDate?.toLocaleDateString() ?? "Not scheduled",
1541
+ size: 170,
1542
+ canSort: true,
1543
+ canHide: true,
1544
+ canResize: true
1545
+ },
1546
+ {
1547
+ id: "updatedAt",
1548
+ header: "Updated",
1549
+ label: "Updated",
1550
+ accessor: (deal) => deal.updatedAt.toISOString(),
1551
+ cell: ({ item }) => item.updatedAt.toLocaleDateString(),
1552
+ size: 140,
1553
+ canSort: true,
1554
+ canHide: true,
1555
+ canResize: true
1556
+ },
1557
+ {
1558
+ id: "actions",
1559
+ header: "Actions",
1560
+ label: "Actions",
1561
+ accessor: (deal) => deal.id,
1562
+ cell: ({ item }) => /* @__PURE__ */ jsxDEV5(Button3, {
1563
+ variant: "ghost",
1564
+ size: "sm",
1565
+ onPress: () => onDealClick?.(item.id),
1566
+ children: "Actions"
1567
+ }, undefined, false, undefined, this),
1568
+ size: 120,
1569
+ canSort: false,
1570
+ canHide: false,
1571
+ canPin: false,
1572
+ canResize: false
1573
+ }
1574
+ ],
1575
+ executionMode: "server",
1576
+ selectionMode: "multiple",
1577
+ totalItems,
1578
+ state: {
1579
+ sorting,
1580
+ pagination: {
1581
+ pageIndex,
1582
+ pageSize
1583
+ }
1584
+ },
1585
+ onSortingChange,
1586
+ onPaginationChange,
1587
+ initialState: {
1588
+ columnVisibility: { updatedAt: false },
1589
+ columnPinning: { left: ["deal", "status"], right: [] }
1590
+ },
1591
+ renderExpandedContent: (deal) => /* @__PURE__ */ jsxDEV5(VStack, {
1592
+ gap: "sm",
1593
+ className: "py-2",
1594
+ children: [
1595
+ /* @__PURE__ */ jsxDEV5(HStack, {
1596
+ justify: "between",
1597
+ children: [
1598
+ /* @__PURE__ */ jsxDEV5(Text, {
1599
+ className: "font-medium text-sm",
1600
+ children: "Owner"
1601
+ }, undefined, false, undefined, this),
1602
+ /* @__PURE__ */ jsxDEV5(Text, {
1603
+ className: "text-muted-foreground text-sm",
1604
+ children: deal.ownerId
1605
+ }, undefined, false, undefined, this)
1606
+ ]
1607
+ }, undefined, true, undefined, this),
1608
+ /* @__PURE__ */ jsxDEV5(HStack, {
1609
+ justify: "between",
1610
+ children: [
1611
+ /* @__PURE__ */ jsxDEV5(Text, {
1612
+ className: "font-medium text-sm",
1613
+ children: "Contact"
1614
+ }, undefined, false, undefined, this),
1615
+ /* @__PURE__ */ jsxDEV5(Text, {
1616
+ className: "text-muted-foreground text-sm",
1617
+ children: deal.contactId ?? "No linked contact"
1618
+ }, undefined, false, undefined, this)
1619
+ ]
1620
+ }, undefined, true, undefined, this),
1621
+ deal.wonSource ? /* @__PURE__ */ jsxDEV5(HStack, {
1622
+ justify: "between",
1623
+ children: [
1624
+ /* @__PURE__ */ jsxDEV5(Text, {
1625
+ className: "font-medium text-sm",
1626
+ children: "Won Source"
1627
+ }, undefined, false, undefined, this),
1628
+ /* @__PURE__ */ jsxDEV5(Text, {
1629
+ className: "text-muted-foreground text-sm",
1630
+ children: deal.wonSource
1631
+ }, undefined, false, undefined, this)
1632
+ ]
1633
+ }, undefined, true, undefined, this) : null,
1634
+ deal.lostReason ? /* @__PURE__ */ jsxDEV5(HStack, {
1635
+ justify: "between",
1636
+ children: [
1637
+ /* @__PURE__ */ jsxDEV5(Text, {
1638
+ className: "font-medium text-sm",
1639
+ children: "Lost Reason"
1640
+ }, undefined, false, undefined, this),
1641
+ /* @__PURE__ */ jsxDEV5(Text, {
1642
+ className: "text-muted-foreground text-sm",
1643
+ children: deal.lostReason
1644
+ }, undefined, false, undefined, this)
1645
+ ]
1646
+ }, undefined, true, undefined, this) : null,
1647
+ deal.notes ? /* @__PURE__ */ jsxDEV5(VStack, {
1648
+ gap: "xs",
1649
+ children: [
1650
+ /* @__PURE__ */ jsxDEV5(Text, {
1651
+ className: "font-medium text-sm",
1652
+ children: "Notes"
1653
+ }, undefined, false, undefined, this),
1654
+ /* @__PURE__ */ jsxDEV5(Text, {
1655
+ className: "text-muted-foreground text-sm",
1656
+ children: deal.notes
1657
+ }, undefined, false, undefined, this)
1658
+ ]
1659
+ }, undefined, true, undefined, this) : null
1660
+ ]
1661
+ }, undefined, true, undefined, this),
1662
+ getCanExpand: () => true
1663
+ });
1664
+ return /* @__PURE__ */ jsxDEV5(DataTable, {
1665
+ controller,
1666
+ title: "All Deals",
1667
+ description: "Server-mode table using the shared ContractSpec controller.",
1668
+ loading,
1669
+ toolbar: /* @__PURE__ */ jsxDEV5(HStack, {
1670
+ gap: "sm",
1671
+ className: "flex-wrap",
1672
+ children: [
1673
+ /* @__PURE__ */ jsxDEV5(Text, {
1674
+ className: "text-muted-foreground text-sm",
1675
+ children: [
1676
+ "Selected ",
1677
+ controller.selectedRowIds.length
1678
+ ]
1679
+ }, undefined, true, undefined, this),
1680
+ /* @__PURE__ */ jsxDEV5(Text, {
1681
+ className: "text-muted-foreground text-sm",
1682
+ children: [
1683
+ totalItems,
1684
+ " total deals"
1685
+ ]
1686
+ }, undefined, true, undefined, this)
1687
+ ]
1688
+ }, undefined, true, undefined, this),
1689
+ footer: `Page ${controller.pageIndex + 1} of ${controller.pageCount}`,
1690
+ emptyState: /* @__PURE__ */ jsxDEV5("div", {
1691
+ className: "rounded-md border border-dashed p-8 text-center text-muted-foreground text-sm",
1692
+ children: "No deals found"
1693
+ }, undefined, false, undefined, this)
1694
+ }, undefined, false, undefined, this);
1695
+ }
1696
+ function DealListTab({
1697
+ onDealClick
1698
+ }) {
1699
+ const [sorting, setSorting] = React.useState([
1700
+ { id: "value", desc: true }
1701
+ ]);
1702
+ const [pagination, setPagination] = React.useState({
1703
+ pageIndex: 0,
1704
+ pageSize: 3
1705
+ });
1706
+ const { data, loading } = useDealList({
1707
+ pageIndex: pagination.pageIndex,
1708
+ pageSize: pagination.pageSize,
1709
+ sorting
1710
+ });
1711
+ if (loading && !data) {
1712
+ return /* @__PURE__ */ jsxDEV5(LoaderBlock, {
1713
+ label: "Loading deals..."
1714
+ }, undefined, false, undefined, this);
1715
+ }
1716
+ return /* @__PURE__ */ jsxDEV5(DealListDataTable, {
1717
+ deals: data?.deals ?? [],
1718
+ totalItems: data?.total ?? 0,
1719
+ pageIndex: pagination.pageIndex,
1720
+ pageSize: pagination.pageSize,
1721
+ sorting,
1722
+ loading,
1723
+ onSortingChange: (nextSorting) => {
1724
+ setSorting(nextSorting);
1725
+ setPagination((current) => ({ ...current, pageIndex: 0 }));
1726
+ },
1727
+ onPaginationChange: setPagination,
1728
+ onDealClick
1729
+ }, undefined, false, undefined, this);
1730
+ }
1731
+
1732
+ // src/ui/CrmDashboard.tsx
1733
+ import {
1734
+ Button as Button4,
1419
1735
  ErrorState,
1420
- LoaderBlock,
1736
+ LoaderBlock as LoaderBlock2,
1421
1737
  StatCard,
1422
1738
  StatCardGroup
1423
1739
  } from "@contractspec/lib.design-system";
@@ -1427,10 +1743,10 @@ import {
1427
1743
  TabsList,
1428
1744
  TabsTrigger
1429
1745
  } from "@contractspec/lib.ui-kit-web/ui/tabs";
1430
- import { useCallback as useCallback3, useState as useState6 } from "react";
1431
- import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
1746
+ import { useCallback as useCallback3, useState as useState7 } from "react";
1747
+ import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
1432
1748
  "use client";
1433
- function formatCurrency4(value, currency = "USD") {
1749
+ function formatCurrency5(value, currency = "USD") {
1434
1750
  return new Intl.NumberFormat("en-US", {
1435
1751
  style: "currency",
1436
1752
  currency,
@@ -1439,9 +1755,9 @@ function formatCurrency4(value, currency = "USD") {
1439
1755
  }).format(value);
1440
1756
  }
1441
1757
  function CrmDashboard() {
1442
- const [isCreateModalOpen, setIsCreateModalOpen] = useState6(false);
1443
- const [selectedDeal, setSelectedDeal] = useState6(null);
1444
- const [isDealActionsOpen, setIsDealActionsOpen] = useState6(false);
1758
+ const [isCreateModalOpen, setIsCreateModalOpen] = useState7(false);
1759
+ const [selectedDeal, setSelectedDeal] = useState7(null);
1760
+ const [isDealActionsOpen, setIsDealActionsOpen] = useState7(false);
1445
1761
  const { data, dealsByStage, stages, loading, error, stats, refetch } = useDealList();
1446
1762
  const mutations = useDealMutations({
1447
1763
  onSuccess: () => {
@@ -1459,32 +1775,32 @@ function CrmDashboard() {
1459
1775
  await mutations.moveDeal({ dealId, stageId: toStageId });
1460
1776
  }, [mutations]);
1461
1777
  if (loading && !data) {
1462
- return /* @__PURE__ */ jsxDEV5(LoaderBlock, {
1778
+ return /* @__PURE__ */ jsxDEV6(LoaderBlock2, {
1463
1779
  label: "Loading CRM..."
1464
1780
  }, undefined, false, undefined, this);
1465
1781
  }
1466
1782
  if (error) {
1467
- return /* @__PURE__ */ jsxDEV5(ErrorState, {
1783
+ return /* @__PURE__ */ jsxDEV6(ErrorState, {
1468
1784
  title: "Failed to load CRM",
1469
1785
  description: error.message,
1470
1786
  onRetry: refetch,
1471
1787
  retryLabel: "Retry"
1472
1788
  }, undefined, false, undefined, this);
1473
1789
  }
1474
- return /* @__PURE__ */ jsxDEV5("div", {
1790
+ return /* @__PURE__ */ jsxDEV6("div", {
1475
1791
  className: "space-y-6",
1476
1792
  children: [
1477
- /* @__PURE__ */ jsxDEV5("div", {
1793
+ /* @__PURE__ */ jsxDEV6("div", {
1478
1794
  className: "flex items-center justify-between",
1479
1795
  children: [
1480
- /* @__PURE__ */ jsxDEV5("h2", {
1796
+ /* @__PURE__ */ jsxDEV6("h2", {
1481
1797
  className: "font-bold text-2xl",
1482
1798
  children: "CRM Pipeline"
1483
1799
  }, undefined, false, undefined, this),
1484
- /* @__PURE__ */ jsxDEV5(Button3, {
1800
+ /* @__PURE__ */ jsxDEV6(Button4, {
1485
1801
  onClick: () => setIsCreateModalOpen(true),
1486
1802
  children: [
1487
- /* @__PURE__ */ jsxDEV5("span", {
1803
+ /* @__PURE__ */ jsxDEV6("span", {
1488
1804
  className: "mr-2",
1489
1805
  children: "+"
1490
1806
  }, undefined, false, undefined, this),
@@ -1493,60 +1809,60 @@ function CrmDashboard() {
1493
1809
  }, undefined, true, undefined, this)
1494
1810
  ]
1495
1811
  }, undefined, true, undefined, this),
1496
- stats && /* @__PURE__ */ jsxDEV5(StatCardGroup, {
1812
+ stats && /* @__PURE__ */ jsxDEV6(StatCardGroup, {
1497
1813
  children: [
1498
- /* @__PURE__ */ jsxDEV5(StatCard, {
1814
+ /* @__PURE__ */ jsxDEV6(StatCard, {
1499
1815
  label: "Total Pipeline",
1500
- value: formatCurrency4(stats.totalValue),
1816
+ value: formatCurrency5(stats.totalValue),
1501
1817
  hint: `${stats.total} deals`
1502
1818
  }, undefined, false, undefined, this),
1503
- /* @__PURE__ */ jsxDEV5(StatCard, {
1819
+ /* @__PURE__ */ jsxDEV6(StatCard, {
1504
1820
  label: "Open Deals",
1505
- value: formatCurrency4(stats.openValue),
1821
+ value: formatCurrency5(stats.openValue),
1506
1822
  hint: `${stats.openCount} active`
1507
1823
  }, undefined, false, undefined, this),
1508
- /* @__PURE__ */ jsxDEV5(StatCard, {
1824
+ /* @__PURE__ */ jsxDEV6(StatCard, {
1509
1825
  label: "Won",
1510
- value: formatCurrency4(stats.wonValue),
1826
+ value: formatCurrency5(stats.wonValue),
1511
1827
  hint: `${stats.wonCount} closed`
1512
1828
  }, undefined, false, undefined, this),
1513
- /* @__PURE__ */ jsxDEV5(StatCard, {
1829
+ /* @__PURE__ */ jsxDEV6(StatCard, {
1514
1830
  label: "Lost",
1515
1831
  value: stats.lostCount,
1516
1832
  hint: "deals lost"
1517
1833
  }, undefined, false, undefined, this)
1518
1834
  ]
1519
1835
  }, undefined, true, undefined, this),
1520
- /* @__PURE__ */ jsxDEV5(Tabs, {
1836
+ /* @__PURE__ */ jsxDEV6(Tabs, {
1521
1837
  defaultValue: "pipeline",
1522
1838
  className: "w-full",
1523
1839
  children: [
1524
- /* @__PURE__ */ jsxDEV5(TabsList, {
1840
+ /* @__PURE__ */ jsxDEV6(TabsList, {
1525
1841
  children: [
1526
- /* @__PURE__ */ jsxDEV5(TabsTrigger, {
1842
+ /* @__PURE__ */ jsxDEV6(TabsTrigger, {
1527
1843
  value: "pipeline",
1528
1844
  children: [
1529
- /* @__PURE__ */ jsxDEV5("span", {
1845
+ /* @__PURE__ */ jsxDEV6("span", {
1530
1846
  className: "mr-2",
1531
1847
  children: "\uD83D\uDCCA"
1532
1848
  }, undefined, false, undefined, this),
1533
1849
  "Pipeline"
1534
1850
  ]
1535
1851
  }, undefined, true, undefined, this),
1536
- /* @__PURE__ */ jsxDEV5(TabsTrigger, {
1852
+ /* @__PURE__ */ jsxDEV6(TabsTrigger, {
1537
1853
  value: "list",
1538
1854
  children: [
1539
- /* @__PURE__ */ jsxDEV5("span", {
1855
+ /* @__PURE__ */ jsxDEV6("span", {
1540
1856
  className: "mr-2",
1541
1857
  children: "\uD83D\uDCCB"
1542
1858
  }, undefined, false, undefined, this),
1543
1859
  "All Deals"
1544
1860
  ]
1545
1861
  }, undefined, true, undefined, this),
1546
- /* @__PURE__ */ jsxDEV5(TabsTrigger, {
1862
+ /* @__PURE__ */ jsxDEV6(TabsTrigger, {
1547
1863
  value: "metrics",
1548
1864
  children: [
1549
- /* @__PURE__ */ jsxDEV5("span", {
1865
+ /* @__PURE__ */ jsxDEV6("span", {
1550
1866
  className: "mr-2",
1551
1867
  children: "\uD83D\uDCC8"
1552
1868
  }, undefined, false, undefined, this),
@@ -1555,34 +1871,33 @@ function CrmDashboard() {
1555
1871
  }, undefined, true, undefined, this)
1556
1872
  ]
1557
1873
  }, undefined, true, undefined, this),
1558
- /* @__PURE__ */ jsxDEV5(TabsContent, {
1874
+ /* @__PURE__ */ jsxDEV6(TabsContent, {
1559
1875
  value: "pipeline",
1560
1876
  className: "min-h-[400px]",
1561
- children: /* @__PURE__ */ jsxDEV5(CrmPipelineBoard, {
1877
+ children: /* @__PURE__ */ jsxDEV6(CrmPipelineBoard, {
1562
1878
  dealsByStage,
1563
1879
  stages,
1564
1880
  onDealClick: handleDealClick,
1565
1881
  onDealMove: handleDealMove
1566
1882
  }, undefined, false, undefined, this)
1567
1883
  }, undefined, false, undefined, this),
1568
- /* @__PURE__ */ jsxDEV5(TabsContent, {
1884
+ /* @__PURE__ */ jsxDEV6(TabsContent, {
1569
1885
  value: "list",
1570
1886
  className: "min-h-[400px]",
1571
- children: /* @__PURE__ */ jsxDEV5(DealListTab, {
1572
- data,
1887
+ children: /* @__PURE__ */ jsxDEV6(DealListTab, {
1573
1888
  onDealClick: handleDealClick
1574
1889
  }, undefined, false, undefined, this)
1575
1890
  }, undefined, false, undefined, this),
1576
- /* @__PURE__ */ jsxDEV5(TabsContent, {
1891
+ /* @__PURE__ */ jsxDEV6(TabsContent, {
1577
1892
  value: "metrics",
1578
1893
  className: "min-h-[400px]",
1579
- children: /* @__PURE__ */ jsxDEV5(MetricsTab, {
1894
+ children: /* @__PURE__ */ jsxDEV6(MetricsTab, {
1580
1895
  stats
1581
1896
  }, undefined, false, undefined, this)
1582
1897
  }, undefined, false, undefined, this)
1583
1898
  ]
1584
1899
  }, undefined, true, undefined, this),
1585
- /* @__PURE__ */ jsxDEV5(CreateDealModal, {
1900
+ /* @__PURE__ */ jsxDEV6(CreateDealModal, {
1586
1901
  isOpen: isCreateModalOpen,
1587
1902
  onClose: () => setIsCreateModalOpen(false),
1588
1903
  onSubmit: async (input) => {
@@ -1591,7 +1906,7 @@ function CrmDashboard() {
1591
1906
  stages,
1592
1907
  isLoading: mutations.createState.loading
1593
1908
  }, undefined, false, undefined, this),
1594
- /* @__PURE__ */ jsxDEV5(DealActionsModal, {
1909
+ /* @__PURE__ */ jsxDEV6(DealActionsModal, {
1595
1910
  isOpen: isDealActionsOpen,
1596
1911
  deal: selectedDeal,
1597
1912
  stages,
@@ -1614,112 +1929,30 @@ function CrmDashboard() {
1614
1929
  ]
1615
1930
  }, undefined, true, undefined, this);
1616
1931
  }
1617
- function DealListTab({ data, onDealClick }) {
1618
- if (!data?.deals.length) {
1619
- return /* @__PURE__ */ jsxDEV5("div", {
1620
- className: "flex h-64 items-center justify-center text-muted-foreground",
1621
- children: "No deals found"
1622
- }, undefined, false, undefined, this);
1623
- }
1624
- return /* @__PURE__ */ jsxDEV5("div", {
1625
- className: "rounded-lg border border-border",
1626
- children: /* @__PURE__ */ jsxDEV5("table", {
1627
- className: "w-full",
1628
- children: [
1629
- /* @__PURE__ */ jsxDEV5("thead", {
1630
- className: "border-border border-b bg-muted/30",
1631
- children: /* @__PURE__ */ jsxDEV5("tr", {
1632
- children: [
1633
- /* @__PURE__ */ jsxDEV5("th", {
1634
- className: "px-4 py-3 text-left font-medium text-sm",
1635
- children: "Deal"
1636
- }, undefined, false, undefined, this),
1637
- /* @__PURE__ */ jsxDEV5("th", {
1638
- className: "px-4 py-3 text-left font-medium text-sm",
1639
- children: "Value"
1640
- }, undefined, false, undefined, this),
1641
- /* @__PURE__ */ jsxDEV5("th", {
1642
- className: "px-4 py-3 text-left font-medium text-sm",
1643
- children: "Status"
1644
- }, undefined, false, undefined, this),
1645
- /* @__PURE__ */ jsxDEV5("th", {
1646
- className: "px-4 py-3 text-left font-medium text-sm",
1647
- children: "Expected Close"
1648
- }, undefined, false, undefined, this),
1649
- /* @__PURE__ */ jsxDEV5("th", {
1650
- className: "px-4 py-3 text-left font-medium text-sm",
1651
- children: "Actions"
1652
- }, undefined, false, undefined, this)
1653
- ]
1654
- }, undefined, true, undefined, this)
1655
- }, undefined, false, undefined, this),
1656
- /* @__PURE__ */ jsxDEV5("tbody", {
1657
- className: "divide-y divide-border",
1658
- children: data.deals.map((deal) => /* @__PURE__ */ jsxDEV5("tr", {
1659
- className: "hover:bg-muted/50",
1660
- children: [
1661
- /* @__PURE__ */ jsxDEV5("td", {
1662
- className: "px-4 py-3",
1663
- children: /* @__PURE__ */ jsxDEV5("div", {
1664
- className: "font-medium",
1665
- children: deal.name
1666
- }, undefined, false, undefined, this)
1667
- }, undefined, false, undefined, this),
1668
- /* @__PURE__ */ jsxDEV5("td", {
1669
- className: "px-4 py-3 font-mono",
1670
- children: formatCurrency4(deal.value, deal.currency)
1671
- }, undefined, false, undefined, this),
1672
- /* @__PURE__ */ jsxDEV5("td", {
1673
- className: "px-4 py-3",
1674
- children: /* @__PURE__ */ jsxDEV5("span", {
1675
- className: `inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${deal.status === "WON" ? "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400" : deal.status === "LOST" ? "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400" : "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400"}`,
1676
- children: deal.status
1677
- }, undefined, false, undefined, this)
1678
- }, undefined, false, undefined, this),
1679
- /* @__PURE__ */ jsxDEV5("td", {
1680
- className: "px-4 py-3 text-muted-foreground",
1681
- children: deal.expectedCloseDate?.toLocaleDateString() ?? "-"
1682
- }, undefined, false, undefined, this),
1683
- /* @__PURE__ */ jsxDEV5("td", {
1684
- className: "px-4 py-3",
1685
- children: /* @__PURE__ */ jsxDEV5(Button3, {
1686
- variant: "ghost",
1687
- size: "sm",
1688
- onPress: () => onDealClick?.(deal.id),
1689
- children: "Actions"
1690
- }, undefined, false, undefined, this)
1691
- }, undefined, false, undefined, this)
1692
- ]
1693
- }, deal.id, true, undefined, this))
1694
- }, undefined, false, undefined, this)
1695
- ]
1696
- }, undefined, true, undefined, this)
1697
- }, undefined, false, undefined, this);
1698
- }
1699
1932
  function MetricsTab({
1700
1933
  stats
1701
1934
  }) {
1702
1935
  if (!stats)
1703
1936
  return null;
1704
- return /* @__PURE__ */ jsxDEV5("div", {
1937
+ return /* @__PURE__ */ jsxDEV6("div", {
1705
1938
  className: "space-y-6",
1706
- children: /* @__PURE__ */ jsxDEV5("div", {
1939
+ children: /* @__PURE__ */ jsxDEV6("div", {
1707
1940
  className: "rounded-xl border border-border bg-card p-6",
1708
1941
  children: [
1709
- /* @__PURE__ */ jsxDEV5("h3", {
1942
+ /* @__PURE__ */ jsxDEV6("h3", {
1710
1943
  className: "mb-4 font-semibold text-lg",
1711
1944
  children: "Pipeline Overview"
1712
1945
  }, undefined, false, undefined, this),
1713
- /* @__PURE__ */ jsxDEV5("dl", {
1946
+ /* @__PURE__ */ jsxDEV6("dl", {
1714
1947
  className: "grid gap-4 sm:grid-cols-3",
1715
1948
  children: [
1716
- /* @__PURE__ */ jsxDEV5("div", {
1949
+ /* @__PURE__ */ jsxDEV6("div", {
1717
1950
  children: [
1718
- /* @__PURE__ */ jsxDEV5("dt", {
1951
+ /* @__PURE__ */ jsxDEV6("dt", {
1719
1952
  className: "text-muted-foreground text-sm",
1720
1953
  children: "Win Rate"
1721
1954
  }, undefined, false, undefined, this),
1722
- /* @__PURE__ */ jsxDEV5("dd", {
1955
+ /* @__PURE__ */ jsxDEV6("dd", {
1723
1956
  className: "font-semibold text-2xl",
1724
1957
  children: [
1725
1958
  stats.total > 0 ? (stats.wonCount / stats.total * 100).toFixed(0) : 0,
@@ -1728,25 +1961,25 @@ function MetricsTab({
1728
1961
  }, undefined, true, undefined, this)
1729
1962
  ]
1730
1963
  }, undefined, true, undefined, this),
1731
- /* @__PURE__ */ jsxDEV5("div", {
1964
+ /* @__PURE__ */ jsxDEV6("div", {
1732
1965
  children: [
1733
- /* @__PURE__ */ jsxDEV5("dt", {
1966
+ /* @__PURE__ */ jsxDEV6("dt", {
1734
1967
  className: "text-muted-foreground text-sm",
1735
1968
  children: "Avg Deal Size"
1736
1969
  }, undefined, false, undefined, this),
1737
- /* @__PURE__ */ jsxDEV5("dd", {
1970
+ /* @__PURE__ */ jsxDEV6("dd", {
1738
1971
  className: "font-semibold text-2xl",
1739
- children: formatCurrency4(stats.total > 0 ? stats.totalValue / stats.total : 0)
1972
+ children: formatCurrency5(stats.total > 0 ? stats.totalValue / stats.total : 0)
1740
1973
  }, undefined, false, undefined, this)
1741
1974
  ]
1742
1975
  }, undefined, true, undefined, this),
1743
- /* @__PURE__ */ jsxDEV5("div", {
1976
+ /* @__PURE__ */ jsxDEV6("div", {
1744
1977
  children: [
1745
- /* @__PURE__ */ jsxDEV5("dt", {
1978
+ /* @__PURE__ */ jsxDEV6("dt", {
1746
1979
  className: "text-muted-foreground text-sm",
1747
1980
  children: "Conversion"
1748
1981
  }, undefined, false, undefined, this),
1749
- /* @__PURE__ */ jsxDEV5("dd", {
1982
+ /* @__PURE__ */ jsxDEV6("dd", {
1750
1983
  className: "font-semibold text-2xl",
1751
1984
  children: [
1752
1985
  stats.wonCount,
@@ -1816,7 +2049,7 @@ var crmOverlays = [
1816
2049
  crmSalesRepOverlay
1817
2050
  ];
1818
2051
  // src/ui/renderers/pipeline.markdown.ts
1819
- function formatCurrency5(value, currency = "USD") {
2052
+ function formatCurrency6(value, currency = "USD") {
1820
2053
  return new Intl.NumberFormat("en-US", {
1821
2054
  style: "currency",
1822
2055
  currency,
@@ -1843,7 +2076,7 @@ var crmPipelineMarkdownRenderer = {
1843
2076
  const lines = [
1844
2077
  "# CRM Pipeline",
1845
2078
  "",
1846
- `**Total Value**: ${formatCurrency5(dealsResult.totalValue)}`,
2079
+ `**Total Value**: ${formatCurrency6(dealsResult.totalValue)}`,
1847
2080
  `**Total Deals**: ${dealsResult.total}`,
1848
2081
  ""
1849
2082
  ];
@@ -1851,13 +2084,13 @@ var crmPipelineMarkdownRenderer = {
1851
2084
  const stageDeals = dealsByStage[stage.id] ?? [];
1852
2085
  const stageValue = stageDeals.reduce((sum, d) => sum + d.value, 0);
1853
2086
  lines.push(`## ${stage.name}`);
1854
- lines.push(`_${stageDeals.length} deals · ${formatCurrency5(stageValue)}_`);
2087
+ lines.push(`_${stageDeals.length} deals · ${formatCurrency6(stageValue)}_`);
1855
2088
  lines.push("");
1856
2089
  if (stageDeals.length === 0) {
1857
2090
  lines.push("_No deals_");
1858
2091
  } else {
1859
2092
  for (const deal of stageDeals) {
1860
- lines.push(`- **${deal.name}** - ${formatCurrency5(deal.value, deal.currency)}`);
2093
+ lines.push(`- **${deal.name}** - ${formatCurrency6(deal.value, deal.currency)}`);
1861
2094
  }
1862
2095
  }
1863
2096
  lines.push("");
@@ -1897,9 +2130,9 @@ var crmDashboardMarkdownRenderer = {
1897
2130
  "| Metric | Value |",
1898
2131
  "|--------|-------|",
1899
2132
  `| Total Deals | ${dealsResult.total} |`,
1900
- `| Pipeline Value | ${formatCurrency5(dealsResult.totalValue)} |`,
1901
- `| Open Deals | ${openDeals.length} (${formatCurrency5(openValue)}) |`,
1902
- `| Won Deals | ${wonDeals.length} (${formatCurrency5(wonValue)}) |`,
2133
+ `| Pipeline Value | ${formatCurrency6(dealsResult.totalValue)} |`,
2134
+ `| Open Deals | ${openDeals.length} (${formatCurrency6(openValue)}) |`,
2135
+ `| Won Deals | ${wonDeals.length} (${formatCurrency6(wonValue)}) |`,
1903
2136
  `| Lost Deals | ${lostDeals.length} |`,
1904
2137
  "",
1905
2138
  "## Pipeline Stages",
@@ -1910,7 +2143,7 @@ var crmDashboardMarkdownRenderer = {
1910
2143
  for (const stage of stageList.sort((a, b) => a.position - b.position)) {
1911
2144
  const stageDeals = openDeals.filter((d) => d.stageId === stage.id);
1912
2145
  const stageValue = stageDeals.reduce((sum, d) => sum + d.value, 0);
1913
- lines.push(`| ${stage.name} | ${stageDeals.length} | ${formatCurrency5(stageValue)} |`);
2146
+ lines.push(`| ${stage.name} | ${stageDeals.length} | ${formatCurrency6(stageValue)} |`);
1914
2147
  }
1915
2148
  lines.push("");
1916
2149
  lines.push("## Recent Deals");
@@ -1923,7 +2156,7 @@ var crmDashboardMarkdownRenderer = {
1923
2156
  lines.push("|------|-------|-------|--------|");
1924
2157
  for (const deal of recentDeals) {
1925
2158
  const stage = stageList.find((s) => s.id === deal.stageId);
1926
- lines.push(`| ${deal.name} | ${formatCurrency5(deal.value, deal.currency)} | ${stage?.name ?? "-"} | ${deal.status} |`);
2159
+ lines.push(`| ${deal.name} | ${formatCurrency6(deal.value, deal.currency)} | ${stage?.name ?? "-"} | ${deal.status} |`);
1927
2160
  }
1928
2161
  }
1929
2162
  return {
@@ -1935,10 +2168,10 @@ var crmDashboardMarkdownRenderer = {
1935
2168
  };
1936
2169
 
1937
2170
  // src/ui/renderers/pipeline.renderer.tsx
1938
- import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
2171
+ import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
1939
2172
  function CrmPipelineBoardWrapper() {
1940
2173
  const { dealsByStage, stages } = useDealList();
1941
- return /* @__PURE__ */ jsxDEV6(CrmPipelineBoard, {
2174
+ return /* @__PURE__ */ jsxDEV7(CrmPipelineBoard, {
1942
2175
  dealsByStage,
1943
2176
  stages
1944
2177
  }, undefined, false, undefined, this);
@@ -1952,7 +2185,7 @@ var crmPipelineReactRenderer = {
1952
2185
  if (desc.source.componentKey !== "CrmPipelineView") {
1953
2186
  throw new Error(`Unknown component: ${desc.source.componentKey}`);
1954
2187
  }
1955
- return /* @__PURE__ */ jsxDEV6(CrmPipelineBoardWrapper, {}, undefined, false, undefined, this);
2188
+ return /* @__PURE__ */ jsxDEV7(CrmPipelineBoardWrapper, {}, undefined, false, undefined, this);
1956
2189
  }
1957
2190
  };
1958
2191
  export {