@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,368 @@
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 { _ as _extends } from "@swc/helpers/_/_extends";
18
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
+ import * as Aglyn from "@aglyn/aglyn";
20
+ import { useSnackbar } from "@aglyn/shared-ui-snackstack";
21
+ import { useUser, useUserName } from "@aglyn/tenant-feature-instance";
22
+ import { Button, Dialog, DialogActions, DialogContent, DialogTitle, MenuItem, Stack, TextField } from "@mui/material";
23
+ import { addDoc, collection, deleteField, doc, getCountFromServer, query, updateDoc, where } from "firebase/firestore";
24
+ import { useCallback, useEffect, useState } from "react";
25
+ import { crmVisibleToClause } from "../hooks/use-crm-scope.js";
26
+ import { CrmSitePicker } from "./crm-site-picker.js";
27
+ /** The longest body a single activity stores — a call summary, not a document. */ const BODY_MAX = 4000;
28
+ const OUTCOME_MAX = 200;
29
+ const DURATION_MAX_MINUTES = 24 * 60;
30
+ /**
31
+ * Epoch millis as the value a `datetime-local` input holds, in the LOCAL
32
+ * zone — the input has no zone of its own, so an ISO string with a `Z`
33
+ * would land the call an offset away from when it happened.
34
+ */ function toLocalInput(ms) {
35
+ if (!Number.isFinite(ms)) return '';
36
+ const date = new Date(ms);
37
+ const pad = (value)=>String(value).padStart(2, '0');
38
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-` + `${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
39
+ }
40
+ /** The inverse: a `datetime-local` value parsed as local time, or `null`. */ function fromLocalInput(value) {
41
+ if (!value) return null;
42
+ const ms = new Date(value).getTime();
43
+ return Number.isFinite(ms) ? ms : null;
44
+ }
45
+ /** The kind a new activity opens on when the caller names none. */ const DEFAULT_KIND = 'call';
46
+ const freshDraft = (kind = DEFAULT_KIND)=>({
47
+ kind,
48
+ body: '',
49
+ at: toLocalInput(Date.now()),
50
+ outcome: '',
51
+ durationMinutes: ''
52
+ });
53
+ const draftFrom = (activity)=>{
54
+ var _activity_body, _activity_outcome;
55
+ return {
56
+ kind: Aglyn.isCrmActivityKind(activity.kind) ? activity.kind : 'other',
57
+ body: (_activity_body = activity.body) != null ? _activity_body : '',
58
+ at: toLocalInput(activity.atMs),
59
+ outcome: (_activity_outcome = activity.outcome) != null ? _activity_outcome : '',
60
+ durationMinutes: typeof activity.durationMinutes === 'number' ? String(activity.durationMinutes) : ''
61
+ };
62
+ };
63
+ /**
64
+ * Log a call, an email, a meeting, a note or something else against a
65
+ * record (AGL-2600) — or correct one already logged.
66
+ *
67
+ * ## What is written
68
+ *
69
+ * A new activity carries the whole `CrmScoped` stamp: `visibleTo` from
70
+ * `crmScopeTokens`, so it lands in exactly the scope a contact captured on
71
+ * this site would; `hostId` as provenance; `byUid` and `byName` for the
72
+ * author, the name denormalized because a colleague reading the log cannot
73
+ * resolve a uid (see `CrmActivity.byName`); `atMs` for when it HAPPENED,
74
+ * which the reader picks and which defaults to now; and the timestamps.
75
+ *
76
+ * An edit rewrites only the fields the dialog shows. `visibleTo` is never
77
+ * touched — the rules refuse a scoped member changing it, and widening a
78
+ * record is an act for an org-wide member on the record itself — and neither
79
+ * is the author or the link. A kind that stops taking an outcome takes the
80
+ * outcome and the duration off the document rather than leaving a stale
81
+ * "left a voicemail" on what is now a note.
82
+ *
83
+ * ## Who may write
84
+ *
85
+ * The rules admit any member who may write scoped org data, on create and
86
+ * on update alike; they do not distinguish the author. The card that opens
87
+ * this dialog for an edit checks the author itself (`useCanEditActivity`),
88
+ * so what reaches here has already passed the console's verdict.
89
+ */ export function LogActivityDialog(props) {
90
+ const { open, onClose, scope, link, activity, kind: presetKind } = props;
91
+ const { firestore, dataScope, hostId, mountedHostId, readTokens, writeTokens } = scope;
92
+ const { data: user } = useUser();
93
+ const authorName = useUserName();
94
+ const { enqueueSnackbar } = useSnackbar();
95
+ const [draft, setDraft] = useState(freshDraft);
96
+ const [saving, setSaving] = useState(false);
97
+ /*
98
+ * Seeded on OPEN, not on mount: the dialog stays mounted between uses so
99
+ * its state survives a close, and "log another call" must start from now
100
+ * rather than from the last call's timestamp.
101
+ */ useEffect(()=>{
102
+ if (open) setDraft(activity ? draftFrom(activity) : freshDraft(presetKind));
103
+ }, [
104
+ open,
105
+ activity,
106
+ presetKind
107
+ ]);
108
+ const hasOutcome = Aglyn.activityKindHasOutcome(draft.kind);
109
+ const atMs = fromLocalInput(draft.at);
110
+ const body = draft.body.trim();
111
+ const duration = draft.durationMinutes.trim() ? Number(draft.durationMinutes) : null;
112
+ const durationValid = duration === null || Number.isInteger(duration) && duration >= 0 && duration <= DURATION_MAX_MINUTES;
113
+ const canSave = Boolean(dataScope) && Boolean(user == null ? void 0 : user.uid) && // A NEW activity is stamped with a site's scope and provenance; at the
114
+ // organization level that is the picked site, and there is nothing to
115
+ // write until there is one (AGL-2630). An edit never touches either.
116
+ (Boolean(activity) || Boolean(hostId)) && body.length > 0 && atMs !== null && durationValid && !saving;
117
+ const handleSave = useCallback(async ()=>{
118
+ // Every guard the button reads, again — a callback can outlive the
119
+ // render that disabled it.
120
+ if (!dataScope || !(user == null ? void 0 : user.uid) || !body || atMs === null || !durationValid) {
121
+ return;
122
+ }
123
+ if (!activity && !hostId) return;
124
+ setSaving(true);
125
+ try {
126
+ const said = {
127
+ kind: draft.kind,
128
+ body: body.slice(0, BODY_MAX),
129
+ atMs
130
+ };
131
+ const outcome = hasOutcome ? draft.outcome.trim().slice(0, OUTCOME_MAX) : '';
132
+ const durationMinutes = hasOutcome && duration !== null ? duration : null;
133
+ if (activity) {
134
+ await updateDoc(doc(firestore, dataScope[0], dataScope[1], Aglyn.CRM_COLLECTIONS.activities, activity.$id), _extends({}, said, {
135
+ // Cleared rather than left: a call turned into a note must not
136
+ // keep the call's outcome, and Firestore refuses `undefined`.
137
+ outcome: outcome ? outcome : deleteField(),
138
+ durationMinutes: durationMinutes !== null ? durationMinutes : deleteField(),
139
+ updatedAt: new Date()
140
+ }));
141
+ enqueueSnackbar('Activity updated', {
142
+ variant: 'success',
143
+ persist: false
144
+ });
145
+ } else {
146
+ /*
147
+ * THE PER-RECORD CEILING (AGL-2611): one aggregate on the record
148
+ * this dialog is filing under, before the write — the same count
149
+ * the automation step and the REST create take, on the same link.
150
+ * Scoped to the tokens this viewer may list, as every activity
151
+ * listener is, so the rules admit the aggregate for a scoped
152
+ * member exactly as they admit the timeline.
153
+ */ const lead = Aglyn.crmActivityCeilingLink(link);
154
+ if (lead) {
155
+ const logged = (await getCountFromServer(query(collection(firestore, dataScope[0], dataScope[1], Aglyn.CRM_COLLECTIONS.activities), ...crmVisibleToClause(readTokens), where(lead.field, '==', lead.id)))).data().count;
156
+ if (!Aglyn.crmActivityLogHasRoom(logged)) {
157
+ enqueueSnackbar(Aglyn.CRM_ACTIVITY_LOG_FULL_MESSAGE, {
158
+ variant: 'warning',
159
+ persist: false
160
+ });
161
+ return;
162
+ }
163
+ }
164
+ await addDoc(collection(firestore, dataScope[0], dataScope[1], Aglyn.CRM_COLLECTIONS.activities), _extends({}, said, outcome ? {
165
+ outcome
166
+ } : {}, durationMinutes !== null ? {
167
+ durationMinutes
168
+ } : {}, link.contactId ? {
169
+ contactId: link.contactId
170
+ } : {}, link.companyId ? {
171
+ companyId: link.companyId
172
+ } : {}, link.dealId ? {
173
+ dealId: link.dealId
174
+ } : {}, link.leadId ? {
175
+ leadId: link.leadId
176
+ } : {}, {
177
+ visibleTo: writeTokens,
178
+ hostId,
179
+ byUid: user.uid
180
+ }, authorName ? {
181
+ byName: authorName
182
+ } : {}, {
183
+ createdAt: new Date(),
184
+ updatedAt: new Date()
185
+ }));
186
+ enqueueSnackbar('Activity logged', {
187
+ variant: 'success',
188
+ persist: false
189
+ });
190
+ }
191
+ onClose();
192
+ } catch (error) {
193
+ console.error(error);
194
+ enqueueSnackbar('An error has occurred', {
195
+ variant: 'error',
196
+ allowDuplicate: true
197
+ });
198
+ } finally{
199
+ setSaving(false);
200
+ }
201
+ }, [
202
+ dataScope,
203
+ user,
204
+ body,
205
+ atMs,
206
+ durationValid,
207
+ draft.kind,
208
+ draft.outcome,
209
+ hasOutcome,
210
+ duration,
211
+ activity,
212
+ firestore,
213
+ enqueueSnackbar,
214
+ link,
215
+ readTokens,
216
+ writeTokens,
217
+ hostId,
218
+ authorName,
219
+ onClose
220
+ ]);
221
+ return /*#__PURE__*/ _jsxs(Dialog, {
222
+ open: open,
223
+ onClose: onClose,
224
+ maxWidth: "sm",
225
+ fullWidth: true,
226
+ children: [
227
+ /*#__PURE__*/ _jsx(DialogTitle, {
228
+ children: activity ? 'Edit activity' : 'Log activity'
229
+ }),
230
+ /*#__PURE__*/ _jsxs(DialogContent, {
231
+ sx: {
232
+ display: 'flex',
233
+ flexDirection: 'column',
234
+ gap: 2
235
+ },
236
+ children: [
237
+ activity ? null : /*#__PURE__*/ _jsx(CrmSitePicker, {
238
+ hostId: mountedHostId,
239
+ disabled: saving,
240
+ helperText: "The site this activity is logged from — it decides which of your sites may see it."
241
+ }),
242
+ /*#__PURE__*/ _jsxs(Stack, {
243
+ direction: "row",
244
+ spacing: 1,
245
+ sx: {
246
+ mt: 1
247
+ },
248
+ children: [
249
+ /*#__PURE__*/ _jsx(TextField, {
250
+ select: true,
251
+ size: "small",
252
+ label: "Kind",
253
+ value: draft.kind,
254
+ onChange: (event)=>setDraft((prev)=>_extends({}, prev, {
255
+ kind: Aglyn.isCrmActivityKind(event.target.value) ? event.target.value : prev.kind
256
+ })),
257
+ sx: {
258
+ minWidth: 140
259
+ },
260
+ children: Aglyn.CRM_ACTIVITY_KINDS.map((kind)=>/*#__PURE__*/ _jsx(MenuItem, {
261
+ value: kind,
262
+ children: Aglyn.CRM_ACTIVITY_KIND_LABELS[kind]
263
+ }, kind))
264
+ }),
265
+ /*#__PURE__*/ _jsx(TextField, {
266
+ size: "small",
267
+ label: "When",
268
+ type: "datetime-local",
269
+ value: draft.at,
270
+ onChange: (event)=>setDraft((prev)=>_extends({}, prev, {
271
+ at: event.target.value
272
+ })),
273
+ error: draft.at.length > 0 && atMs === null,
274
+ slotProps: {
275
+ inputLabel: {
276
+ shrink: true
277
+ }
278
+ },
279
+ sx: {
280
+ flex: 1
281
+ }
282
+ })
283
+ ]
284
+ }),
285
+ /*#__PURE__*/ _jsx(TextField, {
286
+ size: "small",
287
+ label: "What happened",
288
+ value: draft.body,
289
+ onChange: (event)=>setDraft((prev)=>_extends({}, prev, {
290
+ body: event.target.value
291
+ })),
292
+ multiline: true,
293
+ minRows: 3,
294
+ autoFocus: true,
295
+ slotProps: {
296
+ htmlInput: {
297
+ maxLength: BODY_MAX
298
+ }
299
+ }
300
+ }),
301
+ hasOutcome ? /*#__PURE__*/ _jsxs(Stack, {
302
+ direction: "row",
303
+ spacing: 1,
304
+ children: [
305
+ /*#__PURE__*/ _jsx(TextField, {
306
+ size: "small",
307
+ label: "Outcome",
308
+ placeholder: "Left a voicemail",
309
+ value: draft.outcome,
310
+ onChange: (event)=>setDraft((prev)=>_extends({}, prev, {
311
+ outcome: event.target.value
312
+ })),
313
+ slotProps: {
314
+ htmlInput: {
315
+ maxLength: OUTCOME_MAX
316
+ }
317
+ },
318
+ sx: {
319
+ flex: 1
320
+ }
321
+ }),
322
+ /*#__PURE__*/ _jsx(TextField, {
323
+ size: "small",
324
+ label: "Minutes",
325
+ type: "number",
326
+ value: draft.durationMinutes,
327
+ onChange: (event)=>setDraft((prev)=>_extends({}, prev, {
328
+ durationMinutes: event.target.value
329
+ })),
330
+ error: !durationValid,
331
+ slotProps: {
332
+ htmlInput: {
333
+ min: 0,
334
+ max: DURATION_MAX_MINUTES,
335
+ step: 1
336
+ }
337
+ },
338
+ sx: {
339
+ width: 120
340
+ }
341
+ })
342
+ ]
343
+ }) : null
344
+ ]
345
+ }),
346
+ /*#__PURE__*/ _jsxs(DialogActions, {
347
+ children: [
348
+ /*#__PURE__*/ _jsx(Button, {
349
+ onClick: onClose,
350
+ disabled: saving,
351
+ children: 'Cancel'
352
+ }),
353
+ /*#__PURE__*/ _jsx(Button, {
354
+ variant: "contained",
355
+ color: "primary",
356
+ disabled: !canSave,
357
+ onClick: handleSave,
358
+ children: activity ? 'Save' : 'Log'
359
+ })
360
+ ]
361
+ })
362
+ ]
363
+ });
364
+ }
365
+ LogActivityDialog.displayName = 'LogActivityDialog';
366
+ export default LogActivityDialog;
367
+
368
+ //# sourceMappingURL=log-activity-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/log-activity-dialog.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 * as Aglyn from '@aglyn/aglyn'\nimport type { CrmActivityKind, CrmActivityRow } from '@aglyn/aglyn'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useUser, useUserName } from '@aglyn/tenant-feature-instance'\nimport {\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n MenuItem,\n Stack,\n TextField,\n} from '@mui/material'\nimport {\n addDoc,\n collection,\n deleteField,\n doc,\n getCountFromServer,\n query,\n updateDoc,\n where,\n} from 'firebase/firestore'\nimport { useCallback, useEffect, useState } from 'react'\nimport { crmVisibleToClause } from '../hooks/use-crm-scope'\nimport type { ActivityRecordLink, ActivityScope } from './activity-queries'\nimport { CrmSitePicker } from './crm-site-picker'\n\n/** The longest body a single activity stores — a call summary, not a document. */\nconst BODY_MAX = 4000\nconst OUTCOME_MAX = 200\nconst DURATION_MAX_MINUTES = 24 * 60\n\n/**\n * Epoch millis as the value a `datetime-local` input holds, in the LOCAL\n * zone — the input has no zone of its own, so an ISO string with a `Z`\n * would land the call an offset away from when it happened.\n */\nfunction toLocalInput(ms: number): string {\n if (!Number.isFinite(ms)) return ''\n const date = new Date(ms)\n const pad = (value: number) => String(value).padStart(2, '0')\n return (\n `${date.getFullYear()}-${pad(date.getMonth() + 1)}-` +\n `${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`\n )\n}\n\n/** The inverse: a `datetime-local` value parsed as local time, or `null`. */\nfunction fromLocalInput(value: string): number | null {\n if (!value) return null\n const ms = new Date(value).getTime()\n return Number.isFinite(ms) ? ms : null\n}\n\ninterface Draft {\n kind: CrmActivityKind\n body: string\n /** The `datetime-local` string, not millis — what the input holds. */\n at: string\n outcome: string\n /** Free text until save, so a half-typed number does not snap to zero. */\n durationMinutes: string\n}\n\n/** The kind a new activity opens on when the caller names none. */\nconst DEFAULT_KIND: CrmActivityKind = 'call'\n\nconst freshDraft = (kind: CrmActivityKind = DEFAULT_KIND): Draft => ({\n kind,\n body: '',\n at: toLocalInput(Date.now()),\n outcome: '',\n durationMinutes: '',\n})\n\nconst draftFrom = (activity: CrmActivityRow): Draft => ({\n kind: Aglyn.isCrmActivityKind(activity.kind) ? activity.kind : 'other',\n body: activity.body ?? '',\n at: toLocalInput(activity.atMs),\n outcome: activity.outcome ?? '',\n durationMinutes:\n typeof activity.durationMinutes === 'number'\n ? String(activity.durationMinutes)\n : '',\n})\n\nexport interface LogActivityDialogProps {\n open: boolean\n onClose: () => void\n /** Where the activity is written, from `useActivityScope`. */\n scope: ActivityScope\n /**\n * The record the activity is filed against, FIXED by the caller. A\n * contact's page logs against that contact; the dialog offers no picker,\n * because an activity logged from a record page is about that record and\n * a picker would be a way to file it somewhere the reader is not looking.\n */\n link: ActivityRecordLink\n /**\n * When set, the dialog EDITS this activity rather than logging a new one.\n * The link, the author and the scope stay what they were; only what was\n * said, when, and how it went can change.\n */\n activity?: CrmActivityRow | null\n /**\n * What a NEW activity opens as (AGL-2661) — the click-to-call button\n * opens the dialog already a call, so logging one is the button and a\n * sentence rather than the button, the kind and a sentence. Ignored for\n * an edit, whose kind is the activity's own.\n */\n kind?: CrmActivityKind\n}\n\n/**\n * Log a call, an email, a meeting, a note or something else against a\n * record (AGL-2600) — or correct one already logged.\n *\n * ## What is written\n *\n * A new activity carries the whole `CrmScoped` stamp: `visibleTo` from\n * `crmScopeTokens`, so it lands in exactly the scope a contact captured on\n * this site would; `hostId` as provenance; `byUid` and `byName` for the\n * author, the name denormalized because a colleague reading the log cannot\n * resolve a uid (see `CrmActivity.byName`); `atMs` for when it HAPPENED,\n * which the reader picks and which defaults to now; and the timestamps.\n *\n * An edit rewrites only the fields the dialog shows. `visibleTo` is never\n * touched — the rules refuse a scoped member changing it, and widening a\n * record is an act for an org-wide member on the record itself — and neither\n * is the author or the link. A kind that stops taking an outcome takes the\n * outcome and the duration off the document rather than leaving a stale\n * \"left a voicemail\" on what is now a note.\n *\n * ## Who may write\n *\n * The rules admit any member who may write scoped org data, on create and\n * on update alike; they do not distinguish the author. The card that opens\n * this dialog for an edit checks the author itself (`useCanEditActivity`),\n * so what reaches here has already passed the console's verdict.\n */\nexport function LogActivityDialog(props: LogActivityDialogProps) {\n const { open, onClose, scope, link, activity, kind: presetKind } = props\n const { firestore, dataScope, hostId, mountedHostId, readTokens, writeTokens } =\n scope\n const { data: user } = useUser()\n const authorName = useUserName()\n const { enqueueSnackbar } = useSnackbar()\n const [draft, setDraft] = useState<Draft>(freshDraft)\n const [saving, setSaving] = useState(false)\n\n /*\n * Seeded on OPEN, not on mount: the dialog stays mounted between uses so\n * its state survives a close, and \"log another call\" must start from now\n * rather than from the last call's timestamp.\n */\n useEffect(() => {\n if (open) setDraft(activity ? draftFrom(activity) : freshDraft(presetKind))\n }, [open, activity, presetKind])\n\n const hasOutcome = Aglyn.activityKindHasOutcome(draft.kind)\n const atMs = fromLocalInput(draft.at)\n const body = draft.body.trim()\n const duration = draft.durationMinutes.trim()\n ? Number(draft.durationMinutes)\n : null\n const durationValid =\n duration === null ||\n (Number.isInteger(duration) &&\n duration >= 0 &&\n duration <= DURATION_MAX_MINUTES)\n const canSave =\n Boolean(dataScope) &&\n Boolean(user?.uid) &&\n // A NEW activity is stamped with a site's scope and provenance; at the\n // organization level that is the picked site, and there is nothing to\n // write until there is one (AGL-2630). An edit never touches either.\n (Boolean(activity) || Boolean(hostId)) &&\n body.length > 0 &&\n atMs !== null &&\n durationValid &&\n !saving\n\n const handleSave = useCallback(async () => {\n // Every guard the button reads, again — a callback can outlive the\n // render that disabled it.\n if (!dataScope || !user?.uid || !body || atMs === null || !durationValid) {\n return\n }\n if (!activity && !hostId) return\n setSaving(true)\n try {\n const said = {\n kind: draft.kind,\n body: body.slice(0, BODY_MAX),\n atMs,\n }\n const outcome = hasOutcome ? draft.outcome.trim().slice(0, OUTCOME_MAX) : ''\n const durationMinutes = hasOutcome && duration !== null ? duration : null\n if (activity) {\n await updateDoc(\n doc(\n firestore,\n dataScope[0],\n dataScope[1],\n Aglyn.CRM_COLLECTIONS.activities,\n activity.$id,\n ),\n {\n ...said,\n // Cleared rather than left: a call turned into a note must not\n // keep the call's outcome, and Firestore refuses `undefined`.\n outcome: outcome ? outcome : deleteField(),\n durationMinutes:\n durationMinutes !== null ? durationMinutes : deleteField(),\n updatedAt: new Date(),\n },\n )\n enqueueSnackbar('Activity updated', { variant: 'success', persist: false })\n } else {\n /*\n * THE PER-RECORD CEILING (AGL-2611): one aggregate on the record\n * this dialog is filing under, before the write — the same count\n * the automation step and the REST create take, on the same link.\n * Scoped to the tokens this viewer may list, as every activity\n * listener is, so the rules admit the aggregate for a scoped\n * member exactly as they admit the timeline.\n */\n const lead = Aglyn.crmActivityCeilingLink(link)\n if (lead) {\n const logged = (\n await getCountFromServer(\n query(\n collection(\n firestore,\n dataScope[0],\n dataScope[1],\n Aglyn.CRM_COLLECTIONS.activities,\n ),\n ...crmVisibleToClause(readTokens),\n where(lead.field, '==', lead.id),\n ),\n )\n ).data().count\n if (!Aglyn.crmActivityLogHasRoom(logged)) {\n enqueueSnackbar(Aglyn.CRM_ACTIVITY_LOG_FULL_MESSAGE, {\n variant: 'warning',\n persist: false,\n })\n return\n }\n }\n await addDoc(\n collection(\n firestore,\n dataScope[0],\n dataScope[1],\n Aglyn.CRM_COLLECTIONS.activities,\n ),\n {\n ...said,\n ...(outcome ? { outcome } : {}),\n ...(durationMinutes !== null ? { durationMinutes } : {}),\n // Only the link the caller fixed. A key with no value is\n // `undefined`, which Firestore refuses, so each is spread in\n // rather than written blank.\n ...(link.contactId ? { contactId: link.contactId } : {}),\n ...(link.companyId ? { companyId: link.companyId } : {}),\n ...(link.dealId ? { dealId: link.dealId } : {}),\n ...(link.leadId ? { leadId: link.leadId } : {}),\n visibleTo: writeTokens,\n hostId,\n byUid: user.uid,\n // Absent rather than blank while the profile is still resolving:\n // the row reads a stored name over anything else, and an empty\n // string would be a name.\n ...(authorName ? { byName: authorName } : {}),\n createdAt: new Date(),\n updatedAt: new Date(),\n },\n )\n enqueueSnackbar('Activity logged', { variant: 'success', persist: false })\n }\n onClose()\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setSaving(false)\n }\n }, [\n dataScope,\n user,\n body,\n atMs,\n durationValid,\n draft.kind,\n draft.outcome,\n hasOutcome,\n duration,\n activity,\n firestore,\n enqueueSnackbar,\n link,\n readTokens,\n writeTokens,\n hostId,\n authorName,\n onClose,\n ])\n\n return (\n <Dialog open={open} onClose={onClose} maxWidth=\"sm\" fullWidth>\n <DialogTitle>{activity ? 'Edit activity' : 'Log activity'}</DialogTitle>\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>\n {/* Only for a new activity at the organization level — see `canSave`. */}\n {activity ? null : (\n <CrmSitePicker\n hostId={mountedHostId}\n disabled={saving}\n helperText=\"The site this activity is logged from — it decides which of your sites may see it.\"\n />\n )}\n <Stack direction=\"row\" spacing={1} sx={{ mt: 1 }}>\n <TextField\n select\n size=\"small\"\n label=\"Kind\"\n value={draft.kind}\n onChange={(event) =>\n setDraft((prev) => ({\n ...prev,\n kind: Aglyn.isCrmActivityKind(event.target.value)\n ? event.target.value\n : prev.kind,\n }))\n }\n sx={{ minWidth: 140 }}\n >\n {Aglyn.CRM_ACTIVITY_KINDS.map((kind) => (\n <MenuItem key={kind} value={kind}>\n {Aglyn.CRM_ACTIVITY_KIND_LABELS[kind]}\n </MenuItem>\n ))}\n </TextField>\n <TextField\n size=\"small\"\n label=\"When\"\n type=\"datetime-local\"\n value={draft.at}\n onChange={(event) =>\n setDraft((prev) => ({ ...prev, at: event.target.value }))\n }\n error={draft.at.length > 0 && atMs === null}\n slotProps={{ inputLabel: { shrink: true } }}\n sx={{ flex: 1 }}\n />\n </Stack>\n <TextField\n size=\"small\"\n label=\"What happened\"\n value={draft.body}\n onChange={(event) =>\n setDraft((prev) => ({ ...prev, body: event.target.value }))\n }\n multiline\n minRows={3}\n autoFocus\n slotProps={{ htmlInput: { maxLength: BODY_MAX } }}\n />\n {hasOutcome ? (\n <Stack direction=\"row\" spacing={1}>\n <TextField\n size=\"small\"\n label=\"Outcome\"\n placeholder=\"Left a voicemail\"\n value={draft.outcome}\n onChange={(event) =>\n setDraft((prev) => ({ ...prev, outcome: event.target.value }))\n }\n slotProps={{ htmlInput: { maxLength: OUTCOME_MAX } }}\n sx={{ flex: 1 }}\n />\n <TextField\n size=\"small\"\n label=\"Minutes\"\n type=\"number\"\n value={draft.durationMinutes}\n onChange={(event) =>\n setDraft((prev) => ({\n ...prev,\n durationMinutes: event.target.value,\n }))\n }\n error={!durationValid}\n slotProps={{\n htmlInput: { min: 0, max: DURATION_MAX_MINUTES, step: 1 },\n }}\n sx={{ width: 120 }}\n />\n </Stack>\n ) : null}\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose} disabled={saving}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n color=\"primary\"\n disabled={!canSave}\n onClick={handleSave}\n >\n {activity ? 'Save' : 'Log'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\nLogActivityDialog.displayName = 'LogActivityDialog'\n\nexport default LogActivityDialog\n"],"names":["Aglyn","useSnackbar","useUser","useUserName","Button","Dialog","DialogActions","DialogContent","DialogTitle","MenuItem","Stack","TextField","addDoc","collection","deleteField","doc","getCountFromServer","query","updateDoc","where","useCallback","useEffect","useState","crmVisibleToClause","CrmSitePicker","BODY_MAX","OUTCOME_MAX","DURATION_MAX_MINUTES","toLocalInput","ms","Number","isFinite","date","Date","pad","value","String","padStart","getFullYear","getMonth","getDate","getHours","getMinutes","fromLocalInput","getTime","DEFAULT_KIND","freshDraft","kind","body","at","now","outcome","durationMinutes","draftFrom","activity","isCrmActivityKind","atMs","LogActivityDialog","props","open","onClose","scope","link","presetKind","firestore","dataScope","hostId","mountedHostId","readTokens","writeTokens","data","user","authorName","enqueueSnackbar","draft","setDraft","saving","setSaving","hasOutcome","activityKindHasOutcome","trim","duration","durationValid","isInteger","canSave","Boolean","uid","length","handleSave","said","slice","CRM_COLLECTIONS","activities","$id","updatedAt","variant","persist","lead","crmActivityCeilingLink","logged","field","id","count","crmActivityLogHasRoom","CRM_ACTIVITY_LOG_FULL_MESSAGE","contactId","companyId","dealId","leadId","visibleTo","byUid","byName","createdAt","error","console","allowDuplicate","maxWidth","fullWidth","sx","display","flexDirection","gap","disabled","helperText","direction","spacing","mt","select","size","label","onChange","event","prev","target","minWidth","CRM_ACTIVITY_KINDS","map","CRM_ACTIVITY_KIND_LABELS","type","slotProps","inputLabel","shrink","flex","multiline","minRows","autoFocus","htmlInput","maxLength","placeholder","min","max","step","width","onClick","color","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,YAAYA,WAAW,eAAc;AAErC,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SAASC,OAAO,EAAEC,WAAW,QAAQ,iCAAgC;AACrE,SACEC,MAAM,EACNC,MAAM,EACNC,aAAa,EACbC,aAAa,EACbC,WAAW,EACXC,QAAQ,EACRC,KAAK,EACLC,SAAS,QACJ,gBAAe;AACtB,SACEC,MAAM,EACNC,UAAU,EACVC,WAAW,EACXC,GAAG,EACHC,kBAAkB,EAClBC,KAAK,EACLC,SAAS,EACTC,KAAK,QACA,qBAAoB;AAC3B,SAASC,WAAW,EAAEC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AACxD,SAASC,kBAAkB,QAAQ,4BAAwB;AAE3D,SAASC,aAAa,QAAQ,uBAAmB;AAEjD,gFAAgF,GAChF,MAAMC,WAAW;AACjB,MAAMC,cAAc;AACpB,MAAMC,uBAAuB,KAAK;AAElC;;;;CAIC,GACD,SAASC,aAAaC,EAAU;IAC9B,IAAI,CAACC,OAAOC,QAAQ,CAACF,KAAK,OAAO;IACjC,MAAMG,OAAO,IAAIC,KAAKJ;IACtB,MAAMK,MAAM,CAACC,QAAkBC,OAAOD,OAAOE,QAAQ,CAAC,GAAG;IACzD,OACE,GAAGL,KAAKM,WAAW,GAAG,CAAC,EAAEJ,IAAIF,KAAKO,QAAQ,KAAK,GAAG,CAAC,CAAC,GACpD,GAAGL,IAAIF,KAAKQ,OAAO,IAAI,CAAC,EAAEN,IAAIF,KAAKS,QAAQ,IAAI,CAAC,EAAEP,IAAIF,KAAKU,UAAU,KAAK;AAE9E;AAEA,2EAA2E,GAC3E,SAASC,eAAeR,KAAa;IACnC,IAAI,CAACA,OAAO,OAAO;IACnB,MAAMN,KAAK,IAAII,KAAKE,OAAOS,OAAO;IAClC,OAAOd,OAAOC,QAAQ,CAACF,MAAMA,KAAK;AACpC;AAYA,iEAAiE,GACjE,MAAMgB,eAAgC;AAEtC,MAAMC,aAAa,CAACC,OAAwBF,YAAY,GAAa,CAAA;QACnEE;QACAC,MAAM;QACNC,IAAIrB,aAAaK,KAAKiB,GAAG;QACzBC,SAAS;QACTC,iBAAiB;IACnB,CAAA;AAEA,MAAMC,YAAY,CAACC;QAEXA,gBAEGA;WAJ6C;QACtDP,MAAM/C,MAAMuD,iBAAiB,CAACD,SAASP,IAAI,IAAIO,SAASP,IAAI,GAAG;QAC/DC,IAAI,GAAEM,iBAAAA,SAASN,IAAI,YAAbM,iBAAiB;QACvBL,IAAIrB,aAAa0B,SAASE,IAAI;QAC9BL,OAAO,GAAEG,oBAAAA,SAASH,OAAO,YAAhBG,oBAAoB;QAC7BF,iBACE,OAAOE,SAASF,eAAe,KAAK,WAChChB,OAAOkB,SAASF,eAAe,IAC/B;IACR;;AA6BA;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BC,GACD,OAAO,SAASK,kBAAkBC,KAA6B;IAC7D,MAAM,EAAEC,IAAI,EAAEC,OAAO,EAAEC,KAAK,EAAEC,IAAI,EAAER,QAAQ,EAAEP,MAAMgB,UAAU,EAAE,GAAGL;IACnE,MAAM,EAAEM,SAAS,EAAEC,SAAS,EAAEC,MAAM,EAAEC,aAAa,EAAEC,UAAU,EAAEC,WAAW,EAAE,GAC5ER;IACF,MAAM,EAAES,MAAMC,IAAI,EAAE,GAAGrE;IACvB,MAAMsE,aAAarE;IACnB,MAAM,EAAEsE,eAAe,EAAE,GAAGxE;IAC5B,MAAM,CAACyE,OAAOC,SAAS,GAAGrD,SAAgBwB;IAC1C,MAAM,CAAC8B,QAAQC,UAAU,GAAGvD,SAAS;IAErC;;;;GAIC,GACDD,UAAU;QACR,IAAIsC,MAAMgB,SAASrB,WAAWD,UAAUC,YAAYR,WAAWiB;IACjE,GAAG;QAACJ;QAAML;QAAUS;KAAW;IAE/B,MAAMe,aAAa9E,MAAM+E,sBAAsB,CAACL,MAAM3B,IAAI;IAC1D,MAAMS,OAAOb,eAAe+B,MAAMzB,EAAE;IACpC,MAAMD,OAAO0B,MAAM1B,IAAI,CAACgC,IAAI;IAC5B,MAAMC,WAAWP,MAAMtB,eAAe,CAAC4B,IAAI,KACvClD,OAAO4C,MAAMtB,eAAe,IAC5B;IACJ,MAAM8B,gBACJD,aAAa,QACZnD,OAAOqD,SAAS,CAACF,aAChBA,YAAY,KACZA,YAAYtD;IAChB,MAAMyD,UACJC,QAAQpB,cACRoB,QAAQd,wBAAAA,KAAMe,GAAG,KACjB,uEAAuE;IACvE,sEAAsE;IACtE,qEAAqE;IACpED,CAAAA,QAAQ/B,aAAa+B,QAAQnB,OAAM,KACpClB,KAAKuC,MAAM,GAAG,KACd/B,SAAS,QACT0B,iBACA,CAACN;IAEH,MAAMY,aAAapE,YAAY;QAC7B,mEAAmE;QACnE,2BAA2B;QAC3B,IAAI,CAAC6C,aAAa,EAACM,wBAAAA,KAAMe,GAAG,KAAI,CAACtC,QAAQQ,SAAS,QAAQ,CAAC0B,eAAe;YACxE;QACF;QACA,IAAI,CAAC5B,YAAY,CAACY,QAAQ;QAC1BW,UAAU;QACV,IAAI;YACF,MAAMY,OAAO;gBACX1C,MAAM2B,MAAM3B,IAAI;gBAChBC,MAAMA,KAAK0C,KAAK,CAAC,GAAGjE;gBACpB+B;YACF;YACA,MAAML,UAAU2B,aAAaJ,MAAMvB,OAAO,CAAC6B,IAAI,GAAGU,KAAK,CAAC,GAAGhE,eAAe;YAC1E,MAAM0B,kBAAkB0B,cAAcG,aAAa,OAAOA,WAAW;YACrE,IAAI3B,UAAU;gBACZ,MAAMpC,UACJH,IACEiD,WACAC,SAAS,CAAC,EAAE,EACZA,SAAS,CAAC,EAAE,EACZjE,MAAM2F,eAAe,CAACC,UAAU,EAChCtC,SAASuC,GAAG,GAEd,aACKJ;oBACH,+DAA+D;oBAC/D,8DAA8D;oBAC9DtC,SAASA,UAAUA,UAAUrC;oBAC7BsC,iBACEA,oBAAoB,OAAOA,kBAAkBtC;oBAC/CgF,WAAW,IAAI7D;;gBAGnBwC,gBAAgB,oBAAoB;oBAAEsB,SAAS;oBAAWC,SAAS;gBAAM;YAC3E,OAAO;gBACL;;;;;;;SAOC,GACD,MAAMC,OAAOjG,MAAMkG,sBAAsB,CAACpC;gBAC1C,IAAImC,MAAM;oBACR,MAAME,SAAS,AACb,CAAA,MAAMnF,mBACJC,MACEJ,WACEmD,WACAC,SAAS,CAAC,EAAE,EACZA,SAAS,CAAC,EAAE,EACZjE,MAAM2F,eAAe,CAACC,UAAU,MAE/BrE,mBAAmB6C,aACtBjD,MAAM8E,KAAKG,KAAK,EAAE,MAAMH,KAAKI,EAAE,GAEnC,EACA/B,IAAI,GAAGgC,KAAK;oBACd,IAAI,CAACtG,MAAMuG,qBAAqB,CAACJ,SAAS;wBACxC1B,gBAAgBzE,MAAMwG,6BAA6B,EAAE;4BACnDT,SAAS;4BACTC,SAAS;wBACX;wBACA;oBACF;gBACF;gBACA,MAAMpF,OACJC,WACEmD,WACAC,SAAS,CAAC,EAAE,EACZA,SAAS,CAAC,EAAE,EACZjE,MAAM2F,eAAe,CAACC,UAAU,GAElC,aACKH,MACCtC,UAAU;oBAAEA;gBAAQ,IAAI,CAAC,GACzBC,oBAAoB,OAAO;oBAAEA;gBAAgB,IAAI,CAAC,GAIlDU,KAAK2C,SAAS,GAAG;oBAAEA,WAAW3C,KAAK2C,SAAS;gBAAC,IAAI,CAAC,GAClD3C,KAAK4C,SAAS,GAAG;oBAAEA,WAAW5C,KAAK4C,SAAS;gBAAC,IAAI,CAAC,GAClD5C,KAAK6C,MAAM,GAAG;oBAAEA,QAAQ7C,KAAK6C,MAAM;gBAAC,IAAI,CAAC,GACzC7C,KAAK8C,MAAM,GAAG;oBAAEA,QAAQ9C,KAAK8C,MAAM;gBAAC,IAAI,CAAC;oBAC7CC,WAAWxC;oBACXH;oBACA4C,OAAOvC,KAAKe,GAAG;mBAIXd,aAAa;oBAAEuC,QAAQvC;gBAAW,IAAI,CAAC;oBAC3CwC,WAAW,IAAI/E;oBACf6D,WAAW,IAAI7D;;gBAGnBwC,gBAAgB,mBAAmB;oBAAEsB,SAAS;oBAAWC,SAAS;gBAAM;YAC1E;YACApC;QACF,EAAE,OAAOqD,OAAO;YACdC,QAAQD,KAAK,CAACA;YACdxC,gBAAgB,yBAAyB;gBACvCsB,SAAS;gBACToB,gBAAgB;YAClB;QACF,SAAU;YACRtC,UAAU;QACZ;IACF,GAAG;QACDZ;QACAM;QACAvB;QACAQ;QACA0B;QACAR,MAAM3B,IAAI;QACV2B,MAAMvB,OAAO;QACb2B;QACAG;QACA3B;QACAU;QACAS;QACAX;QACAM;QACAC;QACAH;QACAM;QACAZ;KACD;IAED,qBACE,MAACvD;QAAOsD,MAAMA;QAAMC,SAASA;QAASwD,UAAS;QAAKC,SAAS;;0BAC3D,KAAC7G;0BAAa8C,WAAW,kBAAkB;;0BAC3C,MAAC/C;gBAAc+G,IAAI;oBAAEC,SAAS;oBAAQC,eAAe;oBAAUC,KAAK;gBAAE;;oBAEnEnE,WAAW,qBACV,KAAC9B;wBACC0C,QAAQC;wBACRuD,UAAU9C;wBACV+C,YAAW;;kCAGf,MAACjH;wBAAMkH,WAAU;wBAAMC,SAAS;wBAAGP,IAAI;4BAAEQ,IAAI;wBAAE;;0CAC7C,KAACnH;gCACCoH,MAAM;gCACNC,MAAK;gCACLC,OAAM;gCACN9F,OAAOuC,MAAM3B,IAAI;gCACjBmF,UAAU,CAACC,QACTxD,SAAS,CAACyD,OAAU,aACfA;4CACHrF,MAAM/C,MAAMuD,iBAAiB,CAAC4E,MAAME,MAAM,CAAClG,KAAK,IAC5CgG,MAAME,MAAM,CAAClG,KAAK,GAClBiG,KAAKrF,IAAI;;gCAGjBuE,IAAI;oCAAEgB,UAAU;gCAAI;0CAEnBtI,MAAMuI,kBAAkB,CAACC,GAAG,CAAC,CAACzF,qBAC7B,KAACtC;wCAAoB0B,OAAOY;kDACzB/C,MAAMyI,wBAAwB,CAAC1F,KAAK;uCADxBA;;0CAKnB,KAACpC;gCACCqH,MAAK;gCACLC,OAAM;gCACNS,MAAK;gCACLvG,OAAOuC,MAAMzB,EAAE;gCACfiF,UAAU,CAACC,QACTxD,SAAS,CAACyD,OAAU,aAAKA;4CAAMnF,IAAIkF,MAAME,MAAM,CAAClG,KAAK;;gCAEvD8E,OAAOvC,MAAMzB,EAAE,CAACsC,MAAM,GAAG,KAAK/B,SAAS;gCACvCmF,WAAW;oCAAEC,YAAY;wCAAEC,QAAQ;oCAAK;gCAAE;gCAC1CvB,IAAI;oCAAEwB,MAAM;gCAAE;;;;kCAGlB,KAACnI;wBACCqH,MAAK;wBACLC,OAAM;wBACN9F,OAAOuC,MAAM1B,IAAI;wBACjBkF,UAAU,CAACC,QACTxD,SAAS,CAACyD,OAAU,aAAKA;oCAAMpF,MAAMmF,MAAME,MAAM,CAAClG,KAAK;;wBAEzD4G,SAAS;wBACTC,SAAS;wBACTC,SAAS;wBACTN,WAAW;4BAAEO,WAAW;gCAAEC,WAAW1H;4BAAS;wBAAE;;oBAEjDqD,2BACC,MAACpE;wBAAMkH,WAAU;wBAAMC,SAAS;;0CAC9B,KAAClH;gCACCqH,MAAK;gCACLC,OAAM;gCACNmB,aAAY;gCACZjH,OAAOuC,MAAMvB,OAAO;gCACpB+E,UAAU,CAACC,QACTxD,SAAS,CAACyD,OAAU,aAAKA;4CAAMjF,SAASgF,MAAME,MAAM,CAAClG,KAAK;;gCAE5DwG,WAAW;oCAAEO,WAAW;wCAAEC,WAAWzH;oCAAY;gCAAE;gCACnD4F,IAAI;oCAAEwB,MAAM;gCAAE;;0CAEhB,KAACnI;gCACCqH,MAAK;gCACLC,OAAM;gCACNS,MAAK;gCACLvG,OAAOuC,MAAMtB,eAAe;gCAC5B8E,UAAU,CAACC,QACTxD,SAAS,CAACyD,OAAU,aACfA;4CACHhF,iBAAiB+E,MAAME,MAAM,CAAClG,KAAK;;gCAGvC8E,OAAO,CAAC/B;gCACRyD,WAAW;oCACTO,WAAW;wCAAEG,KAAK;wCAAGC,KAAK3H;wCAAsB4H,MAAM;oCAAE;gCAC1D;gCACAjC,IAAI;oCAAEkC,OAAO;gCAAI;;;yBAGnB;;;0BAEN,MAAClJ;;kCACC,KAACF;wBAAOqJ,SAAS7F;wBAAS8D,UAAU9C;kCACjC;;kCAEH,KAACxE;wBACC2F,SAAQ;wBACR2D,OAAM;wBACNhC,UAAU,CAACtC;wBACXqE,SAASjE;kCAERlC,WAAW,SAAS;;;;;;AAK/B;AACAG,kBAAkBkG,WAAW,GAAG;AAEhC,eAAelG,kBAAiB"}
@@ -0,0 +1,26 @@
1
+ export interface LostReasonDialogProps {
2
+ open: boolean;
3
+ /** The deal being closed, for the title. */
4
+ dealTitle: string;
5
+ /**
6
+ * How many deals the reason applies to — the bulk bar's selection
7
+ * (AGL-2621). One, or absent, names the deal; more says the number.
8
+ */
9
+ count?: number;
10
+ busy?: boolean;
11
+ onClose: () => void;
12
+ onConfirm: (reason: string) => void;
13
+ }
14
+ /**
15
+ * The question a loss asks before it is recorded.
16
+ *
17
+ * A lost deal with no reason is a row a report cannot learn from, so the
18
+ * dialog asks — but it does not insist. The reason is optional, because a
19
+ * required field here is how "n/a" becomes the most common answer in the
20
+ * data, and an empty reason is at least honest.
21
+ */
22
+ export declare function LostReasonDialog(props: LostReasonDialogProps): import("react").JSX.Element;
23
+ export declare namespace LostReasonDialog {
24
+ var displayName: string;
25
+ }
26
+ export default LostReasonDialog;
@@ -0,0 +1,95 @@
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 { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField } from "@mui/material";
19
+ import { useEffect, useState } from "react";
20
+ /** Matches the route's own cap on the reason it stores. */ const LOST_REASON_MAX = 500;
21
+ /**
22
+ * The question a loss asks before it is recorded.
23
+ *
24
+ * A lost deal with no reason is a row a report cannot learn from, so the
25
+ * dialog asks — but it does not insist. The reason is optional, because a
26
+ * required field here is how "n/a" becomes the most common answer in the
27
+ * data, and an empty reason is at least honest.
28
+ */ export function LostReasonDialog(props) {
29
+ const { open, dealTitle, count = 1, busy, onClose, onConfirm } = props;
30
+ const [reason, setReason] = useState('');
31
+ const many = count > 1;
32
+ // A fresh field each time the dialog opens: the previous deal's reason is
33
+ // not this deal's.
34
+ useEffect(()=>{
35
+ if (open) setReason('');
36
+ }, [
37
+ open
38
+ ]);
39
+ return /*#__PURE__*/ _jsxs(Dialog, {
40
+ open: open,
41
+ onClose: busy ? undefined : onClose,
42
+ fullWidth: true,
43
+ maxWidth: "xs",
44
+ children: [
45
+ /*#__PURE__*/ _jsx(DialogTitle, {
46
+ children: many ? `Mark ${count} deals lost?` : 'Mark this deal lost?'
47
+ }),
48
+ /*#__PURE__*/ _jsxs(DialogContent, {
49
+ children: [
50
+ /*#__PURE__*/ _jsx(DialogContentText, {
51
+ sx: {
52
+ mb: 2
53
+ },
54
+ children: many ? `${count} deals move to Lost and leave the open pipeline, each ` + 'with the reason below. Any can be reopened from its page.' : `"${dealTitle}" moves to Lost and leaves the open pipeline. ` + 'It can be reopened from its page.'
55
+ }),
56
+ /*#__PURE__*/ _jsx(TextField, {
57
+ label: "Reason",
58
+ value: reason,
59
+ onChange: (event)=>setReason(event.target.value),
60
+ multiline: true,
61
+ minRows: 2,
62
+ fullWidth: true,
63
+ autoFocus: true,
64
+ helperText: many ? 'Optional. Kept on each deal and sent with each dealLost event.' : 'Optional. Kept on the deal and sent with the dealLost event.',
65
+ slotProps: {
66
+ htmlInput: {
67
+ maxLength: LOST_REASON_MAX
68
+ }
69
+ }
70
+ })
71
+ ]
72
+ }),
73
+ /*#__PURE__*/ _jsxs(DialogActions, {
74
+ children: [
75
+ /*#__PURE__*/ _jsx(Button, {
76
+ onClick: onClose,
77
+ disabled: busy,
78
+ children: 'Cancel'
79
+ }),
80
+ /*#__PURE__*/ _jsx(Button, {
81
+ variant: "contained",
82
+ color: "error",
83
+ disabled: busy,
84
+ onClick: ()=>onConfirm(reason.trim()),
85
+ children: 'Mark lost'
86
+ })
87
+ ]
88
+ })
89
+ ]
90
+ });
91
+ }
92
+ LostReasonDialog.displayName = 'LostReasonDialog';
93
+ export default LostReasonDialog;
94
+
95
+ //# sourceMappingURL=lost-reason-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/lost-reason-dialog.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 Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n TextField,\n} from '@mui/material'\nimport { useEffect, useState } from 'react'\n\n/** Matches the route's own cap on the reason it stores. */\nconst LOST_REASON_MAX = 500\n\nexport interface LostReasonDialogProps {\n open: boolean\n /** The deal being closed, for the title. */\n dealTitle: string\n /**\n * How many deals the reason applies to — the bulk bar's selection\n * (AGL-2621). One, or absent, names the deal; more says the number.\n */\n count?: number\n busy?: boolean\n onClose: () => void\n onConfirm: (reason: string) => void\n}\n\n/**\n * The question a loss asks before it is recorded.\n *\n * A lost deal with no reason is a row a report cannot learn from, so the\n * dialog asks — but it does not insist. The reason is optional, because a\n * required field here is how \"n/a\" becomes the most common answer in the\n * data, and an empty reason is at least honest.\n */\nexport function LostReasonDialog(props: LostReasonDialogProps) {\n const { open, dealTitle, count = 1, busy, onClose, onConfirm } = props\n const [reason, setReason] = useState('')\n const many = count > 1\n\n // A fresh field each time the dialog opens: the previous deal's reason is\n // not this deal's.\n useEffect(() => {\n if (open) setReason('')\n }, [open])\n\n return (\n <Dialog open={open} onClose={busy ? undefined : onClose} fullWidth maxWidth=\"xs\">\n <DialogTitle>{many ? `Mark ${count} deals lost?` : 'Mark this deal lost?'}</DialogTitle>\n <DialogContent>\n <DialogContentText sx={{ mb: 2 }}>\n {many\n ? `${count} deals move to Lost and leave the open pipeline, each ` +\n 'with the reason below. Any can be reopened from its page.'\n : `\"${dealTitle}\" moves to Lost and leaves the open pipeline. ` +\n 'It can be reopened from its page.'}\n </DialogContentText>\n <TextField\n label=\"Reason\"\n value={reason}\n onChange={(event) => setReason(event.target.value)}\n multiline\n minRows={2}\n fullWidth\n autoFocus\n helperText={\n many\n ? 'Optional. Kept on each deal and sent with each dealLost event.'\n : 'Optional. Kept on the deal and sent with the dealLost event.'\n }\n slotProps={{ htmlInput: { maxLength: LOST_REASON_MAX } }}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose} disabled={busy}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n color=\"error\"\n disabled={busy}\n onClick={() => onConfirm(reason.trim())}\n >\n {'Mark lost'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\nLostReasonDialog.displayName = 'LostReasonDialog'\n\nexport default LostReasonDialog\n"],"names":["Button","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","TextField","useEffect","useState","LOST_REASON_MAX","LostReasonDialog","props","open","dealTitle","count","busy","onClose","onConfirm","reason","setReason","many","undefined","fullWidth","maxWidth","sx","mb","label","value","onChange","event","target","multiline","minRows","autoFocus","helperText","slotProps","htmlInput","maxLength","onClick","disabled","variant","color","trim","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAEA,SACEA,MAAM,EACNC,MAAM,EACNC,aAAa,EACbC,aAAa,EACbC,iBAAiB,EACjBC,WAAW,EACXC,SAAS,QACJ,gBAAe;AACtB,SAASC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAE3C,yDAAyD,GACzD,MAAMC,kBAAkB;AAgBxB;;;;;;;CAOC,GACD,OAAO,SAASC,iBAAiBC,KAA4B;IAC3D,MAAM,EAAEC,IAAI,EAAEC,SAAS,EAAEC,QAAQ,CAAC,EAAEC,IAAI,EAAEC,OAAO,EAAEC,SAAS,EAAE,GAAGN;IACjE,MAAM,CAACO,QAAQC,UAAU,GAAGX,SAAS;IACrC,MAAMY,OAAON,QAAQ;IAErB,0EAA0E;IAC1E,mBAAmB;IACnBP,UAAU;QACR,IAAIK,MAAMO,UAAU;IACtB,GAAG;QAACP;KAAK;IAET,qBACE,MAACX;QAAOW,MAAMA;QAAMI,SAASD,OAAOM,YAAYL;QAASM,SAAS;QAACC,UAAS;;0BAC1E,KAAClB;0BAAae,OAAO,CAAC,KAAK,EAAEN,MAAM,YAAY,CAAC,GAAG;;0BACnD,MAACX;;kCACC,KAACC;wBAAkBoB,IAAI;4BAAEC,IAAI;wBAAE;kCAC5BL,OACG,GAAGN,MAAM,sDAAsD,CAAC,GAChE,8DACA,CAAC,CAAC,EAAED,UAAU,8CAA8C,CAAC,GAC7D;;kCAEN,KAACP;wBACCoB,OAAM;wBACNC,OAAOT;wBACPU,UAAU,CAACC,QAAUV,UAAUU,MAAMC,MAAM,CAACH,KAAK;wBACjDI,SAAS;wBACTC,SAAS;wBACTV,SAAS;wBACTW,SAAS;wBACTC,YACEd,OACI,mEACA;wBAENe,WAAW;4BAAEC,WAAW;gCAAEC,WAAW5B;4BAAgB;wBAAE;;;;0BAG3D,MAACP;;kCACC,KAACF;wBAAOsC,SAAStB;wBAASuB,UAAUxB;kCACjC;;kCAEH,KAACf;wBACCwC,SAAQ;wBACRC,OAAM;wBACNF,UAAUxB;wBACVuB,SAAS,IAAMrB,UAAUC,OAAOwB,IAAI;kCAEnC;;;;;;AAKX;AACAhC,iBAAiBiC,WAAW,GAAG;AAE/B,eAAejC,iBAAgB"}
@@ -0,0 +1,78 @@
1
+ import { type AglynOrgBilling, type AglynPostalAddress, type ContactLifecycleStage } from '@aglyn/aglyn';
2
+ import type { OrgMemberOption } from './use-org-members';
3
+ /** What the drawer hands back — already normalized where the route would. */
4
+ export interface NewContactValues {
5
+ email: string;
6
+ name: string;
7
+ phone: string;
8
+ jobTitle: string;
9
+ /** The picked company's name — the label the list column and the search read. */
10
+ companyName: string;
11
+ /** The picked company, or `null` for none (AGL-2613). */
12
+ companyId: string | null;
13
+ ownerUid: string;
14
+ lifecycleStage: ContactLifecycleStage | '';
15
+ tags: string[];
16
+ address: AglynPostalAddress | null;
17
+ marketingConsent: boolean;
18
+ }
19
+ export interface NewContactDrawerProps {
20
+ open: boolean;
21
+ onClose: () => void;
22
+ /**
23
+ * The site the contact is being added from — what scopes the company list
24
+ * and the controller the consent checkbox records a basis for. `null` at
25
+ * the organization level (AGL-2630), where the drawer asks which site
26
+ * with a picker and holds its submit until one is named.
27
+ */
28
+ hostId: string | null;
29
+ /** The org document the shell passed, for the company picker's scope. */
30
+ org?: Partial<AglynOrgBilling> | null;
31
+ /** The request is in flight — the form holds still and the button says so. */
32
+ busy?: boolean;
33
+ /** What the route answered when it refused, shown above the form. */
34
+ error?: string | null;
35
+ /** The team, for the owner picker. */
36
+ owners: OrgMemberOption[];
37
+ /** The roster has answered — an empty list is then "nobody to pick". */
38
+ ownersReady: boolean;
39
+ onSubmit: (values: NewContactValues) => void;
40
+ }
41
+ /**
42
+ * ADDING ONE PERSON BY HAND, IN A DRAWER (AGL-2596).
43
+ *
44
+ * A drawer and not a form above the list: a create form sitting on top of a
45
+ * table is the shape every list in this console was built to stop. The
46
+ * button in the list's header opens this, and the list is exactly as it was
47
+ * behind it.
48
+ *
49
+ * ## What is checked here and what is not
50
+ *
51
+ * The two fields a person can mistype in a way the record cannot hold — the
52
+ * email and the phone number — are checked before the request leaves, with
53
+ * the same normalizers the route runs, so the refusal lands under the field
54
+ * rather than as a sentence from the server. Everything else is the route's
55
+ * to decide: whether the address already belongs to somebody (it merges),
56
+ * whether the plan's band has room (it refuses, and its sentence is shown
57
+ * above the form unchanged).
58
+ *
59
+ * ## The consent box is a claim, and says so
60
+ *
61
+ * The forms plugin's rule for the opt-in field is that submitting a form is
62
+ * never itself consent. Typing somebody into the CRM is not either — so the
63
+ * checkbox is worded as the person's act, not the operator's, and the helper
64
+ * carries the group disclosure the form would have shown them.
65
+ *
66
+ * ## The company is a record, picked or created here
67
+ *
68
+ * The Company field is the picker (AGL-2613): a choice from the companies
69
+ * this site may see, with a "Create …" row for a name none of them carry, so
70
+ * the person filing a contact never leaves the drawer to make the account.
71
+ * What leaves the drawer is the company's id AND its name — the id is the
72
+ * link the route writes into the facet, the name is the label the list
73
+ * column and the global search keep reading. The company listen opens with
74
+ * the drawer and closes with it, because the drawer is mounted only while
75
+ * it is open.
76
+ */
77
+ export declare function NewContactDrawer(props: NewContactDrawerProps): import("react").JSX.Element;
78
+ export default NewContactDrawer;