<script lang="ts" setup> import { format, formatDistanceToNow } from "date-fns"; import { IUser } from "@models/user"; import { favourites } from "@client/listActions"; import singleStory from "~/components/listings/singleStory.vue"; import icon from "~/components/icon.vue"; import adminPanel from "~/components/profile/adminPanel.vue"; const rtr = useRoute(); const { data: ses } = useAuth(); const { data: userInfo } = await useApiFetch<IUser | null>(`/user/${rtr.params.id}`); if (userInfo.value === null) { navigateTo("/"); } const activeKey = ref("main"); const activeFavKey = ref("favs/stories"); const uLastVisit = Date.parse((userInfo.value?.lastVisit || userInfo.value?.lastLogin) as unknown as string); const isSelf = userInfo.value?._id === parseInt(rtr.params.id as string); useHead({ title: `Viewing profile for ${userInfo.value.username}`, }); </script> <template> <a-card style="width: 100%"> <template #title> <div style="height: fit-content"> <a-card-meta style="align-items: center; margin: 0.5em"> <template #avatar> <a-avatar :size="75" :src="`/avatars/${userInfo?.profile.avatar}.png`" /> </template> <template #title> <a-typography-title :level="1" style="margin-top: 0.5em"> {{ userInfo!.username }} </a-typography-title> </template> </a-card-meta> </div> <a-badge-ribbon style="z-index: 20" color="#f14668" v-if="userInfo?.profile.isAdmin"> <template #text> Administrator </template> </a-badge-ribbon> </template> <a-descriptions :column="2" :labelStyle="{ fontWeight: 'bold' }" :colon="false"> <a-descriptions-item label="Last visit"> <div v-if="userInfo?.banned" style="color: red; font-weight: bold">BANNED</div> <div v-else-if="userInfo?.profile.hidden"> <i>Unknown</i> </div> <div v-else> <span> {{ format(userInfo.lastVisit, "MM/dd/yyyy @ hh:mm:ss a") }} </span> <span style="margin-left: 0.6em"> ({{ formatDistanceToNow(userInfo.lastVisit, { addSuffix: true }) }}) </span> </div> </a-descriptions-item> <a-descriptions-item label="Website"> <a target="_blank" :href="`${userInfo?.profile.website.startsWith('http') ? '' : 'http://'}${userInfo?.profile.website}`"> {{ userInfo?.profile.website }} </a> </a-descriptions-item> <a-descriptions-item label="Blog/Journal"> <a target="_blank" :href="`${userInfo?.profile.blog.startsWith('http') ? '' : 'http://'}${userInfo?.profile.blog}`"> {{ userInfo?.profile.blog }} </a> </a-descriptions-item> <a-descriptions-item label="Occupation"> {{ userInfo?.profile.occupation }} </a-descriptions-item> <a-descriptions-item label="Email" v-if="userInfo?.profile.showEmail || ses?.user?.profile.isAdmin"> {{ userInfo?.email }} </a-descriptions-item> </a-descriptions> <a-divider style="border: 1px solid #3e1560" /> <a-tabs centered v-model:active-key="activeKey"> <a-tab-pane key="main" tab="Profile"> <div v-html="userInfo?.profile.bio"></div> </a-tab-pane> <a-tab-pane key="stories" tab="Stories"> <listings-stories :prefix="`/user/${rtr.params.id}/stories`" /> </a-tab-pane> <a-tab-pane key="favs" tab="Favourites"> <a-tabs centered v-model:active-key="activeFavKey"> <a-tab-pane key="favs/stories" tab="Stories"> <a-list :pagination="{ defaultPageSize: 20, total: userInfo?.favs.stories.length, defaultCurrent: 1, // onChange: pagiChange, hideOnSinglePage: true, showSizeChanger: false, }" :data-source="userInfo?.favs.stories" item-layout="vertical" > <template #renderItem="{ item }"> <!-- {{ item.title }} --> <a-row :gutter="[25, 0]" :align="'middle'"> <a-col :span="23"> <single-story :last="true" :story="item" /> </a-col> <a-col :span="1" v-if="isSelf"> <a style="color: red" @click="() => favourites(userInfo?.favs.stories || [], item._id, true, 'story')"> <icon istyle="regular" name="trash" color="#f00" /> </a> </a-col> </a-row> </template> </a-list> </a-tab-pane> <a-tab-pane key="favs/authors" tab="Authors"> <a-list item-layout="horizontal" :data-source="userInfo?.favs.authors" :grid="{ gutter: 16, column: 3 }"> <template #renderItem="{ item }"> <a-list-item style="display: flex; align-items: center"> <a-list-item-meta style="align-items: center; width: min-content"> <template #avatar> <a-avatar :src="`/avatars/${item.profile.avatar}.png`" /> </template> <template #title :style="{ background: 'pink' }"> <nuxt-link :to="`/user/${item._id}`"> {{ item.username }} </nuxt-link> </template> </a-list-item-meta> <template #actions v-if="isSelf"> <span> <a style="color: red" @click="() => favourites(userInfo?.favs.authors || [], item._id, true, 'author')"> <icon istyle="regular" name="trash" color="#f00" /> </a> </span> </template> </a-list-item> </template> </a-list> </a-tab-pane> </a-tabs> </a-tab-pane> <a-tab-pane key="admin" tab="Admin" v-if="ses?.user?.profile.isAdmin"> <admin-panel :user="userInfo" /> </a-tab-pane> </a-tabs> </a-card> </template> <style> .ant-list-item-action { width: min-content; } .ant-ribbon-wrapper { position: unset !important; zoom: 200%; } .ant-list-item-meta-title { margin-top: 0.1em; } .ant-card-head-title, .ant-card-head { height: 110% !important; } .ant-list-item-meta-content { align-self: center !important; } </style> <style scoped> .ant-list-items > * + * { margin-top: 1.2em; } </style>