@contractspec/example.crm-pipeline 1.57.0 → 1.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (259) hide show
  1. package/.turbo/turbo-build.log +148 -164
  2. package/.turbo/turbo-prebuild.log +1 -0
  3. package/CHANGELOG.md +39 -0
  4. package/dist/browser/crm-pipeline.feature.js +75 -0
  5. package/dist/browser/deal/deal.enum.js +18 -0
  6. package/dist/browser/deal/deal.operation.js +396 -0
  7. package/dist/browser/deal/deal.schema.js +141 -0
  8. package/dist/browser/deal/deal.test-spec.js +58 -0
  9. package/dist/browser/deal/index.js +408 -0
  10. package/dist/browser/docs/crm-pipeline.docblock.js +113 -0
  11. package/dist/browser/docs/index.js +113 -0
  12. package/dist/browser/entities/company.entity.js +52 -0
  13. package/dist/browser/entities/contact.entity.js +66 -0
  14. package/dist/browser/entities/deal.entity.js +107 -0
  15. package/dist/browser/entities/index.js +343 -0
  16. package/dist/browser/entities/task.entity.js +99 -0
  17. package/dist/browser/events/contact.event.js +31 -0
  18. package/dist/browser/events/deal.event.js +101 -0
  19. package/dist/browser/events/index.js +158 -0
  20. package/dist/browser/events/task.event.js +28 -0
  21. package/dist/browser/example.js +39 -0
  22. package/dist/browser/handlers/crm.handlers.js +160 -0
  23. package/dist/browser/handlers/deal.handlers.js +293 -0
  24. package/dist/browser/handlers/index.js +456 -0
  25. package/dist/browser/handlers/mock-data.js +165 -0
  26. package/dist/browser/index.js +3279 -0
  27. package/dist/browser/operations/index.js +407 -0
  28. package/dist/browser/presentations/dashboard.presentation.js +52 -0
  29. package/dist/browser/presentations/index.js +284 -0
  30. package/dist/browser/presentations/pipeline.presentation.js +233 -0
  31. package/dist/browser/seeders/index.js +22 -0
  32. package/dist/browser/shared/overlay-types.js +0 -0
  33. package/dist/browser/ui/CrmDashboard.js +1325 -0
  34. package/dist/browser/ui/CrmDealCard.js +50 -0
  35. package/dist/browser/ui/CrmPipelineBoard.js +160 -0
  36. package/dist/browser/ui/hooks/index.js +186 -0
  37. package/dist/browser/ui/hooks/useDealList.js +84 -0
  38. package/dist/browser/ui/hooks/useDealMutations.js +100 -0
  39. package/dist/browser/ui/index.js +1972 -0
  40. package/dist/browser/ui/modals/CreateDealModal.js +211 -0
  41. package/dist/browser/ui/modals/DealActionsModal.js +428 -0
  42. package/dist/browser/ui/modals/index.js +638 -0
  43. package/dist/browser/ui/overlays/demo-overlays.js +55 -0
  44. package/dist/browser/ui/overlays/index.js +55 -0
  45. package/dist/browser/ui/renderers/index.js +827 -0
  46. package/dist/browser/ui/renderers/pipeline.markdown.js +564 -0
  47. package/dist/browser/ui/renderers/pipeline.renderer.js +264 -0
  48. package/dist/crm-pipeline.feature.d.ts +1 -6
  49. package/dist/crm-pipeline.feature.d.ts.map +1 -1
  50. package/dist/crm-pipeline.feature.js +74 -164
  51. package/dist/deal/deal.enum.d.ts +2 -7
  52. package/dist/deal/deal.enum.d.ts.map +1 -1
  53. package/dist/deal/deal.enum.js +16 -22
  54. package/dist/deal/deal.operation.d.ts +444 -450
  55. package/dist/deal/deal.operation.d.ts.map +1 -1
  56. package/dist/deal/deal.operation.js +390 -263
  57. package/dist/deal/deal.schema.d.ts +251 -256
  58. package/dist/deal/deal.schema.d.ts.map +1 -1
  59. package/dist/deal/deal.schema.js +131 -275
  60. package/dist/deal/deal.test-spec.d.ts +2 -7
  61. package/dist/deal/deal.test-spec.d.ts.map +1 -1
  62. package/dist/deal/deal.test-spec.js +56 -62
  63. package/dist/deal/index.d.ts +7 -4
  64. package/dist/deal/index.d.ts.map +1 -0
  65. package/dist/deal/index.js +408 -4
  66. package/dist/docs/crm-pipeline.docblock.d.ts +2 -1
  67. package/dist/docs/crm-pipeline.docblock.d.ts.map +1 -0
  68. package/dist/docs/crm-pipeline.docblock.js +45 -51
  69. package/dist/docs/index.d.ts +2 -1
  70. package/dist/docs/index.d.ts.map +1 -0
  71. package/dist/docs/index.js +114 -1
  72. package/dist/entities/company.entity.d.ts +27 -32
  73. package/dist/entities/company.entity.d.ts.map +1 -1
  74. package/dist/entities/company.entity.js +51 -61
  75. package/dist/entities/contact.entity.d.ts +31 -36
  76. package/dist/entities/contact.entity.d.ts.map +1 -1
  77. package/dist/entities/contact.entity.js +65 -76
  78. package/dist/entities/deal.entity.d.ts +52 -57
  79. package/dist/entities/deal.entity.d.ts.map +1 -1
  80. package/dist/entities/deal.entity.js +104 -116
  81. package/dist/entities/index.d.ts +6 -10
  82. package/dist/entities/index.d.ts.map +1 -1
  83. package/dist/entities/index.js +342 -31
  84. package/dist/entities/task.entity.d.ts +42 -47
  85. package/dist/entities/task.entity.d.ts.map +1 -1
  86. package/dist/entities/task.entity.js +95 -124
  87. package/dist/events/contact.event.d.ts +21 -27
  88. package/dist/events/contact.event.d.ts.map +1 -1
  89. package/dist/events/contact.event.js +29 -42
  90. package/dist/events/deal.event.d.ts +100 -106
  91. package/dist/events/deal.event.d.ts.map +1 -1
  92. package/dist/events/deal.event.js +93 -163
  93. package/dist/events/index.d.ts +4 -4
  94. package/dist/events/index.d.ts.map +1 -0
  95. package/dist/events/index.js +158 -4
  96. package/dist/events/task.event.d.ts +21 -27
  97. package/dist/events/task.event.d.ts.map +1 -1
  98. package/dist/events/task.event.js +26 -42
  99. package/dist/example.d.ts +2 -6
  100. package/dist/example.d.ts.map +1 -1
  101. package/dist/example.js +38 -50
  102. package/dist/handlers/crm.handlers.d.ts +80 -78
  103. package/dist/handlers/crm.handlers.d.ts.map +1 -1
  104. package/dist/handlers/crm.handlers.js +155 -166
  105. package/dist/handlers/deal.handlers.d.ts +58 -63
  106. package/dist/handlers/deal.handlers.d.ts.map +1 -1
  107. package/dist/handlers/deal.handlers.js +279 -105
  108. package/dist/handlers/index.d.ts +10 -4
  109. package/dist/handlers/index.d.ts.map +1 -0
  110. package/dist/handlers/index.js +456 -4
  111. package/dist/handlers/mock-data.d.ts +38 -41
  112. package/dist/handlers/mock-data.d.ts.map +1 -1
  113. package/dist/handlers/mock-data.js +162 -184
  114. package/dist/index.d.ts +13 -42
  115. package/dist/index.d.ts.map +1 -1
  116. package/dist/index.js +3277 -53
  117. package/dist/node/crm-pipeline.feature.js +75 -0
  118. package/dist/node/deal/deal.enum.js +18 -0
  119. package/dist/node/deal/deal.operation.js +396 -0
  120. package/dist/node/deal/deal.schema.js +141 -0
  121. package/dist/node/deal/deal.test-spec.js +58 -0
  122. package/dist/node/deal/index.js +408 -0
  123. package/dist/node/docs/crm-pipeline.docblock.js +113 -0
  124. package/dist/node/docs/index.js +113 -0
  125. package/dist/node/entities/company.entity.js +52 -0
  126. package/dist/node/entities/contact.entity.js +66 -0
  127. package/dist/node/entities/deal.entity.js +107 -0
  128. package/dist/node/entities/index.js +343 -0
  129. package/dist/node/entities/task.entity.js +99 -0
  130. package/dist/node/events/contact.event.js +31 -0
  131. package/dist/node/events/deal.event.js +101 -0
  132. package/dist/node/events/index.js +158 -0
  133. package/dist/node/events/task.event.js +28 -0
  134. package/dist/node/example.js +39 -0
  135. package/dist/node/handlers/crm.handlers.js +160 -0
  136. package/dist/node/handlers/deal.handlers.js +293 -0
  137. package/dist/node/handlers/index.js +456 -0
  138. package/dist/node/handlers/mock-data.js +165 -0
  139. package/dist/node/index.js +3279 -0
  140. package/dist/node/operations/index.js +407 -0
  141. package/dist/node/presentations/dashboard.presentation.js +52 -0
  142. package/dist/node/presentations/index.js +284 -0
  143. package/dist/node/presentations/pipeline.presentation.js +233 -0
  144. package/dist/node/seeders/index.js +22 -0
  145. package/dist/node/shared/overlay-types.js +0 -0
  146. package/dist/node/ui/CrmDashboard.js +1325 -0
  147. package/dist/node/ui/CrmDealCard.js +50 -0
  148. package/dist/node/ui/CrmPipelineBoard.js +160 -0
  149. package/dist/node/ui/hooks/index.js +186 -0
  150. package/dist/node/ui/hooks/useDealList.js +84 -0
  151. package/dist/node/ui/hooks/useDealMutations.js +100 -0
  152. package/dist/node/ui/index.js +1972 -0
  153. package/dist/node/ui/modals/CreateDealModal.js +211 -0
  154. package/dist/node/ui/modals/DealActionsModal.js +428 -0
  155. package/dist/node/ui/modals/index.js +638 -0
  156. package/dist/node/ui/overlays/demo-overlays.js +55 -0
  157. package/dist/node/ui/overlays/index.js +55 -0
  158. package/dist/node/ui/renderers/index.js +827 -0
  159. package/dist/node/ui/renderers/pipeline.markdown.js +564 -0
  160. package/dist/node/ui/renderers/pipeline.renderer.js +264 -0
  161. package/dist/operations/index.d.ts +2 -5
  162. package/dist/operations/index.d.ts.map +1 -0
  163. package/dist/operations/index.js +407 -5
  164. package/dist/presentations/dashboard.presentation.d.ts +2 -7
  165. package/dist/presentations/dashboard.presentation.d.ts.map +1 -1
  166. package/dist/presentations/dashboard.presentation.js +51 -60
  167. package/dist/presentations/index.d.ts +3 -3
  168. package/dist/presentations/index.d.ts.map +1 -0
  169. package/dist/presentations/index.js +284 -3
  170. package/dist/presentations/pipeline.presentation.d.ts +4 -9
  171. package/dist/presentations/pipeline.presentation.d.ts.map +1 -1
  172. package/dist/presentations/pipeline.presentation.js +228 -116
  173. package/dist/seeders/index.d.ts +4 -8
  174. package/dist/seeders/index.d.ts.map +1 -1
  175. package/dist/seeders/index.js +21 -45
  176. package/dist/shared/overlay-types.d.ts +25 -28
  177. package/dist/shared/overlay-types.d.ts.map +1 -1
  178. package/dist/shared/overlay-types.js +1 -0
  179. package/dist/ui/CrmDashboard.d.ts +1 -6
  180. package/dist/ui/CrmDashboard.d.ts.map +1 -1
  181. package/dist/ui/CrmDashboard.js +1318 -296
  182. package/dist/ui/CrmDealCard.d.ts +8 -12
  183. package/dist/ui/CrmDealCard.d.ts.map +1 -1
  184. package/dist/ui/CrmDealCard.js +47 -45
  185. package/dist/ui/CrmPipelineBoard.d.ts +11 -20
  186. package/dist/ui/CrmPipelineBoard.d.ts.map +1 -1
  187. package/dist/ui/CrmPipelineBoard.js +157 -94
  188. package/dist/ui/hooks/index.d.ts +3 -3
  189. package/dist/ui/hooks/index.d.ts.map +1 -0
  190. package/dist/ui/hooks/index.js +185 -4
  191. package/dist/ui/hooks/useDealList.d.ts +28 -32
  192. package/dist/ui/hooks/useDealList.d.ts.map +1 -1
  193. package/dist/ui/hooks/useDealList.js +81 -90
  194. package/dist/ui/hooks/useDealMutations.d.ts +18 -22
  195. package/dist/ui/hooks/useDealMutations.d.ts.map +1 -1
  196. package/dist/ui/hooks/useDealMutations.js +97 -155
  197. package/dist/ui/index.d.ts +8 -14
  198. package/dist/ui/index.d.ts.map +1 -0
  199. package/dist/ui/index.js +1973 -15
  200. package/dist/ui/modals/CreateDealModal.d.ts +19 -29
  201. package/dist/ui/modals/CreateDealModal.d.ts.map +1 -1
  202. package/dist/ui/modals/CreateDealModal.js +209 -180
  203. package/dist/ui/modals/DealActionsModal.d.ts +31 -44
  204. package/dist/ui/modals/DealActionsModal.d.ts.map +1 -1
  205. package/dist/ui/modals/DealActionsModal.js +424 -367
  206. package/dist/ui/modals/index.d.ts +3 -3
  207. package/dist/ui/modals/index.d.ts.map +1 -0
  208. package/dist/ui/modals/index.js +638 -3
  209. package/dist/ui/overlays/demo-overlays.d.ts +10 -8
  210. package/dist/ui/overlays/demo-overlays.d.ts.map +1 -1
  211. package/dist/ui/overlays/demo-overlays.js +54 -66
  212. package/dist/ui/overlays/index.d.ts +2 -2
  213. package/dist/ui/overlays/index.d.ts.map +1 -0
  214. package/dist/ui/overlays/index.js +56 -3
  215. package/dist/ui/renderers/index.d.ts +3 -3
  216. package/dist/ui/renderers/index.d.ts.map +1 -0
  217. package/dist/ui/renderers/index.js +827 -3
  218. package/dist/ui/renderers/pipeline.markdown.d.ts +12 -11
  219. package/dist/ui/renderers/pipeline.markdown.d.ts.map +1 -1
  220. package/dist/ui/renderers/pipeline.markdown.js +560 -114
  221. package/dist/ui/renderers/pipeline.renderer.d.ts +9 -7
  222. package/dist/ui/renderers/pipeline.renderer.d.ts.map +1 -1
  223. package/dist/ui/renderers/pipeline.renderer.js +261 -24
  224. package/package.json +476 -90
  225. package/tsdown.config.js +1 -2
  226. package/.turbo/turbo-build$colon$bundle.log +0 -164
  227. package/dist/crm-pipeline.feature.js.map +0 -1
  228. package/dist/deal/deal.enum.js.map +0 -1
  229. package/dist/deal/deal.operation.js.map +0 -1
  230. package/dist/deal/deal.schema.js.map +0 -1
  231. package/dist/deal/deal.test-spec.js.map +0 -1
  232. package/dist/docs/crm-pipeline.docblock.js.map +0 -1
  233. package/dist/entities/company.entity.js.map +0 -1
  234. package/dist/entities/contact.entity.js.map +0 -1
  235. package/dist/entities/deal.entity.js.map +0 -1
  236. package/dist/entities/index.js.map +0 -1
  237. package/dist/entities/task.entity.js.map +0 -1
  238. package/dist/events/contact.event.js.map +0 -1
  239. package/dist/events/deal.event.js.map +0 -1
  240. package/dist/events/task.event.js.map +0 -1
  241. package/dist/example.js.map +0 -1
  242. package/dist/handlers/crm.handlers.js.map +0 -1
  243. package/dist/handlers/deal.handlers.js.map +0 -1
  244. package/dist/handlers/mock-data.js.map +0 -1
  245. package/dist/index.js.map +0 -1
  246. package/dist/presentations/dashboard.presentation.js.map +0 -1
  247. package/dist/presentations/pipeline.presentation.js.map +0 -1
  248. package/dist/seeders/index.js.map +0 -1
  249. package/dist/ui/CrmDashboard.js.map +0 -1
  250. package/dist/ui/CrmDealCard.js.map +0 -1
  251. package/dist/ui/CrmPipelineBoard.js.map +0 -1
  252. package/dist/ui/hooks/useDealList.js.map +0 -1
  253. package/dist/ui/hooks/useDealMutations.js.map +0 -1
  254. package/dist/ui/modals/CreateDealModal.js.map +0 -1
  255. package/dist/ui/modals/DealActionsModal.js.map +0 -1
  256. package/dist/ui/overlays/demo-overlays.js.map +0 -1
  257. package/dist/ui/renderers/pipeline.markdown.js.map +0 -1
  258. package/dist/ui/renderers/pipeline.renderer.js.map +0 -1
  259. package/tsconfig.tsbuildinfo +0 -1
