@aglyn/plugins-crm 1.0.0-beta.143
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +7 -0
- package/package.json +57 -0
- package/src/index.d.ts +21 -0
- package/src/index.js +29 -0
- package/src/index.js.map +1 -0
- package/src/lib/components/activity-list.d.ts +98 -0
- package/src/lib/components/activity-list.js +321 -0
- package/src/lib/components/activity-list.js.map +1 -0
- package/src/lib/components/activity-queries.d.ts +117 -0
- package/src/lib/components/activity-queries.js +198 -0
- package/src/lib/components/activity-queries.js.map +1 -0
- package/src/lib/components/add-to-list-button.d.ts +25 -0
- package/src/lib/components/add-to-list-button.js +64 -0
- package/src/lib/components/add-to-list-button.js.map +1 -0
- package/src/lib/components/add-to-list-dialog.d.ts +24 -0
- package/src/lib/components/add-to-list-dialog.js +327 -0
- package/src/lib/components/add-to-list-dialog.js.map +1 -0
- package/src/lib/components/assignment-rule-drawer.d.ts +43 -0
- package/src/lib/components/assignment-rule-drawer.js +293 -0
- package/src/lib/components/assignment-rule-drawer.js.map +1 -0
- package/src/lib/components/companies-bulk-bar.d.ts +29 -0
- package/src/lib/components/companies-bulk-bar.js +274 -0
- package/src/lib/components/companies-bulk-bar.js.map +1 -0
- package/src/lib/components/companies-section.d.ts +54 -0
- package/src/lib/components/companies-section.js +522 -0
- package/src/lib/components/companies-section.js.map +1 -0
- package/src/lib/components/company-contacts-card.d.ts +49 -0
- package/src/lib/components/company-contacts-card.js +435 -0
- package/src/lib/components/company-contacts-card.js.map +1 -0
- package/src/lib/components/company-deals-card.d.ts +20 -0
- package/src/lib/components/company-deals-card.js +38 -0
- package/src/lib/components/company-deals-card.js.map +1 -0
- package/src/lib/components/company-detail-page.d.ts +20 -0
- package/src/lib/components/company-detail-page.js +165 -0
- package/src/lib/components/company-detail-page.js.map +1 -0
- package/src/lib/components/company-edit-drawer.d.ts +65 -0
- package/src/lib/components/company-edit-drawer.js +433 -0
- package/src/lib/components/company-edit-drawer.js.map +1 -0
- package/src/lib/components/company-import-drawer.d.ts +42 -0
- package/src/lib/components/company-import-drawer.js +99 -0
- package/src/lib/components/company-import-drawer.js.map +1 -0
- package/src/lib/components/company-picker.d.ts +127 -0
- package/src/lib/components/company-picker.js +323 -0
- package/src/lib/components/company-picker.js.map +1 -0
- package/src/lib/components/company-properties-card.d.ts +47 -0
- package/src/lib/components/company-properties-card.js +289 -0
- package/src/lib/components/company-properties-card.js.map +1 -0
- package/src/lib/components/contact-address-fields.d.ts +29 -0
- package/src/lib/components/contact-address-fields.js +149 -0
- package/src/lib/components/contact-address-fields.js.map +1 -0
- package/src/lib/components/contact-associations-card.d.ts +72 -0
- package/src/lib/components/contact-associations-card.js +296 -0
- package/src/lib/components/contact-associations-card.js.map +1 -0
- package/src/lib/components/contact-custom-columns.d.ts +38 -0
- package/src/lib/components/contact-custom-columns.js +102 -0
- package/src/lib/components/contact-custom-columns.js.map +1 -0
- package/src/lib/components/contact-custom-fields-card.d.ts +39 -0
- package/src/lib/components/contact-custom-fields-card.js +204 -0
- package/src/lib/components/contact-custom-fields-card.js.map +1 -0
- package/src/lib/components/contact-deals-card.d.ts +20 -0
- package/src/lib/components/contact-deals-card.js +38 -0
- package/src/lib/components/contact-deals-card.js.map +1 -0
- package/src/lib/components/contact-detail-page.d.ts +46 -0
- package/src/lib/components/contact-detail-page.js +535 -0
- package/src/lib/components/contact-detail-page.js.map +1 -0
- package/src/lib/components/contact-duplicates-card.d.ts +42 -0
- package/src/lib/components/contact-duplicates-card.js +167 -0
- package/src/lib/components/contact-duplicates-card.js.map +1 -0
- package/src/lib/components/contact-field-drawer.d.ts +64 -0
- package/src/lib/components/contact-field-drawer.js +251 -0
- package/src/lib/components/contact-field-drawer.js.map +1 -0
- package/src/lib/components/contact-import-drawer.d.ts +46 -0
- package/src/lib/components/contact-import-drawer.js +149 -0
- package/src/lib/components/contact-import-drawer.js.map +1 -0
- package/src/lib/components/contact-known-by-card.d.ts +39 -0
- package/src/lib/components/contact-known-by-card.js +142 -0
- package/src/lib/components/contact-known-by-card.js.map +1 -0
- package/src/lib/components/contact-list-columns.d.ts +53 -0
- package/src/lib/components/contact-list-columns.js +288 -0
- package/src/lib/components/contact-list-columns.js.map +1 -0
- package/src/lib/components/contact-merge-dialog.d.ts +79 -0
- package/src/lib/components/contact-merge-dialog.js +405 -0
- package/src/lib/components/contact-merge-dialog.js.map +1 -0
- package/src/lib/components/contact-properties-card.d.ts +89 -0
- package/src/lib/components/contact-properties-card.js +492 -0
- package/src/lib/components/contact-properties-card.js.map +1 -0
- package/src/lib/components/contact-timeline-card.d.ts +68 -0
- package/src/lib/components/contact-timeline-card.js +435 -0
- package/src/lib/components/contact-timeline-card.js.map +1 -0
- package/src/lib/components/contacts-bulk-bar.d.ts +91 -0
- package/src/lib/components/contacts-bulk-bar.js +493 -0
- package/src/lib/components/contacts-bulk-bar.js.map +1 -0
- package/src/lib/components/contacts-section.d.ts +26 -0
- package/src/lib/components/contacts-section.js +1025 -0
- package/src/lib/components/contacts-section.js.map +1 -0
- package/src/lib/components/copy-capture-address-button.d.ts +33 -0
- package/src/lib/components/copy-capture-address-button.js +60 -0
- package/src/lib/components/copy-capture-address-button.js.map +1 -0
- package/src/lib/components/crm-attribution-zone.d.ts +38 -0
- package/src/lib/components/crm-attribution-zone.js +36 -0
- package/src/lib/components/crm-attribution-zone.js.map +1 -0
- package/src/lib/components/crm-booking-zone.d.ts +61 -0
- package/src/lib/components/crm-booking-zone.js +50 -0
- package/src/lib/components/crm-booking-zone.js.map +1 -0
- package/src/lib/components/crm-bulk-bar-frame.d.ts +47 -0
- package/src/lib/components/crm-bulk-bar-frame.js +137 -0
- package/src/lib/components/crm-bulk-bar-frame.js.map +1 -0
- package/src/lib/components/crm-call-actions.d.ts +65 -0
- package/src/lib/components/crm-call-actions.js +110 -0
- package/src/lib/components/crm-call-actions.js.map +1 -0
- package/src/lib/components/crm-column-menu.d.ts +21 -0
- package/src/lib/components/crm-column-menu.js +103 -0
- package/src/lib/components/crm-column-menu.js.map +1 -0
- package/src/lib/components/crm-console-page.d.ts +19 -0
- package/src/lib/components/crm-console-page.js +151 -0
- package/src/lib/components/crm-console-page.js.map +1 -0
- package/src/lib/components/crm-console-sections.d.ts +52 -0
- package/src/lib/components/crm-console-sections.js +83 -0
- package/src/lib/components/crm-console-sections.js.map +1 -0
- package/src/lib/components/crm-custom-field-control.d.ts +26 -0
- package/src/lib/components/crm-custom-field-control.js +131 -0
- package/src/lib/components/crm-custom-field-control.js.map +1 -0
- package/src/lib/components/crm-email-template-tools.d.ts +69 -0
- package/src/lib/components/crm-email-template-tools.js +240 -0
- package/src/lib/components/crm-email-template-tools.js.map +1 -0
- package/src/lib/components/crm-export-all-button.d.ts +39 -0
- package/src/lib/components/crm-export-all-button.js +98 -0
- package/src/lib/components/crm-export-all-button.js.map +1 -0
- package/src/lib/components/crm-filter-bar.d.ts +53 -0
- package/src/lib/components/crm-filter-bar.js +294 -0
- package/src/lib/components/crm-filter-bar.js.map +1 -0
- package/src/lib/components/crm-glance-card.d.ts +54 -0
- package/src/lib/components/crm-glance-card.js +219 -0
- package/src/lib/components/crm-glance-card.js.map +1 -0
- package/src/lib/components/crm-next-activity-column.d.ts +35 -0
- package/src/lib/components/crm-next-activity-column.js +100 -0
- package/src/lib/components/crm-next-activity-column.js.map +1 -0
- package/src/lib/components/crm-record-header.d.ts +97 -0
- package/src/lib/components/crm-record-header.js +160 -0
- package/src/lib/components/crm-record-header.js.map +1 -0
- package/src/lib/components/crm-record-insights-zone.d.ts +50 -0
- package/src/lib/components/crm-record-insights-zone.js +169 -0
- package/src/lib/components/crm-record-insights-zone.js.map +1 -0
- package/src/lib/components/crm-record-picker.d.ts +42 -0
- package/src/lib/components/crm-record-picker.js +104 -0
- package/src/lib/components/crm-record-picker.js.map +1 -0
- package/src/lib/components/crm-send-email-button.d.ts +39 -0
- package/src/lib/components/crm-send-email-button.js +81 -0
- package/src/lib/components/crm-send-email-button.js.map +1 -0
- package/src/lib/components/crm-send-email-dialog.d.ts +61 -0
- package/src/lib/components/crm-send-email-dialog.js +851 -0
- package/src/lib/components/crm-send-email-dialog.js.map +1 -0
- package/src/lib/components/crm-site-picker.d.ts +61 -0
- package/src/lib/components/crm-site-picker.js +99 -0
- package/src/lib/components/crm-site-picker.js.map +1 -0
- package/src/lib/components/crm-suite-lock.d.ts +29 -0
- package/src/lib/components/crm-suite-lock.js +114 -0
- package/src/lib/components/crm-suite-lock.js.map +1 -0
- package/src/lib/components/crm-tasks-due-card.d.ts +42 -0
- package/src/lib/components/crm-tasks-due-card.js +225 -0
- package/src/lib/components/crm-tasks-due-card.js.map +1 -0
- package/src/lib/components/crm-views-control.d.ts +65 -0
- package/src/lib/components/crm-views-control.js +518 -0
- package/src/lib/components/crm-views-control.js.map +1 -0
- package/src/lib/components/csv-import-drawer.d.ts +132 -0
- package/src/lib/components/csv-import-drawer.js +746 -0
- package/src/lib/components/csv-import-drawer.js.map +1 -0
- package/src/lib/components/deal-board.d.ts +70 -0
- package/src/lib/components/deal-board.js +478 -0
- package/src/lib/components/deal-board.js.map +1 -0
- package/src/lib/components/deal-detail-page.d.ts +18 -0
- package/src/lib/components/deal-detail-page.js +323 -0
- package/src/lib/components/deal-detail-page.js.map +1 -0
- package/src/lib/components/deal-edit-drawer.d.ts +59 -0
- package/src/lib/components/deal-edit-drawer.js +640 -0
- package/src/lib/components/deal-edit-drawer.js.map +1 -0
- package/src/lib/components/deal-import-drawer.d.ts +24 -0
- package/src/lib/components/deal-import-drawer.js +83 -0
- package/src/lib/components/deal-import-drawer.js.map +1 -0
- package/src/lib/components/deal-products-card.d.ts +48 -0
- package/src/lib/components/deal-products-card.js +614 -0
- package/src/lib/components/deal-products-card.js.map +1 -0
- package/src/lib/components/deal-properties-card.d.ts +29 -0
- package/src/lib/components/deal-properties-card.js +144 -0
- package/src/lib/components/deal-properties-card.js.map +1 -0
- package/src/lib/components/deal-stage-card.d.ts +24 -0
- package/src/lib/components/deal-stage-card.js +199 -0
- package/src/lib/components/deal-stage-card.js.map +1 -0
- package/src/lib/components/deals-bulk-bar.d.ts +31 -0
- package/src/lib/components/deals-bulk-bar.js +340 -0
- package/src/lib/components/deals-bulk-bar.js.map +1 -0
- package/src/lib/components/deals-section.d.ts +49 -0
- package/src/lib/components/deals-section.js +767 -0
- package/src/lib/components/deals-section.js.map +1 -0
- package/src/lib/components/email-capture-card.d.ts +42 -0
- package/src/lib/components/email-capture-card.js +134 -0
- package/src/lib/components/email-capture-card.js.map +1 -0
- package/src/lib/components/email-template-drawer.d.ts +33 -0
- package/src/lib/components/email-template-drawer.js +209 -0
- package/src/lib/components/email-template-drawer.js.map +1 -0
- package/src/lib/components/email-templates-card.d.ts +33 -0
- package/src/lib/components/email-templates-card.js +370 -0
- package/src/lib/components/email-templates-card.js.map +1 -0
- package/src/lib/components/erase-person-action.d.ts +92 -0
- package/src/lib/components/erase-person-action.js +261 -0
- package/src/lib/components/erase-person-action.js.map +1 -0
- package/src/lib/components/fields-section.d.ts +37 -0
- package/src/lib/components/fields-section.js +641 -0
- package/src/lib/components/fields-section.js.map +1 -0
- package/src/lib/components/form-contact-fields-card.d.ts +46 -0
- package/src/lib/components/form-contact-fields-card.js +253 -0
- package/src/lib/components/form-contact-fields-card.js.map +1 -0
- package/src/lib/components/insert-link-at-caret.d.ts +28 -0
- package/src/lib/components/insert-link-at-caret.js +37 -0
- package/src/lib/components/insert-link-at-caret.js.map +1 -0
- package/src/lib/components/lead-convert-dialog.d.ts +32 -0
- package/src/lib/components/lead-convert-dialog.js +493 -0
- package/src/lib/components/lead-convert-dialog.js.map +1 -0
- package/src/lib/components/lead-detail-page.d.ts +16 -0
- package/src/lib/components/lead-detail-page.js +163 -0
- package/src/lib/components/lead-detail-page.js.map +1 -0
- package/src/lib/components/lead-history-card.d.ts +32 -0
- package/src/lib/components/lead-history-card.js +165 -0
- package/src/lib/components/lead-history-card.js.map +1 -0
- package/src/lib/components/lead-import-drawer.d.ts +24 -0
- package/src/lib/components/lead-import-drawer.js +95 -0
- package/src/lib/components/lead-import-drawer.js.map +1 -0
- package/src/lib/components/lead-owner-select.d.ts +35 -0
- package/src/lib/components/lead-owner-select.js +91 -0
- package/src/lib/components/lead-owner-select.js.map +1 -0
- package/src/lib/components/lead-properties-card.d.ts +61 -0
- package/src/lib/components/lead-properties-card.js +395 -0
- package/src/lib/components/lead-properties-card.js.map +1 -0
- package/src/lib/components/lead-status-chip.d.ts +12 -0
- package/src/lib/components/lead-status-chip.js +43 -0
- package/src/lib/components/lead-status-chip.js.map +1 -0
- package/src/lib/components/lead-surfaces-note.d.ts +126 -0
- package/src/lib/components/lead-surfaces-note.js +262 -0
- package/src/lib/components/lead-surfaces-note.js.map +1 -0
- package/src/lib/components/lead-unqualify-dialog.d.ts +24 -0
- package/src/lib/components/lead-unqualify-dialog.js +125 -0
- package/src/lib/components/lead-unqualify-dialog.js.map +1 -0
- package/src/lib/components/leads-bulk-bar.d.ts +58 -0
- package/src/lib/components/leads-bulk-bar.js +307 -0
- package/src/lib/components/leads-bulk-bar.js.map +1 -0
- package/src/lib/components/leads-section.d.ts +23 -0
- package/src/lib/components/leads-section.js +664 -0
- package/src/lib/components/leads-section.js.map +1 -0
- package/src/lib/components/linked-deals-card.d.ts +32 -0
- package/src/lib/components/linked-deals-card.js +163 -0
- package/src/lib/components/linked-deals-card.js.map +1 -0
- package/src/lib/components/log-activity-dialog.d.ts +60 -0
- package/src/lib/components/log-activity-dialog.js +368 -0
- package/src/lib/components/log-activity-dialog.js.map +1 -0
- package/src/lib/components/lost-reason-dialog.d.ts +26 -0
- package/src/lib/components/lost-reason-dialog.js +95 -0
- package/src/lib/components/lost-reason-dialog.js.map +1 -0
- package/src/lib/components/new-contact-drawer.d.ts +78 -0
- package/src/lib/components/new-contact-drawer.js +343 -0
- package/src/lib/components/new-contact-drawer.js.map +1 -0
- package/src/lib/components/org-lead-surfaces-note.d.ts +57 -0
- package/src/lib/components/org-lead-surfaces-note.js +172 -0
- package/src/lib/components/org-lead-surfaces-note.js.map +1 -0
- package/src/lib/components/owner-avatar.d.ts +18 -0
- package/src/lib/components/owner-avatar.js +61 -0
- package/src/lib/components/owner-avatar.js.map +1 -0
- package/src/lib/components/pipeline-stages-dialog.d.ts +43 -0
- package/src/lib/components/pipeline-stages-dialog.js +339 -0
- package/src/lib/components/pipeline-stages-dialog.js.map +1 -0
- package/src/lib/components/pipelines-dialog.d.ts +55 -0
- package/src/lib/components/pipelines-dialog.js +517 -0
- package/src/lib/components/pipelines-dialog.js.map +1 -0
- package/src/lib/components/recent-activity-feed.d.ts +39 -0
- package/src/lib/components/recent-activity-feed.js +103 -0
- package/src/lib/components/recent-activity-feed.js.map +1 -0
- package/src/lib/components/recipes-card.d.ts +39 -0
- package/src/lib/components/recipes-card.js +485 -0
- package/src/lib/components/recipes-card.js.map +1 -0
- package/src/lib/components/record-activity-card.d.ts +26 -0
- package/src/lib/components/record-activity-card.js +121 -0
- package/src/lib/components/record-activity-card.js.map +1 -0
- package/src/lib/components/record-files-card.d.ts +67 -0
- package/src/lib/components/record-files-card.js +290 -0
- package/src/lib/components/record-files-card.js.map +1 -0
- package/src/lib/components/record-tasks-card.d.ts +32 -0
- package/src/lib/components/record-tasks-card.js +306 -0
- package/src/lib/components/record-tasks-card.js.map +1 -0
- package/src/lib/components/reports/activity-card.d.ts +57 -0
- package/src/lib/components/reports/activity-card.js +281 -0
- package/src/lib/components/reports/activity-card.js.map +1 -0
- package/src/lib/components/reports/closed-deals-card.d.ts +20 -0
- package/src/lib/components/reports/closed-deals-card.js +194 -0
- package/src/lib/components/reports/closed-deals-card.js.map +1 -0
- package/src/lib/components/reports/contacts-mix-card.d.ts +27 -0
- package/src/lib/components/reports/contacts-mix-card.js +161 -0
- package/src/lib/components/reports/contacts-mix-card.js.map +1 -0
- package/src/lib/components/reports/contacts-trend-card.d.ts +31 -0
- package/src/lib/components/reports/contacts-trend-card.js +144 -0
- package/src/lib/components/reports/contacts-trend-card.js.map +1 -0
- package/src/lib/components/reports/forecast-card.d.ts +22 -0
- package/src/lib/components/reports/forecast-card.js +251 -0
- package/src/lib/components/reports/forecast-card.js.map +1 -0
- package/src/lib/components/reports/lead-counts.d.ts +32 -0
- package/src/lib/components/reports/lead-counts.js +44 -0
- package/src/lib/components/reports/lead-counts.js.map +1 -0
- package/src/lib/components/reports/lead-funnel-card.d.ts +38 -0
- package/src/lib/components/reports/lead-funnel-card.js +375 -0
- package/src/lib/components/reports/lead-funnel-card.js.map +1 -0
- package/src/lib/components/reports/pipeline-card.d.ts +19 -0
- package/src/lib/components/reports/pipeline-card.js +338 -0
- package/src/lib/components/reports/pipeline-card.js.map +1 -0
- package/src/lib/components/reports/report-bar-chart.d.ts +39 -0
- package/src/lib/components/reports/report-bar-chart.js +133 -0
- package/src/lib/components/reports/report-bar-chart.js.map +1 -0
- package/src/lib/components/reports/report-breakdown.d.ts +32 -0
- package/src/lib/components/reports/report-breakdown.js +105 -0
- package/src/lib/components/reports/report-breakdown.js.map +1 -0
- package/src/lib/components/reports/report-export.d.ts +37 -0
- package/src/lib/components/reports/report-export.js +66 -0
- package/src/lib/components/reports/report-export.js.map +1 -0
- package/src/lib/components/reports/report-format.d.ts +36 -0
- package/src/lib/components/reports/report-format.js +43 -0
- package/src/lib/components/reports/report-format.js.map +1 -0
- package/src/lib/components/reports/report-scope.d.ts +81 -0
- package/src/lib/components/reports/report-scope.js +58 -0
- package/src/lib/components/reports/report-scope.js.map +1 -0
- package/src/lib/components/reports/report-stat-tile.d.ts +47 -0
- package/src/lib/components/reports/report-stat-tile.js +96 -0
- package/src/lib/components/reports/report-stat-tile.js.map +1 -0
- package/src/lib/components/reports/source-conversion-card.d.ts +28 -0
- package/src/lib/components/reports/source-conversion-card.js +205 -0
- package/src/lib/components/reports/source-conversion-card.js.map +1 -0
- package/src/lib/components/reports/tasks-card.d.ts +26 -0
- package/src/lib/components/reports/tasks-card.js +279 -0
- package/src/lib/components/reports/tasks-card.js.map +1 -0
- package/src/lib/components/reports/use-aggregate-read.d.ts +99 -0
- package/src/lib/components/reports/use-aggregate-read.js +195 -0
- package/src/lib/components/reports/use-aggregate-read.js.map +1 -0
- package/src/lib/components/reports/won-lost-by-owner-card.d.ts +30 -0
- package/src/lib/components/reports/won-lost-by-owner-card.js +168 -0
- package/src/lib/components/reports/won-lost-by-owner-card.js.map +1 -0
- package/src/lib/components/reports-section.d.ts +42 -0
- package/src/lib/components/reports-section.js +308 -0
- package/src/lib/components/reports-section.js.map +1 -0
- package/src/lib/components/sending-addresses-card.d.ts +49 -0
- package/src/lib/components/sending-addresses-card.js +262 -0
- package/src/lib/components/sending-addresses-card.js.map +1 -0
- package/src/lib/components/settings-section.d.ts +151 -0
- package/src/lib/components/settings-section.js +783 -0
- package/src/lib/components/settings-section.js.map +1 -0
- package/src/lib/components/task-cells.d.ts +51 -0
- package/src/lib/components/task-cells.js +139 -0
- package/src/lib/components/task-cells.js.map +1 -0
- package/src/lib/components/task-edit-drawer.d.ts +53 -0
- package/src/lib/components/task-edit-drawer.js +483 -0
- package/src/lib/components/task-edit-drawer.js.map +1 -0
- package/src/lib/components/task-import-drawer.d.ts +24 -0
- package/src/lib/components/task-import-drawer.js +82 -0
- package/src/lib/components/task-import-drawer.js.map +1 -0
- package/src/lib/components/task-snooze-menu.d.ts +65 -0
- package/src/lib/components/task-snooze-menu.js +207 -0
- package/src/lib/components/task-snooze-menu.js.map +1 -0
- package/src/lib/components/tasks-bulk-bar.d.ts +25 -0
- package/src/lib/components/tasks-bulk-bar.js +348 -0
- package/src/lib/components/tasks-bulk-bar.js.map +1 -0
- package/src/lib/components/tasks-calendar.d.ts +38 -0
- package/src/lib/components/tasks-calendar.js +228 -0
- package/src/lib/components/tasks-calendar.js.map +1 -0
- package/src/lib/components/tasks-section.d.ts +27 -0
- package/src/lib/components/tasks-section.js +579 -0
- package/src/lib/components/tasks-section.js.map +1 -0
- package/src/lib/components/use-contact-campaign-emails.d.ts +32 -0
- package/src/lib/components/use-contact-campaign-emails.js +83 -0
- package/src/lib/components/use-contact-campaign-emails.js.map +1 -0
- package/src/lib/components/use-crm-api.d.ts +44 -0
- package/src/lib/components/use-crm-api.js +84 -0
- package/src/lib/components/use-crm-api.js.map +1 -0
- package/src/lib/components/use-crm-inbound-address.d.ts +60 -0
- package/src/lib/components/use-crm-inbound-address.js +124 -0
- package/src/lib/components/use-crm-inbound-address.js.map +1 -0
- package/src/lib/components/use-emails-hub-path.d.ts +24 -0
- package/src/lib/components/use-emails-hub-path.js +59 -0
- package/src/lib/components/use-emails-hub-path.js.map +1 -0
- package/src/lib/components/use-member-email-aliases.d.ts +54 -0
- package/src/lib/components/use-member-email-aliases.js +186 -0
- package/src/lib/components/use-member-email-aliases.js.map +1 -0
- package/src/lib/components/use-org-members.d.ts +40 -0
- package/src/lib/components/use-org-members.js +100 -0
- package/src/lib/components/use-org-members.js.map +1 -0
- package/src/lib/constants/api-routes.d.ts +109 -0
- package/src/lib/constants/api-routes.js +74 -0
- package/src/lib/constants/api-routes.js.map +1 -0
- package/src/lib/constants/bundle-common.d.ts +14 -0
- package/src/lib/constants/bundle-common.js +14 -0
- package/src/lib/constants/bundle-common.js.map +1 -0
- package/src/lib/constants/company-filters.d.ts +18 -0
- package/src/lib/constants/company-filters.js +51 -0
- package/src/lib/constants/company-filters.js.map +1 -0
- package/src/lib/constants/contact-filters.d.ts +38 -0
- package/src/lib/constants/contact-filters.js +294 -0
- package/src/lib/constants/contact-filters.js.map +1 -0
- package/src/lib/hooks/use-contact-field-definitions.d.ts +48 -0
- package/src/lib/hooks/use-contact-field-definitions.js +72 -0
- package/src/lib/hooks/use-contact-field-definitions.js.map +1 -0
- package/src/lib/hooks/use-contact-update.d.ts +25 -0
- package/src/lib/hooks/use-contact-update.js +80 -0
- package/src/lib/hooks/use-contact-update.js.map +1 -0
- package/src/lib/hooks/use-crm-activity-logger.d.ts +73 -0
- package/src/lib/hooks/use-crm-activity-logger.js +101 -0
- package/src/lib/hooks/use-crm-activity-logger.js.map +1 -0
- package/src/lib/hooks/use-crm-bulk-apply.d.ts +52 -0
- package/src/lib/hooks/use-crm-bulk-apply.js +112 -0
- package/src/lib/hooks/use-crm-bulk-apply.js.map +1 -0
- package/src/lib/hooks/use-crm-default-view.d.ts +24 -0
- package/src/lib/hooks/use-crm-default-view.js +64 -0
- package/src/lib/hooks/use-crm-default-view.js.map +1 -0
- package/src/lib/hooks/use-crm-email-templates.d.ts +59 -0
- package/src/lib/hooks/use-crm-email-templates.js +103 -0
- package/src/lib/hooks/use-crm-email-templates.js.map +1 -0
- package/src/lib/hooks/use-crm-hub-path.d.ts +29 -0
- package/src/lib/hooks/use-crm-hub-path.js +41 -0
- package/src/lib/hooks/use-crm-hub-path.js.map +1 -0
- package/src/lib/hooks/use-crm-org-mount.d.ts +97 -0
- package/src/lib/hooks/use-crm-org-mount.js +215 -0
- package/src/lib/hooks/use-crm-org-mount.js.map +1 -0
- package/src/lib/hooks/use-crm-record-names.d.ts +52 -0
- package/src/lib/hooks/use-crm-record-names.js +126 -0
- package/src/lib/hooks/use-crm-record-names.js.map +1 -0
- package/src/lib/hooks/use-crm-records-quota.d.ts +68 -0
- package/src/lib/hooks/use-crm-records-quota.js +118 -0
- package/src/lib/hooks/use-crm-records-quota.js.map +1 -0
- package/src/lib/hooks/use-crm-saved-view.d.ts +96 -0
- package/src/lib/hooks/use-crm-saved-view.js +329 -0
- package/src/lib/hooks/use-crm-saved-view.js.map +1 -0
- package/src/lib/hooks/use-crm-scope.d.ts +117 -0
- package/src/lib/hooks/use-crm-scope.js +147 -0
- package/src/lib/hooks/use-crm-scope.js.map +1 -0
- package/src/lib/hooks/use-crm-tasks.d.ts +85 -0
- package/src/lib/hooks/use-crm-tasks.js +153 -0
- package/src/lib/hooks/use-crm-tasks.js.map +1 -0
- package/src/lib/hooks/use-crm-view-grid.d.ts +55 -0
- package/src/lib/hooks/use-crm-view-grid.js +170 -0
- package/src/lib/hooks/use-crm-view-grid.js.map +1 -0
- package/src/lib/hooks/use-crm-views.d.ts +42 -0
- package/src/lib/hooks/use-crm-views.js +84 -0
- package/src/lib/hooks/use-crm-views.js.map +1 -0
- package/src/lib/hooks/use-deal-stage-api.d.ts +69 -0
- package/src/lib/hooks/use-deal-stage-api.js +78 -0
- package/src/lib/hooks/use-deal-stage-api.js.map +1 -0
- package/src/lib/hooks/use-deals.d.ts +47 -0
- package/src/lib/hooks/use-deals.js +105 -0
- package/src/lib/hooks/use-deals.js.map +1 -0
- package/src/lib/hooks/use-org-leads.d.ts +53 -0
- package/src/lib/hooks/use-org-leads.js +114 -0
- package/src/lib/hooks/use-org-leads.js.map +1 -0
- package/src/lib/hooks/use-org-member-directory.d.ts +36 -0
- package/src/lib/hooks/use-org-member-directory.js +116 -0
- package/src/lib/hooks/use-org-member-directory.js.map +1 -0
- package/src/lib/hooks/use-org-member-options.d.ts +38 -0
- package/src/lib/hooks/use-org-member-options.js +131 -0
- package/src/lib/hooks/use-org-member-options.js.map +1 -0
- package/src/lib/hooks/use-pipeline.d.ts +71 -0
- package/src/lib/hooks/use-pipeline.js +159 -0
- package/src/lib/hooks/use-pipeline.js.map +1 -0
- package/src/lib/model/companies-bulk-writes.d.ts +40 -0
- package/src/lib/model/companies-bulk-writes.js +103 -0
- package/src/lib/model/companies-bulk-writes.js.map +1 -0
- package/src/lib/model/companies-csv.d.ts +36 -0
- package/src/lib/model/companies-csv.js +38 -0
- package/src/lib/model/companies-csv.js.map +1 -0
- package/src/lib/model/companies.d.ts +99 -0
- package/src/lib/model/companies.js +168 -0
- package/src/lib/model/companies.js.map +1 -0
- package/src/lib/model/company-delete-route.d.ts +43 -0
- package/src/lib/model/company-delete-route.js +31 -0
- package/src/lib/model/company-delete-route.js.map +1 -0
- package/src/lib/model/company-delete.d.ts +42 -0
- package/src/lib/model/company-delete.js +52 -0
- package/src/lib/model/company-delete.js.map +1 -0
- package/src/lib/model/contact-duplicates.d.ts +58 -0
- package/src/lib/model/contact-duplicates.js +67 -0
- package/src/lib/model/contact-duplicates.js.map +1 -0
- package/src/lib/model/contact-record.d.ts +113 -0
- package/src/lib/model/contact-record.js +70 -0
- package/src/lib/model/contact-record.js.map +1 -0
- package/src/lib/model/contact-update.d.ts +93 -0
- package/src/lib/model/contact-update.js +50 -0
- package/src/lib/model/contact-update.js.map +1 -0
- package/src/lib/model/contacts-bulk-writes.d.ts +173 -0
- package/src/lib/model/contacts-bulk-writes.js +196 -0
- package/src/lib/model/contacts-bulk-writes.js.map +1 -0
- package/src/lib/model/contacts-csv.d.ts +54 -0
- package/src/lib/model/contacts-csv.js +67 -0
- package/src/lib/model/contacts-csv.js.map +1 -0
- package/src/lib/model/contacts-list-seed.d.ts +51 -0
- package/src/lib/model/contacts-list-seed.js +63 -0
- package/src/lib/model/contacts-list-seed.js.map +1 -0
- package/src/lib/model/crm-activity-report.d.ts +27 -0
- package/src/lib/model/crm-activity-report.js +56 -0
- package/src/lib/model/crm-activity-report.js.map +1 -0
- package/src/lib/model/crm-api.d.ts +49 -0
- package/src/lib/model/crm-api.js +47 -0
- package/src/lib/model/crm-api.js.map +1 -0
- package/src/lib/model/crm-bulk-writes.d.ts +147 -0
- package/src/lib/model/crm-bulk-writes.js +207 -0
- package/src/lib/model/crm-bulk-writes.js.map +1 -0
- package/src/lib/model/crm-company-import.d.ts +154 -0
- package/src/lib/model/crm-company-import.js +331 -0
- package/src/lib/model/crm-company-import.js.map +1 -0
- package/src/lib/model/crm-custom-draft.d.ts +62 -0
- package/src/lib/model/crm-custom-draft.js +67 -0
- package/src/lib/model/crm-custom-draft.js.map +1 -0
- package/src/lib/model/crm-deal-import.d.ts +112 -0
- package/src/lib/model/crm-deal-import.js +263 -0
- package/src/lib/model/crm-deal-import.js.map +1 -0
- package/src/lib/model/crm-import.d.ts +244 -0
- package/src/lib/model/crm-import.js +466 -0
- package/src/lib/model/crm-import.js.map +1 -0
- package/src/lib/model/crm-lead-import.d.ts +105 -0
- package/src/lib/model/crm-lead-import.js +255 -0
- package/src/lib/model/crm-lead-import.js.map +1 -0
- package/src/lib/model/crm-record-routes.d.ts +21 -0
- package/src/lib/model/crm-record-routes.js +70 -0
- package/src/lib/model/crm-record-routes.js.map +1 -0
- package/src/lib/model/crm-routes.d.ts +101 -0
- package/src/lib/model/crm-routes.js +92 -0
- package/src/lib/model/crm-routes.js.map +1 -0
- package/src/lib/model/crm-task-import.d.ts +94 -0
- package/src/lib/model/crm-task-import.js +275 -0
- package/src/lib/model/crm-task-import.js.map +1 -0
- package/src/lib/model/crm-view-param.d.ts +43 -0
- package/src/lib/model/crm-view-param.js +49 -0
- package/src/lib/model/crm-view-param.js.map +1 -0
- package/src/lib/model/deal-board-model.d.ts +241 -0
- package/src/lib/model/deal-board-model.js +439 -0
- package/src/lib/model/deal-board-model.js.map +1 -0
- package/src/lib/model/deal-form-model.d.ts +114 -0
- package/src/lib/model/deal-form-model.js +218 -0
- package/src/lib/model/deal-form-model.js.map +1 -0
- package/src/lib/model/deals-csv.d.ts +32 -0
- package/src/lib/model/deals-csv.js +37 -0
- package/src/lib/model/deals-csv.js.map +1 -0
- package/src/lib/model/import-column-shapes.d.ts +36 -0
- package/src/lib/model/import-column-shapes.js +76 -0
- package/src/lib/model/import-column-shapes.js.map +1 -0
- package/src/lib/model/lead-company-suggestion.d.ts +61 -0
- package/src/lib/model/lead-company-suggestion.js +65 -0
- package/src/lib/model/lead-company-suggestion.js.map +1 -0
- package/src/lib/model/lead-filters.d.ts +29 -0
- package/src/lib/model/lead-filters.js +39 -0
- package/src/lib/model/lead-filters.js.map +1 -0
- package/src/lib/model/lead-surfaces.d.ts +58 -0
- package/src/lib/model/lead-surfaces.js +67 -0
- package/src/lib/model/lead-surfaces.js.map +1 -0
- package/src/lib/model/leads-csv.d.ts +40 -0
- package/src/lib/model/leads-csv.js +40 -0
- package/src/lib/model/leads-csv.js.map +1 -0
- package/src/lib/model/next-activity-api.d.ts +31 -0
- package/src/lib/model/next-activity-api.js +57 -0
- package/src/lib/model/next-activity-api.js.map +1 -0
- package/src/lib/model/next-activity.d.ts +64 -0
- package/src/lib/model/next-activity.js +47 -0
- package/src/lib/model/next-activity.js.map +1 -0
- package/src/lib/model/person-key-web.d.ts +43 -0
- package/src/lib/model/person-key-web.js +52 -0
- package/src/lib/model/person-key-web.js.map +1 -0
- package/src/lib/model/record-facts.d.ts +282 -0
- package/src/lib/model/record-facts.js +434 -0
- package/src/lib/model/record-facts.js.map +1 -0
- package/src/lib/model/task-api.d.ts +28 -0
- package/src/lib/model/task-api.js +57 -0
- package/src/lib/model/task-api.js.map +1 -0
- package/src/lib/model/task-calendar.d.ts +108 -0
- package/src/lib/model/task-calendar.js +139 -0
- package/src/lib/model/task-calendar.js.map +1 -0
- package/src/lib/model/task-routes.d.ts +177 -0
- package/src/lib/model/task-routes.js +197 -0
- package/src/lib/model/task-routes.js.map +1 -0
- package/src/lib/model/task-scope.d.ts +45 -0
- package/src/lib/model/task-scope.js +51 -0
- package/src/lib/model/task-scope.js.map +1 -0
- package/src/lib/model/task-views.d.ts +149 -0
- package/src/lib/model/task-views.js +286 -0
- package/src/lib/model/task-views.js.map +1 -0
- package/src/lib/model/tasks-csv.d.ts +28 -0
- package/src/lib/model/tasks-csv.js +28 -0
- package/src/lib/model/tasks-csv.js.map +1 -0
- package/src/lib/plugin.d.ts +32 -0
- package/src/lib/plugin.js +208 -0
- package/src/lib/plugin.js.map +1 -0
- package/src/lib/server/companies-import.d.ts +57 -0
- package/src/lib/server/companies-import.js +242 -0
- package/src/lib/server/companies-import.js.map +1 -0
- package/src/lib/server/company-delete.d.ts +59 -0
- package/src/lib/server/company-delete.js +146 -0
- package/src/lib/server/company-delete.js.map +1 -0
- package/src/lib/server/contact-email-history.d.ts +82 -0
- package/src/lib/server/contact-email-history.js +264 -0
- package/src/lib/server/contact-email-history.js.map +1 -0
- package/src/lib/server/contact-profile.d.ts +41 -0
- package/src/lib/server/contact-profile.js +45 -0
- package/src/lib/server/contact-profile.js.map +1 -0
- package/src/lib/server/contact-update.d.ts +92 -0
- package/src/lib/server/contact-update.js +512 -0
- package/src/lib/server/contact-update.js.map +1 -0
- package/src/lib/server/contacts-import.d.ts +73 -0
- package/src/lib/server/contacts-import.js +263 -0
- package/src/lib/server/contacts-import.js.map +1 -0
- package/src/lib/server/contacts-merge.d.ts +86 -0
- package/src/lib/server/contacts-merge.js +206 -0
- package/src/lib/server/contacts-merge.js.map +1 -0
- package/src/lib/server/deals-import.d.ts +76 -0
- package/src/lib/server/deals-import.js +246 -0
- package/src/lib/server/deals-import.js.map +1 -0
- package/src/lib/server/email-send.d.ts +119 -0
- package/src/lib/server/email-send.js +667 -0
- package/src/lib/server/email-send.js.map +1 -0
- package/src/lib/server/email-template-duplicate.d.ts +19 -0
- package/src/lib/server/email-template-duplicate.js +206 -0
- package/src/lib/server/email-template-duplicate.js.map +1 -0
- package/src/lib/server/erase-person.d.ts +108 -0
- package/src/lib/server/erase-person.js +309 -0
- package/src/lib/server/erase-person.js.map +1 -0
- package/src/lib/server/import-context.d.ts +85 -0
- package/src/lib/server/import-context.js +181 -0
- package/src/lib/server/import-context.js.map +1 -0
- package/src/lib/server/inbound-address.d.ts +61 -0
- package/src/lib/server/inbound-address.js +188 -0
- package/src/lib/server/inbound-address.js.map +1 -0
- package/src/lib/server/lead-convert.d.ts +78 -0
- package/src/lib/server/lead-convert.js +250 -0
- package/src/lib/server/lead-convert.js.map +1 -0
- package/src/lib/server/leads-import.d.ts +84 -0
- package/src/lib/server/leads-import.js +261 -0
- package/src/lib/server/leads-import.js.map +1 -0
- package/src/lib/server/next-activity-routes.d.ts +33 -0
- package/src/lib/server/next-activity-routes.js +110 -0
- package/src/lib/server/next-activity-routes.js.map +1 -0
- package/src/lib/server/org-activity.d.ts +61 -0
- package/src/lib/server/org-activity.js +120 -0
- package/src/lib/server/org-activity.js.map +1 -0
- package/src/lib/server/org-caller.d.ts +110 -0
- package/src/lib/server/org-caller.js +154 -0
- package/src/lib/server/org-caller.js.map +1 -0
- package/src/lib/server/recipe-routes.d.ts +75 -0
- package/src/lib/server/recipe-routes.js +442 -0
- package/src/lib/server/recipe-routes.js.map +1 -0
- package/src/lib/server/record-facts.d.ts +65 -0
- package/src/lib/server/record-facts.js +337 -0
- package/src/lib/server/record-facts.js.map +1 -0
- package/src/lib/server/record-timeline.d.ts +51 -0
- package/src/lib/server/record-timeline.js +215 -0
- package/src/lib/server/record-timeline.js.map +1 -0
- package/src/lib/server/suite-gate.d.ts +42 -0
- package/src/lib/server/suite-gate.js +87 -0
- package/src/lib/server/suite-gate.js.map +1 -0
- package/src/lib/server/task-routes.d.ts +132 -0
- package/src/lib/server/task-routes.js +699 -0
- package/src/lib/server/task-routes.js.map +1 -0
- package/src/lib/server/tasks-import.d.ts +54 -0
- package/src/lib/server/tasks-import.js +157 -0
- package/src/lib/server/tasks-import.js.map +1 -0
- package/src/lib/server-deal-stage.d.ts +88 -0
- package/src/lib/server-deal-stage.js +316 -0
- package/src/lib/server-deal-stage.js.map +1 -0
- package/src/lib/server.d.ts +149 -0
- package/src/lib/server.js +615 -0
- package/src/lib/server.js.map +1 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
18
|
+
import { CRM_LEAD_STATUS_LABELS, crmLeadStatus } from "@aglyn/aglyn";
|
|
19
|
+
import { Chip } from "@mui/material";
|
|
20
|
+
/**
|
|
21
|
+
* One palette key per status, so the list and the record page paint the same
|
|
22
|
+
* state the same way. `qualified` is the converted state and reads as the
|
|
23
|
+
* success it is; `unqualified` is outlined and neutral — closed, not wrong.
|
|
24
|
+
*/ const STATUS_COLOR = {
|
|
25
|
+
new: 'info',
|
|
26
|
+
working: 'primary',
|
|
27
|
+
qualified: 'success',
|
|
28
|
+
unqualified: 'default'
|
|
29
|
+
};
|
|
30
|
+
/** A lead's status as a chip (AGL-2608). An absent status reads as New. */ export function LeadStatusChip(props) {
|
|
31
|
+
const { lead, size = 'small' } = props;
|
|
32
|
+
const status = crmLeadStatus(lead);
|
|
33
|
+
return /*#__PURE__*/ _jsx(Chip, {
|
|
34
|
+
size: size,
|
|
35
|
+
label: CRM_LEAD_STATUS_LABELS[status],
|
|
36
|
+
color: STATUS_COLOR[status],
|
|
37
|
+
variant: status === 'unqualified' ? 'outlined' : 'filled'
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
LeadStatusChip.displayName = 'LeadStatusChip';
|
|
41
|
+
export default LeadStatusChip;
|
|
42
|
+
|
|
43
|
+
//# sourceMappingURL=lead-status-chip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/lead-status-chip.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 CRM_LEAD_STATUS_LABELS,\n type CrmLeadFields,\n type CrmLeadStatus,\n crmLeadStatus,\n} from '@aglyn/aglyn'\nimport { Chip, type ChipProps } from '@mui/material'\n\n/**\n * One palette key per status, so the list and the record page paint the same\n * state the same way. `qualified` is the converted state and reads as the\n * success it is; `unqualified` is outlined and neutral — closed, not wrong.\n */\nconst STATUS_COLOR: Record<CrmLeadStatus, ChipProps['color']> = {\n new: 'info',\n working: 'primary',\n qualified: 'success',\n unqualified: 'default',\n}\n\nexport interface LeadStatusChipProps {\n lead: Pick<CrmLeadFields, 'status'> | null | undefined\n size?: ChipProps['size']\n}\n\n/** A lead's status as a chip (AGL-2608). An absent status reads as New. */\nexport function LeadStatusChip(props: LeadStatusChipProps) {\n const { lead, size = 'small' } = props\n const status = crmLeadStatus(lead)\n return (\n <Chip\n size={size}\n label={CRM_LEAD_STATUS_LABELS[status]}\n color={STATUS_COLOR[status]}\n variant={status === 'unqualified' ? 'outlined' : 'filled'}\n />\n )\n}\nLeadStatusChip.displayName = 'LeadStatusChip'\n\nexport default LeadStatusChip\n"],"names":["CRM_LEAD_STATUS_LABELS","crmLeadStatus","Chip","STATUS_COLOR","new","working","qualified","unqualified","LeadStatusChip","props","lead","size","status","label","color","variant","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAEA,SACEA,sBAAsB,EAGtBC,aAAa,QACR,eAAc;AACrB,SAASC,IAAI,QAAwB,gBAAe;AAEpD;;;;CAIC,GACD,MAAMC,eAA0D;IAC9DC,KAAK;IACLC,SAAS;IACTC,WAAW;IACXC,aAAa;AACf;AAOA,yEAAyE,GACzE,OAAO,SAASC,eAAeC,KAA0B;IACvD,MAAM,EAAEC,IAAI,EAAEC,OAAO,OAAO,EAAE,GAAGF;IACjC,MAAMG,SAASX,cAAcS;IAC7B,qBACE,KAACR;QACCS,MAAMA;QACNE,OAAOb,sBAAsB,CAACY,OAAO;QACrCE,OAAOX,YAAY,CAACS,OAAO;QAC3BG,SAASH,WAAW,gBAAgB,aAAa;;AAGvD;AACAJ,eAAeQ,WAAW,GAAG;AAE7B,eAAeR,eAAc"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { useFirestoreCollection } from '@aglyn/tenant-feature-instance';
|
|
18
|
+
import { type LeadSurfaceForm } from '../model/lead-surfaces';
|
|
19
|
+
export interface LeadSurfacesNoteProps {
|
|
20
|
+
hostId: string;
|
|
21
|
+
}
|
|
22
|
+
/** The always-on surfaces, named once wherever the note is drawn. */
|
|
23
|
+
export declare const LEAD_SURFACES_INTRO = "Leads are created by member sign-ups, bookings, and forms with lead routing on";
|
|
24
|
+
/** What every capture does whether or not it files a lead. */
|
|
25
|
+
export declare const LEAD_SURFACES_CONTACTS_TOO = "Every submission with an email address also updates the contact in Contacts at stage Lead.";
|
|
26
|
+
/** One site's forms, sorted into the two answers the note gives. */
|
|
27
|
+
export interface LeadSurfaceFormsResult {
|
|
28
|
+
/** `routing.lead` is on: every submission with an address files a lead. */
|
|
29
|
+
routed: LeadSurfaceForm[];
|
|
30
|
+
/** The rest, each with its verdict on whether the switch may be offered. */
|
|
31
|
+
unrouted: LeadSurfaceForm[];
|
|
32
|
+
/** The site has more forms than the window; the lists are not the whole answer. */
|
|
33
|
+
truncated: boolean;
|
|
34
|
+
status: ReturnType<typeof useFirestoreCollection>['status'];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The site's forms, ordered by id and bounded at one past the window — the
|
|
38
|
+
* same read the Inbox's form picker makes, ordered by `__name__` because a
|
|
39
|
+
* form saved without a display name would otherwise fall out of an ordered
|
|
40
|
+
* query and vanish from a list about routing. Host-scoped by path, so any
|
|
41
|
+
* member of the site may read it and no scope predicate is needed.
|
|
42
|
+
*
|
|
43
|
+
* One listener per call, so a note that groups several sites mounts one
|
|
44
|
+
* reader per site it shows and nothing for a site it has not opened.
|
|
45
|
+
*/
|
|
46
|
+
export declare function useLeadSurfaceForms(hostId: string): LeadSurfaceFormsResult;
|
|
47
|
+
/** The form a switch is mid-flight on — under which site, since a form id is only unique within one. */
|
|
48
|
+
export interface LeadRoutingTarget {
|
|
49
|
+
hostId: string;
|
|
50
|
+
formId: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The switch: one dotted `updateDoc` on `routing.lead`, so a dataset binding
|
|
54
|
+
* beside it is untouched, under the same host-content write the form's page
|
|
55
|
+
* makes. One at a time, whichever site the form is on — two switches in
|
|
56
|
+
* flight would be two toasts racing for the same reader.
|
|
57
|
+
*
|
|
58
|
+
* `siteName` rides into the toast when the note shows more than one site,
|
|
59
|
+
* because "Contact now files a lead" is an incomplete sentence to a reader
|
|
60
|
+
* who can see three forms called Contact.
|
|
61
|
+
*/
|
|
62
|
+
export declare function useTurnOnLeadRouting(): {
|
|
63
|
+
turningOn: LeadRoutingTarget | null;
|
|
64
|
+
turnOn: (target: {
|
|
65
|
+
hostId: string;
|
|
66
|
+
form: LeadSurfaceForm;
|
|
67
|
+
siteName?: string | null;
|
|
68
|
+
}) => Promise<void>;
|
|
69
|
+
};
|
|
70
|
+
/** A form by name, linked to its own page when the console can address it. */
|
|
71
|
+
export declare function LeadSurfaceFormName(props: {
|
|
72
|
+
form: LeadSurfaceForm;
|
|
73
|
+
href: string | null;
|
|
74
|
+
}): import("react").JSX.Element;
|
|
75
|
+
export declare namespace LeadSurfaceFormName {
|
|
76
|
+
var displayName: string;
|
|
77
|
+
}
|
|
78
|
+
/** The routed forms as one clause — "A, B, and possibly more" — for a sentence to end. */
|
|
79
|
+
export declare function LeadSurfaceFormList(props: {
|
|
80
|
+
forms: LeadSurfaceForm[];
|
|
81
|
+
truncated: boolean;
|
|
82
|
+
formHref: (formId: string) => string | null;
|
|
83
|
+
}): import("react").JSX.Element;
|
|
84
|
+
export declare namespace LeadSurfaceFormList {
|
|
85
|
+
var displayName: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* "Not routing leads:" — every form that does not route, with the switch
|
|
89
|
+
* beside the ones that could and the reason beside the ones that cannot.
|
|
90
|
+
*
|
|
91
|
+
* Offered only where `leadSurfaceForms` says the publish check would honor
|
|
92
|
+
* it — a form with no email field, or one that records no consent, is
|
|
93
|
+
* refused with the reason as the tooltip, because a switch that flips and
|
|
94
|
+
* then fails at publish is the exact confusion this note exists to remove.
|
|
95
|
+
*/
|
|
96
|
+
export declare function UnroutedLeadSurfaces(props: {
|
|
97
|
+
hostId: string;
|
|
98
|
+
forms: LeadSurfaceForm[];
|
|
99
|
+
formHref: (formId: string) => string | null;
|
|
100
|
+
turningOn: LeadRoutingTarget | null;
|
|
101
|
+
onTurnOn: (form: LeadSurfaceForm) => void;
|
|
102
|
+
}): import("react").JSX.Element;
|
|
103
|
+
export declare namespace UnroutedLeadSurfaces {
|
|
104
|
+
var displayName: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* WHAT CREATES A LEAD ON THIS SITE (AGL-2612).
|
|
108
|
+
*
|
|
109
|
+
* Every capture lands in Contacts; a LEAD is filed only by a lead surface —
|
|
110
|
+
* a member sign-up, a booking, or a form whose author declared
|
|
111
|
+
* `routing.lead`. The first two are always on and the third is a switch on
|
|
112
|
+
* each form's own page, which left the Leads list unable to say why one
|
|
113
|
+
* form's people were in it and another's were not. This says so, by name,
|
|
114
|
+
* and offers the switch here for the forms that could carry it.
|
|
115
|
+
*
|
|
116
|
+
* The reader, the switch and the two rows are shared with the
|
|
117
|
+
* organization-level note (`OrgLeadSurfacesNote`), which draws them once
|
|
118
|
+
* per site; this is the one-site composition. The form links resolve the
|
|
119
|
+
* site's console route from the host index, because under a site that is
|
|
120
|
+
* the only address the note is handed.
|
|
121
|
+
*/
|
|
122
|
+
export declare function LeadSurfacesNote(props: LeadSurfacesNoteProps): import("react").JSX.Element;
|
|
123
|
+
export declare namespace LeadSurfacesNote {
|
|
124
|
+
var displayName: string;
|
|
125
|
+
}
|
|
126
|
+
export default LeadSurfacesNote;
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
18
|
+
import { buildRoute, Route } from "@aglyn/aglyn";
|
|
19
|
+
import { AppLink } from "@aglyn/shared-ui-jsx";
|
|
20
|
+
import { useSnackbar } from "@aglyn/shared-ui-snackstack";
|
|
21
|
+
import { useConsoleHostRoute, useFirestore, useFirestoreCollection } from "@aglyn/tenant-feature-instance";
|
|
22
|
+
import { Button, Stack, Tooltip, Typography } from "@mui/material";
|
|
23
|
+
import { collection, doc, limit, orderBy, query, serverTimestamp, updateDoc } from "firebase/firestore";
|
|
24
|
+
import { useCallback, useMemo, useState } from "react";
|
|
25
|
+
import { LEAD_SURFACE_FORMS_WINDOW, leadSurfaceForms } from "../model/lead-surfaces.js";
|
|
26
|
+
/** The always-on surfaces, named once wherever the note is drawn. */ export const LEAD_SURFACES_INTRO = 'Leads are created by member sign-ups, bookings, and forms with lead routing on';
|
|
27
|
+
/** What every capture does whether or not it files a lead. */ export const LEAD_SURFACES_CONTACTS_TOO = 'Every submission with an email address also updates the contact in Contacts at stage Lead.';
|
|
28
|
+
/**
|
|
29
|
+
* The site's forms, ordered by id and bounded at one past the window — the
|
|
30
|
+
* same read the Inbox's form picker makes, ordered by `__name__` because a
|
|
31
|
+
* form saved without a display name would otherwise fall out of an ordered
|
|
32
|
+
* query and vanish from a list about routing. Host-scoped by path, so any
|
|
33
|
+
* member of the site may read it and no scope predicate is needed.
|
|
34
|
+
*
|
|
35
|
+
* One listener per call, so a note that groups several sites mounts one
|
|
36
|
+
* reader per site it shows and nothing for a site it has not opened.
|
|
37
|
+
*/ export function useLeadSurfaceForms(hostId) {
|
|
38
|
+
const firestore = useFirestore();
|
|
39
|
+
const { data: formDocs, status } = useFirestoreCollection(()=>query(collection(firestore, 'hosts', hostId, 'forms'), orderBy('__name__'), limit(LEAD_SURFACE_FORMS_WINDOW + 1)), [
|
|
40
|
+
firestore,
|
|
41
|
+
hostId
|
|
42
|
+
], {
|
|
43
|
+
idField: '$id'
|
|
44
|
+
});
|
|
45
|
+
return useMemo(()=>{
|
|
46
|
+
const forms = leadSurfaceForms(formDocs.slice(0, LEAD_SURFACE_FORMS_WINDOW));
|
|
47
|
+
return {
|
|
48
|
+
routed: forms.filter((form)=>form.routed),
|
|
49
|
+
unrouted: forms.filter((form)=>!form.routed),
|
|
50
|
+
truncated: formDocs.length > LEAD_SURFACE_FORMS_WINDOW,
|
|
51
|
+
status
|
|
52
|
+
};
|
|
53
|
+
}, [
|
|
54
|
+
formDocs,
|
|
55
|
+
status
|
|
56
|
+
]);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The switch: one dotted `updateDoc` on `routing.lead`, so a dataset binding
|
|
60
|
+
* beside it is untouched, under the same host-content write the form's page
|
|
61
|
+
* makes. One at a time, whichever site the form is on — two switches in
|
|
62
|
+
* flight would be two toasts racing for the same reader.
|
|
63
|
+
*
|
|
64
|
+
* `siteName` rides into the toast when the note shows more than one site,
|
|
65
|
+
* because "Contact now files a lead" is an incomplete sentence to a reader
|
|
66
|
+
* who can see three forms called Contact.
|
|
67
|
+
*/ export function useTurnOnLeadRouting() {
|
|
68
|
+
const firestore = useFirestore();
|
|
69
|
+
const { enqueueSnackbar } = useSnackbar();
|
|
70
|
+
const [turningOn, setTurningOn] = useState(null);
|
|
71
|
+
const turnOn = useCallback(async ({ hostId, form, siteName })=>{
|
|
72
|
+
if (turningOn) return;
|
|
73
|
+
setTurningOn({
|
|
74
|
+
hostId,
|
|
75
|
+
formId: form.$id
|
|
76
|
+
});
|
|
77
|
+
const where = siteName ? ` on ${siteName}` : '';
|
|
78
|
+
try {
|
|
79
|
+
await updateDoc(doc(firestore, 'hosts', hostId, 'forms', form.$id), {
|
|
80
|
+
'routing.lead': true,
|
|
81
|
+
updatedAt: serverTimestamp()
|
|
82
|
+
});
|
|
83
|
+
enqueueSnackbar(`"${form.displayName}"${where} now files a lead from every submission ` + 'that carries an email address.', {
|
|
84
|
+
variant: 'success',
|
|
85
|
+
persist: false
|
|
86
|
+
});
|
|
87
|
+
} catch (error) {
|
|
88
|
+
console.error(error);
|
|
89
|
+
enqueueSnackbar(`Lead routing could not be turned on${where}.`, {
|
|
90
|
+
variant: 'error',
|
|
91
|
+
allowDuplicate: true
|
|
92
|
+
});
|
|
93
|
+
} finally{
|
|
94
|
+
setTurningOn(null);
|
|
95
|
+
}
|
|
96
|
+
}, [
|
|
97
|
+
turningOn,
|
|
98
|
+
firestore,
|
|
99
|
+
enqueueSnackbar
|
|
100
|
+
]);
|
|
101
|
+
return {
|
|
102
|
+
turningOn,
|
|
103
|
+
turnOn
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/** A form by name, linked to its own page when the console can address it. */ export function LeadSurfaceFormName(props) {
|
|
107
|
+
const { form, href } = props;
|
|
108
|
+
return href ? /*#__PURE__*/ _jsx(AppLink, {
|
|
109
|
+
href: href,
|
|
110
|
+
children: form.displayName
|
|
111
|
+
}) : /*#__PURE__*/ _jsx("span", {
|
|
112
|
+
children: form.displayName
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
LeadSurfaceFormName.displayName = 'LeadSurfaceFormName';
|
|
116
|
+
/** The routed forms as one clause — "A, B, and possibly more" — for a sentence to end. */ export function LeadSurfaceFormList(props) {
|
|
117
|
+
const { forms, truncated, formHref } = props;
|
|
118
|
+
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
119
|
+
children: [
|
|
120
|
+
forms.map((form, index)=>/*#__PURE__*/ _jsxs("span", {
|
|
121
|
+
children: [
|
|
122
|
+
index ? ', ' : '',
|
|
123
|
+
/*#__PURE__*/ _jsx(LeadSurfaceFormName, {
|
|
124
|
+
form: form,
|
|
125
|
+
href: formHref(form.$id)
|
|
126
|
+
})
|
|
127
|
+
]
|
|
128
|
+
}, form.$id)),
|
|
129
|
+
truncated ? ', and possibly more' : ''
|
|
130
|
+
]
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
LeadSurfaceFormList.displayName = 'LeadSurfaceFormList';
|
|
134
|
+
/**
|
|
135
|
+
* "Not routing leads:" — every form that does not route, with the switch
|
|
136
|
+
* beside the ones that could and the reason beside the ones that cannot.
|
|
137
|
+
*
|
|
138
|
+
* Offered only where `leadSurfaceForms` says the publish check would honor
|
|
139
|
+
* it — a form with no email field, or one that records no consent, is
|
|
140
|
+
* refused with the reason as the tooltip, because a switch that flips and
|
|
141
|
+
* then fails at publish is the exact confusion this note exists to remove.
|
|
142
|
+
*/ export function UnroutedLeadSurfaces(props) {
|
|
143
|
+
const { hostId, forms, formHref, turningOn, onTurnOn } = props;
|
|
144
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
145
|
+
direction: "row",
|
|
146
|
+
spacing: 1,
|
|
147
|
+
sx: {
|
|
148
|
+
alignItems: 'center',
|
|
149
|
+
flexWrap: 'wrap',
|
|
150
|
+
rowGap: 0.5
|
|
151
|
+
},
|
|
152
|
+
children: [
|
|
153
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
154
|
+
variant: "caption",
|
|
155
|
+
color: "text.secondary",
|
|
156
|
+
children: 'Not routing leads:'
|
|
157
|
+
}),
|
|
158
|
+
forms.map((form)=>{
|
|
159
|
+
var _form_blocker;
|
|
160
|
+
const pending = (turningOn == null ? void 0 : turningOn.hostId) === hostId && turningOn.formId === form.$id;
|
|
161
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
162
|
+
direction: "row",
|
|
163
|
+
spacing: 0.5,
|
|
164
|
+
sx: {
|
|
165
|
+
alignItems: 'center'
|
|
166
|
+
},
|
|
167
|
+
children: [
|
|
168
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
169
|
+
variant: "caption",
|
|
170
|
+
component: "span",
|
|
171
|
+
children: /*#__PURE__*/ _jsx(LeadSurfaceFormName, {
|
|
172
|
+
form: form,
|
|
173
|
+
href: formHref(form.$id)
|
|
174
|
+
})
|
|
175
|
+
}),
|
|
176
|
+
/*#__PURE__*/ _jsx(Tooltip, {
|
|
177
|
+
title: (_form_blocker = form.blocker) != null ? _form_blocker : '',
|
|
178
|
+
children: /*#__PURE__*/ _jsx("span", {
|
|
179
|
+
children: /*#__PURE__*/ _jsx(Button, {
|
|
180
|
+
size: "small",
|
|
181
|
+
variant: "text",
|
|
182
|
+
disabled: !form.canRoute || turningOn !== null,
|
|
183
|
+
onClick: ()=>onTurnOn(form),
|
|
184
|
+
children: pending ? 'Turning on…' : 'Turn on lead routing'
|
|
185
|
+
})
|
|
186
|
+
})
|
|
187
|
+
})
|
|
188
|
+
]
|
|
189
|
+
}, form.$id);
|
|
190
|
+
})
|
|
191
|
+
]
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
UnroutedLeadSurfaces.displayName = 'UnroutedLeadSurfaces';
|
|
195
|
+
/**
|
|
196
|
+
* WHAT CREATES A LEAD ON THIS SITE (AGL-2612).
|
|
197
|
+
*
|
|
198
|
+
* Every capture lands in Contacts; a LEAD is filed only by a lead surface —
|
|
199
|
+
* a member sign-up, a booking, or a form whose author declared
|
|
200
|
+
* `routing.lead`. The first two are always on and the third is a switch on
|
|
201
|
+
* each form's own page, which left the Leads list unable to say why one
|
|
202
|
+
* form's people were in it and another's were not. This says so, by name,
|
|
203
|
+
* and offers the switch here for the forms that could carry it.
|
|
204
|
+
*
|
|
205
|
+
* The reader, the switch and the two rows are shared with the
|
|
206
|
+
* organization-level note (`OrgLeadSurfacesNote`), which draws them once
|
|
207
|
+
* per site; this is the one-site composition. The form links resolve the
|
|
208
|
+
* site's console route from the host index, because under a site that is
|
|
209
|
+
* the only address the note is handed.
|
|
210
|
+
*/ export function LeadSurfacesNote(props) {
|
|
211
|
+
const { hostId } = props;
|
|
212
|
+
const { orgSlug, subdomain: host } = useConsoleHostRoute(hostId);
|
|
213
|
+
const { routed, unrouted, truncated, status } = useLeadSurfaceForms(hostId);
|
|
214
|
+
const { turningOn, turnOn } = useTurnOnLeadRouting();
|
|
215
|
+
const formHref = useCallback((formId)=>orgSlug && host ? buildRoute(Route.FORM_DETAILS, {
|
|
216
|
+
orgSlug,
|
|
217
|
+
host,
|
|
218
|
+
formId
|
|
219
|
+
}) : null, [
|
|
220
|
+
orgSlug,
|
|
221
|
+
host
|
|
222
|
+
]);
|
|
223
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
224
|
+
spacing: 0.5,
|
|
225
|
+
children: [
|
|
226
|
+
/*#__PURE__*/ _jsxs(Typography, {
|
|
227
|
+
variant: "body2",
|
|
228
|
+
color: "text.secondary",
|
|
229
|
+
component: "div",
|
|
230
|
+
children: [
|
|
231
|
+
LEAD_SURFACES_INTRO,
|
|
232
|
+
status === 'loading' ? '…' : routed.length ? /*#__PURE__*/ _jsxs(_Fragment, {
|
|
233
|
+
children: [
|
|
234
|
+
': ',
|
|
235
|
+
/*#__PURE__*/ _jsx(LeadSurfaceFormList, {
|
|
236
|
+
forms: routed,
|
|
237
|
+
truncated: truncated,
|
|
238
|
+
formHref: formHref
|
|
239
|
+
}),
|
|
240
|
+
'.'
|
|
241
|
+
]
|
|
242
|
+
}) : ' — no form routes leads yet.',
|
|
243
|
+
` ${LEAD_SURFACES_CONTACTS_TOO}`
|
|
244
|
+
]
|
|
245
|
+
}),
|
|
246
|
+
unrouted.length ? /*#__PURE__*/ _jsx(UnroutedLeadSurfaces, {
|
|
247
|
+
hostId: hostId,
|
|
248
|
+
forms: unrouted,
|
|
249
|
+
formHref: formHref,
|
|
250
|
+
turningOn: turningOn,
|
|
251
|
+
onTurnOn: (form)=>void turnOn({
|
|
252
|
+
hostId,
|
|
253
|
+
form
|
|
254
|
+
})
|
|
255
|
+
}) : null
|
|
256
|
+
]
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
LeadSurfacesNote.displayName = 'LeadSurfacesNote';
|
|
260
|
+
export default LeadSurfacesNote;
|
|
261
|
+
|
|
262
|
+
//# sourceMappingURL=lead-surfaces-note.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/lead-surfaces-note.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n'use client'\n\nimport { buildRoute, Route } from '@aglyn/aglyn'\nimport { AppLink } from '@aglyn/shared-ui-jsx'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport {\n useConsoleHostRoute,\n useFirestore,\n useFirestoreCollection,\n} from '@aglyn/tenant-feature-instance'\nimport { Button, Stack, Tooltip, Typography } from '@mui/material'\nimport {\n collection,\n doc,\n limit,\n orderBy,\n query,\n serverTimestamp,\n updateDoc,\n} from 'firebase/firestore'\nimport { useCallback, useMemo, useState } from 'react'\nimport {\n LEAD_SURFACE_FORMS_WINDOW,\n type LeadSurfaceForm,\n leadSurfaceForms,\n} from '../model/lead-surfaces'\n\nexport interface LeadSurfacesNoteProps {\n hostId: string\n}\n\n/** The always-on surfaces, named once wherever the note is drawn. */\nexport const LEAD_SURFACES_INTRO =\n 'Leads are created by member sign-ups, bookings, and forms with lead routing on'\n/** What every capture does whether or not it files a lead. */\nexport const LEAD_SURFACES_CONTACTS_TOO =\n 'Every submission with an email address also updates the contact in Contacts at stage Lead.'\n\n/** One site's forms, sorted into the two answers the note gives. */\nexport interface LeadSurfaceFormsResult {\n /** `routing.lead` is on: every submission with an address files a lead. */\n routed: LeadSurfaceForm[]\n /** The rest, each with its verdict on whether the switch may be offered. */\n unrouted: LeadSurfaceForm[]\n /** The site has more forms than the window; the lists are not the whole answer. */\n truncated: boolean\n status: ReturnType<typeof useFirestoreCollection>['status']\n}\n\n/**\n * The site's forms, ordered by id and bounded at one past the window — the\n * same read the Inbox's form picker makes, ordered by `__name__` because a\n * form saved without a display name would otherwise fall out of an ordered\n * query and vanish from a list about routing. Host-scoped by path, so any\n * member of the site may read it and no scope predicate is needed.\n *\n * One listener per call, so a note that groups several sites mounts one\n * reader per site it shows and nothing for a site it has not opened.\n */\nexport function useLeadSurfaceForms(hostId: string): LeadSurfaceFormsResult {\n const firestore = useFirestore()\n const { data: formDocs, status } = useFirestoreCollection<\n Record<string, unknown> & { $id: string }\n >(\n () =>\n query(\n collection(firestore, 'hosts', hostId, 'forms'),\n orderBy('__name__'),\n limit(LEAD_SURFACE_FORMS_WINDOW + 1),\n ),\n [firestore, hostId],\n { idField: '$id' },\n )\n return useMemo(() => {\n const forms = leadSurfaceForms(formDocs.slice(0, LEAD_SURFACE_FORMS_WINDOW))\n return {\n routed: forms.filter((form) => form.routed),\n unrouted: forms.filter((form) => !form.routed),\n truncated: formDocs.length > LEAD_SURFACE_FORMS_WINDOW,\n status,\n }\n }, [formDocs, status])\n}\n\n/** The form a switch is mid-flight on — under which site, since a form id is only unique within one. */\nexport interface LeadRoutingTarget {\n hostId: string\n formId: string\n}\n\n/**\n * The switch: one dotted `updateDoc` on `routing.lead`, so a dataset binding\n * beside it is untouched, under the same host-content write the form's page\n * makes. One at a time, whichever site the form is on — two switches in\n * flight would be two toasts racing for the same reader.\n *\n * `siteName` rides into the toast when the note shows more than one site,\n * because \"Contact now files a lead\" is an incomplete sentence to a reader\n * who can see three forms called Contact.\n */\nexport function useTurnOnLeadRouting(): {\n turningOn: LeadRoutingTarget | null\n turnOn: (target: {\n hostId: string\n form: LeadSurfaceForm\n siteName?: string | null\n }) => Promise<void>\n} {\n const firestore = useFirestore()\n const { enqueueSnackbar } = useSnackbar()\n const [turningOn, setTurningOn] = useState<LeadRoutingTarget | null>(null)\n const turnOn = useCallback(\n async ({\n hostId,\n form,\n siteName,\n }: {\n hostId: string\n form: LeadSurfaceForm\n siteName?: string | null\n }) => {\n if (turningOn) return\n setTurningOn({ hostId, formId: form.$id })\n const where = siteName ? ` on ${siteName}` : ''\n try {\n await updateDoc(doc(firestore, 'hosts', hostId, 'forms', form.$id), {\n 'routing.lead': true,\n updatedAt: serverTimestamp(),\n })\n enqueueSnackbar(\n `\"${form.displayName}\"${where} now files a lead from every submission ` +\n 'that carries an email address.',\n { variant: 'success', persist: false },\n )\n } catch (error) {\n console.error(error)\n enqueueSnackbar(`Lead routing could not be turned on${where}.`, {\n variant: 'error',\n allowDuplicate: true,\n })\n } finally {\n setTurningOn(null)\n }\n },\n [turningOn, firestore, enqueueSnackbar],\n )\n return { turningOn, turnOn }\n}\n\n/** A form by name, linked to its own page when the console can address it. */\nexport function LeadSurfaceFormName(props: {\n form: LeadSurfaceForm\n href: string | null\n}) {\n const { form, href } = props\n return href ? (\n <AppLink href={href}>{form.displayName}</AppLink>\n ) : (\n <span>{form.displayName}</span>\n )\n}\nLeadSurfaceFormName.displayName = 'LeadSurfaceFormName'\n\n/** The routed forms as one clause — \"A, B, and possibly more\" — for a sentence to end. */\nexport function LeadSurfaceFormList(props: {\n forms: LeadSurfaceForm[]\n truncated: boolean\n formHref: (formId: string) => string | null\n}) {\n const { forms, truncated, formHref } = props\n return (\n <>\n {forms.map((form, index) => (\n <span key={form.$id}>\n {index ? ', ' : ''}\n <LeadSurfaceFormName form={form} href={formHref(form.$id)} />\n </span>\n ))}\n {truncated ? ', and possibly more' : ''}\n </>\n )\n}\nLeadSurfaceFormList.displayName = 'LeadSurfaceFormList'\n\n/**\n * \"Not routing leads:\" — every form that does not route, with the switch\n * beside the ones that could and the reason beside the ones that cannot.\n *\n * Offered only where `leadSurfaceForms` says the publish check would honor\n * it — a form with no email field, or one that records no consent, is\n * refused with the reason as the tooltip, because a switch that flips and\n * then fails at publish is the exact confusion this note exists to remove.\n */\nexport function UnroutedLeadSurfaces(props: {\n hostId: string\n forms: LeadSurfaceForm[]\n formHref: (formId: string) => string | null\n turningOn: LeadRoutingTarget | null\n onTurnOn: (form: LeadSurfaceForm) => void\n}) {\n const { hostId, forms, formHref, turningOn, onTurnOn } = props\n return (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ alignItems: 'center', flexWrap: 'wrap', rowGap: 0.5 }}\n >\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Not routing leads:'}\n </Typography>\n {forms.map((form) => {\n const pending =\n turningOn?.hostId === hostId && turningOn.formId === form.$id\n return (\n <Stack\n key={form.$id}\n direction=\"row\"\n spacing={0.5}\n sx={{ alignItems: 'center' }}\n >\n <Typography variant=\"caption\" component=\"span\">\n <LeadSurfaceFormName form={form} href={formHref(form.$id)} />\n </Typography>\n {/*\n Disabled with the reason as its tooltip rather than absent:\n an absent control and an inapplicable one look alike, and\n only one of them says what to do about it.\n */}\n <Tooltip title={form.blocker ?? ''}>\n <span>\n <Button\n size=\"small\"\n variant=\"text\"\n disabled={!form.canRoute || turningOn !== null}\n onClick={() => onTurnOn(form)}\n >\n {pending ? 'Turning on…' : 'Turn on lead routing'}\n </Button>\n </span>\n </Tooltip>\n </Stack>\n )\n })}\n </Stack>\n )\n}\nUnroutedLeadSurfaces.displayName = 'UnroutedLeadSurfaces'\n\n/**\n * WHAT CREATES A LEAD ON THIS SITE (AGL-2612).\n *\n * Every capture lands in Contacts; a LEAD is filed only by a lead surface —\n * a member sign-up, a booking, or a form whose author declared\n * `routing.lead`. The first two are always on and the third is a switch on\n * each form's own page, which left the Leads list unable to say why one\n * form's people were in it and another's were not. This says so, by name,\n * and offers the switch here for the forms that could carry it.\n *\n * The reader, the switch and the two rows are shared with the\n * organization-level note (`OrgLeadSurfacesNote`), which draws them once\n * per site; this is the one-site composition. The form links resolve the\n * site's console route from the host index, because under a site that is\n * the only address the note is handed.\n */\nexport function LeadSurfacesNote(props: LeadSurfacesNoteProps) {\n const { hostId } = props\n const { orgSlug, subdomain: host } = useConsoleHostRoute(hostId)\n const { routed, unrouted, truncated, status } = useLeadSurfaceForms(hostId)\n const { turningOn, turnOn } = useTurnOnLeadRouting()\n\n const formHref = useCallback(\n (formId: string) =>\n orgSlug && host\n ? buildRoute(Route.FORM_DETAILS, { orgSlug, host, formId })\n : null,\n [orgSlug, host],\n )\n\n return (\n <Stack spacing={0.5}>\n <Typography variant=\"body2\" color=\"text.secondary\" component=\"div\">\n {LEAD_SURFACES_INTRO}\n {status === 'loading' ? (\n '…'\n ) : routed.length ? (\n <>\n {': '}\n <LeadSurfaceFormList forms={routed} truncated={truncated} formHref={formHref} />\n {'.'}\n </>\n ) : (\n ' — no form routes leads yet.'\n )}\n {` ${LEAD_SURFACES_CONTACTS_TOO}`}\n </Typography>\n {unrouted.length ? (\n <UnroutedLeadSurfaces\n hostId={hostId}\n forms={unrouted}\n formHref={formHref}\n turningOn={turningOn}\n onTurnOn={(form) => void turnOn({ hostId, form })}\n />\n ) : null}\n </Stack>\n )\n}\nLeadSurfacesNote.displayName = 'LeadSurfacesNote'\n\nexport default LeadSurfacesNote\n"],"names":["buildRoute","Route","AppLink","useSnackbar","useConsoleHostRoute","useFirestore","useFirestoreCollection","Button","Stack","Tooltip","Typography","collection","doc","limit","orderBy","query","serverTimestamp","updateDoc","useCallback","useMemo","useState","LEAD_SURFACE_FORMS_WINDOW","leadSurfaceForms","LEAD_SURFACES_INTRO","LEAD_SURFACES_CONTACTS_TOO","useLeadSurfaceForms","hostId","firestore","data","formDocs","status","idField","forms","slice","routed","filter","form","unrouted","truncated","length","useTurnOnLeadRouting","enqueueSnackbar","turningOn","setTurningOn","turnOn","siteName","formId","$id","where","updatedAt","displayName","variant","persist","error","console","allowDuplicate","LeadSurfaceFormName","props","href","span","LeadSurfaceFormList","formHref","map","index","UnroutedLeadSurfaces","onTurnOn","direction","spacing","sx","alignItems","flexWrap","rowGap","color","pending","component","title","blocker","size","disabled","canRoute","onClick","LeadSurfacesNote","orgSlug","subdomain","host","FORM_DETAILS"],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** The most a reason may say — shared with the bulk bar's one-reason-for-all (AGL-2662). */
|
|
2
|
+
export declare const UNQUALIFY_REASON_MAX = 500;
|
|
3
|
+
export interface LeadUnqualifyDialogProps {
|
|
4
|
+
open: boolean;
|
|
5
|
+
onClose: () => void;
|
|
6
|
+
hostId: string;
|
|
7
|
+
leadId: string;
|
|
8
|
+
/** How the lead reads in the title — its name, else its address. */
|
|
9
|
+
leadLabel: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Close a lead without converting it, with the reason why (AGL-2608).
|
|
13
|
+
*
|
|
14
|
+
* The reason is REQUIRED. An unqualified lead with no reason is a row that
|
|
15
|
+
* says only "somebody gave up", and the one thing a report on lost leads
|
|
16
|
+
* wants to count is why. A client-direct write: `hosts/{hostId}/leads` is
|
|
17
|
+
* not in the catch-all's update exclusions, so a site admin, editor or
|
|
18
|
+
* author may update it, and nothing here needs the server.
|
|
19
|
+
*/
|
|
20
|
+
export declare function LeadUnqualifyDialog(props: LeadUnqualifyDialogProps): import("react").JSX.Element;
|
|
21
|
+
export declare namespace LeadUnqualifyDialog {
|
|
22
|
+
var displayName: string;
|
|
23
|
+
}
|
|
24
|
+
export default LeadUnqualifyDialog;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
18
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
19
|
+
import { useSnackbar } from "@aglyn/shared-ui-snackstack";
|
|
20
|
+
import { useFirestore } from "@aglyn/tenant-feature-instance";
|
|
21
|
+
import { Button, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, TextField } from "@mui/material";
|
|
22
|
+
import { doc, serverTimestamp, updateDoc } from "firebase/firestore";
|
|
23
|
+
import { useEffect, useState } from "react";
|
|
24
|
+
/** The most a reason may say — shared with the bulk bar's one-reason-for-all (AGL-2662). */ export const UNQUALIFY_REASON_MAX = 500;
|
|
25
|
+
const REASON_MAX = UNQUALIFY_REASON_MAX;
|
|
26
|
+
/**
|
|
27
|
+
* Close a lead without converting it, with the reason why (AGL-2608).
|
|
28
|
+
*
|
|
29
|
+
* The reason is REQUIRED. An unqualified lead with no reason is a row that
|
|
30
|
+
* says only "somebody gave up", and the one thing a report on lost leads
|
|
31
|
+
* wants to count is why. A client-direct write: `hosts/{hostId}/leads` is
|
|
32
|
+
* not in the catch-all's update exclusions, so a site admin, editor or
|
|
33
|
+
* author may update it, and nothing here needs the server.
|
|
34
|
+
*/ export function LeadUnqualifyDialog(props) {
|
|
35
|
+
const { open, onClose, hostId, leadId, leadLabel } = props;
|
|
36
|
+
const firestore = useFirestore();
|
|
37
|
+
const { enqueueSnackbar } = useSnackbar();
|
|
38
|
+
const [reason, setReason] = useState('');
|
|
39
|
+
const [busy, setBusy] = useState(false);
|
|
40
|
+
useEffect(()=>{
|
|
41
|
+
if (open) setReason('');
|
|
42
|
+
}, [
|
|
43
|
+
open
|
|
44
|
+
]);
|
|
45
|
+
const submit = async ()=>{
|
|
46
|
+
const trimmed = reason.trim();
|
|
47
|
+
if (!trimmed) return;
|
|
48
|
+
setBusy(true);
|
|
49
|
+
try {
|
|
50
|
+
const fields = {
|
|
51
|
+
status: 'unqualified',
|
|
52
|
+
unqualifiedReason: trimmed.slice(0, REASON_MAX)
|
|
53
|
+
};
|
|
54
|
+
await updateDoc(doc(firestore, 'hosts', hostId, 'leads', leadId), _extends({}, fields, {
|
|
55
|
+
updatedAt: serverTimestamp()
|
|
56
|
+
}));
|
|
57
|
+
enqueueSnackbar('Lead marked unqualified', {
|
|
58
|
+
variant: 'success',
|
|
59
|
+
persist: false
|
|
60
|
+
});
|
|
61
|
+
onClose();
|
|
62
|
+
} catch (error) {
|
|
63
|
+
enqueueSnackbar(error instanceof Error ? error.message : 'The lead could not be updated.', {
|
|
64
|
+
variant: 'error'
|
|
65
|
+
});
|
|
66
|
+
} finally{
|
|
67
|
+
setBusy(false);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
return /*#__PURE__*/ _jsxs(Dialog, {
|
|
71
|
+
open: open,
|
|
72
|
+
onClose: onClose,
|
|
73
|
+
maxWidth: "xs",
|
|
74
|
+
fullWidth: true,
|
|
75
|
+
children: [
|
|
76
|
+
/*#__PURE__*/ _jsx(DialogTitle, {
|
|
77
|
+
children: `Unqualify ${leadLabel}?`
|
|
78
|
+
}),
|
|
79
|
+
/*#__PURE__*/ _jsxs(DialogContent, {
|
|
80
|
+
children: [
|
|
81
|
+
/*#__PURE__*/ _jsx(DialogContentText, {
|
|
82
|
+
sx: {
|
|
83
|
+
mb: 2
|
|
84
|
+
},
|
|
85
|
+
children: 'The lead stays on file and drops out of the open list. Say why, ' + 'so the reason can be counted later.'
|
|
86
|
+
}),
|
|
87
|
+
/*#__PURE__*/ _jsx(TextField, {
|
|
88
|
+
label: "Reason",
|
|
89
|
+
value: reason,
|
|
90
|
+
onChange: (event)=>setReason(event.target.value),
|
|
91
|
+
multiline: true,
|
|
92
|
+
minRows: 2,
|
|
93
|
+
fullWidth: true,
|
|
94
|
+
autoFocus: true,
|
|
95
|
+
slotProps: {
|
|
96
|
+
htmlInput: {
|
|
97
|
+
maxLength: REASON_MAX
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
]
|
|
102
|
+
}),
|
|
103
|
+
/*#__PURE__*/ _jsxs(DialogActions, {
|
|
104
|
+
children: [
|
|
105
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
106
|
+
onClick: onClose,
|
|
107
|
+
disabled: busy,
|
|
108
|
+
children: 'Cancel'
|
|
109
|
+
}),
|
|
110
|
+
/*#__PURE__*/ _jsx(Button, {
|
|
111
|
+
variant: "contained",
|
|
112
|
+
color: "warning",
|
|
113
|
+
onClick: ()=>void submit(),
|
|
114
|
+
disabled: busy || !reason.trim(),
|
|
115
|
+
children: 'Unqualify'
|
|
116
|
+
})
|
|
117
|
+
]
|
|
118
|
+
})
|
|
119
|
+
]
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
LeadUnqualifyDialog.displayName = 'LeadUnqualifyDialog';
|
|
123
|
+
export default LeadUnqualifyDialog;
|
|
124
|
+
|
|
125
|
+
//# sourceMappingURL=lead-unqualify-dialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/lead-unqualify-dialog.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport type { CrmLeadFields } from '@aglyn/aglyn'\nimport { useSnackbar } from '@aglyn/shared-ui-snackstack'\nimport { useFirestore } from '@aglyn/tenant-feature-instance'\nimport {\n Button,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n TextField,\n} from '@mui/material'\nimport { doc, serverTimestamp, updateDoc } from 'firebase/firestore'\nimport { useEffect, useState } from 'react'\n\n/** The most a reason may say — shared with the bulk bar's one-reason-for-all (AGL-2662). */\nexport const UNQUALIFY_REASON_MAX = 500\nconst REASON_MAX = UNQUALIFY_REASON_MAX\n\nexport interface LeadUnqualifyDialogProps {\n open: boolean\n onClose: () => void\n hostId: string\n leadId: string\n /** How the lead reads in the title — its name, else its address. */\n leadLabel: string\n}\n\n/**\n * Close a lead without converting it, with the reason why (AGL-2608).\n *\n * The reason is REQUIRED. An unqualified lead with no reason is a row that\n * says only \"somebody gave up\", and the one thing a report on lost leads\n * wants to count is why. A client-direct write: `hosts/{hostId}/leads` is\n * not in the catch-all's update exclusions, so a site admin, editor or\n * author may update it, and nothing here needs the server.\n */\nexport function LeadUnqualifyDialog(props: LeadUnqualifyDialogProps) {\n const { open, onClose, hostId, leadId, leadLabel } = props\n const firestore = useFirestore()\n const { enqueueSnackbar } = useSnackbar()\n const [reason, setReason] = useState('')\n const [busy, setBusy] = useState(false)\n\n useEffect(() => {\n if (open) setReason('')\n }, [open])\n\n const submit = async () => {\n const trimmed = reason.trim()\n if (!trimmed) return\n setBusy(true)\n try {\n const fields: Required<Pick<CrmLeadFields, 'status' | 'unqualifiedReason'>> = {\n status: 'unqualified',\n unqualifiedReason: trimmed.slice(0, REASON_MAX),\n }\n await updateDoc(doc(firestore, 'hosts', hostId, 'leads', leadId), {\n ...fields,\n updatedAt: serverTimestamp(),\n })\n enqueueSnackbar('Lead marked unqualified', { variant: 'success', persist: false })\n onClose()\n } catch (error) {\n enqueueSnackbar(\n error instanceof Error ? error.message : 'The lead could not be updated.',\n { variant: 'error' },\n )\n } finally {\n setBusy(false)\n }\n }\n\n return (\n <Dialog open={open} onClose={onClose} maxWidth=\"xs\" fullWidth>\n <DialogTitle>{`Unqualify ${leadLabel}?`}</DialogTitle>\n <DialogContent>\n <DialogContentText sx={{ mb: 2 }}>\n {'The lead stays on file and drops out of the open list. Say why, ' +\n 'so the reason can be counted later.'}\n </DialogContentText>\n <TextField\n label=\"Reason\"\n value={reason}\n onChange={(event) => setReason(event.target.value)}\n multiline\n minRows={2}\n fullWidth\n autoFocus\n slotProps={{ htmlInput: { maxLength: REASON_MAX } }}\n />\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose} disabled={busy}>\n {'Cancel'}\n </Button>\n <Button\n variant=\"contained\"\n color=\"warning\"\n onClick={() => void submit()}\n disabled={busy || !reason.trim()}\n >\n {'Unqualify'}\n </Button>\n </DialogActions>\n </Dialog>\n )\n}\nLeadUnqualifyDialog.displayName = 'LeadUnqualifyDialog'\n\nexport default LeadUnqualifyDialog\n"],"names":["useSnackbar","useFirestore","Button","Dialog","DialogActions","DialogContent","DialogContentText","DialogTitle","TextField","doc","serverTimestamp","updateDoc","useEffect","useState","UNQUALIFY_REASON_MAX","REASON_MAX","LeadUnqualifyDialog","props","open","onClose","hostId","leadId","leadLabel","firestore","enqueueSnackbar","reason","setReason","busy","setBusy","submit","trimmed","trim","fields","status","unqualifiedReason","slice","updatedAt","variant","persist","error","Error","message","maxWidth","fullWidth","sx","mb","label","value","onChange","event","target","multiline","minRows","autoFocus","slotProps","htmlInput","maxLength","onClick","disabled","color","displayName"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;;AAGA,SAASA,WAAW,QAAQ,8BAA6B;AACzD,SAASC,YAAY,QAAQ,iCAAgC;AAC7D,SACEC,MAAM,EACNC,MAAM,EACNC,aAAa,EACbC,aAAa,EACbC,iBAAiB,EACjBC,WAAW,EACXC,SAAS,QACJ,gBAAe;AACtB,SAASC,GAAG,EAAEC,eAAe,EAAEC,SAAS,QAAQ,qBAAoB;AACpE,SAASC,SAAS,EAAEC,QAAQ,QAAQ,QAAO;AAE3C,0FAA0F,GAC1F,OAAO,MAAMC,uBAAuB,IAAG;AACvC,MAAMC,aAAaD;AAWnB;;;;;;;;CAQC,GACD,OAAO,SAASE,oBAAoBC,KAA+B;IACjE,MAAM,EAAEC,IAAI,EAAEC,OAAO,EAAEC,MAAM,EAAEC,MAAM,EAAEC,SAAS,EAAE,GAAGL;IACrD,MAAMM,YAAYtB;IAClB,MAAM,EAAEuB,eAAe,EAAE,GAAGxB;IAC5B,MAAM,CAACyB,QAAQC,UAAU,GAAGb,SAAS;IACrC,MAAM,CAACc,MAAMC,QAAQ,GAAGf,SAAS;IAEjCD,UAAU;QACR,IAAIM,MAAMQ,UAAU;IACtB,GAAG;QAACR;KAAK;IAET,MAAMW,SAAS;QACb,MAAMC,UAAUL,OAAOM,IAAI;QAC3B,IAAI,CAACD,SAAS;QACdF,QAAQ;QACR,IAAI;YACF,MAAMI,SAAwE;gBAC5EC,QAAQ;gBACRC,mBAAmBJ,QAAQK,KAAK,CAAC,GAAGpB;YACtC;YACA,MAAMJ,UAAUF,IAAIc,WAAW,SAASH,QAAQ,SAASC,SAAS,aAC7DW;gBACHI,WAAW1B;;YAEbc,gBAAgB,2BAA2B;gBAAEa,SAAS;gBAAWC,SAAS;YAAM;YAChFnB;QACF,EAAE,OAAOoB,OAAO;YACdf,gBACEe,iBAAiBC,QAAQD,MAAME,OAAO,GAAG,kCACzC;gBAAEJ,SAAS;YAAQ;QAEvB,SAAU;YACRT,QAAQ;QACV;IACF;IAEA,qBACE,MAACzB;QAAOe,MAAMA;QAAMC,SAASA;QAASuB,UAAS;QAAKC,SAAS;;0BAC3D,KAACpC;0BAAa,CAAC,UAAU,EAAEe,UAAU,CAAC,CAAC;;0BACvC,MAACjB;;kCACC,KAACC;wBAAkBsC,IAAI;4BAAEC,IAAI;wBAAE;kCAC5B,qEACC;;kCAEJ,KAACrC;wBACCsC,OAAM;wBACNC,OAAOtB;wBACPuB,UAAU,CAACC,QAAUvB,UAAUuB,MAAMC,MAAM,CAACH,KAAK;wBACjDI,SAAS;wBACTC,SAAS;wBACTT,SAAS;wBACTU,SAAS;wBACTC,WAAW;4BAAEC,WAAW;gCAAEC,WAAWzC;4BAAW;wBAAE;;;;0BAGtD,MAACX;;kCACC,KAACF;wBAAOuD,SAAStC;wBAASuC,UAAU/B;kCACjC;;kCAEH,KAACzB;wBACCmC,SAAQ;wBACRsB,OAAM;wBACNF,SAAS,IAAM,KAAK5B;wBACpB6B,UAAU/B,QAAQ,CAACF,OAAOM,IAAI;kCAE7B;;;;;;AAKX;AACAf,oBAAoB4C,WAAW,GAAG;AAElC,eAAe5C,oBAAmB"}
|