@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
@@ -15,19 +15,21 @@
15
15
  * limitations under the License.
16
16
  */ 'use client';
17
17
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
18
- import { CRM_COLLECTIONS, dealStageById, findOrgMember, ORG_SCOPE_TOKEN, pluginDocsHelp } from "@aglyn/aglyn";
18
+ import { CRM_COLLECTIONS, crmPicklistRank, dealStageById, ORG_SCOPE_TOKEN, pluginDocsHelp } from "@aglyn/aglyn";
19
19
  import { mdiCogOutline, mdiPlus, mdiTableLarge, mdiViewColumnOutline } from "@aglyn/shared-data-mdi";
20
20
  import { CardDisplay, MdiIcon } from "@aglyn/shared-ui-jsx";
21
21
  import { ListPagination } from "@aglyn/shared-ui-jsx/components/list-pagination.component";
22
22
  import { ListTable } from "@aglyn/shared-ui-jsx/components/list-table.component";
23
- import ListQueryNotices, { listQueryRefusals } from "@aglyn/shared-ui-jsx/components/list-query-notices.component";
23
+ import ListQueryNotices from "@aglyn/shared-ui-jsx/components/list-query-notices.component";
24
24
  import { useCrmSavedView } from "../hooks/use-crm-saved-view.js";
25
25
  import { useCrmViewGrid } from "../hooks/use-crm-view-grid.js";
26
26
  import { CrmListActions, CrmListToolbar } from "./crm-list-toolbar.js";
27
27
  import { CRM_LIST_SLOTS, CrmColumnOrderProvider } from "./crm-column-menu.js";
28
28
  import { CRM_NEXT_ACTIVITY_FILTER_FIELD, CRM_NEXT_ACTIVITY_FILTER_HEADER, nextActivityColumn } from "./crm-next-activity-column.js";
29
- import { DEAL_LIST_DECLARATION, DEAL_LIST_FILTER_FIELDS, DEAL_PREFIX_SEARCH, dealPipelineBase } from "../constants/deal-filters.js";
29
+ import { DEAL_FILTER_CODECS, DEAL_LIST_DECLARATION, DEAL_LIST_FILTER_FIELDS, DEAL_PICKLIST_FILTER_NONE, DEAL_PREFIX_SEARCH, dealPipelineBase, dealQueryClause } from "../constants/deal-filters.js";
30
30
  import { useCrmFoldsScope, useCrmListQuery } from "../hooks/use-crm-list-query.js";
31
+ import { useCrmPicklist } from "../hooks/use-crm-picklist.js";
32
+ import { crmAskClauses, crmQueryRefusals } from "../model/crm-list-query.js";
31
33
  import ListFilterChips from "@aglyn/shared-ui-jsx/components/list-filter-chips.component";
32
34
  import { listFilterGridColumns } from "@aglyn/shared-ui-jsx/const/list-grid-filter";
33
35
  import { useListGridFilter } from "@aglyn/shared-ui-jsx/hooks/use-list-grid-filter";
@@ -43,33 +45,48 @@ import { useDealStageApi } from "../hooks/use-deal-stage-api.js";
43
45
  import { BOARD_CLOSED_LIMIT, BOARD_OPEN_LIMIT, useDealsByStatus } from "../hooks/use-deals.js";
44
46
  import { useOrgMemberDirectory } from "../hooks/use-org-member-directory.js";
45
47
  import { usePipeline } from "../hooks/use-pipeline.js";
46
- import { downloadTextFile } from "../model/contacts-csv.js";
47
48
  import { crmRoutes } from "../model/crm-routes.js";
48
- import { dealsCsv } from "../model/deals-csv.js";
49
49
  import { boardSummary, DEAL_STATUS_LABELS, formatAmountByCurrency, formatMoney } from "../model/deal-board-model.js";
50
50
  import { customFieldColumns } from "./contact-custom-columns.js";
51
51
  import { DealBoard } from "./deal-board.js";
52
52
  import { DealEditDrawer } from "./deal-edit-drawer.js";
53
- import { DealImportButton } from "./deal-import-drawer.js";
53
+ import { CrmExportButton, CrmImportButton } from "./crm-transfer-buttons.js";
54
+ import { CRM_DEALS_RESOURCE } from "../transfer/fields.js";
54
55
  import DealsBulkBar from "./deals-bulk-bar.js";
55
56
  import { LostReasonDialog } from "./lost-reason-dialog.js";
56
57
  import { OwnerAvatar } from "./owner-avatar.js";
57
58
  import { PipelinesDialog } from "./pipelines-dialog.js";
58
- /** What the deals table's panel offers: the status, and "No next activity". */ const DEAL_GRID_FILTER_FIELDS = DEAL_LIST_FILTER_FIELDS;
59
+ /** What the deals table's panel offers: the status, "No next activity", the Type and the Lead source. */ const DEAL_GRID_FILTER_FIELDS = DEAL_LIST_FILTER_FIELDS;
59
60
  const DEAL_GRID_FILTER_HEADERS = {
60
61
  status: 'Status',
61
- [CRM_NEXT_ACTIVITY_FILTER_FIELD.column]: CRM_NEXT_ACTIVITY_FILTER_HEADER
62
+ [CRM_NEXT_ACTIVITY_FILTER_FIELD.column]: CRM_NEXT_ACTIVITY_FILTER_HEADER,
63
+ type: 'Type',
64
+ leadSource: 'Lead source'
62
65
  };
