chats
Deploy app frontend / app frontend (push) Has been cancelled
Deploy db-migrations / db-migrations (push) Successful in 38s

This commit is contained in:
2024-12-06 23:50:51 +02:00
parent cf87c0daa7
commit 51a7f8f354
7 changed files with 124 additions and 16 deletions
+1
View File
@@ -9,6 +9,7 @@ declare module 'vue' {
export interface GlobalComponents {
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']
ChatSubscribeWebPush: typeof import('./src/components/ChatSubscribeWebPush.vue')['default']
Checkbox: typeof import('primevue/checkbox')['default']
+1
View File
@@ -19,6 +19,7 @@ export const getLocalDb = <T extends BaseDocument>(dbName: DB_NAMES) => new Pouc
export const qrCodeDbRemote = getRemoteDb<QRCodeDocument>(DB_NAMES.QR)
export const qrCodeDbLocal = getLocalDb<QRCodeDocument>(DB_NAMES.QR)
export const messagesDbLocal = getLocalDb<MessageDocument>(DB_NAMES.MESSAGES)
export const chatsDbLocal = getLocalDb<ChatDocument>(DB_NAMES.CHATS)
export const chatsDbRemote = getRemoteDb<ChatDocument>(DB_NAMES.CHATS)
export const webPushSubscriptionsDbRemote = getRemoteDb<
WebPushSubscriptionDocument<PushSubscriptionJSON>
+44
View File
@@ -0,0 +1,44 @@
<template>
<RouterLink :to="route" class="p-4 rounded-lg bg-white shadow-md" v-if="chatDoc.qr_code_uri">
<div class="flex items-center justify-between mb-2">
<div class="flex items-center">
<h2 class="text-lg font-semibold">{{ chatDoc.name }}</h2>
</div>
</div>
<div class="text-gray-500">
<span class="text-nowrap">{{ formatedCreatedAt }}</span>
</div>
</RouterLink>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import type { ChatDocument } from '@hereconnect/types'
import { ROUTE_NAMES } from '@/constants/routes'
const props = defineProps<{
chatDoc: ChatDocument
}>()
const formatDate = (date: string) => {
// Форматирование даты
const options: Intl.DateTimeFormatOptions = {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
}
return new Date(date).toLocaleDateString(['ru-RU'], options)
}
const route = computed(() => {
return {
name:
props.chatDoc.role === 'owner' ? ROUTE_NAMES.MANAGE_QR_CODE_CHAT : ROUTE_NAMES.PUBLIC_CHAT,
params: { qr_code_uri: props.chatDoc.qr_code_uri, chat: props.chatDoc.chat },
}
})
const formatedCreatedAt = computed(() => formatDate(props.chatDoc.created_at))
</script>
+38 -9
View File
@@ -52,8 +52,13 @@
<script setup lang="ts">
import { ref, onMounted, onUnmounted, useTemplateRef, watch, nextTick } from 'vue'
import { messagesDbLocal as db, messagesDbRemote as remoteDb } from '@/api/dbs'
import { type MessageDocument } from '@hereconnect/types'
import {
chatsDbLocal,
chatsDbRemote,
messagesDbLocal as db,
messagesDbRemote as remoteDb,
} from '@/api/dbs'
import { type ChatDocument, type MessageDocument } from '@hereconnect/types'
import { getBrowserUuid } from '@/utils/getBrowserUuid'
import { getUserUuid } from '@/utils/getUserUuid'
@@ -70,7 +75,8 @@ const { qr_code_uri, chat, userRole } = defineProps<{
const messages = ref<MessageDocument[]>([])
const newMessage = ref('')
let changesSubscription: PouchDB.Core.Changes<MessageDocument> | null = null
let syncHandler: PouchDB.Replication.Sync<MessageDocument> | null = null
let syncMessages: PouchDB.Replication.Sync<MessageDocument> | null = null
// let syncChats: PouchDB.Replication.Sync<ChatDocument> | null = null
// Селектор для фильтрации сообщений
const messageSelector = {
@@ -95,6 +101,7 @@ async function loadMessages() {
// Отправка нового сообщения
async function sendMessage() {
const created_at = new Date().toISOString()
const user_uuid = getUserUuid()
const message: MessageDocument = {
_id: `message:${qr_code_uri}:${chat}:${created_at}`,
type: 'message',
@@ -103,13 +110,22 @@ async function sendMessage() {
from: userRole,
body: newMessage.value.trim(),
browser_uuid: getBrowserUuid(),
user_uuid: getUserUuid(),
user_uuid,
created_at,
}
try {
await db.put(message)
newMessage.value = ''
// await chatsDbLocal.upsert(`chat:${user_uuid}:${userRole}:${qr_code_uri}:${chat}`, (chatDoc) => {
// if (chatDoc.last_message_at && chatDoc.last_message_at < created_at) {
// chatDoc.last_message_at = created_at
// return chatDoc
// } else {
// return false
// }
// })
} catch (error) {
console.error('Ошибка отправки сообщения:', error)
}
@@ -145,22 +161,35 @@ function watchChanges() {
// Настройка синхронизации
function setupSync() {
syncHandler = db.sync(remoteDb, {
syncMessages = db.sync(remoteDb, {
live: true,
retry: true,
selector: messageSelector,
})
syncHandler.on('error', (err) => {
syncMessages.on('error', (err) => {
console.error('Ошибка синхронизации:', err)
})
// syncChats = chatsDbLocal.sync(chatsDbRemote, {
// live: true,
// retry: true,
// selector: {
// type: 'chat',
// qr_code_uri,
// chat,
// },
// })
}
// Остановка синхронизации
function stopSync() {
if (syncHandler) {
syncHandler.cancel()
syncHandler = null
if (syncMessages) {
syncMessages.cancel()
syncMessages = null
}
// if (syncChats) {
// syncChats.cancel()
// syncChats = null
// }
}
// Отписка от изменений
@@ -80,9 +80,12 @@ async function sendMessage(content: string) {
type: 'chat',
qr_code_uri: doc.uri,
role: 'guest',
// unread_messages_count: 0,
chat,
created_at,
user_uuid,
to_user_uuid: doc.user_uuid,
created_at,
// last_message_at: created_at,
}
const chatOwnerDoc: ChatDocument = {
@@ -91,8 +94,11 @@ async function sendMessage(content: string) {
qr_code_uri: doc.uri,
role: 'owner',
chat,
created_at,
// unread_messages_count: 1,
user_uuid: doc.user_uuid,
to_user_uuid: user_uuid,
created_at,
// last_message_at: created_at,
}
const message: MessageDocument = {
@@ -109,6 +115,7 @@ async function sendMessage(content: string) {
await Promise.all([
chatsDbRemote.bulkDocs([chatGuestDoc, chatOwnerDoc]),
// Сохраняем сообщение в локальную базу данных
db.put(message),
])
@@ -12,11 +12,17 @@
<template #default="{ data }">
<div
v-if="data.rows.length > 0"
class="flex flex-col gap-5 my-4 grid grid-cols-1 sm:grid-cols-3 gap-4"
/>
class="justify-self-start align-baseline-start flex flex-col gap-4"
>
<ChatCard
v-for="{ doc: chatDoc } in data.rows.filter((row) => !!row.doc)"
:key="`${chatDoc!._id}`"
:chatDoc="chatDoc!"
/>
</div>
<div v-else class="place-self-center">
<h1 class="text-2xl font-bold mb-4 text-gray-500">Чаты в разработке</h1>
<h1 class="text-2xl font-bold mb-4 text-gray-500">У вас пока нет чатов</h1>
</div>
</template>
@@ -38,11 +44,19 @@
<script setup lang="ts">
import { useQuery } from '@tanstack/vue-query'
import { chatsDbRemote } from '@/api/dbs'
import { getUserUuid } from '@/utils/getUserUuid'
const query = useQuery({
queryKey: ['qrCodes'],
queryFn: async () => {
return { rows: [] } as const
queryFn: () => {
const user_uuid = getUserUuid()
return chatsDbRemote.allDocs({
startkey: `chat:${user_uuid}:`,
endkey: `chat:${user_uuid}:\uffff`,
limit: Number.MAX_SAFE_INTEGER,
include_docs: true,
})
},
})
</script>