{"version":3,"file":"useChatPusher-fzMLxwdT.js","sources":["../../../app/assets/images/chat/tourhero_support.svg","../../../app/javascript/src/models/message.ts","../../../app/javascript/src/models/file_messsage.ts","../../../app/javascript/src/utils/chatUtils.js","../../../app/javascript/src/stores/channels.js","../../../node_modules/.pnpm/vue3-virtual-scroll-list@0.2.1_vue@3.5.13_typescript@5.8.2_/node_modules/vue3-virtual-scroll-list/dist/index.js","../../../app/javascript/src/components/Chat/ChatBox/ChatInput.vue","../../../app/javascript/src/components/Chat/ChatBox/ChatTitle.vue","../../../app/javascript/src/components/Chat/Message/SystemMessage.vue","../../../app/assets/images/chat/check.jpg","../../../app/javascript/src/components/Chat/Message/FileMessage.vue","../../../app/assets/images/chat/image_upload_error.jpg","../../../app/javascript/src/components/Chat/Message/ImageMessage.vue","../../../app/javascript/src/components/Chat/Message/ProductCardMessage.vue","../../../node_modules/.pnpm/highlight-words-core@1.2.3/node_modules/highlight-words-core/dist/index.js","../../../node_modules/.pnpm/vue-highlight-words@3.0.1_vue@3.5.13_typescript@5.8.2_/node_modules/vue-highlight-words/dist/vue-highlight-words.esm.js","../../../app/javascript/src/components/Chat/Message/TextMessage.vue","../../../app/javascript/src/components/Chat/Message/PromptedMessage.vue","../../../app/javascript/src/components/Chat/Message/UnreadMessageMarker.vue","../../../app/javascript/src/components/Chat/Message/Index.vue","../../../app/javascript/src/components/Chat/ChatBox/Index.vue","../../../app/javascript/src/components/Chat/ChatroomDetails/OperatorSection.vue","../../../app/javascript/src/components/Chat/ChatroomDetails/ChatroomMember.vue","../../../app/javascript/src/components/Chat/ChatroomDetails/InviteOthers.vue","../../../app/javascript/src/components/Chat/ChatroomDetails/ChatroomMembers.vue","../../../app/javascript/src/components/Chat/ChatroomDetails/MessageSearch.vue","../../../app/javascript/src/utils/momentUtils.js","../../../app/javascript/src/components/Chat/ChatroomDetails/SearchResult.vue","../../../app/javascript/src/components/Chat/ChatroomDetails/ItineraryRequestCard.vue","../../../app/javascript/src/components/Chat/ChatroomDetails/Itinerary.vue","../../../app/javascript/src/components/Chat/ChatroomDetails/Requirements.vue","../../../app/javascript/src/components/Chat/ChatroomDetails/Index.vue","../../../app/javascript/src/utils/pusher/useChatPusher.js"],"sourcesContent":["export default \"data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20fill='none'%20viewBox='0%200%2032%2033'%3e%3ccircle%20cx='16'%20cy='16.5'%20r='16'%20fill='%23D50037'/%3e%3cpath%20fill='%23fff'%20d='M18.58%2016.796c.167.732.242%201.604.242%202.66v.112l-.093.054a4.543%204.543%200%200%201-2.04.53%202.958%202.958%200%200%201-2.317-1.066l.26-.255c1.4%201.617%203.37.745%203.826.51-.005-1.104-.092-1.992-.29-2.712h-.01c-.006-.027-.01-.058-.016-.084-.439-1.49-1.38-2.246-3.117-2.72v-3.194c0-1.203.817-1.993%201.347-2.11.81-.18%201.606%200%202.184.984.2.34.304.927.352%201.285a.07.07%200%200%200%20.077.062l.676-.108c.122-.02.136-.024.127-.15a6.046%206.046%200%200%200-.066-.602c-.187-1.088-.772-1.87-1.709-2.37a3.763%203.763%200%200%200-1.211-.386%204.868%204.868%200%200%200-2.173.126c-.788.23-1.47.727-1.929%201.407-.463.68-.673%201.451-.69%202.278-.013.606-.01%201.452-.008%202.06V26.24h2.861v-.776c0-.764.481-1.363%201.271-1.363.687%200%201.186.472%201.186%201.363v.778h2.867v-5.287c.003-1.526-.173-3.415-1.607-4.16Zm-3.285-1.883a.341.341%200%201%201-.322.34.332.332%200%200%201%20.322-.34Z'/%3e%3c/svg%3e\"","import moment from 'moment'\nimport TourHeroSupport from 'app/assets/images/chat/tourhero_support.svg'\n\nexport const SendStatus = {\n  SUCCESS: \"SUCCESS\",\n  SENDING: \"SENDING\",\n  UPLOADING: \"UPLOADING\",\n  UPLOAD_COMPLETE: \"UPLOAD_COMPLETE\",\n  FAIL: \"FAIL\",\n  CANCELLED: \"CANCELLED\"\n} as const\n\ntype SendStatusEnum = typeof SendStatus[keyof typeof SendStatus]\n\nexport const TOURHERO_ADMIN_AVATAR = TourHeroSupport\nexport const DEFAULT_AVATAR = \"https://secure.gravatar.com/avatar/4b5ad43e3f4aa038e1021af85f661278.png?d=mp&r=PG\"\n\nexport default class Message {\n  id: string | number\n  content: string\n  senderName: string\n  senderId: string\n  tempId: string\n  createdAt: string\n  channelId: number\n  messageType: string\n  sendStatus: SendStatusEnum | null\n  displayName: boolean\n  updateMessageCallback: Function\n  error: string | null\n\n\n  constructor({ tempId, content, channelId, senderName, senderId, sendStatus, displayName, updateMessageCallback }) {\n    this.id = tempId\n    this.content = content\n    this.senderName = senderName\n    this.senderId = senderId\n    this.channelId = channelId\n    this.messageType = \"text\"\n    this.tempId = tempId\n    this.createdAt = moment.utc().format()\n    this.sendStatus = sendStatus || null\n    this.displayName = displayName\n    this.updateMessageCallback = updateMessageCallback\n    this.error = null\n  }\n\n\n  sendSucceeded() {\n    this.updateMessageCallback(this.channelId, this.id, \"sendStatus\", SendStatus.SUCCESS)\n  }\n\n  sendFailed(errorMessage) {\n    this.updateMessageCallback(this.channelId, this.id, \"sendStatus\", SendStatus.FAIL)\n    if (errorMessage) this.updateMessageCallback(this.channelId, this.id, \"error\", errorMessage)\n  }\n}","import Message, { SendStatus } from \"@/models/message\";\nimport { convertToBytes } from \"@/utils/numberUtils\";\n\nconst MAX_SIZE_MB = 20\nconst ALLOWED_IMAGE_TYPES = [\"image/png\", \"image/jpeg\", \"image/gif\"]\nconst ALLOWED_FILE_TYPES = [\"application/pdf\", \"application/vnd.ms-powerpoint\", \"application/vnd.openxmlformats-officedocument.presentationml.presentation\", \"video/mp4\"]\n\nexport class FileMessage extends Message {\n  files: Array<string>\n  messageType: string\n  progress: number\n  abortController: AbortController\n\n  constructor({ tempId, content, channelId, senderName, senderId, sendStatus, updateMessageCallback }, files, abortController) {\n    super({ tempId, content, channelId, senderName, senderId, sendStatus, displayName: false, updateMessageCallback })\n    this.files = files\n    this.progress = 1;\n    this.abortController = abortController\n    this.messageType = this.resolveMessageType(files)\n\n    this.validateFileSize(files)\n  }\n\n  sendSucceeded(attachments) {\n    this.updateMessageCallback(this.channelId, this.id, \"sendStatus\", SendStatus.SUCCESS)\n    if (this.messageType == \"file\") this.updateMessageCallback(this.channelId, this.id, \"attachments\", attachments)\n  }\n\n  sendFailed(errorMessage) {\n    this.updateMessageCallback(this.channelId, this.id, \"sendStatus\", SendStatus.FAIL)\n    if (errorMessage) { this.updateMessageCallback(this.channelId, this.id, \"error\", errorMessage) }\n  }\n\n  resolveMessageType(files) {\n    if (ALLOWED_IMAGE_TYPES.includes(files[0].type)) return \"image\";\n    if (ALLOWED_FILE_TYPES.includes(files[0].type)) return \"file\";\n\n    this.sendStatus = SendStatus.FAIL\n    this.error = `Unsupported file type`\n    return \"file\"\n  }\n\n  updateProgress(progress) {\n    this.updateMessageCallback(this.channelId, this.id, 'progress', progress)\n\n    if (progress == 100) {\n      this.updateMessageCallback(this.channelId, this.id, 'sendStatus', SendStatus.UPLOAD_COMPLETE)\n    }\n  }\n\n  cancel() {\n    this.abortController.abort()\n    this.updateMessageCallback(this.channelId, this.id, \"sendStatus\", SendStatus.FAIL)\n    this.updateMessageCallback(this.channelId, this.id, \"error\", \"File upload has been cancelled.\")\n  }\n\n  validateFileSize(files) {\n    const max = convertToBytes(`${MAX_SIZE_MB}mb`)\n\n    if (files[0].size > max) {\n      this.sendStatus = SendStatus.FAIL\n      this.error = `File size exceeds ${MAX_SIZE_MB}MB limit`\n    }\n  }\n}","// utility function to generate temp keys used on Front end\n// keys needs to be sequential as they are used to order messages\n// tempId takes last_message_id (e.g. 185) or another previously generated tempId (e.g. 290-2)\n// and provides the next suitable sequence tempId (e.g. 185-1, 290-3)\nexport const generateTempId = (last_message_id) => {\n  const idParts = last_message_id.toString().split('-');\n\n  if (idParts.length === 1) {\n    const id = parseInt(idParts[0], 10);\n    return `${id}-1`;\n  } else {\n    const id = parseInt(idParts[0], 10);\n    const subId = parseInt(idParts[1], 10);\n    return `${id}-${subId + 1}`;\n  }\n}","import { isEmpty, keyBy, orderBy, uniqBy } from 'lodash';\nimport { AxiosError } from 'axios';\nimport { camelizeKeys } from 'humps';\nimport { defineStore } from \"pinia\";\nimport Message, { SendStatus, DEFAULT_AVATAR, TOURHERO_ADMIN_AVATAR } from '@/models/message';\nimport { FileMessage } from '@/models/file_messsage';\nimport api from '@/utils/api.js';\nimport { generateTempId } from 'app/javascript/src/utils/chatUtils';\nimport { deserializeJsonApi } from '@/utils/jsonApiDeserializer.js';\nimport { until } from \"@vueuse/core\";\n\nexport const useChannelsStore = defineStore('channels', {\n  state: () => ({\n    alias: null,\n    currentChannelId: null,\n    profiles: {},\n    readStatus: {},\n    channels: [],\n    products: {},\n    itineraryRequests: {},\n    userMembers: {},\n    operatorMembers: {},\n    messages: {},\n    isFetchingNext: false,\n    isSearchOpen: false,\n    searchString: \"\",\n    searchSelection: null,\n    searchResults: [],\n    pusher: null,\n    messageScroller: null,\n    isMobileView: false,\n    openMobileDetails: false,\n    isModalOpen: false\n  }),\n\n  getters: {\n    getCurrentChannel(state) {\n      return state.channels.find((chatroom) => chatroom.id == state.currentChannelId)\n    },\n    getProfileName(state) {\n      return isEmpty(state.profiles) ? '' : state.profiles.own.name ?? state.alias\n    },\n    getCurrentChannelName(state) {\n      return state.channels.find((chatroom) => chatroom.id == state.currentChannelId)?.name ?? \"TourHero Support\"\n    },\n    getChannelPreviousMessage: (state) => (chatroomId, ownIndex) => {\n      return state.messages[chatroomId][ownIndex - 1]\n    },\n    getChannelMessages: (state) => (chatroomId) => {\n      return state.messages[chatroomId] ?? []\n    },\n    getCurrentChannelMessages(state) {\n      return state.messages[state.currentChannelId?.toString()] ?? []\n    },\n    getChannelMessageIndex: (state) => (id) => {\n      return state.messages[state.currentChannelId?.toString()].findIndex((message) => message.id == id)\n    },\n    getChannelUnreadMessageIndex(state) {\n      const unreadIndex = state.messages[state.currentChannelId?.toString()]?.findIndex((message) => message.firstUnread)\n      return unreadIndex == -1 ? null : unreadIndex\n    },\n    getChannelLastMessage: (state) => (chatroomId) => {\n      return state.channels.find((chatroom) => chatroom.id == chatroomId)?.lastMessage\n    },\n    getChannelCountry: (state) => (chatroomId) => {\n      const chatroom = state.channels.find((chatroom) => chatroom.id == chatroomId)\n      return chatroom?.product?.itinerary?.targetCountryName ?? chatroom?.itineraryRequest?.country ?? null\n    },\n    getChannelMemberCount: (state) => (chatroomId) => {\n      const userCount = Object.keys(state.userMembers[chatroomId.toString()] ?? {}).length\n      const operatorCount = Object.keys(state.operatorMembers[chatroomId.toString()] ?? {}).length\n\n      return userCount + operatorCount\n    },\n    getMembersProfile(state) {\n      if (!state.currentChannelId) return {};\n\n      const userProfiles = state.userMembers[state.currentChannelId] ?? []\n      const operatorProfiles = state.operatorMembers[state.currentChannelId] ?? []\n      return { ...userProfiles, ...operatorProfiles }\n    },\n    getItineraryRequest(state) {\n      if (!state.currentChannelId) return null;\n\n      return state.itineraryRequests[state.currentChannelId] ?? null\n    },\n    getProduct(state) {\n      if (!state.currentChannelId) return null;\n\n      return state.products[state.currentChannelId] ?? null\n    },\n    getChannel: (state) => (id) => {\n      return state.channels.find((chatroom) => chatroom.id == id) ?? null\n    },\n    getMessageAvatar: (state) => (chatroomId, senderId, senderName, supplierId) => {\n      if (!senderId || senderName.includes(\"TourHero -\")) return TOURHERO_ADMIN_AVATAR;\n      if (supplierId) return state.operatorMembers[chatroomId][supplierId]?.avatar ?? DEFAULT_AVATAR;\n      if (senderId) return state.userMembers[chatroomId][senderId]?.avatar ?? DEFAULT_AVATAR;\n      return DEFAULT_AVATAR\n    },\n    getChannelReadStatus: (state) => (chatroomId) => {\n      if (!chatroomId) return true;\n      return state.readStatus[chatroomId]\n    },\n    getChannelLastReadMessageId: (state) => (chatroomId) => {\n      if (!chatroomId) return undefined;\n      return state.channels.find((chatroom) => chatroom.id == chatroomId)?.lastMessage?.id\n    },\n    hasReadAllMessages: (state) => (chatroomId) => {\n      if (!chatroomId) return true;\n      return state.readStatus[chatroomId.toString()].all_read\n    },\n    isCurrentChannelActive(state) {\n      return state.channels.find((chatroom) => chatroom.id == state.currentChannelId)?.active\n    },\n    isLastMessageFetched(state) {\n      const currentChatroomLastMessage = state.channels.find((chatroom) => chatroom.id == state.currentChannelId)?.lastMessage\n      if (!currentChatroomLastMessage) return true;\n\n      return !!state.messages[state.currentChannelId]?.find((message) => message.id == currentChatroomLastMessage.id)\n    }\n  },\n  actions: {\n    setCurrentChannel(id) {\n      this.currentChannelId = id\n      this.isSearchOpen = false\n      this.searchString = \"\"\n    },\n    closeSearch() {\n      this.isSearchOpen = false\n      this.searchString = \"\"\n    },\n    clearSearch() {\n      this.searchString = \"\"\n      this.searchResults = []\n    },\n    initializeMessageScroller(scroller) {\n      this.messageScoller = scroller\n    },\n    setChannelLastMessage(message, chatroomId) {\n      const chatroom = this.channels.find((chatroom) => chatroom.id == chatroomId)\n      chatroom.lastMessage = message\n    },\n    setChatroomMessages(messages, chatroomId) {\n      this.messages[chatroomId] = uniqBy(messages, 'id')\n    },\n    setHideChannelScrollTop(chatroomId, boolean) {\n      this.readStatus[chatroomId] = { ...this.readStatus[chatroomId], hideScrollTop: boolean }\n    },\n    setHideChannelScrollBottom(chatroomId, boolean) {\n      this.readStatus[chatroomId] = { ...this.readStatus[chatroomId], hideScrollBottom: boolean }\n    },\n    setIsViewingPastMessages(chatroomId, boolean) {\n      this.readStatus[chatroomId.toString()] = { ...this.readStatus[chatroomId], isViewingPastMessages: boolean }\n    },\n    setChannelAllRead(chatroomId, boolean) {\n      this.readStatus[chatroomId.toString()] = { ...this.readStatus[chatroomId], all_read: boolean }\n    },\n    setSearchSelection(searchResultIndex) {\n      this.searchSelection = searchResultIndex\n    },\n    setChannelData(channels, autoLoadFirstChannel = true) {\n      this.channels = orderBy(channels, [(chatroom) => chatroom.lastMessage?.createdAt || \"\", 'createdAt'], ['desc', 'desc'])\n\n      this.channels.forEach((channel) => {\n        if (channel.userMembers) this.userMembers[channel.id] = { ...this.userMembers[channel.id], ...keyBy(channel.userMembers, 'id') }\n        if (channel.operatorMembers) this.operatorMembers[channel.id] = { ...this.operatorMembers[channel.id], ...keyBy(channel.operatorMembers, 'id') }\n        if (channel.product) this.products[channel.id] = { ...channel.product, event: channel.product.displayableEvent }\n        if (channel.itineraryRequest) this.itineraryRequests[channel.id] = channel.itineraryRequest\n      })\n\n      if (this.channels.length && autoLoadFirstChannel && !this.isMobileView) this.currentChannelId = this.channels[0].id\n    },\n    async fetchChannelMessages(chatroom_id) {\n      const results = await api.get(`/api/chatrooms/${chatroom_id}/messages/latest_messages`)\n      const messages = await deserializeJsonApi(results.data)\n      this.setChatroomMessages(uniqBy(messages, 'id'), chatroom_id)\n    },\n    async getChannelUnreadMessages() {\n      const results = await api.get(`/api/chatrooms/${this.currentChannelId}/messages/unread_messages`)\n      const messages = await deserializeJsonApi(results.data)\n      this.setChatroomMessages(uniqBy(messages, 'id'), this.currentChannelId)\n    },\n    toggleOpenMobileDetails() {\n      this.openMobileDetails = !this.openMobileDetails\n    },\n    async addNewChannel(payload) {\n      const channel = await deserializeJsonApi(payload)\n\n      // re-added into only chatroom\n      if (this.channels?.some((chatroom) => chatroom.id == channel.id) && this.channels.length == 1) {\n        window.location.reload()\n        return\n      };\n\n      this.channels = this.channels.filter((existingChannel) => existingChannel.id != channel.id)\n\n      this.channels = [channel, ...this.channels]\n      this.messages[channel.id] = []\n      this.readStatus[channel.id] = payload.meta.read_status\n\n      if (channel.userMembers) this.userMembers[channel.id] = keyBy(channel.userMembers, 'id')\n      if (channel.operatorMembers) this.operatorMembers[channel.id] = keyBy(channel.operatorMembers, 'id')\n      if (channel.product) this.products[channel.id] = { ...channel.product, event: channel.product?.displayableEvent };\n      if (channel.itineraryRequest) this.itineraryRequests[channel.id] = channel.itineraryRequest\n    },\n    async removeChannel(payload) {\n      const removedChannel = await deserializeJsonApi(payload)\n      const chatroom = this.channels.find((chatroom) => chatroom.id == removedChannel.id)\n\n      if (!chatroom) return;\n\n      chatroom.active = false\n    },\n    addNewMessage(payload) {\n      const camelizedPayload = camelizeKeys(payload)\n      const chatroomMessages = this.messages[camelizedPayload.meta.chatroomId]\n      const own_message = chatroomMessages?.find((message) => message.id == camelizedPayload.meta.tempId)\n\n      const lastMessage = this.getChannelLastMessage(camelizedPayload.meta.chatroomId)\n\n      if (own_message) {\n        own_message.sendSucceeded()\n      } else {\n        const newMessagePayload = { ...camelizedPayload.message, displayName: lastMessage.senderId !== camelizedPayload.message.senderId }\n        const isLastMessageFetched = this.isLastMessageFetched\n        const isViewingPastMessages = this.readStatus[this.currentChannelId]['isViewingPastMessages']\n\n        if (chatroomMessages) {\n          this.messages[camelizedPayload.meta.chatroomId] = this.messages[camelizedPayload.meta.chatroomId].concat(newMessagePayload)\n        }\n\n        this.setChannelLastMessage(newMessagePayload, camelizedPayload.meta.chatroomId)\n        this.setChannelAllRead(camelizedPayload.meta.chatroomId, false)\n\n        if (isLastMessageFetched && !isViewingPastMessages && camelizedPayload.meta.chatroomId == this.currentChannelId) {\n          setTimeout(() => {\n            this.messageScroller.scrollToBottom()\n            this.setChannelAllRead(camelizedPayload.meta.chatroomId, true)\n          }, 400)\n        }\n      }\n    },\n    updateChatroomName(payload) {\n      const camelizedPayload = camelizeKeys(payload)\n      const chatroom = this.channels.find((chatroom) => chatroom.id == camelizedPayload.meta.chatroomId)\n\n      chatroom.name = camelizedPayload.chatName\n    },\n    async updateChatroomMembers(payload) {\n      const data = await deserializeJsonApi(payload)\n      this.userMembers[payload.meta.chatroom_id] = keyBy(data.userMembers, 'id')\n      this.operatorMembers[payload.meta.chatroom_id] = keyBy(data.operatorMembers, 'id')\n    },\n    async updateChatroomAssociations(payload) {\n      const chatroom = this.channels.find((chatroom) => chatroom.id == payload.meta.chatroom_id)\n\n      if (!payload.data) {\n        if (payload.meta.association_name === \"Product\") delete this.products[chatroom.id]\n        if (payload.meta.association_name === \"ItineraryRequest\") delete this.itineraryRequests[chatroom.id]\n      } else {\n        const data = await deserializeJsonApi(payload)\n\n        if (payload.meta.association_name === \"Product\") this.products[chatroom.id] = { ...data, event: data?.displayableEvent };\n        if (payload.meta.association_name === \"ItineraryRequest\") this.itineraryRequests[chatroom.id] = data;\n      }\n    },\n    async fetchUserChannels() {\n      const result = await api.get('/api/chatrooms')\n      const data = await deserializeJsonApi(result.data)\n\n      this.alias = result.data.meta.alias\n      this.profiles = result.data.meta.profiles\n      this.readStatus = result.data.meta.read_status\n      this.setChannelData(data)\n\n      return { meta: result.data.meta, data: data }\n    },\n    async sendMessage(text) {\n      if (!text) return;\n\n      const latestChatroomMessage = this.getChannelLastMessage(this.currentChannelId)\n      const tempId = generateTempId(latestChatroomMessage?.id ?? 0)\n      const isViewingPastMessages = this.readStatus[this.currentChannelId]['isViewingPastMessages']\n      const textMessage = new Message({\n        tempId,\n        content: text,\n        channelId: this.currentChannelId,\n        senderName: this.alias,\n        senderId: this.profiles.own.slug,\n        sendStatus: SendStatus.SENDING,\n        displayName: latestChatroomMessage ? latestChatroomMessage.senderId !== this.profiles.own.slug : true,\n        updateMessageCallback: this.updateMessage\n      })\n\n      if (isViewingPastMessages) {\n        await this.fetchChannelMessages(this.currentChannelId)\n        this.setIsViewingPastMessages(this.currentChannelId, false)\n      }\n\n      this.messages[this.currentChannelId] = this.messages[this.currentChannelId].concat(textMessage)\n      this.setChannelLastMessage(textMessage, this.currentChannelId)\n      setTimeout(() => this.messageScroller.scrollToBottom(), 400)\n\n      // we do not need to wait for promise to resolve as we will be getting response via pusher\n      api.post(`/api/chatrooms/${this.currentChannelId}/messages`, { temp_id: tempId, content: text, sender_name: this.alias })\n    },\n    async sendMessasgeOnChannelReady(text) {\n      until(() => this.messages[this.currentChannelId]).toBeTruthy().then(() => this.sendMessage(text));\n    },\n    async sendAttachment(files, abortController) {\n      const latestChatroomMessage = this.getChannelLastMessage(this.currentChannelId)\n      const tempId = generateTempId(latestChatroomMessage?.id ?? 0)\n      const isViewingPastMessages = this.readStatus[this.currentChannelId]['isViewingPastMessages']\n      const fileMessage = new FileMessage({\n        tempId,\n        content: \"\",\n        channelId: this.currentChannelId,\n        senderName: this.alias,\n        senderId: this.profiles.own.slug,\n        sendStatus: SendStatus.UPLOADING,\n        updateMessageCallback: this.updateMessage\n      }, files, abortController)\n\n      if (isViewingPastMessages) {\n        await this.fetchChannelMessages(this.currentChannelId)\n        this.setIsViewingPastMessages(this.currentChannelId, false)\n      }\n\n      this.messages[this.currentChannelId] = this.messages[this.currentChannelId].concat(fileMessage)\n      setTimeout(() => this.messageScroller.scrollToBottom(), 400)\n\n      try {\n        const result = await api.post(`/api/chatrooms/${this.currentChannelId}/messages/attach`, { temp_id: tempId, content: \"\", sender_name: this.alias, files: files }, {\n          signal: abortController.signal,\n          headers: { 'Content-Type': 'multipart/form-data' },\n          onUploadProgress: function (progressEvent) {\n            fileMessage.updateProgress(Math.round((progressEvent.loaded * 100) / progressEvent.total))\n          },\n        })\n        const data = await deserializeJsonApi(result.data)\n        fileMessage.sendSucceeded(data.attachments)\n      } catch (e) {\n        if (e instanceof AxiosError && e.response?.data?.error) {\n          fileMessage.sendFailed(e.response.data.error)\n        } else {\n          fileMessage.sendFailed(\"Something went wrong, please try again.\")\n        }\n      }\n    },\n    cancelAttachment(messageId) {\n      const fileMessage = this.messages[this.currentChannelId].find((message) => message.id == messageId)\n      fileMessage.cancel()\n    },\n    updateMessage(channelId, messageId, property, newValue) {\n      const message = this.messages[channelId.toString()]?.find((message) => message.id == messageId)\n      message[property] = newValue\n    },\n    async read(chatroomId) {\n      const response = await api.put(`/api/chatrooms/${chatroomId}/messages/read`)\n      this.readStatus[chatroomId] = { ...this.readStatus[chatroomId], ...response.data.read_status }\n    },\n    async fetchPrevious(messageId, trigger) {\n      this.isFetchingNext = true\n\n      // mark trigger as fetched to prevent re-fetching\n      this.updateMessage(this.currentChannelId, messageId, \"trigger\", { ...trigger, fetched: true })\n\n      const results = await api.get(`/api/chatrooms/${this.currentChannelId}/messages/fetch_previous`, { params: { cursor: trigger.batchCursor } })\n      const messages = await deserializeJsonApi(results.data)\n\n      this.messages[this.currentChannelId] = orderBy(uniqBy([...messages, ...this.messages[this.currentChannelId]], 'id'), [(message) => parseInt(message.id)], ['asc'])\n\n      this.isFetchingNext = false\n    },\n    async fetchNext(messageId, trigger) {\n      this.isFetchingNext = true\n\n      // mark trigger as fetched to prevent re-fetching\n      this.updateMessage(this.currentChannelId, messageId, \"trigger\", { ...trigger, fetched: true })\n\n      const results = await api.get(`/api/chatrooms/${this.currentChannelId}/messages/fetch_next`, { params: { cursor: trigger.batchCursor } })\n      const messages = await deserializeJsonApi(results.data)\n\n      this.messages[this.currentChannelId] = orderBy(uniqBy([...this.messages[this.currentChannelId], ...messages], 'id'), [(message) => parseInt(message.id)], ['asc'])\n\n      this.isFetchingNext = false\n    },\n    async search(searchString) {\n      const results = await api.get(`/api/chatrooms/${this.currentChannelId}/messages/search`, { params: { search: searchString } })\n      const messages = await deserializeJsonApi(results.data)\n\n      this.isSearchOpen = true\n      this.searchResults = [...messages]\n      this.searchSelection = null\n    },\n    async searchResultMessages(resultId) {\n      const result = await api.get(`/api/chatrooms/${this.currentChannelId}/messages/${resultId}/search_result`)\n      const searchResult = await deserializeJsonApi(result.data)\n      this.messages[this.currentChannelId] = [...searchResult.beforeMessages, searchResult, ...searchResult.afterMessages]\n\n      // we add an extra offset because the message sometimes ends up outside (above) of\n      // scroller, due to variable height image / product cards\n      const scrollIndexWithOffset = Math.max(searchResult.beforeMessages?.length - 2, 0)\n\n      if (this.isMobileView) {\n        this.openMobileDetails = false\n\n        setTimeout(() => {\n          const scrollIndex = this.messages[this.currentChannelId]?.findIndex((message) => message.id === searchResult.id)\n          this.messageScroller.scrollToIndex(scrollIndex ?? scrollIndexWithOffset);\n        }, 700)\n      } else {\n        setTimeout(() => this.messageScroller.scrollToIndex(scrollIndexWithOffset), 700)\n      }\n    },\n    async searchWithResultIndex(index) {\n      if (index < 0 || index >= this.searchResults.length) return;\n\n      const searchMessageId = this.searchResults[index].id\n\n      const result = await api.get(`/api/chatrooms/${this.currentChannelId}/messages/${searchMessageId}/search_result`)\n      const searchResult = await deserializeJsonApi(result.data)\n\n      // we add an extra offset because the message sometimes ends up outside (above) of\n      // scroller, due to variable height image / product cards\n      const scrollIndexWithOffset = Math.max(searchResult.beforeMessages?.length - 2, 0)\n\n      this.messages[this.currentChannelId] = [...searchResult.beforeMessages, searchResult, ...searchResult.afterMessages]\n\n      if (this.messageScroller) setTimeout(() => this.messageScroller.scrollToIndex(scrollIndexWithOffset), 700);\n    },\n    async sendInvites(user_emails) {\n      const result = await api.post(`/api/chatrooms/${this.currentChannelId}/invite_members`, { user_emails: user_emails })\n      const data = await deserializeJsonApi(result.data)\n\n      if (data.userMembers) this.userMembers[this.currentChannelId] = data.userMembers\n    },\n    async getProductCardDetails(product_id) {\n      const result = await api.get(`/api/chatrooms/${this.currentChannelId}/messages/product_card_details`, { params: { product_id: product_id } })\n      return await deserializeJsonApi(result.data)\n    },\n    async initializeChatModal(itineraryRequestId) {\n      const result = await api.post('/api/chatrooms', {\n        chatroom: {\n          itinerary_request_id: itineraryRequestId\n        }\n      });\n\n      const data = await deserializeJsonApi(result.data);\n      this.alias = result.data.meta.alias;\n      this.profiles = result.data.meta.profiles;\n      this.readStatus = result.data.meta.read_status;\n      this.setChannelData(data, false);\n    },\n    closeChatModal() {\n      this.isModalOpen = false;\n    },\n    openChatModal() {\n      this.isModalOpen = true;\n    },\n    toggleChatModal() {\n      this.isModalOpen = !this.isModalOpen;\n    },\n  }\n},)\n","/**\n* vue3-virtual-scroll-list v0.2.1\n* open source under the MIT license\n* https://github.com/reactjser/vue3-virtual-scroll-list#readme\n*/\nimport { defineComponent, ref, createVNode, computed, onMounted, onUpdated, onUnmounted, watch, onBeforeMount, onActivated } from 'vue';\n\nfunction ownKeys(object, enumerableOnly) {\n  var keys = Object.keys(object);\n\n  if (Object.getOwnPropertySymbols) {\n    var symbols = Object.getOwnPropertySymbols(object);\n\n    if (enumerableOnly) {\n      symbols = symbols.filter(function (sym) {\n        return Object.getOwnPropertyDescriptor(object, sym).enumerable;\n      });\n    }\n\n    keys.push.apply(keys, symbols);\n  }\n\n  return keys;\n}\n\nfunction _objectSpread2(target) {\n  for (var i = 1; i < arguments.length; i++) {\n    var source = arguments[i] != null ? arguments[i] : {};\n\n    if (i % 2) {\n      ownKeys(Object(source), true).forEach(function (key) {\n        _defineProperty(target, key, source[key]);\n      });\n    } else if (Object.getOwnPropertyDescriptors) {\n      Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));\n    } else {\n      ownKeys(Object(source)).forEach(function (key) {\n        Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));\n      });\n    }\n  }\n\n  return target;\n}\n\nfunction _classCallCheck(instance, Constructor) {\n  if (!(instance instanceof Constructor)) {\n    throw new TypeError(\"Cannot call a class as a function\");\n  }\n}\n\nfunction _defineProperties(target, props) {\n  for (var i = 0; i < props.length; i++) {\n    var descriptor = props[i];\n    descriptor.enumerable = descriptor.enumerable || false;\n    descriptor.configurable = true;\n    if (\"value\" in descriptor) descriptor.writable = true;\n    Object.defineProperty(target, descriptor.key, descriptor);\n  }\n}\n\nfunction _createClass(Constructor, protoProps, staticProps) {\n  if (protoProps) _defineProperties(Constructor.prototype, protoProps);\n  if (staticProps) _defineProperties(Constructor, staticProps);\n  return Constructor;\n}\n\nfunction _defineProperty(obj, key, value) {\n  if (key in obj) {\n    Object.defineProperty(obj, key, {\n      value: value,\n      enumerable: true,\n      configurable: true,\n      writable: true\n    });\n  } else {\n    obj[key] = value;\n  }\n\n  return obj;\n}\n\nfunction _toConsumableArray(arr) {\n  return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();\n}\n\nfunction _arrayWithoutHoles(arr) {\n  if (Array.isArray(arr)) return _arrayLikeToArray(arr);\n}\n\nfunction _iterableToArray(iter) {\n  if (typeof Symbol !== \"undefined\" && iter[Symbol.iterator] != null || iter[\"@@iterator\"] != null) return Array.from(iter);\n}\n\nfunction _unsupportedIterableToArray(o, minLen) {\n  if (!o) return;\n  if (typeof o === \"string\") return _arrayLikeToArray(o, minLen);\n  var n = Object.prototype.toString.call(o).slice(8, -1);\n  if (n === \"Object\" && o.constructor) n = o.constructor.name;\n  if (n === \"Map\" || n === \"Set\") return Array.from(o);\n  if (n === \"Arguments\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);\n}\n\nfunction _arrayLikeToArray(arr, len) {\n  if (len == null || len > arr.length) len = arr.length;\n\n  for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];\n\n  return arr2;\n}\n\nfunction _nonIterableSpread() {\n  throw new TypeError(\"Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\");\n}\n\n/**\n * virtual list core calculating center\n */\nvar DIRECTION_TYPE = {\n  FRONT: 'FRONT',\n  // scroll up or left\n  BEHIND: 'BEHIND' // scroll down or right\n\n};\nvar CALC_TYPE = {\n  INIT: 'INIT',\n  FIXED: 'FIXED',\n  DYNAMIC: 'DYNAMIC'\n};\nvar LEADING_BUFFER = 2;\n\nvar Virtual = /*#__PURE__*/function () {\n  function Virtual(param, callUpdate) {\n    _classCallCheck(this, Virtual);\n\n    this.init(param, callUpdate);\n  }\n\n  _createClass(Virtual, [{\n    key: \"init\",\n    value: function init(param, callUpdate) {\n      // param data\n      this.param = param;\n      this.callUpdate = callUpdate; // size data\n\n      this.sizes = new Map();\n      this.firstRangeTotalSize = 0;\n      this.firstRangeAverageSize = 0;\n      this.lastCalcIndex = 0;\n      this.fixedSizeValue = 0;\n      this.calcType = CALC_TYPE.INIT; // scroll data\n\n      this.offset = 0;\n      this.direction = ''; // range data\n\n      this.range = Object.create(null);\n\n      if (param) {\n        this.checkRange(0, param.keeps - 1);\n      } // benchmark test data\n      // this.__bsearchCalls = 0\n      // this.__getIndexOffsetCalls = 0\n\n    }\n  }, {\n    key: \"destroy\",\n    value: function destroy() {\n      this.init(null, null);\n    } // return current render range\n\n  }, {\n    key: \"getRange\",\n    value: function getRange() {\n      var range = Object.create(null);\n      range.start = this.range.start;\n      range.end = this.range.end;\n      range.padFront = this.range.padFront;\n      range.padBehind = this.range.padBehind;\n      return range;\n    }\n  }, {\n    key: \"isBehind\",\n    value: function isBehind() {\n      return this.direction === DIRECTION_TYPE.BEHIND;\n    }\n  }, {\n    key: \"isFront\",\n    value: function isFront() {\n      return this.direction === DIRECTION_TYPE.FRONT;\n    } // return start index offset\n\n  }, {\n    key: \"getOffset\",\n    value: function getOffset(start) {\n      return (start < 1 ? 0 : this.getIndexOffset(start)) + this.param.slotHeaderSize;\n    }\n  }, {\n    key: \"updateParam\",\n    value: function updateParam(key, value) {\n      var _this = this;\n\n      if (this.param && key in this.param) {\n        // if uniqueIds change, find out deleted id and remove from size map\n        if (key === 'uniqueIds') {\n          this.sizes.forEach(function (v, key) {\n            if (!value.includes(key)) {\n              _this.sizes[\"delete\"](key);\n            }\n          });\n        }\n\n        this.param[key] = value;\n      }\n    } // save each size map by id\n\n  }, {\n    key: \"saveSize\",\n    value: function saveSize(id, size) {\n      this.sizes.set(id, size); // we assume size type is fixed at the beginning and remember first size value\n      // if there is no size value different from this at next comming saving\n      // we think it's a fixed size list, otherwise is dynamic size list\n\n      if (this.calcType === CALC_TYPE.INIT) {\n        this.fixedSizeValue = size;\n        this.calcType = CALC_TYPE.FIXED;\n      } else if (this.calcType === CALC_TYPE.FIXED && this.fixedSizeValue !== size) {\n        this.calcType = CALC_TYPE.DYNAMIC; // it's no use at all\n\n        delete this.fixedSizeValue;\n      } // calculate the average size only in the first range\n\n\n      if (this.calcType !== CALC_TYPE.FIXED && typeof this.firstRangeTotalSize !== 'undefined') {\n        if (this.sizes.size < Math.min(this.param.keeps, this.param.uniqueIds.length)) {\n          this.firstRangeTotalSize = _toConsumableArray(this.sizes.values()).reduce(function (acc, val) {\n            return acc + val;\n          }, 0);\n          this.firstRangeAverageSize = Math.round(this.firstRangeTotalSize / this.sizes.size);\n        } else {\n          // it's done using\n          delete this.firstRangeTotalSize;\n        }\n      }\n    } // in some special situation (e.g. length change) we need to update in a row\n    // try goiong to render next range by a leading buffer according to current direction\n\n  }, {\n    key: \"handleDataSourcesChange\",\n    value: function handleDataSourcesChange() {\n      var start = this.range.start;\n\n      if (this.isFront()) {\n        start = start - LEADING_BUFFER;\n      } else if (this.isBehind()) {\n        start = start + LEADING_BUFFER;\n      }\n\n      start = Math.max(start, 0);\n      this.updateRange(this.range.start, this.getEndByStart(start));\n    } // when slot size change, we also need force update\n\n  }, {\n    key: \"handleSlotSizeChange\",\n    value: function handleSlotSizeChange() {\n      this.handleDataSourcesChange();\n    } // calculating range on scroll\n\n  }, {\n    key: \"handleScroll\",\n    value: function handleScroll(offset) {\n      this.direction = offset < this.offset ? DIRECTION_TYPE.FRONT : DIRECTION_TYPE.BEHIND;\n      this.offset = offset;\n\n      if (!this.param) {\n        return;\n      }\n\n      if (this.direction === DIRECTION_TYPE.FRONT) {\n        this.handleFront();\n      } else if (this.direction === DIRECTION_TYPE.BEHIND) {\n        this.handleBehind();\n      }\n    } // ----------- public method end -----------\n\n  }, {\n    key: \"handleFront\",\n    value: function handleFront() {\n      var overs = this.getScrollOvers(); // should not change range if start doesn't exceed overs\n\n      if (overs > this.range.start) {\n        return;\n      } // move up start by a buffer length, and make sure its safety\n\n\n      var start = Math.max(overs - this.param.buffer, 0);\n      this.checkRange(start, this.getEndByStart(start));\n    }\n  }, {\n    key: \"handleBehind\",\n    value: function handleBehind() {\n      var overs = this.getScrollOvers(); // range should not change if scroll overs within buffer\n\n      if (overs < this.range.start + this.param.buffer) {\n        return;\n      }\n\n      this.checkRange(overs, this.getEndByStart(overs));\n    } // return the pass overs according to current scroll offset\n\n  }, {\n    key: \"getScrollOvers\",\n    value: function getScrollOvers() {\n      // if slot header exist, we need subtract its size\n      var offset = this.offset - this.param.slotHeaderSize;\n\n      if (offset <= 0) {\n        return 0;\n      } // if is fixed type, that can be easily\n\n\n      if (this.isFixedType()) {\n        return Math.floor(offset / this.fixedSizeValue);\n      }\n\n      var low = 0;\n      var middle = 0;\n      var middleOffset = 0;\n      var high = this.param.uniqueIds.length;\n\n      while (low <= high) {\n        // this.__bsearchCalls++\n        middle = low + Math.floor((high - low) / 2);\n        middleOffset = this.getIndexOffset(middle);\n\n        if (middleOffset === offset) {\n          return middle;\n        } else if (middleOffset < offset) {\n          low = middle + 1;\n        } else if (middleOffset > offset) {\n          high = middle - 1;\n        }\n      }\n\n      return low > 0 ? --low : 0;\n    } // return a scroll offset from given index, can efficiency be improved more here?\n    // although the call frequency is very high, its only a superposition of numbers\n\n  }, {\n    key: \"getIndexOffset\",\n    value: function getIndexOffset(givenIndex) {\n      if (!givenIndex) {\n        return 0;\n      }\n\n      var offset = 0;\n      var indexSize = 0;\n\n      for (var index = 0; index < givenIndex; index++) {\n        // this.__getIndexOffsetCalls++\n        indexSize = this.sizes.get(this.param.uniqueIds[index]);\n        offset = offset + (typeof indexSize === 'number' ? indexSize : this.getEstimateSize());\n      } // remember last calculate index\n\n\n      this.lastCalcIndex = Math.max(this.lastCalcIndex, givenIndex - 1);\n      this.lastCalcIndex = Math.min(this.lastCalcIndex, this.getLastIndex());\n      return offset;\n    } // is fixed size type\n\n  }, {\n    key: \"isFixedType\",\n    value: function isFixedType() {\n      return this.calcType === CALC_TYPE.FIXED;\n    } // return the real last index\n\n  }, {\n    key: \"getLastIndex\",\n    value: function getLastIndex() {\n      return this.param.uniqueIds.length - 1;\n    } // in some conditions range is broke, we need correct it\n    // and then decide whether need update to next range\n\n  }, {\n    key: \"checkRange\",\n    value: function checkRange(start, end) {\n      var keeps = this.param.keeps;\n      var total = this.param.uniqueIds.length; // datas less than keeps, render all\n\n      if (total <= keeps) {\n        start = 0;\n        end = this.getLastIndex();\n      } else if (end - start < keeps - 1) {\n        // if range length is less than keeps, corrent it base on end\n        start = end - keeps + 1;\n      }\n\n      if (this.range.start !== start) {\n        this.updateRange(start, end);\n      }\n    } // setting to a new range and rerender\n\n  }, {\n    key: \"updateRange\",\n    value: function updateRange(start, end) {\n      this.range.start = start;\n      this.range.end = end;\n      this.range.padFront = this.getPadFront();\n      this.range.padBehind = this.getPadBehind();\n      this.callUpdate(this.getRange());\n    } // return end base on start\n\n  }, {\n    key: \"getEndByStart\",\n    value: function getEndByStart(start) {\n      var theoryEnd = start + this.param.keeps - 1;\n      var truelyEnd = Math.min(theoryEnd, this.getLastIndex());\n      return truelyEnd;\n    } // return total front offset\n\n  }, {\n    key: \"getPadFront\",\n    value: function getPadFront() {\n      if (this.isFixedType()) {\n        return this.fixedSizeValue * this.range.start;\n      } else {\n        return this.getIndexOffset(this.range.start);\n      }\n    } // return total behind offset\n\n  }, {\n    key: \"getPadBehind\",\n    value: function getPadBehind() {\n      var end = this.range.end;\n      var lastIndex = this.getLastIndex();\n\n      if (this.isFixedType()) {\n        return (lastIndex - end) * this.fixedSizeValue;\n      } // if it's all calculated, return the exactly offset\n\n\n      if (this.lastCalcIndex === lastIndex) {\n        return this.getIndexOffset(lastIndex) - this.getIndexOffset(end);\n      } else {\n        // if not, use a estimated value\n        return (lastIndex - end) * this.getEstimateSize();\n      }\n    } // get the item estimate size\n\n  }, {\n    key: \"getEstimateSize\",\n    value: function getEstimateSize() {\n      return this.isFixedType() ? this.fixedSizeValue : this.firstRangeAverageSize || this.param.estimateSize;\n    }\n  }]);\n\n  return Virtual;\n}();\n\n/**\n * props declaration for default, item and slot component\n */\nvar VirtualProps = {\n  dataKey: {\n    type: [String, Function],\n    required: true\n  },\n  dataSources: {\n    type: Array,\n    required: true,\n    \"default\": function _default() {\n      return [];\n    }\n  },\n  dataComponent: {\n    type: [Object, Function],\n    required: true\n  },\n  keeps: {\n    type: Number,\n    \"default\": 30\n  },\n  extraProps: {\n    type: Object\n  },\n  estimateSize: {\n    type: Number,\n    \"default\": 50\n  },\n  direction: {\n    type: String,\n    \"default\": 'vertical' // the other value is horizontal\n\n  },\n  start: {\n    type: Number,\n    \"default\": 0\n  },\n  offset: {\n    type: Number,\n    \"default\": 0\n  },\n  topThreshold: {\n    type: Number,\n    \"default\": 0\n  },\n  bottomThreshold: {\n    type: Number,\n    \"default\": 0\n  },\n  pageMode: {\n    type: Boolean,\n    \"default\": false\n  },\n  rootTag: {\n    type: String,\n    \"default\": 'div'\n  },\n  wrapTag: {\n    type: String,\n    \"default\": 'div'\n  },\n  wrapClass: {\n    type: String,\n    \"default\": 'wrap'\n  },\n  wrapStyle: {\n    type: Object\n  },\n  itemTag: {\n    type: String,\n    \"default\": 'div'\n  },\n  itemClass: {\n    type: String,\n    \"default\": ''\n  },\n  itemClassAdd: {\n    type: Function\n  },\n  itemStyle: {\n    type: Object\n  },\n  headerTag: {\n    type: String,\n    \"default\": 'div'\n  },\n  headerClass: {\n    type: String,\n    \"default\": ''\n  },\n  headerStyle: {\n    type: Object\n  },\n  footerTag: {\n    type: String,\n    \"default\": 'div'\n  },\n  footerClass: {\n    type: String,\n    \"default\": ''\n  },\n  footerStyle: {\n    type: Object\n  },\n  itemScopedSlots: {\n    type: Object\n  }\n};\nvar ItemProps = {\n  index: {\n    type: Number\n  },\n  event: {\n    type: String\n  },\n  tag: {\n    type: String\n  },\n  horizontal: {\n    type: Boolean\n  },\n  source: {\n    type: Object\n  },\n  component: {\n    type: [Object, Function]\n  },\n  uniqueKey: {\n    type: [String, Number]\n  },\n  extraProps: {\n    type: Object\n  },\n  scopedSlots: {\n    type: Object\n  }\n};\nvar SlotProps = {\n  event: {\n    type: String\n  },\n  uniqueKey: {\n    type: String\n  },\n  tag: {\n    type: String\n  },\n  horizontal: {\n    type: Boolean\n  }\n};\n\nvar useResizeChange = function useResizeChange(props, rootRef, emit) {\n  var resizeObserver = null;\n  var shapeKey = computed(function () {\n    return props.horizontal ? 'offsetWidth' : 'offsetHeight';\n  });\n\n  var getCurrentSize = function getCurrentSize() {\n    return rootRef.value ? rootRef.value[shapeKey.value] : 0;\n  }; // tell parent current size identify by unqiue key\n\n\n  var dispatchSizeChange = function dispatchSizeChange() {\n    var event = props.event,\n        uniqueKey = props.uniqueKey,\n        hasInitial = props.hasInitial;\n    emit(event, uniqueKey, getCurrentSize(), hasInitial);\n  };\n\n  onMounted(function () {\n    if (typeof ResizeObserver !== 'undefined') {\n      resizeObserver = new ResizeObserver(function () {\n        dispatchSizeChange();\n      });\n      rootRef.value && resizeObserver.observe(rootRef.value);\n    }\n  });\n  onUpdated(function () {\n    dispatchSizeChange();\n  });\n  onUnmounted(function () {\n    if (resizeObserver) {\n      resizeObserver.disconnect();\n      resizeObserver = null;\n    }\n  });\n};\n\nvar Item = defineComponent({\n  name: 'VirtualListItem',\n  props: ItemProps,\n  emits: ['itemResize'],\n  setup: function setup(props, _ref) {\n    var emit = _ref.emit;\n    var rootRef = ref(null);\n    useResizeChange(props, rootRef, emit);\n    return function () {\n      var Tag = props.tag,\n          Comp = props.component,\n          _props$extraProps = props.extraProps,\n          extraProps = _props$extraProps === void 0 ? {} : _props$extraProps,\n          index = props.index,\n          source = props.source,\n          _props$scopedSlots = props.scopedSlots,\n          scopedSlots = _props$scopedSlots === void 0 ? {} : _props$scopedSlots,\n          uniqueKey = props.uniqueKey;\n\n      var mergedProps = _objectSpread2(_objectSpread2({}, extraProps), {}, {\n        source: source,\n        index: index\n      });\n\n      return createVNode(Tag, {\n        \"key\": uniqueKey,\n        \"ref\": rootRef\n      }, {\n        \"default\": function _default() {\n          return [createVNode(Comp, _objectSpread2(_objectSpread2({}, mergedProps), {}, {\n            \"scopedSlots\": scopedSlots\n          }), null)];\n        }\n      });\n    };\n  }\n});\nvar Slot = defineComponent({\n  name: 'VirtualListSlot',\n  props: SlotProps,\n  emits: ['slotResize'],\n  setup: function setup(props, _ref2) {\n    var slots = _ref2.slots,\n        emit = _ref2.emit;\n    var rootRef = ref(null);\n    useResizeChange(props, rootRef, emit);\n    return function () {\n      var _slots$default;\n\n      var Tag = props.tag,\n          uniqueKey = props.uniqueKey;\n      return createVNode(Tag, {\n        \"ref\": rootRef,\n        \"key\": uniqueKey\n      }, {\n        \"default\": function _default() {\n          return [(_slots$default = slots[\"default\"]) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots)];\n        }\n      });\n    };\n  }\n});\n\nvar EVENT_TYPE;\n\n(function (EVENT_TYPE) {\n  EVENT_TYPE[\"ITEM\"] = \"itemResize\";\n  EVENT_TYPE[\"SLOT\"] = \"slotResize\";\n})(EVENT_TYPE || (EVENT_TYPE = {}));\n\nvar SLOT_TYPE;\n\n(function (SLOT_TYPE) {\n  SLOT_TYPE[\"HEADER\"] = \"thead\";\n  SLOT_TYPE[\"FOOTER\"] = \"tfoot\";\n})(SLOT_TYPE || (SLOT_TYPE = {}));\n\nvar VirtualList = defineComponent({\n  name: 'VirtualList',\n  props: VirtualProps,\n  setup: function setup(props, _ref) {\n    var emit = _ref.emit,\n        slots = _ref.slots,\n        expose = _ref.expose;\n    var isHorizontal = props.direction === 'horizontal';\n    var directionKey = isHorizontal ? 'scrollLeft' : 'scrollTop';\n    var range = ref(null);\n    var root = ref();\n    var shepherd = ref(null);\n    var virtual;\n    /**\n     * watch\n     */\n\n    watch(function () {\n      return props.dataSources.length;\n    }, function () {\n      virtual.updateParam('uniqueIds', getUniqueIdFromDataSources());\n      virtual.handleDataSourcesChange();\n    });\n    watch(function () {\n      return props.keeps;\n    }, function (newValue) {\n      virtual.updateParam('keeps', newValue);\n      virtual.handleSlotSizeChange();\n    });\n    watch(function () {\n      return props.start;\n    }, function (newValue) {\n      scrollToIndex(newValue);\n    });\n    watch(function () {\n      return props.offset;\n    }, function (newValue) {\n      return scrollToOffset(newValue);\n    });\n    /**\n     * methods\n     */\n    // get item size by id\n\n    var getSize = function getSize(id) {\n      return virtual.sizes.get(id);\n    };\n\n    var getOffset = function getOffset() {\n      if (props.pageMode) {\n        return document.documentElement[directionKey] || document.body[directionKey];\n      } else {\n        return root.value ? Math.ceil(root.value[directionKey]) : 0;\n      }\n    }; // return client viewport size\n\n\n    var getClientSize = function getClientSize() {\n      var key = isHorizontal ? 'clientWidth' : 'clientHeight';\n\n      if (props.pageMode) {\n        return document.documentElement[key] || document.body[key];\n      } else {\n        return root.value ? Math.ceil(root.value[key]) : 0;\n      }\n    }; // return all scroll size\n\n\n    var getScrollSize = function getScrollSize() {\n      var key = isHorizontal ? 'scrollWidth' : 'scrollHeight';\n\n      if (props.pageMode) {\n        return document.documentElement[key] || document.body[key];\n      } else {\n        return root.value ? Math.ceil(root.value[key]) : 0;\n      }\n    };\n\n    var emitEvent = function emitEvent(offset, clientSize, scrollSize, evt) {\n      emit('scroll', evt, virtual.getRange());\n\n      if (virtual.isFront() && !!props.dataSources.length && offset - props.topThreshold <= 0) {\n        emit('totop');\n      } else if (virtual.isBehind() && offset + clientSize + props.bottomThreshold >= scrollSize) {\n        emit('tobottom');\n      }\n    };\n\n    var onScroll = function onScroll(evt) {\n      var offset = getOffset();\n      var clientSize = getClientSize();\n      var scrollSize = getScrollSize(); // \biOS scroll-spring-back behavior will make direction mistake\n\n      if (offset < 0 || offset + clientSize > scrollSize + 1 || !scrollSize) {\n        return;\n      }\n\n      virtual.handleScroll(offset);\n      emitEvent(offset, clientSize, scrollSize, evt);\n    };\n\n    var getUniqueIdFromDataSources = function getUniqueIdFromDataSources() {\n      var dataKey = props.dataKey,\n          _props$dataSources = props.dataSources,\n          dataSources = _props$dataSources === void 0 ? [] : _props$dataSources;\n      return dataSources.map(function (dataSource) {\n        return typeof dataKey === 'function' ? dataKey(dataSource) : dataSource[dataKey];\n      });\n    };\n\n    var onRangeChanged = function onRangeChanged(newRange) {\n      range.value = newRange;\n    };\n\n    var installVirtual = function installVirtual() {\n      virtual = new Virtual({\n        slotHeaderSize: 0,\n        slotFooterSize: 0,\n        keeps: props.keeps,\n        estimateSize: props.estimateSize,\n        buffer: Math.round(props.keeps / 3),\n        // recommend for a third of keeps\n        uniqueIds: getUniqueIdFromDataSources()\n      }, onRangeChanged); // sync initial range\n\n      range.value = virtual.getRange();\n    }; // set current scroll position to a expectant index\n\n\n    var scrollToIndex = function scrollToIndex(index) {\n      // scroll to bottom\n      if (index >= props.dataSources.length - 1) {\n        scrollToBottom();\n      } else {\n        var offset = virtual.getOffset(index);\n        scrollToOffset(offset);\n      }\n    }; // set current scroll position to a expectant offset\n\n\n    var scrollToOffset = function scrollToOffset(offset) {\n      if (props.pageMode) {\n        document.body[directionKey] = offset;\n        document.documentElement[directionKey] = offset;\n      } else {\n        if (root.value) {\n          root.value[directionKey] = offset;\n        }\n      }\n    }; // get the real render slots based on range data\n    // in-place patch strategy will try to reuse components as possible\n    // so those components that are reused will not trigger lifecycle mounted\n\n\n    var getRenderSlots = function getRenderSlots() {\n      var slots = [];\n      var _range$value = range.value,\n          start = _range$value.start,\n          end = _range$value.end;\n      var dataSources = props.dataSources,\n          dataKey = props.dataKey,\n          itemClass = props.itemClass,\n          itemTag = props.itemTag,\n          itemStyle = props.itemStyle,\n          extraProps = props.extraProps,\n          dataComponent = props.dataComponent,\n          itemScopedSlots = props.itemScopedSlots;\n\n      for (var index = start; index <= end; index++) {\n        var dataSource = dataSources[index];\n\n        if (dataSource) {\n          var uniqueKey = typeof dataKey === 'function' ? dataKey(dataSource) : dataSource[dataKey];\n\n          if (typeof uniqueKey === 'string' || typeof uniqueKey === 'number') {\n            slots.push(createVNode(Item, {\n              \"index\": index,\n              \"tag\": itemTag,\n              \"event\": EVENT_TYPE.ITEM,\n              \"horizontal\": isHorizontal,\n              \"uniqueKey\": uniqueKey,\n              \"source\": dataSource,\n              \"extraProps\": extraProps,\n              \"component\": dataComponent,\n              \"scopedSlots\": itemScopedSlots,\n              \"style\": itemStyle,\n              \"class\": \"\".concat(itemClass).concat(props.itemClassAdd ? ' ' + props.itemClassAdd(index) : ''),\n              \"onItemResize\": onItemResized\n            }, null));\n          } else {\n            console.warn(\"Cannot get the data-key '\".concat(dataKey, \"' from data-sources.\"));\n          }\n        } else {\n          console.warn(\"Cannot get the index '\".concat(index, \"' from data-sources.\"));\n        }\n      }\n\n      return slots;\n    }; // event called when each item mounted or size changed\n\n\n    var onItemResized = function onItemResized(id, size) {\n      virtual.saveSize(id, size);\n      emit('resized', id, size);\n    }; // event called when slot mounted or size changed\n\n\n    var onSlotResized = function onSlotResized(type, size, hasInit) {\n      if (type === SLOT_TYPE.HEADER) {\n        virtual.updateParam('slotHeaderSize', size);\n      } else if (type === SLOT_TYPE.FOOTER) {\n        virtual.updateParam('slotFooterSize', size);\n      }\n\n      if (hasInit) {\n        virtual.handleSlotSizeChange();\n      }\n    }; // set current scroll position to bottom\n\n\n    var scrollToBottom = function scrollToBottom() {\n      if (shepherd.value) {\n        var offset = shepherd.value[isHorizontal ? 'offsetLeft' : 'offsetTop'];\n        scrollToOffset(offset); // check if it's really scrolled to the bottom\n        // maybe list doesn't render and calculate to last range\n        // so we need retry in next event loop until it really at bottom\n\n        setTimeout(function () {\n          if (getOffset() + getClientSize() < getScrollSize()) {\n            scrollToBottom();\n          }\n        }, 3);\n      }\n    }; // when using page mode we need update slot header size manually\n    // taking root offset relative to the browser as slot header size\n\n\n    var updatePageModeFront = function updatePageModeFront() {\n      if (root.value) {\n        var rect = root.value.getBoundingClientRect();\n        var defaultView = root.value.ownerDocument.defaultView;\n        var offsetFront = isHorizontal ? rect.left + defaultView.pageXOffset : rect.top + defaultView.pageYOffset;\n        virtual.updateParam('slotHeaderSize', offsetFront);\n      }\n    }; // get the total number of stored (rendered) items\n\n\n    var getSizes = function getSizes() {\n      return virtual.sizes.size;\n    };\n    /**\n     * life cycles\n     */\n\n\n    onBeforeMount(function () {\n      installVirtual();\n    }); // set back offset when awake from keep-alive\n\n    onActivated(function () {\n      scrollToOffset(virtual.offset);\n    });\n    onMounted(function () {\n      // set position\n      if (props.start) {\n        scrollToIndex(props.start);\n      } else if (props.offset) {\n        scrollToOffset(props.offset);\n      } // in page mode we bind scroll event to document\n\n\n      if (props.pageMode) {\n        updatePageModeFront();\n        document.addEventListener('scroll', onScroll, {\n          passive: false\n        });\n      }\n    });\n    onUnmounted(function () {\n      virtual.destroy();\n\n      if (props.pageMode) {\n        document.removeEventListener('scroll', onScroll);\n      }\n    });\n    /**\n     * public methods\n     */\n\n    expose({\n      scrollToBottom: scrollToBottom,\n      getSizes: getSizes,\n      getSize: getSize,\n      getOffset: getOffset,\n      getScrollSize: getScrollSize,\n      getClientSize: getClientSize,\n      scrollToOffset: scrollToOffset,\n      scrollToIndex: scrollToIndex\n    });\n    return function () {\n      var pageMode = props.pageMode,\n          RootTag = props.rootTag,\n          WrapTag = props.wrapTag,\n          wrapClass = props.wrapClass,\n          wrapStyle = props.wrapStyle,\n          headerTag = props.headerTag,\n          headerClass = props.headerClass,\n          headerStyle = props.headerStyle,\n          footerTag = props.footerTag,\n          footerClass = props.footerClass,\n          footerStyle = props.footerStyle;\n      var _ref2 = range.value,\n          padFront = _ref2.padFront,\n          padBehind = _ref2.padBehind;\n      var paddingStyle = {\n        padding: isHorizontal ? \"0px \".concat(padBehind, \"px 0px \").concat(padFront, \"px\") : \"\".concat(padFront, \"px 0px \").concat(padBehind, \"px\")\n      };\n      var wrapperStyle = wrapStyle ? Object.assign({}, wrapStyle, paddingStyle) : paddingStyle;\n      var header = slots.header,\n          footer = slots.footer;\n      return createVNode(RootTag, {\n        \"ref\": root,\n        \"onScroll\": !pageMode && onScroll\n      }, {\n        \"default\": function _default() {\n          return [header && createVNode(Slot, {\n            \"class\": headerClass,\n            \"style\": headerStyle,\n            \"tag\": headerTag,\n            \"event\": EVENT_TYPE.SLOT,\n            \"uniqueKey\": SLOT_TYPE.HEADER,\n            \"onSlotResize\": onSlotResized\n          }, {\n            \"default\": function _default() {\n              return [header()];\n            }\n          }), createVNode(WrapTag, {\n            \"class\": wrapClass,\n            \"style\": wrapperStyle\n          }, {\n            \"default\": function _default() {\n              return [getRenderSlots()];\n            }\n          }), footer && createVNode(Slot, {\n            \"class\": footerClass,\n            \"style\": footerStyle,\n            \"tag\": footerTag,\n            \"event\": EVENT_TYPE.SLOT,\n            \"uniqueKey\": SLOT_TYPE.FOOTER,\n            \"onSlotResize\": onSlotResized\n          }, {\n            \"default\": function _default() {\n              return [footer()];\n            }\n          }), createVNode(\"div\", {\n            \"ref\": shepherd,\n            \"style\": {\n              width: isHorizontal ? '0px' : '100%',\n              height: isHorizontal ? '100%' : '0px'\n            }\n          }, null)];\n        }\n      });\n    };\n  }\n});\n\nexport { VirtualList as default };\n","<template>\n  <div class=\"container\">\n    <div ref=\"textareaContainer\" class=\"chat-input-content\" :class=\"{\n      'chat-input-content__multiline': multiLine,\n      'chat-input-content__with_send': input,\n      'chat-input-content__disabled': !chatInputEnabled,\n    }\">\n      <textarea\n        ref=\"textarea\"\n        v-model=\"input\"\n        class=\"chat-input\"\n        :class=\"{'chat-input__disabled': !chatInputEnabled}\"\n        :placeholder=\"chatInputEnabled ? t('write_message') : t('chat_disabled')\"\n        :disabled=\"!chatInputEnabled\"\n      />\n      <div class=\"chat-actions\" :class=\"{ 'chat-actions__multiline': multiLine }\">\n        <i id=\"addAttachments\" class=\"icon icon-attach\" @click=\"openFiles\"></i>\n        <input ref=\"attach\" type=\"file\" class=\"upload__input\" :accept=\"acceptStr\"\n          @input=\"onFilesSelected($event.target.files)\">\n      </div>\n    </div>\n    <div class=\"send-button\" v-show=\"input\" @click=\"send\"><i class=\"icon icon-send-email\"></i></div>\n  </div>\n</template>\n\n\n<script setup>\nimport { computed, ref, onMounted } from \"vue\"\nimport { useChannelsStore } from \"app/javascript/src/stores/channels\";\nimport { useTextareaAutosize } from \"@vueuse/core\";\nimport { useShared } from \"@/helpers/vueHelpers.js\"\n\nconst { t } = useShared();\nconst store = useChannelsStore()\nconst attach = ref(null)\n\nconst multiLine = ref(false)\nconst { textarea, input } = useTextareaAutosize({ onResize: onResize })\n\nconst chatInputEnabled = computed(() => store.isCurrentChannelActive)\n\nlet abortController\n\nconst accept = ['.jpg', '.jpeg', '.png', '.pdf', '.ppt', '.pptx', '.mp4'];\nconst acceptStr = accept.join(', ');\n\nonMounted(() => {\n  textarea.value.addEventListener('keypress', (e) => {\n    if (e.key === 'Enter') {\n      e.preventDefault()\n      send()\n    }\n  })\n});\n\nfunction onResize() {\n  if (textarea.value.clientHeight > 24) multiLine.value = true;\n}\n\nasync function send() {\n  if (!chatInputEnabled.value) return;\n  await store.sendMessage(input.value)\n  input.value = \"\"\n}\n\nfunction openFiles() {\n  if (!chatInputEnabled.value) return;\n  attach.value?.click()\n}\n\nasync function onFilesSelected(fileList) {\n  abortController = new AbortController\n\n  await store.sendAttachment(Object.values(fileList), abortController)\n  attach.value.value = '';\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.container {\n  display: flex;\n  position: absolute;\n  width: calc(100% - 2 * $spacing-6);\n  bottom: $spacing-4;\n  background-color: $white;\n}\n\n.file-upload-container {\n  display: none;\n\n  &.show-upload {\n    @include flex-column;\n  }\n}\n\n.upload-popup-anchor {\n  margin-top: -$spacing-10;\n}\n\n.upload-popup {\n  width: 500px;\n  border: 1px solid red;\n}\n\n.chat-input-content {\n  display: flex;\n  flex-wrap: nowrap;\n  width: 100%;\n  min-width: 270px;\n  border: 1px solid $gray-lighter;\n  border-radius: $rounded-2xl;\n  padding: $spacing-2;\n  align-items: center;\n\n  &__with_send {\n    width: calc(100% - 48px - $spacing-2);\n    margin-right: $spacing-2;\n  }\n\n  &__multiline {\n    flex-wrap: wrap;\n  }\n\n  &__disabled {\n    background-color: $grey-25;\n  }\n\n  &:focus,\n  &:focus-within {\n    border: 1px solid $brand-tertiary;\n    outline: none;\n  }\n}\n\n.chat-input {\n  display: flex;\n  width: 100%;\n  overflow: hidden;\n  max-height: 48px;\n  resize: none;\n  border: none !important;\n  font-size: $text-base;\n  line-height: $leading-normal;\n  padding: 0 $spacing-1;\n  border-radius: $spacing-1;\n  overflow-y: auto;\n  scrollbar-width: none;\n  -ms-overflow-style: none;\n\n  &__disabled {\n    background-color: $grey-25;\n  }\n\n  &:focus,\n  &:focus-within {\n    border: 1px solid $brand-tertiary;\n    outline: none;\n  }\n}\n\n.chat-actions {\n  display: flex;\n  align-items: center;\n  width: 30px;\n  justify-content: space-between;\n  margin: 0 0 0 $spacing-3;\n\n  &__multiline {\n    margin: $spacing-2 0 0 0;\n  }\n}\n\n.icon-attach,\n.icon-smile-2 {\n  color: $gray;\n  font-size: $text-xl;\n\n  &:hover {\n    cursor: pointer;\n  }\n}\n\n.icon-send-email {\n  color: $white;\n  font-size: $text-base;\n}\n\n.upload__input {\n  display: none;\n}\n\n.send-button {\n  background: linear-gradient(to bottom left, $brand-primary, $green-200);\n  height: 48px;\n  width: 48px;\n  border-radius: $rounded-max;\n  display: flex;\n  justify-content: center;\n  align-items: center;\n  margin-top: auto;\n\n  &:hover {\n    cursor: pointer;\n  }\n}\n</style>\n\n<i18n lang=\"yaml\">\n  en:\n    write_message: Write a message\n    chat_disabled: You have been removed from chat.\n</i18n>\n","<template>\n  <template v-if=\"mobile\">\n    <div class=\"chat_header_mobile\">\n      <i class=\"icon icon-arrow-left-1\" @click=\"back\"></i>\n      <Avatar :url=\"avatar\" size=\"xl\" class=\"chat_header_mobile__avatar\" />\n      <div>\n        <div class=\"chat_title\">{{ store.getCurrentChannelName }}</div>\n        <div class=\"chat_people_count\">{{ `${memberCount} ${memberCount > 1 ? t('people') : t('person')}` }}</div>\n      </div>\n    </div>\n    <div class=\"chat_header_mobile__actions\">\n      <Button\n        v-show=\"(store.getProduct || store.getItineraryRequest?.matched) && !isSupplier\"\n        class=\"chat_header_mobile__action_button\"\n        color=\"red\"\n        :text=\"t('preview_itinerary')\"\n        @click=\"onClickPreview\"\n      />\n      <Button\n        v-show=\"isSupplier\"\n        class=\"chat_header_mobile__action_button\"\n        color=\"red\"\n        :text=\"t('send_quote')\"\n        @click=\"onClickSendQuote\"\n      />\n      <Button\n        class=\"chat_header_mobile__action_button\"\n        color=\"green\"\n        :text=\"t('details')\"\n        invert\n        @click=\"store.toggleOpenMobileDetails\"\n      />\n    </div>\n  </template>\n  <template v-else>\n    <div class=\"chat_header_desktop\">\n      <div>\n        <div class=\"chat_title\">{{ store.getCurrentChannelName }}</div>\n        <div class=\"chat_people_count\">{{ `${memberCount} ${memberCount > 1 ? t('people') : t('person')}` }}</div>\n      </div>\n      <Button\n        v-show=\"(store.getProduct || store.getItineraryRequest?.matched) && !isSupplier\"\n        class=\"chat_header_desktop__button\"\n        color=\"red\"\n        :text=\"t('preview_itinerary')\"\n        @click=\"onClickPreview\" />\n      <Button\n        v-show=\"isSupplier\"\n        class=\"chat_header_desktop__button\"\n        color=\"red\"\n        :text=\"t('send_quote')\"\n        @click=\"onClickSendQuote\" />\n    </div>\n  </template>\n  <div class=\"divider\" />\n</template>\n\n<script setup>\nimport { computed } from 'vue';\nimport { useChannelsStore } from 'app/javascript/src/stores/channels'\nimport { useShared } from '@/helpers/vueHelpers';\nimport {  DEFAULT_AVATAR } from '@/models/message';\nimport Avatar from '@/components/Theme/Avatar.vue';\nimport Button from '@/components/Theme2/Button.vue';\n\nconst { t, mobile } = useShared()\nconst store = useChannelsStore()\n\nconst memberCount = computed(() => Math.max(Object.keys(store.getMembersProfile).length, 2))\nconst isSupplier = computed(() => store.profiles?.own?.supplier_id !== null)\nconst avatar = DEFAULT_AVATAR\n\nfunction back() {\n  if (store.isModalOpen) {\n    store.closeChatModal();\n  } else {\n    store.setCurrentChannel(null)\n  }\n}\n\nfunction onClickPreview() {\n  window.open(store.getProduct?.meta?.link || store.getItineraryRequest.url, \"_blank\");\n}\n\nfunction onClickSendQuote() {\n  const chat_id = store.currentChannelId;\n  const itinerary_request_id = store.getItineraryRequest.id;\n  window.open(`/en/operators/send_quote?chat_id=${chat_id}&itinerary_request_id=${itinerary_request_id}`, \"_blank\");\n}\n\n</script>\n\n<style lang=\"scss\" scoped>\n.chat_header_mobile {\n  display: flex;\n  align-items: center;\n\n  &__avatar {\n    margin: 0 $spacing-3;\n  }\n\n  &__actions {\n    @include flex-column;\n    margin: $spacing-2 0;\n    gap: $spacing-3;\n  }\n\n  &__action_button {\n    width: 100%;\n  }\n}\n\n.chat_title {\n  font-size: $text-xl;\n  font-weight: $font-semibold;\n  line-height: 26px;\n  margin-bottom: $spacing-1\n}\n\n.chat_people_count {\n  font-size: $text-sm;\n  line-height: 16px;\n}\n\n.chat_header_desktop {\n  display: flex;\n  justify-content: space-between;\n\n  &__button {\n    min-width: 163px;\n    max-width: 234px;\n    height:100%;\n    font-size: $text-base;\n  }\n}\n\n.divider {\n  width: 100%;\n  height: 0.5px;\n  margin-top: $spacing-4;\n  background: $gray-lighter;\n}\n</style>\n\n<i18n lang=\"yaml\">\n  en:\n    details: Details\n    preview_itinerary: Preview Itinerary\n    people: people\n    person: person\n    send_quote: Send quote\n</i18n>\n","<template>\n  <div v-if=\"isInitiator\" class=\"notification-message\">{{ props.content.replace(`${alias} has`, \"You have\") }}</div>\n  <div v-else-if=\"isInvitee\" class=\"notification-message\">{{ props.content.replace(alias, \"you\") }}</div>\n  <div v-else class=\"notification-message\">{{ props.content }}</div>\n</template>\n\n<script setup>\nimport { computed } from 'vue'\nimport { storeToRefs } from \"pinia\";\nimport { useChannelsStore } from '@/stores/channels'\n\n\nconst props = defineProps({\n  content: String,\n  initiator: Object,\n  invitee: Object,\n  removee: Object\n})\n\nconst store = useChannelsStore()\nconst { alias, profiles } = storeToRefs(store)\n\nconst isInitiator = computed(() => profiles.value?.own?.slug == props.initiator?.userSlug)\nconst isInvitee = computed(() => !!props.invitee?.find((invitee) => profiles.value?.own?.slug == invitee.userSlug))\n</script>\n\n<style lang=\"scss\" scoped>\n.notification-message {\n  margin: $spacing-4;\n  text-align: center;\n  font-size: $text-base;\n  color: $gray\n}\n</style>","export default \"data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/wAARCAAQABADAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDc/b9/b5+LH7Xvxd8Zt/wmOv6b8ENL1/VNL+G/w60/UpbHw8vhmyuha6freu6fp8qWuueIdditItZvrzU31M6fPePpmk3MemW0CH9yyLIsLlOEo/uacsbKEZYjESipVPaSV5QhKSvCnBtwio8vMlzTXM2fw/xzxxmnFea4z/a69PJqVerSy/L4VHCgsNCXLTrVqcGo1q9ZQVac6jqezlN06UlTjFHr37IP7Unxl/4J+eIfgZr/AIm+J+s3HgT4q6nb6t45/Zu1V9TvLPQfg5qTWmm6N8TLyPUJZrbwb4n16NrzxF4K0zR9Og1bXPCmhaPret3I8JeKPDseqcmbZZg8+p42FPDQVfCxcKGYx5U54uN5Tw0eWzrUoaU60pycIVZzhBe1pVHD1uFOJc34ExGS18TmVWWCzOpGrjeHqrqThQymo406OYzVRuOExNdOdfB06UI1a2Go0q1aX1XE4dVeg/aT/Zq8ef8ABPz4kfFDw749/Z2i+O37MniPxfF48+EPie9TV7Lwro/iHRv7Tu/Bq+IPEOhW+o3Nrbafp2qX3hn4kfDbV7vQ0+I2jad9s07U9MNhoviLToy7MaGfYfDVKGYfUsyp0nQxdJcjqzpz5VW9nTm4puUoxq4fEQU/q85WlGXNOnLfiHh3HcCZhmWHx2QLO+HMRi1jsqxM1VhhqVej7SWEVfEUY1JxjTp1Z4bMcvqyorMKNPnp1KfJRxFPyn9jj9jv4/f8FAv2i9N8ceMdE8T3Xw41Xxpa+LfjF8WNa0+Sy0KfRVvje6lofh68vYY9P1LVtVtrRvDuhaLocN9aeH4JrSW5sLTQdOZV6c3zfAZDl8qNGdNYiNF0sJhYS5pqfLaM6ii3KMIN+0nObi6jTSk6kjy+EuE8946z+njMXRxMsvq4yOKzbNK1NwoOip89SjQnNKFSrUjD6vQo0VONBODlCNCnYP/Z\"","<template>\n  <div class=\"file_uploading\" v-if=\"['FAIL', 'UPLOADING', 'UPLOAD_COMPLETE'].includes(props.sendStatus)\">\n    <i class=\" icon icon-attach\"></i>\n    <div class=\"file_uploading__details\">\n      <div v-if=\"props.sendStatus === 'FAIL'\" class=\"file_uploading__error\">\n        <i class=\"icon icon-alert-triangle\"></i>\n        <div class=\"file_uploading__error_message\">{{ props.error ?? \"Something went wrong.\" }}</div>\n      </div>\n      <div v-if=\"props.sendStatus === 'UPLOAD_COMPLETE'\" class=\"file_uploading__upload_complete\">\n        <img :src=\"Check\" class=\"file_uploading__check\"></img>\n        <div class=\"file_uploading__progress\">Upload complete (100%)</div>\n      </div>\n      <div v-if=\"props.sendStatus === 'UPLOADING'\" class=\"file_uploading__progress_details\">\n        <div class=\"file_uploading__progress\">{{ `Uploading... (${props.progress}%)` }}</div>\n        <div class=\"file_uploading__cancel_button\" @click=\"cancelUpload\">Cancel</div>\n      </div>\n\n      <div class=\"file_uploading__progress_bar\">\n        <div v-if=\"props.sendStatus === 'FAIL'\" class=\"file_uploading__error_progress_bar\"></div>\n        <SimpleProgress v-else :progress=\"props.progress\" />\n      </div>\n\n      <div class=\"file_uploading__name\">{{ files[0].name ?? '' }}</div>\n    </div>\n  </div>\n  <div v-else class=\"file_message\" @click=\"download.click()\">\n    <i class=\"icon icon-attach\"></i>\n    <div class=\"file_message__name\">{{ props.attachments.fileName }} {{ formatBytes(props.attachments.size) }}</div>\n    <div class=\"file_message__size\">{{ `(${formatBytes(props.attachments.size)})` }}</div>\n    <a ref=\"download\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"file_message__download\" :href=\"props.attachments.url\"></a>\n  </div>\n</template>\n\n<script setup>\nimport { ref } from 'vue';\nimport { SimpleProgress } from \"@/components/Theme/index.js\";\nimport { useChannelsStore } from '@/stores/channels';\nimport { formatBytes } from \"@/utils/numberUtils.js\";\nimport Check from 'app/assets/images/chat/check.jpg'\n\nconst props = defineProps({\n  id: String,\n  attachments: {\n    fileName: String,\n    url: String,\n    size: Number\n  },\n  error: { type: String, default: null },\n  createdAt: String,\n\n  progress: { type: Number, default: 1 },\n  sendStatus: { type: String, default: undefined },\n  files: { type: Array, default: undefined }\n})\n\nconst download = ref(null)\nconst store = useChannelsStore()\n\nconst cancelUpload = () => {\n  store.cancelAttachment(props.id)\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.file_message {\n  padding: $spacing-3;\n  border-radius: $rounded-xs;\n  background-color: $white;\n  border: 1px solid $gray-lighter;\n  display: flex;\n  align-items: center;\n  width: 283px;\n\n  @media (min-width: $breakpoint-sm) and (max-width: $breakpoint-m) {\n    width: 385px;\n  }\n\n  @media (min-width: $breakpoint-xl) {\n    width: 385px;\n  }\n\n  &:hover {\n    cursor: pointer;\n  }\n\n  &__name {\n    font-size: $text-base;\n    font-weight: $font-semibold;\n    white-space: nowrap;\n    overflow: hidden;\n    max-width: 70%;\n    text-overflow: ellipsis;\n  }\n\n  &__size {\n    font-size: $text-base;\n    font-weight: $font-semibold;\n  }\n\n  &__download {\n    display: none\n  }\n}\n\n.file_uploading {\n  width: 100%;\n  display: flex;\n  padding: $spacing-3;\n  border-radius: $rounded-xs;\n  background-color: $white;\n  border: 1px dashed $gray-lighter;\n  align-items: center;\n  max-width: 385px;\n\n\n  &__details {\n    width: calc(100% - 24px - 12px);\n    align-items: center;\n  }\n\n  &__error {\n    color: $brand-secondary;\n    font-size: $text-base;\n    width: 100%;\n    display: flex;\n\n    &_progress_bar {\n      width: 100%;\n      height: 4px;\n      background-color: $grey-50;\n      border-radius: $rounded;\n    }\n  }\n\n  &__check {\n    width: 16px;\n    height: 16px;\n    margin-right: $spacing-2;\n  }\n\n  &__upload_complete {\n    width: 100%;\n    display: flex;\n  }\n\n  &__progress_details {\n    width: 100%;\n    display: flex;\n    justify-content: space-between;\n  }\n\n  &__progress {\n    font-size: $text-base;\n  }\n\n  &__cancel_button {\n    font-size: $text-base;\n    color: $brand-tertiary;\n\n    &:hover {\n      cursor: pointer;\n      font-weight: $font-semibold;\n    }\n  }\n\n  &__progress_bar {\n    display: flex;\n    margin: $spacing-3 0;\n  }\n\n  &__name {\n    font-size: $text-base;\n    color: $gray;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n  }\n}\n\n.icon {\n  flex: 0 0 24px;\n  font-size: $text-2xl;\n  color: $brand-tertiary;\n  margin-right: $spacing-3;\n}\n\n.icon-alert-triangle {\n  font-size: $text-base;\n  color: $brand-secondary;\n  margin-right: 0;\n}\n</style>\n","export default \"__VITE_ASSET__CiodHsVz__\"","<template>\n  <div v-if=\"props.sendStatus === 'FAIL'\" :class=\"{'image_container__own': props.isOwnMessage}\" >\n    <img :src=\"ImageUploadError\" />\n  </div>\n  <div v-else :class=\"{'image_container__own': props.isOwnMessage}\" >\n    <div class=\"image_uploading__details\">\n      <div v-if=\"props.sendStatus === 'UPLOADING'\" class=\"image__loading-overlay\"\n        :style=\"{ width: `${overlayWidth}px` }\">\n      </div>\n      <div class=\"image_message\" :class=\"{ 'image_message__own': props.isOwnMessage, 'image_message__search_result': props.searchResult }\">\n        <div v-if=\"isLoading\" class=\"image_message__loader\"><SpinnerIcon/></div>\n        <MediaGallery v-else :feature-images=\"[attachments]\" layout=\"single\"/>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script setup>\nimport { ref, computed } from 'vue';\nimport { useImage } from '@vueuse/core'\nimport { SpinnerIcon } from \"@/components/Theme/index.js\";\nimport MediaGallery from \"@/modules/MediaGallery/MediaGallery.vue\";\nimport ImageUploadError from 'app/assets/images/chat/image_upload_error.jpg'\n\nconst props = defineProps({\n  id: String,\n  isOwnMessage: { type: Boolean, default: false },\n  attachments: {\n    fileName: String,\n    url: String,\n    size: Number\n  },\n  createdAt: String,\n\n  searchResult: { type: Boolean, default: null },\n  progress: { type: Number, default: 1 },\n  sendStatus: { type: String, default: undefined },\n  files: { type: Array, default: undefined },\n})\n\nconst image = ref(null)\n\nconst attachments = computed(() => props.attachments ?? { url: props.files[0] ? URL.createObjectURL(props.files[0]) : \"#\"})\nconst overlayWidth = computed(() => props.progress / 100 * (image?.value?.clientWidth ?? 1))\nconst { isLoading } = useImage({ src: attachments.value?.url })\n</script>\n\n<style lang=\"scss\" scoped>\n.image_container {\n  &__own {\n    display: flex;\n    justify-content: end;\n  }\n}\n\n.image_message {\n  border-radius: $rounded-2xl;\n\n  &:deep(img) {\n    max-height: 220px;\n  }\n\n  &__own {\n    margin-left: auto;\n  }\n\n  &__search_result {\n    border: 2px solid $yellow-100\n  }\n\n  &__loader {\n    display: flex;\n    height: 220px;\n    width: 220px;\n    align-items: center;\n    justify-content: center;\n  }\n\n  .icon-diagram-dash-circle {\n    font-size: $text-4xl;\n  }\n}\n\n.image_uploading__fail_overlay {\n  position: absolute;\n  top: 0;\n  left: 0;\n  width: 100%;\n  height: 100%;\n  display: none;\n  color: $brand-secondary;\n  display: block;\n  background-color: $white;\n  opacity: 0.4;\n}\n\n.image__loading-overlay {\n  z-index: 2;\n  position: absolute;\n  top: 0;\n  right: 0;\n  background-color: $white;\n  opacity: 0.6;\n  height: 100%;\n  max-width: 100%;\n  border: none;\n}\n\n.image_uploading {\n  width: 100%;\n  display: flex;\n  padding: $spacing-3;\n  border-radius: $rounded-xs;\n  background-color: $white;\n  border: 1px dashed $gray-lighter;\n  align-items: center;\n\n\n  &__details {\n    width: calc(100% - 24px - 12px);\n    position: relative;\n    display: flex;\n  }\n}\n\n.icon {\n  flex: 0 0 24px;\n  font-size: $text-2xl;\n  color: $brand-tertiary;\n  margin-right: $spacing-3;\n}\n</style>","<template>\n  <div class=\"product_card__container\">\n    <ProductCard class=\"product_card__message\" v-if=\"product\" :product=\"product\" openInNewTab/>\n  </div>\n</template>\n\n<script setup>\nimport { ref, onMounted } from 'vue';\nimport { useChannelsStore } from '@/stores/channels';\nimport ProductCard from '@/modules/Explore/ProductCard2.vue';\n\nconst props = defineProps({\n  id: String,\n  productId: String\n})\n\nconst product = ref(null)\nconst store = useChannelsStore()\n\nonMounted(async () => {\n  if (store.getProduct && props.productId == store.getProduct?.id) {\n    product.value = store.getProduct\n    return\n  }\n\n  const data = await store.getProductCardDetails(props.productId)\n  product.value = { ...data, event: data.displayableEvent }\n})\n</script>\n\n<style lang=\"scss\" scoped>\n.product_card__message {\n  width: 200px;\n  height: 355px;\n}\n</style>","module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\texports: {},\n/******/ \t\t\tid: moduleId,\n/******/ \t\t\tloaded: false\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.loaded = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\tmodule.exports = __webpack_require__(1);\n\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t  value: true\n\t});\n\t\n\tvar _utils = __webpack_require__(2);\n\t\n\tObject.defineProperty(exports, 'combineChunks', {\n\t  enumerable: true,\n\t  get: function get() {\n\t    return _utils.combineChunks;\n\t  }\n\t});\n\tObject.defineProperty(exports, 'fillInChunks', {\n\t  enumerable: true,\n\t  get: function get() {\n\t    return _utils.fillInChunks;\n\t  }\n\t});\n\tObject.defineProperty(exports, 'findAll', {\n\t  enumerable: true,\n\t  get: function get() {\n\t    return _utils.findAll;\n\t  }\n\t});\n\tObject.defineProperty(exports, 'findChunks', {\n\t  enumerable: true,\n\t  get: function get() {\n\t    return _utils.findChunks;\n\t  }\n\t});\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports) {\n\n\t'use strict';\n\t\n\tObject.defineProperty(exports, \"__esModule\", {\n\t  value: true\n\t});\n\t\n\t\n\t/**\n\t * Creates an array of chunk objects representing both higlightable and non highlightable pieces of text that match each search word.\n\t * @return Array of \"chunks\" (where a Chunk is { start:number, end:number, highlight:boolean })\n\t */\n\tvar findAll = exports.findAll = function findAll(_ref) {\n\t  var autoEscape = _ref.autoEscape,\n\t      _ref$caseSensitive = _ref.caseSensitive,\n\t      caseSensitive = _ref$caseSensitive === undefined ? false : _ref$caseSensitive,\n\t      _ref$findChunks = _ref.findChunks,\n\t      findChunks = _ref$findChunks === undefined ? defaultFindChunks : _ref$findChunks,\n\t      sanitize = _ref.sanitize,\n\t      searchWords = _ref.searchWords,\n\t      textToHighlight = _ref.textToHighlight;\n\t  return fillInChunks({\n\t    chunksToHighlight: combineChunks({\n\t      chunks: findChunks({\n\t        autoEscape: autoEscape,\n\t        caseSensitive: caseSensitive,\n\t        sanitize: sanitize,\n\t        searchWords: searchWords,\n\t        textToHighlight: textToHighlight\n\t      })\n\t    }),\n\t    totalLength: textToHighlight ? textToHighlight.length : 0\n\t  });\n\t};\n\t\n\t/**\n\t * Takes an array of {start:number, end:number} objects and combines chunks that overlap into single chunks.\n\t * @return {start:number, end:number}[]\n\t */\n\t\n\t\n\tvar combineChunks = exports.combineChunks = function combineChunks(_ref2) {\n\t  var chunks = _ref2.chunks;\n\t\n\t  chunks = chunks.sort(function (first, second) {\n\t    return first.start - second.start;\n\t  }).reduce(function (processedChunks, nextChunk) {\n\t    // First chunk just goes straight in the array...\n\t    if (processedChunks.length === 0) {\n\t      return [nextChunk];\n\t    } else {\n\t      // ... subsequent chunks get checked to see if they overlap...\n\t      var prevChunk = processedChunks.pop();\n\t      if (nextChunk.start < prevChunk.end) {\n\t        // It may be the case that prevChunk completely surrounds nextChunk, so take the\n\t        // largest of the end indexes.\n\t        var endIndex = Math.max(prevChunk.end, nextChunk.end);\n\t        processedChunks.push({ highlight: false, start: prevChunk.start, end: endIndex });\n\t      } else {\n\t        processedChunks.push(prevChunk, nextChunk);\n\t      }\n\t      return processedChunks;\n\t    }\n\t  }, []);\n\t\n\t  return chunks;\n\t};\n\t\n\t/**\n\t * Examine text for any matches.\n\t * If we find matches, add them to the returned array as a \"chunk\" object ({start:number, end:number}).\n\t * @return {start:number, end:number}[]\n\t */\n\tvar defaultFindChunks = function defaultFindChunks(_ref3) {\n\t  var autoEscape = _ref3.autoEscape,\n\t      caseSensitive = _ref3.caseSensitive,\n\t      _ref3$sanitize = _ref3.sanitize,\n\t      sanitize = _ref3$sanitize === undefined ? defaultSanitize : _ref3$sanitize,\n\t      searchWords = _ref3.searchWords,\n\t      textToHighlight = _ref3.textToHighlight;\n\t\n\t  textToHighlight = sanitize(textToHighlight);\n\t\n\t  return searchWords.filter(function (searchWord) {\n\t    return searchWord;\n\t  }) // Remove empty words\n\t  .reduce(function (chunks, searchWord) {\n\t    searchWord = sanitize(searchWord);\n\t\n\t    if (autoEscape) {\n\t      searchWord = escapeRegExpFn(searchWord);\n\t    }\n\t\n\t    var regex = new RegExp(searchWord, caseSensitive ? 'g' : 'gi');\n\t\n\t    var match = void 0;\n\t    while (match = regex.exec(textToHighlight)) {\n\t      var _start = match.index;\n\t      var _end = regex.lastIndex;\n\t      // We do not return zero-length matches\n\t      if (_end > _start) {\n\t        chunks.push({ highlight: false, start: _start, end: _end });\n\t      }\n\t\n\t      // Prevent browsers like Firefox from getting stuck in an infinite loop\n\t      // See http://www.regexguru.com/2008/04/watch-out-for-zero-length-matches/\n\t      if (match.index === regex.lastIndex) {\n\t        regex.lastIndex++;\n\t      }\n\t    }\n\t\n\t    return chunks;\n\t  }, []);\n\t};\n\t// Allow the findChunks to be overridden in findAll,\n\t// but for backwards compatibility we export as the old name\n\texports.findChunks = defaultFindChunks;\n\t\n\t/**\n\t * Given a set of chunks to highlight, create an additional set of chunks\n\t * to represent the bits of text between the highlighted text.\n\t * @param chunksToHighlight {start:number, end:number}[]\n\t * @param totalLength number\n\t * @return {start:number, end:number, highlight:boolean}[]\n\t */\n\t\n\tvar fillInChunks = exports.fillInChunks = function fillInChunks(_ref4) {\n\t  var chunksToHighlight = _ref4.chunksToHighlight,\n\t      totalLength = _ref4.totalLength;\n\t\n\t  var allChunks = [];\n\t  var append = function append(start, end, highlight) {\n\t    if (end - start > 0) {\n\t      allChunks.push({\n\t        start: start,\n\t        end: end,\n\t        highlight: highlight\n\t      });\n\t    }\n\t  };\n\t\n\t  if (chunksToHighlight.length === 0) {\n\t    append(0, totalLength, false);\n\t  } else {\n\t    var lastIndex = 0;\n\t    chunksToHighlight.forEach(function (chunk) {\n\t      append(lastIndex, chunk.start, false);\n\t      append(chunk.start, chunk.end, true);\n\t      lastIndex = chunk.end;\n\t    });\n\t    append(lastIndex, totalLength, false);\n\t  }\n\t  return allChunks;\n\t};\n\t\n\tfunction defaultSanitize(string) {\n\t  return string;\n\t}\n\t\n\tfunction escapeRegExpFn(string) {\n\t  return string.replace(/[\\-\\[\\]\\/\\{\\}\\(\\)\\*\\+\\?\\.\\\\\\^\\$\\|]/g, '\\\\$&');\n\t}\n\n/***/ })\n/******/ ]);\n//# sourceMappingURL=index.js.map","\n/*!\n * vue-highlight-words  v3.0.1\n * © 2022 Yichang Liu\n * LICENCE: MIT\n*/\n\nimport { findAll } from 'highlight-words-core';\nimport { h } from 'vue';\n\nconst VueHighlightWordsImpl = (props, context) => {\r\n    const chunks = findAll({\r\n        autoEscape: props.autoEscape,\r\n        caseSensitive: props.caseSensitive,\r\n        findChunks: props.findChunks,\r\n        sanitize: props.sanitize,\r\n        searchWords: props.searchWords,\r\n        textToHighlight: props.textToHighlight,\r\n    });\r\n    const children = getTextChildren(props, chunks);\r\n    const slots = context.slots;\r\n    if (slots.default) {\r\n        return slots.default && slots.default(children);\r\n    }\r\n    return h('span', { ...context.attrs }, children.map(({ chunk, text, attrs }) => {\r\n        if (!chunk.highlight) {\r\n            return text;\r\n        }\r\n        return h('mark', attrs, [text]);\r\n    }));\r\n};\r\nconst EMPTY_STYLE = {};\r\nfunction getTextChildren(props, chunks) {\r\n    let highlightCount = -1;\r\n    let highlightClassNames = '';\r\n    let highlightStyles = {};\r\n    const { textToHighlight, highlightClassName, highlightStyle = EMPTY_STYLE, activeIndex, activeClassName, activeStyle = EMPTY_STYLE, } = props;\r\n    return chunks.map((chunk, index) => {\r\n        const text = textToHighlight.substr(chunk.start, chunk.end - chunk.start);\r\n        if (!chunk.highlight) {\r\n            return { chunk, text };\r\n        }\r\n        else {\r\n            highlightCount++; // start at 0\r\n            const isActive = highlightCount === +(activeIndex || -1);\r\n            highlightClassNames = `${highlightClassName} ${isActive ? activeClassName : ''}`;\r\n            highlightStyles =\r\n                isActive === true && activeStyle != null\r\n                    ? { ...highlightStyle, ...activeStyle }\r\n                    : highlightStyle;\r\n            const attrs = {\r\n                class: highlightClassNames,\r\n                key: index,\r\n                style: highlightStyles,\r\n                highlightIndex: highlightCount,\r\n            };\r\n            return { chunk, text, attrs };\r\n        }\r\n    });\r\n}\r\nVueHighlightWordsImpl.props = {\r\n    activeClassName: String,\r\n    activeIndex: Number,\r\n    activeStyle: Object,\r\n    autoEscape: Boolean,\r\n    caseSensitive: {\r\n        type: Boolean,\r\n        defualt: false,\r\n    },\r\n    findChunks: Function,\r\n    custom: {\r\n        type: Boolean,\r\n        default: false,\r\n    },\r\n    highlightClassName: String,\r\n    highlightStyle: Object,\r\n    sanitize: Function,\r\n    searchWords: {\r\n        type: Array,\r\n        validator(value) {\r\n            return value.every((word) => typeof word === 'string');\r\n        },\r\n        required: true,\r\n    },\r\n    textToHighlight: {\r\n        type: String,\r\n        required: true,\r\n    },\r\n};\r\nconst VueHighlightWords = VueHighlightWordsImpl;\n\nfunction install(app, options = { name: '' }) {\r\n    app.component(options.name || 'VueHighlightWords', VueHighlightWords);\r\n}\n\nexport { VueHighlightWords, VueHighlightWords as default, install };\n","<template>\n  <div class=\"text_message \" :class=\"{\n    'text_message__self': props.isOwnMessage,\n    'text_message__other': !props.isOwnMessage,\n    'text_message__search_result': props.searchResult\n  }\">\n    <div v-if=\"props.displayName\" class=\"message_details\">\n      <div class=\"message_details_name\">{{ props.senderName }}{{ props.isOwnMessage ? \" (You)\" : \"\" }}</div>\n      <div class=\"message_details_time\" :class=\"{\n        'message_details_time__other': !props.isOwnMessage,\n      }\">\n        {{ sendTime }}</div>\n    </div>\n    <div v-if=\"isSearchOpen\" class=\"text_message_content\">\n      <Highlighter :highlightStyle=\"{ 'background-color': '#F7DD74', 'opacity': '50%' }\" :searchWords=\"[searchString]\"\n        :autoEscape=\"true\" :textToHighlight=\"props.content\" />\n    </div>\n    <div v-else class=\"text_message_content\">{{ text }}</div>\n  </div>\n</template>\n\n<script setup>\nimport { computed } from 'vue';\nimport { storeToRefs } from 'pinia';\nimport moment from 'moment'\nimport Highlighter from 'vue-highlight-words'\nimport { useChannelsStore } from '@/stores/channels';\n\nconst store = useChannelsStore()\n\nconst { isSearchOpen, searchString } = storeToRefs(store)\n\nconst props = defineProps({\n  id: [String, Number],\n  displayName: String,\n  content: String,\n  senderName: String,\n  senderId: String,\n  searchResult: { type: Boolean, default: null },\n  displayName: { type: Boolean, default: null },\n  createdAt: String,\n  isOwnMessage: { type: Boolean, default: false }\n})\n\nconst text = computed(() => props.content)\nconst sendTime = moment.utc(props.createdAt).local().format('LT');\n</script>\n\n<style lang=\"scss\" scoped>\n.text_message {\n  padding: $spacing-3;\n  border-radius: $rounded-2xl;\n  width: 283px;\n\n  @media (max-width: $breakpoint-sm) {\n    width: 100%;\n  }\n\n  @media (min-width: $breakpoint-sm) and (max-width: $breakpoint-m) {\n    width: 385px;\n  }\n\n  @media (min-width: $breakpoint-xl) {\n    width: 385px;\n  }\n\n  &__other {\n    background-color: $gray-lighter;\n    color: $black;\n  }\n\n  &__self {\n    background-color: $brand-tertiary;\n    color: $white;\n  }\n\n  &__search_result {\n    border: 2px solid $yellow-100\n  }\n}\n\n.message_details {\n  display: flex;\n  align-items: center;\n  padding-bottom: $spacing-1;\n}\n\n.message_details_name {\n  font-size: $text-base;\n  font-weight: $font-bold;\n}\n\n.message_details_time {\n  min-width: 50px;\n  font-size: $text-sm;\n  margin-left: $spacing-2;\n  margin-bottom: auto;\n\n  &__other {\n    color: $gray;\n  }\n}\n\n.text_message_content {\n  font-size: $text-base;\n  white-space: pre-wrap;\n}\n\n.text_message_search_content {\n  font-size: $text-base;\n  white-space: pre-wrap;\n  padding-top: 0;\n}\n</style>\n","<template>\n  <div>\n    <TextMessage v-bind=\"props\" :isOwnMessage=\"false\" />\n    <div class=\"prompted_message__options_container\">\n      <div v-for=\"option in props.options\" key=\"option\" class=\"prompted_message__option\" @click=\"send(option)\">\n        {{ option }}\n      </div>\n    </div>\n  </div>\n</template>\n\n<script setup>\nimport { useChannelsStore } from '@/stores/channels';\nimport TextMessage from '@/components/Chat/Message/TextMessage.vue';\n\nconst props = defineProps({\n  id: String,\n  displayName: String,\n  content: String,\n  senderName: String,\n  senderId: String,\n  searchResult: { type: Boolean, default: null },\n  displayName: { type: Boolean, default: null },\n  createdAt: String,\n  options: Array\n})\n\nconst store = useChannelsStore()\n\nfunction send(text) {\n  store.sendMessage(text)\n  store.messageScroller.scrollToBottom()\n}\n\n</script>\n\n<style lang=\"scss\" scoped>\n.prompted_message {\n  &__options_container {\n    @include flex-column($spacing-2);\n    margin-top: $spacing-2;\n  }\n\n  &__option {\n    width: max-content;\n    border: 1px solid $brand-tertiary;\n    color: $brand-tertiary;\n    padding: $spacing-3 $spacing-5;\n    border-radius: $rounded-2xl;\n\n    &:hover {\n      cursor: pointer;\n    }\n  }\n}\n</style>\n","<template>\n  <div class=\"unread-wrapper\">\n    <div class=\"unread-pill\">Unread Message</div>\n  </div>\n</template>\n\n<style lang=\"scss\" scoped>\n.unread-wrapper {\n  width: 100%;\n  display: flex;\n  justify-content: center;\n  margin: $spacing-6 0;\n  position: relative;\n\n  &:before {\n    content: '';\n    position: absolute;\n    top: 50%;\n    left: 0;\n    border-top: 1px solid $yellow-75;\n    background: $yellow-75;\n    width: 100%;\n    transform: translateY(-50%);\n  }\n}\n\n.unread-pill {\n  font-size: $text-sm;\n  color: $grey-100;\n  font-weight: $font-bold;\n  text-transform: uppercase;\n  padding: calc($spacing-2 + 2px) calc($spacing-6 + 4px);\n  background-color: $yellow-50;\n  border-radius: $rounded-2xl;\n  z-index: 2;\n}\n</style>","<template>\n  <div ref=\"message\">\n    <UnreadMessageMarker v-show=\"props.source.firstUnread\" />\n    <div v-show=\"shouldDisplayDate\" class=\"message_date\">\n      {{ moment.utc(props.source.createdAt).local().format('MMM D, YYYY') }}\n    </div>\n    <SystemMessage v-if=\"props.source.messageType == 'system'\" v-bind=\"props.source\" />\n    <div v-else class=\"message_container\" :class=\"{\n      'message_container__next_sender': props.source.displayName,\n      'message_container__own_message': isOwnMessage\n    }\" :style=\"shouldDisplayDate || props.source.firstUnread ? { 'padding-top': 0 } : ''\">\n      <Avatar :class=\"isOwnMessage ? 'message_avatar__own' : 'message_avatar__other'\" :url=\"avatarUrl\"\n        v-if=\"props.source.displayName\" />\n      <div class=\"message_content\" :class=\"{ 'message_content__own_message': isOwnMessage && props.source.messageType !== 'image' }\">\n        <div v-if=\"props.source.messageType == 'product_card'\" class=\"product-card-container\">\n          <ProductCardMessage v-bind=\"props.source\" />\n        </div>\n        <div v-else-if=\"props.source.messageType == 'image'\">\n          <ImageMessage v-bind=\"props.source\" :isOwnMessage=\"isOwnMessage\" />\n        </div>\n        <div v-else-if=\"props.source.messageType == 'file'\"\n          :class=\"isOwnMessage ? 'message_content__own_file_container' : ''\">\n          <FileMessage v-bind=\"props.source\" />\n        </div>\n        <div v-else-if=\"props.source.messageType == 'prompted'\">\n          <PromptedMessage v-bind=\"props.source\" />\n        </div>\n        <TextMessage v-else v-bind=\"props.source\" :isOwnMessage=\"isOwnMessage\" />\n      </div>\n    </div>\n  </div>\n</template>\n\n<script setup>\nimport { ref, computed, watch, nextTick } from 'vue';\nimport { useElementVisibility } from '@vueuse/core'\nimport moment from 'moment'\nimport { useChannelsStore } from '@/stores/channels';\nimport SystemMessage from '@/components/Chat/Message/SystemMessage.vue'\nimport FileMessage from '@/components/Chat/Message/FileMessage.vue'\nimport ImageMessage from '@/components/Chat/Message/ImageMessage.vue';\nimport ProductCardMessage from '@/components/Chat/Message/ProductCardMessage.vue';\nimport PromptedMessage from '@/components/Chat/Message/PromptedMessage.vue';\nimport TextMessage from '@/components/Chat/Message/TextMessage.vue';\nimport UnreadMessageMarker from '@/components/Chat/Message/UnreadMessageMarker.vue';\nimport Avatar from '@/components/Theme/Avatar.vue';\n\nconst store = useChannelsStore()\nconst message = ref(null)\n\nconst isMessageInView = useElementVisibility(message)\n\nconst props = defineProps({\n  source: Object,\n  index: Number,\n  parent: Object\n});\n\nwatch(isMessageInView, async () => {\n  if (isMessageInView && props.source.trigger && !props.source.trigger?.fetched) {\n    await (props.source.trigger?.sequence == 'previous' ? store.fetchPrevious(props.source.id, props.source.trigger) : store.fetchNext(props.source.id, props.source.trigger))\n    const scrollPointIndex = store.getChannelMessageIndex(props.source.id)\n    nextTick(() => {\n      props.parent.scrollToIndex(scrollPointIndex)\n    })\n  }\n})\n\nwatch(isMessageInView, (inView) => {\n  if (props.source.firstUnread) {\n    // We set hide hideScrollTop active for chatroom when\n    //  1. The first unread message is already in view\n    //  2. When the element's y position in scroller is > scroller size (scrolled up, i.e., element exits view from the bottom)\n    if (inView || message.value?.getBoundingClientRect().y > props.parent.getClientSize()) {\n      store.setHideChannelScrollTop(store.currentChannelId, true)\n    } else {\n      // otherwise the element exited view from top (i.e. user scrolled down)\n      store.setHideChannelScrollTop(store.currentChannelId, false)\n    }\n  }\n\n  if (props.source.id == store.getChannelLastReadMessageId(store.currentChannelId)) {\n    if (inView) {\n      store.setHideChannelScrollBottom(store.currentChannelId, true)\n    } else {\n      store.setHideChannelScrollBottom(store.currentChannelId, false)\n    }\n  }\n})\n\nwatch(isMessageInView, async () => {\n  if (isMessageInView && props.source.searchResult && store.isSearchOpen && !props.source.scrolled) {\n    // wait for a short while for Virtualizer to scroll search result into ChatBox\n    setTimeout(() => {\n      message.value?.scrollIntoView({\n        behavior: 'smooth',\n        block: 'nearest',\n      })\n\n      // scrolled is front end utility attribute\n      // used to set message scrolled so that it does not keep page stuck\n      store.updateMessage(store.currentChannelId, props.source.id, \"scrolled\", true)\n    }, 300)\n  }\n})\n\nconst avatarUrl = computed(() => store.getMessageAvatar(store.currentChannelId, props.source.senderId, props.source.senderName, props.source.supplierId))\nconst shouldDisplayDate = computed(() => {\n  if (props.index == 0) return true\n  const previousMessage = store.getChannelPreviousMessage(store.currentChannelId, props.index)\n  return !moment.utc(previousMessage.createdAt).local().isSame(moment.utc(props.source.createdAt).local(), 'day')\n})\nconst isOwnMessage = computed(() => props.source.senderId == store.profiles?.own?.slug)\n</script>\n\n\n<style lang=\"scss\" scoped>\n.message_date {\n  width: 100%;\n  color: $gray;\n  text-align: center;\n  text-transform: uppercase;\n  font-size: $text-xs;\n  font-weight: $font-semibold;\n  margin: $spacing-6 0;\n}\n\n.message_container {\n  display: flex;\n  justify-content: end;\n  padding: $spacing-2 0 0 0;\n\n  @media (min-width: $breakpoint-sm) {\n    padding: $spacing-2 $spacing-6 0 $spacing-6;\n  }\n\n  &__next_sender {\n    padding-top: $spacing-6;\n  }\n\n  &__own_message {\n    flex-direction: row-reverse;\n    justify-content: start;\n  }\n}\n\n.message_avatar {\n  &__own {\n    margin-left: $spacing-3;\n  }\n\n  &__other {\n    margin-right: $spacing-3;\n  }\n}\n\n.message_content {\n  // Avatar width & margin\n  width: calc(100% - 32px - 12px);\n\n  &__own_message {\n    display: flex;\n    flex-direction: row-reverse;\n  }\n\n  &__own_file_container {\n    display: flex;\n    justify-content: end;\n  }\n}\n\n.product-card-container {\n  max-width: 400px;\n}\n\n\n.text_message_search_content {\n  font-size: $text-base;\n  white-space: pre-wrap;\n  padding-top: 0;\n}\n</style>","<template>\n  <div class=\"chatbox\">\n    <div class=\"chatbox__content\" ref=\"content\">\n      <div class=\"chatbox__title_container\" ref=\"title\">\n        <ChatTitle />\n      </div>\n      <Button\n        v-show=\"!hideScrollTop\"\n        @click=\"scrollToUnread\"\n        class=\"chatbox__action_button chatbox__action_button_top\"\n        color=\"green\"\n        invert\n        :style=\"{ 'top': scrollTopPosition }\"\n      >\n        <i class='icon icon-arrow-button-up-1'></i>Scroll to top\n      </Button>\n      <VirtualList\n        ref=\"scroller\"\n        class=\"chatbox__messages_container\"\n        :style=\"{ 'height': messageContainerHeight }\"\n        :data-key=\"'id'\"\n        :data-sources=\"chatroomMessages\"\n        :data-component=\"Message\"\n        :estimate-size=\"220\"\n        :extra-props=\"{ 'parent': scroller }\"\n      />\n      <Button\n        v-show=\"!hideScrollBottom\"\n        class=\"chatbox__action_button chatbox__action_button_bottom\"\n        :style=\"{ 'bottom': scrollBottomPosition }\"\n        @click=\"scrollToBottom\"\n        color=\"green\"\n        invert\n      >\n        <i class='icon icon-arrow-button-down-1'></i>Scroll to bottom\n      </Button>\n      <div v-show=\"showNextSearchButtons\" class=\"chatbox__action_button\" :style=\"{ 'bottom': searchButtonPosition }\">\n        <div class=\"chatbox__action_button_search_container\">\n          <div class=\"chatbox__action_button_search\"\n            v-show=\"searchSelection > 0\"\n            @click=\"onSearchClick(searchSelection - 1)\">\n            <i class=\"icon icon-up\"></i>\n          </div>\n          <div class=\"chatbox__action_button_search\"\n            v-show=\"searchSelection < (searchResults.length - 1)\"\n            @click=\"onSearchClick(searchSelection + 1)\">\n            <i class=\"icon icon-down\"></i>\n          </div>\n        </div>\n      </div>\n      <ChatInput ref=\"chatInput\" />\n    </div>\n  </div>\n</template>\n\n<script setup>\nimport { ref, watch, nextTick, onMounted, computed } from \"vue\";\nimport { storeToRefs } from \"pinia\";\nimport { useElementSize } from \"@vueuse/core\";\nimport { useChannelsStore } from 'app/javascript/src/stores/channels';\nimport VirtualList from 'vue3-virtual-scroll-list';\nimport ChatInput from \"@/components/Chat/ChatBox/ChatInput.vue\";\nimport ChatTitle from \"@/components/Chat/ChatBox/ChatTitle.vue\";\nimport Message from \"@/components/Chat/Message/Index.vue\";\nimport Button from \"@/components/Theme2/Button.vue\";\n\nconst store = useChannelsStore()\nconst scroller = ref(null)\nconst title = ref(null)\nconst content = ref(null)\nconst chatInput = ref(null)\nconst messageContainerHeight = ref('500px')\nconst scrollTopPosition = ref('90px')\nconst scrollBottomPosition = ref('90px')\nconst searchButtonPosition = ref('86px')\n\nconst { isSearchOpen, searchResults, searchSelection, currentChannelId } = storeToRefs(store)\n\nconst { height: chatInputHeight } = useElementSize(chatInput)\nconst { height: contentHeight } = useElementSize(content)\n\nconst hideScrollTop = computed(() => {\n  // hide when:\n  //  1. user is searching\n  //  2. user has already read all message\n  //  3. hideScrollTop trigger active (see Message.vue)\n  return isSearchOpen.value || store.getChannelReadStatus(currentChannelId.value).all_read || store.getChannelReadStatus(currentChannelId.value).hideScrollTop\n})\nconst hideScrollBottom = computed(() => {\n  // hide when:\n  //  1. user is searching\n  //  2. hideScrollBottom trigger active (see Message.vue)\n  return isSearchOpen.value || store.getChannelReadStatus(currentChannelId.value).hideScrollBottom\n})\nconst showNextSearchButtons = computed(() => {\n  return !store.isMobileView && isSearchOpen.value && searchResults.value.length && (searchSelection.value === 0 || searchSelection.value)\n})\n\nconst chatroomMessages = computed(() => store.getCurrentChannelMessages)\n\nwatch(currentChannelId, async (next, prev) => {\n  if (next && !chatroomMessages.value.length) {\n    await store.fetchChannelMessages(next)\n  }\n\n  // always scroll to bottom\n  nextTick(() => {\n    if (scroller.value) { scroller.value.scrollToBottom() };\n    store.setHideChannelScrollBottom(store.currentChannelId, true)\n  })\n\n  if (prev) store.read(prev);\n})\n\nwatch([chatInputHeight, contentHeight], ([nextInputHeight, nextContentHeight], _) => {\n  messageContainerHeight.value = (nextContentHeight - title.value?.clientHeight - nextInputHeight - 8) + 'px'\n  scrollTopPosition.value = (title.value?.clientHeight + 35) + 'px'\n  scrollBottomPosition.value = (nextInputHeight + 30) + 'px'\n  searchButtonPosition.value = (nextInputHeight + 20) + 'px'\n})\n\nonMounted(() => {\n  store.messageScroller = scroller.value\n\n  if (store.isMobileView) { setTimeout(() => scroller.value.scrollToBottom(), 200) }\n})\n\nasync function scrollToUnread() {\n  let unreadMessageIndex = store.getChannelUnreadMessageIndex\n\n  if (!unreadMessageIndex) {\n    await store.getChannelUnreadMessages()\n    unreadMessageIndex = store.getChannelUnreadMessageIndex\n    store.setIsViewingPastMessages(currentChannelId.value, true)\n  }\n\n  nextTick(() => {\n    if (scroller.value) scroller.value.scrollToIndex(unreadMessageIndex);\n    store.setHideChannelScrollTop(currentChannelId.value, true)\n    store.setHideChannelScrollBottom(currentChannelId.value, false)\n  })\n}\n\nasync function scrollToBottom() {\n  const isLastMessageFetched = store.isLastMessageFetched\n\n  if (!isLastMessageFetched) {\n    await store.fetchChannelMessages(store.currentChannelId)\n    store.setIsViewingPastMessages(store.currentChannelId, false)\n  }\n\n  nextTick(() => {\n    if (scroller.value) scroller.value.scrollToBottom()\n    store.setHideChannelScrollBottom(currentChannelId.value, true);\n\n    if (store.getChannelReadStatus(currentChannelId.value).hideScrollTop) store.setHideChannelScrollTop(currentChannelId.value, false);\n  })\n}\n\nasync function onSearchClick(index) {\n  await store.searchWithResultIndex(index)\n  store.setIsViewingPastMessages(currentChannelId.value, true)\n  store.setSearchSelection(index)\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.chatbox {\n  padding: $spacing-6;\n  height: 100%;\n  position: relative;\n\n  &__action_button {\n    position: absolute;\n    font-size: $text-base;\n    display: flex;\n    align-self: center;\n    justify-content: center;\n    align-items: center;\n    width: 100%;\n    padding: $spacing-3 $spacing-5;\n    z-index: 3;\n\n    &_top {\n      width: 128px;\n      font-size: $text-sm;\n      padding: $spacing-2 $spacing-4 !important;\n    }\n\n    &_bottom {\n      margin-top: $spacing-4;\n      width: 153px;\n      font-size: $text-sm;\n      padding: $spacing-2 $spacing-4 !important;\n    }\n\n    &_search_container {\n      margin-left: auto;\n      margin-right: $spacing-4;\n      justify-self: end;\n    }\n\n    &_search {\n      width: 46px;\n      height: 46px;\n      background-color: $white;\n      border: 1px solid $grey-50;\n      display: flex;\n      align-items: center;\n      justify-content: center;\n      border-radius: $rounded-max;\n      margin: calc($spacing-2 - 2px) 0;\n\n      &:hover {\n        cursor: pointer;\n      }\n    }\n  }\n\n  &__content {\n    height: 100%;\n    @include flex-column;\n  }\n\n  &__messages_container {\n    margin: $spacing-2 0;\n    overflow-y: scroll;\n    scrollbar-width: none;\n    -ms-overflow-style: none;\n  }\n}\n\n.spacer {\n  height: $spacing-2;\n}\n\n.icon-arrow-button-up-1,\n.icon-arrow-button-down-1 {\n  margin-top: 2px;\n  margin-right: 5px;\n  font-size: calc($text-xs - 4px);\n}\n\n.icon-up,\n.icon-down {\n  margin-left: $spacing-1;\n}\n</style>","<template>\n  <div class=\"chat-details__item\">\n    <template v-if=\"itineraryRequest\">\n      <div class=\"chat-details__operator-details\">\n        <div class=\"chat-details__operator-title\">{{ t('itineraray_request_id') }}</div>\n        <div class=\"chat-details__operator-field-value\">{{ itineraryRequest?.id }}</div>\n      </div>\n    </template>\n    <template v-if=\"airtableItinerary?.dealId\">\n      <div class=\"chat-details__operator-details\">\n        <div class=\"chat-details__operator-title\">{{ t('deal_id') }}</div>\n        <div class=\"chat-details__operator-field-value\">{{ airtableItinerary?.dealId }}</div>\n      </div>\n    </template>\n\n  </div>\n</template>\n\n<script setup>\nimport { ref, computed } from 'vue'\nimport { useShared } from \"@/helpers/vueHelpers.js\";\nimport { useChannelsStore } from '@/stores/channels';\n\nconst { t } = useShared();\n\nconst store = useChannelsStore()\n\nconst itineraryRequest = computed(() => store.getItineraryRequest)\nconst airtableItinerary = computed(() => itineraryRequest?.value?.airtableItinerary)\n</script>\n\n<style lang=\"scss\" scoped>\n.chat-details__item {\n  width: 100%;\n}\n\n.chat-details__operator-title {\n  font-size: $text-xs;\n  font-weight: $font-semibold;\n}\n\n.chat-details__operator-details {\n  @include flex-column($spacing-3);\n  margin-top: $spacing-2;\n  margin-bottom: $spacing-4;\n}\n\n.chat-details__operator-details:last-child {\n  margin-bottom: 0;\n}\n.chat-details__operator-field-value {\n  font-size: $text-base;\n}\n</style>\n\n<i18n lang=\"yaml\">\nen:\n  itineraray_request_id: ITINERARY REQUEST ID\n  deal_id: Deal ID\n</i18n>\n","<template>\n  <div class=\"chat-details__member-container\">\n    <Avatar :url=\"props.imageUrl ?? DEFAULT_AVATAR\" />\n    <div class=\"chat-details__member-name\">{{ name }}</div>\n  </div>\n</template>\n\n<script setup>\nimport { DEFAULT_AVATAR } from '@/models/message';\nimport Avatar from '@/components/Theme/Avatar.vue';\n\nconst props = defineProps({\n  name: String,\n  imageUrl: String\n})\n</script>\n\n<style scoped lang=\"scss\">\n.chat-details__member-container {\n  display: flex;\n  width: 100%;\n  align-items: center;\n  justify-content: left;\n  gap: $spacing-2\n}\n\n.chat-details__member-name {\n  font-size: $text-base;\n}\n</style>","<template>\n  <Dialog class=\"chat-invite-others__dialog\">\n    <template v-slot:header>\n      <div class=\"chat-invite-others__title\">Invite others</div>\n      <i class=\"icon icon-close\" @click=\"props.onClose\"></i>\n    </template>\n    <div>We will send them an email invitation. After they sign up, they will be able to join your group chat.</div>\n    <div class=\"chat-invite-others__body\">\n      <div class=\"chat-invite-others__input_container\">\n        <textarea ref=\"textarea\" v-model=\"input\" class=\"chat-invite-others__input\"\n          placeholder=\"Add emails, separated by commas\" />\n      </div>\n      <Button class=\"chat-invite-others__button\" color=\"blue\" text=\"Invite\" @click=\"sendInvites\"></Button>\n    </div>\n    <div class=\"chat-invite-others__result\">\n      <div v-show=\"showSent\" class=\"chat-invite-others__sent\">Sent!</div>\n      <ul v-show=\"errors.length\">\n        <li class=\"chat-invite-others__error\" v-for=\"error in errors\">{{ error }}</li>\n      </ul>\n    </div>\n  </Dialog>\n</template>\n\n<script setup>\nimport { compact, uniq } from 'lodash'\nimport { ref } from 'vue'\nimport { useTextareaAutosize } from \"@vueuse/core\";\nimport { useChannelsStore } from '@/stores/channels';\nimport { Dialog } from '@/components/Theme/index.js';\nimport Button from '@/components/Theme2/Button.vue';\nimport { EMAIL_REGEX } from '@/utils/stringUtils.js';\n\nconst props = defineProps({\n  onClose: Function\n})\n\nconst { textarea, input } = useTextareaAutosize()\n\nconst store = useChannelsStore()\n\nconst showSent = ref(false)\nconst errors = ref([])\n\nfunction splitIntoUserEmails() {\n  return compact(input.value.split(\",\").map((email) => email.trim()))\n}\n\nfunction validateEmails() {\n  const emails = splitIntoUserEmails()\n\n  emails.forEach((email) => {\n    if (!EMAIL_REGEX.test(email)) {\n      errors.value = [...errors.value, `${email} is not a valid email.`]\n    }\n  })\n\n  return errors.value.length === 0\n}\n\nasync function sendInvites() {\n  errors.value = []\n\n  if (!input.value || !validateEmails()) return;\n\n  const emailArr = uniq(splitIntoUserEmails())\n\n  try {\n    await store.sendInvites(emailArr)\n    showSent.value = true\n  } catch (e) {\n    errors.value = [e.message]\n  }\n}\n\n</script>\n\n<style lang=\"scss\" scoped>\n.chat-invite-others__dialog {\n  ::v-deep(.modal__container) {\n    max-width: 546px;\n    overflow: hidden;\n\n    @media (min-width: $breakpoint-m) {\n      min-width: unset;\n    }\n  }\n}\n\n.chat-invite-others {\n  &__title {\n    font-size: $text-2xl;\n    font-weight: $font-semibold;\n  }\n\n  &__button {\n    width: 81px;\n    height: 50px;\n    margin-bottom: auto;\n\n    @media (max-width: $breakpoint-m) {\n      width: 100%;\n      margin-top: $spacing-6;\n    }\n  }\n\n  &__body {\n    display: flex;\n    margin-top: $spacing-6;\n\n    @media (max-width: $breakpoint-m) {\n      display: flex;\n      flex-wrap: wrap;\n    }\n  }\n\n  &__input_container {\n    width: 378px;\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    padding: $spacing-3 $spacing-5;\n    font-size: $text-base;\n    border-radius: $rounded-2xl;\n    border: 1px solid $gray-lighter;\n    margin-right: $spacing-6;\n\n    @media (max-width: $breakpoint-m) {\n      width: 100%;\n      margin-right: 0;\n    }\n  }\n\n  &__input {\n    width: 338px;\n    overflow: hidden;\n    resize: none;\n    border: none !important;\n    font-size: $text-base;\n    line-height: $leading-normal;\n    padding: 0 $spacing-1;\n    border-radius: $spacing-1;\n    overflow-y: auto;\n    scrollbar-width: none;\n    -ms-overflow-style: none;\n    max-height: calc(100vh - 500px);\n\n    &:focus,\n    &:focus-within {\n      outline: none;\n    }\n\n    @media (max-width: $breakpoint-m) {\n      width: 100%;\n    }\n  }\n\n  &__result {\n    margin-top: $spacing-3;\n  }\n\n  &__sent {\n    color: $brand-tertiary\n  }\n\n  &__error {\n    color: $red;\n  }\n}\n\n.icon-close {\n  &:hover {\n    cursor: pointer;\n  }\n}\n</style>","<template>\n  <div class=\"chat-details__item\">\n    <div class=\"chat-details__members-title\">\n      <i v-if=\"showMembers\" class=\"icon icon-arrow-down-2\" @click=\"showMembers = false\"></i>\n      <i v-else class=\"icon icon-arrow-right-2\" @click=\"showMembers = true\"></i>\n      {{ t('members') }} ({{ Math.max(memberCount, 2) }})\n    </div>\n    <div v-show=\"showMembers\" class=\"chat-details__members-container\" v-for=\"(member, key) in members\">\n      <ChatroomMember :key=\"key\" :name=\"member.name\" :imageUrl=\"member.avatar\" />\n    </div>\n    <div v-show=\"shouldShowInviteOthers\" class=\"chat-details__member-invite\" @click=\"toggleShowInvitation(true)\">\n      <i class=\"icon icon-single-neutral-actions-add-1\"></i> {{ t('invite_others') }}\n    </div>\n    <InviteOthers v-show=\"showInvitationDialog\" :onClose=\"() => toggleShowInvitation(false)\" />\n  </div>\n</template>\n\n<script setup>\nimport { ref, computed } from 'vue'\nimport { useChannelsStore } from '@/stores/channels';\nimport { useShared } from '@/helpers/vueHelpers';\nimport ChatroomMember from '@/components/Chat/ChatroomDetails/ChatroomMember.vue';\nimport InviteOthers from '@/components/Chat/ChatroomDetails/InviteOthers.vue';\nimport TourHeroSupport from 'app/assets/images/chat/tourhero_support.svg'\n\nconst { t } = useShared()\nconst store = useChannelsStore()\n\nconst tourheroExperienceTeam = {\n  name: \"TourHero Experience Team\",\n  avatar: TourHeroSupport\n}\n\nconst showMembers = ref(true)\nconst showInvitationDialog = ref(false)\nconst members = computed(() => {\n  if (!Object.keys(store.getMembersProfile).length) return {};\n  if (Object.keys(store.getMembersProfile).length === 1) return { ...store.getMembersProfile, \"tourhero-exp-team\": tourheroExperienceTeam }\n  return store.getMembersProfile\n})\nconst memberCount = computed(() => Object.keys(store.getMembersProfile).length)\nconst shouldShowInviteOthers = computed(() => {\n  const chatroom = store.getCurrentChannel\n  if (!chatroom || !chatroom.tourheroes?.length) return false\n  return !!chatroom.tourheroes?.find((user) => user.slug === store.profiles.own.slug)\n})\n\nfunction toggleShowInvitation(boolean) {\n  showInvitationDialog.value = boolean\n}\n\n</script>\n\n<style lang=\"scss\" scoped>\n.chat-details__item {\n  width: 100%;\n}\n\n.chat-details__members-title {\n  font-size: $text-xs;\n  font-weight: $font-semibold;\n}\n\n.chat-details__members-container {\n  margin: $spacing-2 0;\n}\n\n.icon {\n  text-align: center;\n  vertical-align: baseline;\n\n  &:hover {\n    cursor: pointer;\n  }\n}\n\n.chat-details__member-invite {\n  display: flex;\n  align-items: baseline;\n  color: $brand-tertiary;\n  font-weight: $font-semibold;\n\n  &:hover {\n    cursor: pointer;\n  }\n}\n\n.icon-single-neutral-actions-add-1 {\n  font-size: $text-2xl;\n  margin-right: $spacing-3;\n}\n</style>\n\n<i18n lang=\"yaml\">\n  en:\n    members: MEMBERS\n    invite_others: Invite others\n</i18n>","<template>\n  <div class=\"message_search__container\" :class=\"{ 'selected': isSearching }\">\n    <input class=\"message_search__input\" type=\"text\" placeholder=\"Search messages\" :value=\"store.searchString\"\n      @input=\"search($event.target.value)\" @focus=\"onFocus\" @blur=\"onBlur\">\n    <div v-show=\"store.searchString?.length\" @click=\"store.clearSearch\" class=\"clear_button\">Clear</div>\n    <i class=\"icon icon-search\"></i>\n  </div>\n</template>\n\n<script setup>\nimport { ref } from 'vue'\nimport { useDebounceFn } from '@vueuse/core'\nimport { useChannelsStore } from '@/stores/channels';\n\nconst emit = defineEmits([\"focus\", \"blur\"]);\n\nconst store = useChannelsStore()\n\nconst isSearching = ref(false)\n\nfunction search(searchString) {\n  store.searchString = searchString\n  debouncedApiSearchCall(store.searchString)\n}\n\nconst debouncedApiSearchCall = useDebounceFn((searchString) => {\n  store.search(searchString)\n}, 1000)\n\n\nfunction onFocus() {\n  emit('focus', 'FOCUSED')\n  isSearching.value = true\n}\n\nfunction onBlur() {\n  emit('blur', \"NONE\")\n  isSearching.value = false\n}\n</script>\n\n\n<style lang=\"scss\" scoped>\n.message_search {\n  &__container {\n    background-color: $grey-25;\n    height: 48px;\n    display: flex;\n    align-items: center;\n    justify-content: space-between;\n    padding: $spacing-3 $spacing-5;\n    font-size: $text-base;\n    border-radius: $rounded-2xl;\n    border: 1px solid $grey-25;\n  }\n\n\n  &__input {\n    background-color: $grey-25;\n    width: 100%;\n    border: none !important;\n\n    &:focus {\n      outline: none;\n    }\n  }\n}\n\n.clear_button {\n  color: $grey-100;\n  margin: 0 calc($spacing-3 - 2px);\n\n  &:hover {\n   cursor: pointer;\n  }\n}\n\n.selected {\n  border: 1px solid $brand-tertiary;\n}\n</style>","import moment from \"moment-timezone\";\n\nexport function getFuzzyTime(localMoment) {\n  const now = moment().local()\n  const diffDays = now.diff(localMoment, 'days')\n\n  if (diffDays < 1) {\n    return localMoment.format('HH:mm A')\n  } else if (diffDays < 6.5) {\n    return `${Math.round(diffDays)}d`\n  } else if (diffDays < 30) {\n    return `${Math.round(now.diff(localMoment, 'weeks'))}w`\n  } else if (diffDays < 365) {\n    return `${Math.round(now.diff(localMoment, 'months'))}m`\n  } else {\n    return `${Math.round(now.diff(localMoment, 'years'))}y`\n  }\n}","<template>\n  <div class=\"search_result\" :class=\"{ 'search_result__selected': searchSelection == props.searchResultIndex }\" @click=\"onSelect(props.index)\">\n    <Avatar :url=\"avatarUrl\" size=\"sm\" />\n    <div class=\"search_result_message\">\n      <div class=\"search_result_message__info\">\n        <div class=\"search_result_message__name\">{{ senderName }}</div>\n        <div class=\"search_result_message__time\">{{ sentAt }}</div>\n      </div>\n      <div class=\"search_result_message_container\" v-if=\"props.messageType == 'image'\">\n        <div class=\"search_result_text\">\n          <Highlighter :highlightStyle=\"{ 'font-weight': 600, 'background-color': 'transparent' }\"\n            :searchWords=\"[searchString]\" :autoEscape=\"true\"\n            :textToHighlight=\"truncateMatchingSubstring(props.content, searchString, 20)\" />\n        </div>\n        <img class=\"search_result_image\" :src=\"props.attachments?.url\" />\n      </div>\n      <div v-else class=\"search_result_text\">\n        <Highlighter :highlightStyle=\"{ 'font-weight': 600, 'background-color': 'transparent' }\"\n          :searchWords=\"[searchString]\" :autoEscape=\"true\"\n          :textToHighlight=\"truncateMatchingSubstring(props.content, searchString, 20)\" />\n      </div>\n    </div>\n  </div>\n</template>\n\n<script setup>\nimport { computed } from 'vue'\nimport { storeToRefs } from 'pinia';\nimport moment from 'moment';\nimport Highlighter from 'vue-highlight-words'\nimport { useChannelsStore } from '@/stores/channels';\nimport Avatar from '@/components/Theme/Avatar.vue';\nimport { truncateMatchingSubstring } from '@/utils/stringUtils';\nimport { getFuzzyTime } from '@/utils/momentUtils';\n\nconst store = useChannelsStore()\n\nconst props = defineProps({\n  id: String,\n  searchResultIndex: Number,\n  content: { type: String, default: \"\" },\n  messageType: String,\n  senderName: { type: String, default: \"\" },\n  senderId: String,\n  supplierId: String,\n  createdAt: String,\n  attachments: {\n    fileName: String,\n    url: String,\n    size: Number\n  },\n})\n\nconst { currentChannelId, searchSelection, searchString } = storeToRefs(store)\nconst avatarUrl = computed(() => store.getMessageAvatar(store.currentChannelId, props.senderId, props.senderName, props.supplierId))\nconst sentAt = computed(() => getFuzzyTime(moment.utc(props.createdAt).local()))\n\nasync function onSelect() {\n  await store.searchResultMessages(props.id)\n  store.setIsViewingPastMessages(currentChannelId.value, true)\n  store.setSearchSelection(props.searchResultIndex)\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.search_result {\n  width: 100%;\n  display: flex;\n  padding: $spacing-3;\n  border-radius: $rounded-2xl;\n\n  &__selected {\n    background-color: $grey-25;\n  }\n\n  &:hover {\n    background-color: $green-50;\n    cursor: pointer;\n  }\n\n  .search_result_message {\n    width: 100%;\n    display: flex;\n    flex-wrap: wrap;\n    align-items: center;\n    font-size: $text-sm;\n    margin-left: $spacing-3;\n\n    &__info {\n      display: flex;\n      justify-content: space-between;\n      align-items: center;\n      width: 100%\n    }\n\n    &__name {\n      font-weight: $font-bold;\n    }\n\n    &__time {\n      color: $grey-100;\n    }\n  }\n\n  .search_result_text {\n    width: 100%;\n    font-size: $text-base;\n  }\n\n  .search_result_image {\n    max-width: 154px;\n    height: 154px;\n    border-radius: $rounded-2xl;\n  }\n}\n</style>","<template>\n  <Product\n    :featureImageUrl=\"itineraryRequest.featureImageUrl || HeroElephant\"\n    :heroImageUrl=\"HeroElephant\"\n    :country=\"itineraryRequest.targetCountryName\"\n    :title=\"itineraryRequest.title\"\n    :isMba=\"false\"\n    :spotsLeft=\"null\"\n    :externalLink=\"itineraryRequest.url\"\n    classes=\"request-card\"\n  >\n    <template #productMeta>\n      <div class=\"product__price\" v-if=\"itineraryRequest.minPrice\">\n        <span>From </span>\n        <Money\n          :currency=\"itineraryRequest.minPrice.currency\"\n          :options=\"{ maximumFractionDigits: 0, currencyDisplay: 'code' }\"\n          :value=\"itineraryRequest.minPrice.priceCents\"\n          inline\n        />\n      </div>\n      <div class=\"product__date\">\n        {{ itineraryRequest.dates }} -\n        <span>\n          {{ t('nights', { count: itineraryRequest.durationNights }, itineraryRequest.durationNights) }}\n        </span>\n      </div>\n    </template>\n  </Product>\n</template>\n\n<script setup>\nimport { useShared } from \"@/helpers/vueHelpers.js\";\nimport Product from '@/modules/Explore/Product2/index.vue';\nimport HeroElephant from 'app/assets/images/overlands/profiles/hero-elephant.png';\nimport Money from '@/components/Money.vue';\n\n\nconst { t } = useShared();\n\ndefineProps({\n  itineraryRequest: Object\n})\n</script>\n\n<style lang=\"scss\" scoped>\n.product__price {\n  color: $brand-secondary;\n  font-size: 14px;\n  line-height: 16px;\n}\n\n.product__date {\n  color: $gray;\n  font-size: 12px;\n  line-height: 14px;\n  text-transform: uppercase;\n}\n</style>\n\n<i18n lang=\"yaml\">\nen:\n  loading: Loading ...\n  trips_available: 'No trip available | {count} trip available | {count} trips available'\n  mba_trip: MBA Trip\n  nights: '{count} night | {count} nights'\n</i18n>\n","<template>\n  <div class=\"chat-details__item\">\n    <div class=\"chat-details__draft-itinerary-title\">\n      {{ store.getProduct ? t('itinerary') : t('draft_itinerary') }}\n    </div>\n    <ProductCard v-if=\"store.getProduct\" :product=\"store.getProduct\" openInNewTab />\n    <ItineraryRequestCard v-else-if=\"store.getItineraryRequest?.matched\" :itineraryRequest=\"store.getItineraryRequest\" openInNewTab />\n  </div>\n</template>\n\n<script setup>\nimport { useShared } from 'app/javascript/src/helpers/vueHelpers';\nimport { useChannelsStore } from '@/stores/channels';\nimport ProductCard from '@/modules/Explore/ProductCard2.vue';\nimport ItineraryRequestCard from '@/components/Chat/ChatroomDetails/ItineraryRequestCard.vue';\n\nconst store = useChannelsStore()\nconst { t } = useShared()\n</script>\n\n<style lang=\"scss\" scoped>\n.chat-details__item {\n  width: 100%;\n}\n\n.chat-details__draft-itinerary-title {\n  font-size: $text-xs;\n  font-weight: $font-semibold;\n  margin-bottom: $spacing-3;\n  text-transform: uppercase;\n}\n</style>\n\n<i18n lang=\"yaml\">\n  en:\n    itinerary: Itinerary\n    draft_itinerary: Draft Itinerary\n</i18n>\n","<template>\n  <div class=\"chat-details__item\">\n    <div class=\"chat-details__requirements-title\">\n      <i v-if=\"showRequirements\" class=\"icon icon-arrow-down-2\" @click=\"showRequirements = false\"></i>\n      <i v-else class=\"icon icon-arrow-right-2\" @click=\"showRequirements = true\"></i>\n      {{ t('requirements') }}\n    </div>\n    <div v-show=\"showRequirements\">\n      <div class=\"chat-details__requirement-details\" v-if=\"itineraryRequest\">\n        <template v-if=\"itineraryRequest\" v-for=\"field in Object.keys(displayFields)\">\n          <div v-if=\"!nullValue(displayFields[field])\" class=\"chat-details__requirement-field-container\">\n            <div class=\"chat-details__requirement-field-title\">{{ field }}</div>\n            <div class=\"chat-details__requirement-field-value\">{{ itineraryRequest[displayFields[field]] }}</div>\n          </div>\n        </template>\n      </div>\n    </div>\n  </div>\n</template>\n\n<script setup>\nimport { ref, computed } from 'vue'\nimport { useShared } from \"@/helpers/vueHelpers.js\";\nimport { useChannelsStore } from '@/stores/channels';\n\nconst { t } = useShared();\n\nconst store = useChannelsStore()\n\nconst showRequirements = ref(true)\n\nconst itineraryRequest = computed(() => store.getItineraryRequest)\nconst displayFields = { \"Dates\": \"requestDatesText\", \"Accommodation\": \"bedRequirements\", \"Group size\": \"group\", \"Budget\": \"budgetText\", \"Activities\": \"activities\" }\nconst nullValue = (field) => {\n  return itineraryRequest.value[field] === null || itineraryRequest.value[field] === \"I don’t know yet\";\n};\n</script>\n\n<style lang=\"scss\" scoped>\n.chat-details__item {\n  width: 100%;\n  margin-bottom: $spacing-4;\n}\n\n.chat-details__requirements-title {\n  font-size: $text-xs;\n  font-weight: $font-semibold;\n}\n\n.chat-details__requirement-details {\n  @include flex-column($spacing-4);\n  margin-top: $spacing-3;\n}\n\n.chat-details__requirement-field-container {\n  @include flex-column;\n}\n\n.chat-details__requirement-field-title {\n  font-size: $text-base;\n  color: $gray;\n  margin-bottom: $spacing-2\n}\n\n.chat-details__requirement-field-value {\n  font-size: $text-base;\n}\n\n.chat-details__requirement-not-specified {\n  margin-top: $spacing-3;\n  color: $gray;\n  font-size: $text-base;\n}\n</style>\n<i18n lang=\"yaml\">\nen:\n  requirements: REQUIREMENTS\n</i18n>\n","<template>\n  <div ref=\"container\" class=\"chat-details__container\">\n    <div class=\"chat-details__title\">\n      <div v-if=\"isSearchOpen\" class=\"chat-details__title__search\">\n        <i class=\"icon icon-arrow-left-1\" @click=\"store.closeSearch\"></i>{{ t('search') }}\n      </div>\n      <div v-else>{{ t('details') }}</div>\n      <i v-if=\"mobile && openMobileDetails\" class=\"icon icon-close\" @click=\"store.toggleOpenMobileDetails\"></i>\n    </div>\n    <MessageSearch @focus=\"toggleSearchStatus\" @blur=\"toggleSearchStatus\" />\n    <div class=\"chat-details__overlay\" :style=\"{ 'opacity': isSearchOpen ? '100%' : getOverlayOpacity(searchStatus) }\">\n      <div v-if=\"isSearchOpen\" class=\"message-search__results\">\n        <template v-for=\"(searchResult, index) in searchResults\" :key=\"searchResult.id\">\n          <SearchResult :id=\"searchResult.id\" :searchResultIndex=\"index\" :content=\"searchResult.content\"\n            :messageType=\"searchResult.messageType\" :attachments=\"searchResult.attachments\"\n            :senderName=\"searchResult.senderName\" :senderId=\"searchResult.senderId\"\n            :supplierId=\"searchResult.supplierId\" :createdAt=\"searchResult.createdAt\" />\n        </template>\n        <div class=\"message-search__no_results\" v-if=\"searchResults.length === 0\">\n          {{ t('no_search_results') }}\n        </div>\n      </div>\n      <div v-else class=\"chat-details__info\">\n        <OperatorSection v-if=\"isSupplier\"/>\n        <Itinerary v-if=\"store.getProduct || store.getItineraryRequest?.matched\" />\n        <ChatroomMembers />\n        <Requirements v-if=\"store.getItineraryRequest\" />\n      </div>\n    </div>\n  </div>\n</template>\n\n<script setup>\nimport { computed, ref } from 'vue';\nimport { useShared } from '@/helpers/vueHelpers';\nimport { storeToRefs } from 'pinia';\nimport { useChannelsStore } from '@/stores/channels';\nimport OperatorSection from '@/components/Chat/ChatroomDetails/OperatorSection.vue';\nimport ChatroomMembers from '@/components/Chat/ChatroomDetails/ChatroomMembers.vue';\nimport MessageSearch from '@/components/Chat/ChatroomDetails/MessageSearch.vue';\nimport SearchResult from '@/components/Chat/ChatroomDetails/SearchResult.vue';\nimport Itinerary from '@/components/Chat/ChatroomDetails/Itinerary.vue';\nimport Requirements from '@/components/Chat/ChatroomDetails/Requirements.vue';\n\nconst { t, mobile } = useShared()\nconst store = useChannelsStore()\n\nconst { isSearchOpen, searchResults } = storeToRefs(store)\nconst isSupplier = computed(() => store.profiles?.own?.supplier_id !== null)\n\nconst searchStatus = ref(\"NONE\")\nconst container = ref(null)\n\nconst { openMobileDetails } = storeToRefs(store)\n\nfunction getOverlayOpacity(status) {\n  if (status == \"FOCUSED\") return \"50%\"\n  return \"100%\"\n}\n\nfunction toggleSearchStatus(status) {\n  searchStatus.value = status\n}\n\n\n</script>\n\n<style lang=\"scss\" scoped>\n.chat-details__container {\n  @include flex-column;\n  height: 100%;\n  padding: $spacing-6;\n  gap: $spacing-4;\n}\n\n.chat-details__title {\n  display: flex;\n  font-size: $text-lg;\n  font-weight: $font-semibold;\n  justify-content: space-between;\n\n  &__search {\n    display: flex;\n    align-items: center;\n  }\n}\n\n.message-search__no_results {\n  width: 100%;\n  display: flex;\n  justify-content: center;\n  color: $gray;\n}\n\n.message-search__results {\n  height: 100%;\n  overflow-y: scroll;\n  scrollbar-width: none;\n  -ms-overflow-style: none;\n}\n\n.chat-details__overlay {\n  // 90px = title + search bar + padding\n  height: calc(100% - 90px);\n  width: 100%;\n  background-color: $white;\n}\n\n.chat-details__info {\n  display: flex;\n  height: 100%;\n  flex-direction: column;\n  flex-wrap: nowrap;\n  row-gap: $spacing-8;\n  overflow-y: scroll;\n  scrollbar-width: none;\n  -ms-overflow-style: none;\n  margin-top: $spacing-2;\n}\n\n.icon-arrow-left-1 {\n  font-size: $text-base;\n  margin-right: calc($spacing-1 + 1px);\n\n  &:hover {\n    cursor: pointer;\n  }\n}\n\n.icon-close {\n  font-size: $text-sm;\n}\n</style>\n\n<i18n lang=\"yaml\">\n  en:\n    details: Details\n    search: Search\n    no_search_results: No results found for your search\n</i18n>\n","import Pusher from \"pusher-js\";\nimport { metaTagContent } from \"@/helpers/documentHelpers.js\";\n\nexport class ChatroomChannelEventBinder {\n  handledChannelEvents = [\"message_created\", \"message_error\", \"chatroom_name_updated\", \"chatroom_association_updated\", \"chatroom_members_updated\"]\n  handledUserEvents = [\"chatroom_created\", \"chatroom_removed\"]\n\n  constructor(pusher) {\n    this.pusher = pusher\n  }\n\n  bind(user, chatroomIds, bindings) {\n    const channelPrefix = 'private-chat-';\n    const userChannelPrefix = 'private-user-';\n    const userChannelName = userChannelPrefix + user.slug\n\n    let userChannel = this.pusher.subscribe(userChannelName);\n\n    // on new chatroom creation, add channel to store and subscribe event bindings\n    Object.entries(bindings).forEach(([eventName, callback]) => {\n      if (this.handledUserEvents.includes(eventName)) {\n        userChannel.bind(eventName, (payload) => {\n          let channelId = payload.data.id\n          callback(payload)\n\n          switch (eventName) {\n            case \"chatroom_removed\":\n              this.pusher.unsubscribe(channelPrefix + channelId)\n              break\n            case \"chatroom_created\":\n              let chatroomChannel = this.pusher.subscribe(channelPrefix + channelId)\n              this.bindChannel(chatroomChannel, bindings)\n              break\n            default:\n              return\n          }\n        })\n      }\n    })\n\n    // set up event bindings for each chatroom\n    chatroomIds.forEach((id) => {\n      let channelName = channelPrefix + id;\n\n      const subscribedChannels = this.pusher.allChannels().filter(c => c.subscribed).map(c => c.name)\n\n      subscribedChannels.filter(c => c.startsWith(channelPrefix) && c == channelName).forEach(c => this.pusher.unsubscribe(c));\n\n      let chatroomChannel = this.pusher.subscribe(channelName);\n      this.bindChannel(chatroomChannel, bindings)\n    })\n\n    this.pusher.connect();\n  }\n\n  bindChannel(channel, bindings) {\n    Object.entries(bindings).forEach(([eventName, callback]) => {\n      if (this.handledChannelEvents.includes(eventName)) channel.bind(eventName, (data) => { callback(data) });\n    })\n  }\n}\n\nexport function useChatPusher() {\n  const pusher = createPusherGlobalInstance();\n\n  const unsubscribeAllChannels = () => pusher.allChannels().filter(c => c.subscribed).map(c => c.name).forEach(c => pusher.unsubscribe(c));\n\n  const binder = new ChatroomChannelEventBinder(pusher)\n\n  return {\n    pusher,\n    unsubscribeAllChannels,\n    binder\n  };\n}\n\n\nexport function disconnectPusher() {\n  if (window.pusher) {\n    useChatPusher().unsubscribeAllChannels();\n  }\n}\n\nfunction createPusherGlobalInstance() {\n  return window.pusher ??= new Pusher(PUSHER_KEY, {\n    cluster: PUSHER_CLUSTER,\n    channelAuthorization: {\n      endpoint: \"/api/pusher/chat-auth\",\n      headers: {\n        \"X-CSRF-Token\": metaTagContent('csrf-token')\n      },\n    }\n  });\n}"],"names":["TourHeroSupport","SendStatus","TOURHERO_ADMIN_AVATAR","DEFAULT_AVATAR","Message$1","tempId","content","channelId","senderName","senderId","sendStatus","displayName","updateMessageCallback","__publicField","moment","errorMessage","MAX_SIZE_MB","ALLOWED_IMAGE_TYPES","ALLOWED_FILE_TYPES","Message","files","abortController","attachments","progress","max","convertToBytes","generateTempId","last_message_id","idParts","id","subId","useChannelsStore","defineStore","state","chatroom","isEmpty","_a","chatroomId","ownIndex","message","unreadIndex","_b","_c","userCount","operatorCount","userProfiles","operatorProfiles","supplierId","currentChatroomLastMessage","scroller","messages","uniqBy","boolean","searchResultIndex","channels","autoLoadFirstChannel","orderBy","channel","keyBy","chatroom_id","results","api","deserializeJsonApi","payload","existingChannel","removedChannel","camelizedPayload","camelizeKeys","chatroomMessages","own_message","lastMessage","newMessagePayload","isLastMessageFetched","isViewingPastMessages","data","result","text","latestChatroomMessage","textMessage","until","fileMessage","FileMessage","progressEvent","e","AxiosError","messageId","property","newValue","response","trigger","searchString","resultId","searchResult","scrollIndexWithOffset","scrollIndex","index","searchMessageId","user_emails","product_id","itineraryRequestId","ownKeys","object","enumerableOnly","keys","symbols","sym","_objectSpread2","target","i","source","key","_defineProperty","_classCallCheck","instance","Constructor","_defineProperties","props","descriptor","_createClass","protoProps","staticProps","obj","value","_toConsumableArray","arr","_arrayWithoutHoles","_iterableToArray","_unsupportedIterableToArray","_nonIterableSpread","_arrayLikeToArray","iter","o","minLen","n","len","arr2","DIRECTION_TYPE","CALC_TYPE","LEADING_BUFFER","Virtual","param","callUpdate","range","start","_this","v","size","acc","val","offset","overs","low","middle","middleOffset","high","givenIndex","indexSize","end","keeps","total","theoryEnd","truelyEnd","lastIndex","VirtualProps","ItemProps","SlotProps","useResizeChange","rootRef","emit","resizeObserver","shapeKey","computed","getCurrentSize","dispatchSizeChange","event","uniqueKey","hasInitial","onMounted","onUpdated","onUnmounted","Item","defineComponent","_ref","ref","Tag","Comp","_props$extraProps","extraProps","_props$scopedSlots","scopedSlots","mergedProps","createVNode","Slot","_ref2","slots","_slots$default","EVENT_TYPE","SLOT_TYPE","VirtualList","expose","isHorizontal","directionKey","root","shepherd","virtual","watch","getUniqueIdFromDataSources","scrollToIndex","scrollToOffset","getSize","getOffset","getClientSize","getScrollSize","emitEvent","clientSize","scrollSize","evt","onScroll","dataKey","_props$dataSources","dataSources","dataSource","onRangeChanged","newRange","installVirtual","scrollToBottom","getRenderSlots","_range$value","itemClass","itemTag","itemStyle","dataComponent","itemScopedSlots","onItemResized","onSlotResized","type","hasInit","updatePageModeFront","rect","defaultView","offsetFront","getSizes","onBeforeMount","onActivated","pageMode","RootTag","WrapTag","wrapClass","wrapStyle","headerTag","headerClass","headerStyle","footerTag","footerClass","footerStyle","padFront","padBehind","paddingStyle","wrapperStyle","header","footer","t","useShared","store","attach","multiLine","textarea","input","useTextareaAutosize","onResize","chatInputEnabled","acceptStr","send","openFiles","onFilesSelected","fileList","mobile","memberCount","isSupplier","avatar","back","onClickPreview","onClickSendQuote","chat_id","itinerary_request_id","__props","alias","profiles","storeToRefs","isInitiator","isInvitee","invitee","Check","download","cancelUpload","ImageUploadError","image","overlayWidth","isLoading","useImage","product","module","modules","installedModules","__webpack_require__","moduleId","exports","_utils","autoEscape","_ref$caseSensitive","caseSensitive","_ref$findChunks","findChunks","defaultFindChunks","sanitize","searchWords","textToHighlight","fillInChunks","combineChunks","chunks","first","second","processedChunks","nextChunk","prevChunk","endIndex","_ref3","_ref3$sanitize","defaultSanitize","searchWord","escapeRegExpFn","regex","match","_start","_end","_ref4","chunksToHighlight","totalLength","allChunks","append","highlight","chunk","string","VueHighlightWordsImpl","context","findAll","children","getTextChildren","h","attrs","EMPTY_STYLE","highlightCount","highlightClassNames","highlightStyles","highlightClassName","highlightStyle","activeIndex","activeClassName","activeStyle","isActive","word","VueHighlightWords","isSearchOpen","sendTime","_sfc_render","_ctx","_cache","_openBlock","_createElementBlock","_hoisted_1","isMessageInView","useElementVisibility","scrollPointIndex","nextTick","inView","avatarUrl","shouldDisplayDate","previousMessage","isOwnMessage","title","chatInput","messageContainerHeight","scrollTopPosition","scrollBottomPosition","searchButtonPosition","searchResults","searchSelection","currentChannelId","chatInputHeight","useElementSize","contentHeight","hideScrollTop","hideScrollBottom","showNextSearchButtons","next","prev","nextInputHeight","nextContentHeight","_","scrollToUnread","unreadMessageIndex","onSearchClick","itineraryRequest","airtableItinerary","showSent","errors","splitIntoUserEmails","compact","email","validateEmails","EMAIL_REGEX","sendInvites","emailArr","uniq","tourheroExperienceTeam","showMembers","showInvitationDialog","members","shouldShowInviteOthers","user","toggleShowInvitation","__emit","isSearching","search","debouncedApiSearchCall","useDebounceFn","onFocus","onBlur","getFuzzyTime","localMoment","now","diffDays","sentAt","onSelect","showRequirements","displayFields","nullValue","field","searchStatus","container","openMobileDetails","getOverlayOpacity","status","toggleSearchStatus","ChatroomChannelEventBinder","pusher","chatroomIds","bindings","channelPrefix","userChannelName","userChannel","eventName","callback","chatroomChannel","channelName","c","useChatPusher","createPusherGlobalInstance","unsubscribeAllChannels","binder","Pusher","metaTagContent"],"mappings":"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","x_google_ignoreList":[5,14,15]}