@@ -1,8 +1,10 @@
1
- import { PresentationRenderer } from "@contractspec/lib.contracts";
2
- import * as React from "react";
3
-
4
- //#region src/ui/renderers/pipeline.renderer.d.ts
5
- declare const crmPipelineReactRenderer: PresentationRenderer<React.ReactElement>;
6
- //#endregion
7
- export { crmPipelineReactRenderer };
1
+ /**
2
+ * React renderer for CRM Pipeline presentation
3
+ *
4
+ * Renders the CRM pipeline board component.
5
+ * Data is fetched via the CrmPipelineBoard component's internal hooks.
6
+ */
7
+ import * as React from 'react';
8
+ import type { PresentationRenderer } from '@contractspec/lib.contracts';
9
+ export declare const crmPipelineReactRenderer: PresentationRenderer<React.ReactElement>;
8
10
  //# sourceMappingURL=pipeline.renderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.renderer.d.ts","names":[],"sources":["../../../src/ui/renderers/pipeline.renderer.tsx"],"mappings":";;;;cAmBa,wBAAA,EAA0B,oBAAA,CAAqB,KAAA,CAAM,YAAA"}
1
+ {"version":3,"file":"pipeline.renderer.d.ts","sourceRoot":"","sources":["../../../src/ui/renderers/pipeline.renderer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAYxE,eAAO,MAAM,wBAAwB,EAAE,oBAAoB,CAAC,KAAK,CAAC,YAAY,CAe3E,CAAC"}
@@ -1,28 +1,265 @@
1
- import { useDealList } from "../hooks/useDealList.js";
2
- import { CrmPipelineBoard } from "../CrmPipelineBoard.js";
3
- import "react";
4
- import { jsx } from "react/jsx-runtime";
1
+ // @bun
2
+ // src/ui/hooks/useDealList.ts
3
+ import { useCallback, useEffect, useMemo, useState } from "react";
4
+ import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
5
+ "use client";
6
+ function useDealList(options = {}) {
7
+ const { handlers, projectId } = useTemplateRuntime();
8
+ const { crm } = handlers;
9
+ const [data, setData] = useState(null);
10
+ const [dealsByStage, setDealsByStage] = useState({});
11
+ const [stages, setStages] = useState([]);
12
+ const [loading, setLoading] = useState(true);
13
+ const [error, setError] = useState(null);
14
+ const [page, setPage] = useState(1);
15
+ const pipelineId = options.pipelineId ?? "pipeline-1";
16
+ const fetchData = useCallback(async () => {
17
+ setLoading(true);
18
+ setError(null);
19
+ try {
20
+ const [dealsResult, stageDealsResult, stagesResult] = await Promise.all([
21
+ crm.listDeals({
22
+ projectId,
23
+ pipelineId,
24
+ stageId: options.stageId,
25
+ status: options.status === "all" ? undefined : options.status,
26
+ search: options.search,
27
+ limit: options.limit ?? 50,
28
+ offset: (page - 1) * (options.limit ?? 50)
29
+ }),
30
+ crm.getDealsByStage({ projectId, pipelineId }),
31
+ crm.getPipelineStages({ pipelineId })
32
+ ]);
33
+ setData(dealsResult);
34
+ setDealsByStage(stageDealsResult);
35
+ setStages(stagesResult);
36
+ } catch (err) {
37
+ setError(err instanceof Error ? err : new Error("Unknown error"));
38
+ } finally {
39
+ setLoading(false);
40
+ }
41
+ }, [
42
+ crm,
43
+ projectId,
44
+ pipelineId,
45
+ options.stageId,
46
+ options.status,
47
+ options.search,
48
+ options.limit,
49
+ page
50
+ ]);
51
+ useEffect(() => {
52
+ fetchData();
53
+ }, [fetchData]);
54
+ const stats = useMemo(() => {
55
+ if (!data)
56
+ return null;
57
+ const open = data.deals.filter((d) => d.status === "OPEN");
58
+ const won = data.deals.filter((d) => d.status === "WON");
59
+ const lost = data.deals.filter((d) => d.status === "LOST");
60
+ return {
61
+ total: data.total,
62
+ totalValue: data.totalValue,
63
+ openCount: open.length,
64
+ openValue: open.reduce((sum, d) => sum + d.value, 0),
65
+ wonCount: won.length,
66
+ wonValue: won.reduce((sum, d) => sum + d.value, 0),
67
+ lostCount: lost.length
68
+ };
69
+ }, [data]);
70
+ return {
71
+ data,
72
+ dealsByStage,
73
+ stages,
74
+ loading,
75
+ error,
76
+ stats,
77
+ page,
78
+ refetch: fetchData,
79
+ nextPage: () => setPage((p) => p + 1),
80
+ prevPage: () => page > 1 && setPage((p) => p - 1)
81
+ };
82
+ }
5
83
 
6
- //#region src/ui/renderers/pipeline.renderer.tsx
7
- /**
8
- * Wrapper component that provides data to CrmPipelineBoard
9
- */
84
+ // src/ui/CrmDealCard.tsx
85
+ import { jsxDEV } from "react/jsx-dev-runtime";
86
+ "use client";
87
+ function formatCurrency(value, currency) {
88
+ return new Intl.NumberFormat("en-US", {
89
+ style: "currency",
90
+ currency,
91
+ minimumFractionDigits: 0,
92
+ maximumFractionDigits: 0
93
+ }).format(value);
94
+ }
95
+ function CrmDealCard({ deal, onClick }) {
96
+ const daysUntilClose = deal.expectedCloseDate ? Math.ceil((deal.expectedCloseDate.getTime() - Date.now()) / (1000 * 60 * 60 * 24)) : null;
97
+ return /* @__PURE__ */ jsxDEV("div", {
98
+ onClick,
99
+ className: "border-border bg-card cursor-pointer rounded-lg border p-3 shadow-sm transition-shadow hover:shadow-md",
100
+ role: "button",
101
+ tabIndex: 0,
102
+ onKeyDown: (e) => {
103
+ if (e.key === "Enter" || e.key === " ")
104
+ onClick?.();
105
+ },
106
+ children: [
107
+ /* @__PURE__ */ jsxDEV("h4", {
108
+ className: "leading-snug font-medium",
109
+ children: deal.name
110
+ }, undefined, false, undefined, this),
111
+ /* @__PURE__ */ jsxDEV("div", {
112
+ className: "text-primary mt-2 text-lg font-semibold",
113
+ children: formatCurrency(deal.value, deal.currency)
114
+ }, undefined, false, undefined, this),
115
+ /* @__PURE__ */ jsxDEV("div", {
116
+ className: "text-muted-foreground mt-3 flex items-center justify-between text-xs",
117
+ children: [
118
+ daysUntilClose !== null && /* @__PURE__ */ jsxDEV("span", {
119
+ className: daysUntilClose < 0 ? "text-red-500" : daysUntilClose <= 7 ? "text-yellow-600 dark:text-yellow-500" : "",
120
+ children: daysUntilClose < 0 ? `${Math.abs(daysUntilClose)}d overdue` : daysUntilClose === 0 ? "Due today" : `${daysUntilClose}d left`
121
+ }, undefined, false, undefined, this),
122
+ /* @__PURE__ */ jsxDEV("span", {
123
+ className: `rounded px-1.5 py-0.5 text-xs font-medium ${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"}`,
124
+ children: deal.status
125
+ }, undefined, false, undefined, this)
126
+ ]
127
+ }, undefined, true, undefined, this)
128
+ ]
129
+ }, undefined, true, undefined, this);
130
+ }
131
+
132
+ // src/ui/CrmPipelineBoard.tsx
133
+ import { useState as useState2 } from "react";
134
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
135
+ "use client";
136
+ function formatCurrency2(value) {
137
+ if (value >= 1e6)
138
+ return `$${(value / 1e6).toFixed(1)}M`;
139
+ if (value >= 1000)
140
+ return `$${(value / 1000).toFixed(0)}K`;
141
+ return `$${value}`;
142
+ }
143
+ function CrmPipelineBoard({
144
+ dealsByStage,
145
+ stages,
146
+ onDealClick,
147
+ onDealMove
148
+ }) {
149
+ const [quickMoveOpen, setQuickMoveOpen] = useState2(null);
150
+ const sortedStages = [...stages].sort((a, b) => a.position - b.position);
151
+ const handleQuickMove = (dealId, toStageId) => {
152
+ onDealMove?.(dealId, toStageId);
153
+ setQuickMoveOpen(null);
154
+ };
155
+ return /* @__PURE__ */ jsxDEV2("div", {
156
+ className: "flex gap-4 overflow-x-auto pb-4",
157
+ children: sortedStages.map((stage) => {
158
+ const deals = dealsByStage[stage.id] ?? [];
159
+ const stageValue = deals.reduce((sum, d) => sum + d.value, 0);
160
+ return /* @__PURE__ */ jsxDEV2("div", {
161
+ className: "bg-muted/30 flex w-72 flex-shrink-0 flex-col rounded-lg",
162
+ children: [
163
+ /* @__PURE__ */ jsxDEV2("div", {
164
+ className: "border-border flex items-center justify-between border-b px-3 py-2",
165
+ children: [
166
+ /* @__PURE__ */ jsxDEV2("div", {
167
+ children: [
168
+ /* @__PURE__ */ jsxDEV2("h3", {
169
+ className: "font-medium",
170
+ children: stage.name
171
+ }, undefined, false, undefined, this),
172
+ /* @__PURE__ */ jsxDEV2("p", {
173
+ className: "text-muted-foreground text-xs",
174
+ children: [
175
+ deals.length,
176
+ " deals \xB7 ",
177
+ formatCurrency2(stageValue)
178
+ ]
179
+ }, undefined, true, undefined, this)
180
+ ]
181
+ }, undefined, true, undefined, this),
182
+ /* @__PURE__ */ jsxDEV2("span", {
183
+ className: "bg-muted flex h-6 w-6 items-center justify-center rounded-full text-xs font-medium",
184
+ children: deals.length
185
+ }, undefined, false, undefined, this)
186
+ ]
187
+ }, undefined, true, undefined, this),
188
+ /* @__PURE__ */ jsxDEV2("div", {
189
+ className: "flex flex-1 flex-col gap-2 p-2",
190
+ children: deals.length === 0 ? /* @__PURE__ */ jsxDEV2("div", {
191
+ className: "border-muted-foreground/20 text-muted-foreground flex h-24 items-center justify-center rounded-md border-2 border-dashed text-xs",
192
+ children: "No deals"
193
+ }, undefined, false, undefined, this) : deals.map((deal) => /* @__PURE__ */ jsxDEV2("div", {
194
+ className: "group relative",
195
+ children: [
196
+ /* @__PURE__ */ jsxDEV2(CrmDealCard, {
197
+ deal,
198
+ onClick: () => onDealClick?.(deal.id)
199
+ }, undefined, false, undefined, this),
200
+ deal.status === "OPEN" && onDealMove && /* @__PURE__ */ jsxDEV2("div", {
201
+ className: "absolute top-1 right-1 opacity-0 transition-opacity group-hover:opacity-100",
202
+ children: [
203
+ /* @__PURE__ */ jsxDEV2("button", {
204
+ type: "button",
205
+ onClick: (e) => {
206
+ e.stopPropagation();
207
+ setQuickMoveOpen(quickMoveOpen === deal.id ? null : deal.id);
208
+ },
209
+ className: "bg-background border-border hover:bg-muted flex h-6 w-6 items-center justify-center rounded border text-xs shadow-sm",
210
+ title: "Quick move",
211
+ children: "\u27A1\uFE0F"
212
+ }, undefined, false, undefined, this),
213
+ quickMoveOpen === deal.id && /* @__PURE__ */ jsxDEV2("div", {
214
+ className: "bg-card border-border absolute top-7 right-0 z-20 min-w-[140px] rounded-lg border py-1 shadow-lg",
215
+ children: [
216
+ /* @__PURE__ */ jsxDEV2("p", {
217
+ className: "text-muted-foreground px-3 py-1 text-xs font-medium",
218
+ children: "Move to:"
219
+ }, undefined, false, undefined, this),
220
+ sortedStages.filter((s) => s.id !== deal.stageId).map((s) => /* @__PURE__ */ jsxDEV2("button", {
221
+ type: "button",
222
+ onClick: (e) => {
223
+ e.stopPropagation();
224
+ handleQuickMove(deal.id, s.id);
225
+ },
226
+ className: "hover:bg-muted w-full px-3 py-1.5 text-left text-sm",
227
+ children: s.name
228
+ }, s.id, false, undefined, this))
229
+ ]
230
+ }, undefined, true, undefined, this)
231
+ ]
232
+ }, undefined, true, undefined, this)
233
+ ]
234
+ }, deal.id, true, undefined, this))
235
+ }, undefined, false, undefined, this)
236
+ ]
237
+ }, stage.id, true, undefined, this);
238
+ })
239
+ }, undefined, false, undefined, this);
240
+ }
241
+
242
+ // src/ui/renderers/pipeline.renderer.tsx
243
+ import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
10
244
  function CrmPipelineBoardWrapper() {
11
- const { dealsByStage, stages } = useDealList();
12
- return /* @__PURE__ */ jsx(CrmPipelineBoard, {
13
- dealsByStage,
14
- stages
15
- });
245
+ const { dealsByStage, stages } = useDealList();
246
+ return /* @__PURE__ */ jsxDEV3(CrmPipelineBoard, {
247
+ dealsByStage,
248
+ stages
249
+ }, undefined, false, undefined, this);
16
250
  }
17
- const crmPipelineReactRenderer = {
18
- target: "react",
19
- render: async (desc, _ctx) => {
20
- if (desc.source.type !== "component") throw new Error("Invalid source type");
21
- if (desc.source.componentKey !== "CrmPipelineView") throw new Error(`Unknown component: ${desc.source.componentKey}`);
22
- return /* @__PURE__ */ jsx(CrmPipelineBoardWrapper, {});
23
- }
251
+ var crmPipelineReactRenderer = {
252
+ target: "react",
253
+ render: async (desc, _ctx) => {
254
+ if (desc.source.type !== "component") {
255
+ throw new Error("Invalid source type");
256
+ }
257
+ if (desc.source.componentKey !== "CrmPipelineView") {
258
+ throw new Error(`Unknown component: ${desc.source.componentKey}`);
259
+ }
260
+ return /* @__PURE__ */ jsxDEV3(CrmPipelineBoardWrapper, {}, undefined, false, undefined, this);
261
+ }
262
+ };
263
+ export {
264
+ crmPipelineReactRenderer
24
265
  };
25
-
26
- //#endregion
27
- export { crmPipelineReactRenderer };
28
- //# sourceMappingURL=pipeline.renderer.js.map