@meetelise/chat 1.20.151 → 1.20.153

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.
@@ -2,6 +2,7 @@ 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
4
  import { DateWithTimeZoneOffset } from "../../getAvailabilities";
5
+ import { getTimezoneAbbreviation } from "../../getTimezoneString";
5
6
 
6
7
  export type TimePickerOption = {
7
8
  displayTime: string;
@@ -44,6 +45,11 @@ export class TimePicker extends LitElement {
44
45
  font-family: "Helvetica Neue", Arial;
45
46
  }
46
47
 
48
+ .timezone-display-text {
49
+ font-size: 11px;
50
+ opacity: 0.5;
51
+ }
52
+
47
53
  #optionContainer {
48
54
  display: flex;
49
55
  flex-wrap: wrap;
@@ -113,48 +119,57 @@ export class TimePicker extends LitElement {
113
119
  }
114
120
  return this.options?.length
115
121
  ? html`
116
- <div
117
- id="optionContainer"
118
- @click="${(e: MouseEvent) => {
119
- const target = e.target as HTMLElement | undefined;
120
-
121
- if (target?.closest(".option:not(.selected)"))
122
- this.selected = getDateWithTimezoneOffset(
123
- this.options,
124
- target.innerText
125
- );
126
- this.dispatchEvent(
127
- new Event("change", { bubbles: true, composed: true })
128
- );
129
- }}"
130
- @keydown="${(e: KeyboardEvent) => {
131
- const target = e.target as HTMLElement | undefined;
132
- if (
133
- [" ", "Enter"].includes(e.key) &&
134
- target?.closest(".option")
135
- ) {
136
- e.preventDefault();
137
- this.selected =
138
- target.innerText !== this.selected?.displayTime
139
- ? getDateWithTimezoneOffset(this.options, target.innerText)
140
- : undefined;
122
+ <div>
123
+ <div
124
+ id="optionContainer"
125
+ @click="${(e: MouseEvent) => {
126
+ const target = e.target as HTMLElement | undefined;
127
+
128
+ if (target?.closest(".option:not(.selected)"))
129
+ this.selected = getDateWithTimezoneOffset(
130
+ this.options,
131
+ target.innerText
132
+ );
141
133
  this.dispatchEvent(
142
134
  new Event("change", { bubbles: true, composed: true })
143
135
  );
144
- }
145
- }}"
146
- >
147
- ${this.options.map(
148
- (option) =>
149
- html`<div
150
- class="option ${classMap({
151
- selected: this.selected?.displayTime === option.displayTime,
152
- })}"
153
- tabindex="0"
154
- >
155
- <span>${option.displayTime}</span>
156
- </div>`
157
- )}
136
+ }}"
137
+ @keydown="${(e: KeyboardEvent) => {
138
+ const target = e.target as HTMLElement | undefined;
139
+ if (
140
+ [" ", "Enter"].includes(e.key) &&
141
+ target?.closest(".option")
142
+ ) {
143
+ e.preventDefault();
144
+ this.selected =
145
+ target.innerText !== this.selected?.displayTime
146
+ ? getDateWithTimezoneOffset(
147
+ this.options,
148
+ target.innerText
149
+ )
150
+ : undefined;
151
+ this.dispatchEvent(
152
+ new Event("change", { bubbles: true, composed: true })
153
+ );
154
+ }
155
+ }}"
156
+ >
157
+ ${this.options.map(
158
+ (option) =>
159
+ html`<div
160
+ class="option ${classMap({
161
+ selected:
162
+ this.selected?.displayTime === option.displayTime,
163
+ })}"
164
+ tabindex="0"
165
+ >
166
+ <span>${option.displayTime}</span>
167
+ </div>`
168
+ )}
169
+ </div>
170
+ <p class="timezone-display-text">
171
+ *All times displayed in ${getTimezoneAbbreviation()}
172
+ </p>
158
173
  </div>
159
174
  `
