@aglyn/plugins-crm 1.0.0-beta.221 → 1.0.0-beta.223

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 (541) hide show
  1. package/README.md +2 -1
  2. package/package.json +13 -13
  3. package/src/lib/components/activity-list.js +12 -5
  4. package/src/lib/components/activity-list.js.map +1 -1
  5. package/src/lib/components/companies-bulk-bar.d.ts +1 -4
  6. package/src/lib/components/companies-bulk-bar.js +7 -20
  7. package/src/lib/components/companies-bulk-bar.js.map +1 -1
  8. package/src/lib/components/companies-section.d.ts +3 -3
  9. package/src/lib/components/companies-section.js +149 -46
  10. package/src/lib/components/companies-section.js.map +1 -1
  11. package/src/lib/components/company-edit-drawer.js +281 -20
  12. package/src/lib/components/company-edit-drawer.js.map +1 -1
  13. package/src/lib/components/company-properties-card.js +99 -8
  14. package/src/lib/components/company-properties-card.js.map +1 -1
  15. package/src/lib/components/contact-detail-page.js +3 -1
  16. package/src/lib/components/contact-detail-page.js.map +1 -1
  17. package/src/lib/components/contact-merge-dialog.js +33 -10
  18. package/src/lib/components/contact-merge-dialog.js.map +1 -1
  19. package/src/lib/components/contact-properties-card.d.ts +0 -69
  20. package/src/lib/components/contact-properties-card.js +350 -60
  21. package/src/lib/components/contact-properties-card.js.map +1 -1
  22. package/src/lib/components/contact-reports-to-field.d.ts +46 -0
  23. package/src/lib/components/contact-reports-to-field.js +67 -0
  24. package/src/lib/components/contact-reports-to-field.js.map +1 -0
  25. package/src/lib/components/contacts-bulk-bar.d.ts +1 -8
  26. package/src/lib/components/contacts-bulk-bar.js +7 -19
  27. package/src/lib/components/contacts-bulk-bar.js.map +1 -1
  28. package/src/lib/components/contacts-section.js +46 -33
  29. package/src/lib/components/contacts-section.js.map +1 -1
  30. package/src/lib/components/crm-call-actions.d.ts +10 -0
  31. package/src/lib/components/crm-call-actions.js +26 -9
  32. package/src/lib/components/crm-call-actions.js.map +1 -1
  33. package/src/lib/components/crm-next-activity-column.js +1 -1
  34. package/src/lib/components/crm-next-activity-column.js.map +1 -1
  35. package/src/lib/components/crm-record-picker.d.ts +15 -0
  36. package/src/lib/components/crm-record-picker.js +16 -10
  37. package/src/lib/components/crm-record-picker.js.map +1 -1
  38. package/src/lib/components/crm-transfer-buttons.d.ts +54 -0
  39. package/src/lib/components/crm-transfer-buttons.js +167 -0
  40. package/src/lib/components/crm-transfer-buttons.js.map +1 -0
  41. package/src/lib/components/deal-contact-roles-card.d.ts +46 -0
  42. package/src/lib/components/deal-contact-roles-card.js +368 -0
  43. package/src/lib/components/deal-contact-roles-card.js.map +1 -0
  44. package/src/lib/components/deal-detail-page.d.ts +3 -2
  45. package/src/lib/components/deal-detail-page.js +25 -6
  46. package/src/lib/components/deal-detail-page.js.map +1 -1
  47. package/src/lib/components/deal-edit-drawer.d.ts +10 -0
  48. package/src/lib/components/deal-edit-drawer.js +219 -10
  49. package/src/lib/components/deal-edit-drawer.js.map +1 -1
  50. package/src/lib/components/deal-properties-card.d.ts +7 -0
  51. package/src/lib/components/deal-properties-card.js +34 -3
  52. package/src/lib/components/deal-properties-card.js.map +1 -1
  53. package/src/lib/components/deal-stage-card.d.ts +4 -0
  54. package/src/lib/components/deal-stage-card.js +10 -2
  55. package/src/lib/components/deal-stage-card.js.map +1 -1
  56. package/src/lib/components/deals-bulk-bar.d.ts +0 -3
  57. package/src/lib/components/deals-bulk-bar.js +7 -20
  58. package/src/lib/components/deals-bulk-bar.js.map +1 -1
  59. package/src/lib/components/deals-section.d.ts +3 -3
  60. package/src/lib/components/deals-section.js +123 -63
  61. package/src/lib/components/deals-section.js.map +1 -1
  62. package/src/lib/components/fields-section.js +31 -17
  63. package/src/lib/components/fields-section.js.map +1 -1
  64. package/src/lib/components/lead-convert-dialog.d.ts +4 -0
  65. package/src/lib/components/lead-convert-dialog.js +23 -1
  66. package/src/lib/components/lead-convert-dialog.js.map +1 -1
  67. package/src/lib/components/lead-detail-page.js +8 -2
  68. package/src/lib/components/lead-detail-page.js.map +1 -1
  69. package/src/lib/components/lead-profile-fields.d.ts +71 -0
  70. package/src/lib/components/lead-profile-fields.js +386 -0
  71. package/src/lib/components/lead-profile-fields.js.map +1 -0
  72. package/src/lib/components/lead-properties-card.d.ts +2 -1
  73. package/src/lib/components/lead-properties-card.js +85 -176
  74. package/src/lib/components/lead-properties-card.js.map +1 -1
  75. package/src/lib/components/lead-source-select.d.ts +4 -23
  76. package/src/lib/components/lead-source-select.js +9 -73
  77. package/src/lib/components/lead-source-select.js.map +1 -1
  78. package/src/lib/components/lead-status-chip.d.ts +9 -3
  79. package/src/lib/components/lead-status-chip.js +8 -4
  80. package/src/lib/components/lead-status-chip.js.map +1 -1
  81. package/src/lib/components/lead-status-options.d.ts +20 -0
  82. package/src/lib/components/lead-status-options.js +51 -0
  83. package/src/lib/components/lead-status-options.js.map +1 -0
  84. package/src/lib/components/lead-unqualify-dialog.d.ts +5 -0
  85. package/src/lib/components/lead-unqualify-dialog.js +50 -18
  86. package/src/lib/components/lead-unqualify-dialog.js.map +1 -1
  87. package/src/lib/components/leads-bulk-bar.d.ts +0 -3
  88. package/src/lib/components/leads-bulk-bar.js +29 -29
  89. package/src/lib/components/leads-bulk-bar.js.map +1 -1
  90. package/src/lib/components/leads-section.js +120 -68
  91. package/src/lib/components/leads-section.js.map +1 -1
  92. package/src/lib/components/linked-deals-card.d.ts +4 -0
  93. package/src/lib/components/linked-deals-card.js +47 -3
  94. package/src/lib/components/linked-deals-card.js.map +1 -1
  95. package/src/lib/components/log-activity-dialog.js +43 -3
  96. package/src/lib/components/log-activity-dialog.js.map +1 -1
  97. package/src/lib/components/new-contact-drawer.d.ts +8 -0
  98. package/src/lib/components/new-contact-drawer.js +108 -6
  99. package/src/lib/components/new-contact-drawer.js.map +1 -1
  100. package/src/lib/components/new-lead-drawer.d.ts +9 -2
  101. package/src/lib/components/new-lead-drawer.js +88 -121
  102. package/src/lib/components/new-lead-drawer.js.map +1 -1
  103. package/src/lib/components/picklist-select.d.ts +36 -0
  104. package/src/lib/components/picklist-select.js +114 -0
  105. package/src/lib/components/picklist-select.js.map +1 -0
  106. package/src/lib/components/picklist-values-card.d.ts +34 -0
  107. package/src/lib/components/{lead-source-values-card.js → picklist-values-card.js} +241 -58
  108. package/src/lib/components/picklist-values-card.js.map +1 -0
  109. package/src/lib/components/pipeline-stages-dialog.d.ts +7 -0
  110. package/src/lib/components/pipeline-stages-dialog.js +26 -4
  111. package/src/lib/components/pipeline-stages-dialog.js.map +1 -1
  112. package/src/lib/components/pipelines-dialog.js +15 -6
  113. package/src/lib/components/pipelines-dialog.js.map +1 -1
  114. package/src/lib/components/recent-activity-feed.js +20 -5
  115. package/src/lib/components/recent-activity-feed.js.map +1 -1
  116. package/src/lib/components/recipes-card.js +4 -2
  117. package/src/lib/components/recipes-card.js.map +1 -1
  118. package/src/lib/components/record-tasks-card.js +15 -8
  119. package/src/lib/components/record-tasks-card.js.map +1 -1
  120. package/src/lib/components/reports/forecast-card.d.ts +6 -0
  121. package/src/lib/components/reports/forecast-card.js +101 -3
  122. package/src/lib/components/reports/forecast-card.js.map +1 -1
  123. package/src/lib/components/reports/lead-funnel-card.d.ts +12 -0
  124. package/src/lib/components/reports/lead-funnel-card.js +9 -5
  125. package/src/lib/components/reports/lead-funnel-card.js.map +1 -1
  126. package/src/lib/components/reports/lead-source-card.d.ts +23 -0
  127. package/src/lib/components/reports/lead-source-card.js +318 -0
  128. package/src/lib/components/reports/lead-source-card.js.map +1 -0
  129. package/src/lib/components/reports/pipeline-card.js +2 -1
  130. package/src/lib/components/reports/pipeline-card.js.map +1 -1
  131. package/src/lib/components/reports/report-export.js +1 -1
  132. package/src/lib/components/reports/report-export.js.map +1 -1
  133. package/src/lib/components/reports-section.js +8 -0
  134. package/src/lib/components/reports-section.js.map +1 -1
  135. package/src/lib/components/sharing-rule-drawer.d.ts +5 -0
  136. package/src/lib/components/sharing-rule-drawer.js +108 -19
  137. package/src/lib/components/sharing-rule-drawer.js.map +1 -1
  138. package/src/lib/components/sharing-rules-card.js +11 -3
  139. package/src/lib/components/sharing-rules-card.js.map +1 -1
  140. package/src/lib/components/task-cells.d.ts +9 -1
  141. package/src/lib/components/task-cells.js +9 -4
  142. package/src/lib/components/task-cells.js.map +1 -1
  143. package/src/lib/components/task-edit-drawer.js +111 -43
  144. package/src/lib/components/task-edit-drawer.js.map +1 -1
  145. package/src/lib/components/tasks-bulk-bar.d.ts +0 -3
  146. package/src/lib/components/tasks-bulk-bar.js +7 -20
  147. package/src/lib/components/tasks-bulk-bar.js.map +1 -1
  148. package/src/lib/components/tasks-calendar.d.ts +3 -0
  149. package/src/lib/components/tasks-calendar.js +8 -1
  150. package/src/lib/components/tasks-calendar.js.map +1 -1
  151. package/src/lib/components/tasks-section.d.ts +3 -3
  152. package/src/lib/components/tasks-section.js +58 -43
  153. package/src/lib/components/tasks-section.js.map +1 -1
  154. package/src/lib/constants/api-routes.d.ts +2 -9
  155. package/src/lib/constants/api-routes.js +1 -7
  156. package/src/lib/constants/api-routes.js.map +1 -1
  157. package/src/lib/constants/bundle-common.d.ts +6 -0
  158. package/src/lib/constants/bundle-common.js +11 -0
  159. package/src/lib/constants/bundle-common.js.map +1 -1
  160. package/src/lib/constants/company-filters.d.ts +14 -0
  161. package/src/lib/constants/company-filters.js +51 -1
  162. package/src/lib/constants/company-filters.js.map +1 -1
  163. package/src/lib/constants/contact-filters.d.ts +2 -0
  164. package/src/lib/constants/contact-filters.js +18 -1
  165. package/src/lib/constants/contact-filters.js.map +1 -1
  166. package/src/lib/constants/deal-filters.d.ts +22 -1
  167. package/src/lib/constants/deal-filters.js +67 -4
  168. package/src/lib/constants/deal-filters.js.map +1 -1
  169. package/src/lib/declarations.console-server.d.ts +3 -0
  170. package/src/lib/declarations.console-server.js +35 -0
  171. package/src/lib/declarations.console-server.js.map +1 -1
  172. package/src/lib/declarations.d.ts +26 -0
  173. package/src/lib/declarations.js +35 -0
  174. package/src/lib/declarations.js.map +1 -0
  175. package/src/lib/declarations.server.d.ts +11 -0
  176. package/src/lib/declarations.server.js +97 -1
  177. package/src/lib/declarations.server.js.map +1 -1
  178. package/src/lib/hooks/use-company-picklists.d.ts +15 -0
  179. package/src/lib/hooks/use-company-picklists.js +55 -0
  180. package/src/lib/hooks/use-company-picklists.js.map +1 -0
  181. package/src/lib/hooks/use-crm-picklist.d.ts +25 -0
  182. package/src/lib/hooks/use-crm-picklist.js +53 -0
  183. package/src/lib/hooks/use-crm-picklist.js.map +1 -0
  184. package/src/lib/hooks/use-crm-record-names.d.ts +16 -0
  185. package/src/lib/hooks/use-crm-record-names.js +45 -19
  186. package/src/lib/hooks/use-crm-record-names.js.map +1 -1
  187. package/src/lib/hooks/use-crm-task-picklists.d.ts +11 -0
  188. package/src/lib/hooks/use-crm-task-picklists.js +45 -0
  189. package/src/lib/hooks/use-crm-task-picklists.js.map +1 -0
  190. package/src/lib/hooks/use-deals.d.ts +14 -0
  191. package/src/lib/hooks/use-deals.js +29 -0
  192. package/src/lib/hooks/use-deals.js.map +1 -1
  193. package/src/lib/hooks/use-lead-picklists.d.ts +14 -0
  194. package/src/lib/hooks/use-lead-picklists.js +46 -0
  195. package/src/lib/hooks/use-lead-picklists.js.map +1 -0
  196. package/src/lib/hooks/use-lead-source-picklist.d.ts +5 -19
  197. package/src/lib/hooks/use-lead-source-picklist.js +12 -22
  198. package/src/lib/hooks/use-lead-source-picklist.js.map +1 -1
  199. package/src/lib/hooks/use-lead-status-picklist.d.ts +9 -0
  200. package/src/lib/hooks/use-lead-status-picklist.js +40 -0
  201. package/src/lib/hooks/use-lead-status-picklist.js.map +1 -0
  202. package/src/lib/model/companies.d.ts +32 -3
  203. package/src/lib/model/companies.js +133 -16
  204. package/src/lib/model/companies.js.map +1 -1
  205. package/src/lib/model/contact-merge.d.ts +27 -3
  206. package/src/lib/model/contact-merge.js +81 -7
  207. package/src/lib/model/contact-merge.js.map +1 -1
  208. package/src/lib/model/contact-record.d.ts +17 -0
  209. package/src/lib/model/contact-record.js +17 -2
  210. package/src/lib/model/contact-record.js.map +1 -1
  211. package/src/lib/model/contact-update.d.ts +31 -2
  212. package/src/lib/model/contact-update.js +14 -0
  213. package/src/lib/model/contact-update.js.map +1 -1
  214. package/src/lib/model/crm-list-query.d.ts +5 -0
  215. package/src/lib/model/crm-list-query.js +8 -0
  216. package/src/lib/model/crm-list-query.js.map +1 -1
  217. package/src/lib/model/crm-next-activity.d.ts +107 -0
  218. package/src/lib/model/crm-next-activity.js +140 -0
  219. package/src/lib/model/crm-next-activity.js.map +1 -0
  220. package/src/lib/model/crm-recipes.d.ts +40 -0
  221. package/src/lib/model/crm-recipes.js +259 -0
  222. package/src/lib/model/crm-recipes.js.map +1 -0
  223. package/src/lib/model/crm-record-counts.d.ts +36 -0
  224. package/src/lib/model/crm-record-counts.js +54 -0
  225. package/src/lib/model/crm-record-counts.js.map +1 -0
  226. package/src/lib/model/crm-record-lists.d.ts +23 -0
  227. package/src/lib/model/crm-record-lists.js +161 -0
  228. package/src/lib/model/crm-record-lists.js.map +1 -0
  229. package/src/lib/model/crm-reports.d.ts +73 -3
  230. package/src/lib/model/crm-reports.js +120 -1
  231. package/src/lib/model/crm-reports.js.map +1 -1
  232. package/src/lib/model/crm-sharing.d.ts +21 -3
  233. package/src/lib/model/crm-sharing.js +27 -6
  234. package/src/lib/model/crm-sharing.js.map +1 -1
  235. package/src/lib/model/crm-task-reminders.d.ts +152 -0
  236. package/src/lib/model/crm-task-reminders.js +161 -0
  237. package/src/lib/model/crm-task-reminders.js.map +1 -0
  238. package/src/lib/model/deal-board-model.d.ts +8 -2
  239. package/src/lib/model/deal-board-model.js +15 -2
  240. package/src/lib/model/deal-board-model.js.map +1 -1
  241. package/src/lib/model/deal-contact-roles.d.ts +45 -0
  242. package/src/lib/model/deal-contact-roles.js +73 -0
  243. package/src/lib/model/deal-contact-roles.js.map +1 -0
  244. package/src/lib/model/deal-form-model.d.ts +56 -0
  245. package/src/lib/model/deal-form-model.js +79 -7
  246. package/src/lib/model/deal-form-model.js.map +1 -1
  247. package/src/lib/model/download-text-file.d.ts +23 -0
  248. package/src/lib/model/download-text-file.js +34 -0
  249. package/src/lib/model/download-text-file.js.map +1 -0
  250. package/src/lib/model/lead-filters.d.ts +36 -2
  251. package/src/lib/model/lead-filters.js +123 -2
  252. package/src/lib/model/lead-filters.js.map +1 -1
  253. package/src/lib/model/lead-source-direction.d.ts +38 -0
  254. package/src/lib/model/lead-source-direction.js +52 -0
  255. package/src/lib/model/lead-source-direction.js.map +1 -0
  256. package/src/lib/model/next-activity.d.ts +1 -1
  257. package/src/lib/model/next-activity.js.map +1 -1
  258. package/src/lib/model/picklist-values.d.ts +119 -0
  259. package/src/lib/model/picklist-values.js +256 -0
  260. package/src/lib/model/picklist-values.js.map +1 -0
  261. package/src/lib/model/record-facts-disclosed.d.ts +81 -0
  262. package/src/lib/model/record-facts-disclosed.js +281 -0
  263. package/src/lib/model/record-facts-disclosed.js.map +1 -0
  264. package/src/lib/model/record-facts.d.ts +215 -34
  265. package/src/lib/model/record-facts.js +307 -128
  266. package/src/lib/model/record-facts.js.map +1 -1
  267. package/src/lib/model/task-picklists.d.ts +52 -0
  268. package/src/lib/model/task-picklists.js +83 -0
  269. package/src/lib/model/task-picklists.js.map +1 -0
  270. package/src/lib/model/task-routes.d.ts +13 -0
  271. package/src/lib/model/task-routes.js +23 -4
  272. package/src/lib/model/task-routes.js.map +1 -1
  273. package/src/lib/plan-entitlements.js +6 -4
  274. package/src/lib/plan-entitlements.js.map +1 -1
  275. package/src/lib/plugin.js +17 -0
  276. package/src/lib/plugin.js.map +1 -1
  277. package/src/lib/server/api-v1/contacts.js +220 -14
  278. package/src/lib/server/api-v1/contacts.js.map +1 -1
  279. package/src/lib/server/api-v1/crm-activities.js +14 -1
  280. package/src/lib/server/api-v1/crm-activities.js.map +1 -1
  281. package/src/lib/server/api-v1/crm-companies.js +123 -14
  282. package/src/lib/server/api-v1/crm-companies.js.map +1 -1
  283. package/src/lib/server/api-v1/crm-deals.js +291 -26
  284. package/src/lib/server/api-v1/crm-deals.js.map +1 -1
  285. package/src/lib/server/api-v1/crm-leads.js +144 -38
  286. package/src/lib/server/api-v1/crm-leads.js.map +1 -1
  287. package/src/lib/server/api-v1/crm-pipelines.d.ts +6 -0
  288. package/src/lib/server/api-v1/crm-pipelines.js +8 -2
  289. package/src/lib/server/api-v1/crm-pipelines.js.map +1 -1
  290. package/src/lib/server/api-v1/crm-tasks.js +78 -34
  291. package/src/lib/server/api-v1/crm-tasks.js.map +1 -1
  292. package/src/lib/server/api-v1/openapi.d.ts +0 -11
  293. package/src/lib/server/api-v1/openapi.js +171 -16
  294. package/src/lib/server/api-v1/openapi.js.map +1 -1
  295. package/src/lib/server/assign-contact-owner.d.ts +188 -0
  296. package/src/lib/server/assign-contact-owner.js +446 -0
  297. package/src/lib/server/assign-contact-owner.js.map +1 -0
  298. package/src/lib/server/associate-company-by-domain.d.ts +70 -0
  299. package/src/lib/server/associate-company-by-domain.js +153 -0
  300. package/src/lib/server/associate-company-by-domain.js.map +1 -0
  301. package/src/lib/server/automation-steps.d.ts +140 -0
  302. package/src/lib/server/automation-steps.js +669 -0
  303. package/src/lib/server/automation-steps.js.map +1 -0
  304. package/src/lib/server/capture-contact.d.ts +17 -0
  305. package/src/lib/server/capture-contact.js +95 -26
  306. package/src/lib/server/capture-contact.js.map +1 -1
  307. package/src/lib/server/capture-host-contact.d.ts +104 -0
  308. package/src/lib/server/capture-host-contact.js +151 -0
  309. package/src/lib/server/capture-host-contact.js.map +1 -0
  310. package/src/lib/server/company-children.d.ts +25 -0
  311. package/src/lib/server/company-children.js +42 -0
  312. package/src/lib/server/company-children.js.map +1 -0
  313. package/src/lib/server/company-delete.d.ts +18 -0
  314. package/src/lib/server/company-delete.js +44 -21
  315. package/src/lib/server/company-delete.js.map +1 -1
  316. package/src/lib/server/contact-email-history.js +21 -19
  317. package/src/lib/server/contact-email-history.js.map +1 -1
  318. package/src/lib/server/contact-remove.js +27 -2
  319. package/src/lib/server/contact-remove.js.map +1 -1
  320. package/src/lib/server/contact-reports-to.d.ts +61 -0
  321. package/src/lib/server/contact-reports-to.js +114 -0
  322. package/src/lib/server/contact-reports-to.js.map +1 -0
  323. package/src/lib/server/contact-update.d.ts +42 -1
  324. package/src/lib/server/contact-update.js +204 -23
  325. package/src/lib/server/contact-update.js.map +1 -1
  326. package/src/lib/server/convert-host-lead.d.ts +46 -1
  327. package/src/lib/server/convert-host-lead.js +173 -15
  328. package/src/lib/server/convert-host-lead.js.map +1 -1
  329. package/src/lib/server/convert-open-lead.js +12 -5
  330. package/src/lib/server/convert-open-lead.js.map +1 -1
  331. package/src/lib/server/crm-email-activity.d.ts +118 -0
  332. package/src/lib/server/crm-email-activity.js +148 -0
  333. package/src/lib/server/crm-email-activity.js.map +1 -0
  334. package/src/lib/server/crm-inbound-email.js +1 -1
  335. package/src/lib/server/crm-inbound-email.js.map +1 -1
  336. package/src/lib/server/crm-next-activity.d.ts +74 -0
  337. package/src/lib/server/crm-next-activity.js +194 -0
  338. package/src/lib/server/crm-next-activity.js.map +1 -0
  339. package/src/lib/server/crm-record-indexes.d.ts +45 -0
  340. package/src/lib/server/crm-record-indexes.js +78 -0
  341. package/src/lib/server/crm-record-indexes.js.map +1 -0
  342. package/src/lib/server/crm-sharing.d.ts +9 -1
  343. package/src/lib/server/crm-sharing.js +23 -3
  344. package/src/lib/server/crm-sharing.js.map +1 -1
  345. package/src/lib/server/deal-contact-roles.d.ts +27 -0
  346. package/src/lib/server/deal-contact-roles.js +89 -0
  347. package/src/lib/server/deal-contact-roles.js.map +1 -0
  348. package/src/lib/server/email-send.js +2 -1
  349. package/src/lib/server/email-send.js.map +1 -1
  350. package/src/lib/server/lead-convert.d.ts +5 -0
  351. package/src/lib/server/lead-convert.js +19 -3
  352. package/src/lib/server/lead-convert.js.map +1 -1
  353. package/src/lib/server/lead-create.d.ts +17 -2
  354. package/src/lib/server/lead-create.js +46 -14
  355. package/src/lib/server/lead-create.js.map +1 -1
  356. package/src/lib/server/lead-nurturing.d.ts +6 -0
  357. package/src/lib/server/lead-nurturing.js +57 -20
  358. package/src/lib/server/lead-nurturing.js.map +1 -1
  359. package/src/lib/server/lead-picklists.d.ts +35 -0
  360. package/src/lib/server/lead-picklists.js +52 -0
  361. package/src/lib/server/lead-picklists.js.map +1 -0
  362. package/src/lib/server/lead-source-picklist.d.ts +1 -13
  363. package/src/lib/server/lead-source-picklist.js +6 -33
  364. package/src/lib/server/lead-source-picklist.js.map +1 -1
  365. package/src/lib/server/merge-contacts.js +23 -5
  366. package/src/lib/server/merge-contacts.js.map +1 -1
  367. package/src/lib/server/next-activity-routes.js +2 -1
  368. package/src/lib/server/next-activity-routes.js.map +1 -1
  369. package/src/lib/server/person-eraser.d.ts +53 -0
  370. package/src/lib/server/person-eraser.js +149 -0
  371. package/src/lib/server/person-eraser.js.map +1 -0
  372. package/src/lib/server/person-records.d.ts +69 -0
  373. package/src/lib/server/person-records.js +317 -0
  374. package/src/lib/server/person-records.js.map +1 -0
  375. package/src/lib/server/person-refund.d.ts +97 -0
  376. package/src/lib/server/person-refund.js +221 -0
  377. package/src/lib/server/person-refund.js.map +1 -0
  378. package/src/lib/server/picklist-values.d.ts +21 -0
  379. package/src/lib/server/picklist-values.js +308 -0
  380. package/src/lib/server/picklist-values.js.map +1 -0
  381. package/src/lib/server/read-picklist.d.ts +44 -0
  382. package/src/lib/server/read-picklist.js +65 -0
  383. package/src/lib/server/read-picklist.js.map +1 -0
  384. package/src/lib/server/recipe-routes.js +22 -8
  385. package/src/lib/server/recipe-routes.js.map +1 -1
  386. package/src/lib/server/record-email-state.js +7 -1
  387. package/src/lib/server/record-email-state.js.map +1 -1
  388. package/src/lib/server/record-facts.d.ts +3 -0
  389. package/src/lib/server/record-facts.js +233 -31
  390. package/src/lib/server/record-facts.js.map +1 -1
  391. package/src/lib/server/record-origin.d.ts +27 -0
  392. package/src/lib/server/record-origin.js +104 -0
  393. package/src/lib/server/record-origin.js.map +1 -0
  394. package/src/lib/server/record-timeline.js +40 -3
  395. package/src/lib/server/record-timeline.js.map +1 -1
  396. package/src/lib/server/suite-gate.js +4 -3
  397. package/src/lib/server/suite-gate.js.map +1 -1
  398. package/src/lib/server/task-reminders-route.js +2 -1
  399. package/src/lib/server/task-reminders-route.js.map +1 -1
  400. package/src/lib/server/task-routes.js +33 -17
  401. package/src/lib/server/task-routes.js.map +1 -1
  402. package/src/lib/server-deal-stage.d.ts +5 -1
  403. package/src/lib/server-deal-stage.js +10 -5
  404. package/src/lib/server-deal-stage.js.map +1 -1
  405. package/src/lib/server.d.ts +8 -3
  406. package/src/lib/server.js +47 -43
  407. package/src/lib/server.js.map +1 -1
  408. package/src/lib/testing/memory-firestore.d.ts +55 -0
  409. package/src/lib/testing/memory-firestore.js +335 -0
  410. package/src/lib/testing/memory-firestore.js.map +1 -0
  411. package/src/lib/testing/stand-in-email-send-index.d.ts +25 -0
  412. package/src/lib/testing/stand-in-email-send-index.js +49 -0
  413. package/src/lib/testing/stand-in-email-send-index.js.map +1 -0
  414. package/src/lib/transfer/activities.d.ts +30 -0
  415. package/src/lib/transfer/activities.js +132 -0
  416. package/src/lib/transfer/activities.js.map +1 -0
  417. package/src/lib/transfer/aliases.d.ts +22 -0
  418. package/src/lib/transfer/aliases.js +1342 -0
  419. package/src/lib/transfer/aliases.js.map +1 -0
  420. package/src/lib/transfer/common.d.ts +222 -0
  421. package/src/lib/transfer/common.js +832 -0
  422. package/src/lib/transfer/common.js.map +1 -0
  423. package/src/lib/transfer/companies.d.ts +43 -0
  424. package/src/lib/transfer/companies.js +549 -0
  425. package/src/lib/transfer/companies.js.map +1 -0
  426. package/src/lib/transfer/contacts.d.ts +31 -0
  427. package/src/lib/transfer/contacts.js +727 -0
  428. package/src/lib/transfer/contacts.js.map +1 -0
  429. package/src/lib/transfer/deals.d.ts +66 -0
  430. package/src/lib/transfer/deals.js +698 -0
  431. package/src/lib/transfer/deals.js.map +1 -0
  432. package/src/lib/transfer/email-templates-package.d.ts +40 -0
  433. package/src/lib/transfer/email-templates-package.js +76 -0
  434. package/src/lib/transfer/email-templates-package.js.map +1 -0
  435. package/src/lib/transfer/email-templates-package.server.d.ts +32 -0
  436. package/src/lib/transfer/email-templates-package.server.js +176 -0
  437. package/src/lib/transfer/email-templates-package.server.js.map +1 -0
  438. package/src/lib/transfer/fields.d.ts +102 -0
  439. package/src/lib/transfer/fields.js +1755 -0
  440. package/src/lib/transfer/fields.js.map +1 -0
  441. package/src/lib/transfer/leads.d.ts +30 -0
  442. package/src/lib/transfer/leads.js +582 -0
  443. package/src/lib/transfer/leads.js.map +1 -0
  444. package/src/lib/transfer/pipelines.d.ts +21 -0
  445. package/src/lib/transfer/pipelines.js +172 -0
  446. package/src/lib/transfer/pipelines.js.map +1 -0
  447. package/src/lib/transfer/register.d.ts +47 -0
  448. package/src/lib/transfer/register.js +277 -0
  449. package/src/lib/transfer/register.js.map +1 -0
  450. package/src/lib/transfer/tasks.d.ts +30 -0
  451. package/src/lib/transfer/tasks.js +418 -0
  452. package/src/lib/transfer/tasks.js.map +1 -0
  453. package/src/lib/transfer/ui.d.ts +20 -0
  454. package/src/lib/transfer/ui.js +42 -0
  455. package/src/lib/transfer/ui.js.map +1 -0
  456. package/src/lib/components/company-import-drawer.d.ts +0 -42
  457. package/src/lib/components/company-import-drawer.js +0 -99
  458. package/src/lib/components/company-import-drawer.js.map +0 -1
  459. package/src/lib/components/contact-import-drawer.d.ts +0 -46
  460. package/src/lib/components/contact-import-drawer.js +0 -149
  461. package/src/lib/components/contact-import-drawer.js.map +0 -1
  462. package/src/lib/components/crm-export-all-button.d.ts +0 -39
  463. package/src/lib/components/crm-export-all-button.js +0 -98
  464. package/src/lib/components/crm-export-all-button.js.map +0 -1
  465. package/src/lib/components/csv-import-drawer.d.ts +0 -139
  466. package/src/lib/components/csv-import-drawer.js +0 -757
  467. package/src/lib/components/csv-import-drawer.js.map +0 -1
  468. package/src/lib/components/deal-import-drawer.d.ts +0 -24
  469. package/src/lib/components/deal-import-drawer.js +0 -83
  470. package/src/lib/components/deal-import-drawer.js.map +0 -1
  471. package/src/lib/components/lead-import-drawer.d.ts +0 -27
  472. package/src/lib/components/lead-import-drawer.js +0 -118
  473. package/src/lib/components/lead-import-drawer.js.map +0 -1
  474. package/src/lib/components/lead-source-values-card.d.ts +0 -27
  475. package/src/lib/components/lead-source-values-card.js.map +0 -1
  476. package/src/lib/components/task-import-drawer.d.ts +0 -24
  477. package/src/lib/components/task-import-drawer.js +0 -82
  478. package/src/lib/components/task-import-drawer.js.map +0 -1
  479. package/src/lib/model/companies-csv.d.ts +0 -36
  480. package/src/lib/model/companies-csv.js +0 -38
  481. package/src/lib/model/companies-csv.js.map +0 -1
  482. package/src/lib/model/contacts-csv.d.ts +0 -54
  483. package/src/lib/model/contacts-csv.js +0 -67
  484. package/src/lib/model/contacts-csv.js.map +0 -1
  485. package/src/lib/model/crm-company-import.d.ts +0 -154
  486. package/src/lib/model/crm-company-import.js +0 -331
  487. package/src/lib/model/crm-company-import.js.map +0 -1
  488. package/src/lib/model/crm-csv.d.ts +0 -239
  489. package/src/lib/model/crm-csv.js +0 -467
  490. package/src/lib/model/crm-csv.js.map +0 -1
  491. package/src/lib/model/crm-deal-import.d.ts +0 -112
  492. package/src/lib/model/crm-deal-import.js +0 -263
  493. package/src/lib/model/crm-deal-import.js.map +0 -1
  494. package/src/lib/model/crm-import.d.ts +0 -250
  495. package/src/lib/model/crm-import.js +0 -467
  496. package/src/lib/model/crm-import.js.map +0 -1
  497. package/src/lib/model/crm-lead-import.d.ts +0 -138
  498. package/src/lib/model/crm-lead-import.js +0 -446
  499. package/src/lib/model/crm-lead-import.js.map +0 -1
  500. package/src/lib/model/crm-task-import.d.ts +0 -94
  501. package/src/lib/model/crm-task-import.js +0 -275
  502. package/src/lib/model/crm-task-import.js.map +0 -1
  503. package/src/lib/model/deals-csv.d.ts +0 -32
  504. package/src/lib/model/deals-csv.js +0 -36
  505. package/src/lib/model/deals-csv.js.map +0 -1
  506. package/src/lib/model/import-column-shapes.d.ts +0 -36
  507. package/src/lib/model/import-column-shapes.js +0 -76
  508. package/src/lib/model/import-column-shapes.js.map +0 -1
  509. package/src/lib/model/lead-source-values.d.ts +0 -82
  510. package/src/lib/model/lead-source-values.js +0 -149
  511. package/src/lib/model/lead-source-values.js.map +0 -1
  512. package/src/lib/model/leads-csv.d.ts +0 -40
  513. package/src/lib/model/leads-csv.js +0 -40
  514. package/src/lib/model/leads-csv.js.map +0 -1
  515. package/src/lib/model/tasks-csv.d.ts +0 -28
  516. package/src/lib/model/tasks-csv.js +0 -28
  517. package/src/lib/model/tasks-csv.js.map +0 -1
  518. package/src/lib/server/companies-import.d.ts +0 -57
  519. package/src/lib/server/companies-import.js +0 -242
  520. package/src/lib/server/companies-import.js.map +0 -1
  521. package/src/lib/server/contacts-import.d.ts +0 -109
  522. package/src/lib/server/contacts-import.js +0 -393
  523. package/src/lib/server/contacts-import.js.map +0 -1
  524. package/src/lib/server/deals-import.d.ts +0 -76
  525. package/src/lib/server/deals-import.js +0 -248
  526. package/src/lib/server/deals-import.js.map +0 -1
  527. package/src/lib/server/export-route.d.ts +0 -60
  528. package/src/lib/server/export-route.js +0 -447
  529. package/src/lib/server/export-route.js.map +0 -1
  530. package/src/lib/server/import-context.d.ts +0 -87
  531. package/src/lib/server/import-context.js +0 -182
  532. package/src/lib/server/import-context.js.map +0 -1
  533. package/src/lib/server/lead-source-values.d.ts +0 -50
  534. package/src/lib/server/lead-source-values.js +0 -191
  535. package/src/lib/server/lead-source-values.js.map +0 -1
  536. package/src/lib/server/leads-import.d.ts +0 -84
  537. package/src/lib/server/leads-import.js +0 -367
  538. package/src/lib/server/leads-import.js.map +0 -1
  539. package/src/lib/server/tasks-import.d.ts +0 -54
  540. package/src/lib/server/tasks-import.js +0 -160
  541. package/src/lib/server/tasks-import.js.map +0 -1
