@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
@@ -550,7 +550,7 @@ var crmPipelineDocBlocks = [
550
550
  - deal.created, stage.moved, task.completed, contact.updated.
551
551
 
552
552
  ## Presentations
553
- - Pipelines/kanban, deal detail, contact/company profiles, task lists.
553
+ - Pipelines/kanban, deal detail, contact/company profiles, task lists, and a server-mode shared table for the deal list.
554
554
 
555
555
  ## Notes
556
556
  - Stage definitions should be declarative; enforce via spec and regeneration.
@@ -1119,6 +1119,13 @@ function rowToDeal(row) {
1119
1119
  updatedAt: new Date(row.updatedAt)
1120
1120
  };
1121
1121
  }
1122
+ var DEAL_SORT_COLUMNS = {
1123
+ name: "name",
1124
+ value: "value",
1125
+ status: "status",
1126
+ expectedCloseDate: "expectedCloseDate",
1127
+ updatedAt: "updatedAt"
1128
+ };
1122
1129
  function createCrmHandlers(db) {
1123
1130
  async function listDeals(input) {
1124
1131
  const {
@@ -1129,7 +1136,9 @@ function createCrmHandlers(db) {
1129
1136
  ownerId,
1130
1137
  search,
1131
1138
  limit = 20,
1132
- offset = 0
1139
+ offset = 0,
1140
+ sortBy = "value",
1141
+ sortDirection = "desc"
1133
1142
  } = input;
1134
1143
  let whereClause = "WHERE projectId = ?";
1135
1144
  const params = [projectId];
@@ -1157,7 +1166,9 @@ function createCrmHandlers(db) {
1157
1166
  const total = countResult[0]?.count ?? 0;
1158
1167
  const valueResult = (await db.query(`SELECT COALESCE(SUM(value), 0) as total FROM crm_deal ${whereClause}`, params)).rows;
1159
1168
  const totalValue = valueResult[0]?.total ?? 0;
1160
- const dealRows = (await db.query(`SELECT * FROM crm_deal ${whereClause} ORDER BY value DESC LIMIT ? OFFSET ?`, [...params, limit, offset])).rows;
1169
+ const orderByColumn = DEAL_SORT_COLUMNS[sortBy] ?? DEAL_SORT_COLUMNS.value;
1170
+ const orderByDirection = sortDirection === "asc" ? "ASC" : "DESC";
1171
+ const dealRows = (await db.query(`SELECT * FROM crm_deal ${whereClause} ORDER BY ${orderByColumn} ${orderByDirection} LIMIT ? OFFSET ?`, [...params, limit, offset])).rows;
1161
1172
  return {
1162
1173
  deals: dealRows.map(rowToDeal),
1163
1174
  total,
@@ -1859,8 +1870,13 @@ function useDealList(options = {}) {
1859
1870
  const [stages, setStages] = useState2([]);
1860
1871
  const [loading, setLoading] = useState2(true);
1861
1872
  const [error, setError] = useState2(null);
1862
- const [page, setPage] = useState2(1);
1873
+ const [internalPage, setInternalPage] = useState2(0);
1863
1874
  const pipelineId = options.pipelineId ?? "pipeline-1";
1875
+ const pageIndex = options.pageIndex ?? internalPage;
1876
+ const pageSize = options.pageSize ?? options.limit ?? 50;
1877
+ const [sort] = options.sorting ?? [];
1878
+ const sortBy = sort?.id;
1879
+ const sortDirection = sort ? sort.desc ? "desc" : "asc" : undefined;
1864
1880
  const fetchData = useCallback(async () => {
1865
1881
  setLoading(true);
1866
1882
  setError(null);
@@ -1872,8 +1888,10 @@ function useDealList(options = {}) {
1872
1888
  stageId: options.stageId,
1873
1889
  status: options.status === "all" ? undefined : options.status,
1874
1890
  search: options.search,
1875
- limit: options.limit ?? 50,
1876
- offset: (page - 1) * (options.limit ?? 50)
1891
+ limit: pageSize,
1892
+ offset: pageIndex * pageSize,
1893
+ sortBy: sortBy === "name" || sortBy === "value" || sortBy === "status" || sortBy === "expectedCloseDate" || sortBy === "updatedAt" ? sortBy : undefined,
1894
+ sortDirection
1877
1895
  }),
1878
1896
  crm2.getDealsByStage({ projectId, pipelineId }),
1879
1897
  crm2.getPipelineStages({ pipelineId })
@@ -1893,8 +1911,10 @@ function useDealList(options = {}) {
1893
1911
  options.stageId,
1894
1912
  options.status,
1895
1913
  options.search,
1896
- options.limit,
1897
- page
1914
+ pageIndex,
1915
+ pageSize,
1916
+ sortBy,
1917
+ sortDirection
1898
1918
  ]);
1899
1919
  useEffect(() => {
1900
1920
  fetchData();
@@ -1922,10 +1942,12 @@ function useDealList(options = {}) {
1922
1942
  loading,
1923
1943
  error,
1924
1944
  stats,
1925
- page,
1945
+ page: pageIndex + 1,
1946
+ pageIndex,
1947
+ pageSize,
1926
1948
  refetch: fetchData,
1927
- nextPage: () => setPage((p) => p + 1),
1928
- prevPage: () => page > 1 && setPage((p) => p - 1)
1949
+ nextPage: options.pageIndex === undefined ? () => setInternalPage((page) => page + 1) : undefined,
1950
+ prevPage: options.pageIndex === undefined ? () => pageIndex > 0 && setInternalPage((page) => page - 1) : undefined
1929
1951
  };
1930
1952
  }
1931
1953
 
@@ -2662,11 +2684,305 @@ function DealActionsModal({
2662
2684
  }, undefined, true, undefined, this);
2663
2685
  }
2664
2686
 
2665
- // src/ui/CrmDashboard.tsx
2687
+ // src/ui/tables/DealListTab.tsx
2666
2688
  import {
2667
2689
  Button as Button3,
2690
+ DataTable,
2691
+ LoaderBlock
2692
+ } from "@contractspec/lib.design-system";
2693
+ import { useContractTable } from "@contractspec/lib.presentation-runtime-react";
2694
+ import { Badge } from "@contractspec/lib.ui-kit-web/ui/badge";
2695
+ import { HStack, VStack } from "@contractspec/lib.ui-kit-web/ui/stack";
2696
+ import { Text } from "@contractspec/lib.ui-kit-web/ui/text";
2697
+ import * as React from "react";
2698
+ import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
2699
+ "use client";
2700
+ function formatCurrency4(value, currency = "USD") {
2701
+ return new Intl.NumberFormat("en-US", {
2702
+ style: "currency",
2703
+ currency,
2704
+ minimumFractionDigits: 0,
2705
+ maximumFractionDigits: 0
2706
+ }).format(value);
2707
+ }
2708
+ function statusVariant(status) {
2709
+ switch (status) {
2710
+ case "WON":
2711
+ return "default";
2712
+ case "LOST":
2713
+ return "destructive";
2714
+ case "STALE":
2715
+ return "outline";
2716
+ default:
2717
+ return "secondary";
2718
+ }
2719
+ }
2720
+ function DealListDataTable({
2721
+ deals,
2722
+ totalItems,
2723
+ pageIndex,
2724
+ pageSize,
2725
+ sorting,
2726
+ loading,
2727
+ onSortingChange,
2728
+ onPaginationChange,
2729
+ onDealClick
2730
+ }) {
2731
+ const controller = useContractTable({
2732
+ data: deals,
2733
+ columns: [
2734
+ {
2735
+ id: "deal",
2736
+ header: "Deal",
2737
+ label: "Deal",
2738
+ accessor: (deal3) => deal3.name,
2739
+ cell: ({ item }) => /* @__PURE__ */ jsxDEV5(VStack, {
2740
+ gap: "xs",
2741
+ children: [
2742
+ /* @__PURE__ */ jsxDEV5(Text, {
2743
+ className: "font-medium text-sm",
2744
+ children: item.name
2745
+ }, undefined, false, undefined, this),
2746
+ /* @__PURE__ */ jsxDEV5(Text, {
2747
+ className: "text-muted-foreground text-xs",
2748
+ children: item.companyId ?? "Unassigned company"
2749
+ }, undefined, false, undefined, this)
2750
+ ]
2751
+ }, undefined, true, undefined, this),
2752
+ size: 240,
2753
+ minSize: 180,
2754
+ canSort: true,
2755
+ canPin: true,
2756
+ canResize: true
2757
+ },
2758
+ {
2759
+ id: "value",
2760
+ header: "Value",
2761
+ label: "Value",
2762
+ accessorKey: "value",
2763
+ cell: ({ item }) => formatCurrency4(item.value, item.currency),
2764
+ align: "right",
2765
+ size: 140,
2766
+ canSort: true,
2767
+ canResize: true
2768
+ },
2769
+ {
2770
+ id: "status",
2771
+ header: "Status",
2772
+ label: "Status",
2773
+ accessorKey: "status",
2774
+ cell: ({ value }) => /* @__PURE__ */ jsxDEV5(Badge, {
2775
+ variant: statusVariant(value),
2776
+ children: String(value)
2777
+ }, undefined, false, undefined, this),
2778
+ size: 130,
2779
+ canSort: true,
2780
+ canHide: true,
2781
+ canPin: true,
2782
+ canResize: true
2783
+ },
2784
+ {
2785
+ id: "expectedCloseDate",
2786
+ header: "Expected Close",
2787
+ label: "Expected Close",
2788
+ accessor: (deal3) => deal3.expectedCloseDate?.toISOString() ?? "",
2789
+ cell: ({ item }) => item.expectedCloseDate?.toLocaleDateString() ?? "Not scheduled",
2790
+ size: 170,
2791
+ canSort: true,
2792
+ canHide: true,
2793
+ canResize: true
2794
+ },
2795
+ {
2796
+ id: "updatedAt",
2797
+ header: "Updated",
2798
+ label: "Updated",
2799
+ accessor: (deal3) => deal3.updatedAt.toISOString(),
2800
+ cell: ({ item }) => item.updatedAt.toLocaleDateString(),
2801
+ size: 140,
2802
+ canSort: true,
2803
+ canHide: true,
2804
+ canResize: true
2805
+ },
2806
+ {
2807
+ id: "actions",
2808
+ header: "Actions",
2809
+ label: "Actions",
2810
+ accessor: (deal3) => deal3.id,
2811
+ cell: ({ item }) => /* @__PURE__ */ jsxDEV5(Button3, {
2812
+ variant: "ghost",
2813
+ size: "sm",
2814
+ onPress: () => onDealClick?.(item.id),
2815
+ children: "Actions"
2816
+ }, undefined, false, undefined, this),
2817
+ size: 120,
2818
+ canSort: false,
2819
+ canHide: false,
2820
+ canPin: false,
2821
+ canResize: false
2822
+ }
2823
+ ],
2824
+ executionMode: "server",
2825
+ selectionMode: "multiple",
2826
+ totalItems,
2827
+ state: {
2828
+ sorting,
2829
+ pagination: {
2830
+ pageIndex,
2831
+ pageSize
2832
+ }
2833
+ },
2834
+ onSortingChange,
2835
+ onPaginationChange,
2836
+ initialState: {
2837
+ columnVisibility: { updatedAt: false },
2838
+ columnPinning: { left: ["deal", "status"], right: [] }
2839
+ },
2840
+ renderExpandedContent: (deal3) => /* @__PURE__ */ jsxDEV5(VStack, {
2841
+ gap: "sm",
2842
+ className: "py-2",
2843
+ children: [
2844
+ /* @__PURE__ */ jsxDEV5(HStack, {
2845
+ justify: "between",
2846
+ children: [
2847
+ /* @__PURE__ */ jsxDEV5(Text, {
2848
+ className: "font-medium text-sm",
2849
+ children: "Owner"
2850
+ }, undefined, false, undefined, this),
2851
+ /* @__PURE__ */ jsxDEV5(Text, {
2852
+ className: "text-muted-foreground text-sm",
2853
+ children: deal3.ownerId
2854
+ }, undefined, false, undefined, this)
2855
+ ]
2856
+ }, undefined, true, undefined, this),
2857
+ /* @__PURE__ */ jsxDEV5(HStack, {
2858
+ justify: "between",
2859
+ children: [
2860
+ /* @__PURE__ */ jsxDEV5(Text, {
2861
+ className: "font-medium text-sm",
2862
+ children: "Contact"
2863
+ }, undefined, false, undefined, this),
2864
+ /* @__PURE__ */ jsxDEV5(Text, {
2865
+ className: "text-muted-foreground text-sm",
2866
+ children: deal3.contactId ?? "No linked contact"
2867
+ }, undefined, false, undefined, this)
2868
+ ]
2869
+ }, undefined, true, undefined, this),
2870
+ deal3.wonSource ? /* @__PURE__ */ jsxDEV5(HStack, {
2871
+ justify: "between",
2872
+ children: [
2873
+ /* @__PURE__ */ jsxDEV5(Text, {
2874
+ className: "font-medium text-sm",
2875
+ children: "Won Source"
2876
+ }, undefined, false, undefined, this),
2877
+ /* @__PURE__ */ jsxDEV5(Text, {
2878
+ className: "text-muted-foreground text-sm",
2879
+ children: deal3.wonSource
2880
+ }, undefined, false, undefined, this)
2881
+ ]
2882
+ }, undefined, true, undefined, this) : null,
2883
+ deal3.lostReason ? /* @__PURE__ */ jsxDEV5(HStack, {
2884
+ justify: "between",
2885
+ children: [
2886
+ /* @__PURE__ */ jsxDEV5(Text, {
2887
+ className: "font-medium text-sm",
2888
+ children: "Lost Reason"
2889
+ }, undefined, false, undefined, this),
2890
+ /* @__PURE__ */ jsxDEV5(Text, {
2891
+ className: "text-muted-foreground text-sm",
2892
+ children: deal3.lostReason
2893
+ }, undefined, false, undefined, this)
2894
+ ]
2895
+ }, undefined, true, undefined, this) : null,
2896
+ deal3.notes ? /* @__PURE__ */ jsxDEV5(VStack, {
2897
+ gap: "xs",
2898
+ children: [
2899
+ /* @__PURE__ */ jsxDEV5(Text, {
2900
+ className: "font-medium text-sm",
2901
+ children: "Notes"
2902
+ }, undefined, false, undefined, this),
2903
+ /* @__PURE__ */ jsxDEV5(Text, {
2904
+ className: "text-muted-foreground text-sm",
2905
+ children: deal3.notes
2906
+ }, undefined, false, undefined, this)
2907
+ ]
2908
+ }, undefined, true, undefined, this) : null
2909
+ ]
2910
+ }, undefined, true, undefined, this),
2911
+ getCanExpand: () => true
2912
+ });
2913
+ return /* @__PURE__ */ jsxDEV5(DataTable, {
2914
+ controller,
2915
+ title: "All Deals",
2916
+ description: "Server-mode table using the shared ContractSpec controller.",
2917
+ loading,
2918
+ toolbar: /* @__PURE__ */ jsxDEV5(HStack, {
2919
+ gap: "sm",
2920
+ className: "flex-wrap",
2921
+ children: [
2922
+ /* @__PURE__ */ jsxDEV5(Text, {
2923
+ className: "text-muted-foreground text-sm",
2924
+ children: [
2925
+ "Selected ",
2926
+ controller.selectedRowIds.length
2927
+ ]
2928
+ }, undefined, true, undefined, this),
2929
+ /* @__PURE__ */ jsxDEV5(Text, {
2930
+ className: "text-muted-foreground text-sm",
2931
+ children: [
2932
+ totalItems,
2933
+ " total deals"
2934
+ ]
2935
+ }, undefined, true, undefined, this)
2936
+ ]
2937
+ }, undefined, true, undefined, this),
2938
+ footer: `Page ${controller.pageIndex + 1} of ${controller.pageCount}`,
2939
+ emptyState: /* @__PURE__ */ jsxDEV5("div", {
2940
+ className: "rounded-md border border-dashed p-8 text-center text-muted-foreground text-sm",
2941
+ children: "No deals found"
2942
+ }, undefined, false, undefined, this)
2943
+ }, undefined, false, undefined, this);
2944
+ }
2945
+ function DealListTab({
2946
+ onDealClick
2947
+ }) {
2948
+ const [sorting, setSorting] = React.useState([
2949
+ { id: "value", desc: true }
2950
+ ]);
2951
+ const [pagination, setPagination] = React.useState({
2952
+ pageIndex: 0,
2953
+ pageSize: 3
2954
+ });
2955
+ const { data, loading } = useDealList({
2956
+ pageIndex: pagination.pageIndex,
2957
+ pageSize: pagination.pageSize,
2958
+ sorting
2959
+ });
2960
+ if (loading && !data) {
2961
+ return /* @__PURE__ */ jsxDEV5(LoaderBlock, {
2962
+ label: "Loading deals..."
2963
+ }, undefined, false, undefined, this);
2964
+ }
2965
+ return /* @__PURE__ */ jsxDEV5(DealListDataTable, {
2966
+ deals: data?.deals ?? [],
2967
+ totalItems: data?.total ?? 0,
2968
+ pageIndex: pagination.pageIndex,
2969
+ pageSize: pagination.pageSize,
2970
+ sorting,
2971
+ loading,
2972
+ onSortingChange: (nextSorting) => {
2973
+ setSorting(nextSorting);
2974
+ setPagination((current) => ({ ...current, pageIndex: 0 }));
2975
+ },
2976
+ onPaginationChange: setPagination,
2977
+ onDealClick
2978
+ }, undefined, false, undefined, this);
2979
+ }
2980
+
2981
+ // src/ui/CrmDashboard.tsx
2982
+ import {
2983
+ Button as Button4,
2668
2984
  ErrorState,
2669
- LoaderBlock,
2985
+ LoaderBlock as LoaderBlock2,
2670
2986
  StatCard,
2671
2987
  StatCardGroup
2672
2988
  } from "@contractspec/lib.design-system";
@@ -2676,10 +2992,10 @@ import {
2676
2992
  TabsList,
2677
2993
  TabsTrigger
2678
2994
  } from "@contractspec/lib.ui-kit-web/ui/tabs";
2679
- import { useCallback as useCallback3, useState as useState6 } from "react";
2680
- import { jsxDEV as jsxDEV5 } from "react/jsx-dev-runtime";
2995
+ import { useCallback as useCallback3, useState as useState7 } from "react";
2996
+ import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
2681
2997
  "use client";
2682
- function formatCurrency4(value, currency = "USD") {
2998
+ function formatCurrency5(value, currency = "USD") {
2683
2999
  return new Intl.NumberFormat("en-US", {
2684
3000
  style: "currency",
2685
3001
  currency,
@@ -2688,9 +3004,9 @@ function formatCurrency4(value, currency = "USD") {
2688
3004
  }).format(value);
2689
3005
  }
2690
3006
  function CrmDashboard() {
2691
- const [isCreateModalOpen, setIsCreateModalOpen] = useState6(false);
2692
- const [selectedDeal, setSelectedDeal] = useState6(null);
2693
- const [isDealActionsOpen, setIsDealActionsOpen] = useState6(false);
3007
+ const [isCreateModalOpen, setIsCreateModalOpen] = useState7(false);
3008
+ const [selectedDeal, setSelectedDeal] = useState7(null);
3009
+ const [isDealActionsOpen, setIsDealActionsOpen] = useState7(false);
2694
3010
  const { data, dealsByStage, stages, loading, error, stats, refetch } = useDealList();
2695
3011
  const mutations = useDealMutations({
2696
3012
  onSuccess: () => {
@@ -2708,32 +3024,32 @@ function CrmDashboard() {
2708
3024
  await mutations.moveDeal({ dealId, stageId: toStageId });
2709
3025
  }, [mutations]);
2710
3026
  if (loading && !data) {
2711
- return /* @__PURE__ */ jsxDEV5(LoaderBlock, {
3027
+ return /* @__PURE__ */ jsxDEV6(LoaderBlock2, {
2712
3028
  label: "Loading CRM..."
2713
3029
  }, undefined, false, undefined, this);
2714
3030
  }
2715
3031
  if (error) {
2716
- return /* @__PURE__ */ jsxDEV5(ErrorState, {
3032
+ return /* @__PURE__ */ jsxDEV6(ErrorState, {
2717
3033
  title: "Failed to load CRM",
2718
3034
  description: error.message,
2719
3035
  onRetry: refetch,
2720
3036
  retryLabel: "Retry"
2721
3037
  }, undefined, false, undefined, this);
2722
3038
  }
2723
- return /* @__PURE__ */ jsxDEV5("div", {
3039
+ return /* @__PURE__ */ jsxDEV6("div", {
2724
3040
  className: "space-y-6",
2725
3041
  children: [
2726
- /* @__PURE__ */ jsxDEV5("div", {
3042
+ /* @__PURE__ */ jsxDEV6("div", {
2727
3043
  className: "flex items-center justify-between",
2728
3044
  children: [
2729
- /* @__PURE__ */ jsxDEV5("h2", {
3045
+ /* @__PURE__ */ jsxDEV6("h2", {
2730
3046
  className: "font-bold text-2xl",
2731
3047
  children: "CRM Pipeline"
2732
3048
  }, undefined, false, undefined, this),
2733
- /* @__PURE__ */ jsxDEV5(Button3, {
3049
+ /* @__PURE__ */ jsxDEV6(Button4, {
2734
3050
  onClick: () => setIsCreateModalOpen(true),
2735
3051
  children: [
2736
- /* @__PURE__ */ jsxDEV5("span", {
3052
+ /* @__PURE__ */ jsxDEV6("span", {
2737
3053
  className: "mr-2",
2738
3054
  children: "+"
2739
3055
  }, undefined, false, undefined, this),
@@ -2742,60 +3058,60 @@ function CrmDashboard() {
2742
3058
  }, undefined, true, undefined, this)
2743
3059
  ]
2744
3060
  }, undefined, true, undefined, this),
2745
- stats && /* @__PURE__ */ jsxDEV5(StatCardGroup, {
3061
+ stats && /* @__PURE__ */ jsxDEV6(StatCardGroup, {
2746
3062
  children: [
2747
- /* @__PURE__ */ jsxDEV5(StatCard, {
3063
+ /* @__PURE__ */ jsxDEV6(StatCard, {
2748
3064
  label: "Total Pipeline",
2749
- value: formatCurrency4(stats.totalValue),
3065
+ value: formatCurrency5(stats.totalValue),
2750
3066
  hint: `${stats.total} deals`
2751
3067
  }, undefined, false, undefined, this),
2752
- /* @__PURE__ */ jsxDEV5(StatCard, {
3068
+ /* @__PURE__ */ jsxDEV6(StatCard, {
2753
3069
  label: "Open Deals",
2754
- value: formatCurrency4(stats.openValue),
3070
+ value: formatCurrency5(stats.openValue),
2755
3071
  hint: `${stats.openCount} active`
2756
3072
  }, undefined, false, undefined, this),
2757
- /* @__PURE__ */ jsxDEV5(StatCard, {
3073
+ /* @__PURE__ */ jsxDEV6(StatCard, {
2758
3074
  label: "Won",
2759
- value: formatCurrency4(stats.wonValue),
3075
+ value: formatCurrency5(stats.wonValue),
2760
3076
  hint: `${stats.wonCount} closed`
2761
3077
  }, undefined, false, undefined, this),
2762
- /* @__PURE__ */ jsxDEV5(StatCard, {
3078
+ /* @__PURE__ */ jsxDEV6(StatCard, {
2763
3079
  label: "Lost",
2764
3080
  value: stats.lostCount,
2765
3081
  hint: "deals lost"
2766
3082
  }, undefined, false, undefined, this)
2767
3083
  ]
2768
3084
  }, undefined, true, undefined, this),
2769
- /* @__PURE__ */ jsxDEV5(Tabs, {
3085
+ /* @__PURE__ */ jsxDEV6(Tabs, {
2770
3086
  defaultValue: "pipeline",
2771
3087
  className: "w-full",
2772
3088
  children: [
2773
- /* @__PURE__ */ jsxDEV5(TabsList, {
3089
+ /* @__PURE__ */ jsxDEV6(TabsList, {
2774
3090
  children: [
2775
- /* @__PURE__ */ jsxDEV5(TabsTrigger, {
3091
+ /* @__PURE__ */ jsxDEV6(TabsTrigger, {
2776
3092
  value: "pipeline",
2777
3093
  children: [
2778
- /* @__PURE__ */ jsxDEV5("span", {
3094
+ /* @__PURE__ */ jsxDEV6("span", {
2779
3095
  className: "mr-2",
2780
3096
  children: "\uD83D\uDCCA"
2781
3097
  }, undefined, false, undefined, this),
2782
3098
  "Pipeline"
2783
3099
  ]
2784
3100
  }, undefined, true, undefined, this),
2785
- /* @__PURE__ */ jsxDEV5(TabsTrigger, {
3101
+ /* @__PURE__ */ jsxDEV6(TabsTrigger, {
2786
3102
  value: "list",
2787
3103
  children: [
2788
- /* @__PURE__ */ jsxDEV5("span", {
3104
+ /* @__PURE__ */ jsxDEV6("span", {
2789
3105
  className: "mr-2",
2790
3106
  children: "\uD83D\uDCCB"
2791
3107
  }, undefined, false, undefined, this),
2792
3108
  "All Deals"
2793
3109
  ]
2794
3110
  }, undefined, true, undefined, this),
2795
- /* @__PURE__ */ jsxDEV5(TabsTrigger, {
3111
+ /* @__PURE__ */ jsxDEV6(TabsTrigger, {
2796
3112
  value: "metrics",
2797
3113
  children: [
2798
- /* @__PURE__ */ jsxDEV5("span", {
3114
+ /* @__PURE__ */ jsxDEV6("span", {
2799
3115
  className: "mr-2",
2800
3116
  children: "\uD83D\uDCC8"
2801
3117
  }, undefined, false, undefined, this),
@@ -2804,34 +3120,33 @@ function CrmDashboard() {
2804
3120
  }, undefined, true, undefined, this)
2805
3121
  ]
2806
3122
  }, undefined, true, undefined, this),
2807
- /* @__PURE__ */ jsxDEV5(TabsContent, {
3123
+ /* @__PURE__ */ jsxDEV6(TabsContent, {
2808
3124
  value: "pipeline",
2809
3125
  className: "min-h-[400px]",
2810
- children: /* @__PURE__ */ jsxDEV5(CrmPipelineBoard, {
3126
+ children: /* @__PURE__ */ jsxDEV6(CrmPipelineBoard, {
2811
3127
  dealsByStage,
2812
3128
  stages,
2813
3129
  onDealClick: handleDealClick,
2814
3130
  onDealMove: handleDealMove
2815
3131
  }, undefined, false, undefined, this)
2816
3132
  }, undefined, false, undefined, this),
2817
- /* @__PURE__ */ jsxDEV5(TabsContent, {
3133
+ /* @__PURE__ */ jsxDEV6(TabsContent, {
2818
3134
  value: "list",
2819
3135
  className: "min-h-[400px]",
2820
- children: /* @__PURE__ */ jsxDEV5(DealListTab, {
2821
- data,
3136
+ children: /* @__PURE__ */ jsxDEV6(DealListTab, {
2822
3137
  onDealClick: handleDealClick
2823
3138
  }, undefined, false, undefined, this)
2824
3139
  }, undefined, false, undefined, this),
2825
- /* @__PURE__ */ jsxDEV5(TabsContent, {
3140
+ /* @__PURE__ */ jsxDEV6(TabsContent, {
2826
3141
  value: "metrics",
2827
3142
  className: "min-h-[400px]",
2828
- children: /* @__PURE__ */ jsxDEV5(MetricsTab, {
3143
+ children: /* @__PURE__ */ jsxDEV6(MetricsTab, {
2829
3144
  stats
2830
3145
  }, undefined, false, undefined, this)
2831
3146
  }, undefined, false, undefined, this)
2832
3147
  ]
2833
3148
  }, undefined, true, undefined, this),
2834
- /* @__PURE__ */ jsxDEV5(CreateDealModal, {
3149
+ /* @__PURE__ */ jsxDEV6(CreateDealModal, {
2835
3150
  isOpen: isCreateModalOpen,
2836
3151
  onClose: () => setIsCreateModalOpen(false),
2837
3152
  onSubmit: async (input) => {
@@ -2840,7 +3155,7 @@ function CrmDashboard() {
2840
3155
  stages,
2841
3156
  isLoading: mutations.createState.loading
2842
3157
  }, undefined, false, undefined, this),
2843
- /* @__PURE__ */ jsxDEV5(DealActionsModal, {
3158
+ /* @__PURE__ */ jsxDEV6(DealActionsModal, {
2844
3159
  isOpen: isDealActionsOpen,
2845
3160
  deal: selectedDeal,
2846
3161
  stages,
@@ -2863,112 +3178,30 @@ function CrmDashboard() {
2863
3178
  ]
2864
3179
  }, undefined, true, undefined, this);
2865
3180
  }
2866
- function DealListTab({ data, onDealClick }) {
2867
- if (!data?.deals.length) {
2868
- return /* @__PURE__ */ jsxDEV5("div", {
2869
- className: "flex h-64 items-center justify-center text-muted-foreground",
2870
- children: "No deals found"
2871
- }, undefined, false, undefined, this);
2872
- }
2873
- return /* @__PURE__ */ jsxDEV5("div", {
2874
- className: "rounded-lg border border-border",
2875
- children: /* @__PURE__ */ jsxDEV5("table", {
2876
- className: "w-full",
2877
- children: [
2878
- /* @__PURE__ */ jsxDEV5("thead", {
2879
- className: "border-border border-b bg-muted/30",
2880
- children: /* @__PURE__ */ jsxDEV5("tr", {
2881
- children: [
2882
- /* @__PURE__ */ jsxDEV5("th", {
2883
- className: "px-4 py-3 text-left font-medium text-sm",
2884
- children: "Deal"
2885
- }, undefined, false, undefined, this),
2886
- /* @__PURE__ */ jsxDEV5("th", {
2887
- className: "px-4 py-3 text-left font-medium text-sm",
2888
- children: "Value"
2889
- }, undefined, false, undefined, this),
2890
- /* @__PURE__ */ jsxDEV5("th", {
2891
- className: "px-4 py-3 text-left font-medium text-sm",
2892
- children: "Status"
2893
- }, undefined, false, undefined, this),
2894
- /* @__PURE__ */ jsxDEV5("th", {
2895
- className: "px-4 py-3 text-left font-medium text-sm",
2896
- children: "Expected Close"
2897
- }, undefined, false, undefined, this),
2898
- /* @__PURE__ */ jsxDEV5("th", {
2899
- className: "px-4 py-3 text-left font-medium text-sm",
2900
- children: "Actions"
2901
- }, undefined, false, undefined, this)
2902
- ]
2903
- }, undefined, true, undefined, this)
2904
- }, undefined, false, undefined, this),
2905
- /* @__PURE__ */ jsxDEV5("tbody", {
2906
- className: "divide-y divide-border",
2907
- children: data.deals.map((deal3) => /* @__PURE__ */ jsxDEV5("tr", {
2908
- className: "hover:bg-muted/50",
2909
- children: [
2910
- /* @__PURE__ */ jsxDEV5("td", {
2911
- className: "px-4 py-3",
2912
- children: /* @__PURE__ */ jsxDEV5("div", {
2913
- className: "font-medium",
2914
- children: deal3.name
2915
- }, undefined, false, undefined, this)
2916
- }, undefined, false, undefined, this),
2917
- /* @__PURE__ */ jsxDEV5("td", {
2918
- className: "px-4 py-3 font-mono",
2919
- children: formatCurrency4(deal3.value, deal3.currency)
2920
- }, undefined, false, undefined, this),
2921
- /* @__PURE__ */ jsxDEV5("td", {
2922
- className: "px-4 py-3",
2923
- children: /* @__PURE__ */ jsxDEV5("span", {
2924
- className: `inline-flex rounded-full px-2 py-0.5 font-medium text-xs ${deal3.status === "WON" ? "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400" : deal3.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"}`,
2925
- children: deal3.status
2926
- }, undefined, false, undefined, this)
2927
- }, undefined, false, undefined, this),
2928
- /* @__PURE__ */ jsxDEV5("td", {
2929
- className: "px-4 py-3 text-muted-foreground",
2930
- children: deal3.expectedCloseDate?.toLocaleDateString() ?? "-"
2931
- }, undefined, false, undefined, this),
2932
- /* @__PURE__ */ jsxDEV5("td", {
2933
- className: "px-4 py-3",
2934
- children: /* @__PURE__ */ jsxDEV5(Button3, {
2935
- variant: "ghost",
2936
- size: "sm",
2937
- onPress: () => onDealClick?.(deal3.id),
2938
- children: "Actions"
2939
- }, undefined, false, undefined, this)
2940
- }, undefined, false, undefined, this)
2941
- ]
2942
- }, deal3.id, true, undefined, this))
2943
- }, undefined, false, undefined, this)
2944
- ]
2945
- }, undefined, true, undefined, this)
2946
- }, undefined, false, undefined, this);
2947
- }
2948
3181
  function MetricsTab({
2949
3182
  stats
2950
3183
  }) {
2951
3184
  if (!stats)
2952
3185
  return null;
2953
- return /* @__PURE__ */ jsxDEV5("div", {
3186
+ return /* @__PURE__ */ jsxDEV6("div", {
2954
3187
  className: "space-y-6",
2955
- children: /* @__PURE__ */ jsxDEV5("div", {
3188
+ children: /* @__PURE__ */ jsxDEV6("div", {
2956
3189
  className: "rounded-xl border border-border bg-card p-6",
2957
3190
  children: [
2958
- /* @__PURE__ */ jsxDEV5("h3", {
3191
+ /* @__PURE__ */ jsxDEV6("h3", {
2959
3192
  className: "mb-4 font-semibold text-lg",
2960
3193
  children: "Pipeline Overview"
2961
3194
  }, undefined, false, undefined, this),
2962
- /* @__PURE__ */ jsxDEV5("dl", {
3195
+ /* @__PURE__ */ jsxDEV6("dl", {
2963
3196
  className: "grid gap-4 sm:grid-cols-3",
2964
3197
  children: [
2965
- /* @__PURE__ */ jsxDEV5("div", {
3198
+ /* @__PURE__ */ jsxDEV6("div", {
2966
3199
  children: [
2967
- /* @__PURE__ */ jsxDEV5("dt", {
3200
+ /* @__PURE__ */ jsxDEV6("dt", {
2968
3201
  className: "text-muted-foreground text-sm",
2969
3202
  children: "Win Rate"
2970
3203
  }, undefined, false, undefined, this),
2971
- /* @__PURE__ */ jsxDEV5("dd", {
3204
+ /* @__PURE__ */ jsxDEV6("dd", {
2972
3205
  className: "font-semibold text-2xl",
2973
3206
  children: [
2974
3207
  stats.total > 0 ? (stats.wonCount / stats.total * 100).toFixed(0) : 0,
@@ -2977,25 +3210,25 @@ function MetricsTab({
2977
3210
  }, undefined, true, undefined, this)
2978
3211
  ]
2979
3212
  }, undefined, true, undefined, this),
2980
- /* @__PURE__ */ jsxDEV5("div", {
3213
+ /* @__PURE__ */ jsxDEV6("div", {
2981
3214
  children: [
2982
- /* @__PURE__ */ jsxDEV5("dt", {
3215
+ /* @__PURE__ */ jsxDEV6("dt", {
2983
3216
  className: "text-muted-foreground text-sm",
2984
3217
  children: "Avg Deal Size"
2985
3218
  }, undefined, false, undefined, this),
2986
- /* @__PURE__ */ jsxDEV5("dd", {
3219
+ /* @__PURE__ */ jsxDEV6("dd", {
2987
3220
  className: "font-semibold text-2xl",
2988
- children: formatCurrency4(stats.total > 0 ? stats.totalValue / stats.total : 0)
3221
+ children: formatCurrency5(stats.total > 0 ? stats.totalValue / stats.total : 0)
2989
3222
  }, undefined, false, undefined, this)
2990
3223
  ]
2991
3224
  }, undefined, true, undefined, this),
2992
- /* @__PURE__ */ jsxDEV5("div", {
3225
+ /* @__PURE__ */ jsxDEV6("div", {
2993
3226
  children: [
2994
- /* @__PURE__ */ jsxDEV5("dt", {
3227
+ /* @__PURE__ */ jsxDEV6("dt", {
2995
3228
  className: "text-muted-foreground text-sm",
2996
3229
  children: "Conversion"
2997
3230
  }, undefined, false, undefined, this),
2998
- /* @__PURE__ */ jsxDEV5("dd", {
3231
+ /* @__PURE__ */ jsxDEV6("dd", {
2999
3232
  className: "font-semibold text-2xl",
3000
3233
  children: [
3001
3234
  stats.wonCount,
@@ -3065,7 +3298,7 @@ var crmOverlays = [
3065
3298
  crmSalesRepOverlay
3066
3299
  ];
3067
3300
  // src/ui/renderers/pipeline.markdown.ts
3068
- function formatCurrency5(value, currency = "USD") {
3301
+ function formatCurrency6(value, currency = "USD") {
3069
3302
  return new Intl.NumberFormat("en-US", {
3070
3303
  style: "currency",
3071
3304
  currency,
@@ -3092,7 +3325,7 @@ var crmPipelineMarkdownRenderer = {
3092
3325
  const lines = [
3093
3326
  "# CRM Pipeline",
3094
3327
  "",
3095
- `**Total Value**: ${formatCurrency5(dealsResult.totalValue)}`,
3328
+ `**Total Value**: ${formatCurrency6(dealsResult.totalValue)}`,
3096
3329
  `**Total Deals**: ${dealsResult.total}`,
3097
3330
  ""
3098
3331
  ];
@@ -3100,13 +3333,13 @@ var crmPipelineMarkdownRenderer = {
3100
3333
  const stageDeals = dealsByStage[stage.id] ?? [];
3101
3334
  const stageValue = stageDeals.reduce((sum, d) => sum + d.value, 0);
3102
3335
  lines.push(`## ${stage.name}`);
3103
- lines.push(`_${stageDeals.length} deals · ${formatCurrency5(stageValue)}_`);
3336
+ lines.push(`_${stageDeals.length} deals · ${formatCurrency6(stageValue)}_`);
3104
3337
  lines.push("");
3105
3338
  if (stageDeals.length === 0) {
3106
3339
  lines.push("_No deals_");
3107
3340
  } else {
3108
3341
  for (const deal3 of stageDeals) {
3109
- lines.push(`- **${deal3.name}** - ${formatCurrency5(deal3.value, deal3.currency)}`);
3342
+ lines.push(`- **${deal3.name}** - ${formatCurrency6(deal3.value, deal3.currency)}`);
3110
3343
  }
3111
3344
  }
3112
3345
  lines.push("");
@@ -3146,9 +3379,9 @@ var crmDashboardMarkdownRenderer = {
3146
3379
  "| Metric | Value |",
3147
3380
  "|--------|-------|",
3148
3381
  `| Total Deals | ${dealsResult.total} |`,
3149
- `| Pipeline Value | ${formatCurrency5(dealsResult.totalValue)} |`,
3150
- `| Open Deals | ${openDeals.length} (${formatCurrency5(openValue)}) |`,
3151
- `| Won Deals | ${wonDeals.length} (${formatCurrency5(wonValue)}) |`,
3382
+ `| Pipeline Value | ${formatCurrency6(dealsResult.totalValue)} |`,
3383
+ `| Open Deals | ${openDeals.length} (${formatCurrency6(openValue)}) |`,
3384
+ `| Won Deals | ${wonDeals.length} (${formatCurrency6(wonValue)}) |`,
3152
3385
  `| Lost Deals | ${lostDeals.length} |`,
3153
3386
  "",
3154
3387
  "## Pipeline Stages",
@@ -3159,7 +3392,7 @@ var crmDashboardMarkdownRenderer = {
3159
3392
  for (const stage of stageList.sort((a, b) => a.position - b.position)) {
3160
3393
  const stageDeals = openDeals.filter((d) => d.stageId === stage.id);
3161
3394
  const stageValue = stageDeals.reduce((sum, d) => sum + d.value, 0);
3162
- lines.push(`| ${stage.name} | ${stageDeals.length} | ${formatCurrency5(stageValue)} |`);
3395
+ lines.push(`| ${stage.name} | ${stageDeals.length} | ${formatCurrency6(stageValue)} |`);
3163
3396
  }
3164
3397
  lines.push("");
3165
3398
  lines.push("## Recent Deals");
@@ -3172,7 +3405,7 @@ var crmDashboardMarkdownRenderer = {
3172
3405
  lines.push("|------|-------|-------|--------|");
3173
3406
  for (const deal3 of recentDeals) {
3174
3407
  const stage = stageList.find((s) => s.id === deal3.stageId);
3175
- lines.push(`| ${deal3.name} | ${formatCurrency5(deal3.value, deal3.currency)} | ${stage?.name ?? "-"} | ${deal3.status} |`);
3408
+ lines.push(`| ${deal3.name} | ${formatCurrency6(deal3.value, deal3.currency)} | ${stage?.name ?? "-"} | ${deal3.status} |`);
3176
3409
  }
3177
3410
  }
3178
3411
  return {
@@ -3184,10 +3417,10 @@ var crmDashboardMarkdownRenderer = {
3184
3417
  };
3185
3418
 
3186
3419
  // src/ui/renderers/pipeline.renderer.tsx
3187
- import { jsxDEV as jsxDEV6 } from "react/jsx-dev-runtime";
3420
+ import { jsxDEV as jsxDEV7 } from "react/jsx-dev-runtime";
3188
3421
  function CrmPipelineBoardWrapper() {
3189
3422
  const { dealsByStage, stages } = useDealList();
3190
- return /* @__PURE__ */ jsxDEV6(CrmPipelineBoard, {
3423
+ return /* @__PURE__ */ jsxDEV7(CrmPipelineBoard, {
3191
3424
  dealsByStage,
3192
3425
  stages
3193
3426
  }, undefined, false, undefined, this);
@@ -3201,7 +3434,7 @@ var crmPipelineReactRenderer = {
3201
3434
  if (desc.source.componentKey !== "CrmPipelineView") {
3202
3435
  throw new Error(`Unknown component: ${desc.source.componentKey}`);
3203
3436
  }
3204
- return /* @__PURE__ */ jsxDEV6(CrmPipelineBoardWrapper, {}, undefined, false, undefined, this);
3437
+ return /* @__PURE__ */ jsxDEV7(CrmPipelineBoardWrapper, {}, undefined, false, undefined, this);
3205
3438
  }
3206
3439
  };
3207
3440
  // src/index.ts