@meetelise/chat 1.34.1 → 1.34.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.
Files changed (279) hide show
  1. package/package.json +1 -1
  2. package/dist/src/MyPubnub.d.ts +0 -116
  3. package/dist/src/WebComponent/FeeCalculator/components/addons/addon-item-matrix-qty-selector/addon-item-matrix-qty-selector-styles.d.ts +0 -2
  4. package/dist/src/WebComponent/FeeCalculator/components/addons/addon-item-matrix-qty-selector/addon-item-matrix-qty-selector.d.ts +0 -28
  5. package/dist/src/WebComponent/FeeCalculator/components/addons/addon-item-qty-selector/addon-item-qty-selector-styles.d.ts +0 -2
  6. package/dist/src/WebComponent/FeeCalculator/components/addons/addon-item-qty-selector/addon-item-qty-selector.d.ts +0 -18
  7. package/dist/src/WebComponent/FeeCalculator/components/addons/common-addon-styles.d.ts +0 -2
  8. package/dist/src/WebComponent/FeeCalculator/components/addons/rentable-item-qty-selector/rentable-item-qty-selector-styles.d.ts +0 -2
  9. package/dist/src/WebComponent/FeeCalculator/components/addons/rentable-item-qty-selector/rentable-item-qty-selector.d.ts +0 -22
  10. package/dist/src/WebComponent/FeeCalculator/components/fee-calculator-layout/fee-calculator-layout-styles.d.ts +0 -2
  11. package/dist/src/WebComponent/FeeCalculator/components/fee-calculator-layout/fee-calculator-layout.d.ts +0 -46
  12. package/dist/src/WebComponent/FeeCalculator/components/fee-card/fee-card-styles.d.ts +0 -2
  13. package/dist/src/WebComponent/FeeCalculator/components/fee-card/fee-card.d.ts +0 -21
  14. package/dist/src/WebComponent/FeeCalculator/components/fee-item/fee-item-styles.d.ts +0 -2
  15. package/dist/src/WebComponent/FeeCalculator/components/fee-item/fee-item.d.ts +0 -13
  16. package/dist/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector-styles.d.ts +0 -2
  17. package/dist/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector.d.ts +0 -34
  18. package/dist/src/WebComponent/FeeCalculator/components/floorplan-image-card/floorplan-image-card-styles.d.ts +0 -2
  19. package/dist/src/WebComponent/FeeCalculator/components/floorplan-image-card/floorplan-image-card.d.ts +0 -18
  20. package/dist/src/WebComponent/FeeCalculator/components/incentive-banner/incentive-banner-styles.d.ts +0 -1
  21. package/dist/src/WebComponent/FeeCalculator/components/incentive-banner/incentive-banner.d.ts +0 -8
  22. package/dist/src/WebComponent/FeeCalculator/components/incentive-banner/index.d.ts +0 -1
  23. package/dist/src/WebComponent/FeeCalculator/components/index.d.ts +0 -5
  24. package/dist/src/WebComponent/FeeCalculator/components/promo-card/promo-card-styles.d.ts +0 -2
  25. package/dist/src/WebComponent/FeeCalculator/components/promo-card/promo-card.d.ts +0 -13
  26. package/dist/src/WebComponent/FeeCalculator/constants.d.ts +0 -3
  27. package/dist/src/WebComponent/FeeCalculator/fee-calculator-styles.d.ts +0 -1
  28. package/dist/src/WebComponent/FeeCalculator/fee-calculator.d.ts +0 -55
  29. package/dist/src/WebComponent/FeeCalculator/index.d.ts +0 -2
  30. package/dist/src/WebComponent/FeeCalculator/model/building-fee-view.d.ts +0 -41
  31. package/dist/src/WebComponent/FeeCalculator/model/building-fee.d.ts +0 -82
  32. package/dist/src/WebComponent/FeeCalculator/model/desired-addon.d.ts +0 -5
  33. package/dist/src/WebComponent/FeeCalculator/model/desired-rentable-item.d.ts +0 -4
  34. package/dist/src/WebComponent/FeeCalculator/model/index.d.ts +0 -13
  35. package/dist/src/WebComponent/FeeCalculator/model/item-combination.d.ts +0 -6
  36. package/dist/src/WebComponent/FeeCalculator/model/item-quantity.d.ts +0 -4
  37. package/dist/src/WebComponent/FeeCalculator/model/pricing-matrix.d.ts +0 -18
  38. package/dist/src/WebComponent/FeeCalculator/model/pricing-rule.d.ts +0 -8
  39. package/dist/src/WebComponent/FeeCalculator/model/rent-frequency.d.ts +0 -1
  40. package/dist/src/WebComponent/FeeCalculator/model/rentable-item-summary.d.ts +0 -9
  41. package/dist/src/WebComponent/FeeCalculator/model/rentable-item.d.ts +0 -9
  42. package/dist/src/WebComponent/FeeCalculator/model/transaction-category.d.ts +0 -23
  43. package/dist/src/WebComponent/FeeCalculator/model/unit-fee-bundle.d.ts +0 -31
  44. package/dist/src/WebComponent/LeadSourceClient.d.ts +0 -46
  45. package/dist/src/WebComponent/OfficeHours.d.ts +0 -21
  46. package/dist/src/WebComponent/Scheduler/date-picker.d.ts +0 -28
  47. package/dist/src/WebComponent/Scheduler/time-picker.d.ts +0 -14
  48. package/dist/src/WebComponent/Scheduler/tour-scheduler.d.ts +0 -101
  49. package/dist/src/WebComponent/Scheduler/tour-type-option.d.ts +0 -13
  50. package/dist/src/WebComponent/Scheduler/tourSchedulerStyles.d.ts +0 -1
  51. package/dist/src/WebComponent/actions/InputStyles.d.ts +0 -1
  52. package/dist/src/WebComponent/actions/action-confirm-button.d.ts +0 -13
  53. package/dist/src/WebComponent/actions/call-us-window.d.ts +0 -37
  54. package/dist/src/WebComponent/actions/collapse-expand-button.d.ts +0 -8
  55. package/dist/src/WebComponent/actions/details-window.d.ts +0 -14
  56. package/dist/src/WebComponent/actions/email-us-window.d.ts +0 -46
  57. package/dist/src/WebComponent/actions/formatPhoneNumber.d.ts +0 -17
  58. package/dist/src/WebComponent/actions/minimize-expand-button.d.ts +0 -8
  59. package/dist/src/WebComponent/chat-additional-actions.d.ts +0 -28
  60. package/dist/src/WebComponent/health-chat.d.ts +0 -47
  61. package/dist/src/WebComponent/healthchat-styles.d.ts +0 -1
  62. package/dist/src/WebComponent/icons/ApplyOutlineIcon.d.ts +0 -2
  63. package/dist/src/WebComponent/icons/BookTourOutlineIcon.d.ts +0 -2
  64. package/dist/src/WebComponent/icons/CalculatorOutlineIcon.d.ts +0 -2
  65. package/dist/src/WebComponent/icons/ChatOutlineIcon.d.ts +0 -2
  66. package/dist/src/WebComponent/icons/ChevronLeftIcon.d.ts +0 -2
  67. package/dist/src/WebComponent/icons/ChevronRightIcon.d.ts +0 -2
  68. package/dist/src/WebComponent/icons/ContactResidentIcon.d.ts +0 -2
  69. package/dist/src/WebComponent/icons/DollarOutlineIcon.d.ts +0 -7
  70. package/dist/src/WebComponent/icons/EmailOutlineIcon.d.ts +0 -2
  71. package/dist/src/WebComponent/icons/HeyThereEmojiIcon.d.ts +0 -2
  72. package/dist/src/WebComponent/icons/PhoneOutlineIcon.d.ts +0 -2
  73. package/dist/src/WebComponent/icons/SendMessageIcon.d.ts +0 -3
  74. package/dist/src/WebComponent/icons/TourSelfGuidedIcon.d.ts +0 -2
  75. package/dist/src/WebComponent/icons/TourVirtuallyIcon.d.ts +0 -2
  76. package/dist/src/WebComponent/icons/TourWithAgentIcon.d.ts +0 -2
  77. package/dist/src/WebComponent/icons/XOutlineIcon.d.ts +0 -2
  78. package/dist/src/WebComponent/index.d.ts +0 -2
  79. package/dist/src/WebComponent/launcher/Launcher.d.ts +0 -99
  80. package/dist/src/WebComponent/launcher/launcherStyles.d.ts +0 -1
  81. package/dist/src/WebComponent/launcher/mobile-launcher.d.ts +0 -27
  82. package/dist/src/WebComponent/launcher/typeEmojiStyles.d.ts +0 -1
  83. package/dist/src/WebComponent/launcher/typeMiniStyles.d.ts +0 -1
  84. package/dist/src/WebComponent/launcher/typeMobileStyles.d.ts +0 -1
  85. package/dist/src/WebComponent/leasing-chat-styles.d.ts +0 -1
  86. package/dist/src/WebComponent/loaders/index.d.ts +0 -4
  87. package/dist/src/WebComponent/loaders/mega-loader.d.ts +0 -7
  88. package/dist/src/WebComponent/loaders/skeleton-card.d.ts +0 -12
  89. package/dist/src/WebComponent/loaders/skeleton-loader-styles.d.ts +0 -3
  90. package/dist/src/WebComponent/loaders/skeleton-loader.d.ts +0 -13
  91. package/dist/src/WebComponent/me-chat.d.ts +0 -91
  92. package/dist/src/WebComponent/me-select.d.ts +0 -24
  93. package/dist/src/WebComponent/mini-loader.d.ts +0 -5
  94. package/dist/src/WebComponent/pubnub-chat-styles.d.ts +0 -1
  95. package/dist/src/WebComponent/pubnub-chat.d.ts +0 -49
  96. package/dist/src/WebComponent/pubnub-media.d.ts +0 -14
  97. package/dist/src/WebComponent/pubnub-message-styles.d.ts +0 -1
  98. package/dist/src/WebComponent/pubnub-message.d.ts +0 -39
  99. package/dist/src/WebComponent/simple-launcher/simple-launcher-styles.d.ts +0 -1
  100. package/dist/src/WebComponent/simple-launcher/simple-launcher.d.ts +0 -12
  101. package/dist/src/WebComponent/utilities-chat.d.ts +0 -47
  102. package/dist/src/WebComponent/utilities-styles.d.ts +0 -1
  103. package/dist/src/WebComponent/utils.d.ts +0 -31
  104. package/dist/src/analytics.d.ts +0 -64
  105. package/dist/src/disclaimers.d.ts +0 -9
  106. package/dist/src/fetchBuildingABTestType.d.ts +0 -8
  107. package/dist/src/fetchBuildingInfo.d.ts +0 -57
  108. package/dist/src/fetchBuildingWebchatView.d.ts +0 -124
  109. package/dist/src/fetchFeatureFlag.d.ts +0 -14
  110. package/dist/src/fetchLeadSources.d.ts +0 -4
  111. package/dist/src/fetchPhoneNumberFromSource.d.ts +0 -6
  112. package/dist/src/getAvailabilities.d.ts +0 -45
  113. package/dist/src/getBuildingPhoneNumber.d.ts +0 -1
  114. package/dist/src/getShouldAllowScheduling.d.ts +0 -1
  115. package/dist/src/getShouldShowWebchat.d.ts +0 -3
  116. package/dist/src/getTimezoneString.d.ts +0 -1
  117. package/dist/src/globals.d.ts +0 -2
  118. package/dist/src/gtm.d.ts +0 -6
  119. package/dist/src/handleChatId.d.ts +0 -11
  120. package/dist/src/insertDNIIntoWebsite.d.ts +0 -5
  121. package/dist/src/insertLeadSourceIntoSchedulerLinks.d.ts +0 -4
  122. package/dist/src/main/MEChat.d.ts +0 -74
  123. package/dist/src/main/utils.d.ts +0 -2
  124. package/dist/src/postLeadSources.d.ts +0 -3
  125. package/dist/src/rentgrata.d.ts +0 -4
  126. package/dist/src/replaceSelectButtonsWithNewLink.d.ts +0 -5
  127. package/dist/src/services/fees/calculateQuote.d.ts +0 -14
  128. package/dist/src/services/fees/fetchBuildingFeesV2.d.ts +0 -10
  129. package/dist/src/services/fees/fetchBuildingUnits.d.ts +0 -29
  130. package/dist/src/services/fees/utils.d.ts +0 -1
  131. package/dist/src/svgIcons.d.ts +0 -5
  132. package/dist/src/themes.d.ts +0 -5
  133. package/dist/src/types/incentive-v2.d.ts +0 -23
  134. package/dist/src/types/rest-sdk.types.d.ts +0 -11
  135. package/dist/src/types/webchat-no-show-reason.d.ts +0 -1
  136. package/dist/src/utils/queryParamBuilder.d.ts +0 -8
  137. package/dist/src/utils.d.ts +0 -13
  138. package/src/MyPubnub.ts +0 -792
  139. package/src/WebComponent/FeeCalculator/components/addons/addon-item-matrix-qty-selector/addon-item-matrix-qty-selector-styles.ts +0 -35
  140. package/src/WebComponent/FeeCalculator/components/addons/addon-item-matrix-qty-selector/addon-item-matrix-qty-selector.ts +0 -206
  141. package/src/WebComponent/FeeCalculator/components/addons/addon-item-qty-selector/addon-item-qty-selector-styles.ts +0 -6
  142. package/src/WebComponent/FeeCalculator/components/addons/addon-item-qty-selector/addon-item-qty-selector.ts +0 -101
  143. package/src/WebComponent/FeeCalculator/components/addons/common-addon-styles.ts +0 -82
  144. package/src/WebComponent/FeeCalculator/components/addons/rentable-item-qty-selector/rentable-item-qty-selector-styles.ts +0 -9
  145. package/src/WebComponent/FeeCalculator/components/addons/rentable-item-qty-selector/rentable-item-qty-selector.ts +0 -124
  146. package/src/WebComponent/FeeCalculator/components/fee-calculator-layout/fee-calculator-layout-styles.ts +0 -142
  147. package/src/WebComponent/FeeCalculator/components/fee-calculator-layout/fee-calculator-layout.ts +0 -243
  148. package/src/WebComponent/FeeCalculator/components/fee-card/fee-card-styles.ts +0 -65
  149. package/src/WebComponent/FeeCalculator/components/fee-card/fee-card.ts +0 -91
  150. package/src/WebComponent/FeeCalculator/components/fee-item/fee-item-styles.ts +0 -44
  151. package/src/WebComponent/FeeCalculator/components/fee-item/fee-item.ts +0 -38
  152. package/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector-styles.ts +0 -151
  153. package/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector.ts +0 -248
  154. package/src/WebComponent/FeeCalculator/components/floorplan-image-card/floorplan-image-card-styles.ts +0 -82
  155. package/src/WebComponent/FeeCalculator/components/floorplan-image-card/floorplan-image-card.ts +0 -76
  156. package/src/WebComponent/FeeCalculator/components/incentive-banner/incentive-banner-styles.ts +0 -40
  157. package/src/WebComponent/FeeCalculator/components/incentive-banner/incentive-banner.ts +0 -43
  158. package/src/WebComponent/FeeCalculator/components/incentive-banner/index.ts +0 -1
  159. package/src/WebComponent/FeeCalculator/components/index.ts +0 -5
  160. package/src/WebComponent/FeeCalculator/components/promo-card/promo-card-styles.ts +0 -39
  161. package/src/WebComponent/FeeCalculator/components/promo-card/promo-card.ts +0 -39
  162. package/src/WebComponent/FeeCalculator/constants.ts +0 -5
  163. package/src/WebComponent/FeeCalculator/fee-calculator-styles.ts +0 -310
  164. package/src/WebComponent/FeeCalculator/fee-calculator.ts +0 -341
  165. package/src/WebComponent/FeeCalculator/index.ts +0 -4
  166. package/src/WebComponent/FeeCalculator/model/building-fee-view.ts +0 -84
  167. package/src/WebComponent/FeeCalculator/model/building-fee.ts +0 -126
  168. package/src/WebComponent/FeeCalculator/model/desired-addon.ts +0 -6
  169. package/src/WebComponent/FeeCalculator/model/desired-rentable-item.ts +0 -4
  170. package/src/WebComponent/FeeCalculator/model/index.ts +0 -13
  171. package/src/WebComponent/FeeCalculator/model/item-combination.ts +0 -16
  172. package/src/WebComponent/FeeCalculator/model/item-quantity.ts +0 -4
  173. package/src/WebComponent/FeeCalculator/model/pricing-matrix.ts +0 -45
  174. package/src/WebComponent/FeeCalculator/model/pricing-rule.ts +0 -9
  175. package/src/WebComponent/FeeCalculator/model/rent-frequency.ts +0 -1
  176. package/src/WebComponent/FeeCalculator/model/rentable-item-summary.ts +0 -10
  177. package/src/WebComponent/FeeCalculator/model/rentable-item.ts +0 -10
  178. package/src/WebComponent/FeeCalculator/model/transaction-category.ts +0 -23
  179. package/src/WebComponent/FeeCalculator/model/unit-fee-bundle.ts +0 -54
  180. package/src/WebComponent/LeadSourceClient.ts +0 -332
  181. package/src/WebComponent/MEChat.css +0 -5
  182. package/src/WebComponent/OfficeHours.ts +0 -73
  183. package/src/WebComponent/Scheduler/date-picker.ts +0 -405
  184. package/src/WebComponent/Scheduler/time-picker.ts +0 -190
  185. package/src/WebComponent/Scheduler/tour-scheduler.ts +0 -1416
  186. package/src/WebComponent/Scheduler/tour-type-option.ts +0 -112
  187. package/src/WebComponent/Scheduler/tourSchedulerStyles.ts +0 -418
  188. package/src/WebComponent/actions/InputStyles.ts +0 -57
  189. package/src/WebComponent/actions/action-confirm-button.ts +0 -125
  190. package/src/WebComponent/actions/call-us-window.ts +0 -467
  191. package/src/WebComponent/actions/collapse-expand-button.ts +0 -65
  192. package/src/WebComponent/actions/details-window.ts +0 -150
  193. package/src/WebComponent/actions/email-us-window.ts +0 -556
  194. package/src/WebComponent/actions/formatPhoneNumber.ts +0 -72
  195. package/src/WebComponent/actions/minimize-expand-button.ts +0 -93
  196. package/src/WebComponent/chat-additional-actions.ts +0 -135
  197. package/src/WebComponent/health-chat.ts +0 -270
  198. package/src/WebComponent/healthchat-styles.ts +0 -119
  199. package/src/WebComponent/icons/ApplyOutlineIcon.ts +0 -22
  200. package/src/WebComponent/icons/BookTourOutlineIcon.ts +0 -13
  201. package/src/WebComponent/icons/CalculatorOutlineIcon.ts +0 -22
  202. package/src/WebComponent/icons/ChatOutlineIcon.ts +0 -10
  203. package/src/WebComponent/icons/ChevronLeftIcon.ts +0 -7
  204. package/src/WebComponent/icons/ChevronRightIcon.ts +0 -7
  205. package/src/WebComponent/icons/ContactResidentIcon.ts +0 -9
  206. package/src/WebComponent/icons/DollarOutlineIcon.ts +0 -26
  207. package/src/WebComponent/icons/EmailOutlineIcon.ts +0 -7
  208. package/src/WebComponent/icons/HeyThereEmojiIcon.ts +0 -12
  209. package/src/WebComponent/icons/PhoneOutlineIcon.ts +0 -7
  210. package/src/WebComponent/icons/SendMessageIcon.ts +0 -17
  211. package/src/WebComponent/icons/TourSelfGuidedIcon.ts +0 -17
  212. package/src/WebComponent/icons/TourVirtuallyIcon.ts +0 -17
  213. package/src/WebComponent/icons/TourWithAgentIcon.ts +0 -17
  214. package/src/WebComponent/icons/XOutlineIcon.ts +0 -8
  215. package/src/WebComponent/index.ts +0 -2
  216. package/src/WebComponent/launcher/Launcher.ts +0 -1284
  217. package/src/WebComponent/launcher/launcherStyles.ts +0 -500
  218. package/src/WebComponent/launcher/mobile-launcher.ts +0 -162
  219. package/src/WebComponent/launcher/typeEmojiStyles.ts +0 -161
  220. package/src/WebComponent/launcher/typeMiniStyles.ts +0 -60
  221. package/src/WebComponent/launcher/typeMobileStyles.ts +0 -50
  222. package/src/WebComponent/leasing-chat-styles.ts +0 -114
  223. package/src/WebComponent/loaders/index.ts +0 -7
  224. package/src/WebComponent/loaders/mega-loader.ts +0 -36
  225. package/src/WebComponent/loaders/skeleton-card.ts +0 -31
  226. package/src/WebComponent/loaders/skeleton-loader-styles.ts +0 -112
  227. package/src/WebComponent/loaders/skeleton-loader.ts +0 -34
  228. package/src/WebComponent/me-chat.ts +0 -1261
  229. package/src/WebComponent/me-select.ts +0 -322
  230. package/src/WebComponent/mini-loader.ts +0 -28
  231. package/src/WebComponent/pubnub-chat-styles.ts +0 -204
  232. package/src/WebComponent/pubnub-chat.ts +0 -928
  233. package/src/WebComponent/pubnub-media.ts +0 -208
  234. package/src/WebComponent/pubnub-message-styles.ts +0 -54
  235. package/src/WebComponent/pubnub-message.ts +0 -431
  236. package/src/WebComponent/simple-launcher/simple-launcher-styles.ts +0 -34
  237. package/src/WebComponent/simple-launcher/simple-launcher.ts +0 -100
  238. package/src/WebComponent/utilities-chat.ts +0 -270
  239. package/src/WebComponent/utilities-styles.ts +0 -110
  240. package/src/WebComponent/utils.ts +0 -82
  241. package/src/analytics.ts +0 -217
  242. package/src/assetUrls.ts +0 -6
  243. package/src/disclaimers.ts +0 -86
  244. package/src/fetchBuildingABTestType.ts +0 -21
  245. package/src/fetchBuildingInfo.ts +0 -87
  246. package/src/fetchBuildingWebchatView.ts +0 -176
  247. package/src/fetchFeatureFlag.ts +0 -250
  248. package/src/fetchLeadSources.ts +0 -98
  249. package/src/fetchPhoneNumberFromSource.ts +0 -31
  250. package/src/fetchWebchatPreferences.ts +0 -54
  251. package/src/getAvailabilities.ts +0 -179
  252. package/src/getBuildingPhoneNumber.ts +0 -26
  253. package/src/getShouldAllowScheduling.ts +0 -16
  254. package/src/getShouldShowWebchat.ts +0 -114
  255. package/src/getTimezoneString.ts +0 -39
  256. package/src/globals.ts +0 -3
  257. package/src/gtm.ts +0 -17
  258. package/src/handleChatId.ts +0 -101
  259. package/src/insertDNIIntoWebsite.ts +0 -146
  260. package/src/insertLeadSourceIntoSchedulerLinks.ts +0 -71
  261. package/src/main/MEChat.test.ts +0 -110
  262. package/src/main/MEChat.ts +0 -404
  263. package/src/main/utils.ts +0 -70
  264. package/src/postLeadSources.ts +0 -44
  265. package/src/rentgrata.ts +0 -74
  266. package/src/replaceSelectButtonsWithNewLink.ts +0 -90
  267. package/src/services/fees/calculateQuote.ts +0 -74
  268. package/src/services/fees/fetchBuildingFees.ts +0 -50
  269. package/src/services/fees/fetchBuildingFeesV2.ts +0 -56
  270. package/src/services/fees/fetchBuildingFloorplans.ts +0 -74
  271. package/src/services/fees/fetchBuildingUnits.ts +0 -86
  272. package/src/services/fees/utils.ts +0 -4
  273. package/src/svgIcons.ts +0 -14
  274. package/src/themes.ts +0 -65
  275. package/src/types/incentive-v2.ts +0 -24
  276. package/src/types/rest-sdk.types.ts +0 -13
  277. package/src/types/webchat-no-show-reason.ts +0 -6
  278. package/src/utils/queryParamBuilder.ts +0 -28
  279. package/src/utils.ts +0 -121
