This commit is contained in:
Vendored
+1
-1
@@ -10,8 +10,8 @@ declare module 'vue' {
|
||||
Button: typeof import('primevue/button')['default']
|
||||
Card: typeof import('primevue/card')['default']
|
||||
ChatCard: typeof import('./src/components/ChatCard.vue')['default']
|
||||
ChatComponent: typeof import('./src/components/ChatComponent.vue')['default']
|
||||
ChatForm: typeof import('./src/components/chat/ChatForm.vue')['default']
|
||||
ChatMessages: typeof import('./src/components/chat/ChatMessages.vue')['default']
|
||||
ChatSubscribeWebPush: typeof import('./src/components/ChatSubscribeWebPush.vue')['default']
|
||||
Checkbox: typeof import('primevue/checkbox')['default']
|
||||
CopyLinkButton: typeof import('@/components/link/LinkCopyButton.vue')['default']
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="flex gap-3 px-4 pt-0 flex-col-reverse pb-safe-or-4">
|
||||
<div class="sm:max-w-prose mx-auto flex gap-3 px-4 pt-0 flex-col-reverse sm:pb-safe-or-4 w-full">
|
||||
<!-- Форма отправки сообщений -->
|
||||
<form @submit.prevent="sendMessage" class="flex gap-2 items-center" ref="form">
|
||||
<InputText
|
||||
|
||||
+11
-13
@@ -1,12 +1,13 @@
|
||||
<template>
|
||||
<div class="flex flex-col flex-grow place-self-stretch">
|
||||
<!-- Список сообщений -->
|
||||
<div class="flex-grow overflow-y-auto p-4" ref="messagesContainer">
|
||||
<div class="place-self-stretch flex flex-col">
|
||||
<div
|
||||
v-for="message in messages"
|
||||
:key="message._id"
|
||||
class="mb-4 max-w-md"
|
||||
:class="{ 'ml-auto': message.from === userRole, 'mr-auto': message.from !== userRole }"
|
||||
:class="{
|
||||
'ml-auto text-right': message.from === userRole,
|
||||
'mr-auto text-left': message.from !== userRole,
|
||||
}"
|
||||
>
|
||||
<Card
|
||||
class="p-card-sm"
|
||||
@@ -25,10 +26,7 @@
|
||||
name="endOfMessages"
|
||||
:count="messages.length"
|
||||
:lastMessage="messages.length > 0 ? messages[messages.length - 1] : null"
|
||||
></slot>
|
||||
</div>
|
||||
|
||||
<ChatForm :qr_code_uri :chat :userRole />
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -37,8 +35,6 @@ import { ref, onMounted, onUnmounted, useTemplateRef, watch, nextTick } from 'vu
|
||||
import { messagesDbLocal as db, messagesDbRemote as remoteDb } from '@/api/dbs'
|
||||
import { type MessageDocument } from '@hereconnect/types'
|
||||
|
||||
const messagesContainerRef = useTemplateRef('messagesContainer')
|
||||
|
||||
const { qr_code_uri, chat, userRole } = defineProps<{
|
||||
qr_code_uri: MessageDocument['qr_code_uri']
|
||||
chat: MessageDocument['chat']
|
||||
@@ -134,13 +130,15 @@ onMounted(async () => {
|
||||
await loadMessages()
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
(event: 'scrollToBottom'): void
|
||||
}>()
|
||||
|
||||
watch(
|
||||
() => messages.value?.length,
|
||||
async () => {
|
||||
if (messagesContainerRef.value) {
|
||||
await nextTick()
|
||||
messagesContainerRef.value.scrollTop = messagesContainerRef.value.scrollHeight
|
||||
}
|
||||
emit('scrollToBottom')
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
<template>
|
||||
<div class="grid h-full sm:grid-rows-[auto_1fr_auto] grid-rows-[1fr_auto_auto] overflow-hidden">
|
||||
<div class="flex overflow-auto pb-safe-or-4 sm:pt-safe w-full px-4 touch-pan-y">
|
||||
<div class="sm:max-w-prose grid grid-cols-1 mx-auto my-5">
|
||||
<slot />
|
||||
<div
|
||||
class="flex overflow-auto pb-safe-or-4 sm:pt-safe px-4 touch-pan-y"
|
||||
ref="contentScrollContainer"
|
||||
>
|
||||
<div class="sm:max-w-prose grid grid-cols-1 mx-auto my-5 w-full">
|
||||
<slot name="default" v-bind:scrollToBottom />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,11 +28,21 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useTemplateRef } from 'vue'
|
||||
|
||||
const slots = defineSlots<{
|
||||
default?: () => void
|
||||
default?: (slotBindings: { scrollToBottom: typeof scrollToBottom }) => void
|
||||
footer?: () => void
|
||||
}>()
|
||||
|
||||
const contentScrollContainerRef = useTemplateRef('contentScrollContainer')
|
||||
|
||||
const scrollToBottom = () => {
|
||||
if (contentScrollContainerRef.value) {
|
||||
contentScrollContainerRef.value.scrollTop = contentScrollContainerRef.value.scrollHeight
|
||||
}
|
||||
}
|
||||
|
||||
const layoutPageHead = useHead({
|
||||
htmlAttrs: { class: 'overflow-hidden' },
|
||||
bodyAttrs: { class: 'overflow-hidden' },
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<LayoutWithTabs>
|
||||
<template #default="{ scrollToBottom }">
|
||||
<MetaHead>
|
||||
<title>Чат — НаСвязи</title>
|
||||
<meta
|
||||
@@ -8,12 +9,17 @@
|
||||
/>
|
||||
</MetaHead>
|
||||
|
||||
<ChatComponent userRole="guest" :qr_code_uri="qr_code_uri" :chat="chat">
|
||||
<ChatMessages
|
||||
userRole="guest"
|
||||
:qr_code_uri="qr_code_uri"
|
||||
:chat="chat"
|
||||
@scrollToBottom="scrollToBottom()"
|
||||
>
|
||||
<template #endOfMessages="{ count, lastMessage }">
|
||||
<!-- Уведомление, если гость отправил только одно сообщение -->
|
||||
<div
|
||||
v-if="count === 1 && lastMessage && lastMessage.from === 'guest'"
|
||||
class="flex flex-col items-center justify-center text-center bg-gray-50 border border-gray-200 rounded-lg shadow-md p-6 mt-6"
|
||||
class="flex flex-col items-center justify-center text-center bg-gray-50 border border-gray-200 rounded-lg shadow-md p-6 my-6"
|
||||
>
|
||||
<p class="text-gray-700 font-medium text-lg">Ваше сообщение отправлено.</p>
|
||||
<p class="text-gray-600 mt-2">
|
||||
@@ -21,12 +27,16 @@
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</ChatComponent>
|
||||
</ChatMessages>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<ChatForm :qr_code_uri :chat userRole="guest" />
|
||||
</template>
|
||||
</LayoutWithTabs>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { MessageDocument } from '@hereconnect/types'
|
||||
import ChatComponent from '@/components/ChatComponent.vue'
|
||||
defineProps<{ qr_code_uri: MessageDocument['qr_code_uri']; chat: MessageDocument['chat'] }>()
|
||||
</script>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<template #default="{ data }">
|
||||
<div
|
||||
v-if="data.length > 0"
|
||||
class="justify-self-start align-baseline-start flex flex-col gap-4"
|
||||
class="grid grid-cols-1 gap-5 place-self-center sm:place-self-start w-full"
|
||||
>
|
||||
<ChatCard
|
||||
v-for="row in data"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<LayoutWithTabs>
|
||||
<template #default="{ scrollToBottom }">
|
||||
<MetaHead>
|
||||
<title>Чат {{ chatDoc?.name ? `«${chatDoc.name}»` : '' }} — НаСвязи</title>
|
||||
<meta
|
||||
@@ -8,11 +9,12 @@
|
||||
/>
|
||||
</MetaHead>
|
||||
|
||||
<div class="flex flex-col min-h-full">
|
||||
<!-- Основной контент -->
|
||||
<main class="flex-grow flex flex-col">
|
||||
<section class="flex flex-col flex-grow max-w-prose w-full mx-auto">
|
||||
<ChatComponent userRole="owner" :qr_code_uri="qr_code_uri" :chat="chat">
|
||||
<ChatMessages
|
||||
userRole="owner"
|
||||
:qr_code_uri="qr_code_uri"
|
||||
:chat="chat"
|
||||
@scrollToBottom="scrollToBottom()"
|
||||
>
|
||||
<template #endOfMessages="{ count, lastMessage }">
|
||||
<div
|
||||
v-if="!count"
|
||||
@@ -23,7 +25,7 @@
|
||||
</div>
|
||||
<div
|
||||
v-else-if="lastMessage && lastMessage.from === 'owner'"
|
||||
class="flex flex-col items-center justify-center text-center bg-gray-50 border border-gray-200 rounded-lg shadow-md p-6 mt-6"
|
||||
class="flex flex-col items-center justify-center text-center bg-gray-50 border border-gray-200 rounded-lg shadow-md p-6 my-6"
|
||||
>
|
||||
<p class="text-gray-700 font-medium text-lg">Ваше сообщение отправлено.</p>
|
||||
<p class="text-gray-600 mt-2">
|
||||
@@ -31,26 +33,17 @@
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
</ChatComponent>
|
||||
</section>
|
||||
</main>
|
||||
</ChatMessages>
|
||||
</template>
|
||||
|
||||
<!-- Футер -->
|
||||
<!-- <footer class="bg-gray-100 text-center py-4 border-t text-sm text-gray-700">-->
|
||||
<!-- <p><a href="/create" class="underline underline-offset-2">Создайте свой QR‑код</a>.</p>-->
|
||||
<!-- <p class="mt-1">-->
|
||||
<!-- Сделайте НаСвязи удобнее. Будем рады вашей <a href="/donate" class="underline underline-offset-2"-->
|
||||
<!-- >поддержке</a-->
|
||||
<!-- >.-->
|
||||
<!-- </p>-->
|
||||
<!-- </footer>-->
|
||||
</div>
|
||||
<template #footer>
|
||||
<ChatForm :qr_code_uri :chat userRole="owner" />
|
||||
</template>
|
||||
</LayoutWithTabs>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { MessageDocument } from '@hereconnect/types'
|
||||
import ChatComponent from '@/components/ChatComponent.vue'
|
||||
import { getQrCodeDocument } from '@/api/qrCode'
|
||||
import { useQuery } from '@tanstack/vue-query'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user