Skip to content

Commit

Permalink
Merge pull request #108 from BCSDLab/feature/#99
Browse files Browse the repository at this point in the history
[FOLLOW] 친구 목록 페이지 UI 수정 및 에러 처리
  • Loading branch information
chaeseungyun authored Nov 21, 2023
2 parents e17f287 + b7091f2 commit fb4fbd6
Show file tree
Hide file tree
Showing 25 changed files with 409 additions and 152 deletions.
7 changes: 6 additions & 1 deletion src/api/follow/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export interface GetFollowListResponse {
id: number;
nickname: string;
userType: string;
userCountResponse: {
id: number;
reviewCount: number;
friendCount: number;
}
}[];
empty: boolean;
last: boolean;
Expand Down Expand Up @@ -95,5 +100,5 @@ export interface GetDetailReviewResponse {
}

export interface GetFollowerReviewCountParam {
followId: number;
id: number;
}
2 changes: 1 addition & 1 deletion src/api/follow/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ export const getFollowReview = (id: number, pageParam: string) => followApi.get<

export const getDetailReview = (followId: number, placeId: string) => followApi.get<GetDetailReviewResponse>(`/review/follower/${followId}/shop/${placeId}`);

export const getFollowerReviewCount = (param: GetFollowerReviewCountParam) => followApi.get(`/review/follower/${param.followId}/count`);
export const getFollowerReviewCount = (param: GetFollowerReviewCountParam) => followApi.get(`/review/follower/${param.id}/count`);
4 changes: 4 additions & 0 deletions src/assets/svg/follow/empty-star.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
1 change: 0 additions & 1 deletion src/pages/Follow/components/EmptyFriend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,5 @@ export default function EmptyFriend() {
<Empty className={style.content__svg} />
</div>
</div>

);
}
21 changes: 11 additions & 10 deletions src/pages/Follow/components/FollowList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,38 @@ import cn from 'utils/ts/classNames';
import useBooleanState from 'utils/hooks/useBooleanState';
import { ReactComponent as Ellipse } from 'assets/svg/follow/Ellipse.svg';
import Follower from './Follower';
import style from './FollowList.module.scss';
import styles from './FollowList.module.scss';
import { FollowerInfo } from '../static/entity';
import Recent from './Recent';

export interface Props {
title: string;
data: FollowerInfo[];
sended?: FollowerInfo[];
sent?: FollowerInfo[];
}

