@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,163 @@
|
|
|
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 { pluginDocsHelp, normalizeContactEmail, readErasureRequestedAtMs } from "@aglyn/aglyn";
|
|
19
|
+
import { useFirestore, useFirestoreDoc, useOrgDataScope } from "@aglyn/tenant-feature-instance";
|
|
20
|
+
import { Stack, Typography } from "@mui/material";
|
|
21
|
+
import { doc } from "firebase/firestore";
|
|
22
|
+
import { useState } from "react";
|
|
23
|
+
import { useOrgMemberOptions } from "../hooks/use-org-member-options.js";
|
|
24
|
+
import { crmRoutes } from "../model/crm-routes.js";
|
|
25
|
+
import { CrmRecordHeader } from "./crm-record-header.js";
|
|
26
|
+
import { CrmRecordInsightsZone } from "./crm-record-insights-zone.js";
|
|
27
|
+
import { useErasePersonAction } from "./erase-person-action.js";
|
|
28
|
+
import { LeadConvertDialog } from "./lead-convert-dialog.js";
|
|
29
|
+
import { LeadHistoryCard } from "./lead-history-card.js";
|
|
30
|
+
import { LeadPropertiesCard } from "./lead-properties-card.js";
|
|
31
|
+
import { LeadUnqualifyDialog } from "./lead-unqualify-dialog.js";
|
|
32
|
+
import { RecordActivityCard } from "./record-activity-card.js";
|
|
33
|
+
/**
|
|
34
|
+
* `/crm/leads/{leadId}` — one lead (AGL-2608).
|
|
35
|
+
*
|
|
36
|
+
* The record behind a row of the Leads section: what the person did on the
|
|
37
|
+
* site, who is working them, and the conversion that turns them into a
|
|
38
|
+
* contact, a company and a deal. One document listen — `hosts/{hostId}/leads`
|
|
39
|
+
* is host-scoped by path, so there is no `visibleTo` to filter — and one
|
|
40
|
+
* roster request for the owner picker; the convert dialog's reads open only
|
|
41
|
+
* when it does.
|
|
42
|
+
*/ export function LeadDetailPage(props) {
|
|
43
|
+
const { id, hostId, org, basePath } = props;
|
|
44
|
+
const firestore = useFirestore();
|
|
45
|
+
const routes = crmRoutes(basePath);
|
|
46
|
+
const { data: lead, status, fromCache } = useFirestoreDoc(()=>doc(firestore, 'hosts', hostId, 'leads', id), [
|
|
47
|
+
firestore,
|
|
48
|
+
hostId,
|
|
49
|
+
id
|
|
50
|
+
]);
|
|
51
|
+
const { orgId } = useOrgDataScope({
|
|
52
|
+
hostId
|
|
53
|
+
});
|
|
54
|
+
const roster = useOrgMemberOptions(orgId);
|
|
55
|
+
const [converting, setConverting] = useState(false);
|
|
56
|
+
const [unqualifying, setUnqualifying] = useState(false);
|
|
57
|
+
// The privacy erasure (AGL-2623), offered from the lead as from the
|
|
58
|
+
// contact: the same request, filed by the lead's address.
|
|
59
|
+
const leadEmail = lead ? normalizeContactEmail(lead['email']) : null;
|
|
60
|
+
const erase = useErasePersonAction({
|
|
61
|
+
hostId,
|
|
62
|
+
orgId,
|
|
63
|
+
subject: lead && leadEmail ? {
|
|
64
|
+
kind: 'lead',
|
|
65
|
+
id,
|
|
66
|
+
email: leadEmail
|
|
67
|
+
} : null,
|
|
68
|
+
requestedAtMs: readErasureRequestedAtMs(lead)
|
|
69
|
+
});
|
|
70
|
+
const label = lead ? String(lead['name'] || lead['email'] || id) : undefined;
|
|
71
|
+
if (status === 'error' || status === 'success' && !lead) {
|
|
72
|
+
return /*#__PURE__*/ _jsx(CrmRecordHeader, {
|
|
73
|
+
kind: "Lead",
|
|
74
|
+
title: undefined,
|
|
75
|
+
help: pluginDocsHelp('crmLeads', {
|
|
76
|
+
anchor: '#a-leads-page'
|
|
77
|
+
}),
|
|
78
|
+
backHref: routes.section('leads'),
|
|
79
|
+
backLabel: "Back to leads",
|
|
80
|
+
children: /*#__PURE__*/ _jsx(Typography, {
|
|
81
|
+
variant: "body2",
|
|
82
|
+
color: "text.secondary",
|
|
83
|
+
children: status === 'error' ? 'This lead could not be read.' : 'This lead no longer exists — it may have been removed from the Inbox.'
|
|
84
|
+
})
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (!lead) {
|
|
88
|
+
return /*#__PURE__*/ _jsx(CrmRecordHeader, {
|
|
89
|
+
kind: "Lead",
|
|
90
|
+
title: undefined,
|
|
91
|
+
help: pluginDocsHelp('crmLeads', {
|
|
92
|
+
anchor: '#a-leads-page'
|
|
93
|
+
}),
|
|
94
|
+
backHref: routes.section('leads'),
|
|
95
|
+
backLabel: "Back to leads",
|
|
96
|
+
loading: true
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
100
|
+
children: [
|
|
101
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
102
|
+
spacing: 3,
|
|
103
|
+
children: [
|
|
104
|
+
/*#__PURE__*/ _jsx(LeadPropertiesCard, {
|
|
105
|
+
hostId: hostId,
|
|
106
|
+
leadId: id,
|
|
107
|
+
lead: lead,
|
|
108
|
+
leadStatus: status,
|
|
109
|
+
fromCache: fromCache,
|
|
110
|
+
basePath: basePath,
|
|
111
|
+
roster: roster,
|
|
112
|
+
onConvert: ()=>setConverting(true),
|
|
113
|
+
onUnqualify: ()=>setUnqualifying(true),
|
|
114
|
+
extraMenuItems: erase.menuItems,
|
|
115
|
+
banner: erase.banner,
|
|
116
|
+
erasurePending: erase.pendingSinceMs !== null,
|
|
117
|
+
org: org
|
|
118
|
+
}),
|
|
119
|
+
/*#__PURE__*/ _jsx(CrmRecordInsightsZone, {
|
|
120
|
+
hostId: hostId,
|
|
121
|
+
org: org,
|
|
122
|
+
kind: "lead",
|
|
123
|
+
recordId: id,
|
|
124
|
+
name: label != null ? label : ''
|
|
125
|
+
}),
|
|
126
|
+
/*#__PURE__*/ _jsx(LeadHistoryCard, {
|
|
127
|
+
hostId: hostId,
|
|
128
|
+
leadId: id,
|
|
129
|
+
lead: lead
|
|
130
|
+
}),
|
|
131
|
+
/*#__PURE__*/ _jsx(RecordActivityCard, {
|
|
132
|
+
hostId: hostId,
|
|
133
|
+
org: org,
|
|
134
|
+
leadId: id
|
|
135
|
+
})
|
|
136
|
+
]
|
|
137
|
+
}),
|
|
138
|
+
/*#__PURE__*/ _jsx(LeadConvertDialog, {
|
|
139
|
+
open: converting,
|
|
140
|
+
onClose: ()=>setConverting(false),
|
|
141
|
+
hostId: hostId,
|
|
142
|
+
orgId: orgId,
|
|
143
|
+
org: org,
|
|
144
|
+
leadId: id,
|
|
145
|
+
lead: lead,
|
|
146
|
+
basePath: basePath,
|
|
147
|
+
roster: roster
|
|
148
|
+
}),
|
|
149
|
+
/*#__PURE__*/ _jsx(LeadUnqualifyDialog, {
|
|
150
|
+
open: unqualifying,
|
|
151
|
+
onClose: ()=>setUnqualifying(false),
|
|
152
|
+
hostId: hostId,
|
|
153
|
+
leadId: id,
|
|
154
|
+
leadLabel: label != null ? label : id
|
|
155
|
+
}),
|
|
156
|
+
erase.dialog
|
|
157
|
+
]
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
LeadDetailPage.displayName = 'LeadDetailPage';
|
|
161
|
+
export default LeadDetailPage;
|
|
162
|
+
|
|
163
|
+
//# sourceMappingURL=lead-detail-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/lead-detail-page.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport {\n pluginDocsHelp,\n type CrmLeadFields,\n normalizeContactEmail,\n readErasureRequestedAtMs,\n} from '@aglyn/aglyn'\nimport {\n useFirestore,\n useFirestoreDoc,\n useOrgDataScope,\n} from '@aglyn/tenant-feature-instance'\nimport { Stack, Typography } from '@mui/material'\nimport { doc } from 'firebase/firestore'\nimport { useState } from 'react'\nimport { useOrgMemberOptions } from '../hooks/use-org-member-options'\nimport { type CrmDetailPageProps, crmRoutes } from '../model/crm-routes'\nimport { CrmRecordHeader } from './crm-record-header'\nimport { CrmRecordInsightsZone } from './crm-record-insights-zone'\nimport { useErasePersonAction } from './erase-person-action'\nimport { LeadConvertDialog } from './lead-convert-dialog'\nimport { LeadHistoryCard } from './lead-history-card'\nimport { LeadPropertiesCard } from './lead-properties-card'\nimport { LeadUnqualifyDialog } from './lead-unqualify-dialog'\nimport { RecordActivityCard } from './record-activity-card'\n\ntype LeadDocument = Record<string, unknown> & CrmLeadFields\n\n/**\n * `/crm/leads/{leadId}` — one lead (AGL-2608).\n *\n * The record behind a row of the Leads section: what the person did on the\n * site, who is working them, and the conversion that turns them into a\n * contact, a company and a deal. One document listen — `hosts/{hostId}/leads`\n * is host-scoped by path, so there is no `visibleTo` to filter — and one\n * roster request for the owner picker; the convert dialog's reads open only\n * when it does.\n */\nexport function LeadDetailPage(props: CrmDetailPageProps) {\n const { id, hostId, org, basePath } = props\n const firestore = useFirestore()\n const routes = crmRoutes(basePath)\n const {\n data: lead,\n status,\n fromCache,\n } = useFirestoreDoc<LeadDocument>(\n () => doc(firestore, 'hosts', hostId, 'leads', id),\n [firestore, hostId, id],\n )\n const { orgId } = useOrgDataScope({ hostId })\n const roster = useOrgMemberOptions(orgId)\n const [converting, setConverting] = useState(false)\n const [unqualifying, setUnqualifying] = useState(false)\n // The privacy erasure (AGL-2623), offered from the lead as from the\n // contact: the same request, filed by the lead's address.\n const leadEmail = lead ? normalizeContactEmail(lead['email']) : null\n const erase = useErasePersonAction({\n hostId,\n orgId,\n subject: lead && leadEmail ? { kind: 'lead', id, email: leadEmail } : null,\n requestedAtMs: readErasureRequestedAtMs(lead),\n })\n\n const label = lead ? String(lead['name'] || lead['email'] || id) : undefined\n\n if (status === 'error' || (status === 'success' && !lead)) {\n return (\n <CrmRecordHeader\n kind=\"Lead\"\n title={undefined}\n help={pluginDocsHelp('crmLeads', { anchor: '#a-leads-page' })}\n backHref={routes.section('leads')}\n backLabel=\"Back to leads\"\n >\n <Typography variant=\"body2\" color=\"text.secondary\">\n {status === 'error'\n ? 'This lead could not be read.'\n : 'This lead no longer exists — it may have been removed from the Inbox.'}\n </Typography>\n </CrmRecordHeader>\n )\n }\n if (!lead) {\n return (\n <CrmRecordHeader\n kind=\"Lead\"\n title={undefined}\n help={pluginDocsHelp('crmLeads', { anchor: '#a-leads-page' })}\n backHref={routes.section('leads')}\n backLabel=\"Back to leads\"\n loading\n />\n )\n }\n\n return (\n <>\n {/* The properties card is the record's lead card: it publishes the\n page heading and the trail, so the history card under it says what\n it holds rather than repeating the name. */}\n <Stack spacing={3}>\n <LeadPropertiesCard\n hostId={hostId}\n leadId={id}\n lead={lead}\n leadStatus={status}\n fromCache={fromCache}\n basePath={basePath}\n roster={roster}\n onConvert={() => setConverting(true)}\n onUnqualify={() => setUnqualifying(true)}\n extraMenuItems={erase.menuItems}\n banner={erase.banner}\n erasurePending={erase.pendingSinceMs !== null}\n org={org}\n />\n {/* What an assistant says about where the lead stands (AGL-2917): read on its own site. */}\n <CrmRecordInsightsZone\n hostId={hostId}\n org={org as Record<string, unknown> | undefined}\n kind=\"lead\"\n recordId={id}\n name={label ?? ''}\n />\n <LeadHistoryCard hostId={hostId} leadId={id} lead={lead} />\n <RecordActivityCard hostId={hostId} org={org} leadId={id} />\n </Stack>\n <LeadConvertDialog\n open={converting}\n onClose={() => setConverting(false)}\n hostId={hostId}\n orgId={orgId}\n org={org as Record<string, unknown> | undefined}\n leadId={id}\n lead={lead}\n basePath={basePath}\n roster={roster}\n />\n <LeadUnqualifyDialog\n open={unqualifying}\n onClose={() => setUnqualifying(false)}\n hostId={hostId}\n leadId={id}\n leadLabel={label ?? id}\n />\n {erase.dialog}\n </>\n )\n}\nLeadDetailPage.displayName = 'LeadDetailPage'\n\nexport default LeadDetailPage\n"],"names":["pluginDocsHelp","normalizeContactEmail","readErasureRequestedAtMs","useFirestore","useFirestoreDoc","useOrgDataScope","Stack","Typography","doc","useState","useOrgMemberOptions","crmRoutes","CrmRecordHeader","CrmRecordInsightsZone","useErasePersonAction","LeadConvertDialog","LeadHistoryCard","LeadPropertiesCard","LeadUnqualifyDialog","RecordActivityCard","LeadDetailPage","props","id","hostId","org","basePath","firestore","routes","data","lead","status","fromCache","orgId","roster","converting","setConverting","unqualifying","setUnqualifying","leadEmail","erase","subject","kind","email","requestedAtMs","label","String","undefined","title","help","anchor","backHref","section","backLabel","variant","color","loading","spacing","leadId","leadStatus","onConvert","onUnqualify","extraMenuItems","menuItems","banner","erasurePending","pendingSinceMs","recordId","name","open","onClose","leadLabel","dialog","displayName"],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The surfaces `addHostLead` names — `signup`, `booking`, `form:{formId}`,
|
|
3
|
+
* `import` — as they read on screen. A form's id is not a name, so it is
|
|
4
|
+
* shown as the kind with the id beside it rather than as an opaque token.
|
|
5
|
+
* The bare kind `form` is the lifecycle backfill's spelling for a person
|
|
6
|
+
* whose timeline kept no form id (AGL-2631), and reads as the kind, the
|
|
7
|
+
* way the contact's own source chip does.
|
|
8
|
+
*/
|
|
9
|
+
export declare function leadSourceLabel(source: string): string;
|
|
10
|
+
/** Every surface that produced a capture — the array, or the older single field. */
|
|
11
|
+
export declare function leadSources(lead: Record<string, unknown>): string[];
|
|
12
|
+
/** Epoch millis or a Firestore timestamp, as a local date-time, or a dash. */
|
|
13
|
+
export declare function leadTimeLabel(value: unknown): string;
|
|
14
|
+
export interface LeadHistoryCardProps {
|
|
15
|
+
hostId: string;
|
|
16
|
+
leadId: string;
|
|
17
|
+
lead: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* What the capture door recorded about this person (AGL-2608): every
|
|
21
|
+
* surface that produced a capture, how many times, and when the first and
|
|
22
|
+
* the latest happened — the fields `addHostLead` keeps on the one document
|
|
23
|
+
* per person — plus the campaign the first capture is credited to.
|
|
24
|
+
*
|
|
25
|
+
* Read-only by construction. Nothing here is the team's to edit: it is what
|
|
26
|
+
* the visitor did, and the CRM's working state lives on the card above it.
|
|
27
|
+
*/
|
|
28
|
+
export declare function LeadHistoryCard(props: LeadHistoryCardProps): import("react").JSX.Element;
|
|
29
|
+
export declare namespace LeadHistoryCard {
|
|
30
|
+
var displayName: string;
|
|
31
|
+
}
|
|
32
|
+
export default LeadHistoryCard;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
18
|
+
import { CAPTURED_BY_HOST_FIELD, CONTACT_SOURCE_LABELS, pluginDocsHelp } from "@aglyn/aglyn";
|
|
19
|
+
// The component path and NOT the marketing barrel, for the reason the Inbox
|
|
20
|
+
// and the contacts list give: the barrel is the tenant loader's entry point
|
|
21
|
+
// for the plugin's SITE half, and a console card named there ships to every
|
|
22
|
+
// published page.
|
|
23
|
+
import { CrmRecordAttributionZone, useHasCrmRecordAttribution } from "./crm-attribution-zone.js";
|
|
24
|
+
import { CardDisplay } from "@aglyn/shared-ui-jsx";
|
|
25
|
+
import { Chip, Stack, Typography } from "@mui/material";
|
|
26
|
+
/**
|
|
27
|
+
* The surfaces `addHostLead` names — `signup`, `booking`, `form:{formId}`,
|
|
28
|
+
* `import` — as they read on screen. A form's id is not a name, so it is
|
|
29
|
+
* shown as the kind with the id beside it rather than as an opaque token.
|
|
30
|
+
* The bare kind `form` is the lifecycle backfill's spelling for a person
|
|
31
|
+
* whose timeline kept no form id (AGL-2631), and reads as the kind, the
|
|
32
|
+
* way the contact's own source chip does.
|
|
33
|
+
*/ export function leadSourceLabel(source) {
|
|
34
|
+
if (source === 'signup') return 'Sign-up';
|
|
35
|
+
if (source === 'booking') return 'Booking';
|
|
36
|
+
if (source === 'import') return CONTACT_SOURCE_LABELS.import;
|
|
37
|
+
if (source === 'form') return CONTACT_SOURCE_LABELS.form;
|
|
38
|
+
if (source.startsWith('form:')) return `Form ${source.slice('form:'.length)}`;
|
|
39
|
+
return source;
|
|
40
|
+
}
|
|
41
|
+
/** Every surface that produced a capture — the array, or the older single field. */ export function leadSources(lead) {
|
|
42
|
+
const sources = lead['sources'];
|
|
43
|
+
if (Array.isArray(sources) && sources.length) {
|
|
44
|
+
return sources.map((source)=>String(source));
|
|
45
|
+
}
|
|
46
|
+
return typeof lead['source'] === 'string' && lead['source'] ? [
|
|
47
|
+
lead['source']
|
|
48
|
+
] : [];
|
|
49
|
+
}
|
|
50
|
+
/** Epoch millis or a Firestore timestamp, as a local date-time, or a dash. */ export function leadTimeLabel(value) {
|
|
51
|
+
var _value_toDate;
|
|
52
|
+
if (typeof value === 'number' && Number.isFinite(value)) {
|
|
53
|
+
return new Date(value).toLocaleString();
|
|
54
|
+
}
|
|
55
|
+
const asDate = value == null ? void 0 : (_value_toDate = value.toDate) == null ? void 0 : _value_toDate.call(value);
|
|
56
|
+
return asDate ? asDate.toLocaleString() : '—';
|
|
57
|
+
}
|
|
58
|
+
function Fact(props) {
|
|
59
|
+
return /*#__PURE__*/ _jsxs(Stack, {
|
|
60
|
+
spacing: 0.25,
|
|
61
|
+
children: [
|
|
62
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
63
|
+
variant: "caption",
|
|
64
|
+
color: "text.secondary",
|
|
65
|
+
children: props.label
|
|
66
|
+
}),
|
|
67
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
68
|
+
variant: "body2",
|
|
69
|
+
component: "div",
|
|
70
|
+
children: props.children
|
|
71
|
+
})
|
|
72
|
+
]
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* What the capture door recorded about this person (AGL-2608): every
|
|
77
|
+
* surface that produced a capture, how many times, and when the first and
|
|
78
|
+
* the latest happened — the fields `addHostLead` keeps on the one document
|
|
79
|
+
* per person — plus the campaign the first capture is credited to.
|
|
80
|
+
*
|
|
81
|
+
* Read-only by construction. Nothing here is the team's to edit: it is what
|
|
82
|
+
* the visitor did, and the CRM's working state lives on the card above it.
|
|
83
|
+
*/ export function LeadHistoryCard(props) {
|
|
84
|
+
var _lead_submissionCount, _lead_firstSeenAtMs, _lead_lastSeenAtMs;
|
|
85
|
+
const { hostId, leadId, lead } = props;
|
|
86
|
+
// The caption introduces what another plugin draws; with none loaded it
|
|
87
|
+
// would introduce nothing.
|
|
88
|
+
const hasAttribution = useHasCrmRecordAttribution();
|
|
89
|
+
const sources = leadSources(lead);
|
|
90
|
+
const capturedBy = lead[CAPTURED_BY_HOST_FIELD];
|
|
91
|
+
const count = Number((_lead_submissionCount = lead['submissionCount']) != null ? _lead_submissionCount : 0) || (sources.length ? 1 : 0);
|
|
92
|
+
return /*#__PURE__*/ _jsx(CardDisplay, {
|
|
93
|
+
header: 'Captured history',
|
|
94
|
+
help: pluginDocsHelp('crmLeads', {
|
|
95
|
+
anchor: '#a-leads-page'
|
|
96
|
+
}),
|
|
97
|
+
contentGutterX: true,
|
|
98
|
+
contentGutterY: true,
|
|
99
|
+
children: /*#__PURE__*/ _jsxs(Stack, {
|
|
100
|
+
spacing: 3,
|
|
101
|
+
children: [
|
|
102
|
+
/*#__PURE__*/ _jsxs(Stack, {
|
|
103
|
+
direction: {
|
|
104
|
+
xs: 'column',
|
|
105
|
+
md: 'row'
|
|
106
|
+
},
|
|
107
|
+
spacing: 3,
|
|
108
|
+
children: [
|
|
109
|
+
/*#__PURE__*/ _jsx(Fact, {
|
|
110
|
+
label: "First seen",
|
|
111
|
+
children: leadTimeLabel((_lead_firstSeenAtMs = lead['firstSeenAtMs']) != null ? _lead_firstSeenAtMs : lead['createdAt'])
|
|
112
|
+
}),
|
|
113
|
+
/*#__PURE__*/ _jsx(Fact, {
|
|
114
|
+
label: "Last seen",
|
|
115
|
+
children: leadTimeLabel((_lead_lastSeenAtMs = lead['lastSeenAtMs']) != null ? _lead_lastSeenAtMs : lead['createdAt'])
|
|
116
|
+
}),
|
|
117
|
+
/*#__PURE__*/ _jsx(Fact, {
|
|
118
|
+
label: "Captures",
|
|
119
|
+
children: count ? String(count) : '—'
|
|
120
|
+
}),
|
|
121
|
+
/*#__PURE__*/ _jsx(Fact, {
|
|
122
|
+
label: "Captured on",
|
|
123
|
+
children: Array.isArray(capturedBy) && capturedBy.length ? capturedBy.map(String).join(', ') : hostId
|
|
124
|
+
})
|
|
125
|
+
]
|
|
126
|
+
}),
|
|
127
|
+
/*#__PURE__*/ _jsx(Fact, {
|
|
128
|
+
label: "Sources",
|
|
129
|
+
children: sources.length ? /*#__PURE__*/ _jsx(Stack, {
|
|
130
|
+
direction: "row",
|
|
131
|
+
spacing: 0.5,
|
|
132
|
+
sx: {
|
|
133
|
+
flexWrap: 'wrap',
|
|
134
|
+
rowGap: 0.5
|
|
135
|
+
},
|
|
136
|
+
children: sources.map((source)=>/*#__PURE__*/ _jsx(Chip, {
|
|
137
|
+
size: "small",
|
|
138
|
+
variant: "outlined",
|
|
139
|
+
label: leadSourceLabel(source)
|
|
140
|
+
}, source))
|
|
141
|
+
}) : '—'
|
|
142
|
+
}),
|
|
143
|
+
hasAttribution ? /*#__PURE__*/ _jsxs(Stack, {
|
|
144
|
+
spacing: 1,
|
|
145
|
+
children: [
|
|
146
|
+
/*#__PURE__*/ _jsx(Typography, {
|
|
147
|
+
variant: "caption",
|
|
148
|
+
color: "text.secondary",
|
|
149
|
+
children: 'Where this lead came from'
|
|
150
|
+
}),
|
|
151
|
+
/*#__PURE__*/ _jsx(CrmRecordAttributionZone, {
|
|
152
|
+
hostId: hostId,
|
|
153
|
+
recordKind: "lead",
|
|
154
|
+
recordId: leadId
|
|
155
|
+
})
|
|
156
|
+
]
|
|
157
|
+
}) : null
|
|
158
|
+
]
|
|
159
|
+
})
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
LeadHistoryCard.displayName = 'LeadHistoryCard';
|
|
163
|
+
export default LeadHistoryCard;
|
|
164
|
+
|
|
165
|
+
//# sourceMappingURL=lead-history-card.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/lead-history-card.tsx"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n'use client'\n\nimport { CAPTURED_BY_HOST_FIELD, CONTACT_SOURCE_LABELS, pluginDocsHelp } from '@aglyn/aglyn'\n// The component path and NOT the marketing barrel, for the reason the Inbox\n// and the contacts list give: the barrel is the tenant loader's entry point\n// for the plugin's SITE half, and a console card named there ships to every\n// published page.\nimport {\n CrmRecordAttributionZone,\n useHasCrmRecordAttribution,\n} from './crm-attribution-zone'\nimport { CardDisplay } from '@aglyn/shared-ui-jsx'\nimport { Chip, Stack, Typography } from '@mui/material'\n\n/**\n * The surfaces `addHostLead` names — `signup`, `booking`, `form:{formId}`,\n * `import` — as they read on screen. A form's id is not a name, so it is\n * shown as the kind with the id beside it rather than as an opaque token.\n * The bare kind `form` is the lifecycle backfill's spelling for a person\n * whose timeline kept no form id (AGL-2631), and reads as the kind, the\n * way the contact's own source chip does.\n */\nexport function leadSourceLabel(source: string): string {\n if (source === 'signup') return 'Sign-up'\n if (source === 'booking') return 'Booking'\n if (source === 'import') return CONTACT_SOURCE_LABELS.import\n if (source === 'form') return CONTACT_SOURCE_LABELS.form\n if (source.startsWith('form:')) return `Form ${source.slice('form:'.length)}`\n return source\n}\n\n/** Every surface that produced a capture — the array, or the older single field. */\nexport function leadSources(lead: Record<string, unknown>): string[] {\n const sources = lead['sources']\n if (Array.isArray(sources) && sources.length) {\n return sources.map((source) => String(source))\n }\n return typeof lead['source'] === 'string' && lead['source'] ? [lead['source']] : []\n}\n\n/** Epoch millis or a Firestore timestamp, as a local date-time, or a dash. */\nexport function leadTimeLabel(value: unknown): string {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return new Date(value).toLocaleString()\n }\n const asDate = (value as { toDate?: () => Date } | null | undefined)?.toDate?.()\n return asDate ? asDate.toLocaleString() : '—'\n}\n\nfunction Fact(props: { label: string; children: React.ReactNode }) {\n return (\n <Stack spacing={0.25}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {props.label}\n </Typography>\n <Typography variant=\"body2\" component=\"div\">\n {props.children}\n </Typography>\n </Stack>\n )\n}\n\nexport interface LeadHistoryCardProps {\n hostId: string\n leadId: string\n lead: Record<string, unknown>\n}\n\n/**\n * What the capture door recorded about this person (AGL-2608): every\n * surface that produced a capture, how many times, and when the first and\n * the latest happened — the fields `addHostLead` keeps on the one document\n * per person — plus the campaign the first capture is credited to.\n *\n * Read-only by construction. Nothing here is the team's to edit: it is what\n * the visitor did, and the CRM's working state lives on the card above it.\n */\nexport function LeadHistoryCard(props: LeadHistoryCardProps) {\n const { hostId, leadId, lead } = props\n // The caption introduces what another plugin draws; with none loaded it\n // would introduce nothing.\n const hasAttribution = useHasCrmRecordAttribution()\n const sources = leadSources(lead)\n const capturedBy = lead[CAPTURED_BY_HOST_FIELD]\n const count = Number(lead['submissionCount'] ?? 0) || (sources.length ? 1 : 0)\n return (\n <CardDisplay\n header={'Captured history'}\n help={pluginDocsHelp('crmLeads', { anchor: '#a-leads-page' })}\n contentGutterX\n contentGutterY\n >\n <Stack spacing={3}>\n <Stack direction={{ xs: 'column', md: 'row' }} spacing={3}>\n <Fact label=\"First seen\">\n {leadTimeLabel(lead['firstSeenAtMs'] ?? lead['createdAt'])}\n </Fact>\n <Fact label=\"Last seen\">\n {leadTimeLabel(lead['lastSeenAtMs'] ?? lead['createdAt'])}\n </Fact>\n <Fact label=\"Captures\">{count ? String(count) : '—'}</Fact>\n <Fact label=\"Captured on\">\n {Array.isArray(capturedBy) && capturedBy.length\n ? capturedBy.map(String).join(', ')\n : hostId}\n </Fact>\n </Stack>\n <Fact label=\"Sources\">\n {sources.length ? (\n <Stack direction=\"row\" spacing={0.5} sx={{ flexWrap: 'wrap', rowGap: 0.5 }}>\n {sources.map((source) => (\n <Chip key={source} size=\"small\" variant=\"outlined\" label={leadSourceLabel(source)} />\n ))}\n </Stack>\n ) : (\n '—'\n )}\n </Fact>\n {hasAttribution ? (\n <Stack spacing={1}>\n <Typography variant=\"caption\" color=\"text.secondary\">\n {'Where this lead came from'}\n </Typography>\n <CrmRecordAttributionZone\n hostId={hostId}\n recordKind=\"lead\"\n recordId={leadId}\n />\n </Stack>\n ) : null}\n </Stack>\n </CardDisplay>\n )\n}\nLeadHistoryCard.displayName = 'LeadHistoryCard'\n\nexport default LeadHistoryCard\n"],"names":["CAPTURED_BY_HOST_FIELD","CONTACT_SOURCE_LABELS","pluginDocsHelp","CrmRecordAttributionZone","useHasCrmRecordAttribution","CardDisplay","Chip","Stack","Typography","leadSourceLabel","source","import","form","startsWith","slice","length","leadSources","lead","sources","Array","isArray","map","String","leadTimeLabel","value","Number","isFinite","Date","toLocaleString","asDate","toDate","Fact","props","spacing","variant","color","label","component","children","LeadHistoryCard","hostId","leadId","hasAttribution","capturedBy","count","header","help","anchor","contentGutterX","contentGutterY","direction","xs","md","join","sx","flexWrap","rowGap","size","recordKind","recordId","displayName"],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type LeadImportField, type LeadImportRawRow, type LeadImportSkippedRow } from '../model/crm-lead-import';
|
|
2
|
+
import { type CsvImportVocabulary } from './csv-import-drawer';
|
|
3
|
+
/** The browser-side address of the route one chunk is posted to. */
|
|
4
|
+
export declare const LEADS_IMPORT_URL = "/api/crm/leads-import";
|
|
5
|
+
/** Built once: nothing in it depends on a render. */
|
|
6
|
+
export declare const LEAD_IMPORT_VOCABULARY: CsvImportVocabulary<LeadImportField, LeadImportRawRow & Record<string, unknown>, LeadImportSkippedRow>;
|
|
7
|
+
export interface LeadImportDrawerProps {
|
|
8
|
+
open: boolean;
|
|
9
|
+
onClose: () => void;
|
|
10
|
+
/** The site the file is filed under, or `null` at the organization level. */
|
|
11
|
+
hostId: string | null;
|
|
12
|
+
}
|
|
13
|
+
export declare function LeadImportDrawer(props: LeadImportDrawerProps): import("react").JSX.Element;
|
|
14
|
+
export declare namespace LeadImportDrawer {
|
|
15
|
+
var displayName: string;
|
|
16
|
+
}
|
|
17
|
+
/** The "Import CSV" action on the leads list, with the drawer it opens. */
|
|
18
|
+
export declare function LeadImportButton(props: {
|
|
19
|
+
hostId: string | null;
|
|
20
|
+
}): import("react").JSX.Element;
|
|
21
|
+
export declare namespace LeadImportButton {
|
|
22
|
+
var displayName: string;
|
|
23
|
+
}
|
|
24
|
+
export default LeadImportDrawer;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2026 Aglyn LLC
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/ 'use client';
|
|
17
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
18
|
+
/**
|
|
19
|
+
* IMPORTING A LEADS FILE — the lead vocabulary over the shared drawer
|
|
20
|
+
* (AGL-2701).
|
|
21
|
+
*
|
|
22
|
+
* The server half is `server/leads-import.ts`. What is particular to
|
|
23
|
+
* leads: the address is the one cell every row needs AND the document's
|
|
24
|
+
* id, so a row is merged onto the person the site already holds rather
|
|
25
|
+
* than filed twice; the file may set only the team's working state, since
|
|
26
|
+
* the capture history is the capture door's; and there is no consent
|
|
27
|
+
* column, because a spreadsheet is not a checkbox somebody ticked.
|
|
28
|
+
*
|
|
29
|
+
* ## The site is the whole scope, so the picker is the whole question
|
|
30
|
+
*
|
|
31
|
+
* A lead lives under `hosts/{hostId}/leads` and is private to that site by
|
|
32
|
+
* path. At the organization level there is therefore no site to fall back
|
|
33
|
+
* on and no scope token that could stand in for one, so the shared
|
|
34
|
+
* drawer's site picker is not a convenience here — it is the only thing
|
|
35
|
+
* that says where the file lands, and the import stays held until it is
|
|
36
|
+
* answered.
|
|
37
|
+
*/ import { normalizeContactEmail, pluginDocsHelp } from "@aglyn/aglyn";
|
|
38
|
+
import { LEAD_IMPORT_CHUNK_SIZE, LEAD_IMPORT_FIELD_LABELS, LEAD_IMPORT_FIELDS, LEAD_IMPORT_MAX_ROWS, LEAD_IMPORT_PREVIEW_ROWS, LEAD_IMPORT_SKIP_LABELS, emptyLeadImportResult, guessLeadImportMapping, leadImportSkippedCsv, mapLeadImportRow, mergeLeadImportResults } from "../model/crm-lead-import.js";
|
|
39
|
+
import { leadsCsv } from "../model/leads-csv.js";
|
|
40
|
+
import { CsvImportButton, CsvImportDrawer } from "./csv-import-drawer.js";
|
|
41
|
+
/** The browser-side address of the route one chunk is posted to. */ export const LEADS_IMPORT_URL = '/api/crm/leads-import';
|
|
42
|
+
/** Built once: nothing in it depends on a render. */ export const LEAD_IMPORT_VOCABULARY = {
|
|
43
|
+
title: 'Import leads from CSV',
|
|
44
|
+
collection: 'leads',
|
|
45
|
+
help: pluginDocsHelp('crmLeads', {
|
|
46
|
+
anchor: '#import-from-csv'
|
|
47
|
+
}),
|
|
48
|
+
sitePickerHelperText: 'The site these leads are filed under — a lead is private to one site, ' + 'and this is the site that will hold them.',
|
|
49
|
+
intro: 'A CSV with a header row. Match its columns to lead fields below, check ' + 'the preview, then import. A person this site has already met is ' + 'updated rather than added twice. Nobody is emailed, and no marketing ' + 'consent is recorded — a file is not a checkbox somebody ticked, so an ' + 'imported lead can be mailed only if this site already holds a consent ' + `for them. Up to ${LEAD_IMPORT_MAX_ROWS.toLocaleString()} rows per file ` + '— split a larger one.',
|
|
50
|
+
fields: LEAD_IMPORT_FIELDS,
|
|
51
|
+
fieldLabels: LEAD_IMPORT_FIELD_LABELS,
|
|
52
|
+
requiredField: 'email',
|
|
53
|
+
requiredWarning: 'Choose which column holds the email address. It is the one field every ' + 'row needs, and it is what tells one lead from another.',
|
|
54
|
+
unusable: (cell)=>!normalizeContactEmail(cell),
|
|
55
|
+
unusableNotice: (count, total)=>`${count.toLocaleString()} of ${total.toLocaleString()} rows have no ` + 'usable email address and will be skipped. You can download them after ' + 'the import.',
|
|
56
|
+
guessMapping: guessLeadImportMapping,
|
|
57
|
+
mapRow: (cells, mapping)=>mapLeadImportRow(cells, mapping),
|
|
58
|
+
route: LEADS_IMPORT_URL,
|
|
59
|
+
maxRows: LEAD_IMPORT_MAX_ROWS,
|
|
60
|
+
chunkSize: LEAD_IMPORT_CHUNK_SIZE,
|
|
61
|
+
previewRows: LEAD_IMPORT_PREVIEW_ROWS,
|
|
62
|
+
emptyResult: emptyLeadImportResult,
|
|
63
|
+
mergeResults: mergeLeadImportResults,
|
|
64
|
+
skipLabels: LEAD_IMPORT_SKIP_LABELS,
|
|
65
|
+
skippedCsv: leadImportSkippedCsv,
|
|
66
|
+
skippedFileName: 'skipped-leads.csv',
|
|
67
|
+
// The export's own header over no rows, so an export re-imports as is —
|
|
68
|
+
// the columns a file cannot set land on "Do not import".
|
|
69
|
+
templateCsv: ()=>leadsCsv([]),
|
|
70
|
+
templateFileName: 'leads-template.csv'
|
|
71
|
+
};
|
|
72
|
+
export function LeadImportDrawer(props) {
|
|
73
|
+
const { open, onClose, hostId } = props;
|
|
74
|
+
return /*#__PURE__*/ _jsx(CsvImportDrawer, {
|
|
75
|
+
open: open,
|
|
76
|
+
onClose: onClose,
|
|
77
|
+
hostId: hostId,
|
|
78
|
+
vocabulary: LEAD_IMPORT_VOCABULARY
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
LeadImportDrawer.displayName = 'LeadImportDrawer';
|
|
82
|
+
/** The "Import CSV" action on the leads list, with the drawer it opens. */ export function LeadImportButton(props) {
|
|
83
|
+
const { hostId } = props;
|
|
84
|
+
return /*#__PURE__*/ _jsx(CsvImportButton, {
|
|
85
|
+
children: (open, onClose)=>/*#__PURE__*/ _jsx(LeadImportDrawer, {
|
|
86
|
+
open: open,
|
|
87
|
+
onClose: onClose,
|
|
88
|
+
hostId: hostId
|
|
89
|
+
})
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
LeadImportButton.displayName = 'LeadImportButton';
|
|
93
|
+
export default LeadImportDrawer;
|
|
94
|
+
|
|
95
|
+
//# sourceMappingURL=lead-import-drawer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/crm/src/lib/components/lead-import-drawer.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\n/**\n * IMPORTING A LEADS FILE — the lead vocabulary over the shared drawer\n * (AGL-2701).\n *\n * The server half is `server/leads-import.ts`. What is particular to\n * leads: the address is the one cell every row needs AND the document's\n * id, so a row is merged onto the person the site already holds rather\n * than filed twice; the file may set only the team's working state, since\n * the capture history is the capture door's; and there is no consent\n * column, because a spreadsheet is not a checkbox somebody ticked.\n *\n * ## The site is the whole scope, so the picker is the whole question\n *\n * A lead lives under `hosts/{hostId}/leads` and is private to that site by\n * path. At the organization level there is therefore no site to fall back\n * on and no scope token that could stand in for one, so the shared\n * drawer's site picker is not a convenience here — it is the only thing\n * that says where the file lands, and the import stays held until it is\n * answered.\n */\n\nimport { normalizeContactEmail, pluginDocsHelp } from '@aglyn/aglyn'\nimport {\n LEAD_IMPORT_CHUNK_SIZE,\n LEAD_IMPORT_FIELD_LABELS,\n LEAD_IMPORT_FIELDS,\n LEAD_IMPORT_MAX_ROWS,\n LEAD_IMPORT_PREVIEW_ROWS,\n LEAD_IMPORT_SKIP_LABELS,\n type LeadImportField,\n type LeadImportRawRow,\n type LeadImportSkippedRow,\n emptyLeadImportResult,\n guessLeadImportMapping,\n leadImportSkippedCsv,\n mapLeadImportRow,\n mergeLeadImportResults,\n} from '../model/crm-lead-import'\nimport { leadsCsv } from '../model/leads-csv'\nimport {\n CsvImportButton,\n CsvImportDrawer,\n type CsvImportVocabulary,\n} from './csv-import-drawer'\n\n/** The browser-side address of the route one chunk is posted to. */\nexport const LEADS_IMPORT_URL = '/api/crm/leads-import'\n\n/** Built once: nothing in it depends on a render. */\nexport const LEAD_IMPORT_VOCABULARY: CsvImportVocabulary<\n LeadImportField,\n LeadImportRawRow & Record<string, unknown>,\n LeadImportSkippedRow\n> = {\n title: 'Import leads from CSV',\n collection: 'leads',\n help: pluginDocsHelp('crmLeads', { anchor: '#import-from-csv' }),\n sitePickerHelperText:\n 'The site these leads are filed under — a lead is private to one site, ' +\n 'and this is the site that will hold them.',\n intro:\n 'A CSV with a header row. Match its columns to lead fields below, check ' +\n 'the preview, then import. A person this site has already met is ' +\n 'updated rather than added twice. Nobody is emailed, and no marketing ' +\n 'consent is recorded — a file is not a checkbox somebody ticked, so an ' +\n 'imported lead can be mailed only if this site already holds a consent ' +\n `for them. Up to ${LEAD_IMPORT_MAX_ROWS.toLocaleString()} rows per file ` +\n '— split a larger one.',\n fields: LEAD_IMPORT_FIELDS,\n fieldLabels: LEAD_IMPORT_FIELD_LABELS,\n requiredField: 'email',\n requiredWarning:\n 'Choose which column holds the email address. It is the one field every ' +\n 'row needs, and it is what tells one lead from another.',\n unusable: (cell) => !normalizeContactEmail(cell),\n unusableNotice: (count, total) =>\n `${count.toLocaleString()} of ${total.toLocaleString()} rows have no ` +\n 'usable email address and will be skipped. You can download them after ' +\n 'the import.',\n guessMapping: guessLeadImportMapping,\n mapRow: (cells, mapping) =>\n mapLeadImportRow(cells, mapping) as LeadImportRawRow & Record<string, unknown>,\n route: LEADS_IMPORT_URL,\n maxRows: LEAD_IMPORT_MAX_ROWS,\n chunkSize: LEAD_IMPORT_CHUNK_SIZE,\n previewRows: LEAD_IMPORT_PREVIEW_ROWS,\n emptyResult: emptyLeadImportResult,\n mergeResults: mergeLeadImportResults,\n skipLabels: LEAD_IMPORT_SKIP_LABELS,\n skippedCsv: leadImportSkippedCsv,\n skippedFileName: 'skipped-leads.csv',\n // The export's own header over no rows, so an export re-imports as is —\n // the columns a file cannot set land on \"Do not import\".\n templateCsv: () => leadsCsv([]),\n templateFileName: 'leads-template.csv',\n}\n\nexport interface LeadImportDrawerProps {\n open: boolean\n onClose: () => void\n /** The site the file is filed under, or `null` at the organization level. */\n hostId: string | null\n}\n\nexport function LeadImportDrawer(props: LeadImportDrawerProps) {\n const { open, onClose, hostId } = props\n return (\n <CsvImportDrawer\n open={open}\n onClose={onClose}\n hostId={hostId}\n vocabulary={LEAD_IMPORT_VOCABULARY}\n />\n )\n}\nLeadImportDrawer.displayName = 'LeadImportDrawer'\n\n/** The \"Import CSV\" action on the leads list, with the drawer it opens. */\nexport function LeadImportButton(props: { hostId: string | null }) {\n const { hostId } = props\n return (\n <CsvImportButton>\n {(open, onClose) => <LeadImportDrawer open={open} onClose={onClose} hostId={hostId} />}\n </CsvImportButton>\n )\n}\nLeadImportButton.displayName = 'LeadImportButton'\n\nexport default LeadImportDrawer\n"],"names":["normalizeContactEmail","pluginDocsHelp","LEAD_IMPORT_CHUNK_SIZE","LEAD_IMPORT_FIELD_LABELS","LEAD_IMPORT_FIELDS","LEAD_IMPORT_MAX_ROWS","LEAD_IMPORT_PREVIEW_ROWS","LEAD_IMPORT_SKIP_LABELS","emptyLeadImportResult","guessLeadImportMapping","leadImportSkippedCsv","mapLeadImportRow","mergeLeadImportResults","leadsCsv","CsvImportButton","CsvImportDrawer","LEADS_IMPORT_URL","LEAD_IMPORT_VOCABULARY","title","collection","help","anchor","sitePickerHelperText","intro","toLocaleString","fields","fieldLabels","requiredField","requiredWarning","unusable","cell","unusableNotice","count","total","guessMapping","mapRow","cells","mapping","route","maxRows","chunkSize","previewRows","emptyResult","mergeResults","skipLabels","skippedCsv","skippedFileName","templateCsv","templateFileName","LeadImportDrawer","props","open","onClose","hostId","vocabulary","displayName","LeadImportButton"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GACD;;AAEA;;;;;;;;;;;;;;;;;;;CAmBC,GAED,SAASA,qBAAqB,EAAEC,cAAc,QAAQ,eAAc;AACpE,SACEC,sBAAsB,EACtBC,wBAAwB,EACxBC,kBAAkB,EAClBC,oBAAoB,EACpBC,wBAAwB,EACxBC,uBAAuB,EAIvBC,qBAAqB,EACrBC,sBAAsB,EACtBC,oBAAoB,EACpBC,gBAAgB,EAChBC,sBAAsB,QACjB,8BAA0B;AACjC,SAASC,QAAQ,QAAQ,wBAAoB;AAC7C,SACEC,eAAe,EACfC,eAAe,QAEV,yBAAqB;AAE5B,kEAAkE,GAClE,OAAO,MAAMC,mBAAmB,wBAAuB;AAEvD,mDAAmD,GACnD,OAAO,MAAMC,yBAIT;IACFC,OAAO;IACPC,YAAY;IACZC,MAAMnB,eAAe,YAAY;QAAEoB,QAAQ;IAAmB;IAC9DC,sBACE,2EACA;IACFC,OACE,4EACA,qEACA,0EACA,2EACA,2EACA,CAAC,gBAAgB,EAAElB,qBAAqBmB,cAAc,GAAG,eAAe,CAAC,GACzE;IACFC,QAAQrB;IACRsB,aAAavB;IACbwB,eAAe;IACfC,iBACE,4EACA;IACFC,UAAU,CAACC,OAAS,CAAC9B,sBAAsB8B;IAC3CC,gBAAgB,CAACC,OAAOC,QACtB,GAAGD,MAAMR,cAAc,GAAG,IAAI,EAAES,MAAMT,cAAc,GAAG,cAAc,CAAC,GACtE,2EACA;IACFU,cAAczB;IACd0B,QAAQ,CAACC,OAAOC,UACd1B,iBAAiByB,OAAOC;IAC1BC,OAAOtB;IACPuB,SAASlC;IACTmC,WAAWtC;IACXuC,aAAanC;IACboC,aAAalC;IACbmC,cAAc/B;IACdgC,YAAYrC;IACZsC,YAAYnC;IACZoC,iBAAiB;IACjB,wEAAwE;IACxE,yDAAyD;IACzDC,aAAa,IAAMlC,SAAS,EAAE;IAC9BmC,kBAAkB;AACpB,EAAC;AASD,OAAO,SAASC,iBAAiBC,KAA4B;IAC3D,MAAM,EAAEC,IAAI,EAAEC,OAAO,EAAEC,MAAM,EAAE,GAAGH;IAClC,qBACE,KAACnC;QACCoC,MAAMA;QACNC,SAASA;QACTC,QAAQA;QACRC,YAAYrC;;AAGlB;AACAgC,iBAAiBM,WAAW,GAAG;AAE/B,yEAAyE,GACzE,OAAO,SAASC,iBAAiBN,KAAgC;IAC/D,MAAM,EAAEG,MAAM,EAAE,GAAGH;IACnB,qBACE,KAACpC;kBACE,CAACqC,MAAMC,wBAAY,KAACH;gBAAiBE,MAAMA;gBAAMC,SAASA;gBAASC,QAAQA;;;AAGlF;AACAG,iBAAiBD,WAAW,GAAG;AAE/B,eAAeN,iBAAgB"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type AglynOrgMember } from '@aglyn/aglyn';
|
|
2
|
+
import type { OrgMemberOptions } from '../hooks/use-org-member-options';
|
|
3
|
+
/** The `value` an owner select carries for "nobody". */
|
|
4
|
+
export declare const UNASSIGNED_OWNER = "";
|
|
5
|
+
/**
|
|
6
|
+
* How a member reads in a picker: the name they set, else their address,
|
|
7
|
+
* else the id — never blank, because a blank option cannot be chosen on
|
|
8
|
+
* purpose.
|
|
9
|
+
*/
|
|
10
|
+
export declare function orgMemberLabel(member: Pick<AglynOrgMember, '$id' | 'displayName' | 'email'>): string;
|
|
11
|
+
export interface LeadOwnerSelectProps {
|
|
12
|
+
value: string | null | undefined;
|
|
13
|
+
onChange: (uid: string) => void;
|
|
14
|
+
roster: OrgMemberOptions;
|
|
15
|
+
label?: string;
|
|
16
|
+
size?: 'small' | 'medium';
|
|
17
|
+
disabled?: boolean;
|
|
18
|
+
fullWidth?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The owner picker: Unassigned, then the roster by name.
|
|
22
|
+
*
|
|
23
|
+
* The stored value is resolved to a member first — by uid, or by an address
|
|
24
|
+
* the roster has — so the picker highlights the person and a save writes
|
|
25
|
+
* their uid. A value the roster does not hold is kept as its own option
|
|
26
|
+
* rather than dropped, because a controlled `Select` whose value is absent
|
|
27
|
+
* from its options renders empty — which would show a lead owned by
|
|
28
|
+
* somebody who left as owned by nobody, and a save from that state would
|
|
29
|
+
* make it true.
|
|
30
|
+
*/
|
|
31
|
+
export declare function LeadOwnerSelect(props: LeadOwnerSelectProps): import("react").JSX.Element;
|
|
32
|
+
export declare namespace LeadOwnerSelect {
|
|
33
|
+
var displayName: string;
|
|
34
|
+
}
|
|
35
|
+
export default LeadOwnerSelect;
|