Add followers and following lists to profile page

This commit is contained in:
silverpill 2022-01-02 18:03:24 +00:00
parent 1c50089734
commit d440b91033
3 changed files with 102 additions and 19 deletions

View file

@ -1,5 +1,6 @@
import { BACKEND_URL } from "@/constants" import { BACKEND_URL } from "@/constants"
import { http } from "./common" import { http } from "./common"
import { Profile } from "./users"
export interface Relationship { export interface Relationship {
id: string, id: string,
@ -58,3 +59,23 @@ export async function unfollow(
return data return data
} }
} }
export async function getFollowers(
authToken: string,
accountId: string,
): Promise<Profile[]> {
const url = `${BACKEND_URL}/api/v1/accounts/${accountId}/followers`
const response = await http(url, { authToken })
const data = await response.json()
return data
}
export async function getFollowing(
authToken: string,
accountId: string,
): Promise<Profile[]> {
const url = `${BACKEND_URL}/api/v1/accounts/${accountId}/following`
const response = await http(url, { authToken })
const data = await response.json()
return data
}

View file

@ -86,6 +86,12 @@ const routes: Array<RouteRecordRaw> = [
component: ProfileView, component: ProfileView,
meta: { }, meta: { },
}, },
{
path: "/profile/:profileId/:tabName",
name: "profile-tab",
component: ProfileView,
meta: { onlyAuthenticated: true },
},
{ {
path: "/profile-directory", path: "/profile-directory",
name: "profile-directory", name: "profile-directory",

View file

@ -1,7 +1,7 @@
<template> <template>
<div id="main" v-if="profile"> <div id="main" v-if="profile">
<div class="content posts"> <div class="content posts">
<div class="profile"> <div class="profile-block">
<div class="profile-header"> <div class="profile-header">
<img v-if="profile.header" :src="profile.header"> <img v-if="profile.header" :src="profile.header">
</div> </div>
@ -27,16 +27,44 @@
<dd v-html="field.value"></dd> <dd v-html="field.value"></dd>
</dl> </dl>
</div> </div>
<dl class="stats"> <div class="stats">
<dt>{{ profile.statuses_count }}</dt><dd>posts</dd> <component
<dt>{{ profile.following_count }}</dt><dd>following</dd> class="stats-item"
<dt>{{ profile.followers_count }}</dt><dd>followers</dd> :is="isCurrentUser() ? 'router-link' : 'div'"
</dl> :to="{ name: 'profile-tab', params: { profileId: profile.id, tabName: 'posts' }}"
>
<span class="value">{{ profile.statuses_count }}</span>
<span class="label">posts</span>
</component>
<component
class="stats-item"
:is="isCurrentUser() ? 'router-link' : 'div'"
:to="{ name: 'profile-tab', params: { profileId: profile.id, tabName: 'followers' }}">
<span class="value">{{ profile.followers_count }}</span>
<span class="label">followers</span>
</component>
<component
class="stats-item"
:is="isCurrentUser() ? 'router-link' : 'div'"
:to="{ name: 'profile-tab', params: { profileId: profile.id, tabName: 'following' }}"
>
<span class="value">{{ profile.following_count }}</span>
<span class="label">following</span>
</component>
</div>
</div> </div>
<post-list <post-list
v-if="tabName === 'posts'"
:posts="posts" :posts="posts"
@load-next-page="loadNextPage" @load-next-page="loadNextPage"
></post-list> ></post-list>
<template v-if="tabName === 'followers' || tabName === 'following'">
<profile-list-item
v-for="profile in followList"
:profile="profile"
:key="profile.id"
></profile-list-item>
</template>
</div> </div>
<sidebar></sidebar> <sidebar></sidebar>
</div> </div>
@ -52,9 +80,12 @@ import {
unfollow, unfollow,
Relationship, Relationship,
getRelationship, getRelationship,
getFollowers,
getFollowing,
} from "@/api/relationships" } from "@/api/relationships"
import Avatar from "@/components/Avatar.vue" import Avatar from "@/components/Avatar.vue"
import PostList from "@/components/PostList.vue" import PostList from "@/components/PostList.vue"
import ProfileListItem from "@/components/ProfileListItem.vue"
import Sidebar from "@/components/Sidebar.vue" import Sidebar from "@/components/Sidebar.vue"
import { useInstanceInfo } from "@/store/instance" import { useInstanceInfo } from "@/store/instance"
import { useCurrentUser } from "@/store/user" import { useCurrentUser } from "@/store/user"
@ -63,6 +94,7 @@ import { useCurrentUser } from "@/store/user"
components: { components: {
Avatar, Avatar,
PostList, PostList,
ProfileListItem,
Sidebar, Sidebar,
}, },
}) })
@ -76,7 +108,9 @@ export default class ProfileView extends Vue {
profile: Profile | null = null profile: Profile | null = null
relationship: Relationship | null = null relationship: Relationship | null = null
tabName = "posts"
posts: Post[] = [] posts: Post[] = []
followList: Profile[] = []
async created() { async created() {
this.profile = await getProfile( this.profile = await getProfile(
@ -89,10 +123,23 @@ export default class ProfileView extends Vue {
this.profile.id, this.profile.id,
) )
} }
this.posts = await getProfileTimeline( this.tabName = this.$route.params.tabName as string || "posts"
this.store.authToken, if (this.tabName === "posts") {
this.profile.id, this.posts = await getProfileTimeline(
) this.store.authToken,
this.profile.id,
)
} else if (this.tabName === "followers" && this.isCurrentUser()) {
this.followList = await getFollowers(
this.store.ensureAuthToken(),
this.profile.id,
)
} else if (this.tabName === "following" && this.isCurrentUser()) {
this.followList = await getFollowing(
this.store.ensureAuthToken(),
this.profile.id,
)
}
} }
get actorAddress(): string { get actorAddress(): string {
@ -168,7 +215,7 @@ export default class ProfileView extends Vue {
$avatar-size: 170px; $avatar-size: 170px;
.profile { .profile-block {
background-color: $block-background-color; background-color: $block-background-color;
border-radius: $block-border-radius; border-radius: $block-border-radius;
margin-bottom: $block-outer-padding; margin-bottom: $block-outer-padding;
@ -256,19 +303,28 @@ $avatar-size: 170px;
.stats { .stats {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
flex-wrap: wrap;
font-weight: bold; font-weight: bold;
gap: $block-inner-padding 30px;
padding: 0 $block-inner-padding $block-inner-padding; padding: 0 $block-inner-padding $block-inner-padding;
text-align: center; text-align: center;
dt { .stats-item {
font-size: 18px; display: flex;
} gap: 5px;
dd { .value {
align-self: flex-end; font-size: 18px;
color: $secondary-text-color; }
margin-left: 5px;
margin-right: 30px; .label {
align-self: flex-end;
color: $secondary-text-color;
}
} }
} }
.profile {
margin-bottom: $block-outer-padding;
}
</style> </style>