2023-10-10 22:44:04 -04:00
|
|
|
<script lang="ts" setup>
|
2023-12-29 20:11:07 -05:00
|
|
|
import { format, formatDistanceToNow } from "date-fns";
|
2023-12-20 17:23:31 -05:00
|
|
|
import { IUser } from "@models/user";
|
|
|
|
import { favourites } from "@client/listActions";
|
2023-10-10 22:44:04 -04:00
|
|
|
import singleStory from "~/components/listings/singleStory.vue";
|
|
|
|
import icon from "~/components/icon.vue";
|
|
|
|
import adminPanel from "~/components/profile/adminPanel.vue";
|
|
|
|
|
|
|
|
const rtr = useRoute();
|
2023-12-06 21:57:33 -05:00
|
|
|
const { data: ses } = useAuth();
|
2023-10-10 22:44:04 -04:00
|
|
|
|
|
|
|
const { data: userInfo } = await useApiFetch<IUser>(`/user/${rtr.params.id}`);
|
|
|
|
if (userInfo === null) {
|
|
|
|
navigateTo("/");
|
|
|
|
}
|
|
|
|
const activeKey = ref("main");
|
|
|
|
const activeFavKey = ref("favs/stories");
|
2023-12-29 20:11:07 -05:00
|
|
|
const uLastVisit = Date.parse((userInfo.value?.lastVisit || userInfo.value?.lastLogin) as unknown as string);
|
2023-10-10 22:44:04 -04:00
|
|
|
|
|
|
|
const isSelf = userInfo.value?._id === parseInt(rtr.params.id as string);
|
2023-12-06 21:57:33 -05:00
|
|
|
useHead({
|
|
|
|
title: `Viewing profile for ${userInfo.value.username}`,
|
|
|
|
});
|
2023-10-10 22:44:04 -04:00
|
|
|
</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>
|
2023-12-29 20:11:07 -05:00
|
|
|
<a-avatar :size="75" :src="`/avatars/${userInfo?.profile.avatar}.png`" />
|
2023-10-10 22:44:04 -04:00
|
|
|
</template>
|
|
|
|
<template #title>
|
|
|
|
<a-typography-title :level="1" style="margin-top: 0.5em">
|
|
|
|
{{ userInfo!.username }}
|
|
|
|
</a-typography-title>
|
|
|
|
</template>
|
|
|
|
</a-card-meta>
|
|
|
|
</div>
|
2023-10-11 16:41:06 -04:00
|
|
|
<a-badge-ribbon color="#f14668" v-if="userInfo?.profile.isAdmin">
|
2023-10-10 22:44:04 -04:00
|
|
|
<template #text> Administrator </template>
|
|
|
|
</a-badge-ribbon>
|
|
|
|
</template>
|
2023-12-29 20:11:07 -05:00
|
|
|
<a-descriptions :column="2" :labelStyle="{ fontWeight: 'bold' }" :colon="false">
|
2023-10-10 22:44:04 -04:00
|
|
|
<a-descriptions-item label="Last visit">
|
2023-12-29 20:11:07 -05:00
|
|
|
<div v-if="userInfo?.banned" style="color: red; font-weight: bold">BANNED</div>
|
2023-10-10 22:44:04 -04:00
|
|
|
<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>
|
2023-12-29 20:11:07 -05:00
|
|
|
<span style="margin-left: 0.6em"> ({{ formatDistanceToNow(uLastVisit, { addSuffix: true }) }}) </span>
|
2023-10-10 22:44:04 -04:00
|
|
|
</div>
|
|
|
|
</a-descriptions-item>
|
|
|
|
<a-descriptions-item label="Website">
|
2023-12-29 20:11:07 -05:00
|
|
|
<a target="_blank" :href="`${userInfo?.profile.website.startsWith('http') ? '' : 'http://'}${userInfo?.profile.website}`">
|
2023-10-10 22:44:04 -04:00
|
|
|
{{ userInfo?.profile.website }}
|
|
|
|
</a>
|
|
|
|
</a-descriptions-item>
|
|
|
|
<a-descriptions-item label="Blog/Journal">
|
2023-12-29 20:11:07 -05:00
|
|
|
<a target="_blank" :href="`${userInfo?.profile.blog.startsWith('http') ? '' : 'http://'}${userInfo?.profile.blog}`">
|
2023-10-10 22:44:04 -04:00
|
|
|
{{ userInfo?.profile.blog }}
|
|
|
|
</a>
|
|
|
|
</a-descriptions-item>
|
|
|
|
<a-descriptions-item label="Occupation">
|
|
|
|
{{ userInfo?.profile.occupation }}
|
|
|
|
</a-descriptions-item>
|
2023-12-29 20:11:07 -05:00
|
|
|
<a-descriptions-item label="Email" v-if="userInfo?.profile.showEmail || ses?.user?.profile.isAdmin">
|
2023-10-10 22:44:04 -04:00
|
|
|
{{ 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">
|
2023-12-06 21:57:33 -05:00
|
|
|
<listings-stories :prefix="`/user/${rtr.params.id}/stories`" />
|
2023-10-10 22:44:04 -04:00
|
|
|
</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">
|
2023-12-06 21:57:33 -05:00
|
|
|
<single-story :last="true" :story="item" />
|
2023-10-10 22:44:04 -04:00
|
|
|
</a-col>
|
|
|
|
<a-col :span="1" v-if="isSelf">
|
2023-12-29 20:11:07 -05:00
|
|
|
<a style="color: red" @click="() => favourites(userInfo?.favs.stories || [], item._id, true, 'story')">
|
2023-10-10 22:44:04 -04:00
|
|
|
<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">
|
2023-12-29 20:11:07 -05:00
|
|
|
<a-list item-layout="horizontal" :data-source="userInfo?.favs.authors" :grid="{ gutter: 16, column: 3 }">
|
2023-10-10 22:44:04 -04:00
|
|
|
<template #renderItem="{ item }">
|
|
|
|
<a-list-item style="display: flex; align-items: center">
|
2023-12-29 20:11:07 -05:00
|
|
|
<a-list-item-meta style="align-items: center; width: min-content">
|
2023-10-10 22:44:04 -04:00
|
|
|
<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>
|
2023-12-29 20:11:07 -05:00
|
|
|
<a style="color: red" @click="() => favourites(userInfo?.favs.authors || [], item._id, true, 'author')">
|
2023-10-10 22:44:04 -04:00
|
|
|
<icon istyle="regular" name="trash" color="#f00" />
|
|
|
|
</a>
|
|
|
|
</span>
|
|
|
|
</template>
|
|
|
|
</a-list-item>
|
|
|
|
</template>
|
|
|
|
</a-list>
|
|
|
|
</a-tab-pane>
|
|
|
|
</a-tabs>
|
|
|
|
</a-tab-pane>
|
2023-12-06 21:57:33 -05:00
|
|
|
<a-tab-pane key="admin" tab="Admin" v-if="ses?.user?.profile.isAdmin">
|
2023-10-10 22:44:04 -04:00
|
|
|
<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>
|