Add followers and following lists to profile page
This commit is contained in:
parent
1c50089734
commit
d440b91033
3 changed files with 102 additions and 19 deletions
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue