stream day 3
This commit is contained in:
18
App.vue
18
App.vue
@@ -2,9 +2,12 @@
|
||||
<div>
|
||||
<NuxtLayout>
|
||||
<div class="flex h-screen max-h-screen">
|
||||
<Nav />
|
||||
<Sidebar />
|
||||
<NuxtPage />
|
||||
<Nav :servers="servers" />
|
||||
<Sidebar :server="activeServer"
|
||||
:user="user" />
|
||||
<div class="w-full h-full">
|
||||
<NuxtPage :user="user" />
|
||||
</div>
|
||||
</div>
|
||||
</NuxtLayout>
|
||||
</div>
|
||||
@@ -12,12 +15,19 @@
|
||||
|
||||
<script lang="ts">
|
||||
import { useUserStore } from '~/stores/user'
|
||||
import { useServerStore } from './stores/servers'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
servers: useServerStore().servers,
|
||||
activeServer: storeToRefs(useServerStore()).activeServer,
|
||||
user: useUserStore().user
|
||||
}
|
||||
},
|
||||
async setup() {
|
||||
const userStore = useUserStore()
|
||||
const sessionToken = useCookie('sessionToken')
|
||||
console.log(sessionToken.value)
|
||||
if (userStore.user.id === undefined && sessionToken.value) {
|
||||
const user = await $fetch('/api/getCurrentUser')
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<nav class="p-4 bg-zinc-800 grid grid-cols-1 grid-rows-[56px_1fr_56px] h-screen text-white relative">
|
||||
<nav class="p-4 bg-[hsl(216,calc(1*7.2%),13.5%)] grid grid-cols-1 grid-rows-[56px_1fr_56px] h-screen min-w-[88px] text-white relative">
|
||||
<div>
|
||||
<div
|
||||
@click="openServer('@me')"
|
||||
@click="openServer('@me', 'dms')"
|
||||
class="bg-zinc-600/80 p-3 rounded-full transition-all hover:rounded-2xl ease-in-out hover:bg-zinc-500/60 duration-300">
|
||||
<svg width="32"
|
||||
height="32"
|
||||
@@ -16,10 +16,10 @@
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-y-scroll my-2 flex gap-2">
|
||||
<div class="overflow-y-scroll my-2 flex gap-y-2 flex-col">
|
||||
<div v-for="server in servers"
|
||||
:key="server.id"
|
||||
@click="openServer(server.id)"
|
||||
@click="openServer(server.id, 'servers')"
|
||||
class="bg-zinc-600/80 p-3 rounded-full transition-all hover:rounded-2xl ease-in-out hover:bg-zinc-500/60 duration-300 h-[56px] w-[56px]">
|
||||
<svg width="32"
|
||||
height="32"
|
||||
@@ -89,7 +89,6 @@ import { useServerStore } from '~/stores/servers'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
servers: useServerStore().servers,
|
||||
createServerModelOpen: false,
|
||||
serverName: ''
|
||||
}
|
||||
@@ -102,15 +101,12 @@ export default {
|
||||
this.serverName = '';
|
||||
serverStore.addServer(server)
|
||||
},
|
||||
openServer(id: string): void {
|
||||
openServer(id: string, type: string): void {
|
||||
const router = useRouter();
|
||||
useServerStore().servers.find((e: unknown, i: number) => {
|
||||
if (e.id === id) {
|
||||
useServerStore().activeServer = i
|
||||
}
|
||||
})
|
||||
useServerStore().setActive(type, id)
|
||||
router.push({ path: `/channel/${id}` });
|
||||
}
|
||||
}
|
||||
},
|
||||
props: ['servers']
|
||||
}
|
||||
</script>
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div class="flex bg-zinc-700 w-60 h-screen shadow-sm text-white select-none">
|
||||
<div class="flex bg-[hsl(223,calc(1*6.9%),19.8%)] min-w-60 w-60 h-screen shadow-sm text-white select-none">
|
||||
<div class="w-full"
|
||||
v-if="server">
|
||||
<div class="flex p-4 border-b border-zinc-600/80">
|
||||
@@ -22,20 +22,6 @@
|
||||
d="M5 9h14M5 15h14M11 4L7 20M17 4l-4 16" />
|
||||
</svg> {{ channel.name }}
|
||||
</div>
|
||||
<div class="flex text-center hover:bg-zinc-600/70 px-2 py-1.5 w-full transition-colors rounded drop-shadow-sm"
|
||||
v-for="channel in server.channels"
|
||||
:key="channel.id">
|
||||
<svg width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24">
|
||||
<path fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="M5 9h14M5 15h14M11 4L7 20M17 4l-4 16" />
|
||||
</svg> {{ channel.name }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -43,22 +29,12 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { useUserStore } from '~/stores/user'
|
||||
import { useServerStore } from '~/stores/servers'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
user: useUserStore().user,
|
||||
server: useServerStore().servers[useServerStore().activeServer]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const route = useRoute()
|
||||
|
||||
if (route.path.includes('@me')) {
|
||||
this.server = useServerStore().dms[useServerStore().activeServer]
|
||||
}
|
||||
}
|
||||
console.log(useServerStore().currentServer, useServerStore().servers)
|
||||
},
|
||||
props: ['server', 'user']
|
||||
}
|
||||
</script>
|
||||
@@ -28,6 +28,7 @@ export default {
|
||||
autoImports: [
|
||||
// automatically imports `defineStore`
|
||||
'defineStore', // import { defineStore } from 'pinia'
|
||||
'storeToRefs',
|
||||
// automatically imports `defineStore` as `definePiniaStore`
|
||||
['defineStore', 'definePiniaStore'], // import { defineStore as definePiniaStore } from 'pinia'
|
||||
],
|
||||
|
||||
@@ -1,16 +1,105 @@
|
||||
<template>
|
||||
hello world
|
||||
<div class="w-full h-full bg-[hsl(220,calc(1*7.7%),22.9%)] relative text-white">
|
||||
<div class="w-full h-[calc(100%-60px)] overflow-y-scroll pb-1"
|
||||
id="conversation-pane">
|
||||
<div>
|
||||
<div v-if="conversation.length === 0">
|
||||
<p>No messages yet</p>
|
||||
</div>
|
||||
<div v-else
|
||||
v-for="conversations in conversation">
|
||||
<div v-if="conversations.userId == user.id"
|
||||
class="message-container"
|
||||
id="messages-container">
|
||||
<div class="message-sender">
|
||||
<div class="message-sender-text">
|
||||
<p class="message-sender-you">You</p>
|
||||
<p>{{ conversations.body }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else
|
||||
class="message-container">
|
||||
<div class="message-sender">
|
||||
<div class="message-sender-text">
|
||||
<p class="message-sender-you">{{ conversations.userId }}</p>
|
||||
<p>{{ conversations.body }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="conversation-input w-full">
|
||||
<form @submit.prevent="sendMessage"
|
||||
class="relative px-4 w-[calc(100%-12rem)]">
|
||||
<input type="text"
|
||||
class="py-2 px-4 rounded-md bg-[hsl(218,calc(1*7.9%),27.3%)]"
|
||||
id="message"
|
||||
v-model="messageContent"
|
||||
placeholder="Send a Message..." />
|
||||
<input type="submit"
|
||||
class=""
|
||||
value="Send" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { useServerStore } from '~/stores/servers'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
conversation: [],
|
||||
messageContent: ''
|
||||
}
|
||||
},
|
||||
async setup() {
|
||||
const route = useRoute()
|
||||
|
||||
const { server } = await $fetch(`/api/channel/${route.params.dmId}`)
|
||||
if (!useServerStore().dms.includes(server)) useServerStore().addDM(server);
|
||||
if (!server) return;
|
||||
useServerStore().addDM(server);
|
||||
const channelId = server.channels[0].id
|
||||
await useServerStore().setActive('dms', server.id);
|
||||
return {
|
||||
server,
|
||||
channelId
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
const { channel } = await $fetch(`/api/channel/messages/${this.channelId}`)
|
||||
this.conversation = channel.messages
|
||||
},
|
||||
async updated() {
|
||||
if (!useServerStore().activeServer == this.server) await useServerStore().setActive('dms', this.server.id)
|
||||
},
|
||||
methods: {
|
||||
async sendMessage() {
|
||||
const route = useRoute()
|
||||
if (!this.messageContent) return;
|
||||
|
||||
const { message } = await $fetch(`/api/channel/sendMessage`, { method: 'post', body: { body: this.messageContent, channelId: this.channelId } })
|
||||
|
||||
this.conversation.push(message)
|
||||
}
|
||||
},
|
||||
props: ['user']
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.conversation-input {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
flex-direction: row;
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
height: 60px;
|
||||
border-top: #ffffff 1px solid;
|
||||
background-color: #3C3C3C;
|
||||
bottom: calc(0px - 0.5rem);
|
||||
}
|
||||
</style>
|
||||
@@ -1,12 +1,25 @@
|
||||
<template>
|
||||
hello world
|
||||
{{ $route.params.id }}
|
||||
</template>
|
||||
|
||||
<script setup async>
|
||||
<script lang="ts">
|
||||
import { useServerStore } from '~/stores/servers'
|
||||
|
||||
export default {
|
||||
async setup() {
|
||||
const route = useRoute()
|
||||
|
||||
const { server } = await $fetch(`/api/channel/${route.params.id}`)
|
||||
if (!useServerStore().servers.includes(server)) useServerStore().addServer(server);
|
||||
if (!server) return;
|
||||
useServerStore().addServer(server);
|
||||
await useServerStore().setActive('servers', server.id)
|
||||
return {
|
||||
server
|
||||
}
|
||||
},
|
||||
async updated() {
|
||||
if (!this.server) return;
|
||||
if (!await useServerStore().activeServer == this.server.id) await useServerStore().setActive('servers', this.server.id)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -12,10 +12,10 @@ model User {
|
||||
email String @unique
|
||||
username String @unique
|
||||
passwordhash String
|
||||
Server Server[]
|
||||
server Server[]
|
||||
serverId String?
|
||||
Messages Message[]
|
||||
Session Session[]
|
||||
messages Message[]
|
||||
session Session[]
|
||||
}
|
||||
|
||||
model Server {
|
||||
@@ -28,9 +28,9 @@ model Server {
|
||||
model Channel {
|
||||
id String @id @default(cuid())
|
||||
name String
|
||||
Server Server? @relation(fields: [serverId], references: [id])
|
||||
server Server? @relation(fields: [serverId], references: [id])
|
||||
serverId String?
|
||||
Message Message[]
|
||||
messages Message[]
|
||||
}
|
||||
|
||||
model Message {
|
||||
|
||||
35
server/api/channel/messages/[id].get.ts
Normal file
35
server/api/channel/messages/[id].get.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
if (!event.context.user.authenticated) return {
|
||||
message: 'You must be logged in to view a channel.'
|
||||
}
|
||||
|
||||
if (!event.context.params.id) {
|
||||
event.node.res.statusCode = 400;
|
||||
return {
|
||||
message: 'A channelId is required'
|
||||
}
|
||||
}
|
||||
|
||||
const channel = await prisma.channel.findFirst({
|
||||
where: {
|
||||
id: event.context.params.id
|
||||
},
|
||||
include: {
|
||||
messages: true,
|
||||
}
|
||||
})
|
||||
|
||||
if (!channel) {
|
||||
event.node.res.statusCode = 404;
|
||||
return {
|
||||
message: `Channel with id "${event.context.params.id}" not found`
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
channel
|
||||
}
|
||||
})
|
||||
71
server/api/channel/sendMessage.post.ts
Normal file
71
server/api/channel/sendMessage.post.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
const prisma = new PrismaClient()
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
if (!event.context.user.authenticated) {
|
||||
event.node.res.statusCode = 401;
|
||||
return {
|
||||
message: 'You must be logged in to send a message.'
|
||||
}
|
||||
}
|
||||
|
||||
const { body, channelId } = await readBody(event)
|
||||
|
||||
if (!body || !channelId) {
|
||||
event.node.res.statusCode = 400;
|
||||
return {
|
||||
message: 'A body or channelId is required to send a message.'
|
||||
}
|
||||
}
|
||||
|
||||
const channel = await prisma.channel.findFirst({
|
||||
where: {
|
||||
id: channelId
|
||||
}
|
||||
})
|
||||
|
||||
const server = await prisma.server.findFirst({
|
||||
where: {
|
||||
id: channel.serverId
|
||||
},
|
||||
include: {
|
||||
participants: true
|
||||
}
|
||||
})
|
||||
|
||||
const userInServer = server.participants.filter((e) => e.id === event.context.user.id)
|
||||
|
||||
if (!userInServer.length > 0) {
|
||||
event.node.res.statusCode = 401;
|
||||
return {
|
||||
message: 'You must be in the server to send a message.'
|
||||
}
|
||||
}
|
||||
|
||||
if (!server) {
|
||||
event.node.res.statusCode = 404;
|
||||
return {
|
||||
message: 'Server not found'
|
||||
}
|
||||
}
|
||||
|
||||
const message = await prisma.message.create({
|
||||
data: {
|
||||
body,
|
||||
creator: {
|
||||
connect: {
|
||||
id: event.context.user.id
|
||||
}
|
||||
},
|
||||
channel: {
|
||||
connect: {
|
||||
id: channelId
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
message
|
||||
}
|
||||
})
|
||||
@@ -4,8 +4,6 @@ const prisma = new PrismaClient()
|
||||
export default defineEventHandler(async (event) => {
|
||||
const cookies = parseCookies(event)
|
||||
|
||||
console.log(cookies.sessionToken)
|
||||
|
||||
if (!cookies.sessionToken) {
|
||||
event.context.user = { authenticated: false }
|
||||
return;
|
||||
|
||||
@@ -2,14 +2,19 @@ export const useServerStore = defineStore('server', {
|
||||
state: () => ({
|
||||
servers: [],
|
||||
dms: [],
|
||||
activeServer: undefined
|
||||
activeServer: {}
|
||||
}),
|
||||
actions: {
|
||||
addServer(server) {
|
||||
if (this.servers.includes(server)) return;
|
||||
this.servers.push(server)
|
||||
},
|
||||
addDM(server) {
|
||||
if (this.dms.includes(server)) return;
|
||||
this.dms.push(server)
|
||||
}
|
||||
},
|
||||
setActive(type, serverId) {
|
||||
this.activeServer = this[type].find((e) => e.id === serverId)
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user