Skip to content

Commit

Permalink
[#457] LikeButton 컴포넌트 (#458)
Browse files Browse the repository at this point in the history
* feat: LikeButton 컴포넌트 작성

* feat: LikeButton 컴포넌트 작성

* refactor: LikeButton 컴포넌트 타입 지정부 수정

* refactor: 유저 책장 페이지 LikeButton 교체

* refactor: 책장 좋아요 Query 리팩터링

* chore: useMutateBookshelfLikeQuery 이름 변경

* fix: 빌드 에러 수정

* chore: useMutateBookshelfLikeQuery 파라미터 객체로 감싼 것 제거

* chore: 좋아요 버튼 스타일 수정

* fix: LikeButton 컴포넌트 onClick props 옵셔널로 수정
  • Loading branch information
hanyugeon authored and gxxrxn committed Jun 17, 2024
1 parent fd8ad31 commit 9d1a5c7
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 119 deletions.
55 changes: 22 additions & 33 deletions src/app/bookshelf/[bookshelfId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,26 @@
'use client';

import { IconHeart, IconArrowLeft, IconShare, IconKakao } from '@public/icons';
import useToast from '@/v1/base/Toast/useToast';
import useBookShelfBooksQuery from '@/queries/bookshelf/useBookShelfBookListQuery';
import useBookShelfInfoQuery from '@/queries/bookshelf/useBookShelfInfoQuery';
import {
useBookshelfLike,
useBookshelfUnlike,
} from '@/queries/bookshelf/useBookShelfLikeMutation';

import { useEffect } from 'react';
import { useInView } from 'react-intersection-observer';
import Button from '@/v1/base/Button';
import TopNavigation from '@/v1/base/TopNavigation';
import BookShelfRow from '@/v1/bookShelf/BookShelfRow';
import { useRouter } from 'next/navigation';
import { isAuthed } from '@/utils/helpers';
import Link from 'next/link';

import type { APIBookshelf, APIBookshelfInfo } from '@/types/bookshelf';

import useBookShelfBooksQuery from '@/queries/bookshelf/useBookShelfBookListQuery';
import useBookShelfInfoQuery from '@/queries/bookshelf/useBookShelfInfoQuery';
import useMutateBookshelfLikeQuery from '@/queries/bookshelf/useMutateBookshelfLikeQuery';

import useToast from '@/v1/base/Toast/useToast';
import { isAuthed } from '@/utils/helpers';

import { IconArrowLeft, IconShare, IconKakao } from '@public/icons';

import TopNavigation from '@/v1/base/TopNavigation';
import BookShelfRow from '@/v1/bookShelf/BookShelfRow';
import Button from '@/v1/base/Button';
import LikeButton from '@/v1/base/LikeButton';

const KAKAO_OAUTH_LOGIN_URL = `${process.env.NEXT_PUBLIC_API_URL}/oauth2/authorize/kakao?redirect_uri=${process.env.NEXT_PUBLIC_CLIENT_REDIRECT_URI}`;

export default function UserBookShelfPage({
Expand All @@ -29,8 +31,8 @@ export default function UserBookShelfPage({
};
}) {
const { data, isSuccess } = useBookShelfInfoQuery({ bookshelfId });
const { mutate: likeBookshelf } = useBookshelfLike(bookshelfId);
const { mutate: unlikeBookshelf } = useBookshelfUnlike(bookshelfId);
const { mutate: mutateBookshelfLike } =
useMutateBookshelfLikeQuery(bookshelfId);
const { show: showToast } = useToast();
const router = useRouter();

Expand All @@ -55,7 +57,7 @@ export default function UserBookShelfPage({
return;
}

!data.isLiked ? likeBookshelf() : unlikeBookshelf();
mutateBookshelfLike(data.isLiked);
};

return (
Expand All @@ -81,24 +83,11 @@ export default function UserBookShelfPage({
<span className="text-[1.4rem] text-[#939393]">
{`${data.job.jobGroupKoreanName}${data.job.jobNameKoreanName}`}
</span>
<Button
size="small"
colorScheme="warning"
fullRadius
fill={data.isLiked ? true : false}
<LikeButton
isLiked={data.isLiked}
likeCount={data.likeCount}
onClick={handleClickLikeButton}
>
<div className="bold flex items-center gap-[0.3rem] text-xs">
<IconHeart
fill={data.isLiked ? '#F56565' : 'white'}
stroke={!data.isLiked ? '#F56565' : 'white'}
stroke-width={1.5}
height="1.3rem"
w="1.3rem"
/>
{data.likeCount}
</div>
</Button>
/>
</div>
</div>

Expand Down
86 changes: 0 additions & 86 deletions src/queries/bookshelf/useBookShelfLikeMutation.ts

This file was deleted.

52 changes: 52 additions & 0 deletions src/queries/bookshelf/useMutateBookshelfLikeQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import type { APIBookshelfInfo } from '@/types/bookshelf';
import bookshelfAPI from '@/apis/bookshelf';
import bookShelfKeys from './key';

const useMutateBookshelfLikeQuery = (
bookshelfId: APIBookshelfInfo['bookshelfId']
) => {
const queryClient = useQueryClient();

return useMutation({
mutationFn: async (isLiked: APIBookshelfInfo['isLiked']) =>
!isLiked
? bookshelfAPI.likeBookshelf(bookshelfId)
: bookshelfAPI.unlikeBookshelf(bookshelfId),
onMutate: async () => {
await queryClient.cancelQueries(bookShelfKeys.info(bookshelfId));

const prevData = queryClient.getQueryData<APIBookshelfInfo>(
bookShelfKeys.info(bookshelfId)
);

if (prevData) {
const newData: APIBookshelfInfo = {
...prevData,
isLiked: !prevData.isLiked,
likeCount: prevData.isLiked
? prevData.likeCount - 1
: prevData.likeCount + 1,
};

queryClient.setQueryData<APIBookshelfInfo>(
bookShelfKeys.info(bookshelfId),
newData
);
}

return { prevData };
},
onError: (_error, _value, context) => {
queryClient.setQueryData(
bookShelfKeys.info(bookshelfId),
context?.prevData
);
},
onSettled: () => {
queryClient.invalidateQueries(bookShelfKeys.info(bookshelfId));
},
});
};

export default useMutateBookshelfLikeQuery;
26 changes: 26 additions & 0 deletions src/stories/base/LikeButton.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import LikeButton from '@/v1/base/LikeButton';
import { Meta, StoryObj } from '@storybook/react';

const meta: Meta<typeof LikeButton> = {
title: 'Base/LikeButton',
component: LikeButton,
tags: ['autodocs'],
};

export default meta;

type Story = StoryObj<typeof LikeButton>;

export const Default: Story = {
args: {
isLiked: false,
likeCount: 10,
},
};

export const IsLiked: Story = {
args: {
isLiked: true,
likeCount: 999,
},
};
32 changes: 32 additions & 0 deletions src/v1/base/LikeButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { APIBookshelfInfo } from '@/types/bookshelf';
import { IconHeart } from '@public/icons';

type LikeButtonProps = {
isLiked: APIBookshelfInfo['isLiked'];
likeCount: APIBookshelfInfo['likeCount'];
onClick?: () => void;
};

const LikeButton = ({ isLiked, likeCount, onClick }: LikeButtonProps) => {
const BG_COLOR_CLASS = isLiked ? 'bg-warning-800' : 'bg-white';
const ICON_COLOR_CLASS = isLiked ? 'stroke-white' : 'stroke-warning-800';
const TEXT_COLOR_CLASS = isLiked ? 'text-white' : 'text-warning-800';

return (
<button
onClick={onClick}
className={`${BG_COLOR_CLASS} flex h-[2.4rem] min-w-[5.6rem] items-center gap-[0.4rem] rounded-full border-[0.1rem] border-warning-800 bg-warning-800 px-[1rem]`}
>
<IconHeart
className={`${ICON_COLOR_CLASS} h-[1.5rem] w-[1.5rem] fill-white stroke-[0.15rem]`}
/>
<p
className={`${TEXT_COLOR_CLASS} min-w-[1.5rem] text-center text-xs font-bold`}
>
{likeCount}
</p>
</button>
);
};

export default LikeButton;

0 comments on commit 9d1a5c7

Please sign in to comment.