next/pages/user/[id].vue

173 lines
5.7 KiB
Vue

<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>(`/user/${rtr.params.id}`);
if (userInfo === 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 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(uLastVisit, "MM/dd/yyyy @ hh:mm:ss a") }}
</span>
<span style="margin-left: 0.6em"> ({{ formatDistanceToNow(uLastVisit, { 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>