@meetelise/chat 1.30.0 → 1.30.2

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 (228) hide show
  1. package/dist/src/MyPubnub.d.ts +116 -0
  2. package/dist/src/WebComponent/FeeCalculator/components/addon-item/addon-item-styles.d.ts +2 -0
  3. package/dist/src/WebComponent/FeeCalculator/components/addon-item/addon-item.d.ts +22 -0
  4. package/dist/src/WebComponent/FeeCalculator/components/addon-item/index.d.ts +1 -0
  5. package/dist/src/WebComponent/FeeCalculator/components/fee-calculator-layout/fee-calculator-layout-styles.d.ts +2 -0
  6. package/dist/src/WebComponent/FeeCalculator/components/fee-calculator-layout/fee-calculator-layout.d.ts +34 -0
  7. package/dist/src/WebComponent/FeeCalculator/components/fee-card/fee-card-styles.d.ts +2 -0
  8. package/dist/src/WebComponent/FeeCalculator/components/fee-card/fee-card.d.ts +21 -0
  9. package/dist/src/WebComponent/FeeCalculator/components/fee-item/fee-item-styles.d.ts +2 -0
  10. package/dist/src/WebComponent/FeeCalculator/components/fee-item/fee-item.d.ts +13 -0
  11. package/dist/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector-styles.d.ts +2 -0
  12. package/dist/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector.d.ts +33 -0
  13. package/dist/src/WebComponent/FeeCalculator/components/floorplan-image-card/floorplan-image-card-styles.d.ts +2 -0
  14. package/dist/src/WebComponent/FeeCalculator/components/floorplan-image-card/floorplan-image-card.d.ts +18 -0
  15. package/dist/src/WebComponent/FeeCalculator/components/index.d.ts +5 -0
  16. package/dist/src/WebComponent/FeeCalculator/components/promo-card/promo-card-styles.d.ts +2 -0
  17. package/dist/src/WebComponent/FeeCalculator/components/promo-card/promo-card.d.ts +13 -0
  18. package/dist/src/WebComponent/FeeCalculator/constants.d.ts +2 -0
  19. package/dist/src/WebComponent/FeeCalculator/fee-calculator-styles.d.ts +1 -0
  20. package/dist/src/WebComponent/FeeCalculator/fee-calculator.d.ts +59 -0
  21. package/dist/src/WebComponent/FeeCalculator/index.d.ts +2 -0
  22. package/dist/src/WebComponent/FeeCalculator/model/building-fee.d.ts +80 -0
  23. package/dist/src/WebComponent/FeeCalculator/model/transaction-category.d.ts +23 -0
  24. package/dist/src/WebComponent/LeadSourceClient.d.ts +46 -0
  25. package/dist/src/WebComponent/OfficeHours.d.ts +21 -0
  26. package/dist/src/WebComponent/Scheduler/date-picker.d.ts +28 -0
  27. package/dist/src/WebComponent/Scheduler/time-picker.d.ts +14 -0
  28. package/dist/src/WebComponent/Scheduler/tour-scheduler.d.ts +100 -0
  29. package/dist/src/WebComponent/Scheduler/tour-type-option.d.ts +13 -0
  30. package/dist/src/WebComponent/Scheduler/tourSchedulerStyles.d.ts +1 -0
  31. package/dist/src/WebComponent/actions/InputStyles.d.ts +1 -0
  32. package/dist/src/WebComponent/actions/action-confirm-button.d.ts +13 -0
  33. package/dist/src/WebComponent/actions/call-us-window.d.ts +37 -0
  34. package/dist/src/WebComponent/actions/collapse-expand-button.d.ts +8 -0
  35. package/dist/src/WebComponent/actions/details-window.d.ts +14 -0
  36. package/dist/src/WebComponent/actions/email-us-window.d.ts +46 -0
  37. package/dist/src/WebComponent/actions/formatPhoneNumber.d.ts +17 -0
  38. package/dist/src/WebComponent/actions/minimize-expand-button.d.ts +8 -0
  39. package/dist/src/WebComponent/chat-additional-actions.d.ts +28 -0
  40. package/dist/src/WebComponent/health-chat.d.ts +47 -0
  41. package/dist/src/WebComponent/healthchat-styles.d.ts +1 -0
  42. package/dist/src/WebComponent/icons/ApplyOutlineIcon.d.ts +2 -0
  43. package/dist/src/WebComponent/icons/BookTourOutlineIcon.d.ts +2 -0
  44. package/dist/src/WebComponent/icons/CalculatorOutlineIcon.d.ts +2 -0
  45. package/dist/src/WebComponent/icons/ChatOutlineIcon.d.ts +2 -0
  46. package/dist/src/WebComponent/icons/ChevronLeftIcon.d.ts +2 -0
  47. package/dist/src/WebComponent/icons/ChevronRightIcon.d.ts +2 -0
  48. package/dist/src/WebComponent/icons/ContactResidentIcon.d.ts +2 -0
  49. package/dist/src/WebComponent/icons/DollarOutlineIcon.d.ts +3 -0
  50. package/dist/src/WebComponent/icons/EmailOutlineIcon.d.ts +2 -0
  51. package/dist/src/WebComponent/icons/HeyThereEmojiIcon.d.ts +2 -0
  52. package/dist/src/WebComponent/icons/PhoneOutlineIcon.d.ts +2 -0
  53. package/dist/src/WebComponent/icons/SendMessageIcon.d.ts +3 -0
  54. package/dist/src/WebComponent/icons/TourSelfGuidedIcon.d.ts +2 -0
  55. package/dist/src/WebComponent/icons/TourVirtuallyIcon.d.ts +2 -0
  56. package/dist/src/WebComponent/icons/TourWithAgentIcon.d.ts +2 -0
  57. package/dist/src/WebComponent/icons/XOutlineIcon.d.ts +2 -0
  58. package/dist/src/WebComponent/index.d.ts +2 -0
  59. package/dist/src/WebComponent/launcher/Launcher.d.ts +98 -0
  60. package/dist/src/WebComponent/launcher/launcherStyles.d.ts +1 -0
  61. package/dist/src/WebComponent/launcher/mobile-launcher.d.ts +27 -0
  62. package/dist/src/WebComponent/launcher/typeEmojiStyles.d.ts +1 -0
  63. package/dist/src/WebComponent/launcher/typeMiniStyles.d.ts +1 -0
  64. package/dist/src/WebComponent/launcher/typeMobileStyles.d.ts +1 -0
  65. package/dist/src/WebComponent/leasing-chat-styles.d.ts +1 -0
  66. package/dist/src/WebComponent/me-chat.d.ts +91 -0
  67. package/dist/src/WebComponent/me-select.d.ts +24 -0
  68. package/dist/src/WebComponent/mega-loader.d.ts +7 -0
  69. package/dist/src/WebComponent/mini-loader.d.ts +5 -0
  70. package/dist/src/WebComponent/pubnub-chat-styles.d.ts +1 -0
  71. package/dist/src/WebComponent/pubnub-chat.d.ts +49 -0
  72. package/dist/src/WebComponent/pubnub-media.d.ts +14 -0
  73. package/dist/src/WebComponent/pubnub-message-styles.d.ts +1 -0
  74. package/dist/src/WebComponent/pubnub-message.d.ts +39 -0
  75. package/dist/src/WebComponent/simple-launcher/simple-launcher-styles.d.ts +1 -0
  76. package/dist/src/WebComponent/simple-launcher/simple-launcher.d.ts +12 -0
  77. package/dist/src/WebComponent/utilities-chat.d.ts +47 -0
  78. package/dist/src/WebComponent/utilities-styles.d.ts +1 -0
  79. package/dist/src/WebComponent/utils.d.ts +31 -0
  80. package/dist/src/analytics.d.ts +64 -0
  81. package/dist/src/disclaimers.d.ts +8 -0
  82. package/dist/src/fetchBuildingABTestType.d.ts +8 -0
  83. package/dist/src/fetchBuildingInfo.d.ts +57 -0
  84. package/dist/src/fetchBuildingWebchatView.d.ts +123 -0
  85. package/dist/src/fetchFeatureFlag.d.ts +14 -0
  86. package/dist/src/fetchLeadSources.d.ts +4 -0
  87. package/dist/src/fetchPhoneNumberFromSource.d.ts +6 -0
  88. package/dist/src/getAvailabilities.d.ts +45 -0
  89. package/dist/src/getBuildingPhoneNumber.d.ts +1 -0
  90. package/dist/src/getShouldAllowScheduling.d.ts +1 -0
  91. package/dist/src/getShouldShowWebchat.d.ts +3 -0
  92. package/dist/src/getTimezoneString.d.ts +1 -0
  93. package/dist/src/globals.d.ts +1 -0
  94. package/dist/src/gtm.d.ts +6 -0
  95. package/dist/src/handleChatId.d.ts +11 -0
  96. package/dist/src/insertDNIIntoWebsite.d.ts +5 -0
  97. package/dist/src/insertLeadSourceIntoSchedulerLinks.d.ts +4 -0
  98. package/dist/src/main/MEChat.d.ts +74 -0
  99. package/dist/src/main/utils.d.ts +2 -0
  100. package/dist/src/postLeadSources.d.ts +3 -0
  101. package/dist/src/rentgrata.d.ts +4 -0
  102. package/dist/src/replaceSelectButtonsWithNewLink.d.ts +5 -0
  103. package/dist/src/services/fees/calculateQuote.d.ts +53 -0
  104. package/dist/src/services/fees/fetchBuildingFees.d.ts +24 -0
  105. package/dist/src/services/fees/fetchBuildingFloorplans.d.ts +21 -0
  106. package/dist/src/services/fees/utils.d.ts +1 -0
  107. package/dist/src/svgIcons.d.ts +5 -0
  108. package/dist/src/themes.d.ts +5 -0
  109. package/dist/src/types/rest-sdk.types.d.ts +11 -0
  110. package/dist/src/types/webchat-no-show-reason.d.ts +1 -0
  111. package/dist/src/utils.d.ts +13 -0
  112. package/package.json +1 -1
  113. package/public/dist/index.js +2 -3
  114. package/src/MyPubnub.ts +792 -0
  115. package/src/WebComponent/FeeCalculator/components/addon-item/addon-item-styles.ts +79 -0
  116. package/src/WebComponent/FeeCalculator/components/addon-item/addon-item.ts +121 -0
  117. package/src/WebComponent/FeeCalculator/components/addon-item/index.ts +1 -0
  118. package/src/WebComponent/FeeCalculator/components/fee-calculator-layout/fee-calculator-layout-styles.ts +126 -0
  119. package/src/WebComponent/FeeCalculator/components/fee-calculator-layout/fee-calculator-layout.ts +205 -0
  120. package/src/WebComponent/FeeCalculator/components/fee-card/fee-card-styles.ts +65 -0
  121. package/src/WebComponent/FeeCalculator/components/fee-card/fee-card.ts +91 -0
  122. package/src/WebComponent/FeeCalculator/components/fee-item/fee-item-styles.ts +44 -0
  123. package/src/WebComponent/FeeCalculator/components/fee-item/fee-item.ts +38 -0
  124. package/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector-styles.ts +144 -0
  125. package/src/WebComponent/FeeCalculator/components/floor-plan-selector/floor-plan-selector.ts +241 -0
  126. package/src/WebComponent/FeeCalculator/components/floorplan-image-card/floorplan-image-card-styles.ts +74 -0
  127. package/src/WebComponent/FeeCalculator/components/floorplan-image-card/floorplan-image-card.ts +72 -0
  128. package/src/WebComponent/FeeCalculator/components/index.ts +5 -0
  129. package/src/WebComponent/FeeCalculator/components/promo-card/promo-card-styles.ts +39 -0
  130. package/src/WebComponent/FeeCalculator/components/promo-card/promo-card.ts +39 -0
  131. package/src/WebComponent/FeeCalculator/constants.ts +3 -0
  132. package/src/WebComponent/FeeCalculator/fee-calculator-styles.ts +334 -0
  133. package/src/WebComponent/FeeCalculator/fee-calculator.ts +369 -0
  134. package/src/WebComponent/FeeCalculator/index.ts +4 -0
  135. package/src/WebComponent/FeeCalculator/model/building-fee.ts +124 -0
  136. package/src/WebComponent/FeeCalculator/model/transaction-category.ts +23 -0
  137. package/src/WebComponent/LeadSourceClient.ts +332 -0
  138. package/src/WebComponent/MEChat.css +5 -0
  139. package/src/WebComponent/OfficeHours.ts +73 -0
  140. package/src/WebComponent/Scheduler/date-picker.ts +405 -0
  141. package/src/WebComponent/Scheduler/time-picker.ts +190 -0
  142. package/src/WebComponent/Scheduler/tour-scheduler.ts +1373 -0
  143. package/src/WebComponent/Scheduler/tour-type-option.ts +112 -0
  144. package/src/WebComponent/Scheduler/tourSchedulerStyles.ts +418 -0
  145. package/src/WebComponent/actions/InputStyles.ts +57 -0
  146. package/src/WebComponent/actions/action-confirm-button.ts +125 -0
  147. package/src/WebComponent/actions/call-us-window.ts +445 -0
  148. package/src/WebComponent/actions/collapse-expand-button.ts +65 -0
  149. package/src/WebComponent/actions/details-window.ts +150 -0
  150. package/src/WebComponent/actions/email-us-window.ts +555 -0
  151. package/src/WebComponent/actions/formatPhoneNumber.ts +72 -0
  152. package/src/WebComponent/actions/minimize-expand-button.ts +93 -0
  153. package/src/WebComponent/chat-additional-actions.ts +135 -0
  154. package/src/WebComponent/health-chat.ts +270 -0
  155. package/src/WebComponent/healthchat-styles.ts +119 -0
  156. package/src/WebComponent/icons/ApplyOutlineIcon.ts +22 -0
  157. package/src/WebComponent/icons/BookTourOutlineIcon.ts +13 -0
  158. package/src/WebComponent/icons/CalculatorOutlineIcon.ts +22 -0
  159. package/src/WebComponent/icons/ChatOutlineIcon.ts +10 -0
  160. package/src/WebComponent/icons/ChevronLeftIcon.ts +7 -0
  161. package/src/WebComponent/icons/ChevronRightIcon.ts +7 -0
  162. package/src/WebComponent/icons/ContactResidentIcon.ts +9 -0
  163. package/src/WebComponent/icons/DollarOutlineIcon.ts +18 -0
  164. package/src/WebComponent/icons/EmailOutlineIcon.ts +7 -0
  165. package/src/WebComponent/icons/HeyThereEmojiIcon.ts +12 -0
  166. package/src/WebComponent/icons/PhoneOutlineIcon.ts +7 -0
  167. package/src/WebComponent/icons/SendMessageIcon.ts +17 -0
  168. package/src/WebComponent/icons/TourSelfGuidedIcon.ts +17 -0
  169. package/src/WebComponent/icons/TourVirtuallyIcon.ts +17 -0
  170. package/src/WebComponent/icons/TourWithAgentIcon.ts +17 -0
  171. package/src/WebComponent/icons/XOutlineIcon.ts +8 -0
  172. package/src/WebComponent/index.ts +2 -0
  173. package/src/WebComponent/launcher/Launcher.ts +1282 -0
  174. package/src/WebComponent/launcher/launcherStyles.ts +500 -0
  175. package/src/WebComponent/launcher/mobile-launcher.ts +162 -0
  176. package/src/WebComponent/launcher/typeEmojiStyles.ts +161 -0
  177. package/src/WebComponent/launcher/typeMiniStyles.ts +60 -0
  178. package/src/WebComponent/launcher/typeMobileStyles.ts +50 -0
  179. package/src/WebComponent/leasing-chat-styles.ts +114 -0
  180. package/src/WebComponent/me-chat.ts +1262 -0
  181. package/src/WebComponent/me-select.ts +322 -0
  182. package/src/WebComponent/mega-loader.ts +36 -0
  183. package/src/WebComponent/mini-loader.ts +28 -0
  184. package/src/WebComponent/pubnub-chat-styles.ts +204 -0
  185. package/src/WebComponent/pubnub-chat.ts +928 -0
  186. package/src/WebComponent/pubnub-media.ts +208 -0
  187. package/src/WebComponent/pubnub-message-styles.ts +54 -0
  188. package/src/WebComponent/pubnub-message.ts +431 -0
  189. package/src/WebComponent/simple-launcher/simple-launcher-styles.ts +34 -0
  190. package/src/WebComponent/simple-launcher/simple-launcher.ts +100 -0
  191. package/src/WebComponent/utilities-chat.ts +270 -0
  192. package/src/WebComponent/utilities-styles.ts +110 -0
  193. package/src/WebComponent/utils.ts +82 -0
  194. package/src/analytics.ts +217 -0
  195. package/src/assetUrls.ts +6 -0
  196. package/src/disclaimers.ts +58 -0
  197. package/src/fetchBuildingABTestType.ts +21 -0
  198. package/src/fetchBuildingInfo.ts +87 -0
  199. package/src/fetchBuildingWebchatView.ts +156 -0
  200. package/src/fetchFeatureFlag.ts +250 -0
  201. package/src/fetchLeadSources.ts +98 -0
  202. package/src/fetchPhoneNumberFromSource.ts +31 -0
  203. package/src/fetchWebchatPreferences.ts +54 -0
  204. package/src/getAvailabilities.ts +179 -0
  205. package/src/getBuildingPhoneNumber.ts +26 -0
  206. package/src/getShouldAllowScheduling.ts +16 -0
  207. package/src/getShouldShowWebchat.ts +114 -0
  208. package/src/getTimezoneString.ts +39 -0
  209. package/src/globals.ts +1 -0
  210. package/src/gtm.ts +17 -0
  211. package/src/handleChatId.ts +101 -0
  212. package/src/insertDNIIntoWebsite.ts +146 -0
  213. package/src/insertLeadSourceIntoSchedulerLinks.ts +71 -0
  214. package/src/main/MEChat.test.ts +110 -0
  215. package/src/main/MEChat.ts +404 -0
  216. package/src/main/utils.ts +70 -0
  217. package/src/postLeadSources.ts +44 -0
  218. package/src/rentgrata.ts +74 -0
  219. package/src/replaceSelectButtonsWithNewLink.ts +69 -0
  220. package/src/services/fees/calculateQuote.ts +136 -0
  221. package/src/services/fees/fetchBuildingFees.ts +63 -0
  222. package/src/services/fees/fetchBuildingFloorplans.ts +74 -0
  223. package/src/services/fees/utils.ts +4 -0
  224. package/src/svgIcons.ts +14 -0
  225. package/src/themes.ts +65 -0
  226. package/src/types/rest-sdk.types.ts +13 -0
  227. package/src/types/webchat-no-show-reason.ts +6 -0
  228. package/src/utils.ts +121 -0
