@meetelise/chat 1.20.2 → 1.20.4
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/package.json +1 -1
- package/public/dist/index.js +154 -101
- package/src/WebComponent/Launcher.ts +5 -2
- package/src/WebComponent/Scheduler/me-select.ts +22 -6
- package/src/WebComponent/Scheduler/time-picker.ts +28 -8
- package/src/WebComponent/Scheduler/tour-scheduler.ts +147 -55
- package/src/WebComponent/me-chat.ts +2 -1
- package/src/fetchBuildingInfo.ts +21 -1
|
@@ -11,7 +11,7 @@ import { classMap } from "lit/directives/class-map.js";
|
|
|
11
11
|
import { installCallUsWindow } from "./actions/call-us-window";
|
|
12
12
|
import { getRegisteredPhoneNumbers } from "../getRegisteredPhoneNumbers";
|
|
13
13
|
import { TourScheduler } from "./Scheduler/tour-scheduler";
|
|
14
|
-
import { LabeledOption } from "../fetchBuildingInfo";
|
|
14
|
+
import { LabeledOption, UnitV2 } from "../fetchBuildingInfo";
|
|
15
15
|
|
|
16
16
|
@customElement("meetelise-launcher")
|
|
17
17
|
export class Launcher extends LitElement {
|
|
@@ -53,7 +53,9 @@ export class Launcher extends LitElement {
|
|
|
53
53
|
@property({ type: Boolean })
|
|
54
54
|
hasTextUsEnabled = false;
|
|
55
55
|
@property({ attribute: false })
|
|
56
|
-
layoutOptions:
|
|
56
|
+
layoutOptions: string[] = [];
|
|
57
|
+
@property({ attribute: false })
|
|
58
|
+
unitOptions: UnitV2[] = [];
|
|
57
59
|
@property({ attribute: false })
|
|
58
60
|
tourTypeOptions: LabeledOption[] = [];
|
|
59
61
|
@property({ attribute: false })
|
|
@@ -294,6 +296,7 @@ export class Launcher extends LitElement {
|
|
|
294
296
|
orgSlug="${this.orgSlug}"
|
|
295
297
|
buildingSlug="${this.buildingSlug}"
|
|
296
298
|
.layoutOptions=${this.layoutOptions}
|
|
299
|
+
.unitOptions=${this.unitOptions}
|
|
297
300
|
.tourTypeOptions=${this.tourTypeOptions}
|
|
298
301
|
buildingId=${this.buildingId}
|
|
299
302
|
${ref(this.tourSchedulerRef)}
|
|
@@ -2,10 +2,15 @@ import { LitElement, html, TemplateResult, css } from "lit";
|
|
|
2
2
|
import { property, state, query, customElement } from "lit/decorators.js";
|
|
3
3
|
import { classMap } from "lit/directives/class-map.js";
|
|
4
4
|
|
|
5
|
+
type MeSelectOption = {
|
|
6
|
+
label: string;
|
|
7
|
+
value: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
5
10
|
@customElement("me-select")
|
|
6
11
|
export class MESelect extends LitElement {
|
|
7
12
|
@property({ attribute: false })
|
|
8
|
-
options:
|
|
13
|
+
options: MeSelectOption[] = [];
|
|
9
14
|
|
|
10
15
|
@property({ type: String })
|
|
11
16
|
placeholder?: string = "Select";
|
|
@@ -14,7 +19,7 @@ export class MESelect extends LitElement {
|
|
|
14
19
|
value?: string;
|
|
15
20
|
|
|
16
21
|
@state()
|
|
17
|
-
private activeOption:
|
|
22
|
+
private activeOption: MeSelectOption | null = null;
|
|
18
23
|
|
|
19
24
|
@state()
|
|
20
25
|
private isOpen?: boolean = false;
|
|
@@ -29,8 +34,8 @@ export class MESelect extends LitElement {
|
|
|
29
34
|
this.isOpen = !this.isOpen;
|
|
30
35
|
};
|
|
31
36
|
|
|
32
|
-
setSelectedOption = (option:
|
|
33
|
-
this.value = option;
|
|
37
|
+
setSelectedOption = (option: MeSelectOption, closeSelect = true): void => {
|
|
38
|
+
this.value = option.value;
|
|
34
39
|
if (closeSelect) {
|
|
35
40
|
this.isOpen = !this.isOpen;
|
|
36
41
|
this.activeOption = null;
|
|
@@ -103,6 +108,7 @@ export class MESelect extends LitElement {
|
|
|
103
108
|
overflow-y: scroll;
|
|
104
109
|
position: absolute;
|
|
105
110
|
min-height: 40px;
|
|
111
|
+
min-width: 144px;
|
|
106
112
|
max-width: 400px;
|
|
107
113
|
width: max-content;
|
|
108
114
|
background-color: white;
|
|
@@ -112,7 +118,17 @@ export class MESelect extends LitElement {
|
|
|
112
118
|
box-sizing: border-box;
|
|
113
119
|
box-shadow: 0px 4px 14px rgba(0, 0, 0, 0.15);
|
|
114
120
|
border-radius: 10px;
|
|
115
|
-
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
::-webkit-scrollbar {
|
|
124
|
+
-webkit-appearance: none;
|
|
125
|
+
width: 8px;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
::-webkit-scrollbar-thumb {
|
|
129
|
+
border-radius: 10px;
|
|
130
|
+
background-color: rgba(0, 0, 0, 0.4);
|
|
131
|
+
-webkit-box-shadow: 0 0 1px rgba(255, 255, 255, 0.5);
|
|
116
132
|
}
|
|
117
133
|
|
|
118
134
|
.option {
|
|
@@ -228,7 +244,7 @@ export class MESelect extends LitElement {
|
|
|
228
244
|
active: this.activeOption === option,
|
|
229
245
|
})}"
|
|
230
246
|
>
|
|
231
|
-
${option}
|
|
247
|
+
${option.label}
|
|
232
248
|
</li>`
|
|
233
249
|
)}
|
|
234
250
|
</ul>`
|
|
@@ -1,11 +1,27 @@
|
|
|
1
1
|
import { LitElement, html, TemplateResult, css } from "lit";
|
|
2
2
|
import { customElement, property, state } from "lit/decorators.js";
|
|
3
3
|
import { classMap } from "lit/directives/class-map.js";
|
|
4
|
+
import { DateWithTimeZoneOffset } from "../../getAvailabilities";
|
|
5
|
+
|
|
6
|
+
export type TimePickerOption = {
|
|
7
|
+
displayTime: string;
|
|
8
|
+
dateWithTimeZoneOffset: DateWithTimeZoneOffset;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const getDateWithTimezoneOffset = (
|
|
12
|
+
options: TimePickerOption[],
|
|
13
|
+
displayTime: string
|
|
14
|
+
) => {
|
|
15
|
+
return options.reduce(function (map: Record<string, TimePickerOption>, obj) {
|
|
16
|
+
map[obj.displayTime] = obj;
|
|
17
|
+
return map;
|
|
18
|
+
}, {})[displayTime];
|
|
19
|
+
};
|
|
4
20
|
|
|
5
21
|
@customElement("time-picker")
|
|
6
22
|
export class TimePicker extends LitElement {
|
|
7
23
|
@property({ attribute: false })
|
|
8
|
-
options:
|
|
24
|
+
options: TimePickerOption[] = [];
|
|
9
25
|
|
|
10
26
|
@property({ type: Boolean })
|
|
11
27
|
selectedDateExists = false;
|
|
@@ -14,10 +30,10 @@ export class TimePicker extends LitElement {
|
|
|
14
30
|
horizontal = false;
|
|
15
31
|
|
|
16
32
|
@state()
|
|
17
|
-
private selected?:
|
|
33
|
+
private selected?: TimePickerOption;
|
|
18
34
|
|
|
19
35
|
@property({ attribute: false })
|
|
20
|
-
get selectedTime(): undefined |
|
|
36
|
+
get selectedTime(): undefined | TimePickerOption {
|
|
21
37
|
return this.selected;
|
|
22
38
|
}
|
|
23
39
|
|
|
@@ -100,8 +116,12 @@ export class TimePicker extends LitElement {
|
|
|
100
116
|
class=${this.horizontal ? "horizontal" : ""}
|
|
101
117
|
@click="${(e: MouseEvent) => {
|
|
102
118
|
const target = e.target as HTMLElement | undefined;
|
|
119
|
+
|
|
103
120
|
if (target?.closest(".option:not(.selected)"))
|
|
104
|
-
this.selected =
|
|
121
|
+
this.selected = getDateWithTimezoneOffset(
|
|
122
|
+
this.options,
|
|
123
|
+
target.innerText
|
|
124
|
+
);
|
|
105
125
|
this.dispatchEvent(
|
|
106
126
|
new Event("change", { bubbles: true, composed: true })
|
|
107
127
|
);
|
|
@@ -114,8 +134,8 @@ export class TimePicker extends LitElement {
|
|
|
114
134
|
) {
|
|
115
135
|
e.preventDefault();
|
|
116
136
|
this.selected =
|
|
117
|
-
target.innerText !== this.selected
|
|
118
|
-
? target.innerText
|
|
137
|
+
target.innerText !== this.selected?.displayTime
|
|
138
|
+
? getDateWithTimezoneOffset(this.options, target.innerText)
|
|
119
139
|
: undefined;
|
|
120
140
|
this.dispatchEvent(
|
|
121
141
|
new Event("change", { bubbles: true, composed: true })
|
|
@@ -127,11 +147,11 @@ export class TimePicker extends LitElement {
|
|
|
127
147
|
(option) =>
|
|
128
148
|
html`<div
|
|
129
149
|
class="option ${classMap({
|
|
130
|
-
selected: this.selected === option,
|
|
150
|
+
selected: this.selected?.displayTime === option.displayTime,
|
|
131
151
|
})}"
|
|
132
152
|
tabindex="0"
|
|
133
153
|
>
|
|
134
|
-
<span>${option}</span>
|
|
154
|
+
<span>${option.displayTime}</span>
|
|
135
155
|
</div>`
|
|
136
156
|
)}
|
|
137
157
|
</div>
|
|
@@ -19,17 +19,35 @@ import { format } from "date-fns";
|
|
|
19
19
|
import { DatePicker } from "./date-picker";
|
|
20
20
|
import { MESelect } from "./me-select";
|
|
21
21
|
import { TimePicker } from "./time-picker";
|
|
22
|
-
import { LabeledOption } from "../../fetchBuildingInfo";
|
|
22
|
+
import { LabeledOption, UnitV2 } from "../../fetchBuildingInfo";
|
|
23
23
|
import { isMobile } from "../../utils";
|
|
24
24
|
import axios from "axios";
|
|
25
25
|
import { mapValues } from "lodash";
|
|
26
26
|
import classnames from "classnames";
|
|
27
27
|
import parseISO from "date-fns/parseISO";
|
|
28
28
|
|
|
29
|
+
const getHumanReadableLayout = (layout: string) => {
|
|
30
|
+
if (layout == "studio") return "Studio";
|
|
31
|
+
return {
|
|
32
|
+
"1br": "1 bedroom",
|
|
33
|
+
"2br": "2 bedrooms",
|
|
34
|
+
"3br": "3 bedrooms",
|
|
35
|
+
"4br": "4 bedrooms",
|
|
36
|
+
"5br": "5 bedrooms",
|
|
37
|
+
"6br": "6 bedrooms",
|
|
38
|
+
"7br": "7 bedrooms",
|
|
39
|
+
"8br": "8 bedrooms",
|
|
40
|
+
"9br": "9 bedrooms",
|
|
41
|
+
"10br": "10 bedroom",
|
|
42
|
+
}[layout];
|
|
43
|
+
};
|
|
44
|
+
|
|
29
45
|
@customElement("tour-scheduler")
|
|
30
46
|
export class TourScheduler extends LitElement {
|
|
31
47
|
@property({ attribute: false })
|
|
32
|
-
layoutOptions:
|
|
48
|
+
layoutOptions: string[] = [];
|
|
49
|
+
@property({ attribute: false })
|
|
50
|
+
unitOptions: UnitV2[] = [];
|
|
33
51
|
@property({ attribute: false })
|
|
34
52
|
tourTypeOptions: LabeledOption[] = [];
|
|
35
53
|
@property({ type: Number })
|
|
@@ -69,9 +87,9 @@ export class TourScheduler extends LitElement {
|
|
|
69
87
|
@state()
|
|
70
88
|
private tourIsBooked = false;
|
|
71
89
|
|
|
72
|
-
@query(".
|
|
90
|
+
@query(".nameContainer#firstName input")
|
|
73
91
|
firstNameInput!: HTMLInputElement;
|
|
74
|
-
@query(".
|
|
92
|
+
@query(".nameContainer#lastName input")
|
|
75
93
|
lastNameInput!: HTMLInputElement;
|
|
76
94
|
@query(".inputContainer#email input")
|
|
77
95
|
emailInput!: HTMLInputElement;
|
|
@@ -79,6 +97,8 @@ export class TourScheduler extends LitElement {
|
|
|
79
97
|
phoneInput!: HTMLInputElement;
|
|
80
98
|
@query("me-select#unitType")
|
|
81
99
|
unitTypeSelect!: MESelect;
|
|
100
|
+
@query("me-select#layoutType")
|
|
101
|
+
layoutTypeSelect!: MESelect;
|
|
82
102
|
|
|
83
103
|
firstUpdated = async (): Promise<void> => {
|
|
84
104
|
this.availabilitiesGroupedByDay = await getAvailabilitiesGroupedByDay(
|
|
@@ -312,21 +332,25 @@ export class TourScheduler extends LitElement {
|
|
|
312
332
|
last_name: this.lastNameInput.value,
|
|
313
333
|
tour_type: tourTypeForSubmission[this.tourType],
|
|
314
334
|
tour_time: `${this.selectedTime.datetime}${this.selectedTime.offset}`, // e.g., "2022-06-27T09:00:00-07:00"
|
|
335
|
+
layouts: [this.layoutTypeSelect.value],
|
|
336
|
+
unit_numbers: [this.unitTypeSelect.value],
|
|
315
337
|
};
|
|
316
338
|
const url = `https://app.meetelise.com/platformApi/state/create/scheduleMe`;
|
|
317
339
|
this.isSubmitting = true;
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
340
|
+
|
|
341
|
+
try {
|
|
342
|
+
await axios.post(url, data, {
|
|
343
|
+
headers: {
|
|
344
|
+
["building-slug"]: this.buildingSlug,
|
|
345
|
+
["X-SecurityKey"]: "JRL8jV4VcSCwOSir5gWkpgNLfKghmhBG",
|
|
346
|
+
["org-slug"]: this.orgSlug,
|
|
347
|
+
},
|
|
348
|
+
});
|
|
326
349
|
this.isSubmitting = false;
|
|
327
350
|
this.tourIsBooked = true;
|
|
328
|
-
|
|
329
|
-
|
|
351
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
352
|
+
} catch (e: any) {
|
|
353
|
+
const message = e.response.data["detail"] || "Failed to book tour";
|
|
330
354
|
alert(message);
|
|
331
355
|
this.isSubmitting = false;
|
|
332
356
|
this.tourIsBooked = false;
|
|
@@ -355,7 +379,7 @@ export class TourScheduler extends LitElement {
|
|
|
355
379
|
/* grid stuff */
|
|
356
380
|
display: grid;
|
|
357
381
|
grid-template-columns: 229px 432px 305px;
|
|
358
|
-
grid-template-rows: 44px 54px 32px 195px
|
|
382
|
+
grid-template-rows: 44px 54px 32px 195px 167px 1px;
|
|
359
383
|
}
|
|
360
384
|
|
|
361
385
|
h1,
|
|
@@ -449,7 +473,7 @@ export class TourScheduler extends LitElement {
|
|
|
449
473
|
}
|
|
450
474
|
|
|
451
475
|
#yourInformationMenu input {
|
|
452
|
-
width:
|
|
476
|
+
width: 100%;
|
|
453
477
|
height: 49px;
|
|
454
478
|
border: 1px solid #83818e;
|
|
455
479
|
padding: 13px 11px 14px 11px;
|
|
@@ -464,7 +488,7 @@ export class TourScheduler extends LitElement {
|
|
|
464
488
|
color: #202020;
|
|
465
489
|
}
|
|
466
490
|
|
|
467
|
-
|
|
491
|
+
.unitLayoutChoices {
|
|
468
492
|
grid-row: 5 / 6;
|
|
469
493
|
grid-column: 3;
|
|
470
494
|
align-self: start;
|
|
@@ -472,11 +496,15 @@ export class TourScheduler extends LitElement {
|
|
|
472
496
|
flex-direction: column;
|
|
473
497
|
}
|
|
474
498
|
|
|
475
|
-
|
|
499
|
+
.unitLayoutChoice {
|
|
500
|
+
margin-bottom: 12px;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
h2.unitLayoutChoice {
|
|
476
504
|
margin-bottom: 7px;
|
|
477
505
|
}
|
|
478
506
|
|
|
479
|
-
|
|
507
|
+
.unitLayoutOptions {
|
|
480
508
|
display: flex;
|
|
481
509
|
flex-direction: column;
|
|
482
510
|
gap: 8px;
|
|
@@ -584,10 +612,6 @@ export class TourScheduler extends LitElement {
|
|
|
584
612
|
width: 205px;
|
|
585
613
|
}
|
|
586
614
|
|
|
587
|
-
.tour-scheduler.loading #yourInformationMenu .inputContainer::after {
|
|
588
|
-
width: 100%;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
615
|
.tour-scheduler.loading #yourInformationMenu .inputContainer input {
|
|
592
616
|
visibility: hidden;
|
|
593
617
|
}
|
|
@@ -596,6 +620,19 @@ export class TourScheduler extends LitElement {
|
|
|
596
620
|
display: none;
|
|
597
621
|
}
|
|
598
622
|
|
|
623
|
+
#namesWrapper {
|
|
624
|
+
display: flex;
|
|
625
|
+
justify-content: space-between;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
.nameContainer {
|
|
629
|
+
width: 48%;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
.nameInput {
|
|
633
|
+
width: 100%;
|
|
634
|
+
}
|
|
635
|
+
|
|
599
636
|
@media (max-width: 767px) {
|
|
600
637
|
/* TODO: separate styles into general, desktop-specific, and mobile-specific.
|
|
601
638
|
basically everything I have "unset" or "initial" on should become desktop-specific. the grid layout is only for desktop.
|
|
@@ -832,9 +869,15 @@ export class TourScheduler extends LitElement {
|
|
|
832
869
|
.options=${this.selectedDate
|
|
833
870
|
? this.availabilitiesGroupedByDay[
|
|
834
871
|
format(this.selectedDate, "y-MM-dd")
|
|
835
|
-
]?.map((date) =>
|
|
836
|
-
|
|
837
|
-
|
|
872
|
+
]?.map((date) => {
|
|
873
|
+
return {
|
|
874
|
+
dateWithTimeZoneOffset: date,
|
|
875
|
+
displayTime: format(
|
|
876
|
+
parseISO(`${date.datetime}${date.offset}`),
|
|
877
|
+
"h:mmaaa"
|
|
878
|
+
),
|
|
879
|
+
};
|
|
880
|
+
})
|
|
838
881
|
: []}
|
|
839
882
|
@change=${(e: Event) => {
|
|
840
883
|
if (e.target instanceof TimePicker) {
|
|
@@ -844,9 +887,9 @@ export class TourScheduler extends LitElement {
|
|
|
844
887
|
format(new Date(this.selectedDate), "y-MM-dd")
|
|
845
888
|
];
|
|
846
889
|
const index = e.target.selectedTime
|
|
847
|
-
? daysAvailabilities
|
|
848
|
-
.
|
|
849
|
-
|
|
890
|
+
? daysAvailabilities.indexOf(
|
|
891
|
+
e.target.selectedTime.dateWithTimeZoneOffset
|
|
892
|
+
)
|
|
850
893
|
: null;
|
|
851
894
|
this.selectedTime =
|
|
852
895
|
index !== null ? daysAvailabilities[index] : null;
|
|
@@ -927,24 +970,29 @@ export class TourScheduler extends LitElement {
|
|
|
927
970
|
userInfoAndLayoutMenu(): TemplateResult {
|
|
928
971
|
return html`<h2 id="yourInformation">Your information</h2>
|
|
929
972
|
<div id="yourInformationMenu">
|
|
930
|
-
<div
|
|
931
|
-
<
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
973
|
+
<div id="namesWrapper">
|
|
974
|
+
<div class="nameContainer" id="firstName">
|
|
975
|
+
<input
|
|
976
|
+
class="nameInput"
|
|
977
|
+
type="text"
|
|
978
|
+
placeholder="First name"
|
|
979
|
+
name="firstName"
|
|
980
|
+
autocomplete="given-name"
|
|
981
|
+
@input=${() => this.requestUpdate()}
|
|
982
|
+
/>
|
|
983
|
+
</div>
|
|
984
|
+
<div class="nameContainer" id="lastName">
|
|
985
|
+
<input
|
|
986
|
+
class="nameInput"
|
|
987
|
+
type="text"
|
|
988
|
+
placeholder="Last name"
|
|
989
|
+
name="lastName"
|
|
990
|
+
autocomplete="family-name"
|
|
991
|
+
@input=${() => this.requestUpdate()}
|
|
992
|
+
/>
|
|
993
|
+
</div>
|
|
947
994
|
</div>
|
|
995
|
+
|
|
948
996
|
<div class="inputContainer" id="email">
|
|
949
997
|
<input
|
|
950
998
|
type="email"
|
|
@@ -978,20 +1026,64 @@ export class TourScheduler extends LitElement {
|
|
|
978
1026
|
/>
|
|
979
1027
|
</div>
|
|
980
1028
|
</div>
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
1029
|
+
<div class="unitLayoutChoices">
|
|
1030
|
+
${this.layoutOptions.length > 0
|
|
1031
|
+
? html`<div class="unitLayoutChoice">
|
|
1032
|
+
<h2 class="unitLayoutChoice">What would you like to view?</h2>
|
|
1033
|
+
<div class="unitLayoutOptions">
|
|
1034
|
+
<me-select
|
|
1035
|
+
id="layoutType"
|
|
1036
|
+
placeholder="Select type"
|
|
1037
|
+
.options="${this.layoutOptions.map((i) => ({
|
|
1038
|
+
label: getHumanReadableLayout(i),
|
|
1039
|
+
value: i,
|
|
1040
|
+
}))}"
|
|
1041
|
+
defaultOption="Studio"
|
|
1042
|
+
@change=${() => {
|
|
1043
|
+
// to revalidate the form
|
|
1044
|
+
this.requestUpdate();
|
|
1045
|
+
}}
|
|
1046
|
+
>Studio
|
|
1047
|
+
</me-select>
|
|
1048
|
+
</div>
|
|
1049
|
+
</div>`
|
|
1050
|
+
: ""}
|
|
1051
|
+
${this.unitOptions.length > 0
|
|
1052
|
+
? html`<div class="unitLayoutChoice">
|
|
1053
|
+
<div class="unitLayoutOptions">
|
|
1054
|
+
<me-select
|
|
1055
|
+
id="unitType"
|
|
1056
|
+
placeholder="Select type"
|
|
1057
|
+
.options="${this.unitOptions
|
|
1058
|
+
.filter(
|
|
1059
|
+
(i) =>
|
|
1060
|
+
!this.layoutTypeSelect ||
|
|
1061
|
+
i.layout === this.layoutTypeSelect.value
|
|
1062
|
+
)
|
|
1063
|
+
.map((i) => ({
|
|
1064
|
+
label: i.name,
|
|
1065
|
+
value: i.name,
|
|
1066
|
+
}))}"
|
|
1067
|
+
defaultOption="Studio"
|
|
1068
|
+
@change=${() => {
|
|
1069
|
+
// to revalidate the form
|
|
1070
|
+
this.requestUpdate();
|
|
1071
|
+
}}
|
|
1072
|
+
>Studio
|
|
1073
|
+
</me-select>
|
|
1074
|
+
</div>
|
|
1075
|
+
</div>`
|
|
1076
|
+
: ""}
|
|
1077
|
+
</div> `;
|
|
986
1078
|
}
|
|
987
1079
|
|
|
988
1080
|
confirmationMessage(): TemplateResult {
|
|
989
1081
|
if (!this.selectedDate || !this.selectedTime) return html``;
|
|
990
1082
|
// format example: "November 9th, 2022 at 11:00am"
|
|
991
|
-
const readableDateAndTime =
|
|
992
|
-
|
|
993
|
-
"
|
|
994
|
-
)
|
|
1083
|
+
const readableDateAndTime = format(
|
|
1084
|
+
parseISO(`${this.selectedTime.datetime}${this.selectedTime.offset}`),
|
|
1085
|
+
"h:mmaaa"
|
|
1086
|
+
);
|
|
995
1087
|
return html`
|
|
996
1088
|
<div id="confirmationMessage">
|
|
997
1089
|
<svg
|
|
@@ -285,7 +285,8 @@ export class MEChat extends LitElement {
|
|
|
285
285
|
.isFirstMount=${!this.hasMounted}
|
|
286
286
|
.isMini=${this.useMiniWidget}
|
|
287
287
|
.buildingId=${this.building?.id ?? 0}
|
|
288
|
-
.layoutOptions=${this.building?.
|
|
288
|
+
.layoutOptions=${this.building?.layoutOptionsV2 ?? []}
|
|
289
|
+
.unitOptions=${this.building?.unitOptionsV2 ?? []}
|
|
289
290
|
.tourTypeOptions=${this.building?.tourTypeOptions ?? []}
|
|
290
291
|
.launcherStyles=${this.launcherStyles}
|
|
291
292
|
chatCallUsHeader=${this.building?.chatCallUsHeader ?? "Call us"}
|
package/src/fetchBuildingInfo.ts
CHANGED
|
@@ -21,12 +21,18 @@ export interface Building {
|
|
|
21
21
|
conversationMaintenanceMode: boolean;
|
|
22
22
|
orgId: number;
|
|
23
23
|
phoneNumber: string;
|
|
24
|
-
layoutOptions: LabeledOption[];
|
|
25
24
|
tourTypeOptions: LabeledOption[];
|
|
26
25
|
chatWidgets?: string[] | null;
|
|
27
26
|
chatCallUsHeader?: string;
|
|
27
|
+
unitOptionsV2: UnitV2[];
|
|
28
|
+
layoutOptionsV2: string[];
|
|
28
29
|
}
|
|
29
30
|
|
|
31
|
+
export type UnitV2 = {
|
|
32
|
+
name: string;
|
|
33
|
+
layout: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
30
36
|
/**
|
|
31
37
|
* Load the publicly-available info for a building.
|
|
32
38
|
*
|
|
@@ -42,5 +48,19 @@ export default async function fetchBuildingInfo(
|
|
|
42
48
|
const url = `${host}/api/pub/v1/organization/${orgSlug}/building/${buildingSlug}`;
|
|
43
49
|
const response = await fetch(url);
|
|
44
50
|
const building: Building = await response.json();
|
|
51
|
+
|
|
52
|
+
// HACK
|
|
53
|
+
// We will fetch these units/layouts from elise-crm-api and supplement the DTO
|
|
54
|
+
const unitsResponse = await fetch(
|
|
55
|
+
`${host}/eliseCrmApi/pub/building/${buildingSlug}/units`
|
|
56
|
+
);
|
|
57
|
+
const units: UnitV2[] = await unitsResponse.json();
|
|
58
|
+
const layoutsResponse = await fetch(
|
|
59
|
+
`${host}/eliseCrmApi/pub/building/${buildingSlug}/layouts`
|
|
60
|
+
);
|
|
61
|
+
const layouts: string[] = await layoutsResponse.json();
|
|
62
|
+
|
|
63
|
+
building.unitOptionsV2 = units;
|
|
64
|
+
building.layoutOptionsV2 = layouts;
|
|
45
65
|
return building;
|
|
46
66
|
}
|