|
16 | 16 |
|
17 | 17 | 'use client'; |
18 | 18 |
|
19 | | -import { useSession } from 'next-auth/react'; |
20 | | -import { usePathname, useRouter } from 'next/navigation'; |
21 | | -import { useState, useCallback, useEffect } from 'react'; |
22 | | - |
23 | | -import Avatar from '@/components/Avatar'; |
24 | | -import { Button } from '@/components/Button'; |
25 | | -import { SvgIcon } from '@/components/Image'; |
26 | | -import Loader from '@/components/Loader'; |
27 | | -import { NoData } from '@/components/NoData'; |
28 | | - |
29 | | -import { fetchFollowerList, fetchFollowedList, followUser, unfollowUser } from '#/domain/profile/repository'; |
30 | | -import TabBarWidget from '#/domain/profile/widgets/tab-bar'; |
31 | | -import { useUser } from '#/state/application/hooks'; |
32 | | - |
33 | | -const followFetchMap = { |
34 | | - followers: fetchFollowerList, |
35 | | - following: fetchFollowedList, |
36 | | -}; |
| 19 | +import FollowerListViewWidget from '#/domain/profile/views/follower-list'; |
37 | 20 |
|
38 | 21 | export default function Follow({ params }) { |
39 | | - const { status } = useSession(); |
40 | | - const router = useRouter(); |
41 | | - const pathname = usePathname(); |
42 | | - const user = useUser(); |
43 | | - const [loading, setLoading] = useState(false); |
44 | | - |
45 | | - const [followLoading, setFollowLoading] = useState(false); |
46 | | - |
47 | | - const [page, setPage] = useState(1); |
48 | | - const [list, setList] = useState(); |
49 | | - const [count, setCount] = useState(); |
50 | | - |
51 | | - const fetchList = useCallback(async () => { |
52 | | - // handle |
53 | | - setLoading(true); |
54 | | - const data = await followFetchMap[params.follow]({ handle: params.handle, pageNum: page }); |
55 | | - setLoading(false); |
56 | | - if (page === 1) { |
57 | | - setList(data.data.list); |
58 | | - } else { |
59 | | - setList(list => list.concat(data.data.list)); |
60 | | - } |
61 | | - setCount(data.data.count); |
62 | | - }, [params, page]); |
63 | | - |
64 | | - useEffect(() => { |
65 | | - fetchList(); |
66 | | - }, [fetchList]); |
67 | | - |
68 | | - const follow = async (item, index, type) => { |
69 | | - if (status !== 'authenticated') { |
70 | | - router.push(`/signin?from=${pathname}`); |
71 | | - } else { |
72 | | - setFollowLoading(index); |
73 | | - const res = await followUser(item.user.user_id); |
74 | | - setFollowLoading(null); |
75 | | - if (res.success) { |
76 | | - const _prevList = [...list]; |
77 | | - _prevList[index].mutual = type; |
78 | | - setList(_prevList); |
79 | | - } |
80 | | - } |
81 | | - }; |
82 | | - |
83 | | - const unfollow = async (item, index, type) => { |
84 | | - if (status !== 'authenticated') { |
85 | | - router.push(`/signin?from=${pathname}`); |
86 | | - } else { |
87 | | - setFollowLoading(index); |
88 | | - const res = await unfollowUser(item.user.user_id); |
89 | | - setFollowLoading(null); |
90 | | - if (res.success) { |
91 | | - const _prevList = [...list]; |
92 | | - _prevList[index].mutual = type; |
93 | | - setList(_prevList); |
94 | | - } |
95 | | - } |
96 | | - }; |
97 | | - |
98 | | - const tabs = ['Followers', 'Following']; |
99 | | - |
100 | 22 | return ( |
101 | | - <div className="md:pl-[410px] md:pb-14 md:pr-14"> |
102 | | - <TabBarWidget |
103 | | - tabs={tabs} |
104 | | - tabClassName="h-14 md:h-9 md:px-6" |
105 | | - current={tabs.findIndex(tab => tab.toLowerCase() === params.follow)} |
106 | | - onChange={tabIndex => router.push(`/u/${params.handle}/${tabs[tabIndex].toLowerCase()}`)} |
107 | | - /> |
108 | | - <div> |
109 | | - <ul> |
110 | | - {list?.map((i, k) => <li key={`user-follow-${params.follow}-${i.user_id}`} className="flex items-center mt-6"> |
111 | | - <Avatar size={60} user={i.user} /> |
112 | | - <div className="flex-1 h-12 ml-4 mr-8"> |
113 | | - <h6> |
114 | | - <a href={`/u/${i.user.user_handle}`}>{i.user.user_nick_name}</a> |
115 | | - </h6> |
116 | | - <p>{i.user.user_handle}</p> |
117 | | - </div> |
118 | | - {user?.base.user_id === i.user.user_id ? <></> : i.mutual ? <Button |
119 | | - className="!h-10 group" |
120 | | - variant="outlined" |
121 | | - loading={followLoading === k} |
122 | | - onClick={() => unfollow(i, k, false)} |
123 | | - > |
124 | | - <span className="!font-bold block group-hover:hidden">Following</span> |
125 | | - <span className="!font-bold hidden group-hover:block">Unfollow</span> |
126 | | - </Button> : <Button |
127 | | - loading={followLoading === k} |
128 | | - variant="contained" |
129 | | - className="!h-10" |
130 | | - onClick={() => follow(i, k, true)} |
131 | | - > |
132 | | - <SvgIcon name="plus" size={16} /> |
133 | | - <span className="!font-bold">Follow</span> |
134 | | - </Button>} |
135 | | - </li>)} |
136 | | - </ul> |
137 | | - </div> |
138 | | - {list?.length !== 0 && list?.length < count && !loading && ( |
139 | | - <div onClick={() => setPage(page + 1)} className="flex bg-gray-400 justify-center gap-2 h-9 items-center cursor-pointer rounded group"> |
140 | | - <svg className="opacity-40 transition-all group-hover:opacity-80" width="19" height="19" viewBox="0 0 19 19" fill="none" xmlns="http://www.w3.org/2000/svg"> |
141 | | - <g> |
142 | | - <path d="M14.25 4.75L9.5 9.5L4.75 4.75" stroke="#1A1A1A" strokeLinecap="round" strokeLinejoin="round"/> |
143 | | - <path d="M14.25 9.5L9.5 14.25L4.75 9.5" stroke="#1A1A1A" strokeLinecap="round" strokeLinejoin="round"/> |
144 | | - </g> |
145 | | - </svg> |
146 | | - <span className="opacity-40 transition-all group-hover:opacity-80">More</span> |
147 | | - </div> |
148 | | - )} |
149 | | - {(list?.length === 0 || list === null) && !loading && <NoData />} |
150 | | - {loading && ( |
151 | | - <div className="flex justify-center pt-10"> |
152 | | - <Loader color="#1a1a1a" /> |
153 | | - </div> |
154 | | - )} |
155 | | - </div> |
| 23 | + <FollowerListViewWidget userHandle={params.handle} followType={params.follow} /> |
156 | 24 | ); |
157 | 25 | } |
0 commit comments