-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #484 from depromeet/feat/follow-list
[Feat] 팔로잉/팔로워 리스트 페이지
- Loading branch information
Showing
26 changed files
with
558 additions
and
158 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import Link from 'next/link'; | ||
import { type FollowerMemberWithStatusType, FollowStatus } from '@/apis/schema/member'; | ||
import { useGetMeId, useViewList } from '@/app/profile/[id]/follows/index.hooks'; | ||
import { | ||
FollowingMember, | ||
type MemberItemProps, | ||
MineMemberItem, | ||
NotFollowingMember, | ||
} from '@/components/ListItem/Follow/MemberItem'; | ||
import { stagger } from '@/components/Motion/Motion.constants'; | ||
import StaggerWrapper from '@/components/Motion/StaggerWrapper'; | ||
import { ROUTER } from '@/constants/router'; | ||
import { css } from '@/styled-system/css'; | ||
|
||
interface Props { | ||
list: FollowerMemberWithStatusType[]; | ||
refetch: () => void; | ||
} | ||
|
||
function FollowingList(props: Props) { | ||
const { list, onUpdateItem } = useViewList(props.list); | ||
|
||
return ( | ||
<StaggerWrapper wrapperOverrideCss={containerCss} staggerVariants={stagger(0.1)}> | ||
{list.map((item) => ( | ||
<Link key={item.memberId} href={ROUTER.PROFILE.DETAIL(item.memberId)} passHref> | ||
<Item | ||
{...item} | ||
onUpdateList={(_item) => { | ||
onUpdateItem(_item); | ||
props.refetch(); | ||
}} | ||
/> | ||
</Link> | ||
))} | ||
</StaggerWrapper> | ||
); | ||
} | ||
|
||
export default FollowingList; | ||
|
||
interface ItemProps extends Omit<MemberItemProps, 'onButtonClick'> { | ||
onUpdateList: (item: FollowerMemberWithStatusType) => void; | ||
} | ||
|
||
function Item({ onUpdateList, ...props }: ItemProps) { | ||
const myId = useGetMeId(); | ||
|
||
if (props.memberId === myId) { | ||
return <MineMemberItem {...props} />; | ||
} | ||
|
||
switch (props.followStatus) { | ||
case FollowStatus.FOLLOWING: | ||
return <FollowingMember {...props} onButtonClick={onUpdateList} />; | ||
case FollowStatus.NOT_FOLLOWING: | ||
case FollowStatus.FOLLOWED_BY_ME: | ||
return <NotFollowingMember {...props} onButtonClick={onUpdateList} />; | ||
default: | ||
return null; | ||
} | ||
} | ||
|
||
const containerCss = css({ | ||
padding: '16px', | ||
width: '100%', | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import Link from 'next/link'; | ||
import { useAddFollow } from '@/apis/follow'; | ||
import { type FollowerMemberWithStatusType, FollowStatus } from '@/apis/schema/member'; | ||
import { useViewList } from '@/app/profile/[id]/follows/index.hooks'; | ||
import { ProfileListItem } from '@/components/ListItem'; | ||
import { stagger } from '@/components/Motion/Motion.constants'; | ||
import StaggerWrapper from '@/components/Motion/StaggerWrapper'; | ||
import { ROUTER } from '@/constants/router'; | ||
import { css } from '@/styled-system/css'; | ||
|
||
interface Props { | ||
list: FollowerMemberWithStatusType[]; | ||
refetch: () => void; | ||
} | ||
|
||
function MyFollowerList(props: Props) { | ||
const { list, onUpdateItem } = useViewList(props.list); | ||
|
||
return ( | ||
<StaggerWrapper wrapperOverrideCss={containerCss} staggerVariants={stagger(0.1)}> | ||
{list.map((item) => ( | ||
<Item | ||
key={`${item.memberId}-${item.followStatus}`} | ||
item={item} | ||
onUpdateItem={(_item) => { | ||
onUpdateItem(_item); | ||
props.refetch(); | ||
}} | ||
/> | ||
))} | ||
</StaggerWrapper> | ||
); | ||
} | ||
|
||
export default MyFollowerList; | ||
|
||
interface ItemProps { | ||
item: FollowerMemberWithStatusType; | ||
onUpdateItem: (member: FollowerMemberWithStatusType) => void; | ||
} | ||
|
||
function Item({ item, onUpdateItem }: ItemProps) { | ||
const { mutate } = useAddFollow({ | ||
onSuccess: () => { | ||
onUpdateItem({ ...item, followStatus: FollowStatus.FOLLOWING }); | ||
}, | ||
}); | ||
|
||
const isFollowing = item.followStatus === FollowStatus.FOLLOWING; | ||
|
||
return ( | ||
<Link key={item.memberId} href={ROUTER.PROFILE.DETAIL(item.memberId)}> | ||
<ProfileListItem | ||
variant={isFollowing ? 'one-button' : 'two-button'} | ||
subElement={ | ||
!isFollowing && ( | ||
<span className={followLabelCss} onClick={() => mutate(item.memberId)}> | ||
팔로우 | ||
</span> | ||
) | ||
} | ||
buttonElement={ | ||
// TODO : 삭제 버튼 추가 필요 (맞팔 관계 팔로우 삭제, 맞팔 x, 팔로워 관계 삭제) | ||
// 일정 상 무리라고 판단 (2/6) 추후 수정 | ||
<div></div> | ||
} | ||
thumbnailUrl={item.profileImageUrl} | ||
name={item.nickname} | ||
/> | ||
</Link> | ||
); | ||
} | ||
|
||
const containerCss = css({ | ||
padding: '16px', | ||
}); | ||
|
||
const followLabelCss = css({ | ||
padding: '8px 12px', | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { useEffect, useState } from 'react'; | ||
import { useGetMembersMe } from '@/apis/member'; | ||
import { type FollowerMemberWithStatusType } from '@/apis/schema/member'; | ||
import { sorFollowerList } from '@/app/profile/[id]/follows/index.utils'; | ||
|
||
export const useViewList = (list: FollowerMemberWithStatusType[]) => { | ||
const myId = useGetMeId(); | ||
const [viewList, setViewList] = useState(list); | ||
|
||
const onUpdateItem = (member: FollowerMemberWithStatusType) => { | ||
setViewList((prev) => prev.map((item) => (item.memberId === member.memberId ? member : item))); | ||
}; | ||
|
||
useEffect(() => { | ||
const sortList = sorFollowerList(list, Number(myId)); | ||
setViewList(sortList); | ||
}, []); | ||
|
||
return { list: viewList, onUpdateItem }; | ||
}; | ||
|
||
// @description 현재 로그인한 사용자의 memberId를 가져옵니다. | ||
export const useGetMeId = () => { | ||
const { data } = useGetMembersMe(); | ||
const memberId = data?.memberId ?? 0; | ||
return memberId; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { type FollowerMemberWithStatusType, FollowStatus } from '@/apis/schema/member'; | ||
|
||
export const sorFollowerList = (list: FollowerMemberWithStatusType[], myId: number): FollowerMemberWithStatusType[] => { | ||
// 1순위) 내 계정, 내가 팔로잉 중인 계정, 내가 팔로우 중이지 않은 계정 순으로 리스트 나열 | ||
// 2순위) 가나다 순, ABC순으로 나열 | ||
|
||
const myAccount = list.filter((item) => item.memberId === myId); | ||
const followingList = list.filter((item) => item.followStatus === FollowStatus.FOLLOWING); | ||
const followedByMeList = list.filter((item) => item.followStatus === FollowStatus.FOLLOWED_BY_ME); | ||
const notFollowingList = list.filter((item) => item.followStatus === FollowStatus.NOT_FOLLOWING); | ||
|
||
const sortedList = [...myAccount, ...followingList, ...followedByMeList, ...notFollowingList]; | ||
|
||
return sortedList; | ||
}; |
Oops, something went wrong.