@contractspec/example.crm-pipeline 0.0.0-canary-20260113170453

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 (206) hide show
  1. package/.turbo/turbo-build$colon$bundle.log +172 -0
  2. package/.turbo/turbo-build.log +173 -0
  3. package/CHANGELOG.md +436 -0
  4. package/LICENSE +21 -0
  5. package/README.md +139 -0
  6. package/dist/crm-pipeline.feature.d.ts +12 -0
  7. package/dist/crm-pipeline.feature.d.ts.map +1 -0
  8. package/dist/crm-pipeline.feature.js +166 -0
  9. package/dist/crm-pipeline.feature.js.map +1 -0
  10. package/dist/deal/deal.enum.d.ts +14 -0
  11. package/dist/deal/deal.enum.d.ts.map +1 -0
  12. package/dist/deal/deal.enum.js +25 -0
  13. package/dist/deal/deal.enum.js.map +1 -0
  14. package/dist/deal/deal.operation.d.ts +513 -0
  15. package/dist/deal/deal.operation.d.ts.map +1 -0
  16. package/dist/deal/deal.operation.js +270 -0
  17. package/dist/deal/deal.operation.js.map +1 -0
  18. package/dist/deal/deal.schema.d.ts +300 -0
  19. package/dist/deal/deal.schema.d.ts.map +1 -0
  20. package/dist/deal/deal.schema.js +286 -0
  21. package/dist/deal/deal.schema.js.map +1 -0
  22. package/dist/deal/deal.test-spec.d.ts +8 -0
  23. package/dist/deal/deal.test-spec.d.ts.map +1 -0
  24. package/dist/deal/deal.test-spec.js +65 -0
  25. package/dist/deal/deal.test-spec.js.map +1 -0
  26. package/dist/deal/index.d.ts +4 -0
  27. package/dist/deal/index.js +5 -0
  28. package/dist/docs/crm-pipeline.docblock.d.ts +1 -0
  29. package/dist/docs/crm-pipeline.docblock.js +100 -0
  30. package/dist/docs/crm-pipeline.docblock.js.map +1 -0
  31. package/dist/docs/index.d.ts +1 -0
  32. package/dist/docs/index.js +1 -0
  33. package/dist/entities/company.entity.d.ts +40 -0
  34. package/dist/entities/company.entity.d.ts.map +1 -0
  35. package/dist/entities/company.entity.js +63 -0
  36. package/dist/entities/company.entity.js.map +1 -0
  37. package/dist/entities/contact.entity.d.ts +44 -0
  38. package/dist/entities/contact.entity.d.ts.map +1 -0
  39. package/dist/entities/contact.entity.js +78 -0
  40. package/dist/entities/contact.entity.js.map +1 -0
  41. package/dist/entities/deal.entity.d.ts +73 -0
  42. package/dist/entities/deal.entity.d.ts.map +1 -0
  43. package/dist/entities/deal.entity.js +120 -0
  44. package/dist/entities/deal.entity.js.map +1 -0
  45. package/dist/entities/index.d.ts +15 -0
  46. package/dist/entities/index.d.ts.map +1 -0
  47. package/dist/entities/index.js +33 -0
  48. package/dist/entities/index.js.map +1 -0
  49. package/dist/entities/task.entity.d.ts +65 -0
  50. package/dist/entities/task.entity.d.ts.map +1 -0
  51. package/dist/entities/task.entity.js +129 -0
  52. package/dist/entities/task.entity.js.map +1 -0
  53. package/dist/events/contact.event.d.ts +29 -0
  54. package/dist/events/contact.event.d.ts.map +1 -0
  55. package/dist/events/contact.event.js +45 -0
  56. package/dist/events/contact.event.js.map +1 -0
  57. package/dist/events/deal.event.d.ts +111 -0
  58. package/dist/events/deal.event.d.ts.map +1 -0
  59. package/dist/events/deal.event.js +172 -0
  60. package/dist/events/deal.event.js.map +1 -0
  61. package/dist/events/index.d.ts +4 -0
  62. package/dist/events/index.js +5 -0
  63. package/dist/events/task.event.d.ts +29 -0
  64. package/dist/events/task.event.d.ts.map +1 -0
  65. package/dist/events/task.event.js +45 -0
  66. package/dist/events/task.event.js.map +1 -0
  67. package/dist/example.d.ts +7 -0
  68. package/dist/example.d.ts.map +1 -0
  69. package/dist/example.js +53 -0
  70. package/dist/example.js.map +1 -0
  71. package/dist/handlers/crm.handlers.d.ts +89 -0
  72. package/dist/handlers/crm.handlers.d.ts.map +1 -0
  73. package/dist/handlers/crm.handlers.js +172 -0
  74. package/dist/handlers/crm.handlers.js.map +1 -0
  75. package/dist/handlers/deal.handlers.d.ts +94 -0
  76. package/dist/handlers/deal.handlers.d.ts.map +1 -0
  77. package/dist/handlers/deal.handlers.js +120 -0
  78. package/dist/handlers/deal.handlers.js.map +1 -0
  79. package/dist/handlers/index.d.ts +4 -0
  80. package/dist/handlers/index.js +5 -0
  81. package/dist/handlers/mock-data.d.ts +49 -0
  82. package/dist/handlers/mock-data.d.ts.map +1 -0
  83. package/dist/handlers/mock-data.js +188 -0
  84. package/dist/handlers/mock-data.js.map +1 -0
  85. package/dist/index.d.ts +47 -0
  86. package/dist/index.d.ts.map +1 -0
  87. package/dist/index.js +56 -0
  88. package/dist/index.js.map +1 -0
  89. package/dist/operations/index.d.ts +5 -0
  90. package/dist/operations/index.js +6 -0
  91. package/dist/presentations/dashboard.presentation.d.ts +14 -0
  92. package/dist/presentations/dashboard.presentation.d.ts.map +1 -0
  93. package/dist/presentations/dashboard.presentation.js +62 -0
  94. package/dist/presentations/dashboard.presentation.js.map +1 -0
  95. package/dist/presentations/index.d.ts +3 -0
  96. package/dist/presentations/index.js +4 -0
  97. package/dist/presentations/pipeline.presentation.d.ts +22 -0
  98. package/dist/presentations/pipeline.presentation.d.ts.map +1 -0
  99. package/dist/presentations/pipeline.presentation.js +122 -0
  100. package/dist/presentations/pipeline.presentation.js.map +1 -0
  101. package/dist/seeders/index.d.ts +10 -0
  102. package/dist/seeders/index.d.ts.map +1 -0
  103. package/dist/seeders/index.js +47 -0
  104. package/dist/seeders/index.js.map +1 -0
  105. package/dist/shared/overlay-types.d.ts +34 -0
  106. package/dist/shared/overlay-types.d.ts.map +1 -0
  107. package/dist/shared/overlay-types.js +0 -0
  108. package/dist/ui/CrmDashboard.d.ts +7 -0
  109. package/dist/ui/CrmDashboard.d.ts.map +1 -0
  110. package/dist/ui/CrmDashboard.js +304 -0
  111. package/dist/ui/CrmDashboard.js.map +1 -0
  112. package/dist/ui/CrmDealCard.d.ts +15 -0
  113. package/dist/ui/CrmDealCard.d.ts.map +1 -0
  114. package/dist/ui/CrmDealCard.js +49 -0
  115. package/dist/ui/CrmDealCard.js.map +1 -0
  116. package/dist/ui/CrmPipelineBoard.d.ts +23 -0
  117. package/dist/ui/CrmPipelineBoard.d.ts.map +1 -0
  118. package/dist/ui/CrmPipelineBoard.js +98 -0
  119. package/dist/ui/CrmPipelineBoard.js.map +1 -0
  120. package/dist/ui/hooks/index.d.ts +3 -0
  121. package/dist/ui/hooks/index.js +6 -0
  122. package/dist/ui/hooks/useDealList.d.ts +35 -0
  123. package/dist/ui/hooks/useDealList.d.ts.map +1 -0
  124. package/dist/ui/hooks/useDealList.js +94 -0
  125. package/dist/ui/hooks/useDealList.js.map +1 -0
  126. package/dist/ui/hooks/useDealMutations.d.ts +26 -0
  127. package/dist/ui/hooks/useDealMutations.d.ts.map +1 -0
  128. package/dist/ui/hooks/useDealMutations.js +159 -0
  129. package/dist/ui/hooks/useDealMutations.js.map +1 -0
  130. package/dist/ui/index.d.ts +14 -0
  131. package/dist/ui/index.js +15 -0
  132. package/dist/ui/modals/CreateDealModal.d.ts +33 -0
  133. package/dist/ui/modals/CreateDealModal.d.ts.map +1 -0
  134. package/dist/ui/modals/CreateDealModal.js +183 -0
  135. package/dist/ui/modals/CreateDealModal.js.map +1 -0
  136. package/dist/ui/modals/DealActionsModal.d.ts +51 -0
  137. package/dist/ui/modals/DealActionsModal.d.ts.map +1 -0
  138. package/dist/ui/modals/DealActionsModal.js +372 -0
  139. package/dist/ui/modals/DealActionsModal.js.map +1 -0
  140. package/dist/ui/modals/index.d.ts +3 -0
  141. package/dist/ui/modals/index.js +4 -0
  142. package/dist/ui/overlays/demo-overlays.d.ts +19 -0
  143. package/dist/ui/overlays/demo-overlays.d.ts.map +1 -0
  144. package/dist/ui/overlays/demo-overlays.js +68 -0
  145. package/dist/ui/overlays/demo-overlays.js.map +1 -0
  146. package/dist/ui/overlays/index.d.ts +2 -0
  147. package/dist/ui/overlays/index.js +3 -0
  148. package/dist/ui/renderers/index.d.ts +3 -0
  149. package/dist/ui/renderers/index.js +4 -0
  150. package/dist/ui/renderers/pipeline.markdown.d.ts +23 -0
  151. package/dist/ui/renderers/pipeline.markdown.d.ts.map +1 -0
  152. package/dist/ui/renderers/pipeline.markdown.js +118 -0
  153. package/dist/ui/renderers/pipeline.markdown.js.map +1 -0
  154. package/dist/ui/renderers/pipeline.renderer.d.ts +9 -0
  155. package/dist/ui/renderers/pipeline.renderer.d.ts.map +1 -0
  156. package/dist/ui/renderers/pipeline.renderer.js +28 -0
  157. package/dist/ui/renderers/pipeline.renderer.js.map +1 -0
  158. package/example.ts +1 -0
  159. package/package.json +127 -0
  160. package/src/crm-pipeline.feature.ts +100 -0
  161. package/src/deal/deal.enum.ts +21 -0
  162. package/src/deal/deal.operation.ts +291 -0
  163. package/src/deal/deal.schema.ts +154 -0
  164. package/src/deal/deal.test-spec.ts +55 -0
  165. package/src/deal/index.ts +26 -0
  166. package/src/docs/crm-pipeline.docblock.ts +98 -0
  167. package/src/docs/index.ts +1 -0
  168. package/src/entities/company.entity.ts +77 -0
  169. package/src/entities/contact.entity.ts +93 -0
  170. package/src/entities/deal.entity.ts +160 -0
  171. package/src/entities/index.ts +45 -0
  172. package/src/entities/task.entity.ts +137 -0
  173. package/src/events/contact.event.ts +31 -0
  174. package/src/events/deal.event.ts +104 -0
  175. package/src/events/index.ts +3 -0
  176. package/src/events/task.event.ts +28 -0
  177. package/src/example.ts +38 -0
  178. package/src/handlers/crm.handlers.ts +415 -0
  179. package/src/handlers/deal.handlers.ts +253 -0
  180. package/src/handlers/index.ts +30 -0
  181. package/src/handlers/mock-data.ts +198 -0
  182. package/src/index.ts +32 -0
  183. package/src/operations/index.ts +20 -0
  184. package/src/presentations/dashboard.presentation.ts +59 -0
  185. package/src/presentations/index.ts +2 -0
  186. package/src/presentations/pipeline.presentation.ts +117 -0
  187. package/src/seeders/index.ts +35 -0
  188. package/src/shared/overlay-types.ts +39 -0
  189. package/src/ui/CrmDashboard.tsx +311 -0
  190. package/src/ui/CrmDealCard.tsx +83 -0
  191. package/src/ui/CrmPipelineBoard.tsx +136 -0
  192. package/src/ui/hooks/index.ts +10 -0
  193. package/src/ui/hooks/useDealList.ts +113 -0
  194. package/src/ui/hooks/useDealMutations.ts +174 -0
  195. package/src/ui/index.ts +18 -0
  196. package/src/ui/modals/CreateDealModal.tsx +239 -0
  197. package/src/ui/modals/DealActionsModal.tsx +424 -0
  198. package/src/ui/modals/index.ts +2 -0
  199. package/src/ui/overlays/demo-overlays.ts +68 -0
  200. package/src/ui/overlays/index.ts +1 -0
  201. package/src/ui/renderers/index.ts +6 -0
  202. package/src/ui/renderers/pipeline.markdown.ts +198 -0
  203. package/src/ui/renderers/pipeline.renderer.tsx +35 -0
  204. package/tsconfig.json +10 -0
  205. package/tsconfig.tsbuildinfo +1 -0
  206. package/tsdown.config.js +7 -0
