@contractspec/example.crm-pipeline 3.7.7 → 3.7.10

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