@meetelise/chat 1.53.6 → 1.54.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/WebComponent/actions/details-window.d.ts +7 -0
- package/dist/src/WebComponent/actions/email-us-window.d.ts +30 -0
- package/dist/src/WebComponent/launcher/Launcher.d.ts +1 -0
- package/dist/src/WebComponent/me-chat.d.ts +1 -0
- package/dist/src/fetchFeatureFlag.d.ts +2 -0
- package/package.json +1 -1
- package/public/dist/index.js +526 -441
- package/src/WebComponent/FeeCalculator/components/charge-inputs/charge-inputs.ts +1 -11
- package/src/WebComponent/actions/details-window.ts +24 -0
- package/src/WebComponent/actions/email-us-window.ts +280 -22
- package/src/WebComponent/launcher/Launcher.ts +3 -0
- package/src/WebComponent/me-chat.ts +7 -0
- package/src/brokerReferralSubmission.test.ts +287 -0
- package/src/fetchFeatureFlag.ts +20 -0
|
@@ -118,15 +118,6 @@ export class ChargeInputsComponent extends LitElement {
|
|
|
118
118
|
font-weight: 500;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
.rentable-item-type {
|
|
122
|
-
font-size: 12px;
|
|
123
|
-
color: #9ca3af;
|
|
124
|
-
margin-top: 1px;
|
|
125
|
-
font-weight: 500;
|
|
126
|
-
text-transform: uppercase;
|
|
127
|
-
letter-spacing: 0.025em;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
121
|
.rentable-item-price {
|
|
131
122
|
font-size: 12px;
|
|
132
123
|
color: #6b7280;
|
|
@@ -266,7 +257,6 @@ export class ChargeInputsComponent extends LitElement {
|
|
|
266
257
|
<div class="rentable-item-row">
|
|
267
258
|
<div class="rentable-item-info">
|
|
268
259
|
<div class="rentable-item-label">${item.description}</div>
|
|
269
|
-
<div class="rentable-item-type">${item.type}</div>
|
|
270
260
|
<div class="rentable-item-price">${item.priceDescription}</div>
|
|
271
261
|
</div>
|
|
272
262
|
<input
|
|
@@ -275,7 +265,7 @@ export class ChargeInputsComponent extends LitElement {
|
|
|
275
265
|
.checked=${isSelected}
|
|
276
266
|
?disabled=${this.disabled}
|
|
277
267
|
@change=${() => this.handleRentableItemToggle(item)}
|
|
278
|
-
aria-label="Select ${item.description}
|
|
268
|
+
aria-label="Select ${item.description}"
|
|
279
269
|
/>
|
|
280
270
|
</div>
|
|
281
271
|
`;
|
|
@@ -97,18 +97,42 @@ export class DetailsWindow extends LitElement {
|
|
|
97
97
|
|
|
98
98
|
private _cleanupMobileListener?: () => void;
|
|
99
99
|
|
|
100
|
+
private readonly _onWindowResize = (): void => this.fitAboveBottom();
|
|
101
|
+
|
|
100
102
|
connectedCallback(): void {
|
|
101
103
|
super.connectedCallback();
|
|
102
104
|
this._cleanupMobileListener = onMobileChange((m) => {
|
|
103
105
|
this.isMobileSized = m;
|
|
104
106
|
});
|
|
107
|
+
window.addEventListener("resize", this._onWindowResize);
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
disconnectedCallback(): void {
|
|
108
111
|
this._cleanupMobileListener?.();
|
|
112
|
+
window.removeEventListener("resize", this._onWindowResize);
|
|
109
113
|
super.disconnectedCallback();
|
|
110
114
|
}
|
|
111
115
|
|
|
116
|
+
updated(): void {
|
|
117
|
+
this.fitAboveBottom();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The window is anchored at its bottom, above the launcher, so the 100vh cap alone can push its top (header and
|
|
122
|
+
* close button) off screen when the form is tall. Cap it to the room above its bottom edge; it scrolls past that.
|
|
123
|
+
*/
|
|
124
|
+
fitAboveBottom(): void {
|
|
125
|
+
const inner = this.shadowRoot?.getElementById("details-window-inner");
|
|
126
|
+
if (!inner) return;
|
|
127
|
+
const bottom = inner.getBoundingClientRect().bottom;
|
|
128
|
+
// max-height sizes the content box, so the wrapper's vertical padding comes off the room.
|
|
129
|
+
const style = getComputedStyle(inner);
|
|
130
|
+
const padding =
|
|
131
|
+
parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);
|
|
132
|
+
const room = Math.min(window.innerHeight - 40, bottom - 16) - padding;
|
|
133
|
+
inner.style.maxHeight = bottom > 0 ? `${Math.max(200, room)}px` : "";
|
|
134
|
+
}
|
|
135
|
+
|
|
112
136
|
render(): TemplateResult {
|
|
113
137
|
return html`
|
|
114
138
|
<div
|
|
@@ -57,7 +57,14 @@ export class EmailUsWindow extends LitElement {
|
|
|
57
57
|
.action-bttn-container {
|
|
58
58
|
margin-top: 19px;
|
|
59
59
|
display: flex;
|
|
60
|
+
align-items: center;
|
|
60
61
|
justify-content: flex-end;
|
|
62
|
+
gap: 8px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/* With the broker toggle on its left, the toggle and Send sit at either end. */
|
|
66
|
+
.action-bttn-container--with-toggle {
|
|
67
|
+
justify-content: space-between;
|
|
61
68
|
}
|
|
62
69
|
|
|
63
70
|
.email-us__message-input {
|
|
@@ -70,6 +77,11 @@ export class EmailUsWindow extends LitElement {
|
|
|
70
77
|
height: 159px;
|
|
71
78
|
}
|
|
72
79
|
|
|
80
|
+
/* A referral adds the broker's rows, so the message box gives back some height. */
|
|
81
|
+
.email-us__message-input--compact {
|
|
82
|
+
height: 80px;
|
|
83
|
+
}
|
|
84
|
+
|
|
73
85
|
.email-us__submitted-info {
|
|
74
86
|
font-size: 18px;
|
|
75
87
|
line-height: 24px;
|
|
@@ -87,6 +99,24 @@ export class EmailUsWindow extends LitElement {
|
|
|
87
99
|
color: rgb(235, 64, 52);
|
|
88
100
|
}
|
|
89
101
|
|
|
102
|
+
.email-us__broker-toggle {
|
|
103
|
+
display: flex;
|
|
104
|
+
align-items: center;
|
|
105
|
+
gap: 6px;
|
|
106
|
+
font-family: "Helvetica", Arial;
|
|
107
|
+
font-size: 13px;
|
|
108
|
+
color: #5c5c5c;
|
|
109
|
+
cursor: pointer;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.email-us__section-label {
|
|
113
|
+
font-family: "Helvetica", Arial;
|
|
114
|
+
font-size: 12px;
|
|
115
|
+
font-weight: 600;
|
|
116
|
+
color: #5c5c5c;
|
|
117
|
+
margin-bottom: 4px;
|
|
118
|
+
}
|
|
119
|
+
|
|
90
120
|
.email-us__center_icon {
|
|
91
121
|
display: flex;
|
|
92
122
|
justify-content: center;
|
|
@@ -133,6 +163,10 @@ export class EmailUsWindow extends LitElement {
|
|
|
133
163
|
@property({ attribute: true })
|
|
134
164
|
featureFlagShowDropdown = "";
|
|
135
165
|
|
|
166
|
+
/** Broker intake is on for the building: offer the broker referral fields. */
|
|
167
|
+
@property({ attribute: false })
|
|
168
|
+
brokerIntakeEnabled = false;
|
|
169
|
+
|
|
136
170
|
@property()
|
|
137
171
|
privatePolicyUrl = "https://www.meetelise.com/privacy";
|
|
138
172
|
@property()
|
|
@@ -153,6 +187,17 @@ export class EmailUsWindow extends LitElement {
|
|
|
153
187
|
@state()
|
|
154
188
|
message = "";
|
|
155
189
|
|
|
190
|
+
@state()
|
|
191
|
+
isBrokerReferral = false;
|
|
192
|
+
@state()
|
|
193
|
+
brokerFirstName = "";
|
|
194
|
+
@state()
|
|
195
|
+
brokerLastName = "";
|
|
196
|
+
@state()
|
|
197
|
+
brokerEmail = "";
|
|
198
|
+
@state()
|
|
199
|
+
brokerFirmName = "";
|
|
200
|
+
|
|
156
201
|
@query("me-select#leadSource")
|
|
157
202
|
selectedLeadSource!: MESelect;
|
|
158
203
|
|
|
@@ -168,6 +213,10 @@ export class EmailUsWindow extends LitElement {
|
|
|
168
213
|
@state()
|
|
169
214
|
hasMessageError = false;
|
|
170
215
|
@state()
|
|
216
|
+
hasBrokerNameError = false;
|
|
217
|
+
@state()
|
|
218
|
+
brokerEmailError: string | null = null;
|
|
219
|
+
@state()
|
|
171
220
|
hasSubmittedForm = false;
|
|
172
221
|
@state()
|
|
173
222
|
windowHeight = 525;
|
|
@@ -216,12 +265,102 @@ export class EmailUsWindow extends LitElement {
|
|
|
216
265
|
this.message = (e.target as HTMLTextAreaElement).value;
|
|
217
266
|
};
|
|
218
267
|
|
|
268
|
+
/**
|
|
269
|
+
* A broker usually starts typing their own details before ticking the box, so ticking it moves
|
|
270
|
+
* the name and email into the broker's empty details and leaves the client's fields empty. Once
|
|
271
|
+
* the broker's details are filled, re-ticking leaves both sections alone: the main fields then
|
|
272
|
+
* hold the client. Unticking with the client's fields still empty moves the details back.
|
|
273
|
+
*/
|
|
274
|
+
onToggleBrokerReferral = (e: Event): void => {
|
|
275
|
+
const isBrokerReferral = (e.target as HTMLInputElement).checked;
|
|
276
|
+
const brokerIsEmpty =
|
|
277
|
+
!this.brokerFirstName && !this.brokerLastName && !this.brokerEmail;
|
|
278
|
+
if (isBrokerReferral && brokerIsEmpty) {
|
|
279
|
+
this.brokerFirstName = this.firstName;
|
|
280
|
+
this.brokerLastName = this.lastName;
|
|
281
|
+
this.brokerEmail = this.email;
|
|
282
|
+
this.firstName = "";
|
|
283
|
+
this.lastName = "";
|
|
284
|
+
this.email = "";
|
|
285
|
+
// There's no broker phone field: what was typed is the broker's, not the client's.
|
|
286
|
+
this.phoneNumber = "";
|
|
287
|
+
this.phoneNumberE164 = null;
|
|
288
|
+
} else if (
|
|
289
|
+
!isBrokerReferral &&
|
|
290
|
+
!this.firstName &&
|
|
291
|
+
!this.lastName &&
|
|
292
|
+
!this.email
|
|
293
|
+
) {
|
|
294
|
+
this.firstName = this.brokerFirstName;
|
|
295
|
+
this.lastName = this.brokerLastName;
|
|
296
|
+
this.email = this.brokerEmail;
|
|
297
|
+
this.brokerFirstName = "";
|
|
298
|
+
this.brokerLastName = "";
|
|
299
|
+
this.brokerEmail = "";
|
|
300
|
+
}
|
|
301
|
+
this.isBrokerReferral = isBrokerReferral;
|
|
302
|
+
this.hasNameError = false;
|
|
303
|
+
this.hasEmailError = false;
|
|
304
|
+
this.hasPhoneNumberError = false;
|
|
305
|
+
this.hasBrokerNameError = false;
|
|
306
|
+
this.brokerEmailError = null;
|
|
307
|
+
this.windowHeight = this.baseHeight() + 30 * this.getNumErrors();
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
onChangeBrokerField =
|
|
311
|
+
(
|
|
312
|
+
field:
|
|
313
|
+
| "brokerFirstName"
|
|
314
|
+
| "brokerLastName"
|
|
315
|
+
| "brokerEmail"
|
|
316
|
+
| "brokerFirmName"
|
|
317
|
+
) =>
|
|
318
|
+
(e: Event): void => {
|
|
319
|
+
if (!e.target) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
this[field] = (e.target as HTMLInputElement).value;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
/** The form's height without error lines: the broker's section adds rows when shown. */
|
|
326
|
+
baseHeight = (): number =>
|
|
327
|
+
525 +
|
|
328
|
+
// The broker's rows, less the 79px the compact message box gives back.
|
|
329
|
+
(this.brokerIntakeEnabled && this.isBrokerReferral ? 170 - 79 : 0);
|
|
330
|
+
|
|
331
|
+
/** The broker's details to send, only when the submitter says they're referring a client. */
|
|
332
|
+
brokerReferral = (): BrokerReferral | null =>
|
|
333
|
+
this.brokerIntakeEnabled && this.isBrokerReferral
|
|
334
|
+
? {
|
|
335
|
+
firstName: this.brokerFirstName.trim(),
|
|
336
|
+
lastName: this.brokerLastName.trim(),
|
|
337
|
+
email: this.brokerEmail.trim(),
|
|
338
|
+
firmName: this.brokerFirmName.trim(),
|
|
339
|
+
}
|
|
340
|
+
: null;
|
|
341
|
+
|
|
219
342
|
validateFormFields = (): void => {
|
|
220
343
|
this.hasNameError = false;
|
|
221
344
|
this.hasEmailError = false;
|
|
222
345
|
this.hasPhoneNumberError = false;
|
|
223
346
|
this.hasMessageError = false;
|
|
224
347
|
this.hasSubmissionError = false;
|
|
348
|
+
this.hasBrokerNameError = false;
|
|
349
|
+
this.brokerEmailError = null;
|
|
350
|
+
const broker = this.brokerReferral();
|
|
351
|
+
if (broker) {
|
|
352
|
+
if (!broker.firstName || !broker.lastName) {
|
|
353
|
+
this.hasBrokerNameError = true;
|
|
354
|
+
}
|
|
355
|
+
// Broker intake opens a broker thread only for a broker email, and a broker can't be their own client.
|
|
356
|
+
if (!broker.email || !isValidEmail(broker.email)) {
|
|
357
|
+
this.brokerEmailError = "Enter your valid email address";
|
|
358
|
+
} else if (
|
|
359
|
+
broker.email.toLowerCase() === this.email.trim().toLowerCase()
|
|
360
|
+
) {
|
|
361
|
+
this.brokerEmailError = "Enter your client's details below, not yours";
|
|
362
|
+
}
|
|
363
|
+
}
|
|
225
364
|
if (!this.firstName || !this.lastName) {
|
|
226
365
|
this.hasNameError = true;
|
|
227
366
|
}
|
|
@@ -231,7 +370,7 @@ export class EmailUsWindow extends LitElement {
|
|
|
231
370
|
if (!this.phoneNumberE164) {
|
|
232
371
|
this.hasPhoneNumberError = true;
|
|
233
372
|
}
|
|
234
|
-
this.windowHeight =
|
|
373
|
+
this.windowHeight = this.baseHeight() + 30 * this.getNumErrors();
|
|
235
374
|
};
|
|
236
375
|
|
|
237
376
|
onClick = async (): Promise<void> => {
|
|
@@ -243,7 +382,9 @@ export class EmailUsWindow extends LitElement {
|
|
|
243
382
|
this.hasNameError ||
|
|
244
383
|
this.hasEmailError ||
|
|
245
384
|
this.hasPhoneNumberError ||
|
|
246
|
-
this.hasMessageError
|
|
385
|
+
this.hasMessageError ||
|
|
386
|
+
this.hasBrokerNameError ||
|
|
387
|
+
this.brokerEmailError
|
|
247
388
|
) {
|
|
248
389
|
return;
|
|
249
390
|
}
|
|
@@ -255,7 +396,7 @@ export class EmailUsWindow extends LitElement {
|
|
|
255
396
|
try {
|
|
256
397
|
this.isSubmitting = true;
|
|
257
398
|
// Height of the button when it's in the loading state
|
|
258
|
-
this.windowHeight =
|
|
399
|
+
this.windowHeight = this.baseHeight() + 60;
|
|
259
400
|
const parsedLeadSource =
|
|
260
401
|
this.selectedLeadSource && this.selectedLeadSource.value
|
|
261
402
|
? this.selectedLeadSource.value
|
|
@@ -288,7 +429,8 @@ export class EmailUsWindow extends LitElement {
|
|
|
288
429
|
? this.selectedLeadSource.value
|
|
289
430
|
: null,
|
|
290
431
|
}
|
|
291
|
-
)
|
|
432
|
+
),
|
|
433
|
+
this.brokerReferral()
|
|
292
434
|
);
|
|
293
435
|
this.leadSourceClient?.checkAndHandleForLogLeadSource({
|
|
294
436
|
webchatAction: "email-us",
|
|
@@ -299,12 +441,12 @@ export class EmailUsWindow extends LitElement {
|
|
|
299
441
|
this.hasSubmittedForm = true;
|
|
300
442
|
this.isSubmitting = false;
|
|
301
443
|
// Remove the height of the button when it leaves the loading state
|
|
302
|
-
this.windowHeight =
|
|
444
|
+
this.windowHeight = this.baseHeight();
|
|
303
445
|
} catch (e) {
|
|
304
446
|
this.hasSubmissionError = true;
|
|
305
447
|
this.isSubmitting = false;
|
|
306
448
|
// Remove the height of the button when it leaves the loading state
|
|
307
|
-
this.windowHeight =
|
|
449
|
+
this.windowHeight = this.baseHeight();
|
|
308
450
|
}
|
|
309
451
|
};
|
|
310
452
|
|
|
@@ -315,9 +457,88 @@ export class EmailUsWindow extends LitElement {
|
|
|
315
457
|
this.hasPhoneNumberError,
|
|
316
458
|
this.hasMessageError,
|
|
317
459
|
this.hasSubmissionError,
|
|
460
|
+
this.hasBrokerNameError,
|
|
461
|
+
!!this.brokerEmailError,
|
|
318
462
|
].filter((v) => v).length;
|
|
319
463
|
};
|
|
320
464
|
|
|
465
|
+
renderBrokerToggle = (): TemplateResult => html`
|
|
466
|
+
<label class="email-us__broker-toggle">
|
|
467
|
+
<input
|
|
468
|
+
type="checkbox"
|
|
469
|
+
id="broker-referral-toggle"
|
|
470
|
+
.checked=${this.isBrokerReferral}
|
|
471
|
+
@change=${this.onToggleBrokerReferral}
|
|
472
|
+
/>
|
|
473
|
+
Agent or broker? Refer a client
|
|
474
|
+
</label>
|
|
475
|
+
`;
|
|
476
|
+
|
|
477
|
+
renderBrokerSection = (): TemplateResult => {
|
|
478
|
+
const inputClasses = (extra: string) =>
|
|
479
|
+
classMap({
|
|
480
|
+
["webchat-input"]: true,
|
|
481
|
+
[extra]: true,
|
|
482
|
+
["webchat-font__desktop"]: !isMobile(),
|
|
483
|
+
["webchat-font__mobile"]: isMobile(),
|
|
484
|
+
});
|
|
485
|
+
return html`
|
|
486
|
+
${this.isBrokerReferral
|
|
487
|
+
? html`
|
|
488
|
+
<div class="email-us__section-label">Your details</div>
|
|
489
|
+
<div class="email-us__name-wrapper">
|
|
490
|
+
<input
|
|
491
|
+
type="text"
|
|
492
|
+
class=${inputClasses("email-us__name-input")}
|
|
493
|
+
placeholder="Your first name"
|
|
494
|
+
autocomplete="given-name"
|
|
495
|
+
.value=${this.brokerFirstName}
|
|
496
|
+
@input=${this.onChangeBrokerField("brokerFirstName")}
|
|
497
|
+
/>
|
|
498
|
+
<input
|
|
499
|
+
type="text"
|
|
500
|
+
class=${inputClasses("email-us__name-input")}
|
|
501
|
+
placeholder="Your last name"
|
|
502
|
+
autocomplete="family-name"
|
|
503
|
+
.value=${this.brokerLastName}
|
|
504
|
+
@input=${this.onChangeBrokerField("brokerLastName")}
|
|
505
|
+
/>
|
|
506
|
+
</div>
|
|
507
|
+
${this.hasBrokerNameError
|
|
508
|
+
? html`<div class="email-us__error-text">
|
|
509
|
+
Enter your full name
|
|
510
|
+
</div>`
|
|
511
|
+
: ""}
|
|
512
|
+
<div class="email-us__vertical-spacer"></div>
|
|
513
|
+
<input
|
|
514
|
+
type="email"
|
|
515
|
+
class=${inputClasses("email-us__contact-input")}
|
|
516
|
+
placeholder="Your email"
|
|
517
|
+
autocomplete="email"
|
|
518
|
+
.value=${this.brokerEmail}
|
|
519
|
+
@input=${this.onChangeBrokerField("brokerEmail")}
|
|
520
|
+
/>
|
|
521
|
+
${this.brokerEmailError
|
|
522
|
+
? html`<div class="email-us__error-text">
|
|
523
|
+
${this.brokerEmailError}
|
|
524
|
+
</div>`
|
|
525
|
+
: ""}
|
|
526
|
+
<div class="email-us__vertical-spacer"></div>
|
|
527
|
+
<input
|
|
528
|
+
type="text"
|
|
529
|
+
class=${inputClasses("email-us__contact-input")}
|
|
530
|
+
placeholder="Brokerage (optional)"
|
|
531
|
+
autocomplete="organization"
|
|
532
|
+
.value=${this.brokerFirmName}
|
|
533
|
+
@input=${this.onChangeBrokerField("brokerFirmName")}
|
|
534
|
+
/>
|
|
535
|
+
<div class="email-us__vertical-spacer"></div>
|
|
536
|
+
<div class="email-us__section-label">Your client</div>
|
|
537
|
+
`
|
|
538
|
+
: ""}
|
|
539
|
+
`;
|
|
540
|
+
};
|
|
541
|
+
|
|
321
542
|
render = (): TemplateResult => {
|
|
322
543
|
installDetailsWindow();
|
|
323
544
|
installActionConfirmButton();
|
|
@@ -350,8 +571,9 @@ export class EmailUsWindow extends LitElement {
|
|
|
350
571
|
</div>
|
|
351
572
|
<div class="email-us__vertical-spacer"></div>
|
|
352
573
|
<div class="email-us__submitted-info">
|
|
353
|
-
|
|
354
|
-
|
|
574
|
+
${this.isBrokerReferral
|
|
575
|
+
? "Thank you for the referral. A member of our leasing team will contact your client."
|
|
576
|
+
: "Thank you for your message. A member of our leasing team will contact you."}
|
|
355
577
|
</div>
|
|
356
578
|
</div>
|
|
357
579
|
</details-window>
|
|
@@ -366,6 +588,7 @@ export class EmailUsWindow extends LitElement {
|
|
|
366
588
|
height="${this.windowHeight}px"
|
|
367
589
|
>
|
|
368
590
|
<div class="email-us-wrapper" id="email-us-form">
|
|
591
|
+
${this.brokerIntakeEnabled ? this.renderBrokerSection() : ""}
|
|
369
592
|
<div class="email-us__name-wrapper">
|
|
370
593
|
<input
|
|
371
594
|
type="text"
|
|
@@ -375,10 +598,12 @@ export class EmailUsWindow extends LitElement {
|
|
|
375
598
|
["webchat-font__desktop"]: !isMobile(),
|
|
376
599
|
["webchat-font__mobile"]: isMobile(),
|
|
377
600
|
})}
|
|
378
|
-
placeholder
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
601
|
+
placeholder=${this.isBrokerReferral
|
|
602
|
+
? "Client first name"
|
|
603
|
+
: "First name"}
|
|
604
|
+
autocomplete=${this.isBrokerReferral ? "off" : "given-name"}
|
|
605
|
+
.value=${this.firstName}
|
|
606
|
+
@input=${this.onChangeFirstName}
|
|
382
607
|
/>
|
|
383
608
|
<div class="email-us__horizontal-spacer"></div>
|
|
384
609
|
<input
|
|
@@ -389,22 +614,28 @@ export class EmailUsWindow extends LitElement {
|
|
|
389
614
|
["webchat-font__desktop"]: !isMobile(),
|
|
390
615
|
["webchat-font__mobile"]: isMobile(),
|
|
391
616
|
})}
|
|
392
|
-
placeholder
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
617
|
+
placeholder=${this.isBrokerReferral
|
|
618
|
+
? "Client last name"
|
|
619
|
+
: "Last name"}
|
|
620
|
+
autocomplete=${this.isBrokerReferral ? "off" : "family-name"}
|
|
621
|
+
.value=${this.lastName}
|
|
622
|
+
@input=${this.onChangeLastName}
|
|
396
623
|
/>
|
|
397
624
|
</div>
|
|
398
625
|
${this.hasNameError
|
|
399
626
|
? html`
|
|
400
|
-
<div class="email-us__error-text">
|
|
627
|
+
<div class="email-us__error-text">
|
|
628
|
+
${this.isBrokerReferral
|
|
629
|
+
? "Enter your client's full name"
|
|
630
|
+
: "Enter your full name"}
|
|
631
|
+
</div>
|
|
401
632
|
`
|
|
402
633
|
: ""}
|
|
403
634
|
<div class="email-us__vertical-spacer"></div>
|
|
404
635
|
<input
|
|
405
636
|
type="email"
|
|
406
|
-
placeholder
|
|
407
|
-
autocomplete
|
|
637
|
+
placeholder=${this.isBrokerReferral ? "Client email" : "Email"}
|
|
638
|
+
autocomplete=${this.isBrokerReferral ? "off" : "email"}
|
|
408
639
|
class=${classMap({
|
|
409
640
|
["webchat-input"]: true,
|
|
410
641
|
["email-us__contact-input"]: true,
|
|
@@ -412,7 +643,7 @@ export class EmailUsWindow extends LitElement {
|
|
|
412
643
|
["webchat-font__mobile"]: isMobile(),
|
|
413
644
|
})}
|
|
414
645
|
.value=${this.email}
|
|
415
|
-
@
|
|
646
|
+
@input=${this.onChangeEmail}
|
|
416
647
|
/>
|
|
417
648
|
${this.hasEmailError
|
|
418
649
|
? html`
|
|
@@ -463,6 +694,7 @@ export class EmailUsWindow extends LitElement {
|
|
|
463
694
|
.value=${this.message}
|
|
464
695
|
class=${classMap({
|
|
465
696
|
["email-us__message-input"]: true,
|
|
697
|
+
["email-us__message-input--compact"]: this.isBrokerReferral,
|
|
466
698
|
["webchat-input"]: true,
|
|
467
699
|
["webchat-textarea"]: true,
|
|
468
700
|
["webchat-font__desktop"]: !isMobile(),
|
|
@@ -473,7 +705,13 @@ export class EmailUsWindow extends LitElement {
|
|
|
473
705
|
${this.hasMessageError
|
|
474
706
|
? html` <div class="email-us__error-text">Include a message</div> `
|
|
475
707
|
: ""}
|
|
476
|
-
<div
|
|
708
|
+
<div
|
|
709
|
+
class=${classMap({
|
|
710
|
+
["action-bttn-container"]: true,
|
|
711
|
+
["action-bttn-container--with-toggle"]: this.brokerIntakeEnabled,
|
|
712
|
+
})}
|
|
713
|
+
>
|
|
714
|
+
${this.brokerIntakeEnabled ? this.renderBrokerToggle() : ""}
|
|
477
715
|
<action-confirm-button
|
|
478
716
|
.onClick=${this.onClick}
|
|
479
717
|
.isLoading=${this.isSubmitting}
|
|
@@ -508,6 +746,14 @@ export const installEmailUsWindow = (): void => {
|
|
|
508
746
|
}
|
|
509
747
|
};
|
|
510
748
|
|
|
749
|
+
/** A broker submitting the form for a client: sent as the request's broker fields. */
|
|
750
|
+
export type BrokerReferral = {
|
|
751
|
+
firstName: string;
|
|
752
|
+
lastName: string;
|
|
753
|
+
email: string;
|
|
754
|
+
firmName: string;
|
|
755
|
+
};
|
|
756
|
+
|
|
511
757
|
const createEmail = async (
|
|
512
758
|
firstName: string,
|
|
513
759
|
lastName: string,
|
|
@@ -519,7 +765,8 @@ const createEmail = async (
|
|
|
519
765
|
buildingSlug: string,
|
|
520
766
|
leadSources: string[],
|
|
521
767
|
chatId?: string | null,
|
|
522
|
-
leadSourcesWithTimestamps?: LeadSourceSubmittedListItem[]
|
|
768
|
+
leadSourcesWithTimestamps?: LeadSourceSubmittedListItem[],
|
|
769
|
+
broker?: BrokerReferral | null
|
|
523
770
|
) => {
|
|
524
771
|
const queryParams = new URLSearchParams(window.location.search);
|
|
525
772
|
const requestBody = {
|
|
@@ -538,6 +785,15 @@ const createEmail = async (
|
|
|
538
785
|
lead_sources_with_timestamps: (leadSourcesWithTimestamps ?? []).map(
|
|
539
786
|
(source) => snakify({ ...source })
|
|
540
787
|
),
|
|
788
|
+
// The prospect fields above are the client's; broker intake links the broker to them.
|
|
789
|
+
...(broker
|
|
790
|
+
? {
|
|
791
|
+
broker_first_name: broker.firstName,
|
|
792
|
+
broker_last_name: broker.lastName,
|
|
793
|
+
broker_email: broker.email,
|
|
794
|
+
broker_firm_name: broker.firmName || null,
|
|
795
|
+
}
|
|
796
|
+
: {}),
|
|
541
797
|
};
|
|
542
798
|
pushGtmEvent("emailUsSubmitted", {
|
|
543
799
|
firstName,
|
|
@@ -548,6 +804,8 @@ const createEmail = async (
|
|
|
548
804
|
originatingSource:
|
|
549
805
|
leadSources.find((i) => i !== "property-website") || null,
|
|
550
806
|
conversationTrackingId: chatId ?? null,
|
|
807
|
+
// A flag only: the broker's own details stay out of the data layer.
|
|
808
|
+
...(broker ? { isBrokerReferral: true } : {}),
|
|
551
809
|
});
|
|
552
810
|
await axios.post(
|
|
553
811
|
"https://app.meetelise.com/platformApi/state/create/emailMe",
|
|
@@ -157,6 +157,8 @@ export class Launcher extends LitElement {
|
|
|
157
157
|
layoutOptions: LayoutOption[] = [];
|
|
158
158
|
@property({ attribute: true })
|
|
159
159
|
bedroomPreferenceRequired = false;
|
|
160
|
+
@property({ attribute: false })
|
|
161
|
+
brokerIntakeEnabled = false;
|
|
160
162
|
@property({ attribute: true })
|
|
161
163
|
hasDynamicSchedulingEnabled = false;
|
|
162
164
|
|
|
@@ -1343,6 +1345,7 @@ export class Launcher extends LitElement {
|
|
|
1343
1345
|
.orgLegalName=${this.orgLegalName}
|
|
1344
1346
|
.country=${this.country}
|
|
1345
1347
|
.buildingState=${this.buildingState}
|
|
1348
|
+
.brokerIntakeEnabled=${this.brokerIntakeEnabled}
|
|
1346
1349
|
>
|
|
1347
1350
|
</email-us-window>
|
|
1348
1351
|
</div>`
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
fetchFeatureFlagUseApplicationsLinkReplacement,
|
|
16
16
|
fetchFeatureFlagUseOverrideContactUsForm,
|
|
17
17
|
fetchTrackedRolloutBedroomPreferenceRequired,
|
|
18
|
+
fetchTrackedRolloutBrokerIntake,
|
|
18
19
|
} from "../fetchFeatureFlag";
|
|
19
20
|
import { HIDE_DATA_LAYER_PII_ORG_IDS, setGtmPiiRedaction } from "../gtm";
|
|
20
21
|
import fetchPhoneNumberFromSource, {
|
|
@@ -180,6 +181,8 @@ export class MEChat extends LitElement {
|
|
|
180
181
|
@state()
|
|
181
182
|
private bedroomPreferenceRequired = false;
|
|
182
183
|
@state()
|
|
184
|
+
private brokerIntakeEnabled = false;
|
|
185
|
+
@state()
|
|
183
186
|
private phoneNumberForSource: NumberForSelectedSource | null = null;
|
|
184
187
|
@state()
|
|
185
188
|
private hasMounted = false;
|
|
@@ -380,11 +383,13 @@ export class MEChat extends LitElement {
|
|
|
380
383
|
featureFlagUseApplicationsLinkReplacement,
|
|
381
384
|
isAip,
|
|
382
385
|
bedroomPreferenceRequired,
|
|
386
|
+
brokerIntakeEnabled,
|
|
383
387
|
] = await Promise.all([
|
|
384
388
|
fetchLeadSources(this.orgSlug, this.buildingSlug),
|
|
385
389
|
fetchFeatureFlagUseApplicationsLinkReplacement(this.buildingSlug),
|
|
386
390
|
fetchBuildingAip(this.buildingSlug),
|
|
387
391
|
fetchTrackedRolloutBedroomPreferenceRequired(this.buildingSlug),
|
|
392
|
+
fetchTrackedRolloutBrokerIntake(this.buildingSlug),
|
|
388
393
|
]);
|
|
389
394
|
|
|
390
395
|
if (this.buildingWebchatView) {
|
|
@@ -397,6 +402,7 @@ export class MEChat extends LitElement {
|
|
|
397
402
|
this.featureFlagShowDropdown =
|
|
398
403
|
featureFlagShowDropdown as FeatureFlagsShowDropdown;
|
|
399
404
|
this.bedroomPreferenceRequired = bedroomPreferenceRequired;
|
|
405
|
+
this.brokerIntakeEnabled = brokerIntakeEnabled;
|
|
400
406
|
|
|
401
407
|
// The backend is cached for ~4 hours, so falling back to the existing api request until the cache propagates all the changes
|
|
402
408
|
const buildingPhoneNumber = buildingDetails.textWithUsPhoneNumber
|
|
@@ -1050,6 +1056,7 @@ export class MEChat extends LitElement {
|
|
|
1050
1056
|
.layoutOptions=${this.buildingWebchatView?.layoutOptions ??
|
|
1051
1057
|
[]}
|
|
1052
1058
|
.bedroomPreferenceRequired=${this.bedroomPreferenceRequired}
|
|
1059
|
+
.brokerIntakeEnabled=${this.brokerIntakeEnabled}
|
|
1053
1060
|
.launcherStyles=${this.launcherStyles}
|
|
1054
1061
|
.primaryColor=${this.primaryColor}
|
|
1055
1062
|
.backgroundColor=${this.backgroundColor}
|