diff --git a/package-lock.json b/package-lock.json index ada6fa9..edb80f2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,13 @@ "name": "chat-client", "version": "0.0.0", "dependencies": { + "@fontsource/roboto": "^5.2.9", "pinia": "^3.0.4", - "vue": "^3.5.28" + "vue": "^3.5.28", + "vuetify": "^3.11.8" }, "devDependencies": { + "@mdi/font": "^7.4.47", "@tsconfig/node24": "^24.0.4", "@types/node": "^24.10.13", "@vitejs/plugin-vue": "^6.0.4", @@ -1140,6 +1143,15 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@fontsource/roboto": { + "version": "5.2.9", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.9.tgz", + "integrity": "sha512-ZTkyHiPk74B/aj8BZWbsxD5Yu+Lq+nR64eV4wirlrac2qXR7jYk2h6JlLYuOuoruTkGQWNw2fMuKNavw7/rg0w==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -1241,6 +1253,13 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@mdi/font": { + "version": "7.4.47", + "resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz", + "integrity": "sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -5196,6 +5215,33 @@ "typescript": ">=5.0.0" } }, + "node_modules/vuetify": { + "version": "3.11.8", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.11.8.tgz", + "integrity": "sha512-4iKnntOnLFFklygZjzlVfcHrtLO8+iK4HOhiia6HP2U8v82x+ngaSCgm+epvPrGyCMfCpfuEttqD2qElrr1axw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/johnleider" + }, + "peerDependencies": { + "typescript": ">=4.7", + "vite-plugin-vuetify": ">=2.1.0", + "vue": "^3.5.0", + "webpack-plugin-vuetify": ">=3.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vite-plugin-vuetify": { + "optional": true + }, + "webpack-plugin-vuetify": { + "optional": true + } + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index a3d81d1..d3d2cd4 100644 --- a/package.json +++ b/package.json @@ -15,10 +15,13 @@ "format": "prettier --write --experimental-cli src/" }, "dependencies": { + "@fontsource/roboto": "^5.2.9", "pinia": "^3.0.4", - "vue": "^3.5.28" + "vue": "^3.5.28", + "vuetify": "^3.11.8" }, "devDependencies": { + "@mdi/font": "^7.4.47", "@tsconfig/node24": "^24.0.4", "@types/node": "^24.10.13", "@vitejs/plugin-vue": "^6.0.4", diff --git a/src/App.vue b/src/App.vue index e9cd6f7..51f6695 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,8 +1,11 @@ - + diff --git a/src/components/ChatMessage.vue b/src/components/ChatMessage.vue new file mode 100644 index 0000000..2677587 --- /dev/null +++ b/src/components/ChatMessage.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/src/components/ChatMessageText.vue b/src/components/ChatMessageText.vue new file mode 100644 index 0000000..5419ca7 --- /dev/null +++ b/src/components/ChatMessageText.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/src/components/WebSocketComponent.vue b/src/components/WebSocketComponent.vue index dd7c0ca..55f52bf 100644 --- a/src/components/WebSocketComponent.vue +++ b/src/components/WebSocketComponent.vue @@ -3,6 +3,7 @@ import { ref } from 'vue' import { useSharedWebSocket, WsDataType } from '../composables/useSharedWebSocket' const message = ref('') +const selectedChat = ref('') const { messages, chats, isConnected, error, send } = useSharedWebSocket({ // onMessage: (data) => { @@ -10,11 +11,21 @@ const { messages, chats, isConnected, error, send } = useSharedWebSocket({ // }, }) +const onChatClick = (id: string) => { + console.log(id) + selectedChat.value = id + send({ + type: WsDataType.GET_MESSAGES, + data: { chat_id: id }, + }) +} + const sendMessage = () => { if (message.value.trim()) { send({ - type: WsDataType.MESSAGE, + type: WsDataType.CREATE_MESSAGE, data: { + chat_id: selectedChat.value, text: message.value, }, }) @@ -24,37 +35,55 @@ const sendMessage = () => { diff --git a/src/composables/useSharedWebSocket.ts b/src/composables/useSharedWebSocket.ts index cb016e5..c66b8b2 100644 --- a/src/composables/useSharedWebSocket.ts +++ b/src/composables/useSharedWebSocket.ts @@ -21,13 +21,17 @@ export interface User { export interface WsData { type: WsDataType // data: Chat | Message | User | User[] | Message[] | Chat[] - data: {text: string} + data: unknown } export enum WsDataType { - CHAT = 'CHAT', + GET_CHATS = 'GET_CHATS', + GET_USERS = 'GET_USERS', + GET_MESSAGES = 'GET_MESSAGES', + CREATE_MESSAGE = 'CREATE_MESSAGE', + CHATS = 'CHATS', USER = 'USER', - MESSAGE = 'MESSAGE', + MESSAGES = 'MESSAGES', STATUS = 'STATUS', ERROR = 'ERROR', } @@ -69,16 +73,19 @@ export function useSharedWebSocket(options?: { url?: string; autoConnect?: true case WsDataType.USER: console.log('USER') break - case WsDataType.CHAT: + case WsDataType.CHATS: console.log('chat') chats.value = data break - case WsDataType.MESSAGE: - messages.value.push(data) + case WsDataType.MESSAGES: + messages.value = data // if (options.onMessage) { // options.onMessage(data) // } break + case WsDataType.CREATE_MESSAGE: + messages.value.push(data) + break case WsDataType.STATUS: isConnected.value = connected break diff --git a/src/main.ts b/src/main.ts index 5f77a89..a6d1513 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,9 +1,28 @@ +import '@fontsource/roboto/100.css' +import '@fontsource/roboto/300.css' +import '@fontsource/roboto/400.css' +import '@mdi/font/css/materialdesignicons.css' + import { createApp } from 'vue' import { createPinia } from 'pinia' import App from './App.vue' +import 'vuetify/styles' +import { createVuetify } from 'vuetify' +import * as components from 'vuetify/components' +import * as directives from 'vuetify/directives' + const app = createApp(App) app.use(createPinia()) +const vuetify = createVuetify({ + components, + directives, + icons: { + defaultSet: 'mdi', + }, +}) +app.use(vuetify) + app.mount('#app')