140 lines
3.3 KiB
Vue
140 lines
3.3 KiB
Vue
<template>
|
|
<v-container class="wrapper h-auto no-scrollbar">
|
|
<div class="timeline mt-[-16px]">
|
|
<post-list v-model:posts="posts" :loader="readMore" />
|
|
</div>
|
|
|
|
<div class="aside max-md:order-first">
|
|
<v-card :loading="loading">
|
|
<template #title>
|
|
<div class="flex justify-between">
|
|
<span>Realm Info</span>
|
|
|
|
<realm-action :item="metadata" />
|
|
</div>
|
|
</template>
|
|
<template #text>
|
|
<div>
|
|
<h2 class="font-medium">Name</h2>
|
|
<p>{{ metadata?.name }}</p>
|
|
|
|
<h2 class="font-medium mt-2">Description</h2>
|
|
<div v-html="parseContent(metadata?.description ?? '')"></div>
|
|
</div>
|
|
</template>
|
|
</v-card>
|
|
|
|
<v-card class="mt-3 pb-3" title="Realm Members">
|
|
<realm-members class="mt-[-8px]" :item="metadata" />
|
|
</v-card>
|
|
</div>
|
|
</v-container>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { reactive, ref, watch } from "vue"
|
|
import { request } from "@/scripts/request"
|
|
import { useRealms } from "@/stores/realms"
|
|
import { useRoute } from "vue-router"
|
|
import { parse } from "marked"
|
|
import dompurify from "dompurify"
|
|
import PostList from "@/components/posts/PostList.vue"
|
|
import RealmAction from "@/components/realms/RealmAction.vue"
|
|
import RealmMembers from "@/components/realms/RealmMembers.vue"
|
|
|
|
const route = useRoute()
|
|
const realms = useRealms()
|
|
|
|
const loading = ref(false)
|
|
const error = ref<string | null>(null)
|
|
const pagination = reactive({ page: 1, pageSize: 10, total: 0 })
|
|
|
|
const metadata = ref<any>(null)
|
|
const posts = ref<any[]>([])
|
|
|
|
async function readMetadata() {
|
|
loading.value = true
|
|
const res = await request("interactive", `/api/realms/${route.params.realmId}`)
|
|
if (res.status !== 200) {
|
|
error.value = await res.text()
|
|
} else {
|
|
error.value = null
|
|
metadata.value = await res.json()
|
|
}
|
|
loading.value = false
|
|
}
|
|
|
|
async function readPosts() {
|
|
const res = await request(
|
|
"interactive",
|
|
`/api/feed?` +
|
|
new URLSearchParams({
|
|
take: pagination.pageSize.toString(),
|
|
offset: ((pagination.page - 1) * pagination.pageSize).toString(),
|
|
realmId: route.params.realmId as string
|
|
})
|
|
)
|
|
if (res.status !== 200) {
|
|
error.value = await res.text()
|
|
} else {
|
|
error.value = null
|
|
const data = await res.json()
|
|
pagination.total = data["count"]
|
|
posts.value.push(...(data["data"] ?? []))
|
|
}
|
|
}
|
|
|
|
async function readMore({ done }: any) {
|
|
// Reach the end of data
|
|
if (pagination.total <= pagination.page * pagination.pageSize) {
|
|
done("empty")
|
|
return
|
|
}
|
|
|
|
pagination.page++
|
|
await readPosts()
|
|
|
|
if (error.value != null) done("error")
|
|
else {
|
|
if (pagination.total > 0) done("ok")
|
|
else done("empty")
|
|
}
|
|
}
|
|
|
|
watch(
|
|
() => route.params.realmId,
|
|
() => {
|
|
posts.value = []
|
|
pagination.page = 1
|
|
pagination.total = 0
|
|
readMetadata()
|
|
readPosts()
|
|
},
|
|
{ immediate: true }
|
|
)
|
|
|
|
watch(realms, (val) => {
|
|
if (val.done) {
|
|
readMetadata().then(() => (realms.done = false))
|
|
}
|
|
})
|
|
|
|
function parseContent(src: string): string {
|
|
return dompurify().sanitize(parse(src) as string)
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.wrapper {
|
|
display: grid;
|
|
grid-template-columns: 2fr 1fr;
|
|
|
|
gap: 0.75rem;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.wrapper {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
}
|
|
</style> |