@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
@@ -0,0 +1,638 @@
1
+ // src/ui/modals/CreateDealModal.tsx
2
+ import { useState } from "react";
3
+ import { Button, Input } from "@contractspec/lib.design-system";
4
+ import { jsxDEV } from "react/jsx-dev-runtime";
5
+ "use client";
6
+ var CURRENCIES = ["USD", "EUR", "GBP", "CAD"];
7
+ var DEFAULT_PIPELINE_ID = "pipeline-1";
8
+ function CreateDealModal({
9
+ isOpen,
10
+ onClose,
11
+ onSubmit,
12
+ stages,
13
+ isLoading = false
14
+ }) {
15
+ const [name, setName] = useState("");
16
+ const [value, setValue] = useState("");
17
+ const [currency, setCurrency] = useState("USD");
18
+ const [stageId, setStageId] = useState(stages[0]?.id ?? "");
19
+ const [expectedCloseDate, setExpectedCloseDate] = useState("");
20
+ const [error, setError] = useState(null);
21
+ const handleSubmit = async (e) => {
22
+ e.preventDefault();
23
+ setError(null);
24
+ if (!name.trim()) {
25
+ setError("Deal name is required");
26
+ return;
27
+ }
28
+ const numericValue = parseFloat(value);
29
+ if (isNaN(numericValue) || numericValue <= 0) {
30
+ setError("Value must be a positive number");
31
+ return;
32
+ }
33
+ if (!stageId) {
34
+ setError("Please select a pipeline stage");
35
+ return;
36
+ }
37
+ try {
38
+ await onSubmit({
39
+ name: name.trim(),
40
+ value: numericValue,
41
+ currency,
42
+ pipelineId: DEFAULT_PIPELINE_ID,
43
+ stageId,
44
+ expectedCloseDate: expectedCloseDate ? new Date(expectedCloseDate) : undefined
45
+ });
46
+ setName("");
47
+ setValue("");
48
+ setCurrency("USD");
49
+ setStageId(stages[0]?.id ?? "");
50
+ setExpectedCloseDate("");
51
+ onClose();
52
+ } catch (err) {
53
+ setError(err instanceof Error ? err.message : "Failed to create deal");
54
+ }
55
+ };
56
+ if (!isOpen)
57
+ return null;
58
+ return /* @__PURE__ */ jsxDEV("div", {
59
+ className: "fixed inset-0 z-50 flex items-center justify-center",
60
+ children: [
61
+ /* @__PURE__ */ jsxDEV("div", {
62
+ className: "bg-background/80 absolute inset-0 backdrop-blur-sm",
63
+ onClick: onClose,
64
+ role: "button",
65
+ tabIndex: 0,
66
+ onKeyDown: (e) => {
67
+ if (e.key === "Enter" || e.key === " ")
68
+ onClose();
69
+ },
70
+ "aria-label": "Close modal"
71
+ }, undefined, false, undefined, this),
72
+ /* @__PURE__ */ jsxDEV("div", {
73
+ className: "bg-card border-border relative z-10 w-full max-w-md rounded-xl border p-6 shadow-xl",
74
+ children: [
75
+ /* @__PURE__ */ jsxDEV("h2", {
76
+ className: "mb-4 text-xl font-semibold",
77
+ children: "Create New Deal"
78
+ }, undefined, false, undefined, this),
79
+ /* @__PURE__ */ jsxDEV("form", {
80
+ onSubmit: handleSubmit,
81
+ className: "space-y-4",
82
+ children: [
83
+ /* @__PURE__ */ jsxDEV("div", {
84
+ children: [
85
+ /* @__PURE__ */ jsxDEV("label", {
86
+ htmlFor: "deal-name",
87
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
88
+ children: "Deal Name *"
89
+ }, undefined, false, undefined, this),
90
+ /* @__PURE__ */ jsxDEV(Input, {
91
+ id: "deal-name",
92
+ value: name,
93
+ onChange: (e) => setName(e.target.value),
94
+ placeholder: "e.g., Enterprise License - Acme Corp",
95
+ disabled: isLoading
96
+ }, undefined, false, undefined, this)
97
+ ]
98
+ }, undefined, true, undefined, this),
99
+ /* @__PURE__ */ jsxDEV("div", {
100
+ className: "flex gap-3",
101
+ children: [
102
+ /* @__PURE__ */ jsxDEV("div", {
103
+ className: "flex-1",
104
+ children: [
105
+ /* @__PURE__ */ jsxDEV("label", {
106
+ htmlFor: "deal-value",
107
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
108
+ children: "Value *"
109
+ }, undefined, false, undefined, this),
110
+ /* @__PURE__ */ jsxDEV(Input, {
111
+ id: "deal-value",
112
+ type: "number",
113
+ min: "0",
114
+ step: "0.01",
115
+ value,
116
+ onChange: (e) => setValue(e.target.value),
117
+ placeholder: "50000",
118
+ disabled: isLoading
119
+ }, undefined, false, undefined, this)
120
+ ]
121
+ }, undefined, true, undefined, this),
122
+ /* @__PURE__ */ jsxDEV("div", {
123
+ className: "w-24",
124
+ children: [
125
+ /* @__PURE__ */ jsxDEV("label", {
126
+ htmlFor: "deal-currency",
127
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
128
+ children: "Currency"
129
+ }, undefined, false, undefined, this),
130
+ /* @__PURE__ */ jsxDEV("select", {
131
+ id: "deal-currency",
132
+ value: currency,
133
+ onChange: (e) => setCurrency(e.target.value),
134
+ disabled: isLoading,
135
+ className: "border-input bg-background focus:ring-ring h-10 w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none disabled:opacity-50",
136
+ children: CURRENCIES.map((c) => /* @__PURE__ */ jsxDEV("option", {
137
+ value: c,
138
+ children: c
139
+ }, c, false, undefined, this))
140
+ }, undefined, false, undefined, this)
141
+ ]
142
+ }, undefined, true, undefined, this)
143
+ ]
144
+ }, undefined, true, undefined, this),
145
+ /* @__PURE__ */ jsxDEV("div", {
146
+ children: [
147
+ /* @__PURE__ */ jsxDEV("label", {
148
+ htmlFor: "deal-stage",
149
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
150
+ children: "Pipeline Stage *"
151
+ }, undefined, false, undefined, this),
152
+ /* @__PURE__ */ jsxDEV("select", {
153
+ id: "deal-stage",
154
+ value: stageId,
155
+ onChange: (e) => setStageId(e.target.value),
156
+ disabled: isLoading,
157
+ className: "border-input bg-background focus:ring-ring h-10 w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none disabled:opacity-50",
158
+ children: stages.map((stage) => /* @__PURE__ */ jsxDEV("option", {
159
+ value: stage.id,
160
+ children: stage.name
161
+ }, stage.id, false, undefined, this))
162
+ }, undefined, false, undefined, this)
163
+ ]
164
+ }, undefined, true, undefined, this),
165
+ /* @__PURE__ */ jsxDEV("div", {
166
+ children: [
167
+ /* @__PURE__ */ jsxDEV("label", {
168
+ htmlFor: "deal-close-date",
169
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
170
+ children: "Expected Close Date"
171
+ }, undefined, false, undefined, this),
172
+ /* @__PURE__ */ jsxDEV(Input, {
173
+ id: "deal-close-date",
174
+ type: "date",
175
+ value: expectedCloseDate,
176
+ onChange: (e) => setExpectedCloseDate(e.target.value),
177
+ disabled: isLoading
178
+ }, undefined, false, undefined, this)
179
+ ]
180
+ }, undefined, true, undefined, this),
181
+ error && /* @__PURE__ */ jsxDEV("div", {
182
+ className: "bg-destructive/10 text-destructive rounded-md p-3 text-sm",
183
+ children: error
184
+ }, undefined, false, undefined, this),
185
+ /* @__PURE__ */ jsxDEV("div", {
186
+ className: "flex justify-end gap-3 pt-2",
187
+ children: [
188
+ /* @__PURE__ */ jsxDEV(Button, {
189
+ type: "button",
190
+ variant: "ghost",
191
+ onPress: onClose,
192
+ disabled: isLoading,
193
+ children: "Cancel"
194
+ }, undefined, false, undefined, this),
195
+ /* @__PURE__ */ jsxDEV(Button, {
196
+ type: "submit",
197
+ disabled: isLoading,
198
+ children: isLoading ? "Creating..." : "Create Deal"
199
+ }, undefined, false, undefined, this)
200
+ ]
201
+ }, undefined, true, undefined, this)
202
+ ]
203
+ }, undefined, true, undefined, this)
204
+ ]
205
+ }, undefined, true, undefined, this)
206
+ ]
207
+ }, undefined, true, undefined, this);
208
+ }
209
+
210
+ // src/ui/modals/DealActionsModal.tsx
211
+ import { useState as useState2 } from "react";
212
+ import { Button as Button2 } from "@contractspec/lib.design-system";
213
+ import { jsxDEV as jsxDEV2, Fragment } from "react/jsx-dev-runtime";
214
+ "use client";
215
+ function formatCurrency(value, currency) {
216
+ return new Intl.NumberFormat("en-US", {
217
+ style: "currency",
218
+ currency,
219
+ minimumFractionDigits: 0,
220
+ maximumFractionDigits: 0
221
+ }).format(value);
222
+ }
223
+ function DealActionsModal({
224
+ isOpen,
225
+ deal,
226
+ stages,
227
+ onClose,
228
+ onWin,
229
+ onLose,
230
+ onMove,
231
+ isLoading = false
232
+ }) {
233
+ const [mode, setMode] = useState2("menu");
234
+ const [wonSource, setWonSource] = useState2("");
235
+ const [lostReason, setLostReason] = useState2("");
236
+ const [notes, setNotes] = useState2("");
237
+ const [selectedStageId, setSelectedStageId] = useState2("");
238
+ const [error, setError] = useState2(null);
239
+ const resetForm = () => {
240
+ setMode("menu");
241
+ setWonSource("");
242
+ setLostReason("");
243
+ setNotes("");
244
+ setSelectedStageId("");
245
+ setError(null);
246
+ };
247
+ const handleClose = () => {
248
+ resetForm();
249
+ onClose();
250
+ };
251
+ const handleWin = async () => {
252
+ if (!deal)
253
+ return;
254
+ setError(null);
255
+ try {
256
+ await onWin({
257
+ dealId: deal.id,
258
+ wonSource: wonSource.trim() || undefined,
259
+ notes: notes.trim() || undefined
260
+ });
261
+ handleClose();
262
+ } catch (err) {
263
+ setError(err instanceof Error ? err.message : "Failed to mark deal as won");
264
+ }
265
+ };
266
+ const handleLose = async () => {
267
+ if (!deal)
268
+ return;
269
+ setError(null);
270
+ if (!lostReason.trim()) {
271
+ setError("Please provide a reason for losing the deal");
272
+ return;
273
+ }
274
+ try {
275
+ await onLose({
276
+ dealId: deal.id,
277
+ lostReason: lostReason.trim(),
278
+ notes: notes.trim() || undefined
279
+ });
280
+ handleClose();
281
+ } catch (err) {
282
+ setError(err instanceof Error ? err.message : "Failed to mark deal as lost");
283
+ }
284
+ };
285
+ const handleMove = async () => {
286
+ if (!deal)
287
+ return;
288
+ setError(null);
289
+ if (!selectedStageId) {
290
+ setError("Please select a stage");
291
+ return;
292
+ }
293
+ if (selectedStageId === deal.stageId) {
294
+ setError("Deal is already in this stage");
295
+ return;
296
+ }
297
+ try {
298
+ await onMove({
299
+ dealId: deal.id,
300
+ stageId: selectedStageId
301
+ });
302
+ handleClose();
303
+ } catch (err) {
304
+ setError(err instanceof Error ? err.message : "Failed to move deal");
305
+ }
306
+ };
307
+ if (!isOpen || !deal)
308
+ return null;
309
+ return /* @__PURE__ */ jsxDEV2("div", {
310
+ className: "fixed inset-0 z-50 flex items-center justify-center",
311
+ children: [
312
+ /* @__PURE__ */ jsxDEV2("div", {
313
+ className: "bg-background/80 absolute inset-0 backdrop-blur-sm",
314
+ onClick: handleClose,
315
+ role: "button",
316
+ tabIndex: 0,
317
+ onKeyDown: (e) => {
318
+ if (e.key === "Enter" || e.key === " ")
319
+ handleClose();
320
+ },
321
+ "aria-label": "Close modal"
322
+ }, undefined, false, undefined, this),
323
+ /* @__PURE__ */ jsxDEV2("div", {
324
+ className: "bg-card border-border relative z-10 w-full max-w-md rounded-xl border p-6 shadow-xl",
325
+ children: [
326
+ /* @__PURE__ */ jsxDEV2("div", {
327
+ className: "border-border mb-4 border-b pb-4",
328
+ children: [
329
+ /* @__PURE__ */ jsxDEV2("h2", {
330
+ className: "text-xl font-semibold",
331
+ children: deal.name
332
+ }, undefined, false, undefined, this),
333
+ /* @__PURE__ */ jsxDEV2("p", {
334
+ className: "text-primary text-lg font-medium",
335
+ children: formatCurrency(deal.value, deal.currency)
336
+ }, undefined, false, undefined, this),
337
+ /* @__PURE__ */ jsxDEV2("span", {
338
+ className: `mt-2 inline-flex rounded-full px-2 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"}`,
339
+ children: deal.status
340
+ }, undefined, false, undefined, this)
341
+ ]
342
+ }, undefined, true, undefined, this),
343
+ mode === "menu" && /* @__PURE__ */ jsxDEV2("div", {
344
+ className: "space-y-3",
345
+ children: [
346
+ deal.status === "OPEN" && /* @__PURE__ */ jsxDEV2(Fragment, {
347
+ children: [
348
+ /* @__PURE__ */ jsxDEV2(Button2, {
349
+ className: "w-full justify-start",
350
+ variant: "ghost",
351
+ onPress: () => setMode("win"),
352
+ children: [
353
+ /* @__PURE__ */ jsxDEV2("span", {
354
+ className: "mr-2",
355
+ children: "\uD83C\uDFC6"
356
+ }, undefined, false, undefined, this),
357
+ " Mark as Won"
358
+ ]
359
+ }, undefined, true, undefined, this),
360
+ /* @__PURE__ */ jsxDEV2(Button2, {
361
+ className: "w-full justify-start",
362
+ variant: "ghost",
363
+ onPress: () => setMode("lose"),
364
+ children: [
365
+ /* @__PURE__ */ jsxDEV2("span", {
366
+ className: "mr-2",
367
+ children: "❌"
368
+ }, undefined, false, undefined, this),
369
+ " Mark as Lost"
370
+ ]
371
+ }, undefined, true, undefined, this),
372
+ /* @__PURE__ */ jsxDEV2(Button2, {
373
+ className: "w-full justify-start",
374
+ variant: "ghost",
375
+ onPress: () => {
376
+ setSelectedStageId(deal.stageId);
377
+ setMode("move");
378
+ },
379
+ children: [
380
+ /* @__PURE__ */ jsxDEV2("span", {
381
+ className: "mr-2",
382
+ children: "➡️"
383
+ }, undefined, false, undefined, this),
384
+ " Move to Stage"
385
+ ]
386
+ }, undefined, true, undefined, this)
387
+ ]
388
+ }, undefined, true, undefined, this),
389
+ deal.status !== "OPEN" && /* @__PURE__ */ jsxDEV2("p", {
390
+ className: "text-muted-foreground py-4 text-center",
391
+ children: [
392
+ "This deal is already ",
393
+ deal.status.toLowerCase(),
394
+ ". No actions available."
395
+ ]
396
+ }, undefined, true, undefined, this),
397
+ /* @__PURE__ */ jsxDEV2("div", {
398
+ className: "border-border border-t pt-3",
399
+ children: /* @__PURE__ */ jsxDEV2(Button2, {
400
+ className: "w-full",
401
+ variant: "outline",
402
+ onPress: handleClose,
403
+ children: "Close"
404
+ }, undefined, false, undefined, this)
405
+ }, undefined, false, undefined, this)
406
+ ]
407
+ }, undefined, true, undefined, this),
408
+ mode === "win" && /* @__PURE__ */ jsxDEV2("div", {
409
+ className: "space-y-4",
410
+ children: [
411
+ /* @__PURE__ */ jsxDEV2("div", {
412
+ children: [
413
+ /* @__PURE__ */ jsxDEV2("label", {
414
+ htmlFor: "won-source",
415
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
416
+ children: "How did you win this deal?"
417
+ }, undefined, false, undefined, this),
418
+ /* @__PURE__ */ jsxDEV2("select", {
419
+ id: "won-source",
420
+ value: wonSource,
421
+ onChange: (e) => setWonSource(e.target.value),
422
+ className: "border-input bg-background focus:ring-ring h-10 w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none",
423
+ children: [
424
+ /* @__PURE__ */ jsxDEV2("option", {
425
+ value: "",
426
+ children: "Select a source..."
427
+ }, undefined, false, undefined, this),
428
+ /* @__PURE__ */ jsxDEV2("option", {
429
+ value: "referral",
430
+ children: "Referral"
431
+ }, undefined, false, undefined, this),
432
+ /* @__PURE__ */ jsxDEV2("option", {
433
+ value: "cold_outreach",
434
+ children: "Cold Outreach"
435
+ }, undefined, false, undefined, this),
436
+ /* @__PURE__ */ jsxDEV2("option", {
437
+ value: "inbound",
438
+ children: "Inbound Lead"
439
+ }, undefined, false, undefined, this),
440
+ /* @__PURE__ */ jsxDEV2("option", {
441
+ value: "upsell",
442
+ children: "Upsell"
443
+ }, undefined, false, undefined, this),
444
+ /* @__PURE__ */ jsxDEV2("option", {
445
+ value: "other",
446
+ children: "Other"
447
+ }, undefined, false, undefined, this)
448
+ ]
449
+ }, undefined, true, undefined, this)
450
+ ]
451
+ }, undefined, true, undefined, this),
452
+ /* @__PURE__ */ jsxDEV2("div", {
453
+ children: [
454
+ /* @__PURE__ */ jsxDEV2("label", {
455
+ htmlFor: "win-notes",
456
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
457
+ children: "Notes (optional)"
458
+ }, undefined, false, undefined, this),
459
+ /* @__PURE__ */ jsxDEV2("textarea", {
460
+ id: "win-notes",
461
+ value: notes,
462
+ onChange: (e) => setNotes(e.target.value),
463
+ placeholder: "Any additional notes about the win...",
464
+ rows: 3,
465
+ className: "border-input bg-background focus:ring-ring w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
466
+ }, undefined, false, undefined, this)
467
+ ]
468
+ }, undefined, true, undefined, this),
469
+ error && /* @__PURE__ */ jsxDEV2("div", {
470
+ className: "bg-destructive/10 text-destructive rounded-md p-3 text-sm",
471
+ children: error
472
+ }, undefined, false, undefined, this),
473
+ /* @__PURE__ */ jsxDEV2("div", {
474
+ className: "flex justify-end gap-3 pt-2",
475
+ children: [
476
+ /* @__PURE__ */ jsxDEV2(Button2, {
477
+ variant: "ghost",
478
+ onPress: () => setMode("menu"),
479
+ disabled: isLoading,
480
+ children: "Back"
481
+ }, undefined, false, undefined, this),
482
+ /* @__PURE__ */ jsxDEV2(Button2, {
483
+ onPress: handleWin,
484
+ disabled: isLoading,
485
+ children: isLoading ? "Processing..." : "\uD83C\uDFC6 Confirm Win"
486
+ }, undefined, false, undefined, this)
487
+ ]
488
+ }, undefined, true, undefined, this)
489
+ ]
490
+ }, undefined, true, undefined, this),
491
+ mode === "lose" && /* @__PURE__ */ jsxDEV2("div", {
492
+ className: "space-y-4",
493
+ children: [
494
+ /* @__PURE__ */ jsxDEV2("div", {
495
+ children: [
496
+ /* @__PURE__ */ jsxDEV2("label", {
497
+ htmlFor: "lost-reason",
498
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
499
+ children: "Why was this deal lost? *"
500
+ }, undefined, false, undefined, this),
501
+ /* @__PURE__ */ jsxDEV2("select", {
502
+ id: "lost-reason",
503
+ value: lostReason,
504
+ onChange: (e) => setLostReason(e.target.value),
505
+ className: "border-input bg-background focus:ring-ring h-10 w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none",
506
+ children: [
507
+ /* @__PURE__ */ jsxDEV2("option", {
508
+ value: "",
509
+ children: "Select a reason..."
510
+ }, undefined, false, undefined, this),
511
+ /* @__PURE__ */ jsxDEV2("option", {
512
+ value: "price",
513
+ children: "Price too high"
514
+ }, undefined, false, undefined, this),
515
+ /* @__PURE__ */ jsxDEV2("option", {
516
+ value: "competitor",
517
+ children: "Lost to competitor"
518
+ }, undefined, false, undefined, this),
519
+ /* @__PURE__ */ jsxDEV2("option", {
520
+ value: "no_budget",
521
+ children: "No budget"
522
+ }, undefined, false, undefined, this),
523
+ /* @__PURE__ */ jsxDEV2("option", {
524
+ value: "no_decision",
525
+ children: "No decision made"
526
+ }, undefined, false, undefined, this),
527
+ /* @__PURE__ */ jsxDEV2("option", {
528
+ value: "timing",
529
+ children: "Bad timing"
530
+ }, undefined, false, undefined, this),
531
+ /* @__PURE__ */ jsxDEV2("option", {
532
+ value: "product_fit",
533
+ children: "Product not a fit"
534
+ }, undefined, false, undefined, this),
535
+ /* @__PURE__ */ jsxDEV2("option", {
536
+ value: "other",
537
+ children: "Other"
538
+ }, undefined, false, undefined, this)
539
+ ]
540
+ }, undefined, true, undefined, this)
541
+ ]
542
+ }, undefined, true, undefined, this),
543
+ /* @__PURE__ */ jsxDEV2("div", {
544
+ children: [
545
+ /* @__PURE__ */ jsxDEV2("label", {
546
+ htmlFor: "lose-notes",
547
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
548
+ children: "Notes (optional)"
549
+ }, undefined, false, undefined, this),
550
+ /* @__PURE__ */ jsxDEV2("textarea", {
551
+ id: "lose-notes",
552
+ value: notes,
553
+ onChange: (e) => setNotes(e.target.value),
554
+ placeholder: "Any additional details...",
555
+ rows: 3,
556
+ className: "border-input bg-background focus:ring-ring w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none"
557
+ }, undefined, false, undefined, this)
558
+ ]
559
+ }, undefined, true, undefined, this),
560
+ error && /* @__PURE__ */ jsxDEV2("div", {
561
+ className: "bg-destructive/10 text-destructive rounded-md p-3 text-sm",
562
+ children: error
563
+ }, undefined, false, undefined, this),
564
+ /* @__PURE__ */ jsxDEV2("div", {
565
+ className: "flex justify-end gap-3 pt-2",
566
+ children: [
567
+ /* @__PURE__ */ jsxDEV2(Button2, {
568
+ variant: "ghost",
569
+ onPress: () => setMode("menu"),
570
+ disabled: isLoading,
571
+ children: "Back"
572
+ }, undefined, false, undefined, this),
573
+ /* @__PURE__ */ jsxDEV2(Button2, {
574
+ variant: "destructive",
575
+ onPress: handleLose,
576
+ disabled: isLoading,
577
+ children: isLoading ? "Processing..." : "❌ Confirm Loss"
578
+ }, undefined, false, undefined, this)
579
+ ]
580
+ }, undefined, true, undefined, this)
581
+ ]
582
+ }, undefined, true, undefined, this),
583
+ mode === "move" && /* @__PURE__ */ jsxDEV2("div", {
584
+ className: "space-y-4",
585
+ children: [
586
+ /* @__PURE__ */ jsxDEV2("div", {
587
+ children: [
588
+ /* @__PURE__ */ jsxDEV2("label", {
589
+ htmlFor: "move-stage",
590
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
591
+ children: "Move to Stage"
592
+ }, undefined, false, undefined, this),
593
+ /* @__PURE__ */ jsxDEV2("select", {
594
+ id: "move-stage",
595
+ value: selectedStageId,
596
+ onChange: (e) => setSelectedStageId(e.target.value),
597
+ className: "border-input bg-background focus:ring-ring h-10 w-full rounded-md border px-3 py-2 text-sm focus:ring-2 focus:outline-none",
598
+ children: stages.map((stage) => /* @__PURE__ */ jsxDEV2("option", {
599
+ value: stage.id,
600
+ children: [
601
+ stage.name,
602
+ stage.id === deal.stageId ? " (current)" : ""
603
+ ]
604
+ }, stage.id, true, undefined, this))
605
+ }, undefined, false, undefined, this)
606
+ ]
607
+ }, undefined, true, undefined, this),
608
+ error && /* @__PURE__ */ jsxDEV2("div", {
609
+ className: "bg-destructive/10 text-destructive rounded-md p-3 text-sm",
610
+ children: error
611
+ }, undefined, false, undefined, this),
612
+ /* @__PURE__ */ jsxDEV2("div", {
613
+ className: "flex justify-end gap-3 pt-2",
614
+ children: [
615
+ /* @__PURE__ */ jsxDEV2(Button2, {
616
+ variant: "ghost",
617
+ onPress: () => setMode("menu"),
618
+ disabled: isLoading,
619
+ children: "Back"
620
+ }, undefined, false, undefined, this),
621
+ /* @__PURE__ */ jsxDEV2(Button2, {
622
+ onPress: handleMove,
623
+ disabled: isLoading,
624
+ children: isLoading ? "Moving..." : "➡️ Move Deal"
625
+ }, undefined, false, undefined, this)
626
+ ]
627
+ }, undefined, true, undefined, this)
628
+ ]
629
+ }, undefined, true, undefined, this)
630
+ ]
631
+ }, undefined, true, undefined, this)
632
+ ]
633
+ }, undefined, true, undefined, this);
634
+ }
635
+ export {
636
+ DealActionsModal,
637
+ CreateDealModal
638
+ };
@@ -0,0 +1,55 @@
1
+ // src/ui/overlays/demo-overlays.ts
2
+ var crmDemoOverlay = {
3
+ overlayId: "crm-pipeline.demo-user",
4
+ version: "1.0.0",
5
+ description: "Demo mode with sample data",
6
+ appliesTo: {
7
+ feature: "crm-pipeline",
8
+ role: "demo"
9
+ },
10
+ modifications: [
11
+ {
12
+ type: "hideField",
13
+ field: "importButton",
14
+ reason: "Not available in demo"
15
+ },
16
+ {
17
+ type: "hideField",
18
+ field: "exportButton",
19
+ reason: "Not available in demo"
20
+ },
21
+ {
22
+ type: "addBadge",
23
+ position: "header",
24
+ label: "Demo Mode",
25
+ variant: "warning"
26
+ }
27
+ ]
28
+ };
29
+ var crmSalesRepOverlay = {
30
+ overlayId: "crm-pipeline.sales-rep",
31
+ version: "1.0.0",
32
+ description: "Sales rep focused view",
33
+ appliesTo: {
34
+ feature: "crm-pipeline",
35
+ role: "sales-rep"
36
+ },
37
+ modifications: [
38
+ {
39
+ type: "hideField",
40
+ field: "teamMetrics",
41
+ reason: "Team metrics for managers only"
42
+ },
43
+ { type: "hideField", field: "pipelineSettings", reason: "Admin only" },
44
+ { type: "renameLabel", field: "deals", newLabel: "My Deals" }
45
+ ]
46
+ };
47
+ var crmOverlays = [
48
+ crmDemoOverlay,
49
+ crmSalesRepOverlay
50
+ ];
51
+ export {
52
+ crmSalesRepOverlay,
53
+ crmOverlays,
54
+ crmDemoOverlay
55
+ };