Skip to content
Merged
13 changes: 10 additions & 3 deletions src/components/Header/ReviewMemoHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import DeleteWellItem from '@/features/Well/components/DeleteWellItem';
import TabMenu from '@/components/Tab/TabMenu';
import { MEMO_REVIEW_TABS } from '@/constants/tabs';
import HeaderWrapper from '@/components/Wrapper/HeaderWrapper';
import useNavigateStore from '@/store/navigateStore';
import DeleteFeedItem from '@/features/Profile/components/Feed/DeleteFeedItem';

interface Props {
userId: string;
Expand All @@ -18,6 +20,8 @@ interface Props {

function ReviewMemoHeader({ userId, wellId, bookId, category }: Props) {
const rootUserId = useUserId();
const navigateState = useNavigateStore((state) => state.navigateState);
const isFromProfile = navigateState?.from === 'profile' || false;

useScroll({
categoryColor: CATEGORY[category].bg,
Expand All @@ -30,9 +34,12 @@ function ReviewMemoHeader({ userId, wellId, bookId, category }: Props) {
<HeaderWrapper isResponsive>
<div className='flex w-full items-center justify-between'>
<TabMenu tabs={MEMO_REVIEW_TABS} />
{userId === rootUserId && (
<DeleteWellItem wellId={wellId} bookId={bookId} />
)}
{userId === rootUserId &&
(isFromProfile ? (
<DeleteFeedItem />
) : (
<DeleteWellItem wellId={wellId} bookId={bookId} />
))}
</div>
</HeaderWrapper>
</>
Expand Down
14 changes: 14 additions & 0 deletions src/data/ui/bottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -222,4 +222,18 @@ export const sheetData: {
extraButtonText: '취소',
description: () => <>포인트가 충분하면 캐릭터가 보여요</>,
},
delete_profile_feed: {
getTitle: () => (
<>
이 책과 관련된 기록을
<br /> 전부 삭제할까요?
</>
),
type: 'error',
buttonText: '네, 전부 삭제할게요',
extraButtonText: '아니요, 유지할게요',
description: () => (
<>이 책과 관련된 모든 기록이 우물과 프로필에서 지워져요.</>
),
},
};
16 changes: 15 additions & 1 deletion src/features/Profile/api/feed.api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { baseOptions } from '@/api/options';
import { DEFAULT_LIMIT } from '@/constants/api';
import { GetProfileFeed } from '@frolog/frolog-api';
import { GetProfileFeed, DeleteUserBookContent } from '@frolog/frolog-api';
import * as Sentry from '@sentry/nextjs';

const getUserProfileFeed = new GetProfileFeed(baseOptions);
Expand All @@ -24,3 +24,17 @@ export const getProfileFeed = async (id: string, page: number) => {
};
}
};

export const deleteProfileFeedItem = async (id: string, isbn: string) => {
try {
const response = await new DeleteUserBookContent(baseOptions).fetch({
id,
isbn,
});

return response;
} catch (error) {
Sentry.captureException(error);
return null;
}
};
23 changes: 23 additions & 0 deletions src/features/Profile/components/Feed/DeleteFeedItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { bottomSheet } from '@/modules/BottomSheet';
import { MoreDotButton } from 'public/icons';
import React from 'react';
import { useDeleteProfileFeedItem } from '../../hooks/useDeleteProfileFeedItem';

function DeleteFeedItem() {
const { deleteProfileFeedItemMutate } = useDeleteProfileFeedItem();
return (
<button
type='button'
onClick={() => {
bottomSheet.open({
sheetKey: 'delete_profile_feed',
onClick: () => deleteProfileFeedItemMutate(),
});
}}
>
<MoreDotButton />
</button>
);
}

export default DeleteFeedItem;
2 changes: 1 addition & 1 deletion src/features/Profile/components/Feed/FeedItemDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ function FeedItemDetail({ title, count, category, path }: Props) {
<button
type='button'
className={`flex items-center justify-between bg-category-bg-${category} py-[13px] pl-[12px] pr-[4px] text-category-text-${category}`}
onClick={() => navigate(path)}
onClick={() => navigate(path, { from: 'profile' })}
>
<h3 className='text-body-md-bold'>{title}</h3>
<div className='flex items-center'>
Expand Down
6 changes: 5 additions & 1 deletion src/features/Profile/components/Feed/ProfileFeedItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ function ProfileFeedItem({ feedData }: Props) {
width={191}
height={272}
className='flex-[8] cursor-pointer'
onClick={() => navigate(getPath.rootUserMemo(userId!, wellId!, isbn))}
onClick={() =>
navigate(getPath.rootUserMemo(userId!, wellId!, isbn), {
from: 'profile',
})
}
/>
<div className='flex flex-col gap-[1px]'>
<FeedItemDetail
Expand Down
33 changes: 33 additions & 0 deletions src/features/Profile/hooks/useDeleteProfileFeedItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useParams, useRouter } from 'next/navigation';
import { getPath } from '@/utils/getPath';
import { useUserId } from '@/store/sessionStore';
import { toast } from '@/modules/Toast';
import { QUERY_KEY } from '@/constants/query';
import { deleteProfileFeedItem } from '../api/feed.api';

export const useDeleteProfileFeedItem = () => {
const router = useRouter();
const userId = useUserId();
const params = useParams();
const bookId = params.bookId as string;
const queryClient = useQueryClient();

const { mutate: deleteProfileFeedItemMutate } = useMutation({
mutationFn: async () => {
const res = await deleteProfileFeedItem(userId!, bookId);
return res;
},
onSuccess: () => {
router.replace(getPath.profile(userId!));
queryClient.invalidateQueries({
queryKey: [QUERY_KEY.profileFeed, userId],
});
},
onError: () => {
toast.error('다시 시도해주세요.');
},
});

return { deleteProfileFeedItemMutate };
};
7 changes: 6 additions & 1 deletion src/hooks/useCustomRouter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { NAV_ITEM } from '@/constants/nav';
import { NavItemLabel } from '@/types/nav';
import { useRouter, useSearchParams } from 'next/navigation';
import useNavigateStore from '@/store/navigateStore';

/** nav 상태를 붙여주는 커스텀 라우터
* @param defaultNav - 기본으로 적용될 nav key
Expand All @@ -14,6 +15,7 @@ export const useCustomRouter = (
const searchParams = useSearchParams();
const currentNav =
searchParams.get('nav') ?? (defaultNav ? NAV_ITEM[defaultNav].key : '');
const setNavigateState = useNavigateStore((state) => state.setNavigateState);

const generatePath = (path: string) => {
const separator = path.includes('?') ? '&' : '?';
Expand All @@ -25,7 +27,10 @@ export const useCustomRouter = (
}
};

const navigate = (path: string) => router.push(generatePath(path));
const navigate = (path: string, state?: any) => {
router.push(generatePath(path));
setNavigateState(state);
};
const replace = (path: string) => router.replace(generatePath(path));

return { navigate, replace, router };
Expand Down
13 changes: 13 additions & 0 deletions src/store/navigateStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { create } from 'zustand';

interface NavigateStore {
navigateState: any;
setNavigateState: (state: any) => void;
}

const useNavigateStore = create<NavigateStore>((set) => ({
navigateState: null,
setNavigateState: (state) => set({ navigateState: state }),
}));

export default useNavigateStore;