@@ -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, Fragment as _Fragment } from "react/jsx-runtime";
19
+ import { CRM_COLLECTIONS, dealContactRolesOf, dealContactRolesWithout, dealContactRolesWithPrimary, pluginDocsHelp } from "@aglyn/aglyn";
20
+ import { mdiAccountPlusOutline, mdiAccountRemoveOutline } from "@aglyn/shared-data-mdi";
21
+ import { AppLink, CardDisplay, MdiIcon } from "@aglyn/shared-ui-jsx";
22
+ import EmptyStateComponent from "@aglyn/shared-ui-jsx/components/empty-state.component";
23
+ import { useSnackbar } from "@aglyn/shared-ui-snackstack";
24
+ import { useFirestore, writeGuardedBySeed } from "@aglyn/tenant-feature-instance";
25
+ import { Box, Button, Checkbox, Chip, Dialog, DialogActions, DialogContent, DialogTitle, FormControlLabel, IconButton, Stack, Tooltip, Typography } from "@mui/material";
26
+ import { deleteField, doc, updateDoc } from "firebase/firestore";
27
+ import { useCallback, useMemo, useState } from "react";
28
+ import { useCrmPicklist } from "../hooks/use-crm-picklist.js";
29
+ import { useCrmRecordNames } from "../hooks/use-crm-record-names.js";
30
+ import { useCrmScope } from "../hooks/use-crm-scope.js";
31
+ import { CRM_DEAL_CONTACT_ROLE_LIST_FIELDS, crmClientListFields } from "../model/crm-list-query.js";
32
+ import { dealContactRoleAddProblem, dealContactRolesAdded, dealContactRolesSave, dealContactRolesWithRole } from "../model/deal-contact-roles.js";
33
+ import CrmRecordPicker from "./crm-record-picker.js";
34
+ import { CrmPicklistSelect } from "./picklist-select.js";
35
+ /**
36
+ * Salesforce's Opportunity Contact Roles on a deal's page (AGL-3521): the
37
+ * people on the deal, the part each plays, and which one is Primary.
38
+ *
39
+ * Every edit is one client-direct write of the whole list beside the
40
+ * `contactId` its Primary names — the field every reader that came before
41
+ * roles still reads — and the list fields a contact's page finds the deal
42
+ * by. A role is one of the org's `opportunityContactRole` values, kept on
43
+ * the Deals tab of Fields; a contact keeps the role it holds even once that
44
+ * value is deactivated. Adding opens a dialog rather than a row of fields
45
+ * above the list.
46
+ */ export function DealContactRolesCard(props) {
47
+ var _ref;
48
+ var _scope_consentGroup;
49
+ const { deal, hostId, org, routes, fromCache, unreadable } = props;
50
+ const firestore = useFirestore();
51
+ const { enqueueSnackbar } = useSnackbar();
52
+ const scope = useCrmScope({
53
+ hostId,
54
+ org
55
+ });
56
+ const groupId = (_ref = (_scope_consentGroup = scope.consentGroup) == null ? void 0 : _scope_consentGroup.groupId) != null ? _ref : null;
57
+ const roles = useMemo(()=>dealContactRolesOf(deal), [
58
+ deal
59
+ ]);
60
+ const roleList = useCrmPicklist('opportunityContactRole', scope.orgId);
61
+ const nameOf = useCrmRecordNames({
62
+ orgId: scope.orgId,
63
+ groupId,
64
+ org: org != null ? org : null,
65
+ records: roles.map((row)=>({
66
+ kind: 'contact',
67
+ id: row.contactId
68
+ }))
69
+ });
70
+ const [busy, setBusy] = useState(false);
71
+ const [adding, setAdding] = useState(false);
72
+ /** The one write: the list, its Primary as `contactId`, and the list fields. */ const save = useCallback(async (next, done)=>{
73
+ var _verdict_contactId;
74
+ if (!scope.orgId) return false;
75
+ const verdict = dealContactRolesSave(deal, next, roleList.picklist);
76
+ if (verdict.ok === false) {
77
+ enqueueSnackbar(verdict.error, {
78
+ variant: 'warning',
79
+ persist: false
80
+ });
81
+ return false;
82
+ }
83
+ const primaryName = verdict.contactId ? nameOf('contact', verdict.contactId) : undefined;
84
+ const patch = _extends({
85
+ contactRoles: verdict.contactRoles,
86
+ contactId: (_verdict_contactId = verdict.contactId) != null ? _verdict_contactId : deleteField()
87
+ }, verdict.primaryChanged ? {
88
+ contactName: primaryName || deleteField()
89
+ } : {});
90
+ setBusy(true);
91
+ try {
92
+ const written = await writeGuardedBySeed({
93
+ subject: 'deal',
94
+ unreadable,
95
+ fromCache
96
+ }, async ()=>{
97
+ await updateDoc(doc(firestore, 'orgs', scope.orgId, CRM_COLLECTIONS.deals, deal.$id), _extends({}, patch, crmClientListFields('deals', deal, patch, CRM_DEAL_CONTACT_ROLE_LIST_FIELDS), {
98
+ updatedAt: new Date()
99
+ }));
100
+ });
101
+ if (!written.ok) {
102
+ enqueueSnackbar(written.message, {
103
+ variant: 'warning',
104
+ persist: false
105
+ });
106
+ return false;
107
+ }
108
+ enqueueSnackbar(done, {
109
+ variant: 'success',
110
+ persist: false
111
+ });
112
+ return true;
113
+ } catch (error) {
114
+ console.error(error);
115
+ enqueueSnackbar('An error has occurred', {
116
+ variant: 'error',
117
+ allowDuplicate: true
118
+ });
119
+ return false;
120
+ } finally{
121
+ setBusy(false);
122
+ }
123
+ }, [
124
+ scope.orgId,
125
+ deal,
126
+ roleList.picklist,
127
+ nameOf,
128
+ unreadable,
129
+ fromCache,
130
+ firestore,
131
+ enqueueSnackbar
132
+ ]);
133
+ const addButton = (variant)=>/*#__PURE__*/ _jsx(Button, {
134
+ size: "small",
135
+ variant: variant,
136
+ startIcon: /*#__PURE__*/ _jsx(MdiIcon, {
137
+ path: mdiAccountPlusOutline.path,
138
+ size: 0.8
139
+ }),
140
+ disabled: busy || !scope.orgId,
141
+ onClick: ()=>setAdding(true),
142
+ children: 'Add contact'
143
+ });
144
+ return /*#__PURE__*/ _jsxs(_Fragment, {
145
+ children: [
146
+ /*#__PURE__*/ _jsx(CardDisplay, {
147
+ header: 'Contact roles',
148
+ help: pluginDocsHelp('deals', {
149
+ anchor: '#contact-roles'
150
+ }),
151
+ HeaderProps: {
152
+ action: addButton('text')
153
+ },
154
+ contentGutterX: true,
155
+ contentGutterY: true,
156
+ children: roles.length === 0 ? /*#__PURE__*/ _jsx(EmptyStateComponent, {
157
+ compact: true,
158
+ label: 'No contacts on this deal',
159
+ description: 'Name the people on the deal and the part each plays — one of them Primary.',
160
+ action: addButton('contained')
161
+ }) : /*#__PURE__*/ _jsx(Stack, {
162
+ spacing: 1.5,
163
+ children: roles.map((row)=>{
164
+ var _row_role;
165
+ const name = nameOf('contact', row.contactId) || row.contactId;
166
+ return /*#__PURE__*/ _jsxs(Stack, {
167
+ direction: {
168
+ xs: 'column',
169
+ sm: 'row'
170
+ },
171
+ spacing: 1,
172
+ sx: {
173
+ alignItems: {
174
+ sm: 'center'
175
+ }
176
+ },
177
+ children: [
178
+ /*#__PURE__*/ _jsxs(Stack, {
179
+ direction: "row",
180
+ spacing: 1,
181
+ sx: {
182
+ flex: 1,
183
+ minWidth: 0,
184
+ alignItems: 'center'
185
+ },
186
+ children: [
187
+ /*#__PURE__*/ _jsx(Typography, {
188
+ variant: "body2",
189
+ noWrap: true,
190
+ children: /*#__PURE__*/ _jsx(AppLink, {
191
+ href: routes.contact(row.contactId),
192
+ children: name
193
+ })
194
+ }),
195
+ row.primary ? /*#__PURE__*/ _jsx(Chip, {
196
+ size: "small",
197
+ color: "primary",
198
+ label: "Primary"
199
+ }) : null
200
+ ]
201
+ }),
202
+ /*#__PURE__*/ _jsx(Box, {
203
+ sx: {
204
+ width: {
205
+ xs: '100%',
206
+ sm: 220
207
+ }
208
+ },
209
+ children: /*#__PURE__*/ _jsx(CrmPicklistSelect, {
210
+ picklistId: "opportunityContactRole",
211
+ picklist: roleList.picklist,
212
+ label: "Role",
213
+ value: (_row_role = row.role) != null ? _row_role : '',
214
+ stored: row.role,
215
+ disabled: busy,
216
+ onChange: (role)=>void save(dealContactRolesWithRole(roles, row.contactId, role), 'Role saved')
217
+ })
218
+ }),
219
+ /*#__PURE__*/ _jsxs(Stack, {
220
+ direction: "row",
221
+ spacing: 0.5,
222
+ sx: {
223
+ alignItems: 'center'
224
+ },
225
+ children: [
226
+ row.primary ? null : /*#__PURE__*/ _jsx(Button, {
227
+ size: "small",
228
+ disabled: busy,
229
+ onClick: ()=>void save(dealContactRolesWithPrimary(roles, row.contactId), 'Primary contact set'),
230
+ children: 'Make primary'
231
+ }),
232
+ /*#__PURE__*/ _jsx(Tooltip, {
233
+ title: `Remove ${name} from this deal`,
234
+ children: /*#__PURE__*/ _jsx("span", {
235
+ children: /*#__PURE__*/ _jsx(IconButton, {
236
+ size: "small",
237
+ "aria-label": `Remove ${name} from this deal`,
238
+ disabled: busy,
239
+ onClick: ()=>void save(dealContactRolesWithout(roles, row.contactId), 'Contact removed'),
240
+ children: /*#__PURE__*/ _jsx(MdiIcon, {
241
+ path: mdiAccountRemoveOutline.path,
242
+ size: 0.8
243
+ })
244
+ })
245
+ })
246
+ })
247
+ ]
248
+ })
249
+ ]
250
+ }, row.contactId);
251
+ })
252
+ })
253
+ }),
254
+ /*#__PURE__*/ _jsx(AddContactRoleDialog, {
255
+ open: adding,
256
+ busy: busy,
257
+ roles: roles,
258
+ hostId: hostId,
259
+ org: org,
260
+ picklist: roleList.picklist,
261
+ onClose: ()=>setAdding(false),
262
+ onAdd: async (added)=>{
263
+ const ok = await save(dealContactRolesAdded(roles, added), 'Contact added');
264
+ if (ok) setAdding(false);
265
+ return ok;
266
+ }
267
+ })
268
+ ]
269
+ });
270
+ }
271
+ DealContactRolesCard.displayName = 'DealContactRolesCard';
272
+ /** Pick a contact, the part they play, and whether they are the Primary. */ function AddContactRoleDialog(props) {
273
+ var _ref;
274
+ var _scope_consentGroup;
275
+ const { open, busy, roles, hostId, org, picklist, onClose, onAdd } = props;
276
+ const scope = useCrmScope({
277
+ hostId,
278
+ org
279
+ });
280
+ const [contactId, setContactId] = useState(null);
281
+ const [role, setRole] = useState('');
282
+ // The first contact on a deal is always its Primary; later ones when ticked.
283
+ const [primary, setPrimary] = useState(false);
284
+ const problem = contactId ? dealContactRoleAddProblem(roles, contactId) : null;
285
+ const reset = ()=>{
286
+ setContactId(null);
287
+ setRole('');
288
+ setPrimary(false);
289
+ };
290
+ const close = ()=>{
291
+ reset();
292
+ onClose();
293
+ };
294
+ return /*#__PURE__*/ _jsxs(Dialog, {
295
+ open: open,
296
+ onClose: busy ? undefined : close,
297
+ fullWidth: true,
298
+ maxWidth: "xs",
299
+ children: [
300
+ /*#__PURE__*/ _jsx(DialogTitle, {
301
+ children: 'Add a contact to this deal'
302
+ }),
303
+ /*#__PURE__*/ _jsx(DialogContent, {
304
+ children: /*#__PURE__*/ _jsxs(Stack, {
305
+ spacing: 2,
306
+ sx: {
307
+ pt: 1
308
+ },
309
+ children: [
310
+ /*#__PURE__*/ _jsx(CrmRecordPicker, {
311
+ kind: "contact",
312
+ scope: scope.scope,
313
+ readTokens: scope.visibleTo,
314
+ groupId: (_ref = (_scope_consentGroup = scope.consentGroup) == null ? void 0 : _scope_consentGroup.groupId) != null ? _ref : null,
315
+ org: org != null ? org : null,
316
+ value: contactId,
317
+ onChange: setContactId,
318
+ disabled: busy,
319
+ helperText: problem != null ? problem : undefined
320
+ }),
321
+ /*#__PURE__*/ _jsx(CrmPicklistSelect, {
322
+ picklistId: "opportunityContactRole",
323
+ picklist: picklist,
324
+ label: "Role",
325
+ value: role,
326
+ onChange: setRole,
327
+ disabled: busy
328
+ }),
329
+ /*#__PURE__*/ _jsx(FormControlLabel, {
330
+ control: /*#__PURE__*/ _jsx(Checkbox, {
331
+ checked: primary || roles.length === 0,
332
+ disabled: busy || roles.length === 0,
333
+ onChange: (event)=>setPrimary(event.target.checked)
334
+ }),
335
+ label: "Primary contact"
336
+ })
337
+ ]
338
+ })
339
+ }),
340
+ /*#__PURE__*/ _jsxs(DialogActions, {
341
+ children: [
342
+ /*#__PURE__*/ _jsx(Button, {
343
+ onClick: close,
344
+ disabled: busy,
345
+ children: 'Cancel'
346
+ }),
347
+ /*#__PURE__*/ _jsx(Button, {
348
+ variant: "contained",
349
+ disabled: busy || !contactId || Boolean(problem),
350
+ onClick: async ()=>{
351
+ if (!contactId) return;
352
+ const added = await onAdd({
353
+ contactId,
354
+ role: role || undefined,
355
+ primary: primary || roles.length === 0
356
+ });
357
+ if (added) reset();
358
+ },
359
+ children: 'Add'
360
+ })
361
+ ]
362
+ })
363
+ ]
364
+ });
365
+ }
366
+ export default DealContactRolesCard;
367
+
368
+ //# sourceMappingURL=deal-contact-roles-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/deal-contact-roles-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\n'use client'\n\nimport {\n CRM_COLLECTIONS,\n type CrmDealContactRole,\n dealContactRolesOf,\n dealContactRolesWithout,\n dealContactRolesWithPrimary,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport { mdiAccountPlusOutline, mdiAccountRemoveOutline } from '@aglyn/shared-data-mdi'\nimport { AppLink, CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport EmptyStateComponent from '@aglyn/shared-ui-jsx/components/empty-state.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useFirestore, writeGuardedBySeed } from '@aglyn/tenant-feature-instance'\nimport {\n Box,\n Button,\n Checkbox,\n Chip,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n FormControlLabel,\n IconButton,\n Stack,\n Tooltip,\n Typography,\n} from '@mui/material'\nimport { deleteField, doc, updateDoc } from 'firebase/firestore'\nimport { useCallback, useMemo, useState } from 'react'\nimport { useCrmPicklist } from '../hooks/use-crm-picklist'\nimport { useCrmRecordNames } from '../hooks/use-crm-record-names'\nimport { type CrmOrgDoc, useCrmScope } from '../hooks/use-crm-scope'\nimport { CRM_DEAL_CONTACT_ROLE_LIST_FIELDS, crmClientListFields } from '../model/crm-list-query'\nimport type { CrmRoutes } from '../model/crm-routes'\nimport type { DealDoc } from '../model/deal-board-model'\nimport {\n dealContactRoleAddProblem,\n dealContactRolesAdded,\n dealContactRolesSave,\n dealContactRolesWithRole,\n} from '../model/deal-contact-roles'\nimport CrmRecordPicker from './crm-record-picker'\nimport { CrmPicklistSelect } from './picklist-select'\n\nexport interface DealContactRolesCardProps {\n deal: DealDoc\n /** The site the page is read under, or `null` at the organization level. */\n hostId: string | null\n org: CrmOrgDoc\n routes: CrmRoutes\n /** The listener's verdict on the deal, for the stale-seed guard. */\n fromCache: boolean\n unreadable: boolean\n}\n\n/**\n * Salesforce's Opportunity Contact Roles on a deal's page (AGL-3521): the\n * people on the deal, the part each plays, and which one is Primary.\n *\n * Every edit is one client-direct write of the whole list beside the\n * `contactId` its Primary names — the field every reader that came before\n * roles still reads — and the list fields a contact's page finds the deal\n * by. A role is one of the org's `opportunityContactRole` values, kept on\n * the Deals tab of Fields; a contact keeps the role it holds even once that\n * value is deactivated. Adding opens a dialog rather than a row of fields\n * above the list.\n */\nexport function DealContactRolesCard(props: DealContactRolesCardProps) {\n const { deal, hostId, org, routes, fromCache, unreadable } = props\n const firestore = useFirestore()\n const { enqueueSnackbar } = useSnackbar()\n const scope = useCrmScope({ hostId, org })\n const groupId = scope.consentGroup?.groupId ?? null\n const roles = useMemo(() => dealContactRolesOf(deal), [deal])\n const roleList = useCrmPicklist('opportunityContactRole', scope.orgId)\n const nameOf = useCrmRecordNames({\n orgId: scope.orgId,\n groupId,\n org: (org ?? null) as Record<string, unknown> | null,\n records: roles.map((row) => ({ kind: 'contact' as const, id: row.contactId })),\n })\n const [busy, setBusy] = useState(false)\n const [adding, setAdding] = useState(false)\n\n /** The one write: the list, its Primary as `contactId`, and the list fields. */\n const save = useCallback(\n async (next: CrmDealContactRole[], done: string) => {\n if (!scope.orgId) return false\n const verdict = dealContactRolesSave(deal, next, roleList.picklist)\n if (verdict.ok === false) {\n enqueueSnackbar(verdict.error, { variant: 'warning', persist: false })\n return false\n }\n const primaryName = verdict.contactId ? nameOf('contact', verdict.contactId) : undefined\n const patch: Record<string, unknown> = {\n contactRoles: verdict.contactRoles,\n contactId: verdict.contactId ?? deleteField(),\n // The name the drawer copies beside `contactId`, moved with the Primary.\n ...(verdict.primaryChanged ? { contactName: primaryName || deleteField() } : {}),\n }\n setBusy(true)\n try {\n const written = await writeGuardedBySeed(\n { subject: 'deal', unreadable, fromCache },\n async () => {\n await updateDoc(doc(firestore, 'orgs', scope.orgId as string, CRM_COLLECTIONS.deals, deal.$id), {\n ...patch,\n ...crmClientListFields(\n 'deals',\n deal as unknown as Record<string, unknown>,\n patch,\n CRM_DEAL_CONTACT_ROLE_LIST_FIELDS,\n ),\n updatedAt: new Date(),\n })\n },\n )\n if (!written.ok) {\n enqueueSnackbar(written.message, { variant: 'warning', persist: false })\n return false\n }\n enqueueSnackbar(done, { variant: 'success', persist: false })\n return true\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', { variant: 'error', allowDuplicate: true })\n return false\n } finally {\n setBusy(false)\n }\n },\n [scope.orgId, deal, roleList.picklist, nameOf, unreadable, fromCache, firestore, enqueueSnackbar],\n )\n\n const addButton = (variant: 'text' | 'contained') => (\n <Button\n size=\"small\"\n variant={variant}\n startIcon={<MdiIcon path={mdiAccountPlusOutline.path} size={0.8} />}\n disabled={busy || !scope.orgId}\n onClick={() => setAdding(true)}\n >\n {'Add contact'}\n </Button>\n )\n\n return (\n <>\n <CardDisplay\n header={'Contact roles'}\n help={pluginDocsHelp('deals', { anchor: '#contact-roles' })}\n HeaderProps={{ action: addButton('text') }}\n contentGutterX\n contentGutterY\n >\n {roles.length === 0 ? (\n <EmptyStateComponent\n compact\n label={'No contacts on this deal'}\n description={'Name the people on the deal and the part each plays — one of them Primary.'}\n action={addButton('contained')}\n />\n ) : (\n <Stack spacing={1.5}>\n {roles.map((row) => {\n const name = nameOf('contact', row.contactId) || row.contactId\n return (\n <Stack\n key={row.contactId}\n direction={{ xs: 'column', sm: 'row' }}\n spacing={1}\n sx={{ alignItems: { sm: 'center' } }}\n >\n <Stack direction=\"row\" spacing={1} sx={{ flex: 1, minWidth: 0, alignItems: 'center' }}>\n <Typography variant=\"body2\" noWrap>\n <AppLink href={routes.contact(row.contactId)}>{name}</AppLink>\n </Typography>\n {row.primary ? <Chip size=\"small\" color=\"primary\" label=\"Primary\" /> : null}\n </Stack>\n <Box sx={{ width: { xs: '100%', sm: 220 } }}>\n <CrmPicklistSelect\n picklistId=\"opportunityContactRole\"\n picklist={roleList.picklist}\n label=\"Role\"\n value={row.role ?? ''}\n stored={row.role}\n disabled={busy}\n onChange={(role) =>\n void save(dealContactRolesWithRole(roles, row.contactId, role), 'Role saved')\n }\n />\n </Box>\n <Stack direction=\"row\" spacing={0.5} sx={{ alignItems: 'center' }}>\n {row.primary ? null : (\n <Button\n size=\"small\"\n disabled={busy}\n onClick={() =>\n void save(dealContactRolesWithPrimary(roles, row.contactId), 'Primary contact set')\n }\n >\n {'Make primary'}\n </Button>\n )}\n <Tooltip title={`Remove ${name} from this deal`}>\n <span>\n <IconButton\n size=\"small\"\n aria-label={`Remove ${name} from this deal`}\n disabled={busy}\n onClick={() =>\n void save(dealContactRolesWithout(roles, row.contactId), 'Contact removed')\n }\n >\n <MdiIcon path={mdiAccountRemoveOutline.path} size={0.8} />\n </IconButton>\n </span>\n </Tooltip>\n </Stack>\n </Stack>\n )\n })}\n </Stack>\n )}\n </CardDisplay>\n <AddContactRoleDialog\n open={adding}\n busy={busy}\n roles={roles}\n hostId={hostId}\n org={org}\n picklist={roleList.picklist}\n onClose={() => setAdding(false)}\n onAdd={async (added) => {\n const ok = await save(dealContactRolesAdded(roles, added), 'Contact added')\n if (ok) setAdding(false)\n return ok\n }}\n />\n </>\n )\n}\nDealContactRolesCard.displayName = 'DealContactRolesCard'\n\ninterface AddContactRoleDialogProps {\n open: boolean\n busy: boolean\n roles: readonly CrmDealContactRole[]\n hostId: string | null\n org: CrmOrgDoc\n picklist: ReturnType<typeof useCrmPicklist>['picklist']\n onClose: () => void\n /** Answers whether the contact was added — the dialog keeps its picks when not. */\n onAdd: (added: { contactId: string; role?: string; primary: boolean }) => Promise<boolean>\n}\n\n/** Pick a contact, the part they play, and whether they are the Primary. */\nfunction AddContactRoleDialog(props: AddContactRoleDialogProps) {\n const { open, busy, roles, hostId, org, picklist, onClose, onAdd } = props\n const scope = useCrmScope({ hostId, org })\n const [contactId, setContactId] = useState<string | null>(null)\n const [role, setRole] = useState('')\n // The first contact on a deal is always its Primary; later ones when ticked.\n const [primary, setPrimary] = useState(false)\n const problem = contactId ? dealContactRoleAddProblem(roles, contactId) : null\n\n const reset = () => {\n setContactId(null)\n setRole('')\n setPrimary(false)\n }\n const close = () => {\n reset()\n onClose()\n }\n\n return (\n <Dialog open={open} onClose={busy ? undefined : close} fullWidth maxWidth=\"xs\">\n <DialogTitle>{'Add a contact to this deal'}</DialogTitle>\n <DialogContent>\n <Stack spacing={2} sx={{ pt: 1 }}>\n <CrmRecordPicker\n kind=\"contact\"\n scope={scope.scope}\n readTokens={scope.visibleTo}\n groupId={scope.consentGroup?.groupId ?? null}\n org={(org ?? null) as Record<string, unknown> | null}\n value={contactId}\n onChange={setContactId}\n disabled={busy}\n helperText={problem ?? undefined}\n />\n <CrmPicklistSelect\n picklistId=\"opportunityContactRole\"\n picklist={picklist}\n label=\"Role\"\n value={role}\n onChange={setRole}\n disabled={busy}\n />\n <FormControlLabel\n control={\n <Checkbox\n checked={primary || roles.length === 0}\n disabled={busy || roles.length === 0}\n onChange={(event) => setPrimary(event.target.checked)}\n />\n }\n label=\"Primary contact\"\n />\n </Stack>\n </DialogContent>\n <DialogActions>\n <Button onClick={close} disabled={busy}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n disabled={busy || !contactId || Boolean(problem)}\n onClick={async () => {\n if (!contactId) return\n const added = await onAdd({\n contactId,\n role: role || undefined,\n primary: primary || roles.length === 0,\n })\n if (added) reset()\n }}\n >\n {'Add'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\n\nexport default DealContactRolesCard\n"],"names":["CRM_COLLECTIONS","dealContactRolesOf","dealContactRolesWithout","dealContactRolesWithPrimary","pluginDocsHelp","mdiAccountPlusOutline","mdiAccountRemoveOutline","AppLink","CardDisplay","MdiIcon","EmptyStateComponent","useSnackbar","useFirestore","writeGuardedBySeed","Box","Button","Checkbox","Chip","Dialog","DialogActions","DialogContent","DialogTitle","FormControlLabel","IconButton","Stack","Tooltip","Typography","deleteField","doc","updateDoc","useCallback","useMemo","useState","useCrmPicklist","useCrmRecordNames","useCrmScope","CRM_DEAL_CONTACT_ROLE_LIST_FIELDS","crmClientListFields","dealContactRoleAddProblem","dealContactRolesAdded","dealContactRolesSave","dealContactRolesWithRole","CrmRecordPicker","CrmPicklistSelect","DealContactRolesCard","props","scope","deal","hostId","org","routes","fromCache","unreadable","firestore","enqueueSnackbar","groupId","consentGroup","roles","roleList","orgId","nameOf","records","map","row","kind","id","contactId","busy","setBusy","adding","setAdding","save","next","done","verdict","picklist","ok","error","variant","persist","primaryName","undefined","patch","contactRoles","primaryChanged","contactName","written","subject","deals","$id","updatedAt","Date","message","console","allowDuplicate","addButton","size","startIcon","path","disabled","onClick","header","help","anchor","HeaderProps","action","contentGutterX","contentGutterY","length","compact","label","description","spacing","name","direction","xs","sm","sx","alignItems","flex","minWidth","noWrap","href","contact","primary","color","width","picklistId","value","role","stored","onChange","title","span","aria-label","AddContactRoleDialog","open","onClose","onAdd","added","displayName","setContactId","setRole","setPrimary","problem","reset","close","fullWidth","maxWidth","pt","readTokens","visibleTo","helperText","control","checked","event","target","Boolean"],"mappings":"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"}
@@ -3,8 +3,9 @@ import { type CrmDetailPageProps } from '../model/crm-routes';
3
3
  * `/crm/deals/{dealId}` — one deal (AGL-2598).