@@ -0,0 +1,124 @@
1
+ import { formatCurrency, sentenceTitleCase } from "../../../utils";
2
+ import { TransactionCategory } from "./transaction-category";
3
+
4
+ export class BuildingFee {
5
+ id: number;
6
+ buildingId: number;
7
+ blueprint: FeeBlueprint;
8
+ unitIds: number[] | null;
9
+ layoutIds: number[] | null;
10
+ startDate: Date | null;
11
+ endDate: Date | null;
12
+ source: string | null;
13
+ timeCreated: Date;
14
+ externalKey: string | null;
15
+ syncActive: boolean;
16
+ hiddenReason: string | null;
17
+ refundable: boolean | null;
18
+ required?: boolean;
19
+
20
+ constructor(data: Partial<BuildingFee> = {}) {
21
+ this.id = data.id ?? 0;
22
+ this.buildingId = data.buildingId ?? 0;
23
+ this.blueprint = data.blueprint ?? ({} as FeeBlueprint);
24
+ this.unitIds = data.unitIds ?? null;
25
+ this.layoutIds = data.layoutIds ?? null;
26
+ this.startDate = data.startDate ?? null;
27
+ this.endDate = data.endDate ?? null;
28
+ this.source = data.source ?? null;
29
+ this.timeCreated = data.timeCreated ?? new Date();
30
+ this.externalKey = data.externalKey ?? null;
31
+ this.syncActive = data.syncActive ?? false;
32
+ this.hiddenReason = data.hiddenReason ?? null;
33
+ this.refundable = data.refundable ?? null;
34
+ this.required = data.required ?? false;
35
+ }
36
+
37
+ get isAddOn(): boolean {
38
+ return this.blueprint.addOnInfo !== null;
39
+ }
40
+
41
+ displayName(fallback = "Fee"): string {
42
+ if (this.isAddOn && this.blueprint.addOnInfo?.addOnType) {
43
+ return sentenceTitleCase(this.blueprint.addOnInfo.addOnType);
44
+ }
45
+
46
+ return this.blueprint.category
47
+ ? sentenceTitleCase(this.blueprint.category)
48
+ : fallback;
49
+ }
50
+
51
+ get description(): string {
52
+ return this.blueprint.transactionDescription || "";
53
+ }
54
+
55
+ get displayAmount(): string {
56
+ const amount = this.blueprint.transactionAmount;
57
+ return formatCurrency(amount ?? 0);
58
+ }
59
+ }
60
+
61
+ interface FeeBlueprint {
62
+ transactionId: number | null;
63
+ transactionAmount: number | null;
64
+ flowDirection: TransactionFlow;
65
+ transactionDescription: string | null;
66
+ category: TransactionCategory;
67
+ recurrenceInfo: RecurrenceInfo | null;
68
+ adjustmentInfo: AdjustmentInfo | null;
69
+ triggerInfo: TriggerInfo | null;
70
+ addOnInfo: AddOnInfo | null;
71
+ priceType: PriceType;
72
+ handledByThirdParty: boolean;
73
+ handledByThirdPartyReasoning: string | null;
74
+ leaseStartDate: Date | null;
75
+ leaseEndDate: Date | null;
76
+ }
77
+
78
+ interface AdjustmentInfo {
79
+ reason: string;
80
+ percentage: number;
81
+ }
82
+
83
+ export enum RecurrenceFrequency {
84
+ OneTime = "OneTime",
85
+ Daily = "Daily",
86
+ Weekly = "Weekly",
87
+ BiWeekly = "BiWeekly",
88
+ Monthly = "Monthly",
89
+ Yearly = "Yearly",
90
+ Unknown = "Unknown",
91
+ }
92
+
93
+ interface RecurrenceInfo {
94
+ frequency: RecurrenceFrequency;
95
+ startDate: Date | null;
96
+ endDate: Date | null;
97
+ }
98
+
99
+ interface TriggerInfo {
100
+ triggerEvent: string;
101
+ maxDaysBeforeEvent: number;
102
+ maxDaysAfterEvent: number;
103
+ triggerEventEmbedding: number[] | null;
104
+ startDate: Date | null;
105
+ endDate: Date | null;
106
+ }
107
+
108
+ export interface AddOnInfo {
109
+ addOnType: string;
110
+ maxUnitsCharged: number | null;
111
+ minUnitsCharged: number | null;
112
+ addOnTypeEmbedding: number[] | null;
113
+ }
114
+
115
+ export enum TransactionFlow {
116
+ Debit = "Debit",
117
+ Credit = "Credit",
118
+ }
119
+
120
+ export enum PriceType {
121
+ Fixed = "Fixed",
122
+ UsageBased = "UsageBased",
123
+ Varies = "Varies",
124
+ }
@@ -0,0 +1,23 @@
1
+ export enum TransactionCategory {
2
+ AdminFee = "AdminFee",
3
+ ApplicationFee = "ApplicationFee",
4
+ Concession = "Concession",
5
+ Insurance = "Insurance",
6
+ LateFee = "LateFee",
7
+ Legal = "Legal",
8
+ NonSufficientFundFee = "NSF",
9
+ Other = "Other",
10
+ Parking = "Parking",
11
+ Penalty = "Penalty",
12
+ Pest = "Pest",
13
+ PetDeposit = "PetDeposit",
14
+ PetRent = "PetRent",
15
+ Refund = "Refund",
16
+ Relet = "Relet",
17
+ Rent = "Rent",
18
+ SecurityDeposit = "SecurityDeposit",
19
+ Storage = "Storage",
20
+ Trash = "Trash",
21
+ Utility = "Utility",
22
+ WaterSewer = "WaterSewer",
23
+ }
@@ -0,0 +1,332 @@
1
+ import axios from "axios";
2
+ import parseISO from "date-fns/parseISO";
3
+ import formatISO from "date-fns/formatISO";
4
+ import { CampaignSources, getCampaignSources } from "../analytics";
5
+ import { getUrlQueryParameters } from "../postLeadSources";
6
+ import { isTimestampExpired } from "../utils";
7
+ import isEmpty from "lodash/isEmpty";
8
+
9
+ export interface LeadSourceInput {
10
+ buildingSlug: string | null;
11
+ queryParams: {
12
+ [queryKey: string]: string;
13
+ } | null;
14
+ referrer: string;
15
+ campaignSources: CampaignSources;
16
+ }
17
+
18
+ export function getDefaultLeadSourceAttribution(orgSlug: string): string {
19
+ if (orgSlug === "avb") {
20
+ // this is stupid and we should not do this
21
+ // if anything, should read from DB and give clients default ability to set this
22
+ return "AVB Company Website";
23
+ }
24
+ if (orgSlug === "windsor") {
25
+ return "Windsorcommunities.com";
26
+ }
27
+ return "property-website";
28
+ }
29
+
30
+ class LeadSourceClient {
31
+ chatId: string | null = null;
32
+
33
+ private apiHost = "https://app.meetelise.com";
34
+ public leadSource: string | null = null;
35
+ private localStorageTTLDays = 30;
36
+
37
+ buildingId: number | null = null;
38
+ orgSlug: string | null = null;
39
+ buildingSlug: string | null = null;
40
+ queryParameters: {
41
+ [queryKey: string]: string;
42
+ } | null = null;
43
+
44
+ leadSourceInput: {
45
+ websiteOrigin: string | null;
46
+ websiteSearch: string | null;
47
+ queryParameters: {
48
+ [queryKey: string]: string;
49
+ } | null;
50
+ referrer: string | null;
51
+ parsedUtmSource: string | null;
52
+ campaignSources: string[] | null;
53
+ } | null = null;
54
+
55
+ private updateLeadSourceLocalStorage = (
56
+ buildingSlug: string,
57
+ leadSource: string | null,
58
+ leadId: string,
59
+ ignorePost: boolean, // if we dont have lead source, we just want to still use for logging
60
+ isOverrideFromNewLeadSource: boolean
61
+ ) => {
62
+ const queryParameters = getUrlQueryParameters();
63
+ this.leadSourceInput = {
64
+ websiteOrigin: window.location.origin,
65
+ websiteSearch: window.location.search,
66
+ queryParameters: queryParameters,
67
+ referrer: document.referrer,
68
+ parsedUtmSource: queryParameters ? queryParameters["utm_source"] : null,
69
+ campaignSources: Object.values(getCampaignSources()).filter(
70
+ (source) => source
71
+ ),
72
+ };
73
+ if (ignorePost) return;
74
+
75
+ if (!isOverrideFromNewLeadSource) {
76
+ const existingLeadSource = this.getLeadSourceBodyIfValid(buildingSlug);
77
+ if (existingLeadSource) {
78
+ const isExpired = isTimestampExpired(
79
+ existingLeadSource.timestamp,
80
+ this.localStorageTTLDays * 24
81
+ );
82
+ if (!isExpired) {
83
+ return {
84
+ ...existingLeadSource,
85
+ timestamp: parseISO(existingLeadSource.timestamp),
86
+ };
87
+ }
88
+ }
89
+ }
90
+
91
+ const body = {
92
+ leadSource: leadSource,
93
+ leadId: leadId,
94
+ buildingSlug: buildingSlug,
95
+ timestamp: formatISO(new Date()),
96
+ leadSourceInput: this.leadSourceInput,
97
+ };
98
+ localStorage.setItem(
99
+ "com.elise.webchat.leadsource.slug=" + buildingSlug,
100
+ JSON.stringify(body)
101
+ );
102
+ return { ...body, timestamp: parseISO(body.timestamp) };
103
+ };
104
+
105
+ private getLeadSourceBodyIfValid = (buildingSlug: string) => {
106
+ const body = localStorage.getItem(
107
+ "com.elise.webchat.leadsource.slug=" + buildingSlug
108
+ );
109
+ if (body) {
110
+ try {
111
+ const parsedBody = JSON.parse(body);
112
+ const isValid =
113
+ parsedBody.buildingSlug === buildingSlug &&
114
+ parsedBody.leadSource &&
115
+ parsedBody.leadId &&
116
+ parsedBody.timestamp &&
117
+ !isTimestampExpired(
118
+ parseISO(parsedBody.timestamp),
119
+ this.localStorageTTLDays * 24
120
+ );
121
+ if (isValid) {
122
+ try {
123
+ this.leadSourceInput = parsedBody.leadSourceInput;
124
+ } catch (_) {
125
+ // eslint-disable-next-line no-console
126
+ console.error("Error parsing leadSourceInput from localStorage");
127
+ }
128
+ return parsedBody;
129
+ }
130
+ } catch (_) {
131
+ return null;
132
+ }
133
+ }
134
+ return null;
135
+ };
136
+
137
+ private async fetchCurrentParsedLeadSource({
138
+ buildingSlug,
139
+ queryParams,
140
+ referrer,
141
+ campaignSources,
142
+ }: LeadSourceInput): Promise<string | null> {
143
+ try {
144
+ const currentParsedLeadSourceResponse = await axios.post(
145
+ `${this.apiHost}/platformApi/webchat/current-parsed-lead-source`,
146
+ {
147
+ query_params: queryParams,
148
+ building_slug: buildingSlug,
149
+ referrer: referrer,
150
+ campaign_sources: campaignSources,
151
+ }
152
+ );
153
+ return currentParsedLeadSourceResponse.data;
154
+ } catch (_) {
155
+ return null;
156
+ }
157
+ }
158
+
159
+ async checkAndHandleForLogLeadSource({
160
+ webchatAction,
161
+ stateId,
162
+ }: {
163
+ webchatAction: string;
164
+ stateId: string | null;
165
+ }): Promise<null> {
166
+ try {
167
+ if (!this.chatId) {
168
+ // eslint-disable-next-line no-console
169
+ console.error("chatId is not set");
170
+ return null;
171
+ }
172
+ if (!this.orgSlug) {
173
+ // eslint-disable-next-line no-console
174
+ console.error("orgId is not set");
175
+ return null;
176
+ }
177
+
178
+ let google_analytics_client_id = null;
179
+ let extras = null;
180
+ try {
181
+ if (this.orgSlug === "f1ba5a20-d207-4e5a-879e-65199e7d0a53") {
182
+ // SCION only
183
+ const gaCookie = await this.getCookieValue("_ga");
184
+ if (gaCookie) {
185
+ google_analytics_client_id = gaCookie;
186
+ }
187
+ // find the object in the dataLayer that has the extras gtagApiGet
188
+ extras = window.dataLayer.find(
189
+ (obj) => obj.value?.event == "gtagApiGet"
190
+ )?.value;
191
+ }
192
+ } catch (error) {
193
+ // eslint-disable-next-line no-console
194
+ console.error("error getting cookie");
195
+ }
196
+
197
+ await axios.post(`${this.apiHost}/platformApi/webchat/log/lead-source`, {
198
+ chat_id: this.chatId,
199
+ webchat_action: webchatAction,
200
+ state_id: stateId,
201
+ building_id: this.buildingId,
202
+ org_slug: this.orgSlug,
203
+ building_slug: this.buildingSlug,
204
+ website_origin: this.leadSourceInput?.websiteOrigin,
205
+ website_search: this.leadSourceInput?.websiteSearch,
206
+ query_parameters: this.leadSourceInput?.queryParameters,
207
+ referrer: this.leadSourceInput?.referrer,
208
+ parsed_utm_source: this.leadSourceInput?.parsedUtmSource,
209
+ campaign_sources: this.leadSourceInput?.campaignSources,
210
+ lead_source_output: this.leadSource,
211
+ google_analytics_client_id: isEmpty(google_analytics_client_id)
212
+ ? null
213
+ : google_analytics_client_id,
214
+ extras: extras ?? null,
215
+ });
216
+ return null;
217
+ } catch (_) {
218
+ return null;
219
+ }
220
+ }
221
+
222
+ async getCookieValue(key: string): Promise<string | null> {
223
+ try {
224
+ const cookies = document.cookie.split(";");
225
+ for (let i = 0; i < cookies.length; i++) {
226
+ const cookie = cookies[i].trim();
227
+ if (cookie.startsWith(key + "=")) {
228
+ const value = cookie.substring(
229
+ (key + "=").length,
230
+ cookie.indexOf(";") === -1 ? undefined : cookie.indexOf(";")
231
+ );
232
+ return value;
233
+ }
234
+ }
235
+ return null;
236
+ } catch (error) {
237
+ // eslint-disable-next-line no-console
238
+ console.error("error getting cookie value");
239
+ }
240
+ return null;
241
+ }
242
+
243
+ // TODO(erol): clean up this entire function
244
+ async generateUserLeadSource({
245
+ leadId,
246
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
247
+ orgSlug,
248
+ buildingSlug,
249
+ }: {
250
+ leadId: string;
251
+ orgSlug: string;
252
+ buildingSlug: string | null;
253
+ }): Promise<string | null> {
254
+ try {
255
+ // 1. try to generate a lead source
256
+ // 2. if we have a match, use that
257
+ // 3. if we dont have a match utilize the one from local storage
258
+ const leadSourceInput: LeadSourceInput = {
259
+ queryParams: getUrlQueryParameters(),
260
+ buildingSlug: buildingSlug,
261
+ referrer: document.referrer,
262
+ campaignSources: getCampaignSources(),
263
+ };
264
+
265
+ let isOverrideFromNewLeadSource = false;
266
+ // We detect if there is an existing lead source in local storage
267
+ const isCurrentlyStoredLeadSource = buildingSlug
268
+ ? this.getLeadSourceBodyIfValid(buildingSlug)
269
+ : null;
270
+ if (isCurrentlyStoredLeadSource) {
271
+ const orgSlugsAlwaysUseMostRecentLeadSource = [
272
+ "test-company",
273
+ "daf00bd2-1ecb-482c-b6f4-e1c5511a01be", // talked w/ carbon https://meetelise.zendesk.com/agent/tickets/75095
274
+ ];
275
+ if (orgSlugsAlwaysUseMostRecentLeadSource.includes(orgSlug)) {
276
+ const currentParsedLeadSource =
277
+ await this.fetchCurrentParsedLeadSource(leadSourceInput);
278
+
279
+ if (currentParsedLeadSource) {
280
+ this.leadSource = currentParsedLeadSource;
281
+ isOverrideFromNewLeadSource = true;
282
+ } else {
283
+ this.leadSource = isCurrentlyStoredLeadSource.leadSource;
284
+ return this.leadSource;
285
+ }
286
+ } else {
287
+ this.leadSource = isCurrentlyStoredLeadSource.leadSource;
288
+ return this.leadSource;
289
+ }
290
+ }
291
+
292
+ const currentParsedLeadSource = await this.fetchCurrentParsedLeadSource(
293
+ leadSourceInput
294
+ );
295
+ this.leadSource = currentParsedLeadSource;
296
+
297
+ this.buildingId = null;
298
+ this.orgSlug = orgSlug;
299
+ this.buildingSlug = buildingSlug;
300
+
301
+ // If we do NOT detect a lead source from the current session, we check the local storage and use that
302
+ if (buildingSlug && !currentParsedLeadSource) {
303
+ const isCurrentlyStoredLeadSource =
304
+ this.getLeadSourceBodyIfValid(buildingSlug);
305
+ if (isCurrentlyStoredLeadSource) {
306
+ this.leadSource = isCurrentlyStoredLeadSource.leadSource;
307
+ return this.leadSource;
308
+ }
309
+ }
310
+
311
+ if (buildingSlug) {
312
+ const leadSourceExistsInLocalStorage =
313
+ !!currentParsedLeadSource && currentParsedLeadSource.length > 0;
314
+
315
+ this.updateLeadSourceLocalStorage(
316
+ buildingSlug,
317
+ currentParsedLeadSource,
318
+ leadId,
319
+ !leadSourceExistsInLocalStorage && !isOverrideFromNewLeadSource,
320
+ isOverrideFromNewLeadSource
321
+ );
322
+ }
323
+ return currentParsedLeadSource;
324
+ } catch (error) {
325
+ // eslint-disable-next-line no-console
326
+ console.error(error);
327
+ }
328
+ return null;
329
+ }
330
+ }
331
+
332
+ export default LeadSourceClient;
@@ -0,0 +1,5 @@
1
+ @media screen and (min-width: 767px) {
2
+ .meetelise-chat.pane.launcher__desktop {
3
+ right: -32px;
4
+ }
5
+ }
@@ -0,0 +1,73 @@
1
+ import eachDayOfInterval from "date-fns/eachDayOfInterval";
2
+ import startOfWeek from "date-fns/startOfWeek";
3
+ import endOfWeek from "date-fns/endOfWeek";
4
+ import setHours from "date-fns/setHours";
5
+ import getDay from "date-fns/getDay";
6
+ import axios from "axios";
7
+
8
+ interface OfficeHourAvailabilityReponse {
9
+ [dayOfWeek: string]: { start: string; end: string };
10
+ }
11
+
12
+ const officeHoursCache: {
13
+ [buildingId: number]: OfficeHourAvailabilityReponse;
14
+ } = {};
15
+
16
+ export const getRawOfficeHours = async (
17
+ buildingId: number
18
+ ): Promise<OfficeHourAvailabilityReponse> => {
19
+ if (officeHoursCache[buildingId]) {
20
+ return officeHoursCache[buildingId];
21
+ }
22
+ const url = `https://app.meetelise.com/platformApi/connectors/talk_js/leasing_office_hours/${buildingId}`;
23
+ const result = await axios.get<OfficeHourAvailabilityReponse>(url);
24
+ officeHoursCache[buildingId] = result.data;
25
+ return result.data;
26
+ };
27
+
28
+ export const getDefaultOfficeHours = (): {
29
+ startTime: Date;
30
+ endTime: Date;
31
+ }[] => {
32
+ return eachDayOfInterval({
33
+ start: startOfWeek(new Date()),
34
+ end: endOfWeek(new Date()),
35
+ })
36
+ .filter((date) => getDay(date) !== 0 && getDay(date) !== 6)
37
+ .map((date) => ({
38
+ startTime: setHours(date, 9),
39
+ endTime: setHours(date, 17),
40
+ }));
41
+ };
42
+
43
+ export const dayNamesInOrder = [
44
+ "monday",
45
+ "tuesday",
46
+ "wednesday",
47
+ "thursday",
48
+ "friday",
49
+ "saturday",
50
+ "sunday",
51
+ ];
52
+
53
+ /**
54
+ * Based on the design, we're going with monday as the first day of the week
55
+ */
56
+ export const getOfficeHourText = async (
57
+ buildingId: number
58
+ ): Promise<
59
+ (string | { dayOfWeek: string; startTime: string; endTime: string })[]
60
+ > => {
61
+ const rawOfficeHours = await getRawOfficeHours(buildingId);
62
+ return dayNamesInOrder.map((dow) => {
63
+ const officeHourInfo = rawOfficeHours[dow];
64
+ if (!officeHourInfo) {
65
+ return dow;
66
+ }
67
+ return {
68
+ dayOfWeek: dow,
69
+ startTime: officeHourInfo.start,
70
+ endTime: officeHourInfo.end,
71
+ };
72
+ });
73
+ };