@aglyn/plugins-crm 1.0.0-beta.143

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 (669) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +7 -0
  3. package/package.json +57 -0
  4. package/src/index.d.ts +21 -0
  5. package/src/index.js +29 -0
  6. package/src/index.js.map +1 -0
  7. package/src/lib/components/activity-list.d.ts +98 -0
  8. package/src/lib/components/activity-list.js +321 -0
  9. package/src/lib/components/activity-list.js.map +1 -0
  10. package/src/lib/components/activity-queries.d.ts +117 -0
  11. package/src/lib/components/activity-queries.js +198 -0
  12. package/src/lib/components/activity-queries.js.map +1 -0
  13. package/src/lib/components/add-to-list-button.d.ts +25 -0
  14. package/src/lib/components/add-to-list-button.js +64 -0
  15. package/src/lib/components/add-to-list-button.js.map +1 -0
  16. package/src/lib/components/add-to-list-dialog.d.ts +24 -0
  17. package/src/lib/components/add-to-list-dialog.js +327 -0
  18. package/src/lib/components/add-to-list-dialog.js.map +1 -0
  19. package/src/lib/components/assignment-rule-drawer.d.ts +43 -0
  20. package/src/lib/components/assignment-rule-drawer.js +293 -0
  21. package/src/lib/components/assignment-rule-drawer.js.map +1 -0
  22. package/src/lib/components/companies-bulk-bar.d.ts +29 -0
  23. package/src/lib/components/companies-bulk-bar.js +274 -0
  24. package/src/lib/components/companies-bulk-bar.js.map +1 -0
  25. package/src/lib/components/companies-section.d.ts +54 -0
  26. package/src/lib/components/companies-section.js +522 -0
  27. package/src/lib/components/companies-section.js.map +1 -0
  28. package/src/lib/components/company-contacts-card.d.ts +49 -0
  29. package/src/lib/components/company-contacts-card.js +435 -0
  30. package/src/lib/components/company-contacts-card.js.map +1 -0
  31. package/src/lib/components/company-deals-card.d.ts +20 -0
  32. package/src/lib/components/company-deals-card.js +38 -0
  33. package/src/lib/components/company-deals-card.js.map +1 -0
  34. package/src/lib/components/company-detail-page.d.ts +20 -0
  35. package/src/lib/components/company-detail-page.js +165 -0
  36. package/src/lib/components/company-detail-page.js.map +1 -0
  37. package/src/lib/components/company-edit-drawer.d.ts +65 -0
  38. package/src/lib/components/company-edit-drawer.js +433 -0
  39. package/src/lib/components/company-edit-drawer.js.map +1 -0
  40. package/src/lib/components/company-import-drawer.d.ts +42 -0
  41. package/src/lib/components/company-import-drawer.js +99 -0
  42. package/src/lib/components/company-import-drawer.js.map +1 -0
  43. package/src/lib/components/company-picker.d.ts +127 -0
  44. package/src/lib/components/company-picker.js +323 -0
  45. package/src/lib/components/company-picker.js.map +1 -0
  46. package/src/lib/components/company-properties-card.d.ts +47 -0
  47. package/src/lib/components/company-properties-card.js +289 -0
  48. package/src/lib/components/company-properties-card.js.map +1 -0
  49. package/src/lib/components/contact-address-fields.d.ts +29 -0
  50. package/src/lib/components/contact-address-fields.js +149 -0
  51. package/src/lib/components/contact-address-fields.js.map +1 -0
  52. package/src/lib/components/contact-associations-card.d.ts +72 -0
  53. package/src/lib/components/contact-associations-card.js +296 -0
  54. package/src/lib/components/contact-associations-card.js.map +1 -0
  55. package/src/lib/components/contact-custom-columns.d.ts +38 -0
  56. package/src/lib/components/contact-custom-columns.js +102 -0
  57. package/src/lib/components/contact-custom-columns.js.map +1 -0
  58. package/src/lib/components/contact-custom-fields-card.d.ts +39 -0
  59. package/src/lib/components/contact-custom-fields-card.js +204 -0
  60. package/src/lib/components/contact-custom-fields-card.js.map +1 -0
  61. package/src/lib/components/contact-deals-card.d.ts +20 -0
  62. package/src/lib/components/contact-deals-card.js +38 -0
  63. package/src/lib/components/contact-deals-card.js.map +1 -0
  64. package/src/lib/components/contact-detail-page.d.ts +46 -0
  65. package/src/lib/components/contact-detail-page.js +535 -0
  66. package/src/lib/components/contact-detail-page.js.map +1 -0
  67. package/src/lib/components/contact-duplicates-card.d.ts +42 -0
  68. package/src/lib/components/contact-duplicates-card.js +167 -0
  69. package/src/lib/components/contact-duplicates-card.js.map +1 -0
  70. package/src/lib/components/contact-field-drawer.d.ts +64 -0
  71. package/src/lib/components/contact-field-drawer.js +251 -0
  72. package/src/lib/components/contact-field-drawer.js.map +1 -0
  73. package/src/lib/components/contact-import-drawer.d.ts +46 -0
  74. package/src/lib/components/contact-import-drawer.js +149 -0
  75. package/src/lib/components/contact-import-drawer.js.map +1 -0
  76. package/src/lib/components/contact-known-by-card.d.ts +39 -0
  77. package/src/lib/components/contact-known-by-card.js +142 -0
  78. package/src/lib/components/contact-known-by-card.js.map +1 -0
  79. package/src/lib/components/contact-list-columns.d.ts +53 -0
  80. package/src/lib/components/contact-list-columns.js +288 -0
  81. package/src/lib/components/contact-list-columns.js.map +1 -0
  82. package/src/lib/components/contact-merge-dialog.d.ts +79 -0
  83. package/src/lib/components/contact-merge-dialog.js +405 -0
  84. package/src/lib/components/contact-merge-dialog.js.map +1 -0
  85. package/src/lib/components/contact-properties-card.d.ts +89 -0
  86. package/src/lib/components/contact-properties-card.js +492 -0
  87. package/src/lib/components/contact-properties-card.js.map +1 -0
  88. package/src/lib/components/contact-timeline-card.d.ts +68 -0
  89. package/src/lib/components/contact-timeline-card.js +435 -0
  90. package/src/lib/components/contact-timeline-card.js.map +1 -0
  91. package/src/lib/components/contacts-bulk-bar.d.ts +91 -0
  92. package/src/lib/components/contacts-bulk-bar.js +493 -0
  93. package/src/lib/components/contacts-bulk-bar.js.map +1 -0
  94. package/src/lib/components/contacts-section.d.ts +26 -0
  95. package/src/lib/components/contacts-section.js +1025 -0
  96. package/src/lib/components/contacts-section.js.map +1 -0
  97. package/src/lib/components/copy-capture-address-button.d.ts +33 -0
  98. package/src/lib/components/copy-capture-address-button.js +60 -0
  99. package/src/lib/components/copy-capture-address-button.js.map +1 -0
  100. package/src/lib/components/crm-attribution-zone.d.ts +38 -0
  101. package/src/lib/components/crm-attribution-zone.js +36 -0
  102. package/src/lib/components/crm-attribution-zone.js.map +1 -0
  103. package/src/lib/components/crm-booking-zone.d.ts +61 -0
  104. package/src/lib/components/crm-booking-zone.js +50 -0
  105. package/src/lib/components/crm-booking-zone.js.map +1 -0
  106. package/src/lib/components/crm-bulk-bar-frame.d.ts +47 -0
  107. package/src/lib/components/crm-bulk-bar-frame.js +137 -0
  108. package/src/lib/components/crm-bulk-bar-frame.js.map +1 -0
  109. package/src/lib/components/crm-call-actions.d.ts +65 -0
  110. package/src/lib/components/crm-call-actions.js +110 -0
  111. package/src/lib/components/crm-call-actions.js.map +1 -0
  112. package/src/lib/components/crm-column-menu.d.ts +21 -0
  113. package/src/lib/components/crm-column-menu.js +103 -0
  114. package/src/lib/components/crm-column-menu.js.map +1 -0
  115. package/src/lib/components/crm-console-page.d.ts +19 -0
  116. package/src/lib/components/crm-console-page.js +151 -0
  117. package/src/lib/components/crm-console-page.js.map +1 -0
  118. package/src/lib/components/crm-console-sections.d.ts +52 -0
  119. package/src/lib/components/crm-console-sections.js +83 -0
  120. package/src/lib/components/crm-console-sections.js.map +1 -0
  121. package/src/lib/components/crm-custom-field-control.d.ts +26 -0
  122. package/src/lib/components/crm-custom-field-control.js +131 -0
  123. package/src/lib/components/crm-custom-field-control.js.map +1 -0
  124. package/src/lib/components/crm-email-template-tools.d.ts +69 -0
  125. package/src/lib/components/crm-email-template-tools.js +240 -0
  126. package/src/lib/components/crm-email-template-tools.js.map +1 -0
  127. package/src/lib/components/crm-export-all-button.d.ts +39 -0
  128. package/src/lib/components/crm-export-all-button.js +98 -0
  129. package/src/lib/components/crm-export-all-button.js.map +1 -0
  130. package/src/lib/components/crm-filter-bar.d.ts +53 -0
  131. package/src/lib/components/crm-filter-bar.js +294 -0
  132. package/src/lib/components/crm-filter-bar.js.map +1 -0
  133. package/src/lib/components/crm-glance-card.d.ts +54 -0
  134. package/src/lib/components/crm-glance-card.js +219 -0
  135. package/src/lib/components/crm-glance-card.js.map +1 -0
  136. package/src/lib/components/crm-next-activity-column.d.ts +35 -0
  137. package/src/lib/components/crm-next-activity-column.js +100 -0
  138. package/src/lib/components/crm-next-activity-column.js.map +1 -0
  139. package/src/lib/components/crm-record-header.d.ts +97 -0
  140. package/src/lib/components/crm-record-header.js +160 -0
  141. package/src/lib/components/crm-record-header.js.map +1 -0
  142. package/src/lib/components/crm-record-insights-zone.d.ts +50 -0
  143. package/src/lib/components/crm-record-insights-zone.js +169 -0
  144. package/src/lib/components/crm-record-insights-zone.js.map +1 -0
  145. package/src/lib/components/crm-record-picker.d.ts +42 -0
  146. package/src/lib/components/crm-record-picker.js +104 -0
  147. package/src/lib/components/crm-record-picker.js.map +1 -0
  148. package/src/lib/components/crm-send-email-button.d.ts +39 -0
  149. package/src/lib/components/crm-send-email-button.js +81 -0
  150. package/src/lib/components/crm-send-email-button.js.map +1 -0
  151. package/src/lib/components/crm-send-email-dialog.d.ts +61 -0
  152. package/src/lib/components/crm-send-email-dialog.js +851 -0
  153. package/src/lib/components/crm-send-email-dialog.js.map +1 -0
  154. package/src/lib/components/crm-site-picker.d.ts +61 -0
  155. package/src/lib/components/crm-site-picker.js +99 -0
  156. package/src/lib/components/crm-site-picker.js.map +1 -0
  157. package/src/lib/components/crm-suite-lock.d.ts +29 -0
  158. package/src/lib/components/crm-suite-lock.js +114 -0
  159. package/src/lib/components/crm-suite-lock.js.map +1 -0
  160. package/src/lib/components/crm-tasks-due-card.d.ts +42 -0
  161. package/src/lib/components/crm-tasks-due-card.js +225 -0
  162. package/src/lib/components/crm-tasks-due-card.js.map +1 -0
  163. package/src/lib/components/crm-views-control.d.ts +65 -0
  164. package/src/lib/components/crm-views-control.js +518 -0
  165. package/src/lib/components/crm-views-control.js.map +1 -0
  166. package/src/lib/components/csv-import-drawer.d.ts +132 -0
  167. package/src/lib/components/csv-import-drawer.js +746 -0
  168. package/src/lib/components/csv-import-drawer.js.map +1 -0
  169. package/src/lib/components/deal-board.d.ts +70 -0
  170. package/src/lib/components/deal-board.js +478 -0
  171. package/src/lib/components/deal-board.js.map +1 -0
  172. package/src/lib/components/deal-detail-page.d.ts +18 -0
  173. package/src/lib/components/deal-detail-page.js +323 -0
  174. package/src/lib/components/deal-detail-page.js.map +1 -0
  175. package/src/lib/components/deal-edit-drawer.d.ts +59 -0
  176. package/src/lib/components/deal-edit-drawer.js +640 -0
  177. package/src/lib/components/deal-edit-drawer.js.map +1 -0
  178. package/src/lib/components/deal-import-drawer.d.ts +24 -0
  179. package/src/lib/components/deal-import-drawer.js +83 -0
  180. package/src/lib/components/deal-import-drawer.js.map +1 -0
  181. package/src/lib/components/deal-products-card.d.ts +48 -0
  182. package/src/lib/components/deal-products-card.js +614 -0
  183. package/src/lib/components/deal-products-card.js.map +1 -0
  184. package/src/lib/components/deal-properties-card.d.ts +29 -0
  185. package/src/lib/components/deal-properties-card.js +144 -0
  186. package/src/lib/components/deal-properties-card.js.map +1 -0
  187. package/src/lib/components/deal-stage-card.d.ts +24 -0
  188. package/src/lib/components/deal-stage-card.js +199 -0
  189. package/src/lib/components/deal-stage-card.js.map +1 -0
  190. package/src/lib/components/deals-bulk-bar.d.ts +31 -0
  191. package/src/lib/components/deals-bulk-bar.js +340 -0
  192. package/src/lib/components/deals-bulk-bar.js.map +1 -0
  193. package/src/lib/components/deals-section.d.ts +49 -0
  194. package/src/lib/components/deals-section.js +767 -0
  195. package/src/lib/components/deals-section.js.map +1 -0
  196. package/src/lib/components/email-capture-card.d.ts +42 -0
  197. package/src/lib/components/email-capture-card.js +134 -0
  198. package/src/lib/components/email-capture-card.js.map +1 -0
  199. package/src/lib/components/email-template-drawer.d.ts +33 -0
  200. package/src/lib/components/email-template-drawer.js +209 -0
  201. package/src/lib/components/email-template-drawer.js.map +1 -0
  202. package/src/lib/components/email-templates-card.d.ts +33 -0
  203. package/src/lib/components/email-templates-card.js +370 -0
  204. package/src/lib/components/email-templates-card.js.map +1 -0
  205. package/src/lib/components/erase-person-action.d.ts +92 -0
  206. package/src/lib/components/erase-person-action.js +261 -0
  207. package/src/lib/components/erase-person-action.js.map +1 -0
  208. package/src/lib/components/fields-section.d.ts +37 -0
  209. package/src/lib/components/fields-section.js +641 -0
  210. package/src/lib/components/fields-section.js.map +1 -0
  211. package/src/lib/components/form-contact-fields-card.d.ts +46 -0
  212. package/src/lib/components/form-contact-fields-card.js +253 -0
  213. package/src/lib/components/form-contact-fields-card.js.map +1 -0
  214. package/src/lib/components/insert-link-at-caret.d.ts +28 -0
  215. package/src/lib/components/insert-link-at-caret.js +37 -0
  216. package/src/lib/components/insert-link-at-caret.js.map +1 -0
  217. package/src/lib/components/lead-convert-dialog.d.ts +32 -0
  218. package/src/lib/components/lead-convert-dialog.js +493 -0
  219. package/src/lib/components/lead-convert-dialog.js.map +1 -0
  220. package/src/lib/components/lead-detail-page.d.ts +16 -0
  221. package/src/lib/components/lead-detail-page.js +163 -0
  222. package/src/lib/components/lead-detail-page.js.map +1 -0
  223. package/src/lib/components/lead-history-card.d.ts +32 -0
  224. package/src/lib/components/lead-history-card.js +165 -0
  225. package/src/lib/components/lead-history-card.js.map +1 -0
  226. package/src/lib/components/lead-import-drawer.d.ts +24 -0
  227. package/src/lib/components/lead-import-drawer.js +95 -0
  228. package/src/lib/components/lead-import-drawer.js.map +1 -0
  229. package/src/lib/components/lead-owner-select.d.ts +35 -0
  230. package/src/lib/components/lead-owner-select.js +91 -0
  231. package/src/lib/components/lead-owner-select.js.map +1 -0
  232. package/src/lib/components/lead-properties-card.d.ts +61 -0
  233. package/src/lib/components/lead-properties-card.js +395 -0
  234. package/src/lib/components/lead-properties-card.js.map +1 -0
  235. package/src/lib/components/lead-status-chip.d.ts +12 -0
  236. package/src/lib/components/lead-status-chip.js +43 -0
  237. package/src/lib/components/lead-status-chip.js.map +1 -0
  238. package/src/lib/components/lead-surfaces-note.d.ts +126 -0
  239. package/src/lib/components/lead-surfaces-note.js +262 -0
  240. package/src/lib/components/lead-surfaces-note.js.map +1 -0
  241. package/src/lib/components/lead-unqualify-dialog.d.ts +24 -0
  242. package/src/lib/components/lead-unqualify-dialog.js +125 -0
  243. package/src/lib/components/lead-unqualify-dialog.js.map +1 -0
  244. package/src/lib/components/leads-bulk-bar.d.ts +58 -0
  245. package/src/lib/components/leads-bulk-bar.js +307 -0
  246. package/src/lib/components/leads-bulk-bar.js.map +1 -0
  247. package/src/lib/components/leads-section.d.ts +23 -0
  248. package/src/lib/components/leads-section.js +664 -0
  249. package/src/lib/components/leads-section.js.map +1 -0
  250. package/src/lib/components/linked-deals-card.d.ts +32 -0
  251. package/src/lib/components/linked-deals-card.js +163 -0
  252. package/src/lib/components/linked-deals-card.js.map +1 -0
  253. package/src/lib/components/log-activity-dialog.d.ts +60 -0
  254. package/src/lib/components/log-activity-dialog.js +368 -0
  255. package/src/lib/components/log-activity-dialog.js.map +1 -0
  256. package/src/lib/components/lost-reason-dialog.d.ts +26 -0
  257. package/src/lib/components/lost-reason-dialog.js +95 -0
  258. package/src/lib/components/lost-reason-dialog.js.map +1 -0
  259. package/src/lib/components/new-contact-drawer.d.ts +78 -0
  260. package/src/lib/components/new-contact-drawer.js +343 -0
  261. package/src/lib/components/new-contact-drawer.js.map +1 -0
  262. package/src/lib/components/org-lead-surfaces-note.d.ts +57 -0
  263. package/src/lib/components/org-lead-surfaces-note.js +172 -0
  264. package/src/lib/components/org-lead-surfaces-note.js.map +1 -0
  265. package/src/lib/components/owner-avatar.d.ts +18 -0
  266. package/src/lib/components/owner-avatar.js +61 -0
  267. package/src/lib/components/owner-avatar.js.map +1 -0
  268. package/src/lib/components/pipeline-stages-dialog.d.ts +43 -0
  269. package/src/lib/components/pipeline-stages-dialog.js +339 -0
  270. package/src/lib/components/pipeline-stages-dialog.js.map +1 -0
  271. package/src/lib/components/pipelines-dialog.d.ts +55 -0
  272. package/src/lib/components/pipelines-dialog.js +517 -0
  273. package/src/lib/components/pipelines-dialog.js.map +1 -0
  274. package/src/lib/components/recent-activity-feed.d.ts +39 -0
  275. package/src/lib/components/recent-activity-feed.js +103 -0
  276. package/src/lib/components/recent-activity-feed.js.map +1 -0
  277. package/src/lib/components/recipes-card.d.ts +39 -0
  278. package/src/lib/components/recipes-card.js +485 -0
  279. package/src/lib/components/recipes-card.js.map +1 -0
  280. package/src/lib/components/record-activity-card.d.ts +26 -0
  281. package/src/lib/components/record-activity-card.js +121 -0
  282. package/src/lib/components/record-activity-card.js.map +1 -0
  283. package/src/lib/components/record-files-card.d.ts +67 -0
  284. package/src/lib/components/record-files-card.js +290 -0
  285. package/src/lib/components/record-files-card.js.map +1 -0
  286. package/src/lib/components/record-tasks-card.d.ts +32 -0
  287. package/src/lib/components/record-tasks-card.js +306 -0
  288. package/src/lib/components/record-tasks-card.js.map +1 -0
  289. package/src/lib/components/reports/activity-card.d.ts +57 -0
  290. package/src/lib/components/reports/activity-card.js +281 -0
  291. package/src/lib/components/reports/activity-card.js.map +1 -0
  292. package/src/lib/components/reports/closed-deals-card.d.ts +20 -0
  293. package/src/lib/components/reports/closed-deals-card.js +194 -0
  294. package/src/lib/components/reports/closed-deals-card.js.map +1 -0
  295. package/src/lib/components/reports/contacts-mix-card.d.ts +27 -0
  296. package/src/lib/components/reports/contacts-mix-card.js +161 -0
  297. package/src/lib/components/reports/contacts-mix-card.js.map +1 -0
  298. package/src/lib/components/reports/contacts-trend-card.d.ts +31 -0
  299. package/src/lib/components/reports/contacts-trend-card.js +144 -0
  300. package/src/lib/components/reports/contacts-trend-card.js.map +1 -0
  301. package/src/lib/components/reports/forecast-card.d.ts +22 -0
  302. package/src/lib/components/reports/forecast-card.js +251 -0
  303. package/src/lib/components/reports/forecast-card.js.map +1 -0
  304. package/src/lib/components/reports/lead-counts.d.ts +32 -0
  305. package/src/lib/components/reports/lead-counts.js +44 -0
  306. package/src/lib/components/reports/lead-counts.js.map +1 -0
  307. package/src/lib/components/reports/lead-funnel-card.d.ts +38 -0
  308. package/src/lib/components/reports/lead-funnel-card.js +375 -0
  309. package/src/lib/components/reports/lead-funnel-card.js.map +1 -0
  310. package/src/lib/components/reports/pipeline-card.d.ts +19 -0
  311. package/src/lib/components/reports/pipeline-card.js +338 -0
  312. package/src/lib/components/reports/pipeline-card.js.map +1 -0
  313. package/src/lib/components/reports/report-bar-chart.d.ts +39 -0
  314. package/src/lib/components/reports/report-bar-chart.js +133 -0
  315. package/src/lib/components/reports/report-bar-chart.js.map +1 -0
  316. package/src/lib/components/reports/report-breakdown.d.ts +32 -0
  317. package/src/lib/components/reports/report-breakdown.js +105 -0
  318. package/src/lib/components/reports/report-breakdown.js.map +1 -0
  319. package/src/lib/components/reports/report-export.d.ts +37 -0
  320. package/src/lib/components/reports/report-export.js +66 -0
  321. package/src/lib/components/reports/report-export.js.map +1 -0
  322. package/src/lib/components/reports/report-format.d.ts +36 -0
  323. package/src/lib/components/reports/report-format.js +43 -0
  324. package/src/lib/components/reports/report-format.js.map +1 -0
  325. package/src/lib/components/reports/report-scope.d.ts +81 -0
  326. package/src/lib/components/reports/report-scope.js +58 -0
  327. package/src/lib/components/reports/report-scope.js.map +1 -0
  328. package/src/lib/components/reports/report-stat-tile.d.ts +47 -0
  329. package/src/lib/components/reports/report-stat-tile.js +96 -0
  330. package/src/lib/components/reports/report-stat-tile.js.map +1 -0
  331. package/src/lib/components/reports/source-conversion-card.d.ts +28 -0
  332. package/src/lib/components/reports/source-conversion-card.js +205 -0
  333. package/src/lib/components/reports/source-conversion-card.js.map +1 -0
  334. package/src/lib/components/reports/tasks-card.d.ts +26 -0
  335. package/src/lib/components/reports/tasks-card.js +279 -0
  336. package/src/lib/components/reports/tasks-card.js.map +1 -0
  337. package/src/lib/components/reports/use-aggregate-read.d.ts +99 -0
  338. package/src/lib/components/reports/use-aggregate-read.js +195 -0
  339. package/src/lib/components/reports/use-aggregate-read.js.map +1 -0
  340. package/src/lib/components/reports/won-lost-by-owner-card.d.ts +30 -0
  341. package/src/lib/components/reports/won-lost-by-owner-card.js +168 -0
  342. package/src/lib/components/reports/won-lost-by-owner-card.js.map +1 -0
  343. package/src/lib/components/reports-section.d.ts +42 -0
  344. package/src/lib/components/reports-section.js +308 -0
  345. package/src/lib/components/reports-section.js.map +1 -0
  346. package/src/lib/components/sending-addresses-card.d.ts +49 -0
  347. package/src/lib/components/sending-addresses-card.js +262 -0
  348. package/src/lib/components/sending-addresses-card.js.map +1 -0
  349. package/src/lib/components/settings-section.d.ts +151 -0
  350. package/src/lib/components/settings-section.js +783 -0
  351. package/src/lib/components/settings-section.js.map +1 -0
  352. package/src/lib/components/task-cells.d.ts +51 -0
  353. package/src/lib/components/task-cells.js +139 -0
  354. package/src/lib/components/task-cells.js.map +1 -0
  355. package/src/lib/components/task-edit-drawer.d.ts +53 -0
  356. package/src/lib/components/task-edit-drawer.js +483 -0
  357. package/src/lib/components/task-edit-drawer.js.map +1 -0
  358. package/src/lib/components/task-import-drawer.d.ts +24 -0
  359. package/src/lib/components/task-import-drawer.js +82 -0
  360. package/src/lib/components/task-import-drawer.js.map +1 -0
  361. package/src/lib/components/task-snooze-menu.d.ts +65 -0
  362. package/src/lib/components/task-snooze-menu.js +207 -0
  363. package/src/lib/components/task-snooze-menu.js.map +1 -0
  364. package/src/lib/components/tasks-bulk-bar.d.ts +25 -0
  365. package/src/lib/components/tasks-bulk-bar.js +348 -0
  366. package/src/lib/components/tasks-bulk-bar.js.map +1 -0
  367. package/src/lib/components/tasks-calendar.d.ts +38 -0
  368. package/src/lib/components/tasks-calendar.js +228 -0
  369. package/src/lib/components/tasks-calendar.js.map +1 -0
  370. package/src/lib/components/tasks-section.d.ts +27 -0
  371. package/src/lib/components/tasks-section.js +579 -0
  372. package/src/lib/components/tasks-section.js.map +1 -0
  373. package/src/lib/components/use-contact-campaign-emails.d.ts +32 -0
  374. package/src/lib/components/use-contact-campaign-emails.js +83 -0
  375. package/src/lib/components/use-contact-campaign-emails.js.map +1 -0
  376. package/src/lib/components/use-crm-api.d.ts +44 -0
  377. package/src/lib/components/use-crm-api.js +84 -0
  378. package/src/lib/components/use-crm-api.js.map +1 -0
  379. package/src/lib/components/use-crm-inbound-address.d.ts +60 -0
  380. package/src/lib/components/use-crm-inbound-address.js +124 -0
  381. package/src/lib/components/use-crm-inbound-address.js.map +1 -0
  382. package/src/lib/components/use-emails-hub-path.d.ts +24 -0
  383. package/src/lib/components/use-emails-hub-path.js +59 -0
  384. package/src/lib/components/use-emails-hub-path.js.map +1 -0
  385. package/src/lib/components/use-member-email-aliases.d.ts +54 -0
  386. package/src/lib/components/use-member-email-aliases.js +186 -0
  387. package/src/lib/components/use-member-email-aliases.js.map +1 -0
  388. package/src/lib/components/use-org-members.d.ts +40 -0
  389. package/src/lib/components/use-org-members.js +100 -0
  390. package/src/lib/components/use-org-members.js.map +1 -0
  391. package/src/lib/constants/api-routes.d.ts +109 -0
  392. package/src/lib/constants/api-routes.js +74 -0
  393. package/src/lib/constants/api-routes.js.map +1 -0
  394. package/src/lib/constants/bundle-common.d.ts +14 -0
  395. package/src/lib/constants/bundle-common.js +14 -0
  396. package/src/lib/constants/bundle-common.js.map +1 -0
  397. package/src/lib/constants/company-filters.d.ts +18 -0
  398. package/src/lib/constants/company-filters.js +51 -0
  399. package/src/lib/constants/company-filters.js.map +1 -0
  400. package/src/lib/constants/contact-filters.d.ts +38 -0
  401. package/src/lib/constants/contact-filters.js +294 -0
  402. package/src/lib/constants/contact-filters.js.map +1 -0
  403. package/src/lib/hooks/use-contact-field-definitions.d.ts +48 -0
  404. package/src/lib/hooks/use-contact-field-definitions.js +72 -0
  405. package/src/lib/hooks/use-contact-field-definitions.js.map +1 -0
  406. package/src/lib/hooks/use-contact-update.d.ts +25 -0
  407. package/src/lib/hooks/use-contact-update.js +80 -0
  408. package/src/lib/hooks/use-contact-update.js.map +1 -0
  409. package/src/lib/hooks/use-crm-activity-logger.d.ts +73 -0
  410. package/src/lib/hooks/use-crm-activity-logger.js +101 -0
  411. package/src/lib/hooks/use-crm-activity-logger.js.map +1 -0
  412. package/src/lib/hooks/use-crm-bulk-apply.d.ts +52 -0
  413. package/src/lib/hooks/use-crm-bulk-apply.js +112 -0
  414. package/src/lib/hooks/use-crm-bulk-apply.js.map +1 -0
  415. package/src/lib/hooks/use-crm-default-view.d.ts +24 -0
  416. package/src/lib/hooks/use-crm-default-view.js +64 -0
  417. package/src/lib/hooks/use-crm-default-view.js.map +1 -0
  418. package/src/lib/hooks/use-crm-email-templates.d.ts +59 -0
  419. package/src/lib/hooks/use-crm-email-templates.js +103 -0
  420. package/src/lib/hooks/use-crm-email-templates.js.map +1 -0
  421. package/src/lib/hooks/use-crm-hub-path.d.ts +29 -0
  422. package/src/lib/hooks/use-crm-hub-path.js +41 -0
  423. package/src/lib/hooks/use-crm-hub-path.js.map +1 -0
  424. package/src/lib/hooks/use-crm-org-mount.d.ts +97 -0
  425. package/src/lib/hooks/use-crm-org-mount.js +215 -0
  426. package/src/lib/hooks/use-crm-org-mount.js.map +1 -0
  427. package/src/lib/hooks/use-crm-record-names.d.ts +52 -0
  428. package/src/lib/hooks/use-crm-record-names.js +126 -0
  429. package/src/lib/hooks/use-crm-record-names.js.map +1 -0
  430. package/src/lib/hooks/use-crm-records-quota.d.ts +68 -0
  431. package/src/lib/hooks/use-crm-records-quota.js +118 -0
  432. package/src/lib/hooks/use-crm-records-quota.js.map +1 -0
  433. package/src/lib/hooks/use-crm-saved-view.d.ts +96 -0
  434. package/src/lib/hooks/use-crm-saved-view.js +329 -0
  435. package/src/lib/hooks/use-crm-saved-view.js.map +1 -0
  436. package/src/lib/hooks/use-crm-scope.d.ts +117 -0
  437. package/src/lib/hooks/use-crm-scope.js +147 -0
  438. package/src/lib/hooks/use-crm-scope.js.map +1 -0
  439. package/src/lib/hooks/use-crm-tasks.d.ts +85 -0
  440. package/src/lib/hooks/use-crm-tasks.js +153 -0
  441. package/src/lib/hooks/use-crm-tasks.js.map +1 -0
  442. package/src/lib/hooks/use-crm-view-grid.d.ts +55 -0
  443. package/src/lib/hooks/use-crm-view-grid.js +170 -0
  444. package/src/lib/hooks/use-crm-view-grid.js.map +1 -0
  445. package/src/lib/hooks/use-crm-views.d.ts +42 -0
  446. package/src/lib/hooks/use-crm-views.js +84 -0
  447. package/src/lib/hooks/use-crm-views.js.map +1 -0
  448. package/src/lib/hooks/use-deal-stage-api.d.ts +69 -0
  449. package/src/lib/hooks/use-deal-stage-api.js +78 -0
  450. package/src/lib/hooks/use-deal-stage-api.js.map +1 -0
  451. package/src/lib/hooks/use-deals.d.ts +47 -0
  452. package/src/lib/hooks/use-deals.js +105 -0
  453. package/src/lib/hooks/use-deals.js.map +1 -0
  454. package/src/lib/hooks/use-org-leads.d.ts +53 -0
  455. package/src/lib/hooks/use-org-leads.js +114 -0
  456. package/src/lib/hooks/use-org-leads.js.map +1 -0
  457. package/src/lib/hooks/use-org-member-directory.d.ts +36 -0
  458. package/src/lib/hooks/use-org-member-directory.js +116 -0
  459. package/src/lib/hooks/use-org-member-directory.js.map +1 -0
  460. package/src/lib/hooks/use-org-member-options.d.ts +38 -0
  461. package/src/lib/hooks/use-org-member-options.js +131 -0
  462. package/src/lib/hooks/use-org-member-options.js.map +1 -0
  463. package/src/lib/hooks/use-pipeline.d.ts +71 -0
  464. package/src/lib/hooks/use-pipeline.js +159 -0
  465. package/src/lib/hooks/use-pipeline.js.map +1 -0
  466. package/src/lib/model/companies-bulk-writes.d.ts +40 -0
  467. package/src/lib/model/companies-bulk-writes.js +103 -0
  468. package/src/lib/model/companies-bulk-writes.js.map +1 -0
  469. package/src/lib/model/companies-csv.d.ts +36 -0
  470. package/src/lib/model/companies-csv.js +38 -0
  471. package/src/lib/model/companies-csv.js.map +1 -0
  472. package/src/lib/model/companies.d.ts +99 -0
  473. package/src/lib/model/companies.js +168 -0
  474. package/src/lib/model/companies.js.map +1 -0
  475. package/src/lib/model/company-delete-route.d.ts +43 -0
  476. package/src/lib/model/company-delete-route.js +31 -0
  477. package/src/lib/model/company-delete-route.js.map +1 -0
  478. package/src/lib/model/company-delete.d.ts +42 -0
  479. package/src/lib/model/company-delete.js +52 -0
  480. package/src/lib/model/company-delete.js.map +1 -0
  481. package/src/lib/model/contact-duplicates.d.ts +58 -0
  482. package/src/lib/model/contact-duplicates.js +67 -0
  483. package/src/lib/model/contact-duplicates.js.map +1 -0
  484. package/src/lib/model/contact-record.d.ts +113 -0
  485. package/src/lib/model/contact-record.js +70 -0
  486. package/src/lib/model/contact-record.js.map +1 -0
  487. package/src/lib/model/contact-update.d.ts +93 -0
  488. package/src/lib/model/contact-update.js +50 -0
  489. package/src/lib/model/contact-update.js.map +1 -0
  490. package/src/lib/model/contacts-bulk-writes.d.ts +173 -0
  491. package/src/lib/model/contacts-bulk-writes.js +196 -0
  492. package/src/lib/model/contacts-bulk-writes.js.map +1 -0
  493. package/src/lib/model/contacts-csv.d.ts +54 -0
  494. package/src/lib/model/contacts-csv.js +67 -0
  495. package/src/lib/model/contacts-csv.js.map +1 -0
  496. package/src/lib/model/contacts-list-seed.d.ts +51 -0
  497. package/src/lib/model/contacts-list-seed.js +63 -0
  498. package/src/lib/model/contacts-list-seed.js.map +1 -0
  499. package/src/lib/model/crm-activity-report.d.ts +27 -0
  500. package/src/lib/model/crm-activity-report.js +56 -0
  501. package/src/lib/model/crm-activity-report.js.map +1 -0
  502. package/src/lib/model/crm-api.d.ts +49 -0
  503. package/src/lib/model/crm-api.js +47 -0
  504. package/src/lib/model/crm-api.js.map +1 -0
  505. package/src/lib/model/crm-bulk-writes.d.ts +147 -0
  506. package/src/lib/model/crm-bulk-writes.js +207 -0
  507. package/src/lib/model/crm-bulk-writes.js.map +1 -0
  508. package/src/lib/model/crm-company-import.d.ts +154 -0
  509. package/src/lib/model/crm-company-import.js +331 -0
  510. package/src/lib/model/crm-company-import.js.map +1 -0
  511. package/src/lib/model/crm-custom-draft.d.ts +62 -0
  512. package/src/lib/model/crm-custom-draft.js +67 -0
  513. package/src/lib/model/crm-custom-draft.js.map +1 -0
  514. package/src/lib/model/crm-deal-import.d.ts +112 -0
  515. package/src/lib/model/crm-deal-import.js +263 -0
  516. package/src/lib/model/crm-deal-import.js.map +1 -0
  517. package/src/lib/model/crm-import.d.ts +244 -0
  518. package/src/lib/model/crm-import.js +466 -0
  519. package/src/lib/model/crm-import.js.map +1 -0
  520. package/src/lib/model/crm-lead-import.d.ts +105 -0
  521. package/src/lib/model/crm-lead-import.js +255 -0
  522. package/src/lib/model/crm-lead-import.js.map +1 -0
  523. package/src/lib/model/crm-record-routes.d.ts +21 -0
  524. package/src/lib/model/crm-record-routes.js +70 -0
  525. package/src/lib/model/crm-record-routes.js.map +1 -0
  526. package/src/lib/model/crm-routes.d.ts +101 -0
  527. package/src/lib/model/crm-routes.js +92 -0
  528. package/src/lib/model/crm-routes.js.map +1 -0
  529. package/src/lib/model/crm-task-import.d.ts +94 -0
  530. package/src/lib/model/crm-task-import.js +275 -0
  531. package/src/lib/model/crm-task-import.js.map +1 -0
  532. package/src/lib/model/crm-view-param.d.ts +43 -0
  533. package/src/lib/model/crm-view-param.js +49 -0
  534. package/src/lib/model/crm-view-param.js.map +1 -0
  535. package/src/lib/model/deal-board-model.d.ts +241 -0
  536. package/src/lib/model/deal-board-model.js +439 -0
  537. package/src/lib/model/deal-board-model.js.map +1 -0
  538. package/src/lib/model/deal-form-model.d.ts +114 -0
  539. package/src/lib/model/deal-form-model.js +218 -0
  540. package/src/lib/model/deal-form-model.js.map +1 -0
  541. package/src/lib/model/deals-csv.d.ts +32 -0
  542. package/src/lib/model/deals-csv.js +37 -0
  543. package/src/lib/model/deals-csv.js.map +1 -0
  544. package/src/lib/model/import-column-shapes.d.ts +36 -0
  545. package/src/lib/model/import-column-shapes.js +76 -0
  546. package/src/lib/model/import-column-shapes.js.map +1 -0
  547. package/src/lib/model/lead-company-suggestion.d.ts +61 -0
  548. package/src/lib/model/lead-company-suggestion.js +65 -0
  549. package/src/lib/model/lead-company-suggestion.js.map +1 -0
  550. package/src/lib/model/lead-filters.d.ts +29 -0
  551. package/src/lib/model/lead-filters.js +39 -0
  552. package/src/lib/model/lead-filters.js.map +1 -0
  553. package/src/lib/model/lead-surfaces.d.ts +58 -0
  554. package/src/lib/model/lead-surfaces.js +67 -0
  555. package/src/lib/model/lead-surfaces.js.map +1 -0
  556. package/src/lib/model/leads-csv.d.ts +40 -0
  557. package/src/lib/model/leads-csv.js +40 -0
  558. package/src/lib/model/leads-csv.js.map +1 -0
  559. package/src/lib/model/next-activity-api.d.ts +31 -0
  560. package/src/lib/model/next-activity-api.js +57 -0
  561. package/src/lib/model/next-activity-api.js.map +1 -0
  562. package/src/lib/model/next-activity.d.ts +64 -0
  563. package/src/lib/model/next-activity.js +47 -0
  564. package/src/lib/model/next-activity.js.map +1 -0
  565. package/src/lib/model/person-key-web.d.ts +43 -0
  566. package/src/lib/model/person-key-web.js +52 -0
  567. package/src/lib/model/person-key-web.js.map +1 -0
  568. package/src/lib/model/record-facts.d.ts +282 -0
  569. package/src/lib/model/record-facts.js +434 -0
  570. package/src/lib/model/record-facts.js.map +1 -0
  571. package/src/lib/model/task-api.d.ts +28 -0
  572. package/src/lib/model/task-api.js +57 -0
  573. package/src/lib/model/task-api.js.map +1 -0
  574. package/src/lib/model/task-calendar.d.ts +108 -0
  575. package/src/lib/model/task-calendar.js +139 -0
  576. package/src/lib/model/task-calendar.js.map +1 -0
  577. package/src/lib/model/task-routes.d.ts +177 -0
  578. package/src/lib/model/task-routes.js +197 -0
  579. package/src/lib/model/task-routes.js.map +1 -0
  580. package/src/lib/model/task-scope.d.ts +45 -0
  581. package/src/lib/model/task-scope.js +51 -0
  582. package/src/lib/model/task-scope.js.map +1 -0
  583. package/src/lib/model/task-views.d.ts +149 -0
  584. package/src/lib/model/task-views.js +286 -0
  585. package/src/lib/model/task-views.js.map +1 -0
  586. package/src/lib/model/tasks-csv.d.ts +28 -0
  587. package/src/lib/model/tasks-csv.js +28 -0
  588. package/src/lib/model/tasks-csv.js.map +1 -0
  589. package/src/lib/plugin.d.ts +32 -0
  590. package/src/lib/plugin.js +208 -0
  591. package/src/lib/plugin.js.map +1 -0
  592. package/src/lib/server/companies-import.d.ts +57 -0
  593. package/src/lib/server/companies-import.js +242 -0
  594. package/src/lib/server/companies-import.js.map +1 -0
  595. package/src/lib/server/company-delete.d.ts +59 -0
  596. package/src/lib/server/company-delete.js +146 -0
  597. package/src/lib/server/company-delete.js.map +1 -0
  598. package/src/lib/server/contact-email-history.d.ts +82 -0
  599. package/src/lib/server/contact-email-history.js +264 -0
  600. package/src/lib/server/contact-email-history.js.map +1 -0
  601. package/src/lib/server/contact-profile.d.ts +41 -0
  602. package/src/lib/server/contact-profile.js +45 -0
  603. package/src/lib/server/contact-profile.js.map +1 -0
  604. package/src/lib/server/contact-update.d.ts +92 -0
  605. package/src/lib/server/contact-update.js +512 -0
  606. package/src/lib/server/contact-update.js.map +1 -0
  607. package/src/lib/server/contacts-import.d.ts +73 -0
  608. package/src/lib/server/contacts-import.js +263 -0
  609. package/src/lib/server/contacts-import.js.map +1 -0
  610. package/src/lib/server/contacts-merge.d.ts +86 -0
  611. package/src/lib/server/contacts-merge.js +206 -0
  612. package/src/lib/server/contacts-merge.js.map +1 -0
  613. package/src/lib/server/deals-import.d.ts +76 -0
  614. package/src/lib/server/deals-import.js +246 -0
  615. package/src/lib/server/deals-import.js.map +1 -0
  616. package/src/lib/server/email-send.d.ts +119 -0
  617. package/src/lib/server/email-send.js +667 -0
  618. package/src/lib/server/email-send.js.map +1 -0
  619. package/src/lib/server/email-template-duplicate.d.ts +19 -0
  620. package/src/lib/server/email-template-duplicate.js +206 -0
  621. package/src/lib/server/email-template-duplicate.js.map +1 -0
  622. package/src/lib/server/erase-person.d.ts +108 -0
  623. package/src/lib/server/erase-person.js +309 -0
  624. package/src/lib/server/erase-person.js.map +1 -0
  625. package/src/lib/server/import-context.d.ts +85 -0
  626. package/src/lib/server/import-context.js +181 -0
  627. package/src/lib/server/import-context.js.map +1 -0
  628. package/src/lib/server/inbound-address.d.ts +61 -0
  629. package/src/lib/server/inbound-address.js +188 -0
  630. package/src/lib/server/inbound-address.js.map +1 -0
  631. package/src/lib/server/lead-convert.d.ts +78 -0
  632. package/src/lib/server/lead-convert.js +250 -0
  633. package/src/lib/server/lead-convert.js.map +1 -0
  634. package/src/lib/server/leads-import.d.ts +84 -0
  635. package/src/lib/server/leads-import.js +261 -0
  636. package/src/lib/server/leads-import.js.map +1 -0
  637. package/src/lib/server/next-activity-routes.d.ts +33 -0
  638. package/src/lib/server/next-activity-routes.js +110 -0
  639. package/src/lib/server/next-activity-routes.js.map +1 -0
  640. package/src/lib/server/org-activity.d.ts +61 -0
  641. package/src/lib/server/org-activity.js +120 -0
  642. package/src/lib/server/org-activity.js.map +1 -0
  643. package/src/lib/server/org-caller.d.ts +110 -0
  644. package/src/lib/server/org-caller.js +154 -0
  645. package/src/lib/server/org-caller.js.map +1 -0
  646. package/src/lib/server/recipe-routes.d.ts +75 -0
  647. package/src/lib/server/recipe-routes.js +442 -0
  648. package/src/lib/server/recipe-routes.js.map +1 -0
  649. package/src/lib/server/record-facts.d.ts +65 -0
  650. package/src/lib/server/record-facts.js +337 -0
  651. package/src/lib/server/record-facts.js.map +1 -0
  652. package/src/lib/server/record-timeline.d.ts +51 -0
  653. package/src/lib/server/record-timeline.js +215 -0
  654. package/src/lib/server/record-timeline.js.map +1 -0
  655. package/src/lib/server/suite-gate.d.ts +42 -0
  656. package/src/lib/server/suite-gate.js +87 -0
  657. package/src/lib/server/suite-gate.js.map +1 -0
  658. package/src/lib/server/task-routes.d.ts +132 -0
  659. package/src/lib/server/task-routes.js +699 -0
  660. package/src/lib/server/task-routes.js.map +1 -0
  661. package/src/lib/server/tasks-import.d.ts +54 -0
  662. package/src/lib/server/tasks-import.js +157 -0
  663. package/src/lib/server/tasks-import.js.map +1 -0
  664. package/src/lib/server-deal-stage.d.ts +88 -0
  665. package/src/lib/server-deal-stage.js +316 -0
  666. package/src/lib/server-deal-stage.js.map +1 -0
  667. package/src/lib/server.d.ts +149 -0
  668. package/src/lib/server.js +615 -0
  669. package/src/lib/server.js.map +1 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/deal-products-card.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n type AglynOrgBilling,\n checkEntitlement,\n CRM_COLLECTIONS,\n type CrmDealLineItem,\n DEAL_LINE_ITEM_NAME_MAX,\n DEAL_LINE_ITEM_QUANTITY_MAX,\n DEAL_LINE_ITEMS_MAX,\n lineItemsTotalCents,\n nameSearchToken,\n pluginDocsHelp,\n readDealLineItems,\n} from '@aglyn/aglyn'\nimport { mdiDeleteOutline, mdiPlus } from '@aglyn/shared-data-mdi'\nimport { CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { ScrollTable } from '@aglyn/shared-ui-jsx/components/scroll-table.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useFirestore, writeGuardedBySeed } from '@aglyn/tenant-feature-instance'\nimport {\n Autocomplete,\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n IconButton,\n Stack,\n TableBody,\n TableCell,\n TableHead,\n TableRow,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport {\n collection,\n doc,\n getDocs,\n limit,\n orderBy,\n query,\n updateDoc,\n where,\n} from 'firebase/firestore'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport type { CrmOrgDoc } from '../hooks/use-crm-scope'\nimport {\n amountInputValue,\n type DealDoc,\n DEFAULT_DEAL_CURRENCY,\n formatMoney,\n parseAmountInput,\n} from '../model/deal-board-model'\n\n/** Catalog matches offered per keystroke; a longer list is a scroll, not a pick. */\nconst CATALOG_MATCHES = 8\n\n/** One thing the catalog search offers: a product, or one variant of it. */\ninterface CatalogChoice {\n key: string\n productId: string\n label: string\n unitAmountCents: number\n}\n\nexport interface DealProductsCardProps {\n deal: DealDoc\n orgId: string\n /**\n * The site whose catalog the search reads — the console's own, or\n * `null` at the organization level (AGL-2630), where the deal's own\n * capturing site is searched; a deal with none takes lines by hand only.\n */\n hostId: string | null\n org: CrmOrgDoc\n /** The listener's verdict on the deal, for the stale-seed guard. */\n fromCache: boolean\n unreadable: boolean\n}\n\n/**\n * The products behind a deal's amount (AGL-2620).\n *\n * ## The amount follows the lines\n *\n * Every write here stores `lineItems` AND `amountCents` as their sum, in\n * one update, so the board, the reports and the API keep reading the one\n * field they always read and no reader adds up lines. Once a deal has a\n * line, the drawer's Amount goes read-only and says why; remove the last\n * line and the amount is typed again, keeping the last sum rather than\n * dropping to nothing. The currency is the deal's — a line cannot be in\n * another, because their sum is one number.\n *\n * ## Two doors to a line\n *\n * **From the catalog** searches THIS site's products — a prefix on\n * `nameTokens` over active products, the query the products hub runs and\n * the `(status, nameTokens, nameLower)` index serves — and offers each\n * variant priced. The catalog is USD; a deal in another currency is told\n * so and can edit the unit amount after. **By hand** takes a name and a\n * price with no product behind them, which is also all a plan without\n * commerce gets: the catalog door is not drawn for it, because the site\n * has no catalog to search.\n *\n * Adding opens a dialog rather than a row of fields above the table, and\n * a quantity is edited in place and written on blur.\n */\nexport function DealProductsCard(props: DealProductsCardProps) {\n const { deal, orgId, hostId, org, fromCache, unreadable } = props\n const firestore = useFirestore()\n // The catalog searched: the mounted site's, or the deal's own.\n const catalogHostId = hostId ?? deal.hostId ?? null\n const { enqueueSnackbar } = useSnackbar()\n const currency = String(deal.currency || DEFAULT_DEAL_CURRENCY).toLowerCase()\n const items = useMemo(() => deal.lineItems ?? [], [deal.lineItems])\n const hasCommerce = checkEntitlement(\n (org ?? null) as Partial<AglynOrgBilling> | null,\n 'commerce',\n )\n const [busy, setBusy] = useState(false)\n const [adding, setAdding] = useState(false)\n\n /** The one write: the lines and their sum, together. */\n const save = useCallback(\n async (next: CrmDealLineItem[], done: string) => {\n const read = readDealLineItems(next, currency)\n if ('error' in read) {\n enqueueSnackbar(read.error, { variant: 'warning', persist: false })\n return false\n }\n setBusy(true)\n try {\n const verdict = await writeGuardedBySeed(\n { subject: 'deal', unreadable, fromCache },\n async () => {\n await updateDoc(doc(firestore, 'orgs', orgId, CRM_COLLECTIONS.deals, deal.$id), {\n lineItems: read.items,\n // The last sum stays on a deal whose lines were all removed:\n // the forecast should not drop to zero because a quote was\n // cleared to be retyped.\n ...(read.items.length ? { amountCents: lineItemsTotalCents(read.items) } : {}),\n updatedAt: new Date(),\n })\n },\n )\n if (!verdict.ok) {\n enqueueSnackbar(verdict.message, { variant: 'warning', persist: false })\n return false\n }\n enqueueSnackbar(done, { variant: 'success', persist: false })\n return true\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', { variant: 'error', allowDuplicate: true })\n return false\n } finally {\n setBusy(false)\n }\n },\n [currency, enqueueSnackbar, unreadable, fromCache, firestore, orgId, deal.$id],\n )\n\n const handleRemove = useCallback(\n (index: number) =>\n void save(\n items.filter((_item, at) => at !== index),\n 'Line removed',\n ),\n [items, save],\n )\n const handleQuantity = useCallback(\n (index: number, quantity: number) => {\n if (quantity === items[index]?.quantity) return\n void save(\n items.map((item, at) => (at === index ? { ...item, quantity } : item)),\n 'Quantity saved',\n )\n },\n [items, save],\n )\n const handleAdd = useCallback(\n async (line: CrmDealLineItem) => {\n const ok = await save([...items, line], 'Line added')\n if (ok) setAdding(false)\n },\n [items, save],\n )\n\n const total = lineItemsTotalCents(items)\n const full = items.length >= DEAL_LINE_ITEMS_MAX\n\n return (\n <>\n <CardDisplay\n header={'Products'}\n help={pluginDocsHelp('deals', { anchor: '#line-items' })}\n actions={\n <Tooltip title={full ? `A deal carries at most ${DEAL_LINE_ITEMS_MAX} lines` : ''}>\n <span>\n <Button\n size=\"small\"\n startIcon={<MdiIcon path={mdiPlus.path} size={0.8} />}\n disabled={busy || full}\n onClick={() => setAdding(true)}\n >\n {'Add line'}\n </Button>\n </span>\n </Tooltip>\n }\n contentGutterX\n contentGutterY\n >\n {items.length === 0 ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {hasCommerce\n ? 'No line items yet. Add products from your catalog or by hand; the amount becomes their sum.'\n : 'No line items yet. Add what the deal is for, priced by hand; the amount becomes their sum.'}\n </Typography>\n ) : (\n <ScrollTable size=\"small\" aria-label=\"Line items\">\n <TableHead>\n <TableRow>\n <TableCell>{'Item'}</TableCell>\n <TableCell align=\"right\" sx={{ width: 110 }}>\n {'Quantity'}\n </TableCell>\n <TableCell align=\"right\">{'Unit'}</TableCell>\n <TableCell align=\"right\">{'Total'}</TableCell>\n <TableCell sx={{ width: 48 }} />\n </TableRow>\n </TableHead>\n <TableBody>\n {items.map((item, index) => (\n <TableRow key={`${index}:${item.productId ?? item.name}`}>\n <TableCell>\n <Typography variant=\"body2\">{item.name}</Typography>\n {item.productId ? (\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'From the catalog'}\n </Typography>\n ) : null}\n </TableCell>\n <TableCell align=\"right\">\n <QuantityField\n value={item.quantity}\n disabled={busy}\n label={`Quantity of ${item.name}`}\n onCommit={(quantity) => handleQuantity(index, quantity)}\n />\n </TableCell>\n <TableCell align=\"right\">{formatMoney(item.unitAmountCents, currency)}</TableCell>\n <TableCell align=\"right\">\n {formatMoney(item.quantity * item.unitAmountCents, currency)}\n </TableCell>\n <TableCell padding=\"none\" align=\"right\">\n <Tooltip title=\"Remove line\">\n <span>\n <IconButton\n size=\"small\"\n color=\"error\"\n disabled={busy}\n aria-label={`Remove ${item.name}`}\n onClick={() => handleRemove(index)}\n >\n <MdiIcon path={mdiDeleteOutline.path} size={0.8} />\n </IconButton>\n </span>\n </Tooltip>\n </TableCell>\n </TableRow>\n ))}\n <TableRow>\n <TableCell colSpan={3}>\n <Typography variant=\"subtitle2\">{'Amount'}</Typography>\n </TableCell>\n <TableCell align=\"right\">\n <Typography variant=\"subtitle2\" data-testid=\"line-items-total\">\n {formatMoney(total, currency)}\n </Typography>\n </TableCell>\n <TableCell padding=\"none\" />\n </TableRow>\n </TableBody>\n </ScrollTable>\n )}\n </CardDisplay>\n <AddLineDialog\n open={adding}\n onClose={() => setAdding(false)}\n hostId={catalogHostId}\n currency={currency}\n catalog={hasCommerce && Boolean(catalogHostId)}\n busy={busy}\n onAdd={handleAdd}\n />\n </>\n )\n}\nDealProductsCard.displayName = 'DealProductsCard'\n\ninterface QuantityFieldProps {\n value: number\n disabled: boolean\n label: string\n onCommit: (quantity: number) => void\n}\n\n/** A quantity edited in place, committed on blur or Enter, refused below one. */\nfunction QuantityField(props: QuantityFieldProps) {\n const { value, disabled, label, onCommit } = props\n const [draft, setDraft] = useState(String(value))\n useEffect(() => setDraft(String(value)), [value])\n const commit = () => {\n const quantity = Number(draft)\n if (Number.isInteger(quantity) && quantity >= 1 && quantity <= DEAL_LINE_ITEM_QUANTITY_MAX) {\n onCommit(quantity)\n } else {\n setDraft(String(value))\n }\n }\n return (\n <TextField\n size=\"small\"\n type=\"number\"\n value={draft}\n disabled={disabled}\n onChange={(event) => setDraft(event.target.value)}\n onBlur={commit}\n onKeyDown={(event) => {\n if (event.key === 'Enter') {\n event.preventDefault()\n ;(event.target as HTMLInputElement).blur()\n }\n }}\n sx={{ width: 88 }}\n slotProps={{\n htmlInput: {\n min: 1,\n max: DEAL_LINE_ITEM_QUANTITY_MAX,\n step: 1,\n 'aria-label': label,\n style: { textAlign: 'right' },\n },\n }}\n />\n )\n}\nQuantityField.displayName = 'QuantityField'\n\ninterface AddLineDialogProps {\n open: boolean\n onClose: () => void\n /** The site whose catalog is searched; `null` draws no catalog door. */\n hostId: string | null\n currency: string\n /** Whether the catalog door is drawn — the plan has commerce. */\n catalog: boolean\n busy: boolean\n onAdd: (line: CrmDealLineItem) => Promise<void>\n}\n\ntype Door = 'catalog' | 'manual'\n\nfunction AddLineDialog(props: AddLineDialogProps) {\n const { open, onClose, hostId, currency, catalog, busy, onAdd } = props\n const firestore = useFirestore()\n const [door, setDoor] = useState<Door>(catalog ? 'catalog' : 'manual')\n const [picked, setPicked] = useState<CatalogChoice | null>(null)\n const [name, setName] = useState('')\n const [quantity, setQuantity] = useState('1')\n const [unit, setUnit] = useState('')\n const [search, setSearch] = useState('')\n const [choices, setChoices] = useState<CatalogChoice[]>([])\n\n useEffect(() => {\n if (!open) return\n setDoor(catalog ? 'catalog' : 'manual')\n setPicked(null)\n setName('')\n setQuantity('1')\n setUnit('')\n setSearch('')\n setChoices([])\n }, [open, catalog])\n\n /*\n * THE CATALOG SEARCH: the first typed word as a prefix token over active\n * products, ordered by name, debounced so a name typed at speed is one\n * query rather than one per letter. Each variant is its own choice,\n * priced from `priceUsd` in cents.\n */\n useEffect(() => {\n if (!open || door !== 'catalog' || !hostId) return\n const token = nameSearchToken(search)\n if (!token) {\n setChoices([])\n return\n }\n let active = true\n const timer = setTimeout(() => {\n void getDocs(\n query(\n collection(firestore, 'hosts', hostId, 'products'),\n where('status', '==', 'active'),\n where('nameTokens', 'array-contains', token),\n orderBy('nameLower'),\n limit(CATALOG_MATCHES),\n ),\n )\n .then((snapshot) => {\n if (!active) return\n const next: CatalogChoice[] = []\n for (const entry of snapshot.docs) {\n const productName = String(entry.get('name') ?? '')\n const variants = (entry.get('variants') as Array<Record<string, unknown>> | undefined) ?? []\n const priced = variants.length\n ? variants\n : [{ id: '', priceUsd: entry.get('priceUsd') }]\n for (const variant of priced) {\n const options = Object.values((variant['options'] as Record<string, string>) ?? {})\n const label = options.length ? `${productName} — ${options.join(' / ')}` : productName\n next.push({\n key: `${entry.id}:${String(variant['id'] ?? '')}`,\n productId: entry.id,\n label,\n unitAmountCents: Math.max(0, Math.round((Number(variant['priceUsd']) || 0) * 100)),\n })\n }\n }\n setChoices(next)\n })\n .catch(() => {\n if (active) setChoices([])\n })\n }, 200)\n return () => {\n active = false\n clearTimeout(timer)\n }\n }, [firestore, open, door, hostId, search])\n\n const unitCents = parseAmountInput(unit)\n const quantityNumber = Number(quantity)\n const lineName = (door === 'catalog' ? (name || picked?.label || '') : name).trim()\n const problem = !lineName\n ? door === 'catalog'\n ? 'Pick a product.'\n : 'A line needs a name.'\n : !Number.isInteger(quantityNumber) || quantityNumber < 1\n ? 'The quantity has to be a whole number of one or more.'\n : unitCents === null\n ? 'The unit amount has to be a number of zero or more.'\n : null\n\n const handleAdd = () => {\n if (problem || unitCents === null) return\n void onAdd({\n ...(door === 'catalog' && picked ? { productId: picked.productId } : {}),\n name: lineName.slice(0, DEAL_LINE_ITEM_NAME_MAX),\n quantity: quantityNumber,\n unitAmountCents: unitCents,\n currency,\n })\n }\n\n return (\n <Dialog open={open} onClose={busy ? undefined : onClose} fullWidth maxWidth=\"xs\">\n <DialogTitle>{'Add a line'}</DialogTitle>\n <DialogContent>\n <Stack spacing={2} sx={{ pt: 1 }}>\n {catalog ? (\n <ToggleButtonGroup\n exclusive\n size=\"small\"\n color=\"primary\"\n value={door}\n onChange={(_event, next) => {\n if (next) setDoor(next as Door)\n }}\n aria-label=\"Where the line comes from\"\n >\n <ToggleButton value=\"catalog\">{'From the catalog'}</ToggleButton>\n <ToggleButton value=\"manual\">{'By hand'}</ToggleButton>\n </ToggleButtonGroup>\n ) : null}\n {door === 'catalog' ? (\n <Autocomplete<CatalogChoice, false, false, false>\n options={choices}\n value={picked}\n inputValue={search}\n onInputChange={(_event, next, reason) => {\n if (reason !== 'reset') setSearch(next)\n }}\n onChange={(_event, choice) => {\n setPicked(choice)\n setName(choice?.label ?? '')\n setUnit(choice ? amountInputValue(choice.unitAmountCents) : '')\n }}\n getOptionLabel={(choice) => choice.label}\n isOptionEqualToValue={(option, value) => option.key === value.key}\n // The match is the query's own prefix over `nameTokens`, never\n // MUI's substring filter over labels.\n filterOptions={(options) => options}\n renderOption={(optionProps, choice) => (\n <li {...optionProps} key={choice.key}>\n <Stack direction=\"row\" spacing={1} sx={{ width: '100%', alignItems: 'baseline' }}>\n <Typography variant=\"body2\" sx={{ flex: 1 }}>\n {choice.label}\n </Typography>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {formatMoney(choice.unitAmountCents, 'usd')}\n </Typography>\n </Stack>\n </li>\n )}\n noOptionsText={search.trim() ? 'No active product matches' : 'Type a product name'}\n renderInput={(params) => (\n <TextField\n {...params}\n label=\"Product\"\n placeholder=\"Search this site's catalog\"\n autoFocus\n helperText={\n currency !== 'usd'\n ? `Catalog prices are in USD; this deal is in ${currency.toUpperCase()}. Check the unit amount.`\n : undefined\n }\n />\n )}\n />\n ) : (\n <TextField\n label=\"Name\"\n value={name}\n onChange={(event) => setName(event.target.value)}\n autoFocus\n fullWidth\n slotProps={{ htmlInput: { maxLength: DEAL_LINE_ITEM_NAME_MAX } }}\n />\n )}\n <Stack direction=\"row\" spacing={1}>\n <TextField\n label=\"Quantity\"\n type=\"number\"\n value={quantity}\n onChange={(event) => setQuantity(event.target.value)}\n sx={{ width: 120 }}\n slotProps={{ htmlInput: { min: 1, max: DEAL_LINE_ITEM_QUANTITY_MAX, step: 1 } }}\n />\n <TextField\n label={`Unit amount (${currency.toUpperCase()})`}\n value={unit}\n onChange={(event) => setUnit(event.target.value)}\n placeholder=\"0.00\"\n sx={{ flex: 1 }}\n slotProps={{ htmlInput: { inputMode: 'decimal' } }}\n />\n </Stack>\n {problem && (lineName || unit) ? (\n <Typography variant=\"caption\" color=\"warning.main\">\n {problem}\n </Typography>\n ) : null}\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose} disabled={busy}>\n {'Cancel'}\n </Button>\n <Button variant=\"contained\" disabled={busy || Boolean(problem)} onClick={handleAdd}>\n {'Add line'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\nAddLineDialog.displayName = 'AddLineDialog'\n\nexport default DealProductsCard\n"],"names":["checkEntitlement","CRM_COLLECTIONS","DEAL_LINE_ITEM_NAME_MAX","DEAL_LINE_ITEM_QUANTITY_MAX","DEAL_LINE_ITEMS_MAX","lineItemsTotalCents","nameSearchToken","pluginDocsHelp","readDealLineItems","mdiDeleteOutline","mdiPlus","CardDisplay","MdiIcon","ScrollTable","useSnackbar","useFirestore","writeGuardedBySeed","Autocomplete","Button","Dialog","DialogActions","DialogContent","DialogTitle","IconButton","Stack","TableBody","TableCell","TableHead","TableRow","TextField","ToggleButton","ToggleButtonGroup","Tooltip","Typography","collection","doc","getDocs","limit","orderBy","query","updateDoc","where","useCallback","useEffect","useMemo","useState","amountInputValue","DEFAULT_DEAL_CURRENCY","formatMoney","parseAmountInput","CATALOG_MATCHES","DealProductsCard","props","hostId","deal","orgId","org","fromCache","unreadable","firestore","catalogHostId","enqueueSnackbar","currency","String","toLowerCase","items","lineItems","hasCommerce","busy","setBusy","adding","setAdding","save","next","done","read","error","variant","persist","verdict","subject","deals","$id","length","amountCents","updatedAt","Date","ok","message","console","allowDuplicate","handleRemove","index","filter","_item","at","handleQuantity","quantity","map","item","handleAdd","line","total","full","header","help","anchor","actions","title","span","size","startIcon","path","disabled","onClick","contentGutterX","contentGutterY","color","aria-label","align","sx","width","name","productId","QuantityField","value","label","onCommit","unitAmountCents","padding","colSpan","data-testid","AddLineDialog","open","onClose","catalog","Boolean","onAdd","displayName","draft","setDraft","commit","Number","isInteger","type","onChange","event","target","onBlur","onKeyDown","key","preventDefault","blur","slotProps","htmlInput","min","max","step","style","textAlign","door","setDoor","picked","setPicked","setName","setQuantity","unit","setUnit","search","setSearch","choices","setChoices","token","active","timer","setTimeout","then","snapshot","entry","docs","productName","get","variants","priced","id","priceUsd","options","Object","values","join","push","Math","round","catch","clearTimeout","unitCents","quantityNumber","lineName","trim","problem","slice","undefined","fullWidth","maxWidth","spacing","pt","exclusive","_event","inputValue","onInputChange","reason","choice","getOptionLabel","isOptionEqualToValue","option","filterOptions","renderOption","optionProps","li","direction","alignItems","flex","noOptionsText","renderInput","params","placeholder","autoFocus","helperText","toUpperCase","maxLength","inputMode"],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { type ContactFieldDefinition } from '@aglyn/aglyn';
2
+ import { type DealDoc, type PipelineDoc } from '../model/deal-board-model';
3
+ import type { CrmRoutes } from '../model/crm-routes';
4
+ export interface DealPropertiesCardProps {
5
+ deal: DealDoc;
6
+ pipeline: PipelineDoc | null;
7
+ ownerLabel: string;
8
+ routes: CrmRoutes;
9
+ /**
10
+ * The org's ACTIVE deal field definitions (AGL-2661), one row each under
11
+ * the fixed properties. Handed in by the page, which resolves the org
12
+ * once for every card on it.
13
+ */
14
+ customFields?: readonly ContactFieldDefinition[];
15
+ }
16
+ /**
17
+ * What the deal is worth and who it is with (AGL-2598).
18
+ *
19
+ * The weighted value is computed here from the live pipeline rather than
20
+ * stored, because the stage's probability is the merchant's to change and
21
+ * a stored figure would go stale the moment they did. The contact and the
22
+ * company are links into their own pages — the id is the link; the name on
23
+ * the deal is a caption that may lag a rename.
24
+ */
25
+ export declare function DealPropertiesCard(props: DealPropertiesCardProps): import("react").JSX.Element;
26
+ export declare namespace DealPropertiesCard {
27
+ var displayName: string;
28
+ }
29
+ export default DealPropertiesCard;
@@ -0,0 +1,144 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ 'use client';
17
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
+ import { dealStageById, pluginDocsHelp, weightedDealAmountCents } from "@aglyn/aglyn";
19
+ import { AppLink, CardDisplay } from "@aglyn/shared-ui-jsx";
20
+ import { Link, Stack, Typography } from "@mui/material";
21
+ import { formatContactCustomValue } from "./contact-custom-columns.js";
22
+ import { formatMoney, timestampMs } from "../model/deal-board-model.js";
23
+ function Row(props) {
24
+ return /*#__PURE__*/ _jsxs(Stack, {
25
+ direction: "row",
26
+ spacing: 2,
27
+ sx: {
28
+ alignItems: 'baseline'
29
+ },
30
+ children: [
31
+ /*#__PURE__*/ _jsx(Typography, {
32
+ variant: "caption",
33
+ color: "text.secondary",
34
+ sx: {
35
+ width: 120,
36
+ flexShrink: 0
37
+ },
38
+ children: props.label
39
+ }),
40
+ /*#__PURE__*/ _jsx(Typography, {
41
+ variant: "body2",
42
+ component: "div",
43
+ sx: {
44
+ flex: 1,
45
+ minWidth: 0
46
+ },
47
+ children: props.children
48
+ })
49
+ ]
50
+ });
51
+ }
52
+ /**
53
+ * What the deal is worth and who it is with (AGL-2598).
54
+ *
55
+ * The weighted value is computed here from the live pipeline rather than
56
+ * stored, because the stage's probability is the merchant's to change and
57
+ * a stored figure would go stale the moment they did. The contact and the
58
+ * company are links into their own pages — the id is the link; the name on
59
+ * the deal is a caption that may lag a rename.
60
+ */ export function DealPropertiesCard(props) {
61
+ var _ref;
62
+ const { deal, pipeline, ownerLabel, routes, customFields = [] } = props;
63
+ const stage = dealStageById(pipeline, deal.stageId);
64
+ const weighted = weightedDealAmountCents(deal, stage);
65
+ const createdMs = timestampMs(deal.createdAt);
66
+ return /*#__PURE__*/ _jsx(CardDisplay, {
67
+ header: 'Properties',
68
+ help: pluginDocsHelp('deals', {
69
+ anchor: '#a-deals-page'
70
+ }),
71
+ contentGutterX: true,
72
+ contentGutterY: true,
73
+ children: /*#__PURE__*/ _jsxs(Stack, {
74
+ spacing: 1.25,
75
+ children: [
76
+ /*#__PURE__*/ _jsx(Row, {
77
+ label: "Amount",
78
+ children: typeof deal.amountCents === 'number' ? formatMoney(deal.amountCents, deal.currency) : 'Not set'
79
+ }),
80
+ /*#__PURE__*/ _jsx(Row, {
81
+ label: "Weighted value",
82
+ children: `${formatMoney(weighted, deal.currency)}` + (deal.status === 'open' && stage ? ` at ${stage.probability}%` : '')
83
+ }),
84
+ /*#__PURE__*/ _jsx(Row, {
85
+ label: "Expected close",
86
+ children: typeof deal.expectedCloseAtMs === 'number' ? new Date(deal.expectedCloseAtMs).toLocaleDateString() : 'Not set'
87
+ }),
88
+ /*#__PURE__*/ _jsx(Row, {
89
+ label: "Owner",
90
+ children: ownerLabel || 'Nobody yet'
91
+ }),
92
+ /*#__PURE__*/ _jsx(Row, {
93
+ label: "Contact",
94
+ children: deal.contactId ? /*#__PURE__*/ _jsx(AppLink, {
95
+ href: routes.contact(deal.contactId),
96
+ children: deal.contactName || 'Open contact'
97
+ }) : 'None'
98
+ }),
99
+ /*#__PURE__*/ _jsx(Row, {
100
+ label: "Company",
101
+ children: deal.companyId ? /*#__PURE__*/ _jsx(AppLink, {
102
+ href: routes.company(deal.companyId),
103
+ children: deal.companyName || 'Open company'
104
+ }) : 'None'
105
+ }),
106
+ /*#__PURE__*/ _jsx(Row, {
107
+ label: "Pipeline",
108
+ children: (_ref = pipeline == null ? void 0 : pipeline.name) != null ? _ref : deal.pipelineId
109
+ }),
110
+ /*#__PURE__*/ _jsx(Row, {
111
+ label: "Created",
112
+ children: createdMs ? new Date(createdMs).toLocaleDateString() : '—'
113
+ }),
114
+ deal.notes ? /*#__PURE__*/ _jsx(Row, {
115
+ label: "Notes",
116
+ children: /*#__PURE__*/ _jsx(Typography, {
117
+ variant: "body2",
118
+ sx: {
119
+ whiteSpace: 'pre-wrap'
120
+ },
121
+ children: deal.notes
122
+ })
123
+ }) : null,
124
+ customFields.map((definition)=>{
125
+ var _deal_custom;
126
+ const text = formatContactCustomValue(definition, (_deal_custom = deal.custom) == null ? void 0 : _deal_custom[definition.key]);
127
+ return /*#__PURE__*/ _jsx(Row, {
128
+ label: definition.label || definition.key,
129
+ children: text && definition.type === 'url' ? /*#__PURE__*/ _jsx(Link, {
130
+ href: text,
131
+ target: "_blank",
132
+ rel: "noreferrer noopener",
133
+ children: text
134
+ }) : text || 'Not set'
135
+ }, definition.key);
136
+ })
137
+ ]
138
+ })
139
+ });
140
+ }
141
+ DealPropertiesCard.displayName = 'DealPropertiesCard';
142
+ export default DealPropertiesCard;
143
+
144
+ //# sourceMappingURL=deal-properties-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/deal-properties-card.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n type ContactFieldDefinition,\n dealStageById,\n pluginDocsHelp,\n weightedDealAmountCents,\n} from '@aglyn/aglyn'\nimport { AppLink, CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { Link, Stack, Typography } from '@mui/material'\nimport type { ReactNode } from 'react'\nimport { formatContactCustomValue } from './contact-custom-columns'\nimport {\n type DealDoc,\n formatMoney,\n type PipelineDoc,\n timestampMs,\n} from '../model/deal-board-model'\nimport type { CrmRoutes } from '../model/crm-routes'\n\nexport interface DealPropertiesCardProps {\n deal: DealDoc\n pipeline: PipelineDoc | null\n ownerLabel: string\n routes: CrmRoutes\n /**\n * The org's ACTIVE deal field definitions (AGL-2661), one row each under\n * the fixed properties. Handed in by the page, which resolves the org\n * once for every card on it.\n */\n customFields?: readonly ContactFieldDefinition[]\n}\n\nfunction Row(props: { label: string; children: ReactNode }) {\n return (\n <Stack direction=\"row\" spacing={2} sx={{ alignItems: 'baseline' }}>\n <Typography\n variant=\"caption\"\n color=\"text.secondary\"\n sx={{ width: 120, flexShrink: 0 }}\n >\n {props.label}\n </Typography>\n <Typography variant=\"body2\" component=\"div\" sx={{ flex: 1, minWidth: 0 }}>\n {props.children}\n </Typography>\n </Stack>\n )\n}\n\n/**\n * What the deal is worth and who it is with (AGL-2598).\n *\n * The weighted value is computed here from the live pipeline rather than\n * stored, because the stage's probability is the merchant's to change and\n * a stored figure would go stale the moment they did. The contact and the\n * company are links into their own pages — the id is the link; the name on\n * the deal is a caption that may lag a rename.\n */\nexport function DealPropertiesCard(props: DealPropertiesCardProps) {\n const { deal, pipeline, ownerLabel, routes, customFields = [] } = props\n const stage = dealStageById(pipeline, deal.stageId)\n const weighted = weightedDealAmountCents(deal, stage)\n const createdMs = timestampMs(deal.createdAt)\n return (\n <CardDisplay\n header={'Properties'}\n help={pluginDocsHelp('deals', { anchor: '#a-deals-page' })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={1.25}>\n <Row label=\"Amount\">\n {typeof deal.amountCents === 'number'\n ? formatMoney(deal.amountCents, deal.currency)\n : 'Not set'}\n </Row>\n <Row label=\"Weighted value\">\n {`${formatMoney(weighted, deal.currency)}` +\n (deal.status === 'open' && stage ? ` at ${stage.probability}%` : '')}\n </Row>\n <Row label=\"Expected close\">\n {typeof deal.expectedCloseAtMs === 'number'\n ? new Date(deal.expectedCloseAtMs).toLocaleDateString()\n : 'Not set'}\n </Row>\n <Row label=\"Owner\">{ownerLabel || 'Nobody yet'}</Row>\n <Row label=\"Contact\">\n {deal.contactId ? (\n <AppLink href={routes.contact(deal.contactId)}>\n {deal.contactName || 'Open contact'}\n </AppLink>\n ) : (\n 'None'\n )}\n </Row>\n <Row label=\"Company\">\n {deal.companyId ? (\n <AppLink href={routes.company(deal.companyId)}>\n {deal.companyName || 'Open company'}\n </AppLink>\n ) : (\n 'None'\n )}\n </Row>\n <Row label=\"Pipeline\">{pipeline?.name ?? deal.pipelineId}</Row>\n <Row label=\"Created\">\n {createdMs ? new Date(createdMs).toLocaleDateString() : '—'}\n </Row>\n {deal.notes ? (\n <Row label=\"Notes\">\n <Typography variant=\"body2\" sx={{ whiteSpace: 'pre-wrap' }}>\n {deal.notes}\n </Typography>\n </Row>\n ) : null}\n {customFields.map((definition) => {\n const text = formatContactCustomValue(definition, deal.custom?.[definition.key])\n return (\n <Row key={definition.key} label={definition.label || definition.key}>\n {text && definition.type === 'url' ? (\n <Link href={text} target=\"_blank\" rel=\"noreferrer noopener\">\n {text}\n </Link>\n ) : (\n text || 'Not set'\n )}\n </Row>\n )\n })}\n </Stack>\n </CardDisplay>\n )\n}\nDealPropertiesCard.displayName = 'DealPropertiesCard'\n\nexport default DealPropertiesCard\n"],"names":["dealStageById","pluginDocsHelp","weightedDealAmountCents","AppLink","CardDisplay","Link","Stack","Typography","formatContactCustomValue","formatMoney","timestampMs","Row","props","direction","spacing","sx","alignItems","variant","color","width","flexShrink","label","component","flex","minWidth","children","DealPropertiesCard","deal","pipeline","ownerLabel","routes","customFields","stage","stageId","weighted","createdMs","createdAt","header","help","anchor","contentGutterX","contentGutterY","amountCents","currency","status","probability","expectedCloseAtMs","Date","toLocaleDateString","contactId","href","contact","contactName","companyId","company","companyName","name","pipelineId","notes","whiteSpace","map","definition","text","custom","key","type","target","rel","displayName"],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { type DealStageApi } from '../hooks/use-deal-stage-api';
2
+ import { type DealDoc, type PipelineDoc } from '../model/deal-board-model';
3
+ export interface DealStageCardProps {
4
+ deal: DealDoc;
5
+ pipeline: PipelineDoc | null;
6
+ api: DealStageApi;
7
+ nowMs: number;
8
+ }
9
+ /**
10
+ * Where the deal is, and the controls that move it (AGL-2598).
11
+ *
12
+ * A stepper across the open stages — click one to move there — and the two
13
+ * closing buttons. Every one of them calls the stage route, never Firestore:
14
+ * the move is what an automation listens for, and the route is the only
15
+ * writer that emits it. On a closed deal the stepper gives way to the
16
+ * verdict — Won or Lost, when, and why — and a way back: reopening is a
17
+ * move into an open stage, which the route emits as `dealStageChanged` like
18
+ * any other move.
19
+ */
20
+ export declare function DealStageCard(props: DealStageCardProps): import("react").JSX.Element;
21
+ export declare namespace DealStageCard {
22
+ var displayName: string;
23
+ }
24
+ export default DealStageCard;
@@ -0,0 +1,199 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ 'use client';
17
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
+ import { pluginDocsHelp } from "@aglyn/aglyn";
19
+ import { mdiThumbDownOutline, mdiTrophyOutline } from "@aglyn/shared-data-mdi";
20
+ import { CardDisplay, MdiIcon } from "@aglyn/shared-ui-jsx";
21
+ import { useSnackbar } from "@aglyn/shared-ui-snackstack";
22
+ import { Button, Chip, MenuItem, Stack, Step, StepButton, Stepper, TextField, Typography } from "@mui/material";
23
+ import { useCallback, useState } from "react";
24
+ import { daysInStage, DEAL_STATUS_LABELS, openStages } from "../model/deal-board-model.js";
25
+ import { LostReasonDialog } from "./lost-reason-dialog.js";
26
+ /**
27
+ * Where the deal is, and the controls that move it (AGL-2598).
28
+ *
29
+ * A stepper across the open stages — click one to move there — and the two
30
+ * closing buttons. Every one of them calls the stage route, never Firestore:
31
+ * the move is what an automation listens for, and the route is the only
32
+ * writer that emits it. On a closed deal the stepper gives way to the
33
+ * verdict — Won or Lost, when, and why — and a way back: reopening is a
34
+ * move into an open stage, which the route emits as `dealStageChanged` like
35
+ * any other move.
36
+ */ export function DealStageCard(props) {
37
+ const { deal, pipeline, api, nowMs } = props;
38
+ const { enqueueSnackbar } = useSnackbar();
39
+ const [busy, setBusy] = useState(false);
40
+ const [losing, setLosing] = useState(false);
41
+ const stages = openStages(pipeline);
42
+ const activeIndex = stages.findIndex((stage)=>stage.id === deal.stageId);
43
+ const run = useCallback(async (request, done)=>{
44
+ setBusy(true);
45
+ try {
46
+ await request();
47
+ enqueueSnackbar(done, {
48
+ variant: 'success',
49
+ persist: false
50
+ });
51
+ return true;
52
+ } catch (error) {
53
+ enqueueSnackbar(error instanceof Error ? error.message : 'The deal could not be moved.', {
54
+ variant: 'warning',
55
+ allowDuplicate: true
56
+ });
57
+ return false;
58
+ } finally{
59
+ setBusy(false);
60
+ }
61
+ }, [
62
+ enqueueSnackbar
63
+ ]);
64
+ const closed = deal.status !== 'open';
65
+ const days = daysInStage(deal, nowMs);
66
+ return /*#__PURE__*/ _jsxs(CardDisplay, {
67
+ header: 'Stage',
68
+ help: pluginDocsHelp('deals', {
69
+ anchor: '#moving-winning-and-losing'
70
+ }),
71
+ actions: !closed ? /*#__PURE__*/ _jsxs(Stack, {
72
+ direction: "row",
73
+ spacing: 1,
74
+ children: [
75
+ /*#__PURE__*/ _jsx(Button, {
76
+ size: "small",
77
+ color: "success",
78
+ variant: "outlined",
79
+ disabled: busy || !pipeline,
80
+ startIcon: /*#__PURE__*/ _jsx(MdiIcon, {
81
+ path: mdiTrophyOutline.path,
82
+ size: 0.8
83
+ }),
84
+ onClick: ()=>void run(()=>api.markWon(deal), 'Deal won'),
85
+ children: 'Won'
86
+ }),
87
+ /*#__PURE__*/ _jsx(Button, {
88
+ size: "small",
89
+ color: "error",
90
+ variant: "outlined",
91
+ disabled: busy || !pipeline,
92
+ startIcon: /*#__PURE__*/ _jsx(MdiIcon, {
93
+ path: mdiThumbDownOutline.path,
94
+ size: 0.8
95
+ }),
96
+ onClick: ()=>setLosing(true),
97
+ children: 'Lost'
98
+ })
99
+ ]
100
+ }) : null,
101
+ contentGutterX: true,
102
+ contentGutterY: true,
103
+ children: [
104
+ !pipeline ? /*#__PURE__*/ _jsx(Typography, {
105
+ variant: "body2",
106
+ color: "text.secondary",
107
+ children: "This deal's pipeline no longer exists, so it has no stages to move through."
108
+ }) : closed ? /*#__PURE__*/ _jsxs(Stack, {
109
+ spacing: 1.5,
110
+ children: [
111
+ /*#__PURE__*/ _jsxs(Stack, {
112
+ direction: "row",
113
+ spacing: 1,
114
+ sx: {
115
+ alignItems: 'center'
116
+ },
117
+ children: [
118
+ /*#__PURE__*/ _jsx(Chip, {
119
+ label: DEAL_STATUS_LABELS[deal.status],
120
+ color: deal.status === 'won' ? 'success' : 'default'
121
+ }),
122
+ /*#__PURE__*/ _jsx(Typography, {
123
+ variant: "body2",
124
+ color: "text.secondary",
125
+ children: typeof deal.closedAtMs === 'number' ? `Closed ${new Date(deal.closedAtMs).toLocaleDateString()}` : 'Closed'
126
+ })
127
+ ]
128
+ }),
129
+ deal.status === 'lost' && deal.lostReason ? /*#__PURE__*/ _jsx(Typography, {
130
+ variant: "body2",
131
+ children: deal.lostReason
132
+ }) : null,
133
+ /*#__PURE__*/ _jsxs(TextField, {
134
+ select: true,
135
+ size: "small",
136
+ label: "Reopen into",
137
+ value: "",
138
+ disabled: busy,
139
+ onChange: (event)=>{
140
+ const stageId = event.target.value;
141
+ if (!stageId) return;
142
+ void run(()=>api.moveToStage(deal, stageId), 'Deal reopened');
143
+ },
144
+ helperText: "Reopening puts the deal back in an open stage and tells the automations.",
145
+ sx: {
146
+ maxWidth: 320
147
+ },
148
+ children: [
149
+ /*#__PURE__*/ _jsx(MenuItem, {
150
+ value: "",
151
+ children: 'Pick a stage'
152
+ }),
153
+ stages.map((stage)=>/*#__PURE__*/ _jsx(MenuItem, {
154
+ value: stage.id,
155
+ children: stage.name
156
+ }, stage.id))
157
+ ]
158
+ })
159
+ ]
160
+ }) : /*#__PURE__*/ _jsxs(Stack, {
161
+ spacing: 1.5,
162
+ children: [
163
+ /*#__PURE__*/ _jsx(Stepper, {
164
+ nonLinear: true,
165
+ activeStep: activeIndex,
166
+ alternativeLabel: true,
167
+ children: stages.map((stage, index)=>/*#__PURE__*/ _jsx(Step, {
168
+ completed: index < activeIndex,
169
+ children: /*#__PURE__*/ _jsx(StepButton, {
170
+ disabled: busy || stage.id === deal.stageId,
171
+ onClick: ()=>void run(()=>api.moveToStage(deal, stage.id), `Moved to ${stage.name}`),
172
+ children: stage.name
173
+ })
174
+ }, stage.id))
175
+ }),
176
+ /*#__PURE__*/ _jsx(Typography, {
177
+ variant: "body2",
178
+ color: "text.secondary",
179
+ sx: {
180
+ textAlign: 'center'
181
+ },
182
+ children: activeIndex === -1 ? 'This deal sits in a stage the pipeline no longer has. Pick one above.' : `${days} ${days === 1 ? 'day' : 'days'} in ${stages[activeIndex].name} · ` + `${stages[activeIndex].probability}% likely to close`
183
+ })
184
+ ]
185
+ }),
186
+ /*#__PURE__*/ _jsx(LostReasonDialog, {
187
+ open: losing,
188
+ dealTitle: deal.title,
189
+ busy: busy,
190
+ onClose: ()=>setLosing(false),
191
+ onConfirm: (reason)=>void run(()=>api.markLost(deal, reason), 'Deal marked lost').then((ok)=>ok && setLosing(false))
192
+ })
193
+ ]
194
+ });
195
+ }
196
+ DealStageCard.displayName = 'DealStageCard';
197
+ export default DealStageCard;
198
+
199
+ //# sourceMappingURL=deal-stage-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/deal-stage-card.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { pluginDocsHelp } from '@aglyn/aglyn'\nimport { mdiThumbDownOutline, mdiTrophyOutline } from '@aglyn/shared-data-mdi'\nimport { CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport {\n Button,\n Chip,\n MenuItem,\n Stack,\n Step,\n StepButton,\n Stepper,\n TextField,\n Typography,\n} from '@mui/material'\nimport { useCallback, useState } from 'react'\nimport { type DealStageApi } from '../hooks/use-deal-stage-api'\nimport {\n daysInStage,\n DEAL_STATUS_LABELS,\n type DealDoc,\n openStages,\n type PipelineDoc,\n} from '../model/deal-board-model'\nimport { LostReasonDialog } from './lost-reason-dialog'\n\nexport interface DealStageCardProps {\n deal: DealDoc\n pipeline: PipelineDoc | null\n api: DealStageApi\n nowMs: number\n}\n\n/**\n * Where the deal is, and the controls that move it (AGL-2598).\n *\n * A stepper across the open stages — click one to move there — and the two\n * closing buttons. Every one of them calls the stage route, never Firestore:\n * the move is what an automation listens for, and the route is the only\n * writer that emits it. On a closed deal the stepper gives way to the\n * verdict — Won or Lost, when, and why — and a way back: reopening is a\n * move into an open stage, which the route emits as `dealStageChanged` like\n * any other move.\n */\nexport function DealStageCard(props: DealStageCardProps) {\n const { deal, pipeline, api, nowMs } = props\n const { enqueueSnackbar } = useSnackbar()\n const [busy, setBusy] = useState(false)\n const [losing, setLosing] = useState(false)\n const stages = openStages(pipeline)\n const activeIndex = stages.findIndex((stage) => stage.id === deal.stageId)\n\n const run = useCallback(\n async (request: () => Promise<unknown>, done: string) => {\n setBusy(true)\n try {\n await request()\n enqueueSnackbar(done, { variant: 'success', persist: false })\n return true\n } catch (error) {\n enqueueSnackbar(\n error instanceof Error ? error.message : 'The deal could not be moved.',\n { variant: 'warning', allowDuplicate: true },\n )\n return false\n } finally {\n setBusy(false)\n }\n },\n [enqueueSnackbar],\n )\n\n const closed = deal.status !== 'open'\n const days = daysInStage(deal, nowMs)\n\n return (\n <CardDisplay\n header={'Stage'}\n help={pluginDocsHelp('deals', { anchor: '#moving-winning-and-losing' })}\n actions={\n !closed ? (\n <Stack direction=\"row\" spacing={1}>\n <Button\n size=\"small\"\n color=\"success\"\n variant=\"outlined\"\n disabled={busy || !pipeline}\n startIcon={<MdiIcon path={mdiTrophyOutline.path} size={0.8} />}\n onClick={() => void run(() => api.markWon(deal), 'Deal won')}\n >\n {'Won'}\n </Button>\n <Button\n size=\"small\"\n color=\"error\"\n variant=\"outlined\"\n disabled={busy || !pipeline}\n startIcon={<MdiIcon path={mdiThumbDownOutline.path} size={0.8} />}\n onClick={() => setLosing(true)}\n >\n {'Lost'}\n </Button>\n </Stack>\n ) : null\n }\n contentGutterX\n contentGutterY\n >\n {!pipeline ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {\"This deal's pipeline no longer exists, so it has no stages to move through.\"}\n </Typography>\n ) : closed ? (\n <Stack spacing={1.5}>\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <Chip\n label={DEAL_STATUS_LABELS[deal.status]}\n color={deal.status === 'won' ? 'success' : 'default'}\n />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {typeof deal.closedAtMs === 'number'\n ? `Closed ${new Date(deal.closedAtMs).toLocaleDateString()}`\n : 'Closed'}\n </Typography>\n </Stack>\n {deal.status === 'lost' && deal.lostReason ? (\n <Typography variant=\"body2\">{deal.lostReason}</Typography>\n ) : null}\n <TextField\n select\n size=\"small\"\n label=\"Reopen into\"\n value=\"\"\n disabled={busy}\n onChange={(event) => {\n const stageId = event.target.value\n if (!stageId) return\n void run(() => api.moveToStage(deal, stageId), 'Deal reopened')\n }}\n helperText=\"Reopening puts the deal back in an open stage and tells the automations.\"\n sx={{ maxWidth: 320 }}\n >\n <MenuItem value=\"\">{'Pick a stage'}</MenuItem>\n {stages.map((stage) => (\n <MenuItem key={stage.id} value={stage.id}>\n {stage.name}\n </MenuItem>\n ))}\n </TextField>\n </Stack>\n ) : (\n <Stack spacing={1.5}>\n <Stepper nonLinear activeStep={activeIndex} alternativeLabel>\n {stages.map((stage, index) => (\n <Step key={stage.id} completed={index < activeIndex}>\n <StepButton\n disabled={busy || stage.id === deal.stageId}\n onClick={() =>\n void run(\n () => api.moveToStage(deal, stage.id),\n `Moved to ${stage.name}`,\n )\n }\n >\n {stage.name}\n </StepButton>\n </Step>\n ))}\n </Stepper>\n <Typography variant=\"body2\" color=\"text.secondary\" sx={{ textAlign: 'center' }}>\n {activeIndex === -1\n ? 'This deal sits in a stage the pipeline no longer has. Pick one above.'\n : `${days} ${days === 1 ? 'day' : 'days'} in ${stages[activeIndex].name} · ` +\n `${stages[activeIndex].probability}% likely to close`}\n </Typography>\n </Stack>\n )}\n <LostReasonDialog\n open={losing}\n dealTitle={deal.title}\n busy={busy}\n onClose={() => setLosing(false)}\n onConfirm={(reason) =>\n void run(() => api.markLost(deal, reason), 'Deal marked lost').then(\n (ok) => ok && setLosing(false),\n )\n }\n />\n </CardDisplay>\n )\n}\nDealStageCard.displayName = 'DealStageCard'\n\nexport default DealStageCard\n"],"names":["pluginDocsHelp","mdiThumbDownOutline","mdiTrophyOutline","CardDisplay","MdiIcon","useSnackbar","Button","Chip","MenuItem","Stack","Step","StepButton","Stepper","TextField","Typography","useCallback","useState","daysInStage","DEAL_STATUS_LABELS","openStages","LostReasonDialog","DealStageCard","props","deal","pipeline","api","nowMs","enqueueSnackbar","busy","setBusy","losing","setLosing","stages","activeIndex","findIndex","stage","id","stageId","run","request","done","variant","persist","error","Error","message","allowDuplicate","closed","status","days","header","help","anchor","actions","direction","spacing","size","color","disabled","startIcon","path","onClick","markWon","contentGutterX","contentGutterY","sx","alignItems","label","closedAtMs","Date","toLocaleDateString","lostReason","select","value","onChange","event","target","moveToStage","helperText","maxWidth","map","name","nonLinear","activeStep","alternativeLabel","index","completed","textAlign","probability","open","dealTitle","title","onClose","onConfirm","reason","markLost","then","ok","displayName"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { DealStageApi } from '../hooks/use-deal-stage-api';
2
+ import type { OrgMemberDirectory } from '../hooks/use-org-member-directory';
3
+ import { type DealDoc, type PipelineDoc } from '../model/deal-board-model';
4
+ import { type DealCsvOptions } from '../model/deals-csv';
5
+ export interface DealsBulkBarProps {
6
+ /**
7
+ * The site whose activity feed the bar's acts are logged in, or `null`
8
+ * at the organization level (AGL-2630), where the selection spans sites
9
+ * and the org's feed takes one line for the action instead (AGL-2634);
10
+ * a stage move runs as the org there and is logged per deal by the route.
11
+ */
12
+ hostId: string | null;
13
+ /** `['orgs', orgId]`, or `null` while the org is unresolved. */
14
+ scope: readonly ['orgs', string] | null;
15
+ rows: readonly DealDoc[];
16
+ selected: readonly string[];
17
+ onSelectedChange: (ids: string[]) => void;
18
+ /** The pipeline a deal's `pipelineId` names, for the stage list. */
19
+ pipelineById: (id: string | undefined) => PipelineDoc | null;
20
+ /** The section's roster — already read for the Owner column. */
21
+ roster: OrgMemberDirectory;
22
+ /** The one door a stage change goes through. */
23
+ api: DealStageApi;
24
+ /** How the export names the pipeline, the stage and the owner — the table's own. */
25
+ csv?: DealCsvOptions;
26
+ }
27
+ export declare function DealsBulkBar(props: DealsBulkBarProps): import("react").JSX.Element;
28
+ export declare namespace DealsBulkBar {
29
+ var displayName: string;
30
+ }
31
+ export default DealsBulkBar;