4
4
  *
5
5
  * The record behind a card: its stage and the controls that move it, what
6
- * it is worth and who it is with, the products behind the amount
7
- * (AGL-2620), and the tasks and activity filed against it. One live
6
+ * it is worth and who it is with — every contact on it and the part each
7
+ * plays (AGL-3521) — the products behind the amount (AGL-2620), and the
8
+ * tasks and activity filed against it. One live
8
9
  * document read; the pipeline and the roster are the same bounded reads
9
10
  * the board makes. Editing opens the same drawer the board creates with,
10
11
  * and deleting is the one destructive act here — confirmed, then a
@@ -40,8 +40,10 @@ import { RecordActivityCard } from "./record-activity-card.js";
40
40
  import { CrmShareChipView, RecordSharingCard } from "./record-sharing-card.js";
41
41
  import { crmShareChipFor } from "../model/crm-sharing.js";
42
42
  import { CrmSendEmailButton } from "./crm-send-email-button.js";
43
+ import { DealContactRolesCard } from "./deal-contact-roles-card.js";
43
44
  import { DealEditDrawer } from "./deal-edit-drawer.js";
44
45
  import { DealProductsCard } from "./deal-products-card.js";
46
+ import { useCrmCampaigns } from "../hooks/use-crm-campaigns.js";
45
47
  import { DealPropertiesCard } from "./deal-properties-card.js";
