Skip to content

Commit

Permalink
Merge pull request #159 from Board-Buddy/Feat/#158
Browse files Browse the repository at this point in the history
Feat/#158 뱃지 목록 조회 기능 구현
  • Loading branch information
ChaeYubin authored Aug 6, 2024
2 parents a787a74 + 20bf12d commit e0a8dd0
Show file tree
Hide file tree
Showing 12 changed files with 129 additions and 76 deletions.
3 changes: 3 additions & 0 deletions src/app/(without-nav)/my/badges/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import BadgeListDetail from '@/containers/profile/BadgeListDetail';

export const dynamic = 'force-dynamic';
export const fetchCache = 'force-no-store';

const page = () => {
return <BadgeListDetail />;
};
Expand Down
4 changes: 2 additions & 2 deletions src/app/(without-nav)/profile/[nickname]/badges/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import BadgeListDetail from '@/containers/profile/BadgeListDetail';

const page = () => {
return <BadgeListDetail />;
const page = ({ params }: { params: { nickname: string } }) => {
return <BadgeListDetail nickname={params.nickname} />;
};

export default page;
28 changes: 2 additions & 26 deletions src/app/(without-nav)/profile/[nickname]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,7 @@
'use client';

import BadgeList from '@/containers/profile/BadgeList';
import BuddyPoint from '@/containers/profile/BuddyPoint';
import MyParticipation from '@/containers/profile/MyParticipation';
import ProfileInfo from '@/containers/profile/ProfileInfo';
import ReviewList from '@/containers/profile/ReviewList';
import Profile from '@/containers/profile/Profile';

const Page = ({ params }: { params: { nickname: string } }) => {
return (
<div className="items-center p-4">
<div className="pb-4">
<ProfileInfo
nickname={decodeURIComponent(params.nickname)}
description="자기소개"
rank={null}
/>
<BuddyPoint score={50} />
<BadgeList badges={[]} />
<ReviewList
totalExcellentCount={0}
totalGoodCount={2}
totalBadCount={0}
/>
<MyParticipation joinCount={2} />
</div>
</div>
);
return <Profile nickname={params.nickname} />;
};

export default Page;
5 changes: 3 additions & 2 deletions src/containers/profile/BadgeList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import Link from 'next/link';

interface Props {
badges: string[];
nickname?: string;
}

const BadgeList = ({ badges }: Props) => {
const BadgeList = ({ badges, nickname }: Props) => {
return (
<div className="border-b-[1px] border-gray-200 py-4">
<div className="flex justify-between items-center font-bold mb-4">
<div className="flex gap-2 px-1">뱃지 목록</div>
<Link href="/my/badges">
<Link href={nickname ? `${nickname}/badges` : '/my/badges'}>
<div
className={cn(
'flex items-center text-sm text-gray-700 font-bold',
Expand Down
45 changes: 27 additions & 18 deletions src/containers/profile/BadgeListDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
'use client';

import Loading from '@/components/Loading';
import { useGetBadgeList } from '@/hooks/useProfile';
import { UserInfo } from '@/types/user';
import { cn } from '@/utils/tailwind';
import { useQueryClient } from '@tanstack/react-query';
import Image from 'next/image';

const BadgeListDetail = () => {
const badges = [
{
badgeImageS3SavedURL: '',
},
{
badgeImageS3SavedURL: '',
},
{
badgeImageS3SavedURL: '',
},
{
badgeImageS3SavedURL: '',
},
{
badgeImageS3SavedURL: '',
},
];
interface Props {
nickname?: string;
}

const BadgeListDetail = ({ nickname }: Props) => {
const cache = useQueryClient();
const userInfo = cache.getQueryData(['userInfo']) as UserInfo;
const { nickname: myNickname } = userInfo;

const {
data: badges,
isPending,
isError,
error,
} = useGetBadgeList(nickname || myNickname);

if (isPending) {
return <Loading />;
}

if (isError) {
return <div>Error: {error.message}</div>;
}

return (
<div className="px-4 py-8">
Expand Down
3 changes: 0 additions & 3 deletions src/containers/profile/MyParticipation.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
import { ChevronRight } from 'lucide-react';

const MyParticipation = ({ joinCount }: { joinCount: number }) => {
return (
<div className="border-b-[1px] border-gray-200 py-4 px-1">
<div className="flex justify-between items-center text-md">
<div className="flex gap-2">참여 횟수 {joinCount}</div>
<ChevronRight className="w-5 h-5 text-gray-700 ml-1" />
</div>
</div>
);
Expand Down
46 changes: 37 additions & 9 deletions src/containers/profile/Profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,27 @@ import LocationSetting from '@/containers/profile/LocationSetting';
import LogoutButton from '@/containers/profile/LogoutButton';
import DeleteAccountButton from '@/containers/profile/DeleteAccountButton';

import { useGetMyProfile } from '@/hooks/useProfile';
import { useGetProfile } from '@/hooks/useProfile';
import { LoaderCircleIcon } from 'lucide-react';
import { useQueryClient } from '@tanstack/react-query';
import { UserInfo } from '@/types/user';
import { cn } from '@/utils/tailwind';

const Profile = () => {
const { data: profile, isPending, isError, error } = useGetMyProfile();
interface Props {
nickname?: string;
}

const Profile = ({ nickname }: Props) => {
const cache = useQueryClient();
const userInfo = cache.getQueryData(['userInfo']) as UserInfo;
const { nickname: myNickname } = userInfo;

const {
data: profile,
isPending,
isError,
error,
} = useGetProfile(nickname || myNickname);

if (isPending) {
return (
Expand All @@ -29,26 +45,38 @@ const Profile = () => {
}

return (
<div className="items-center">
<div className={cn('items-center', nickname && 'p-4')}>
<div className="mb-4">
<ProfileInfo
nickname={nickname && decodeURIComponent(nickname)}
description={profile.description}
rank={profile.rank}
profileImageS3SavedURL={profile.profileImageS3SavedURL}
/>
<BuddyPoint score={profile.buddyScore} />
<BadgeList badges={profile.badges} />
<BadgeList
badges={profile.badges}
nickname={nickname && decodeURIComponent(nickname)}
/>
<ReviewList
totalExcellentCount={profile.totalExcellentCount}
totalGoodCount={profile.totalGoodCount}
totalBadCount={profile.totalBadCount}
/>
<MyArticle />
<LocationSetting />
{!nickname && (
<>
<MyArticle />
<LocationSetting />
</>
)}
<MyParticipation joinCount={profile.joinCount} />
</div>
<LogoutButton />
<DeleteAccountButton />
{!nickname && (
<>
<LogoutButton />
<DeleteAccountButton />
</>
)}
</div>
);
};
Expand Down
27 changes: 11 additions & 16 deletions src/hooks/useProfile.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,11 @@
import { editProfile, getProfile } from '@/services/profile';
import { editProfile, getBadgeList, getProfile } from '@/services/profile';
import { UserInfo } from '@/types/user';
import { blobToJson } from '@/utils/blobToJson';
import { successToast } from '@/utils/customToast';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/navigation';
import toast from 'react-hot-toast';

export const useGetMyProfile = () => {
const queryClient = useQueryClient();
const userInfo = queryClient.getQueryData(['userInfo']) as UserInfo;
const { nickname } = userInfo;

return useQuery({
queryKey: ['profile', { nickname }],
queryFn: () => getProfile(nickname),
staleTime: 0,
gcTime: 0,
});
};

export const useGetOtherUserProfile = (nickname: string) => {
export const useGetProfile = (nickname: string) => {
return useQuery({
queryKey: ['profile', { nickname }],
queryFn: () => getProfile(nickname),
Expand Down Expand Up @@ -52,3 +38,12 @@ export const useEditProfile = () => {
retry: 0,
});
};

export const useGetBadgeList = (nickname: string) => {
return useQuery<{ badgeImageS3SavedURL: string }[]>({
queryKey: ['badgeList', { nickname }],
queryFn: () => getBadgeList(nickname),
staleTime: 0,
gcTime: 0,
});
};
33 changes: 33 additions & 0 deletions src/mocks/badges/[nickname].ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { API_BASE_URL } from '@/constants/env';
import { http, HttpResponse } from 'msw';

export const getBadgeList = http.get(
`${API_BASE_URL}/api/badges/:nickname`,
async () => {
const result = {
status: 'success',
data: {
badges: [
{
badgeImageS3SavedURL: '',
},
{
badgeImageS3SavedURL: '',
},
{
badgeImageS3SavedURL: '',
},
{
badgeImageS3SavedURL: '',
},
{
badgeImageS3SavedURL: '',
},
],
},
message: '뱃지가 조회되었습니다.',
};

return HttpResponse.json(result, { status: 200 });
},
);
3 changes: 3 additions & 0 deletions src/mocks/badges/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { getBadgeList } from './[nickname]';

export const badgeHandlers = [getBadgeList];
2 changes: 2 additions & 0 deletions src/mocks/handlers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { authHandlers } from './auth';
import { badgeHandlers } from './badges';
import { boardCafeHandlers } from './board-cafes';
import { chatHandlers } from './chat';
import { articleHandlers } from './gather-articles';
Expand All @@ -20,4 +21,5 @@ export const handlers = [
...chatHandlers,
...notificationHandlers,
...profileHandlers,
...badgeHandlers,
];
6 changes: 6 additions & 0 deletions src/services/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ export const getProfile = (nickname: string) =>
/** 프로필 수정 API */
export const editProfile = (editProfileDTO: FormData) =>
api.put(`/api/profiles`, editProfileDTO);

/** 뱃지 목록 조회 */
export const getBadgeList = (nickname: string) =>
api
.get(`/api/badges/${nickname}`)
.then((response) => response.data.data.badges);

0 comments on commit e0a8dd0

Please sign in to comment.