wip
This commit is contained in:
10
src/App.vue
10
src/App.vue
@@ -2,17 +2,15 @@
|
||||
import { useAuthStore } from '@/stores/auth.ts'
|
||||
import SignInView from '@/views/SignInView.vue'
|
||||
import MainView from '@/views/MainView.vue'
|
||||
import TestView from '@/views/TestView.vue'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-screen bg-gray-200">
|
||||
<div class="h-full m-auto p-4">
|
||||
<!-- <MainView v-if="authStore.isAuth" />-->
|
||||
<!-- <SignInView v-else />-->
|
||||
<TestView />
|
||||
<div class="h-screen bg-gray-500">
|
||||
<div class="h-full m-auto py-4 md:w-4/5 sm:w-full w-full">
|
||||
<MainView v-if="authStore.isAuth" />
|
||||
<SignInView v-else />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
@import "tailwindcss";
|
||||
@import "tailwindcss-primeui";
|
||||
@import "primeicons/primeicons.css";
|
||||
|
||||
html {
|
||||
font-size: 13px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
font-family: "Montserrat", sans-serif;
|
||||
font-optical-sizing: auto;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.p-component, .p-component * {
|
||||
}
|
||||
|
||||
13
src/assets/main_.css
Normal file
13
src/assets/main_.css
Normal file
@@ -0,0 +1,13 @@
|
||||
@import "tailwindcss";
|
||||
@import "tailwindcss-primeui";
|
||||
@import "primeicons/primeicons.css";
|
||||
|
||||
html {
|
||||
font-size: 13px;
|
||||
font-weight: 400;
|
||||
font-family: "Montserrat", sans-serif;
|
||||
font-optical-sizing: auto;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
.p-component, .p-component * {}
|
||||
@@ -9,32 +9,44 @@ interface Props {
|
||||
|
||||
const { chat } = defineProps<Props>()
|
||||
const authStore = useAuthStore()
|
||||
const chatsStore = useChatsStore()
|
||||
|
||||
const getChatName = computed(() => {
|
||||
if (chat.type_id === 2) {
|
||||
return chat.name
|
||||
} else if (chat.type_id === 1) {
|
||||
const otherUsers = chat.users.filter((user) => user.id !== authStore.me?.id)
|
||||
return otherUsers[0]?.name ?? otherUsers[0]?.email ?? 'unknown'
|
||||
const chatName = computed(() => {
|
||||
switch (chat.type_id) {
|
||||
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 'unknown ID'
|
||||
})
|
||||
|
||||
const isSelected = computed(() => {
|
||||
return chatsStore.selected === chat.id
|
||||
const avatarText = computed(() => {
|
||||
return chatName.value.slice(0, 1).toUpperCase()
|
||||
})
|
||||
|
||||
const lastMessageCreatedAt = computed(() => {
|
||||
return new Date().toLocaleTimeString('ru-RU', { timeStyle: 'short' })
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="border p-2" :class="{ 'bg-gray-400': isSelected }">
|
||||
<!-- {{ chat }}-->
|
||||
<div>id:{{ chat.id }}</div>
|
||||
<div>name:{{ chat.name }}</div>
|
||||
<div>type:{{ chat.type_id }}</div>
|
||||
<div>chatName:{{ getChatName }}</div>
|
||||
</div>
|
||||
<VListItem :value="chat.id">
|
||||
<template v-slot:prepend>
|
||||
<VAvatar color="primary" :text="avatarText" />
|
||||
</template>
|
||||
|
||||
<template v-slot:append>
|
||||
<div class="flex flex-col justify-end">
|
||||
<div class="text-xs">{{ lastMessageCreatedAt }}</div>
|
||||
<VChip size="small">12</VChip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<v-list-item-title>{{ chatName }}</v-list-item-title>
|
||||
<v-list-item-subtitle>subtitle</v-list-item-subtitle>
|
||||
</VListItem>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -2,12 +2,24 @@
|
||||
import { useChatsStore } from '@/stores/chats.ts'
|
||||
import { SocketDataReq, useSocketsStore } from '@/stores/sockets.ts'
|
||||
import ChatListElement from '@/components/ChatListElement.vue'
|
||||
import { onMounted, watchEffect } from 'vue'
|
||||
import { onMounted, ref, watch, watchEffect } from 'vue'
|
||||
import { type SelectedMenu, useMenuStore } from '@/stores/menu.ts'
|
||||
|
||||
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) => {
|
||||
console.log(val)
|
||||
if (val) menuStore.selected = val[0] as SelectedMenu
|
||||
})
|
||||
|
||||
function getMessages(chatId?: string) {
|
||||
if (!chatId) return
|
||||
@@ -17,28 +29,36 @@ function getMessages(chatId?: string) {
|
||||
})
|
||||
}
|
||||
|
||||
function onSelect(id: string) {
|
||||
chatsStore.selected = id
|
||||
}
|
||||
|
||||
onMounted(() => console.log('CHAT LIST'))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-2 h-full overflow-hidden px-2">
|
||||
<div>chats</div>
|
||||
|
||||
<!-- <div class="overflow-y-auto">-->
|
||||
<!-- <div v-for="i in 30" :key="i" class="pa-4 border">bla</div>-->
|
||||
<!-- </div>-->
|
||||
<div class="flex flex-col gap-2 h-full overflow-y-auto">
|
||||
<chat-list-element
|
||||
v-for="chat in chatsStore.chats"
|
||||
:key="chat.id"
|
||||
v-bind="{ chat }"
|
||||
@click="onSelect(chat.id)"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col h-full">
|
||||
<VToolbar>
|
||||
<VMenu transition="slide-y-transition">
|
||||
<template v-slot:activator="{ props }">
|
||||
<VBtn icon="mdi-menu" v-bind="props" />
|
||||
</template>
|
||||
<VList class="top-1" density="compact" slim v-model:selected="menu">
|
||||
<VListItem density="compact" value="profile" prepend-gap="8" title="Profile">
|
||||
<template #prepend>
|
||||
<VAvatar color="primary" text="A" />
|
||||
</template>
|
||||
</VListItem>
|
||||
<VDivider class="my-1" />
|
||||
<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" />
|
||||
<VListItem value="logout" title="Log Out" />
|
||||
</VList>
|
||||
</VMenu>
|
||||
<VSheet class="w-full mx-2">
|
||||
<VTextField prepend-inner-icon="mdi-magnify" label="search chat"></VTextField>
|
||||
</VSheet>
|
||||
</VToolbar>
|
||||
<VList v-model:selected="selected" mandatory>
|
||||
<ChatListElement v-for="chat in chatsStore.chats" :key="chat.id" v-bind="{ chat }" />
|
||||
</VList>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ function getChatName(chat: Chat) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full flex flex-col h-full gap-2">
|
||||
<div class="flex flex-col h-full gap-2">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -30,7 +30,7 @@ watch(messages, async () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full h-full bg-blue-200 border">
|
||||
<div class="h-full">
|
||||
<!-- <button class="position-absolute scroll-down" @click="scrollToBottom">UP</button>-->
|
||||
<div class="flex flex-col h-full">
|
||||
<div class="flex h-full flex-col overflow-hidden">
|
||||
|
||||
@@ -30,8 +30,13 @@ function onStartChat(userId: number) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex flex-col gap-2 h-full overflow-hidden px-2">
|
||||
<div>contacts</div>
|
||||
<div class="flex flex-col h-full">
|
||||
<VToolbar>
|
||||
<VBtn icon="mdi-arrow-left"></VBtn>
|
||||
<VSheet class="w-full mx-2">
|
||||
<VTextField prepend-inner-icon="mdi-magnify" label="search contacts"></VTextField>
|
||||
</VSheet>
|
||||
</VToolbar>
|
||||
|
||||
<div class="flex flex-col gap-2 h-full overflow-y-auto">
|
||||
<UsersListElement
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<div class="w-16 flex flex-col gap-2 items-stretch p-1 border">
|
||||
<div class="flex flex-col gap-2 items-stretch p-1 border">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
30
src/main.ts
30
src/main.ts
@@ -3,17 +3,39 @@ import './assets/main.css'
|
||||
|
||||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import PrimeVue from 'primevue/config'
|
||||
// import PrimeVue from 'primevue/config'
|
||||
|
||||
import 'vuetify/styles'
|
||||
import { createVuetify } from 'vuetify'
|
||||
import * as components from 'vuetify/components'
|
||||
import * as directives from 'vuetify/directives'
|
||||
|
||||
import App from './App.vue'
|
||||
import { version } from 'vue'
|
||||
import theme from '@/themes/noir.ts'
|
||||
|
||||
const app = createApp(App)
|
||||
|
||||
console.log('version', version)
|
||||
|
||||
app.use(PrimeVue, { theme: theme })
|
||||
app.use(createPinia())
|
||||
// app.use(PrimeVue, { theme: theme })
|
||||
|
||||
const vuetify = createVuetify({
|
||||
components,
|
||||
directives,
|
||||
theme: { defaultTheme: 'light' },
|
||||
icons: {
|
||||
defaultSet: 'mdi',
|
||||
},
|
||||
defaults: {
|
||||
VAvatar: { density: 'compact' },
|
||||
VChip: { density: 'compact' },
|
||||
VBtn: { color: 'black', variant: 'flat' },
|
||||
VSwitch: { color: 'black', hideDetails: true },
|
||||
VOtpInput: { density: 'compact' },
|
||||
VTextField: { color: 'black', density: 'compact', variant: 'outlined', hideDetails: true },
|
||||
},
|
||||
})
|
||||
app.use(vuetify)
|
||||
|
||||
app.use(createPinia())
|
||||
app.mount('#app')
|
||||
|
||||
@@ -58,6 +58,7 @@ export const useSocketsStore = defineStore('sockets', () => {
|
||||
|
||||
worker.value.port.onmessage = (event) => {
|
||||
const { type, data, connected, message } = event.data
|
||||
console.log('Received message', data)
|
||||
|
||||
switch (type) {
|
||||
case SocketDataRes.USERS:
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { useSocketsStore } from '@/stores/sockets.ts'
|
||||
import AppMenu from '@/components/AppMenu.vue'
|
||||
import LeftPane from '@/components/LeftPane.vue'
|
||||
import RightPane from '@/components/RightPane.vue'
|
||||
import UsersList from '@/components/Users/UsersList.vue'
|
||||
@@ -13,6 +12,7 @@ const socketsStore = useSocketsStore()
|
||||
const menuStore = useMenuStore()
|
||||
|
||||
const component = computed(() => {
|
||||
console.log(menuStore.selected)
|
||||
switch (menuStore.selected) {
|
||||
case 'chats':
|
||||
return ChatsList
|
||||
@@ -32,13 +32,14 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div class="flex h-full">
|
||||
<div class="flex w-full">
|
||||
<AppMenu />
|
||||
<div class="md:w-1/3 sm:w-1/2 w-1/2 bg-white">
|
||||
<LeftPane>
|
||||
<component :is="component" />
|
||||
</LeftPane>
|
||||
</div>
|
||||
<RightPane />
|
||||
<div class="md:w-2/3 sm:w-1/2 w-1/2">
|
||||
<RightPane></RightPane>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,32 +1,48 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { useAuthStore } from '@/stores/auth.ts'
|
||||
import { JustButton, JustInput } from '@/components/simple'
|
||||
// import {
|
||||
// Button,
|
||||
// InputText,
|
||||
// Card,
|
||||
// InputOtp,
|
||||
// ToggleSwitch,
|
||||
// Divider,
|
||||
// IconField,
|
||||
// InputIcon,
|
||||
// } from 'primevue'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const email = ref('vadim.olonin@gmail.com')
|
||||
const name = ref('')
|
||||
const name = ref('Vadim')
|
||||
const otp = ref('123456')
|
||||
|
||||
async function onSubmit() {
|
||||
await authStore.login(email.value)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-full flex flex-col justify-center items-center">
|
||||
<div class="bg-white border border-gray-500 p-4 rounded-md w-64">
|
||||
<form @submit.prevent="onSubmit">
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="">Sign in</div>
|
||||
<JustInput v-model="email" placeholder="email" type="email" class="" />
|
||||
<input v-if="false" v-model="name" placeholder="name" />
|
||||
<div class="flex justify-end">
|
||||
<input type="checkbox" v-if="false" />
|
||||
<JustButton type="submit">sign in</JustButton>
|
||||
<div class="h-full flex flex-col justify-center items-center px-4">
|
||||
<VCard class="w-full md:w-1/2">
|
||||
<template #title>
|
||||
<div class="text-2xl">Sign in</div>
|
||||
</template>
|
||||
<template #text>
|
||||
<form @submit.prevent="onSubmit" class="flex flex-col gap-4">
|
||||
<VTextField v-model="email" placeholder="email" />
|
||||
<VTextField v-model="name" placeholder="name" />
|
||||
<div class="flex justify-center">
|
||||
<VOtpInput v-model="otp" />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<VSwitch hide-details label="Keep me signed in" />
|
||||
<VBtn type="submit">Sign In</VBtn>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
</VCard>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user