@meetelise/chat 1.46.0 → 1.47.1

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.
@@ -226,6 +226,8 @@ export class TourScheduler extends LitElement {
226
226
 
227
227
  @state()
228
228
  private centralConvoBuildings: CentralConvoBuilding[] = [];
229
+ @state()
230
+ private isGeneralBuilding = false;
229
231
  @query("me-select#building")
230
232
  selectedBuildingEl?: MESelect;
231
233
  @state()
@@ -466,7 +468,14 @@ export class TourScheduler extends LitElement {
466
468
  };
467
469
 
468
470
  firstUpdated = async (): Promise<void> => {
469
- this._fetchCentralConvoBuildings();
471
+ await this._fetchCentralConvoBuildings();
472
+ if (this.isGeneralBuilding) {
473
+ this.waitingForAvailabilities = false;
474
+ this.shouldAllowScheduleLoading = false;
475
+ this.statusMessage =
476
+ "Please select a building to see tour availabilities.";
477
+ return;
478
+ }
470
479
  await this._loadForCurrentBuilding();
471
480
  };
472
481
 
@@ -493,12 +502,15 @@ export class TourScheduler extends LitElement {
493
502
  private _fetchCentralConvoBuildings = async (): Promise<void> => {
494
503
  if (!this.orgSlug || !this.buildingSlug) return;
495
504
  try {
496
- this.centralConvoBuildings = await fetchCentralConvoBuildings(
505
+ const res = await fetchCentralConvoBuildings(
497
506
  this.orgSlug,
498
507
  this.buildingSlug
499
508
  );
509
+ this.centralConvoBuildings = res.buildings;
510
+ this.isGeneralBuilding = res.is_general_building;
500
511
  } catch (e) {
501
512
  this.centralConvoBuildings = [];
513
+ this.isGeneralBuilding = false;
502
514
  }
503
515
  };
504
516
 
@@ -508,6 +520,7 @@ export class TourScheduler extends LitElement {
508
520
  const building = this.centralConvoBuildings.find((b) => b.slug === slug);
509
521
  if (!building) return;
510
522
 
523
+ this.isGeneralBuilding = false;
511
524
  this.waitingForAvailabilities = true;
512
525
  this.errorGettingAvailabilities = false;
513
526
  this.tourType = null;
@@ -561,20 +574,28 @@ export class TourScheduler extends LitElement {
561
574
  }
562
575
  };
563
576
 
577
+ buildingSelectMenu(): TemplateResult {
578
+ return html`<me-select
579
+ id="building"
580
+ placeholder="Select a property"
581
+ .value=${this.isGeneralBuilding ? "" : this.buildingSlug}
582
+ .options="${this.centralConvoBuildings.map((b) => ({
583
+ label: b.name,
584
+ value: b.slug,
585
+ }))}"
586
+ @change=${this._onBuildingChange}
587
+ >
588
+ </me-select>`;
589
+ }
590
+
564
591
  buildingSelector(): TemplateResult | string {
565
- if (this.centralConvoBuildings.length <= 1) return "";
592
+ if (this.isGeneralBuilding) {
593
+ if (this.centralConvoBuildings.length === 0) return "";
594
+ } else if (this.centralConvoBuildings.length <= 1) {
595
+ return "";
596
+ }
566
597
  return html`<h2 class="journey-header">Building</h2>
567
- <me-select
568
- id="building"
569
- placeholder="Select a property"
570
- .value=${this.buildingSlug}
571
- .options="${this.centralConvoBuildings.map((b) => ({
572
- label: b.name,
573
- value: b.slug,
574
- }))}"
575
- @change=${this._onBuildingChange}
576
- >
577
- </me-select>`;
598
+ ${this.buildingSelectMenu()}`;
578
599
  }
579
600
 
580
601
  protected willUpdate = async (
@@ -1578,27 +1599,42 @@ export class TourScheduler extends LitElement {
1578
1599
  `;
1579
1600
  }
1580
1601
 
1602
+ private renderCenteredCard(content: TemplateResult): TemplateResult {
1603
+ return html` <div
1604
+ id="tour-scheduler-inner-form"
1605
+ class="${classnames({
1606
+ "tour-scheduler-full": !this.compactDesign && !isMobile(),
1607
+ "tour-scheduler-compact": this.compactDesign && !isMobile(),
1608
+ "tour-scheduler-mobile": isMobile(),
1609
+ })}"
1610
+ >
1611
+ <div id="top-header">
1612
+ <div></div>
1613
+ ${this.closeButton()}
1614
+ </div>
1615
+ <div class="center-tour-not-avail">${content}</div>
1616
+ </div>`;
1617
+ }
1618
+
1581
1619
  private renderBody(): TemplateResult {
1582
1620
  const isLoading =
1583
1621
  this.waitingForAvailabilities || this.shouldAllowScheduleLoading;
1622
+ if (this.isGeneralBuilding && !isLoading) {
1623
+ return this.renderCenteredCard(html`
1624
+ <h1>Please select a building</h1>
1625
+ <p>Choose a property to see available tours.</p>
1626
+ ${this.centralConvoBuildings.length > 0
1627
+ ? html`<div class="general-building-select">
1628
+ ${this.buildingSelectMenu()}
1629
+ </div>`
1630
+ : ""}
1631
+ `);
1632
+ }
1584
1633
  if (!this.shouldAllowScheduling && !isLoading) {
1585
- return html` <div
1586
- id="tour-scheduler-inner-form"
1587
- class="${classnames({
1588
- "tour-scheduler-full": !this.compactDesign && !isMobile(),
1589
- "tour-scheduler-compact": this.compactDesign && !isMobile(),
1590
- "tour-scheduler-mobile": isMobile(),
1591
- })}"
1592
- >
1593
- <div id="top-header">
1594
- <div></div>
1595
- ${this.closeButton()}
1596
- </div>
1597
- <div class="center-tour-not-avail">
1598
- <h1>Sorry, there are currently no tour availabilities</h1>
1599
- <p>Please check back again later</p>
1600
- </div>
1601
- </div>`;
1634
+ return this.renderCenteredCard(html`
1635
+ <h1>Sorry, there are currently no tour availabilities</h1>
1636
+ <p>Please check back again later</p>
1637
+ `);
1602
1638
  }
1603
1639
  if (isLoading) {
1604
1640
  return html` <div
@@ -441,6 +441,10 @@ otherwise there's some empty space at the bottom of the button, which interferes
441
441
  font-size: 14px;
442
442
  text-align: left;
443
443
  }
444
+ .general-building-select {
445
+ width: 100%;
446
+ margin-top: 16px;
447
+ }
444
448
  .loading-entire-tour-icon {
445
449
  padding: 24px;
446
450
  }
@@ -31,6 +31,7 @@ import { StyleInfo } from "lit/directives/style-map";
31
31
  import addMinutes from "date-fns/addMinutes";
32
32
  import formatISO from "date-fns/formatISO";
33
33
  import fetchLeadSources from "../fetchLeadSources";
34
+ import fetchBuildingAip from "../fetchBuildingAip";
34
35
  import { formatPhoneNumber } from "./actions/formatPhoneNumber";
35
36
  import MyPubnub from "../MyPubnub";
36
37
  import { insertDNIIntoWebsite } from "../insertDNIIntoWebsite";
@@ -351,16 +352,18 @@ export class MEChat extends LitElement {
351
352
  const featureFlagReplaceScheduleTourCtaWebsite =
352
353
  buildingDetails.featureFlagWebchatReplaceAnyScheduleTourCtaWebsite;
353
354
 
354
- const [leadSources, featureFlagUseApplicationsLinkReplacement] =
355
+ const [leadSources, featureFlagUseApplicationsLinkReplacement, isAip] =
355
356
  await Promise.all([
356
357
  fetchLeadSources(this.orgSlug, this.buildingSlug),
357
358
  fetchFeatureFlagUseApplicationsLinkReplacement(this.buildingSlug),
359
+ fetchBuildingAip(this.buildingSlug),
358
360
  ]);
359
361
 
360
362
  if (this.buildingWebchatView) {
361
363
  this.buildingWebchatView.phoneNumber = formatPhoneNumber(
362
364
  buildingDetails.phoneNumber
363
365
  );
366
+ this.buildingWebchatView.isAip = isAip;
364
367
  }
365
368
  this.leadSources = leadSources;
366
369
  this.featureFlagShowDropdown =
@@ -518,12 +521,11 @@ export class MEChat extends LitElement {
518
521
  }
519
522
  }
520
523
  getRawAvailabilities(buildingDetails.id); // we're not using this here, just want to cache the result
521
-
522
- if (
523
- featureFlagUseApplicationsLinkReplacement &&
524
- this.buildingSlug &&
525
- this.buildingWebchatView?.isLiveOnApplications
526
- ) {
524
+ const isApplicationLinkReplacementEnabled =
525
+ (featureFlagUseApplicationsLinkReplacement ||
526
+ this.buildingWebchatView?.isAip) &&
527
+ this.buildingWebchatView?.isLiveOnApplications;
528
+ if (isApplicationLinkReplacementEnabled && this.buildingSlug) {
527
529
  const totalReplacements = replaceSelectButtonsWithNewLink(
528
530
  `https://applications.eliseai.com/building/${this.buildingSlug}/units`,
529
531
  this.orgSlug,
@@ -0,0 +1,18 @@
1
+ import axios from "axios";
2
+
3
+ export default async function fetchBuildingAip(
4
+ buildingSlug: string
5
+ ): Promise<boolean> {
6
+ if (!buildingSlug) {
7
+ return false;
8
+ }
9
+ const host = "https://app.meetelise.com";
10
+ try {
11
+ const response = await axios.get(
12
+ `${host}/platformApi/webchat/${buildingSlug}/aip`
13
+ );
14
+ return response.data?.is_aip ?? false;
15
+ } catch (_) {
16
+ return false;
17
+ }
18
+ }
@@ -130,6 +130,7 @@ export interface BuildingWebchatView {
130
130
  featureFlagInsertDniIntoWebsite: boolean;
131
131
  featureFlagWebchatReplaceAnyScheduleTourCtaWebsite: boolean;
132
132
  customAdditionalDisclaimer: string | null;
133
+ isAip: boolean;
133
134
  }
134
135
 
135
136
  /**
@@ -145,7 +146,6 @@ export default async function fetchBuildingWebchatView(
145
146
  ): Promise<BuildingWebchatView> {
146
147
  const host = "https://app.meetelise.com";
147
148
  const buildingUrl = `${host}/api/pub/v1/organization/${orgSlug}/building/${buildingSlug}/v2`;
148
-
149
149
  const buildingResponse = await axios.get(buildingUrl);
150
150
 
151
151
  const buildingWebchatView: BuildingWebchatView = buildingResponse.data;
@@ -6,10 +6,14 @@ export interface CentralConvoBuilding {
6
6
  slug: string;
7
7
  }
8
8
 
9
+ export interface CentralConvoBuildingsResponse {
10
+ is_general_building: boolean;
11
+ buildings: CentralConvoBuilding[];
12
+ }
13
+
9
14
  /**
10
15
  * Fetch the buildings that belong to the same central conversation group as the
11
- * current building. Returns an empty array when the building is not part of a
12
- * central conversation group (in which case no building selector is shown).
16
+ * current building.
13
17
  *
14
18
  * @param orgSlug - The org slug, e.g. "big-prop-co"
15
19
  * @param buildingSlug - The current building's slug, e.g. "gravity-falls"
@@ -17,16 +21,20 @@ export interface CentralConvoBuilding {
17
21
  export default async function fetchCentralConvoBuildings(
18
22
  orgSlug: string,
19
23
  buildingSlug: string
20
- ): Promise<CentralConvoBuilding[]> {
24
+ ): Promise<CentralConvoBuildingsResponse> {
21
25
  const host = "https://app.meetelise.com";
22
- const url = `${host}/platformApi/webchat/central-convo-buildings`;
26
+ const url = `${host}/platformApi/webchat/central-convo-buildings-v2`;
23
27
 
24
- const response = await axios.get<CentralConvoBuilding[]>(url, {
28
+ const response = await axios.get<CentralConvoBuildingsResponse>(url, {
25
29
  headers: {
26
30
  ["building-slug"]: buildingSlug,
27
31
  ["org-slug"]: orgSlug,
28
32
  },
29
33
  });
30
34
 
31
- return response.data ?? [];
35
+ const data = response.data;
36
+ return {
37
+ is_general_building: data?.is_general_building ?? false,
38
+ buildings: data?.buildings ?? [],
39
+ };
32
40
  }
@@ -17,6 +17,9 @@ export const replaceSelectButtonsWithNewLink = (
17
17
  /thehavenatgreenhill\.securecafe\.com\/onlineleasing\/the-haven-at-greenhill\/oleapplication\.aspx(\?.*)?$/,
18
18
  /securecafe\.com\/onlineleasing.*\/oleapplication\.aspx(\?.*)?$/,
19
19
  /\/onlineleasing.*\/oleapplication\.aspx(\?.*)?$/,
20
+ /\/content\/apply/,
21
+ /\/apply-now/,
22
+ /\/apply/,
20
23
  /vsc\.myresman\.com\/Portal\/Applicants\/Availability(\?.*)?$/,
21
24
  /vsc\.myresman\.com\/Portal\/Applicants\/New\/.*(\?.*)?$/,
22
25
  /busboomgroup\.myresman\.com\/Portal\/Applicants\/Availability(\?.*)?$/,