// 유저 검색 시 자신의 정보는 안보이도록 자신의 정보를 받아서 비교, 자신과의 followedType은 NONE
export default function FollowList({
title, data, sended,
title, data, sent,
}: Props) {
const [isShow, , , toggle] = useBooleanState(true);
return (
<div className={style.container}>
<button onClick={toggle} type="button" className={style.title}>
<div className={styles.container}>
<button onClick={toggle} type="button" className={styles.title}>
<span>
{title}
{' '}
{title === '친구 신청' && data.length !== 0 ? <Ellipse /> : null}
</span>
<Arrow className={cn(
{
[style.title__arrow]: true,
[style['title__arrow--up']]: isShow,
[styles.title__arrow]: true,
[styles['title__arrow--up']]: isShow,
},
)}
/>
</button>
<div className={style.recent}>
<div className={styles.recent}>
{isShow && title === '최근 접속한 친구' && data.map((item) => (
<Recent
key={item.id}
Expand All @@ -45,14 +45,15 @@ export default function FollowList({
{isShow && title !== '최근 접속한 친구' && data.map((item) => (
<Follower
id={item.id}
key={item.account}
key={item.nickname}
nickname={item.nickname}
account={item.account}
followedType={item.followedType}
requestId={item.requestId}
userCountResponse={item.userCountResponse}
/>
))}
{isShow && sended && sended.map((item) => (
{isShow && sent && sent.map((item) => (
<Follower
id={item.id}
key={item.id}
Expand Down
28 changes: 18 additions & 10 deletions src/pages/Follow/components/FollowProfile.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,23 @@
@include media.media-breakpoint-down(mobile) {
width: 100vw;
}

&__container {
display: flex;
width: 90%;
justify-content: space-between;
align-items: center;
}
}

.user {
display: flex;
height: 200px;
justify-content: center;
align-items: center;
width: 100%;

&__container {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
}

Expand All @@ -49,7 +53,6 @@

&__info {
margin-left: 20px;
width: 3vw;

&--span {
font-size: 25px;
Expand All @@ -69,15 +72,20 @@

&__button {
border: none;
background-color: #ffffff;
border-radius: 2em;
width: 80px;
height: 40px;
background-color: #eeeeee;
}
}

.set {
display: none;
&__count {
display: flex;
gap: 10px;

@include media.media-breakpoint-down(mobile) {
display: block;
&--font {
font-weight: 600;
text-align: center;
}
}
}

Expand Down
75 changes: 30 additions & 45 deletions src/pages/Follow/components/FollowProfile.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import defaultImage from 'assets/images/follow/default-image.png';
import { useEffect, useState } from 'react';
import { ReactComponent as Remove } from 'assets/svg/follow/user-remove.svg';
import cn from 'utils/ts/classNames';
import { ReactComponent as Checkerboard } from 'assets/svg/follow/checkerboard.svg';
import { ReactComponent as ClickedCheckerboard } from 'assets/svg/follow/checkerboard-click.svg';
import { ReactComponent as List } from 'assets/svg/follow/list.svg';
import { ReactComponent as ClickedList } from 'assets/svg/follow/list-click.svg';
import useBooleanState from 'utils/hooks/useBooleanState';
import useMediaQuery from 'utils/hooks/useMediaQuery';
import { useLocation } from 'react-router-dom';
import { ReactComponent as Add } from 'assets/svg/follow/user-add.svg';
import { EmailUser } from 'api/user/entity';
import style from './FollowProfile.module.scss';
import FollowReview from './FollowReview';
import useDeleteFollow from '../hooks/useDeleteFollow';
Expand All @@ -18,60 +11,62 @@ import useGetFollowerReview from '../hooks/useGetFollowerReview';
import useGetFollowerReviewCount from '../hooks/useGetFollowerReviewCount';

const useDeleteState = () => {
const [canDelete, setCanDelete] = useState(true);
const [isFollowed, setIsFollowed] = useState(true);
const { del, data: deletedUser } = useDeleteFollow();

useEffect(() => {
if (deletedUser && deletedUser.status >= 200 && deletedUser.status <= 299) {
setCanDelete((prev) => !prev);
setIsFollowed((prev) => !prev);
}
}, [deletedUser]);

return { del, canDelete, deletedUser };
return { del, isFollowed, deletedUser };
};

export default function FollowProfile() {
const location = useLocation();
const state = location.state as {
followId: number, nickname: string, account: string, followedType: string
};
const { data } = useGetFollowerReview(state.followId);
const [isCheckerboard, setIsCheckerboard, setIsList] = useBooleanState(true);
const { isMobile } = useMediaQuery();
const { del, canDelete } = useDeleteState();
const state = location.state as EmailUser;
const { data } = useGetFollowerReview(state.id);
const { del, isFollowed } = useDeleteState();
const request = useRequestAndUpdate();
const reviewCount = useGetFollowerReviewCount(state.followId);

useEffect(() => {
if (isMobile) setIsList();
});
const reviewCount = useGetFollowerReviewCount(state.id);

return (
<div className={style.container}>
<div className={style.top}>
<div className={style.user}>
<img alt="img" src={defaultImage} className={style.user__profile} />
<div className={style.user__container}>
<div className={style.top__container}>
<div className={style.user}>
<img alt="유저 프로필 이미지" src={defaultImage} className={style.user__profile} />
<div className={style.user__info}>
<div>
<span className={cn({ [style['user__info--span']]: true })}>{state.nickname}</span>
</div>
<span>
<div>
@
{state.account}
</span>
{state.account !== undefined ? state.account : 'SNS User'}
</div>
</div>
<button
type="button"
className={style.user__button}
onClick={() => (canDelete && del(state.account))
|| (!canDelete && request(state.account))}
onClick={() => (isFollowed && del(state.account))
|| (!isFollowed && request(state.account))}
>
{canDelete
? <Remove className={style.user__svg} />
: <Add className={style.user__svg} />}
{isFollowed
? '팔로잉'
: '팔로우'}
</button>
</div>
<div className={style.user__count}>
<div>
<div className={cn({ [style['user__count--font']]: true })}>{state.userCountResponse.reviewCount}</div>
<div>게시물</div>
</div>
<div>
<div className={cn({ [style['user__count--font']]: true })}>{state.userCountResponse.friendCount}</div>
<div>팔로워</div>
</div>
</div>
</div>
<div className={style.set}>리뷰</div>
</div>
Expand All @@ -82,25 +77,15 @@ export default function FollowProfile() {
{' '}
개의 리뷰
</div>
<div className={style.type}>
<button type="button" onClick={() => setIsCheckerboard()} className={style.type__button}>
{isCheckerboard ? <ClickedCheckerboard /> : <Checkerboard />}
</button>
<button type="button" onClick={() => setIsList()} className={style.type__button}>
{!isCheckerboard ? <ClickedList /> : <List />}
</button>
</div>
<div className={style.content}>
<div className={isCheckerboard ? style.review : style.review__list}>
<div className={style.review__list}>
{data && data.content.map(
(item) => (
<FollowReview
key={item.shopId}
placeId={item.placeId}
name={item.name}
photos={item.photos?.[0]}
category={item.category}
isCheckerboard={isCheckerboard}
/>
),
)}
Expand Down
17 changes: 5 additions & 12 deletions src/pages/Follow/components/FollowReview.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import useMediaQuery from 'utils/hooks/useMediaQuery';
import { useInfiniteQuery } from '@tanstack/react-query';
import { getDetailReview } from 'api/follow';
import useBooleanState from 'utils/hooks/useBooleanState';
Expand All @@ -10,8 +9,6 @@ import ListReview from './ListReview';
interface Props {
placeId: string;
name: string;
photos: string | undefined;
isCheckerboard: boolean;
category: string;
}

Expand All @@ -35,18 +32,15 @@ const useGetDetailReview = (placeId: string, followerId: number) => {
};

export default function FollowReview({
placeId, name, photos, isCheckerboard, category,
placeId, name, category,
}: Props) {
const { isMobile } = useMediaQuery();
const { data } = useGetDetailReview(placeId, 361);
const [isShow, , , toggle] = useBooleanState(false);

return (
<div className={style.container}>
{!isMobile && isCheckerboard && photos ? <img alt="shop" src={photos} className={style.review__img} /> : isCheckerboard && <div className={style.review__img}>{name}</div>}
{!isCheckerboard && (
<div className={style.content}>
{data
<div className={style.content}>
{data
&& (
<button type="button" onClick={toggle} className={style.title}>
<div>
Expand All @@ -62,16 +56,15 @@ export default function FollowReview({
/>
</button>
)}
{data && !isCheckerboard && isShow
{data && isShow
&& data.content.map((item) => (
<ListReview
createdAt={item.createdAt}
content={item.content}
rate={item.rate}
/>
))}
</div>
)}
</div>
</div>
);
}
Loading

0 comments on commit fb4fbd6

Please sign in to comment.