This commit is contained in:
2026-03-15 20:55:00 +03:00
parent 43366a5089
commit b84a76ac08
16 changed files with 91 additions and 103 deletions

8
package-lock.json generated
View File

@@ -17,7 +17,7 @@
"tailwindcss": "^4.2.1",
"tailwindcss-primeui": "^0.6.1",
"vue": "^3.5.28",
"vuetify": "^4.0.0"
"vuetify": "^4.0.2"
},
"devDependencies": {
"@mdi/font": "^7.4.47",
@@ -5843,9 +5843,9 @@
}
},
"node_modules/vuetify": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/vuetify/-/vuetify-4.0.0.tgz",
"integrity": "sha512-TRyNWd2KlX1KXbKwuHYRfrX24yLHq85AdVKmokfy5llAgVx7MNW4oBPwFmYLeuuSrWvw5ITtDJ5VjdBIKD5WVw==",
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/vuetify/-/vuetify-4.0.2.tgz",
"integrity": "sha512-klgSGmfXoLajdTuuxreilzDQjp0ojzL2U5v6Z3ZbMYtpihPPXT9rkd/FxWL3dIGevnWdgaP2Kpwoz6aS/MISDA==",
"license": "MIT",
"funding": {
"type": "github",

View File

@@ -24,7 +24,7 @@
"tailwindcss": "^4.2.1",
"tailwindcss-primeui": "^0.6.1",
"vue": "^3.5.28",
"vuetify": "^4.0.0"
"vuetify": "^4.0.2"
},
"devDependencies": {
"@mdi/font": "^7.4.47",

View File

@@ -5,7 +5,12 @@ const menuStore = useMenuStore()
</script>
<template>
<VBtn icon="mdi-arrow-left" size="small" @click="menuStore.selected = 'chats'" />
<VBtn
icon="mdi-arrow-left"
color="default"
size="small"
@click="menuStore.selected = ['chats']"
/>
</template>
<style scoped></style>

View File

@@ -1,6 +1,5 @@
<script setup lang="ts">
import { type Chat } from '@/stores/chats.ts'
import { useAuthStore } from '@/stores/auth.ts'
import { type Chat, useChatsStore } from '@/stores/chats.ts'
import { computed } from 'vue'
interface Props {
@@ -8,18 +7,10 @@ interface Props {
}
const { chat } = defineProps<Props>()
const authStore = useAuthStore()
const chatsStore = useChatsStore()
const chatName = computed(() => {
switch (chat.typeId) {
case 1:
const otherUsers = chat.users.filter((user) => user.id !== authStore.me?.id)
return otherUsers[0]?.name ?? otherUsers[0]?.email ?? 'unknown'
case 2:
return chat.name
default:
return 'chat'
}
return chatsStore.getChatInfo(chat).name
})
const lastMessage = computed(() => {

View File

@@ -1,44 +1,34 @@
<script setup lang="ts">
import { useChatsStore } from '@/stores/chats.ts'
import { SocketDataReq, useSocketsStore } from '@/stores/sockets.ts'
import { onMounted, ref, watch, watchEffect } from 'vue'
import { type SelectedMenu, useMenuStore } from '@/stores/menu.ts'
import { watchEffect } from 'vue'
import { useMenuStore } from '@/stores/menu.ts'
import ChatListElement from '@/components/Chats/ChatListElement.vue'
const chatsStore = useChatsStore()
const socketsStore = useSocketsStore()
const menuStore = useMenuStore()
const selected = ref<string[]>()
const menu = ref<string[]>()
watchEffect(() => getMessages(chatsStore.selected))
watch(selected, (val) => {
if (val) chatsStore.selected = val[0]
})
watch(menu, (val) => {
if (val) menuStore.selected = val[0] as SelectedMenu
})
function getMessages(chatId?: string) {
if (!chatId) return
function getMessages([selected]: string[]) {
if (selected) {
socketsStore.send({
type: SocketDataReq.GET_MESSAGES,
data: { chatId: chatId },
data: { chatId: selected },
})
}
}
onMounted(() => console.log('CHAT LIST'))
</script>
<template>
<div class="flex flex-col h-full">
<VToolbar class="px-2">
<VToolbar theme="dark" class="px-2">
<VMenu transition="slide-y-transition">
<template v-slot:activator="{ props }">
<VBtn size="small" icon="mdi-menu" class="mr-2" v-bind="props" />
<VBtn size="small" icon="mdi-menu" class="mr-2" color="white" v-bind="props" />
</template>
<VList class="top-1" density="compact" slim v-model:selected="menu">
<VList class="top-1" density="compact" slim v-model:selected="menuStore.selected">
<VListItem value="users" title="Contacts" prepend-gap="8" prepend-icon="mdi-account" />
<VListItem value="settings" title="Settings" prepend-gap="8" prepend-icon="mdi-cog" />
<VDivider class="my-1" />
@@ -46,10 +36,10 @@ onMounted(() => console.log('CHAT LIST'))
</VList>
</VMenu>
<VTextField bg-color="white" prepend-inner-icon="mdi-magnify" placeholder="search chat" />
<VTextField bg-color="black" prepend-inner-icon="mdi-magnify" placeholder="search chat" />
</VToolbar>
<VList v-model:selected="selected" mandatory lines="one">
<ChatListElement v-for="chat in chatsStore.chats" :key="chat.id" v-bind="{ chat }" />
<VList theme="dark" v-model:selected="chatsStore.selected" mandatory lines="one">
<ChatListElement v-for="chat in chatsStore.chats" :key="chat.id" :chat />
</VList>
</div>
</template>

View File

@@ -8,7 +8,7 @@ import SettingsList from '@/components/Settings/SettingsList.vue'
const menuStore = useMenuStore()
const component = computed(() => {
switch (menuStore.selected) {
switch (menuStore.selected[0]) {
case 'chats':
return ChatsList
case 'users':

View File

@@ -1,13 +1,16 @@
<script setup lang="ts">
import type { User } from '@/stores/users.ts'
interface Props {
name: string
image?: string
}
const {user} = defineProps<{ user: User }>()
const { name, image } = defineProps<Props>()
</script>
<template>
<VToolbar class="px-2">
<VToolbar theme="dark" class="px-2">
<VAvatar text="A" color="primary" />
<VToolbarTitle :text="user.name" />
<VToolbarTitle :text="name" />
</VToolbar>
</template>

View File

@@ -2,33 +2,27 @@
import { computed, nextTick, ref, useTemplateRef, watch } from 'vue'
import { useScroll } from '@vueuse/core'
import type { User } from '@/stores/users.ts'
import { useChatsStore } from '@/stores/chats.ts'
const area = useTemplateRef('messageArea')
const chatsStore = useChatsStore()
// const area = useTemplateRef('messageArea')
// const { y, arrivedState } = useScroll(area)
// const messages = computed(() => {
// return [...messagesStore.messages]
// })
// async function scrollToBottom() {
// await nextTick()
// if (area.value) y.value = area.value?.scrollHeight
// }
const user = ref<User>({
id: 1,
name: 'test',
email: 'test@test.ru',
})
const messages = ref([])
</script>
<template>
<div class="flex h-full flex-col overflow-hidden">
<div class="grow-0">
<slot name="toolbar" :user="user" />
<div class="grow-0" v-if="chatsStore.selectedChat">
<slot name="toolbar" :toolBarData="chatsStore.getChatInfo(chatsStore.selectedChat)" />
</div>
<div class="px-8 gap-2 grow flex flex-col-reverse overflow-y-auto" ref="messageArea">
<slot :messages="messages" />

View File

@@ -7,29 +7,6 @@ const { messages } = defineProps<{ messages: Message[] }>()
<template>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData on-right-side>Hello world</MessageData>
<MessageData on-right-side>Hello world</MessageData>
<MessageData on-right-side>Hello world</MessageData>
<MessageData on-right-side>Hello world</MessageData>
<MessageData on-right-side>Hello world</MessageData>
<MessageData on-right-side>Hello world</MessageData>
<MessageData on-right-side>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
<MessageData>Hello world</MessageData>
</template>
<style scoped></style>

View File

@@ -1,19 +1,19 @@
<script setup lang="ts">
import { useAuthStore } from '@/stores/auth.ts'
import MessagesForm from '@/components/Messages/MessagesForm.vue'
import MessageToolbar from '@/components/Messages/MessageToolbar.vue'
import MessageInput from '@/components/Messages/MessageInput.vue'
import MessagesList from '@/components/Messages/MessagesList.vue'
import { useChatsStore } from '@/stores/chats.ts'
const authStore = useAuthStore()
const chatsStore = useChatsStore()
</script>
<template>
<div class="h-full bg-gray-100">
<div class="flex flex-col h-full">
<MessagesForm>
<template #toolbar="{ user }">
<MessageToolbar :user />
<MessagesForm v-if="chatsStore.selected.length">
<template #toolbar="{ toolBarData }">
<MessageToolbar :name="toolBarData.name" />
</template>
<template #default="{ messages }">
<MessagesList :messages />

View File

@@ -23,20 +23,17 @@ function onStartChat(userId: number) {
socketsStore.send({
type: SocketDataReq.CREATE_CHAT,
data: {
userId: userId,
},
data: { userId: userId },
})
}
</script>
<template>
<div class="flex flex-col h-full">
<VToolbar class="px-2">
<VToolbar theme="dark" class="px-2">
<BackToChats class="mr-2" />
<VSheet class="w-full">
<VTextField prepend-inner-icon="mdi-magnify" placeholder="search contacts" />
</VSheet>
<VTextField bg-color="black" prepend-inner-icon="mdi-magnify" placeholder="search contacts" />
</VToolbar>
<VList>

View File

@@ -33,7 +33,12 @@ const avatarText = computed(() => {
</template>
<template #append>
<VBtn icon="mdi-message" color="default" slim size="small" @click="emit('click', user.id)" />
<VBtn
icon="mdi-message-outline"
variant="plain"
size="small"
@click="emit('click', user.id)"
/>
</template>
</VListItem>
</template>

View File

@@ -1,7 +1,8 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { computed, ref } from 'vue'
import type { User } from '@/stores/users.ts'
import type { Message } from '@/stores/messages.ts'
import { useAuthStore } from '@/stores/auth.ts'
export interface Chat {
id: string
@@ -12,8 +13,31 @@ export interface Chat {
}
export const useChatsStore = defineStore('chats', () => {
const authStore = useAuthStore()
const chats = ref<Chat[]>([])
const selected = ref<string>()
const selected = ref<string[]>([])
return { chats, selected }
const selectedChat = computed(() => {
const chatId = selected.value[0]
return chats.value.find((chat: Chat) => {
return chat.id === chatId
})
})
function getChatInfo(chat: Chat) {
switch (chat.typeId) {
case 1:
const user = chat.users.find((user) => {
return user.id !== authStore.me?.id
})
return user ?? chat
case 2:
return chat
default:
return chat
}
}
return { chats, selected, selectedChat, getChatInfo }
})

View File

@@ -1,10 +1,10 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
export type SelectedMenu = 'chats' | 'users' | 'settings'
export type MenuItems = 'chats' | 'users' | 'settings'
export const useMenuStore = defineStore('menu', () => {
const selected = ref<SelectedMenu>('chats')
const selected = ref<MenuItems[]>(['chats'])
return { selected }
})

View File

@@ -76,8 +76,9 @@ export const useSocketsStore = defineStore('sockets', () => {
const idx = chatsStore.chats.findIndex((chat) => chat.id === data.id)
if (idx < 0) chatsStore.chats.push(data)
menuStore.selected = 'chats'
chatsStore.selected = data.id
console.log(data.id)
menuStore.selected = ['chats']
chatsStore.selected = [data.id]
}
break
@@ -114,6 +115,7 @@ export const useSocketsStore = defineStore('sockets', () => {
}
const send = (data: unknown) => {
console.log(COMMAND.SEND, data)
postMessage(COMMAND.SEND, data)
}

View File

@@ -21,7 +21,7 @@ onMounted(() => {
</LeftPane>
</div>
<div class="md:w-2/3 sm:w-1/2 w-1/2">
<RightPane></RightPane>
<RightPane />
</div>
</div>
</template>