1(function() { 2 try { 3 var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {}; 4 e.SENTRY_RELEASE = { id: "b96dc26" }; 5 var n = new e.Error().stack; 6 n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "d86d26e4-fc44-4ea0-8fd7-2e3da6868f6a", e._sentryDebugIdIdentifier = "sentry-dbid-d86d26e4-fc44-4ea0-8fd7-2e3da6868f6a"); 7 } catch (e) {} 8})(); 9import { n as __esmMin } from "./rolldown-runtime-sLwMD6dS.js"; 10import { As as Input, Ba as new_leads_import_path, Bi as leads_bulk_path, Dt as DropdownSearchInput, Eo as sequences_path, Et as DropdownMenuTrigger, Fi as lead_custom_attributes_path, Ii as lead_path, Ir as data_overview_leads_path, It as TabsList, Ja as operation_path, Ka as onboarding_steps_path, Li as lead_tag_path, Lt as init_tabs, M as init_currency_helper, Mi as init_routes, Mo as settings_leads_path, Nt as Tab, Os as Checkbox, Pt as Tabs, Qi as leads_export_path, Ri as lead_tagging_path, Xi as leads_crm_sync_path, Xn as checkout_get_more_credits_path, Xt as init_label, Yn as checkout_buy_credits_pack_path, Yr as discovers_path, Yt as Label, Zi as leads_email_finder_path, Zn as checkout_upgrade_plan_path, Zr as edit_lead_path, _a as leads_verify_path, aa as leads_list_folder_path, at as AlertDescription, bt as DropdownMenuItem, ca as leads_list_history_path, da as leads_list_path, ea as leads_import_path, er as columns_preferences_leads_path, et as Skeleton, fn as formatNumber, fo as sequence_audience_path, ft as DropdownMenu, ga as leads_selection_permissions_path, h as init_costCalculator, ha as leads_selection_ids_path, ht as DropdownMenuDivider, it as AlertContent, j as CurrencyHelper, js as init_input, ks as init_checkbox, kt as init_dropdown_menu, ln as countryCodeToFlag, lt as init_alert, m as CostCalculator, ma as leads_path, mo as sequence_path, mt as DropdownMenuContent, nt as Alert, pa as leads_lists_path, pn as init_text_helpers, ra as leads_list_favorite_path, sa as leads_list_folders_path, st as AlertIcon, tt as init_skeleton, ua as leads_list_merge_index_path, vt as DropdownMenuInlineItem, zi as lead_taggings_path } from "./controllers-jdPQjaCB.js"; 11import { a as isNumber, l as unsafeCast, o as isObject, r as isBoolean, s as isString, t as dictLookup } from "./type-guards-DVyG5ljW.js"; 12import { a as cn, i as require_compiler_runtime, l as getCsrfToken, t as require_jsx_runtime, u as init_utils } from "./jsx-runtime-CHSMGLHp.js"; 13import { t as require_react } from "./react-CrLPhuc5.js"; 14import { n as init_icon, t as Icon } from "./icon-BNzYbsdJ.js"; 15import { n as ButtonSuffix, r as init_button, t as Button } from "./button-DOiPZHfy.js"; 16import { a as init_tooltip, i as TooltipTrigger, n as TooltipContent, r as TooltipProvider, t as Tooltip } from "./tooltip-HHfiWInP.js"; 17import { dr as init_lead_lookalikes_sheet, fr as getLeadAvatarColor, hr as init_leadAvatar, i as init_radio_group, mr as getLeadInitials, n as RadioGroup, pr as getLeadGravatarUrl, r as RadioGroupItem, ur as LeadLookalikesSheet } from "./turbo-mount-DM0tFk1M.js"; 18import { a as SheetContent, c as SheetHeader, f as init_sheet, i as SheetBody, s as SheetFooter, t as Sheet, u as SheetTitle } from "./sheet-2lP39BDr.js"; 19import { n as Select, r as init_select } from "./select-CGg0QGYX.js"; 20import { n as init_hint, t as Hint } from "./hint-D06PdzJb.js"; 21import { n as init_radio, t as Radio } from "./radio-Dq6WWq34.js"; 22import { a as FilterValue, o as init_FilterValue } from "./inferred-email-tag-C2HWuGMo.js"; 23import { n as init_cost_indicator, t as CostIndicator } from "./cost-indicator-DKlBRQzL.js"; 24import { n as init_FolderSelect, t as FolderSelect } from "./FolderSelect--AzLq7IU.js"; 25import { r as init_company_logo, t as CompanyLogo } from "./company-logo-iCJP3mFk.js"; 26import { n as useActionCable, t as init_useActionCable } from "./useActionCable-BKKuFkGL.js"; 27import { n as init_PendingOperation, r as normalizePendingOperation, t as REVEAL_OPERATION_STARTED_EVENT } from "./PendingOperation-CmWkhrlg.js"; 28import { a as DialogFooter, i as DialogContent, n as DialogBody, o as DialogHeader, r as DialogCloseButton, s as DialogTitle, t as Dialog, u as init_dialog } from "./dialog-XgiZyeRA.js"; 29import { n as init_toggle_button, t as ToggleButton } from "./toggle-button-BRXgmw0N.js"; 30import { i as init_select_count_menu, n as SelectCountMenu, r as SelectCountMenuItems } from "./select-count-menu-CyKZwGL-.js"; 31import { a as EmptyStateDescription, c as EmptyStateImage, d as init_empty_state, i as EmptyStateContent, l as EmptyStateTitle, n as EmptyStateActions, t as EmptyState } from "./empty-state-Crv2GUlN.js"; 32import { n as useDialog, t as init_useDialog } from "./useDialog-CwjC07YA.js"; 33import { a as DataTableCheckboxCell, c as DataTableHeader, d as init_data_table, n as DataTableBody, r as DataTableCell, t as DataTable, u as DataTableRow } from "./data-table-DoMOEGfF.js"; 34import { n as init_data_table_bulk_actions_bar, t as DataTableBulkActionsBar } from "./data-table-bulk-actions-bar-Bw1ayYQn.js"; 35import { n as init_data_table_skeleton, t as DataTableSkeleton } from "./data-table-skeleton-CsePl50l.js"; 36import { n as init_toast, r as toast }
36 from "./toast-DdFPY0Ky.js"; 37import { a as init_dist, l as router, s as usePage, t as Head_default } from "./dist-ZlUHm0R7.js"; 38import { r as init_AppLayout, t as AppLayout } from "./AppLayout-KSwds5qH.js"; 39import { n as init_switch, t as Switch } from "./switch-BaZYiTgE.js"; 40import { C as FolderSettingsProvider, T as init_FolderSettingsMenu } from "./FilteredSidebarLists-BRH1D-HK.js"; 41import { n as useBulkSelection, t as init_useBulkSelection } from "./useBulkSelection-CP_rgTwY.js"; 42import { C as init_LocationFilter, D as useColumnResize, E as init_useColumnResize, O as OperationProgressBar, S as getLocationValueSelection, T as init_data_table_row_boundary, _ as TagsColumn, a as InsightsRow, b as LocationFilter, c as init_InsightsPanel, d as init_encoded_filter_value, f as isDateRangeEncoded, g as init_ListHeader$1, h as EntityListHeader, i as useInsightsPanel, k as init_OperationProgressBar, l as countOtherStaticLists, m as splitGenuineMultiValue, n as init_leads_reorganization_onboarding_dialog, o as init_InsightsRow, p as normalizeEncodedFilterValue, r as init_useInsightsPanel, s as InsightsPanel, t as LeadsReorganizationOnboardingDialog, v as init_TagsColumn, w as DataTableRowBoundary, x as getLocationValueLabel, y as LOCATION_PARAM_NAMES } from "./leads_reorganization_onboarding_dialog-CthYEICA.js"; 43import { c as init_date_presets, m as init_ColumnHeaderMenu, n as init_data_table_pagination, p as ColumnHeaderMenu, s as DATE_PRESET_LABELS, t as DataTablePagination } from "./data-table-pagination-CSSpM264.js"; 44import { n as leads_default, t as init_leads } from "./leads-BJeP3VZj.js"; 45import { n as init_CompanySidePanel, t as CompanySidePanel } from "./CompanySidePanel-DRX-ZQzq.js"; 46import { _ as init_SendingStatusColumn, a as focusFirstInvalidField, c as unfieldedErrors, g as SendingStatusColumn, i as FormErrors, n as init_LeadSidePanel, o as init_formErrors, r as FieldError, s as normalizeFormErrors, t as LeadSidePanel, u as leadCustomAttrValue } from "./LeadSidePanel-CR2rlYVP.js"; 47import { n as useScopedBodyClass, t as init_useScopedBodyClass } from "./useScopedBodyClass-DZ-bIKpP.js"; 48import { n as init_LeadsListSidebar, t as LeadsListSidebar } from "./LeadsListSidebar-DMsre0SF.js"; 49import { n as useLatestRef, t as init_useLatestRef } from "./useLatestRef-RoDCGx-y.js"; 50import { a as BOOLEAN_FILTERS, c as getFilterType, f as POSITION_KEYWORDS_FILTER, i as init_VerificationColumn, l as init_FilterBody, n as useImportProgress, p as init_JobTitleFilter, r as VerificationColumn, s as FilterBody, t as init_useImportProgress } from "./useImportProgress-GaQHT3Wj.js"; 51import { n as init_AddToListModal, t as AddToListModal } from "./AddToListModal-lfyxRoTj.js"; 52import { n as useSequencePicker, t as init_useSequencePicker } from "./useSequencePicker-DhIZOix7.js"; 53import { i as init_ImportProgressBar, r as ImportProgressBar } from "./estimateTimeLeft-BeLoWcA9.js"; 54//#region app/frontend/pages/Leads/leadUrlSync.ts 55function parseLeadPath(pathname) { 56 const match = pathname.match(LEAD_PATH_RE); 57 if (!match) return null; 58 return { 59 leadId: Number(match[1]), 60 mode: match[2] ? "edit" : "view" 61 }; 62} 63function buildLeadsUrl(params, leadId, mode) { 64 const base = leadId !== null ? mode === "edit" ? edit_lead_path(leadId) : lead_path(leadId) : leads_path(); 65 const qs = params.toString(); 66 return qs ? `${base}?${qs}` : base; 67} 68function searchParamsToRecord(params) { 69 const record = {}; 70 for (const key of new Set(params.keys())) { 71 const values = params.getAll(key); 72 record[key] = values.length > 1 ? values : values[0]; 73 } 74 return record; 75} 76var LEAD_PATH_RE; 77function init_leadUrlSync() { 78 return (init_leadUrlSync = __esmMin((() => { 79 init_routes(); 80 LEAD_PATH_RE = /^\/leads\/(\d+)(\/edit)?\/?$/; 81 })))(); 82} 83//#endregion 84//#region app/frontend/pages/Leads/listOperations.ts 85function listFilterScope(filters) { 86 const values = LIST_FILTER_KEYS.flatMap((key) => filterValues(filters, key)); 87 return { 88 listIds: values.map((value) => Number(value)).filter((id) => Number.isInteger(id) && id > 0), 89 matchesAnyList: values.some((value) => MEMBERSHIP_SENTINELS.includes(value)) 90 }; 91} 92function urlView(href, currentList, knownLists = []) { 93 const params = new URL(href, "http://localhost").searchParams; 94 const filters = {};
95 params.forEach((value, key) => { 96 filters[key] = filters[key] === void 0 ? value : `${filters[key]}|${value}`; 97 }); 98 const id = Number(params.get("leads_list_id") ?? params.get("leads_list_id[]")); 99 return { 100 list: !(Number.isInteger(id) && id > 0) ? VIRTUAL_VIEW : id === currentList.id ? currentList : knownLists.find((list) => list.id === id) ?? { 101 id, 102 type: "dynamic" 103 }, 104 filters, 105 scope: listFilterScope(filters) 106 }; 107} 108function listOperationRefresh(msg, leadsList, scope = NO_LIST_SCOPE) { 109 const scopedListIds = scope.listIds; 110 const touchedListIds = [msg.source_leads_list_id, msg.destination_leads_list_id]; 111 const touchesScopedList = scope.matchesAnyList || scopedListIds.some((id) => touchedListIds.includes(id)); 112 const destroyedListId = msg.operation === "merge" || msg.source_leads_list_destroyed ? msg.source_leads_list_id : null; 113 if (destroyedListId !== null && (leadsList.type !== "virtual" && leadsList.id === destroyedListId || scopedListIds.length > 0 && scopedListIds.every((id) => id === destroyedListId))) { 114 if (msg.destination_leads_list_id == null) return "leave-list"; 115 return msg.final_chunk ?? true ? "leave-list" : "wait"; 116 } 117 if (leadsList.type === "virtual") return touchesScopedList ? "refetch" : "counts-only"; 118 if (leadsList.type === "dynamic") return "refetch"; 119 return touchedListIds.includes(leadsList.id) || touchesScopedList ? "refetch" : "counts-only"; 120} 121var LIST_FILTER_KEYS, MEMBERSHIP_SENTINELS, filterValues, NO_LIST_SCOPE, VIRTUAL_VIEW; 122function init_listOperations() { 123 return (init_listOperations = __esmMin((() => { 124 LIST_FILTER_KEYS = ["static_list_id", "leads_list_id"]; 125 MEMBERSHIP_SENTINELS = ["*", "~"]; 126 filterValues = (filters, key) => [filters[key], filters[`${key}[]`]].flatMap((value) => (value ?? "").split("|")).filter(Boolean); 127 NO_LIST_SCOPE = { 128 listIds: [], 129 matchesAnyList: false 130 }; 131 VIRTUAL_VIEW = { 132 id: 0, 133 type: "virtual" 134 }; 135 })))(); 136} 137//#endregion 138//#region app/frontend/pages/Leads/importPathParams.ts 139function importPathParamsForList(leadsList) { 140 if (leadsList.type === "virtual") return {}; 141 return { leads_list_id: leadsList.id }; 142} 143//#endregion 144//#region app/frontend/pages/Leads/columns/NameColumn.tsx 145function LeadAvatar(t0) { 146 const $ = (0, import_compiler_runtime$14.c)(14); 147 const { lead } = t0; 148 const [imgFailed, setImgFailed] = (0, import_react$30.useState)(false); 149 let t1; 150 if ($[0] !== lead) { 151 t1 = getLeadGravatarUrl(lead); 152 $[0] = lead; 153 $[1] = t1; 154 } else t1 = $[1]; 155 const url = t1; 156 let t2; 157 let t3; 158 if ($[2] !== imgFailed || $[3] !== lead || $[4] !== url) { 159 t3 = Symbol.for("react.early_return_sentinel"); 160 bb0: { 161 const initials = getLeadInitials(lead); 162 let t4; 163 if ($[7] !== lead.id) { 164 t4 = getLeadAvatarColor(lead.id); 165 $[7] = lead.id; 166 $[8] = t4; 167 } else t4 = $[8]; 168 const bg = `#${t4}`; 169 if (url && !imgFailed) { 170 let t5; 171 if ($[9] === Symbol.for("react.memo_cache_sentinel")) { 172 t5 = () => setImgFailed(true); 173 $[9] = t5; 174 } else t5 = $[9]; 175 let t6; 176 if ($[10] !== url) { 177 t6 = /* @__PURE__ */ (0, import_jsx_runtime$32.jsx)("img", { 178 src: url, 179 alt: "", 180 className: "lead-tag__avatar", 181 loading: "lazy", 182 onError: t5 183 }); 184 $[10] = url; 185 $[11] = t6; 186 } else t6 = $[11]; 187 t3 = t6; 188 break bb0; 189 } 190 let t5; 191 if ($[12] !== bg) { 192 t5 = { backgroundColor: bg }; 193 $[12] = bg; 194 $[13] = t5; 195 } else t5 = $[13]; 196 t2 = /* @__PURE__ */ (0, import_jsx_runtime$32.jsx)("span", { 197 className: "lead-tag__avatar lead-tag__avatar--initials", 198 style: t5, 199 children: initials.toUpperCase() 200 }); 201 } 202 $[2] = imgFailed; 203 $[3] = lead; 204 $[4] = url; 205 $[5] = t2; 206 $[6] = t3; 207 } else { 208 t2 = $[5]; 209 t3 = $[6]; 210 } 211 if (t3 !== Symbol.for("react.early_return_sentinel")) return t3; 212 return t2; 213} 214var import_compiler_runtime$14, import_react$30, import_jsx_runtime$32, t$24, NameColumn; 215function init_NameColumn() { 216 return (init_NameColumn = __esmMin((() => { 217 import_compiler_runtime$14 = require_compiler_runtime(); 218 import_react$30 = require_react(); 219 init_leadAvatar(); 220 init_icon(); 221 import_jsx_runtime$32 = require_jsx_runtime(); 222 t$24 = (key) => window.i18n.t(key); 223 NameColumn = (0, import_react$30.memo)(function NameColumn(t0) { 224 const $ = (0, import_compiler_runtime$14.c)(14); 225 const { lead, onLeadClick } = t0; 226 let t1; 227 if ($[0] !== lead.id || $[1] !== onLeadClick) { 228 t1 = () => onLeadClick?.(lead.id); 229 $[0] = lead.id; 230 $[1] = onLeadClick; 231 $[2] = t1; 232 } else t1 = $[2]; 233 let t2; 234 if ($[3] !== lead) { 235 t2 = /* @__PURE__ */ (0, import_jsx_runtime$32.jsx)(LeadAvatar, { lead }); 236 $[3] = lead; 237 $[4] = t2; 238 } else t2 = $[4]; 239 let t3; 240 if ($[5] !== lead.fullName) {
241 t3 = lead.fullName?.trim() ? /* @__PURE__ */ (0, import_jsx_runtime$32.jsx)("div", { 242 className: "lead-tag__name", 243 children: lead.fullName 244 }) : /* @__PURE__ */ (0, import_jsx_runtime$32.jsx)("div", { 245 className: "lead-tag__name text-muted", 246 children: t$24("js.leads.page.no_name") 247 }); 248 $[5] = lead.fullName; 249 $[6] = t3; 250 } else t3 = $[6]; 251 let t4; 252 if ($[7] !== lead.decisionMaker) { 253 t4 = lead.decisionMaker && /* @__PURE__ */ (0, import_jsx_runtime$32.jsx)(Icon, { 254 icon: "crown", 255 size: "sm", 256 className: "text-hint", 257 role: "img", 258 "aria-hidden": false, 259 "aria-label": t$24("js.leads.page.decision_maker"), 260 title: t$24("js.leads.page.decision_maker") 261 }); 262 $[7] = lead.decisionMaker; 263 $[8] = t4; 264 } else t4 = $[8]; 265 let t5; 266 if ($[9] !== t1 || $[10] !== t2 || $[11] !== t3 || $[12] !== t4) { 267 t5 = /* @__PURE__ */ (0, import_jsx_runtime$32.jsxs)("button", { 268 type: "button", 269 className: "lead-tag lead-tag--people", 270 onClick: t1, 271 children: [ 272 t2, 273 t3, 274 t4 275 ] 276 }); 277 $[9] = t1; 278 $[10] = t2; 279 $[11] = t3; 280 $[12] = t4; 281 $[13] = t5; 282 } else t5 = $[13]; 283 return t5; 284 }); 285 })))(); 286} 287//#endregion 288//#region app/frontend/pages/Leads/columns/EmailColumn.tsx 289async function handleFindEmail(leadId, onFindEmailRequested, onFindEmailFailed) { 290 onFindEmailRequested?.(leadId); 291 const formData = new FormData(); 292 formData.append("lead_ids[]", String(leadId)); 293 formData.append("authenticity_token", getCsrfToken()); 294 try { 295 if (!(await fetch(leads_email_finder_path(), { 296 method: "POST", 297 headers: { Accept: "application/json" }, 298 body: formData 299 })).ok) onFindEmailFailed?.(leadId); 300 } catch { 301 onFindEmailFailed?.(leadId); 302 } 303} 304var import_compiler_runtime$13, import_react$29, import_jsx_runtime$31, t$23, EmailColumn; 305function init_EmailColumn() { 306 return (init_EmailColumn = __esmMin((() => { 307 import_compiler_runtime$13 = require_compiler_runtime(); 308 import_react$29 = require_react(); 309 init_button(); 310 init_icon(); 311 init_tooltip(); 312 init_routes(); 313 init_utils(); 314 import_jsx_runtime$31 = require_jsx_runtime(); 315 t$23 = (key) => window.i18n.t(key); 316 EmailColumn = (0, import_react$29.memo)(function EmailColumn(t0) { 317 const $ = (0, import_compiler_runtime$13.c)(32); 318 const { lead, editable, onFindEmailRequested, onFindEmailFailed, onLeadClick } = t0; 319 if (lead.emailFinderStatus === "pending") { 320 let t1; 321 if ($[0] === Symbol.for("react.memo_cache_sentinel")) { 322 t1 = /* @__PURE__ */ (0, import_jsx_runtime$31.jsxs)("span", { 323 className: "h-data-table-cell__loading", 324 children: [/* @__PURE__ */ (0, import_jsx_runtime$31.jsx)(Icon, { loading: true }), t$23("js.leads.page.email_column.searching")] 325 }); 326 $[0] = t1; 327 } else t1 = $[0]; 328 return t1; 329 } 330 if (lead.emailFinderStatus === "duplicate" && lead.originalLeadId) { 331 let t1; 332 if ($[1] === Symbol.for("react.memo_cache_sentinel")) { 333 t1 = t$23("js.leads.page.email_column.duplicate_tooltip"); 334 $[1] = t1; 335 } else t1 = $[1]; 336 const duplicateTooltip = t1; 337 const t2 = `${lead.originalLeadEmail} â ${duplicateTooltip}`; 338 let t3; 339 if ($[2] === Symbol.for("react.memo_cache_sentinel")) { 340 t3 = /* @__PURE__ */ (0, import_jsx_runtime$31.jsx)("span", { 341 className: "h-data-table-cell__status-dot h-data-table-cell__status-dot--warning mr-2", 342 "aria-hidden": "true" 343 }); 344 $[2] = t3; 345 } else t3 = $[2]; 346 let t4; 347 if ($[3] === Symbol.for("react.memo_cache_sentinel")) { 348 t4 = /* @__PURE__ */ (0, import_jsx_runtime$31.jsx)("span", { 349 className: "sr-only", 350 children: duplicateTooltip 351 }); 352 $[3] = t4; 353 } else t4 = $[3]; 354 let t5; 355 if ($[4] !== lead.originalLeadEmail || $[5] !== t2) { 356 t5 = /* @__PURE__ */ (0, import_jsx_runtime$31.jsx)(TooltipTrigger, { 357 asChild: true, 358 children: /* @__PURE__ */ (0, import_jsx_runtime$31.jsxs)("span", { 359 tabIndex: 0, 360 "aria-label": t2, 361 children: [ 362 t3, 363 lead.originalLeadEmail, 364 t4 365 ] 366 }) 367 }); 368 $[4] = lead.originalLeadEmail; 369 $[5] = t2; 370 $[6] = t5; 371 } else t5 = $[6]; 372 let t6; 373 if ($[7] === Symbol.for("react.memo_cache_sentinel")) { 374 t6 = /* @__PURE__ */ (0, import_jsx_runtime$31.jsx)(TooltipContent, { children: duplicateTooltip }); 375 $[7] = t6; 376 } else t6 = $[7]; 377 let t7; 378 if ($[8] !== t5) { 379 t7 = /* @__PURE__ */ (0, import_jsx_runtime$31.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime$31.jsxs)(Tooltip, { children: [t5, t6] }) }); 380 $[8] = t5; 381 $[9] = t7; 382 } else t7 = $[9]; 383 let t8; 384 if ($[10] !== lead.originalLeadId || $[11] !== onLeadClick) { 385 t8 = () => onLeadClick?.(lead.originalLeadId); 386 $[10] = lead.originalLeadId; 387 $[11] = onLeadClick; 388 $[12] = t8; 389 } else t8 = $[12]; 390 let t10; 391 let t9; 392 if ($[13] === Symbol.for("react.memo_cache_sentinel")) { 393 t9 = /* @__PURE__ */ (0, import_jsx_runtime$31.jsx)(Icon, { 394 icon: "eye", 395 size: "xs" 396 }); 397 t10 = t$23("js.leads.page.email_column.see_original_lead"); 398 $[13] = t10; 399 $[14] = t9; 400 } else { 401 t10 = $[13]; 402 t9 = $[14]; 403 } 404 let t11; 405 if ($[15] !== t8) { 406 t11 = /* @__PURE__ */ (0, import_jsx_runtime$31.jsx)("div", { 407 className: "h-data-table-cell__actions", 408 children: /* @__PURE__ */ (0, import_jsx_runtime$31.jsxs)(Button, { 409 type: "button", 410 size: "xs", 411 onClick: t8, 412 children: [t9, t10] 413 }) 414 }); 415 $[15] = t8; 416 $[16] = t11; 417 } else t11 = $[16]; 418 let t12; 419 if ($[17] !== t11 || $[18] !== t7) { 420 t12 = /* @__PURE__ */ (0, import_jsx_runtime$31.jsxs)(import_jsx_runtime$31.Fragment, { children: [t7, t11] }); 421 $[17] = t11; 422 $[18] = t7; 423 $[19] = t12; 424 } else t12 = $[19]; 425 return t12; 426 }
427 const isRetryable = lead.emailFinderStatus === "not_found" || lead.emailFinderStatus === "error"; 428 let t1; 429 if ($[20] !== isRetryable) { 430 t1 = isRetryable ? t$23("js.leads.page.email_column.not_found") : t$23("js.leads.page.no_email"); 431 $[20] = isRetryable; 432 $[21] = t1; 433 } else t1 = $[21]; 434 let t2; 435 if ($[22] !== t1) { 436 t2 = /* @__PURE__ */ (0, import_jsx_runtime$31.jsx)("div", { 437 className: "text-hint", 438 children: t1 439 }); 440 $[22] = t1; 441 $[23] = t2; 442 } else t2 = $[23]; 443 let t3; 444 if ($[24] !== editable || $[25] !== lead.id || $[26] !== onFindEmailFailed || $[27] !== onFindEmailRequested) { 445 t3 = editable && /* @__PURE__ */ (0, import_jsx_runtime$31.jsx)("div", { 446 className: "h-data-table-cell__actions is-visible", 447 children: /* @__PURE__ */ (0, import_jsx_runtime$31.jsx)(Button, { 448 type: "button", 449 iconOnly: true, 450 size: "xs", 451 "aria-label": t$23("js.leads.page.email_column.find_email"), 452 onClick: () => handleFindEmail(lead.id, onFindEmailRequested, onFindEmailFailed), 453 children: /* @__PURE__ */ (0, import_jsx_runtime$31.jsx)(Icon, { 454 icon: "magnifying-glass", 455 size: "xs" 456 }) 457 }) 458 }); 459 $[24] = editable; 460 $[25] = lead.id; 461 $[26] = onFindEmailFailed; 462 $[27] = onFindEmailRequested; 463 $[28] = t3; 464 } else t3 = $[28]; 465 let t4; 466 if ($[29] !== t2 || $[30] !== t3) { 467 t4 = /* @__PURE__ */ (0, import_jsx_runtime$31.jsxs)(import_jsx_runtime$31.Fragment, { children: [t2, t3] }); 468 $[29] = t2; 469 $[30] = t3; 470 $[31] = t4; 471 } else t4 = $[31]; 472 return t4; 473 }); 474 })))(); 475} 476//#endregion 477//#region app/frontend/pages/Leads/columns/ConfidenceColumn.tsx 478var import_compiler_runtime$12, import_react$28, import_jsx_runtime$30, ConfidenceColumn; 479function init_ConfidenceColumn() { 480 return (init_ConfidenceColumn = __esmMin((() => { 481 import_compiler_runtime$12 = require_compiler_runtime(); 482 import_react$28 = require_react(); 483 import_jsx_runtime$30 = require_jsx_runtime(); 484 ConfidenceColumn = (0, import_react$28.memo)(function ConfidenceColumn(t0) { 485 const $ = (0, import_compiler_runtime$12.c)(2); 486 const { score } = t0; 487 if (score === null || score === void 0) return null; 488 let t1; 489 if ($[0] !== score) { 490 t1 = /* @__PURE__ */ (0, import_jsx_runtime$30.jsxs)("span", { children: [score, "%"] }); 491 $[0] = score; 492 $[1] = t1; 493 } else t1 = $[1]; 494 return t1; 495 }); 496 })))(); 497} 498//#endregion 499//#region app/frontend/pages/Leads/columns/EditableCell.tsx 500var import_react$27, import_jsx_runtime$29, EditableCell; 501function init_EditableCell() { 502 return (init_EditableCell = __esmMin((() => { 503 import_react$27 = require_react(); 504 init_dist(); 505 init_routes(); 506 import_jsx_runtime$29 = require_jsx_runtime(); 507 EditableCell = (0, import_react$27.memo)(function EditableCell({ leadId, columnName, value }) { 508 const { props } = usePage(); 509 const tdRef = (0, import_react$27.useRef)(null); 510 const cellRef = (0, import_react$27.useRef)(null); 511 const originalValue = (0, import_react$27.useRef)(value); 512 const isEditing = (0, import_react$27.useRef)(false); 513 const abortRef = (0, import_react$27.useRef)(null); 514 const successTimer = (0, import_react$27.useRef)(null); 515 (0, import_react$27.useEffect)(() => { 516 originalValue.current = value; 517 if (!isEditing.current && cellRef.current) { 518 clearIcons(); 519 cellRef.current.textContent = value; 520 } 521 }, [value]); 522 (0, import_react$27.useEffect)(() => { 523 const td = tdRef.current; 524 if (!td) return; 525 if (cellRef.current && td.contains(cellRef.current)) return; 526 const div = document.createElement("div"); 527 div.className = "h-data-table-cell"; 528 div.textContent = originalValue.current; 529 td.appendChild(div); 530 cellRef.current = div; 531 div.addEventListener("dblclick", startEditing); 532 div.addEventListener("keydown", handleKeyDown); 533 div.addEventListener("blur", handleBlur); 534 div.addEventListener("paste", handlePaste); 535 return () => { 536 abortRef.current?.abort(); 537 if (successTimer.current) clearTimeout(successTimer.current); 538 div.removeEventListener("dblclick", startEditing); 539 div.removeEventListener("keydown", handleKeyDown); 540 div.removeEventListener("blur", handleBlur); 541 div.removeEventListener("paste", handlePaste); 542 div.remove(); 543 cellRef.current = null; 544 }; 545 }, []); 546 function clearIcons() { 547 cellRef.current?.querySelector(".h-data-table-cell__info-icon")?.remove(); 548 if (successTimer.current) { 549 clearTimeout(successTimer.current); 550 successTimer.current = null; 551 } 552 } 553 function startEditing() { 554 if (isEditing.current) return; 555 const el = cellRef.current; 556 if (!el) return; 557 isEditing.current = true; 558 clearIcons(); 559 el.textContent = originalValue.current; 560 el.classList.add("h-data-table-cell--editing"); 561 el.setAttribute("contenteditable", "true"); 562 el.focus(); 563 const range = document.createRange(); 564 range.selectNodeContents(el); 565 range.collapse(false); 566 window.getSelection()?.removeAllRanges(); 567 window.getSelection()?.addRange(range); 568 } 569 function stopEditing() { 570 const el_0 = cellRef.current; 571 if (!el_0) return; 572 isEditing.current = false;
573 el_0.classList.remove("h-data-table-cell--editing"); 574 el_0.removeAttribute("contenteditable"); 575 el_0.blur(); 576 } 577 function cancel() { 578 const el_1 = cellRef.current; 579 if (!el_1) return; 580 el_1.textContent = originalValue.current; 581 stopEditing(); 582 } 583 async function save() { 584 const el_2 = cellRef.current; 585 if (!el_2) return; 586 const newValue = el_2.innerText.trim(); 587 stopEditing(); 588 if (newValue === originalValue.current) { 589 el_2.textContent = originalValue.current; 590 return; 591 } 592 if (newValue.length === 0) { 593 el_2.textContent = originalValue.current; 594 return; 595 } 596 originalValue.current = newValue; 597 el_2.textContent = newValue; 598 abortRef.current?.abort(); 599 const controller = new AbortController(); 600 abortRef.current = controller; 601 try { 602 const body = columnName.startsWith("custom_attribute-") ? { lead: { custom_attributes: { [columnName.split("-").slice(1).join("-")]: newValue } } } : { lead: { [columnName]: newValue } }; 603 const response = await fetch(lead_path(leadId), { 604 method: "PATCH", 605 headers: { 606 "Content-Type": "application/json", 607 Accept: "application/json", 608 "X-CSRF-Token": props.csrf.token 609 }, 610 body: JSON.stringify(body), 611 signal: controller.signal 612 }); 613 if (!response.ok) throw new Error(`HTTP ${response.status}`); 614 showSuccess(); 615 } catch (e) { 616 if (e.name === "AbortError") return; 617 originalValue.current = value; 618 el_2.textContent = value; 619 } 620 } 621 function showSuccess() { 622 const el_3 = cellRef.current; 623 if (!el_3) return; 624 clearIcons(); 625 const icon = document.createElement("span"); 626 icon.className = "h-data-table-cell__info-icon far fa-check text-success"; 627 icon.setAttribute("aria-label", "Changes successfully saved!"); 628 el_3.insertBefore(icon, el_3.firstChild); 629 successTimer.current = setTimeout(() => { 630 icon.classList.add("is-hidden"); 631 setTimeout(() => icon.remove(), 300); 632 }, 3e3); 633 } 634 function handleKeyDown(e_0) { 635 if (!isEditing.current) return; 636 const ke = e_0; 637 if (ke.key === "Enter") { 638 ke.preventDefault(); 639 save(); 640 } else if (ke.key === "Escape") { 641 ke.preventDefault(); 642 cancel(); 643 } 644 } 645 function handleBlur() { 646 if (!isEditing.current) return; 647 save(); 648 } 649 function handlePaste(e_1) { 650 if (!isEditing.current) return; 651 e_1.preventDefault(); 652 const ce = e_1; 653 document.execCommand("insertText", false, ce.clipboardData?.getData("text/plain") ?? ""); 654 } 655 return /* @__PURE__ */ (0, import_jsx_runtime$29.jsx)("td", { ref: tdRef }); 656 }); 657 })))(); 658} 659//#endregion 660//#region app/frontend/pages/Leads/columns/DateCell.tsx 661var import_compiler_runtime$11, import_react$26, import_jsx_runtime$28, dateFormatter, DateCell; 662function init_DateCell() { 663 return (init_DateCell = __esmMin((() => { 664 import_compiler_runtime$11 = require_compiler_runtime(); 665 import_react$26 = require_react(); 666 import_jsx_runtime$28 = require_jsx_runtime(); 667 dateFormatter = new Intl.DateTimeFormat(void 0, { 668 year: "numeric", 669 month: "short", 670 day: "numeric" 671 }); 672 DateCell = (0, import_react$26.memo)(function DateCell(t0) { 673 const $ = (0, import_compiler_runtime$11.c)(5); 674 const { value } = t0; 675 if (!value) return null; 676 let t1; 677 if ($[0] !== value) { 678 t1 = dateFormatter.format(new Date(value)); 679 $[0] = value; 680 $[1] = t1; 681 } else t1 = $[1]; 682 let t2; 683 if ($[2] !== t1 || $[3] !== value) { 684 t2 = /* @__PURE__ */ (0, import_jsx_runtime$28.jsx)("time", { 685 dateTime: value, 686 children: t1 687 }); 688 $[2] = t1; 689 $[3] = value; 690 $[4] = t2; 691 } else t2 = $[4]; 692 return t2; 693 }); 694 })))(); 695} 696//#endregion 697//#region app/frontend/pages/Leads/columns/LinkCell.tsx 698var import_compiler_runtime$10, import_react$25, import_jsx_runtime$27, LinkCell; 699function init_LinkCell() { 700 return (init_LinkCell = __esmMin((() => { 701 import_compiler_runtime$10 = require_compiler_runtime(); 702 import_react$25 = require_react(); 703 import_jsx_runtime$27 = require_jsx_runtime(); 704 LinkCell = (0, import_react$25.memo)(function LinkCell(t0) { 705 const $ = (0, import_compiler_runtime$10.c)(3); 706 const { url, label } = t0; 707 if (!url) return null; 708 const t1 = label || url; 709 let t2; 710 if ($[0] !== t1 || $[1] !== url) { 711 t2 = /* @__PURE__ */ (0, import_jsx_runtime$27.jsx)("a", { 712 href: url, 713 target: "_blank", 714 rel: "noopener noreferrer", 715 className: "text-truncate d-block", 716 children: t1 717 }); 718 $[0] = t1; 719 $[1] = url; 720 $[2] = t2; 721 } else t2 = $[2]; 722 return t2; 723 }); 724 })))(); 725} 726//#endregion 727//#region app/frontend/pages/Leads/columns/ActionsColumn.tsx 728var import_compiler_runtime$9, import_react$24, import_jsx_runtime$26, t$22, ActionsColumn; 729function init_ActionsColumn() { 730 return (init_ActionsColumn = __esmMin((() => { 731 import_compiler_runtime$9 = require_compiler_runtime(); 732 import_react$24 = require_react(); 733 init_button(); 734 init_icon(); 735 init_dropdown_menu(); 736 init_routes(); 737 init_utils(); 738 import_jsx_runtime$26 = require_jsx_runtime(); 739 t$22 = (key) => window.i18n.t(key); 740 ActionsColumn = (0, import_react$24.memo)(function ActionsColumn(t0) { 741 const $ = (0, import_compiler_runtime$9.c)(34); 742 const { lead, onView, onEdit, onDelete, onVerifyRequested } = t0; 743 let t1; 744 if ($[0] !== lead.id || $[1] !== onVerifyRequested) { 745 t1 = async function handleVerify() { 746 onVerifyRequested?.(lead.id); 747 const formData = new FormData(); 748 formData.append("lead_ids[]", String(lead.id)); 749 formData.append("authenticity_token", getCsrfToken()); 750 await fetch(leads_verify_path(), { 751 method: "POST", 752 headers: { Accept: "text/html" }, 753 body: formData 754 }); 755 }; 756 $[0] = lead.id; 757 $[1] = onVerifyRequested; 758 $[2] = t1; 759 } else t1 = $[2]; 760 const handleVerify = t1; 761 let t2; 762 if ($[3] === Symbol.for("react.memo_cache_sentinel")) { 763 t2 = t$22("js.leads.page.view_lead"); 764 $[3] = t2; 765 } else t2 = $[3]; 766 let t3; 767 if ($[4] !== lead.id || $[5] !== onView) { 768 t3 = () => onView(lead.id); 769 $[4] = lead.id; 770 $[5] = onView; 771 $[6] = t3; 772 } else t3 = $[6]; 773 let t4; 774 if ($[7] === Symbol.for("react.memo_cache_sentinel")) { 775 t4 = /* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(Icon, { 776 icon: "eye", 777 size: "sm" 778 }); 779 $[7] = t4; 780 } else t4 = $[7]; 781 let t5; 782 if ($[8] !== t3) { 783 t5 = /* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(Button, { 784 type: "button", 785 iconOnly: true, 786 size: "xs", 787 "aria-label": t2, 788 onClick: t3, 789 children: t4 790 }); 791 $[8] = t3; 792 $[9] = t5; 793 } else t5 = $[9]; 794 let t6; 795 if ($[10] !== lead.editable || $[11] !== lead.id || $[12] !== onEdit) {
796 t6 = lead.editable && /* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(Button, { 797 type: "button", 798 iconOnly: true, 799 size: "xs", 800 "aria-label": t$22("js.leads.page.edit_lead"), 801 onClick: () => onEdit(lead.id), 802 children: /* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(Icon, { 803 icon: "pen", 804 size: "sm" 805 }) 806 }); 807 $[10] = lead.editable; 808 $[11] = lead.id; 809 $[12] = onEdit; 810 $[13] = t6; 811 } else t6 = $[13]; 812 let t7; 813 if ($[14] === Symbol.for("react.memo_cache_sentinel")) { 814 t7 = /* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(DropdownMenuTrigger, { 815 asChild: true, 816 children: /* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(Button, { 817 type: "button", 818 iconOnly: true, 819 size: "xs", 820 "aria-label": t$22("js.leads.page.more_actions"), 821 children: /* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(Icon, { 822 icon: "ellipsis-vertical", 823 size: "sm" 824 }) 825 }) 826 }); 827 $[14] = t7; 828 } else t7 = $[14]; 829 let t8; 830 let t9; 831 if ($[15] === Symbol.for("react.memo_cache_sentinel")) { 832 t8 = /* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(Icon, { icon: "shield-check" }); 833 t9 = t$22("js.leads.page.verify"); 834 $[15] = t8; 835 $[16] = t9; 836 } else { 837 t8 = $[15]; 838 t9 = $[16]; 839 } 840 let t10; 841 if ($[17] !== handleVerify) { 842 t10 = /* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(DropdownMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime$26.jsxs)("button", { 843 type: "button", 844 className: "dropdown-menu__action", 845 onClick: handleVerify, 846 children: [t8, t9] 847 }) }); 848 $[17] = handleVerify; 849 $[18] = t10; 850 } else t10 = $[18]; 851 let t11; 852 if ($[19] !== lead.email || $[20] !== lead.id) { 853 t11 = lead.email && /* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(DropdownMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime$26.jsxs)("button", { 854 type: "button", 855 className: "dropdown-menu__action", 856 "data-controller": "compose-button", 857 "data-action": "click->compose-button#open", 858 "data-compose-button-lead-id-value": lead.id, 859 "data-compose-button-recipient-value": lead.email, 860 children: [/* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(Icon, { icon: "envelope" }), t$22("js.leads.page.send_a_message")] 861 }) }); 862 $[19] = lead.email; 863 $[20] = lead.id; 864 $[21] = t11; 865 } else t11 = $[21]; 866 let t12; 867 if ($[22] !== lead.editable || $[23] !== lead.id || $[24] !== onDelete) { 868 t12 = lead.editable && /* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(DropdownMenuItem, { children: /* @__PURE__ */ (0, import_jsx_runtime$26.jsxs)("button", { 869 type: "button", 870 className: "dropdown-menu__action dropdown-menu__action--danger", 871 onClick: () => onDelete(lead.id), 872 children: [/* @__PURE__ */ (0, import_jsx_runtime$26.jsx)(Icon, { icon: "trash-alt" }), t$22("js.leads.page.delete")] 873 }) }); 874 $[22] = lead.editable; 875 $[23] = lead.id; 876 $[24] = onDelete; 877 $[25] = t12; 878 } else t12 = $[25]; 879 let t13; 880 if ($[26] !== t10 || $[27] !== t11 || $[28] !== t12) { 881 t13 = /* @__PURE__ */ (0, import_jsx_runtime$26.jsxs)(DropdownMenu, { children: [t7, /* @__PURE__ */ (0, import_jsx_runtime$26.jsxs)(DropdownMenuContent, { 882 align: "end", 883 children: [ 884 t10, 885 t11, 886 t12 887 ] 888 })] }); 889 $[26] = t10; 890 $[27] = t11; 891 $[28] = t12; 892 $[29] = t13; 893 } else t13 = $[29]; 894 let t14; 895 if ($[30] !== t13 || $[31] !== t5 || $[32] !== t6) { 896 t14 = /* @__PURE__ */ (0, import_jsx_runtime$26.jsxs)("div", { 897 className: "d-flex align-items-center gap-1", 898 children: [ 899 t5, 900 t6, 901 t13 902 ] 903 }); 904 $[30] = t13; 905 $[31] = t5; 906 $[32] = t6; 907 $[33] = t14; 908 } else t14 = $[33]; 909 return t14; 910 }); 911 })))(); 912} 913//#endregion 914//#region app/frontend/pages/Leads/columns/CountCell.tsx 915var import_compiler_runtime$8, import_react$23, import_jsx_runtime$25, CountCell; 916function init_CountCell() { 917 return (init_CountCell = __esmMin((() => { 918 import_compiler_runtime$8 = require_compiler_runtime(); 919 import_react$23 = require_react(); 920 import_jsx_runtime$25 = require_jsx_runtime(); 921 CountCell = (0, import_react$23.memo)(function CountCell(t0) { 922 const $ = (0, import_compiler_runtime$8.c)(10); 923 const { label, tooltip, href, onClick } = t0; 924 if (href) { 925 let t1; 926 if ($[0] !== href || $[1] !== label || $[2] !== tooltip) { 927 t1 = /* @__PURE__ */ (0, import_jsx_runtime$25.jsx)("a", { 928 href, 929 className: "h-data-table-cell__link", 930 title: tooltip, 931 children: label 932 }); 933 $[0] = href; 934 $[1] = label; 935 $[2] = tooltip; 936 $[3] = t1; 937 } else t1 = $[3]; 938 return t1; 939 } 940 if (onClick) { 941 let t1; 942 if ($[4] !== label || $[5] !== onClick || $[6] !== tooltip) { 943 t1 = /* @__PURE__ */ (0, import_jsx_runtime$25.jsx)("button", { 944 type: "button", 945 className: "h-data-table-cell__link", 946 title: tooltip, 947 onClick, 948 children: label 949 }); 950 $[4] = label; 951 $[5] = onClick; 952 $[6] = tooltip; 953 $[7] = t1; 954 } else t1 = $[7]; 955 return t1; 956 } 957 let t1; 958 if ($[8] !== label) { 959 t1 = /* @__PURE__ */ (0, import_jsx_runtime$25.jsx)("span", { 960 className: "text-body-secondary", 961 children: label 962 }); 963 $[8] = label; 964 $[9] = t1; 965 } else t1 = $[9]; 966 return t1; 967 }); 968 })))(); 969} 970//#endregion 971//#region app/frontend/pages/Leads/columns/SequenceColumn.tsx 972function _temp$4(c) { 973 return c.name; 974} 975var import_compiler_runtime$7, import_react$22, import_jsx_runtime$24, t$21, SequenceColumn; 976function init_SequenceColumn() { 977 return (init_SequenceColumn = __esmMin((() => { 978 import_compiler_runtime$7 = require_compiler_runtime(); 979 import_react$22 = require_react(); 980 init_routes(); 981 init_CountCell(); 982 import_jsx_runtime$24 = require_jsx_runtime(); 983 t$21 = (key, opts) => window.i18n.t(key, opts); 984 SequenceColumn = (0, import_react$22.memo)(function SequenceColumn(t0) { 985 const $ = (0, import_compiler_runtime$7.c)(19); 986 const { lead, onLeadClick } = t0; 987 const campaigns = lead.campaigns; 988 const count = campaigns.length; 989 let t1; 990 if ($[0] !== count) { 991 t1 = t$21("js.leads.page.sequences_count", { count }); 992 $[0] = count; 993 $[1] = t1; 994 } else t1 = $[1]; 995 const label = t1; 996 if (count === 0) { 997 let t2; 998 if ($[2] !== label) { 999 t2 = /* @__PURE__ */ (0, import_jsx_runtime$24.jsx)(CountCell, { label }); 1000 $[2] = label; 1001 $[3] = t2; 1002 } else t2 = $[3]; 1003 return t2; 1004 } 1005 let t2; 1006 if ($[4] !== campaigns) { 1007 t2 = campaigns.map(_temp$4).join(", "); 1008 $[4] = campaigns; 1009 $[5] = t2; 1010 } else t2 = $[5]; 1011 const tooltip = t2; 1012 if (count === 1) { 1013 let t3; 1014 if ($[6] !== campaigns[0].id) { 1015 t3 = sequence_path(campaigns[0].id); 1016 $[6] = campaigns[0].id; 1017 $[7] = t3; 1018 } else t3 = $[7]; 1019 let t4; 1020 if ($[8] !== label || $[9] !== t3 || $[10] !== tooltip) { 1021 t4 = /* @__PURE__ */ (0, import_jsx_runtime$24.jsx)(CountCell, { 1022 label, 1023 tooltip, 1024 href: t3 1025 }); 1026 $[8] = label; 1027 $[9] = t3; 1028 $[10] = tooltip; 1029 $[11] = t4; 1030 } else t4 = $[11]; 1031 return t4; 1032 } 1033 let t3; 1034 if ($[12] !== lead.id || $[13] !== onLeadClick) { 1035 t3 = () => onLeadClick(lead.id, "sequences"); 1036 $[12] = lead.id; 1037 $[13] = onLeadClick; 1038 $[14] = t3; 1039 } else t3 = $[14]; 1040 let t4; 1041 if ($[15] !== label || $[16] !== t3 || $[17] !== tooltip) { 1042 t4 = /* @__PURE__ */ (0, import_jsx_runtime$24.jsx)(CountCell, { 1043 label, 1044 tooltip, 1045 onClick: t3 1046 }); 1047 $[15] = label; 1048 $[16] = t3; 1049 $[17] = tooltip; 1050 $[18] = t4; 1051 } else t4 = $[18]; 1052 return t4; 1053 }); 1054 })))(); 1055} 1056//#endregion 1057//#region app/frontend/pages/Leads/LeadsTable.tsx 1058function columnIsSticky(col) { 1059 return Boolean(col.sticky); 1060} 1061function renderCell(lead, col, ctx) { 1062 const cellEditable = (name) => lead.editable && ctx.editableColumnNames.includes(name); 1063 switch (col.name) { 1064 case "full_name": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(NameColumn, { 1065 lead, 1066 onLeadClick: ctx.onLeadClick 1067 }); 1068 case "email": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(EmailColumn, { 1069 lead, 1070 editable: cellEditable("email"), 1071 onFindEmailRequested: ctx.onFindEmailRequested, 1072 onFindEmailFailed: ctx.onFindEmailFailed, 1073 onLeadClick: ctx.onLeadClick 1074 }); 1075 case "verification_status": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(VerificationColumn, { 1076 status: lead.verificationStatus, 1077 verificationDate: lead.verificationDate, 1078 leadId: lead.id, 1079 email: lead.email, 1080 onVerifyRequested: ctx.onVerifyRequested 1081 }); 1082 case "confidence_score": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(ConfidenceColumn, { score: lead.confidenceScore }); 1083 case "sending_status": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(SendingStatusColumn, { status: lead.sendingStatus }); 1084 case "tags": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(TagsColumn, { 1085 recordId: lead.id, 1086 tags: lead.tags, 1087 availableTags: ctx.availableTags, 1088 taggingsPath: lead_taggings_path, 1089 taggingPath: lead_tagging_path, 1090 tagPath: lead_tag_path, 1091 onTagsChange: ctx.onTagsChange, 1092 onTagUpdate: ctx.onTagUpdate, 1093 onTagDelete: ctx.onTagDelete, 1094 readOnly: !lead.editable 1095 }); 1096 case "company": 1097 if (lead.company && lead.domainId != null && ctx.discoverEnabled) { 1098 const domainId = lead.domainId; 1099 return /* @__PURE__ */ (0, import_jsx_runtime$23.jsxs)("button", { 1100 type: "button", 1101 className: "lead-tag lead-tag--people", 1102 onClick: () => ctx.onCompanyClick(domainId, lead.company), 1103 children: [/* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(CompanyLogo, { 1104 domain: lead.website, 1105 size: "xs", 1106 alt: "" 1107 }
1107), /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("span", { 1108 className: "lead-tag__name", 1109 children: lead.company 1110 })] 1111 }); 1112 } 1113 return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("span", { children: lead.company }); 1114 case "website": { 1115 if (!lead.website) return null; 1116 const href = /^https?:\/\//i.test(lead.website) ? lead.website : `https://${lead.website}`; 1117 return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("a", { 1118 href, 1119 target: "_blank", 1120 rel: "noopener noreferrer", 1121 className: "h-data-table-cell__link", 1122 children: lead.website 1123 }); 1124 } 1125 case "linkedin_url": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(LinkCell, { 1126 url: lead.linkedinUrl, 1127 label: "LinkedIn" 1128 }); 1129 case "twitter": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(LinkCell, { 1130 url: lead.twitter ? `https://twitter.com/${lead.twitter}` : null, 1131 label: lead.twitter 1132 }); 1133 case "verification_date": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DateCell, { value: lead.verificationDate }); 1134 case "updated_at": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DateCell, { value: lead.updatedAt }); 1135 case "created_at": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DateCell, { value: lead.createdAt }); 1136 case "last_activity_at": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DateCell, { value: lead.lastActivityAt }); 1137 case "last_contacted_at": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DateCell, { value: lead.lastContactedAt }); 1138 case "last_exported_at": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DateCell, { value: lead.lastExportedAt }); 1139 case "user_id": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("span", { children: lead.userName }); 1140 case "lead_location": 1141 if (!lead.leadLocation) return null; 1142 return /* @__PURE__ */ (0, import_jsx_runtime$23.jsxs)("span", { children: [lead.leadCountryCode ? `${countryCodeToFlag(lead.leadCountryCode)} ` : "", lead.leadLocation] }); 1143 case "campaign_ids": return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(SequenceColumn, { 1144 lead, 1145 onLeadClick: ctx.onLeadClick 1146 }); 1147 default: { 1148 if (col.name.startsWith("custom_attribute-")) { 1149 const slug = col.name.split("-").slice(1).join("-"); 1150 const value = leadCustomAttrValue(lead.customAttributes, slug); 1151 if (cellEditable(col.name)) return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(EditableCell, { 1152 leadId: lead.id, 1153 columnName: col.name, 1154 value 1155 }); 1156 return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("span", { children: value }); 1157 } 1158 const accessor = COLUMN_ACCESSORS[col.name]; 1159 const value = accessor ? accessor(lead) : null; 1160 if (cellEditable(col.name)) return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(EditableCell, { 1161 leadId: lead.id, 1162 columnName: col.name, 1163 value: value ?? "" 1164 }); 1165 return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("span", { children: value }); 1166 } 1167 } 1168} 1169function LeadsTable({ leads, columns: visibleColumns, visibleColumnNames, editableColumnNames, sort, direction, totalCount, onSort, isSelected, allSelected, onToggleRow, onSelectAllLeads, onSelectPage, onSelectCount, onClearSelection, onLeadClick, onCompanyClick, discoverEnabled, enrichingLeadIds, onEditLead, onColumnsUpdate, availableTags, onTagsChange, onTagUpdate, onTagDelete, onDeleteLead, onVerifyRequested, onFindEmailRequested, onFindEmailFailed, filters, formOptions, companyDropdownEnabled, notContainsEnabled = false, leadsListId, onApplyFilter, onApplyBatchFilter, bulkActionsBar, columnResizeDisabled = false, footer }) { 1170 const checkboxChecked = leads.length > 0 && leads.every((l) => isSelected(l.id)) || allSelected; 1171 const singlePage = totalCount <= leads.length; 1172 function handleHideColumn(columnName) { 1173 onColumnsUpdate(visibleColumnNames.filter((name) => name !== columnName)); 1174 } 1175 function handleMoveColumn(columnName_0, dir) { 1176 const order = [...visibleColumnNames]; 1177 const index = order.indexOf(columnName_0); 1178 if (index === -1) return; 1179 const swapIndex = dir === "left" ? index - 1 : index + 1; 1180 if (swapIndex < 0 || swapIndex >= order.length) return; 1181 [order[index], order[swapIndex]] = [order[swapIndex], order[index]]; 1182 onColumnsUpdate(order); 1183 } 1184 const firstMoveableIndex = visibleColumnNames.findIndex((name_0) => !NON_HIDEABLE_COLUMNS$1.includes(name_0)); 1185 const lastMoveableIndex = visibleColumnNames.length - 1; 1186 const dragColumnRef = (0, import_react$21.useRef)(null); 1187 const [dragColumnOrder, setDragColumnOrder] = (0, import_react$21.useState)(null); 1188 const displayColumns = (0, import_react$21.useMemo)(() => { 1189 if (!dragColumnOrder) return visibleColumns; 1190 return dragColumnOrder.map((name_1) => visibleColumns.find((col) => col.name === name_1)).filter((col_0) => col_0 !== void 0); 1191 }, [dragColumnOrder, visibleColumns]); 1192 function handleDragStart(e, columnName_1) { 1193 dragColumnRef.current = columnName_1; 1194 e.dataTransfer.effectAllowed = "move"; 1195 e.dataTransfer.setData("text/plain", columnName_1); 1196 e.currentTarget.classList.add("dragging"); 1197 setDragColumnOrder(visibleColumns.map((col_1) => col_1.name)); 1198 } 1199 function handleDragOver(e_0, targetColumnName) { 1200 e_0.preventDefault(); 1201 e_0.dataTransfer.dropEffect = "move"; 1202 const draggedName = dragColumnRef.current; 1203 if (!draggedName || draggedName === targetColumnName) return; 1204 if (NON_HIDEABLE_COLUMNS$1.includes(targetColumnName)) return; 1205 setDragColumnOrder((prev) => { 1206 if (!prev) return prev; 1207 const order_0 = [...prev]; 1208 const fromIndex = order_0.indexOf(draggedName); 1209 const toIndex = order_0.indexOf(targetColumnName); 1210 if (fromIndex === -1 || toIndex === -1) return prev; 1211 order_0.splice(fromIndex, 1); 1212 order_0.splice(toIndex, 0, draggedName); 1213 return order_0; 1214 }); 1215 } 1216 function handleDragEnd(e_1) { 1217 e_1.currentTarget.classList.remove("dragging"); 1218 if (dragColumnOrder) onColumnsUpdate(dragColumnOrder); 1219 setDragColumnOrder(null); 1220 dragColumnRef.current = null; 1221 } 1222 const { columnWidths, resizeHandleProps, resizableThProps } = useColumnResize(); 1223 return /* @__PURE__ */ (0, import_jsx_runtime$23.jsxs)(DataTable, { 1224 className: "h-data-table--react", 1225 bulkActionsBar, 1226 footer, 1227 tableClassName: Object.keys(columnWidths).length > 0 ? "is-resizing" : void 0, 1228 children: [/* @__PURE__ */ (0, import_jsx_runtime$23.jsxs)(DataTableHeader, { children: [
1229 /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("th", { 1230 className: "h-data-table__checkbox", 1231 children: /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("div", { 1232 className: "h-data-table-cell h-data-table-cell--checkbox", 1233 children: singlePage ? /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(Checkbox, { 1234 checked: checkboxChecked, 1235 "aria-label": t$20("js.leads.page.select_all"), 1236 onChange: () => checkboxChecked ? onClearSelection() : onSelectAllLeads() 1237 }) : /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(SelectCountMenu, { 1238 className: "h-table__check-all", 1239 onSelectCount, 1240 trigger: /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(Checkbox, { 1241 checked: checkboxChecked, 1242 readOnly: true, 1243 "aria-label": t$20("js.leads.page.select_all") 1244 }), 1245 renderItems: ({ openCustom }) => /* @__PURE__ */ (0, import_jsx_runtime$23.jsxs)(import_jsx_runtime$23.Fragment, { children: [ 1246 /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DropdownMenuItem, { 1247 closeOnClick: true, 1248 children: /* @__PURE__ */ (0, import_jsx_runtime$23.jsxs)("button", { 1249 type: "button", 1250 className: "dropdown-menu__action", 1251 onClick: onSelectAllLeads, 1252 children: [t$20("js.leads.page.select_all"), /* @__PURE__ */ (0, import_jsx_runtime$23.jsxs)("small", { 1253 className: "grey ml-auto", 1254 children: [ 1255 "(", 1256 totalCount.toLocaleString(), 1257 ")" 1258 ] 1259 })] 1260 }) 1261 }), 1262 /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DropdownMenuItem, { 1263 closeOnClick: true, 1264 children: /* @__PURE__ */ (0, import_jsx_runtime$23.jsxs)("button", { 1265 type: "button", 1266 className: "dropdown-menu__action", 1267 onClick: onSelectPage, 1268 children: [t$20("js.leads.page.select_this_page"), /* @__PURE__ */ (0, import_jsx_runtime$23.jsxs)("small", { 1269 className: "grey ml-auto", 1270 children: [ 1271 "(", 1272 leads.length, 1273 ")" 1274 ] 1275 })] 1276 }) 1277 }), 1278 onSelectCount ? /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(SelectCountMenuItems, { onOpenCustom: openCustom }) : null,
1279 checkboxChecked && /* @__PURE__ */ (0, import_jsx_runtime$23.jsxs)(import_jsx_runtime$23.Fragment, { children: [onSelectCount ? /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DropdownMenuDivider, {}) : null, /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DropdownMenuItem, { 1280 closeOnClick: true, 1281 children: /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("button", { 1282 type: "button", 1283 className: "dropdown-menu__action", 1284 onClick: onClearSelection, 1285 children: t$20("js.leads.page.deselect_all") 1286 }) 1287 })] }) 1288 ] }) 1289 }) 1290 }) 1291 }), 1292 displayColumns.map((col_2) => { 1293 const isSorted = sort === col_2.name; 1294 const isHideable = !NON_HIDEABLE_COLUMNS$1.includes(col_2.name); 1295 const colIndex = visibleColumnNames.indexOf(col_2.name); 1296 const canMoveLeft = isHideable && colIndex > firstMoveableIndex; 1297 const canMoveRight = isHideable && colIndex < lastMoveableIndex; 1298 return /* @__PURE__ */ (0, import_jsx_runtime$23.jsxs)("th", { 1299 className: cn(isSorted && "active-sort"), 1300 "aria-sort": isSorted ? direction === "asc" ? "ascending" : "descending" : void 0, 1301 style: columnWidths[col_2.name] ? { width: `${columnWidths[col_2.name]}px` } : void 0, 1302 ...resizableThProps(col_2.name), 1303 draggable: isHideable, 1304 onDragStart: isHideable ? (e_2) => handleDragStart(e_2, col_2.name) : void 0, 1305 onDragOver: isHideable ? (e_3) => handleDragOver(e_3, col_2.name) : void 0, 1306 onDragEnd: isHideable ? handleDragEnd : void 0, 1307 children: [/* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(ColumnHeaderMenu, { 1308 column: { 1309 ...col_2, 1310 sticky: columnIsSticky(col_2) 1311 }, 1312 isSorted, 1313 direction, 1314 isHideable, 1315 canMoveLeft, 1316 canMoveRight, 1317 onSort, 1318 onMoveColumn: handleMoveColumn, 1319 onHideColumn: handleHideColumn, 1320 filterConfig: onApplyFilter && formOptions ? { 1321 currentValue: filters?.[col_2.name], 1322 onApplyFilter, 1323 renderFilterBody: (props) => { 1324 if (props.filterName === "lead_location" && onApplyBatchFilter) return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(LocationFilter, { 1325 title: props.filterTitle, 1326 currentFilters: filters ?? {}, 1327 onApplyBatch: (batch) => { 1328 props.onClose(); 1329 onApplyBatchFilter(batch); 1330 }, 1331 countryNames: Object.fromEntries(formOptions.countries.map((country) => [country.value, country.label])), 1332 showHeader: false 1333 }); 1334 return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(FilterBody, { 1335 filterName: props.filterName, 1336 filterTitle: props.filterTitle, 1337 currentValue: props.currentValue, 1338 currentKeywordValue: props.filterName === "position" ? filters?.[POSITION_KEYWORDS_FILTER] : void 0, 1339 formOptions, 1340 companyDropdownEnabled, 1341 notContainsEnabled, 1342 leadsListId, 1343 onApply: props.onApply, 1344 onApplyBatch: (batch_0) => { 1345 props.onClose(); 1346 onApplyBatchFilter(batch_0); 1347 }, 1348 onBack: props.onBack, 1349 showHeader: false 1350 }); 1351 } 1352 } : void 0 1353 }
1353), !columnResizeDisabled && /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("div", { 1354 className: "h-data-table-cell__resize-handle", 1355 ...resizeHandleProps(col_2.name), 1356 role: "separator", 1357 "aria-orientation": "vertical" 1358 })] 1359 }, col_2.name); 1360 }), 1361 /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("th", { 1362 className: "h-data-table__thead-actions", 1363 children: /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("div", { 1364 className: "h-data-table-cell h-data-table-cell--heading is-disabled", 1365 children: t$20("js.leads.page.actions") 1366 }) 1367 }) 1368 ] }), /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DataTableBody, { children: leads.map((lead) => /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DataTableRowBoundary, { 1369 recordId: lead.id, 1370 componentName: "LeadsTable", 1371 children: () => /* @__PURE__ */ (0, import_jsx_runtime$23.jsxs)(DataTableRow, { 1372 id: lead.id, 1373 children: [ 1374 /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DataTableCheckboxCell, { 1375 checked: isSelected(lead.id), 1376 recordId: lead.id, 1377 onChange: () => onToggleRow(lead.id) 1378 }), 1379 displayColumns.map((col_3) => { 1380 if (enrichingLeadIds?.has(lead.id) && lead.domainId == null && ENRICHING_COLUMNS.has(col_3.name)) return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(Skeleton, { 1381 className: "h-data-table-cell h-data-table-cell--skeleton", 1382 "aria-label": t$20("js.data_table.loading"), 1383 noAnimate: true 1384 }) }, col_3.name); 1385 const isEditable = lead.editable && editableColumnNames.includes(col_3.name); 1386 const isCustomEditable = col_3.name.startsWith("custom_attribute-") && isEditable; 1387 const useCustomRenderer = col_3.name === "email" && !lead.email || col_3.name === "company" || col_3.name === "website"; 1388 const isStandardEditable = isEditable && !col_3.name.startsWith("custom_attribute-") && !useCustomRenderer && COLUMN_ACCESSORS[col_3.name]; 1389 if (isCustomEditable) { 1390 const slug = col_3.name.split("-").slice(1).join("-"); 1391 return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(EditableCell, { 1392 leadId: lead.id, 1393 columnName: col_3.name, 1394 value: leadCustomAttrValue(lead.customAttributes, slug) 1395 }, col_3.name); 1396 } 1397 if (isStandardEditable) { 1398 const accessor = COLUMN_ACCESSORS[col_3.name]; 1399 return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(EditableCell, { 1400 leadId: lead.id, 1401 columnName: col_3.name, 1402 value: accessor ? accessor(lead) ?? "" : "" 1403 }, col_3.name); 1404 } 1405 return /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(DataTableCell, { 1406 sticky: columnIsSticky(col_3), 1407 children: renderCell(lead, col_3, { 1408 editableColumnNames, 1409 onLeadClick, 1410 onCompanyClick, 1411 discoverEnabled, 1412 availableTags, 1413 onTagsChange, 1414 onTagUpdate, 1415 onTagDelete, 1416 onVerifyRequested, 1417 onFindEmailRequested, 1418 onFindEmailFailed 1419 }) 1420 }, col_3.name); 1421 }), 1422 /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("td", { children: /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)("div", { 1423 className: "h-data-table-cell", 1424 children: /* @__PURE__ */ (0, import_jsx_runtime$23.jsx)(ActionsColumn, { 1425 lead, 1426 onView: onLeadClick, 1427 onEdit: onEditLead, 1428 onDelete: onDeleteLead, 1429 onVerifyRequested 1430 }) 1431 }) }) 1432 ] 1433 }) 1434 }, lead.id)) })] 1435 }); 1436} 1437var import_react$21, import_jsx_runtime$23, t$20, NON_HIDEABLE_COLUMNS$1, ENRICHING_COLUMNS, COLUMN_ACCESSORS; 1438function init_LeadsTable() { 1439 return (init_LeadsTable = __esmMin((() => { 1440 import_react$21 = require_react(); 1441 init_useColumnResize(); 1442 init_checkbox(); 1443 init_dropdown_menu(); 1444 init_select_count_menu(); 1445 init_utils(); 1446 init_data_table(); 1447 init_company_logo(); 1448 init_skeleton(); 1449 init_data_table_row_boundary(); 1450 init_ColumnHeaderMenu(); 1451 init_FilterBody(); 1452 init_JobTitleFilter(); 1453 init_LocationFilter(); 1454 init_text_helpers(); 1455 init_NameColumn(); 1456 init_EmailColumn(); 1457 init_VerificationColumn(); 1458 init_ConfidenceColumn(); 1459 init_SendingStatusColumn(); 1460 init_TagsColumn(); 1461 init_routes(); 1462 init_EditableCell(); 1463 init_DateCell(); 1464 init_LinkCell(); 1465 init_ActionsColumn(); 1466 init_SequenceColumn(); 1467 import_jsx_runtime$23 = require_jsx_runtime(); 1468 t$20 = (key) => window.i18n.t(key); 1469 NON_HIDEABLE_COLUMNS$1 = ["full_name", "email"];
1470 ENRICHING_COLUMNS = /* @__PURE__ */ new Set([ 1471 "company", 1472 "company_industry", 1473 "company_size", 1474 "company_type" 1475 ]); 1476 COLUMN_ACCESSORS = { 1477 first_name: (lead) => lead.firstName, 1478 last_name: (lead) => lead.lastName, 1479 email: (lead) => lead.email, 1480 company: (lead) => lead.company, 1481 position: (lead) => lead.position, 1482 website: (lead) => lead.website, 1483 phone_number: (lead) => lead.phoneNumber, 1484 linkedin_url: (lead) => lead.linkedinUrl, 1485 twitter: (lead) => lead.twitter, 1486 company_industry: (lead) => lead.companyIndustry, 1487 company_size: (lead) => lead.companySize, 1488 company_type: (lead) => lead.companyType, 1489 source: (lead) => lead.source, 1490 notes: (lead) => lead.notes, 1491 country_code: (lead) => lead.countryCode, 1492 country_name: (lead) => lead.countryName, 1493 lead_country_code: (lead) => lead.leadCountryCode, 1494 lead_country_name: (lead) => lead.leadCountryName, 1495 lead_city: (lead) => lead.leadCity, 1496 lead_state: (lead) => lead.leadState, 1497 lead_location: (lead) => lead.leadLocation, 1498 department: (lead) => lead.department, 1499 user_id: (lead) => lead.userName 1500 }; 1501 })))(); 1502} 1503//#endregion 1504//#region app/frontend/pages/Leads/ColumnsManagement.tsx 1505function isDefaultToggleable(name) { 1506 return !NON_HIDEABLE_COLUMNS.includes(name) && !name.startsWith("custom_attribute-"); 1507} 1508function isCustomColumn(name) { 1509 return name.startsWith("custom_attribute-"); 1510} 1511function ColumnsManagement(t0) { 1512 const $ = (0, import_compiler_runtime$6.c)(51); 1513 const { allColumns, visibleColumnNames, customAttributes, onUpdate, onCreateCustomAttribute } = t0; 1514 const [isOpen, setIsOpen] = (0, import_react$20.useState)(false); 1515 let t1; 1516 if ($[0] !== visibleColumnNames) { 1517 t1 = new Set(visibleColumnNames); 1518 $[0] = visibleColumnNames; 1519 $[1] = t1; 1520 } else t1 = $[1]; 1521 const visibleSet = t1; 1522 const hasCustomAttributes = customAttributes.length > 0; 1523 const [activeTab, setActiveTab] = (0, import_react$20.useState)("default"); 1524 let t2; 1525 if ($[2] !== allColumns || $[3] !== visibleColumnNames) { 1526 t2 = () => buildInitialColumnOrder(allColumns, visibleColumnNames); 1527 $[2] = allColumns; 1528 $[3] = visibleColumnNames; 1529 $[4] = t2; 1530 } else t2 = $[4]; 1531 const [columnOrder, setColumnOrder] = (0, import_react$20.useState)(t2); 1532 const previousVisibleNamesRef = (0, import_react$20.useRef)(visibleColumnNames); 1533 let t3; 1534 let t4; 1535 if ($[5] !== visibleColumnNames) { 1536 t3 = () => { 1537 const previous = previousVisibleNamesRef.current; 1538 previousVisibleNamesRef.current = visibleColumnNames; 1539 if (previous === visibleColumnNames) return; 1540 const previousSet = new Set(previous); 1541 if (!(previousSet.size === visibleColumnNames.length && visibleColumnNames.every((name) => previousSet.has(name)))) return; 1542 setColumnOrder((current) => replaceVisibleSlots(current, visibleColumnNames, previousSet)); 1543 }; 1544 t4 = [visibleColumnNames]; 1545 $[5] = visibleColumnNames; 1546 $[6] = t3; 1547 $[7] = t4; 1548 } else { 1549 t3 = $[6]; 1550 t4 = $[7]; 1551 } 1552 (0, import_react$20.useEffect)(t3, t4); 1553 let t5; 1554 let t6; 1555 if ($[8] !== allColumns) { 1556 t5 = () => { 1557 setColumnOrder((current_0) => syncWithAllColumns(current_0, allColumns)); 1558 }; 1559 t6 = [allColumns]; 1560 $[8] = allColumns; 1561 $[9] = t5; 1562 $[10] = t6; 1563 } else { 1564 t5 = $[9]; 1565 t6 = $[10]; 1566 } 1567 (0, import_react$20.useEffect)(t5, t6); 1568 let t7; 1569 if ($[11] !== allColumns || $[12] !== columnOrder) { 1570 t7 = mapNamesToColumns(columnOrder.filter(isDefaultToggleable), allColumns); 1571 $[11] = allColumns; 1572 $[12] = columnOrder; 1573 $[13] = t7; 1574 } else t7 = $[13]; 1575 const defaultColumns = t7; 1576 let t8; 1577 if ($[14] !== allColumns || $[15] !== columnOrder) { 1578 t8 = mapNamesToColumns(columnOrder.filter(isCustomColumn), allColumns); 1579 $[14] = allColumns; 1580 $[15] = columnOrder; 1581 $[16] = t8; 1582 } else t8 = $[16]; 1583 const customColumns = t8; 1584 let t9; 1585 if ($[17] !== defaultColumns) { 1586 t9 = [...defaultColumns].sort(_temp$3); 1587 $[17] = defaultColumns; 1588 $[18] = t9; 1589 } else t9 = $[18];
1590 const displayedColumns = hasCustomAttributes && activeTab === "custom" ? customColumns : t9; 1591 let t10; 1592 if ($[19] !== customColumns || $[20] !== defaultColumns || $[21] !== onUpdate || $[22] !== visibleColumnNames || $[23] !== visibleSet) { 1593 t10 = function handleToggle(columnName) { 1594 const nextVisibleSet = new Set(visibleSet); 1595 if (nextVisibleSet.has(columnName)) nextVisibleSet.delete(columnName); 1596 else nextVisibleSet.add(columnName); 1597 const nonToggleable = visibleColumnNames.filter(_temp2); 1598 const defaultInOrder = defaultColumns.filter((col) => nextVisibleSet.has(col.name)).map(_temp3); 1599 const customInOrder = customColumns.filter((col_1) => nextVisibleSet.has(col_1.name)).map(_temp4); 1600 onUpdate([ 1601 ...nonToggleable, 1602 ...defaultInOrder, 1603 ...customInOrder 1604 ]); 1605 }; 1606 $[19] = customColumns; 1607 $[20] = defaultColumns; 1608 $[21] = onUpdate; 1609 $[22] = visibleColumnNames; 1610 $[23] = visibleSet; 1611 $[24] = t10; 1612 } else t10 = $[24]; 1613 const handleToggle = t10; 1614 let t11; 1615 if ($[25] !== onCreateCustomAttribute) { 1616 t11 = function handleCreateClick() { 1617 setIsOpen(false); 1618 onCreateCustomAttribute(); 1619 }; 1620 $[25] = onCreateCustomAttribute; 1621 $[26] = t11; 1622 } else t11 = $[26]; 1623 const handleCreateClick = t11; 1624 let t12; 1625 if ($[27] === Symbol.for("react.memo_cache_sentinel")) { 1626 t12 = /* @__PURE__ */ (0, import_jsx_runtime$22.jsx)(DropdownMenuTrigger, { 1627 asChild: true, 1628 children: /* @__PURE__ */ (0, import_jsx_runtime$22.jsxs)(Button, { 1629 type: "button", 1630 variant: "default", 1631 size: "sm", 1632 children: [/* @__PURE__ */ (0, import_jsx_runtime$22.jsx)(Icon, { icon: "table-columns" }), t$19("js.leads.page.columns_button")] 1633 }) 1634 }); 1635 $[27] = t12; 1636 } else t12 = $[27]; 1637 let t13; 1638 if ($[28] !== activeTab || $[29] !== hasCustomAttributes) { 1639 t13 = hasCustomAttributes && /* @__PURE__ */ (0, import_jsx_runtime$22.jsx)(Tabs, { 1640 value: activeTab, 1641 onValueChange: (v) => setActiveTab(v), 1642 children: /* @__PURE__ */ (0, import_jsx_runtime$22.jsxs)(TabsList, { 1643 className: "px-3", 1644 children: [/* @__PURE__ */ (0, import_jsx_runtime$22.jsx)(Tab, { 1645 value: "default", 1646 label: t$19("js.leads.page.columns_default") 1647 }), /* @__PURE__ */ (0, import_jsx_runtime$22.jsx)(Tab, { 1648 value: "custom", 1649 label: t$19("js.leads.page.columns_custom") 1650 })] 1651 }) 1652 }); 1653 $[28] = activeTab; 1654 $[29] = hasCustomAttributes; 1655 $[30] = t13; 1656 } else t13 = $[30]; 1657 let t14; 1658 if ($[31] !== displayedColumns || $[32] !== handleToggle || $[33] !== visibleSet) { 1659 let t15; 1660 if ($[35] !== handleToggle || $[36] !== visibleSet) { 1661 t15 = (col_3) => /* @__PURE__ */ (0, import_jsx_runtime$22.jsxs)(DropdownMenuItem, { 1662 clickable: false, 1663 checked: visibleSet.has(col_3.name), 1664 children: [/* @__PURE__ */ (0, import_jsx_runtime$22.jsx)("label", { 1665 htmlFor: `column_${col_3.name}`, 1666 children: col_3.title 1667 }), /* @__PURE__ */ (0, import_jsx_runtime$22.jsx)(Switch, { 1668 id: `column_${col_3.name}`, 1669 size: "sm", 1670 className: "ml-auto", 1671 checked: visibleSet.has(col_3.name), 1672 onCheckedChange: () => handleToggle(col_3.name) 1673 })] 1674 }, col_3.name); 1675 $[35] = handleToggle; 1676 $[36] = visibleSet; 1677 $[37] = t15; 1678 } else t15 = $[37]; 1679 t14 = displayedColumns.map(t15); 1680 $[31] = displayedColumns; 1681 $[32] = handleToggle; 1682 $[33] = visibleSet; 1683 $[34] = t14; 1684 } else t14 = $[34]; 1685 let t15; 1686 if ($[38] !== t14) { 1687 t15 = /* @__PURE__ */ (0, import_jsx_runtime$22.jsx)("ul", { 1688 className: "dropdown-menu__list--scrollable", 1689 children: t14 1690 }); 1691 $[38] = t14; 1692 $[39] = t15; 1693 } else t15 = $[39]; 1694 let t16; 1695 if ($[40] !== activeTab || $[41] !== handleCreateClick || $[42] !== hasCustomAttributes) { 1696 t16 = (!hasCustomAttributes || activeTab === "custom") && /* @__P
1696URE__ */ (0, import_jsx_runtime$22.jsxs)(import_jsx_runtime$22.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime$22.jsx)("div", { className: "dropdown-divider" }), /* @__PURE__ */ (0, import_jsx_runtime$22.jsx)(DropdownMenuInlineItem, { children: /* @__PURE__ */ (0, import_jsx_runtime$22.jsxs)("button", { 1697 type: "button", 1698 className: "dropdown-menu__action", 1699 onClick: handleCreateClick, 1700 children: [/* @__PURE__ */ (0, import_jsx_runtime$22.jsx)(Icon, { 1701 icon: "plus", 1702 variant: "regular", 1703 size: "sm" 1704 }), t$19("js.leads.page.create_custom_attribute")] 1705 }) })] }); 1706 $[40] = activeTab; 1707 $[41] = handleCreateClick; 1708 $[42] = hasCustomAttributes; 1709 $[43] = t16; 1710 } else t16 = $[43]; 1711 let t17; 1712 if ($[44] !== t13 || $[45] !== t15 || $[46] !== t16) { 1713 t17 = /* @__PURE__ */ (0, import_jsx_runtime$22.jsxs)(DropdownMenuContent, { 1714 headerNavigable: true, 1715 children: [ 1716 t13, 1717 t15, 1718 t16 1719 ] 1720 }); 1721 $[44] = t13; 1722 $[45] = t15; 1723 $[46] = t16; 1724 $[47] = t17; 1725 } else t17 = $[47]; 1726 let t18; 1727 if ($[48] !== isOpen || $[49] !== t17) { 1728 t18 = /* @__PURE__ */ (0, import_jsx_runtime$22.jsxs)(DropdownMenu, { 1729 open: isOpen, 1730 onOpenChange: setIsOpen, 1731 children: [t12, t17] 1732 }); 1733 $[48] = isOpen; 1734 $[49] = t17; 1735 $[50] = t18; 1736 } else t18 = $[50]; 1737 return t18; 1738} 1739function _temp4(col_2) { 1740 return col_2.name; 1741} 1742function _temp3(col_0) { 1743 return col_0.name; 1744} 1745function _temp2(name_0) { 1746 return NON_HIDEABLE_COLUMNS.includes(name_0); 1747} 1748function _temp$3(a, b) { 1749 return a.title.localeCompare(b.title); 1750} 1751function buildInitialColumnOrder(allColumns, visibleColumnNames) { 1752 const visibleSet = new Set(visibleColumnNames); 1753 const merged = [...visibleColumnNames]; 1754 const hiddenColumns = allColumns.filter((col) => !visibleSet.has(col.name)); 1755 for (const hidden of hiddenColumns) { 1756 const staticIndex = allColumns.findIndex((c) => c.name === hidden.name); 1757 let insertAfterIndex = -1; 1758 for (let i = staticIndex - 1; i >= 0; i--) { 1759 const mergedIdx = merged.indexOf(allColumns[i].name); 1760 if (mergedIdx !== -1) { 1761 insertAfterIndex = mergedIdx; 1762 break; 1763 } 1764 } 1765 merged.splice(insertAfterIndex + 1, 0, hidden.name); 1766 } 1767 return merged; 1768} 1769function replaceVisibleSlots(current, newVisibleOrder, previousVisibleSet) { 1770 const next = [...current]; 1771 let visibleIdx = 0; 1772 for (let i = 0; i < next.length; i++) if (previousVisibleSet.has(next[i])) next[i] = newVisibleOrder[visibleIdx++]; 1773 return next; 1774} 1775function syncWithAllColumns(current, allColumns) { 1776 const allNames = new Set(allColumns.map((c) => c.name)); 1777 const filtered = current.filter((name) => allNames.has(name)); 1778 const known = new Set(filtered); 1779 const additions = allColumns.filter((c) => !known.has(c.name)).map((c) => c.name); 1780 if (additions.length === 0 && filtered.length === current.length) return current; 1781 return [...filtered, ...additions]; 1782} 1783function mapNamesToColumns(names, allColumns) { 1784 return names.map((name) => allColumns.find((col) => col.name === name)).filter((col) => col !== void 0); 1785} 1786var import_compiler_runtime$6, import_react$20, import_jsx_runtime$22, t$19, NON_HIDEABLE_COLUMNS; 1787function init_ColumnsManagement() { 1788 return (init_ColumnsManagement = __esmMin((() => { 1789 import_compiler_runtime$6 = require_compiler_runtime(); 1790 import_react$20 = require_react(); 1791 init_button(); 1792 init_icon(); 1793 init_dropdown_menu(); 1794 init_switch(); 1795 init_tabs(); 1796 import_jsx_runtime$22 = require_jsx_runtime(); 1797 t$19 = (key) => window.i18n.t(key); 1798 NON_HIDEABLE_COLUMNS = ["full_name", "email"]; 1799 })))(); 1800} 1801//#endregion 1802//#region app/frontend/pages/Leads/FiltersDropdown.tsx 1803function FiltersDropdown({ columns, customAttributes, filters, formOptions, companyDropdownEnabled, notContainsEnabled = false, decisionMakersAndPpcFiltersEnabled = false, leadsListId, onApplyFilter, onApplyBatchFilter }) { 1804 const menuRef = (0, import_react$19.useRef)(null); 1805 const [isOpen, setIsOpen] = (0, import_react$19.useState)(false); 1806 const [selectedFilter, setSelectedFilter] = (0, import_react$19.useState)(null); 1807 const [searchQuery, setSearchQuery] = (0, import_react$19.useState)(""); 1808 const [activeTab, setActiveTab] = (0, import_react$19.useState)("default"); 1809 const hasCustomAttributes = customAttributes.length > 0; 1810 const defaultFilters = (0, import_react$19.useMemo)(() => { 1811 const columnFilters = columns.filter((col) => !col.name.startsWith("custom_attribute-") && col.name !== "full_name_and_email"); 1812 const standalone = decisionMakersAndPpcFiltersEnabled ? [{ 1813 name: "decision_maker", 1814 title: t$18("js.leads.page.filters.decision_makers_only"), 1815 type: "string", 1816 sortable: false, 1817 visible: false 1818 }, { 1819 name: "people_per_company", 1820 title: t$18("js.leads.page.filters.people_per_company"), 1821 type: "string", 1822 sortable: false, 1823 visible: false 1824 }] : []; 1825 return [...columnFilters, ...standalone].sort((a, b) => a.title.localeCompare(b.title)); 1826 }, [columns, decisionMakersAndPpcFiltersEnabled]); 1827 const customFilters = (0, import_react$19.useMemo)(() => customAttributes.map((ca) => ({ 1828 name: `custom_attribute-${ca.slug}`, 1829 title: ca.label, 1830 type: "text", 1831 sortable: false, 1832 visible: false 1833 })), [customAttributes]); 1834 const currentList = activeTab === "custom" ? customFilters : defaultFilters; 1835 const filteredItems = (0, import_react$19.useMemo)(() => { 1836 if (!searchQuery.trim()) return currentList; 1837 const query = searchQuery.toLowerCase(); 1838 return currentList.filter((f) => f.title.toLowerCase().includes(query)); 1839 }, [currentList, searchQuery]); 1840 const selectedColumn = (0, import_react$19.useMemo)(() => { 1841 const col_0 = columns.find((c) => c.name === selectedFilter); 1842 if (col_0) return col_0; 1843 return customFilters.find((f_0) => f_0.name === selectedFilter) ?? null; 1844 }, [ 1845 columns, 1846 customFilters, 1847 selectedFilter 1848 ]); 1849 function handleBack() { 1850 setSelectedFilter(null); 1851 } 1852 function closeDropdown() { 1853 setSelectedFilter(null); 1854 setSearchQuery(""); 1855 setIsOpen(false); 1856 } 1857 function handleApply(name, value) { 1858 onApplyFilter(name, value); 1859 closeDropdown(); 1860 } 1861 function handleApplyBatch(batchFilters) { 1862 onApplyBatchFilter(batchFilters); 1863 closeDropdown(); 1864 } 1865 function handleDropdownHidden() { 1866 setSelectedFilter(null); 1867 setSearchQuery(""); 1868 setActiveTab("default"); 1869 } 1870 (0, import_react$19.useEffect)(() => { 1871 const el = menuRef.current; 1872 if (!el) return; 1873 if (selectedFilter ? getFilterType(selectedFilter, companyDropdownEnabled) === "tag_text" : false) { 1874 el.style.overflowX = "visible"; 1875 el.style.overflowY = "visible"; 1876 } else if (!selectedFilter) { 1877 el.style.overflowX = "hidden"; 1878 el.style.overflowY = "auto"; 1879 } 1880 }, [ 1881 isOpen, 1882 selectedFilter, 1883 companyDropdownEnabled 1884 ]); 1885 function renderFilterBody() { 1886 if (!selectedFilter) return null; 1887 if (!selectedColumn && !STANDALONE_FILTERS.has(selectedFilter)) return null; 1888 const filterTitle = selectedColumn?.title ?? (selectedFilter === "decision_maker" ? t$18("js.leads.page.filters.decision_makers_only") : selectedFilter === "people_per_company" ? t$18("js.leads.page.filters.people_per_company") : selectedFilter); 1889 if (selectedFilter === "lead_location") return /* @__PURE__ */ (0, import_jsx_runtime$21.jsx)(LocationFilter, { 1890 title: filterTitle, 1891 currentFilters: filters, 1892 onApplyBatch: handleApplyBatch, 1893 countryNames: Object.fromEntries(formOptions.countries.map((country) => [country.value, country.label])), 1894 onBack: handleBack 1895 }); 1896 return /* @__PURE__ */ (0, import_jsx_runtime$21.jsx)(FilterBody, { 1897 filterName: selectedFilter, 1898 filterTitle, 1899 currentValue: filters[selectedFilter], 1900 currentKeywordValue: selectedFilter === "position" ? filters[POSITION_KEYWORDS_FILTER] : void 0, 1901 formOptions,
1902 companyDropdownEnabled, 1903 notContainsEnabled, 1904 leadsListId, 1905 onApply: handleApply, 1906 onApplyBatch: handleApplyBatch, 1907 onBack: handleBack 1908 }); 1909 } 1910 return /* @__PURE__ */ (0, import_jsx_runtime$21.jsxs)(DropdownMenu, { 1911 open: isOpen, 1912 onOpenChange: setIsOpen, 1913 children: [/* @__PURE__ */ (0, import_jsx_runtime$21.jsx)(DropdownMenuTrigger, { 1914 asChild: true, 1915 children: /* @__PURE__ */ (0, import_jsx_runtime$21.jsxs)(Button, { 1916 type: "button", 1917 size: "sm", 1918 children: [/* @__PURE__ */ (0, import_jsx_runtime$21.jsx)(Icon, { icon: "filter" }), t$18("js.leads.page.filters_label")] 1919 }) 1920 }), /* @__PURE__ */ (0, import_jsx_runtime$21.jsx)(DropdownMenuContent, { 1921 ref: menuRef, 1922 className: cn("leads-filters-dropdown", selectedFilter && "leads-filters-dropdown--panel"), 1923 fitViewport: true, 1924 tabNavigable: Boolean(selectedFilter), 1925 headerNavigable: !selectedFilter, 1926 onHide: handleDropdownHidden, 1927 children: selectedFilter ? renderFilterBody() : /* @__PURE__ */ (0, import_jsx_runtime$21.jsxs)(import_jsx_runtime$21.Fragment, { children: [ 1928 hasCustomAttributes && /* @__PURE__ */ (0, import_jsx_runtime$21.jsx)(Tabs, { 1929 value: activeTab, 1930 onValueChange: (v) => { 1931 setActiveTab(v); 1932 setSearchQuery(""); 1933 }, 1934 children: /* @__PURE__ */ (0, import_jsx_runtime$21.jsxs)(TabsList, { 1935 className: "px-2", 1936 children: [/* @__PURE__ */ (0, import_jsx_runtime$21.jsx)(Tab, { 1937 value: "default", 1938 label: t$18("js.leads.page.columns_default") 1939 }), /* @__PURE__ */ (0, import_jsx_runtime$21.jsx)(Tab, { 1940 value: "custom", 1941 label: t$18("js.leads.page.columns_custom") 1942 })] 1943 }) 1944 }),
1945 /* @__PURE__ */ (0, import_jsx_runtime$21.jsxs)("div", { 1946 className: "dropdown-search dropdown-search--alternative mb-05", 1947 children: [ 1948 /* @__PURE__ */ (0, import_jsx_runtime$21.jsx)("label", { 1949 className: "sr-only", 1950 htmlFor: "leads-filter-search", 1951 children: t$18("js.leads.page.search_filter") 1952 }), 1953 /* @__PURE__ */ (0, import_jsx_runtime$21.jsx)(DropdownSearchInput, { 1954 id: "leads-filter-search", 1955 placeholder: t$18("js.leads.page.search_filter"), 1956 value: searchQuery, 1957 onChange: (e) => setSearchQuery(e.target.value) 1958 }), 1959 /* @__PURE__ */ (0, import_jsx_runtime$21.jsx)(Icon, { 1960 icon: "search", 1961 size: "sm", 1962 className: "dropdown-search__btn" 1963 }) 1964 ] 1965 }), 1966 /* @__PURE__ */ (0, import_jsx_runtime$21.jsxs)("ul", { 1967 className: "leads-filters-dropdown__list", 1968 children: [filteredItems.map((filter) => { 1969 const isActive = filter.name === "lead_location" ? LOCATION_PARAM_NAMES.some((p) => filters[p] && filters[p
1969] !== "") : filter.name in filters && filters[filter.name] !== "" || filter.name === "position" && Boolean(filters["position_keywords"]); 1970 const isBoolean = BOOLEAN_FILTERS.has(filter.name); 1971 return /* @__PURE__ */ (0, import_jsx_runtime$21.jsxs)(DropdownMenuItem, { 1972 disabled: isActive, 1973 onClick: () => isBoolean ? handleApply(filter.name, "true") : setSelectedFilter(filter.name), 1974 children: [filter.title, !isBoolean && /* @__PURE__ */ (0, import_jsx_runtime$21.jsx)(Icon, { 1975 icon: "angle-right", 1976 size: "sm", 1977 className: "ml-auto" 1978 })] 1979 }, filter.name); 1980 }), filteredItems.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime$21.jsx)("li", { 1981 className: "dropdown-search-no-results", 1982 children: t$18("js.leads.page.no_filters_found") 1983 })] 1984 }) 1985 ] }) 1986 })] 1987 }); 1988} 1989var import_react$19, import_jsx_runtime$21, t$18, STANDALONE_FILTERS; 1990function init_FiltersDropdown() { 1991 return (init_FiltersDropdown = __esmMin((() => { 1992 import_react$19 = require_react(); 1993 init_button(); 1994 init_icon(); 1995 init_dropdown_menu(); 1996 init_FilterBody(); 1997 init_LocationFilter(); 1998 init_tabs(); 1999 init_utils(); 2000 init_JobTitleFilter(); 2001 import_jsx_runtime$21 = require_jsx_runtime(); 2002 t$18 = (key) => window.i18n.t(key); 2003 STANDALONE_FILTERS = /* @__PURE__ */ new Set(["decision_maker", "people_per_company"]); 2004 })))(); 2005} 2006//#endregion 2007//#region app/frontend/pages/Leads/filters/ActiveFilters.tsx 2008function regularFilterEntriesFor(filters) { 2009 return Object.entries(filters).filter(([key, value]) => value !== "" && !NON_FILTER_PARAMS.has(key) && !INTERNAL_COMPANION_FILTERS.has(key) && !LOCATION_PARAM_SET.has(key)); 2010} 2011function locationFilterCount(filters) { 2012 return LOCATION_PARAM_NAMES.filter((p) =>
2012 filters[p] && filters[p] !== "").reduce((sum, p) => sum + (filters[p]?.split("|").filter(Boolean).length || 0), 0); 2013} 2014function hasActiveFilters(filters) { 2015 return regularFilterEntriesFor(filters).length > 0 || Boolean(filters["position_keywords"]) || locationFilterCount(filters) > 0; 2016} 2017function jobTitleFilterDisplay(positionValue, keywordValue, notContainsEnabled = false) { 2018 if (!keywordValue || positionValue === "*" || positionValue === "~") return null; 2019 const titles = positionValue.replace(/^!/, "").split("|").filter(Boolean); 2020 const keywords = keywordValue.split("|").filter(Boolean); 2021 const selectionSummary = [titles.length > 0 && t$17("js.multi_domain_search.filters.job_titles", { count: titles.length }), keywords.length > 0 && t$17("js.multi_domain_search.filters.keywords", { count: keywords.length })].filter(Boolean).join(" · "); 2022 return { 2023 summary: notContainsEnabled && positionValue.startsWith("!") ? `${t$17("js.leads.page.filters.does_not_contain")}: ${selectionSummary}` : selectionSummary, 2024 tooltip: titles.length > 0 && keywords.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime$20.jsxs)(import_jsx_runtime$20.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime$20.jsxs)("div", { children: [ 2025 /* @__PURE__ */ (0, import_jsx_runtime$20.jsxs)("strong", { 2026 className: "fw-medium", 2027 children: [t$17("js.multi_domain_search.filters.job_titles", { count: titles.length }), ":"] 2028 }), 2029 " ", 2030 titles.join(", ") 2031 ] }
2031), /* @__PURE__ */ (0, import_jsx_runtime$20.jsxs)("div", { children: [ 2032 /* @__PURE__ */ (0, import_jsx_runtime$20.jsxs)("strong", { 2033 className: "fw-medium", 2034 children: [t$17("js.multi_domain_search.filters.keywords", { count: keywords.length }), ":"] 2035 }), 2036 " ", 2037 keywords.join(", ") 2038 ] })] }) : (titles.length > 0 ? titles : keywords).join(", ") 2039 }; 2040} 2041function buildValueResolver(filterName, formOptions) { 2042 if (filterName === "country_code") { 2043 const countryMap = new Map(formOptions.countries.map((c) => [c.value.toLowerCase(), c.label])); 2044 return (val) => countryMap.get(String(val).toLowerCase()) || String(val); 2045 } 2046 if (filterName === "verification_status") return (val) => { 2047 const label = dictLookup(VERIFICATION_STATUS_LABELS, val); 2048 return label ? t$17(label) : val; 2049 }; 2050 if (filterName === "sending_status") return (val) => { 2051 const label = dictLookup(SENDING_STATUS_LABELS, val); 2052 return label ? t$17(label) : val; 2053 }; 2054 if (filterName === "sync_status") return (val) => { 2055 const label = dictLookup(SYNC_STATUS_LABELS, val); 2056 return label ? t$17(label) : val; 2057 }; 2058 if (filterName === "company_industry") return (val) => String(val).charAt(0).toUpperCase() + String(val).slice(1); 2059 if (filterName === "department") { 2060 const departmentMap = new Map(formOptions.departments.map((d) => [d.value, d.label])); 2061 return (val) => departmentMap.get(String(val)) || String(val); 2062 } 2063 if (filterName === "tags") { 2064 const tagMap = new Map(formOptions.availableTags.map((tag) => [tag.value, tag.label])); 2065 return (val) => tagMap.get(String(val)) || String(val); 2066 } 2067 if (filterName === "campaign_ids") { 2068 const campaignMap = new Map(formOptions.availableCampaigns.map((c) => [c.value, c.label])); 2069 return (val) => campaignMap.get(String(val)) || String(val); 2070 } 2071 if (filterName === "user_id") { 2072 const memberMap = new Map((formOptions.teamMembers ?? []).map((m) => [m.value, m.label])); 2073 return (val) => memberMap.get(String(val)) || String(val); 2074 } 2075 return null; 2076} 2077function getFilterValueLabel(filterName, rawValue, formOptions, notContainsEnabled = false) { 2078 const value = normalizeEncodedFilterValue(rawValue); 2079 if (filterName === "decision_maker") return ""; 2080 if (filterName === "people_per_company") return t$17("js.leads.page.filters.people_per_company_value", { count: CurrencyHelper.numberWithDelimiter(Number(value)) }); 2081 if (value === "*") return t$17("js.leads.page.filters.has_any_value"); 2082 if (value === "~") return t$17("js.leads.page.filters.is_empty"); 2083 if (getFilterType(filterName) === "date") { 2084 const preset = dictLookup(DATE_PRESET_LABELS, value); 2085 if (preset) return t$17(preset); 2086 } 2087 if (notContainsEnabled && value.startsWith("!") && value.length > 1) { 2088 const parts = splitGenuineMultiValue(value, { 2089 notContainsEnabled, 2090 includeNegation: true 2091 }); 2092 const label = parts ? t$17("js.leads.page.filters.n_options", { count: parts.length }) : value.slice(1); 2093 return `${t$17("js.leads.page.filters.does_not_contain")}: ${label}`; 2094 } 2095 const resolver = buildValueResolver(filterName, formOptions); 2096 if (isDateRangeEncoded(value)) { 2097 const [from, to] = value.split("|"); 2098 return `${from} \u2013 ${to}`; 2099 } 2100 const multi = splitGenuineMultiValue(value, { notContainsEnabled }); 2101 if (multi) return t$17("js.leads.page.filters.n_options", { count: multi.length }); 2102 if (value.includes("|")) { 2103 const parts = value.split("|"); 2104 return resolver ? resolver(parts[0]) : parts[0]; 2105 } 2106 if (value.includes(":")) { 2107 const [from, to] = value.split(":"); 2108 return `${from} \u2013 ${to}`; 2109 } 2110 return resolver ? resolver(value) : value; 2111} 2112function getFilterValueSelection(filterName, rawValue, formOptions, notContainsEnabled = false) { 2113 const value = normalizeEncodedFilterValue(rawValue); 2114 const parts = splitGenuineMultiValue(value, { 2115 notContainsEnabled, 2116 includeNegation: true, 2117 isDateFilter: getFilterType(filterName) === "date" 2118 }); 2119 if (!parts) return []; 2120 const resolver = buildValueResolver(filterName, formOptions); 2121 return parts.map((part) => resolver ? resolver(part) : part); 2122} 2123function ActiveFilters(t0) { 2124 const $ = (0, import_compiler_runtime$5.c)(42); 2125 const { filters, columns, customAttributes, formOptions, companyDropdownEnabled, notContainsEnabled, leadsListId, onApplyFilter, onApplyBatchFilter, onRemoveFilter, onRemoveBatchFilter, onClearAll } = t0; 2126 let t1; 2127 let t2; 2128 let t3; 2129 if ($[0] !== columns || $[1] !== companyDropdownEnabled || $[2] !== customAttributes || $[3] !== filters || $[4] !== formOptions || $[5] !== leadsListId || $[6] !== notContainsEnabled || $[7] !== onApplyBatchFilter || $[8] !== onApplyFilter || $[9] !== onRemoveBatchFilter || $[10] !== onRemoveFilter) { 2130 t3 = Symbol.for("react.early_return_sentinel"); 2131 bb0: { 2132 const filterEntries = regularFilterEntriesFor(filters); 2133 if (filters["position_keywords"] && !filters.position) filterEntries.push(["position", ""]); 2134 let t4; 2135 if ($[14] !== filters) { 2136 t4 = (p) =>
2136 filters[p] && filters[p] !== ""; 2137 $[14] = filters; 2138 $[15] = t4; 2139 } else t4 = $[15]; 2140 const activeLocationParams = LOCATION_PARAM_NAMES.filter(t4); 2141 const locationCount = locationFilterCount(filters); 2142 if (filterEntries.length === 0 && locationCount === 0) { 2143 t3 = null; 2144 break bb0; 2145 } 2146 let t5; 2147 if ($[16] !== columns || $[17] !== customAttributes) { 2148 t5 = function getFilterLabel(filterName) { 2149 if (filterName === "decision_maker") return t$17("js.leads.page.filters.decision_makers_only"); 2150 if (filterName === "people_per_company") return t$17("js.leads.page.filters.people_per_company"); 2151 const column = columns.find((c) => c.name === filterName); 2152 if (column) return column.title; 2153 const ca = customAttributes.find((a) => `custom_attribute-${a.slug}` === filterName); 2154 if (ca) return ca.label; 2155 return filterName; 2156 }; 2157 $[16] = columns; 2158 $[17] = customAttributes; 2159 $[18] = t5; 2160 } else t5 = $[18]; 2161 const getFilterLabel = t5; 2162 let t6; 2163 if ($[19] !== onRemoveBatchFilter) { 2164 t6 = function handleRemoveLocation() { 2165 onRemoveBatchFilter([...LOCATION_PARAM_NAMES]); 2166 }; 2167 $[19] = onRemoveBatchFilter; 2168 $[20] = t6; 2169 } else t6 = $[20]; 2170 const handleRemoveLocation = t6; 2171 let t7; 2172 if ($[21] !== filters || $[22] !== getFilterLabel || $[23] !== notContainsEnabled || $[24] !== onRemoveBatchFilter || $[25] !== onRemoveFilter) { 2173 t7 = (t8) => { 2174 const [filterName_0, value] = t8; 2175 const display = filterName_0 === "position" ? jobTitleFilterDisplay(value, filters[POSITION_KEYWORDS_FILTER], notContainsEnabled) : null; 2176 return { 2177 filterName: filterName_0, 2178 filterTitle: getFilterLabel(filterName_0), 2179 value, 2180 summaryOverride: display?.summary, 2181 tooltipOverride: display?.tooltip, 2182 onRemove: () => filterName_0 === "position" ? onRemoveBatchFilter(["position", POSITION_KEYWORDS_FILTER]) : onRemoveFilter(filterName_0) 2183 }; 2184 }; 2185 $[21] = filters; 2186 $[22] = getFilterLabel; 2187 $[23] = notContainsEnabled; 2188 $[24] = onRemoveBatchFilter; 2189 $[25] = onRemoveFilter; 2190 $[26] = t7; 2191 } else t7 = $[26]; 2192 const pills = filterEntries.map(t7); 2193 if (locationCount > 0) pills.push({ 2194 filterName: "lead_location", 2195 filterTitle: getFilterLabel("lead_location"), 2196 value: getLocationValueLabel(activeLocationParams, filters, formOptions.countries), 2197 selectionOverride: getLocationValueSelection(activeLocationParams, filters, formOptions.countries), 2198 onRemove: handleRemoveLocation 2199 }); 2200 pills.sort(_temp$2); 2201 t1 = "main-filters mb-4"; 2202 let t8; 2203 if ($[27] !== companyDropdownEnabled || $[28] !== filters || $[29] !== formOptions || $[30] !== leadsListId || $[31] !== notContainsEnabled || $[32] !== onApplyBatchFilter || $[33] !== onApplyFilter) { 2204 t8 = (pill) => /* @__PURE__ */ (0, import_jsx_runtime$20.jsx)(ActiveFilterPill, { 2205 filterName: pill.filterName, 2206 filterTitle: pill.filterTitle, 2207 value: pill.value, 2208 selectionOverride: pill.selectionOverride, 2209 summaryOverride: pill.summaryOverride, 2210 tooltipOverride: pill.tooltipOverride, 2211 filters, 2212 formOptions, 2213 companyDropdownEnabled, 2214 notContainsEnabled, 2215 leadsListId, 2216 onApplyFilter, 2217 onApplyBatchFilter, 2218 onRemove: pill.onRemove 2219 }, pill.filterName); 2220 $[27] = companyDropdownEnabled; 2221 $[28] = filters; 2222 $[29] = formOptions; 2223 $[30] = leadsListId; 2224 $[31] = notContainsEnabled; 2225 $[32] = onApplyBatchFilter; 2226 $[33] = onApplyFilter; 2227 $[34] = t8; 2228 } else t8 = $[34]; 2229 t2 = pills.map(t8); 2230 } 2231 $[0] = columns; 2232 $[1] = companyDropdownEnabled; 2233 $[2] = customAttributes; 2234 $[3] = filters; 2235 $[4] = formOptions; 2236 $[5] = leadsListId; 2237 $[6] = notContainsEnabled; 2238 $[7] = onApplyBatchFilter; 2239 $[8] = onApplyFilter; 2240 $[9] = onRemoveBatchFilter; 2241 $[10] = onRemoveFilter; 2242 $[11] = t1; 2243 $[12] = t2; 2244 $[13] = t3; 2245 } else { 2246 t1 = $[11]; 2247 t2 = $[12]; 2248 t3 = $[13]; 2249 } 2250 if (t3 !== Symbol.for("react.early_return_sentinel")) return t3; 2251 let t4; 2252 if ($[35] === Symbol.for("react.memo_cache_sentinel")) { 2253 t4 = t$17("js.leads.page.filters.clear_all"); 2254 $[35] = t4; 2255 } else t4 = $[35]; 2256 let t5; 2257 if ($[36] !== onClearAll) { 2258 t5 = /* @__PURE__ */ (0, import_jsx_runtime$20.jsx)("div", { 2259 className: "ml-auto d-flex align-items-center gap-2", 2260 children: /* @__PURE__ */ (0, import_jsx_runtime$20.jsx)(Button, { 2261 type: "button", 2262 variant: "ghost", 2263 size: "sm", 2264 onClick: onClearAll, 2265 children: t4 2266 }) 2267 }); 2268 $[36] = onClearAll; 2269 $[37] = t5; 2270 } else t5 = $[37]; 2271 let t6; 2272 if ($[38] !== t1 || $[39] !== t2 || $[40] !== t5) { 2273 t6 = /* @__PURE__ */ (0, import_jsx_runtime$20.jsxs)("div", { 2274 className: t1, 2275 children: [t2, t5] 2276 }); 2277 $[38] = t1; 2278 $[39] = t2; 2279 $[40] = t5; 2280 $[41] = t6; 2281 } else t6 = $[41]; 2282 return t6; 2283} 2284function _temp$2(a_0, b) { 2285 return a_0.filterTitle.localeCompare(b.filterTitle); 2286} 2287function ActiveFilterPill({ filterName, filterTitle, value, selectionOverride, summaryOverride, tooltipOverride, filters, formOptions, companyDropdownEnabled, notContainsEnabled = false, leadsListId, onApplyFilter, onApplyBatchFilter, onRemove }) { 2288 const [isOpen, setIsOpen] = (0, import_react$18.useState)(false); 2289 const isLocation = filterName === "lead_location"; 2290 if (BOOLEAN_FILTERS.has(filterName)) return /* @__PURE__ */ (0, import_jsx_runtime$20.jsx)("div", { 2291 className: "h-filter h-filter--boolean", 2292 children: /* @__PURE__ */ (0, import_jsx_runtime$20.jsxs)("span", { 2293 className: "h-filter__value",
2294 children: [filterTitle, /* @__PURE__ */ (0, import_jsx_runtime$20.jsx)("button", { 2295 type: "button", 2296 className: "btn-empty h-filter__remove", 2297 "aria-label": t$17("js.leads.page.filters.remove_filter", { filter: filterTitle }), 2298 onClick: onRemove, 2299 children: /* @__PURE__ */ (0, import_jsx_runtime$20.jsx)(Icon, { 2300 icon: "times", 2301 size: "sm" 2302 }) 2303 })] 2304 }) 2305 }); 2306 function handleApply(name, newValue) { 2307 onApplyFilter(name, newValue); 2308 setIsOpen(false); 2309 } 2310 function handleApplyBatch(batchFilters) { 2311 onApplyBatchFilter(batchFilters); 2312 setIsOpen(false); 2313 } 2314 const valueLabel = summaryOverride ?? (isLocation ? value : getFilterValueLabel(filterName, value, formOptions, notContainsEnabled)); 2315 const selection = isLocation ? selectionOverride ?? [] : getFilterValueSelection(filterName, value, formOptions, notContainsEnabled); 2316 return /* @__PURE__ */ (0, import_jsx_runtime$20.jsxs)(DropdownMenu, { 2317 className: "h-filter", 2318 open: isOpen, 2319 onOpenChange: setIsOpen, 2320 children: [ 2321 /* @__PURE__ */ (0, import_jsx_runtime$20.jsx)(DropdownMenuTrigger, { 2322 asChild: true, 2323 children: /* @__PURE__ */ (0, import_jsx_runtime$20.jsxs)(Button, { 2324 type: "button", 2325 size: "sm", 2326 className: "h-filter__button", 2327 children: [filterTitle, /* @__PURE__ */ (0, import_jsx_runtime$20.jsx)(Icon, { icon: "angle-down" })] 2328 }) 2329 }), 2330 /* @__PURE__ */ (0, import_jsx_runtime$20.jsx)(FilterValue, { 2331 summary: valueLabel, 2332 labels: selection, 2333 tooltip: tooltipOverride, 2334 removeAriaLabel: `Remove ${filterTitle} filter`, 2335 onRemove 2336 }), 2337 /* @__PURE__ */ (0, import_jsx_runtime$20.jsx)(DropdownMenuContent, { 2338 className: "leads-filters-dropdown leads-filters-dropdown--panel", 2339 tabNavigable: true, 2340 children: isLocation ? /* @__PURE__ */ (0, import_jsx_runtime$20.jsx)(LocationFilter, { 2341 title: filterTitle, 2342 currentFilters: filters, 2343 onApplyBatch: handleApplyBatch, 2344 countryNames: Object.fromEntries(formOptions.countries.map((country) => [country.value, country.label])), 2345 showHeader: false 2346 }) : /* @__PURE__ */ (0, import_jsx_runtime$20.jsx)(FilterBody, { 2347 filterName, 2348 filterTitle, 2349 currentValue: value, 2350 currentKeywordValue: filterName === "position" ? filters[POSITION_KEYWORDS_FILTER] : void 0, 2351 formOptions, 2352 companyDropdownEnabled, 2353 notContainsEnabled, 2354 leadsListId, 2355 onApply: handleApply, 2356 onApplyBatch: handleApplyBatch, 2357 showHeader: false 2358 }) 2359 }) 2360 ] 2361 }); 2362} 2363var import_compiler_runtime$5, import_react$18, import_jsx_runtime$20, t$17, LOCATION_PARAM_SET, INTERNAL_COMPANION_FILTERS, NON_FILTER_PARAMS, VERIFICATION_STATUS_LABELS, SENDING_STATUS_LABELS, SYNC_STATUS_LABELS; 2364function init_ActiveFilters() { 2365 return (init_ActiveFilters = __esmMin((() => { 2366 import_compiler_runtime$5 = require_compiler_runtime(); 2367 import_react$18 = require_react(); 2368 init_button(); 2369 init_icon(); 2370 init_dropdown_menu(); 2371 init_FilterBody(); 2372 init_LocationFilter(); 2373 init_date_presets(); 2374 init_encoded_filter_value(); 2375 init_FilterValue(); 2376 init_currency_helper(); 2377 init_JobTitleFilter(); 2378 import_jsx_runtime$20 = require_jsx_runtime(); 2379 t$17 = (key, options) => window.i18n.t(key, options); 2380 LOCATION_PARAM_SET = new Set(LOCATION_PARAM_NAMES); 2381 INTERNAL_COMPANION_FILTERS = /* @__PURE__ */ new Set([POSITION_KEYWORDS_FILTER]); 2382 NON_FILTER_PARAMS = /* @__PURE__ */ new Set([ 2383 "query", 2384 "sort", 2385 "direction", 2386 "offset", 2387 "leads_list_id", 2388 "filters_changed", 2389 "filter_from_chart", 2390 "page_size" 2391 ]); 2392 VERIFICATION_STATUS_LABELS = { 2393 valid: "js.leads.page.verification_status.valid", 2394 invalid: "js.leads.page.verification_status.invalid", 2395 accept_all: "js.leads.page.verification_status.accept_all", 2396 webmail: "js.leads.page.verification_status.webmail", 2397 disposable: "js.leads.page.verification_status.disposable", 2398 unknown: "js.leads.page.verification_status.unknown" 2399 }; 2400 SENDING_STATUS_LABELS = { 2401 pending: "js.leads.page.sending_status.pending", 2402 error: "js.leads.page.sending_status.error", 2403 sent: "js.leads.page.sending_status.sent", 2404 bounced: "js.leads.page.sending_status.bounced", 2405 opened: "js.leads.page.sending_status.opened", 2406 clicked: "js.leads.page.sending_status.clicked", 2407 replied: "js.leads.page.sending_status.replied", 2408 unsubscribed: "js.leads.page.sending_status.unsubscribed", 2409 canceled: "js.leads.page.sending_status.canceled" 2410 }; 2411 SYNC_STATUS_LABELS = { 2412 pending: "js.leads.page.sync_status.pending", 2413 error: "js.leads.page.sync_status.error", 2414 success: "js.leads.page.sync_status.success" 2415 }; 2416 })))(); 2417} 2418//#endregion 2419//#region app/frontend/pages/Leads/modals/MergeListModal.tsx 2420function mergeSuccessMessage(sourceLeadsCount) { 2421 return sourceLeadsCount > 100 ? t$16("js.leads.page.list_actions.merge_modal.success_async") : t$16("js.leads.page.list_actions.merge_modal.success"); 2422} 2423function mergeDestinationLists(source, leadsLists) { 2424 return leadsLists.filter((list) => list.type === "static" && list.id !== source.id && list.userId === source.userId); 2425} 2426function canMergeList(currentUser, leadsList, leadsLists) { 2427 if (leadsList.type !== "static" || leadsList.leadsCount === 0) return false;
2428 if (!currentUser.teamAdmin && !currentUser.teamOwner && currentUser.id !== leadsList.userId) return false; 2429 return mergeDestinationLists(leadsList, leadsLists).length > 0; 2430} 2431function MergeListModal({ open, onClose, onMerged, leadsList, leadsLists }) { 2432 const [destinationId, setDestinationId] = (0, import_react$17.useState)(""); 2433 const [submitting, setSubmitting] = (0, import_react$17.useState)(false); 2434 const [error, setError] = (0, import_react$17.useState)(null); 2435 const destinationLists = mergeDestinationLists(leadsList, leadsLists); 2436 const handleClose = (0, import_react$17.useCallback)(() => { 2437 setDestinationId(""); 2438 setSubmitting(false); 2439 setError(null); 2440 onClose(); 2441 }, [onClose]); 2442 const { dialogRef, close, createAbortController } = useDialog({ 2443 isOpen: open, 2444 onClose: handleClose 2445 }); 2446 (0, import_react$17.useEffect)(() => { 2447 if (open) setError(null); 2448 }, [open]); 2449 async function handleSubmit(e) { 2450 e.preventDefault(); 2451 if (!destinationId || submitting) return; 2452 setSubmitting(true); 2453 setError(null); 2454 const controller = createAbortController(); 2455 try { 2456 const response = await fetch(leads_list_merge_index_path(leadsList.id), { 2457 method: "POST", 2458 headers: { 2459 "X-CSRF-Token": getCsrfToken(), 2460 Accept: "text/html" 2461 }, 2462 body: new URLSearchParams({ destination_leads_list_id: destinationId }), 2463 redirect: "follow", 2464 signal: controller.signal 2465 }); 2466 if (controller.signal.aborted) return; 2467 if (response.url.match(/[?&]leads_list_id=(\d+)/)?.[1] === destinationId) { 2468 const destinationListId = Number(destinationId); 2469 close(); 2470 onMerged(destinationListId); 2471 return; 2472 } 2473 setError(t$16("js.leads.page.list_actions.merge_modal.error")); 2474 setSubmitting(false); 2475 } catch (err) { 2476 if (err?.name === "AbortError") return; 2477 setError(t$16("js.leads.page.list_actions.merge_modal.error")); 2478 setSubmitting(false); 2479 } 2480 } 2481 return /* @__PURE__ */ (0, import_jsx_runtime$19.jsx)(Dialog, { 2482 ref: dialogRef, 2483 children: /* @__PURE__ */ (0, import_jsx_runtime$19.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$19.jsxs)("form", { 2484 onSubmit: handleSubmit, 2485 children: [
2486 /* @__PURE__ */ (0, import_jsx_runtime$19.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime$19.jsx)(DialogTitle, { children: t$16("js.leads.page.list_actions.merge_modal.title") }), /* @__PURE__ */ (0, import_jsx_runtime$19.jsx)(DialogCloseButton, { 2487 type: "button", 2488 onClick: close 2489 })] }), 2490 /* @__PURE__ */ (0, import_jsx_runtime$19.jsxs)(DialogBody, { children: [ 2491 /* @__PURE__ */ (0, import_jsx_runtime$19.jsxs)("p", { children: [ 2492 t$16("js.leads.page.list_actions.merge_modal.merge_list"), 2493 " ", 2494 /* @__PURE__ */ (0, import_jsx_runtime$19.jsx)("strong", { children: leadsList.name }), 2495 " (", 2496 t$16("js.leads.page.list_actions.merge_modal.leads_count", { 2497 count: leadsList.leadsCount, 2498 formatted_count: CurrencyHelper.numberWithDelimiter(leadsList.leadsCount) 2499 }), 2500 ") ", 2501 t$16("js.leads.page.list_actions.merge_modal.into") 2502 ] }), 2503 /* @__PURE__ */ (0, import_jsx_runtime$19.jsx)("p", { children: t$16("js.leads.page.list_actions.merge_modal.warning", { list_name: leadsList.name }) }), 2504 /* @__PURE__ */ (0, import_jsx_runtime$19.jsxs)("div", { 2505 className: "form-group mt-4", 2506 children: [/* @__PURE__ */ (0, import_jsx_runtime$19.jsx)(Label, { 2507 fullWidth: true, 2508 htmlFor: "merge-list-destination-select", 2509 children: t$16("js.leads.page.list_actions.merge_modal.destination_list") 2510 }), /* @__PURE__ */ (0, import_jsx_runtime$19.jsxs)("select", { 2511 className: "h-select h-select--block", 2512 id: "merge-list-destination-select", 2513 value: destinationId, 2514 onChange: (e_0) => setDestinationId(e_0.target.value), 2515 required: true, 2516 "aria-invalid": error ? true : void 0, 2517 "aria-describedby": error ? "merge-list-error" : void 0, 2518 children: [/* @__PURE__ */ (0, import_jsx_runtime$19.jsx)("option", { 2519 value: "", 2520 disabled: true, 2521 children: t$16("js.leads.page.list_actions.merge_modal.placeholder") 2522 }), destinationLists.map((list) => /* @__PURE__ */ (0, import_jsx_runtime$19.jsx)("option", { 2523 value: list.id, 2524 children: list.name 2525 }, list.id))] 2526 })] 2527 }), 2528 error && /* @__PURE__ */ (0, import_jsx_runtime$19.jsxs)(Alert, { 2529 variant: "destructive", 2530 size: "small", 2531 className: "mt-3", 2532 id: "merge-list-error", 2533 "data-testid": "submit-error-alert", 2534 children: [/* @__PURE__ */ (0, import_jsx_runtime$19.jsx)(AlertIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime$19.jsx)(Icon, { icon: "circle-exclamation" }) }
2534), /* @__PURE__ */ (0, import_jsx_runtime$19.jsx)(AlertContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$19.jsx)(AlertDescription, { children: error }) })] 2535 }) 2536 ] }), 2537 /* @__PURE__ */ (0, import_jsx_runtime$19.jsxs)(DialogFooter, { children: [/* @__PURE__ */ (0, import_jsx_runtime$19.jsx)(Button, { 2538 type: "button", 2539 onClick: close, 2540 children: t$16("js.leads.page.cancel") 2541 }), /* @__PURE__ */ (0, import_jsx_runtime$19.jsx)(Button, { 2542 type: "submit", 2543 variant: "danger", 2544 disabled: !destinationId || submitting, 2545 "data-loading": "none", 2546 children: t$16("js.leads.page.list_actions.merge_modal.submit") 2547 })] }) 2548 ] 2549 }) }) 2550 }); 2551} 2552var import_react$17, import_jsx_runtime$19, t$16; 2553function init_MergeListModal() { 2554 return (init_MergeListModal = __esmMin((() => { 2555 import_react$17 = require_react(); 2556 init_routes(); 2557 init_utils(); 2558 init_currency_helper(); 2559 init_dialog(); 2560 init_button(); 2561 init_label(); 2562 init_alert(); 2563 init_icon(); 2564 init_useDialog(); 2565 import_jsx_runtime$19 = require_jsx_runtime(); 2566 t$16 = (key, options) => window.i18n.t(key, options); 2567 })))(); 2568} 2569//#endregion 2570//#region app/frontend/pages/Leads/ListHeader.tsx 2571function exportLeadsList(leadsListId) { 2572 const form = document.createElement("form"); 2573 form.method = "POST"; 2574 form.action = leads_export_path(); 2575 form.style.display = "none"; 2576 const csrfInput = document.createElement("input"); 2577 csrfInput.type = "hidden"; 2578 csrfInput.name = "authenticity_token"; 2579 csrfInput.value = getCsrfToken(); 2580 form.appendChild(csrfInput); 2581 const filterInput = document.createElement("input"); 2582 filterInput.type = "hidden"; 2583 filterInput.name = "filters[leads_list_id]"; 2584 filterInput.value = String(leadsListId); 2585 form.appendChild(filterInput); 2586 document.body.appendChild(form); 2587 form.submit(); 2588 document.body.removeChild(form); 2589} 2590function ListHeader(t0) { 2591 const $ = (0, import_compiler_runtime$4.c)(18); 2592 const { leadsList, leadsLists, folders, onRenamed, onFolderChanged, children } = t0; 2593 const { currentUser } = usePage().props; 2594 let t1; 2595 if ($[0] !== currentUser || $[1] !== leadsList || $[2] !== leadsLists) { 2596 t1 = canMergeList(currentUser, leadsList, leadsLists); 2597 $[0] = currentUser; 2598 $[1] = leadsList; 2599 $[2] = leadsLists; 2600 $[3] = t1; 2601 } else t1 = $[3]; 2602 const canMerge = t1; 2603 let t2; 2604 if ($[4] !== leadsList.leadsCount) { 2605 t2 = function handleMerged(destinationListId) { 2606 toast.success(mergeSuccessMessage(leadsList.leadsCount)); 2607 router.visit(leads_path({ leads_list_id: destinationListId })); 2608 }; 2609 $[4] = leadsList.leadsCount; 2610 $[5] = t2; 2611 } else t2 = $[5]; 2612 const handleMerged = t2; 2613 let t3; 2614 if ($[6] !== handleMerged || $[7] !== leadsList || $[8] !== leadsLists) { 2615 t3 = (t4) => { 2616 const { open, onClose } = t4; 2617 return /* @__PURE__ */ (0, import_jsx_runtime$18.jsx)(MergeListModal, { 2618 leadsList, 2619 leadsLists, 2620 open, 2621 onClose, 2622 onMerged: handleMerged 2623 }); 2624 }; 2625 $[6] = handleMerged; 2626 $[7] = leadsList; 2627 $[8] = leadsLists; 2628 $[9] = t3; 2629 } else t3 = $[9]; 2630 let t4; 2631 if ($[10] !== canMerge || $[11] !== children || $[12] !== folders || $[13] !== leadsList || $[14] !== onFolderChanged || $[15] !== onRenamed || $[16] !== t3) { 2632 t4 = /* @__PURE__ */ (0, import_jsx_runtime$18.jsx)(EntityListHeader, { 2633 list: leadsList, 2634 folders, 2635 config: CONFIG, 2636 onRenamed, 2637 onFolderChanged, 2638 showMergeAction: canMerge, 2639 renderMergeModal: t3, 2640 children 2641 }); 2642 $[10] = canMerge; 2643 $[11] = children; 2644 $[12] = folders; 2645 $[13] = leadsList; 2646 $[14] = onFolderChanged; 2647 $[15] = onRenamed; 2648 $[16] = t3; 2649 $[17] = t4; 2650 } else t4 = $[17]; 2651 return t4; 2652} 2653var import_compiler_runtime$4, import_jsx_runtime$18, CONFIG; 2654function init_ListHeader() { 2655 return (init_ListHeader = __esmMin((() => { 2656 import_compiler_runtime$4 = require_compiler_runtime(); 2657 init_dist(); 2658 init_utils(); 2659 init_routes(); 2660 init_toast(); 2661 init_MergeListModal(); 2662 init_ListHeader$1(); 2663 import_jsx_runtime$18 = require_jsx_runtime(); 2664 CONFIG = { 2665 i18nPrefix: "js.leads.page", 2666 breadcrumbKey: "breadcrumb_leads", 2667 breadcrumbHref: () => leads_path(), 2668 folderIdParam: "leads_list_folder_id", 2669 folderMutationLockKey: "leads-list-folder", 2670 listPath: leads_list_path, 2671 favoritePath: leads_list_favorite_path, 2672 folderPath: leads_list_folder_path, 2673 foldersPath: () => leads_list_folders_path(), 2674 afterDeleteHref: () => leads_path(), 2675 exportList: exportLeadsList, 2676 historyPath: leads_list_history_path 2677 }; 2678 })))(); 2679} 2680//#endregion 2681//#region app/frontend/pages/Leads/PageHeader.tsx 2682function LeadsPageHeader({ leadsList, leadsLists, totalCount, totalCountApproximate = false, query, columns, customAttributes, formOptions, folders, filters, onSearch, onRenamed, onFolderChanged, onNewLead, onApplyFilter, onApplyBatchFilter, onRemoveFilter, onRemoveBatchFilter, onClearAllFilters, onSaveAsList, companyDropdownEnabled, notContainsEnabled, decisionMakersAndPpcFiltersEnabled, companyDropdownListId, lookalikes, previewSourceLeads, searchFilters, hideMainHeading = false, visibleColumnNames, onColumnsUpdate, onCreateCustomAttribute, insightsOpen = false, onToggleInsights, children }) { 2683 const [searchValue, setSearchValue] = (0, import_react$16.useState)(query ?? ""); 2684 const showSaveAsList = Boolean(onSaveAsList) && totalCount > 0 && hasActiveFilters(filters); 2685 (0, import_react$16.useEffect)(() => { 2686 setSearchValue(query ?? ""); 2687 }, [query]); 2688 function handleSubmit(e) { 2689 e.preventDefault(); 2690 onSearch(searchValue); 2691 } 2692 return /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)(import_jsx_runtime$17.Fragment, { children: [
2693 /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)(ListHeader, { 2694 leadsList, 2695 leadsLists, 2696 folders, 2697 onRenamed, 2698 onFolderChanged, 2699 children: [ 2700 /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)("div", { 2701 className: "d-flex align-items-center gap-2", 2702 children: [/* @__PURE__ */ (0, import_jsx_runtime$17.jsx)(Button, { 2703 size: "sm", 2704 asChild: true, 2705 children: /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)("a", { 2706 href: new_leads_import_path(importPathParamsForList(leadsList)), 2707 children: [/* @__PURE__ */ (0, import_jsx_runtime$17.jsx)(Icon, { icon: "plus" }), t$15("js.leads.page.import_leads")] 2708 }) 2709 }), /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)(Button, { 2710 variant: "primary", 2711 size: "sm", 2712 onClick: onNewLead, 2713 children: [/* @__PURE__ */ (0, import_jsx_runtime$17.jsx)(Icon, { icon: "plus" }), t$15("js.leads.page.new_lead")] 2714 })] 2715 }), 2716 leadsList.type !== "virtual" && /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)("div", { className: "main-heading__separator" }),
2717 /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)(LeadLookalikesSheet, { 2718 showTrigger: leadsList.type !== "virtual", 2719 buttonLabel: t$15("js.leads.page.find_similar_leads"), 2720 leadIds: [], 2721 sourceLeads: previewSourceLeads, 2722 searchFilters, 2723 sourceListCount: totalCount, 2724 user: lookalikes?.user, 2725 leadsLists: lookalikes?.leadsLists, 2726 folders, 2727 numberOfCreditsLeft: lookalikes?.numberOfCreditsLeft, 2728 similarityThresholds: lookalikes?.similarityThresholds, 2729 maxLookalikesLimit: lookalikes?.maxLookalikesLimit, 2730 isPremium: lookalikes?.isPremium, 2731 upgradeUrl: lookalikes?.upgradeUrl, 2732 upgradeImageUrl: lookalikes?.upgradeImageUrl, 2733 debugLogging: lookalikes?.debugLogging, 2734 countryNames: lookalikes?.countryNames, 2735 decisionMakersFilterEnabled: decisionMakersAndPpcFiltersEnabled 2736 }) 2737 ] 2738 }), 2739 children, 2740 !hideMainHeading && /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)("div", { 2741 className: "main-heading", 2742 children: [ 2743 /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)("h2", { 2744 className: "main-heading__count", 2745 children: [ 2746 /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)("strong", { 2747 className: "fw-medium", 2748 children: [formatNumber(totalCount), totalCountApproximate ? "+" : ""] 2749 }), 2750 " ", 2751 t$15("js.leads.page.leads_count_label") 2752 ] 2753 }),
2754 /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)("hr", { className: "main-heading__separator" }), 2755 /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)("div", { 2756 className: "main-heading__filtering", 2757 children: [ 2758 /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)("div", { 2759 className: "h-search-form leads-search-form", 2760 role: "search", 2761 onKeyDown: (e_0) => { 2762 if (e_0.key === "Enter") handleSubmit(e_0); 2763 }, 2764 children: [ 2765 /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)("input", { 2766 type: "search", 2767 className: "h-search-form__input", 2768 placeholder: t$15("js.leads.page.search_by_name_or_email"), 2769 value: searchValue, 2770 onChange: (e_1) => setSearchValue(e_1.target.value), 2771 "aria-label": t$15("js.leads.page.search_by_name_or_email") 2772 }), 2773 query && /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)("button", { 2774 type: "button", 2775 className: "h-search-form__reset", 2776 "aria-label": "Clear search", 2777 onClick: () => { 2778 setSearchValue(""); 2779 onSearch(""); 2780 }, 2781 children: /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)(Icon, { 2782 icon: "times", 2783 size: "sm" 2784 }) 2785 }), 2786 /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)("button", { 2787 type: "button", 2788 className: "h-search-form__submit", 2789 "aria-label": "Search", 2790 onClick: handleSubmit, 2791 children: /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)(Icon, { 2792 icon: "magnifying-glass", 2793 size: "sm" 2794 }) 2795 }) 2796 ] 2797 }), 2798 /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)(FiltersDropdown, { 2799 columns, 2800 customAttributes, 2801 filters, 2802 formOptions, 2803 companyDropdownEnabled, 2804 notContainsEnabled, 2805 decisionMakersAndPpcFiltersEnabled, 2806 leadsListId: companyDropdownListId, 2807 onApplyFilter, 2808 onApplyBatchFilter 2809 }), 2810 showSaveAsList && /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)(import_jsx_runtime$17.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime$17.jsx)("hr", { className: "main-heading__separator" }), /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)(Button, { 2811 type: "button", 2812 size: "sm", 2813 onClick: onSaveAsList, 2814 children: t$15("js.leads.page.save_list.button") 2815 })] }) 2816 ] 2817 }), 2818 totalCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)("div", { 2819 className: "ml-auto d-flex align-items-center gap-2", 2820 children: [/* @__PURE__ */ (0, import_jsx_runtime$17.jsx)(ColumnsManagement, { 2821 allColumns: columns, 2822 visibleColumnNames, 2823 customAttributes, 2824 onUpdate: onColumnsUpdate, 2825 onCreateCustomAttribute 2826 }), /* @__PURE__ */ (0, import_jsx_runtime$17.jsxs)(ToggleButton, { 2827 size: "sm", 2828 selected: insightsOpen, 2829 onSelectedChange: () => onToggleInsights?.(), 2830 className: "leads-insights-toggle", 2831 children: [ 2832 /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)(Icon, { icon: "chart-bar" }), 2833 t$15("js.insights.button"), 2834 /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)("span", { 2835 className: "leads-insights-toggle__close", 2836 "aria-hidden": "true", 2837 children: /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)(Icon, { 2838 icon: "times", 2839 size: "sm" 2840 }) 2841 }) 2842 ] 2843 })] 2844 }) 2845 ] 2846 }), 2847 /* @__PURE__ */ (0, import_jsx_runtime$17.jsx)(ActiveFilters, { 2848 filters, 2849 columns, 2850 customAttributes, 2851 formOptions, 2852 companyDropdownEnabled, 2853 notContainsEnabled, 2854 leadsListId: companyDropdownListId, 2855 onApplyFilter, 2856 onApplyBatchFilter, 2857 onRemoveFilter, 2858 onRemoveBatchFilter, 2859 onClearAll: onClearAllFilters 2860 }) 2861 ] }); 2862} 2863var import_react$16, import_jsx_runtime$17, t$15; 2864function init_PageHeader() { 2865 return (init_PageHeader = __esmMin((() => { 2866 import_react$16 = require_react(); 2867 init_button(); 2868 init_toggle_button(); 2869 init_icon(); 2870 init_routes(); 2871 init_text_helpers(); 2872 init_ColumnsManagement(); 2873 init_FiltersDropdown(); 2874 init_ActiveFilters(); 2875 init_ListHeader(); 2876 init_lead_lookalikes_sheet(); 2877 import_jsx_runtime$17 = require_jsx_runtime(); 2878 t$15 = (key) => window.i18n.t(key); 2879 })))(); 2880} 2881//#endregion 2882//#region app/frontend/pages/Leads/EmptyState.tsx 2883function LeadsEmptyState(t0) { 2884 const $ = (0, import_compiler_runtime$3.c)(24); 2885 const { hasNoMatch, leadsListId, totalOwnedLeads, importPathParams } = t0; 2886 if (hasNoMatch) { 2887 let t1; 2888 if ($[0] === Symbol.for("react.memo_cache_sentinel")) { 2889 t1 = /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)(EmptyStateImage, { children: /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)("img", { 2890 src: leads_default, 2891 alt: "" 2892 }) }); 2893 $[0] = t1; 2894 } else t1 = $[0]; 2895 let t2; 2896 if ($[1] === Symbol.for("react.memo_cache_sentinel")) { 2897 t2 = /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)(EmptyStateTitle, { children: t$14("js.leads.page.no_match") }); 2898 $[1] = t2; 2899 } else t2 = $[1]; 2900 let t3; 2901 if ($[2] === Symbol.for("react.memo_cache_sentinel")) { 2902 t3 = /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)(EmptyStateDescription, { children: t$14("js.leads.page.no_match_subt
2902itle") }); 2903 $[2] = t3; 2904 } else t3 = $[2]; 2905 let t4; 2906 if ($[3] !== leadsListId) { 2907 t4 = leads_path({ leads_list_id: leadsListId }); 2908 $[3] = leadsListId; 2909 $[4] = t4; 2910 } else t4 = $[4]; 2911 let t5; 2912 if ($[5] === Symbol.for("react.memo_cache_sentinel")) { 2913 t5 = t$14("js.leads.page.reset_search"); 2914 $[5] = t5; 2915 } else t5 = $[5]; 2916 let t6; 2917 if ($[6] !== t4) { 2918 t6 = /* @__PURE__ */ (0, import_jsx_runtime$16.jsxs)(EmptyState, { 2919 orientation: "horizontal", 2920 children: [t1, /* @__PURE__ */ (0, import_jsx_runtime$16.jsxs)(EmptyStateContent, { children: [ 2921 t2, 2922 t3, 2923 /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)(EmptyStateActions, { children: /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)(Button, { 2924 size: "sm", 2925 asChild: true, 2926 children: /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)("a", { 2927 href: t4, 2928 "data-turbo-frame": "_top", 2929 children: t5 2930 }) 2931 }) }) 2932 ] })] 2933 }); 2934 $[6] = t4; 2935 $[7] = t6; 2936 } else t6 = $[7]; 2937 return t6; 2938 } 2939 let t1; 2940 if ($[8] === Symbol.for("react.memo_cache_sentinel")) { 2941 t1 = /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)(EmptyStateImage, { children: /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)("img", { 2942 src: leads_default, 2943 alt: "" 2944 }) }); 2945 $[8] = t1; 2946 } else t1 = $[8]; 2947 let t2; 2948 if ($[9] === Symbol.for("react.memo_cache_sentinel")) { 2949 t2 = /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)(EmptyStateTitle, { children: t$14("js.leads.page.no_leads_in_list.title") }); 2950 $[9] = t2; 2951 } else t2 = $[9]; 2952 let t3; 2953 if ($[10] !== totalOwnedLeads) { 2954 t3 = t$14("js.leads.page.no_leads_in_list.description_html", { 2955 count: totalOwnedLeads, 2956 all_people_path: leads_path() 2957 }); 2958 $[10] = totalOwnedLeads; 2959 $[11] = t3; 2960 } else t3 = $[11]; 2961 let t4; 2962 if ($[12] !== t3) { 2963 t4 = /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)(EmptyStateDescription, { 2964 className: "text-balance", 2965 dangerouslySetInnerHTML: { __html: t3 } 2966 }); 2967 $[12] = t3; 2968 $[13] = t4; 2969 } else t4 = $[13]; 2970 let t5; 2971 if ($[14] === Symbol.for("react.memo_cache_sentinel")) { 2972 t5 = discovers_path(); 2973 $[14] = t5; 2974 } else t5 = $[14]; 2975 let t6; 2976 if ($[15] === Symbol.for("react.memo_cache_sentinel")) { 2977 t6 = /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)(Button, { 2978 variant: "primary", 2979 size: "sm", 2980 asChild: true, 2981 children: /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)("a", { 2982 href: t5, 2983 "data-turbo-frame": "_top", 2984 children: t$14("js.leads.page.no_leads_in_list.cta_secondary") 2985 }) 2986 }); 2987 $[15] = t6; 2988 } else t6 = $[15]; 2989 let t7; 2990 if ($[16] !== importPathParams) { 2991 t7 = new_leads_import_path(importPathParams); 2992 $[16] = importPathParams; 2993 $[17] = t7; 2994 } else t7 = $[17]; 2995 let t8; 2996 if ($[18] === Symbol.for("react.memo_cache_sentinel")) { 2997 t8 = t$14("js.leads.page.no_leads_in_list.cta_primary"); 2998 $[18] = t8; 2999 } else t8 = $[18]; 3000 let t9; 3001 if ($[19] !== t7) { 3002 t9 = /* @__PURE__ */ (0, import_jsx_runtime$16.jsxs)(EmptyStateActions, { children: [t6, /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)(Button, { 3003 size: "sm", 3004 asChild: true, 3005 children: /* @__PURE__ */ (0, import_jsx_runtime$16.jsx)("a", { 3006 href: t7, 3007 "data-turbo-frame": "_top", 3008 children: t8 3009 }) 3010 })] }); 3011 $[19] = t7; 3012 $[20] = t9; 3013 } else t9 = $[20]; 3014 let t10; 3015 if ($[21] !== t4 || $[22] !== t9) { 3016 t10 = /* @__PURE__ */ (0, import_jsx_runtime$16.jsxs)(EmptyState, { children: [t1, /* @__PURE__ */ (0, import_jsx_runtime$16.jsxs)(EmptyStateContent, { children: [ 3017 t2, 3018 t4, 3019 t9 3020 ] })] }); 3021 $[21] = t4; 3022 $[22] = t9; 3023 $[23] = t10; 3024 } else t10 = $[23]; 3025 return t10; 3026} 3027var import_compiler_runtime$3, import_jsx_runtime$16, t$14; 3028function init_EmptyState() { 3029 return (init_EmptyState = __esmMin((() => { 3030 import_compiler_runtime$3 = require_compiler_runtime(); 3031 init_empty_state(); 3032 init_button(); 3033 init_routes(); 3034 init_leads(); 3035 import_jsx_runtime$16 = require_jsx_runtime(); 3036 t$14 = (key, options) => window.i18n.t(key, options); 3037 })))(); 3038} 3039//#endregion 3040//#region app/frontend/pages/Leads/CreateLeadSheet.tsx 3041function buildInitialFormData(currentListId) { 3042 return { 3043 email: "", 3044 leads_list_ids: currentListId ? String(currentListId) : "", 3045 first_name: "", 3046 last_name: "", 3047 position: "", 3048 phone_number: "", 3049 department: "", 3050 lead_country_code: "", 3051 lead_city: "", 3052 linkedin_url: "", 3053 twitter: "", 3054 company: "", 3055 website: "", 3056 company_industry: "", 3057 company_type: "", 3058 country_code: "" 3059 }; 3060} 3061function CreateLeadSheet({ open, onOpenChange, onLeadCreated, leadsLists, currentListId, customAttributes, formOptions }) {
3062 const [formData, setFormData] = (0, import_react$15.useState)(() => buildInitialFormData(currentListId)); 3063 const [customAttrValues, setCustomAttrValues] = (0, import_react$15.useState)({}); 3064 const [submitting, setSubmitting] = (0, import_react$15.useState)(false); 3065 const [errors, setErrors] = (0, import_react$15.useState)({}); 3066 const formRef = (0, import_react$15.useRef)(null); 3067 const submitGenerationRef = (0, import_react$15.useRef)(0); 3068 const formErrors = unfieldedErrors(errors, [...Object.keys(formData), ...customAttributes.map((attr) => attr.slug)]); 3069 (0, import_react$15.useEffect)(() => { 3070 if (Object.keys(errors).length === 0 || formErrors.length > 0) return; 3071 focusFirstInvalidField(formRef.current); 3072 }, [errors]); 3073 const wasOpenRef = (0, import_react$15.useRef)(open); 3074 (0, import_react$15.useEffect)(() => { 3075 if (open && !wasOpenRef.current) resetForm(); 3076 wasOpenRef.current = open; 3077 }, [open, currentListId]); 3078 function resetForm() { 3079 submitGenerationRef.current += 1; 3080 setFormData(buildInitialFormData(currentListId)); 3081 setCustomAttrValues({}); 3082 setErrors({}); 3083 setSubmitting(false); 3084 } 3085 function handleClose() { 3086 resetForm(); 3087 onOpenChange(false); 3088 } 3089 function handleChange(field, value) { 3090 setFormData((prev) => ({ 3091 ...prev, 3092 [field]: value 3093 })); 3094 } 3095 function handleCustomAttrChange(slug, value_0) { 3096 setCustomAttrValues((prev_0) => ({ 3097 ...prev_0, 3098 [slug]: value_0 3099 })); 3100 } 3101 async function handleSubmit(e) { 3102 e.preventDefault(); 3103 const generation = submitGenerationRef.current; 3104 setSubmitting(true); 3105 setErrors({}); 3106 const leadParams = { 3107 ...formData, 3108 source: "Hunter (manual entry)" 3109 }; 3110 const listId = leadParams.leads_list_ids; 3111 if (!listId || listId === "" || listId === "0" || listId === "null" || listId === "undefined") delete leadParams.leads_list_ids;
3112 const filledCustomAttrs = {}; 3113 for (const [slug_0, value_1] of Object.entries(customAttrValues)) if (value_1.trim()) filledCustomAttrs[slug_0] = value_1; 3114 if (Object.keys(filledCustomAttrs).length > 0) leadParams.custom_attributes = filledCustomAttrs; 3115 try { 3116 const response = await fetch(leads_path(), { 3117 method: "POST", 3118 headers: { 3119 "X-CSRF-Token": getCsrfToken(), 3120 "Content-Type": "application/json", 3121 Accept: "application/json" 3122 }, 3123 body: JSON.stringify({ lead: leadParams }) 3124 }); 3125 const data = await response.json(); 3126 if (submitGenerationRef.current !== generation) { 3127 if (response.ok) onLeadCreated?.(data.lead.id, data.lead.enriching ?? false); 3128 return; 3129 } 3130 if (response.ok) { 3131 handleClose(); 3132 onLeadCreated?.(data.lead.id, data.lead.enriching ?? false); 3133 } else setErrors(normalizeFormErrors(data.errors)); 3134 } finally { 3135 if (submitGenerationRef.current === generation) setSubmitting(false); 3136 } 3137 } 3138 const listOptions = leadsLists.filter((l) => l.type !== "dynamic"); 3139 return /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Sheet, { 3140 open, 3141 onOpenChange: (isOpen) => { 3142 if (!isOpen) handleClose(); 3143 }, 3144 modal: false, 3145 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)(SheetContent, { 3146 overlay: false, 3147 className: "p-0", 3148 children: [/* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(SheetTitle, { 3149 className: "sr-only", 3150 children: t$13("js.leads.page.create_lead_title") 3151 }), /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(SheetBody, { 3152 padding: "none", 3153 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3154 className: "lead-edit", 3155 children: [/* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("header", { 3156 className: "lead-edit__header", 3157 children: [/* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("button", { 3158 type: "button", 3159 className: "lead-edit__back", 3160 onClick: handleClose, 3161 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Icon, { icon: "arrow-left" }) 3162 }), /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("h2", { 3163 className: "lead-edit__title", 3164 children: t$13("js.leads.page.create_lead_title") 3165 })] 3166 }), /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("form", { 3167 className: "edit_lead", 3168 onSubmit: handleSubmit, 3169 ref: formRef, 3170 children: [ 3171 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FormErrors, { messages: formErrors }), 3172 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3173 className: "lead-edit__section-header", 3174 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("h3", { 3175 className: "lead-edit__section-title", 3176 children: t$13("js.leads.page.form.profile") 3177 }) 3178 }), 3179 /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3180 className: "row", 3181 children: [ 3182 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3183 className: "col-md-6", 3184 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3185 className: "form-group", 3186 children: [ 3187 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3188 htmlFor: "create-lead-email-field", 3189 children: t$13("js.leads.page.form.email_address") 3190 }), 3191 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Input, { 3192 type: "email", 3193 id: "create-lead-email-field", 3194 fullWidth: true, 3195 className: errors.email ? "error" : "", 3196 "aria-invalid": errors.email ? true : void 0, 3197 "aria-describedby": errors.email ? "create-lead-email-field-error" : void 0, 3198 value: formData.email, 3199 onChange: (e_0) => handleChange("email", e_0.target.value) 3200 }), 3201 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3202 id: "create-lead-email-field-error", 3203 message: errors.email 3204 }) 3205 ] 3206 }) 3207 }), 3208 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3209 className: "col-md-6", 3210 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3211 className: "form-group", 3212 children: [
3213 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3214 htmlFor: "create-lead-list-field", 3215 children: t$13("js.leads.page.form.list") 3216 }), 3217 /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("select", { 3218 id: "create-lead-list-field", 3219 className: `h-select h-select--block ${errors.leads_list_ids ? "error" : ""}`, 3220 "aria-invalid": errors.leads_list_ids ? true : void 0, 3221 "aria-describedby": errors.leads_list_ids ? "create-lead-list-field-error" : void 0, 3222 value: formData.leads_list_ids, 3223 onChange: (e_1) => handleChange("leads_list_ids", e_1.target.value), 3224 children: [/* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("option", { 3225 value: "", 3226 children: t$13("js.leads.page.form.all_people") 3227 }), listOptions.map((list) => /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("option", { 3228 value: String(list.id), 3229 children: list.name 3230 }, list.id))] 3231 }), 3232 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3233 id: "create-lead-list-field-error", 3234 message: errors.leads_list_ids 3235 }) 3236 ] 3237 }) 3238 }), 3239 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3240 className: "col-md-6 clear-left", 3241 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3242 className: "form-group", 3243 children: [ 3244 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3245 htmlFor: "create-lead-first-name-field", 3246 children: t$13("js.leads.page.form.first_name") 3247 }), 3248 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Input, { 3249 type: "text", 3250 id: "create-lead-first-name-field", 3251 fullWidth: true, 3252 value: formData.first_name, 3253 onChange: (e_2) => handleChange("first_name", e_2.target.value), 3254 className: errors.first_name ? "error" : "", 3255 "aria-invalid": errors.first_name ? true : void 0, 3256 "aria-describedby": errors.first_name ? "create-lead-first-name-field-error" : void 0 3257 }), 3258 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3259 id: "create-lead-first-name-field-error", 3260 message: errors.first_name 3261 }) 3262 ] 3263 }) 3264 }), 3265 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3266 className: "col-md-6", 3267 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3268 className: "form-group", 3269 children: [ 3270 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3271 htmlFor: "create-lead-last-name-field", 3272 children: t$13("js.leads.page.form.last_name") 3273 }), 3274 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Input, { 3275 type: "text", 3276 id: "create-lead-last-name-field", 3277 fullWidth: true, 3278 value: formData.last_name, 3279 onChange: (e_3) => handleChange("last_name", e_3.target.value), 3280 className: errors.last_name ? "error" : "", 3281 "aria-invalid": errors.last_name ? true : void 0, 3282 "aria-describedby": errors.last_name ? "create-lead-last-name-field-error" : void 0 3283 }), 3284 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3285 id: "create-lead-last-name-field-error", 3286 message: errors.last_name 3287 }) 3288 ] 3289 }) 3290 }), 3291 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3292 className: "col-md-6 clear-left", 3293 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3294 className: "form-group", 3295 children: [ 3296 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3297 htmlFor: "create-lead-position-field", 3298 children: t$13("js.leads.page.form.job_title") 3299 }),
3300 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Input, { 3301 type: "text", 3302 id: "create-lead-position-field", 3303 fullWidth: true, 3304 value: formData.position, 3305 onChange: (e_4) => handleChange("position", e_4.target.value), 3306 className: errors.position ? "error" : "", 3307 "aria-invalid": errors.position ? true : void 0, 3308 "aria-describedby": errors.position ? "create-lead-position-field-error" : void 0 3309 }), 3310 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3311 id: "create-lead-position-field-error", 3312 message: errors.position 3313 }) 3314 ] 3315 }) 3316 }), 3317 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3318 className: "col-md-6", 3319 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3320 className: "form-group", 3321 children: [ 3322 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3323 htmlFor: "create-lead-phone-field", 3324 children: t$13("js.leads.page.form.phone_number") 3325 }), 3326 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Input, { 3327 type: "tel", 3328 id: "create-lead-phone-field", 3329 fullWidth: true, 3330 value: formData.phone_number, 3331 onChange: (e_5) => handleChange("phone_number", e_5.target.value), 3332 className: errors.phone_number ? "error" : "", 3333 "aria-invalid": errors.phone_number ? true : void 0, 3334 "aria-describedby": errors.phone_number ? "create-lead-phone-field-error" : void 0 3335 }), 3336 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3337 id: "create-lead-phone-field-error", 3338 message: errors.phone_number 3339 }) 3340 ] 3341 }) 3342 }), 3343 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3344 className: "col-md-6", 3345 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3346 className: "form-group", 3347 children: [ 3348 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3349 htmlFor: "create-lead-department-field", 3350 children: t$13("js.leads.page.form.department") 3351 }), 3352 /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("select", { 3353 id: "create-lead-department-field", 3354 className: `h-select h-select--block ${errors.department ? "error" : ""}`, 3355 "aria-invalid": errors.department ? true : void 0, 3356 "aria-describedby": errors.department ? "create-lead-department-field-error" : void 0, 3357 value: formData.department, 3358 onChange: (e_6) => handleChange("department", e_6.target.value), 3359 children: [/* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("option", { 3360 value: "", 3361 children: t$13("js.leads.page.form.select_a_department") 3362 }), formOptions.departments.map((d) => /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("option", { 3363 value: d.value, 3364 children: d.label 3365 }, d.value))] 3366 }), 3367 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3368 id: "create-lead-department-field-error", 3369 message: errors.department 3370 }) 3371 ] 3372 }) 3373 }), 3374 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3375 className: "col-md-6", 3376 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3377 className: "form-group", 3378 children: [ 3379 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3380 htmlFor: "create-lead-country-field", 3381 children: t$13("js.leads.page.form.country") 3382 }), 3383 /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("select", { 3384 id: "create-lead-country-field", 3385 className: `h-select h-select--block ${errors.lead_country_code ? "error" : ""}`, 3386 "aria-invalid": errors.lead_country_code ? true : void 0, 3387 "aria-describedby": errors.lead_country_code ? "create-lead-country-field-error" : void 0, 3388 value: formData.lead_country_code, 3389 onChange: (e_7) => handleChange("lead_country_code", e_7.target.value), 3390 children: [/* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("option", { 3391 value: "", 3392 children: t$13("js.leads.page.form.select_a_country") 3393 }), formOptions.countries.map((c) => /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("option", { 3394 value: c.value, 3395 children: c.label 3396 }, c.value))] 3397 }),
3398 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3399 id: "create-lead-country-field-error", 3400 message: errors.lead_country_code 3401 }) 3402 ] 3403 }) 3404 }), 3405 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3406 className: "col-md-6", 3407 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3408 className: "form-group", 3409 children: [ 3410 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3411 htmlFor: "create-lead-city-field", 3412 children: t$13("js.leads.page.form.city") 3413 }), 3414 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Input, { 3415 type: "text", 3416 id: "create-lead-city-field", 3417 fullWidth: true, 3418 placeholder: formData.lead_country_code ? "" : t$13("js.leads.page.form.select_a_country_first"), 3419 disabled: !formData.lead_country_code, 3420 value: formData.lead_city, 3421 onChange: (e_8) => handleChange("lead_city", e_8.target.value), 3422 className: errors.lead_city ? "error" : "", 3423 "aria-invalid": errors.lead_city ? true : void 0, 3424 "aria-describedby": errors.lead_city ? "create-lead-city-field-error" : void 0 3425 }), 3426 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3427 id: "create-lead-city-field-error", 3428 message: errors.lead_city 3429 }) 3430 ] 3431 }) 3432 }), 3433 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3434 className: "col-md-6", 3435 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3436 className: "form-group", 3437 children: [ 3438 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3439 htmlFor: "create-lead-linkedin-field", 3440 children: t$13("js.leads.page.form.linkedin_profile") 3441 }), 3442 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Input, { 3443 type: "url", 3444 id: "create-lead-linkedin-field", 3445 fullWidth: true, 3446 value: formData.linkedin_url, 3447 onChange: (e_9) => handleChange("linkedin_url", e_9.target.value), 3448 className: errors.linkedin_url ? "error" : "", 3449 "aria-invalid": errors.linkedin_url ? true : void 0, 3450 "aria-describedby": errors.linkedin_url ? "create-lead-linkedin-field-error" : void 0 3451 }), 3452 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3453 id: "create-lead-linkedin-field-error", 3454 message: errors.linkedin_url 3455 }) 3456 ] 3457 }) 3458 }), 3459 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3460 className: "col-md-6", 3461 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3462 className: "form-group", 3463 children: [ 3464 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3465 htmlFor: "create-lead-twitter-field", 3466 children: t$13("js.leads.page.form.twitter_handle") 3467 }), 3468 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Input, { 3469 type: "text", 3470 id: "create-lead-twitter-field", 3471 fullWidth: true, 3472 value: formData.twitter, 3473 onChange: (e_10) => handleChange("twitter", e_10.target.value), 3474 className: errors.twitter ? "error" : "", 3475 "aria-invalid": errors.twitter ? true : void 0, 3476 "aria-describedby": errors.twitter ? "create-lead-twitter-field-error" : void 0 3477 }), 3478 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3479 id: "create-lead-twitter-field-error", 3480 message: errors.twitter 3481 }) 3482 ] 3483 }) 3484 }) 3485 ] 3486 }), 3487 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3488 className: "lead-edit__section-header", 3489 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("h3", { 3490 className: "lead-edit__section-title", 3491 children: t$13("js.leads.page.form.company") 3492 }) 3493 }),
3494 /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3495 className: "row", 3496 children: [ 3497 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3498 className: "col-md-6", 3499 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3500 className: "form-group", 3501 children: [ 3502 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3503 htmlFor: "create-lead-company-name-field", 3504 children: t$13("js.leads.page.form.company_name") 3505 }), 3506 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Input, { 3507 type: "text", 3508 id: "create-lead-company-name-field", 3509 fullWidth: true, 3510 value: formData.company, 3511 onChange: (e_11) => handleChange("company", e_11.target.value), 3512 className: errors.company ? "error" : "", 3513 "aria-invalid": errors.company ? true : void 0, 3514 "aria-describedby": errors.company ? "create-lead-company-name-field-error" : void 0 3515 }), 3516 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3517 id: "create-lead-company-name-field-error", 3518 message: errors.company 3519 }) 3520 ] 3521 }) 3522 }), 3523 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3524 className: "col-md-6", 3525 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3526 className: "form-group", 3527 children: [ 3528 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3529 htmlFor: "create-lead-company-website-field", 3530 children: t$13("js.leads.page.form.website") 3531 }), 3532 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Input, { 3533 type: "text", 3534 id: "create-lead-company-website-field", 3535 fullWidth: true, 3536 value: formData.website, 3537 onChange: (e_12) => handleChange("website", e_12.target.value), 3538 className: errors.website ? "error" : "", 3539 "aria-invalid": errors.website ? true : void 0, 3540 "aria-describedby": errors.website ? "create-lead-company-website-field-error" : void 0 3541 }), 3542 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3543 id: "create-lead-company-website-field-error", 3544 message: errors.website 3545 }) 3546 ] 3547 }) 3548 }), 3549 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3550 className: "col-md-6", 3551 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3552 className: "form-group", 3553 children: [ 3554 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3555 htmlFor: "create-lead-company-industry-field", 3556 children: t$13("js.leads.page.form.industry") 3557 }), 3558 /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("select", { 3559 id: "create-lead-company-industry-field", 3560 className: `h-select h-select--block ${errors.company_industry ? "error" : ""}`, 3561 "aria-invalid": errors.company_industry ? true : void 0, 3562 "aria-describedby": errors.company_industry ? "create-lead-company-industry-field-error" : void 0, 3563 value: formData.company_industry, 3564 onChange: (e_13) => handleChange("company_industry", e_13.target.value), 3565 children: [/* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("option", { 3566 value: "", 3567 children: t$13("js.leads.page.form.select_an_industry") 3568 }), formOptions.industries.map((industry) => /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("option", { 3569 value: industry, 3570 children: industry 3571 }, industry))] 3572 }), 3573 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3574 id: "create-lead-company-industry-field-error", 3575 message: errors.company_industry 3576 }) 3577 ] 3578 }) 3579 }),
3580 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3581 className: "col-md-6", 3582 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3583 className: "form-group", 3584 children: [ 3585 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3586 htmlFor: "create-lead-company-type-field", 3587 children: t$13("js.leads.page.form.company_type") 3588 }), 3589 /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("select", { 3590 id: "create-lead-company-type-field", 3591 className: `h-select h-select--block ${errors.company_type ? "error" : ""}`, 3592 "aria-invalid": errors.company_type ? true : void 0, 3593 "aria-describedby": errors.company_type ? "create-lead-company-type-field-error" : void 0, 3594 value: formData.company_type, 3595 onChange: (e_14) => handleChange("company_type", e_14.target.value), 3596 children: [/* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("option", { 3597 value: "", 3598 children: t$13("js.leads.page.form.select_a_type") 3599 }), formOptions.companyTypes.map((type) => /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("option", { 3600 value: type, 3601 children: type 3602 }, type))] 3603 }), 3604 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3605 id: "create-lead-company-type-field-error", 3606 message: errors.company_type 3607 }) 3608 ] 3609 }) 3610 }), 3611 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3612 className: "col-md-6", 3613 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3614 className: "form-group", 3615 children: [ 3616 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3617 htmlFor: "create-lead-company-country-field", 3618 children: t$13("js.leads.page.form.company_country") 3619 }), 3620 /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("select", { 3621 id: "create-lead-company-country-field", 3622 className: `h-select h-select--block ${errors.country_code ? "error" : ""}`, 3623 "aria-invalid": errors.country_code ? true : void 0, 3624 "aria-describedby": errors.country_code ? "create-lead-company-country-field-error" : void 0, 3625 value: formData.country_code, 3626 onChange: (e_15) => handleChange("country_code", e_15.target.value), 3627 children: [/* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("option", { 3628 value: "", 3629 children: t$13("js.leads.page.form.select_a_country") 3630 }), formOptions.countries.map((c_0) => /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("option", { 3631 value: c_0.value, 3632 children: c_0.label 3633 }, c_0.value))] 3634 }), 3635 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3636 id: "create-lead-company-country-field-error", 3637 message: errors.country_code 3638 }) 3639 ] 3640 }) 3641 }) 3642 ] 3643 }), 3644 customAttributes.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)(import_jsx_runtime$15.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3645 className: "lead-edit__section-header", 3646 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("h3", { 3647 className: "lead-edit__section-title", 3648 children: t$13("js.leads.page.form.custom_attributes") 3649 }) 3650 }), /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3651 className: "row", 3652 children: customAttributes.map((attr_0) => /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("div", { 3653 className: "col-md-6", 3654 children: /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("div", { 3655 className: "form-group", 3656 children: [ 3657 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Label, { 3658 htmlFor: `create-lead-custom-${attr_0.slug}`, 3659 children: attr_0.label 3660 }),
3661 attr_0.attributeType === "textarea" ? /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)("textarea", { 3662 id: `create-lead-custom-${attr_0.slug}`, 3663 className: `h-input h-input--block ${errors[attr_0.slug] ? "error" : ""}`, 3664 rows: 3, 3665 value: customAttrValues[attr_0.slug] ?? "", 3666 onChange: (e_16) => handleCustomAttrChange(attr_0.slug, e_16.target.value), 3667 "aria-invalid": errors[attr_0.slug] ? true : void 0, 3668 "aria-describedby": errors[attr_0.slug] ? `create-lead-custom-${attr_0.slug}-error` : void 0 3669 }) : /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Input, { 3670 type: "text", 3671 id: `create-lead-custom-${attr_0.slug}`, 3672 fullWidth: true, 3673 value: customAttrValues[attr_0.slug] ?? "", 3674 onChange: (e_17) => handleCustomAttrChange(attr_0.slug, e_17.target.value), 3675 className: errors[attr_0.slug] ? "error" : "", 3676 "aria-invalid": errors[attr_0.slug] ? true : void 0, 3677 "aria-describedby": errors[attr_0.slug] ? `create-lead-custom-${attr_0.slug}-error` : void 0 3678 }), 3679 /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(FieldError, { 3680 id: `create-lead-custom-${attr_0.slug}-error`, 3681 message: errors[attr_0.slug] 3682 }) 3683 ] 3684 }) 3685 }, attr_0.slug)) 3686 })] }), 3687 /* @__PURE__ */ (0, import_jsx_runtime$15.jsxs)("footer", { 3688 className: "lead-edit__actions", 3689 children: [/* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Button, { 3690 variant: "primary", 3691 type: "submit", 3692 disabled: submitting, 3693 children: t$13("js.leads.page.create_lead") 3694 }), /* @__PURE__ */ (0, import_jsx_runtime$15.jsx)(Button, { 3695 type: "button", 3696 onClick: handleClose, 3697 children: t$13("js.leads.page.cancel") 3698 })] 3699 }) 3700 ] 3701 })] 3702 }) 3703 })] 3704 }) 3705 }); 3706} 3707var import_react$15, import_jsx_runtime$15, t$13; 3708function init_CreateLeadSheet() { 3709 return (init_CreateLeadSheet = __esmMin((() => { 3710 import_react$15 = require_react(); 3711 init_sheet(); 3712 init_button(); 3713 init_icon(); 3714 init_input(); 3715 init_label(); 3716 init_routes(); 3717 init_utils(); 3718 init_formErrors(); 3719 import_jsx_runtime$15 = require_jsx_runtime(); 3720 t$13 = (key) => window.i18n.t(key); 3721 })))(); 3722} 3723//#endregion 3724//#region app/frontend/pages/Leads/BulkActionsToolbar.tsx 3725function BulkActionsToolbar(t0) { 3726 const $ = (0, import_compiler_runtime$2.c)(101); 3727 const { selectedCount, totalCount, pageCount, campaignsAccess, permissions, leadsList, leadsLists, syncableApps, onClearSelection, onSelectAll, onSelectPage, onSelectCount, onOpenModal, buildSelectionParams, buildSelectedLeadsSummary } = t0; 3728 let t1; 3729 if ($[0] !== buildSelectionParams) { 3730 t1 = () => { 3731 const params = buildSelectionParams(); 3732 const form = document.createElement("form"); 3733 form.method = "POST"; 3734 form.action = leads_export_path(); 3735 form.style.display = "none"; 3736 const csrfInput = document.createElement("input"); 3737 csrfInput.type = "hidden"; 3738 csrfInput.name = "authenticity_token"; 3739 csrfInput.value = getCsrfToken(); 3740 form.appendChild(csrfInput); 3741 for (const [key, value] of params.entries()) { 3742 const input = document.createElement("input"); 3743 input.type = "hidden"; 3744 input.name = key; 3745 input.value = value; 3746 form.appendChild(input); 3747 } 3748 document.body.appendChild(form); 3749 form.submit(); 3750 document.body.removeChild(form); 3751 }; 3752 $[0] = buildSelectionParams; 3753 $[1] = t1; 3754 } else t1 = $[1]; 3755 const handleExport = t1; 3756 let t2; 3757 if ($[2] !== buildSelectionParams) { 3758 t2 = async () => { 3759 const selectionParams = buildSelectionParams(); 3760 const formData = new URLSearchParams(); 3761 formData.append("filters_type", "leads"); 3762 formData.append("action_source", "leads list page"); 3763 for (const [key_0, value_0] of selectionParams.entries()) formData.append(key_0, value_0); 3764 const response = await fetch(sequences_path(), { 3765 method: "POST", 3766 headers: { 3767 "X-CSRF-Token": getCsrfToken(), 3768 Accept: "text/html" 3769 }, 3770 body: formData, 3771 redirect: "follow" 3772 }); 3773 if (response.redirected) window.location.href = response.url; 3774 }; 3775 $[2] = buildSelectionParams; 3776 $[3] = t2; 3777 } else t2 = $[3]; 3778 const handleCreateSequence = t2; 3779 let items; 3780 if ($[4] !== buildSelectedLeadsSummary || $[5] !== buildSelectionParams || $[6] !== campaignsAccess || $[7] !== handleCreateSequence || $[8] !== handleExport || $[9] !== leadsList.id || $[10] !== leadsList.type || $[11] !== leadsLists || $[12] !== onOpenModal || $[13] !== permissions || $[14] !== syncableApps[0] || $[15] !== syncableApps.length) { 3781 items = []; 3782 const permissionsLoaded = permissions !== "loading" && permissions !== "unavailable"; 3783 const canEdit = permissionsLoaded && permissions.editable; 3784 const canFindEmails = permissionsLoaded && permissions.findEmails; 3785 const t3 = `js.leads.page.bulk_actions.${permissions === "loading" ? "checking_permissions" : permissions === "unavailable" ? "permissions_unavailable" : "permission_denied"}`; 3786 let t4; 3787 if ($[17] !== t3) { 3788 t4 = t$12(t3); 3789 $[17] = t3; 3790 $[18] = t4; 3791 } else t4 = $[18]; 3792 const permissionTooltip = t4; 3793 const t5 = !canEdit; 3794 const t6 = canEdit ? void 0 : permissionTooltip; 3795 let t7; 3796 if ($[19] !== t5 || $[20] !== t6) { 3797 t7 = { 3798 disabled: t5, 3799 tooltip: t6 3800 }; 3801 $[19] = t5; 3802 $[20] = t6; 3803 $[21] = t7; 3804 } else t7 = $[21]; 3805 const mutationGate = t7; 3806 let t8; 3807 if ($[22] === Symbol.for("react.memo_cache_sentinel")) { 3808 t8 = t$12("js.leads.page.bulk_actions.find_similar_leads"); 3809 $[22] = t8; 3810 } else t8 = $[22]; 3811 let t9; 3812 if ($[23] !== buildSelectedLeadsSummary || $[24] !== buildSelectionParams || $[25] !== leadsList.id || $[26] !== leadsList.type) { 3813 t9 = { 3814 label: t8, 3815 icon: "sparkle", 3816 onClick: () => { 3817 const params_0 = buildSelectionParams(); 3818 const leadIds = params_0.getAll("lead_ids[]").map(Number).slice(0, 1e3); 3819 const filters = {}; 3820 for (const [key_1, value_1] of params_0.entries()) if (key_1 !== "lead_ids[]" && key_1 !== "select_all") filters[key_1] = value_1; 3821 const sourceLeads = buildSelectedLeadsSummary(); 3822 const originatingLeadsListId = leadsList.type !== "virtual" ? leadsList.id : null; 3823 document.dispatchEvent(new CustomEvent("open-lookalikes-sheet", { detail: { 3824 leadIds, 3825 filters, 3826 sourceLeads, 3827 originatingLeadsListId 3828 } })); 3829 } 3830 }; 3831 $[23] = buildSelectedLeadsSummary; 3832 $[24] = buildSelectionParams; 3833 $[25] = leadsList.id; 3834 $[26] = leadsList.type; 3835 $[27] = t9; 3836 } else t9 = $[27]; 3837 items.push(t9); 3838 let t10; 3839 if ($[28] === Symbol.for("react.memo_cache_sentinel")) { 3840 t10 = t$12("js.leads.page.bulk_actions.find_email_addresses"); 3841 $[28] = t10; 3842 } else t10 = $[28]; 3843 let t11; 3844 if ($[29] !== onOpenModal) { 3845 t11 = () => onOpenModal("findEmails"); 3846 $[29] = onOpenModal; 3847 $[30] = t11; 3848 } else t11 = $[30]; 3849 const t12 = !canFindEmails; 3850 let t13; 3851 if ($[31] !== canFindEmails || $[32] !== mutationGate) { 3852 t13 = canFindEmails ? void 0 : mutationGate.tooltip ?? t$12("js.leads.page.bulk_actions.list_permission_denied"); 3853 $[31] = canFindEmails; 3854 $[32] = mutationGate; 3855 $[33] = t13; 3856 } else t13 = $[33]; 3857 let t14; 3858 if ($[34] !== t11 || $[35] !== t12 || $[36] !== t13) { 3859 t14 = { 3860 label: t10, 3861 icon: "magnifying-glass", 3862 onClick: t11, 3863 disabled: t12, 3864 tooltip: t13 3865 }; 3866 $[34] = t11; 3867 $[35] = t12; 3868 $[36] = t13; 3869 $[37] = t14; 3870 } else t14 = $[37]; 3871 let t15; 3872 if ($[38] === Symbol.for("react.memo_cache_sentinel")) { 3873 t15 = t$12("js.leads.page.bulk_actions.verify_leads"); 3874 $[38] = t15; 3875 } else t15 = $[38]; 3876 let t16; 3877 if ($[39] !== onOpenModal) { 3878 t16 = { 3879 label: t15, 3880 icon: "shield-check", 3881 onClick: () => onOpenModal("verifyLeads") 3882 }; 3883 $[39] = onOpenModal; 3884 $[40] = t16; 3885 } else t16 = $[40]; 3886 items.push(t14, t16); 3887 if (campaignsAccess) { 3888 let t17; 3889 if ($[41] === Symbol.for("react.memo_cache_sentinel")) { 3890 t17 = t$12("js.leads.page.bulk_actions.add_to_sequence"); 3891 $[41] = t17; 3892 } else t17 = $[41]; 3893 let t18; 3894 if ($[42] !== onOpenModal) { 3895 t18 = { 3896 label: t17, 3897 icon: "envelopes", 3898 onClick: () => onOpenModal("addToSequence") 3899 }; 3900 $[42] = onOpenModal; 3901 $[43] = t18; 3902 } else t18 = $[43]; 3903 let t19; 3904 if ($[44] === Symbol.for("react.memo_cache_sentinel")) { 3905 t19 = t$12("js.leads.page.bulk_actions.create_new_sequence"); 3906 $[44] = t19; 3907 } else t19 = $[44]; 3908 let t20; 3909 if ($[45] !== handleCreateSequence) { 3910 t20 = { 3911 label: t19, 3912 icon: "envelope", 3913 onClick: handleCreateSequence 3914 }; 3915 $[45] = handleCreateSequence; 3916 $[46] = t20; 3917 } else t20 = $[46]; 3918 items.push(t18, t20); 3919 } 3920 let t17; 3921 if ($[47] === Symbol.for("react.memo_cache_sentinel")) { 3922 t17 = t$12("js.leads.page.bulk_actions.export"); 3923 $[47] = t17; 3924 } else t17 = $[47]; 3925 let t18; 3926 if ($[48] !== handleExport) { 3927 t18 = { 3928 label: t17, 3929 icon: "download", 3930 onClick: handleExport 3931 }; 3932 $[48] = handleExport; 3933 $[49] = t18; 3934 } else t18 = $[49]; 3935 let t19; 3936 if ($[50] === Symbol.for("react.memo_cache_sentinel")) { 3937 t19 = t$12("js.leads.page.bulk_actions.add_to_list"); 3938 $[50] = t19; 3939 } else t19 = $[50]; 3940 let t20; 3941 if ($[51] !== onOpenModal) { 3942 t20 = () => onOpenModal("addToList"); 3943 $[51] = onOpenModal; 3944 $[52] = t20; 3945 } else t20 = $[52]; 3946 let t21; 3947 if ($[53] !== mutationGate || $[54] !== t20) { 3948 t21 = { 3949 label: t19, 3950 icon: "copy", 3951 onClick: t20, 3952 ...mutationGate 3953 }; 3954 $[53] = mutationGate; 3955 $[54] = t20; 3956 $[55] = t21; 3957 } else t21 = $[55]; 3958 let t22; 3959 if ($[56] === Symbol.for("react.memo_cache_sentinel")) { 3960 t22 = t$12("js.leads.page.bulk_actions.save_as_list"); 3961 $[56] = t22; 3962 } else t22 = $[56]; 3963 let t23; 3964 if ($[57] !== onOpenModal) { 3965 t23 = () => onOpenModal("saveAsList"); 3966 $[57] = onOpenModal; 3967 $[58] = t23; 3968 } else t23 = $[58]; 3969 let t24; 3970 if ($[59] !== mutationGate || $[60] !== t23) { 3971 t24 = { 3972 label: t22, 3973 icon: "file-circle-plus", 3974 onClick: t23, 3975 ...mutationGate 3976 }; 3977 $[59] = mutationGate; 3978 $[60] = t23; 3979 $[61] = t24; 3980 } else t24 = $[61]; 3981 items.push(t18, t21, t24); 3982 if (syncableApps.length > 0) { 3983 let t25; 3984 if ($[62] !== syncableApps[0] || $[63] !== syncableApps.length) { 3985 t25 = syncableApps.length === 1 ? window.i18n.t("js.leads.page.bulk_actions.sync_to_crm_provider", { provider: syncableApps[0].providerName }) : t$12("js.leads.page.bulk_actions.sync_to_crm"); 3986 $[62] = syncableApps[0]; 3987 $[63] = syncableApps.length; 3988 $[64] = t25; 3989 } else t25 = $[64]; 3990 const label = t25; 3991 let t26; 3992 if ($[65] !== onOpenModal) { 3993 t26 = () => onOpenModal("syncToCrm"); 3994 $[65] = onOpenModal; 3995 $[66] = t26; 3996 } else t26 = $[66]; 3997 let t27; 3998 if ($[67] !== label || $[68] !== t26) { 3999 t27 = { 4000 label, 4001 icon: "arrows-rotate", 4002 onClick: t26 4003 }; 4004 $[67] = label; 4005 $[68] = t26; 4006 $[69] = t27; 4007 } else t27 = $[69]; 4008 items.push(t27); 4009 } 4010 if (leadsList.type === "static") { 4011 const canMove = countOtherStaticLists(leadsLists, leadsList.id) > 0; 4012 let t25; 4013 if ($[70] === Symbol.for("react.memo_cache_sentinel")) { 4014 t25 = t$12("js.leads.page.bulk_actions.move_to_list"); 4015 $[70] = t25; 4016 } else t25 = $[70]; 4017 let t26; 4018 if ($[71] !== onOpenModal) { 4019 t26 = () => onOpenModal("moveToList"); 4020 $[71] = onOpenModal; 4021 $[72] = t26; 4022 } else t26 = $[72]; 4023 const t27 = mutationGate.disabled || !canMove; 4024 let t28; 4025 if ($[73] !== canMove || $[74] !== mutationGate.tooltip) { 4026 t28 = mutationGate.tooltip ?? (canMove ? void 0 : t$12("js.leads.page.bulk_actions.move_to_list_disabled_tooltip")); 4027 $[73] = canMove; 4028 $[74] = mutationGate.tooltip; 4029 $[75] = t28; 4030 } else t28 = $[75]; 4031 let t29; 4032 if ($[76] !== t26 || $[77] !== t27 || $[78] !== t28) { 4033 t29 = { 4034 label: t25, 4035 icon: "share", 4036 onClick: t26, 4037 disabled: t27, 4038 tooltip: t28 4039 }; 4040 $[76] = t26; 4041 $[77] = t27; 4042 $[78] = t28; 4043 $[79] = t29; 4044 } else t29 = $[79]; 4045 items.push(t29); 4046 let t30; 4047 if ($[80] === Symbol.for("react.memo_cache_sentinel")) { 4048 t30 = t$12("js.leads.page.bulk_actions.remove_from_list"); 4049 $[80] = t30; 4050 } else t30 = $[80]; 4051 let t31; 4052 if ($[81] !== onOpenModal) { 4053 t31 = () => onOpenModal("removeFromList"); 4054 $[81] = onOpenModal; 4055 $[82] = t31; 4056 } else t31 = $[82]; 4057 let t32; 4058 if ($[83] !== mutationGate || $[84] !== t31) { 4059 t32 = { 4060 label: t30, 4061 icon: "circle-minus", 4062 onClick: t31, 4063 ...mutationGate 4064 }; 4065 $[83] = mutationGate; 4066 $[84] = t31; 4067 $[85] = t32; 4068 } else t32 = $[85]; 4069 items.push(t32); 4070 } 4071 let t25; 4072 if ($[86] === Symbol.for("react.memo_cache_sentinel")) { 4073 t25 = t$12("js.leads.page.bulk_actions.delete"); 4074 $[86] = t25; 4075 } else t25 = $[86]; 4076 let t26; 4077 if ($[87] !== onOpenModal) { 4078 t26 = () => onOpenModal("deleteLeads"); 4079 $[87] = onOpenModal; 4080 $[88] = t26; 4081 } else t26 = $[88]; 4082 let t27; 4083 if ($[89] !== mutationGate || $[90] !== t26) { 4084 t27 = { 4085 label: t25, 4086 icon: "trash-alt", 4087 onClick: t26, 4088 variant: "danger", 4089 ...mutationGate 4090 }; 4091 $[89] = mutationGate; 4092 $[90] = t26; 4093 $[91] = t27; 4094 } else t27 = $[91]; 4095 items.push(t27); 4096 $[4] = buildSelectedLeadsSummary; 4097 $[5] = buildSelectionParams; 4098 $[6] = campaignsAccess; 4099 $[7] = handleCreateSequence; 4100 $[8] = handleExport; 4101 $[9] = leadsList.id; 4102 $[10] = leadsList.type; 4103 $[11] = leadsLists; 4104 $[12] = onOpenModal; 4105 $[13] = permissions; 4106 $[14] = syncableApps[0]; 4107 $[15] = syncableApps.length; 4108 $[16] = items; 4109 } else items = $[16]; 4110 const actions = items; 4111 let t3; 4112 if ($[92] !== actions || $[93] !== onClearSelection || $[94] !== onSelectAll || $[95] !== onSelectCount || $[96] !== onSelectPage || $[97] !== pageCount || $[98] !== selectedCount || $[99] !== totalCount) { 4113 t3 = /* @__PURE__ */ (0, import_jsx_runtime$14.jsx)(DataTableBulkActionsBar, { 4114 totalCount, 4115 pageCount, 4116 selectedCount, 4117 onClearSelection, 4118 onSelectAll, 4119 onSelectPage, 4120 onSelectCount, 4121 actions 4122 }); 4123 $[92] = actions;
4124 $[93] = onClearSelection; 4125 $[94] = onSelectAll; 4126 $[95] = onSelectCount; 4127 $[96] = onSelectPage; 4128 $[97] = pageCount; 4129 $[98] = selectedCount; 4130 $[99] = totalCount; 4131 $[100] = t3; 4132 } else t3 = $[100]; 4133 return t3; 4134} 4135var import_compiler_runtime$2, import_jsx_runtime$14, t$12; 4136function init_BulkActionsToolbar() { 4137 return (init_BulkActionsToolbar = __esmMin((() => { 4138 import_compiler_runtime$2 = require_compiler_runtime(); 4139 init_routes(); 4140 init_utils(); 4141 init_data_table_bulk_actions_bar(); 4142 import_jsx_runtime$14 = require_jsx_runtime(); 4143 t$12 = (key) => window.i18n.t(key); 4144 })))(); 4145} 4146//#endregion 4147//#region app/frontend/pages/Leads/useSelectionPermissions.ts 4148function useSelectionPermissions(params, leads) { 4149 const request = (0, import_react$14.useMemo)(() => ({ 4150 params, 4151 leads 4152 }), [params, leads]); 4153 const loadedPermissions = (0, import_react$14.useMemo)(() => { 4154 const ids = new Set(new URLSearchParams(request.params).getAll("lead_ids[]").map(Number)); 4155 if (ids.size === 0) return null; 4156 const selected = request.leads.filter((lead) => ids.has(lead.id)); 4157 if (selected.some((lead_0) => !lead_0.editable)) return { 4158 editable: false, 4159 findEmails: false 4160 }; 4161 return selected.length === ids.size ? { 4162 editable: true, 4163 findEmails: true 4164 } : null; 4165 }, [request]); 4166 const [result, setResult] = (0, import_react$14.useState)(null); 4167 (0, import_react$14.useEffect)(() => { 4168 if (!request.params || loadedPermissions) return; 4169 const controller = new AbortController(); 4170 async function checkPermissions() { 4171 let permissions = "unavailable"; 4172 try { 4173 const response = await fetch(leads_selection_permissions_path(), { 4174 method: "POST", 4175 headers: { 4176 "X-CSRF-Token": getCsrfToken(), 4177 Accept: "application/json" 4178 }, 4179 body: new URLSearchParams(request.params), 4180 signal: controller.signal 4181 }); 4182 if (response.ok) { 4183 const data = await response.json(); 4184 if (isObject(data) && isBoolean(data.editable) && isBoolean(data.findEmails)) permissions = { 4185 editable: data.editable, 4186 findEmails: data.findEmails 4187 }; 4188 } 4189 } catch { 4190 permissions = "unavailable"; 4191 } 4192 if (!controller.signal.aborted) setResult({ 4193 request, 4194 permissions 4195 }); 4196 } 4197 checkPermissions(); 4198 return () => controller.abort(); 4199 }, [request, loadedPermissions]); 4200 return loadedPermissions ?? (result?.request === request ? result.permissions : "loading"); 4201} 4202var import_react$14; 4203function init_useSelectionPermissions() { 4204 return (init_useSelectionPermissions = __esmMin((() => { 4205 import_react$14 = require_react(); 4206 init_routes(); 4207 init_utils(); 4208 })))(); 4209} 4210//#endregion 4211//#region app/frontend/pages/Leads/modals/DeleteLeadsModal.tsx 4212function DeleteLeadsModal({ open, onClose, onDeleted, selectedCount, selectionParams }) { 4213 const [submitting, setSubmitting] = (0, import_react$13.useState)(false); 4214 const [error, setError] = (0, import_react$13.useState)(null); 4215 const handleClose = (0, import_react$13.useCallback)(() => { 4216 setSubmitting(false); 4217 setError(null); 4218 onClose(); 4219 }, [onClose]); 4220 const { dialogRef, close, createAbortController } = useDialog({ 4221 isOpen: open, 4222 onClose: handleClose 4223 }); 4224 (0, import_react$13.useEffect)(() => { 4225 if (open) setError(null); 4226 }, [open]); 4227 async function handleSubmit(e) { 4228 e.preventDefault(); 4229 if (submitting || selectedCount === 0) return; 4230 setSubmitting(true); 4231 setError(null); 4232 const controller = createAbortController(); 4233 const body = new URLSearchParams(selectionParams); 4234 body.append("_method", "delete"); 4235 try { 4236 const response = await fetch(leads_bulk_path(), { 4237 method: "POST", 4238 headers: { 4239 "X-CSRF-Token": getCsrfToken(), 4240 Accept: "application/json" 4241 }, 4242 body, 4243 signal: controller.signal 4244 }); 4245 if (controller.signal.aborted) return; 4246 if (!response.ok) { 4247 const data = await response.json().catch(() => ({})); 4248 setError(data.message ?? t$11("js.leads.page.bulk_actions.delete_submit_error")); 4249 setSubmitting(false); 4250 return; 4251 } 4252 const data_0 = await response.json().catch(() => null); 4253 if (controller.signal.aborted) return; 4254 if (!data_0) { 4255 setError(t$11("js.leads.page.bulk_actions.delete_submit_error")); 4256 setSubmitting(false); 4257 return; 4258 } 4259 close(); 4260 if (data_0.operation) onDeleted({ 4261 async: true, 4262 operationId: data_0.operation.id 4263 }); 4264 else onDeleted({ 4265 async: false, 4266 deletedCount: data_0.deleted_count, 4267 totalCount: data_0.total_count 4268 }); 4269 } catch (err) { 4270 if (err?.name === "AbortError") return; 4271 setError(t$11("js.leads.page.bulk_actions.delete_submit_error")); 4272 setSubmitting(false); 4273 } 4274 } 4275 return /* @__PURE__ */ (0, import_jsx_runtime$13.jsx)(Dialog, { 4276 ref: dialogRef, 4277 children: /* @__PURE__ */ (0, import_jsx_runtime$13.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$13.jsxs)("form", { 4278 onSubmit: handleSubmit, 4279 children: [
4280 /* @__PURE__ */ (0, import_jsx_runtime$13.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime$13.jsx)(DialogTitle, { children: t$11("js.leads.page.bulk_actions.delete_title") }), /* @__PURE__ */ (0, import_jsx_runtime$13.jsx)(DialogCloseButton, { 4281 type: "button", 4282 onClick: close 4283 })] }), 4284 /* @__PURE__ */ (0, import_jsx_runtime$13.jsxs)(DialogBody, { children: [/* @__PURE__ */ (0, import_jsx_runtime$13.jsx)("p", { dangerouslySetInnerHTML: { __html: t$11("js.leads.page.bulk_actions.delete_body", { count: CurrencyHelper.numberWithDelimiter(selectedCount) }) } }), error && /* @__PURE__ */ (0, import_jsx_runtime$13.jsxs)(Alert, { 4285 variant: "destructive", 4286 size: "small", 4287 className: "mt-3", 4288 "data-testid": "submit-error-alert", 4289 children: [/* @__PURE__ */ (0, import_jsx_runtime$13.jsx)(AlertIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime$13.jsx)(Icon, { icon: "circle-exclamation" }) }), /* @__PURE__ */ (0, import_jsx_runtime$13.jsx)(AlertContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$13.jsx)(AlertDescription, { children: error }) })] 4290 })] }),
4291 /* @__PURE__ */ (0, import_jsx_runtime$13.jsxs)(DialogFooter, { children: [/* @__PURE__ */ (0, import_jsx_runtime$13.jsx)(Button, { 4292 type: "button", 4293 onClick: close, 4294 children: t$11("js.leads.page.cancel") 4295 }), /* @__PURE__ */ (0, import_jsx_runtime$13.jsx)(Button, { 4296 type: "submit", 4297 variant: "danger", 4298 disabled: submitting || selectedCount === 0, 4299 "data-loading": "none", 4300 children: t$11("js.leads.page.bulk_actions.delete_confirm") 4301 })] }) 4302 ] 4303 }) }) 4304 }); 4305} 4306var import_react$13, import_jsx_runtime$13, t$11; 4307function init_DeleteLeadsModal() { 4308 return (init_DeleteLeadsModal = __esmMin((() => { 4309 import_react$13 = require_react(); 4310 init_routes(); 4311 init_utils(); 4312 init_dialog(); 4313 init_button(); 4314 init_alert(); 4315 init_icon(); 4316 init_useDialog(); 4317 init_currency_helper(); 4318 import_jsx_runtime$13 = require_jsx_runtime(); 4319 t$11 = (key, options) => window.i18n.t(key, options); 4320 })))(); 4321} 4322//#endregion 4323//#region app/frontend/pages/Leads/modals/DeleteLeadModal.tsx 4324function DeleteLeadModal({ leadId, open, onClose, onDeleted }) { 4325 const dialogRef = (0, import_react$12.useRef)(null); 4326 const [submitting, setSubmitting] = (0, import_react$12.useState)(false); 4327 const handleClose = (0, import_react$12.useCallback)(() => { 4328 setSubmitting(false); 4329 onClose(); 4330 }, [onClose]); 4331 (0, import_react$12.useEffect)(() => { 4332 const dialog = dialogRef.current; 4333 if (!dialog) return; 4334 if (open) { 4335 if (!dialog.open) dialog.showModal(); 4336 } else if (dialog.open) dialog.close(); 4337 }, [open]); 4338 (0, import_react$12.useEffect)(() => { 4339 const dialog_0 = dialogRef.current; 4340 if (!dialog_0) return; 4341 const handleCancel = () => handleClose(); 4342 dialog_0.addEventListener("close", handleCancel); 4343 return () => dialog_0.removeEventListener("close", handleCancel); 4344 }, [handleClose]); 4345 async function handleSubmit(e) { 4346 e.preventDefault(); 4347 if (submitting || leadId === null) return; 4348 setSubmitting(true); 4349 try { 4350 if (!(await fetch(lead_path(leadId), { 4351 method: "DELETE", 4352 headers: { 4353 "X-CSRF-Token": getCsrfToken(), 4354 Accept: "application/json" 4355 } 4356 })).ok) throw new Error("Delete failed"); 4357 handleClose(); 4358 onDeleted(leadId); 4359 } catch { 4360 setSubmitting(false); 4361 } 4362 }
4363 return /* @__PURE__ */ (0, import_jsx_runtime$12.jsx)(Dialog, { 4364 ref: dialogRef, 4365 children: /* @__PURE__ */ (0, import_jsx_runtime$12.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$12.jsxs)("form", { 4366 onSubmit: handleSubmit, 4367 children: [ 4368 /* @__PURE__ */ (0, import_jsx_runtime$12.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime$12.jsx)(DialogTitle, { children: t$10("js.leads.page.delete") }), /* @__PURE__ */ (0, import_jsx_runtime$12.jsx)(DialogCloseButton, { 4369 type: "button", 4370 onClick: handleClose 4371 })] }), 4372 /* @__PURE__ */ (0, import_jsx_runtime$12.jsx)(DialogBody, { children: /* @__PURE__ */ (0, import_jsx_runtime$12.jsx)("p", { children: t$10("js.leads.page.sidepanel.delete_confirm") }) }), 4373 /* @__PURE__ */ (0, import_jsx_runtime$12.jsxs)(DialogFooter, { children: [/* @__PURE__ */ (0, import_jsx_runtime$12.jsx)(Button, { 4374 type: "button", 4375 onClick: handleClose, 4376 children: t$10("js.leads.page.cancel") 4377 }), /* @__PURE__ */ (0, import_jsx_runtime$12.
4377jsx)(Button, { 4378 type: "submit", 4379 variant: "danger", 4380 disabled: submitting, 4381 "data-loading": "none", 4382 children: t$10("js.leads.page.sidepanel.delete") 4383 })] }) 4384 ] 4385 }) }) 4386 }); 4387} 4388var import_react$12, import_jsx_runtime$12, t$10; 4389function init_DeleteLeadModal() { 4390 return (init_DeleteLeadModal = __esmMin((() => { 4391 import_react$12 = require_react(); 4392 init_routes(); 4393 init_utils(); 4394 init_dialog(); 4395 init_button(); 4396 import_jsx_runtime$12 = require_jsx_runtime(); 4397 t$10 = (key) => window.i18n.t(key); 4398 })))(); 4399} 4400//#endregion 4401//#region app/frontend/pages/Leads/modals/MoveToListModal.tsx 4402function MoveToListModal({ open, onClose, onSuccess, selectedCount, selectionParams, leadsLists, currentListId }) { 4403 const [listId, setListId] = (0, import_react$11.useState)(""); 4404 const [submitting, setSubmitting] = (0, import_react$11.useState)(false); 4405 const [error, setError] = (0, import_react$11.useState)(null); 4406 const destinationLists = leadsLists.filter((l) => l.type === "static" && l.id !== currentListId); 4407 const handleClose = (0, import_react$11.useCallback)(() => { 4408 setListId(""); 4409 setSubmitting(false); 4410 setError(null); 4411 onClose(); 4412 }, [onClose]); 4413 const { dialogRef, close, createAbortController } = useDialog({ 4414 isOpen: open, 4415 onClose: handleClose 4416 }); 4417 (0, import_react$11.useEffect)(() => { 4418 if (open) setError(null); 4419 }, [open]); 4420 async function handleSubmit(e) { 4421 e.preventDefault(); 4422 if (!listId || submitting) return; 4423 setSubmitting(true); 4424 setError(null); 4425 const controller = createAbortController(); 4426 const body = new URLSearchParams(selectionParams); 4427 body.append("_method", "put"); 4428 body.append("to_leads_list_id", listId); 4429 body.append("from_leads_list_id", String(currentListId)); 4430 body.append("remove_from_list", "true"); 4431 try { 4432 const response = await fetch(leads_bulk_path(), { 4433 method: "POST", 4434 headers: { 4435 "X-CSRF-Token": getCsrfToken(), 4436 Accept: "application/json" 4437 }, 4438 body, 4439 signal: controller.signal 4440 }); 4441 if (controller.signal.aborted) return; 4442 if (!response.ok) { 4443 const data = await response.json().catch(() => ({})); 4444 setError(data.message ?? t$9("js.leads.page.bulk_actions.move_to_list_submit_error")); 4445 setSubmitting(false); 4446 return; 4447 } 4448 const destinationListId = Number(listId); 4449 close(); 4450 onSuccess?.(destinationListId); 4451 router.reload(); 4452 } catch (err) { 4453 if (err?.name === "AbortError") return; 4454 setError(t$9("js.leads.page.bulk_actions.move_to_list_submit_error")); 4455 setSubmitting(false); 4456 } 4457 } 4458 return /* @__PURE__ */ (0, import_jsx_runtime$11.jsx)(Dialog, { 4459 ref: dialogRef, 4460 children: /* @__PURE__ */ (0, import_jsx_runtime$11.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$11.jsxs)("form", { 4461 onSubmit: handleSubmit, 4462 children: [
4463 /* @__PURE__ */ (0, import_jsx_runtime$11.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime$11.jsx)(DialogTitle, { children: t$9("js.leads.page.bulk_actions.move_to_list_title") }), /* @__PURE__ */ (0, import_jsx_runtime$11.jsx)(DialogCloseButton, { 4464 type: "button", 4465 onClick: close 4466 })] }), 4467 /* @__PURE__ */ (0, import_jsx_runtime$11.jsxs)(DialogBody, { children: [ 4468 /* @__PURE__ */ (0, import_jsx_runtime$11.jsx)("p", { children: t$9("js.leads.page.bulk_actions.move_to_list_body", { count: CurrencyHelper.numberWithDelimiter(selectedCount) }) }), 4469 /* @__PURE__ */ (0, import_jsx_runtime$11.jsxs)("div", { 4470 className: "form-group mt-4", 4471 children: [/* @__PURE__ */ (0, import_jsx_runtime$11.jsx)(Label, { 4472 fullWidth: true, 4473 htmlFor: "move-to-list-select", 4474 children: t$9("js.leads.page.bulk_actions.move_to_list_label") 4475 }), /* @__PURE__ */ (0, import_jsx_runtime$11.jsxs)("select", { 4476 className: "h-select h-select--block", 4477 id: "move-to-list-select", 4478 value: listId, 4479 onChange: (e_0) => setListId(e_0.target.value), 4480 required: true, 4481 children: [/* @__PURE__ */ (0, import_jsx_runtime$11.jsx)("option", { 4482 value: "", 4483 disabled: true, 4484 children: t$9("js.leads.page.bulk_actions.select_list_placeholder") 4485 }), destinationLists.map((list) => /* @__PURE__ */ (0, import_jsx_runtime$11.jsx)("option", { 4486 value: list.id, 4487 children: list.name 4488 }, list.id))] 4489 })] 4490 }), 4491 error && /* @__PURE__ */ (0, import_jsx_runtime$11.jsxs)(Alert, { 4492 variant: "destructive", 4493 size: "small", 4494 className: "mt-3", 4495 "data-testid": "submit-error-alert", 4496 children: [/* @__PURE__ */ (0, import_jsx_runtime$11.jsx)(AlertIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime$11.jsx)(Icon, { icon: "circle-exclamation" }) }
4496), /* @__PURE__ */ (0, import_jsx_runtime$11.jsx)(AlertContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$11.jsx)(AlertDescription, { children: error }) })] 4497 }) 4498 ] }), 4499 /* @__PURE__ */ (0, import_jsx_runtime$11.jsxs)(DialogFooter, { children: [/* @__PURE__ */ (0, import_jsx_runtime$11.jsx)(Button, { 4500 type: "button", 4501 onClick: close, 4502 children: t$9("js.leads.page.cancel") 4503 }), /* @__PURE__ */ (0, import_jsx_runtime$11.jsx)(Button, { 4504 type: "submit", 4505 variant: "primary", 4506 disabled: !listId || submitting, 4507 "data-loading": "none", 4508 children: t$9("js.leads.page.bulk_actions.move_to_list_confirm") 4509 })] }) 4510 ] 4511 }) }) 4512 }); 4513} 4514var import_react$11, import_jsx_runtime$11, t$9; 4515function init_MoveToListModal() { 4516 return (init_MoveToListModal = __esmMin((() => { 4517 import_react$11 = require_react(); 4518 init_dist(); 4519 init_routes(); 4520 init_utils(); 4521 init_dialog(); 4522 init_button(); 4523 init_label(); 4524 init_alert(); 4525 init_icon(); 4526 init_useDialog(); 4527 init_currency_helper(); 4528 import_jsx_runtime$11 = require_jsx_runtime(); 4529 t$9 = (key, options) => window.i18n.t(key, options); 4530 })))(); 4531} 4532//#endregion 4533//#region app/frontend/pages/Leads/modals/RemoveFromListModal.tsx 4534function RemoveFromListModal({ open, onClose, onSuccess, selectedCount, selectionParams, currentListId }) { 4535 const [submitting, setSubmitting] = (0, import_react$10.useState)(false); 4536 const [error, setError] = (0, import_react$10.useState)(null); 4537 const handleClose = (0, import_react$10.useCallback)(() => { 4538 setSubmitting(false); 4539 setError(null); 4540 onClose(); 4541 }, [onClose]); 4542 const { dialogRef, close, createAbortController } = useDialog({ 4543 isOpen: open, 4544 onClose: handleClose 4545 }); 4546 (0, import_react$10.useEffect)(() => { 4547 if (open) setError(null); 4548 }, [open]); 4549 async function handleSubmit(e) { 4550 e.preventDefault(); 4551 if (submitting) return; 4552 setSubmitting(true); 4553 setError(null); 4554 const controller = createAbortController(); 4555 const body = new URLSearchParams(selectionParams); 4556 body.append("_method", "put"); 4557 body.append("remove_from_list", "true"); 4558 body.append("to_leads_list_id", "0"); 4559 body.append("from_leads_list_id", String(currentListId)); 4560 try { 4561 const response = await fetch(leads_bulk_path(), { 4562 method: "POST", 4563 headers: { 4564 "X-CSRF-Token": getCsrfToken(), 4565 Accept: "application/json" 4566 }, 4567 body, 4568 signal: controller.signal 4569 }); 4570 if (controller.signal.aborted) return; 4571 if (!response.ok) { 4572 const data = await response.json().catch(() => ({})); 4573 setError(data.message ?? t$8("js.leads.page.bulk_actions.remove_from_list_submit_error")); 4574 setSubmitting(false); 4575 return; 4576 } 4577 close(); 4578 onSuccess?.(); 4579 router.reload(); 4580 } catch (err) { 4581 if (err?.name === "AbortError") return; 4582 setError(t$8("js.leads.page.bulk_actions.remove_from_list_submit_error")); 4583 setSubmitting(false); 4584 } 4585 } 4586 return /* @__PURE__ */ (0, import_jsx_runtime$10.jsx)(Dialog, { 4587 ref: dialogRef, 4588 children: /* @__PURE__ */ (0, import_jsx_runtime$10.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$10.jsxs)("form", { 4589 onSubmit: handleSubmit, 4590 children: [
4591 /* @__PURE__ */ (0, import_jsx_runtime$10.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime$10.jsx)(DialogTitle, { children: t$8("js.leads.page.bulk_actions.remove_from_list_title") }), /* @__PURE__ */ (0, import_jsx_runtime$10.jsx)(DialogCloseButton, { 4592 type: "button", 4593 onClick: close 4594 })] }), 4595 /* @__PURE__ */ (0, import_jsx_runtime$10.jsxs)(DialogBody, { children: [/* @__PURE__ */ (0, import_jsx_runtime$10.jsx)("p", { children: t$8("js.leads.page.bulk_actions.remove_from_list_body", { count: CurrencyHelper.numberWithDelimiter(selectedCount) }) }), error && /* @__PURE__ */ (0, import_jsx_runtime$10.jsxs)(Alert, { 4596 variant: "destructive", 4597 size: "small", 4598 className: "mt-3", 4599 "data-testid": "submit-error-alert", 4600 children: [/* @__PURE__ */ (0, import_jsx_runtime$10.jsx)(AlertIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime$10.jsx)(Icon, { icon: "circle-exclamation" }) }), /* @__PURE__ */ (0, import_jsx_runtime$10.jsx)(AlertContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$10.jsx)(AlertDescription, { children: error }) })] 4601 })] }),
4602 /* @__PURE__ */ (0, import_jsx_runtime$10.jsxs)(DialogFooter, { children: [/* @__PURE__ */ (0, import_jsx_runtime$10.jsx)(Button, { 4603 type: "button", 4604 onClick: close, 4605 children: t$8("js.leads.page.cancel") 4606 }), /* @__PURE__ */ (0, import_jsx_runtime$10.jsx)(Button, { 4607 type: "submit", 4608 variant: "danger", 4609 disabled: submitting, 4610 "data-loading": "none", 4611 children: t$8("js.leads.page.bulk_actions.remove_from_list_confirm") 4612 })] }) 4613 ] 4614 }) }) 4615 }); 4616} 4617var import_react$10, import_jsx_runtime$10, t$8; 4618function init_RemoveFromListModal() { 4619 return (init_RemoveFromListModal = __esmMin((() => { 4620 import_react$10 = require_react(); 4621 init_dist(); 4622 init_routes(); 4623 init_utils(); 4624 init_dialog(); 4625 init_button(); 4626 init_alert(); 4627 init_icon(); 4628 init_useDialog(); 4629 init_currency_helper(); 4630 import_jsx_runtime$10 = require_jsx_runtime(); 4631 t$8 = (key, options) => window.i18n.t(key, options); 4632 })))(); 4633} 4634//#endregion 4635//#region app/frontend/pages/Leads/modals/SaveAsListModal.tsx 4636function SaveAsListModal({ open, onClose, selectedCount, selectionParams, folders }) { 4637 const dialogRef = (0, import_react$9.useRef)(null); 4638 const [name, setName] = (0, import_react$9.useState)(""); 4639 const [folderId, setFolderId] = (0, import_react$9.useState)(""); 4640 const [submitting, setSubmitting] = (0, import_react$9.useState)(false); 4641 const [error, setError] = (0, import_react$9.useState)(null); 4642 const [localFolders, setLocalFolders] = (0, import_react$9.useState)(folders); 4643 const handleClose = (0, import_react$9.useCallback)(() => { 4644 setName(""); 4645 setFolderId(""); 4646 setSubmitting(false); 4647 setError(null); 4648 onClose(); 4649 }, [onClose]); 4650 (0, import_react$9.useEffect)(() => { 4651 const dialog = dialogRef.current; 4652 if (!dialog) return; 4653 if (open) { 4654 if (!dialog.open) dialog.showModal(); 4655 } else if (dialog.open) dialog.close(); 4656 }, [open]); 4657 (0, import_react$9.useEffect)(() => { 4658 const dialog_0 = dialogRef.current; 4659 if (!dialog_0) return; 4660 const handleCancel = () => handleClose(); 4661 dialog_0.addEventListener("close", handleCancel); 4662 return () => dialog_0.removeEventListener("close", handleCancel); 4663 }, [handleClose]); 4664 async function handleSubmit(e) { 4665 e.preventDefault(); 4666 if (!name.trim() || submitting) return; 4667 setSubmitting(true); 4668 setError(null); 4669 const formData = new FormData(); 4670 formData.append("name", name.trim()); 4671 if (folderId) formData.append("leads_list_folder_id", folderId); 4672 for (const [key, value] of selectionParams.entries()) if (key === "select_all") formData.append(key, value); 4673 else if (key.endsWith("[]")) formData.append(`filters[${key.slice(0, -2)}][]`, value); 4674 else formData.append(`filters[${key}]`, value); 4675 try { 4676 const response = await fetch(leads_lists_path(), { 4677 method: "POST", 4678 headers: { 4679 "X-CSRF-Token": getCsrfToken(), 4680 Accept: "application/json" 4681 }, 4682 body: formData 4683 }); 4684 if (response.ok) { 4685 const data = await response.json(); 4686 const id = isObject(data) && isNumber(data.id) ? data.id : null; 4687 handleClose(); 4688 router.visit(id ? leads_path({ leads_list_id: id }) : leads_path()); 4689 } else { 4690 const fallback = t$7("js.leads.page.save_list.error");
4691 try { 4692 const data_0 = await response.json(); 4693 const serverError = isObject(data_0) && isString(data_0.error) ? data_0.error.trim() : ""; 4694 setError(serverError || fallback); 4695 } catch { 4696 setError(fallback); 4697 } 4698 setSubmitting(false); 4699 } 4700 } catch { 4701 setError(t$7("js.leads.page.save_list.error")); 4702 setSubmitting(false); 4703 } 4704 } 4705 return /* @__PURE__ */ (0, import_jsx_runtime$9.jsx)(Dialog, { 4706 ref: dialogRef, 4707 children: /* @__PURE__ */ (0, import_jsx_runtime$9.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$9.jsxs)("form", { 4708 onSubmit: handleSubmit, 4709 children: [ 4710 /* @__PURE__ */ (0, import_jsx_runtime$9.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime$9.jsx)(DialogTitle, { children: t$7("js.leads.page.bulk_actions.save_as_list_title", { count: CurrencyHelper.numberWithDelimiter(selectedCount) }) }), /* @__PURE__ */ (0, import_jsx_runtime$9.jsx)(DialogCloseButton, { 4711 type: "button", 4712 onClick: handleClose 4713 })] }), 4714 /* @__PURE__ */ (0, import_jsx_runtime$9.jsxs)(DialogBody, { children: [ 4715 /* @__PURE__ */ (0, import_jsx_runtime$9.jsxs)("div", { 4716 className: "form-group", 4717 children: [/* @__PURE__ */ (0, import_jsx_runtime$9.jsx)(Label, { 4718 htmlFor: "save-as-list-name", 4719 children: t$7("js.leads.page.bulk_actions.save_as_list_name") 4720 }), /* @__PURE__ */ (0, import_jsx_runtime$9.jsx)(Input, { 4721 fullWidth: true, 4722 type: "text", 4723 id: "save-as-list-name", 4724 required: true, 4725 autoFocus: true, 4726 value: name, 4727 onChange: (e_0) => setName(e_0.target.value) 4728 })] 4729 }), 4730 /* @__PURE__ */ (0, import_jsx_runtime$9.jsxs)("div", { 4731 className: "form-group", 4732 children: [/* @__PURE__ */ (0, import_jsx_runtime$9.jsx)(Label, { 4733 fullWidth: true, 4734 className: "mt-4", 4735 children: t$7("js.leads.page.bulk_actions.save_as_list_folder") 4736 }), /* @__PURE__ */ (0, import_jsx_runtime$9.jsx)(FolderSelect, { 4737 folders: localFolders, 4738 selectedFolderId: folderId, 4739 onSelect: setFolderId, 4740 onFolderCreated: (folder) => setLocalFolders((prev) => [...prev, folder]) 4741 })] 4742 }), 4743 error && /* @__PURE__ */ (0, import_jsx_runtime$9.jsx)("p", { 4744 className: "text-danger text-sm", 4745 role: "alert", 4746 children: error 4747 }) 4748 ] }),
4749 /* @__PURE__ */ (0, import_jsx_runtime$9.jsxs)(DialogFooter, { children: [/* @__PURE__ */ (0, import_jsx_runtime$9.jsx)(Button, { 4750 type: "button", 4751 onClick: handleClose, 4752 children: t$7("js.leads.page.cancel") 4753 }), /* @__PURE__ */ (0, import_jsx_runtime$9.jsx)(Button, { 4754 type: "submit", 4755 variant: "primary", 4756 disabled: !name.trim() || submitting, 4757 "data-loading": "none", 4758 children: t$7("js.leads.page.bulk_actions.save_as_list_confirm") 4759 })] }) 4760 ] 4761 }) }) 4762 }); 4763} 4764var import_react$9, import_jsx_runtime$9, t$7; 4765function init_SaveAsListModal() { 4766 return (init_SaveAsListModal = __esmMin((() => { 4767 import_react$9 = require_react(); 4768 init_dist(); 4769 init_routes(); 4770 init_utils(); 4771 init_dialog(); 4772 init_button(); 4773 init_label(); 4774 init_input(); 4775 init_FolderSelect(); 4776 init_currency_helper(); 4777 import_jsx_runtime$9 = require_jsx_runtime(); 4778 t$7 = (key, options) => window.i18n.t(key, options); 4779 })))(); 4780} 4781//#endregion 4782//#region app/frontend/pages/Leads/SaveFilteredListSidePanel.tsx 4783function SaveFilteredListSidePanel({ open, onClose, filters, query, leadsList, folders, sort, direction }) { 4784 const nameInputRef = (0, import_react$8.useRef)(null); 4785 const defaultToStatic = STATIC_ONLY_FILTER_KEYS.some((key) => key in filters); 4786 const [type, setType] = (0, import_react$8.useState)(defaultToStatic ? "static" : "dynamic"); 4787 const [name, setName] = (0, import_react$8.useState)(""); 4788 const [folderId, setFolderId] = (0, import_react$8.useState)(""); 4789 const [submitting, setSubmitting] = (0, import_react$8.useState)(false); 4790 const [error, setError] = (0, import_react$8.useState)(null); 4791 const [localFolders, setLocalFolders] = (0, import_react$8.useState)(folders); 4792 const handleClose = (0, import_react$8.useCallback)(() => { 4793 setName(""); 4794 setFolderId(""); 4795 setSubmitting(false); 4796 setError(null); 4797 onClose(); 4798 }, [onClose]); 4799 (0, import_react$8.useEffect)(() => { 4800 if (open) setType(defaultToStatic ? "static" : "dynamic"); 4801 }, [open, defaultToStatic]); 4802 (0, import_react$8.useEffect)(() => { 4803 if (open) { 4804 setName(""); 4805 setFolderId(""); 4806 setSubmitting(false); 4807 setError(null); 4808 } 4809 }, [open]); 4810 (0, import_react$8.useEffect)(() => { 4811 setLocalFolders(folders); 4812 }, [folders]); 4813 async function handleSubmit(e) { 4814 e.preventDefault(); 4815 if (!name.trim() || submitting) return; 4816 setSubmitting(true); 4817 setError(null); 4818 const formData = new FormData(); 4819 formData.append("name", name.trim()); 4820 formData.append("type", type); 4821 if (folderId) formData.append("leads_list_folder_id", folderId); 4822 for (const [key_0, value] of Object.entries(filters)) { 4823 if (!value || NON_FILTER_KEYS.has(key_0)) continue; 4824 formData.append(`filters[${key_0}]`, value); 4825 } 4826 if (type === "static" && filters.people_per_company) { 4827 formData.append("filters[people_per_company]", filters.people_per_company); 4828 if (sort) formData.append("filters[sort]", sort); 4829 if (direction) formData.append("filters[direction]", direction); 4830 } 4831 if (query) formData.append("filters[query]", query); 4832 if (leadsList.type !== "virtual") formData.append("filters[leads_list_id]", String(leadsList.id)); 4833 try { 4834 const response = await fetch(leads_lists_path(), { 4835 method: "POST", 4836 headers: { 4837 "X-CSRF-Token": getCsrfToken(), 4838 Accept: "application/json" 4839 }, 4840 body: formData 4841 }); 4842 if (response.ok) { 4843 const data = await response.json(); 4844 handleClose(); 4845 router.visit(leads_path({ leads_list_id: data.id })); 4846 } else { 4847 const fallback = t$6("js.leads.page.save_list.error");
4848 try { 4849 const data_0 = await response.json(); 4850 const serverError = isObject(data_0) && isString(data_0.error) ? data_0.error.trim() : ""; 4851 setError(serverError || fallback); 4852 } catch { 4853 setError(fallback); 4854 } 4855 setSubmitting(false); 4856 } 4857 } catch { 4858 setError(t$6("js.leads.page.save_list.error")); 4859 setSubmitting(false); 4860 } 4861 } 4862 return /* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(Sheet, { 4863 open, 4864 onOpenChange: (next) => { 4865 if (!next) handleClose(); 4866 }, 4867 children: /* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(SheetContent, { 4868 className: "p-0", 4869 onOpenAutoFocus: (event) => { 4870 event.preventDefault(); 4871 nameInputRef.current?.focus(); 4872 }, 4873 children: /* @__PURE__ */ (0, import_jsx_runtime$8.jsxs)("form", { 4874 onSubmit: handleSubmit, 4875 children: [ 4876 /* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(SheetHeader, { children: /* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(SheetTitle, { children: t$6("js.leads.page.save_list.title") }) }), 4877 /* @__PURE__ */ (0, import_jsx_runtime$8.jsxs)(SheetBody, { children: [ 4878 /* @__PURE__ */ (0, import_jsx_runtime$8.jsxs)("fieldset", { 4879 className: "h-fieldset form-group", 4880 children: [ 4881 /* @__PURE__ */ (0, import_jsx_runtime$8.jsx)("legend", { 4882 className: "h-label mb-2", 4883 children: t$6("js.leads.page.save_list.type_label") 4884 }), 4885 /* @__PURE__ */ (0, import_jsx_runtime$8.jsxs)(RadioGroup, { 4886 role: "radiogroup", 4887 "aria-label": t$6("js.leads.page.save_list.type_label"), 4888 children: [/* @__PURE__ */ (0, import_jsx_runtime$8.jsxs)(RadioGroupItem, { 4889 className: "d-flex align-items-center gap-2 mb-1", 4890 children: [/* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(Radio, { 4891 id: "save-list-type-dynamic", 4892 name: "save-list-type", 4893 value: "dynamic", 4894 checked: type === "dynamic", 4895 onChange: () => setType("dynamic") 4896 }), /* @__PURE__ */ (0, import_jsx_runtime$8.jsxs)(Label, { 4897 htmlFor: "save-list-type-dynamic", 4898 className: "mb-0", 4899 children: [t$6("js.leads.page.save_list.dynamic"), /* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(Icon, { 4900 icon: "layer-group", 4901 className: "text-hint ml-1" 4902 })] 4903 })] 4904 }), /* @__PURE__ */ (0, import_jsx_runtime$8.jsxs)(RadioGroupItem, { 4905 className: "d-flex align-items-center gap-2", 4906 children: [/* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(Radio, { 4907 id: "save-list-type-static", 4908 name: "save-list-type", 4909 value: "static", 4910 checked: type === "static", 4911 onChange: () => setType("static") 4912 }), /* @__PURE__ */ (0, import_jsx_runtime$8.jsxs)(Label, { 4913 htmlFor: "save-list-type-static", 4914 className: "mb-0", 4915 children: [t$6("js.leads.page.save_list.static"), /* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(Icon, { 4916 icon: "diamond", 4917 className: "text-hint ml-1" 4918 })] 4919 })] 4920 })] 4921 }), 4922 /* @__PURE__ */ (0, import_jsx_runtime$8.jsx)("div", { 4923 className: "h-hint mt-2", 4924 children: type === "dynamic" ? t$6("js.leads.page.save_list.dynamic_hint") : t$6("js.leads.page.save_list.static_hint") 4925 }) 4926 ] 4927 }), 4928 /* @__PURE__ */ (0, import_jsx_runtime$8.jsxs)("div", { 4929 className: "form-group", 4930 children: [/* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(Label, { 4931 htmlFor: "save-filtered-list-name", 4932 children: t$6("js.leads.page.save_list.name_label") 4933 }), /* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(Input, { 4934 ref: nameInputRef, 4935 fullWidth: true, 4936 type: "text", 4937 id: "save-filtered-list-name", 4938 required: true, 4939 value: name, 4940 onChange: (e_0) => setName(e_0.target.value) 4941 })] 4942 }), 4943 /* @__PURE__ */ (0, import_jsx_runtime$8.jsxs)("div", { 4944 className: "form-group", 4945 children: [/* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(Label, { 4946 fullWidth: true, 4947 className: "mt-4", 4948 children: t$6("js.leads.page.save_list.folder_label") 4949 }
4949), /* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(FolderSelect, { 4950 folders: localFolders, 4951 selectedFolderId: folderId, 4952 onSelect: setFolderId, 4953 onFolderCreated: (folder) => setLocalFolders((prev) => [...prev, folder]) 4954 })] 4955 }), 4956 error && /* @__PURE__ */ (0, import_jsx_runtime$8.jsx)("p", { 4957 className: "text-danger text-sm", 4958 role: "alert", 4959 children: error 4960 }) 4961 ] }), 4962 /* @__PURE__ */ (0, import_jsx_runtime$8.jsxs)(SheetFooter, { children: [/* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(Button, { 4963 type: "submit", 4964 variant: "primary", 4965 disabled: !name.trim() || submitting, 4966 "data-loading": "none", 4967 children: t$6("js.leads.page.save_list.confirm") 4968 }), /* @__PURE__ */ (0, import_jsx_runtime$8.jsx)(Button, { 4969 type: "button", 4970 variant: "ghost", 4971 onClick: handleClose, 4972 children: t$6("js.leads.page.cancel") 4973 })] }) 4974 ] 4975 }) 4976 }) 4977 }); 4978} 4979var import_react$8, import_jsx_runtime$8, t$6, NON_FILTER_KEYS, STATIC_ONLY_FILTER_KEYS; 4980function init_SaveFilteredListSidePanel() { 4981 return (init_SaveFilteredListSidePanel = __esmMin((() => { 4982 import_react$8 = require_react(); 4983 init_dist(); 4984 init_routes(); 4985 init_utils(); 4986 init_sheet(); 4987 init_button(); 4988 init_label(); 4989 init_input(); 4990 init_icon(); 4991 init_radio(); 4992 init_radio_group(); 4993 init_FolderSelect(); 4994 import_jsx_runtime$8 = require_jsx_runtime(); 4995 t$6 = (key) => window.i18n.t(key); 4996 NON_FILTER_KEYS = /* @__PURE__ */ new Set([ 4997 "query", 4998 "sort", 4999 "direction", 5000 "offset", 5001 "page_size", 5002 "filters_changed", 5003 "filter_from_chart", 5004 "leads_list_id", 5005 "people_per_company" 5006 ]); 5007 STATIC_ONLY_FILTER_KEYS = [ 5008 "operation_id", 5009 "updated_at", 5010 "people_per_company" 5011 ]; 5012 })))(); 5013} 5014//#endregion 5015//#region app/frontend/pages/Leads/modals/AddToSequenceModal.tsx 5016function AddToSequenceModal({ open, onClose, selectionParams }) { 5017 const dialogRef = (0, import_react$7.useRef)(null); 5018 const [selectedCampaign, setSelectedCampaign] = (0, import_react$7.useState)(null); 5019 const [submitting, setSubmitting] = (0, import_react$7.useState)(false); 5020 const { sequences: campaigns, loading: loadingCampaigns, onInputChange } = useSequencePicker(open); 5021 const handleClose = (0, import_react$7.useCallback)(() => { 5022 setSelectedCampaign(null); 5023 setSubmitting(false); 5024 onClose(); 5025 }, [onClose]); 5026 (0, import_react$7.useEffect)(() => { 5027 const dialog = dialogRef.current; 5028 if (!dialog) return; 5029 if (open) { 5030 if (!dialog.open) dialog.showModal(); 5031 } else if (dialog.open) dialog.close(); 5032 }, [open]); 5033 (0, import_react$7.useEffect)(() => { 5034 const dialog_0 = dialogRef.current; 5035 if (!dialog_0) return; 5036 const handleCancel = () => handleClose(); 5037 dialog_0.addEventListener("close", handleCancel); 5038 return () => dialog_0.removeEventListener("close", handleCancel); 5039 }, [handleClose]); 5040 async function handleSubmit(e) { 5041 e.preventDefault(); 5042 if (!selectedCampaign || submitting) return; 5043 setSubmitting(true); 5044 const body = new URLSearchParams(); 5045 body.append("filters_type", "leads"); 5046 for (const [key, value] of selectionParams.entries()) if (key === "lead_ids[]") body.append("campaign[leads_filters][id][]", value); 5047 else if (key === "people_per_company") body.append("campaign[people_per_company]", value); 5048 else if (key === "sort" || key === "direction") body.append(`campaign[${key}]`, value); 5049 else if (key === "excluded_lead_ids[]") body.append("excluded_lead_ids[]", value); 5050 else body.append(`campaign[leads_filters][${key}]`, value); 5051 try { 5052 const response = await fetch(sequence_audience_path(selectedCampaign.value), { 5053 method: "PUT", 5054 headers: { 5055 "X-CSRF-Token": getCsrfToken(), 5056 Accept: "application/json" 5057 }, 5058 body 5059 }); 5060 const data = await response.json().catch(() => null); 5061 if (response.ok) { 5062 handleClose(); 5063 if (data?.message) toast.success(data.message); 5064 router.reload(); 5065 } else { 5066 toast.danger(data?.message ?? t$5("js.leads.page.bulk_actions.add_to_sequence_error")); 5067 setSubmitting(false); 5068 } 5069 } catch { 5070 toast.danger(t$5("js.leads.page.bulk_actions.add_to_sequence_error")); 5071 setSubmitting(false); 5072 } 5073 } 5074 return /* @__PURE__ */ (0, import_jsx_runtime$7.jsx)(Dialog, { 5075 ref: dialogRef, 5076 className: "add-to-sequence-dialog", 5077 children: /* @__PURE__ */ (0, import_jsx_runtime$7.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$7.jsxs)("form", { 5078 onSubmit: handleSubmit, 5079 children: [
5080 /* @__PURE__ */ (0, import_jsx_runtime$7.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime$7.jsx)(DialogTitle, { children: t$5("js.leads.page.bulk_actions.add_to_sequence_title") }), /* @__PURE__ */ (0, import_jsx_runtime$7.jsx)(DialogCloseButton, { 5081 type: "button", 5082 onClick: handleClose 5083 })] }), 5084 /* @__PURE__ */ (0, import_jsx_runtime$7.jsx)(DialogBody, { children: /* @__PURE__ */ (0, import_jsx_runtime$7.jsxs)("div", { 5085 className: "form-group", 5086 children: [/* @__PURE__ */ (0, import_jsx_runtime$7.jsx)(Label, { 5087 fullWidth: true, 5088 id: "add-to-sequence-label", 5089 children: t$5("js.leads.page.bulk_actions.add_to_sequence_label") 5090 }), /* @__PURE__ */ (0, import_jsx_runtime$7.jsx)(Select, { 5091 inputId: "add-to-sequence-select", 5092 "aria-labelledby": "add-to-sequence-label", 5093 placeholder: t$5("js.leads.page.bulk_actions.select_sequence_placeholder"), 5094 isSearchable: true, 5095 isClearable: false, 5096 isLoading: loadingCampaigns, 5097 loadingMessage: () => t$5("js.leads.page.bulk_actions.add_to_sequence_loading"), 5098 noOptionsMessage: ({ inputValue }) => inputValue ? t$5("js.leads.page.bulk_actions.add_to_sequence_no_matches") : t$5("js.leads.page.bulk_actions.add_to_sequence_no_sequences"), 5099 menuPlacement: "auto", 5100 options: campaigns.map((campaign) => ({ 5101 value: campaign.id, 5102 label: campaign.name 5103 })), 5104 value: selectedCampaign, 5105 onInputChange, 5106 onChange: (option) => setSelectedCampaign(option ?? null) 5107 })] 5108 }) }),
5109 /* @__PURE__ */ (0, import_jsx_runtime$7.jsxs)(DialogFooter, { children: [/* @__PURE__ */ (0, import_jsx_runtime$7.jsx)(Button, { 5110 type: "button", 5111 onClick: handleClose, 5112 children: t$5("js.leads.page.cancel") 5113 }), /* @__PURE__ */ (0, import_jsx_runtime$7.jsx)(Button, { 5114 type: "submit", 5115 variant: "primary", 5116 disabled: !selectedCampaign || submitting, 5117 "data-loading": "none", 5118 children: t$5("js.leads.page.bulk_actions.add_to_sequence_confirm") 5119 })] }) 5120 ] 5121 }) }) 5122 }); 5123} 5124var import_react$7, import_jsx_runtime$7, t$5; 5125function init_AddToSequenceModal() { 5126 return (init_AddToSequenceModal = __esmMin((() => { 5127 import_react$7 = require_react(); 5128 init_dist(); 5129 init_routes(); 5130 init_utils(); 5131 init_useSequencePicker(); 5132 init_dialog(); 5133 init_button(); 5134 init_label(); 5135 init_select(); 5136 init_toast(); 5137 import_jsx_runtime$7 = require_jsx_runtime(); 5138 t$5 = (key) => window.i18n.t(key); 5139 })))(); 5140} 5141//#endregion 5142//#region app/frontend/pages/Leads/modals/SyncToCrmModal.tsx 5143function SyncToCrmModal({ open, onClose, onSuccess, selectionParams, selectedCount, syncableApps }) { 5144 const dialogRef = (0, import_react$6.useRef)(null); 5145 const options = syncableApps.map((app) => ({ 5146 value: app.id, 5147 label: app.providerName 5148 })); 5149 const [selectedApp, setSelectedApp] = (0, import_react$6.useState)(options.length === 1 ? options[0] : null); 5150 const [submitting, setSubmitting] = (0, import_react$6.useState)(false); 5151 const handleClose = (0, import_react$6.useCallback)(() => { 5152 setSelectedApp(options.length === 1 ? options[0] : null); 5153 setSubmitting(false); 5154 onClose(); 5155 }, [onClose]); 5156 (0, import_react$6.useEffect)(() => { 5157 const dialog = dialogRef.current; 5158 if (!dialog) return; 5159 if (open) { 5160 if (!dialog.open) dialog.showModal(); 5161 } else if (dialog.open) dialog.close(); 5162 }, [open]); 5163 (0, import_react$6.useEffect)(() => { 5164 const dialog = dialogRef.current; 5165 if (!dialog) return; 5166 const handleCancel = () => handleClose(); 5167 dialog.addEventListener("close", handleCancel); 5168 return () => dialog.removeEventListener("close", handleCancel); 5169 }, [handleClose]); 5170 async function handleSubmit(e) { 5171 e.preventDefault(); 5172 if (!selectedApp || submitting) return; 5173 setSubmitting(true); 5174 const body = new URLSearchParams(selectionParams); 5175 body.append("connected_app_id", String(selectedApp.value)); 5176 try { 5177 const response = await fetch(leads_crm_sync_path(), { 5178 method: "POST", 5179 headers: { 5180 "X-CSRF-Token": getCsrfToken(), 5181 Accept: "application/json" 5182 }, 5183 body 5184 }); 5185 const data = await response.json().catch(() => null); 5186 if (response.ok) { 5187 handleClose(); 5188 onSuccess(); 5189 toast.success(window.i18n.t("js.leads.page.bulk_actions.sync_to_crm_started", { 5190 formatted_count: CurrencyHelper.numberWithDelimiter(selectedCount), 5191 provider: selectedApp.label 5192 })); 5193 } else { 5194 toast.danger(data?.message ?? t$4("js.leads.page.bulk_actions.sync_to_crm_error")); 5195 setSubmitting(false); 5196 } 5197 } catch { 5198 toast.danger(t$4("js.leads.page.bulk_actions.sync_to_crm_error")); 5199 setSubmitting(false); 5200 } 5201 } 5202 return /* @__PURE__ */ (0, import_jsx_runtime$6.jsx)(Dialog, { 5203 ref: dialogRef, 5204 className: "sync-to-crm-dialog", 5205 children: /* @__PURE__ */ (0, import_jsx_runtime$6.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$6.jsxs)("form", { 5206 onSubmit: handleSubmit, 5207 children: [
5208 /* @__PURE__ */ (0, import_jsx_runtime$6.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime$6.jsx)(DialogTitle, { children: t$4("js.leads.page.bulk_actions.sync_to_crm_title") }), /* @__PURE__ */ (0, import_jsx_runtime$6.jsx)(DialogCloseButton, { 5209 type: "button", 5210 onClick: handleClose 5211 })] }), 5212 /* @__PURE__ */ (0, import_jsx_runtime$6.jsxs)(DialogBody, { children: [/* @__PURE__ */ (0, import_jsx_runtime$6.jsx)("p", { children: t$4("js.leads.page.bulk_actions.sync_to_crm_description") }), options.length > 1 && /* @__PURE__ */ (0, import_jsx_runtime$6.jsxs)("div", { 5213 className: "form-group", 5214 children: [/* @__PURE__ */ (0, import_jsx_runtime$6.jsx)(Label, { 5215 fullWidth: true, 5216 id: "sync-to-crm-label", 5217 children: t$4("js.leads.page.bulk_actions.sync_to_crm_label") 5218 }), /* @__PURE__ */ (0, import_jsx_runtime$6.jsx)(Select, { 5219 inputId: "sync-to-crm-select", 5220 "aria-labelledby": "sync-to-crm-label", 5221 placeholder: t$4("js.leads.page.bulk_actions.sync_to_crm_placeholder"), 5222 isClearable: false, 5223 menuPlacement: "auto", 5224 options, 5225 value: selectedApp, 5226 onChange: (option) => setSelectedApp(option ?? null) 5227 })] 5228 })] }),
5229 /* @__PURE__ */ (0, import_jsx_runtime$6.jsxs)(DialogFooter, { children: [/* @__PURE__ */ (0, import_jsx_runtime$6.jsx)(Button, { 5230 type: "button", 5231 onClick: handleClose, 5232 children: t$4("js.leads.page.cancel") 5233 }), /* @__PURE__ */ (0, import_jsx_runtime$6.jsx)(Button, { 5234 type: "submit", 5235 variant: "primary", 5236 disabled: !selectedApp || submitting, 5237 "data-loading": "none", 5238 children: t$4("js.leads.page.bulk_actions.sync_to_crm_confirm") 5239 })] }) 5240 ] 5241 }) }) 5242 }); 5243} 5244var import_react$6, import_jsx_runtime$6, t$4; 5245function init_SyncToCrmModal() { 5246 return (init_SyncToCrmModal = __esmMin((() => { 5247 import_react$6 = require_react(); 5248 init_routes(); 5249 init_utils(); 5250 init_currency_helper(); 5251 init_dialog(); 5252 init_button(); 5253 init_label(); 5254 init_select(); 5255 init_toast(); 5256 import_jsx_runtime$6 = require_jsx_runtime(); 5257 t$4 = (key) => window.i18n.t(key); 5258 })))(); 5259} 5260//#endregion 5261//#region app/frontend/pages/Leads/modals/FindEmailsModal.tsx 5262function FindEmailsModal({ open, onClose, onSuccess, selectedCount, selectionParams, singleCreditsBucket, searchCallsLeft, searchOverageEnabled, isTeamOwner, creditsAutoPurchaseEnabled, personalLimitReached, checkoutAction }) { 5263 const dialogRef = (0, import_react$5.useRef)(null); 5264 const [submitting, setSubmitting] = (0, import_react$5.useState)(false); 5265 const [isUpgrading, setIsUpgrading] = (0, import_react$5.useState)(false); 5266 const [error, setError] = (0, import_react$5.useState)(null); 5267 const { cost, missingBackendCredits, visualCost, visualAvailable, affordableCount, visualAffordableCost, visualMissing, insufficientCredits } = (0, import_react$5.useMemo)(() => { 5268 const rawCost = CostCalculator.calculate("search", selectedCount, singleCreditsBucket); 5269 const rawPerLead = CostCalculator.calculate("search", 1, singleCreditsBucket); 5270 const exceedsQuota = rawCost > searchCallsLeft; 5271 const affordable = Math.max(0, Math.floor(searchCallsLeft / rawPerLead)); 5272 const visualTotal = CostCalculator.calculateVisualRepresentation("search", selectedCount, singleCreditsBucket); 5273 const visualAvail = singleCreditsBucket ? searchCallsLeft / 10 : searchCallsLeft; 5274 const autoPurchaseWillCover = singleCreditsBucket && creditsAutoPurchaseEnabled && !personalLimitReached; 5275 return { 5276 cost: rawCost, 5277 missingBackendCredits: Math.max(1, rawCost - searchCallsLeft), 5278 visualCost: visualTotal, 5279 visualAvailable: visualAvail, 5280 affordableCount: affordable, 5281 visualAffordableCost: CostCalculator.calculateVisualRepresentation("search", affordable, singleCreditsBucket), 5282 visualMissing: Math.max(0, visualTotal - visualAvail), 5283 insufficientCredits: exceedsQuota && !searchOverageEnabled && !autoPurchaseWillCover 5284 }; 5285 }, [ 5286 selectedCount, 5287 singleCreditsBucket, 5288 searchCallsLeft, 5289 searchOverageEnabled, 5290 creditsAutoPurchaseEnabled, 5291 personalLimitReached 5292 ]); 5293 const canTrimSelection = selectionParams.getAll("lead_ids[]").length > 0; 5294 const showFindFirstCta = insufficientCredits && canTrimSelection && affordableCount > 0; 5295 const checkoutParams = { 5296 operation: "search", 5297 needed_credits: missingBackendCredits, 5298 needed_level: 1, 5299 direct_route: true, 5300 format: "turbo_stream" 5301 }; 5302 const upgradeHref = checkoutAction === "get_more_credits" ? checkout_get_more_credits_path(checkoutParams) : checkoutAction === "buy_credits_packs" ? checkout_buy_credits_pack_path(checkoutParams) : checkoutAction === "upgrade_plans" ? checkout_upgrade_plan_path(checkoutParams) : null; 5303 const canOfferUpgrade = isTeamOwner && upgradeHref !== null; 5304 const handleClose = (0, import_react$5.useCallback)(() => { 5305 setSubmitting(false); 5306 setIsUpgrading(false); 5307 setError(null); 5308 onClose(); 5309 }, [onClose]); 5310 (0, import_react$5.useEffect)(() => { 5311 if (!isUpgrading) return; 5312 const handleCheckoutModalShown = () => handleClose(); 5313 document.addEventListener("shown.bs.modal", handleCheckoutModalShown); 5314 return () => document.removeEventListener("shown.bs.modal", handleCheckoutModalShown); 5315 }, [isUpgrading, handleClose]); 5316 (0, import_react$5.useEffect)(() => { 5317 const dialog = dialogRef.current; 5318 if (!dialog) return; 5319 if (open) { 5320 if (!dialog.open) dialog.showModal(); 5321 } else if (dialog.open) dialog.close(); 5322 }, [open]); 5323 (0, import_react$5.useEffect)(() => { 5324 const dialog_0 = dialogRef.current; 5325 if (!dialog_0) return; 5326 const handleCancel = () => handleClose(); 5327 dialog_0.addEventListener("close", handleCancel); 5328 return () => dialog_0.removeEventListener("close", handleCancel); 5329 }, [handleClose]); 5330 async function submitFind(params) { 5331 if (submitting) return; 5332 setSubmitting(true); 5333 setError(null); 5334 try { 5335 const response = await fetch(leads_email_finder_path(), { 5336 method: "POST", 5337 headers: { 5338 "X-CSRF-Token": getCsrfToken(), 5339 Accept: "application/json" 5340 }, 5341 body: params 5342 }); 5343 if (!response.ok) { 5344 const fallback = t$3("js.leads.page.find_emails_confirmation.submit_error");
5345 try { 5346 const data = await response.json(); 5347 const serverError = isObject(data) && isString(data.message) ? data.message.trim() : ""; 5348 setError(serverError || fallback); 5349 } catch { 5350 setError(fallback); 5351 } 5352 setSubmitting(false); 5353 return; 5354 } 5355 onSuccess?.(); 5356 handleClose(); 5357 } catch { 5358 setError(t$3("js.leads.page.find_emails_confirmation.submit_error")); 5359 setSubmitting(false); 5360 } 5361 } 5362 function handleSubmit(e) { 5363 e.preventDefault(); 5364 if (insufficientCredits || cost === 0) return; 5365 submitFind(selectionParams); 5366 } 5367 function handleFindFirstAffordable() { 5368 const trimmed = new URLSearchParams(); 5369 let kept = 0; 5370 for (const [key, value] of selectionParams.entries()) if (key === "lead_ids[]") { 5371 if (kept < affordableCount) { 5372 trimmed.append(key, value); 5373 kept += 1; 5374 } 5375 } else trimmed.append(key, value); 5376 submitFind(trimmed); 5377 } 5378 return /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(Dialog, { 5379 ref: dialogRef, 5380 children: /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$5.jsxs)("form", { 5381 onSubmit: handleSubmit, 5382 children: [
5383 /* @__PURE__ */ (0, import_jsx_runtime$5.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(DialogTitle, { children: t$3("js.leads.page.find_emails_confirmation.title", { 5384 count: selectedCount, 5385 formatted_count: CurrencyHelper.numberWithDelimiter(selectedCount) 5386 }) }), /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(DialogCloseButton, { 5387 type: "button", 5388 onClick: handleClose 5389 })] }), 5390 /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(DialogBody, { children: insufficientCredits ? /* @__PURE__ */ (0, import_jsx_runtime$5.jsxs)("div", { 5391 "data-testid": "insufficient-credits-body", 5392 children: [ 5393 /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)("p", { dangerouslySetInnerHTML: { __html: t$3("js.leads.page.find_emails_confirmation.insufficient_credits.intro", { 5394 count: CurrencyHelper.numberWithDelimiter(selectedCount), 5395 cost: CurrencyHelper.numberWithDelimiter(visualCost) 5396 }) } }), 5397 /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)("p", { 5398 className: "mt-2", 5399 dangerouslySetInnerHTML: { __html: t$3("js.leads.page.find_emails_confirmation.insufficient_credits.quota", { 5400 available: CurrencyHelper.numberWithDelimiter(visualAvailable), 5401 affordable: CurrencyHelper.numberWithDelimiter(affordableCount), 5402 missing: CurrencyHelper.numberWithDelimiter(visualMissing) 5403 }) } 5404 }), 5405 /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)("p", { 5406 className: "mt-2", 5407 children: t$3("js.leads.page.find_emails_confirmation.insufficient_credits.action", { 5408 count: CurrencyHelper.numberWithDelimiter(selectedCount), 5409 affordable: CurrencyHelper.numberWithDelimiter(affordableCount) 5410 }) 5411 }) 5412 ] 5413 }) : /* @__PURE__ */ (0, import_jsx_runtime$5.jsxs)(import_jsx_runtime$5.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime$5.jsx)("p", { dangerouslySetInnerHTML: { __html: t$3("js.leads.page.find_emails_confirmation.body", { 5414 count: selectedCount, 5415 formatted_count: CurrencyHelper.numberWithDelimiter(selectedCount) 5416 }) } }), error && /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)("p", { 5417 className: "text-danger text-sm mt-3", 5418 role: "alert", 5419 children: error 5420 })] }) }),
5421 /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(DialogFooter, { children: insufficientCredits ? /* @__PURE__ */ (0, import_jsx_runtime$5.jsxs)(import_jsx_runtime$5.Fragment, { children: [ 5422 !canOfferUpgrade && /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)("p", { 5423 className: "text-sm grey mr-auto", 5424 children: t$3("js.leads.page.find_emails_confirmation.insufficient_credits.contact_owner") 5425 }), 5426 showFindFirstCta && /* @__PURE__ */ (0, import_jsx_runtime$5.jsxs)(Button, { 5427 type: "button", 5428 onClick: handleFindFirstAffordable, 5429 disabled: submitting, 5430 "data-loading": "none", 5431 children: [t$3("js.leads.page.find_emails_confirmation.find_first", { 5432 count: affordableCount, 5433 formatted_count: CurrencyHelper.numberWithDelimiter(affordableCount) 5434 }), /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(ButtonSuffix, { children: /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(CostIndicator, { cost: visualAffordableCost }) })] 5435 }), 5436 canOfferUpgrade && upgradeHref && /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(Button, { 5437 variant: "primary", 5438 asChild: true, 5439 children: /* @__PURE__ */ (0, import_jsx_runtime$5.jsxs)("a", { 5440 href: upgradeHref, 5441 "data-turbo-stream": "true", 5442 "data-turbo-prefetch": "false", 5443 "aria-disabled": isUpgrading, 5444 onClick: (event) => { 5445 if (isUpgrading) { 5446 event.preventDefault(); 5447 return; 5448 } 5449 setIsUpgrading(true); 5450 }, 5451 children: [isUpgrading && /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(Icon, { 5452 loading: true, 5453 size: "sm" 5454 }), t$3(checkoutAction === "upgrade_plans" ? "js.leads.page.find_emails_confirmation.upgrade" : "js.leads.page.find_emails_confirmation.get_more_credits")] 5455 }) 5456 }) 5457 ] }) : /* @__PURE__ */ (0, import_jsx_runtime$5.jsxs)(import_jsx_runtime$5.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(Button, { 5458 type: "button", 5459 onClick: handleClose, 5460 children: t$3("js.leads.page.cancel") 5461 }), /* @__PURE__ */ (0, import_jsx_runtime$5.jsxs)(Button, { 5462 type: "submit", 5463 variant: "primary", 5464 disabled: submitting, 5465 "data-loading": "none", 5466 children: [t$3("js.leads.page.find_emails_confirmation.confirm"), /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(ButtonSuffix, { children: /* @__PURE__ */ (0, import_jsx_runtime$5.jsx)(CostIndicator, { cost: visualCost }) })] 5467 })] }) }) 5468 ] 5469 }) }) 5470 }); 5471} 5472var import_react$5, import_jsx_runtime$5, t$3; 5473function init_FindEmailsModal() { 5474 return (init_FindEmailsModal = __esmMin((() => { 5475 import_react$5 = require_react(); 5476 init_routes(); 5477 init_utils(); 5478 init_costCalculator(); 5479 init_currency_helper(); 5480 init_dialog(); 5481 init_button(); 5482 init_icon(); 5483 init_cost_indicator(); 5484 import_jsx_runtime$5 = require_jsx_runtime(); 5485 t$3 = (key, options) => window.i18n.t(key, options); 5486 })))(); 5487} 5488//#endregion 5489//#region app/frontend/pages/Leads/modals/VerifyLeadsModal.tsx 5490function VerifyLeadsModal({ open, onClose, onVerified, selectedCount, selectionParams, sort, direction, verifyCallsLeft, verifyOverageEnabled, singleCreditsBucket, isTeamOwner, creditsAutoPurchaseEnabled, personalLimitReached, checkoutAction }) { 5491 const dialogRef = (0, import_react$4.useRef)(null); 5492 const isClosingRef = (0, import_react$4.useRef)(false); 5493 const abortRef = (0, import_react$4.useRef)(null); 5494 const [submitting, setSubmitting] = (0, import_react$4.useState)(false); 5495 const [errorMessage, setErrorMessage] = (0, import_react$4.useState)(null); 5496 const [isUpgrading, setIsUpgrading] = (0, import_react$4.useState)(false); 5497 const { cost, missingBackendCredits, visualCost, visualAvailable, affordableCount, visualAffordableCost, visualMissing, insufficientCredits, overageRequired } = (0, import_react$4.useMemo)(() => { 5498 const rawCost = CostCalculator.calculate("verify", selectedCount, singleCreditsBucket); 5499 const rawPerLead = CostCalculator.calculate("verify", 1, singleCreditsBucket); 5500 const exceedsQuota = rawCost > verifyCallsLeft; 5501 const affordable = Math.max(0, Math.floor(verifyCallsLeft / rawPerLead)); 5502 const visualTotal = CostCalculator.calculateVisualRepresentation("verify", selectedCount, singleCreditsBucket); 5503 const visualAvail = singleCreditsBucket ? verifyCallsLeft / 10 : verifyCallsLeft; 5504 const autoPurchaseWillCover = singleCreditsBucket && creditsAutoPurchaseEnabled && !personalLimitReached; 5505 return { 5506 cost: rawCost, 5507 missingBackendCredits: Math.max(1, rawCost - verifyCallsLeft), 5508 visualCost: visualTotal, 5509 visualAvailable: visualAvail, 5510 affordableCount: affordable, 5511 visualAffordableCost: CostCalculator.calculateVisualRepresentation("verify", affordable, singleCreditsBucket), 5512 visualMissing: Math.max(0, visualTotal - visualAvail), 5513 insufficientCredits: exceedsQuota && !verifyOverageEnabled && !autoPurchaseWillCover, 5514 overageRequired: exceedsQuota && verifyOverageEnabled 5515 }; 5516 }, [ 5517 selectedCount, 5518 singleCreditsBucket, 5519 verifyCallsLeft, 5520 verifyOverageEnabled, 5521 creditsAutoPurchaseEnabled, 5522 personalLimitReached 5523 ]); 5524 const showFirstAffordableCta = insufficientCredits && affordableCount > 0; 5525 const checkoutParams = { 5526 operation: "verify", 5527 needed_credits: missingBackendCredits, 5528 needed_level: 1, 5529 direct_route: true, 5530 format: "turbo_stream" 5531 }; 5532 const upgradeHref = checkoutAction === "get_more_credits" ? checkout_get_more_credits_path(checkoutParams) : checkoutAction === "buy_credits_packs" ? checkout_buy_credits_pack_path(checkoutParams) : checkoutAction === "upgrade_plans" ? checkout_upgrade_plan_path(checkoutParams) : null; 5533 const canOfferUpgrade = isTeamOwner && upgradeHref !== null; 5534 function handleClose() { 5535 if (isClosingRef.current) return; 5536 isClosingRef.current = true; 5537 abortRef.current?.abort(); 5538 abortRef.current = null; 5539 setSubmitting(false); 5540 setErrorMessage(null); 5541 setIsUpgrading(false); 5542 onClose(); 5543 } 5544 (0, import_react$4.useEffect)(() => { 5545 if (!isUpgrading) return; 5546 const handleCheckoutModalShown = () => handleClose(); 5547 document.addEventListener("shown.bs.modal", handleCheckoutModalShown); 5548 return () => document.removeEventListener("shown.bs.modal", handleCheckoutModalShown); 5549 }, [isUpgrading]); 5550 (0, import_react$4.useEffect)(() => { 5551 const dialog = dialogRef.current; 5552 if (!dialog) return; 5553 if (open) { 5554 isClosingRef.current = false;
5555 setErrorMessage(null); 5556 if (!dialog.open) dialog.showModal(); 5557 } else if (dialog.open) dialog.close(); 5558 }, [open]); 5559 (0, import_react$4.useEffect)(() => { 5560 const dialog = dialogRef.current; 5561 if (!dialog) return; 5562 const handleNativeClose = () => { 5563 if (isClosingRef.current) return; 5564 handleClose(); 5565 }; 5566 dialog.addEventListener("close", handleNativeClose); 5567 return () => dialog.removeEventListener("close", handleNativeClose); 5568 }, []); 5569 async function submitVerify(params) { 5570 if (submitting) return; 5571 setSubmitting(true); 5572 setErrorMessage(null); 5573 const controller = new AbortController(); 5574 abortRef.current = controller; 5575 try { 5576 const response = await fetch(leads_verify_path(), { 5577 method: "POST", 5578 headers: { 5579 "X-CSRF-Token": getCsrfToken(), 5580 Accept: "application/json" 5581 }, 5582 body: params, 5583 signal: controller.signal 5584 }); 5585 if (!response.ok) { 5586 const body = await response.json().catch(() => ({})); 5587 setErrorMessage(body.message ?? t$2("js.leads.page.verify_leads_confirmation.submit_error")); 5588 setSubmitting(false); 5589 return; 5590 } 5591 onVerified?.(); 5592 handleClose(); 5593 router.reload(); 5594 } catch (err) { 5595 if (err instanceof DOMException && err.name === "AbortError") return; 5596 setErrorMessage(t$2("js.leads.page.verify_leads_confirmation.submit_error")); 5597 setSubmitting(false); 5598 } 5599 } 5600 function handleSubmit(e) { 5601 e.preventDefault(); 5602 if (insufficientCredits || cost === 0) return; 5603 submitVerify(selectionParams); 5604 } 5605 function handleVerifyFirstAffordable() { 5606 const trimmed = new URLSearchParams(); 5607 let kept = 0; 5608 for (const [key, value] of selectionParams.entries()) if (key === "lead_ids[]") { 5609 if (kept < affordableCount) { 5610 trimmed.append(key, value); 5611 kept += 1; 5612 } 5613 } else trimmed.append(key, value); 5614 trimmed.append("limit", affordableCount.toString()); 5615 if (sort) trimmed.append("sort", sort); 5616 if (direction) trimmed.append("direction", direction); 5617 submitVerify(trimmed); 5618 } 5619 const bodyKey = singleCreditsBucket ? "js.leads.page.verify_leads_confirmation.body_unified" : "js.leads.page.verify_leads_confirmation.body"; 5620 return /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(Dialog, { 5621 ref: dialogRef, 5622 children: /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$4.jsxs)("form", { 5623 onSubmit: handleSubmit, 5624 children: [
5625 /* @__PURE__ */ (0, import_jsx_runtime$4.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(DialogTitle, { children: t$2("js.leads.page.verify_leads_confirmation.title", { 5626 count: selectedCount, 5627 formatted_count: CurrencyHelper.numberWithDelimiter(selectedCount) 5628 }) }), /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(DialogCloseButton, { 5629 type: "button", 5630 onClick: handleClose 5631 })] }), 5632 /* @__PURE__ */ (0, import_jsx_runtime$4.jsxs)(DialogBody, { children: [ 5633 insufficientCredits ? /* @__PURE__ */ (0, import_jsx_runtime$4.jsxs)("div", { 5634 "data-testid": "insufficient-credits-body", 5635 children: [ 5636 /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)("p", { dangerouslySetInnerHTML: { __html: t$2("js.leads.page.verify_leads_confirmation.insufficient_credits.intro", { 5637 count: CurrencyHelper.numberWithDelimiter(selectedCount), 5638 cost: CurrencyHelper.numberWithDelimiter(visualCost) 5639 }) } }), 5640 /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)("p", { 5641 className: "mt-2", 5642 dangerouslySetInnerHTML: { __html: t$2("js.leads.page.verify_leads_confirmation.insufficient_credits.quota", { 5643 available: CurrencyHelper.numberWithDelimiter(visualAvailable), 5644 affordable: CurrencyHelper.numberWithDelimiter(affordableCount), 5645 missing: CurrencyHelper.numberWithDelimiter(visualMissing) 5646 }) } 5647 }), 5648 /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)("p", { 5649 className: "mt-2", 5650 children: t$2("js.leads.page.verify_leads_confirmation.insufficient_credits.action", { 5651 count: CurrencyHelper.numberWithDelimiter(selectedCount), 5652 affordable: CurrencyHelper.numberWithDelimiter(affordableCount) 5653 }) 5654 }) 5655 ] 5656 }) : /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)("p", { dangerouslySetInnerHTML: { __html: t$2(bodyKey, { 5657 count: CurrencyHelper.numberWithDelimiter(selectedCount), 5658 credits: CurrencyHelper.numberWithDelimiter(visualCost) 5659 }) } }),
5660 overageRequired && /* @__PURE__ */ (0, import_jsx_runtime$4.jsxs)(Alert, { 5661 variant: "warning", 5662 size: "small", 5663 className: "mt-3", 5664 "data-testid": "overage-warning-alert", 5665 children: [/* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(AlertIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(Icon, { icon: "circle-exclamation" }) }), /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(AlertContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(AlertDescription, { children: t$2("js.leads.page.verify_leads_confirmation.overage_warning") }) })] 5666 }), 5667 errorMessage && /* @__PURE__ */ (0, import_jsx_runtime$4.jsxs)(Alert, { 5668 variant: "destructive", 5669 size: "small", 5670 className: "mt-3", 5671 "data-testid": "submit-error-alert", 5672 children: [/* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(AlertIcon, { children: /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(Icon, { icon: "circle-exclamation" }) }), /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(AlertContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(AlertDescription, { children: errorMessage }) })] 5673 }) 5674 ] }),
5675 /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(DialogFooter, { children: insufficientCredits ? /* @__PURE__ */ (0, import_jsx_runtime$4.jsxs)(import_jsx_runtime$4.Fragment, { children: [ 5676 !canOfferUpgrade && /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)("p", { 5677 className: "text-sm grey mr-auto", 5678 children: t$2("js.leads.page.verify_leads_confirmation.insufficient_credits.contact_owner") 5679 }), 5680 showFirstAffordableCta && /* @__PURE__ */ (0, import_jsx_runtime$4.jsxs)(Button, { 5681 type: "button", 5682 onClick: handleVerifyFirstAffordable, 5683 disabled: submitting, 5684 "data-loading": "none", 5685 children: [t$2("js.leads.page.verify_leads_confirmation.verify_first", { 5686 count: affordableCount, 5687 formatted_count: CurrencyHelper.numberWithDelimiter(affordableCount) 5688 }), /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(ButtonSuffix, { children: /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(CostIndicator, { cost: visualAffordableCost }) })] 5689 }), 5690 canOfferUpgrade && upgradeHref && /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(Button, { 5691 variant: "primary", 5692 asChild: true, 5693 children: /* @__PURE__ */ (0, import_jsx_runtime$4.jsxs)("a", { 5694 href: upgradeHref, 5695 "data-turbo-stream": "true", 5696 "data-turbo-prefetch": "false", 5697 "aria-disabled": isUpgrading, 5698 onClick: (event) => { 5699 if (isUpgrading) { 5700 event.preventDefault(); 5701 return; 5702 } 5703 setIsUpgrading(true); 5704 }, 5705 children: [isUpgrading && /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(Icon, { 5706 loading: true, 5707 size: "sm" 5708 }), t$2(checkoutAction === "upgrade_plans" ? "js.leads.page.verify_leads_confirmation.upgrade" : "js.leads.page.verify_leads_confirmation.get_more_credits")] 5709 }) 5710 }) 5711 ] }) : /* @__PURE__ */ (0, import_jsx_runtime$4.jsxs)(import_jsx_runtime$4.Fragment, { children: [/* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(Button, { 5712 type: "button", 5713 onClick: handleClose, 5714 children: t$2("js.leads.page.cancel") 5715 }), /* @__PURE__ */ (0, import_jsx_runtime$4.jsxs)(Button, { 5716 type: "submit", 5717 variant: "primary", 5718 disabled: submitting || cost === 0, 5719 "data-loading": "none", 5720 children: [t$2("js.leads.page.verify_leads_confirmation.confirm"), /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(ButtonSuffix, { children: /* @__PURE__ */ (0, import_jsx_runtime$4.jsx)(CostIndicator, { cost: visualCost }) })] 5721 })] }) }) 5722 ] 5723 }) }) 5724 }); 5725} 5726var import_react$4, import_jsx_runtime$4, t$2; 5727function init_VerifyLeadsModal() { 5728 return (init_VerifyLeadsModal = __esmMin((() => { 5729 import_react$4 = require_react(); 5730 init_dist(); 5731 init_routes(); 5732 init_utils(); 5733 init_costCalculator(); 5734 init_currency_helper(); 5735 init_dialog(); 5736 init_button(); 5737 init_alert(); 5738 init_icon(); 5739 init_cost_indicator(); 5740 import_jsx_runtime$4 = require_jsx_runtime(); 5741 t$2 = (key, options) => window.i18n.t(key, options); 5742 })))(); 5743} 5744//#endregion 5745//#region app/frontend/pages/Leads/modals/CreateCustomAttributeModal.tsx 5746function CreateCustomAttributeModal({ open, onClose, onCreated }) { 5747 const dialogRef = (0, import_react$3.useRef)(null); 5748 const [label, setLabel] = (0, import_react$3.useState)(""); 5749 const [defaultValue, setDefaultValue] = (0, import_react$3.useState)(""); 5750 const [description, setDescription] = (0, import_react$3.useState)(""); 5751 const [submitting, setSubmitting] = (0, import_react$3.useState)(false); 5752 const [error, setError] = (0, import_react$3.useState)(null); 5753 const handleClose = (0, import_react$3.useCallback)(() => { 5754 setLabel(""); 5755 setDefaultValue(""); 5756 setDescription(""); 5757 setSubmitting(false); 5758 setError(null); 5759 onClose(); 5760 }, [onClose]); 5761 (0, import_react$3.useEffect)(() => { 5762 const dialog = dialogRef.current; 5763 if (!dialog) return; 5764 if (open) { 5765 if (!dialog.open) dialog.showModal(); 5766 } else if (dialog.open) dialog.close(); 5767 }, [open]); 5768 (0, import_react$3.useEffect)(() => { 5769 const dialog_0 = dialogRef.current; 5770 if (!dialog_0) return; 5771 const handleCancel = () => handleClose(); 5772 dialog_0.addEventListener("close", handleCancel); 5773 return () => dialog_0.removeEventListener("close", handleCancel); 5774 }, [handleClose]); 5775 async function handleSubmit(e) { 5776 e.preventDefault(); 5777 if (!label.trim() || submitting) return; 5778 setSubmitting(true); 5779 setError(null); 5780 const body = new URLSearchParams(); 5781 body.append("lead_custom_attribute[label]", label.trim()); 5782 body.append("lead_custom_attribute[default_value]", defaultValue); 5783 body.append("lead_custom_attribute[description]", description); 5784 try { 5785 const response = await fetch(lead_custom_attributes_path({ format: "json" }), { 5786 method: "POST", 5787 headers: { 5788 "X-CSRF-Token": getCsrfToken(), 5789 "Content-Type": "application/x-www-form-urlencoded", 5790 Accept: "application/json" 5791 }, 5792 body: body.toString() 5793 }); 5794 if (response.ok) { 5795 const created = await response.json(); 5796 handleClose(); 5797 onCreated(created); 5798 toast.success(t$1("js.leads.page.create_custom_attribute_modal.create_success")); 5799 } else { 5800 const data = await response.json().catch(() => ({})); 5801 setError(data.errors ?? null); 5802 setSubmitting(false); 5803 } 5804 } catch { 5805 setSubmitting(false); 5806 } 5807 } 5808 return /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Dialog, { 5809 ref: dialogRef, 5810 children: /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(DialogContent, { children: /* @__PURE__ */ (0, import_jsx_runtime$3.jsxs)("form", { 5811 onSubmit: handleSubmit, 5812 children: [
5813 /* @__PURE__ */ (0, import_jsx_runtime$3.jsxs)(DialogHeader, { children: [/* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(DialogTitle, { children: t$1("js.leads.page.create_custom_attribute_modal.title") }), /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(DialogCloseButton, { 5814 type: "button", 5815 onClick: handleClose 5816 })] }), 5817 /* @__PURE__ */ (0, import_jsx_runtime$3.jsxs)(DialogBody, { children: [ 5818 /* @__PURE__ */ (0, import_jsx_runtime$3.jsxs)("div", { 5819 className: "form-group", 5820 children: [ 5821 /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Label, { 5822 htmlFor: "custom-attribute-name", 5823 children: t$1("js.leads.page.create_custom_attribute_modal.name") 5824 }), 5825 /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Input, { 5826 fullWidth: true, 5827 type: "text", 5828 id: "custom-attribute-name", 5829 required: true, 5830 autoFocus: true, 5831 value: label, 5832 onChange: (e_0) => setLabel(e_0.target.value) 5833 }), 5834 /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Hint, { 5835 className: "mt-1", 5836 children: t$1("js.leads.page.create_custom_attribute_modal.name_hint") 5837 }) 5838 ] 5839 }), 5840 /* @__PURE__ */ (0, import_jsx_runtime$3.jsxs)("div", { 5841 className: "form-group mt-4", 5842 children: [ 5843 /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Label, { 5844 htmlFor: "custom-attribute-default-value", 5845 children: t$1("js.leads.page.create_custom_attribute_modal.default_value") 5846 }), 5847 /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Input, { 5848 fullWidth: true, 5849 type: "text", 5850 id: "custom-attribute-default-value", 5851 value: defaultValue, 5852 onChange: (e_1) => setDefaultValue(e_1.target.value) 5853 }), 5854 /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Hint, { 5855 className: "mt-1", 5856 children: t$1("js.leads.page.create_custom_attribute_modal.default_value_hint") 5857 }) 5858 ] 5859 }), 5860 /* @__PURE__ */ (0, import_jsx_runtime$3.jsxs)("div", { 5861 className: "form-group mt-4", 5862 children: [ 5863 /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Label, { 5864 htmlFor: "custom-attribute-description", 5865 children: t$1("js.leads.page.create_custom_attribute_modal.description") 5866 }), 5867 /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Input, { 5868 fullWidth: true, 5869 type: "text", 5870 id: "custom-attribute-description", 5871 maxLength: MAX_DESCRIPTION_LENGTH, 5872 value: description, 5873 onChange: (e_2) => setDescription(e_2.target.value) 5874 }), 5875 /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Hint, { 5876 className: "mt-1", 5877 children: t$1("js.leads.page.create_custom_attribute_modal.description_hint") 5878 }) 5879 ] 5880 }), 5881 error && /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Hint, { 5882 variant: "error", 5883 className: "mt-3", 5884 children: error 5885 }) 5886 ] }),
5887 /* @__PURE__ */ (0, import_jsx_runtime$3.jsxs)(DialogFooter, { children: [/* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Button, { 5888 type: "button", 5889 onClick: handleClose, 5890 children: t$1("js.leads.page.cancel") 5891 }), /* @__PURE__ */ (0, import_jsx_runtime$3.jsx)(Button, { 5892 type: "submit", 5893 variant: "primary", 5894 disabled: !label.trim() || submitting, 5895 "data-loading": "none", 5896 children: t$1("js.leads.page.create_custom_attribute_modal.submit") 5897 })] }) 5898 ] 5899 }) }) 5900 }); 5901} 5902var import_react$3, import_jsx_runtime$3, t$1, MAX_DESCRIPTION_LENGTH; 5903function init_CreateCustomAttributeModal() { 5904 return (init_CreateCustomAttributeModal = __esmMin((() => { 5905 import_react$3 = require_react(); 5906 init_routes(); 5907 init_utils(); 5908 init_dialog(); 5909 init_button(); 5910 init_label(); 5911 init_input(); 5912 init_hint(); 5913 init_toast(); 5914 import_jsx_runtime$3 = require_jsx_runtime(); 5915 t$1 = (key) => window.i18n.t(key); 5916 MAX_DESCRIPTION_LENGTH = 150; 5917 })))(); 5918} 5919//#endregion 5920//#region app/frontend/pages/Leads/VerificationBanner.tsx 5921function VerificationBanner(t0) { 5922 const $ = (0, import_compiler_runtime$1.c)(28); 5923 const { banner } = t0; 5924 const [dismissed, setDismissed] = (0, import_react$2.useState)(false); 5925 const [submitting, setSubmitting] = (0, import_react$2.useState)(false); 5926 const formRef = (0, import_react$2.useRef)(null); 5927 if (dismissed) return null; 5928 let t1; 5929 if ($[0] !== banner.emailsCount) { 5930 t1 = banner.emailsCount === 1 ? `${CurrencyHelper.numberWithDelimiter(banner.emailsCount)} email address can be verified from your leads` : `${CurrencyHelper.numberWithDelimiter(banner.emailsCount)} email addresses can be verified from your leads`; 5931 $[0] = banner.emailsCount; 5932 $[1] = t1; 5933 } else t1 = $[1]; 5934 const title = t1; 5935 let t2; 5936 if ($[2] !== banner.creditsCount) { 5937 t2 = CurrencyHelper.numberWithDelimiter(banner.creditsCount); 5938 $[2] = banner.creditsCount; 5939 $[3] = t2; 5940 } else t2 = $[3]; 5941 const description = `Keep your data clean and make sure you\u2019re reaching the right contacts. \u00b7 ${t2} credits required`; 5942 let t3; 5943 if ($[4] !== submitting) { 5944 t3 = function handleVerify() { 5945 if (submitting) return; 5946 setSubmitting(true); 5947 formRef.current?.submit(); 5948 }; 5949 $[4] = submitting; 5950 $[5] = t3; 5951 } else t3 = $[5]; 5952 const handleVerify = t3; 5953 const t4 = banner.verifyUrl; 5954 let t5; 5955 if ($[6] === Symbol.for("react.memo_cache_sentinel")) { 5956 t5 = { display: "none" }; 5957 $[6] = t5; 5958 } else t5 = $[6]; 5959 let t6; 5960 if ($[7] === Symbol.for("react.memo_cache_sentinel")) { 5961 t6 = /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("input", { 5962 type: "hidden", 5963 name: "authenticity_token", 5964 value: getCsrfToken() 5965 }); 5966 $[7] = t6; 5967 } else t6 = $[7]; 5968 let t7; 5969 if ($[8] !== banner.filters) { 5970 t7 = Object.entries(banner.filters).map(_temp$1); 5971 $[8] = banner.filters; 5972 $[9] = t7; 5973 } else t7 = $[9]; 5974 let t8; 5975 if ($[10] !== banner.verifyUrl || $[11] !== t7) { 5976 t8 = /* @__PURE__ */ (0, import_jsx_runtime$2.jsxs)("form", { 5977 ref: formRef, 5978 action: t4, 5979 method: "post", 5980 style: t5, 5981 children: [t6, t7] 5982 }); 5983 $[10] = banner.verifyUrl; 5984 $[11] = t7; 5985 $[12] = t8; 5986 } else t8 = $[12]; 5987 let t9; 5988 if ($[13] !== title) { 5989 t9 = /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("span", { 5990 className: "banner__title", 5991 children: title 5992 }); 5993 $[13] = title; 5994 $[14] = t9; 5995 } else t9 = $[14]; 5996 let t10; 5997 if ($[15] !== description) { 5998 t10 = /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("span", { 5999 className: "banner__description", 6000 children: description 6001 }); 6002 $[15] = description; 6003 $[16] = t10; 6004 } else t10 = $[16]; 6005 let t11; 6006 if ($[17] !== t10 || $[18] !== t9) { 6007 t11 = /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("div", { 6008 className: "banner__content", 6009 children: /* @__PURE__ */ (0, import_jsx_runtime$2.jsxs)("div", { 6010 className: "banner__content-text", 6011 children: [t9, t10] 6012 }) 6013 }); 6014 $[17] = t10; 6015 $[18] = t9; 6016 $[19] = t11; 6017 } else t11 = $[19]; 6018 let t12; 6019 if ($[20] === Symbol.for("react.memo_cache_sentinel")) { 6020 t12 = /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)(Button, { 6021 variant: "ghost", 6022 size: "sm", 6023 onClick: () => setDismissed(true), 6024 children: "Maybe later" 6025 }); 6026 $[20] = t12; 6027 } else t12 = $[20]; 6028 let t13; 6029 if ($[21] !== handleVerify || $[22] !== submitting) { 6030 t13 = /* @__PURE__ */ (0, import_jsx_runtime$2.jsxs)("div", { 6031 className: "banner__actions",
6032 children: [t12, /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)(Button, { 6033 variant: "default", 6034 size: "sm", 6035 onClick: handleVerify, 6036 disabled: submitting, 6037 children: "Verify emails" 6038 })] 6039 }); 6040 $[21] = handleVerify; 6041 $[22] = submitting; 6042 $[23] = t13; 6043 } else t13 = $[23]; 6044 let t14; 6045 if ($[24] !== t11 || $[25] !== t13 || $[26] !== t8) { 6046 t14 = /* @__PURE__ */ (0, import_jsx_runtime$2.jsxs)("div", { 6047 className: "banner mb-4", 6048 children: [ 6049 t8, 6050 t11, 6051 t13 6052 ] 6053 }); 6054 $[24] = t11; 6055 $[25] = t13; 6056 $[26] = t8; 6057 $[27] = t14; 6058 } else t14 = $[27]; 6059 return t14; 6060} 6061function _temp$1(t0) { 6062 const [key, value] = t0; 6063 return /* @__PURE__ */ (0, import_jsx_runtime$2.jsx)("input", { 6064 type: "hidden", 6065 name: key, 6066 value 6067 }, key); 6068} 6069var import_compiler_runtime$1, import_react$2, import_jsx_runtime$2; 6070function init_VerificationBanner() { 6071 return (init_VerificationBanner = __esmMin((() => { 6072 import_compiler_runtime$1 = require_compiler_runtime(); 6073 import_react$2 = require_react(); 6074 init_button(); 6075 init_utils(); 6076 init_currency_helper(); 6077 import_jsx_runtime$2 = require_jsx_runtime(); 6078 })))(); 6079} 6080//#endregion 6081//#region app/frontend/react/components/leads/pseo_welcome_dialog.tsx 6082function readSessionFlag(key) { 6083 try { 6084 return sessionStorage.getItem(key) === "1"; 6085 } catch { 6086 return false; 6087 } 6088} 6089function writeSessionFlag(key) { 6090 try { 6091 sessionStorage.setItem(key, "1"); 6092 } catch {} 6093} 6094function stripWelcomeParam() { 6095 try { 6096 const url = new URL(window.location.href); 6097 if (!url.searchParams.has(WELCOME_PARAM)) return; 6098 url.searchParams.delete(WELCOME_PARAM); 6099 const search = url.searchParams.toString(); 6100 window.history.replaceState(window.history.state, "", `${url.pathname}${search ? `?${search}` : ""}${url.hash}`); 6101 } catch {} 6102} 6103function submitCampaignForm(action, leadIds) { 6104 const form = document.createElement("form"); 6105 form.method = "post"; 6106 form.action = action; 6107 const appendInput = (name, value) => { 6108 const input = document.createElement("input"); 6109 input.type = "hidden"; 6110 input.name = name; 6111 input.value = value; 6112 form.appendChild(input); 6113 }; 6114 appendInput("authenticity_token", getCsrfToken()); 6115 appendInput("filters_type", "leads_partial"); 6116 appendInput("action_source", "pseo welcome modal"); 6117 leadIds.forEach((leadId) => appendInput("lead_ids[]", String(leadId))); 6118 document.body.appendChild(form); 6119 form.submit(); 6120} 6121function creditsCopy(credits) { 6122 if (credits.singleCreditsBucket) return t("js.leads.pseo_welcome.credits_unified", { 6123 count: credits.credits ?? 0, 6124 formatted_count: CurrencyHelper.numberWithDelimiter(credits.credits ?? 0) 6125 }); 6126 return t("js.leads.pseo_welcome.credits_dual", { 6127 search: CurrencyHelper.numberWithDelimiter(credits.search ?? 0), 6128 verify: CurrencyHelper.numberWithDelimiter(credits.verify ?? 0) 6129 }); 6130} 6131function PseoWelcomeDialog(t0) { 6132 const $ = (0, import_compiler_runtime.c)(62); 6133 const { show, welcome } = t0; 6134 const sessionFlagKey = `onboarding-dialog:shown:${STEP_NAME}:${welcome?.listId ?? "unknown"}`; 6135 let t1; 6136 if ($[0] !== sessionFlagKey || $[1] !== show || $[2] !== welcome) { 6137 t1 = show && welcome !== null && !readSessionFlag(sessionFlagKey); 6138 $[0] = sessionFlagKey; 6139 $[1] = show; 6140 $[2] = welcome; 6141 $[3] = t1; 6142 } else t1 = $[3]; 6143 const eligible = t1; 6144 const [isOpen, setIsOpen] = (0, import_react$1.useState)(false); 6145 const hasPersistedSeenRef = (0, import_react$1.useRef)(false); 6146 const [navigating, setNavigating] = (0, import_react$1.useState)(false); 6147 const navigatingRef = (0, import_react$1.useRef)(false); 6148 let t2; 6149 let t3; 6150 if ($[4] !== eligible || $[5] !== sessionFlagKey) { 6151 t2 = () => { 6152 if (!eligible) return; 6153 const open = () => { 6154 if (readSessionFlag(sessionFlagKey)) return; 6155 writeSessionFlag(sessionFlagKey); 6156 stripWelcomeParam(); 6157 setIsOpen(true); 6158 }; 6159 const timer = window.setTimeout(open, OPEN_DELAY_MS); 6160 const cancel = () => { 6161 window.clearTimeout(timer); 6162 removeInteractionListeners(); 6163 writeSessionFlag(sessionFlagKey); 6164 stripWelcomeParam(); 6165 }; 6166 const interactionEvents = [ 6167 "scroll", 6168 "pointerdown", 6169 "keydown" 6170 ]; 6171 const removeInteractionListeners = () => { 6172 for (const event of interactionEvents) window.removeEventListener(event, cancel); 6173 }; 6174 for (const event_0 of interactionEvents) window.addEventListener(event_0, cancel, { 6175 passive: true, 6176 once: true 6177 }); 6178 return () => { 6179 window.clearTimeout(timer); 6180 removeInteractionListeners(); 6181 }; 6182 }; 6183 t3 = [eligible, sessionFlagKey]; 6184 $[4] = eligible; 6185 $[5] = sessionFlagKey; 6186 $[6] = t2; 6187 $[7] = t3; 6188 } else { 6189 t2 = $[6]; 6190 t3 = $[7]; 6191 } 6192 (0, import_react$1.useEffect)(t2, t3); 6193 let t4; 6194 if ($[8] !== sessionFlagKey) { 6195 t4 = () => { 6196 if (hasPersistedSeenRef.current) return; 6197 hasPersistedSeenRef.current = true; 6198 writeSessionFlag(sessionFlagKey); 6199 fetch(onboarding_steps_path(), { 6200 method: "POST", 6201 headers: { 6202 "Content-Type": "application/json", 6203 "X-CSRF-Token": getCsrfToken() 6204 }, 6205 body: JSON.stringify({ onboarding_step: { 6206 name: STEP_NAME, 6207 seen: true 6208 } }), 6209 keepalive: true 6210 }).catch(_temp); 6211 }; 6212 $[8] = sessionFlagKey; 6213 $[9] = t4; 6214 } else t4 = $[9]; 6215 const markSeen = t4; 6216 let t5; 6217 if ($[10] !== markSeen) { 6218 t5 = () => { 6219 markSeen(); 6220 setIsOpen(false); 6221 }; 6222 $[10] = markSeen; 6223 $[11] = t5; 6224 } else t5 = $[11]; 6225 const handleClose = t5; 6226 let t6; 6227 if ($[12] !== handleClose || $[13] !== isOpen) { 6228 t6 = { 6229 isOpen, 6230 onClose: handleClose 6231 }; 6232 $[12] = handleClose; 6233 $[13] = isOpen; 6234 $[14] = t6; 6235 } else t6 = $[14]; 6236 const { dialogRef, handleBackdropClick, stopPropagation } = useDialog(t6); 6237 let t7; 6238 if ($[15] !== markSeen || $[16] !== welcome) { 6239 t7 = () => { 6240 if (navigatingRef.current || !welcome) return; 6241 navigatingRef.current = true; 6242 setNavigating(true); 6243 markSeen(); 6244 window.location.assign(welcome.discoverHref); 6245 }; 6246 $[15] = markSeen; 6247 $[16] = welcome; 6248 $[17] = t7; 6249 } else t7 = $[17]; 6250 const handleFindMore = t7; 6251 let t8; 6252 if ($[18] !== markSeen || $[19] !== welcome) { 6253 t8 = () => { 6254 if (navigatingRef.current || !welcome) return; 6255 navigatingRef.current = true; 6256 setNavigating(true); 6257 markSeen(); 6258 submitCampaignForm(welcome.campaignsPath, welcome.leadIds); 6259 }; 6260 $[18] = markSeen; 6261 $[19] = welcome; 6262 $[20] = t8; 6263 } else t8 = $[20]; 6264 const handleEmailThem = t8; 6265 if (!isOpen || !welcome) return null; 6266 const emailDisabled = welcome.leadIds.length === 0 || navigating; 6267 let t9; 6268 if ($[21] !== welcome.role) { 6269 t9 = t("js.leads.pseo_welcome.title", { role: welcome.role }); 6270 $[21] = welcome.role; 6271 $[22] = t9; 6272 } else t9 = $[22]; 6273 let t10; 6274 if ($[23] !== t9) { 6275 t10 = /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)(DialogHeader, { 6276 variant: "plain", 6277 children: /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)(DialogTitle, { children: /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("span", { 6278 id: "pseo-welcome-title", 6279 children: t9 6280 }) }) 6281 }); 6282 $[23] = t9; 6283 $[24] = t10; 6284 } else t10 = $[24]; 6285 let t11; 6286 if ($[25] !== welcome.leadsCount || $[26] !== welcome.role) { 6287 t11 = t("js.leads.pseo_welcome.body", {
6288 count: welcome.leadsCount, 6289 formatted_count: CurrencyHelper.numberWithDelimiter(welcome.leadsCount), 6290 role: welcome.role 6291 }); 6292 $[25] = welcome.leadsCount; 6293 $[26] = welcome.role; 6294 $[27] = t11; 6295 } else t11 = $[27]; 6296 let t12; 6297 if ($[28] !== t11) { 6298 t12 = /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)("p", { 6299 className: "pseo-welcome__lead", 6300 children: t11 6301 }); 6302 $[28] = t11; 6303 $[29] = t12; 6304 } else t12 = $[29]; 6305 let t13; 6306 if ($[30] === Symbol.for("react.memo_cache_sentinel")) { 6307 t13 = /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)(Icon, { 6308 icon: "bolt", 6309 variant: "regular" 6310 }); 6311 $[30] = t13; 6312 } else t13 = $[30]; 6313 let t14; 6314 if ($[31] !== welcome.credits) { 6315 t14 = creditsCopy(welcome.credits); 6316 $[31] = welcome.credits; 6317 $[32] = t14; 6318 } else t14 = $[32]; 6319 let t15; 6320 if ($[33] !== t14) { 6321 t15 = /* @__PURE__ */ (0, import_jsx_runtime$1.jsxs)("p", { 6322 className: "pseo-welcome__credits", 6323 children: [t13, t14] 6324 }); 6325 $[33] = t14; 6326 $[34] = t15; 6327 } else t15 = $[34]; 6328 let t16; 6329 if ($[35] !== t12 || $[36] !== t15) { 6330 t16 = /* @__PURE__ */ (0, import_jsx_runtime$1.jsxs)(DialogBody, { children: [t12, t15] }); 6331 $[35] = t12; 6332 $[36] = t15; 6333 $[37] = t16; 6334 } else t16 = $[37]; 6335 let t17; 6336 if ($[38] !== welcome.role) { 6337 t17 = t("js.leads.pseo_welcome.email_them", { role: welcome.role }); 6338 $[38] = welcome.role; 6339 $[39] = t17; 6340 } else t17 = $[39]; 6341 let t18; 6342 if ($[40] !== emailDisabled || $[41] !== handleEmailThem || $[42] !== t17) { 6343 t18 = /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)(Button, { 6344 type: "button", 6345 variant: "default", 6346 onClick: handleEmailThem, 6347 disabled: emailDisabled, 6348 children: t17 6349 }); 6350 $[40] = emailDisabled; 6351 $[41] = handleEmailThem; 6352 $[42] = t17; 6353 $[43] = t18; 6354 } else t18 = $[43]; 6355 let t19; 6356 if ($[44] !== welcome.role) { 6357 t19 = t("js.leads.pseo_welcome.find_more", { role: welcome.role }); 6358 $[44] = welcome.role; 6359 $[45] = t19; 6360 } else t19 = $[45]; 6361 let t20; 6362 if ($[46] !== handleFindMore || $[47] !== navigating || $[48] !== t19) { 6363 t20 = /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)(Button, { 6364 type: "button", 6365 variant: "ghost", 6366 onClick: handleFindMore, 6367 disabled: navigating, 6368 children: t19 6369 }); 6370 $[46] = handleFindMore; 6371 $[47] = navigating; 6372 $[48] = t19; 6373 $[49] = t20; 6374 } else t20 = $[49]; 6375 let t21; 6376 if ($[50] !== t18 || $[51] !== t20) { 6377 t21 = /* @__PURE__ */ (0, import_jsx_runtime$1.jsxs)(DialogFooter, { children: [t18, t20] }); 6378 $[50] = t18; 6379 $[51] = t20; 6380 $[52] = t21; 6381 } else t21 = $[52]; 6382 let t22; 6383 if ($[53] !== t10 || $[54] !== t16 || $[55] !== t21) { 6384 t22 = /* @__PURE__ */ (0, import_jsx_runtime$1.jsxs)(DialogContent, { children: [ 6385 t10, 6386 t16, 6387 t21 6388 ] }); 6389 $[53] = t10; 6390 $[54] = t16; 6391 $[55] = t21; 6392 $[56] = t22; 6393 } else t22 = $[56]; 6394 let t23; 6395 if ($[57] !== dialogRef || $[58] !== handleBackdropClick || $[59] !== stopPropagation || $[60] !== t22) { 6396 t23 = /* @__PURE__ */ (0, import_jsx_runtime$1.jsx)(Dialog, { 6397 ref: dialogRef, 6398 onClick: handleBackdropClick, 6399 onPointerDown: stopPropagation, 6400 onMouseDown: stopPropagation, 6401 "aria-labelledby": "pseo-welcome-title", 6402 children: t22 6403 }); 6404 $[57] = dialogRef; 6405 $[58] = handleBackdropClick; 6406 $[59] = stopPropagation; 6407 $[60] = t22; 6408 $[61] = t23; 6409 } else t23 = $[61]; 6410 return t23; 6411} 6412function _temp() {} 6413var import_compiler_runtime, import_react$1, import_jsx_runtime$1, STEP_NAME, OPEN_DELAY_MS, WELCOME_PARAM, t; 6414function init_pseo_welcome_dialog() { 6415 return (init_pseo_welcome_dialog = __esmMin((() => { 6416 import_compiler_runtime = require_compiler_runtime(); 6417 import_react$1 = require_react(); 6418 init_dialog(); 6419 init_button(); 6420 init_icon(); 6421 init_useDialog(); 6422 init_routes(); 6423 init_utils(); 6424 init_currency_helper(); 6425 import_jsx_runtime$1 = require_jsx_runtime(); 6426 STEP_NAME = "pseo_welcome"; 6427 OPEN_DELAY_MS = 2e3; 6428 WELCOME_PARAM = "welcome"; 6429 t = (key, options) => window.i18n.t(key, options); 6430 })))(); 6431} 6432//#endregion 6433//#region app/frontend/pages/Leads/Index.tsx 6434function normalizeFilters(filters) { 6435 const normalized = {}; 6436 for (const [key, value] of Object.entries(filters)) { 6437 const normalizedKey = key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase(); 6438 normalized[normalizedKey] = Array.isArray(value) ? value.join("|") : String(value); 6439 } 6440 return normalized; 6441} 6442function pinnedImportId() { 6443 return new URLSearchParams(window.location.search).get("leads_import_id") ?? void 0; 6444} 6445function Index() { 6446 const { props } = usePage(); 6447 const { columns, visibleColumnNames, editableColumnNames, customAttributes, formOptions, hasSyncableApps, syncableApps, lookalikes, featureFlags, verificationBanner, verifyCreditsInfo, totalOwnedLeads, showLeadsReorganizationTour, showPseoWelcome, pseoWelcome, currentUser } = props; 6448 useScopedBodyClass("leads index"); 6449 const { open: insightsOpen, toggle: toggleInsights } = useInsightsPanel("leads_insights_panel_open"); 6450 const [pageSize, setPageSize] = (0, import_react.useState)(props.pageSize); 6451 const [sidebar, setSidebar] = (0, import_react.useState)(props.sidebar); 6452 (0, import_react.useEffect)(() => { 6453 setSidebar(props.sidebar); 6454 }, [props.sidebar]); 6455 const [leadsList, setLeadsList] = (0, import_react.useState)(props.leadsList); 6456 const [leads, setLeads] = (0, import_react.useState)(props.leads); 6457 const [sort, setSort] = (0, import_react.useState)(props.sort); 6458 const [direction, setDirection] = (0, import_react.useState)(props.direction); 6459 const [offset, setOffset] = (0, import_react.useState)(props.offset); 6460 const [totalCount, setTotalCount] = (0, import_react.useState)(props.totalCount);
6461 const [totalCountApproximate, setTotalCountApproximate] = (0, import_react.useState)(props.totalCountApproximate ?? false); 6462 const [hasMoreLeads, setHasMoreLeads] = (0, import_react.useState)(props.hasMoreLeads); 6463 const [query, setQuery] = (0, import_react.useState)(props.query); 6464 const [filters, setFilters] = (0, import_react.useState)(() => normalizeFilters(props.filters)); 6465 const [leadsImport, setLeadsImport] = (0, import_react.useState)(props.leadsImport); 6466 const [hasPendingImport, setHasPendingImport] = (0, import_react.useState)(props.hasPendingImport); 6467 const importScopeId = leadsList.type === "virtual" ? null : leadsList.id; 6468 const importScopeIdRef = (0, import_react.useRef)(importScopeId); 6469 importScopeIdRef.current = importScopeId; 6470 (0, import_react.useEffect)(() => { 6471 if (props.leadsImportScopeId !== importScopeIdRef.current) return; 6472 setLeadsImport(props.leadsImport); 6473 setHasPendingImport(props.hasPendingImport); 6474 }, [ 6475 props.leadsImport, 6476 props.hasPendingImport, 6477 props.leadsImportScopeId 6478 ]); 6479 const [availableTags, setAvailableTags] = (0, import_react.useState)(props.availableTags); 6480 const { selection, selectedCount, isSelected, toggleRow, selectAll, selectPage, selectCount, clearSelection: clearBulkSelection, removeId } = useBulkSelection(totalCount); 6481 const selectCountAbortRef = (0, import_react.useRef)(null); 6482 const clearSelection = (0, import_react.useCallback)(() => { 6483 selectCountAbortRef.current?.abort(); 6484 clearBulkSelection(); 6485 }, [clearBulkSelection]); 6486 const cancelPendingCount = (0, import_react.useCallback)(() => { 6487 selectCountAbortRef.current?.abort(); 6488 selectCountAbortRef.current = null; 6489 }, []); 6490 const [selectedLeadId, setSelectedLeadId] = (0, import_react.useState)(props.initialSelectedLeadId ?? null); 6491 const [selectedCompany, setSelectedCompany] = (0, import_react.useState)(null); 6492 const [enrichingLeadIds, setEnrichingLeadIds] = (0, import_react.useState)(() => /* @__PURE__ */ new Set()); 6493 const recentEnrichmentsRef = (0, import_react.useRef)(/* @__PURE__ */ new Map()); 6494 const enrichFallbackTimersRef = (0, import_react.useRef)(/* @__PURE__ */ new Map()); 6495 const stopEnriching = (leadId) => setEnrichingLeadIds((prev) => { 6496 if (!prev.has(leadId)) return prev; 6497 const next = new Set(prev); 6498 next.delete(leadId); 6499 return next; 6500 }); 6501 (0, import_react.useEffect)(() => { 6502 const timers = enrichFallbackTimersRef.current; 6503 return () => { 6504 timers.forEach((timer) => window.clearTimeout(timer)); 6505 timers.clear(); 6506 }; 6507 }, []); 6508 const [sidePanelMode, setSidePanelMode] = (0, import_react.useState)(() => { 6509 if (!("window" in globalThis)) return "view"; 6510 return parseLeadPath(window.location.pathname)?.mode ?? "view"; 6511 }); 6512 const [sidePanelInitialTab, setSidePanelInitialTab] = (0, import_react.useState)("activity"); 6513 const [sidePanelInitialStateKey, setSidePanelInitialStateKey] = (0, import_react.useState)(0); 6514 const [preloadedLead, setPreloadedLead] = (0, import_react.useState)(props.initialSelectedLead ?? null); 6515 const [showCreateLead, setShowCreateLead] = (0, import_react.useState)(false); 6516 const [localVisibleColumnNames, setLocalVisibleColumnNames] = (0, import_react.useState)(visibleColumnNames); 6517 const [bulkModal, setBulkModal] = (0, import_react.useState)(null); 6518 const [verifyAllSelection, setVerifyAllSelection] = (0, import_react.useState)(null); 6519 const [verifyAllLaunchedSignal, setVerifyAllLaunchedSignal] = (0, import_react.useState)(0); 6520 const [deleteLeadId, setDeleteLeadId] = (0, import_react.useState)(null); 6521 const [showCreateCustomAttribute, setShowCreateCustomAttribute] = (0, import_react.useState)(false); 6522 const [showSaveFilteredList, setShowSaveFilteredList] = (0, import_react.useState)(false); 6523 const abortControllerRef = (0, import_react.useRef)(null); 6524 const selectionStaleUnderModalRef = (0, import_react.useRef)(false); 6525 const pendingPanelCheckRef = (0, import_react.useRef)(null); 6526 const selectedLeadIdRef = (0, import_react.useRef)(selectedLeadId); 6527 const sidePanelModeRef = (0, import_react.useRef)(sidePanelMode); 6528 (0, import_react.useLayoutEffect)(() => { 6529 selectedLeadIdRef.current = selectedLeadId; 6530 }, [selectedLeadId]); 6531 (0, import_react.useLayoutEffect)(() => { 6532 sidePanelModeRef.current = sidePanelMode; 6533 }, [sidePanelMode]); 6534 const selectedLead = (0, import_react.useMemo)(() => { 6535 if (selectedLeadId === null) return null; 6536 return leads.find((l) => l.id === selectedLeadId) ?? (preloadedLead?.id === selectedLeadId ? preloadedLead : null); 6537 }, [ 6538 leads, 6539 selectedLeadId, 6540 preloadedLead 6541 ]); 6542 const formOptionsWithTags = (0, import_react.useMemo)(() => ({ 6543 ...formOptions, 6544 availableTags: availableTags.map((tag) => ({ 6545 value: String(tag.id), 6546 label: tag.name 6547 })) 6548 }), [formOptions, availableTags]); 6549 const fetchLeads = (0, import_react.useCallback)(async (params) => { 6550 abortControllerRef.current?.abort(); 6551 const controller = new AbortController(); 6552 abortControllerRef.current = controller; 6553 const searchParams = new URLSearchParams(); 6554 for (const [key, value] of Object.entries(params)) { 6555 if (value === void 0 || value === null || value === "") continue; 6556 if (Array.isArray(value)) value.forEach((item) => searchParams.append(key, item)); 6557 else searchParams.append(key, String(value)); 6558 } 6559 const urlMode = sidePanelModeRef.current === "edit" ? "edit" : "view"; 6560 const newUrl = buildLeadsUrl(searchParams, selectedLeadIdRef.current, urlMode); 6561 if (newUrl !== `${window.location.pathname}${window.location.search}`) { 6562 if (newUrl.split("?")[0] === window.location.pathname) window.history.replaceState({}, "", newUrl); 6563 else window.history.pushState({}, "", newUrl); 6564 } 6565 try { 6566 const response = await fetch(`${leads_path({ format: "json" })}?${searchParams.toString()}`, { 6567 signal: controller.signal, 6568 headers: { 6569 "X-CSRF-Token": getCsrfToken(), 6570 Accept: "application/json" 6571 } 6572 }); 6573 if (response.status === 404) { 6574 router.visit(leads_path()); 6575 return; 6576 } 6577 if (!response.ok) throw new Error("Failed to fetch leads"); 6578 const data = await response.json(); 6579 setLeads(data.leads.map((l_0) => { 6580 const enrichment = recentEnrichmentsRef.current.get(l_0.id); 6581 if (!enrichment) return l_0; 6582 if (l_0.domainId === enrichment.domainId) { 6583 recentEnrichmentsRef.current.delete(l_0.id); 6584 return l_0; 6585 } 6586 return { 6587 ...l_0, 6588 ...enrichment 6589 }; 6590 })); 6591 if (data.leadsList) setLeadsList((selectedList) => selectedList.id === data.leadsList.id && selectedList.type === "dynamic" ? { 6592 ...data.leadsList, 6593 leadsCount: selectedList.leadsCount 6594 } : data.leadsList); 6595 setLeadsImport(data.leadsImport); 6596 setHasPendingImport(data.hasPendingImport); 6597 setTotalCount(data.totalCount); 6598 setTotalCountApproximate(data.totalCountApproximate ?? false); 6599 setHasMoreLeads(data.hasMoreLeads); 6600 setOffset(data.offset); 6601 setSort(data.sort); 6602 setDirection(data.direction); 6603 setQuery(data.query); 6604 setFilters((prev_0) => { 6605 const next_0 = normalizeFilters(data.filters); 6606 if (JSON.stringify(prev_0) === JSON.stringify(next_0)) return prev_0; 6607 return next_0; 6608 }); 6609 return data; 6610 } catch (error) {
6611 if (error instanceof DOMException && error.name === "AbortError") return void 0; 6612 } 6613 }, []); 6614 (0, import_react.useEffect)(() => { 6615 function handlePopState() { 6616 clearSelection(); 6617 setSelectedCompany(null); 6618 const url = new URL(window.location.href); 6619 const parsed = parseLeadPath(url.pathname); 6620 if (parsed) { 6621 setSelectedLeadId(parsed.leadId); 6622 setSidePanelMode(parsed.mode); 6623 setSidePanelInitialTab("activity"); 6624 setSidePanelInitialStateKey((key_0) => key_0 + 1); 6625 if (parsed.leadId !== preloadedLead?.id) fetch(lead_path(parsed.leadId, { format: "json" }), { headers: { 6626 "X-CSRF-Token": getCsrfToken(), 6627 Accept: "application/json" 6628 } }).then((r) => r.ok ? r.json() : null).then((lead) => { 6629 if (lead) setPreloadedLead(lead); 6630 }).catch(() => {}); 6631 } else { 6632 setSelectedLeadId(null); 6633 setSidePanelMode("view"); 6634 setSidePanelInitialTab("activity"); 6635 setSidePanelInitialStateKey((key_1) => key_1 + 1); 6636 setPreloadedLead(null); 6637 } 6638 fetchLeads(searchParamsToRecord(url.searchParams)); 6639 } 6640 window.addEventListener("popstate", handlePopState); 6641 return () => window.removeEventListener("popstate", handlePopState); 6642 }, [ 6643 fetchLeads, 6644 clearSelection, 6645 preloadedLead?.id 6646 ]); 6647 const syncUrlToState = (0, import_react.useCallback)((leadId_0, mode) => { 6648 const current_0 = new URL(window.location.href); 6649 const urlMode_0 = mode === "edit" ? "edit" : "view"; 6650 const target = buildLeadsUrl(current_0.searchParams, leadId_0, urlMode_0); 6651 if (target === `${window.location.pathname}${window.location.search}`) return; 6652 if (target.split("?")[0] === window.location.pathname) window.history.replaceState({}, "", target); 6653 else window.history.pushState({}, "", target); 6654 }, []); 6655 const openLead = (0, import_react.useCallback)((leadId_1, mode_0, initialTab = "activity") => { 6656 setSelectedCompany(null); 6657 setSidePanelMode(mode_0); 6658 setSidePanelInitialTab(initialTab); 6659 setSidePanelInitialStateKey((key_2) => key_2 + 1); 6660 setSelectedLeadId(leadId_1); 6661 syncUrlToState(leadId_1, mode_0); 6662 if (!leads.find((l_1) => l_1.id === leadId_1) && preloadedLead?.id !== leadId_1) fetch(lead_path(leadId_1, { format: "json" }), { headers: { 6663 "X-CSRF-Token": getCsrfToken(), 6664 Accept: "application/json" 6665 } }).then((r_0) => r_0.ok ? r_0.json() : null).then((lead_0) => { 6666 if (selectedLeadIdRef.current !== leadId_1) return; 6667 if (lead_0) setPreloadedLead(lead_0); 6668 else { 6669 setSelectedLeadId(null); 6670 syncUrlToState(null, "view"); 6671 } 6672 }).catch(() => { 6673 if (selectedLeadIdRef.current === leadId_1) { 6674 setSelectedLeadId(null); 6675 syncUrlToState(null, "view"); 6676 } 6677 }); 6678 }, [ 6679 syncUrlToState, 6680 leads, 6681 preloadedLead 6682 ]); 6683 const closeLead = (0, import_react.useCallback)(() => { 6684 setSelectedLeadId(null); 6685 setSidePanelMode("view"); 6686 setSidePanelInitialTab("activity"); 6687 setSidePanelInitialStateKey((key_3) => key_3 + 1); 6688 setPreloadedLead(null); 6689 syncUrlToState(null, "view"); 6690 }, [syncUrlToState]); 6691 const openCompany = (0, import_react.useCallback)((domainId, companyName) => { 6692 if (selectedLeadId !== null) closeLead(); 6693 setShowCreateLead(false); 6694 setShowSaveFilteredList(false); 6695 setSelectedCompany({ 6696 domainId, 6697 companyName 6698 }); 6699 }, [closeLead, selectedLeadId]); 6700 (0, import_react.useEffect)(() => { 6701 function closeCompanyPanel() { 6702 setSelectedCompany(null); 6703 } 6704 document.addEventListener("lookalikes-sheet-opened", closeCompanyPanel); 6705 return () => document.removeEventListener("lookalikes-sheet-opened", closeCompanyPanel); 6706 }, []); 6707 const closeLeadRef = useLatestRef(closeLead); 6708 const handleListOperationRef = (0, import_react.useRef)(() => {}); 6709 const handleListsDeletedRef = (0, import_react.useRef)(() => {}); 6710 const previousListIdRef = (0, import_react.useRef)(props.leadsList.id); 6711 (0, import_react.useEffect)(() => { 6712 if (props.leadsList.id !== previousListIdRef.current) { 6713 previousListIdRef.current = props.leadsList.id; 6714 closeLead(); 6715 setSelectedCompany(null); 6716 } 6717 }, [props.leadsList.id, closeLead]); 6718 const buildQueryParams = (0, import_react.useCallback)((overrides = {}) => { 6719 return { 6720 ...filters, 6721 sort, 6722 direction, 6723 offset: 0, 6724 page_size: pageSize, 6725 query: query || void 0, 6726 leads_list_id: leadsList.type !== "virtual" ? leadsList.id : void 0, 6727 leads_import_id: pinnedImportId(), 6728 ...overrides 6729 }; 6730 }, [ 6731 filters, 6732 sort, 6733 direction, 6734 query, 6735 leadsList, 6736 pageSize 6737 ]); 6738 const handleImportComplete = (0, import_react.useCallback)(async () => { 6739 await fetchLeads(buildQueryParams()); 6740 router.reload({ 6741 only: ["sidebar"], 6742 preserveUrl: true 6743 }); 6744 }, [fetchLeads, buildQueryParams]); 6745 const { displayPercentage, isPolling, isCompleting, isDone, timeLeftText } = useImportProgress(leadsImport, { 6746 onComplete: handleImportComplete, 6747 scopeKey: importScopeId 6748 }); 6749 function handleSort(columnName, newDirection) { 6750 clearSelection(); 6751 fetchLeads(buildQueryParams({ 6752 sort: columnName, 6753 direction: newDirection, 6754 offset: 0 6755 })); 6756 } 6757 function handlePageChange(newOffset) { 6758 fetchLeads(buildQueryParams({ offset: newOffset })); 6759 } 6760 function handlePageSizeChange(newPageSize) { 6761 setPageSize(newPageSize); 6762 clearSelection(); 6763 fetch(settings_leads_path(), { 6764 method: "PATCH", 6765 headers: { 6766 "Content-Type": "application/json", 6767 "X-CSRF-Token": getCsrfToken() 6768 }, 6769 body: JSON.stringify({ user: { leads_page_size: newPageSize } }) 6770 }).catch(() => {}); 6771 fetchLeads(buildQueryParams({ 6772 offset: 0, 6773 page_size: newPageSize 6774 })); 6775 } 6776 function handleSearch(searchQuery) { 6777 clearSelection(); 6778 fetchLeads(buildQueryParams({ 6779 query: searchQuery || void 0, 6780 offset: 0 6781 })); 6782 } 6783 function handleListSelect(listId) { 6784 clearSelection(); 6785 closeLead(); 6786 setSelectedCompany(null); 6787 fetchLeads({ 6788 sort, 6789 direction, 6790 offset: 0, 6791 leads_list_id: listId ?? void 0 6792 }); 6793 } 6794 function handleListCreated(newList) { 6795 setSidebar((prev_1) => ({ 6796 ...prev_1, 6797 leadsLists: [...prev_1.leadsLists, newList] 6798 })); 6799 handleListSelect(newList.id); 6800 } 6801 const handleLeadsCountRefresh = (0, import_react.useCallback)((listId_0, leadsCount) => { 6802 setSidebar((prev_2) => ({ 6803 ...prev_2, 6804 leadsLists: prev_2.leadsLists.map((list) => list.id === listId_0 ? { 6805 ...list, 6806 leadsCount 6807 } : list) 6808 })); 6809 setLeadsList((prev_3) => prev_3.id === listId_0 && prev_3.leadsCount !== leadsCount ? { 6810 ...prev_3, 6811 leadsCount 6812 } : prev_3); 6813 }, []); 6814 const decrementSelectedLeadsCount = (0, import_react.useCallback)((listId_1, count) => { 6815 if (count <= 0) return; 6816 setLeadsList((current_1) => current_1.id === listId_1 ? { 6817 ...current_1, 6818 leadsCount: Math.max(0, current_1.leadsCount - count) 6819 } : current_1); 6820 }, []); 6821 function handleFilterApply(newFilters, options = {}) { 6822 clearSelection(); 6823 const params_1 = { 6824 ...normalizeFilters(newFilters), 6825 sort, 6826 direction, 6827 offset: 0, 6828 query: query || void 0, 6829 leads_list_id: leadsList.type !== "virtual" ? leadsList.id : void 0, 6830 leads_import_id: pinnedImportId(), 6831 filters_changed: 1 6832 }; 6833 if (options.filterFromChart) params_1.filter_from_chart = "true"; 6834 fetchLeads(params_1); 6835 } 6836 function handleSingleFilterApply(name, value_0) { 6837 const newFilters_0 = { ...filters }; 6838 if (value_0 === "") delete newFilters_0[name]; 6839 else newFilters_0[name] = value_0; 6840 handleFilterApply(newFilters_0); 6841 } 6842 function handleRemoveFilter(filterName) { 6843 const newFilters_1 = { ...filters }; 6844 delete newFilters_1[filterName]; 6845 handleFilterApply(newFilters_1); 6846 } 6847 function handleBatchFilterApply(batchFilters) { 6848 const newFilters_2 = { ...filters }; 6849 for (const [name_0, value_1] of Object.entries(batchFilters)) if (value_1 === "") delete newFilters_2[name_0]; 6850 else newFilters_2[name_0] = value_1; 6851 handleFilterApply(newFilters_2); 6852 } 6853 function handleRemoveBatchFilter(names) { 6854 const newFilters_3 = { ...filters }; 6855 for (const name_1 of names) delete newFilters_3[name_1]; 6856 handleFilterApply(newFilters_3); 6857 } 6858 const handleLeadDeleted = (0, import_react.useCallback)((deletedLeadId) => { 6859 if (selectedLeadId === deletedLeadId) closeLead(); 6860 removeId(deletedLeadId); 6861 setDeleteLeadId(null); 6862 fetchLeads(buildQueryParams()); 6863 setSidebar((prev_4) => ({ 6864 ...prev_4, 6865 allLeadsList: prev_4.allLeadsList ? { 6866 ...prev_4.allLeadsList, 6867 leadsCount: Math.max(0, prev_4.allLeadsList.leadsCount - 1) 6868 } : prev_4.allLeadsList, 6869 leadsLists: prev_4.leadsLists.map((l_2) => l_2.id === leadsList.id ? { 6870 ...l_2, 6871 leadsCount: Math.max(0, l_2.leadsCount - 1) 6872 } : l_2) 6873 })); 6874 decrementSelectedLeadsCount(leadsList.id, 1); 6875 toast.success(window.i18n.t("js.leads.page.sidepanel.delete_success")); 6876 }, [ 6877 selectedLeadId, 6878 closeLead, 6879 removeId, 6880 fetchLeads, 6881 buildQueryParams, 6882 leadsList.id, 6883 decrementSelectedLeadsCount 6884 ]); 6885 const handleTagsChange = (0, import_react.useCallback)((leadId_2, newTags, newAvailableTag) => { 6886 setLeads((prev_5) => prev_5.map((l_3) => l_3.id === leadId_2 ? { 6887 ...l_3, 6888 tags: newTags 6889 } : l_3)); 6890 if (newAvailableTag) setAvailableTags((prev_6) => { 6891 if (prev_6.some((t) => t.id === newAvailableTag.id)) return prev_6; 6892 return [...prev_6, newAvailableTag]; 6893 }); 6894 }, []); 6895 const handleTagUpdate = (0, import_react.useCallback)((updatedTag) => { 6896 setAvailableTags((prev_7) => prev_7.map((t_0) => t_0.id === updatedTag.id ? updatedTag : t_0)); 6897 setLeads((prev_8) => prev_8.map((l_4) => { 6898 if (!l_4.tags.some((t_1) => t_1.id === updatedTag.id)) return l_4; 6899 return { 6900 ...l_4, 6901 tags: l_4.tags.map((t_2) => t_2.id === updatedTag.id ? { 6902 id: updatedTag.id, 6903 name: updatedTag.name, 6904 color: updatedTag.color 6905 } : t_2) 6906 }; 6907 })); 6908 }, []); 6909 function handleTagDelete(tagId) { 6910 setAvailableTags((prev_9) => prev_9.filter((t_3) => t_3.id !== tagId)); 6911 setLeads((prev_10) => prev_10.map((l_5) => { 6912 const filtered = l_5.tags.filter((t_4) => t_4.id !== tagId); 6913 if (filtered.length === l_5.tags.length) return l_5; 6914 return { 6915 ...l_5, 6916 tags: filtered 6917 }; 6918 })); 6919 if (filters.tags?.split("|").includes(String(tagId))) handleSingleFilterApply("tags", filters.tags.split("|").filter((id) => id !== String(tagId)).join("|")); 6920 } 6921 function handleClearAllFilters() { 6922 handleFilterApply({}); 6923 } 6924 const handleVerifyRequested = (0, import_react.useCallback)((leadId_3) => { 6925 setLeads((prev_11) => prev_11.map((l_6) => l_6.id === leadId_3 ? { 6926 ...l_6, 6927 verificationStatus: "pending" 6928 }
6928 : l_6)); 6929 }, []); 6930 const handleFindEmailRequested = (0, import_react.useCallback)((leadId_4) => { 6931 setLeads((prev_12) => prev_12.map((l_7) => l_7.id === leadId_4 ? { 6932 ...l_7, 6933 emailFinderStatus: "pending" 6934 } : l_7)); 6935 }, []); 6936 const handleFindEmailFailed = (0, import_react.useCallback)((leadId_5) => { 6937 setLeads((prev_13) => prev_13.map((l_8) => l_8.id === leadId_5 ? { 6938 ...l_8, 6939 emailFinderStatus: null 6940 } : l_8)); 6941 }, []); 6942 const cableParams = (0, import_react.useMemo)(() => ({ channel: "LeadsChannel" }), []); 6943 const cableCallbacks = (0, import_react.useMemo)(() => ({ received: (data_0) => { 6944 const msg = data_0; 6945 if (msg.type === "verification_update" && msg.lead_id) setLeads((prev_14) => prev_14.map((l_9) => l_9.id === msg.lead_id ? { 6946 ...l_9, 6947 verificationStatus: msg.verification_status ?? l_9.verificationStatus, 6948 confidenceScore: msg.confidence_score ?? l_9.confidenceScore, 6949 verificationDate: msg.verification_date ?? l_9.verificationDate 6950 } : l_9)); 6951 if (msg.type === "email_finder_update" && msg.lead_id) setLeads((prev_15) => prev_15.map((l_10) => l_10.id === msg.lead_id ? { 6952 ...l_10, 6953 email: unsafeCast(msg.email) ?? l_10.email, 6954 emailFinderStatus: unsafeCast(msg.email_finder_status) ?? l_10.emailFinderStatus, 6955 originalLeadId: unsafeCast(msg.original_lead_id) ?? l_10.originalLeadId, 6956 originalLeadEmail: "original_lead_email" in msg ? unsafeCast(msg.original_lead_email) : l_10.originalLeadEmail, 6957 confidenceScore: unsafeCast(msg.confidence_score) ?? l_10.confidenceScore, 6958 verificationStatus: unsafeCast(msg.verification_status) ?? l_10.verificationStatus, 6959 company: unsafeCast(msg.company) ?? l_10.company, 6960 website: unsafeCast(msg.website) ?? l_10.website 6961 } : l_10)); 6962 if (msg.type === "enrichment_update" && msg.lead_id) { 6963 const enrichedLeadId = unsafeCast(msg.lead_id); 6964 recentEnrichmentsRef.current.set(enrichedLeadId, { 6965 domainId: unsafeCast(msg.domain_id), 6966 company: unsafeCast(msg.company), 6967 website: unsafeCast(msg.website), 6968 companyIndustry: unsafeCast(msg.company_industry), 6969 companySize: unsafeCast(msg.company_size), 6970 companyType: unsafeCast(msg.company_type) 6971 }); 6972 window.setTimeout(() => recentEnrichmentsRef.current.delete(enrichedLeadId), 15e3); 6973 setEnrichingLeadIds((prev_16) => { 6974 if (!prev_16.has(enrichedLeadId)) return prev_16; 6975 const next_1 = new Set(prev_16); 6976 next_1.delete(enrichedLeadId); 6977 return next_1; 6978 }); 6979 setLeads((prev_17) => prev_17.map((l_11) => l_11.id === msg.lead_id ? { 6980 ...l_11, 6981 domainId: unsafeCast(msg.domain_id) ?? l_11.domainId, 6982 company: unsafeCast(msg.company) ?? l_11.company, 6983 website: unsafeCast(msg.website) ?? l_11.website, 6984 companyIndustry: unsafeCast(msg.company_industry) ?? l_11.companyIndustry, 6985 companySize: unsafeCast(msg.company_size) ?? l_11.companySize, 6986 companyType: unsafeCast(msg.company_type) ?? l_11.companyType 6987 } : l_11)); 6988 } 6989 if (msg.type === "lead_merged" && msg.lead_id) { 6990 setLeads((prev_18) => prev_18.filter((l_12) => l_12.id !== msg.lead_id)); 6991 if (selectedLeadIdRef.current === msg.lead_id) closeLeadRef.current(); 6992 } 6993 if (msg.type === "leads_list_operation") handleListOperationRef.current(unsafeCast(msg)); 6994 if (msg.type === "leads_lists_deleted") handleListsDeletedRef.current(unsafeCast(msg)); 6995 } }), []); 6996 useActionCable({ 6997 params: cableParams, 6998 callbacks: cableCallbacks 6999 }); 7000 const [deletingOperation, setDeletingOperation] = (0, import_react.useState)(null); 7001 const isDeletionInProgress = deletingOperation !== null; 7002 const settledOperationIdRef = (0, import_react.useRef)(null); 7003 const reloadSidebar = (0, import_react.useCallback)(() => { 7004 router.reload({ 7005 only: ["sidebar"], 7006 preserveUrl: true, 7007 onHttpException: (response_0) => { 7008 if (response_0.status !== 404) return; 7009 router.visit(leads_path()); 7010 return false; 7011 } 7012 }); 7013 }, []); 7014 const refreshLeadsFromCurrentUrl = (0, import_react.useCallback)(() => { 7015 const url_0 = new URL(window.location.href); 7016 return fetchLeads(searchParamsToRecord(url_0.searchParams)); 7017 }, [fetchLeads]); 7018 const handleListOperation = (0, import_react.useCallback)((msg_0) => { 7019 const view = urlView(window.location.href, leadsList, sidebar.leadsLists); 7020 const refresh = listOperationRefresh(msg_0, view.list, view.scope); 7021 if (refresh === "leave-list") { 7022 router.visit(msg_0.destination_leads_list_id ? leads_path({ leads_list_id: msg_0.destination_leads_list_id }) : leads_path()); 7023 return; 7024 } 7025 if (refresh === "wait") return; 7026 reloadSidebar(); 7027 if (refresh === "refetch") { 7028 if (bulkModal === null) clearSelection(); 7029 else selectionStaleUnderModalRef.current = true; 7030 pendingPanelCheckRef.current = selectedLeadIdRef.current; 7031 refreshLeadsFromCurrentUrl(); 7032 } 7033 }, [ 7034 leadsList, 7035 sidebar.leadsLists, 7036 bulkModal, 7037 clearSelection, 7038 refreshLeadsFromCurrentUrl, 7039 reloadSidebar 7040 ]); 7041 (0, import_react.useEffect)(() => { 7042 const openLeadId = pendingPanelCheckRef.current; 7043 if (openLeadId === null) return; 7044 pendingPanelCheckRef.current = null; 7045 if (selectedLeadId !== openLeadId) return; 7046 if (!leads.some((lead_1) => lead_1.id === openLeadId) && preloadedLead?.id !== openLeadId) closeLead(); 7047 }, [ 7048 leads, 7049 selectedLeadId, 7050 preloadedLead?.id, 7051 closeLead 7052 ]); 7053 (0, import_react.useLayoutEffect)(() => { 7054 handleListOperationRef.current = handleListOperation; 7055 }, [handleListOperation]); 7056 const handleListsDeleted = (0, import_react.useCallback)((msg_1) => { 7057 const deletedIds = msg_1.leads_list_ids ?? []; 7058 const view_0 = urlView(window.location.href, leadsList, sidebar.leadsLists); 7059 const viewingDeletedList = view_0.list.type !== "virtual" && deletedIds.includes(view_0.list.id); 7060 const scopedListIds = view_0.scope.listIds; 7061 const scopeFullyDeleted = scopedListIds.length > 0 && scopedListIds.every((id_0) => deletedIds.includes(id_0)); 7062 if (viewingDeletedList || scopeFullyDeleted) { 7063 router.visit(msg_1.destination_leads_list_id ? leads_path({ leads_list_id: msg_1.destination_leads_list_id }) : leads_path()); 7064 return; 7065 } 7066 reloadSidebar(); 7067 }, [ 7068 leadsList, 7069 sidebar.leadsLists, 7070 reloadSidebar 7071 ]); 7072 (0, import_react.useLayoutEffect)(() => { 7073 handleListsDeletedRef.current = handleListsDeleted; 7074 }, [handleListsDeleted]); 7075 const finishDeletion = (0, import_react.useCallback)((op) => { 7076 if (settledOperationIdRef.current === op.id) return; 7077 settledOperationIdRef.current = op.id; 7078 toast.success(window.i18n.t("js.leads.page.bulk_actions.deleted_count", {
7079 count: op.count, 7080 formatted_count: CurrencyHelper.numberWithDelimiter(op.count) 7081 }), { id: `delete-op-${op.id}` }); 7082 refreshLeadsFromCurrentUrl(); 7083 reloadSidebar(); 7084 setDeletingOperation(null); 7085 }, [refreshLeadsFromCurrentUrl, reloadSidebar]); 7086 const failDeletion = (0, import_react.useCallback)((op_0) => { 7087 if (settledOperationIdRef.current === op_0.id) return; 7088 settledOperationIdRef.current = op_0.id; 7089 toast.danger(window.i18n.t("js.leads.page.bulk_actions.delete_failed"), { id: `delete-op-${op_0.id}` }); 7090 setDeletingOperation(null); 7091 }, []); 7092 const operationsChannelParams = (0, import_react.useMemo)(() => ({ channel: "OperationsChannel" }), []); 7093 const handleDeleteOperationReceived = (0, import_react.useCallback)((data_1) => { 7094 const op_1 = data_1.operation; 7095 if (!op_1 || op_1.kind !== "leads/delete" || !deletingOperation || op_1.id !== deletingOperation.id) return; 7096 if (op_1.status === "finished") finishDeletion(deletingOperation); 7097 else if (op_1.status === "failed") failDeletion(deletingOperation); 7098 }, [ 7099 deletingOperation, 7100 finishDeletion, 7101 failDeletion 7102 ]); 7103 const operationsChannelCallbacks = (0, import_react.useMemo)(() => ({ 7104 connected: () => { 7105 if (!deletingOperation) return; 7106 const tracked = deletingOperation; 7107 fetch(operation_path(tracked.id), { headers: { 7108 Accept: "application/json", 7109 "X-CSRF-Token": getCsrfToken() 7110 } }).then((r_1) => { 7111 if (!r_1.ok) return; 7112 return r_1.json(); 7113 }).then((op_2) => { 7114 if (!op_2) return; 7115 if (op_2.status === "finished") finishDeletion(tracked); 7116 else if (op_2.status === "failed") failDeletion(tracked); 7117 }).catch(() => {}); 7118 }, 7119 received: handleDeleteOperationReceived 7120 }), [ 7121 deletingOperation, 7122 handleDeleteOperationReceived, 7123 finishDeletion, 7124 failDeletion 7125 ]); 7126 useActionCable({
7127 params: operationsChannelParams, 7128 callbacks: operationsChannelCallbacks, 7129 enabled: isDeletionInProgress 7130 }); 7131 const [activeOperation, setActiveOperation] = (0, import_react.useState)(normalizePendingOperation(props.pendingOperation)); 7132 const activeOperationRef = (0, import_react.useRef)(activeOperation); 7133 (0, import_react.useEffect)(() => { 7134 activeOperationRef.current = activeOperation; 7135 }, [activeOperation]); 7136 (0, import_react.useEffect)(() => { 7137 setActiveOperation(normalizePendingOperation(props.pendingOperation)); 7138 }, [props.pendingOperation?.id]); 7139 const settledRevealOperationIdRef = (0, import_react.useRef)(null); 7140 const REVEAL_PROGRESS_REFRESH_THROTTLE_MS = 3e3; 7141 const lastRevealRefreshAtRef = (0, import_react.useRef)(0); 7142 const lastRevealProcessedCountRef = (0, import_react.useRef)(0); 7143 const refreshLeadsOnRevealProgress = (0, import_react.useCallback)((op_3) => { 7144 if (op_3.processedCount <= lastRevealProcessedCountRef.current) return; 7145 const now = Date.now(); 7146 if (now - lastRevealRefreshAtRef.current < REVEAL_PROGRESS_REFRESH_THROTTLE_MS) return; 7147 lastRevealRefreshAtRef.current = now; 7148 lastRevealProcessedCountRef.current = op_3.processedCount; 7149 refreshLeadsFromCurrentUrl(); 7150 }, [refreshLeadsFromCurrentUrl]); 7151 const revealInProgressTitle = (0, import_react.useCallback)((op_4) => op_4.listName ? window.i18n.t("js.leads.page.reveal_progress.saving_count", { 7152 count: op_4.totalCount, 7153 formatted_count: CurrencyHelper.numberWithDelimiter(op_4.totalCount), 7154 list_name: op_4.listName 7155 }) : window.i18n.t("js.leads.page.reveal_progress.saving_count_no_list", { 7156 count: op_4.totalCount, 7157 formatted_count: CurrencyHelper.numberWithDelimiter(op_4.totalCount) 7158 }), []); 7159 const finishReveal = (0, import_react.useCallback)((op_5) => { 7160 if (settledRevealOperationIdRef.current === op_5.id) return; 7161 settledRevealOperationIdRef.current = op_5.id; 7162 const savedCount = op_5.listName ? op_5.successCount + op_5.skippedCount : op_5.successCount; 7163 toast.success(window.i18n.t("js.leads.page.reveal_progress.saved_count", { 7164 count: savedCount, 7165 formatted_count: CurrencyHelper.numberWithDelimiter(savedCount) 7166 }), { id: `reveal-op-${op_5.id}` }); 7167 refreshLeadsFromCurrentUrl(); 7168 router.reload({ only: ["sidebar"] }); 7169 setActiveOperation(null); 7170 }, [refreshLeadsFromCurrentUrl]); 7171 const failReveal = (0, import_react.useCallback)((op_6) => { 7172 if (settledRevealOperationIdRef.current === op_6.id) return; 7173 settledRevealOperationIdRef.current = op_6.id; 7174 toast.danger(window.i18n.t("js.leads.page.reveal_progress.failed"), { id: `reveal-op-${op_6.id}` }); 7175 setActiveOperation(null); 7176 }, []); 7177 const cancelReveal = (0, import_react.useCallback)((op_7) => { 7178 if (settledRevealOperationIdRef.current === op_7.id) return; 7179 settledRevealOperationIdRef.current = op_7.id; 7180 toast.warning(window.i18n.t("js.leads.page.reveal_progress.canceled"), { id: `reveal-op-${op_7.id}` }); 7181 refreshLeadsFromCurrentUrl(); 7182 router.reload({ only: ["sidebar"] }); 7183 setActiveOperation(null); 7184 }, [refreshLeadsFromCurrentUrl]); 7185 const handleRevealReceived = (0, import_react.useCallback)((data_2) => { 7186 const tracked_0 = activeOperationRef.current; 7187 if (!tracked_0) return; 7188 const op_8 = normalizePendingOperation(data_2.operation); 7189 if (!op_8 || op_8.kind !== "reveal_emails" || op_8.id !== tracked_0.id) return; 7190 setActiveOperation(op_8); 7191 if (op_8.status === "finished") finishReveal(op_8); 7192 else if (op_8.status === "failed") failReveal(op_8); 7193 else if (op_8.status === "canceled") cancelReveal(op_8); 7194 else if (op_8.status === "started") refreshLeadsOnRevealProgress(op_8); 7195 }, [ 7196 finishReveal, 7197 failReveal, 7198 cancelReveal, 7199 refreshLeadsOnRevealProgress 7200 ]); 7201 const pollRevealOperation = (0, import_react.useCallback)((operationId) => { 7202 fetch(operation_path(operationId), { headers: { 7203 Accept: "application/json", 7204 "X-CSRF-Token": getCsrfToken() 7205 } }).then((r_2) => r_2.ok ? r_2.json() : void 0).then((data_3) => { 7206 const op_9 = normalizePendingOperation(data_3); 7207 if (!op_9) return; 7208 if (settledRevealOperationIdRef.current === op_9.id) return; 7209 const tracked_1 = activeOperationRef.current; 7210 if (tracked_1 && tracked_1.id !== op_9.id) return; 7211 setActiveOperation(op_9); 7212 if (op_9.status === "finished") finishReveal(op_9); 7213 else if (op_9.status === "failed") failReveal(op_9); 7214 else if (op_9.status === "canceled") cancelReveal(op_9); 7215 }).catch(() => {}); 7216 }, [ 7217 finishReveal, 7218 failReveal, 7219 cancelReveal 7220 ]); 7221 const revealChannelCallbacks = (0, import_react.useMemo)(() => ({ 7222 connected: () => { 7223 const tracked_2 = activeOperationRef.current; 7224 if (tracked_2) pollRevealOperation(tracked_2.id); 7225 }, 7226 received: handleRevealReceived 7227 }), [handleRevealReceived, pollRevealOperation]); 7228 useActionCable({
7229 params: operationsChannelParams, 7230 callbacks: revealChannelCallbacks, 7231 enabled: activeOperation !== null 7232 }); 7233 (0, import_react.useEffect)(() => { 7234 const handleRevealOperationStarted = (event) => { 7235 const detail = event.detail; 7236 if (!detail) return; 7237 if (!isNumber(detail.operationId)) { 7238 refreshLeadsFromCurrentUrl(); 7239 router.reload({ only: ["sidebar"] }); 7240 return; 7241 } 7242 lastRevealRefreshAtRef.current = 0; 7243 lastRevealProcessedCountRef.current = 0; 7244 const operation = { 7245 id: detail.operationId, 7246 kind: "reveal_emails", 7247 status: "started", 7248 totalCount: detail.totalCount, 7249 processedCount: 0, 7250 successCount: 0, 7251 failedCount: 0, 7252 skippedCount: 0, 7253 updatedCount: 0, 7254 percentageDone: 0, 7255 listName: detail.listName 7256 }; 7257 activeOperationRef.current = operation; 7258 setActiveOperation(operation); 7259 pollRevealOperation(detail.operationId); 7260 }; 7261 document.addEventListener(REVEAL_OPERATION_STARTED_EVENT, handleRevealOperationStarted); 7262 return () => document.removeEventListener(REVEAL_OPERATION_STARTED_EVENT, handleRevealOperationStarted); 7263 }, [pollRevealOperation, refreshLeadsFromCurrentUrl]); 7264 function handleColumnsUpdate(selectedColumns) { 7265 setLocalVisibleColumnNames(selectedColumns); 7266 const columnParams = new URLSearchParams(); 7267 for (const name_2 of selectedColumns) columnParams.append(`column[${name_2}]`, "true"); 7268 fetch(columns_preferences_leads_path(), { 7269 method: "POST", 7270 headers: { 7271 "X-CSRF-Token": getCsrfToken(), 7272 "Content-Type": "application/x-www-form-urlencoded", 7273 Accept: "application/json" 7274 }, 7275 body: columnParams.toString() 7276 }); 7277 } 7278 const buildSelectedLeadsSummary = (0, import_react.useCallback)(() => { 7279 let candidates = []; 7280 if (selection.mode === "partial" || selection.mode === "count") candidates = leads.filter((lead_2) => selection.selectedIds.has(lead_2.id)); 7281 else if (selection.mode === "all") candidates = leads.filter((lead_3) => !selection.excludedIds.has(lead_3.id)); 7282 return candidates.map((lead_4) => ({ 7283 id: lead_4.id, 7284 firstName: lead_4.firstName, 7285 lastName: lead_4.lastName, 7286 fullName: lead_4.fullName 7287 })); 7288 }, [selection, leads]); 7289 const buildSelectionParams = (0, import_react.useCallback)(() => { 7290 const params_2 = new URLSearchParams(); 7291 if (selection.mode === "all") { 7292 params_2.append("select_all", "1"); 7293 for (const [key_4, value_2] of Object.entries(filters)) if (value_2) params_2.append(key_4, value_2); 7294 if (leadsList.type !== "virtual") params_2.append("leads_list_id", leadsList.id.toString()); 7295 if (query) params_2.append("query", query); 7296 if (sort) params_2.append("sort", sort); 7297 if (direction) params_2.append("direction", direction); 7298 for (const id_1 of selection.excludedIds) params_2.append("excluded_lead_ids[]", id_1.toString()); 7299 } else if (selection.mode === "partial" || selection.mode === "count") for (const id_2 of selection.selectedIds) params_2.append("lead_ids[]", id_2.toString()); 7300 return params_2; 7301 }, [ 7302 selection, 7303 filters, 7304 leadsList, 7305 query, 7306 sort, 7307 direction 7308 ]); 7309 const selectionPermissions = useSelectionPermissions(buildSelectionParams().toString(), leads); 7310 const handleSelectCount = (0, import_react.useCallback)(async (count_0) => { 7311 selectCountAbortRef.current?.abort(); 7312 const controller_0 = new AbortController(); 7313 selectCountAbortRef.current = controller_0; 7314 clearBulkSelection(); 7315 const params_3 = new URLSearchParams(); 7316 for (const [key_5, value_3] of Object.entries(filters)) if (value_3) params_3.append(key_5, value_3); 7317 if (leadsList.type === "static" && !params_3.has("leads_list_id")) params_3.append("leads_list_id", leadsList.id.toString()); 7318 if (query) params_3.append("query", query); 7319 if (sort) params_3.append("sort", sort); 7320 if (direction) params_3.append("direction", direction); 7321 params_3.append("limit", count_0.toString()); 7322 try { 7323 const response_1 = await fetch(`${leads_selection_ids_path()}?${params_3.toString()}`, { 7324 headers: { Accept: "application/json" }, 7325 signal: controller_0.signal 7326 }); 7327 if (!response_1.ok) { 7328 const fallback = window.i18n.t("js.leads.page.bulk_actions.select_count_error");
7329 try { 7330 const data_4 = await response_1.json(); 7331 const fromMessage = isObject(data_4) && isString(data_4.message) ? data_4.message.trim() : ""; 7332 const fromError = isObject(data_4) && isString(data_4.error) ? data_4.error.trim() : ""; 7333 toast.danger(fromMessage || fromError || fallback); 7334 } catch { 7335 toast.danger(fallback); 7336 } 7337 return; 7338 } 7339 const data_5 = await response_1.json(); 7340 selectCount(data_5.ids ?? []); 7341 } catch {} 7342 }, [ 7343 filters, 7344 leadsList, 7345 query, 7346 sort, 7347 direction, 7348 selectCount, 7349 clearBulkSelection 7350 ]); 7351 const handleToggleRow = (0, import_react.useCallback)((id_3) => { 7352 cancelPendingCount(); 7353 toggleRow(id_3); 7354 }, [cancelPendingCount, toggleRow]); 7355 const handleSelectAllLeads = (0, import_react.useCallback)(() => { 7356 cancelPendingCount(); 7357 selectAll(); 7358 }, [cancelPendingCount, selectAll]); 7359 const handleSelectPage = (0, import_react.useCallback)(() => { 7360 cancelPendingCount(); 7361 selectPage(leads.map((l_13) => l_13.id)); 7362 }, [ 7363 cancelPendingCount, 7364 selectPage, 7365 leads 7366 ]); 7367 function handleBulkModalClose() { 7368 setBulkModal(null); 7369 setVerifyAllSelection(null); 7370 selectionStaleUnderModalRef.current = false; 7371 clearSelection(); 7372 } 7373 function handleBulkModalCancel() { 7374 setBulkModal(null); 7375 setVerifyAllSelection(null); 7376 if (selectionStaleUnderModalRef.current) { 7377 selectionStaleUnderModalRef.current = false; 7378 clearSelection(); 7379 } 7380 } 7381 const handleVerifyAllInsights = (0, import_react.useCallback)((notVerifiedCount, filterValue) => { 7382 const params_4 = new URLSearchParams(); 7383 for (const [key_6, value_4] of Object.entries(filters)) if (value_4 && key_6 !== "verification_status") params_4.append(key_6, value_4); 7384 params_4.append("verification_status", Array.isArray(filterValue) ? filterValue.join("|") : filterValue); 7385 if (leadsList.type !== "virtual") params_4.append("leads_list_id", leadsList.id.toString()); 7386 if (query) params_4.append("query", query); 7387 if (sort) params_4.append("sort", sort); 7388 if (direction) params_4.append("direction", direction); 7389 setVerifyAllSelection({ 7390 params: params_4, 7391 count: notVerifiedCount 7392 }); 7393 setBulkModal("verifyLeads"); 7394 }, [ 7395 filters, 7396 leadsList, 7397 query, 7398 sort, 7399 direction 7400 ]); 7401 const visibleColumns = (0, import_react.useMemo)(() => localVisibleColumnNames.map((name_3) => columns.find((col) => col.name === name_3)).filter((col_0) => col_0 !== void 0), [localVisibleColumnNames, columns]); 7402 const showImportSkeleton = leads.length === 0 && (isPolling || isCompleting) && !activeOperation; 7403 const showEmptyState = leads.length === 0 && !isPolling && !isCompleting; 7404 const hasNoMatch = leadsList.leadsCount > 0 || hasPendingImport; 7405 const hideMainHeading = showEmptyState && !hasNoMatch; 7406 const skeletonColumns = (0, import_react.useMemo)(() => visibleColumns.map((col_1) => ({ 7407 label: col_1.title, 7408 sticky: col_1.sticky 7409 })), [visibleColumns]); 7410 return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ 7411 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Head_default, { title: leadsList.name }), 7412 /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("main", { 7413 className: "dashboard-main", 7414 children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { 7415 className: "dashboard-main__submenu", 7416 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LeadsListSidebar, { 7417 sidebar, 7418 currentListId: leadsList.id, 7419 onListSelect: handleListSelect, 7420 onListCreated: handleListCreated, 7421 onLeadsCountRefresh: handleLeadsCountRefresh 7422 }) 7423 }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { 7424 className: "dashboard-main__content", 7425 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { 7426 className: "master-details", 7427 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { 7428 className: "master-details__master", 7429 children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { 7430 className: "board-box", 7431 children: [ 7432 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LeadsPageHeader, { 7433 leadsList, 7434 leadsLists: sidebar.leadsLists, 7435 totalCount, 7436 totalCountApproximate, 7437 query, 7438 hideMainHeading, 7439 columns, 7440 customAttributes, 7441 formOptions: formOptionsWithTags, 7442 folders: sidebar.folders, 7443 filters, 7444 onSearch: handleSearch, 7445 onRenamed: (name_4) => { 7446 setLeadsList((prev_19) => ({ 7447 ...prev_19, 7448 name: name_4 7449 })); 7450 setSidebar((prev_20) => ({ 7451 ...prev_20, 7452 leadsLists: prev_20.leadsLists.map((l_14) => l_14.id === leadsList.id ? { 7453 ...l_14, 7454 name: name_4 7455 } : l_14) 7456 })); 7457 }, 7458 onFolderChanged: (folderId) => setLeadsList((prev_21) => ({ 7459 ...prev_21, 7460 folderId 7461 })), 7462 onNewLead: () => { 7463 setSelectedCompany(null); 7464 setShowCreateLead(true); 7465 }, 7466 onApplyFilter: handleSingleFilterApply, 7467 onApplyBatchFilter: handleBatchFilterApply, 7468 onRemoveFilter: handleRemoveFilter, 7469 onRemoveBatchFilter: handleRemoveBatchFilter, 7470 onClearAllFilters: handleClearAllFilters, 7471 onSaveAsList: () => { 7472 setSelectedCompany(null); 7473 setShowSaveFilteredList(true); 7474 }, 7475 companyDropdownEnabled: featureFlags?.companyFilterDropdown ?? false, 7476 notContainsEnabled: true, 7477 decisionMakersAndPpcFiltersEnabled: featureFlags?.decisionMakersAndPpcFilters ?? false, 7478 companyDropdownListId: leadsList.type !== "virtual" ? leadsList.id : void 0, 7479 lookalikes, 7480 previewSourceLeads: leads.slice(0, 10).map((lead_5) => ({ 7481 id: lead_5.id, 7482 firstName: lead_5.firstName, 7483 lastName: lead_5.lastName, 7484 fullName: lead_5.fullName 7485 })), 7486 searchFilters: filters, 7487 visibleColumnNames: localVisibleColumnNames, 7488 onColumnsUpdate: handleColumnsUpdate, 7489 onCreateCustomAttribute: () => setShowCreateCustomAttribute(true), 7490 insightsOpen, 7491 onToggleInsights: toggleInsights 7492 }),
7493 leadsImport && !isDone && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImportProgressBar, { 7494 containerClassName: "progress-bar-container mb-4", 7495 percentage: displayPercentage, 7496 finished: leadsImport.finished || isCompleting, 7497 successfulLines: leadsImport.linesImported, 7498 updatedLines: leadsImport.updatedLeadsCount, 7499 failedLines: leadsImport.failedLines, 7500 errorCsvDownloadUrl: leadsImport.errorCsvDownloadUrl, 7501 detailsHref: leads_import_path(leadsImport.id), 7502 timeLeftText, 7503 dismissible: true 7504 }, leadsImport.id), 7505 activeOperation && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OperationProgressBar, { 7506 operation: activeOperation, 7507 inProgressTitle: revealInProgressTitle(activeOperation), 7508 completeTitle: window.i18n.t("js.leads.page.reveal_progress.saved_count", { 7509 count: activeOperation.successCount || activeOperation.totalCount, 7510 formatted_count: CurrencyHelper.numberWithDelimiter(activeOperation.successCount || activeOperation.totalCount) 7511 }), 7512 onDismiss: () => setActiveOperation(null) 7513 }), 7514 verificationBanner && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VerificationBanner, { banner: verificationBanner }), 7515 showImportSkeleton ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DataTableSkeleton, { 7516 columns: skeletonColumns, 7517 checkboxAriaLabel: window.i18n.t("js.leads.page.select_all"), 7518 rows: Math.min(pageSize, 10) 7519 }) : showEmptyState && !activeOperation ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LeadsEmptyState, { 7520 hasNoMatch, 7521 leadsListId: leadsList.id, 7522 totalOwnedLeads, 7523 importPathParams: importPathParamsForList(leadsList) 7524 }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsRow, { 7525 open: insightsOpen, 7526 panel: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InsightsPanel, { 7527 open: insightsOpen, 7528 filters, 7529 query, 7530 listId: leadsList.type !== "virtual" ? leadsList.id : void 0, 7531 listParamName: "leads_list_id", 7532 dataOverviewPath: data_overview_leads_path, 7533 cookieKey: "leads_data_overview_configuration", 7534 onFilterApply: (newFilters_4) => handleFilterApply(newFilters_4, { filterFromChart: true }), 7535 onVerifyAll: handleVerifyAllInsights, 7536 verifyLaunchedSignal: verifyAllLaunchedSignal, 7537 tab: "people" 7538 }), 7539 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LeadsTable, { 7540 leads, 7541 columns: visibleColumns, 7542 visibleColumnNames: localVisibleColumnNames, 7543 editableColumnNames, 7544 sort, 7545 direction, 7546 totalCount, 7547 onSort: handleSort, 7548 isSelected, 7549 allSelected: selection.mode === "all", 7550 onToggleRow: handleToggleRow, 7551 onSelectAllLeads: handleSelectAllLeads, 7552 onSelectPage: handleSelectPage, 7553 onSelectCount: handleSelectCount, 7554 onClearSelection: clearSelection, 7555 onLeadClick: (leadId_6, initialTab_0) => openLead(leadId_6, "view", initialTab_0), 7556 onCompanyClick: openCompany, 7557 discoverEnabled: props.entitlements.discoverAccess && !props.currentTeam.dataPlatform, 7558 enrichingLeadIds, 7559 onEditLead: (leadId_7) => openLead(leadId_7, "edit"), 7560 onColumnsUpdate: handleColumnsUpdate, 7561 availableTags, 7562 onTagsChange: handleTagsChange, 7563 onTagUpdate: handleTagUpdate, 7564 onTagDelete: handleTagDelete, 7565 onDeleteLead: setDeleteLeadId, 7566 onVerifyRequested: handleVerifyRequested, 7567 onFindEmailRequested: handleFindEmailRequested, 7568 onFindEmailFailed: handleFindEmailFailed, 7569 filters, 7570 formOptions: formOptionsWithTags, 7571 companyDropdownEnabled: featureFlags?.companyFilterDropdown ?? false, 7572 notContainsEnabled: true, 7573 leadsListId: leadsList.type !== "virtual" ? leadsList.id : void 0, 7574 onApplyFilter: handleSingleFilterApply, 7575 onApplyBatchFilter: handleBatchFilterApply, 7576 columnResizeDisabled: selectedCount > 0, 7577 bulkActionsBar: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BulkActionsToolbar, { 7578 selectedCount, 7579 totalCount, 7580 pageCount: leads.length, 7581 campaignsAccess: props.entitlements.campaignsAccess, 7582 permissions: selectionPermissions, 7583 leadsList, 7584 leadsLists: sidebar.leadsLists, 7585 syncableApps, 7586 onClearSelection: clearSelection, 7587 onSelectAll: handleSelectAllLeads, 7588 onSelectPage: handleSelectPage, 7589 onSelectCount: handleSelectCount, 7590 onOpenModal: setBulkModal, 7591 buildSelectionParams, 7592 buildSelectedLeadsSummary 7593 }), 7594 footer: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DataTablePagination, { 7595 offset, 7596 pageSize, 7597 totalCount, 7598 totalApproximate: totalCountApproximate, 7599 hasMore: hasMoreLeads, 7600 onPageChange: handlePageChange, 7601 onPageSizeChange: handlePageSizeChange, 7602 "aria-label": window.i18n.t("js.leads.page.pagination"), 7603 pageSizeLabel: window.i18n.t("js.leads.page.number_of_leads_per_page") 7604 }) 7605 }) 7606 }) 7607 ] 7608 }) 7609 }) 7610 }) 7611 })] 7612 }),
7613 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LeadSidePanel, { 7614 lead: selectedLead, 7615 open: selectedLeadId !== null, 7616 initialMode: sidePanelMode, 7617 initialTab: sidePanelInitialTab, 7618 initialStateKey: sidePanelInitialStateKey, 7619 onOpenChange: (open) => { 7620 if (!open) closeLead(); 7621 }, 7622 customAttributes, 7623 formOptions: formOptionsWithTags, 7624 leadsLists: sidebar.leadsLists, 7625 onLeadUpdated: (updatedLead) => { 7626 setLeads((prev_22) => prev_22.map((l_15) => l_15.id === updatedLead.id ? updatedLead : l_15)); 7627 }, 7628 onLeadDeleted: handleLeadDeleted, 7629 onLeadClick: (leadId_8) => openLead(leadId_8, "view"), 7630 hasSyncableApps, 7631 currentListId: leadsList.type !== "virtual" ? leadsList.id : void 0 7632 }), 7633 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CompanySidePanel, { 7634 company: selectedCompany, 7635 open: selectedCompany !== null, 7636 onOpenChange: (open_0) => { 7637 if (!open_0) setSelectedCompany(null); 7638 }, 7639 from: "people" 7640 }), 7641 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CreateLeadSheet, { 7642 open: showCreateLead, 7643 onOpenChange: setShowCreateLead, 7644 onLeadCreated: (leadId_9, enriching) => { 7645 if (enriching) { 7646 setEnrichingLeadIds((prev_23) => new Set(prev_23).add(leadId_9)); 7647 const reconcileTimer = window.setTimeout(() => { 7648 enrichFallbackTimersRef.current.delete(leadId_9); 7649 stopEnriching(leadId_9); 7650 refreshLeadsFromCurrentUrl(); 7651 }, 15e3); 7652 enrichFallbackTimersRef.current.set(leadId_9, reconcileTimer); 7653 } 7654 refreshLeadsFromCurrentUrl(); 7655 }, 7656 leadsLists: sidebar.leadsLists, 7657 currentListId: leadsList.type !== "virtual" ? leadsList.id : void 0, 7658 customAttributes, 7659 formOptions: formOptionsWithTags 7660 }), 7661 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DeleteLeadsModal, { 7662 open: bulkModal === "deleteLeads", 7663 onClose: handleBulkModalClose, 7664 onDeleted: (result) => { 7665 const count_1 = selectedCount; 7666 handleBulkModalClose(); 7667 if (result.async && result.operationId) { 7668 settledOperationIdRef.current = null; 7669 toast.loading(window.i18n.t("js.leads.page.bulk_actions.deleting_count", { 7670 count: count_1, 7671 formatted_count: CurrencyHelper.numberWithDelimiter(count_1) 7672 }), { 7673 id: `delete-op-${result.operationId}`, 7674 duration: Number.POSITIVE_INFINITY 7675 }); 7676 setDeletingOperation({ 7677 id: result.operationId, 7678 count: count_1 7679 }); 7680 } else { 7681 fetchLeads(buildQueryParams()); 7682 const deletedCount = result.deletedCount ?? 0; 7683 setSidebar((prev_24) => ({ 7684 ...prev_24, 7685 allLeadsList: prev_24.allLeadsList ? { 7686 ...prev_24.allLeadsList, 7687 leadsCount: Math.max(0, prev_24.allLeadsList.leadsCount - deletedCount) 7688 } : prev_24.allLeadsList, 7689 leadsLists: prev_24.leadsLists.map((l_16) => l_16.id === leadsList.id ? { 7690 ...l_16, 7691 leadsCount: Math.max(0, l_16.leadsCount - deletedCount) 7692 } : l_16) 7693 })); 7694 decrementSelectedLeadsCount(leadsList.id, deletedCount); 7695 } 7696 }, 7697 selectedCount, 7698 selectionParams: buildSelectionParams() 7699 }), 7700 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(DeleteLeadModal, { 7701 leadId: deleteLeadId, 7702 open: deleteLeadId !== null, 7703 onClose: () => setDeleteLeadId(null), 7704 onDeleted: handleLeadDeleted 7705 }), 7706 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AddToListModal, { 7707 open: bulkModal === "addToList", 7708 onClose: handleBulkModalClose, 7709 onSuccess: (destinationListId) => { 7710 const addedCount = selectedCount; 7711 setSidebar((prev_25) => ({ 7712 ...prev_25, 7713 leadsLists: prev_25.leadsLists.map((l_17) => l_17.id === destinationListId ? { 7714 ...l_17, 7715 leadsCount: l_17.leadsCount + addedCount 7716 } : l_17) 7717 })); 7718 }, 7719 selectedCount, 7720 selectionParams: buildSelectionParams(), 7721 leadsLists: sidebar.leadsLists, 7722 currentListId: leadsList.id 7723 }), 7724 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MoveToListModal, { 7725 open: bulkModal === "moveToList", 7726 onClose: handleBulkModalClose, 7727 onSuccess: (destinationListId_0) => { 7728 const movedCount = selectedCount; 7729 fetchLeads(buildQueryParams()); 7730 setSidebar((prev_26) => ({ 7731 ...prev_26, 7732 leadsLists: prev_26.leadsLists.map((l_18) => { 7733 if (l_18.id === leadsList.id) return { 7734 ...l_18, 7735 leadsCount: Math.max(0, l_18.leadsCount - movedCount) 7736 }; 7737 if (l_18.id === destinationListId_0) return { 7738 ...l_18, 7739 leadsCount: l_18.leadsCount + movedCount 7740 }; 7741 return l_18; 7742 }) 7743 })); 7744 decrementSelectedLeadsCount(leadsList.id, movedCount); 7745 }, 7746 selectedCount, 7747 selectionParams: buildSelectionParams(), 7748 leadsLists: sidebar.leadsLists, 7749 currentListId: leadsList.id 7750 }),
7751 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RemoveFromListModal, { 7752 open: bulkModal === "removeFromList", 7753 onClose: handleBulkModalClose, 7754 onSuccess: () => { 7755 const removedCount = selectedCount; 7756 fetchLeads(buildQueryParams()); 7757 setSidebar((prev_27) => ({ 7758 ...prev_27, 7759 leadsLists: prev_27.leadsLists.map((l_19) => l_19.id === leadsList.id ? { 7760 ...l_19, 7761 leadsCount: Math.max(0, l_19.leadsCount - removedCount) 7762 } : l_19) 7763 })); 7764 decrementSelectedLeadsCount(leadsList.id, removedCount); 7765 }, 7766 selectedCount, 7767 selectionParams: buildSelectionParams(), 7768 currentListId: leadsList.id 7769 }), 7770 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SaveAsListModal, { 7771 open: bulkModal === "saveAsList", 7772 onClose: handleBulkModalClose, 7773 selectedCount, 7774 selectionParams: buildSelectionParams(), 7775 folders: sidebar.folders 7776 }), 7777 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SaveFilteredListSidePanel, { 7778 open: showSaveFilteredList, 7779 onClose: () => setShowSaveFilteredList(false), 7780 filters, 7781 query, 7782 leadsList, 7783 folders: sidebar.folders, 7784 sort, 7785 direction 7786 }), 7787 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AddToSequenceModal, { 7788 open: bulkModal === "addToSequence", 7789 onClose: handleBulkModalClose, 7790 selectionParams: buildSelectionParams() 7791 }), 7792 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SyncToCrmModal, { 7793 open: bulkModal === "syncToCrm", 7794 onClose: handleBulkModalCancel, 7795 onSuccess: handleBulkModalClose, 7796 selectionParams: buildSelectionParams(), 7797 selectedCount, 7798 syncableApps 7799 }), 7800 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FindEmailsModal, { 7801 open: bulkModal === "findEmails", 7802 onClose: handleBulkModalCancel, 7803 onSuccess: clearSelection, 7804 selectedCount, 7805 selectionParams: buildSelectionParams(), 7806 singleCreditsBucket: verifyCreditsInfo.singleCreditsBucket, 7807 searchCallsLeft: verifyCreditsInfo.searchCallsLeft, 7808 searchOverageEnabled: verifyCreditsInfo.searchOverageEnabled, 7809 creditsAutoPurchaseEnabled: verifyCreditsInfo.creditsAutoPurchaseEnabled, 7810 personalLimitReached: verifyCreditsInfo.searchPersonalLimitReached, 7811 checkoutAction: verifyCreditsInfo.searchCheckoutAction, 7812 isTeamOwner: currentUser.teamOwner 7813 }), 7814 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(VerifyLeadsModal, { 7815 open: bulkModal === "verifyLeads", 7816 onClose: handleBulkModalCancel, 7817 onVerified: () => { 7818 if (verifyAllSelection) setVerifyAllLaunchedSignal((n) => n + 1); 7819 clearSelection(); 7820 }, 7821 sort, 7822 direction, 7823 selectedCount: verifyAllSelection ? verifyAllSelection.count : selectedCount, 7824 selectionParams: verifyAllSelection ? verifyAllSelection.params : buildSelectionParams(), 7825 verifyCallsLeft: verifyCreditsInfo.verifyCallsLeft, 7826 verifyOverageEnabled: verifyCreditsInfo.verifyOverageEnabled, 7827 singleCreditsBucket: verifyCreditsInfo.singleCreditsBucket, 7828 creditsAutoPurchaseEnabled: verifyCreditsInfo.creditsAutoPurchaseEnabled, 7829 personalLimitReached: verifyCreditsInfo.verifyPersonalLimitReached, 7830 checkoutAction: verifyCreditsInfo.verifyCheckoutAction, 7831 isTeamOwner: currentUser.teamOwner 7832 }), 7833 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LeadsReorganizationOnboardingDialog, { show: showLeadsReorganizationTour }), 7834 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PseoWelcomeDialog, { 7835 show: showPseoWelcome, 7836 welcome: pseoWelcome 7837 }), 7838 /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CreateCustomAttributeModal, { 7839 open: showCreateCustomAttribute, 7840 onClose: () => setShowCreateCustomAttribute(false), 7841 onCreated: () => { 7842 setShowCreateCustomAttribute(false); 7843 router.reload(); 7844 } 7845 }) 7846 ] }); 7847} 7848var import_react, import_jsx_runtime; 7849function init_Index() { 7850 return (init_Index = __esmMin((() => { 7851 init_dist(); 7852 import_react = require_react(); 7853 init_routes(); 7854 init_leadUrlSync(); 7855 init_listOperations(); 7856 init_utils(); 7857 init_currency_helper(); 7858 init_useActionCable(); 7859 init_useLatestRef(); 7860 init_useBulkSelection(); 7861 init_AppLayout(); 7862 init_FolderSettingsMenu(); 7863 init_LeadsListSidebar(); 7864 init_LeadsTable(); 7865 init_PageHeader(); 7866 init_data_table_pagination(); 7867 init_EmptyState(); 7868 init_InsightsPanel(); 7869 init_InsightsRow(); 7870 init_useInsightsPanel(); 7871 init_useScopedBodyClass(); 7872 init_LeadSidePanel(); 7873 init_CompanySidePanel(); 7874 init_CreateLeadSheet(); 7875 init_BulkActionsToolbar(); 7876 init_useSelectionPermissions(); 7877 init_DeleteLeadsModal(); 7878 init_DeleteLeadModal(); 7879 init_AddToListModal(); 7880 init_MoveToListModal(); 7881 init_RemoveFromListModal(); 7882 init_SaveAsListModal(); 7883 init_SaveFilteredListSidePanel(); 7884 init_AddToSequenceModal(); 7885 init_SyncToCrmModal(); 7886 init_FindEmailsModal(); 7887 init_VerifyLeadsModal(); 7888 init_CreateCustomAttributeModal(); 7889 init_ImportProgressBar(); 7890 init_OperationProgressBar(); 7891 init_VerificationBanner(); 7892 init_useImportProgress(); 7893 init_data_table_skeleton(); 7894 init_PendingOperation(); 7895 init_leads_reorganization_onboarding_dialog(); 7896 init_pseo_welcome_dialog(); 7897 init_toast(); 7898 import_jsx_runtime = require_jsx_runtime(); 7899 Index.layout = (page) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AppLayout, { 7900 navCollapsed: true, 7901 children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FolderSettingsProvi
7901der, { children: page }, "leads") 7902 }); 7903 })))(); 7904} 7905//#endregion 7906init_Index(); 7907export { Index as default };
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.