@@ -0,0 +1,51 @@
1
+ import * as react_jsx_runtime2 from "react/jsx-runtime";
2
+
3
+ //#region src/ui/modals/DealActionsModal.d.ts
4
+ interface Deal {
5
+ id: string;
6
+ name: string;
7
+ value: number;
8
+ currency: string;
9
+ stageId: string;
10
+ status: 'OPEN' | 'WON' | 'LOST' | 'STALE';
11
+ }
12
+ interface WinDealInput {
13
+ dealId: string;
14
+ wonSource?: string;
15
+ notes?: string;
16
+ }
17
+ interface LoseDealInput {
18
+ dealId: string;
19
+ lostReason: string;
20
+ notes?: string;
21
+ }
22
+ interface MoveDealInput {
23
+ dealId: string;
24
+ stageId: string;
25
+ }
26
+ interface DealActionsModalProps {
27
+ isOpen: boolean;
28
+ deal: Deal | null;
29
+ stages: {
30
+ id: string;
31
+ name: string;
32
+ }[];
33
+ onClose: () => void;
34
+ onWin: (input: WinDealInput) => Promise<void>;
35
+ onLose: (input: LoseDealInput) => Promise<void>;
36
+ onMove: (input: MoveDealInput) => Promise<void>;
37
+ isLoading?: boolean;
38
+ }
39
+ declare function DealActionsModal({
40
+ isOpen,
41
+ deal,
42
+ stages,
43
+ onClose,
44
+ onWin,
45
+ onLose,
46
+ onMove,
47
+ isLoading
48
+ }: DealActionsModalProps): react_jsx_runtime2.JSX.Element | null;
49
+ //#endregion
50
+ export { Deal, DealActionsModal, LoseDealInput, MoveDealInput, WinDealInput };
51
+ //# sourceMappingURL=DealActionsModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DealActionsModal.d.ts","names":[],"sources":["../../../src/ui/modals/DealActionsModal.tsx"],"sourcesContent":[],"mappings":";;;UAYiB,IAAA;;;EAAA,KAAA,EAAI,MAAA;EASJ,QAAA,EAAA,MAAY;EAMZ,OAAA,EAAA,MAAA;EAMA,MAAA,EAAA,MAAA,GAAa,KAAA,GAAA,MAAA,GAAA,OAAA;AAG7B;AAMO,UArBS,YAAA,CAqBT;EAGS,MAAA,EAAA,MAAA;EAAiB,SAAA,CAAA,EAAA,MAAA;EAChB,KAAA,CAAA,EAAA,MAAA;;AACA,UApBD,aAAA,CAoBC;EAAkB,MAAA,EAAA,MAAA;EAAO,UAAA,EAAA,MAAA;EAa3B,KAAA,CAAA,EAAA,MAAA;;AAEd,UA7Be,aAAA,CA6Bf;EACA,MAAA,EAAA,MAAA;EACA,OAAA,EAAA,MAAA;;UAxBQ,qBAAA,CA0BR;EACA,MAAA,EAAA,OAAA;EACA,IAAA,EA1BM,IA0BN,GAAA,IAAA;EACC,MAAA,EAAA;IAAqB,EAAA,EAAA,MAAA;IAAA,IAAA,EAAA,MAAA;;;iBAxBP,iBAAiB;kBAChB,kBAAkB;kBAClB,kBAAkB;;;iBAapB,gBAAA;;;;;;;;;GASb,wBAAqB,kBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -0,0 +1,372 @@
1
+ 'use client';
2
+
3
+ import { useState } from "react";
4
+ import { Button } from "@contractspec/lib.design-system";
5
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6
+
7
+ //#region src/ui/modals/DealActionsModal.tsx
8
+ /**
9
+ * DealActionsModal - Actions for a specific deal (Win, Lose, Move)
10
+ *
11
+ * Wires to WinDealContract, LoseDealContract, MoveDealContract
12
+ * via useDealMutations hook.
13
+ */
14
+ function formatCurrency(value, currency) {
15
+ return new Intl.NumberFormat("en-US", {
16
+ style: "currency",
17
+ currency,
18
+ minimumFractionDigits: 0,
19
+ maximumFractionDigits: 0
20
+ }).format(value);
21
+ }
22
+ function DealActionsModal({ isOpen, deal, stages, onClose, onWin, onLose, onMove, isLoading = false }) {
23
+ const [mode, setMode] = useState("menu");
24
+ const [wonSource, setWonSource] = useState("");
25
+ const [lostReason, setLostReason] = useState("");
26
+ const [notes, setNotes] = useState("");
27
+ const [selectedStageId, setSelectedStageId] = useState("");
28
+ const [error, setError] = useState(null);
29
+ const resetForm = () => {
30
+ setMode("menu");
31
+ setWonSource("");
32
+ setLostReason("");
33
+ setNotes("");
34
+ setSelectedStageId("");
35
+ setError(null);
36
+ };
37
+ const handleClose = () => {
38
+ resetForm();
39
+ onClose();
40
+ };
41
+ const handleWin = async () => {
42
+ if (!deal) return;
43
+ setError(null);
44
+ try {
45
+ await onWin({
46
+ dealId: deal.id,
47
+ wonSource: wonSource.trim() || void 0,
48
+ notes: notes.trim() || void 0
49
+ });
50
+ handleClose();
51
+ } catch (err) {
52
+ setError(err instanceof Error ? err.message : "Failed to mark deal as won");
53
+ }
54
+ };
55
+ const handleLose = async () => {
56
+ if (!deal) return;
57
+ setError(null);
58
+ if (!lostReason.trim()) {
59
+ setError("Please provide a reason for losing the deal");
60
+ return;
61
+ }
62
+ try {
63
+ await onLose({
64
+ dealId: deal.id,
65
+ lostReason: lostReason.trim(),
66
+ notes: notes.trim() || void 0
67
+ });
68
+ handleClose();
69
+ } catch (err) {
70
+ setError(err instanceof Error ? err.message : "Failed to mark deal as lost");
71
+ }
72
+ };
73
+ const handleMove = async () => {
74
+ if (!deal) return;
75
+ setError(null);
76
+ if (!selectedStageId) {
77
+ setError("Please select a stage");
78
+ return;
79
+ }
80
+ if (selectedStageId === deal.stageId) {
81
+ setError("Deal is already in this stage");
82
+ return;
83
+ }
84
+ try {
85
+ await onMove({
86
+ dealId: deal.id,
87
+ stageId: selectedStageId
88
+ });
89
+ handleClose();
90
+ } catch (err) {
91
+ setError(err instanceof Error ? err.message : "Failed to move deal");
92
+ }
93
+ };
94
+ if (!isOpen || !deal) return null;
95
+ return /* @__PURE__ */ jsxs("div", {
96
+ className: "fixed inset-0 z-50 flex items-center justify-center",
97
+ children: [/* @__PURE__ */ jsx("div", {
98
+ className: "bg-background/80 absolute inset-0 backdrop-blur-sm",
99
+ onClick: handleClose,
100
+ role: "button",
101
+ tabIndex: 0,
102
+ onKeyDown: (e) => {
103
+ if (e.key === "Enter" || e.key === " ") handleClose();
104
+ },
105
+ "aria-label": "Close modal"
106
+ }), /* @__PURE__ */ jsxs("div", {
107
+ className: "bg-card border-border relative z-10 w-full max-w-md rounded-xl border p-6 shadow-xl",
108
+ children: [
109
+ /* @__PURE__ */ jsxs("div", {
110
+ className: "border-border mb-4 border-b pb-4",
111
+ children: [
112
+ /* @__PURE__ */ jsx("h2", {
113
+ className: "text-xl font-semibold",
114
+ children: deal.name
115
+ }),
116
+ /* @__PURE__ */ jsx("p", {
117
+ className: "text-primary text-lg font-medium",
118
+ children: formatCurrency(deal.value, deal.currency)
119
+ }),
120
+ /* @__PURE__ */ jsx("span", {
121
+ 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"}`,
122
+ children: deal.status
123
+ })
124
+ ]
125
+ }),
126
+ mode === "menu" && /* @__PURE__ */ jsxs("div", {
127
+ className: "space-y-3",
128
+ children: [
129
+ deal.status === "OPEN" && /* @__PURE__ */ jsxs(Fragment, { children: [
130
+ /* @__PURE__ */ jsxs(Button, {
131
+ className: "w-full justify-start",
132
+ variant: "ghost",
133
+ onPress: () => setMode("win"),
134
+ children: [/* @__PURE__ */ jsx("span", {
135
+ className: "mr-2",
136
+ children: "🏆"
137
+ }), " Mark as Won"]
138
+ }),
139
+ /* @__PURE__ */ jsxs(Button, {
140
+ className: "w-full justify-start",
141
+ variant: "ghost",
142
+ onPress: () => setMode("lose"),
143
+ children: [/* @__PURE__ */ jsx("span", {
144
+ className: "mr-2",
145
+ children: "❌"
146
+ }), " Mark as Lost"]
147
+ }),
148
+ /* @__PURE__ */ jsxs(Button, {
149
+ className: "w-full justify-start",
150
+ variant: "ghost",
151
+ onPress: () => {
152
+ setSelectedStageId(deal.stageId);
153
+ setMode("move");
154
+ },
155
+ children: [/* @__PURE__ */ jsx("span", {
156
+ className: "mr-2",
157
+ children: "➡️"
158
+ }), " Move to Stage"]
159
+ })
160
+ ] }),
161
+ deal.status !== "OPEN" && /* @__PURE__ */ jsxs("p", {
162
+ className: "text-muted-foreground py-4 text-center",
163
+ children: [
164
+ "This deal is already ",
165
+ deal.status.toLowerCase(),
166
+ ". No actions available."
167
+ ]
168
+ }),
169
+ /* @__PURE__ */ jsx("div", {
170
+ className: "border-border border-t pt-3",
171
+ children: /* @__PURE__ */ jsx(Button, {
172
+ className: "w-full",
173
+ variant: "outline",
174
+ onPress: handleClose,
175
+ children: "Close"
176
+ })
177
+ })
178
+ ]
179
+ }),
180
+ mode === "win" && /* @__PURE__ */ jsxs("div", {
181
+ className: "space-y-4",
182
+ children: [
183
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
184
+ htmlFor: "won-source",
185
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
186
+ children: "How did you win this deal?"
187
+ }), /* @__PURE__ */ jsxs("select", {
188
+ id: "won-source",
189
+ value: wonSource,
190
+ onChange: (e) => setWonSource(e.target.value),
191
+ 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",
192
+ children: [
193
+ /* @__PURE__ */ jsx("option", {
194
+ value: "",
195
+ children: "Select a source..."
196
+ }),
197
+ /* @__PURE__ */ jsx("option", {
198
+ value: "referral",
199
+ children: "Referral"
200
+ }),
201
+ /* @__PURE__ */ jsx("option", {
202
+ value: "cold_outreach",
203
+ children: "Cold Outreach"
204
+ }),
205
+ /* @__PURE__ */ jsx("option", {
206
+ value: "inbound",
207
+ children: "Inbound Lead"
208
+ }),
209
+ /* @__PURE__ */ jsx("option", {
210
+ value: "upsell",
211
+ children: "Upsell"
212
+ }),
213
+ /* @__PURE__ */ jsx("option", {
214
+ value: "other",
215
+ children: "Other"
216
+ })
217
+ ]
218
+ })] }),
219
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
220
+ htmlFor: "win-notes",
221
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
222
+ children: "Notes (optional)"
223
+ }), /* @__PURE__ */ jsx("textarea", {
224
+ id: "win-notes",
225
+ value: notes,
226
+ onChange: (e) => setNotes(e.target.value),
227
+ placeholder: "Any additional notes about the win...",
228
+ rows: 3,
229
+ 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"
230
+ })] }),
231
+ error && /* @__PURE__ */ jsx("div", {
232
+ className: "bg-destructive/10 text-destructive rounded-md p-3 text-sm",
233
+ children: error
234
+ }),
235
+ /* @__PURE__ */ jsxs("div", {
236
+ className: "flex justify-end gap-3 pt-2",
237
+ children: [/* @__PURE__ */ jsx(Button, {
238
+ variant: "ghost",
239
+ onPress: () => setMode("menu"),
240
+ disabled: isLoading,
241
+ children: "Back"
242
+ }), /* @__PURE__ */ jsx(Button, {
243
+ onPress: handleWin,
244
+ disabled: isLoading,
245
+ children: isLoading ? "Processing..." : "🏆 Confirm Win"
246
+ })]
247
+ })
248
+ ]
249
+ }),
250
+ mode === "lose" && /* @__PURE__ */ jsxs("div", {
251
+ className: "space-y-4",
252
+ children: [
253
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
254
+ htmlFor: "lost-reason",
255
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
256
+ children: "Why was this deal lost? *"
257
+ }), /* @__PURE__ */ jsxs("select", {
258
+ id: "lost-reason",
259
+ value: lostReason,
260
+ onChange: (e) => setLostReason(e.target.value),
261
+ 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",
262
+ children: [
263
+ /* @__PURE__ */ jsx("option", {
264
+ value: "",
265
+ children: "Select a reason..."
266
+ }),
267
+ /* @__PURE__ */ jsx("option", {
268
+ value: "price",
269
+ children: "Price too high"
270
+ }),
271
+ /* @__PURE__ */ jsx("option", {
272
+ value: "competitor",
273
+ children: "Lost to competitor"
274
+ }),
275
+ /* @__PURE__ */ jsx("option", {
276
+ value: "no_budget",
277
+ children: "No budget"
278
+ }),
279
+ /* @__PURE__ */ jsx("option", {
280
+ value: "no_decision",
281
+ children: "No decision made"
282
+ }),
283
+ /* @__PURE__ */ jsx("option", {
284
+ value: "timing",
285
+ children: "Bad timing"
286
+ }),
287
+ /* @__PURE__ */ jsx("option", {
288
+ value: "product_fit",
289
+ children: "Product not a fit"
290
+ }),
291
+ /* @__PURE__ */ jsx("option", {
292
+ value: "other",
293
+ children: "Other"
294
+ })
295
+ ]
296
+ })] }),
297
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
298
+ htmlFor: "lose-notes",
299
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
300
+ children: "Notes (optional)"
301
+ }), /* @__PURE__ */ jsx("textarea", {
302
+ id: "lose-notes",
303
+ value: notes,
304
+ onChange: (e) => setNotes(e.target.value),
305
+ placeholder: "Any additional details...",
306
+ rows: 3,
307
+ 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"
308
+ })] }),
309
+ error && /* @__PURE__ */ jsx("div", {
310
+ className: "bg-destructive/10 text-destructive rounded-md p-3 text-sm",
311
+ children: error
312
+ }),
313
+ /* @__PURE__ */ jsxs("div", {
314
+ className: "flex justify-end gap-3 pt-2",
315
+ children: [/* @__PURE__ */ jsx(Button, {
316
+ variant: "ghost",
317
+ onPress: () => setMode("menu"),
318
+ disabled: isLoading,
319
+ children: "Back"
320
+ }), /* @__PURE__ */ jsx(Button, {
321
+ variant: "destructive",
322
+ onPress: handleLose,
323
+ disabled: isLoading,
324
+ children: isLoading ? "Processing..." : "❌ Confirm Loss"
325
+ })]
326
+ })
327
+ ]
328
+ }),
329
+ mode === "move" && /* @__PURE__ */ jsxs("div", {
330
+ className: "space-y-4",
331
+ children: [
332
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("label", {
333
+ htmlFor: "move-stage",
334
+ className: "text-muted-foreground mb-1 block text-sm font-medium",
335
+ children: "Move to Stage"
336
+ }), /* @__PURE__ */ jsx("select", {
337
+ id: "move-stage",
338
+ value: selectedStageId,
339
+ onChange: (e) => setSelectedStageId(e.target.value),
340
+ 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",
341
+ children: stages.map((stage) => /* @__PURE__ */ jsxs("option", {
342
+ value: stage.id,
343
+ children: [stage.name, stage.id === deal.stageId ? " (current)" : ""]
344
+ }, stage.id))
345
+ })] }),
346
+ error && /* @__PURE__ */ jsx("div", {
347
+ className: "bg-destructive/10 text-destructive rounded-md p-3 text-sm",
348
+ children: error
349
+ }),
350
+ /* @__PURE__ */ jsxs("div", {
351
+ className: "flex justify-end gap-3 pt-2",
352
+ children: [/* @__PURE__ */ jsx(Button, {
353
+ variant: "ghost",
354
+ onPress: () => setMode("menu"),
355
+ disabled: isLoading,
356
+ children: "Back"
357
+ }), /* @__PURE__ */ jsx(Button, {
358
+ onPress: handleMove,
359
+ disabled: isLoading,
360
+ children: isLoading ? "Moving..." : "➡️ Move Deal"
361
+ })]
362
+ })
363
+ ]
364
+ })
365
+ ]
366
+ })]
367
+ });
368
+ }
369
+
370
+ //#endregion
371
+ export { DealActionsModal };
372
+ //# sourceMappingURL=DealActionsModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DealActionsModal.js","names":[],"sources":["../../../src/ui/modals/DealActionsModal.tsx"],"sourcesContent":["'use client';\n\n/**\n * DealActionsModal - Actions for a specific deal (Win, Lose, Move)\n *\n * Wires to WinDealContract, LoseDealContract, MoveDealContract\n * via useDealMutations hook.\n */\nimport { useState } from 'react';\nimport { Button } from '@contractspec/lib.design-system';\n\n// Local type definitions for modal props\nexport interface Deal {\n id: string;\n name: string;\n value: number;\n currency: string;\n stageId: string;\n status: 'OPEN' | 'WON' | 'LOST' | 'STALE';\n}\n\nexport interface WinDealInput {\n dealId: string;\n wonSource?: string;\n notes?: string;\n}\n\nexport interface LoseDealInput {\n dealId: string;\n lostReason: string;\n notes?: string;\n}\n\nexport interface MoveDealInput {\n dealId: string;\n stageId: string;\n}\n\ntype ActionMode = 'menu' | 'win' | 'lose' | 'move';\n\ninterface DealActionsModalProps {\n isOpen: boolean;\n deal: Deal | null;\n stages: { id: string; name: string }[];\n onClose: () => void;\n onWin: (input: WinDealInput) => Promise<void>;\n onLose: (input: LoseDealInput) => Promise<void>;\n onMove: (input: MoveDealInput) => Promise<void>;\n isLoading?: boolean;\n}\n\nfunction formatCurrency(value: number, currency: string): string {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency,\n minimumFractionDigits: 0,\n maximumFractionDigits: 0,\n }).format(value);\n}\n\nexport function DealActionsModal({\n isOpen,\n deal,\n stages,\n onClose,\n onWin,\n onLose,\n onMove,\n isLoading = false,\n}: DealActionsModalProps) {\n const [mode, setMode] = useState<ActionMode>('menu');\n const [wonSource, setWonSource] = useState('');\n const [lostReason, setLostReason] = useState('');\n const [notes, setNotes] = useState('');\n const [selectedStageId, setSelectedStageId] = useState('');\n const [error, setError] = useState<string | null>(null);\n\n const resetForm = () => {\n setMode('menu');\n setWonSource('');\n setLostReason('');\n setNotes('');\n setSelectedStageId('');\n setError(null);\n };\n\n const handleClose = () => {\n resetForm();\n onClose();\n };\n\n const handleWin = async () => {\n if (!deal) return;\n setError(null);\n\n try {\n await onWin({\n dealId: deal.id,\n wonSource: wonSource.trim() || undefined,\n notes: notes.trim() || undefined,\n });\n handleClose();\n } catch (err) {\n setError(\n err instanceof Error ? err.message : 'Failed to mark deal as won'\n );\n }\n };\n\n const handleLose = async () => {\n if (!deal) return;\n setError(null);\n\n if (!lostReason.trim()) {\n setError('Please provide a reason for losing the deal');\n return;\n }\n\n try {\n await onLose({\n dealId: deal.id,\n lostReason: lostReason.trim(),\n notes: notes.trim() || undefined,\n });\n handleClose();\n } catch (err) {\n setError(\n err instanceof Error ? err.message : 'Failed to mark deal as lost'\n );\n }\n };\n\n const handleMove = async () => {\n if (!deal) return;\n setError(null);\n\n if (!selectedStageId) {\n setError('Please select a stage');\n return;\n }\n\n if (selectedStageId === deal.stageId) {\n setError('Deal is already in this stage');\n return;\n }\n\n try {\n await onMove({\n dealId: deal.id,\n stageId: selectedStageId,\n });\n handleClose();\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to move deal');\n }\n };\n\n if (!isOpen || !deal) return null;\n\n return (\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\n {/* Backdrop */}\n <div\n className=\"bg-background/80 absolute inset-0 backdrop-blur-sm\"\n onClick={handleClose}\n role=\"button\"\n tabIndex={0}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') handleClose();\n }}\n aria-label=\"Close modal\"\n />\n\n {/* Modal */}\n <div className=\"bg-card border-border relative z-10 w-full max-w-md rounded-xl border p-6 shadow-xl\">\n {/* Deal Header */}\n <div className=\"border-border mb-4 border-b pb-4\">\n <h2 className=\"text-xl font-semibold\">{deal.name}</h2>\n <p className=\"text-primary text-lg font-medium\">\n {formatCurrency(deal.value, deal.currency)}\n </p>\n <span\n className={`mt-2 inline-flex rounded-full px-2 py-0.5 text-xs font-medium ${\n deal.status === 'WON'\n ? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400'\n : deal.status === 'LOST'\n ? 'bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400'\n : 'bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400'\n }`}\n >\n {deal.status}\n </span>\n </div>\n\n {/* Main Menu */}\n {mode === 'menu' && (\n <div className=\"space-y-3\">\n {deal.status === 'OPEN' && (\n <>\n <Button\n className=\"w-full justify-start\"\n variant=\"ghost\"\n onPress={() => setMode('win')}\n >\n <span className=\"mr-2\">🏆</span> Mark as Won\n </Button>\n <Button\n className=\"w-full justify-start\"\n variant=\"ghost\"\n onPress={() => setMode('lose')}\n >\n <span className=\"mr-2\">❌</span> Mark as Lost\n </Button>\n <Button\n className=\"w-full justify-start\"\n variant=\"ghost\"\n onPress={() => {\n setSelectedStageId(deal.stageId);\n setMode('move');\n }}\n >\n <span className=\"mr-2\">➡️</span> Move to Stage\n </Button>\n </>\n )}\n {deal.status !== 'OPEN' && (\n <p className=\"text-muted-foreground py-4 text-center\">\n This deal is already {deal.status.toLowerCase()}. No actions\n available.\n </p>\n )}\n <div className=\"border-border border-t pt-3\">\n <Button\n className=\"w-full\"\n variant=\"outline\"\n onPress={handleClose}\n >\n Close\n </Button>\n </div>\n </div>\n )}\n\n {/* Win Form */}\n {mode === 'win' && (\n <div className=\"space-y-4\">\n <div>\n <label\n htmlFor=\"won-source\"\n className=\"text-muted-foreground mb-1 block text-sm font-medium\"\n >\n How did you win this deal?\n </label>\n <select\n id=\"won-source\"\n value={wonSource}\n onChange={(e) => setWonSource(e.target.value)}\n 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\"\n >\n <option value=\"\">Select a source...</option>\n <option value=\"referral\">Referral</option>\n <option value=\"cold_outreach\">Cold Outreach</option>\n <option value=\"inbound\">Inbound Lead</option>\n <option value=\"upsell\">Upsell</option>\n <option value=\"other\">Other</option>\n </select>\n </div>\n\n <div>\n <label\n htmlFor=\"win-notes\"\n className=\"text-muted-foreground mb-1 block text-sm font-medium\"\n >\n Notes (optional)\n </label>\n <textarea\n id=\"win-notes\"\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n placeholder=\"Any additional notes about the win...\"\n rows={3}\n 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\"\n />\n </div>\n\n {error && (\n <div className=\"bg-destructive/10 text-destructive rounded-md p-3 text-sm\">\n {error}\n </div>\n )}\n\n <div className=\"flex justify-end gap-3 pt-2\">\n <Button\n variant=\"ghost\"\n onPress={() => setMode('menu')}\n disabled={isLoading}\n >\n Back\n </Button>\n <Button onPress={handleWin} disabled={isLoading}>\n {isLoading ? 'Processing...' : '🏆 Confirm Win'}\n </Button>\n </div>\n </div>\n )}\n\n {/* Lose Form */}\n {mode === 'lose' && (\n <div className=\"space-y-4\">\n <div>\n <label\n htmlFor=\"lost-reason\"\n className=\"text-muted-foreground mb-1 block text-sm font-medium\"\n >\n Why was this deal lost? *\n </label>\n <select\n id=\"lost-reason\"\n value={lostReason}\n onChange={(e) => setLostReason(e.target.value)}\n 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\"\n >\n <option value=\"\">Select a reason...</option>\n <option value=\"price\">Price too high</option>\n <option value=\"competitor\">Lost to competitor</option>\n <option value=\"no_budget\">No budget</option>\n <option value=\"no_decision\">No decision made</option>\n <option value=\"timing\">Bad timing</option>\n <option value=\"product_fit\">Product not a fit</option>\n <option value=\"other\">Other</option>\n </select>\n </div>\n\n <div>\n <label\n htmlFor=\"lose-notes\"\n className=\"text-muted-foreground mb-1 block text-sm font-medium\"\n >\n Notes (optional)\n </label>\n <textarea\n id=\"lose-notes\"\n value={notes}\n onChange={(e) => setNotes(e.target.value)}\n placeholder=\"Any additional details...\"\n rows={3}\n 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\"\n />\n </div>\n\n {error && (\n <div className=\"bg-destructive/10 text-destructive rounded-md p-3 text-sm\">\n {error}\n </div>\n )}\n\n <div className=\"flex justify-end gap-3 pt-2\">\n <Button\n variant=\"ghost\"\n onPress={() => setMode('menu')}\n disabled={isLoading}\n >\n Back\n </Button>\n <Button\n variant=\"destructive\"\n onPress={handleLose}\n disabled={isLoading}\n >\n {isLoading ? 'Processing...' : '❌ Confirm Loss'}\n </Button>\n </div>\n </div>\n )}\n\n {/* Move Form */}\n {mode === 'move' && (\n <div className=\"space-y-4\">\n <div>\n <label\n htmlFor=\"move-stage\"\n className=\"text-muted-foreground mb-1 block text-sm font-medium\"\n >\n Move to Stage\n </label>\n <select\n id=\"move-stage\"\n value={selectedStageId}\n onChange={(e) => setSelectedStageId(e.target.value)}\n 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\"\n >\n {stages.map((stage) => (\n <option key={stage.id} value={stage.id}>\n {stage.name}\n {stage.id === deal.stageId ? ' (current)' : ''}\n </option>\n ))}\n </select>\n </div>\n\n {error && (\n <div className=\"bg-destructive/10 text-destructive rounded-md p-3 text-sm\">\n {error}\n </div>\n )}\n\n <div className=\"flex justify-end gap-3 pt-2\">\n <Button\n variant=\"ghost\"\n onPress={() => setMode('menu')}\n disabled={isLoading}\n >\n Back\n </Button>\n <Button onPress={handleMove} disabled={isLoading}>\n {isLoading ? 'Moving...' : '➡️ Move Deal'}\n </Button>\n </div>\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAmDA,SAAS,eAAe,OAAe,UAA0B;AAC/D,QAAO,IAAI,KAAK,aAAa,SAAS;EACpC,OAAO;EACP;EACA,uBAAuB;EACvB,uBAAuB;EACxB,CAAC,CAAC,OAAO,MAAM;;AAGlB,SAAgB,iBAAiB,EAC/B,QACA,MACA,QACA,SACA,OACA,QACA,QACA,YAAY,SACY;CACxB,MAAM,CAAC,MAAM,WAAW,SAAqB,OAAO;CACpD,MAAM,CAAC,WAAW,gBAAgB,SAAS,GAAG;CAC9C,MAAM,CAAC,YAAY,iBAAiB,SAAS,GAAG;CAChD,MAAM,CAAC,OAAO,YAAY,SAAS,GAAG;CACtC,MAAM,CAAC,iBAAiB,sBAAsB,SAAS,GAAG;CAC1D,MAAM,CAAC,OAAO,YAAY,SAAwB,KAAK;CAEvD,MAAM,kBAAkB;AACtB,UAAQ,OAAO;AACf,eAAa,GAAG;AAChB,gBAAc,GAAG;AACjB,WAAS,GAAG;AACZ,qBAAmB,GAAG;AACtB,WAAS,KAAK;;CAGhB,MAAM,oBAAoB;AACxB,aAAW;AACX,WAAS;;CAGX,MAAM,YAAY,YAAY;AAC5B,MAAI,CAAC,KAAM;AACX,WAAS,KAAK;AAEd,MAAI;AACF,SAAM,MAAM;IACV,QAAQ,KAAK;IACb,WAAW,UAAU,MAAM,IAAI;IAC/B,OAAO,MAAM,MAAM,IAAI;IACxB,CAAC;AACF,gBAAa;WACN,KAAK;AACZ,YACE,eAAe,QAAQ,IAAI,UAAU,6BACtC;;;CAIL,MAAM,aAAa,YAAY;AAC7B,MAAI,CAAC,KAAM;AACX,WAAS,KAAK;AAEd,MAAI,CAAC,WAAW,MAAM,EAAE;AACtB,YAAS,8CAA8C;AACvD;;AAGF,MAAI;AACF,SAAM,OAAO;IACX,QAAQ,KAAK;IACb,YAAY,WAAW,MAAM;IAC7B,OAAO,MAAM,MAAM,IAAI;IACxB,CAAC;AACF,gBAAa;WACN,KAAK;AACZ,YACE,eAAe,QAAQ,IAAI,UAAU,8BACtC;;;CAIL,MAAM,aAAa,YAAY;AAC7B,MAAI,CAAC,KAAM;AACX,WAAS,KAAK;AAEd,MAAI,CAAC,iBAAiB;AACpB,YAAS,wBAAwB;AACjC;;AAGF,MAAI,oBAAoB,KAAK,SAAS;AACpC,YAAS,gCAAgC;AACzC;;AAGF,MAAI;AACF,SAAM,OAAO;IACX,QAAQ,KAAK;IACb,SAAS;IACV,CAAC;AACF,gBAAa;WACN,KAAK;AACZ,YAAS,eAAe,QAAQ,IAAI,UAAU,sBAAsB;;;AAIxE,KAAI,CAAC,UAAU,CAAC,KAAM,QAAO;AAE7B,QACE,qBAAC;EAAI,WAAU;aAEb,oBAAC;GACC,WAAU;GACV,SAAS;GACT,MAAK;GACL,UAAU;GACV,YAAY,MAAM;AAChB,QAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,IAAK,cAAa;;GAEvD,cAAW;IACX,EAGF,qBAAC;GAAI,WAAU;;IAEb,qBAAC;KAAI,WAAU;;MACb,oBAAC;OAAG,WAAU;iBAAyB,KAAK;QAAU;MACtD,oBAAC;OAAE,WAAU;iBACV,eAAe,KAAK,OAAO,KAAK,SAAS;QACxC;MACJ,oBAAC;OACC,WAAW,iEACT,KAAK,WAAW,QACZ,yEACA,KAAK,WAAW,SACd,iEACA;iBAGP,KAAK;QACD;;MACH;IAGL,SAAS,UACR,qBAAC;KAAI,WAAU;;MACZ,KAAK,WAAW,UACf;OACE,qBAAC;QACC,WAAU;QACV,SAAQ;QACR,eAAe,QAAQ,MAAM;mBAE7B,oBAAC;SAAK,WAAU;mBAAO;UAAS;SACzB;OACT,qBAAC;QACC,WAAU;QACV,SAAQ;QACR,eAAe,QAAQ,OAAO;mBAE9B,oBAAC;SAAK,WAAU;mBAAO;UAAQ;SACxB;OACT,qBAAC;QACC,WAAU;QACV,SAAQ;QACR,eAAe;AACb,4BAAmB,KAAK,QAAQ;AAChC,iBAAQ,OAAO;;mBAGjB,oBAAC;SAAK,WAAU;mBAAO;UAAS;SACzB;UACR;MAEJ,KAAK,WAAW,UACf,qBAAC;OAAE,WAAU;;QAAyC;QAC9B,KAAK,OAAO,aAAa;QAAC;;QAE9C;MAEN,oBAAC;OAAI,WAAU;iBACb,oBAAC;QACC,WAAU;QACV,SAAQ;QACR,SAAS;kBACV;SAEQ;QACL;;MACF;IAIP,SAAS,SACR,qBAAC;KAAI,WAAU;;MACb,qBAAC,oBACC,oBAAC;OACC,SAAQ;OACR,WAAU;iBACX;QAEO,EACR,qBAAC;OACC,IAAG;OACH,OAAO;OACP,WAAW,MAAM,aAAa,EAAE,OAAO,MAAM;OAC7C,WAAU;;QAEV,oBAAC;SAAO,OAAM;mBAAG;UAA2B;QAC5C,oBAAC;SAAO,OAAM;mBAAW;UAAiB;QAC1C,oBAAC;SAAO,OAAM;mBAAgB;UAAsB;QACpD,oBAAC;SAAO,OAAM;mBAAU;UAAqB;QAC7C,oBAAC;SAAO,OAAM;mBAAS;UAAe;QACtC,oBAAC;SAAO,OAAM;mBAAQ;UAAc;;QAC7B,IACL;MAEN,qBAAC,oBACC,oBAAC;OACC,SAAQ;OACR,WAAU;iBACX;QAEO,EACR,oBAAC;OACC,IAAG;OACH,OAAO;OACP,WAAW,MAAM,SAAS,EAAE,OAAO,MAAM;OACzC,aAAY;OACZ,MAAM;OACN,WAAU;QACV,IACE;MAEL,SACC,oBAAC;OAAI,WAAU;iBACZ;QACG;MAGR,qBAAC;OAAI,WAAU;kBACb,oBAAC;QACC,SAAQ;QACR,eAAe,QAAQ,OAAO;QAC9B,UAAU;kBACX;SAEQ,EACT,oBAAC;QAAO,SAAS;QAAW,UAAU;kBACnC,YAAY,kBAAkB;SACxB;QACL;;MACF;IAIP,SAAS,UACR,qBAAC;KAAI,WAAU;;MACb,qBAAC,oBACC,oBAAC;OACC,SAAQ;OACR,WAAU;iBACX;QAEO,EACR,qBAAC;OACC,IAAG;OACH,OAAO;OACP,WAAW,MAAM,cAAc,EAAE,OAAO,MAAM;OAC9C,WAAU;;QAEV,oBAAC;SAAO,OAAM;mBAAG;UAA2B;QAC5C,oBAAC;SAAO,OAAM;mBAAQ;UAAuB;QAC7C,oBAAC;SAAO,OAAM;mBAAa;UAA2B;QACtD,oBAAC;SAAO,OAAM;mBAAY;UAAkB;QAC5C,oBAAC;SAAO,OAAM;mBAAc;UAAyB;QACrD,oBAAC;SAAO,OAAM;mBAAS;UAAmB;QAC1C,oBAAC;SAAO,OAAM;mBAAc;UAA0B;QACtD,oBAAC;SAAO,OAAM;mBAAQ;UAAc;;QAC7B,IACL;MAEN,qBAAC,oBACC,oBAAC;OACC,SAAQ;OACR,WAAU;iBACX;QAEO,EACR,oBAAC;OACC,IAAG;OACH,OAAO;OACP,WAAW,MAAM,SAAS,EAAE,OAAO,MAAM;OACzC,aAAY;OACZ,MAAM;OACN,WAAU;QACV,IACE;MAEL,SACC,oBAAC;OAAI,WAAU;iBACZ;QACG;MAGR,qBAAC;OAAI,WAAU;kBACb,oBAAC;QACC,SAAQ;QACR,eAAe,QAAQ,OAAO;QAC9B,UAAU;kBACX;SAEQ,EACT,oBAAC;QACC,SAAQ;QACR,SAAS;QACT,UAAU;kBAET,YAAY,kBAAkB;SACxB;QACL;;MACF;IAIP,SAAS,UACR,qBAAC;KAAI,WAAU;;MACb,qBAAC,oBACC,oBAAC;OACC,SAAQ;OACR,WAAU;iBACX;QAEO,EACR,oBAAC;OACC,IAAG;OACH,OAAO;OACP,WAAW,MAAM,mBAAmB,EAAE,OAAO,MAAM;OACnD,WAAU;iBAET,OAAO,KAAK,UACX,qBAAC;QAAsB,OAAO,MAAM;mBACjC,MAAM,MACN,MAAM,OAAO,KAAK,UAAU,eAAe;UAFjC,MAAM,GAGV,CACT;QACK,IACL;MAEL,SACC,oBAAC;OAAI,WAAU;iBACZ;QACG;MAGR,qBAAC;OAAI,WAAU;kBACb,oBAAC;QACC,SAAQ;QACR,eAAe,QAAQ,OAAO;QAC9B,UAAU;kBACX;SAEQ,EACT,oBAAC;QAAO,SAAS;QAAY,UAAU;kBACpC,YAAY,cAAc;SACpB;QACL;;MACF;;IAEJ;GACF"}
@@ -0,0 +1,3 @@
1
+ import { CreateDealModal } from "./CreateDealModal.js";
2
+ import { DealActionsModal } from "./DealActionsModal.js";
3
+ export { CreateDealModal, DealActionsModal };
@@ -0,0 +1,4 @@
1
+ import { CreateDealModal } from "./CreateDealModal.js";
2
+ import { DealActionsModal } from "./DealActionsModal.js";
3
+
4
+ export { CreateDealModal, DealActionsModal };
@@ -0,0 +1,19 @@
1
+ import { OverlayDefinition } from "../../shared/overlay-types.js";
2
+
3
+ //#region src/ui/overlays/demo-overlays.d.ts
4
+
5
+ /**
6
+ * Demo user overlay - sample data mode
7
+ */
8
+ declare const crmDemoOverlay: OverlayDefinition;
9
+ /**
10
+ * Sales rep overlay - focused view for sales
11
+ */
12
+ declare const crmSalesRepOverlay: OverlayDefinition;
13
+ /**
14
+ * All overlays for crm-pipeline
15
+ */
16
+ declare const crmOverlays: OverlayDefinition[];
17
+ //#endregion
18
+ export { crmDemoOverlay, crmOverlays, crmSalesRepOverlay };
19
+ //# sourceMappingURL=demo-overlays.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demo-overlays.d.ts","names":[],"sources":["../../../src/ui/overlays/demo-overlays.ts"],"sourcesContent":[],"mappings":";;;;;;;cAWa,gBAAgB;;;;cA+BhB,oBAAoB;;;;cAsBpB,aAAa"}
@@ -0,0 +1,68 @@
1
+ //#region src/ui/overlays/demo-overlays.ts
2
+ /**
3
+ * Demo user overlay - sample data mode
4
+ */
5
+ const crmDemoOverlay = {
6
+ overlayId: "crm-pipeline.demo-user",
7
+ version: "1.0.0",
8
+ description: "Demo mode with sample data",
9
+ appliesTo: {
10
+ feature: "crm-pipeline",
11
+ role: "demo"
12
+ },
13
+ modifications: [
14
+ {
15
+ type: "hideField",
16
+ field: "importButton",
17
+ reason: "Not available in demo"
18
+ },
19
+ {
20
+ type: "hideField",
21
+ field: "exportButton",
22
+ reason: "Not available in demo"
23
+ },
24
+ {
25
+ type: "addBadge",
26
+ position: "header",
27
+ label: "Demo Mode",
28
+ variant: "warning"
29
+ }
30
+ ]
31
+ };
32
+ /**
33
+ * Sales rep overlay - focused view for sales
34
+ */
35
+ const crmSalesRepOverlay = {
36
+ overlayId: "crm-pipeline.sales-rep",
37
+ version: "1.0.0",
38
+ description: "Sales rep focused view",
39
+ appliesTo: {
40
+ feature: "crm-pipeline",
41
+ role: "sales-rep"
42
+ },
43
+ modifications: [
44
+ {
45
+ type: "hideField",
46
+ field: "teamMetrics",
47
+ reason: "Team metrics for managers only"
48
+ },
49
+ {
50
+ type: "hideField",
51
+ field: "pipelineSettings",
52
+ reason: "Admin only"
53
+ },
54
+ {
55
+ type: "renameLabel",
56
+ field: "deals",
57
+ newLabel: "My Deals"
58
+ }
59
+ ]
60
+ };
61
+ /**
62
+ * All overlays for crm-pipeline
63
+ */
64
+ const crmOverlays = [crmDemoOverlay, crmSalesRepOverlay];
65
+
66
+ //#endregion
67
+ export { crmDemoOverlay, crmOverlays, crmSalesRepOverlay };
68
+ //# sourceMappingURL=demo-overlays.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demo-overlays.js","names":[],"sources":["../../../src/ui/overlays/demo-overlays.ts"],"sourcesContent":["/**\n * Demo Overlay Definitions for CRM Pipeline\n *\n * These overlays customize the presentation for different contexts\n * (e.g., demo users, different roles).\n */\nimport type { OverlayDefinition } from '../../shared/overlay-types';\n\n/**\n * Demo user overlay - sample data mode\n */\nexport const crmDemoOverlay: OverlayDefinition = {\n overlayId: 'crm-pipeline.demo-user',\n version: '1.0.0',\n description: 'Demo mode with sample data',\n appliesTo: {\n feature: 'crm-pipeline',\n role: 'demo',\n },\n modifications: [\n {\n type: 'hideField',\n field: 'importButton',\n reason: 'Not available in demo',\n },\n {\n type: 'hideField',\n field: 'exportButton',\n reason: 'Not available in demo',\n },\n {\n type: 'addBadge',\n position: 'header',\n label: 'Demo Mode',\n variant: 'warning',\n },\n ],\n};\n\n/**\n * Sales rep overlay - focused view for sales\n */\nexport const crmSalesRepOverlay: OverlayDefinition = {\n overlayId: 'crm-pipeline.sales-rep',\n version: '1.0.0',\n description: 'Sales rep focused view',\n appliesTo: {\n feature: 'crm-pipeline',\n role: 'sales-rep',\n },\n modifications: [\n {\n type: 'hideField',\n field: 'teamMetrics',\n reason: 'Team metrics for managers only',\n },\n { type: 'hideField', field: 'pipelineSettings', reason: 'Admin only' },\n { type: 'renameLabel', field: 'deals', newLabel: 'My Deals' },\n ],\n};\n\n/**\n * All overlays for crm-pipeline\n */\nexport const crmOverlays: OverlayDefinition[] = [\n crmDemoOverlay,\n crmSalesRepOverlay,\n];\n"],"mappings":";;;;AAWA,MAAa,iBAAoC;CAC/C,WAAW;CACX,SAAS;CACT,aAAa;CACb,WAAW;EACT,SAAS;EACT,MAAM;EACP;CACD,eAAe;EACb;GACE,MAAM;GACN,OAAO;GACP,QAAQ;GACT;EACD;GACE,MAAM;GACN,OAAO;GACP,QAAQ;GACT;EACD;GACE,MAAM;GACN,UAAU;GACV,OAAO;GACP,SAAS;GACV;EACF;CACF;;;;AAKD,MAAa,qBAAwC;CACnD,WAAW;CACX,SAAS;CACT,aAAa;CACb,WAAW;EACT,SAAS;EACT,MAAM;EACP;CACD,eAAe;EACb;GACE,MAAM;GACN,OAAO;GACP,QAAQ;GACT;EACD;GAAE,MAAM;GAAa,OAAO;GAAoB,QAAQ;GAAc;EACtE;GAAE,MAAM;GAAe,OAAO;GAAS,UAAU;GAAY;EAC9D;CACF;;;;AAKD,MAAa,cAAmC,CAC9C,gBACA,mBACD"}
@@ -0,0 +1,2 @@
1
+ import { crmDemoOverlay, crmOverlays, crmSalesRepOverlay } from "./demo-overlays.js";
2
+ export { crmDemoOverlay, crmOverlays, crmSalesRepOverlay };
@@ -0,0 +1,3 @@
1
+ import { crmDemoOverlay, crmOverlays, crmSalesRepOverlay } from "./demo-overlays.js";
2
+
3
+ export { crmDemoOverlay, crmOverlays, crmSalesRepOverlay };
@@ -0,0 +1,3 @@
1
+ import { crmPipelineReactRenderer } from "./pipeline.renderer.js";
2
+ import { crmDashboardMarkdownRenderer, crmPipelineMarkdownRenderer } from "./pipeline.markdown.js";
3
+ export { crmDashboardMarkdownRenderer, crmPipelineMarkdownRenderer, crmPipelineReactRenderer };
@@ -0,0 +1,4 @@
1
+ import { crmPipelineReactRenderer } from "./pipeline.renderer.js";
2
+ import { crmDashboardMarkdownRenderer, crmPipelineMarkdownRenderer } from "./pipeline.markdown.js";
3
+
4
+ export { crmDashboardMarkdownRenderer, crmPipelineMarkdownRenderer, crmPipelineReactRenderer };
@@ -0,0 +1,23 @@
1
+ import { PresentationRenderer } from "@contractspec/lib.contracts";
2
+
3
+ //#region src/ui/renderers/pipeline.markdown.d.ts
4
+
5
+ /**
6
+ * Markdown renderer for CRM Pipeline Kanban view (crm-pipeline.deal.pipeline)
7
+ * Only handles PipelineKanbanView component
8
+ */
9
+ declare const crmPipelineMarkdownRenderer: PresentationRenderer<{
10
+ mimeType: string;
11
+ body: string;
12
+ }>;
13
+ /**
14
+ * Markdown renderer for CRM Dashboard (crm-pipeline.dashboard)
15
+ * Only handles CrmDashboard component
16
+ */
17
+ declare const crmDashboardMarkdownRenderer: PresentationRenderer<{
18
+ mimeType: string;
19
+ body: string;
20
+ }>;
21
+ //#endregion
22
+ export { crmDashboardMarkdownRenderer, crmPipelineMarkdownRenderer };
23
+ //# sourceMappingURL=pipeline.markdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pipeline.markdown.d.ts","names":[],"sources":["../../../src/ui/renderers/pipeline.markdown.ts"],"sourcesContent":[],"mappings":";;;;;;;;cAsCa,6BAA6B;;;;;;;;cA0E7B,8BAA8B"}