@icvdeveloper/common-module 1.4.13 → 2.0.0

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 (109) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +10 -0
  4. package/dist/runtime/@types/components.d.ts +22 -0
  5. package/dist/runtime/@types/configVariables.d.ts +6 -0
  6. package/dist/runtime/analytics.d.ts +1 -1
  7. package/dist/runtime/assets/scss/index.css +0 -705
  8. package/dist/runtime/assets/svg/icon-minus.svg +6 -0
  9. package/dist/runtime/assets/svg/icon-video.svg +6 -0
  10. package/dist/runtime/components/affiliates/AffiliateModal.vue +66 -0
  11. package/dist/runtime/components/affiliates/AffiliatePage.vue +337 -132
  12. package/dist/runtime/components/agenda/AgendaTabbed.vue +43 -34
  13. package/dist/runtime/components/agenda/components/Calendar.vue +8 -3
  14. package/dist/runtime/components/agenda/components/Favorite.vue +44 -0
  15. package/dist/runtime/components/agenda/components/PlayIcon.vue +1 -1
  16. package/dist/runtime/components/agenda/components/PresentationLink.vue +26 -15
  17. package/dist/runtime/components/chat/ChatConversationList.vue +108 -0
  18. package/dist/runtime/components/chat/ChatCreateConversation.vue +205 -0
  19. package/dist/runtime/components/chat/ChatCreateGroupConversation.vue +159 -0
  20. package/dist/runtime/components/chat/ChatHeader.vue +98 -0
  21. package/dist/runtime/components/chat/ChatMessage.vue +40 -0
  22. package/dist/runtime/components/chat/ChatShowConversation.vue +77 -0
  23. package/dist/runtime/components/chat/ChatWidget.vue +65 -0
  24. package/dist/runtime/components/chat/ChatWindow.vue +211 -0
  25. package/dist/runtime/components/chat/ChatWindow.vue.d.ts +6 -0
  26. package/dist/runtime/components/chat/MessageInput.vue +30 -0
  27. package/dist/runtime/components/chat/SearchInput.vue +32 -0
  28. package/dist/runtime/components/core/Accordion.vue +1 -1
  29. package/dist/runtime/components/core/AttendeeList.vue +25 -16
  30. package/dist/runtime/components/core/CountdownTimer.vue +1 -1
  31. package/dist/runtime/components/core/Modal.vue +21 -13
  32. package/dist/runtime/components/core/ModalButton.vue +43 -0
  33. package/dist/runtime/components/core/Navbar.vue +3 -3
  34. package/dist/runtime/components/core/Navigation.vue +293 -0
  35. package/dist/runtime/components/core/SvgIcon.vue +31 -1
  36. package/dist/runtime/components/core/VButton.vue +41 -0
  37. package/dist/runtime/components/core/ZoomModal.vue +1 -1
  38. package/dist/runtime/components/events/ListEvents.vue +3 -4
  39. package/dist/runtime/components/forms/CheckboxGroup.vue +46 -0
  40. package/dist/runtime/components/forms/ErrorField.vue +11 -2
  41. package/dist/runtime/components/forms/RadioGroup.vue +50 -0
  42. package/dist/runtime/components/forms/SelectDropDown.vue +47 -0
  43. package/dist/runtime/components/forms/SupportForm.vue +6 -6
  44. package/dist/runtime/components/layouts/Accordion.vue +2 -2
  45. package/dist/runtime/components/media/ArchivePlayerAndContentContainer.vue +20 -4
  46. package/dist/runtime/components/media/ArchiveVideoPlayer.vue +14 -6
  47. package/dist/runtime/components/media/WebcastVideoPlayer.vue +1 -1
  48. package/dist/runtime/components/media/components/ArchiveMediaContainer.vue +8 -8
  49. package/dist/runtime/components/media/components/CeCreditNotification.vue +2 -2
  50. package/dist/runtime/components/media/components/ContentArea.vue +51 -14
  51. package/dist/runtime/components/media/components/ContentTabs.vue +2 -2
  52. package/dist/runtime/components/media/components/DocumentsPanel.vue +2 -2
  53. package/dist/runtime/components/media/components/MediaContainer.vue +3 -7
  54. package/dist/runtime/components/media/components/PresentersPanel.vue +69 -50
  55. package/dist/runtime/components/media/components/SessionReporting.vue +5 -4
  56. package/dist/runtime/components/media/components/SponsorsPanel.vue +3 -3
  57. package/dist/runtime/components/presenters/PresenterListing.vue +30 -20
  58. package/dist/runtime/components/presenters/PresenterModal.vue +26 -21
  59. package/dist/runtime/components/presenters/Presenters.vue +139 -0
  60. package/dist/runtime/components/profile/Profile.vue +10 -6
  61. package/dist/runtime/components/profile/components/Sidebar.vue +1 -1
  62. package/dist/runtime/components/profile/components/SidebarNavItem.vue +1 -1
  63. package/dist/runtime/components/profile/tabs/Favorites.vue +5 -4
  64. package/dist/runtime/components/profile/tabs/GeneralInformation.vue +26 -16
  65. package/dist/runtime/components/registration/AlreadyRegisteredModal.vue +99 -0
  66. package/dist/runtime/components/registration/PaymentForm.vue +136 -0
  67. package/dist/runtime/components/registration/RegistrationForm.vue +417 -0
  68. package/dist/runtime/components/registration/RegistrationGroupSelect.vue +142 -0
  69. package/dist/runtime/components/registration/StripePaymentForm.vue +141 -0
  70. package/dist/runtime/composables/useAgenda.d.ts +12 -0
  71. package/dist/runtime/composables/useAgenda.mjs +101 -10
  72. package/dist/runtime/composables/useAuth.mjs +1 -1
  73. package/dist/runtime/composables/useConferenceHelpers.d.ts +5 -1
  74. package/dist/runtime/composables/useConferenceHelpers.mjs +15 -1
  75. package/dist/runtime/composables/useEventHooks.d.ts +26 -0
  76. package/dist/runtime/composables/useEventHooks.mjs +21 -0
  77. package/dist/runtime/composables/useEvents.d.ts +17 -1
  78. package/dist/runtime/composables/useEvents.mjs +29 -1
  79. package/dist/runtime/composables/useLogin.mjs +7 -3
  80. package/dist/runtime/composables/usePresentation.mjs +1 -1
  81. package/dist/runtime/composables/usePusher.d.ts +4 -0
  82. package/dist/runtime/composables/usePusher.mjs +38 -26
  83. package/dist/runtime/composables/useStream.mjs +7 -1
  84. package/dist/runtime/enums/general.d.ts +4 -1
  85. package/dist/runtime/enums/general.mjs +4 -1
  86. package/dist/runtime/models/authUser.d.ts +1 -0
  87. package/dist/runtime/models/conference.d.ts +14 -0
  88. package/dist/runtime/models/conversation.d.ts +2 -4
  89. package/dist/runtime/models/globalConfig.d.ts +6 -2
  90. package/dist/runtime/models/group.d.ts +32 -2
  91. package/dist/runtime/models/icons.d.ts +7 -0
  92. package/dist/runtime/models/templateConfig.d.ts +6 -0
  93. package/dist/runtime/models/user.d.ts +1 -0
  94. package/dist/runtime/models/virtualPagesConfig.d.ts +335 -0
  95. package/dist/runtime/models/virtualPagesConfig.mjs +0 -0
  96. package/dist/runtime/plugin.mjs +11 -1
  97. package/dist/runtime/store/affiliates.d.ts +3 -0
  98. package/dist/runtime/store/affiliates.mjs +38 -0
  99. package/dist/runtime/store/auth.mjs +6 -0
  100. package/dist/runtime/store/conferences.d.ts +3 -1
  101. package/dist/runtime/store/conferences.mjs +7 -2
  102. package/dist/runtime/store/conversations.d.ts +4040 -10
  103. package/dist/runtime/store/conversations.mjs +255 -22
  104. package/dist/runtime/store/modalPlayerConfig.d.ts +498 -0
  105. package/dist/runtime/store/modalPlayerConfig.mjs +58 -0
  106. package/dist/runtime/store/templateConfigs.d.ts +3 -2
  107. package/dist/runtime/store/templateConfigs.mjs +2 -1
  108. package/package.json +5 -2
  109. package/dist/runtime/components/media/components/PresentersPanel.vue.d.ts +0 -32
