@meetelise/chat 1.40.1 → 1.40.3

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.
@@ -32,12 +32,15 @@ export class DatePicker extends LitElement {
32
32
  @property({ attribute: "year", type: Number })
33
33
  defaultYear?: number;
34
34
 
35
+ @property({ attribute: true })
36
+ defaultDate?: Date;
37
+
35
38
  @property({ attribute: false })
36
39
  availabilities?: {
37
40
  [day: string]: Date[];
38
41
  };
39
42
 
40
- private _selectedDate?: Date = undefined;
43
+ private _selectedDate?: Date = this.defaultDate;
41
44
  set selectedDate(date: Date | undefined) {
42
45
  const old = this._selectedDate;
43
46
  this._selectedDate = date;
@@ -55,6 +58,13 @@ export class DatePicker extends LitElement {
55
58
  return this._selectedDate;
56
59
  }
57
60
 
61
+ protected firstUpdated(): void {
62
+ if (!this.defaultDate) {
63
+ return;
64
+ }
65
+ this.selectedDate = this.defaultDate;
66
+ }
67
+
58
68
  now = new Date();
59
69
 
60
70
  private _monthShown =
@@ -31,14 +31,26 @@ export class TimePicker extends LitElement {
31
31
  @property({ attribute: true })
32
32
  timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
33
33
 
34
+ @property({ attribute: true })
35
+ defaultSelectedTime?: TimePickerOption | null = null;
36
+
34
37
  @state()
35
- private selected?: TimePickerOption;
38
+ private selected?: TimePickerOption | null = this.defaultSelectedTime;
36
39
 
37
40
  @property({ attribute: false })
38
- get selectedTime(): undefined | TimePickerOption {
41
+ get selectedTime(): undefined | TimePickerOption | null {
39
42
  return this.selected;
40
43
  }
41
44
 
45
+ willUpdate(changedProperties: Map<string, unknown>): void {
46
+ if (
47
+ changedProperties.has("defaultSelectedTime") &&
48
+ this.selected === null
49
+ ) {
50
+ this.selected = this.defaultSelectedTime;
51
+ }
52
+ }
53
+
42
54
  static styles = css`
43
55
  * {
44
56
  box-sizing: border-box;
@@ -10,13 +10,19 @@ import "./date-picker.ts";
10
10
  import "./time-picker.ts";
11
11
  import "../me-select.ts";
12
12
  import {
13
+ dateStringToDateWithTimeZoneOffset,
14
+ dateToDateWithTimeZoneOffset,
13
15
  DateWithTimeZoneOffset,
14
16
  getAvailabilitiesGroupedByDay,
15
17
  getExistenceOfAvailabilitiesByTourType,
18
+ getRawAvailabilities,
16
19
  getTimezoneForBuilding,
17
20
  resetAvailabilitiesCache,
18
21
  } from "../../getAvailabilities";
19
- import { TourAvailabilityResponseRankOrderedSupportedTourTypesEnum } from "../../types/rest-sdk.types";
22
+ import {
23
+ TourAvailabilityResponse,
24
+ TourAvailabilityResponseRankOrderedSupportedTourTypesEnum,
25
+ } from "../../types/rest-sdk.types";
20
26
  import { format } from "date-fns";
21
27
  import { DatePicker } from "./date-picker";
22
28
  import { MESelect } from "../me-select";
@@ -46,6 +52,7 @@ import { TourWithAgentIcon } from "../icons/TourWithAgentIcon";
46
52
  import { shouldOpenTourLink } from "../../fetchBuildingWebchatView";
47
53
  import formatInTimeZone from "date-fns-tz/formatInTimeZone";
48
54
  import { getTimezoneAbbreviation } from "../../getTimezoneString";
55
+ import startOfDay from "date-fns/startOfDay";
49
56
 
50
57
  @customElement("tour-scheduler")
51
58
  export class TourScheduler extends LitElement {
@@ -66,6 +73,8 @@ export class TourScheduler extends LitElement {
66
73
  @property({ attribute: true })
67
74
  escortedToursLink = "";
68
75
  @property({ attribute: true })
76
+ escortedToursTypeOffered = "";
77
+ @property({ attribute: true })
69
78
  virtualToursLink = "";
70
79
  @property({ attribute: true })
71
80
  virtualToursTypeOffered = "";
@@ -234,6 +243,40 @@ export class TourScheduler extends LitElement {
234
243
  }
235
244
  }, 0) === 1;
236
245
 
246
+ const availabilities = await getRawAvailabilities(this.buildingId);
247
+ const highestRankedTourType =
248
+ this._getHighestRankedTourType(availabilities);
249
+ const availableTimesForHighestRankedTourType = highestRankedTourType
250
+ ? availabilities.availability?.[highestRankedTourType]
251
+ ?.availableTourStartTimes
252
+ : [];
253
+ const firstAvailableTimeSlotForHighestRankedTourType =
254
+ availableTimesForHighestRankedTourType?.[0];
255
+ if (
256
+ highestRankedTourType &&
257
+ firstAvailableTimeSlotForHighestRankedTourType &&
258
+ highestRankedTourType !==
259
+ TourAvailabilityResponseRankOrderedSupportedTourTypesEnum.Unknown &&
260
+ highestRankedTourType !==
261
+ TourAvailabilityResponseRankOrderedSupportedTourTypesEnum.MediaTour
262
+ ) {
263
+ this.selectedDate =
264
+ typeof firstAvailableTimeSlotForHighestRankedTourType === "string"
265
+ ? startOfDay(
266
+ parseISO(firstAvailableTimeSlotForHighestRankedTourType)
267
+ )
268
+ : startOfDay(firstAvailableTimeSlotForHighestRankedTourType);
269
+ this.tourType = rankedOrderTourTypeToTourType[highestRankedTourType];
270
+ this.selectedTime =
271
+ typeof firstAvailableTimeSlotForHighestRankedTourType === "string"
272
+ ? dateStringToDateWithTimeZoneOffset(
273
+ firstAvailableTimeSlotForHighestRankedTourType
274
+ )
275
+ : dateToDateWithTimeZoneOffset(
276
+ firstAvailableTimeSlotForHighestRankedTourType
277
+ );
278
+ }
279
+
237
280
  if (hasOneShowTourType) {
238
281
  this.tourType = Object.keys(this.shouldShowTourType).find(
239
282
  (key) => this.shouldShowTourType[key as TourType]
@@ -271,6 +314,56 @@ export class TourScheduler extends LitElement {
271
314
  }
272
315
  };
273
316
 
317
+ _getHighestRankedTourType = (
318
+ availabilities: TourAvailabilityResponse
319
+ ): TourAvailabilityResponseRankOrderedSupportedTourTypesEnum => {
320
+ const rankedTourTypeToAvailabilities = (
321
+ availabilities.rankOrderedSupportedTourTypes ?? []
322
+ )
323
+ .map((tt) => {
324
+ return {
325
+ tourType: tt,
326
+ availabilities:
327
+ availabilities.availability?.[tt]?.availableTourStartTimes,
328
+ };
329
+ })
330
+ .filter((rtt) => {
331
+ if (
332
+ rtt.tourType ===
333
+ TourAvailabilityResponseRankOrderedSupportedTourTypesEnum.Unknown ||
334
+ rtt.tourType ===
335
+ TourAvailabilityResponseRankOrderedSupportedTourTypesEnum.MediaTour
336
+ ) {
337
+ return false;
338
+ }
339
+ const convertedTourType = rankedOrderTourTypeToTourType[rtt.tourType];
340
+ const tourTypeOffered = this._getTourTypeOffered(convertedTourType);
341
+
342
+ if (!tourTypeOffered) {
343
+ return false;
344
+ }
345
+ return (
346
+ !shouldOpenTourLink(convertedTourType, tourTypeOffered) &&
347
+ rtt.availabilities &&
348
+ rtt.availabilities.length > 0
349
+ );
350
+ });
351
+
352
+ const highestRankedTourType = rankedTourTypeToAvailabilities[0];
353
+ return highestRankedTourType.tourType;
354
+ };
355
+
356
+ _getTourTypeOffered = (tourType: TourType): string | null => {
357
+ if (tourType === TourType.Guided) {
358
+ return this.escortedToursTypeOffered;
359
+ } else if (tourType === TourType.Self) {
360
+ return this.selfGuidedToursTypeOffered;
361
+ } else if (tourType === TourType.Virtual) {
362
+ return this.virtualToursTypeOffered;
363
+ }
364
+ return null;
365
+ };
366
+
274
367
  firstUpdated = async (): Promise<void> => {
275
368
  await this._setAvailabilities();
276
369
  };
@@ -756,6 +849,7 @@ export class TourScheduler extends LitElement {
756
849
  this.availabilitiesGroupedByDay,
757
850
  (dates) => dates.map((date) => new Date(date.offset))
758
851
  )}
852
+ .defaultDate=${this.selectedDate}
759
853
  @change=${(e: Event) => {
760
854
  // if the user clicked a tour type that is suppose to redirect, we redirect that use when they select a date
761
855
  // This can happen if the user clicks, is redirect, and then comes back to the webchat
@@ -792,6 +886,24 @@ export class TourScheduler extends LitElement {
792
886
  <time-picker
793
887
  ?selecteddateexists=${!!this.selectedDate}
794
888
  .timezone=${this.calendarTimeZone}
889
+ .defaultSelectedTime=${this.selectedTime
890
+ ? {
891
+ dateWithTimeZoneOffset: this.selectedTime,
892
+ displayTime: format(
893
+ parseISO(
894
+ `${this.selectedTime.datetime}${this.selectedTime.offset}`
895
+ ),
896
+ "h:mmaaa"
897
+ ),
898
+ displayTimeZoned: formatInTimeZone(
899
+ parseISO(
900
+ `${this.selectedTime.datetime}${this.selectedTime.offset}`
901
+ ),
902
+ this.calendarTimeZone,
903
+ "h:mmaaa"
904
+ ),
905
+ }
906
+ : null}
795
907
  .options=${this.selectedDate
796
908
  ? this.availabilitiesGroupedByDay[
797
909
  format(this.selectedDate, "y-MM-dd")
@@ -1423,6 +1535,15 @@ const tourTypeMap = {
1423
1535
  TourAvailabilityResponseRankOrderedSupportedTourTypesEnum.VirtualShowing,
1424
1536
  };
1425
1537
 
1538
+ const rankedOrderTourTypeToTourType = {
1539
+ [TourAvailabilityResponseRankOrderedSupportedTourTypesEnum.WithAgent]:
1540
+ TourType.Guided,
1541
+ [TourAvailabilityResponseRankOrderedSupportedTourTypesEnum.SelfGuided]:
1542
+ TourType.Self,
1543
+ [TourAvailabilityResponseRankOrderedSupportedTourTypesEnum.VirtualShowing]:
1544
+ TourType.Virtual,
1545
+ };
1546
+
1426
1547
  const tourTypeForSubmission = {
1427
1548
  [TourType.Guided]: "escorted-tour",
1428
1549
  [TourType.Self]: "self-guided-tour",
@@ -99,6 +99,8 @@ export class Launcher extends LitElement {
99
99
  @property({ attribute: true })
100
100
  escortedToursLink = "";
101
101
  @property({ attribute: true })
102
+ escortedToursTypeOffered = "";
103
+ @property({ attribute: true })
102
104
  virtualToursLink = "";
103
105
  @property({ attribute: true })
104
106
  virtualToursTypeOffered = "";
@@ -1201,6 +1203,7 @@ export class Launcher extends LitElement {
1201
1203
  selfGuidedTourEnabled="${this.selfGuidedTourEnabled}"
1202
1204
  selfGuidedToursTypeOffered="${this.selfGuidedToursTypeOffered}"
1203
1205
  escortedToursLink="${this.escortedToursLink}"
1206
+ .escortedToursTypeOffered="${this.escortedToursTypeOffered}"
1204
1207
  virtualToursLink="${this.virtualToursLink}"
1205
1208
  virtualToursTypeOffered="${this.virtualToursTypeOffered}"
1206
1209
  currentLeadSource="${this.currentLeadSource}"
@@ -924,6 +924,8 @@ export class MEChat extends LitElement {
924
924
  .leadSources="${this.leadSources ?? []}"
925
925
  escortedToursLink="${this.buildingWebchatView
926
926
  ?.escortedToursLink ?? ""}"
927
+ .escortedToursTypeOffered="${this.buildingWebchatView
928
+ .escortedToursTypeOffered}"
927
929
  virtualToursLink="${this.buildingWebchatView
928
930
  ?.virtualToursLink ?? ""}"
929
931
  virtualToursTypeOffered="${this.buildingWebchatView
@@ -45,7 +45,7 @@ export const shouldOpenTourLink = (
45
45
  return !shouldntOpenTourTypesOffered.includes(tourTypeOffered);
46
46
  }
47
47
 
48
- return true;
48
+ return false;
49
49
  };
50
50
 
51
51
  export interface LayoutOption {
@@ -181,9 +181,18 @@ export const getAvailabilitiesGroupedByDay = async (
181
181
  * // returns { datetime: '2022-06-27T09:00:00', offset: '-07:00' }
182
182
  * dateStringToDateWithTimeZoneOffset('2022-06-27T09:00:00-07:00')
183
183
  * */
184
- const dateStringToDateWithTimeZoneOffset = (
184
+ export const dateStringToDateWithTimeZoneOffset = (
185
185
  dateString: string
186
186
  ): DateWithTimeZoneOffset => ({
187
187
  datetime: dateString.slice(0, 19),
188
188
  offset: dateString.slice(19),
189
189
  });
190
+
191
+ export const dateToDateWithTimeZoneOffset = (
192
+ date: Date
193
+ ): DateWithTimeZoneOffset => {
194
+ const datetime = format(date, "yyyy-MM-dd'T'HH:mm:ss");
195
+ const offset = format(date, "xxx");
196
+
197
+ return { datetime, offset };
198
+ };