160
175
  : html` <div id="noAvailabilityText">
@@ -644,42 +644,44 @@ export class TourScheduler extends LitElement {
644
644
  }
645
645
  }}
646
646
  ></date-picker>
647
- <time-picker
648
- ?selecteddateexists=${!!this.selectedDate}
649
- .options=${this.selectedDate
650
- ? this.availabilitiesGroupedByDay[
651
- format(this.selectedDate, "y-MM-dd")
652
- ]
653
- ?.sort((a, b) =>
654
- compareAsc(parseISO(a.datetime), parseISO(b.datetime))
655
- )
656
- .map((date) => {
657
- return {
658
- dateWithTimeZoneOffset: date,
659
- displayTime: format(
660
- parseISO(`${date.datetime}${date.offset}`),
661
- "h:mmaaa"
662
- ),
663
- };
664
- })
665
- : []}
666
- @change=${(e: Event) => {
667
- if (e.target instanceof TimePicker) {
668
- if (!this.selectedDate) return;
669
- const daysAvailabilities =
670
- this.availabilitiesGroupedByDay[
671
- format(new Date(this.selectedDate), "y-MM-dd")
672
- ];
673
- const index = e.target.selectedTime
674
- ? daysAvailabilities.indexOf(
675
- e.target.selectedTime.dateWithTimeZoneOffset
647
+ <div>
648
+ <time-picker
649
+ ?selecteddateexists=${!!this.selectedDate}
650
+ .options=${this.selectedDate
651
+ ? this.availabilitiesGroupedByDay[
652
+ format(this.selectedDate, "y-MM-dd")
653
+ ]
654
+ ?.sort((a, b) =>
655
+ compareAsc(parseISO(a.datetime), parseISO(b.datetime))
676
656
  )
677
- : null;
678
- this.selectedTime =
679
- index !== null ? daysAvailabilities[index] : null;
680
- }
681
- }}
682
- ></time-picker>
657
+ .map((date) => {
658
+ return {
659
+ dateWithTimeZoneOffset: date,
660
+ displayTime: format(
661
+ parseISO(`${date.datetime}${date.offset}`),
662
+ "h:mmaaa"
663
+ ),
664
+ };
665
+ })
666
+ : []}
667
+ @change=${(e: Event) => {
668
+ if (e.target instanceof TimePicker) {
669
+ if (!this.selectedDate) return;
670
+ const daysAvailabilities =
671
+ this.availabilitiesGroupedByDay[
672
+ format(new Date(this.selectedDate), "y-MM-dd")
673
+ ];
674
+ const index = e.target.selectedTime
675
+ ? daysAvailabilities.indexOf(
676
+ e.target.selectedTime.dateWithTimeZoneOffset
677
+ )
678
+ : null;
679
+ this.selectedTime =
680
+ index !== null ? daysAvailabilities[index] : null;
681
+ }
682
+ }}
683
+ ></time-picker>
684
+ </div>
683
685
  </div>
684
686
  </div>`;
685
687
  }
@@ -171,19 +171,7 @@ export class PubnubChat extends LitElement {
171
171
  ["hidden"]: this.needsConsent(),
172
172
  })}
173
173
  >