@@ -1,1416 +0,0 @@
1
- import { html, LitElement, PropertyValueMap, TemplateResult } from "lit";
2
- import { customElement, property, query, state } from "lit/decorators.js";
3
- import {
4
- shortcutKeyIsPressed,
5
- formatToPhoneInput,
6
- isPrintableCharacter,
7
- } from "../actions/formatPhoneNumber";
8
- import "./tour-type-option.ts";
9
- import "./date-picker.ts";
10
- import "./time-picker.ts";
11
- import "../me-select.ts";
12
- import {
13
- DateWithTimeZoneOffset,
14
- getAvailabilitiesGroupedByDay,
15
- getExistenceOfAvailabilitiesByTourType,
16
- resetAvailabilitiesCache,
17
- } from "../../getAvailabilities";
18
- import { TourAvailabilityResponseRankOrderedSupportedTourTypesEnum } from "../../types/rest-sdk.types";
19
- import { format } from "date-fns";
20
- import { DatePicker } from "./date-picker";
21
- import { MESelect } from "../me-select";
22
- import { TimePicker } from "./time-picker";
23
- import { LabeledOption } from "../../fetchBuildingInfo";
24
- import { isMobile, isValidPhoneNumber } from "../../utils";
25
- import axios, { AxiosError } from "axios";
26
- import mapValues from "lodash/mapValues";
27
- import classnames from "classnames";
28
- import parseISO from "date-fns/parseISO";
29
- import compareAsc from "date-fns/compareAsc";
30
- import { InputStyles } from "../actions/InputStyles";
31
- import { classMap } from "lit/directives/class-map.js";
32
- import { FeatureFlagsShowDropdown } from "../../fetchFeatureFlag";
33
- import { pushGtmEvent } from "../../gtm";
34
- import disclaimer from "../../disclaimers";
35
- import { tourSchedulerStyles } from "./tourSchedulerStyles";
36
- import { defaultPrimaryColor, defaultBackgroundColor } from "../../themes";
37
- import { LogType, sendLoggingEvent } from "../../analytics";
38
- import LeadSourceClient, {
39
- getDefaultLeadSourceAttribution,
40
- } from "../LeadSourceClient";
41
- import { getShouldAllowScheduling } from "../../getShouldAllowScheduling";
42
- import { TourVirtuallyIcon } from "../icons/TourVirtuallyIcon";
43
- import { TourSelfGuidedIcon } from "../icons/TourSelfGuidedIcon";
44
- import { TourWithAgentIcon } from "../icons/TourWithAgentIcon";
45
- import { shouldOpenTourLink } from "../../fetchBuildingWebchatView";
46
-
47
- @customElement("tour-scheduler")
48
- export class TourScheduler extends LitElement {
49
- @property({ attribute: false })
50
- tourTypeOptions: LabeledOption[] = [];
51
- @property({ attribute: true })
52
- chatId = "";
53
- @property({ type: Number })
54
- buildingId = 0;
55
- @property({ attribute: true })
56
- buildingSlug = "";
57
- @property({ attribute: true })
58
- sgtUrl = "";
59
- @property({ attribute: true })
60
- selfGuidedToursTypeOffered = "";
61
- @property({ attribute: true })
62
- selfGuidedTourEnabled = false;
63
- @property({ attribute: true })
64
- escortedToursLink = "";
65
- @property({ attribute: true })
66
- virtualToursLink = "";
67
- @property({ attribute: true })
68
- virtualToursTypeOffered = "";
69
- @property({ attribute: true })
70
- orgSlug = "";
71
- @property({ attribute: true })
72
- hasDynamicSchedulingEnabled = false;
73
-
74
- @property({ attribute: true })
75
- private leadSourceClient: LeadSourceClient | null = null;
76
-
77
- @property({ attribute: true })
78
- buildingName = "";
79
-
80
- onCloseClicked?: (e: MouseEvent) => void;
81
-
82
- @state()
83
- private tourType: TourType | null = null;
84
- @state()
85
- private shouldShowTourType = {
86
- [TourType.Guided]: true,
87
- [TourType.Self]: true,
88
- [TourType.Virtual]: true,
89
- };
90
- @state()
91
- private email = "";
92
- @state()
93
- private phoneNumber = "";
94
- @state()
95
- private availabilitiesGroupedByDay: {
96
- [day: string]: DateWithTimeZoneOffset[];
97
- } = {};
98
- @state()
99
- private waitingForAvailabilities = true;
100
- @state()
101
- private selectedDate?: Date;
102
- @state()
103
- private selectedTime?: DateWithTimeZoneOffset | null;
104
- @state()
105
- private mobilePageIndex = 0;
106
- @state()
107
- private isSubmitting = false;
108
- @state()
109
- private tourIsBooked = false;
110
- @state()
111
- private shouldAllowScheduling = false;
112
- @state()
113
- private shouldAllowScheduleLoading = true;
114
- @state()
115
- private promptForReschedule = false;
116
- @state()
117
- private canceledReschedule = false;
118
-
119
- @property({ attribute: false })
120
- leadSources: string[] = [];
121
-
122
- @property({ attribute: true })
123
- orgLegalName = "";
124
-
125
- @property({ attribute: true })
126
- currentLeadSource = ""; // the default lead source based on referrer and query params.
127
-
128
- @property({ attribute: true })
129
- featureFlagShowDropdown = "";
130
-
131
- @property({ attribute: true })
132
- compactDesign = false;
133
-
134
- @property({ attribute: true })
135
- primaryColor: string = defaultPrimaryColor;
136
-
137
- @property({ attribute: true })
138
- backgroundColor: string = defaultBackgroundColor;
139
-
140
- @property({ attribute: true })
141
- foregroundColorOnPrimaryBackgroundColor = "white";
142
-
143
- @property({ attribute: true })
144
- foregroundColorOnSecondaryBackgroundColor = "black";
145
-
146
- @query(".nameContainer#firstName input")
147
- firstNameInput!: HTMLInputElement;
148
- @query(".nameContainer#lastName input")
149
- lastNameInput!: HTMLInputElement;
150
- @query(".inputContainer#email input")
151
- emailInput!: HTMLInputElement;
152
- @query(".inputContainer#phone input")
153
- phoneInput!: HTMLInputElement;
154
- @query("me-select#leadSource")
155
- selectedLeadSource!: MESelect;
156
-
157
- @state()
158
- firstNameInputValue = "";
159
- @state()
160
- lastNameInputValue = "";
161
- @state()
162
- leadSourceInputValue = "";
163
-
164
- @state()
165
- errorGettingAvailabilities = false;
166
-
167
- _setAvailabilities = async (): Promise<void> => {
168
- try {
169
- const [allowScheduling, availabilitiesExistForTourType] =
170
- await Promise.all([
171
- getShouldAllowScheduling(
172
- this.buildingId,
173
- this.hasDynamicSchedulingEnabled
174
- ),
175
- getExistenceOfAvailabilitiesByTourType(),
176
- ]);
177
-
178
- this.shouldAllowScheduling = allowScheduling;
179
- this.shouldAllowScheduleLoading = false;
180
-
181
- sendLoggingEvent({
182
- logTitle: "AVAILABILITIES_EXIST_FOR_TOUR_TYPE",
183
- logData: availabilitiesExistForTourType,
184
- logType: LogType.info,
185
- buildingSlug: this.buildingSlug,
186
- orgSlug: this.orgSlug,
187
- });
188
- const allValuesAreFalse = Object.values(
189
- availabilitiesExistForTourType
190
- ).every((v) => v === false);
191
- const hasNoTourLinks =
192
- !this.sgtUrl && !this.escortedToursLink && !this.virtualToursLink;
193
- if (allValuesAreFalse && hasNoTourLinks) {
194
- this.errorGettingAvailabilities = true;
195
- this.waitingForAvailabilities = false;
196
- sendLoggingEvent({
197
- logTitle: "NO_AVAILABILITIES_EXIST",
198
- logData: null,
199
- logType: LogType.warn,
200
- buildingSlug: this.buildingSlug,
201
- orgSlug: this.orgSlug,
202
- });
203
- return;
204
- }
205
- this.shouldShowTourType = {
206
- [TourType.Guided]:
207
- this.tourTypeOptions.map((o) => o.value).includes("WITH_AGENT") &&
208
- (availabilitiesExistForTourType[TourType.Guided] ||
209
- !!this.escortedToursLink),
210
- [TourType.Self]:
211
- this.tourTypeOptions.map((o) => o.value).includes("SELF_GUIDED") &&
212
- (availabilitiesExistForTourType[TourType.Self] || !!this.sgtUrl),
213
- [TourType.Virtual]:
214
- this.tourTypeOptions
215
- .map((o) => o.value)
216
- .includes("VIRTUAL_SHOWING") &&
217
- (availabilitiesExistForTourType[TourType.Virtual] ||
218
- !!this.virtualToursLink),
219
- };
220
-
221
- // if there is only a single option for tour type, have that be the default
222
- const hasOneShowTourType =
223
- Object.values(this.shouldShowTourType).reduce((acc, cur) => {
224
- if (cur === true) {
225
- return acc + 1;
226
- } else {
227
- return acc;
228
- }
229
- }, 0) === 1;
230
-
231
- if (hasOneShowTourType) {
232
- this.tourType = Object.keys(this.shouldShowTourType).find(
233
- (key) => this.shouldShowTourType[key as TourType]
234
- ) as TourType;
235
- } else {
236
- // if we have multiple tour types, then check if there is a default that the client wants selected
237
- // HACK: FOR DEMO, FOR https://www.sofioceanhills.com/ -
238
- // THIS SHOULD BE ADDED TO WEBCHAT CONFIGURATION
239
- // if (
240
- // this.buildingSlug === "1ac49f90-6150-11ed-b327-1b3f05e7b9db" &&
241
- // this.shouldShowTourType[TourType.Self]
242
- // ) {
243
- // this.tourType = TourType.Self;
244
- // }
245
- }
246
-
247
- if (this.tourType === null) {
248
- this.waitingForAvailabilities = false;
249
- return;
250
- }
251
- this.availabilitiesGroupedByDay = await getAvailabilitiesGroupedByDay(
252
- tourTypeMap[this.tourType]
253
- );
254
- this.waitingForAvailabilities = false;
255
- } catch (e) {
256
- this.errorGettingAvailabilities = true;
257
- this.waitingForAvailabilities = false;
258
- sendLoggingEvent({
259
- logTitle: "ERROR_LOADING_AVAILABILITIES",
260
- logData: { error: e },
261
- logType: LogType.error,
262
- buildingSlug: this.buildingSlug,
263
- orgSlug: this.orgSlug,
264
- });
265
- }
266
- };
267
-
268
- firstUpdated = async (): Promise<void> => {
269
- await this._setAvailabilities();
270
- };
271
-
272
- protected willUpdate = async (
273
- _changedProperties:
274
- | PropertyValueMap<{ tourType: TourType }>
275
- | Map<PropertyKey, unknown>
276
- ): Promise<void> => {
277
- if (_changedProperties.has("tourType") && this.tourType) {
278
- this.availabilitiesGroupedByDay = await getAvailabilitiesGroupedByDay(
279
- tourTypeMap[this.tourType]
280
- );
281
- }
282
- };
283
-
284
- handlePhoneKeydown = (e: Event): void => {
285
- // these should always be true, this is just here to mollify TypeScript
286
- if (
287
- !(e instanceof KeyboardEvent) ||
288
- !(e.target instanceof HTMLInputElement) ||
289
- e.target.selectionStart === null
290
- // !e.target.selectionStart
291
- )
292
- return;
293
-
294
- const cursorPosition = e.target.selectionStart;
295
-
296
- if (isPrintableCharacter(e) && !shortcutKeyIsPressed(e)) {
297
- // If e.key is a character, and no modifier key is pressed, insert it at the cursor, filter out non-numbers, and auto-format
298
- e.preventDefault();
299
- e.stopPropagation();
300
- const updated =
301
- this.phoneNumber.slice(0, cursorPosition) +
302
- e.key +
303
- this.phoneNumber.slice(cursorPosition);
304
- this.phoneNumber = formatToPhoneInput(updated.replace(/\D/g, ""));
305
- this.phoneInput.value = this.phoneNumber;
306
- } else if (e.key === "Backspace") {
307
- /*
308
- Handling backspace:
309
- - A single backspace should delete the last digit before the cursor, not just a punctuation character; the user shouldn't interact directly with the punctuation
310
- - Let the OS handle backspace combos like `Alt + Backspace`, then re-autoformat if necessary (in keyup)
311
- - If the user wants to select and backspace a range of text, let them, then auto-format the remainder
312
- */
313
-
314
- // backspace combos
315
- if (shortcutKeyIsPressed(e)) {
316
- return;
317
- }
318
-
319
- // backspace selection
320
- if (
321
- this.phoneInput.selectionEnd &&
322
- this.phoneInput.selectionStart &&
323
- this.phoneInput.selectionEnd - this.phoneInput.selectionStart > 0
324
- ) {
325
- return;
326
- }
327
-
328
- // regular backspace
329
- const originalCharacterCount = this.phoneNumber.length;
330
- const digitsBeforeCursor = this.phoneNumber
331
- .slice(0, cursorPosition)
332
- .replace(/\D/g, "");
333
- const digitsAfterCursor = this.phoneNumber
334
- .slice(cursorPosition)
335
- .replace(/\D/g, "");
336
- const updatedDigits = `${digitsBeforeCursor.slice(
337
- 0,
338
- -1
339
- )}${digitsAfterCursor}`;
340
- this.phoneNumber = formatToPhoneInput(updatedDigits);
341
- this.phoneInput.value = this.phoneNumber;
342
- const numOfCharactersDeleted =
343
- originalCharacterCount - this.phoneNumber.length;
344
- const newCursorPosition = cursorPosition - numOfCharactersDeleted;
345
- this.phoneInput.setSelectionRange(newCursorPosition, newCursorPosition);
346
- e.preventDefault();
347
- e.stopPropagation();
348
- return;
349
- } else if (
350
- ["ArrowLeft", "ArrowRight"].includes(e.key) &&
351
- !shortcutKeyIsPressed(e) &&
352
- !e.shiftKey
353
- ) {
354
- // when navigating with arrow keys, skip punctuation
355
- if (e.key === "ArrowLeft") {
356
- const charactersBeforeCursor = this.phoneNumber.slice(
357
- 0,
358
- cursorPosition
359
- );
360
- const numberOfNonDigitsBeforeCursor =
361
- charactersBeforeCursor.split(/\d+/).at(-1)?.length || 0;
362
- const moveLeftBy = numberOfNonDigitsBeforeCursor + 1;
363
- const newCursorPosition =
364
- cursorPosition - moveLeftBy > -1 ? cursorPosition - moveLeftBy : 0;
365
- this.phoneInput.setSelectionRange(newCursorPosition, newCursorPosition);
366
- }
367
- if (e.key === "ArrowRight") {
368
- const charactersAfterCursor = this.phoneNumber.slice(cursorPosition);
369
- const numberOfNonDigitsAfterCursor =
370
- charactersAfterCursor.split(/\d+/)[0].length || 0;
371
- const moveRightBy = numberOfNonDigitsAfterCursor + 1;
372
- const newCursorPosition =
373
- cursorPosition + moveRightBy < this.phoneNumber.length
374
- ? cursorPosition + moveRightBy
375
- : this.phoneNumber.length;
376
- this.phoneInput.setSelectionRange(newCursorPosition, newCursorPosition);
377
- }
378
- e.preventDefault();
379
- e.stopPropagation();
380
- } else {
381
- // Let browser/OS handle anything else. We'll handle any changes to the phone input in the `keyup` handler.
382
- // Could be a keyboard shortcut that modifies the input (like `Cmd/Ctrl + V`, which we'll handle in `keyup`),
383
- // or a keyboard shortcut that doesn't (like `Cmd + L` to jump to URL bar or `Cmd + R` to reload the page),
384
- // or Tab, an arrow key, etc.
385
- return;
386
- }
387
- };
388
-
389
- handlePhoneKeyup = (e: KeyboardEvent): void => {
390
- if (!e.key) {
391
- return;
392
- }
393
- // After formatting, place the cursor where it was before, defined as "before the digit that followed it before formatting, if any, otherwise at the end".
394
- // (We never want the cursor to be before a punctuation mark because the next digit typed will appear after the punctuation mark, not before.)
395
- // If we don't do this, the cursor automatically goes to the end when we set `this.phoneNumber`.
396
- // This is sometimes undesired: for example, if we've ended up here because a Mac user typed `Alt + Backspace` in the middle.
397
-
398
- // Arrow keys are intended to change the cursor position, so don't get in their way
399
- if (
400
- e.key.includes("Arrow") ||
401
- ["Meta", "Shift", "Control", "Alt"].includes(e.key)
402
- ) {
403
- return;
404
- }
405
-
406
- const cursorPosition = this.phoneInput.selectionStart;
407
- // find the numbers it's before and count backward from end after formatting
408
- const numbersAfterCursor = cursorPosition
409
- ? this.phoneInput.value.slice(cursorPosition).replace(/\D/g, "")
410
- : "";
411
- this.phoneNumber = formatToPhoneInput(this.phoneInput.value);
412
-
413
- // EXAMPLES: (123)| 4 numbersAfterCursor will be '4'.
414
- let cursorNegativeIndex = 0;
415
- let numbersLeft = numbersAfterCursor.length;
416
- while (numbersLeft) {
417
- if (this.phoneNumber.at(cursorNegativeIndex)?.match(/\d/)) {
418
- numbersLeft--;
419
- }
420
- cursorNegativeIndex++;
421
- }
422
- const cursorPositiveIndex =
423
- this.phoneInput.value.length - cursorNegativeIndex + 1;
424
- this.phoneInput.setSelectionRange(cursorPositiveIndex, cursorPositiveIndex);
425
- };
426
-
427
- onChangeEmail = (e: Event): void => {
428
- if (!e.target) {
429
- return;
430
- }
431
-
432
- this.email = (e.target as HTMLInputElement).value;
433
- };
434
-
435
- validators = {
436
- tourType: (): boolean => this.tourType !== null,
437
- dateAndTime: (): boolean => !!this.selectedDate && !!this.selectedTime,
438
- leadInfo: (): boolean => {
439
- return (
440
- (!!this.firstNameInput?.value || !!this.lastNameInput?.value) &&
441
- this.emailInput?.value.includes("@") &&
442
- // TODO: deleting phone number doesn't cause validation to fail, at least on mobile
443
- !!this.phoneNumber &&
444
- this.phoneNumber.length === 14 &&
445
- isValidPhoneNumber(this.phoneNumber)
446
- );
447
- },
448
- };
449
-
450
- formIsValidForSubmission = (): boolean => {
451
- const isValid =
452
- this.validators.tourType() &&
453
- this.validators.dateAndTime() &&
454
- this.validators.leadInfo();
455
- return isValid;
456
- };
457
-
458
- /** E.g., `timeStringToHoursAndMinutes("4:15pm")` -> `[16, 15]`
459
- */
460
- timeStringToHoursAndMinutes = (
461
- timeString: string
462
- ): [hours: number, minutes: number] => {
463
- const [hoursString, minutesString] = timeString.split(/\D/g);
464
- const hours =
465
- parseInt(hoursString) +
466
- (timeString.toLowerCase().includes("pm") ? 12 : 0);
467
- const minutes = parseInt(minutesString);
468
-
469
- return [hours, minutes];
470
- };
471
-
472
- submit = async (): Promise<void> => {
473
- if (!this.selectedDate || !this.selectedTime || this.tourType === null) {
474
- return;
475
- }
476
- const queryParams = new URLSearchParams(window.location.search);
477
-
478
- let parsedLeadSource = null;
479
- if (
480
- this.selectedLeadSource &&
481
- this.selectedLeadSource.value &&
482
- this.selectedLeadSource.value.length > 0
483
- ) {
484
- parsedLeadSource = this.selectedLeadSource.value;
485
- } else if (
486
- this.leadSourceInputValue &&
487
- this.leadSourceInputValue.length > 0
488
- ) {
489
- parsedLeadSource = this.leadSourceInputValue;
490
- } else {
491
- parsedLeadSource = this.currentLeadSource;
492
- }
493
-
494
- const leadSources = [
495
- ...new Set(
496
- parsedLeadSource
497
- ? [parsedLeadSource, "property-website"]
498
- : ["property-website"]
499
- ),
500
- ];
501
- if (this.firstNameInput) {
502
- this.firstNameInputValue = this.firstNameInput.value;
503
- }
504
- if (this.lastNameInput) {
505
- this.lastNameInputValue = this.lastNameInput.value;
506
- }
507
- this.leadSourceInputValue = parsedLeadSource;
508
- pushGtmEvent("scheduleTourSubmitted", {
509
- email: this.email,
510
- phone: `+1${this.phoneNumber.match(/\d/g)?.join("")}`,
511
- firstName: this.firstNameInput?.value ?? this.firstNameInputValue,
512
- lastName: this.lastNameInput?.value ?? this.lastNameInputValue,
513
- tourType: tourTypeForSubmission[this.tourType],
514
- tourTime: `${this.selectedTime.datetime}${this.selectedTime.offset}`,
515
- originatingSource:
516
- leadSources.find((i) => i !== "property-website") || null,
517
- });
518
- const data = {
519
- referrer: document.referrer,
520
- email_address: this.email,
521
- phone_number: `+1${this.phoneNumber.match(/\d/g)?.join("")}`, // e.g. +12125555555
522
- building_id: this.buildingId,
523
- first_name: this.firstNameInput?.value ?? this.firstNameInputValue,
524
- last_name: this.lastNameInput?.value ?? this.lastNameInputValue,
525
- tour_type: tourTypeForSubmission[this.tourType],
526
- tour_time: `${this.selectedTime.datetime}${this.selectedTime.offset}`, // e.g., "2022-06-27T09:00:00-07:00"
527
- cancel_existing_tours: this.promptForReschedule,
528
- lead_sources: [
529
- ...new Set(
530
- parsedLeadSource
531
- ? [parsedLeadSource, getDefaultLeadSourceAttribution(this.orgSlug)]
532
- : [getDefaultLeadSourceAttribution(this.orgSlug)]
533
- ),
534
- ],
535
- query_params: Object.fromEntries(queryParams.entries()),
536
- conversation_tracking_id: this.leadSourceClient?.chatId,
537
- };
538
-
539
- const url = `https://app.meetelise.com/platformApi/state/create/v2/scheduleMe`;
540
- this.isSubmitting = true;
541
- try {
542
- await axios.post(url, data, {
543
- headers: {
544
- ["building-slug"]: this.buildingSlug,
545
- ["X-SecurityKey"]: "JRL8jV4VcSCwOSir5gWkpgNLfKghmhBG",
546
- ["org-slug"]: this.orgSlug,
547
- },
548
- });
549
-
550
- this.leadSourceClient?.checkAndHandleForLogLeadSource({
551
- webchatAction: "tour-scheduler",
552
- stateId: null,
553
- });
554
- this.isSubmitting = false;
555
- this.tourIsBooked = true;
556
- } catch (e: unknown) {
557
- const typedError = e as AxiosError<{ detail: string }>;
558
- const message =
559
- typedError.response?.data?.["detail"] || "Failed to book tour";
560
- if (
561
- typedError.response &&
562
- typedError.response.headers &&
563
- typedError.response.headers[
564
- "funnel-prospect-conflicting-appointment-error"
565
- ]
566
- ) {
567
- if (this.selectedDate && this.selectedTime) {
568
- const dateAvailabilities =
569
- this.availabilitiesGroupedByDay[
570
- format(this.selectedDate, "yyyy-MM-dd")
571
- ];
572
- if (dateAvailabilities) {
573
- this.availabilitiesGroupedByDay[
574
- format(this.selectedDate, "yyyy-MM-dd")
575
- ] = dateAvailabilities.filter(
576
- (availability) => availability !== this.selectedTime
577
- );
578
- }
579
- }
580
- } else if (
581
- typedError.response?.status === 409 &&
582
- !this.promptForReschedule &&
583
- message === "User already has a tour scheduled for this building"
584
- ) {
585
- this.promptForReschedule = true;
586
- this.isSubmitting = false;
587
- this.tourIsBooked = false;
588
- return;
589
- } else if (
590
- typedError.response?.status === 409 &&
591
- !this.promptForReschedule
592
- ) {
593
- this.isSubmitting = false;
594
- this.tourIsBooked = false;
595
- resetAvailabilitiesCache();
596
- this.availabilitiesGroupedByDay = await getAvailabilitiesGroupedByDay(
597
- tourTypeMap[this.tourType],
598
- this.buildingId
599
- );
600
- alert(
601
- "This timeslot is no longer available. Please select a different time."
602
- );
603
- return;
604
- }
605
- alert(message);
606
- this.isSubmitting = false;
607
- this.tourIsBooked = false;
608
- }
609
- };
610
-
611
- static styles = [tourSchedulerStyles, InputStyles];
612
-
613
- tourTypeMenu(): TemplateResult {
614
- return html`<h2 class="journey-header">Tour Type</h2>
615
- <div id="tour-type-menu">
616
- ${this.shouldShowTourType[TourType.Self]
617
- ? html` <tour-type-option
618
- heading="Take a tour"
619
- subtitle="on your own"
620
- .primaryColor=${this.primaryColor}
621
- .backgroundColor=${this.backgroundColor}
622
- @click="${async () => {
623
- this.tourType = TourType.Self;
624
- if (
625
- this.sgtUrl &&
626
- shouldOpenTourLink(
627
- TourType.Self,
628
- this.selfGuidedToursTypeOffered
629
- )
630
- ) {
631
- window.open(this.sgtUrl, "_blank");
632
- }
633
- this.availabilitiesGroupedByDay =
634
- await getAvailabilitiesGroupedByDay(
635
- tourTypeMap[TourType.Self]
636
- );
637
- }}"
638
- @keydown="${(e: KeyboardEvent) => {
639
- if ([" ", "Enter"].includes(e.key)) {
640
- e.preventDefault();
641
- this.tourType = TourType.Self;
642
- }
643
- }}"
644
- ?selected="${this.tourType === TourType.Self}"
645
- >
646
- ${TourSelfGuidedIcon(
647
- this.tourType === TourType.Self
648
- ? this.foregroundColorOnPrimaryBackgroundColor
649
- : this.foregroundColorOnSecondaryBackgroundColor
650
- )}
651
- </tour-type-option>`
652
- : ""}
653
- ${this.shouldShowTourType[TourType.Guided]
654
- ? html` <tour-type-option
655
- heading="Guided tour"
656
- subtitle="with an agent"
657
- .primaryColor=${this.primaryColor}
658
- .backgroundColor=${this.backgroundColor}
659
- .foregroundColorOnPrimaryBackgroundColor=${this
660
- .foregroundColorOnPrimaryBackgroundColor}
661
- .foregroundColorOnSecondaryBackgroundColor=${this
662
- .foregroundColorOnSecondaryBackgroundColor}
663
- @click="${async () => {
664
- this.tourType = TourType.Guided;
665
-
666
- if (this.escortedToursLink) {
667
- window.open(this.escortedToursLink, "_blank");
668
- }
669
- this.availabilitiesGroupedByDay =
670
- await getAvailabilitiesGroupedByDay(
671
- tourTypeMap[TourType.Guided]
672
- );
673
- }}"
674
- @keydown="${(e: KeyboardEvent) => {
675
- if ([" ", "Enter"].includes(e.key)) {
676
- e.preventDefault();
677
- this.tourType = TourType.Guided;
678
- }
679
- }}"
680
- ?selected="${this.tourType === TourType.Guided}"
681
- >
682
- ${TourWithAgentIcon(
683
- this.tourType === TourType.Guided
684
- ? this.foregroundColorOnPrimaryBackgroundColor
685
- : this.foregroundColorOnSecondaryBackgroundColor
686
- )}
687
- </tour-type-option>`
688
- : ""}
689
- ${this.shouldShowTourType[TourType.Virtual]
690
- ? html` <tour-type-option
691
- heading="Virtual tour"
692
- subtitle="over video"
693
- .primaryColor=${this.primaryColor}
694
- .backgroundColor=${this.backgroundColor}
695
- @click="${async () => {
696
- this.tourType = TourType.Virtual;
697
- if (
698
- this.virtualToursLink &&
699
- shouldOpenTourLink(
700
- TourType.Virtual,
701
- this.virtualToursTypeOffered
702
- )
703
- ) {
704
- window.open(this.virtualToursLink, "_blank");
705
- }
706
- this.availabilitiesGroupedByDay =
707
- await getAvailabilitiesGroupedByDay(
708
- tourTypeMap[TourType.Virtual]
709
- );
710
- }}"
711
- @keydown="${(e: KeyboardEvent) => {
712
- if ([" ", "Enter"].includes(e.key)) {
713
- e.preventDefault();
714
- this.tourType = TourType.Virtual;
715
- }
716
- }}"
717
- ?selected="${this.tourType === TourType.Virtual}"
718
- >
719
- ${TourVirtuallyIcon(
720
- this.tourType === TourType.Virtual
721
- ? this.foregroundColorOnPrimaryBackgroundColor
722
- : this.foregroundColorOnSecondaryBackgroundColor
723
- )}
724
- </tour-type-option>`
725
- : ""}
726
- </div>`;
727
- }
728
-
729
- dateAndTimeMenu(): TemplateResult {
730
- if (
731
- this.tourType === TourType.Self &&
732
- this.sgtUrl &&
733
- shouldOpenTourLink(this.tourType, this.selfGuidedToursTypeOffered)
734
- ) {
735
- return html`<h2 class="journey-header">Date and Time</h2>
736
- <div id="dateAndTimeMenu">
737
- <button
738
- id="self-guided-redirect-bttn"
739
- @click=${() => window.open(this.sgtUrl, "_blank")}
740
- >
741
- View Self Guided Tour Times
742
- </button>
743
- </div>`;
744
- }
745
- return html`<h2 class="journey-header">Date and Time</h2>
746
- <div id="dateAndTimeMenu">
747
- <div id="datePicker">
748
- <date-picker
749
- .availabilities=${mapValues(
750
- this.availabilitiesGroupedByDay,
751
- (dates) => dates.map((date) => new Date(date.offset))
752
- )}
753
- @change=${(e: Event) => {
754
- // if the user clicked a tour type that is suppose to redirect, we redirect that use when they select a date
755
- // This can happen if the user clicks, is redirect, and then comes back to the webchat
756
- if (
757
- this.tourType === TourType.Self &&
758
- this.sgtUrl &&
759
- shouldOpenTourLink(
760
- this.tourType,
761
- this.selfGuidedToursTypeOffered
762
- )
763
- ) {
764
- window.open(this.sgtUrl, "_blank");
765
- return;
766
- }
767
- if (this.tourType === TourType.Guided && this.escortedToursLink) {
768
- window.open(this.escortedToursLink, "_blank");
769
- return;
770
- }
771
- if (
772
- this.tourType === TourType.Virtual &&
773
- this.virtualToursLink &&
774
- shouldOpenTourLink(this.tourType, this.virtualToursTypeOffered)
775
- ) {
776
- window.open(this.virtualToursLink, "_blank");
777
- return;
778
- }
779
-
780
- if (e.target instanceof DatePicker) {
781
- this.selectedDate = e.target.selectedDate;
782
- }
783
- }}
784
- ></date-picker>
785
- <div>
786
- <time-picker
787
- ?selecteddateexists=${!!this.selectedDate}
788
- .options=${this.selectedDate
789
- ? this.availabilitiesGroupedByDay[
790
- format(this.selectedDate, "y-MM-dd")
791
- ]
792
- ?.sort((a, b) =>
793
- compareAsc(parseISO(a.datetime), parseISO(b.datetime))
794
- )
795
- .map((date) => {
796
- return {
797
- dateWithTimeZoneOffset: date,
798
- displayTime: format(
799
- parseISO(`${date.datetime}${date.offset}`),
800
- "h:mmaaa"
801
- ),
802
- };
803
- })
804
- : []}
805
- @change=${(e: Event) => {
806
- if (e.target instanceof TimePicker) {
807
- if (!this.selectedDate) return;
808
- const daysAvailabilities =
809
- this.availabilitiesGroupedByDay[
810
- format(new Date(this.selectedDate), "y-MM-dd")
811
- ];
812
- const index = e.target.selectedTime
813
- ? daysAvailabilities.indexOf(
814
- e.target.selectedTime.dateWithTimeZoneOffset
815
- )
816
- : null;
817
- this.selectedTime =
818
- index !== null ? daysAvailabilities[index] : null;
819
- }
820
- }}
821
- ></time-picker>
822
- </div>
823
- </div>
824
- </div>`;
825
- }
826
-
827
- closeButton(): TemplateResult {
828
- return html` <button
829
- id="close-button"
830
- @click=${this.onCloseClicked}
831
- aria-label="Close"
832
- aria-describedby="close-button"
833
- >
834
- <svg
835
- width="19"
836
- height="19"
837
- viewBox="0 0 19 19"
838
- fill="none"
839
- xmlns="http://www.w3.org/2000/svg"
840
- >
841
- <line
842
- x1="0.986863"
843
- y1="18.2746"
844
- x2="18.2929"
845
- y2="0.968593"
846
- stroke="#202020"
847
- stroke-width="2"
848
- />
849
- <path
850
- d="M1.01394 0.999997L18.0103 18.0243"
851
- stroke="#202020"
852
- stroke-width="2"
853
- />
854
- </svg>
855
- </button>`;
856
- }
857
-
858
- mobilePages = [
859
- {
860
- validate: this.validators.tourType,
861
- nextButtonText: "Next",
862
- nextButtonAction: (): void => {
863
- this.mobilePageIndex++;
864
- },
865
- render: (): TemplateResult => {
866
- return html`${this.tourTypeMenu()}`;
867
- },
868
- },
869
- {
870
- validate: this.validators.dateAndTime,
871
- nextButtonText: "Next",
872
- nextButtonAction: (): void => {
873
- this.mobilePageIndex++;
874
- },
875
- render: (): TemplateResult => {
876
- return html`${this.dateAndTimeMenu()}`;
877
- },
878
- },
879
- {
880
- validate: (): boolean => this.validators.leadInfo(),
881
- // last page gets <action-confirm-button> instead of the regular button
882
- nextButtonText: null,
883
- renderNextButton: (): TemplateResult => html` <action-confirm-button
884
- id="schedule-bttn"
885
- .onClick=${this.submit}
886
- .isLoading=${this.isSubmitting}
887
- height="50px"
888
- width="145px"
889
- text="Schedule tour"
890
- ?disabled=${!this.formIsValidForSubmission()}
891
- ></action-confirm-button>`,
892
- nextButtonAction: null,
893
- render: (): TemplateResult => {
894
- return html`${this.userInfoAndLayoutMenu()}`;
895
- },
896
- },
897
- ];
898
-
899
- userInfoAndLayoutMenu(): TemplateResult {
900
- return html`<h2 class="journey-header">Your Information</h2>
901
- <div id="yourInformationMenu">
902
- <div id="namesWrapper">
903
- <div class="nameContainer" id="firstName">
904
- <input
905
- class=${classMap({
906
- ["webchat-input"]: true,
907
- ["nameInput"]: true,
908
- ["webchat-font__desktop"]: !isMobile(),
909
- ["webchat-font__mobile"]: isMobile(),
910
- })}
911
- type="text"
912
- placeholder="First name"
913
- name="firstName"
914
- autocomplete="given-name"
915
- @input=${() => this.requestUpdate()}
916
- />
917
- </div>
918
- <div class="nameContainer" id="lastName">
919
- <input
920
- class=${classMap({
921
- ["webchat-input"]: true,
922
- ["nameInput"]: true,
923
- ["webchat-font__desktop"]: !isMobile(),
924
- ["webchat-font__mobile"]: isMobile(),
925
- })}
926
- type="text"
927
- placeholder="Last name"
928
- name="lastName"
929
- autocomplete="family-name"
930
- @input=${() => this.requestUpdate()}
931
- />
932
- </div>
933
- </div>
934
-
935
- <div class="inputContainer" id="email">
936
- <input
937
- class=${classMap({
938
- ["webchat-input"]: true,
939
- ["webchat-font__desktop"]: !isMobile(),
940
- ["webchat-font__mobile"]: isMobile(),
941
- })}
942
- type="email"
943
- inputmode="email"
944
- placeholder="Email"
945
- name="email"
946
- autocomplete="email"
947
- .value=${this.email}
948
- @input=${this.onChangeEmail}
949
- />
950
- </div>
951
- <div class="inputContainer" id="phone">
952
- <input
953
- class=${classMap({
954
- ["webchat-input"]: true,
955
- ["webchat-font__desktop"]: !isMobile(),
956
- ["webchat-font__mobile"]: isMobile(),
957
- ["webchat-input__error"]:
958
- this.phoneNumber.length === 14 &&
959
- !isValidPhoneNumber(this.phoneNumber),
960
- })}
961
- type="tel"
962
- inputmode="tel"
963
- placeholder="Phone"
964
- name="phone"
965
- autocomplete="tel-national"
966
- maxlength="14"
967
- .value=${this.phoneNumber}
968
- @keydown=${this.handlePhoneKeydown}
969
- @keyup=${this.handlePhoneKeyup}
970
- @input=${(e: Event) => {
971
- if (!e.target) {
972
- return;
973
- }
974
- this.phoneNumber = formatToPhoneInput(
975
- (e.target as HTMLInputElement).value
976
- );
977
- }}
978
- />
979
- ${this.phoneNumber.length === 14 &&
980
- !isValidPhoneNumber(this.phoneNumber)
981
- ? html`<p class="error-message">Invalid phone number</p>`
982
- : ""}
983
- </div>
984
- ${this.leadSources.length > 0 &&
985
- (this.featureFlagShowDropdown === FeatureFlagsShowDropdown.always ||
986
- (this.featureFlagShowDropdown ===
987
- FeatureFlagsShowDropdown.onAttributionFailure &&
988
- this.currentLeadSource.length === 0))
989
- ? html` <me-select
990
- id="leadSource"
991
- value="${this.currentLeadSource}"
992
- placeholder="How did you hear about us?"
993
- .options="${this.leadSources.map((i) => ({
994
- label: i,
995
- value: i,
996
- }))}"
997
- @change=${() => {
998
- this.requestUpdate();
999
- }}
1000
- >
1001
- </me-select>`
1002
- : ""}
1003
- </div> `;
1004
- }
1005
-
1006
- confirmationMessage(): TemplateResult {
1007
- if (!this.selectedDate || !this.selectedTime || this.tourType === null)
1008
- return html``;
1009
- // format example: "November 9th, 2022 at 11:00pm"
1010
- const readableDateAndTime = format(
1011
- parseISO(`${this.selectedTime.datetime}${this.selectedTime.offset}`),
1012
- "h:mmaaa"
1013
- );
1014
-
1015
- if (this.canceledReschedule) {
1016
- return html`
1017
- <div id="confirmationMessage">
1018
- <svg
1019
- width="20"
1020
- height="20"
1021
- viewBox="0 0 20 20"
1022
- fill="none"
1023
- xmlns="http://www.w3.org/2000/svg"
1024
- >
1025
- <path
1026
- d="M7 0V2H13V0H15V2H19C19.2652 2 19.5196 2.10536 19.7071 2.29289C19.8946 2.48043 20 2.73478 20 3V19C20 19.2652 19.8946 19.5196 19.7071 19.7071C19.5196 19.8946 19.2652 20 19 20H1C0.734784 20 0.48043 19.8946 0.292893 19.7071C0.105357 19.5196 0 19.2652 0 19V3C0 2.73478 0.105357 2.48043 0.292893 2.29289C0.48043 2.10536 0.734784 2 1 2H5V0H7ZM18 9H2V18H18V9ZM13.036 10.136L14.45 11.55L9.5 16.5L5.964 12.964L7.38 11.55L9.501 13.672L13.037 10.136H13.036ZM5 4H2V7H18V4H15V5H13V4H7V5H5V4Z"
1027
- fill="#202020"
1028
- />
1029
- </svg>
1030
- <p>Thank you!</p>
1031
- <p>We'll see you at your originally schedule tour time.</p>
1032
- </div>
1033
- `;
1034
- }
1035
-
1036
- return html`
1037
- <div id="confirmationMessage">
1038
- <svg
1039
- width="20"
1040
- height="20"
1041
- viewBox="0 0 20 20"
1042
- fill="none"
1043
- xmlns="http://www.w3.org/2000/svg"
1044
- >
1045
- <path
1046
- d="M7 0V2H13V0H15V2H19C19.2652 2 19.5196 2.10536 19.7071 2.29289C19.8946 2.48043 20 2.73478 20 3V19C20 19.2652 19.8946 19.5196 19.7071 19.7071C19.5196 19.8946 19.2652 20 19 20H1C0.734784 20 0.48043 19.8946 0.292893 19.7071C0.105357 19.5196 0 19.2652 0 19V3C0 2.73478 0.105357 2.48043 0.292893 2.29289C0.48043 2.10536 0.734784 2 1 2H5V0H7ZM18 9H2V18H18V9ZM13.036 10.136L14.45 11.55L9.5 16.5L5.964 12.964L7.38 11.55L9.501 13.672L13.037 10.136H13.036ZM5 4H2V7H18V4H15V5H13V4H7V5H5V4Z"
1047
- fill="#202020"
1048
- />
1049
- </svg>
1050
- <p>Thank you!</p>
1051
- <p>
1052
- Your
1053
- ${{
1054
- [TourType.Guided]: "guided",
1055
- [TourType.Self]: "self-guided",
1056
- [TourType.Virtual]: "virtual",
1057
- }[this.tourType]}
1058
- tour is
1059
- ${this.promptForReschedule ? html`rescheduled` : html`scheduled`} for
1060
- ${readableDateAndTime}.
1061
- </p>
1062
- <p>
1063
- Look for an email confirmation along with instructions and directions.
1064
- </p>
1065
- <p>You can make changes at any time, just reply to the email.</p>
1066
- </div>
1067
- `;
1068
- }
1069
-
1070
- loadingIcon(size = 21): TemplateResult {
1071
- return html` <svg
1072
- id="loadingIcon"
1073
- width=${size}
1074
- height=${size}
1075
- viewBox="0 0 21 21"
1076
- fill="none"
1077
- xmlns="http://www.w3.org/2000/svg"
1078
- >
1079
- <path
1080
- d="M17.835 13.1045C18.4839 11.5628 18.6332 9.85647 18.2621 8.22548C17.8909 6.5945 17.018 5.12084 15.7659 4.0117C14.5139 2.90256 12.9457 2.21372 11.2818 2.04201C9.618 1.87031 7.94218 2.22438 6.49 3.05445L5.498 1.31745C7.01563 0.450066 8.73419 -0.00418222 10.4822 2.90165e-05C12.2302 0.00424025 13.9466 0.466764 15.46 1.34145C19.95 3.93345 21.67 9.48345 19.577 14.1115L20.919 14.8855L16.754 17.0995L16.589 12.3855L17.835 13.1045ZM3.085 6.89845C2.43614 8.44015 2.28678 10.1464 2.65792 11.7774C3.02905 13.4084 3.90201 14.8821 5.15407 15.9912C6.40613 17.1003 7.97432 17.7892 9.63816 17.9609C11.302 18.1326 12.9778 17.7785 14.43 16.9485L15.422 18.6855C13.9044 19.5528 12.1858 20.0071 10.4378 20.0029C8.68979 19.9987 6.97344 19.5361 5.46 18.6615C0.97 16.0695 -0.75 10.5195 1.343 5.89145L0 5.11845L4.165 2.90445L4.33 7.61845L3.084 6.89945L3.085 6.89845Z"
1081
- fill="#1E1E1E"
1082
- />
1083
- </svg>`;
1084
- }
1085
-
1086
- render(): TemplateResult {
1087
- const isLoading =
1088
- this.waitingForAvailabilities || this.shouldAllowScheduleLoading;
1089
- if (!this.shouldAllowScheduling && !isLoading) {
1090
- return html` <div
1091
- id="tour-scheduler-inner-form"
1092
- class="${classnames({
1093
- "tour-scheduler-full": !this.compactDesign && !isMobile(),
1094
- "tour-scheduler-compact": this.compactDesign && !isMobile(),
1095
- "tour-scheduler-mobile": isMobile(),
1096
- })}"
1097
- >
1098
- <div id="top-header">
1099
- <div></div>
1100
- ${this.closeButton()}
1101
- </div>
1102
- <div class="center-tour-not-avail">
1103
- <h1>Sorry, there are currently no tour availabilities</h1>
1104
- <p>Please check back again later</p>
1105
- </div>
1106
- </div>`;
1107
- }
1108
- if (isLoading) {
1109
- return html` <div
1110
- id="tour-scheduler-inner-form"
1111
- class="${classnames({
1112
- "tour-scheduler-full": !this.compactDesign && !isMobile(),
1113
- "tour-scheduler-compact": this.compactDesign && !isMobile(),
1114
- "tour-scheduler-mobile": isMobile(),
1115
- })}"
1116
- >
1117
- <div class="center-tour-not-avail">
1118
- <h1>Searching for availabilities...</h1>
1119
- <div class="loading-entire-tour-icon">${this.loadingIcon(48)}</div>
1120
- </div>
1121
- </div>`;
1122
- }
1123
- if (this.errorGettingAvailabilities) {
1124
- if (this.buildingId === 123519) {
1125
- // https://meetelise.zendesk.com/agent/tickets/94824
1126
- return html` <div
1127
- class="${classnames({
1128
- "tour-scheduler-full": !this.compactDesign && !isMobile(),
1129
- "tour-scheduler-compact": this.compactDesign && !isMobile(),
1130
- "tour-scheduler-mobile": isMobile(),
1131
- })}"
1132
- >
1133
- <div id="top-header">
1134
- <div></div>
1135
- ${this.closeButton()}
1136
- </div>
1137
- <div class="center-tour-not-avail">
1138
- <div>
1139
- <p>
1140
- Tours are by appointment only. Please call our leasing office at
1141
- (844) 779-7491 to schedule your tour!"
1142
- </p>
1143
- </div>
1144
- </div>
1145
- </div>`;
1146
- }
1147
- return html` <div
1148
- class="${classnames({
1149
- "tour-scheduler-full": !this.compactDesign && !isMobile(),
1150
- "tour-scheduler-compact": this.compactDesign && !isMobile(),
1151
- "tour-scheduler-mobile": isMobile(),
1152
- })}"
1153
- >
1154
- <div id="top-header">
1155
- <div></div>
1156
- ${this.closeButton()}
1157
- </div>
1158
- <div class="center-tour-not-avail">
1159
- <div>
1160
- <p>Sorry, there are currently no tour availabilities!</p>
1161
- <p>
1162
- We apologize, but there are currently no tours available. This
1163
- could be due to all slots being filled, off-season periods, or
1164
- maintenance.
1165
- </p>
1166
- <p>
1167
- We understand that this may be disappointing and we apologize for
1168
- any inconvenience. We recommend checking back soon as our schedule
1169
- frequently updates.
1170
- </p>
1171
- <p>
1172
- In the meantime, feel free to explore our website for other
1173
- information and attractions. Thank you for your understanding and
1174
- patience!
1175
- </p>
1176
- </div>
1177
- </div>
1178
- </div>`;
1179
- }
1180
- if (!isMobile()) {
1181
- return html`
1182
- <div
1183
- class="${classnames({
1184
- "tour-scheduler-full": !this.compactDesign,
1185
- "tour-scheduler-compact": this.compactDesign,
1186
- loading: isLoading,
1187
- })}"
1188
- @leadsource="${(e: CustomEvent) =>
1189
- (this.selectedLeadSource = e.detail.selectedLeadSource)}"
1190
- >
1191
- <div id="top-header">
1192
- <h1 id="tour-header-title">
1193
- ${isLoading
1194
- ? html`${this.loadingIcon()} Searching availabilities...`
1195
- : "Schedule a Tour"}
1196
- </h1>
1197
- ${this.closeButton()}
1198
- </div>
1199
-
1200
- ${this.tourIsBooked || this.canceledReschedule
1201
- ? html`
1202
- <div class="tour-scheduler">${this.confirmationMessage()}</div>
1203
- `
1204
- : this.promptForReschedule
1205
- ? html`
1206
- <div id="scheduler-container">
1207
- <div>
1208
- <h2 class="journey-header">Reschedule Tour</h2>
1209
- <p class="explanation">
1210
- You already have a tour scheduled. Would you like to
1211
- reschedule?
1212
- </p>
1213
- </div>
1214
- </div>
1215
- <div id="tour-scheduler-footer">
1216
- <p class="explanation">
1217
- We'll send a confirmation and any follow-ups to your email
1218
- address, please reply to the email to make any appointment
1219
- changes.
1220
- ${disclaimer({
1221
- buildingName: this.buildingName,
1222
- phoneNumberInput: this.phoneInput?.value,
1223
- emailInput: this.emailInput?.value,
1224
- orgLegalName: this.orgLegalName,
1225
- orgSlug: this.orgSlug,
1226
- })}
1227
- </p>
1228
-
1229
- <div class="reschedule-buttons-wrapper">
1230
- <action-confirm-button
1231
- id="cancel-reschedule-bttn"
1232
- .onClick=${() => {
1233
- this.canceledReschedule = true;
1234
- }}
1235
- .isLoading=${this.isSubmitting}
1236
- height="50px"
1237
- width="145px"
1238
- text="Cancel"
1239
- ?disabled=${!this.formIsValidForSubmission()}
1240
- ></action-confirm-button>
1241
- <action-confirm-button
1242
- id="reschedule-button"
1243
- .onClick=${this.submit}
1244
- .isLoading=${this.isSubmitting}
1245
- height="50px"
1246
- width="145px"
1247
- text="Reschedule"
1248
- ?disabled=${!this.formIsValidForSubmission()}
1249
- ></action-confirm-button>
1250
- </div>
1251
- </div>
1252
- `
1253
- : html`
1254
- <div id="scheduler-container">
1255
- <div id="book-tour-journey-items">
1256
- <div id="tour-type-menu-outer-container">
1257
- ${this.tourTypeMenu()}
1258
- </div>
1259
- <div id="date-and-time-menu-outer-container">
1260
- ${this.dateAndTimeMenu()}
1261
- </div>
1262
-
1263
- <div id="user-info-and-layout-menu-outer-container">
1264
- ${this.userInfoAndLayoutMenu()}
1265
- </div>
1266
- </div>
1267
- </div>
1268
- <div id="tour-scheduler-footer">
1269
- <p class="explanation">
1270
- We'll send a confirmation and any follow-ups to your email
1271
- address, please reply to the email to make any appointment
1272
- changes.
1273
- ${disclaimer({
1274
- buildingName: this.buildingName,
1275
- phoneNumberInput: this.phoneInput?.value,
1276
- emailInput: this.emailInput?.value,
1277
- orgLegalName: this.orgLegalName,
1278
- orgSlug: this.orgSlug,
1279
- })}
1280
- </p>
1281
-
1282
- <action-confirm-button
1283
- id="schedule-bttn"
1284
- .onClick=${this.submit}
1285
- .isLoading=${this.isSubmitting}
1286
- height="50px"
1287
- width="145px"
1288
- text="Schedule tour"
1289
- ?disabled=${!this.formIsValidForSubmission()}
1290
- ></action-confirm-button>
1291
- </div>
1292
- `}
1293
- </div>
1294
- `;
1295
- } else {
1296
- const currentPage = this.mobilePages[this.mobilePageIndex];
1297
- return html`
1298
- <div
1299
- class="${classnames("tour-scheduler-mobile", {
1300
- loading: isLoading,
1301
- })}"
1302
- >
1303
- <div id="top-header">
1304
- <h1 id="scheduleATour">
1305
- ${isLoading
1306
- ? html`${this.loadingIcon()} Searching availabilities...`
1307
- : "Schedule a tour"}
1308
- </h1>
1309
- ${this.closeButton()}
1310
- </div>
1311
- <div id="mobile-body-container">
1312
- ${this.canceledReschedule
1313
- ? html`
1314
- <div id="confirmationMessage">
1315
- <svg
1316
- width="20"
1317
- height="20"
1318
- viewBox="0 0 20 20"
1319
- fill="none"
1320
- xmlns="http://www.w3.org/2000/svg"
1321
- >
1322
- <path
1323
- d="M7 0V2H13V0H15V2H19C19.2652 2 19.5196 2.10536 19.7071 2.29289C19.8946 2.48043 20 2.73478 20 3V19C20 19.2652 19.8946 19.5196 19.7071 19.7071C19.5196 19.8946 19.2652 20 19 20H1C0.734784 20 0.48043 19.8946 0.292893 19.7071C0.105357 19.5196 0 19.2652 0 19V3C0 2.73478 0.105357 2.48043 0.292893 2.29289C0.48043 2.10536 0.734784 2 1 2H5V0H7ZM18 9H2V18H18V9ZM13.036 10.136L14.45 11.55L9.5 16.5L5.964 12.964L7.38 11.55L9.501 13.672L13.037 10.136H13.036ZM5 4H2V7H18V4H15V5H13V4H7V5H5V4Z"
1324
- fill="#202020"
1325
- />
1326
- </svg>
1327
- <p>Thank you!</p>
1328
- <p>We'll see you at your originally schedule tour time.</p>
1329
- </div>
1330
- `
1331
- : this.tourIsBooked
1332
- ? this.confirmationMessage()
1333
- : this.promptForReschedule
1334
- ? html` <div id="scheduler-container">
1335
- <div>
1336
- <h2 class="journey-header">Reschedule Tour</h2>
1337
- <p class="explanation">
1338
- You already have a tour scheduled. Would you like to
1339
- reschedule?
1340
- </p>
1341
- </div>
1342
- </div>
1343
- <div id="tour-scheduler-footer">
1344
- <div class="reschedule-buttons-wrapper">
1345
- <action-confirm-button
1346
- id="cancel-reschedule-bttn"
1347
- .onClick=${() => {
1348
- this.canceledReschedule = true;
1349
- }}
1350
- .isLoading=${this.isSubmitting}
1351
- height="50px"
1352
- width="145px"
1353
- text="Cancel"
1354
- ?disabled=${!this.formIsValidForSubmission()}
1355
- ></action-confirm-button>
1356
- <action-confirm-button
1357
- id="reschedule-button"
1358
- .onClick=${this.submit}
1359
- .isLoading=${this.isSubmitting}
1360
- height="50px"
1361
- width="145px"
1362
- text="Reschedule"
1363
- ?disabled=${!this.formIsValidForSubmission()}
1364
- ></action-confirm-button>
1365
- </div>
1366
- </div>`
1367
- : html` ${currentPage.render()}
1368
- ${!currentPage.renderNextButton
1369
- ? html` <button
1370
- id="mobile-next-bttn"
1371
- @click=${currentPage.nextButtonAction}
1372
- ?disabled=${(() => {
1373
- return !currentPage.validate() || isLoading;
1374
- })()}
1375
- >
1376
- ${currentPage.nextButtonText}
1377
- </button>`
1378
- : currentPage.renderNextButton()}`}
1379
- ${this.mobilePageIndex + 1 === this.mobilePages.length
1380
- ? html`
1381
- ${disclaimer({
1382
- buildingName: this.buildingName,
1383
- phoneNumberInput: this.phoneInput?.value,
1384
- emailInput: this.emailInput?.value,
1385
- orgLegalName: this.orgLegalName,
1386
- orgSlug: this.orgSlug,
1387
- })}
1388
- `
1389
- : html``}
1390
- </div>
1391
- </div>
1392
- `;
1393
- }
1394
- }
1395
- }
1396
-
1397
- export enum TourType {
1398
- Guided = "guided",
1399
- Self = "self",
1400
- Virtual = "virtual",
1401
- }
1402
-
1403
- const tourTypeMap = {
1404
- [TourType.Guided]:
1405
- TourAvailabilityResponseRankOrderedSupportedTourTypesEnum.WithAgent,
1406
- [TourType.Self]:
1407
- TourAvailabilityResponseRankOrderedSupportedTourTypesEnum.SelfGuided,
1408
- [TourType.Virtual]:
1409
- TourAvailabilityResponseRankOrderedSupportedTourTypesEnum.VirtualShowing,
1410
- };
1411
-
1412
- const tourTypeForSubmission = {
1413
- [TourType.Guided]: "escorted-tour",
1414
- [TourType.Self]: "self-guided-tour",
1415
- [TourType.Virtual]: "live-virtual-tour",
1416
- };