@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,492 @@
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 { CONTACT_LIFECYCLE_STAGE_LABELS, CONTACT_LIFECYCLE_STAGES, crmTelHref, normalizePhone } from "@aglyn/aglyn";
21
+ import { mdiPhoneOutline } from "@aglyn/shared-data-mdi";
22
+ import { CardDisplay, MdiIcon } from "@aglyn/shared-ui-jsx";
23
+ import { useSnackbar } from "@aglyn/shared-ui-snackstack";
24
+ import { useUser, writeGuardedBySeed } from "@aglyn/tenant-feature-instance";
25
+ import { Button, Grid, IconButton, InputAdornment, MenuItem, Stack, TextField, Tooltip, Typography } from "@mui/material";
26
+ import { useCallback, useEffect, useState } from "react";
27
+ import { useContactUpdate } from "../hooks/use-contact-update.js";
28
+ import { useCrmActivityLogger } from "../hooks/use-crm-activity-logger.js";
29
+ import { parseContactTags } from "../model/contact-record.js";
30
+ import { setContactStage } from "../model/crm-api.js";
31
+ import { CompanyPicker, useCompanyOptions, useCreateCompany } from "./company-picker.js";
32
+ import { addressDraftFrom, ContactAddressFields } from "./contact-address-fields.js";
33
+ import { crmSuiteLockedReason } from "./crm-suite-lock.js";
34
+ /**
35
+ * THE RECORD ITSELF: every field a team keeps on a person, in one card with
36
+ * one Save (AGL-2596).
37
+ *
38
+ * ## One save, one request, one guard
39
+ *
40
+ * A field-at-a-time save would be nine requests and nine chances for the
41
+ * stale-seed guard to refuse one of them — so the card holds a draft of the
42
+ * whole profile and sends it once. The guard WRAPS the send: a row seeded
43
+ * from the cache or from a failed read is refused with the message the guard
44
+ * chooses, and what was typed stays in the fields, because a refusal that
45
+ * also emptied the form would read as a save that worked.
46
+ *
47
+ * ## The server writes the facet (AGL-2804)
48
+ *
49
+ * Every field here lives in THIS holder's facet, and the Firestore rules
50
+ * cannot tell one field of a facet from another, so the card writes nothing
51
+ * itself. The draft goes to `crm/contact-update`, which writes each field by
52
+ * dotted path into the holder's facet — never a nested object, which would
53
+ * take every other holder's records with it — clears a blank field rather
54
+ * than storing it empty, keeps the phone's and the company's search echoes
55
+ * at the top of the document, and refuses every field to a plan without
56
+ * the CRM. A refusal is shown in the route's own words.
57
+ *
58
+ * ## The stage goes to its own route
59
+ *
60
+ * The lifecycle stage is the one field an automation listens for:
61
+ * `contactStageChanged` (AGL-2605) is emitted by `crm/contact-stage` after it
62
+ * performs the write, and by nothing else. So when the stage the reader
63
+ * picked differs from the one the record holds, it is sent to that route
64
+ * once the rest of the profile has landed — the stage picked, or `null` for
65
+ * "Not placed yet", which clears it and announces nothing. A refusal from
66
+ * that route is reported on its own, with its sentence, after the fields that
67
+ * did save.
68
+ *
69
+ * ## The name is an override
70
+ *
71
+ * The canonical name is shared by every site holding the person, so this
72
+ * card never edits it. What it saves is this holder's own name for them,
73
+ * and the helper says what a blank falls back to, so nobody clears the
74
+ * field expecting the record to go nameless.
75
+ *
76
+ * ## Company is a record, with its name kept beside it
77
+ *
78
+ * The Company field is the picker (AGL-2613): the link is `companyId` in
79
+ * this holder's facet, mirrored into the top-level `companyIds` for the
80
+ * company page's query, and the company's contacts count moves with it —
81
+ * all planned by the route from the stored document, so this card never
82
+ * reasons about another holder's link. The name is sent too, from the picked
83
+ * company, because the list column and the global search read the name and
84
+ * not the id; a record that carries a name with no link — an import, a save
85
+ * from before the picker — keeps it as the label, and the picker offers it
86
+ * as the company to link or create.
87
+ */ export function ContactPropertiesCard(props) {
88
+ const { hostId, org, record, consentGroup, seed, members, suiteLocked = false } = props;
89
+ const { data: user } = useUser();
90
+ const { enqueueSnackbar } = useSnackbar();
91
+ const contactUpdate = useContactUpdate(hostId);
92
+ // The site a stage move is routed through: the mounted one, or at the
93
+ // organization level the holder's own (AGL-2630).
94
+ const siteHostId = hostId != null ? hostId : consentGroup.hostId || null;
95
+ /*
96
+ * The feed the act is logged in, decided by the level it was performed
97
+ * at (AGL-2738) and so given the MOUNTED site rather than `siteHostId`:
98
+ * at the org hub a client-direct append to the holder's own site would
99
+ * face a gate the record write never had to pass.
100
+ */ const logActivity = useCrmActivityLogger(hostId);
101
+ const companies = useCompanyOptions({
102
+ hostId,
103
+ org
104
+ });
105
+ const createCompany = useCreateCompany({
106
+ hostId,
107
+ org
108
+ });
109
+ const [nameOverride, setNameOverride] = useState(record.nameOverride);
110
+ const [phone, setPhone] = useState(record.phone);
111
+ const [jobTitle, setJobTitle] = useState(record.jobTitle);
112
+ const [companyName, setCompanyName] = useState(record.companyName);
113
+ const [companyId, setCompanyId] = useState(record.companyId || null);
114
+ const [ownerUid, setOwnerUid] = useState(record.ownerUid);
115
+ const [lifecycleStage, setLifecycleStage] = useState(record.lifecycleStage);
116
+ const [tags, setTags] = useState(record.tags.join(', '));
117
+ const [notes, setNotes] = useState(record.notes);
118
+ const [address, setAddress] = useState(addressDraftFrom(record.address));
119
+ const [phoneError, setPhoneError] = useState('');
120
+ const [saving, setSaving] = useState(false);
121
+ /*
122
+ * Re-seeded when the RECORD changes, not when it re-renders. The listener
123
+ * delivers a fresh row on every snapshot, including the one this card's
124
+ * own save produces; re-seeding on each would overwrite what somebody is
125
+ * in the middle of typing with what the server last confirmed.
126
+ */ const recordId = record.$id;
127
+ useEffect(()=>{
128
+ setNameOverride(record.nameOverride);
129
+ setPhone(record.phone);
130
+ setJobTitle(record.jobTitle);
131
+ setCompanyName(record.companyName);
132
+ setCompanyId(record.companyId || null);
133
+ setOwnerUid(record.ownerUid);
134
+ setLifecycleStage(record.lifecycleStage);
135
+ setTags(record.tags.join(', '));
136
+ setNotes(record.notes);
137
+ setAddress(addressDraftFrom(record.address));
138
+ setPhoneError('');
139
+ // eslint-disable-next-line react-hooks/exhaustive-deps
140
+ }, [
141
+ recordId
142
+ ]);
143
+ const handleSave = useCallback(async ()=>{
144
+ const trimmedPhone = phone.trim();
145
+ const normalizedPhone = trimmedPhone ? normalizePhone(trimmedPhone) : '';
146
+ if (trimmedPhone && !normalizedPhone) {
147
+ setPhoneError('Enter it with its country code, like +1 512 555 0107.');
148
+ return;
149
+ }
150
+ setPhoneError('');
151
+ // A stage that differs from the record's is the stage route's to write —
152
+ // see the note above.
153
+ const stageChanged = !suiteLocked && lifecycleStage !== record.lifecycleStage;
154
+ const set = _extends({
155
+ name: nameOverride.trim().slice(0, 120),
156
+ phone: normalizedPhone != null ? normalizedPhone : '',
157
+ jobTitle: jobTitle.trim().slice(0, 120),
158
+ address,
159
+ tags: parseContactTags(tags),
160
+ notes: notes.slice(0, 2000)
161
+ }, suiteLocked ? {} : {
162
+ ownerUid,
163
+ companyId,
164
+ companyName: companyName.trim().slice(0, 120)
165
+ });
166
+ setSaving(true);
167
+ try {
168
+ const verdict = await writeGuardedBySeed({
169
+ subject: 'contact',
170
+ unreadable: seed.status === 'error',
171
+ fromCache: seed.fromCache
172
+ }, ()=>contactUpdate.updateOne(record.$id, set));
173
+ if (!verdict.ok) {
174
+ return void enqueueSnackbar(verdict.message, {
175
+ variant: 'warning',
176
+ persist: false
177
+ });
178
+ }
179
+ logActivity('Updated contact', {
180
+ type: 'contact',
181
+ id: record.$id,
182
+ name: record.name || record.email
183
+ });
184
+ if (stageChanged && siteHostId) {
185
+ try {
186
+ await setContactStage(user, siteHostId, record.$id, lifecycleStage || null);
187
+ } catch (error) {
188
+ // The rest of the profile is saved; only the stage was refused, and
189
+ // the route's own sentence says why.
190
+ return void enqueueSnackbar(`Saved, but the stage could not be changed: ${error instanceof Error ? error.message : 'the request failed'}`, {
191
+ variant: 'warning',
192
+ persist: false
193
+ });
194
+ }
195
+ }
196
+ enqueueSnackbar('Contact saved', {
197
+ variant: 'success',
198
+ persist: false
199
+ });
200
+ } catch (error) {
201
+ console.error(error);
202
+ enqueueSnackbar(error instanceof Error && error.message ? error.message : 'An error has occurred', {
203
+ variant: 'error',
204
+ allowDuplicate: true
205
+ });
206
+ } finally{
207
+ setSaving(false);
208
+ }
209
+ }, [
210
+ address,
211
+ companyId,
212
+ companyName,
213
+ contactUpdate,
214
+ enqueueSnackbar,
215
+ siteHostId,
216
+ jobTitle,
217
+ lifecycleStage,
218
+ logActivity,
219
+ nameOverride,
220
+ notes,
221
+ ownerUid,
222
+ phone,
223
+ record.$id,
224
+ record.email,
225
+ record.lifecycleStage,
226
+ record.name,
227
+ seed.fromCache,
228
+ seed.status,
229
+ suiteLocked,
230
+ tags,
231
+ user
232
+ ]);
233
+ /*
234
+ * An owner the roster no longer lists — somebody who left the team — is
235
+ * still offered as the current value, named by their uid, so the select is
236
+ * never handed a value it has no option for and the reader can see who it
237
+ * was before reassigning.
238
+ */ const ownerKnown = members.options.some((option)=>option.uid === ownerUid);
239
+ /** The number in the box as something a dialer takes, or nothing (AGL-2661). */ const telHref = crmTelHref(phone);
240
+ return /*#__PURE__*/ _jsx(CardDisplay, {
241
+ header: 'Properties',
242
+ help: Aglyn.pluginDocsHelp('contactRecord', {
243
+ anchor: '#the-record-page'
244
+ }),
245
+ contentGutterX: true,
246
+ contentGutterY: true,
247
+ HeaderProps: {
248
+ action: /*#__PURE__*/ _jsx(Button, {
249
+ variant: "contained",
250
+ color: "primary",
251
+ size: "small",
252
+ disabled: saving,
253
+ onClick: ()=>void handleSave(),
254
+ children: saving ? 'Saving…' : 'Save'
255
+ })
256
+ },
257
+ children: /*#__PURE__*/ _jsxs(Grid, {
258
+ container: true,
259
+ spacing: 2,
260
+ children: [
261
+ /*#__PURE__*/ _jsx(Grid, {
262
+ size: {
263
+ xs: 12,
264
+ sm: 6
265
+ },
266
+ children: /*#__PURE__*/ _jsx(TextField, {
267
+ size: "small",
268
+ label: "Email",
269
+ value: record.email,
270
+ slotProps: {
271
+ input: {
272
+ readOnly: true
273
+ }
274
+ },
275
+ helperText: "The identity every site shares — it cannot be edited here.",
276
+ fullWidth: true
277
+ })
278
+ }),
279
+ /*#__PURE__*/ _jsx(Grid, {
280
+ size: {
281
+ xs: 12,
282
+ sm: 6
283
+ },
284
+ children: /*#__PURE__*/ _jsx(TextField, {
285
+ size: "small",
286
+ label: "Name",
287
+ value: nameOverride,
288
+ onChange: (event)=>setNameOverride(event.target.value),
289
+ slotProps: {
290
+ htmlInput: {
291
+ maxLength: 120
292
+ }
293
+ },
294
+ helperText: record.canonicalName ? `Your own name for this person. Blank shows the name they gave: ${record.canonicalName}.` : 'Your own name for this person.',
295
+ fullWidth: true
296
+ })
297
+ }),
298
+ /*#__PURE__*/ _jsx(Grid, {
299
+ size: {
300
+ xs: 12,
301
+ sm: 6
302
+ },
303
+ children: /*#__PURE__*/ _jsx(TextField, {
304
+ size: "small",
305
+ label: "Phone",
306
+ value: phone,
307
+ onChange: (event)=>setPhone(event.target.value),
308
+ error: Boolean(phoneError),
309
+ helperText: phoneError || 'With the country code, like +1 512 555 0107',
310
+ fullWidth: true,
311
+ slotProps: {
312
+ input: {
313
+ /*
314
+ * Click-to-call (AGL-2661), off what is IN the box rather
315
+ * than off the saved value: the number on screen is the one
316
+ * a reader means to ring, and `crmTelHref` withholds the
317
+ * link from anything half-typed.
318
+ */ endAdornment: telHref ? /*#__PURE__*/ _jsx(InputAdornment, {
319
+ position: "end",
320
+ children: /*#__PURE__*/ _jsx(Tooltip, {
321
+ title: `Call ${phone.trim()}`,
322
+ children: /*#__PURE__*/ _jsx(IconButton, {
323
+ component: "a",
324
+ href: telHref,
325
+ size: "small",
326
+ edge: "end",
327
+ "aria-label": `Call ${phone.trim()}`,
328
+ children: /*#__PURE__*/ _jsx(MdiIcon, {
329
+ path: mdiPhoneOutline.path,
330
+ size: 0.8
331
+ })
332
+ })
333
+ })
334
+ }) : null
335
+ }
336
+ }
337
+ })
338
+ }),
339
+ /*#__PURE__*/ _jsx(Grid, {
340
+ size: {
341
+ xs: 12,
342
+ sm: 6
343
+ },
344
+ children: /*#__PURE__*/ _jsx(TextField, {
345
+ size: "small",
346
+ label: "Job title",
347
+ value: jobTitle,
348
+ onChange: (event)=>setJobTitle(event.target.value),
349
+ slotProps: {
350
+ htmlInput: {
351
+ maxLength: 120
352
+ }
353
+ },
354
+ fullWidth: true
355
+ })
356
+ }),
357
+ /*#__PURE__*/ _jsx(Grid, {
358
+ size: {
359
+ xs: 12,
360
+ sm: 6
361
+ },
362
+ children: /*#__PURE__*/ _jsx(CompanyPicker, {
363
+ options: companies.options,
364
+ ready: companies.ready,
365
+ truncated: companies.truncated,
366
+ value: companyId,
367
+ onChange: (id, company)=>{
368
+ setCompanyId(id);
369
+ // The label follows the link: the picked name, or nothing
370
+ // once the link is cleared. A company the list cannot name
371
+ // keeps whatever label the record already had.
372
+ setCompanyName(company ? company.name : id ? companyName : '');
373
+ },
374
+ onCreate: createCompany,
375
+ email: record.email,
376
+ fallbackName: companyName,
377
+ disabled: saving || suiteLocked,
378
+ helperText: suiteLocked ? crmSuiteLockedReason() : undefined
379
+ })
380
+ }),
381
+ /*#__PURE__*/ _jsx(Grid, {
382
+ size: {
383
+ xs: 12,
384
+ sm: 6
385
+ },
386
+ children: /*#__PURE__*/ _jsxs(TextField, {
387
+ select: true,
388
+ size: "small",
389
+ label: "Lifecycle stage",
390
+ value: lifecycleStage,
391
+ onChange: (event)=>setLifecycleStage(event.target.value),
392
+ disabled: suiteLocked,
393
+ helperText: suiteLocked ? crmSuiteLockedReason() : undefined,
394
+ fullWidth: true,
395
+ children: [
396
+ /*#__PURE__*/ _jsx(MenuItem, {
397
+ value: "",
398
+ children: 'Not placed yet'
399
+ }),
400
+ CONTACT_LIFECYCLE_STAGES.map((stage)=>/*#__PURE__*/ _jsx(MenuItem, {
401
+ value: stage,
402
+ children: CONTACT_LIFECYCLE_STAGE_LABELS[stage]
403
+ }, stage))
404
+ ]
405
+ })
406
+ }),
407
+ /*#__PURE__*/ _jsx(Grid, {
408
+ size: {
409
+ xs: 12,
410
+ sm: 6
411
+ },
412
+ children: /*#__PURE__*/ _jsxs(TextField, {
413
+ select: true,
414
+ size: "small",
415
+ label: "Owner",
416
+ value: ownerUid,
417
+ onChange: (event)=>setOwnerUid(event.target.value),
418
+ disabled: suiteLocked,
419
+ helperText: suiteLocked ? crmSuiteLockedReason() : members.ready && !members.options.length ? 'The team roster could not be read, so nobody can be picked yet.' : 'The team member responsible for this relationship',
420
+ fullWidth: true,
421
+ children: [
422
+ /*#__PURE__*/ _jsx(MenuItem, {
423
+ value: "",
424
+ children: 'Unassigned'
425
+ }),
426
+ ownerUid && !ownerKnown ? /*#__PURE__*/ _jsx(MenuItem, {
427
+ value: ownerUid,
428
+ children: members.memberName(ownerUid)
429
+ }) : null,
430
+ members.options.map((owner)=>/*#__PURE__*/ _jsx(MenuItem, {
431
+ value: owner.uid,
432
+ children: owner.label
433
+ }, owner.uid))
434
+ ]
435
+ })
436
+ }),
437
+ /*#__PURE__*/ _jsx(Grid, {
438
+ size: {
439
+ xs: 12,
440
+ sm: 6
441
+ },
442
+ children: /*#__PURE__*/ _jsx(TextField, {
443
+ size: "small",
444
+ label: "Tags",
445
+ placeholder: "vip, beta",
446
+ helperText: "Comma-separated",
447
+ value: tags,
448
+ onChange: (event)=>setTags(event.target.value),
449
+ fullWidth: true
450
+ })
451
+ }),
452
+ /*#__PURE__*/ _jsx(Grid, {
453
+ size: {
454
+ xs: 12
455
+ },
456
+ children: /*#__PURE__*/ _jsxs(Stack, {
457
+ spacing: 1,
458
+ children: [
459
+ /*#__PURE__*/ _jsx(Typography, {
460
+ variant: "subtitle2",
461
+ children: 'Address'
462
+ }),
463
+ /*#__PURE__*/ _jsx(ContactAddressFields, {
464
+ value: address,
465
+ onChange: setAddress
466
+ })
467
+ ]
468
+ })
469
+ }),
470
+ /*#__PURE__*/ _jsx(Grid, {
471
+ size: {
472
+ xs: 12
473
+ },
474
+ children: /*#__PURE__*/ _jsx(TextField, {
475
+ size: "small",
476
+ label: "About",
477
+ value: notes,
478
+ onChange: (event)=>setNotes(event.target.value),
479
+ helperText: "Notes for your team. Nobody outside this site's group can read them.",
480
+ multiline: true,
481
+ minRows: 3,
482
+ fullWidth: true
483
+ })
484
+ })
485
+ ]
486
+ })
487
+ });
488
+ }
489
+ ContactPropertiesCard.displayName = 'ContactPropertiesCard';
490
+ export default ContactPropertiesCard;
491
+
492
+ //# sourceMappingURL=contact-properties-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/contact-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 * as Aglyn from '@aglyn/aglyn'\nimport {\n type AglynOrgBilling,\n CONTACT_LIFECYCLE_STAGE_LABELS,\n CONTACT_LIFECYCLE_STAGES,\n type ConsentGroup,\n type ContactLifecycleStage,\n crmTelHref,\n normalizePhone,\n} from '@aglyn/aglyn'\nimport { mdiPhoneOutline } from '@aglyn/shared-data-mdi'\nimport { CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useUser, writeGuardedBySeed } from '@aglyn/tenant-feature-instance'\nimport {\n Button,\n Grid,\n IconButton,\n InputAdornment,\n MenuItem,\n Stack,\n TextField,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport { useCallback, useEffect, useState } from 'react'\nimport { useContactUpdate } from '../hooks/use-contact-update'\nimport { useCrmActivityLogger } from '../hooks/use-crm-activity-logger'\nimport { type ContactRecord, parseContactTags } from '../model/contact-record'\nimport type { ContactUpdateFields } from '../model/contact-update'\nimport { setContactStage } from '../model/crm-api'\nimport {\n CompanyPicker,\n useCompanyOptions,\n useCreateCompany,\n} from './company-picker'\nimport {\n addressDraftFrom,\n ContactAddressFields,\n type AddressDraft,\n} from './contact-address-fields'\nimport { crmSuiteLockedReason } from './crm-suite-lock'\nimport type { OrgMembers } from './use-org-members'\n\nexport interface ContactPropertiesCardProps {\n /** The site the record is read under, or `null` at the organization level. */\n hostId: string | null\n /** The org document the shell passed, for the company picker's scope. */\n org?: Partial<AglynOrgBilling> | null\n /** The row, flattened through the viewing group's facet. */\n record: ContactRecord\n /** The controller whose facet the edits are saved into. */\n consentGroup: ConsentGroup\n /**\n * The listener's verdict on the row the drafts were seeded from, for the\n * guard that refuses a save over an unconfirmed read.\n */\n seed: { status: 'loading' | 'success' | 'error'; fromCache: boolean }\n /** The team, for the owner picker and the owner's name. */\n members: OrgMembers\n /**\n * The org's plan lacks the CRM (AGL-2788), which the shell mounts no CRM\n * page for (AGL-2851). The owner, the lifecycle stage and the company\n * show, locked, and are left out of a save; `crm/contact-update` refuses\n * such a plan the rest of the profile, the tags and the notes too.\n */\n suiteLocked?: boolean\n}\n\n/**\n * THE RECORD ITSELF: every field a team keeps on a person, in one card with\n * one Save (AGL-2596).\n *\n * ## One save, one request, one guard\n *\n * A field-at-a-time save would be nine requests and nine chances for the\n * stale-seed guard to refuse one of them — so the card holds a draft of the\n * whole profile and sends it once. The guard WRAPS the send: a row seeded\n * from the cache or from a failed read is refused with the message the guard\n * chooses, and what was typed stays in the fields, because a refusal that\n * also emptied the form would read as a save that worked.\n *\n * ## The server writes the facet (AGL-2804)\n *\n * Every field here lives in THIS holder's facet, and the Firestore rules\n * cannot tell one field of a facet from another, so the card writes nothing\n * itself. The draft goes to `crm/contact-update`, which writes each field by\n * dotted path into the holder's facet — never a nested object, which would\n * take every other holder's records with it — clears a blank field rather\n * than storing it empty, keeps the phone's and the company's search echoes\n * at the top of the document, and refuses every field to a plan without\n * the CRM. A refusal is shown in the route's own words.\n *\n * ## The stage goes to its own route\n *\n * The lifecycle stage is the one field an automation listens for:\n * `contactStageChanged` (AGL-2605) is emitted by `crm/contact-stage` after it\n * performs the write, and by nothing else. So when the stage the reader\n * picked differs from the one the record holds, it is sent to that route\n * once the rest of the profile has landed — the stage picked, or `null` for\n * \"Not placed yet\", which clears it and announces nothing. A refusal from\n * that route is reported on its own, with its sentence, after the fields that\n * did save.\n *\n * ## The name is an override\n *\n * The canonical name is shared by every site holding the person, so this\n * card never edits it. What it saves is this holder's own name for them,\n * and the helper says what a blank falls back to, so nobody clears the\n * field expecting the record to go nameless.\n *\n * ## Company is a record, with its name kept beside it\n *\n * The Company field is the picker (AGL-2613): the link is `companyId` in\n * this holder's facet, mirrored into the top-level `companyIds` for the\n * company page's query, and the company's contacts count moves with it —\n * all planned by the route from the stored document, so this card never\n * reasons about another holder's link. The name is sent too, from the picked\n * company, because the list column and the global search read the name and\n * not the id; a record that carries a name with no link — an import, a save\n * from before the picker — keeps it as the label, and the picker offers it\n * as the company to link or create.\n */\nexport function ContactPropertiesCard(props: ContactPropertiesCardProps) {\n const {\n hostId,\n org,\n record,\n consentGroup,\n seed,\n members,\n suiteLocked = false,\n } = props\n const { data: user } = useUser()\n const { enqueueSnackbar } = useSnackbar()\n const contactUpdate = useContactUpdate(hostId)\n // The site a stage move is routed through: the mounted one, or at the\n // organization level the holder's own (AGL-2630).\n const siteHostId = hostId ?? (consentGroup.hostId || null)\n /*\n * The feed the act is logged in, decided by the level it was performed\n * at (AGL-2738) and so given the MOUNTED site rather than `siteHostId`:\n * at the org hub a client-direct append to the holder's own site would\n * face a gate the record write never had to pass.\n */\n const logActivity = useCrmActivityLogger(hostId)\n const companies = useCompanyOptions({ hostId, org })\n const createCompany = useCreateCompany({ hostId, org })\n\n const [nameOverride, setNameOverride] = useState(record.nameOverride)\n const [phone, setPhone] = useState(record.phone)\n const [jobTitle, setJobTitle] = useState(record.jobTitle)\n const [companyName, setCompanyName] = useState(record.companyName)\n const [companyId, setCompanyId] = useState<string | null>(\n record.companyId || null,\n )\n const [ownerUid, setOwnerUid] = useState(record.ownerUid)\n const [lifecycleStage, setLifecycleStage] = useState<ContactLifecycleStage | ''>(\n record.lifecycleStage,\n )\n const [tags, setTags] = useState(record.tags.join(', '))\n const [notes, setNotes] = useState(record.notes)\n const [address, setAddress] = useState<AddressDraft>(\n addressDraftFrom(record.address),\n )\n const [phoneError, setPhoneError] = useState('')\n const [saving, setSaving] = useState(false)\n\n /*\n * Re-seeded when the RECORD changes, not when it re-renders. The listener\n * delivers a fresh row on every snapshot, including the one this card's\n * own save produces; re-seeding on each would overwrite what somebody is\n * in the middle of typing with what the server last confirmed.\n */\n const recordId = record.$id\n useEffect(() => {\n setNameOverride(record.nameOverride)\n setPhone(record.phone)\n setJobTitle(record.jobTitle)\n setCompanyName(record.companyName)\n setCompanyId(record.companyId || null)\n setOwnerUid(record.ownerUid)\n setLifecycleStage(record.lifecycleStage)\n setTags(record.tags.join(', '))\n setNotes(record.notes)\n setAddress(addressDraftFrom(record.address))\n setPhoneError('')\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [recordId])\n\n const handleSave = useCallback(async () => {\n const trimmedPhone = phone.trim()\n const normalizedPhone = trimmedPhone ? normalizePhone(trimmedPhone) : ''\n if (trimmedPhone && !normalizedPhone) {\n setPhoneError('Enter it with its country code, like +1 512 555 0107.')\n return\n }\n setPhoneError('')\n // A stage that differs from the record's is the stage route's to write —\n // see the note above.\n const stageChanged = !suiteLocked && lifecycleStage !== record.lifecycleStage\n const set: ContactUpdateFields = {\n name: nameOverride.trim().slice(0, 120),\n phone: normalizedPhone ?? '',\n jobTitle: jobTitle.trim().slice(0, 120),\n address,\n tags: parseContactTags(tags),\n notes: notes.slice(0, 2000),\n // The owner and the company, sent only on a plan that carries the CRM.\n ...(suiteLocked\n ? {}\n : { ownerUid, companyId, companyName: companyName.trim().slice(0, 120) }),\n }\n setSaving(true)\n try {\n const verdict = await writeGuardedBySeed(\n {\n subject: 'contact',\n unreadable: seed.status === 'error',\n fromCache: seed.fromCache,\n },\n () => contactUpdate.updateOne(record.$id, set),\n )\n if (!verdict.ok) {\n return void enqueueSnackbar(verdict.message, {\n variant: 'warning',\n persist: false,\n })\n }\n logActivity('Updated contact', {\n type: 'contact',\n id: record.$id,\n name: record.name || record.email,\n })\n if (stageChanged && siteHostId) {\n try {\n await setContactStage(user, siteHostId, record.$id, lifecycleStage || null)\n } catch (error) {\n // The rest of the profile is saved; only the stage was refused, and\n // the route's own sentence says why.\n return void enqueueSnackbar(\n `Saved, but the stage could not be changed: ${\n error instanceof Error ? error.message : 'the request failed'\n }`,\n { variant: 'warning', persist: false },\n )\n }\n }\n enqueueSnackbar('Contact saved', { variant: 'success', persist: false })\n } catch (error) {\n console.error(error)\n enqueueSnackbar(\n error instanceof Error && error.message ? error.message : 'An error has occurred',\n { variant: 'error', allowDuplicate: true },\n )\n } finally {\n setSaving(false)\n }\n }, [\n address,\n companyId,\n companyName,\n contactUpdate,\n enqueueSnackbar,\n siteHostId,\n jobTitle,\n lifecycleStage,\n logActivity,\n nameOverride,\n notes,\n ownerUid,\n phone,\n record.$id,\n record.email,\n record.lifecycleStage,\n record.name,\n seed.fromCache,\n seed.status,\n suiteLocked,\n tags,\n user,\n ])\n\n /*\n * An owner the roster no longer lists — somebody who left the team — is\n * still offered as the current value, named by their uid, so the select is\n * never handed a value it has no option for and the reader can see who it\n * was before reassigning.\n */\n const ownerKnown = members.options.some((option) => option.uid === ownerUid)\n\n /** The number in the box as something a dialer takes, or nothing (AGL-2661). */\n const telHref = crmTelHref(phone)\n\n return (\n <CardDisplay\n header={'Properties'}\n help={Aglyn.pluginDocsHelp('contactRecord', { anchor: '#the-record-page' })}\n contentGutterX\n contentGutterY\n HeaderProps={{\n action: (\n <Button\n variant=\"contained\"\n color=\"primary\"\n size=\"small\"\n disabled={saving}\n onClick={() => void handleSave()}\n >\n {saving ? 'Saving…' : 'Save'}\n </Button>\n ),\n }}\n >\n <Grid container spacing={2}>\n <Grid size={{ xs: 12, sm: 6 }}>\n <TextField\n size=\"small\"\n label=\"Email\"\n value={record.email}\n slotProps={{ input: { readOnly: true } }}\n helperText=\"The identity every site shares — it cannot be edited here.\"\n fullWidth\n />\n </Grid>\n <Grid size={{ xs: 12, sm: 6 }}>\n <TextField\n size=\"small\"\n label=\"Name\"\n value={nameOverride}\n onChange={(event) => setNameOverride(event.target.value)}\n slotProps={{ htmlInput: { maxLength: 120 } }}\n helperText={\n record.canonicalName\n ? `Your own name for this person. Blank shows the name they gave: ${record.canonicalName}.`\n : 'Your own name for this person.'\n }\n fullWidth\n />\n </Grid>\n <Grid size={{ xs: 12, sm: 6 }}>\n <TextField\n size=\"small\"\n label=\"Phone\"\n value={phone}\n onChange={(event) => setPhone(event.target.value)}\n error={Boolean(phoneError)}\n helperText={phoneError || 'With the country code, like +1 512 555 0107'}\n fullWidth\n slotProps={{\n input: {\n /*\n * Click-to-call (AGL-2661), off what is IN the box rather\n * than off the saved value: the number on screen is the one\n * a reader means to ring, and `crmTelHref` withholds the\n * link from anything half-typed.\n */\n endAdornment: telHref ? (\n <InputAdornment position=\"end\">\n <Tooltip title={`Call ${phone.trim()}`}>\n <IconButton\n component=\"a\"\n href={telHref}\n size=\"small\"\n edge=\"end\"\n aria-label={`Call ${phone.trim()}`}\n >\n <MdiIcon path={mdiPhoneOutline.path} size={0.8} />\n </IconButton>\n </Tooltip>\n </InputAdornment>\n ) : null,\n },\n }}\n />\n </Grid>\n <Grid size={{ xs: 12, sm: 6 }}>\n <TextField\n size=\"small\"\n label=\"Job title\"\n value={jobTitle}\n onChange={(event) => setJobTitle(event.target.value)}\n slotProps={{ htmlInput: { maxLength: 120 } }}\n fullWidth\n />\n </Grid>\n <Grid size={{ xs: 12, sm: 6 }}>\n <CompanyPicker\n options={companies.options}\n ready={companies.ready}\n truncated={companies.truncated}\n value={companyId}\n onChange={(id, company) => {\n setCompanyId(id)\n // The label follows the link: the picked name, or nothing\n // once the link is cleared. A company the list cannot name\n // keeps whatever label the record already had.\n setCompanyName(company ? company.name : id ? companyName : '')\n }}\n onCreate={createCompany}\n email={record.email}\n fallbackName={companyName}\n disabled={saving || suiteLocked}\n helperText={suiteLocked ? crmSuiteLockedReason() : undefined}\n />\n </Grid>\n <Grid size={{ xs: 12, sm: 6 }}>\n <TextField\n select\n size=\"small\"\n label=\"Lifecycle stage\"\n value={lifecycleStage}\n onChange={(event) =>\n setLifecycleStage(event.target.value as ContactLifecycleStage | '')\n }\n disabled={suiteLocked}\n helperText={suiteLocked ? crmSuiteLockedReason() : undefined}\n fullWidth\n >\n <MenuItem value=\"\">{'Not placed yet'}</MenuItem>\n {CONTACT_LIFECYCLE_STAGES.map((stage) => (\n <MenuItem key={stage} value={stage}>\n {CONTACT_LIFECYCLE_STAGE_LABELS[stage]}\n </MenuItem>\n ))}\n </TextField>\n </Grid>\n <Grid size={{ xs: 12, sm: 6 }}>\n <TextField\n select\n size=\"small\"\n label=\"Owner\"\n value={ownerUid}\n onChange={(event) => setOwnerUid(event.target.value)}\n disabled={suiteLocked}\n helperText={\n suiteLocked\n ? crmSuiteLockedReason()\n : members.ready && !members.options.length\n ? 'The team roster could not be read, so nobody can be picked yet.'\n : 'The team member responsible for this relationship'\n }\n fullWidth\n >\n <MenuItem value=\"\">{'Unassigned'}</MenuItem>\n {ownerUid && !ownerKnown ? (\n <MenuItem value={ownerUid}>{members.memberName(ownerUid)}</MenuItem>\n ) : null}\n {members.options.map((owner) => (\n <MenuItem key={owner.uid} value={owner.uid}>\n {owner.label}\n </MenuItem>\n ))}\n </TextField>\n </Grid>\n <Grid size={{ xs: 12, sm: 6 }}>\n <TextField\n size=\"small\"\n label=\"Tags\"\n placeholder=\"vip, beta\"\n helperText=\"Comma-separated\"\n value={tags}\n onChange={(event) => setTags(event.target.value)}\n fullWidth\n />\n </Grid>\n <Grid size={{ xs: 12 }}>\n <Stack spacing={1}>\n <Typography variant=\"subtitle2\">{'Address'}</Typography>\n <ContactAddressFields value={address} onChange={setAddress} />\n </Stack>\n </Grid>\n <Grid size={{ xs: 12 }}>\n <TextField\n size=\"small\"\n label=\"About\"\n value={notes}\n onChange={(event) => setNotes(event.target.value)}\n helperText=\"Notes for your team. Nobody outside this site's group can read them.\"\n multiline\n minRows={3}\n fullWidth\n />\n </Grid>\n </Grid>\n </CardDisplay>\n )\n}\nContactPropertiesCard.displayName = 'ContactPropertiesCard'\n\nexport default ContactPropertiesCard\n"],"names":["Aglyn","CONTACT_LIFECYCLE_STAGE_LABELS","CONTACT_LIFECYCLE_STAGES","crmTelHref","normalizePhone","mdiPhoneOutline","CardDisplay","MdiIcon","useSnackbar","useUser","writeGuardedBySeed","Button","Grid","IconButton","InputAdornment","MenuItem","Stack","TextField","Tooltip","Typography","useCallback","useEffect","useState","useContactUpdate","useCrmActivityLogger","parseContactTags","setContactStage","CompanyPicker","useCompanyOptions","useCreateCompany","addressDraftFrom","ContactAddressFields","crmSuiteLockedReason","ContactPropertiesCard","props","hostId","org","record","consentGroup","seed","members","suiteLocked","data","user","enqueueSnackbar","contactUpdate","siteHostId","logActivity","companies","createCompany","nameOverride","setNameOverride","phone","setPhone","jobTitle","setJobTitle","companyName","setCompanyName","companyId","setCompanyId","ownerUid","setOwnerUid","lifecycleStage","setLifecycleStage","tags","setTags","join","notes","setNotes","address","setAddress","phoneError","setPhoneError","saving","setSaving","recordId","$id","handleSave","trimmedPhone","trim","normalizedPhone","stageChanged","set","name","slice","verdict","subject","unreadable","status","fromCache","updateOne","ok","message","variant","persist","type","id","email","error","Error","console","allowDuplicate","ownerKnown","options","some","option","uid","telHref","header","help","pluginDocsHelp","anchor","contentGutterX","contentGutterY","HeaderProps","action","color","size","disabled","onClick","container","spacing","xs","sm","label","value","slotProps","input","readOnly","helperText","fullWidth","onChange","event","target","htmlInput","maxLength","canonicalName","Boolean","endAdornment","position","title","component","href","edge","aria-label","path","ready","truncated","company","onCreate","fallbackName","undefined","select","map","stage","length","memberName","owner","placeholder","multiline","minRows","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAEA,YAAYA,WAAW,eAAc;AACrC,SAEEC,8BAA8B,EAC9BC,wBAAwB,EAGxBC,UAAU,EACVC,cAAc,QACT,eAAc;AACrB,SAASC,eAAe,QAAQ,yBAAwB;AACxD,SAASC,WAAW,EAAEC,OAAO,QAAQ,uBAAsB;AAC3D,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SAASC,OAAO,EAAEC,kBAAkB,QAAQ,iCAAgC;AAC5E,SACEC,MAAM,EACNC,IAAI,EACJC,UAAU,EACVC,cAAc,EACdC,QAAQ,EACRC,KAAK,EACLC,SAAS,EACTC,OAAO,EACPC,UAAU,QACL,gBAAe;AACtB,SAASC,WAAW,EAAEC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AACxD,SAASC,gBAAgB,QAAQ,iCAA6B;AAC9D,SAASC,oBAAoB,QAAQ,sCAAkC;AACvE,SAA6BC,gBAAgB,QAAQ,6BAAyB;AAE9E,SAASC,eAAe,QAAQ,sBAAkB;AAClD,SACEC,aAAa,EACbC,iBAAiB,EACjBC,gBAAgB,QACX,sBAAkB;AACzB,SACEC,gBAAgB,EAChBC,oBAAoB,QAEf,8BAA0B;AACjC,SAASC,oBAAoB,QAAQ,sBAAkB;AA4BvD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqDC,GACD,OAAO,SAASC,sBAAsBC,KAAiC;IACrE,MAAM,EACJC,MAAM,EACNC,GAAG,EACHC,MAAM,EACNC,YAAY,EACZC,IAAI,EACJC,OAAO,EACPC,cAAc,KAAK,EACpB,GAAGP;IACJ,MAAM,EAAEQ,MAAMC,IAAI,EAAE,GAAGlC;IACvB,MAAM,EAAEmC,eAAe,EAAE,GAAGpC;IAC5B,MAAMqC,gBAAgBtB,iBAAiBY;IACvC,sEAAsE;IACtE,kDAAkD;IAClD,MAAMW,aAAaX,iBAAAA,SAAWG,aAAaH,MAAM,IAAI;IACrD;;;;;GAKC,GACD,MAAMY,cAAcvB,qBAAqBW;IACzC,MAAMa,YAAYpB,kBAAkB;QAAEO;QAAQC;IAAI;IAClD,MAAMa,gBAAgBpB,iBAAiB;QAAEM;QAAQC;IAAI;IAErD,MAAM,CAACc,cAAcC,gBAAgB,GAAG7B,SAASe,OAAOa,YAAY;IACpE,MAAM,CAACE,OAAOC,SAAS,GAAG/B,SAASe,OAAOe,KAAK;IAC/C,MAAM,CAACE,UAAUC,YAAY,GAAGjC,SAASe,OAAOiB,QAAQ;IACxD,MAAM,CAACE,aAAaC,eAAe,GAAGnC,SAASe,OAAOmB,WAAW;IACjE,MAAM,CAACE,WAAWC,aAAa,GAAGrC,SAChCe,OAAOqB,SAAS,IAAI;IAEtB,MAAM,CAACE,UAAUC,YAAY,GAAGvC,SAASe,OAAOuB,QAAQ;IACxD,MAAM,CAACE,gBAAgBC,kBAAkB,GAAGzC,SAC1Ce,OAAOyB,cAAc;IAEvB,MAAM,CAACE,MAAMC,QAAQ,GAAG3C,SAASe,OAAO2B,IAAI,CAACE,IAAI,CAAC;IAClD,MAAM,CAACC,OAAOC,SAAS,GAAG9C,SAASe,OAAO8B,KAAK;IAC/C,MAAM,CAACE,SAASC,WAAW,GAAGhD,SAC5BQ,iBAAiBO,OAAOgC,OAAO;IAEjC,MAAM,CAACE,YAAYC,cAAc,GAAGlD,SAAS;IAC7C,MAAM,CAACmD,QAAQC,UAAU,GAAGpD,SAAS;IAErC;;;;;GAKC,GACD,MAAMqD,WAAWtC,OAAOuC,GAAG;IAC3BvD,UAAU;QACR8B,gBAAgBd,OAAOa,YAAY;QACnCG,SAAShB,OAAOe,KAAK;QACrBG,YAAYlB,OAAOiB,QAAQ;QAC3BG,eAAepB,OAAOmB,WAAW;QACjCG,aAAatB,OAAOqB,SAAS,IAAI;QACjCG,YAAYxB,OAAOuB,QAAQ;QAC3BG,kBAAkB1B,OAAOyB,cAAc;QACvCG,QAAQ5B,OAAO2B,IAAI,CAACE,IAAI,CAAC;QACzBE,SAAS/B,OAAO8B,KAAK;QACrBG,WAAWxC,iBAAiBO,OAAOgC,OAAO;QAC1CG,cAAc;IACd,uDAAuD;IACzD,GAAG;QAACG;KAAS;IAEb,MAAME,aAAazD,YAAY;QAC7B,MAAM0D,eAAe1B,MAAM2B,IAAI;QAC/B,MAAMC,kBAAkBF,eAAe1E,eAAe0E,gBAAgB;QACtE,IAAIA,gBAAgB,CAACE,iBAAiB;YACpCR,cAAc;YACd;QACF;QACAA,cAAc;QACd,yEAAyE;QACzE,sBAAsB;QACtB,MAAMS,eAAe,CAACxC,eAAeqB,mBAAmBzB,OAAOyB,cAAc;QAC7E,MAAMoB,MAA2B;YAC/BC,MAAMjC,aAAa6B,IAAI,GAAGK,KAAK,CAAC,GAAG;YACnChC,KAAK,EAAE4B,0BAAAA,kBAAmB;YAC1B1B,UAAUA,SAASyB,IAAI,GAAGK,KAAK,CAAC,GAAG;YACnCf;YACAL,MAAMvC,iBAAiBuC;YACvBG,OAAOA,MAAMiB,KAAK,CAAC,GAAG;WAElB3C,cACA,CAAC,IACD;YAAEmB;YAAUF;YAAWF,aAAaA,YAAYuB,IAAI,GAAGK,KAAK,CAAC,GAAG;QAAK;QAE3EV,UAAU;QACV,IAAI;YACF,MAAMW,UAAU,MAAM3E,mBACpB;gBACE4E,SAAS;gBACTC,YAAYhD,KAAKiD,MAAM,KAAK;gBAC5BC,WAAWlD,KAAKkD,SAAS;YAC3B,GACA,IAAM5C,cAAc6C,SAAS,CAACrD,OAAOuC,GAAG,EAAEM;YAE5C,IAAI,CAACG,QAAQM,EAAE,EAAE;gBACf,OAAO,KAAK/C,gBAAgByC,QAAQO,OAAO,EAAE;oBAC3CC,SAAS;oBACTC,SAAS;gBACX;YACF;YACA/C,YAAY,mBAAmB;gBAC7BgD,MAAM;gBACNC,IAAI3D,OAAOuC,GAAG;gBACdO,MAAM9C,OAAO8C,IAAI,IAAI9C,OAAO4D,KAAK;YACnC;YACA,IAAIhB,gBAAgBnC,YAAY;gBAC9B,IAAI;oBACF,MAAMpB,gBAAgBiB,MAAMG,YAAYT,OAAOuC,GAAG,EAAEd,kBAAkB;gBACxE,EAAE,OAAOoC,OAAO;oBACd,oEAAoE;oBACpE,qCAAqC;oBACrC,OAAO,KAAKtD,gBACV,CAAC,2CAA2C,EAC1CsD,iBAAiBC,QAAQD,MAAMN,OAAO,GAAG,sBACzC,EACF;wBAAEC,SAAS;wBAAWC,SAAS;oBAAM;gBAEzC;YACF;YACAlD,gBAAgB,iBAAiB;gBAAEiD,SAAS;gBAAWC,SAAS;YAAM;QACxE,EAAE,OAAOI,OAAO;YACdE,QAAQF,KAAK,CAACA;YACdtD,gBACEsD,iBAAiBC,SAASD,MAAMN,OAAO,GAAGM,MAAMN,OAAO,GAAG,yBAC1D;gBAAEC,SAAS;gBAASQ,gBAAgB;YAAK;QAE7C,SAAU;YACR3B,UAAU;QACZ;IACF,GAAG;QACDL;QACAX;QACAF;QACAX;QACAD;QACAE;QACAQ;QACAQ;QACAf;QACAG;QACAiB;QACAP;QACAR;QACAf,OAAOuC,GAAG;QACVvC,OAAO4D,KAAK;QACZ5D,OAAOyB,cAAc;QACrBzB,OAAO8C,IAAI;QACX5C,KAAKkD,SAAS;QACdlD,KAAKiD,MAAM;QACX/C;QACAuB;QACArB;KACD;IAED;;;;;GAKC,GACD,MAAM2D,aAAa9D,QAAQ+D,OAAO,CAACC,IAAI,CAAC,CAACC,SAAWA,OAAOC,GAAG,KAAK9C;IAEnE,8EAA8E,GAC9E,MAAM+C,UAAUxG,WAAWiD;IAE3B,qBACE,KAAC9C;QACCsG,QAAQ;QACRC,MAAM7G,MAAM8G,cAAc,CAAC,iBAAiB;YAAEC,QAAQ;QAAmB;QACzEC,cAAc;QACdC,cAAc;QACdC,aAAa;YACXC,sBACE,KAACxG;gBACCkF,SAAQ;gBACRuB,OAAM;gBACNC,MAAK;gBACLC,UAAU7C;gBACV8C,SAAS,IAAM,KAAK1C;0BAEnBJ,SAAS,YAAY;;QAG5B;kBAEA,cAAA,MAAC7D;YAAK4G,SAAS;YAACC,SAAS;;8BACvB,KAAC7G;oBAAKyG,MAAM;wBAAEK,IAAI;wBAAIC,IAAI;oBAAE;8BAC1B,cAAA,KAAC1G;wBACCoG,MAAK;wBACLO,OAAM;wBACNC,OAAOxF,OAAO4D,KAAK;wBACnB6B,WAAW;4BAAEC,OAAO;gCAAEC,UAAU;4BAAK;wBAAE;wBACvCC,YAAW;wBACXC,SAAS;;;8BAGb,KAACtH;oBAAKyG,MAAM;wBAAEK,IAAI;wBAAIC,IAAI;oBAAE;8BAC1B,cAAA,KAAC1G;wBACCoG,MAAK;wBACLO,OAAM;wBACNC,OAAO3E;wBACPiF,UAAU,CAACC,QAAUjF,gBAAgBiF,MAAMC,MAAM,CAACR,KAAK;wBACvDC,WAAW;4BAAEQ,WAAW;gCAAEC,WAAW;4BAAI;wBAAE;wBAC3CN,YACE5F,OAAOmG,aAAa,GAChB,CAAC,+DAA+D,EAAEnG,OAAOmG,aAAa,CAAC,CAAC,CAAC,GACzF;wBAENN,SAAS;;;8BAGb,KAACtH;oBAAKyG,MAAM;wBAAEK,IAAI;wBAAIC,IAAI;oBAAE;8BAC1B,cAAA,KAAC1G;wBACCoG,MAAK;wBACLO,OAAM;wBACNC,OAAOzE;wBACP+E,UAAU,CAACC,QAAU/E,SAAS+E,MAAMC,MAAM,CAACR,KAAK;wBAChD3B,OAAOuC,QAAQlE;wBACf0D,YAAY1D,cAAc;wBAC1B2D,SAAS;wBACTJ,WAAW;4BACTC,OAAO;gCACL;;;;;iBAKC,GACDW,cAAc/B,wBACZ,KAAC7F;oCAAe6H,UAAS;8CACvB,cAAA,KAACzH;wCAAQ0H,OAAO,CAAC,KAAK,EAAExF,MAAM2B,IAAI,IAAI;kDACpC,cAAA,KAAClE;4CACCgI,WAAU;4CACVC,MAAMnC;4CACNU,MAAK;4CACL0B,MAAK;4CACLC,cAAY,CAAC,KAAK,EAAE5F,MAAM2B,IAAI,IAAI;sDAElC,cAAA,KAACxE;gDAAQ0I,MAAM5I,gBAAgB4I,IAAI;gDAAE5B,MAAM;;;;qCAI/C;4BACN;wBACF;;;8BAGJ,KAACzG;oBAAKyG,MAAM;wBAAEK,IAAI;wBAAIC,IAAI;oBAAE;8BAC1B,cAAA,KAAC1G;wBACCoG,MAAK;wBACLO,OAAM;wBACNC,OAAOvE;wBACP6E,UAAU,CAACC,QAAU7E,YAAY6E,MAAMC,MAAM,CAACR,KAAK;wBACnDC,WAAW;4BAAEQ,WAAW;gCAAEC,WAAW;4BAAI;wBAAE;wBAC3CL,SAAS;;;8BAGb,KAACtH;oBAAKyG,MAAM;wBAAEK,IAAI;wBAAIC,IAAI;oBAAE;8BAC1B,cAAA,KAAChG;wBACC4E,SAASvD,UAAUuD,OAAO;wBAC1B2C,OAAOlG,UAAUkG,KAAK;wBACtBC,WAAWnG,UAAUmG,SAAS;wBAC9BtB,OAAOnE;wBACPyE,UAAU,CAACnC,IAAIoD;4BACbzF,aAAaqC;4BACb,0DAA0D;4BAC1D,2DAA2D;4BAC3D,+CAA+C;4BAC/CvC,eAAe2F,UAAUA,QAAQjE,IAAI,GAAGa,KAAKxC,cAAc;wBAC7D;wBACA6F,UAAUpG;wBACVgD,OAAO5D,OAAO4D,KAAK;wBACnBqD,cAAc9F;wBACd8D,UAAU7C,UAAUhC;wBACpBwF,YAAYxF,cAAcT,yBAAyBuH;;;8BAGvD,KAAC3I;oBAAKyG,MAAM;wBAAEK,IAAI;wBAAIC,IAAI;oBAAE;8BAC1B,cAAA,MAAC1G;wBACCuI,MAAM;wBACNnC,MAAK;wBACLO,OAAM;wBACNC,OAAO/D;wBACPqE,UAAU,CAACC,QACTrE,kBAAkBqE,MAAMC,MAAM,CAACR,KAAK;wBAEtCP,UAAU7E;wBACVwF,YAAYxF,cAAcT,yBAAyBuH;wBACnDrB,SAAS;;0CAET,KAACnH;gCAAS8G,OAAM;0CAAI;;4BACnB3H,yBAAyBuJ,GAAG,CAAC,CAACC,sBAC7B,KAAC3I;oCAAqB8G,OAAO6B;8CAC1BzJ,8BAA8B,CAACyJ,MAAM;mCADzBA;;;;8BAMrB,KAAC9I;oBAAKyG,MAAM;wBAAEK,IAAI;wBAAIC,IAAI;oBAAE;8BAC1B,cAAA,MAAC1G;wBACCuI,MAAM;wBACNnC,MAAK;wBACLO,OAAM;wBACNC,OAAOjE;wBACPuE,UAAU,CAACC,QAAUvE,YAAYuE,MAAMC,MAAM,CAACR,KAAK;wBACnDP,UAAU7E;wBACVwF,YACExF,cACIT,yBACAQ,QAAQ0G,KAAK,IAAI,CAAC1G,QAAQ+D,OAAO,CAACoD,MAAM,GACtC,oEACA;wBAERzB,SAAS;;0CAET,KAACnH;gCAAS8G,OAAM;0CAAI;;4BACnBjE,YAAY,CAAC0C,2BACZ,KAACvF;gCAAS8G,OAAOjE;0CAAWpB,QAAQoH,UAAU,CAAChG;iCAC7C;4BACHpB,QAAQ+D,OAAO,CAACkD,GAAG,CAAC,CAACI,sBACpB,KAAC9I;oCAAyB8G,OAAOgC,MAAMnD,GAAG;8CACvCmD,MAAMjC,KAAK;mCADCiC,MAAMnD,GAAG;;;;8BAM9B,KAAC9F;oBAAKyG,MAAM;wBAAEK,IAAI;wBAAIC,IAAI;oBAAE;8BAC1B,cAAA,KAAC1G;wBACCoG,MAAK;wBACLO,OAAM;wBACNkC,aAAY;wBACZ7B,YAAW;wBACXJ,OAAO7D;wBACPmE,UAAU,CAACC,QAAUnE,QAAQmE,MAAMC,MAAM,CAACR,KAAK;wBAC/CK,SAAS;;;8BAGb,KAACtH;oBAAKyG,MAAM;wBAAEK,IAAI;oBAAG;8BACnB,cAAA,MAAC1G;wBAAMyG,SAAS;;0CACd,KAACtG;gCAAW0E,SAAQ;0CAAa;;0CACjC,KAAC9D;gCAAqB8F,OAAOxD;gCAAS8D,UAAU7D;;;;;8BAGpD,KAAC1D;oBAAKyG,MAAM;wBAAEK,IAAI;oBAAG;8BACnB,cAAA,KAACzG;wBACCoG,MAAK;wBACLO,OAAM;wBACNC,OAAO1D;wBACPgE,UAAU,CAACC,QAAUhE,SAASgE,MAAMC,MAAM,CAACR,KAAK;wBAChDI,YAAW;wBACX8B,SAAS;wBACTC,SAAS;wBACT9B,SAAS;;;;;;AAMrB;AACAjG,sBAAsBgI,WAAW,GAAG;AAEpC,eAAehI,sBAAqB"}
@@ -0,0 +1,68 @@
1
+ import type { ContactCampaignEmail } from '@aglyn/aglyn';
2
+ import { type CrmOrg } from './activity-queries';
3
+ export interface ContactTimelineCardProps {
4
+ /** The site the record is read under, or `null` at the organization level. */
5
+ hostId: string | null;
6
+ org: CrmOrg;
7
+ contactId: string;
8
+ /**
9
+ * The RAW contact document, as the page's listener hands it back. The card
10
+ * resolves the viewing group and reads that group's facet itself, so a
11
+ * page cannot hand it another holder's timeline by flattening the row
12
+ * through the wrong group.
13
+ */
14
+ contact: Record<string, unknown> | null | undefined;
15
+ /**
16
+ * Where a campaign entry links to — the email's report — or `null` for
17
+ * one the page cannot address. Handed in rather than built here because
18
+ * the report lives on another surface whose path is the MOUNT's to know:
19
+ * a site's record page reaches its own Emails hub, an org-level mount
20
+ * holds the org's site list and can reach every site's. No builder means
21
+ * no links, never a guessed one.
22
+ */
23
+ campaignHref?: (email: ContactCampaignEmail) => string | null;
24
+ /**
25
+ * The org's plan lacks the CRM (AGL-2788), which the shell mounts no CRM
26
+ * page for (AGL-2851). The history still draws; logging an activity stands
27
+ * locked, and one already logged cannot be edited.
28
+ */
29
+ suiteLocked?: boolean;
30
+ }
31
+ /**
32
+ * A person's whole history in one newest-first stream (AGL-2600): what the
33
+ * platform CAPTURED — a form, an order, a booking, a sign-up — what a person
34
+ * LOGGED beside it — a call, an email, a meeting, a note — and, since
35
+ * AGL-2616, the campaign mail the platform SENT them and what became of it.
36
+ *
37
+ * ## Why one stream
38
+ *
39
+ * The histories answer one question, "what has happened with this person",
40
+ * and a page showing them as separate lists asks the reader to interleave
41
+ * them by eye. The merge is `mergeContactTimeline`, pure and specced: newest
42
+ * first, stable at a tie, an undated entry last, a campaign at the instant
43
+ * it was sent.
44
+ *
45
+ * Each entry says which it is. A captured entry carries the door's label and
46
+ * a "Captured" chip and offers no controls; a logged entry carries its kind
47
+ * and a "Logged" chip, and its author may edit or delete it; a campaign
48
+ * entry carries "Campaign" and "Sent", links to the email's report, and is
49
+ * nobody's to edit.
50
+ *
51
+ * ## What is read
52
+ *
53
+ * The captured side comes off the contact document the page already holds
54
+ * — THIS group's facet, filtered to the sites the group may see, the same
55
+ * projection the contacts list makes — and costs no read. The logged side is
56
+ * the bounded listener every activity surface uses, filtered to this
57
+ * contact, with a foot for the next hundred. The campaign side is one
58
+ * request to `crm/contact-email-history`, which reads down this person's
59
+ * own delivery log, capped, and never a campaign's recipients. The facet's
60
+ * history is capped at fifty by the platform, so past the window the stream
61
+ * is the logged side alone; the foot says as much by asking for "more
62
+ * activity" rather than "more history".
63
+ */
64
+ export declare function ContactTimelineCard(props: ContactTimelineCardProps): import("react").JSX.Element;
65
+ export declare namespace ContactTimelineCard {
66
+ var displayName: string;
67
+ }
68
+ export default ContactTimelineCard;