46
48
  import { DealStageCard } from "./deal-stage-card.js";
47
49
  import RecordFilesCard from "./record-files-card.js";
@@ -50,16 +52,17 @@ import { RecordTasksCard } from "./record-tasks-card.js";
50
52
  * `/crm/deals/{dealId}` — one deal (AGL-2598).
51
53
  *
52
54
  * The record behind a card: its stage and the controls that move it, what
53
- * it is worth and who it is with, the products behind the amount
54
- * (AGL-2620), and the tasks and activity filed against it. One live
55
+ * it is worth and who it is with — every contact on it and the part each
56
+ * plays (AGL-3521) — the products behind the amount (AGL-2620), and the
57
+ * tasks and activity filed against it. One live
55
58
  * document read; the pipeline and the roster are the same bounded reads
56
59
  * the board makes. Editing opens the same drawer the board creates with,
57
60
  * and deleting is the one destructive act here — confirmed, then a
58
61
  * client-direct delete the rules allow the same people who could have
59
62
  * created it.
60
63
  */ export function DealDetailPage(props) {
61
- var _ref, _ref1, _ref2, _ref3, _DEAL_STATUS_LABELS_deal_status, _ref4, _ref5;
62
- var _scope_consentGroup, _scope_consentGroup1;
64
+ var _ref, _ref1, _ref2, _ref3, _DEAL_STATUS_LABELS_deal_status, _ref4, _ref5, _ref6;
65
+ var _scope_consentGroup, _campaigns_options_find, _scope_consentGroup1;
63
66
  const { id, basePath, hostId, org } = props;
64
67
  const routes = crmRoutes(basePath);
65
68
  const router = useRouter();
@@ -88,6 +91,13 @@ import { RecordTasksCard } from "./record-tasks-card.js";
88
91
  const [deleting, setDeleting] = useState(false);
89
92
  // The org's deal fields (AGL-2661), for the properties card's rows.
90
93
  const dealFields = useContactFieldDefinitions(scope.orgId, 'deal');
94
+ // The deal's campaign by name (AGL-3516), read only for a deal that names one.
95
+ const campaigns = useCrmCampaigns({
96
+ hostId,
97
+ orgId: scope.orgId
98
+ }, {
99
+ enabled: Boolean(deal == null ? void 0 : deal.campaignId)
100
+ });
91
101
  const notFound = scope.ready && (!scope.orgId || status !== 'loading' && !deal);
92
102
  const handleDelete = useCallback(async ()=>{
93
103
  if (!deal || !scope.orgId) return;
@@ -269,7 +279,8 @@ import { RecordTasksCard } from "./record-tasks-card.js";
269
279
  pipeline: pipeline,
270
280
  ownerLabel: roster.nameOf(deal.ownerUid),
271
281
  routes: routes,
272
- customFields: dealFields.active
282
+ customFields: dealFields.active,
283
+ campaignName: deal.campaignId ? (_ref5 = (_campaigns_options_find = campaigns.options.find((option)=>option.value === deal.campaignId)) == null ? void 0 : _campaigns_options_find.label) != null ? _ref5 : deal.campaignId : undefined
273
284
  })
274
285
  }),
