@meetelise/chat 1.13.8 → 1.13.11

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.
@@ -11,7 +11,7 @@ import "./time-picker.ts";
11
11
  import "./me-select.ts";
12
12
  import {
13
13
  DateWithTimeZoneOffset,
14
- getAvailabilitiesGroupedByDayCached,
14
+ getAvailabilitiesGroupedByDay,
15
15
  } from "../../getAvailabilities";
16
16
  import { TourAvailabilityResponseRankOrderedSupportedTourTypesEnum } from "@meetelise/rest-sdk";
17
17
  import { format } from "date-fns";
@@ -53,8 +53,10 @@ export class TourScheduler extends LitElement {
53
53
  @state()
54
54
  private tourIsBooked = false;
55
55
 
56
- @query("input#name")
57
- nameInput!: HTMLInputElement;
56
+ @query("input#firstName")
57
+ firstNameInput!: HTMLInputElement;
58
+ @query("input#lastName")
59
+ lastNameInput!: HTMLInputElement;
58
60
  @query("input#email")
59
61
  emailInput!: HTMLInputElement;
60
62
  @query("input#phone")
@@ -63,7 +65,7 @@ export class TourScheduler extends LitElement {
63
65
  unitTypeSelect!: MESelect;
64
66
 
65
67
  firstUpdated = async (): Promise<void> => {
66
- this.availabilitiesGroupedByDay = await getAvailabilitiesGroupedByDayCached(
68
+ this.availabilitiesGroupedByDay = await getAvailabilitiesGroupedByDay(
67
69
  tourTypeMap[this.tourType]
68
70
  );
69
71
  };
@@ -74,8 +76,9 @@ export class TourScheduler extends LitElement {
74
76
  | Map<PropertyKey, unknown>
75
77
  ): Promise<void> => {
76
78
  if (_changedProperties.has("tourType")) {
77
- this.availabilitiesGroupedByDay =
78
- await getAvailabilitiesGroupedByDayCached(tourTypeMap[this.tourType]);
79
+ this.availabilitiesGroupedByDay = await getAvailabilitiesGroupedByDay(
80
+ tourTypeMap[this.tourType]
81
+ );
79
82
  }
80
83
  };
81
84
 
@@ -235,7 +238,7 @@ export class TourScheduler extends LitElement {
235
238
  dateAndTime: (): boolean => !!this.selectedDate && !!this.selectedTime,
236
239
  leadInfo: (): boolean => {
237
240
  return (
238
- !!this.nameInput?.value &&
241
+ (!!this.firstNameInput?.value || !!this.lastNameInput?.value) &&
239
242
  this.emailInput?.value.includes("@") &&
240
243
  // TODO: deleting phone number doesn't cause validation to fail, at least on mobile
241
244
  !!this.phoneNumber &&
@@ -272,9 +275,8 @@ export class TourScheduler extends LitElement {
272
275
  email_address: this.email,
273
276
  phone_number: `+1${this.phoneNumber.match(/\d/g)?.join("")}`, // e.g. +12125555555
274
277
  building_id: this.buildingId,
275
- // TODO: this is very bad dumb name-splitting logic! I'm only doing it because the design had one name field and the backend expects two
276
- first_name: this.nameInput.value.split(" ")[0],
277
- last_name: this.nameInput.value.split(" ").slice(1).join(" "),
278
+ first_name: this.firstNameInput.value,
279
+ last_name: this.lastNameInput.value,
278
280
  tour_type: tourTypeForSubmission[this.tourType],
279
281
  tour_time: `${this.selectedTime.datetime}${this.selectedTime.offset}`, // e.g., "2022-06-27T09:00:00-07:00"
280
282
  };
@@ -606,7 +608,6 @@ export class TourScheduler extends LitElement {
606
608
  <div id="tourTypeMenu">
607
609
  ${this.tourTypeOptions.map((o) => o.value).includes("WITH_AGENT")
608
610
  ? html` <tour-type-option
609
- tourtype="guided"
610
611
  heading="Guided tour"
611
612
  subtitle="with an agent"
612
613
  @click="${() => {
@@ -639,7 +640,6 @@ export class TourScheduler extends LitElement {
639
640
  : ""}
640
641
  ${this.tourTypeOptions.map((o) => o.value).includes("SELF_GUIDED")
641
642
  ? html`<tour-type-option
642
- tourtype="self"
643
643
  heading="Take a tour"
644
644
  subtitle="on your own"
645
645
  @click="${() => {
@@ -670,9 +670,8 @@ export class TourScheduler extends LitElement {
670
670
  </svg>
671
671
  </tour-type-option>`
672
672
  : ""}
673
- ${this.tourTypeOptions.map((o) => o.value).includes("SELF_GUIDED")
673
+ ${this.tourTypeOptions.map((o) => o.value).includes("VIRTUAL_SHOWING")
674
674
  ? html`<tour-type-option
675
- tourtype="guided"
676
675
  heading="Virtual tour"
677
676
  subtitle="over video"
678
677
  @click="${() => {
@@ -741,7 +740,8 @@ export class TourScheduler extends LitElement {
741
740
  .map((date) => format(new Date(date.datetime), "h:mmaaa"))
742
741
  .indexOf(e.target.selectedTime)
743
742
  : null;
744
- this.selectedTime = index ? daysAvailabilities[index] : null; // this.selectedAvailabilityString ?
743
+ this.selectedTime =
744
+ index !== null ? daysAvailabilities[index] : null;
745
745
  }
746
746
  }}
747
747
  ></time-picker>
@@ -811,8 +811,14 @@ export class TourScheduler extends LitElement {
811
811
  <div id="yourInformationMenu">
812
812
  <input
813
813
  type="text"
814
- placeholder="Name"
815
- id="name"
814
+ placeholder="First name"
815
+ id="firstName"
816
+ @input=${() => this.requestUpdate()}
817
+ />
818
+ <input
819
+ type="text"
820
+ placeholder="Last name"
821
+ id="lastName"
816
822
  @input=${() => this.requestUpdate()}
817
823
  />
818
824
  <input
@@ -842,25 +848,11 @@ export class TourScheduler extends LitElement {
842
848
  }}
843
849
  />
844
850
  </div>
845
-
846
- ${this.layoutOptions.length > 0
847
- ? html`<div id="unitChoiceMenu">
848
- <h2 id="unitChoice">What would you like to view?</h2>
849
- <div id="unitOptions">
850
- <me-select
851
- id="unitType"
852
- placeholder="Select type"
853
- .options="${this.layoutOptions.map((o) => o.label)}"
854
- defaultOption="Studio"
855
- @change=${() => {
856
- // to revalidate the form
857
- this.requestUpdate();
858
- }}
859
- >Studio
860
- </me-select>
861
- </div>
862
- </div>`
863
- : ""} `;
851
+ <!--
852
+ Layout dropdown would go here, but has been removed pending backend support.
853
+ Here is the code to add it back:
854
+ https://github.com/MeetElise/chat-ui/blob/e17aca8b39a0eed9430f22c182f2ebcdfb796417/src/WebComponent/Scheduler/tour-scheduler.ts#L846-L863
855
+ --> `;
864
856
  }
865
857
 
866
858
  confirmationMessage(): TemplateResult {
@@ -1,20 +1,16 @@
1
1
  import { css, html, LitElement, TemplateResult } from "lit";
2
2
  import { customElement, property } from "lit/decorators.js";
3
- import { TourType } from "./tour-scheduler";
4
3
 
5
4
  @customElement("tour-type-option")
6
5
  export class TourTypeOption extends LitElement {
7
- @property({ type: String })
8
- tourtype = "";
9
6
  @property({ type: String })
10
7
  heading = "";
11
8
  @property({ type: String })
12
9
  subtitle = "";
13
10
  @property({ type: Boolean })
14
11
  selected = false;
15
-
16
12
  @property({ attribute: false })
17
- onClick?: (tourType: TourType) => void;
13
+ onClick?: () => void;
18
14
 
19
15
  static styles = [
20
16
  css`
@@ -46,7 +46,7 @@ export default function createConversation(
46
46
  building.avatarType === "image" && building.avatarSrc
47
47
  ? avatarSrc
48
48
  : defaultAvatarUrl,
49
- // uncomment this to test changes to the default avatar if your test building has its own avatar
49
+ // uncomment the following line to test changes to the default avatar if your test building has its own avatar
50
50
  // avatarUrl: defaultAvatarUrl,
51
51
  };
52
52
  return conversation;
@@ -12,29 +12,46 @@ import {
12
12
  import groupBy from "lodash/groupBy";
13
13
 
14
14
  const availabilitiesCache: {
15
- [buildingId: number]: TourAvailabilityResponse;
16
- } = {};
15
+ buildingId?: number | null;
16
+ availabilities: { [buildingId: number]: TourAvailabilityResponse };
17
+ } = { buildingId: null, availabilities: {} };
17
18
 
19
+ /**
20
+ * Returns the raw availabilities.
21
+ *
22
+ * If no `buildingId` is provided, it will use a cached buildingId from the previous call.
23
+ * If there is none cached, it will throw an error.
24
+ */
18
25
  export const getRawAvailabilities = async (
19
- buildingId: number
26
+ buildingId?: number
20
27
  ): Promise<TourAvailabilityResponse> => {
21
- if (availabilitiesCache[buildingId]) {
22
- return availabilitiesCache[buildingId];
28
+ if (buildingId) {
29
+ availabilitiesCache.buildingId = buildingId;
30
+ }
31
+ const buildingIdToUse = availabilitiesCache.buildingId;
32
+ if (!buildingIdToUse) {
33
+ throw new Error(
34
+ "No buildingId was provided to getRawAvailabilities and there is no buildingId cached."
35
+ );
36
+ }
37
+ const availabilities = availabilitiesCache.availabilities;
38
+ if (availabilities[buildingIdToUse]) {
39
+ return availabilities[buildingIdToUse];
23
40
  }
24
41
  const startTime = startOfToday();
25
42
  const endTime = formatISO(endOfDay(addDays(startTime, 30)));
26
- const url = `https://app.meetelise.com/api/pub/v1/buildings/${buildingId}/tour/availabilities?startTime=${formatISO(
43
+ const url = `https://app.meetelise.com/api/pub/v1/buildings/${buildingIdToUse}/tour/availabilities?startTime=${formatISO(
27
44
  startTime
28
45
  )}&endTime=${endTime}`;
29
46
  const result = await axios.get<TourAvailabilityResponse>(url);
30
- availabilitiesCache[buildingId] = result.data;
47
+ availabilitiesCache.availabilities[buildingIdToUse] = result.data;
31
48
  // The endpoint INCORRECTLY states that these are returned as dates. They are, in fact, strings.
32
49
  return result.data;
33
50
  };
34
51
 
35
52
  export const getAvailabilitiesForTourType = async (
36
- buildingId: number,
37
- tourType: TourAvailabilityResponseRankOrderedSupportedTourTypesEnum
53
+ tourType: TourAvailabilityResponseRankOrderedSupportedTourTypesEnum,
54
+ buildingId?: number
38
55
  ): Promise<{
39
56
  /**
40
57
  *
@@ -69,12 +86,12 @@ export interface DateWithTimeZoneOffset {
69
86
  }
70
87
 
71
88
  export const getAvailabilitiesGroupedByDay = async (
72
- buildingId: number,
73
- tourType: TourAvailabilityResponseRankOrderedSupportedTourTypesEnum
89
+ tourType: TourAvailabilityResponseRankOrderedSupportedTourTypesEnum,
90
+ buildingId?: number
74
91
  ): Promise<{ [day: string]: DateWithTimeZoneOffset[] }> => {
75
92
  const availabilitiesForTourTypeRaw = await getAvailabilitiesForTourType(
76
- buildingId,
77
- tourType
93
+ tourType,
94
+ buildingId
78
95
  );
79
96
  if (!availabilitiesForTourTypeRaw) {
80
97
  return {};
@@ -97,16 +114,6 @@ export const getAvailabilitiesGroupedByDay = async (
97
114
  );
98
115
  };
99
116
 
100
- // TODO: if cache is empty, observe it and wait for it to be filled in.
101
- // TODO: alternative to this: cache the building id when getRawAvailabilities is called. Then I can call the normal methods.
102
- export const getAvailabilitiesGroupedByDayCached = async (
103
- tourType: TourAvailabilityResponseRankOrderedSupportedTourTypesEnum
104
- ): Promise<{ [day: string]: DateWithTimeZoneOffset[] }> =>
105
- getAvailabilitiesGroupedByDay(
106
- Object.keys(availabilitiesCache).map(Number)[0],
107
- tourType
108
- );
109
-
110
117
  /**
111
118
  * Takes an ISO 8601 date string with time zone offset and returns
112
119
  * an object of our custom type DateWithTimeZoneOffset.