63
- const DEAL_FILTER_OPTIONS = {
64
- status: [
65
- 'open',
66
- 'won',
67
- 'lost'
68
- ].map((value)=>({
69
- value,
70
- label: DEAL_STATUS_LABELS[value]
71
- }))
66
+ const DEAL_STATUS_FILTER_OPTIONS = [
67
+ 'open',
68
+ 'won',
69
+ 'lost'
70
+ ].map((value)=>({
71
+ value,
72
+ label: DEAL_STATUS_LABELS[value]
73
+ }));
74
+ /** Salesforce's Type and Lead source columns are offered, not shown, until a view turns them on (AGL-3516). */ const DEAL_HIDDEN_COLUMNS = {
75
+ type: false,
76
+ leadSource: false
72
77
  };
78
+ /** A picklist's choices for its filter: every value the org keeps, inactive ones marked, then "none". */ function picklistFilterOptions(picklist, none) {
79
+ return [
80
+ ...picklist.values.map((value)=>({
81
+ value: value.label,
82
+ label: value.active ? value.label : `${value.label} (inactive)`
83
+ })),
84
+ {
85
+ value: DEAL_PICKLIST_FILTER_NONE,
86
+ label: none
87
+ }
88
+ ];
89
+ }
73
90
  /** What a pipeline made at the organization level is stamped with — the org's own token. */ const ORG_PIPELINE_TOKENS = [
74
91
  ORG_SCOPE_TOKEN
75
92
  ];
@@ -112,9 +129,9 @@ const DEAL_FILTER_OPTIONS = {
112
129
  *
113
130
  * The table's rows are selectable, and a selection raises `DealsBulkBar`
114
131
  * over it — whose stage moves go through the same `useDealStageApi` as a
115
- * drag. Export CSV beside the status toggle writes the page through
116
- * `dealsCsv()`, naming the pipeline, the stage and the owner; the bar
117
- * writes the same file over the selection.
132
+ * drag. Import and Export open the console's import wizard and export
133
+ * dialog on `crm.deals` (AGL-3528): the export over the selection, the
134
+ * list's own query, or every deal.
118
135
  */ export function DealsSection(props) {
119
136
  var _ref, _ref1, _ref2, _ref3, _scope_orgId, _ref4;
120
137
  const { hostId, org, basePath } = props;
@@ -140,6 +157,9 @@ const DEAL_FILTER_OPTIONS = {
140
157
  const nowMs = useMemo(()=>Date.now(), []);
141
158
  // The org's deal fields, for the table's optional columns (AGL-2661).
142
159
  const dealFields = useContactFieldDefinitions(scope.orgId, 'deal');
160
+ // Salesforce's Type and Lead source lists, for their columns and filters (AGL-3516).
161
+ const typeList = useCrmPicklist('opportunityType', scope.orgId);
162
+ const leadSourceList = useCrmPicklist('leadSource', scope.orgId);
143
163
  const [view, setView] = useState('board');
144
164
  const [closedExpanded, setClosedExpanded] = useState(false);
145
165
  /*
@@ -188,13 +208,18 @@ const DEAL_FILTER_OPTIONS = {
188
208
  }, [
189
209
  pipeline == null ? void 0 : pipeline.$id
190
210
  ]);
211
+ // Each stored clause asked through the field its writer keeps — a Type
212
+ // or a Lead source by its key (AGL-3516).
213
+ const asked = useMemo(()=>crmAskClauses(viewFilters, dealQueryClause), [
214
+ viewFilters
215
+ ]);
191
216
  const paged = useCrmListQuery({
192
217
  scope: scope.scope,
193
218
  collection: CRM_COLLECTIONS.deals,
194
219
  visibleTo: scope.visibleTo,
195
220
  foldsScope,
196
221
  declaration: DEAL_LIST_DECLARATION,
197
- clauses: viewFilters,
222
+ clauses: asked.clauses,
198
223
  search: searchWords,
199
224
  base: pipelineBase,
200
225
  prefixSearch: DEAL_PREFIX_SEARCH,
@@ -271,29 +296,13 @@ const DEAL_FILTER_OPTIONS = {
271
296
  paged.plan,
272
297
  paged.page
273
298
  ]);
274
- const csvOptions = useMemo(()=>({
275
- pipelineName: (id)=>{
276
- var _pipelineState_pipelineById;
277
- return (_pipelineState_pipelineById = pipelineState.pipelineById(id)) == null ? void 0 : _pipelineState_pipelineById.name;
278
- },
279
- stageName: (pipelineId, stageId)=>{
280
- var _dealStageById;
281
- return (_dealStageById = dealStageById(pipelineState.pipelineById(pipelineId), stageId)) == null ? void 0 : _dealStageById.name;
282
- },
283
- ownerEmail: (uid)=>{
284
- const member = findOrgMember(roster.members, uid);
285
- return (member == null ? void 0 : member.email) || (member == null ? void 0 : member.label) || uid;
286
- }
287
- }), [
288
- pipelineState,
289
- roster.members
290
- ]);
291
- // The page on screen; Export all on the bulk bar takes the whole list.
292
- const handleExport = useCallback(()=>{
293
- downloadTextFile('deals.csv', 'text/csv', dealsCsv(paged.rows, csvOptions));
294
- }, [
295
- paged.rows,
296
- csvOptions
299
+ // The list's filter, when one narrows it, for the export to read the same
300
+ // records the list does (AGL-3528).
301
+ const exportFilter = useMemo(()=>paged.plan.served.length || paged.plan.searched ? {
302
+ label: 'what the list shows',
303
+ plan: paged.plan
304
+ } : null, [
305
+ paged.plan
297
306
  ]);
298
307
  const columns = useMemo(()=>[
299
308
  {
@@ -414,41 +423,78 @@ const DEAL_FILTER_OPTIONS = {
414
423
  },
415
424
  // When the earliest open task against the deal is due (AGL-2661).
416
425
  nextActivityColumn(nowMs),
426
+ // Salesforce's Type and Lead source, optional, in their lists' order (AGL-3516).
427
+ picklistColumn('type', 'Type', typeList.picklist),
428
+ picklistColumn('leadSource', 'Lead source', leadSourceList.picklist),
417
429
  // The org's deal fields as optional columns (AGL-2661).
418
430
  ...customFieldColumns(dealFields.active)
419
431
  ], [
420
432
  pipelineState,
421
433
  roster,
422
434
  dealFields.active,
423
- nowMs
435
+ nowMs,
436
+ typeList.picklist,
437
+ leadSourceList.picklist
424
438
  ]);
425
439
  /** The table's rows: the query's page. */ const tableRows = paged.rows;
426
440
  /*
427
441
  * The table's column and sort models are the view's (AGL-2617); its
428
442
  * filters are the grid's own panel over the view's clauses (AGL-3313),
429
443
  * every one of them asked of the query (AGL-3321).
430
- */ const filterColumns = useMemo(()=>listFilterGridColumns(columns, DEAL_GRID_FILTER_FIELDS, DEAL_FILTER_OPTIONS, DEAL_GRID_FILTER_HEADERS), [
431
- columns
444
+ */ /*
445
+ * The choices each select column offers. A stored clause naming a value
446
+ * no longer listed stays a choice, so the panel can show it and clear it.
447
+ */ const filterOptions = useMemo(()=>{
448
+ const stale = (field, known)=>viewFilters.filter((clause)=>clause.field === field && clause.op !== 'isEmpty').flatMap((clause)=>clause.value.split(',')).map((value)=>value.trim()).filter((value)=>value && !known.some((option)=>option.value === value)).map((value)=>({
449
+ value,
450
+ label: value
451
+ }));
452
+ const types = picklistFilterOptions(typeList.picklist, 'No type');
453
+ const sources = picklistFilterOptions(leadSourceList.picklist, 'No lead source');
454
+ return {
455
+ status: DEAL_STATUS_FILTER_OPTIONS,
456
+ type: [
457
+ ...types,
458
+ ...stale('type', types)
459
+ ],
460
+ leadSource: [
461
+ ...sources,
462
+ ...stale('leadSource', sources)
463
+ ]
464
+ };
465
+ }, [
466
+ viewFilters,
467
+ typeList.picklist,
468
+ leadSourceList.picklist
432
469
  ]);
433
- const grid = useCrmViewGrid(views, filterColumns);
470
+ const filterColumns = useMemo(()=>listFilterGridColumns(columns, DEAL_GRID_FILTER_FIELDS, filterOptions, DEAL_GRID_FILTER_HEADERS), [
471
+ columns,
472
+ filterOptions
473
+ ]);
474
+ const grid = useCrmViewGrid(views, filterColumns, DEAL_HIDDEN_COLUMNS);
434
475
  const gridFilter = useListGridFilter({
435
476
  clauses: viewFilters,
436
477
  onChange: views.setFilters,
437
478
  selectFields: [
438
- 'status'
479
+ 'status',
480
+ 'type',
481
+ 'leadSource'
439
482
  ],
483
+ codecs: DEAL_FILTER_CODECS,
440
484
  search: {
441
485
  words: searchWords,
442
486
  onChange: setSearchWords
443
487
  }
444
488
  });
445
489
  // What the query could not hold, named by the clause the reader set.
446
- const refused = useMemo(()=>listQueryRefusals(paged.plan.refused, {
490
+ const refused = useMemo(()=>crmQueryRefusals(paged.plan, asked, {
447
491
  fields: DEAL_GRID_FILTER_FIELDS,
448
492
  headers: DEAL_GRID_FILTER_HEADERS,
449
- options: DEAL_FILTER_OPTIONS
493
+ options: filterOptions
450
494
  }), [
451
- paged.plan.refused
495
+ paged.plan,
496
+ asked,
497
+ filterOptions
452
498
  ]);
453
499
  const noOrg = scope.ready && !scope.orgId;
454
500
  const pipelineLoading = !noOrg && (pipelineState.status === 'loading' || pipelineState.seeding || !pipeline && pipelineState.status !== 'error');
@@ -465,15 +511,17 @@ const DEAL_FILTER_OPTIONS = {
465
511
  // The record actions, top right and never clipped (AGL-3311).
466
512
  action: /*#__PURE__*/ _jsxs(CrmListActions, {
467
513
  children: [
468
- /*#__PURE__*/ _jsx(DealImportButton, {
469
- hostId: hostId
514
+ /*#__PURE__*/ _jsx(CrmImportButton, {
515
+ resource: CRM_DEALS_RESOURCE,
516
+ noun: "deals",
517
+ hostId: hostId,
518
+ mappingZone: "deals"
519
+ }),
520
+ /*#__PURE__*/ _jsx(CrmExportButton, {
521
+ resource: CRM_DEALS_RESOURCE,
522
+ hostId: hostId,
523
+ filter: exportFilter
470
524
  }),
471
- view === 'table' ? /*#__PURE__*/ _jsx(Button, {
472
- size: "small",
473
- onClick: handleExport,
474
- disabled: !paged.rows.length,
475
- children: 'Export CSV'
476
- }) : null,
477
525
  /*#__PURE__*/ _jsx(Button, {
478
526
  size: "small",
479
527
  startIcon: /*#__PURE__*/ _jsx(MdiIcon, {
@@ -665,7 +713,7 @@ const DEAL_FILTER_OPTIONS = {
665
713
  headers: DEAL_GRID_FILTER_HEADERS,
666
714
  clauses: viewFilters,
667
715
  onChange: views.setFilters,
668
- options: DEAL_FILTER_OPTIONS,
716
+ options: filterOptions,
669
717
  marksServed: false
670
718
  })
671
719
  ]
@@ -684,8 +732,7 @@ const DEAL_FILTER_OPTIONS = {
684
732
  onSelectedChange: setSelectedIds,
685
733
  pipelineById: pipelineState.pipelineById,
686
734
  roster: roster,
687
- api: api,
688
- csv: csvOptions
735
+ api: api
689
736
  }),
690
737
  /*#__PURE__*/ _jsx(CrmColumnOrderProvider, {
691
738
  value: grid.columnOrder,
@@ -775,6 +822,19 @@ const DEAL_FILTER_OPTIONS = {
775
822
  });
776
823
  }
777
824
  DealsSection.displayName = 'DealsSection';
825
+ /** An optional column of a picklist field: its label, sorted in the list's order. */ function picklistColumn(field, headerName, picklist) {
826
+ return {
827
+ field,
828
+ headerName,
829
+ flex: 0.8,
830
+ minWidth: 130,
831
+ valueGetter: (_value, row)=>{
832
+ var _row_field;
833
+ return String((_row_field = row[field]) != null ? _row_field : '');
834
+ },
835
+ sortComparator: (a, b)=>crmPicklistRank(picklist, a) - crmPicklistRank(picklist, b) || a.localeCompare(b)
836
+ };
837
+ }
778
838
  function Figure(props) {
779
839
  return /*#__PURE__*/ _jsxs(Stack, {
780
840
  sx: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/deals-section.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n type ConsolePluginPageProps,\n type CrmDealStatus,\n CRM_COLLECTIONS,\n dealStageById,\n findOrgMember,\n ORG_SCOPE_TOKEN,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport {\n mdiCogOutline,\n mdiPlus,\n mdiTableLarge,\n mdiViewColumnOutline,\n} from '@aglyn/shared-data-mdi'\nimport { CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport { ListTable } from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport ListQueryNotices, {\n listQueryRefusals,\n} from '@aglyn/shared-ui-jsx/components/list-query-notices.component'\nimport { useCrmSavedView } from '../hooks/use-crm-saved-view'\nimport { useCrmViewGrid } from '../hooks/use-crm-view-grid'\nimport { CrmListActions, CrmListToolbar } from './crm-list-toolbar'\nimport { CRM_LIST_SLOTS, CrmColumnOrderProvider } from './crm-column-menu'\nimport {\n CRM_NEXT_ACTIVITY_FILTER_FIELD,\n CRM_NEXT_ACTIVITY_FILTER_HEADER,\n nextActivityColumn,\n} from './crm-next-activity-column'\nimport {\n DEAL_LIST_DECLARATION,\n DEAL_LIST_FILTER_FIELDS,\n DEAL_PREFIX_SEARCH,\n dealPipelineBase,\n} from '../constants/deal-filters'\nimport { useCrmFoldsScope, useCrmListQuery } from '../hooks/use-crm-list-query'\nimport ListFilterChips from '@aglyn/shared-ui-jsx/components/list-filter-chips.component'\nimport { listFilterGridColumns } from '@aglyn/shared-ui-jsx/const/list-grid-filter'\nimport { useListGridFilter } from '@aglyn/shared-ui-jsx/hooks/use-list-grid-filter'\nimport CrmViewsControl from './crm-views-control'\nimport EmptyStateComponent from '@aglyn/shared-ui-jsx/components/empty-state.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport {\n Alert,\n Button,\n Chip,\n CircularProgress,\n MenuItem,\n Stack,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n} from '@mui/material'\nimport type { GridColDef } from '@mui/x-data-grid'\nimport { useRouter } from 'next/navigation'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useContactFieldDefinitions } from '../hooks/use-contact-field-definitions'\nimport { useCrmScope } from '../hooks/use-crm-scope'\nimport { useDealStageApi } from '../hooks/use-deal-stage-api'\nimport {\n BOARD_CLOSED_LIMIT,\n BOARD_OPEN_LIMIT,\n useDealsByStatus,\n} from '../hooks/use-deals'\nimport { useOrgMemberDirectory } from '../hooks/use-org-member-directory'\nimport { usePipeline } from '../hooks/use-pipeline'\nimport { downloadTextFile } from '../model/contacts-csv'\nimport { crmRoutes } from '../model/crm-routes'\nimport { type DealCsvOptions, dealsCsv } from '../model/deals-csv'\nimport {\n boardSummary,\n DEAL_STATUS_LABELS,\n type DealDoc,\n formatAmountByCurrency,\n formatMoney,\n} from '../model/deal-board-model'\nimport { customFieldColumns } from './contact-custom-columns'\nimport { DealBoard } from './deal-board'\nimport { DealEditDrawer } from './deal-edit-drawer'\nimport { DealImportButton } from './deal-import-drawer'\nimport DealsBulkBar from './deals-bulk-bar'\nimport { LostReasonDialog } from './lost-reason-dialog'\nimport { OwnerAvatar } from './owner-avatar'\nimport { PipelinesDialog } from './pipelines-dialog'\n\ntype View = 'board' | 'table'\ntype StatusFilter = CrmDealStatus | 'all'\n\n/** What the deals table's panel offers: the status, and \"No next activity\". */\nconst DEAL_GRID_FILTER_FIELDS = DEAL_LIST_FILTER_FIELDS\nconst DEAL_GRID_FILTER_HEADERS: Readonly<Record<string, string>> = {\n status: 'Status',\n [CRM_NEXT_ACTIVITY_FILTER_FIELD.column]: CRM_NEXT_ACTIVITY_FILTER_HEADER,\n}\nconst DEAL_FILTER_OPTIONS = {\n status: (['open', 'won', 'lost'] as const).map((value) => ({\n value,\n label: DEAL_STATUS_LABELS[value],\n })),\n}\n\n\n/** What a pipeline made at the organization level is stamped with — the org's own token. */\nconst ORG_PIPELINE_TOKENS: readonly string[] = [ORG_SCOPE_TOKEN]\n\n/**\n * `/crm/deals` — the pipeline (AGL-2598).\n *\n * ## Two views of one pipeline\n *\n * The BOARD is one pipeline's open deals, one column per open stage, read\n * in one bounded listener over `(visibleTo, pipelineId, status, updatedAt)`\n * and sorted into columns here — a listener per column would be five\n * subscriptions for one board. The TABLE is the same pipeline's deals,\n * paged by a query that carries its status, \"No next activity\" and search\n * word (AGL-3321); it is where the closed history is found. The three figures above both come from the board's read, so\n * they describe what is in play whichever view is showing.\n *\n * ## Which pipeline\n *\n * The switcher in the header (AGL-2620) picks among the ACTIVE pipelines\n * and opens on the default; the board, the table, the figures and the New\n * deal drawer all follow it. It is section state rather than a route: a\n * pipeline is a lens on the section, and a saved view that names one\n * composes with it. **Pipelines** opens the dialog that creates, renames,\n * defaults, archives and — through it — edits the stages of each.\n *\n * ## Every move goes through the route\n *\n * A drag, a card's \"Move to\", \"Mark won\" and \"Mark lost\" all end in\n * `useDealStageApi`, never a Firestore write: the stage is the fact the\n * automations listen for, and only the server emits the event. The section\n * marks the card pending while the request runs and lets the listener land\n * it — see `DealBoard` for why a move is not applied optimistically.\n *\n * ## Creation is a button\n *\n * \"New deal\" opens a drawer; there is no form above the list. The drawer\n * writes client-direct against the rules, stamped with this console's scope.\n *\n * ## The table selects and exports (AGL-2621)\n *\n * The table's rows are selectable, and a selection raises `DealsBulkBar`\n * over it — whose stage moves go through the same `useDealStageApi` as a\n * drag. Export CSV beside the status toggle writes the page through\n * `dealsCsv()`, naming the pipeline, the stage and the owner; the bar\n * writes the same file over the selection.\n */\nexport function DealsSection(props: ConsolePluginPageProps) {\n const { hostId, org, basePath } = props\n const routes = crmRoutes(basePath ?? '')\n const router = useRouter()\n const { enqueueSnackbar } = useSnackbar()\n const scope = useCrmScope({ hostId, org })\n const pipelineState = usePipeline(scope.orgId, {\n hostId,\n org: (org ?? null) as Record<string, unknown> | null,\n })\n const { activePipelines } = pipelineState\n const [pipelineId, setPipelineId] = useState<string | null>(null)\n // The chosen pipeline while it is still active; else the default. A\n // pipeline archived from another tab falls back rather than leaving the\n // board on a pipeline the picker no longer lists.\n const pipeline =\n (pipelineId ? activePipelines.find((entry) => entry.$id === pipelineId) : null) ??\n pipelineState.pipeline\n const roster = useOrgMemberDirectory(scope.orgId)\n const api = useDealStageApi(hostId)\n const nowMs = useMemo(() => Date.now(), [])\n // The org's deal fields, for the table's optional columns (AGL-2661).\n const dealFields = useContactFieldDefinitions(scope.orgId, 'deal')\n\n const [view, setView] = useState<View>('board')\n const [closedExpanded, setClosedExpanded] = useState(false)\n /*\n * The table's status filter is the saved VIEW'S (AGL-2617): a view of\n * deals is a view of the table, and it holds the status beside the\n * columns and the sort. Opening one shows the table, because the board\n * has no columns to arrange and answers to the pipeline's stages alone.\n */\n const views = useCrmSavedView({\n section: 'deals',\n hostId,\n org,\n basePath: basePath ?? '',\n })\n const statusFilter: StatusFilter = useMemo(() => {\n const value = views.state.filters.find((clause) => clause.field === 'status')?.value\n return value === 'open' || value === 'won' || value === 'lost' ? value : 'all'\n }, [views.state.filters])\n // Every clause is the query's, the status and \"No next activity\" alike.\n const viewFilters = views.state.filters\n useEffect(() => {\n if (views.currentId) setView('table')\n }, [views.currentId])\n\n // The board's read stays on in the table view too: it is what the summary\n // above both views is computed from, and it is already bounded.\n const open = useDealsByStatus(\n scope.orgId,\n scope.visibleTo,\n pipeline?.$id ?? null,\n 'open',\n BOARD_OPEN_LIMIT,\n )\n const closedPipelineId =\n view === 'board' && closedExpanded ? (pipeline?.$id ?? null) : null\n const won = useDealsByStatus(scope.orgId, scope.visibleTo, closedPipelineId, 'won', BOARD_CLOSED_LIMIT)\n const lost = useDealsByStatus(scope.orgId, scope.visibleTo, closedPipelineId, 'lost', BOARD_CLOSED_LIMIT)\n /*\n * THE TABLE (AGL-3321): the pipeline's deals, every clause and the search\n * word on one query — the search reads the title's word prefixes every\n * deal writer stamps, so a deal on page four is found by any word of its\n * title — paged by that query, and read only while the table is showing.\n */\n const [searchWords, setSearchWords] = useState<string[]>([])\n const searching = searchWords.some((word) => word.trim())\n const searchKey = searchWords.join(' ')\n const foldsScope = useCrmFoldsScope(scope.orgId, scope.visibleTo)\n const pipelineBase = useMemo(() => dealPipelineBase(pipeline?.$id ?? null), [pipeline?.$id])\n const paged = useCrmListQuery<DealDoc>({\n scope: scope.scope,\n collection: CRM_COLLECTIONS.deals,\n visibleTo: scope.visibleTo,\n foldsScope,\n declaration: DEAL_LIST_DECLARATION,\n clauses: viewFilters,\n search: searchWords,\n base: pipelineBase,\n prefixSearch: DEAL_PREFIX_SEARCH,\n enabled: view === 'table' && Boolean(pipeline),\n })\n\n const summary = useMemo(() => boardSummary(open.data, pipeline), [open.data, pipeline])\n\n /*\n * MOVES IN FLIGHT. A card in this set is dimmed and cannot be dragged\n * again until the route answers; the listener is what moves it.\n */\n const [moving, setMoving] = useState<ReadonlySet<string>>(() => new Set())\n const track = useCallback(\n async (deal: DealDoc, request: () => Promise<unknown>, done: string) => {\n setMoving((current) => new Set(current).add(deal.$id))\n try {\n await request()\n enqueueSnackbar(done, { variant: 'success', persist: false })\n return true\n } catch (error) {\n enqueueSnackbar(\n error instanceof Error ? error.message : 'The deal could not be moved.',\n { variant: 'warning', allowDuplicate: true },\n )\n return false\n } finally {\n setMoving((current) => {\n const next = new Set(current)\n next.delete(deal.$id)\n return next\n })\n }\n },\n [enqueueSnackbar],\n )\n const handleMove = useCallback(\n (deal: DealDoc, stageId: string) => {\n const stage = dealStageById(pipeline, stageId)\n void track(\n deal,\n () => api.moveToStage(deal, stageId),\n `Moved to ${stage?.name ?? 'stage'}`,\n )\n },\n [api, pipeline, track],\n )\n const handleWon = useCallback(\n (deal: DealDoc) => void track(deal, () => api.markWon(deal), 'Deal won'),\n [api, track],\n )\n const [losing, setLosing] = useState<DealDoc | null>(null)\n const handleLost = useCallback((deal: DealDoc) => setLosing(deal), [])\n const confirmLost = useCallback(\n (reason: string) => {\n const deal = losing\n if (!deal) return\n setLosing(null)\n void track(deal, () => api.markLost(deal, reason), 'Deal marked lost')\n },\n [api, losing, track],\n )\n\n const openDeal = useCallback(\n (deal: DealDoc) => router.push(routes.deal(deal.$id)),\n [router, routes],\n )\n\n const [creating, setCreating] = useState(false)\n const [managingPipelines, setManagingPipelines] = useState(false)\n\n const [selectedIds, setSelectedIds] = useState<string[]>([])\n // A page or a status is a different set of rows; a selection made on\n // the last one would be a count over rows no longer on screen.\n useEffect(() => setSelectedIds([]), [paged.plan, paged.page])\n const csvOptions: DealCsvOptions = useMemo(\n () => ({\n pipelineName: (id) => pipelineState.pipelineById(id)?.name,\n stageName: (pipelineId, stageId) =>\n dealStageById(pipelineState.pipelineById(pipelineId), stageId)?.name,\n ownerEmail: (uid) => {\n const member = findOrgMember(roster.members, uid)\n return member?.email || member?.label || uid\n },\n }),\n [pipelineState, roster.members],\n )\n // The page on screen; Export all on the bulk bar takes the whole list.\n const handleExport = useCallback(() => {\n downloadTextFile('deals.csv', 'text/csv', dealsCsv(paged.rows, csvOptions))\n }, [paged.rows, csvOptions])\n\n const columns: GridColDef[] = useMemo(\n () => [\n {\n field: 'title',\n headerName: 'Deal',\n flex: 1.6,\n minWidth: 220,\n renderCell: ({ row }: { row: DealDoc }) => {\n const withWhom = [row.contactName, row.companyName].filter(Boolean).join(' · ')\n return (\n <Stack sx={{ justifyContent: 'center', lineHeight: 1.25 }}>\n <Typography variant=\"body2\" sx={{ lineHeight: 1.25 }}>\n {row.title || 'Untitled deal'}\n </Typography>\n {withWhom ? (\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap sx={{ lineHeight: 1.25 }}>\n {withWhom}\n </Typography>\n ) : null}\n </Stack>\n )\n },\n },\n {\n field: 'stageId',\n headerName: 'Stage',\n flex: 0.9,\n minWidth: 140,\n valueGetter: (_value: unknown, row: DealDoc) =>\n dealStageById(pipelineState.pipelineById(row.pipelineId), row.stageId)?.name ??\n row.stageId,\n },\n {\n field: 'amountCents',\n headerName: 'Amount',\n flex: 0.8,\n minWidth: 120,\n align: 'right',\n headerAlign: 'right',\n valueGetter: (_value: unknown, row: DealDoc) => row.amountCents ?? null,\n renderCell: ({ row }: { row: DealDoc }) =>\n typeof row.amountCents === 'number' ? formatMoney(row.amountCents, row.currency) : '—',\n },\n {\n field: 'ownerUid',\n headerName: 'Owner',\n flex: 0.9,\n minWidth: 140,\n valueGetter: (_value: unknown, row: DealDoc) => roster.nameOf(row.ownerUid),\n renderCell: ({ row }: { row: DealDoc }) => {\n const label = roster.nameOf(row.ownerUid)\n return label ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <OwnerAvatar label={label} size={22} />\n <Typography variant=\"body2\" noWrap>\n {label}\n </Typography>\n </Stack>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'—'}\n </Typography>\n )\n },\n },\n {\n field: 'expectedCloseAtMs',\n headerName: 'Expected close',\n flex: 0.8,\n minWidth: 130,\n type: 'date',\n valueGetter: (_value: unknown, row: DealDoc) =>\n typeof row.expectedCloseAtMs === 'number' ? new Date(row.expectedCloseAtMs) : null,\n renderCell: ({ row }: { row: DealDoc }) =>\n typeof row.expectedCloseAtMs === 'number'\n ? new Date(row.expectedCloseAtMs).toLocaleDateString()\n : '—',\n },\n {\n field: 'status',\n headerName: 'Status',\n flex: 0.6,\n minWidth: 100,\n renderCell: ({ row }: { row: DealDoc }) => (\n <Chip\n size=\"small\"\n label={DEAL_STATUS_LABELS[row.status] ?? row.status}\n color={row.status === 'won' ? 'success' : row.status === 'lost' ? 'default' : 'primary'}\n variant={row.status === 'open' ? 'outlined' : 'filled'}\n />\n ),\n },\n // When the earliest open task against the deal is due (AGL-2661).\n nextActivityColumn(nowMs),\n // The org's deal fields as optional columns (AGL-2661).\n ...customFieldColumns(dealFields.active),\n ],\n [pipelineState, roster, dealFields.active, nowMs],\n )\n /** The table's rows: the query's page. */\n const tableRows = paged.rows\n /*\n * The table's column and sort models are the view's (AGL-2617); its\n * filters are the grid's own panel over the view's clauses (AGL-3313),\n * every one of them asked of the query (AGL-3321).\n */\n const filterColumns = useMemo(\n () => listFilterGridColumns(columns, DEAL_GRID_FILTER_FIELDS, DEAL_FILTER_OPTIONS, DEAL_GRID_FILTER_HEADERS),\n [columns],\n )\n const grid = useCrmViewGrid(views, filterColumns)\n const gridFilter = useListGridFilter({\n clauses: viewFilters,\n onChange: views.setFilters,\n selectFields: ['status'],\n search: { words: searchWords, onChange: setSearchWords },\n })\n // What the query could not hold, named by the clause the reader set.\n const refused = useMemo(\n () =>\n listQueryRefusals(paged.plan.refused, {\n fields: DEAL_GRID_FILTER_FIELDS,\n headers: DEAL_GRID_FILTER_HEADERS,\n options: DEAL_FILTER_OPTIONS,\n }),\n [paged.plan.refused],\n )\n\n const noOrg = scope.ready && !scope.orgId\n const pipelineLoading =\n !noOrg && (pipelineState.status === 'loading' || pipelineState.seeding || (!pipeline && pipelineState.status !== 'error'))\n\n return (\n <>\n <CardDisplay\n header={'Deals'}\n help={pluginDocsHelp('deals', { anchor: '#the-board-and-the-table' })}\n contentGutterX\n contentGutterY\n HeaderProps={{\n // The record actions, top right and never clipped (AGL-3311).\n action: (\n <CrmListActions>\n <DealImportButton hostId={hostId} />\n {/* The file is the table's rows, so it is offered with the table. */}\n {view === 'table' ? (\n <Button\n size=\"small\"\n onClick={handleExport}\n disabled={!paged.rows.length}\n >\n {'Export CSV'}\n </Button>\n ) : null}\n <Button\n size=\"small\"\n startIcon={<MdiIcon path={mdiCogOutline.path} size={0.8} />}\n disabled={!scope.orgId || pipelineState.status === 'loading'}\n onClick={() => setManagingPipelines(true)}\n >\n {'Pipelines'}\n </Button>\n <Button\n size=\"small\"\n variant=\"contained\"\n startIcon={<MdiIcon path={mdiPlus.path} size={0.8} />}\n disabled={!pipeline || !scope.orgId}\n onClick={() => setCreating(true)}\n >\n {'New deal'}\n </Button>\n </CrmListActions>\n ),\n }}\n >\n <Stack spacing={2}>\n <Stack\n direction=\"row\"\n spacing={3}\n sx={{ alignItems: 'flex-end', flexWrap: 'wrap', rowGap: 1 }}\n >\n <Figure label=\"Open deals\" value={summary.openCount.toLocaleString()} />\n <Figure label=\"Pipeline value\" value={formatAmountByCurrency(summary.valueByCurrency)} />\n <Figure label=\"Weighted value\" value={formatAmountByCurrency(summary.weightedByCurrency)} />\n <Stack sx={{ flex: 1 }} />\n {/* Which pipeline the board and table show, above them rather than under (AGL-3311). */}\n {activePipelines.length > 1 ? (\n <TextField\n select\n size=\"small\"\n label=\"Pipeline\"\n value={pipeline?.$id ?? ''}\n onChange={(event) => setPipelineId(event.target.value)}\n sx={{ minWidth: 160 }}\n slotProps={{ select: { 'aria-label': 'Pipeline' } }}\n >\n {activePipelines.map((entry) => (\n <MenuItem key={entry.$id} value={entry.$id}>\n {entry.name}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n <ToggleButtonGroup\n exclusive\n size=\"small\"\n color=\"primary\"\n value={view}\n onChange={(_event, next) => {\n if (next) setView(next as View)\n }}\n aria-label=\"View\"\n >\n <ToggleButton value=\"board\" aria-label=\"Board\">\n <MdiIcon path={mdiViewColumnOutline.path} size={0.8} />\n <Typography variant=\"button\" sx={{ ml: 0.5 }}>\n {'Board'}\n </Typography>\n </ToggleButton>\n <ToggleButton value=\"table\" aria-label=\"Table\">\n <MdiIcon path={mdiTableLarge.path} size={0.8} />\n <Typography variant=\"button\" sx={{ ml: 0.5 }}>\n {'Table'}\n </Typography>\n </ToggleButton>\n </ToggleButtonGroup>\n </Stack>\n\n {noOrg ? (\n <Alert severity=\"info\">\n {'This site has no organization, so it has no pipeline.'}\n </Alert>\n ) : pipelineState.status === 'error' ? (\n <Alert severity=\"warning\">\n {'The pipeline could not be read. Deals need the \"Manage data\" permission.'}\n </Alert>\n ) : pipelineLoading ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <CircularProgress size={18} />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {pipelineState.seeding ? 'Setting up your Sales pipeline…' : 'Loading the pipeline…'}\n </Typography>\n </Stack>\n ) : view === 'board' && pipeline ? (\n <>\n {open.status === 'success' && open.data.length === 0 ? (\n <EmptyStateComponent\n compact\n label={'No open deals yet'}\n description={'A deal is a sale in progress, moved across the stages below as it advances.'}\n action={\n <Button\n size=\"small\"\n variant=\"contained\"\n startIcon={<MdiIcon path={mdiPlus.path} size={0.8} />}\n disabled={!pipeline || !scope.orgId}\n onClick={() => setCreating(true)}\n >\n {'New deal'}\n </Button>\n }\n />\n ) : null}\n <DealBoard\n pipeline={pipeline}\n deals={open.data}\n won={closedExpanded && won.status !== 'loading' ? won.data : null}\n lost={closedExpanded && lost.status !== 'loading' ? lost.data : null}\n closedExpanded={closedExpanded}\n onToggleClosed={() => setClosedExpanded((current) => !current)}\n labelFor={roster.nameOf}\n moving={moving}\n onOpen={openDeal}\n onMove={handleMove}\n onWon={handleWon}\n onLost={handleLost}\n nowMs={nowMs}\n />\n </>\n ) : (\n <Stack spacing={1.5}>\n {/*\n The view this table is showing, and the clauses narrowing it\n as chips (AGL-2617, AGL-3313). Status and \"No next activity\"\n are set in the grid's own Filters panel.\n */}\n <CrmListToolbar label=\"Deal filters\">\n <CrmViewsControl controller={views} allLabel=\"All deals\" />\n <ListFilterChips\n fields={DEAL_GRID_FILTER_FIELDS}\n headers={DEAL_GRID_FILTER_HEADERS}\n clauses={viewFilters}\n onChange={views.setFilters}\n options={DEAL_FILTER_OPTIONS}\n marksServed={false}\n />\n </CrmListToolbar>\n <ListQueryNotices refused={refused} notices={paged.plan.notices} />\n <>\n <DealsBulkBar\n hostId={hostId}\n scope={scope.scope}\n rows={tableRows}\n selected={selectedIds}\n onSelectedChange={setSelectedIds}\n pipelineById={pipelineState.pipelineById}\n roster={roster}\n api={api}\n csv={csvOptions}\n />\n <CrmColumnOrderProvider value={grid.columnOrder}>\n <ListTable\n rows={tableRows}\n columns={grid.columns}\n slots={CRM_LIST_SLOTS}\n selectable={{ selected: selectedIds, onChange: setSelectedIds }}\n onOpen={(_id, row) => openDeal(row as DealDoc)}\n // The panel and the search are the query's (AGL-3321).\n filterMode=\"server\"\n filterModel={gridFilter.filterModel}\n onFilterModelChange={gridFilter.onFilterModelChange}\n quickFilter\n loading={paged.status === 'loading'}\n // An empty table is said inside the grid, so its toolbar\n // stays to change the status that emptied it.\n noRowsLabel={\n searching\n ? `No deals match “${searchKey.trim()}”`\n : statusFilter === 'all'\n ? 'No deals yet'\n : `No ${statusFilter} deals`\n }\n noRowsDescription={\n statusFilter === 'all' && !searching\n ? 'A deal is a sale in progress, moved across the pipeline as it advances.'\n : undefined\n }\n noRowsAction={\n statusFilter === 'all' && !searching ? (\n <Button\n size=\"small\"\n variant=\"contained\"\n startIcon={<MdiIcon path={mdiPlus.path} size={0.8} />}\n disabled={!pipeline || !scope.orgId}\n onClick={() => setCreating(true)}\n >\n {'New deal'}\n </Button>\n ) : undefined\n }\n // Columns and sort are the view's, controlled (AGL-2617).\n columnVisibilityModel={grid.columnVisibilityModel}\n onColumnVisibilityModelChange={grid.onColumnVisibilityModelChange}\n sortModel={grid.sortModel}\n onSortModelChange={grid.onSortModelChange}\n hideFooter\n />\n </CrmColumnOrderProvider>\n <ListPagination\n page={paged.page}\n pageSize={paged.pageSize}\n rowCount={paged.rows.length}\n hasMore={paged.hasMore}\n onPageChange={paged.setPage}\n onPageSizeChange={paged.setPageSize}\n />\n </>\n </Stack>\n )}\n </Stack>\n </CardDisplay>\n <DealEditDrawer\n open={creating}\n onClose={() => setCreating(false)}\n hostId={hostId}\n org={org}\n pipelines={activePipelines}\n defaultPipeline={pipeline}\n />\n <PipelinesDialog\n open={managingPipelines}\n onClose={() => setManagingPipelines(false)}\n orgId={scope.orgId ?? ''}\n // A pipeline made here is stamped the way the seeded default is\n // (`usePipeline`): the site's own tokens under a site; at the\n // organization level the org token, with the picked site as its\n // provenance (AGL-2630).\n hostId={scope.createHostId}\n pipelines={pipelineState.pipelines}\n fromCache={pipelineState.fromCache}\n unreadable={pipelineState.status === 'error'}\n visibleToTokens={scope.visibleTo}\n createTokens={scope.level === 'site' ? scope.createTokens : ORG_PIPELINE_TOKENS}\n />\n <LostReasonDialog\n open={Boolean(losing)}\n dealTitle={losing?.title ?? ''}\n onClose={() => setLosing(null)}\n onConfirm={confirmLost}\n />\n </>\n )\n}\nDealsSection.displayName = 'DealsSection'\n\nfunction Figure(props: { label: string; value: string }) {\n return (\n <Stack sx={{ lineHeight: 1.2 }}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {props.label}\n </Typography>\n <Typography variant=\"h6\" component=\"span\">\n {props.value}\n </Typography>\n </Stack>\n )\n}\nFigure.displayName = 'Figure'\n\nexport default DealsSection\n"],"names":["CRM_COLLECTIONS","dealStageById","findOrgMember","ORG_SCOPE_TOKEN","pluginDocsHelp","mdiCogOutline","mdiPlus","mdiTableLarge","mdiViewColumnOutline","CardDisplay","MdiIcon","ListPagination","ListTable","ListQueryNotices","listQueryRefusals","useCrmSavedView","useCrmViewGrid","CrmListActions","CrmListToolbar","CRM_LIST_SLOTS","CrmColumnOrderProvider","CRM_NEXT_ACTIVITY_FILTER_FIELD","CRM_NEXT_ACTIVITY_FILTER_HEADER","nextActivityColumn","DEAL_LIST_DECLARATION","DEAL_LIST_FILTER_FIELDS","DEAL_PREFIX_SEARCH","dealPipelineBase","useCrmFoldsScope","useCrmListQuery","ListFilterChips","listFilterGridColumns","useListGridFilter","CrmViewsControl","EmptyStateComponent","useSnackbar","Alert","Button","Chip","CircularProgress","MenuItem","Stack","TextField","ToggleButton","ToggleButtonGroup","Typography","useRouter","useCallback","useEffect","useMemo","useState","useContactFieldDefinitions","useCrmScope","useDealStageApi","BOARD_CLOSED_LIMIT","BOARD_OPEN_LIMIT","useDealsByStatus","useOrgMemberDirectory","usePipeline","downloadTextFile","crmRoutes","dealsCsv","boardSummary","DEAL_STATUS_LABELS","formatAmountByCurrency","formatMoney","customFieldColumns","DealBoard","DealEditDrawer","DealImportButton","DealsBulkBar","LostReasonDialog","OwnerAvatar","PipelinesDialog","DEAL_GRID_FILTER_FIELDS","DEAL_GRID_FILTER_HEADERS","status","column","DEAL_FILTER_OPTIONS","map","value","label","ORG_PIPELINE_TOKENS","DealsSection","props","pipelineId","scope","hostId","org","basePath","routes","router","enqueueSnackbar","pipelineState","orgId","activePipelines","setPipelineId","pipeline","find","entry","$id","roster","api","nowMs","Date","now","dealFields","view","setView","closedExpanded","setClosedExpanded","views","section","statusFilter","state","filters","clause","field","viewFilters","currentId","open","visibleTo","closedPipelineId","won","lost","searchWords","setSearchWords","searching","some","word","trim","searchKey","join","foldsScope","pipelineBase","paged","collection","deals","declaration","clauses","search","base","prefixSearch","enabled","Boolean","summary","data","moving","setMoving","Set","track","deal","request","done","current","add","variant","persist","error","Error","message","allowDuplicate","next","delete","handleMove","stageId","stage","moveToStage","name","handleWon","markWon","losing","setLosing","handleLost","confirmLost","reason","markLost","openDeal","push","creating","setCreating","managingPipelines","setManagingPipelines","selectedIds","setSelectedIds","plan","page","csvOptions","pipelineName","id","pipelineById","stageName","ownerEmail","uid","member","members","email","handleExport","rows","columns","headerName","flex","minWidth","renderCell","row","withWhom","contactName","companyName","filter","sx","justifyContent","lineHeight","title","color","noWrap","valueGetter","_value","align","headerAlign","amountCents","currency","nameOf","ownerUid","direction","spacing","alignItems","size","type","expectedCloseAtMs","toLocaleDateString","active","tableRows","filterColumns","grid","gridFilter","onChange","setFilters","selectFields","words","refused","fields","headers","options","noOrg","ready","pipelineLoading","seeding","header","help","anchor","contentGutterX","contentGutterY","HeaderProps","action","onClick","disabled","length","startIcon","path","flexWrap","rowGap","Figure","openCount","toLocaleString","valueByCurrency","weightedByCurrency","select","event","target","slotProps","exclusive","_event","aria-label","ml","severity","compact","description","onToggleClosed","labelFor","onOpen","onMove","onWon","onLost","controller","allLabel","marksServed","notices","selected","onSelectedChange","csv","columnOrder","slots","selectable","_id","filterMode","filterModel","onFilterModelChange","quickFilter","loading","noRowsLabel","noRowsDescription","undefined","noRowsAction","columnVisibilityModel","onColumnVisibilityModelChange","sortModel","onSortModelChange","hideFooter","pageSize","rowCount","hasMore","onPageChange","setPage","onPageSizeChange","setPageSize","onClose","pipelines","defaultPipeline","createHostId","fromCache","unreadable","visibleToTokens","createTokens","level","dealTitle","onConfirm","displayName","component"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAEA,SAGEA,eAAe,EACfC,aAAa,EACbC,aAAa,EACbC,eAAe,EACfC,cAAc,QACT,eAAc;AACrB,SACEC,aAAa,EACbC,OAAO,EACPC,aAAa,EACbC,oBAAoB,QACf,yBAAwB;AAC/B,SAASC,WAAW,EAAEC,OAAO,QAAQ,uBAAsB;AAC3D,SAASC,cAAc,QAAQ,4DAA2D;AAC1F,SAASC,SAAS,QAAQ,uDAAsD;AAChF,OAAOC,oBACLC,iBAAiB,QACZ,+DAA8D;AACrE,SAASC,eAAe,QAAQ,iCAA6B;AAC7D,SAASC,cAAc,QAAQ,gCAA4B;AAC3D,SAASC,cAAc,EAAEC,cAAc,QAAQ,wBAAoB;AACnE,SAASC,cAAc,EAAEC,sBAAsB,QAAQ,uBAAmB;AAC1E,SACEC,8BAA8B,EAC9BC,+BAA+B,EAC/BC,kBAAkB,QACb,gCAA4B;AACnC,SACEC,qBAAqB,EACrBC,uBAAuB,EACvBC,kBAAkB,EAClBC,gBAAgB,QACX,+BAA2B;AAClC,SAASC,gBAAgB,EAAEC,eAAe,QAAQ,iCAA6B;AAC/E,OAAOC,qBAAqB,8DAA6D;AACzF,SAASC,qBAAqB,QAAQ,8CAA6C;AACnF,SAASC,iBAAiB,QAAQ,kDAAiD;AACnF,OAAOC,qBAAqB,yBAAqB;AACjD,OAAOC,yBAAyB,wDAAuD;AACvF,SAASC,WAAW,QAAQ,8BAA6B;AACzD,SACEC,KAAK,EACLC,MAAM,EACNC,IAAI,EACJC,gBAAgB,EAChBC,QAAQ,EACRC,KAAK,EACLC,SAAS,EACTC,YAAY,EACZC,iBAAiB,EACjBC,UAAU,QACL,gBAAe;AAEtB,SAASC,SAAS,QAAQ,kBAAiB;AAC3C,SAASC,WAAW,EAAEC,SAAS,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAO;AACjE,SAASC,0BAA0B,QAAQ,4CAAwC;AACnF,SAASC,WAAW,QAAQ,4BAAwB;AACpD,SAASC,eAAe,QAAQ,iCAA6B;AAC7D,SACEC,kBAAkB,EAClBC,gBAAgB,EAChBC,gBAAgB,QACX,wBAAoB;AAC3B,SAASC,qBAAqB,QAAQ,uCAAmC;AACzE,SAASC,WAAW,QAAQ,2BAAuB;AACnD,SAASC,gBAAgB,QAAQ,2BAAuB;AACxD,SAASC,SAAS,QAAQ,yBAAqB;AAC/C,SAA8BC,QAAQ,QAAQ,wBAAoB;AAClE,SACEC,YAAY,EACZC,kBAAkB,EAElBC,sBAAsB,EACtBC,WAAW,QACN,+BAA2B;AAClC,SAASC,kBAAkB,QAAQ,8BAA0B;AAC7D,SAASC,SAAS,QAAQ,kBAAc;AACxC,SAASC,cAAc,QAAQ,wBAAoB;AACnD,SAASC,gBAAgB,QAAQ,0BAAsB;AACvD,OAAOC,kBAAkB,sBAAkB;AAC3C,SAASC,gBAAgB,QAAQ,0BAAsB;AACvD,SAASC,WAAW,QAAQ,oBAAgB;AAC5C,SAASC,eAAe,QAAQ,wBAAoB;AAKpD,6EAA6E,GAC7E,MAAMC,0BAA0BjD;AAChC,MAAMkD,2BAA6D;IACjEC,QAAQ;IACR,CAACvD,+BAA+BwD,MAAM,CAAC,EAAEvD;AAC3C;AACA,MAAMwD,sBAAsB;IAC1BF,QAAQ,AAAC;QAAC;QAAQ;QAAO;KAAO,CAAWG,GAAG,CAAC,CAACC,QAAW,CAAA;YACzDA;YACAC,OAAOlB,kBAAkB,CAACiB,MAAM;QAClC,CAAA;AACF;AAGA,0FAA0F,GAC1F,MAAME,sBAAyC;IAAC/E;CAAgB;AAEhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CC,GACD,OAAO,SAASgF,aAAaC,KAA6B;QAgBrDC,2BAyhBUC;IAxiBb,MAAM,EAAEC,MAAM,EAAEC,GAAG,EAAEC,QAAQ,EAAE,GAAGL;IAClC,MAAMM,SAAS9B,UAAU6B,mBAAAA,WAAY;IACrC,MAAME,SAAS7C;IACf,MAAM,EAAE8C,eAAe,EAAE,GAAGzD;IAC5B,MAAMmD,QAAQlC,YAAY;QAAEmC;QAAQC;IAAI;IACxC,MAAMK,gBAAgBnC,YAAY4B,MAAMQ,KAAK,EAAE;QAC7CP;QACAC,GAAG,EAAGA,cAAAA,MAAO;IACf;IACA,MAAM,EAAEO,eAAe,EAAE,GAAGF;IAC5B,MAAM,CAACR,YAAYW,cAAc,GAAG9C,SAAwB;IAC5D,oEAAoE;IACpE,wEAAwE;IACxE,kDAAkD;IAClD,MAAM+C,YACHZ,OAAAA,aAAaU,gBAAgBG,IAAI,CAAC,CAACC,QAAUA,MAAMC,GAAG,KAAKf,cAAc,gBAAzEA,OACDQ,cAAcI,QAAQ;IACxB,MAAMI,SAAS5C,sBAAsB6B,MAAMQ,KAAK;IAChD,MAAMQ,MAAMjD,gBAAgBkC;IAC5B,MAAMgB,QAAQtD,QAAQ,IAAMuD,KAAKC,GAAG,IAAI,EAAE;IAC1C,sEAAsE;IACtE,MAAMC,aAAavD,2BAA2BmC,MAAMQ,KAAK,EAAE;IAE3D,MAAM,CAACa,MAAMC,QAAQ,GAAG1D,SAAe;IACvC,MAAM,CAAC2D,gBAAgBC,kBAAkB,GAAG5D,SAAS;IACrD;;;;;GAKC,GACD,MAAM6D,QAAQhG,gBAAgB;QAC5BiG,SAAS;QACTzB;QACAC;QACAC,QAAQ,EAAEA,mBAAAA,WAAY;IACxB;IACA,MAAMwB,eAA6BhE,QAAQ;YAC3B8D;QAAd,MAAM/B,SAAQ+B,4BAAAA,MAAMG,KAAK,CAACC,OAAO,CAACjB,IAAI,CAAC,CAACkB,SAAWA,OAAOC,KAAK,KAAK,8BAAtDN,0BAAiE/B,KAAK;QACpF,OAAOA,UAAU,UAAUA,UAAU,SAASA,UAAU,SAASA,QAAQ;IAC3E,GAAG;QAAC+B,MAAMG,KAAK,CAACC,OAAO;KAAC;IACxB,wEAAwE;IACxE,MAAMG,cAAcP,MAAMG,KAAK,CAACC,OAAO;IACvCnE,UAAU;QACR,IAAI+D,MAAMQ,SAAS,EAAEX,QAAQ;IAC/B,GAAG;QAACG,MAAMQ,SAAS;KAAC;IAEpB,0EAA0E;IAC1E,gEAAgE;IAChE,MAAMC,OAAOhE,iBACX8B,MAAMQ,KAAK,EACXR,MAAMmC,SAAS,WACfxB,4BAAAA,SAAUG,GAAG,oBAAI,MACjB,QACA7C;IAEF,MAAMmE,mBACJf,SAAS,WAAWE,0BAAkBZ,4BAAAA,SAAUG,GAAG,oBAAI,OAAQ;IACjE,MAAMuB,MAAMnE,iBAAiB8B,MAAMQ,KAAK,EAAER,MAAMmC,SAAS,EAAEC,kBAAkB,OAAOpE;IACpF,MAAMsE,OAAOpE,iBAAiB8B,MAAMQ,KAAK,EAAER,MAAMmC,SAAS,EAAEC,kBAAkB,QAAQpE;IACtF;;;;;GAKC,GACD,MAAM,CAACuE,aAAaC,eAAe,GAAG5E,SAAmB,EAAE;IAC3D,MAAM6E,YAAYF,YAAYG,IAAI,CAAC,CAACC,OAASA,KAAKC,IAAI;IACtD,MAAMC,YAAYN,YAAYO,IAAI,CAAC;IACnC,MAAMC,aAAazG,iBAAiB0D,MAAMQ,KAAK,EAAER,MAAMmC,SAAS;IAChE,MAAMa,eAAerF,QAAQ;;eAAMtB,yBAAiBsE,4BAAAA,SAAUG,GAAG,mBAAI;OAAO;QAACH,4BAAAA,SAAUG,GAAG;KAAC;IAC3F,MAAMmC,QAAQ1G,gBAAyB;QACrCyD,OAAOA,MAAMA,KAAK;QAClBkD,YAAYxI,gBAAgByI,KAAK;QACjChB,WAAWnC,MAAMmC,SAAS;QAC1BY;QACAK,aAAalH;QACbmH,SAASrB;QACTsB,QAAQf;QACRgB,MAAMP;QACNQ,cAAcpH;QACdqH,SAASpC,SAAS,WAAWqC,QAAQ/C;IACvC;IAEA,MAAMgD,UAAUhG,QAAQ,IAAMa,aAAa0D,KAAK0B,IAAI,EAAEjD,WAAW;QAACuB,KAAK0B,IAAI;QAAEjD;KAAS;IAEtF;;;GAGC,GACD,MAAM,CAACkD,QAAQC,UAAU,GAAGlG,SAA8B,IAAM,IAAImG;IACpE,MAAMC,QAAQvG,YACZ,OAAOwG,MAAeC,SAAiCC;QACrDL,UAAU,CAACM,UAAY,IAAIL,IAAIK,SAASC,GAAG,CAACJ,KAAKnD,GAAG;QACpD,IAAI;YACF,MAAMoD;YACN5D,gBAAgB6D,MAAM;gBAAEG,SAAS;gBAAWC,SAAS;YAAM;YAC3D,OAAO;QACT,EAAE,OAAOC,OAAO;YACdlE,gBACEkE,iBAAiBC,QAAQD,MAAME,OAAO,GAAG,gCACzC;gBAAEJ,SAAS;gBAAWK,gBAAgB;YAAK;YAE7C,OAAO;QACT,SAAU;YACRb,UAAU,CAACM;gBACT,MAAMQ,OAAO,IAAIb,IAAIK;gBACrBQ,KAAKC,MAAM,CAACZ,KAAKnD,GAAG;gBACpB,OAAO8D;YACT;QACF;IACF,GACA;QAACtE;KAAgB;IAEnB,MAAMwE,aAAarH,YACjB,CAACwG,MAAec;;QACd,MAAMC,QAAQrK,cAAcgG,UAAUoE;QACtC,KAAKf,MACHC,MACA,IAAMjD,IAAIiE,WAAW,CAAChB,MAAMc,UAC5B,CAAC,SAAS,UAAEC,yBAAAA,MAAOE,IAAI,mBAAI,SAAS;IAExC,GACA;QAAClE;QAAKL;QAAUqD;KAAM;IAExB,MAAMmB,YAAY1H,YAChB,CAACwG,OAAkB,KAAKD,MAAMC,MAAM,IAAMjD,IAAIoE,OAAO,CAACnB,OAAO,aAC7D;QAACjD;QAAKgD;KAAM;IAEd,MAAM,CAACqB,QAAQC,UAAU,GAAG1H,SAAyB;IACrD,MAAM2H,aAAa9H,YAAY,CAACwG,OAAkBqB,UAAUrB,OAAO,EAAE;IACrE,MAAMuB,cAAc/H,YAClB,CAACgI;QACC,MAAMxB,OAAOoB;QACb,IAAI,CAACpB,MAAM;QACXqB,UAAU;QACV,KAAKtB,MAAMC,MAAM,IAAMjD,IAAI0E,QAAQ,CAACzB,MAAMwB,SAAS;IACrD,GACA;QAACzE;QAAKqE;QAAQrB;KAAM;IAGtB,MAAM2B,WAAWlI,YACf,CAACwG,OAAkB5D,OAAOuF,IAAI,CAACxF,OAAO6D,IAAI,CAACA,KAAKnD,GAAG,IACnD;QAACT;QAAQD;KAAO;IAGlB,MAAM,CAACyF,UAAUC,YAAY,GAAGlI,SAAS;IACzC,MAAM,CAACmI,mBAAmBC,qBAAqB,GAAGpI,SAAS;IAE3D,MAAM,CAACqI,aAAaC,eAAe,GAAGtI,SAAmB,EAAE;IAC3D,qEAAqE;IACrE,+DAA+D;IAC/DF,UAAU,IAAMwI,eAAe,EAAE,GAAG;QAACjD,MAAMkD,IAAI;QAAElD,MAAMmD,IAAI;KAAC;IAC5D,MAAMC,aAA6B1I,QACjC,IAAO,CAAA;YACL2I,cAAc,CAACC;oBAAOhG;wBAAAA,8BAAAA,cAAciG,YAAY,CAACD,wBAA3BhG,4BAAgC2E,IAAI;;YAC1DuB,WAAW,CAAC1G,YAAYgF;oBACtBpK;wBAAAA,iBAAAA,cAAc4F,cAAciG,YAAY,CAACzG,aAAagF,6BAAtDpK,eAAgEuK,IAAI;;YACtEwB,YAAY,CAACC;gBACX,MAAMC,SAAShM,cAAcmG,OAAO8F,OAAO,EAAEF;gBAC7C,OAAOC,CAAAA,0BAAAA,OAAQE,KAAK,MAAIF,0BAAAA,OAAQjH,KAAK,KAAIgH;YAC3C;QACF,CAAA,GACA;QAACpG;QAAeQ,OAAO8F,OAAO;KAAC;IAEjC,uEAAuE;IACvE,MAAME,eAAetJ,YAAY;QAC/BY,iBAAiB,aAAa,YAAYE,SAAS0E,MAAM+D,IAAI,EAAEX;IACjE,GAAG;QAACpD,MAAM+D,IAAI;QAAEX;KAAW;IAE3B,MAAMY,UAAwBtJ,QAC5B,IAAM;YACJ;gBACEoE,OAAO;gBACPmF,YAAY;gBACZC,MAAM;gBACNC,UAAU;gBACVC,YAAY,CAAC,EAAEC,GAAG,EAAoB;oBACpC,MAAMC,WAAW;wBAACD,IAAIE,WAAW;wBAAEF,IAAIG,WAAW;qBAAC,CAACC,MAAM,CAAChE,SAASZ,IAAI,CAAC;oBACzE,qBACE,MAAC3F;wBAAMwK,IAAI;4BAAEC,gBAAgB;4BAAUC,YAAY;wBAAK;;0CACtD,KAACtK;gCAAW+G,SAAQ;gCAAQqD,IAAI;oCAAEE,YAAY;gCAAK;0CAChDP,IAAIQ,KAAK,IAAI;;4BAEfP,yBACC,KAAChK;gCAAW+G,SAAQ;gCAAUyD,OAAM;gCAAiBC,MAAM;gCAACL,IAAI;oCAAEE,YAAY;gCAAK;0CAChFN;iCAED;;;gBAGV;YACF;YACA;gBACExF,OAAO;gBACPmF,YAAY;gBACZC,MAAM;gBACNC,UAAU;gBACVa,aAAa,CAACC,QAAiBZ;;wBAC7B3M;oCAAAA,iBAAAA,cAAc4F,cAAciG,YAAY,CAACc,IAAIvH,UAAU,GAAGuH,IAAIvC,OAAO,sBAArEpK,eAAwEuK,IAAI,mBAC5EoC,IAAIvC,OAAO;;YACf;YACA;gBACEhD,OAAO;gBACPmF,YAAY;gBACZC,MAAM;gBACNC,UAAU;gBACVe,OAAO;gBACPC,aAAa;gBACbH,aAAa,CAACC,QAAiBZ;wBAAiBA;4BAAAA,mBAAAA,IAAIe,WAAW,YAAff,mBAAmB;;gBACnED,YAAY,CAAC,EAAEC,GAAG,EAAoB,GACpC,OAAOA,IAAIe,WAAW,KAAK,WAAW1J,YAAY2I,IAAIe,WAAW,EAAEf,IAAIgB,QAAQ,IAAI;YACvF;YACA;gBACEvG,OAAO;gBACPmF,YAAY;gBACZC,MAAM;gBACNC,UAAU;gBACVa,aAAa,CAACC,QAAiBZ,MAAiBvG,OAAOwH,MAAM,CAACjB,IAAIkB,QAAQ;gBAC1EnB,YAAY,CAAC,EAAEC,GAAG,EAAoB;oBACpC,MAAM3H,QAAQoB,OAAOwH,MAAM,CAACjB,IAAIkB,QAAQ;oBACxC,OAAO7I,sBACL,MAACxC;wBAAMsL,WAAU;wBAAMC,SAAS;wBAAGf,IAAI;4BAAEgB,YAAY;wBAAS;;0CAC5D,KAACzJ;gCAAYS,OAAOA;gCAAOiJ,MAAM;;0CACjC,KAACrL;gCAAW+G,SAAQ;gCAAQ0D,MAAM;0CAC/BrI;;;uCAIL,KAACpC;wBAAW+G,SAAQ;wBAAQyD,OAAM;kCAC/B;;gBAGP;YACF;YACA;gBACEhG,OAAO;gBACPmF,YAAY;gBACZC,MAAM;gBACNC,UAAU;gBACVyB,MAAM;gBACNZ,aAAa,CAACC,QAAiBZ,MAC7B,OAAOA,IAAIwB,iBAAiB,KAAK,WAAW,IAAI5H,KAAKoG,IAAIwB,iBAAiB,IAAI;gBAChFzB,YAAY,CAAC,EAAEC,GAAG,EAAoB,GACpC,OAAOA,IAAIwB,iBAAiB,KAAK,WAC7B,IAAI5H,KAAKoG,IAAIwB,iBAAiB,EAAEC,kBAAkB,KAClD;YACR;YACA;gBACEhH,OAAO;gBACPmF,YAAY;gBACZC,MAAM;gBACNC,UAAU;gBACVC,YAAY,CAAC,EAAEC,GAAG,EAAoB;wBAG3B7I;yCAFT,KAACzB;wBACC4L,MAAK;wBACLjJ,KAAK,GAAElB,iCAAAA,kBAAkB,CAAC6I,IAAIhI,MAAM,CAAC,YAA9Bb,iCAAkC6I,IAAIhI,MAAM;wBACnDyI,OAAOT,IAAIhI,MAAM,KAAK,QAAQ,YAAYgI,IAAIhI,MAAM,KAAK,SAAS,YAAY;wBAC9EgF,SAASgD,IAAIhI,MAAM,KAAK,SAAS,aAAa;;;YAGpD;YACA,kEAAkE;YAClErD,mBAAmBgF;YACnB,wDAAwD;eACrDrC,mBAAmBwC,WAAW4H,MAAM;SACxC,EACD;QAACzI;QAAeQ;QAAQK,WAAW4H,MAAM;QAAE/H;KAAM;IAEnD,wCAAwC,GACxC,MAAMgI,YAAYhG,MAAM+D,IAAI;IAC5B;;;;GAIC,GACD,MAAMkC,gBAAgBvL,QACpB,IAAMlB,sBAAsBwK,SAAS7H,yBAAyBI,qBAAqBH,2BACnF;QAAC4H;KAAQ;IAEX,MAAMkC,OAAOzN,eAAe+F,OAAOyH;IACnC,MAAME,aAAa1M,kBAAkB;QACnC2G,SAASrB;QACTqH,UAAU5H,MAAM6H,UAAU;QAC1BC,cAAc;YAAC;SAAS;QACxBjG,QAAQ;YAAEkG,OAAOjH;YAAa8G,UAAU7G;QAAe;IACzD;IACA,qEAAqE;IACrE,MAAMiH,UAAU9L,QACd,IACEnC,kBAAkByH,MAAMkD,IAAI,CAACsD,OAAO,EAAE;YACpCC,QAAQtK;YACRuK,SAAStK;YACTuK,SAASpK;QACX,IACF;QAACyD,MAAMkD,IAAI,CAACsD,OAAO;KAAC;IAGtB,MAAMI,QAAQ7J,MAAM8J,KAAK,IAAI,CAAC9J,MAAMQ,KAAK;IACzC,MAAMuJ,kBACJ,CAACF,SAAUtJ,CAAAA,cAAcjB,MAAM,KAAK,aAAaiB,cAAcyJ,OAAO,IAAK,CAACrJ,YAAYJ,cAAcjB,MAAM,KAAK,OAAO;IAE1H,qBACE;;0BACE,KAACnE;gBACC8O,QAAQ;gBACRC,MAAMpP,eAAe,SAAS;oBAAEqP,QAAQ;gBAA2B;gBACnEC,cAAc;gBACdC,cAAc;gBACdC,aAAa;oBACX,8DAA8D;oBAC9DC,sBACE,MAAC5O;;0CACC,KAACoD;gCAAiBkB,QAAQA;;4BAEzBoB,SAAS,wBACR,KAACtE;gCACC6L,MAAK;gCACL4B,SAASzD;gCACT0D,UAAU,CAACxH,MAAM+D,IAAI,CAAC0D,MAAM;0CAE3B;iCAED;0CACJ,KAAC3N;gCACC6L,MAAK;gCACL+B,yBAAW,KAACvP;oCAAQwP,MAAM7P,cAAc6P,IAAI;oCAAEhC,MAAM;;gCACpD6B,UAAU,CAACzK,MAAMQ,KAAK,IAAID,cAAcjB,MAAM,KAAK;gCACnDkL,SAAS,IAAMxE,qBAAqB;0CAEnC;;0CAEH,KAACjJ;gCACC6L,MAAK;gCACLtE,SAAQ;gCACRqG,yBAAW,KAACvP;oCAAQwP,MAAM5P,QAAQ4P,IAAI;oCAAEhC,MAAM;;gCAC9C6B,UAAU,CAAC9J,YAAY,CAACX,MAAMQ,KAAK;gCACnCgK,SAAS,IAAM1E,YAAY;0CAE1B;;;;gBAIT;0BAEA,cAAA,MAAC3I;oBAAMuL,SAAS;;sCACd,MAACvL;4BACCsL,WAAU;4BACVC,SAAS;4BACTf,IAAI;gCAAEgB,YAAY;gCAAYkC,UAAU;gCAAQC,QAAQ;4BAAE;;8CAE1D,KAACC;oCAAOpL,OAAM;oCAAaD,OAAOiE,QAAQqH,SAAS,CAACC,cAAc;;8CAClE,KAACF;oCAAOpL,OAAM;oCAAiBD,OAAOhB,uBAAuBiF,QAAQuH,eAAe;;8CACpF,KAACH;oCAAOpL,OAAM;oCAAiBD,OAAOhB,uBAAuBiF,QAAQwH,kBAAkB;;8CACvF,KAAChO;oCAAMwK,IAAI;wCAAER,MAAM;oCAAE;;gCAEpB1G,gBAAgBiK,MAAM,GAAG,kBACxB,KAACtN;oCACCgO,MAAM;oCACNxC,MAAK;oCACLjJ,OAAM;oCACND,KAAK,WAAEiB,4BAAAA,SAAUG,GAAG,oBAAI;oCACxBuI,UAAU,CAACgC,QAAU3K,cAAc2K,MAAMC,MAAM,CAAC5L,KAAK;oCACrDiI,IAAI;wCAAEP,UAAU;oCAAI;oCACpBmE,WAAW;wCAAEH,QAAQ;4CAAE,cAAc;wCAAW;oCAAE;8CAEjD3K,gBAAgBhB,GAAG,CAAC,CAACoB,sBACpB,KAAC3D;4CAAyBwC,OAAOmB,MAAMC,GAAG;sDACvCD,MAAMqE,IAAI;2CADErE,MAAMC,GAAG;qCAK1B;8CACJ,MAACxD;oCACCkO,SAAS;oCACT5C,MAAK;oCACLb,OAAM;oCACNrI,OAAO2B;oCACPgI,UAAU,CAACoC,QAAQ7G;wCACjB,IAAIA,MAAMtD,QAAQsD;oCACpB;oCACA8G,cAAW;;sDAEX,MAACrO;4CAAaqC,OAAM;4CAAQgM,cAAW;;8DACrC,KAACtQ;oDAAQwP,MAAM1P,qBAAqB0P,IAAI;oDAAEhC,MAAM;;8DAChD,KAACrL;oDAAW+G,SAAQ;oDAASqD,IAAI;wDAAEgE,IAAI;oDAAI;8DACxC;;;;sDAGL,MAACtO;4CAAaqC,OAAM;4CAAQgM,cAAW;;8DACrC,KAACtQ;oDAAQwP,MAAM3P,cAAc2P,IAAI;oDAAEhC,MAAM;;8DACzC,KAACrL;oDAAW+G,SAAQ;oDAASqD,IAAI;wDAAEgE,IAAI;oDAAI;8DACxC;;;;;;;;wBAMR9B,sBACC,KAAC/M;4BAAM8O,UAAS;sCACb;6BAEDrL,cAAcjB,MAAM,KAAK,wBAC3B,KAACxC;4BAAM8O,UAAS;sCACb;6BAED7B,gCACF,MAAC5M;4BAAMsL,WAAU;4BAAMC,SAAS;4BAAGf,IAAI;gCAAEgB,YAAY;4BAAS;;8CAC5D,KAAC1L;oCAAiB2L,MAAM;;8CACxB,KAACrL;oCAAW+G,SAAQ;oCAAQyD,OAAM;8CAC/BxH,cAAcyJ,OAAO,GAAG,oCAAoC;;;6BAG/D3I,SAAS,WAAWV,yBACtB;;gCACGuB,KAAK5C,MAAM,KAAK,aAAa4C,KAAK0B,IAAI,CAAC8G,MAAM,KAAK,kBACjD,KAAC9N;oCACCiP,OAAO;oCACPlM,OAAO;oCACPmM,aAAa;oCACbvB,sBACE,KAACxN;wCACC6L,MAAK;wCACLtE,SAAQ;wCACRqG,yBAAW,KAACvP;4CAAQwP,MAAM5P,QAAQ4P,IAAI;4CAAEhC,MAAM;;wCAC9C6B,UAAU,CAAC9J,YAAY,CAACX,MAAMQ,KAAK;wCACnCgK,SAAS,IAAM1E,YAAY;kDAE1B;;qCAIL;8CACJ,KAACjH;oCACC8B,UAAUA;oCACVwC,OAAOjB,KAAK0B,IAAI;oCAChBvB,KAAKd,kBAAkBc,IAAI/C,MAAM,KAAK,YAAY+C,IAAIuB,IAAI,GAAG;oCAC7DtB,MAAMf,kBAAkBe,KAAKhD,MAAM,KAAK,YAAYgD,KAAKsB,IAAI,GAAG;oCAChErC,gBAAgBA;oCAChBwK,gBAAgB,IAAMvK,kBAAkB,CAAC4C,UAAY,CAACA;oCACtD4H,UAAUjL,OAAOwH,MAAM;oCACvB1E,QAAQA;oCACRoI,QAAQtG;oCACRuG,QAAQpH;oCACRqH,OAAOhH;oCACPiH,QAAQ7G;oCACRtE,OAAOA;;;2CAIX,MAAC9D;4BAAMuL,SAAS;;8CAMd,MAAC9M;oCAAe+D,OAAM;;sDACpB,KAAChD;4CAAgB0P,YAAY5K;4CAAO6K,UAAS;;sDAC7C,KAAC9P;4CACCkN,QAAQtK;4CACRuK,SAAStK;4CACTgE,SAASrB;4CACTqH,UAAU5H,MAAM6H,UAAU;4CAC1BM,SAASpK;4CACT+M,aAAa;;;;8CAGjB,KAAChR;oCAAiBkO,SAASA;oCAAS+C,SAASvJ,MAAMkD,IAAI,CAACqG,OAAO;;8CAC7D;;sDACE,KAACxN;4CACCiB,QAAQA;4CACRD,OAAOA,MAAMA,KAAK;4CAClBgH,MAAMiC;4CACNwD,UAAUxG;4CACVyG,kBAAkBxG;4CAClBM,cAAcjG,cAAciG,YAAY;4CACxCzF,QAAQA;4CACRC,KAAKA;4CACL2L,KAAKtG;;sDAEP,KAACvK;4CAAuB4D,OAAOyJ,KAAKyD,WAAW;sDAC7C,cAAA,KAACtR;gDACC0L,MAAMiC;gDACNhC,SAASkC,KAAKlC,OAAO;gDACrB4F,OAAOhR;gDACPiR,YAAY;oDAAEL,UAAUxG;oDAAaoD,UAAUnD;gDAAe;gDAC9D+F,QAAQ,CAACc,KAAKzF,MAAQ3B,SAAS2B;gDAC/B,uDAAuD;gDACvD0F,YAAW;gDACXC,aAAa7D,WAAW6D,WAAW;gDACnCC,qBAAqB9D,WAAW8D,mBAAmB;gDACnDC,WAAW;gDACXC,SAASnK,MAAM3D,MAAM,KAAK;gDAC1B,yDAAyD;gDACzD,8CAA8C;gDAC9C+N,aACE5K,YACI,CAAC,gBAAgB,EAAEI,UAAUD,IAAI,GAAG,CAAC,CAAC,GACtCjB,iBAAiB,QACf,iBACA,CAAC,GAAG,EAAEA,aAAa,MAAM,CAAC;gDAElC2L,mBACE3L,iBAAiB,SAAS,CAACc,YACvB,4EACA8K;gDAENC,cACE7L,iBAAiB,SAAS,CAACc,0BACzB,KAAC1F;oDACC6L,MAAK;oDACLtE,SAAQ;oDACRqG,yBAAW,KAACvP;wDAAQwP,MAAM5P,QAAQ4P,IAAI;wDAAEhC,MAAM;;oDAC9C6B,UAAU,CAAC9J,YAAY,CAACX,MAAMQ,KAAK;oDACnCgK,SAAS,IAAM1E,YAAY;8DAE1B;qDAEDyH;gDAEN,0DAA0D;gDAC1DE,uBAAuBtE,KAAKsE,qBAAqB;gDACjDC,+BAA+BvE,KAAKuE,6BAA6B;gDACjEC,WAAWxE,KAAKwE,SAAS;gDACzBC,mBAAmBzE,KAAKyE,iBAAiB;gDACzCC,UAAU;;;sDAGd,KAACxS;4CACC+K,MAAMnD,MAAMmD,IAAI;4CAChB0H,UAAU7K,MAAM6K,QAAQ;4CACxBC,UAAU9K,MAAM+D,IAAI,CAAC0D,MAAM;4CAC3BsD,SAAS/K,MAAM+K,OAAO;4CACtBC,cAAchL,MAAMiL,OAAO;4CAC3BC,kBAAkBlL,MAAMmL,WAAW;;;;;;;;;0BAOjD,KAACtP;gBACCoD,MAAM2D;gBACNwI,SAAS,IAAMvI,YAAY;gBAC3B7F,QAAQA;gBACRC,KAAKA;gBACLoO,WAAW7N;gBACX8N,iBAAiB5N;;0BAEnB,KAACxB;gBACC+C,MAAM6D;gBACNsI,SAAS,IAAMrI,qBAAqB;gBACpCxF,KAAK,GAAER,eAAAA,MAAMQ,KAAK,YAAXR,eAAe;gBACtB,gEAAgE;gBAChE,8DAA8D;gBAC9D,gEAAgE;gBAChE,yBAAyB;gBACzBC,QAAQD,MAAMwO,YAAY;gBAC1BF,WAAW/N,cAAc+N,SAAS;gBAClCG,WAAWlO,cAAckO,SAAS;gBAClCC,YAAYnO,cAAcjB,MAAM,KAAK;gBACrCqP,iBAAiB3O,MAAMmC,SAAS;gBAChCyM,cAAc5O,MAAM6O,KAAK,KAAK,SAAS7O,MAAM4O,YAAY,GAAGhP;;0BAE9D,KAACX;gBACCiD,MAAMwB,QAAQ2B;gBACdyJ,SAAS,WAAEzJ,0BAAAA,OAAQyC,KAAK,oBAAI;gBAC5BuG,SAAS,IAAM/I,UAAU;gBACzByJ,WAAWvJ;;;;AAInB;AACA3F,aAAamP,WAAW,GAAG;AAE3B,SAASjE,OAAOjL,KAAuC;IACrD,qBACE,MAAC3C;QAAMwK,IAAI;YAAEE,YAAY;QAAI;;0BAC3B,KAACtK;gBAAW+G,SAAQ;gBAAUyD,OAAM;0BACjCjI,MAAMH,KAAK;;0BAEd,KAACpC;gBAAW+G,SAAQ;gBAAK2K,WAAU;0BAChCnP,MAAMJ,KAAK;;;;AAIpB;AACAqL,OAAOiE,WAAW,GAAG;AAErB,eAAenP,aAAY"}
1
+ {"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/deals-section.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n type ConsolePluginPageProps,\n type CrmDealStatus,\n type CrmPicklist,\n CRM_COLLECTIONS,\n crmPicklistRank,\n dealStageById,\n ORG_SCOPE_TOKEN,\n pluginDocsHelp,\n} from '@aglyn/aglyn'\nimport {\n mdiCogOutline,\n mdiPlus,\n mdiTableLarge,\n mdiViewColumnOutline,\n} from '@aglyn/shared-data-mdi'\nimport { CardDisplay, MdiIcon } from '@aglyn/shared-ui-jsx'\nimport { ListPagination } from '@aglyn/shared-ui-jsx/components/list-pagination.component'\nimport { ListTable } from '@aglyn/shared-ui-jsx/components/list-table.component'\nimport ListQueryNotices from '@aglyn/shared-ui-jsx/components/list-query-notices.component'\nimport { useCrmSavedView } from '../hooks/use-crm-saved-view'\nimport { useCrmViewGrid } from '../hooks/use-crm-view-grid'\nimport { CrmListActions, CrmListToolbar } from './crm-list-toolbar'\nimport { CRM_LIST_SLOTS, CrmColumnOrderProvider } from './crm-column-menu'\nimport {\n CRM_NEXT_ACTIVITY_FILTER_FIELD,\n CRM_NEXT_ACTIVITY_FILTER_HEADER,\n nextActivityColumn,\n} from './crm-next-activity-column'\nimport {\n DEAL_FILTER_CODECS,\n DEAL_LIST_DECLARATION,\n DEAL_LIST_FILTER_FIELDS,\n DEAL_PICKLIST_FILTER_NONE,\n DEAL_PREFIX_SEARCH,\n dealPipelineBase,\n dealQueryClause,\n} from '../constants/deal-filters'\nimport { useCrmFoldsScope, useCrmListQuery } from '../hooks/use-crm-list-query'\nimport { useCrmPicklist } from '../hooks/use-crm-picklist'\nimport { crmAskClauses, crmQueryRefusals } from '../model/crm-list-query'\nimport ListFilterChips from '@aglyn/shared-ui-jsx/components/list-filter-chips.component'\nimport {\n type ListFilterOption,\n listFilterGridColumns,\n} from '@aglyn/shared-ui-jsx/const/list-grid-filter'\nimport { useListGridFilter } from '@aglyn/shared-ui-jsx/hooks/use-list-grid-filter'\nimport CrmViewsControl from './crm-views-control'\nimport EmptyStateComponent from '@aglyn/shared-ui-jsx/components/empty-state.component'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport {\n Alert,\n Button,\n Chip,\n CircularProgress,\n MenuItem,\n Stack,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n} from '@mui/material'\nimport type { GridColDef } from '@mui/x-data-grid'\nimport { useRouter } from 'next/navigation'\nimport { useCallback, useEffect, useMemo, useState } from 'react'\nimport { useContactFieldDefinitions } from '../hooks/use-contact-field-definitions'\nimport { useCrmScope } from '../hooks/use-crm-scope'\nimport { useDealStageApi } from '../hooks/use-deal-stage-api'\nimport {\n BOARD_CLOSED_LIMIT,\n BOARD_OPEN_LIMIT,\n useDealsByStatus,\n} from '../hooks/use-deals'\nimport { useOrgMemberDirectory } from '../hooks/use-org-member-directory'\nimport { usePipeline } from '../hooks/use-pipeline'\nimport { crmRoutes } from '../model/crm-routes'\nimport {\n boardSummary,\n DEAL_STATUS_LABELS,\n type DealDoc,\n formatAmountByCurrency,\n formatMoney,\n} from '../model/deal-board-model'\nimport { customFieldColumns } from './contact-custom-columns'\nimport { DealBoard } from './deal-board'\nimport { DealEditDrawer } from './deal-edit-drawer'\nimport { CrmExportButton, CrmImportButton } from './crm-transfer-buttons'\nimport { CRM_DEALS_RESOURCE } from '../transfer/fields'\nimport DealsBulkBar from './deals-bulk-bar'\nimport { LostReasonDialog } from './lost-reason-dialog'\nimport { OwnerAvatar } from './owner-avatar'\nimport { PipelinesDialog } from './pipelines-dialog'\n\ntype View = 'board' | 'table'\ntype StatusFilter = CrmDealStatus | 'all'\n\n/** What the deals table's panel offers: the status, \"No next activity\", the Type and the Lead source. */\nconst DEAL_GRID_FILTER_FIELDS = DEAL_LIST_FILTER_FIELDS\nconst DEAL_GRID_FILTER_HEADERS: Readonly<Record<string, string>> = {\n status: 'Status',\n [CRM_NEXT_ACTIVITY_FILTER_FIELD.column]: CRM_NEXT_ACTIVITY_FILTER_HEADER,\n type: 'Type',\n leadSource: 'Lead source',\n}\nconst DEAL_STATUS_FILTER_OPTIONS = (['open', 'won', 'lost'] as const).map((value) => ({\n value,\n label: DEAL_STATUS_LABELS[value],\n}))\n\n/** Salesforce's Type and Lead source columns are offered, not shown, until a view turns them on (AGL-3516). */\nconst DEAL_HIDDEN_COLUMNS: Readonly<Record<string, boolean>> = { type: false, leadSource: false }\n\n/** A picklist's choices for its filter: every value the org keeps, inactive ones marked, then \"none\". */\nfunction picklistFilterOptions(picklist: CrmPicklist, none: string): ListFilterOption[] {\n return [\n ...picklist.values.map((value) => ({\n value: value.label,\n label: value.active ? value.label : `${value.label} (inactive)`,\n })),\n { value: DEAL_PICKLIST_FILTER_NONE, label: none },\n ]\n}\n\n\n/** What a pipeline made at the organization level is stamped with — the org's own token. */\nconst ORG_PIPELINE_TOKENS: readonly string[] = [ORG_SCOPE_TOKEN]\n\n/**\n * `/crm/deals` — the pipeline (AGL-2598).\n *\n * ## Two views of one pipeline\n *\n * The BOARD is one pipeline's open deals, one column per open stage, read\n * in one bounded listener over `(visibleTo, pipelineId, status, updatedAt)`\n * and sorted into columns here — a listener per column would be five\n * subscriptions for one board. The TABLE is the same pipeline's deals,\n * paged by a query that carries its status, \"No next activity\" and search\n * word (AGL-3321); it is where the closed history is found. The three figures above both come from the board's read, so\n * they describe what is in play whichever view is showing.\n *\n * ## Which pipeline\n *\n * The switcher in the header (AGL-2620) picks among the ACTIVE pipelines\n * and opens on the default; the board, the table, the figures and the New\n * deal drawer all follow it. It is section state rather than a route: a\n * pipeline is a lens on the section, and a saved view that names one\n * composes with it. **Pipelines** opens the dialog that creates, renames,\n * defaults, archives and — through it — edits the stages of each.\n *\n * ## Every move goes through the route\n *\n * A drag, a card's \"Move to\", \"Mark won\" and \"Mark lost\" all end in\n * `useDealStageApi`, never a Firestore write: the stage is the fact the\n * automations listen for, and only the server emits the event. The section\n * marks the card pending while the request runs and lets the listener land\n * it — see `DealBoard` for why a move is not applied optimistically.\n *\n * ## Creation is a button\n *\n * \"New deal\" opens a drawer; there is no form above the list. The drawer\n * writes client-direct against the rules, stamped with this console's scope.\n *\n * ## The table selects and exports (AGL-2621)\n *\n * The table's rows are selectable, and a selection raises `DealsBulkBar`\n * over it — whose stage moves go through the same `useDealStageApi` as a\n * drag. Import and Export open the console's import wizard and export\n * dialog on `crm.deals` (AGL-3528): the export over the selection, the\n * list's own query, or every deal.\n */\nexport function DealsSection(props: ConsolePluginPageProps) {\n const { hostId, org, basePath } = props\n const routes = crmRoutes(basePath ?? '')\n const router = useRouter()\n const { enqueueSnackbar } = useSnackbar()\n const scope = useCrmScope({ hostId, org })\n const pipelineState = usePipeline(scope.orgId, {\n hostId,\n org: (org ?? null) as Record<string, unknown> | null,\n })\n const { activePipelines } = pipelineState\n const [pipelineId, setPipelineId] = useState<string | null>(null)\n // The chosen pipeline while it is still active; else the default. A\n // pipeline archived from another tab falls back rather than leaving the\n // board on a pipeline the picker no longer lists.\n const pipeline =\n (pipelineId ? activePipelines.find((entry) => entry.$id === pipelineId) : null) ??\n pipelineState.pipeline\n const roster = useOrgMemberDirectory(scope.orgId)\n const api = useDealStageApi(hostId)\n const nowMs = useMemo(() => Date.now(), [])\n // The org's deal fields, for the table's optional columns (AGL-2661).\n const dealFields = useContactFieldDefinitions(scope.orgId, 'deal')\n // Salesforce's Type and Lead source lists, for their columns and filters (AGL-3516).\n const typeList = useCrmPicklist('opportunityType', scope.orgId)\n const leadSourceList = useCrmPicklist('leadSource', scope.orgId)\n\n const [view, setView] = useState<View>('board')\n const [closedExpanded, setClosedExpanded] = useState(false)\n /*\n * The table's status filter is the saved VIEW'S (AGL-2617): a view of\n * deals is a view of the table, and it holds the status beside the\n * columns and the sort. Opening one shows the table, because the board\n * has no columns to arrange and answers to the pipeline's stages alone.\n */\n const views = useCrmSavedView({\n section: 'deals',\n hostId,\n org,\n basePath: basePath ?? '',\n })\n const statusFilter: StatusFilter = useMemo(() => {\n const value = views.state.filters.find((clause) => clause.field === 'status')?.value\n return value === 'open' || value === 'won' || value === 'lost' ? value : 'all'\n }, [views.state.filters])\n // Every clause is the query's, the status and \"No next activity\" alike.\n const viewFilters = views.state.filters\n useEffect(() => {\n if (views.currentId) setView('table')\n }, [views.currentId])\n\n // The board's read stays on in the table view too: it is what the summary\n // above both views is computed from, and it is already bounded.\n const open = useDealsByStatus(\n scope.orgId,\n scope.visibleTo,\n pipeline?.$id ?? null,\n 'open',\n BOARD_OPEN_LIMIT,\n )\n const closedPipelineId =\n view === 'board' && closedExpanded ? (pipeline?.$id ?? null) : null\n const won = useDealsByStatus(scope.orgId, scope.visibleTo, closedPipelineId, 'won', BOARD_CLOSED_LIMIT)\n const lost = useDealsByStatus(scope.orgId, scope.visibleTo, closedPipelineId, 'lost', BOARD_CLOSED_LIMIT)\n /*\n * THE TABLE (AGL-3321): the pipeline's deals, every clause and the search\n * word on one query — the search reads the title's word prefixes every\n * deal writer stamps, so a deal on page four is found by any word of its\n * title — paged by that query, and read only while the table is showing.\n */\n const [searchWords, setSearchWords] = useState<string[]>([])\n const searching = searchWords.some((word) => word.trim())\n const searchKey = searchWords.join(' ')\n const foldsScope = useCrmFoldsScope(scope.orgId, scope.visibleTo)\n const pipelineBase = useMemo(() => dealPipelineBase(pipeline?.$id ?? null), [pipeline?.$id])\n // Each stored clause asked through the field its writer keeps — a Type\n // or a Lead source by its key (AGL-3516).\n const asked = useMemo(() => crmAskClauses(viewFilters, dealQueryClause), [viewFilters])\n const paged = useCrmListQuery<DealDoc>({\n scope: scope.scope,\n collection: CRM_COLLECTIONS.deals,\n visibleTo: scope.visibleTo,\n foldsScope,\n declaration: DEAL_LIST_DECLARATION,\n clauses: asked.clauses,\n search: searchWords,\n base: pipelineBase,\n prefixSearch: DEAL_PREFIX_SEARCH,\n enabled: view === 'table' && Boolean(pipeline),\n })\n\n const summary = useMemo(() => boardSummary(open.data, pipeline), [open.data, pipeline])\n\n /*\n * MOVES IN FLIGHT. A card in this set is dimmed and cannot be dragged\n * again until the route answers; the listener is what moves it.\n */\n const [moving, setMoving] = useState<ReadonlySet<string>>(() => new Set())\n const track = useCallback(\n async (deal: DealDoc, request: () => Promise<unknown>, done: string) => {\n setMoving((current) => new Set(current).add(deal.$id))\n try {\n await request()\n enqueueSnackbar(done, { variant: 'success', persist: false })\n return true\n } catch (error) {\n enqueueSnackbar(\n error instanceof Error ? error.message : 'The deal could not be moved.',\n { variant: 'warning', allowDuplicate: true },\n )\n return false\n } finally {\n setMoving((current) => {\n const next = new Set(current)\n next.delete(deal.$id)\n return next\n })\n }\n },\n [enqueueSnackbar],\n )\n const handleMove = useCallback(\n (deal: DealDoc, stageId: string) => {\n const stage = dealStageById(pipeline, stageId)\n void track(\n deal,\n () => api.moveToStage(deal, stageId),\n `Moved to ${stage?.name ?? 'stage'}`,\n )\n },\n [api, pipeline, track],\n )\n const handleWon = useCallback(\n (deal: DealDoc) => void track(deal, () => api.markWon(deal), 'Deal won'),\n [api, track],\n )\n const [losing, setLosing] = useState<DealDoc | null>(null)\n const handleLost = useCallback((deal: DealDoc) => setLosing(deal), [])\n const confirmLost = useCallback(\n (reason: string) => {\n const deal = losing\n if (!deal) return\n setLosing(null)\n void track(deal, () => api.markLost(deal, reason), 'Deal marked lost')\n },\n [api, losing, track],\n )\n\n const openDeal = useCallback(\n (deal: DealDoc) => router.push(routes.deal(deal.$id)),\n [router, routes],\n )\n\n const [creating, setCreating] = useState(false)\n const [managingPipelines, setManagingPipelines] = useState(false)\n\n const [selectedIds, setSelectedIds] = useState<string[]>([])\n // A page or a status is a different set of rows; a selection made on\n // the last one would be a count over rows no longer on screen.\n useEffect(() => setSelectedIds([]), [paged.plan, paged.page])\n // The list's filter, when one narrows it, for the export to read the same\n // records the list does (AGL-3528).\n const exportFilter = useMemo(\n () => (paged.plan.served.length || paged.plan.searched ? { label: 'what the list shows', plan: paged.plan } : null),\n [paged.plan],\n )\n\n const columns: GridColDef[] = useMemo(\n () => [\n {\n field: 'title',\n headerName: 'Deal',\n flex: 1.6,\n minWidth: 220,\n renderCell: ({ row }: { row: DealDoc }) => {\n const withWhom = [row.contactName, row.companyName].filter(Boolean).join(' · ')\n return (\n <Stack sx={{ justifyContent: 'center', lineHeight: 1.25 }}>\n <Typography variant=\"body2\" sx={{ lineHeight: 1.25 }}>\n {row.title || 'Untitled deal'}\n </Typography>\n {withWhom ? (\n <Typography variant=\"caption\" color=\"text.secondary\" noWrap sx={{ lineHeight: 1.25 }}>\n {withWhom}\n </Typography>\n ) : null}\n </Stack>\n )\n },\n },\n {\n field: 'stageId',\n headerName: 'Stage',\n flex: 0.9,\n minWidth: 140,\n valueGetter: (_value: unknown, row: DealDoc) =>\n dealStageById(pipelineState.pipelineById(row.pipelineId), row.stageId)?.name ??\n row.stageId,\n },\n {\n field: 'amountCents',\n headerName: 'Amount',\n flex: 0.8,\n minWidth: 120,\n align: 'right',\n headerAlign: 'right',\n valueGetter: (_value: unknown, row: DealDoc) => row.amountCents ?? null,\n renderCell: ({ row }: { row: DealDoc }) =>\n typeof row.amountCents === 'number' ? formatMoney(row.amountCents, row.currency) : '—',\n },\n {\n field: 'ownerUid',\n headerName: 'Owner',\n flex: 0.9,\n minWidth: 140,\n valueGetter: (_value: unknown, row: DealDoc) => roster.nameOf(row.ownerUid),\n renderCell: ({ row }: { row: DealDoc }) => {\n const label = roster.nameOf(row.ownerUid)\n return label ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <OwnerAvatar label={label} size={22} />\n <Typography variant=\"body2\" noWrap>\n {label}\n </Typography>\n </Stack>\n ) : (\n <Typography variant=\"body2\" color=\"text.secondary\">\n {'—'}\n </Typography>\n )\n },\n },\n {\n field: 'expectedCloseAtMs',\n headerName: 'Expected close',\n flex: 0.8,\n minWidth: 130,\n type: 'date',\n valueGetter: (_value: unknown, row: DealDoc) =>\n typeof row.expectedCloseAtMs === 'number' ? new Date(row.expectedCloseAtMs) : null,\n renderCell: ({ row }: { row: DealDoc }) =>\n typeof row.expectedCloseAtMs === 'number'\n ? new Date(row.expectedCloseAtMs).toLocaleDateString()\n : '—',\n },\n {\n field: 'status',\n headerName: 'Status',\n flex: 0.6,\n minWidth: 100,\n renderCell: ({ row }: { row: DealDoc }) => (\n <Chip\n size=\"small\"\n label={DEAL_STATUS_LABELS[row.status] ?? row.status}\n color={row.status === 'won' ? 'success' : row.status === 'lost' ? 'default' : 'primary'}\n variant={row.status === 'open' ? 'outlined' : 'filled'}\n />\n ),\n },\n // When the earliest open task against the deal is due (AGL-2661).\n nextActivityColumn(nowMs),\n // Salesforce's Type and Lead source, optional, in their lists' order (AGL-3516).\n picklistColumn('type', 'Type', typeList.picklist),\n picklistColumn('leadSource', 'Lead source', leadSourceList.picklist),\n // The org's deal fields as optional columns (AGL-2661).\n ...customFieldColumns(dealFields.active),\n ],\n [pipelineState, roster, dealFields.active, nowMs, typeList.picklist, leadSourceList.picklist],\n )\n /** The table's rows: the query's page. */\n const tableRows = paged.rows\n /*\n * The table's column and sort models are the view's (AGL-2617); its\n * filters are the grid's own panel over the view's clauses (AGL-3313),\n * every one of them asked of the query (AGL-3321).\n */\n /*\n * The choices each select column offers. A stored clause naming a value\n * no longer listed stays a choice, so the panel can show it and clear it.\n */\n const filterOptions = useMemo<Record<string, ListFilterOption[]>>(() => {\n const stale = (field: string, known: readonly { value: string }[]) =>\n viewFilters\n .filter((clause) => clause.field === field && clause.op !== 'isEmpty')\n .flatMap((clause) => clause.value.split(','))\n .map((value) => value.trim())\n .filter((value) => value && !known.some((option) => option.value === value))\n .map((value) => ({ value, label: value }))\n const types = picklistFilterOptions(typeList.picklist, 'No type')\n const sources = picklistFilterOptions(leadSourceList.picklist, 'No lead source')\n return {\n status: DEAL_STATUS_FILTER_OPTIONS,\n type: [...types, ...stale('type', types)],\n leadSource: [...sources, ...stale('leadSource', sources)],\n }\n }, [viewFilters, typeList.picklist, leadSourceList.picklist])\n const filterColumns = useMemo(\n () => listFilterGridColumns(columns, DEAL_GRID_FILTER_FIELDS, filterOptions, DEAL_GRID_FILTER_HEADERS),\n [columns, filterOptions],\n )\n const grid = useCrmViewGrid(views, filterColumns, DEAL_HIDDEN_COLUMNS)\n const gridFilter = useListGridFilter({\n clauses: viewFilters,\n onChange: views.setFilters,\n selectFields: ['status', 'type', 'leadSource'],\n codecs: DEAL_FILTER_CODECS,\n search: { words: searchWords, onChange: setSearchWords },\n })\n // What the query could not hold, named by the clause the reader set.\n const refused = useMemo(\n () =>\n crmQueryRefusals(paged.plan, asked, {\n fields: DEAL_GRID_FILTER_FIELDS,\n headers: DEAL_GRID_FILTER_HEADERS,\n options: filterOptions,\n }),\n [paged.plan, asked, filterOptions],\n )\n\n const noOrg = scope.ready && !scope.orgId\n const pipelineLoading =\n !noOrg && (pipelineState.status === 'loading' || pipelineState.seeding || (!pipeline && pipelineState.status !== 'error'))\n\n return (\n <>\n <CardDisplay\n header={'Deals'}\n help={pluginDocsHelp('deals', { anchor: '#the-board-and-the-table' })}\n contentGutterX\n contentGutterY\n HeaderProps={{\n // The record actions, top right and never clipped (AGL-3311).\n action: (\n <CrmListActions>\n <CrmImportButton resource={CRM_DEALS_RESOURCE} noun=\"deals\" hostId={hostId} mappingZone=\"deals\" />\n <CrmExportButton resource={CRM_DEALS_RESOURCE} hostId={hostId} filter={exportFilter} />\n <Button\n size=\"small\"\n startIcon={<MdiIcon path={mdiCogOutline.path} size={0.8} />}\n disabled={!scope.orgId || pipelineState.status === 'loading'}\n onClick={() => setManagingPipelines(true)}\n >\n {'Pipelines'}\n </Button>\n <Button\n size=\"small\"\n variant=\"contained\"\n startIcon={<MdiIcon path={mdiPlus.path} size={0.8} />}\n disabled={!pipeline || !scope.orgId}\n onClick={() => setCreating(true)}\n >\n {'New deal'}\n </Button>\n </CrmListActions>\n ),\n }}\n >\n <Stack spacing={2}>\n <Stack\n direction=\"row\"\n spacing={3}\n sx={{ alignItems: 'flex-end', flexWrap: 'wrap', rowGap: 1 }}\n >\n <Figure label=\"Open deals\" value={summary.openCount.toLocaleString()} />\n <Figure label=\"Pipeline value\" value={formatAmountByCurrency(summary.valueByCurrency)} />\n <Figure label=\"Weighted value\" value={formatAmountByCurrency(summary.weightedByCurrency)} />\n <Stack sx={{ flex: 1 }} />\n {/* Which pipeline the board and table show, above them rather than under (AGL-3311). */}\n {activePipelines.length > 1 ? (\n <TextField\n select\n size=\"small\"\n label=\"Pipeline\"\n value={pipeline?.$id ?? ''}\n onChange={(event) => setPipelineId(event.target.value)}\n sx={{ minWidth: 160 }}\n slotProps={{ select: { 'aria-label': 'Pipeline' } }}\n >\n {activePipelines.map((entry) => (\n <MenuItem key={entry.$id} value={entry.$id}>\n {entry.name}\n </MenuItem>\n ))}\n </TextField>\n ) : null}\n <ToggleButtonGroup\n exclusive\n size=\"small\"\n color=\"primary\"\n value={view}\n onChange={(_event, next) => {\n if (next) setView(next as View)\n }}\n aria-label=\"View\"\n >\n <ToggleButton value=\"board\" aria-label=\"Board\">\n <MdiIcon path={mdiViewColumnOutline.path} size={0.8} />\n <Typography variant=\"button\" sx={{ ml: 0.5 }}>\n {'Board'}\n </Typography>\n </ToggleButton>\n <ToggleButton value=\"table\" aria-label=\"Table\">\n <MdiIcon path={mdiTableLarge.path} size={0.8} />\n <Typography variant=\"button\" sx={{ ml: 0.5 }}>\n {'Table'}\n </Typography>\n </ToggleButton>\n </ToggleButtonGroup>\n </Stack>\n\n {noOrg ? (\n <Alert severity=\"info\">\n {'This site has no organization, so it has no pipeline.'}\n </Alert>\n ) : pipelineState.status === 'error' ? (\n <Alert severity=\"warning\">\n {'The pipeline could not be read. Deals need the \"Manage data\" permission.'}\n </Alert>\n ) : pipelineLoading ? (\n <Stack direction=\"row\" spacing={1} sx={{ alignItems: 'center' }}>\n <CircularProgress size={18} />\n <Typography variant=\"body2\" color=\"text.secondary\">\n {pipelineState.seeding ? 'Setting up your Sales pipeline…' : 'Loading the pipeline…'}\n </Typography>\n </Stack>\n ) : view === 'board' && pipeline ? (\n <>\n {open.status === 'success' && open.data.length === 0 ? (\n <EmptyStateComponent\n compact\n label={'No open deals yet'}\n description={'A deal is a sale in progress, moved across the stages below as it advances.'}\n action={\n <Button\n size=\"small\"\n variant=\"contained\"\n startIcon={<MdiIcon path={mdiPlus.path} size={0.8} />}\n disabled={!pipeline || !scope.orgId}\n onClick={() => setCreating(true)}\n >\n {'New deal'}\n </Button>\n }\n />\n ) : null}\n <DealBoard\n pipeline={pipeline}\n deals={open.data}\n won={closedExpanded && won.status !== 'loading' ? won.data : null}\n lost={closedExpanded && lost.status !== 'loading' ? lost.data : null}\n closedExpanded={closedExpanded}\n onToggleClosed={() => setClosedExpanded((current) => !current)}\n labelFor={roster.nameOf}\n moving={moving}\n onOpen={openDeal}\n onMove={handleMove}\n onWon={handleWon}\n onLost={handleLost}\n nowMs={nowMs}\n />\n </>\n ) : (\n <Stack spacing={1.5}>\n {/*\n The view this table is showing, and the clauses narrowing it\n as chips (AGL-2617, AGL-3313). Status and \"No next activity\"\n are set in the grid's own Filters panel.\n */}\n <CrmListToolbar label=\"Deal filters\">\n <CrmViewsControl controller={views} allLabel=\"All deals\" />\n <ListFilterChips\n fields={DEAL_GRID_FILTER_FIELDS}\n headers={DEAL_GRID_FILTER_HEADERS}\n clauses={viewFilters}\n onChange={views.setFilters}\n options={filterOptions}\n marksServed={false}\n />\n </CrmListToolbar>\n <ListQueryNotices refused={refused} notices={paged.plan.notices} />\n <>\n <DealsBulkBar\n hostId={hostId}\n scope={scope.scope}\n rows={tableRows}\n selected={selectedIds}\n onSelectedChange={setSelectedIds}\n pipelineById={pipelineState.pipelineById}\n roster={roster}\n api={api}\n />\n <CrmColumnOrderProvider value={grid.columnOrder}>\n <ListTable\n rows={tableRows}\n columns={grid.columns}\n slots={CRM_LIST_SLOTS}\n selectable={{ selected: selectedIds, onChange: setSelectedIds }}\n onOpen={(_id, row) => openDeal(row as DealDoc)}\n // The panel and the search are the query's (AGL-3321).\n filterMode=\"server\"\n filterModel={gridFilter.filterModel}\n onFilterModelChange={gridFilter.onFilterModelChange}\n quickFilter\n loading={paged.status === 'loading'}\n // An empty table is said inside the grid, so its toolbar\n // stays to change the status that emptied it.\n noRowsLabel={\n searching\n ? `No deals match “${searchKey.trim()}”`\n : statusFilter === 'all'\n ? 'No deals yet'\n : `No ${statusFilter} deals`\n }\n noRowsDescription={\n statusFilter === 'all' && !searching\n ? 'A deal is a sale in progress, moved across the pipeline as it advances.'\n : undefined\n }\n noRowsAction={\n statusFilter === 'all' && !searching ? (\n <Button\n size=\"small\"\n variant=\"contained\"\n startIcon={<MdiIcon path={mdiPlus.path} size={0.8} />}\n disabled={!pipeline || !scope.orgId}\n onClick={() => setCreating(true)}\n >\n {'New deal'}\n </Button>\n ) : undefined\n }\n // Columns and sort are the view's, controlled (AGL-2617).\n columnVisibilityModel={grid.columnVisibilityModel}\n onColumnVisibilityModelChange={grid.onColumnVisibilityModelChange}\n sortModel={grid.sortModel}\n onSortModelChange={grid.onSortModelChange}\n hideFooter\n />\n </CrmColumnOrderProvider>\n <ListPagination\n page={paged.page}\n pageSize={paged.pageSize}\n rowCount={paged.rows.length}\n hasMore={paged.hasMore}\n onPageChange={paged.setPage}\n onPageSizeChange={paged.setPageSize}\n />\n </>\n </Stack>\n )}\n </Stack>\n </CardDisplay>\n <DealEditDrawer\n open={creating}\n onClose={() => setCreating(false)}\n hostId={hostId}\n org={org}\n pipelines={activePipelines}\n defaultPipeline={pipeline}\n />\n <PipelinesDialog\n open={managingPipelines}\n onClose={() => setManagingPipelines(false)}\n orgId={scope.orgId ?? ''}\n // A pipeline made here is stamped the way the seeded default is\n // (`usePipeline`): the site's own tokens under a site; at the\n // organization level the org token, with the picked site as its\n // provenance (AGL-2630).\n hostId={scope.createHostId}\n pipelines={pipelineState.pipelines}\n fromCache={pipelineState.fromCache}\n unreadable={pipelineState.status === 'error'}\n visibleToTokens={scope.visibleTo}\n createTokens={scope.level === 'site' ? scope.createTokens : ORG_PIPELINE_TOKENS}\n />\n <LostReasonDialog\n open={Boolean(losing)}\n dealTitle={losing?.title ?? ''}\n onClose={() => setLosing(null)}\n onConfirm={confirmLost}\n />\n </>\n )\n}\nDealsSection.displayName = 'DealsSection'\n\n/** An optional column of a picklist field: its label, sorted in the list's order. */\nfunction picklistColumn(field: 'type' | 'leadSource', headerName: string, picklist: CrmPicklist): GridColDef {\n return {\n field,\n headerName,\n flex: 0.8,\n minWidth: 130,\n valueGetter: (_value: unknown, row: DealDoc) => String(row[field] ?? ''),\n sortComparator: (a: string, b: string) =>\n crmPicklistRank(picklist, a) - crmPicklistRank(picklist, b) || a.localeCompare(b),\n }\n}\n\nfunction Figure(props: { label: string; value: string }) {\n return (\n <Stack sx={{ lineHeight: 1.2 }}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {props.label}\n </Typography>\n <Typography variant=\"h6\" component=\"span\">\n {props.value}\n </Typography>\n </Stack>\n )\n}\nFigure.displayName = 'Figure'\n\nexport default DealsSection\n"],"names":["CRM_COLLECTIONS","crmPicklistRank","dealStageById","ORG_SCOPE_TOKEN","pluginDocsHelp","mdiCogOutline","mdiPlus","mdiTableLarge","mdiViewColumnOutline","CardDisplay","MdiIcon","ListPagination","ListTable","ListQueryNotices","useCrmSavedView","useCrmViewGrid","CrmListActions","CrmListToolbar","CRM_LIST_SLOTS","CrmColumnOrderProvider","CRM_NEXT_ACTIVITY_FILTER_FIELD","CRM_NEXT_ACTIVITY_FILTER_HEADER","nextActivityColumn","DEAL_FILTER_CODECS","DEAL_LIST_DECLARATION","DEAL_LIST_FILTER_FIELDS","DEAL_PICKLIST_FILTER_NONE","DEAL_PREFIX_SEARCH","dealPipelineBase","dealQueryClause","useCrmFoldsScope","useCrmListQuery","useCrmPicklist","crmAskClauses","crmQueryRefusals","ListFilterChips","listFilterGridColumns","useListGridFilter","CrmViewsControl","EmptyStateComponent","useSnackbar","Alert","Button","Chip","CircularProgress","MenuItem","Stack","TextField","ToggleButton","ToggleButtonGroup","Typography","useRouter","useCallback","useEffect","useMemo","useState","useContactFieldDefinitions","useCrmScope","useDealStageApi","BOARD_CLOSED_LIMIT","BOARD_OPEN_LIMIT","useDealsByStatus","useOrgMemberDirectory","usePipeline","crmRoutes","boardSummary","DEAL_STATUS_LABELS","formatAmountByCurrency","formatMoney","customFieldColumns","DealBoard","DealEditDrawer","CrmExportButton","CrmImportButton","CRM_DEALS_RESOURCE","DealsBulkBar","LostReasonDialog","OwnerAvatar","PipelinesDialog","DEAL_GRID_FILTER_FIELDS","DEAL_GRID_FILTER_HEADERS","status","column","type","leadSource","DEAL_STATUS_FILTER_OPTIONS","map","value","label","DEAL_HIDDEN_COLUMNS","picklistFilterOptions","picklist","none","values","active","ORG_PIPELINE_TOKENS","DealsSection","props","pipelineId","scope","hostId","org","basePath","routes","router","enqueueSnackbar","pipelineState","orgId","activePipelines","setPipelineId","pipeline","find","entry","$id","roster","api","nowMs","Date","now","dealFields","typeList","leadSourceList","view","setView","closedExpanded","setClosedExpanded","views","section","statusFilter","state","filters","clause","field","viewFilters","currentId","open","visibleTo","closedPipelineId","won","lost","searchWords","setSearchWords","searching","some","word","trim","searchKey","join","foldsScope","pipelineBase","asked","paged","collection","deals","declaration","clauses","search","base","prefixSearch","enabled","Boolean","summary","data","moving","setMoving","Set","track","deal","request","done","current","add","variant","persist","error","Error","message","allowDuplicate","next","delete","handleMove","stageId","stage","moveToStage","name","handleWon","markWon","losing","setLosing","handleLost","confirmLost","reason","markLost","openDeal","push","creating","setCreating","managingPipelines","setManagingPipelines","selectedIds","setSelectedIds","plan","page","exportFilter","served","length","searched","columns","headerName","flex","minWidth","renderCell","row","withWhom","contactName","companyName","filter","sx","justifyContent","lineHeight","title","color","noWrap","valueGetter","_value","pipelineById","align","headerAlign","amountCents","currency","nameOf","ownerUid","direction","spacing","alignItems","size","expectedCloseAtMs","toLocaleDateString","picklistColumn","tableRows","rows","filterOptions","stale","known","op","flatMap","split","option","types","sources","filterColumns","grid","gridFilter","onChange","setFilters","selectFields","codecs","words","refused","fields","headers","options","noOrg","ready","pipelineLoading","seeding","header","help","anchor","contentGutterX","contentGutterY","HeaderProps","action","resource","noun","mappingZone","startIcon","path","disabled","onClick","flexWrap","rowGap","Figure","openCount","toLocaleString","valueByCurrency","weightedByCurrency","select","event","target","slotProps","exclusive","_event","aria-label","ml","severity","compact","description","onToggleClosed","labelFor","onOpen","onMove","onWon","onLost","controller","allLabel","marksServed","notices","selected","onSelectedChange","columnOrder","slots","selectable","_id","filterMode","filterModel","onFilterModelChange","quickFilter","loading","noRowsLabel","noRowsDescription","undefined","noRowsAction","columnVisibilityModel","onColumnVisibilityModelChange","sortModel","onSortModelChange","hideFooter","pageSize","rowCount","hasMore","onPageChange","setPage","onPageSizeChange","setPageSize","onClose","pipelines","defaultPipeline","createHostId","fromCache","unreadable","visibleToTokens","createTokens","level","dealTitle","onConfirm","displayName","String","sortComparator","a","b","localeCompare","component"],"mappings":"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"}