275
286
  /*#__PURE__*/ _jsx(Stack, {
@@ -286,10 +297,18 @@ import { RecordTasksCard } from "./record-tasks-card.js";
286
297
  })
287
298
  ]
288
299
  }),
300
+ /*#__PURE__*/ _jsx(DealContactRolesCard, {
301
+ deal: deal,
302
+ hostId: hostId,
303
+ org: org,
304
+ routes: routes,
305
+ fromCache: fromCache,
306
+ unreadable: status === 'error'
307
+ }),
289
308
  scope.orgId ? /*#__PURE__*/ _jsx(DealProductsCard, {
290
309
  deal: deal,
291
310
  orgId: scope.orgId,
292
- hostId: (_ref5 = hostId != null ? hostId : deal.hostId) != null ? _ref5 : null,
311
+ hostId: (_ref6 = hostId != null ? hostId : deal.hostId) != null ? _ref6 : null,
293
312
  org: org,
294
313
  fromCache: fromCache,
295
314
  unreadable: status === 'error'
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/deal-detail-page.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 { CRM_COLLECTIONS, dealStageById, pluginDocsHelp } from '@aglyn/aglyn'\nimport { mdiDeleteOutline, mdiPencilOutline } from '@aglyn/shared-data-mdi'\nimport { MdiIcon, useConfirmationContext } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useFirestore } from '@aglyn/tenant-feature-instance'\nimport { Button, Stack, Typography } from '@mui/material'\nimport { deleteDoc, doc } from 'firebase/firestore'\nimport { useRouter } from 'next/navigation'\nimport { useCallback, useMemo, useState } from 'react'\nimport { useContactFieldDefinitions } from '../hooks/use-contact-field-definitions'\nimport { useCrmActivityLogger } from '../hooks/use-crm-activity-logger'\nimport { CrmCreateSiteDefault } from '../hooks/use-crm-org-mount'\nimport { useCrmScope } from '../hooks/use-crm-scope'\nimport { useDealStageApi } from '../hooks/use-deal-stage-api'\nimport { useDeal } from '../hooks/use-deals'\nimport { useOrgMemberDirectory } from '../hooks/use-org-member-directory'\nimport { usePipeline } from '../hooks/use-pipeline'\nimport { type CrmDetailPageProps, crmRoutes } from '../model/crm-routes'\nimport { DEAL_STATUS_LABELS, formatMoney } from '../model/deal-board-model'\nimport { CrmRecordChip, CrmRecordHeader } from './crm-record-header'\nimport { CrmRecordInsightsZone } from './crm-record-insights-zone'\nimport { RecordActivityCard } from './record-activity-card'\nimport { CrmShareChipView, RecordSharingCard } from './record-sharing-card'\nimport { crmShareChipFor } from '../model/crm-sharing'\nimport { CrmSendEmailButton } from './crm-send-email-button'\nimport { DealEditDrawer } from './deal-edit-drawer'\nimport { DealProductsCard } from './deal-products-card'\nimport { DealPropertiesCard } from './deal-properties-card'\nimport { DealStageCard } from './deal-stage-card'\nimport RecordFilesCard from './record-files-card'\nimport { RecordTasksCard } from './record-tasks-card'\n\n/**\n * `/crm/deals/{dealId}` — one deal (AGL-2598).\n *\n * The record behind a card: its stage and the controls that move it, what\n * it is worth and who it is with, the products behind the amount\n * (AGL-2620), and the tasks and activity filed against it. One live\n * document read; the pipeline and the roster are the same bounded reads\n * the board makes. Editing opens the same drawer the board creates with,\n * and deleting is the one destructive act here — confirmed, then a\n * client-direct delete the rules allow the same people who could have\n * created it.\n */\nexport function DealDetailPage(props: CrmDetailPageProps) {\n const { id, basePath, hostId, org } = props\n const routes = crmRoutes(basePath)\n const router = useRouter()\n const firestore = useFirestore()\n const { enqueueSnackbar } = useSnackbar()\n const { confirm } = useConfirmationContext()\n const scope = useCrmScope({ hostId, org })\n const { data: deal, status, fromCache } = useDeal(scope.orgId, id)\n // The feed the act is logged in, decided by the level it was performed\n // at (AGL-2738): this site's under a site, the organization's at the org\n // hub, where a client-direct append to the deal's own site would face a\n // gate the record write never had to pass.\n const logActivity = useCrmActivityLogger(hostId)\n const pipelineState = usePipeline(scope.orgId, {\n hostId,\n org: (org ?? null) as Record<string, unknown> | null,\n })\n const pipeline = pipelineState.pipelineById(deal?.pipelineId)\n const roster = useOrgMemberDirectory(scope.orgId)\n const api = useDealStageApi(hostId)\n const nowMs = useMemo(() => Date.now(), [])\n const [editing, setEditing] = useState(false)\n const [deleting, setDeleting] = useState(false)\n // The org's deal fields (AGL-2661), for the properties card's rows.\n const dealFields = useContactFieldDefinitions(scope.orgId, 'deal')\n\n const notFound = scope.ready && (!scope.orgId || (status !== 'loading' && !deal))\n\n const handleDelete = useCallback(async () => {\n if (!deal || !scope.orgId) return\n const agreed = await confirm({\n title: 'Delete this deal?',\n description:\n `\"${deal.title}\" is removed from the pipeline along with its notes. ` +\n 'The contact and the company it names are not touched.',\n confirmationText: 'Delete deal',\n confirmationButtonProps: { color: 'error' },\n })\n .then(() => true)\n .catch(() => false)\n if (!agreed) return\n setDeleting(true)\n try {\n await deleteDoc(doc(firestore, 'orgs', scope.orgId, CRM_COLLECTIONS.deals, deal.$id))\n // Setup → Activity shows CRM work (AGL-2622): the deal is org data,\n // but the act happened in this site's console and belongs in its feed.\n logActivity('Deleted deal', { type: 'deal', id: deal.$id, name: deal.title })\n enqueueSnackbar('Deal deleted', { variant: 'success', persist: false })\n router.push(routes.section('deals'))\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', { variant: 'error', allowDuplicate: true })\n setDeleting(false)\n }\n }, [deal, scope.orgId, confirm, firestore, logActivity, enqueueSnackbar, router, routes])\n\n const stage = deal ? dealStageById(pipeline, deal.stageId) : undefined\n\n return (\n // A create opened from this page — a task, an activity — files under\n // the deal's own site unless the reader says otherwise (AGL-2630).\n <CrmCreateSiteDefault hostId={deal?.hostId ?? null}>\n <Stack spacing={2}>\n <CrmRecordHeader\n kind=\"Deal\"\n title={deal?.title}\n subtitle={\n deal\n ? [pipeline?.name, stage?.name ?? deal.stageId].filter(Boolean).join(' · ')\n : undefined\n }\n help={pluginDocsHelp('deals', { anchor: '#a-deals-page' })}\n backHref={routes.section('deals')}\n backLabel=\"Back to deals\"\n loading={!deal && !notFound}\n // The booking door (AGL-2660): the deal's own site's services.\n booking={\n deal\n ? { hostId: hostId ?? deal.hostId ?? null, org, kind: 'deal', recordId: deal.$id }\n : undefined\n }\n actions={\n deal ? (\n <>\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiPencilOutline.path} size={0.8} />}\n onClick={() => setEditing(true)}\n >\n {'Edit'}\n </Button>\n <CrmSendEmailButton\n hostId={hostId ?? deal.hostId ?? null}\n org={org}\n dealId={deal.$id}\n contactId={deal.contactId}\n name={deal.contactName}\n />\n </>\n ) : null\n }\n menuItems={\n deal\n ? [\n {\n key: 'delete',\n label: 'Delete deal',\n icon: <MdiIcon path={mdiDeleteOutline.path} size={0.8} />,\n destructive: true,\n disabled: deleting,\n disabledReason: 'The deal is being deleted',\n onClick: () => void handleDelete(),\n },\n ]\n : undefined\n }\n chips={\n deal ? (\n <>\n <CrmRecordChip\n label=\"Status\"\n value={DEAL_STATUS_LABELS[deal.status] ?? deal.status}\n color={deal.status === 'won' ? 'success' : deal.status === 'lost' ? 'default' : 'primary'}\n />\n <CrmRecordChip\n label=\"Amount\"\n value={\n typeof deal.amountCents === 'number'\n ? formatMoney(deal.amountCents, deal.currency)\n : undefined\n }\n />\n <CrmRecordChip label=\"Owner\" value={roster.nameOf(deal.ownerUid) || undefined} />\n {/* Seen here only through a share (AGL-3336). */}\n <CrmShareChipView\n chip={crmShareChipFor(\n deal as unknown as Record<string, unknown>,\n scope.consentGroup?.hostIds ?? [],\n )}\n org={org}\n />\n </>\n ) : null\n }\n >\n {notFound ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'This deal does not exist, or is not visible to this site.'}\n </Typography>\n ) : null}\n </CrmRecordHeader>\n {deal ? (\n <>\n {/* What an assistant proposes about the deal, its stage included (AGL-2917). */}\n <CrmRecordInsightsZone\n hostId={hostId}\n org={org as Record<string, unknown> | undefined}\n kind=\"deal\"\n recordId={deal.$id}\n name={deal.title}\n taskLink={{ dealId: deal.$id }}\n deal={{ pipeline, ref: deal, stageId: deal.stageId, status: deal.status, api }}\n />\n <DealStageCard deal={deal} pipeline={pipeline} api={api} nowMs={nowMs} />\n <Stack direction={{ xs: 'column', md: 'row' }} spacing={2} sx={{ alignItems: 'stretch' }}>\n <Stack sx={{ flex: 1, minWidth: 0 }}>\n <DealPropertiesCard\n deal={deal}\n pipeline={pipeline}\n ownerLabel={roster.nameOf(deal.ownerUid)}\n routes={routes}\n customFields={dealFields.active}\n />\n </Stack>\n <Stack sx={{ flex: 1, minWidth: 0 }}>\n <RecordTasksCard hostId={hostId} org={org} basePath={basePath} dealId={deal.$id} />\n </Stack>\n </Stack>\n {scope.orgId ? (\n <DealProductsCard\n deal={deal}\n orgId={scope.orgId}\n hostId={hostId ?? deal.hostId ?? null}\n org={org}\n fromCache={fromCache}\n unreadable={status === 'error'}\n />\n ) : null}\n <RecordFilesCard\n scope={scope.scope}\n collection={CRM_COLLECTIONS.deals}\n recordId={deal.$id}\n mediaIds={deal.mediaIds}\n topic=\"deals\"\n />\n {/* Where the deal is visible and why, and a manager's share (AGL-3336). */}\n <RecordSharingCard\n object=\"deals\"\n id={deal.$id}\n record={deal as unknown as Record<string, unknown>}\n hostId={hostId ?? null}\n orgId={scope.orgId}\n org={org}\n viewingHostIds={scope.consentGroup?.hostIds}\n />\n <RecordActivityCard hostId={hostId} org={org} dealId={deal.$id} />\n </>\n ) : null}\n </Stack>\n <DealEditDrawer\n open={editing}\n onClose={() => setEditing(false)}\n hostId={hostId}\n org={org}\n deal={deal ?? null}\n pipelines={pipelineState.activePipelines}\n defaultPipeline={pipeline ?? pipelineState.pipeline}\n unreadable={status === 'error'}\n fromCache={fromCache}\n />\n </CrmCreateSiteDefault>\n )\n}\nDealDetailPage.displayName = 'DealDetailPage'\n\nexport default DealDetailPage\n"],"names":["CRM_COLLECTIONS","dealStageById","pluginDocsHelp","mdiDeleteOutline","mdiPencilOutline","MdiIcon","useConfirmationContext","useSnackbar","useFirestore","Button","Stack","Typography","deleteDoc","doc","useRouter","useCallback","useMemo","useState","useContactFieldDefinitions","useCrmActivityLogger","CrmCreateSiteDefault","useCrmScope","useDealStageApi","useDeal","useOrgMemberDirectory","usePipeline","crmRoutes","DEAL_STATUS_LABELS","formatMoney","CrmRecordChip","CrmRecordHeader","CrmRecordInsightsZone","RecordActivityCard","CrmShareChipView","RecordSharingCard","crmShareChipFor","CrmSendEmailButton","DealEditDrawer","DealProductsCard","DealPropertiesCard","DealStageCard","RecordFilesCard","RecordTasksCard","DealDetailPage","props","hostId","scope","id","basePath","org","routes","router","firestore","enqueueSnackbar","confirm","data","deal","status","fromCache","orgId","logActivity","pipelineState","pipeline","pipelineById","pipelineId","roster","api","nowMs","Date","now","editing","setEditing","deleting","setDeleting","dealFields","notFound","ready","handleDelete","agreed","title","description","confirmationText","confirmationButtonProps","color","then","catch","deals","$id","type","name","variant","persist","push","section","error","console","allowDuplicate","stage","stageId","undefined","spacing","kind","subtitle","filter","Boolean","join","help","anchor","backHref","backLabel","loading","booking","recordId","actions","size","startIcon","path","onClick","dealId","contactId","contactName","menuItems","key","label","icon","destructive","disabled","disabledReason","chips","value","amountCents","currency","nameOf","ownerUid","chip","consentGroup","hostIds","taskLink","ref","direction","xs","md","sx","alignItems","flex","minWidth","ownerLabel","customFields","active","unreadable","collection","mediaIds","topic","object","record","viewingHostIds","open","onClose","pipelines","activePipelines","defaultPipeline","displayName"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/deal-detail-page.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 { CRM_COLLECTIONS, dealStageById, pluginDocsHelp } from '@aglyn/aglyn'\nimport { mdiDeleteOutline, mdiPencilOutline } from '@aglyn/shared-data-mdi'\nimport { MdiIcon, useConfirmationContext } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useFirestore } from '@aglyn/tenant-feature-instance'\nimport { Button, Stack, Typography } from '@mui/material'\nimport { deleteDoc, doc } from 'firebase/firestore'\nimport { useRouter } from 'next/navigation'\nimport { useCallback, useMemo, useState } from 'react'\nimport { useContactFieldDefinitions } from '../hooks/use-contact-field-definitions'\nimport { useCrmActivityLogger } from '../hooks/use-crm-activity-logger'\nimport { CrmCreateSiteDefault } from '../hooks/use-crm-org-mount'\nimport { useCrmScope } from '../hooks/use-crm-scope'\nimport { useDealStageApi } from '../hooks/use-deal-stage-api'\nimport { useDeal } from '../hooks/use-deals'\nimport { useOrgMemberDirectory } from '../hooks/use-org-member-directory'\nimport { usePipeline } from '../hooks/use-pipeline'\nimport { type CrmDetailPageProps, crmRoutes } from '../model/crm-routes'\nimport { DEAL_STATUS_LABELS, formatMoney } from '../model/deal-board-model'\nimport { CrmRecordChip, CrmRecordHeader } from './crm-record-header'\nimport { CrmRecordInsightsZone } from './crm-record-insights-zone'\nimport { RecordActivityCard } from './record-activity-card'\nimport { CrmShareChipView, RecordSharingCard } from './record-sharing-card'\nimport { crmShareChipFor } from '../model/crm-sharing'\nimport { CrmSendEmailButton } from './crm-send-email-button'\nimport { DealContactRolesCard } from './deal-contact-roles-card'\nimport { DealEditDrawer } from './deal-edit-drawer'\nimport { DealProductsCard } from './deal-products-card'\nimport { useCrmCampaigns } from '../hooks/use-crm-campaigns'\nimport { DealPropertiesCard } from './deal-properties-card'\nimport { DealStageCard } from './deal-stage-card'\nimport RecordFilesCard from './record-files-card'\nimport { RecordTasksCard } from './record-tasks-card'\n\n/**\n * `/crm/deals/{dealId}` — one deal (AGL-2598).\n *\n * The record behind a card: its stage and the controls that move it, what\n * it is worth and who it is with — every contact on it and the part each\n * plays (AGL-3521) — the products behind the amount (AGL-2620), and the\n * tasks and activity filed against it. One live\n * document read; the pipeline and the roster are the same bounded reads\n * the board makes. Editing opens the same drawer the board creates with,\n * and deleting is the one destructive act here — confirmed, then a\n * client-direct delete the rules allow the same people who could have\n * created it.\n */\nexport function DealDetailPage(props: CrmDetailPageProps) {\n const { id, basePath, hostId, org } = props\n const routes = crmRoutes(basePath)\n const router = useRouter()\n const firestore = useFirestore()\n const { enqueueSnackbar } = useSnackbar()\n const { confirm } = useConfirmationContext()\n const scope = useCrmScope({ hostId, org })\n const { data: deal, status, fromCache } = useDeal(scope.orgId, id)\n // The feed the act is logged in, decided by the level it was performed\n // at (AGL-2738): this site's under a site, the organization's at the org\n // hub, where a client-direct append to the deal's own site would face a\n // gate the record write never had to pass.\n const logActivity = useCrmActivityLogger(hostId)\n const pipelineState = usePipeline(scope.orgId, {\n hostId,\n org: (org ?? null) as Record<string, unknown> | null,\n })\n const pipeline = pipelineState.pipelineById(deal?.pipelineId)\n const roster = useOrgMemberDirectory(scope.orgId)\n const api = useDealStageApi(hostId)\n const nowMs = useMemo(() => Date.now(), [])\n const [editing, setEditing] = useState(false)\n const [deleting, setDeleting] = useState(false)\n // The org's deal fields (AGL-2661), for the properties card's rows.\n const dealFields = useContactFieldDefinitions(scope.orgId, 'deal')\n // The deal's campaign by name (AGL-3516), read only for a deal that names one.\n const campaigns = useCrmCampaigns(\n { hostId, orgId: scope.orgId },\n { enabled: Boolean(deal?.campaignId) },\n )\n\n const notFound = scope.ready && (!scope.orgId || (status !== 'loading' && !deal))\n\n const handleDelete = useCallback(async () => {\n if (!deal || !scope.orgId) return\n const agreed = await confirm({\n title: 'Delete this deal?',\n description:\n `\"${deal.title}\" is removed from the pipeline along with its notes. ` +\n 'The contact and the company it names are not touched.',\n confirmationText: 'Delete deal',\n confirmationButtonProps: { color: 'error' },\n })\n .then(() => true)\n .catch(() => false)\n if (!agreed) return\n setDeleting(true)\n try {\n await deleteDoc(doc(firestore, 'orgs', scope.orgId, CRM_COLLECTIONS.deals, deal.$id))\n // Setup → Activity shows CRM work (AGL-2622): the deal is org data,\n // but the act happened in this site's console and belongs in its feed.\n logActivity('Deleted deal', { type: 'deal', id: deal.$id, name: deal.title })\n enqueueSnackbar('Deal deleted', { variant: 'success', persist: false })\n router.push(routes.section('deals'))\n } catch (error) {\n console.error(error)\n enqueueSnackbar('An error has occurred', { variant: 'error', allowDuplicate: true })\n setDeleting(false)\n }\n }, [deal, scope.orgId, confirm, firestore, logActivity, enqueueSnackbar, router, routes])\n\n const stage = deal ? dealStageById(pipeline, deal.stageId) : undefined\n\n return (\n // A create opened from this page — a task, an activity — files under\n // the deal's own site unless the reader says otherwise (AGL-2630).\n <CrmCreateSiteDefault hostId={deal?.hostId ?? null}>\n <Stack spacing={2}>\n <CrmRecordHeader\n kind=\"Deal\"\n title={deal?.title}\n subtitle={\n deal\n ? [pipeline?.name, stage?.name ?? deal.stageId].filter(Boolean).join(' · ')\n : undefined\n }\n help={pluginDocsHelp('deals', { anchor: '#a-deals-page' })}\n backHref={routes.section('deals')}\n backLabel=\"Back to deals\"\n loading={!deal && !notFound}\n // The booking door (AGL-2660): the deal's own site's services.\n booking={\n deal\n ? { hostId: hostId ?? deal.hostId ?? null, org, kind: 'deal', recordId: deal.$id }\n : undefined\n }\n actions={\n deal ? (\n <>\n <Button\n size=\"small\"\n variant=\"outlined\"\n startIcon={<MdiIcon path={mdiPencilOutline.path} size={0.8} />}\n onClick={() => setEditing(true)}\n >\n {'Edit'}\n </Button>\n <CrmSendEmailButton\n hostId={hostId ?? deal.hostId ?? null}\n org={org}\n dealId={deal.$id}\n contactId={deal.contactId}\n name={deal.contactName}\n />\n </>\n ) : null\n }\n menuItems={\n deal\n ? [\n {\n key: 'delete',\n label: 'Delete deal',\n icon: <MdiIcon path={mdiDeleteOutline.path} size={0.8} />,\n destructive: true,\n disabled: deleting,\n disabledReason: 'The deal is being deleted',\n onClick: () => void handleDelete(),\n },\n ]\n : undefined\n }\n chips={\n deal ? (\n <>\n <CrmRecordChip\n label=\"Status\"\n value={DEAL_STATUS_LABELS[deal.status] ?? deal.status}\n color={deal.status === 'won' ? 'success' : deal.status === 'lost' ? 'default' : 'primary'}\n />\n <CrmRecordChip\n label=\"Amount\"\n value={\n typeof deal.amountCents === 'number'\n ? formatMoney(deal.amountCents, deal.currency)\n : undefined\n }\n />\n <CrmRecordChip label=\"Owner\" value={roster.nameOf(deal.ownerUid) || undefined} />\n {/* Seen here only through a share (AGL-3336). */}\n <CrmShareChipView\n chip={crmShareChipFor(\n deal as unknown as Record<string, unknown>,\n scope.consentGroup?.hostIds ?? [],\n )}\n org={org}\n />\n </>\n ) : null\n }\n >\n {notFound ? (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'This deal does not exist, or is not visible to this site.'}\n </Typography>\n ) : null}\n </CrmRecordHeader>\n {deal ? (\n <>\n {/* What an assistant proposes about the deal, its stage included (AGL-2917). */}\n <CrmRecordInsightsZone\n hostId={hostId}\n org={org as Record<string, unknown> | undefined}\n kind=\"deal\"\n recordId={deal.$id}\n name={deal.title}\n taskLink={{ dealId: deal.$id }}\n deal={{ pipeline, ref: deal, stageId: deal.stageId, status: deal.status, api }}\n />\n <DealStageCard deal={deal} pipeline={pipeline} api={api} nowMs={nowMs} />\n <Stack direction={{ xs: 'column', md: 'row' }} spacing={2} sx={{ alignItems: 'stretch' }}>\n <Stack sx={{ flex: 1, minWidth: 0 }}>\n <DealPropertiesCard\n deal={deal}\n pipeline={pipeline}\n ownerLabel={roster.nameOf(deal.ownerUid)}\n routes={routes}\n customFields={dealFields.active}\n campaignName={\n deal.campaignId\n ? (campaigns.options.find((option) => option.value === deal.campaignId)?.label ??\n deal.campaignId)\n : undefined\n }\n />\n </Stack>\n <Stack sx={{ flex: 1, minWidth: 0 }}>\n <RecordTasksCard hostId={hostId} org={org} basePath={basePath} dealId={deal.$id} />\n </Stack>\n </Stack>\n {/* The people on the deal and the part each plays (AGL-3521). */}\n <DealContactRolesCard\n deal={deal}\n hostId={hostId}\n org={org}\n routes={routes}\n fromCache={fromCache}\n unreadable={status === 'error'}\n />\n {scope.orgId ? (\n <DealProductsCard\n deal={deal}\n orgId={scope.orgId}\n hostId={hostId ?? deal.hostId ?? null}\n org={org}\n fromCache={fromCache}\n unreadable={status === 'error'}\n />\n ) : null}\n <RecordFilesCard\n scope={scope.scope}\n collection={CRM_COLLECTIONS.deals}\n recordId={deal.$id}\n mediaIds={deal.mediaIds}\n topic=\"deals\"\n />\n {/* Where the deal is visible and why, and a manager's share (AGL-3336). */}\n <RecordSharingCard\n object=\"deals\"\n id={deal.$id}\n record={deal as unknown as Record<string, unknown>}\n hostId={hostId ?? null}\n orgId={scope.orgId}\n org={org}\n viewingHostIds={scope.consentGroup?.hostIds}\n />\n <RecordActivityCard hostId={hostId} org={org} dealId={deal.$id} />\n </>\n ) : null}\n </Stack>\n <DealEditDrawer\n open={editing}\n onClose={() => setEditing(false)}\n hostId={hostId}\n org={org}\n deal={deal ?? null}\n pipelines={pipelineState.activePipelines}\n defaultPipeline={pipeline ?? pipelineState.pipeline}\n unreadable={status === 'error'}\n fromCache={fromCache}\n />\n </CrmCreateSiteDefault>\n )\n}\nDealDetailPage.displayName = 'DealDetailPage'\n\nexport default DealDetailPage\n"],"names":["CRM_COLLECTIONS","dealStageById","pluginDocsHelp","mdiDeleteOutline","mdiPencilOutline","MdiIcon","useConfirmationContext","useSnackbar","useFirestore","Button","Stack","Typography","deleteDoc","doc","useRouter","useCallback","useMemo","useState","useContactFieldDefinitions","useCrmActivityLogger","CrmCreateSiteDefault","useCrmScope","useDealStageApi","useDeal","useOrgMemberDirectory","usePipeline","crmRoutes","DEAL_STATUS_LABELS","formatMoney","CrmRecordChip","CrmRecordHeader","CrmRecordInsightsZone","RecordActivityCard","CrmShareChipView","RecordSharingCard","crmShareChipFor","CrmSendEmailButton","DealContactRolesCard","DealEditDrawer","DealProductsCard","useCrmCampaigns","DealPropertiesCard","DealStageCard","RecordFilesCard","RecordTasksCard","DealDetailPage","props","hostId","scope","campaigns","id","basePath","org","routes","router","firestore","enqueueSnackbar","confirm","data","deal","status","fromCache","orgId","logActivity","pipelineState","pipeline","pipelineById","pipelineId","roster","api","nowMs","Date","now","editing","setEditing","deleting","setDeleting","dealFields","enabled","Boolean","campaignId","notFound","ready","handleDelete","agreed","title","description","confirmationText","confirmationButtonProps","color","then","catch","deals","$id","type","name","variant","persist","push","section","error","console","allowDuplicate","stage","stageId","undefined","spacing","kind","subtitle","filter","join","help","anchor","backHref","backLabel","loading","booking","recordId","actions","size","startIcon","path","onClick","dealId","contactId","contactName","menuItems","key","label","icon","destructive","disabled","disabledReason","chips","value","amountCents","currency","nameOf","ownerUid","chip","consentGroup","hostIds","taskLink","ref","direction","xs","md","sx","alignItems","flex","minWidth","ownerLabel","customFields","active","campaignName","options","find","option","unreadable","collection","mediaIds","topic","object","record","viewingHostIds","open","onClose","pipelines","activePipelines","defaultPipeline","displayName"],"mappings":"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"}