-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
165 additions
and
32 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import axiosInstance from '@/lib/axios/axiosInstance'; | ||
|
||
const createFollowUser = async (userId: number) => { | ||
return await axiosInstance.post(`/follow/${userId}`); | ||
}; | ||
|
||
export default createFollowUser; |
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,7 @@ | ||
import axiosInstance from '@/lib/axios/axiosInstance'; | ||
|
||
const deleteFollowUser = async (userId: number) => { | ||
return await axiosInstance.delete(`/follow/${userId}`); | ||
}; | ||
|
||
export default deleteFollowUser; |
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 |
---|---|---|
@@ -1,8 +1,10 @@ | ||
import axiosInstance from '@/lib/axios/axiosInstance'; | ||
import { UserType } from '@/lib/types/userProfileType'; | ||
|
||
export const getUserOne = async (userId: number) => { | ||
const getUserOne = async (userId: number) => { | ||
const response = await axiosInstance.get<UserType>(`/users/${userId}`); | ||
|
||
return response.data; | ||
}; | ||
|
||
export default getUserOne; |
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 |
---|---|---|
@@ -1,13 +1,26 @@ | ||
import { style } from '@vanilla-extract/css'; | ||
import { style, styleVariants } from '@vanilla-extract/css'; | ||
import { vars } from '@/styles/theme.css'; | ||
|
||
export const button = style({ | ||
padding: '0.8rem 1.2rem', | ||
|
||
backgroundColor: vars.color.blue, | ||
borderRadius: '5rem', | ||
fontWeight: '400', | ||
lineHeight: '1.6rem', | ||
}); | ||
|
||
fontSize: '1rem', | ||
fontWeight: '600', | ||
color: vars.color.white, | ||
export const variant = styleVariants({ | ||
primary: [ | ||
button, | ||
{ | ||
backgroundColor: vars.color.blue, | ||
color: vars.color.white, | ||
}, | ||
], | ||
gray: [ | ||
button, | ||
{ | ||
backgroundColor: vars.color.gray7, | ||
color: vars.color.white, | ||
}, | ||
], | ||
}); |
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 |
---|---|---|
@@ -1,27 +1,81 @@ | ||
'use client'; | ||
|
||
/** | ||
TODO | ||
- [ ] 상태(팔로우, 언팔로우)에 따른 팔로우 버튼 UI | ||
- [ ] 조건(비회원, 회원)에 따른 팔로우 버튼 동작(api 연동) | ||
*/ | ||
import { useRouter } from 'next/navigation'; | ||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; | ||
import { AxiosError } from 'axios'; | ||
|
||
import * as styles from './FollowButton.css'; | ||
|
||
interface ActionProps { | ||
import createFollowUser from '@/app/_api/follow/createFollowUser'; | ||
import deleteFollowUser from '@/app/_api/follow/deleteFollowUser'; | ||
import getUserOne from '@/app/_api/user/getUserOne'; | ||
|
||
import { QUERY_KEYS } from '@/lib/constants/queryKeys'; | ||
import { UserType } from '@/lib/types/userProfileType'; | ||
import { useUser } from '@/store/useUser'; | ||
import toasting from '@/lib/utils/toasting'; | ||
import { MAX_FOLLOWING, toastMessage } from '@/lib/constants/toastMessage'; | ||
|
||
interface FollowButtonProps { | ||
userId: number; | ||
isFollowed: boolean; | ||
} | ||
|
||
export default function FollowButton({ isFollowed }: ActionProps) { | ||
const label = isFollowed ? '팔로우' : '팔로우 취소'; | ||
export default function FollowButton({ isFollowed, userId }: FollowButtonProps) { | ||
const queryClient = useQueryClient(); | ||
const router = useRouter(); | ||
const { user: userMe } = useUser(); | ||
|
||
const { data: userMeData } = useQuery<UserType>({ | ||
queryKey: [QUERY_KEYS.userOne, userMe.id], | ||
queryFn: () => getUserOne(userMe.id), | ||
enabled: !!userMe.id, | ||
}); | ||
|
||
const followUser = useMutation({ | ||
mutationKey: [QUERY_KEYS.follow, userId], | ||
mutationFn: () => createFollowUser(userId), | ||
onSuccess: () => { | ||
queryClient.invalidateQueries({ | ||
queryKey: [QUERY_KEYS.userOne, userId], | ||
}); | ||
}, | ||
onError: (error: AxiosError) => { | ||
if (error.response?.status === 401) { | ||
toasting({ type: 'warning', txt: toastMessage.ko.requiredLogin }); | ||
router.push('/login'); | ||
} | ||
}, | ||
}); | ||
|
||
const deleteFollowingUser = useMutation({ | ||
mutationKey: [QUERY_KEYS.deleteFollow, userId], | ||
mutationFn: () => deleteFollowUser(userId), | ||
onSuccess: () => { | ||
queryClient.invalidateQueries({ | ||
queryKey: [QUERY_KEYS.userOne, userId], | ||
}); | ||
}, | ||
}); | ||
|
||
const handleFollowUser = () => { | ||
// 1. follow 하는 api 요청 + update | ||
const handleFollowUser = (isFollowed: boolean) => () => { | ||
if (isFollowed) { | ||
deleteFollowingUser.mutate(); | ||
} else { | ||
if (userMeData && userMeData?.followingCount >= MAX_FOLLOWING) { | ||
toasting({ type: 'warning', txt: toastMessage.ko.limitFollow }); | ||
return; | ||
} | ||
followUser.mutate(); | ||
} | ||
}; | ||
|
||
return ( | ||
<button className={styles.button} onClick={handleFollowUser}> | ||
{label} | ||
<button | ||
className={`${isFollowed ? styles.variant.gray : styles.variant.primary}`} | ||
onClick={handleFollowUser(isFollowed)} | ||
> | ||
{isFollowed ? '팔로우 취소' : '팔로우'} | ||
</button> | ||
); | ||
} |
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,34 @@ | ||
/** | ||
* 숫자 형태를 단위에 맞게 변환해주는 포매팅 함수입니다. | ||
- 만 미만: 축약 없이 컴마(,) 처리 ex. 1~9,999 (ko, en) | ||
- 만 이상: 만 단위 ex. 1만, 35.5만, 510만... (ko) | ||
- 만 이상: K 단위(소숫점 1자리) ex. 10K, 355.3K (en) | ||
- 백만 이상: M 단위(소숫점 1자리) ex. 5.1M (en) | ||
* @param {number} num 축약할 숫자입니다. | ||
* @param {'ko' | 'en'} lang 적용할 숫자 국가 단위입니다. | ||
* @returns {number} 단위에 맞게 변환된 숫자입니다. | ||
*/ | ||
|
||
const numberFormatter = (num: number, lang: 'ko' | 'en') => { | ||
const unit = 10000; | ||
|
||
if (num / unit < 1) { | ||
return num.toLocaleString('ko-KR'); | ||
} | ||
|
||
if (lang === 'ko') { | ||
const formattedNumKo = Math.trunc((num / unit) * 10) / 10; | ||
return formattedNumKo + '만'; | ||
} else { | ||
const formattedNumEn = Math.trunc((num / unit) * 10); | ||
if (formattedNumEn < 1000) { | ||
return formattedNumEn + 'K'; | ||
} else { | ||
const formattedMillion = Math.trunc((formattedNumEn / 1000) * 10) / 10; | ||
return formattedMillion + 'M'; | ||
} | ||
} | ||
}; | ||
|
||
export default numberFormatter; |