@@ -0,0 +1,205 @@
1
+ <script lang="ts" setup>
2
+ import { inject, onMounted, onBeforeUnmount, ref, toRefs, watch } from 'vue';
3
+ import { storeToRefs } from 'pinia';
4
+ import { debounce, find, remove } from 'lodash-es';
5
+ import { VueEternalLoading, LoadAction } from "@ts-pro/vue-eternal-loading";
6
+ import { useConversationStore } from '#imports';
7
+ import { chatSearchEventHook } from '../../composables/useEventHooks';
8
+ import type { UsersResult } from '../../store/conversations';
9
+ import type { User } from '../../models/user';
10
+
11
+ const conversationStore = useConversationStore();
12
+
13
+ const { user, users, isInitial } = storeToRefs(conversationStore);
14
+
15
+ const { getName, createConversation } = conversationStore;
16
+
17
+ // data
18
+ const selectedUsers = ref<User[]>([] as User[]);
19
+ const filteredUsers = ref<UsersResult>({} as UsersResult);
20
+
21
+ // emits
22
+ const emit = defineEmits<{
23
+ (event: 'onCreate', value: User[]): void;
24
+ }>();
25
+
26
+ // injected load function
27
+ // (see Vue Eternal Loading docs for reference: https://ts-pro.github.io/vue-eternal-loading/guide/simple-usage.html)
28
+ const load = inject('attendeeListLoad', (loaded: LoadAction) => { console.log('no scroll'); loaded(0); })
29
+
30
+ // methods
31
+ const toggle = (user: User) => {
32
+ console.log('selected: ', user.name);
33
+ if (exists(user) == undefined) {
34
+ console.log('user not already selected');
35
+ selectedUsers.value?.push(user);
36
+ } else {
37
+ console.log('user already selected, removing');
38
+ const array = selectedUsers.value as User[];
39
+
40
+ remove(array, (element) => {
41
+ return element.id === user.id;
42
+ });
43
+
44
+ selectedUsers.value = [...array];
45
+ }
46
+ };
47
+
48
+ const exists = (user: User): User | undefined => {
49
+ return find(selectedUsers.value, {'id': user.id});
50
+ };
51
+
52
+ const onSearchChange = debounce((value: string) => {
53
+ console.log('debounced');
54
+ chatSearchEventHook.trigger({value: value, iterate: true});
55
+ }, 500);
56
+
57
+ const clear = (): void => {
58
+ console.log('clear');
59
+ chatSearchEventHook.trigger({value: undefined, iterate: true});
60
+ };
61
+
62
+ watch(users.value, (_users, _newUsers) => {
63
+ filteredUsers.value = _newUsers;
64
+ });
65
+
66
+ // lifecycle hooks
67
+ onMounted(() => {
68
+ filteredUsers.value = users.value;
69
+ });
70
+
71
+ onBeforeUnmount(() => {
72
+ clear();
73
+ });
74
+ </script>
75
+
76
+ <template>
77
+ <div class="flex h-full justify-between flex-col overflow-y-hidden">
78
+ <CommonSearchInput
79
+ @on-change="onSearchChange"
80
+ @clear="clear"
81
+ />
82
+ <div class="overflow-y-auto h-full bg-gray-300">
83
+ <!-- Selected Users -->
84
+ <div class="z-50 sticky flex pin-t border-b-4 border-blue bg-gray-300 overflow-x-auto">
85
+ <div
86
+ v-if="selectedUsers?.length"
87
+ class="flex flex-row"
88
+ >
89
+ <div
90
+ v-for="currentUser in selectedUsers"
91
+ :key="currentUser.id"
92
+ class="py-1"
93
+ >
94
+ <div
95
+ v-if="currentUser.id !== user.data.id"
96
+ class="selected-user-item"
97
+ @click="toggle(currentUser)"
98
+ >
99
+ <CommonSvgIcon icon="person" />
100
+ <div class="text-sm py-2">
101
+ <p class="pt-2 text-black leading-none">
102
+ {{ getName(currentUser) }}
103
+ </p>
104
+ </div>
105
+ <CommonSvgIcon icon="close" />
106
+ </div>
107
+ </div>
108
+ </div>
109
+
110
+ <div
111
+ v-else
112
+ class="flex py-4 w-full"
113
+ >
114
+ <p class="text-center mb-0 text-green-500 w-full">
115
+ Select one or more users to chat with,
116
+ <br>
117
+ then click Start Chat
118
+ </p>
119
+ </div>
120
+ </div>
121
+
122
+ <!-- All Users -->
123
+ <div
124
+ v-for="currentUser in filteredUsers?.data"
125
+ :key="currentUser.id"
126
+ >
127
+ <div
128
+ v-if="currentUser.id !== user.data.id && !exists(currentUser)"
129
+ class="user-item"
130
+ @click="toggle(currentUser)"
131
+ >
132
+ <CommonSvgIcon
133
+ v-if="currentUser.online"
134
+ icon="online"
135
+ />
136
+ <CommonSvgIcon
137
+ v-if="!currentUser.online"
138
+ icon="offline"
139
+ />
140
+ <CommonSvgIcon
141
+ icon="person"
142
+ />
143
+ <div class="text-sm py-4">
144
+ <p class="pt-2 text-black leading-none">
145
+ {{ getName(currentUser) }}
146
+ </p>
147
+ </div>
148
+ </div>
149
+ </div>
150
+ <VueEternalLoading
151
+ v-model:is-initial="isInitial"
152
+ :load="load"
153
+ >
154
+ <template #no-more>
155
+ &nbsp;
156
+ </template>
157
+ </VueEternalLoading>
158
+ </div>
159
+ <button
160
+ v-if="selectedUsers?.length !== 0"
161
+ class="create-conversation-button bg-blue-500 border-0 hover:bg-blue-700 text-white font-bold py-3 px-4 focus:outline-none cursor-pointer"
162
+ type="button"
163
+ @click="createConversation(selectedUsers as User[])"
164
+ >
165
+ Start Chat
166
+ </button>
167
+ </div>
168
+ </template>
169
+
170
+ <style scoped>
171
+ .disabled {
172
+ opacity: 50%;
173
+ cursor: not-allowed;
174
+ }
175
+
176
+ .disabled:hover {
177
+ background-color: #3490dc !important;
178
+ }
179
+
180
+ .create-conversation-button {
181
+ border-bottom-left-radius: 9px;
182
+ border-bottom-right-radius: 9px;
183
+ }
184
+
185
+ .user-item {
186
+ @apply cursor-pointer flex items-center px-4 bg-gray-300;
187
+ border-bottom: 1px solid #dae1e7;
188
+ }
189
+ .user-item:hover {
190
+ background-color: #f9fafb;
191
+ }
192
+ .user-item:active {
193
+ background-color: #bbc8d3;
194
+ }
195
+
196
+ .selected-user-item {
197
+ @apply cursor-pointer flex items-center px-4 border-r-2 border-gray-400;
198
+ }
199
+ .selected-user-item:hover {
200
+ background-color: #f9fafb;
201
+ }
202
+ .selected-user-item:active {
203
+ background-color: #bbc8d3;
204
+ }
205
+ </style>
@@ -0,0 +1,159 @@
1
+ <script lang="ts" setup>
2
+ import { inject, onMounted, onBeforeUnmount, ref, toRefs, watch } from 'vue';
3
+ import { storeToRefs } from 'pinia';
4
+ import { debounce, find, remove } from 'lodash-es';
5
+ import { VueEternalLoading, LoadAction } from "@ts-pro/vue-eternal-loading";
6
+ import { useConversationStore } from '#imports';
7
+ import { chatSearchEventHook } from '../../composables/useEventHooks';
8
+ import type { User } from '../../models/user';
9
+
10
+ // data
11
+ const selectedUsers = ref<User[]>();
12
+ const filteredUsers = ref<User[]>();
13
+
14
+ const conversationStore = useConversationStore();
15
+
16
+ const { user, users, isInitial } = storeToRefs(conversationStore);
17
+
18
+ // emits
19
+ const emit = defineEmits<{
20
+ (event: 'onCreate', value: User[]): void;
21
+ }>();
22
+
23
+ // injected load function
24
+ // (see Vue Eternal Loading docs for reference: https://ts-pro.github.io/vue-eternal-loading/guide/simple-usage.html)
25
+ const load = inject('attendeeListLoad', (loaded: LoadAction) => { console.log('no scroll'); loaded(0); })
26
+
27
+ const { getName } = conversationStore;
28
+
29
+ // methods
30
+ const toggle = (user: User) => {
31
+ if (exists(user) == undefined) {
32
+ selectedUsers.value?.push(user);
33
+ } else {
34
+ const array = selectedUsers.value as User[];
35
+
36
+ remove(array, (element) => {
37
+ return element.id === user.id;
38
+ });
39
+
40
+ selectedUsers.value = [...array];
41
+ }
42
+ };
43
+
44
+ const exists = (user: User): User | undefined => {
45
+ return find(selectedUsers.value, {'id': user.id});
46
+ };
47
+
48
+ const onSearchChange = debounce((value: string) => {
49
+ chatSearchEventHook.trigger({value: value, iterate: true});
50
+ }, 500);
51
+
52
+ const clear = (): void => {
53
+ chatSearchEventHook.trigger({value: undefined, iterate: true});
54
+ };
55
+
56
+ watch(users.value, (_users, _newUsers) => {
57
+ filteredUsers.value = _newUsers.data;
58
+ });
59
+
60
+ // lifecycle hooks
61
+ onMounted(() => {
62
+ filteredUsers.value = users.value.data;
63
+ });
64
+
65
+ onBeforeUnmount(() => {
66
+ clear();
67
+ });
68
+ </script>
69
+
70
+ <template>
71
+ <div class="flex h-full justify-between flex-col overflow-y-hidden">
72
+ <CommonSearchInput
73
+ @on-change="onSearchChange"
74
+ />
75
+ <div class="overflow-y-auto h-full bg-grey-lighter">
76
+ <!-- Selected Users -->
77
+ <div
78
+ v-if="selectedUsers?.length"
79
+ class="z-50 sticky pin-t border-b-4 border-blue bg-grey-lighter"
80
+ >
81
+ <div
82
+ v-for="currentUser in selectedUsers"
83
+ :key="currentUser.id"
84
+ >
85
+ <div
86
+ v-if="currentUser.id !== user.id"
87
+ class="cursor-pointer flex items-center px-4"
88
+ style="border-bottom: 1px solid #dae1e7"
89
+ @click="toggle(currentUser)"
90
+ >
91
+ <CommonSvgIcon icon="check" />
92
+ <CommonSvgIcon icon="person" />
93
+ <div class="text-sm py-2">
94
+ <p class="pt-2 text-black leading-none">
95
+ {{ getName(currentUser) }}
96
+ </p>
97
+ </div>
98
+ </div>
99
+ </div>
100
+ </div>
101
+
102
+ <!-- All Users -->
103
+ <div
104
+ v-for="currentUser in filteredUsers"
105
+ :key="currentUser.id"
106
+ >
107
+ <div
108
+ v-if="currentUser.id !== user.id"
109
+ :class="{selected: exists(currentUser), 'bg-grey-lighter': !exists(currentUser) }"
110
+ class="cursor-pointer flex items-center px-4"
111
+ style="border-bottom: 1px solid #dae1e7"
112
+ @click="toggle(currentUser)"
113
+ >
114
+ <CommonSvgIcon
115
+ v-if="currentUser.online"
116
+ icon="online"
117
+ />
118
+ <CommonSvgIcon
119
+ v-else
120
+ icon="online"
121
+ />
122
+ <CommonSvgIcon
123
+ icon="person"
124
+ />
125
+ <div class="text-sm py-4">
126
+ <p class="pt-2 text-black leading-none">
127
+ {{ getName(currentUser) }}
128
+ </p>
129
+ </div>
130
+ </div>
131
+ </div>
132
+ <VueEternalLoading
133
+ v-model:is-initial="isInitial"
134
+ :load="load"
135
+ >
136
+ <template #no-more>
137
+ &nbsp;
138
+ </template>
139
+ </VueEternalLoading>
140
+ </div>
141
+ <button
142
+ class="create-conversation-button bg-blue border-0 hover:bg-blue-dark text-white font-bold py-3 px-4 focus:outline-none cursor-pointer"
143
+ type="button"
144
+ @click="emit('onCreate', selectedUsers as User[])"
145
+ >
146
+ Create Conversation
147
+ </button>
148
+ </div>
149
+ </template>
150
+
151
+ <style scoped>
152
+ .selected {
153
+ background-color: #b8c2cc;
154
+ }
155
+ .create-conversation-button {
156
+ border-bottom-left-radius: 9px;
157
+ border-bottom-right-radius: 9px;
158
+ }
159
+ </style>
@@ -0,0 +1,98 @@
1
+ <script lang="ts" setup>
2
+ import { useConversationStore } from '#imports';
3
+
4
+ import { MenuOptions } from './ChatWindow.vue';
5
+
6
+ const { toggleChat } = useConversationStore();
7
+
8
+ const emit = defineEmits<{
9
+ (event: 'itemSelected', value: MenuOptions): void;
10
+ }>();
11
+ </script>
12
+
13
+ <template>
14
+ <div class="header bg-blue-500">
15
+ <div class="flex flex-row text-center text-white w-full">
16
+ <div
17
+ class="flex-1 grow flex items-center h-full header-button"
18
+ @click="emit('itemSelected', MenuOptions.LIST)"
19
+ >
20
+ <p class="flex-1 py-0 px-2 m-0">
21
+ All Chats
22
+ </p>
23
+ </div>
24
+ <div
25
+ class="flex-1 flex items-center h-full header-button"
26
+ @click="emit('itemSelected', MenuOptions.CREATE)"
27
+ >
28
+ <p class="flex-1 py-0 px-2 m-0">
29
+ New Chat
30
+ </p>
31
+ </div>
32
+ <div
33
+ class="flex-shrink flex items-center h-full header-button"
34
+ @click="toggleChat"
35
+ >
36
+ <CommonSvgIcon
37
+ class="flex-1 flex items-center justify-center"
38
+ fill-color="white"
39
+ icon="close"
40
+ />
41
+ </div>
42
+ </div>
43
+ </div>
44
+ </template>
45
+
46
+ <style scoped>
47
+ .header {
48
+ border-top-left-radius: 9px;
49
+ border-top-right-radius: 9px;
50
+ padding: 0.25rem;
51
+ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
52
+ position: relative;
53
+ box-sizing: border-box;
54
+ display: flex;
55
+ }
56
+
57
+ .header-title {
58
+ align-self: center;
59
+ padding: 10px;
60
+ flex: 1;
61
+ user-select: none;
62
+ font-size: 16px;
63
+ }
64
+
65
+ .header-button {
66
+ align-self: center;
67
+ cursor: pointer;
68
+ border-radius: 5px;
69
+ padding: 0.5rem;
70
+ }
71
+ .header-button:hover {
72
+ @apply shadow;
73
+ }
74
+ .header-button:hover:active {
75
+ @apply shadow-inner;
76
+ }
77
+
78
+ .icon-button {
79
+ width: 40px;
80
+ height: 40px;
81
+ padding: 13px;
82
+ margin-left: auto;
83
+ margin-right: 10px;
84
+ box-sizing: border-box;
85
+ }
86
+
87
+ .header-button img, .header-button svg {
88
+ width: 100%;
89
+ height: 100%;
90
+ box-sizing: border-box;
91
+ }
92
+
93
+ @media (max-width: 450px) {
94
+ .header {
95
+ border-radius: 0px;
96
+ }
97
+ }
98
+ </style>
@@ -0,0 +1,40 @@
1
+ <script lang="ts" setup>
2
+ import { toRefs } from 'vue';
3
+ type Props = {
4
+ from: string;
5
+ time: string;
6
+ text: string;
7
+ inbound: boolean;
8
+ }
9
+
10
+ const props = defineProps<Props>();
11
+
12
+ const { from, time, text, inbound } = toRefs(props);
13
+ </script>
14
+
15
+ <template>
16
+ <div class="clearfix">
17
+ <div
18
+ class="w-3/4 mx-4"
19
+ :class="{ 'float-right': !inbound }"
20
+ >
21
+ <div class="flex items-start items-center mb-4 text-sm">
22
+ <CommonSvgIcon icon="person" />
23
+ <div class="flex-1 overflow-hidden">
24
+ <p class="text-gray-500 text-xs mt-0 pt-1">
25
+ {{ from }}
26
+ </p>
27
+ <p
28
+ class="rounded border-2 border-gray-100 leading-normal m-0 p-2"
29
+ :class="{'bg-blue-500 text-white' : !inbound, 'bg-gray-100 text-black' : inbound}"
30
+ >
31
+ {{ text }}
32
+ </p>
33
+ <p class="text-gray-500 text-xs mt-0 pt-1">
34
+ {{ time }}
35
+ </p>
36
+ </div>
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </template>
@@ -0,0 +1,77 @@
1
+ <script lang="ts" setup>
2
+ import { toRefs } from 'vue';
3
+ import { storeToRefs } from 'pinia';
4
+ import { useConversationStore } from '#imports';
5
+ import MessageInput from './MessageInput.vue';
6
+ import { sendMessageEventHook } from '../../composables/useEventHooks';
7
+ import type { User } from '../../models/user';
8
+ import type { Conversation, Message } from '../../models/conversation';
9
+
10
+ const conversationStore = useConversationStore();
11
+
12
+ const { selectedConversation, user } = storeToRefs(conversationStore);
13
+
14
+ const { getName } = conversationStore;
15
+
16
+ // methods
17
+ const isInbound = (userArg: User): boolean => {
18
+ return userArg.id !== user.value.data.id;
19
+ };
20
+ </script>
21
+
22
+ <template>
23
+ <div class="flex justify-between flex-col h-full overflow-y-hidden">
24
+ <div class="overflow-y-auto">
25
+ <div class="z-50 sticky flex pin-t border-b-4 border-blue-500 bg-gray-300 overflow-x-auto">
26
+ <div class="flex flex-row">
27
+ <div
28
+ v-for="currentUser in selectedConversation?.users"
29
+ :key="currentUser.id"
30
+ class="py-1"
31
+ >
32
+ <div
33
+ v-if="currentUser.id !== user.id"
34
+ class="flex items-center px-4 border-r-2 border-gray-400"
35
+ >
36
+ <CommonSvgIcon icon="person" />
37
+ <div class="text-sm py-2">
38
+ <p class="pt-2 text-black leading-none">
39
+ {{ getName(currentUser) }}
40
+ </p>
41
+ </div>
42
+ </div>
43
+ </div>
44
+
45
+ <div
46
+ v-if="Object.keys(selectedConversation as Conversation[]).length > 0 && selectedConversation?.user?.id !== user.id"
47
+ class="py-1"
48
+ >
49
+ <div
50
+ class="flex items-center px-4 border-r-2 border-gray-400"
51
+ >
52
+ <CommonSvgIcon icon="person" />
53
+ <div class="text-sm py-2">
54
+ <p class="pt-2 text-black leading-none">
55
+ {{ getName(selectedConversation?.user as User) }}
56
+ </p>
57
+ </div>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ </div>
62
+
63
+ <div>
64
+ <CommonChatMessage
65
+ v-for="message in selectedConversation?.messages"
66
+ :key="message.id"
67
+ :from="message?.user?.name"
68
+ :text="message.message"
69
+ :time="message.created_at"
70
+ :inbound="isInbound(message?.user as User)"
71
+ />
72
+ </div>
73
+ </div>
74
+
75
+ <MessageInput @send-message="(message: string) => {console.log('message event: ', message); sendMessageEventHook.trigger(message)}" />
76
+ </div>
77
+ </template>
@@ -0,0 +1,65 @@
1
+ <script lang="ts" setup>
2
+ import { toRefs } from 'vue';
3
+ import { toggleChatWindowEventHook } from '../../composables/useEventHooks';
4
+ import ChatWindow from './ChatWindow.vue';
5
+ import SvgIcon from '../core/SvgIcon.vue';
6
+
7
+ type Props = {
8
+ hasNotifications: boolean;
9
+ }
10
+
11
+ const props = defineProps<Props>();
12
+
13
+ const { hasNotifications } = toRefs(props);
14
+ </script>
15
+
16
+ <template>
17
+ <div>
18
+ <div
19
+ class="launcher"
20
+ @click="toggleChatWindowEventHook.trigger()"
21
+ >
22
+ <SvgIcon icon="chat" />
23
+ </div>
24
+
25
+ <div
26
+ v-if="hasNotifications"
27
+ class="bell"
28
+ >
29
+ <SvgIcon icon="bell" />
30
+ </div>
31
+
32
+ <ChatWindow
33
+ @close="toggleChatWindowEventHook.trigger()"
34
+ />
35
+ </div>
36
+ </template>
37
+
38
+ <style scoped>
39
+ .launcher {
40
+ z-index: 9999;
41
+ width: 60px;
42
+ height: 60px;
43
+ background-position: center;
44
+ background-repeat: no-repeat;
45
+ position: fixed;
46
+ right: 75px;
47
+ bottom: 25px;
48
+ border-radius: 50%;
49
+ box-shadow: none;
50
+ transition: box-shadow 0.2s ease-in-out;
51
+ cursor: pointer;
52
+ }
53
+
54
+ .bell {
55
+ z-index: 9999;
56
+ position: fixed;
57
+ bottom: 60px;
58
+ right: 15px;
59
+ padding: 2px 0;
60
+ }
61
+
62
+ .bell svg {
63
+ height: 90px;
64
+ }
65
+ </style>