174
- <li class="message-container disclaimer-message">
175
- <p class="disclaimer-inner">
176
- By interacting with this system, you consent to
177
- <a
178
- href="http://bit.ly/me_privacy_policy"
179
- target="_blank"
180
- rel="noopener noreferrer"
181
- >
182
- this privacy policy</a
183
- >, including being contacted by AI or a human & having your
184
- conversation recorded by a third party.
185
- </p>
186
- </li>
174
+ ${getChatDisclaimer(this.orgSlug ?? "")}
187
175
  ${this.building.welcomeMessage
188
176
  ? html` <li class="message-container ai-message">
189
177
  <p
@@ -265,11 +253,80 @@ export class PubnubChat extends LitElement {
265
253
  }
266
254
  }
267
255
 
256
+ const getChatDisclaimer = (orgSlug: string) => {
257
+ if (orgSlug === "avb") {
258
+ return html`
259
+ <li class="message-container disclaimer-message">
260
+ <p class="disclaimer-inner">
261
+ Chats may be recorded by us and our vendors.
262
+ </p>
263
+ </li>
264
+ `;
265
+ }
266
+ return html`<li class="message-container disclaimer-message">
267
+ <p class="disclaimer-inner">
268
+ By interacting with this system, you consent to
269
+ <a
270
+ href="http://bit.ly/me_privacy_policy"
271
+ target="_blank"
272
+ rel="noopener noreferrer"
273
+ >
274
+ this privacy policy</a
275
+ >, including being contacted by AI or a human & having your conversation
276
+ recorded by a third party.
277
+ </p>
278
+ </li>`;
279
+ };
280
+
268
281
  const getConsentPreChatDisclaimer = (
269
282
  orgSlug: string | null,
270
283
  privacyPolicyUrl: string,
271
284
  changeConsent: (hasConsent: boolean) => void
272
285
  ): TemplateResult => {
286
+ if (orgSlug === "avb") {
287
+ return html`
288
+ <div class="legal-confirmation-inner-container">
289
+ <div>${HeyThereEmoji}</div>
290
+ <div>
291
+ <span style="font-weight: 600">Confirm to continue</span>
292
+ <p>
293
+ By using this feature you accept our
294
+ <a
295
+ href="https://www.avaloncommunities.com/terms-of-use"
296
+ target="_blank"
297
+ rel="noopener noreferrer"
298
+ class="privacy-policy-link"
299
+ >Terms</a
300
+ >,
301
+ <a
302
+ href="https://www.avaloncommunities.com/privacy-policy"
303
+ target="_blank"
304
+ rel="noopener noreferrer"
305
+ class="privacy-policy-link"
306
+ >Privacy Policy</a
307
+ >,
308
+ <a
309
+ href="https://www.avaloncommunities.com/us-state-privacy-notice"
310
+ target="_blank"
311
+ rel="noopener noreferrer"
312
+ class="privacy-policy-link"
313
+ >U.S. State Privacy Notice</a
314
+ >, and that chats may use automated or AI responses from a bot and
315
+ may be recorded by us and our vendors.
316
+ </p>
317
+ </div>
318
+
319
+ <button
320
+ class="agreeButton"
321
+ @click=${() => {
322
+ changeConsent(true);
323
+ }}
324
+ >
325
+ I agree
326
+ </button>
327
+ </div>
328
+ `;
329
+ }
273
330
  if (orgSlug === "mill-creek") {
274
331
  return html`<div class="legal-confirmation-inner-container">
275
332
  <div>${HeyThereEmoji}</div>
@@ -0,0 +1,39 @@
1
+ const isDaylightSavingTime = (date: Date): boolean => {
2
+ const jan = new Date(date.getFullYear(), 0, 1);
3
+ const jul = new Date(date.getFullYear(), 6, 1);
4
+ const stdTimezoneOffset = Math.max(
5
+ jan.getTimezoneOffset(),
6
+ jul.getTimezoneOffset()
7
+ );
8
+
9
+ return date.getTimezoneOffset() < stdTimezoneOffset;
10
+ };
11
+
12
+ export const getTimezoneAbbreviation = (): string => {
13
+ const date = new Date();
14
+ const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
15
+ const isDST = isDaylightSavingTime(date);
16
+
17
+ switch (timeZone) {
18
+ case "America/New_York":
19
+ return isDST ? "EDT" : "EST";
20
+ case "America/Chicago":
21
+ return isDST ? "CDT" : "CST";
22
+ case "America/Denver":
23
+ return isDST ? "MDT" : "MST";
24
+ case "America/Los_Angeles":
25
+ return isDST ? "PDT" : "PST";
26
+ case "America/Anchorage":
27
+ return isDST ? "AKDT" : "AKST";
28
+ case "America/Honolulu":
29
+ return "HST";
30
+ case "America/Phoenix":
31
+ return "MST";
32
+ case "America/Indiana/Indianapolis":
33
+ return isDST ? "EDT" : "EST";
34
+ case "America/Indiana/Knox":
35
+ return isDST ? "CDT" : "CST";
36
+ default:
37
+ return "Unknown";
38
+ }
39
+ };