Skip to content

Commit

Permalink
FEAT: ✨ 카테고리 이동 후 restore
Browse files Browse the repository at this point in the history
  • Loading branch information
hoongding committed Sep 29, 2024
1 parent 5d99f54 commit 1590401
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 93 deletions.
2 changes: 1 addition & 1 deletion src/apis/bookmark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ export const useBookmarkMoveCategory = () => {
{
bookMarkMovingDtos: {
originCategoryId: number | null;
movingCategoryId: number;
movingCategoryId: number | null;
bookMarkId: number;
}[];
}
Expand Down
132 changes: 132 additions & 0 deletions src/components/FilterBox/EditMode/hooks/useHandleMoveCategory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { usePathname, useRouter } from 'next/navigation';

import { useBookmarkMoveCategory } from '@/apis/bookmark';
import useEditModeStore, { MovingBookmarkDto } from '@/stores/editModeStore';
import useToastStore from '@/stores/toastStore';

// 실제 API 함수 경로로 수정

const useHandleMoveCategory = () => {
const router = useRouter();
const pathname = usePathname();

const { addToast } = useToastStore();

const { mutate: moveCategory } = useBookmarkMoveCategory();
// Zustand 스토어에서 필요한 상태와 함수 가져오기
const {
selectedBookmarks,
setMovedBookmarks,
resetSelectedBookmarks,
setEditMode,
setIsOpenCategoryOptions,
} = useEditModeStore((state) => ({
selectedBookmarks: state.selectedBookmarks,
setMovedBookmarks: state.setMovedBookmarks,
resetSelectedBookmarks: state.resetSelectedBookmarks,
setEditMode: state.setEditMode,
setIsOpenCategoryOptions: state.setIsOpenCategoryOptions,
}));

// DTO 생성 함수
const createMovingBookmarksDtos = (
bookmarks: typeof selectedBookmarks,
categoryId: number,
): MovingBookmarkDto[] => {
return bookmarks.map((bookmark) => ({
originCategoryId: bookmark.categoryDtos.length ? bookmark.categoryDtos[0].categoryId : null,
bookMarkId: bookmark.bookmarkId,
movingCategoryId: categoryId,
}));
};

// 복구 DTO 생성 함수
const createReverseDtos = (dtos: MovingBookmarkDto[]): MovingBookmarkDto[] => {
return dtos.map((dto) => ({
originCategoryId: dto.movingCategoryId,
bookMarkId: dto.bookMarkId,
movingCategoryId: dto.originCategoryId,
}));
};

// 복구 핸들러 함수
const handleRestore = (reverseDtos: MovingBookmarkDto[]) => {
moveCategory(
{
bookMarkMovingDtos: reverseDtos,
},
{
onSuccess: () => {
addToast({
message: '북마크 이동을 복구했어요.',
type: 'default',
});

setMovedBookmarks(reverseDtos.map((dto) => dto.bookMarkId));

if (reverseDtos.length > 0) {
router.replace(`${pathname}/?tab=${reverseDtos[0].movingCategoryId}`);
}
},
onError: () => {
addToast({
message: '복구에 실패했어요.',
type: 'error',
});
},
},
);
};

// 성공 시 처리 함수
const handleMoveSuccess = (movingBookmarksDtos: MovingBookmarkDto[]) => {
setMovedBookmarks(selectedBookmarks.map((bookmark) => bookmark.bookmarkId));

addToast({
message: '북마크를 이동했어요.',
type: 'default',
clickText: '복구하기',
onClick: () => {
const reverseDtos = createReverseDtos(movingBookmarksDtos);

handleRestore(reverseDtos);
},
});

resetSelectedBookmarks();
setEditMode(false);

if (movingBookmarksDtos.length > 0) {
router.replace(`${pathname}/?tab=${movingBookmarksDtos[0].movingCategoryId}`);
}
};

// 에러 핸들러 함수
const handleMoveError = () => {
addToast({
message: '북마크 이동에 실패했어요.',
type: 'error',
});
};

// 메인 이동 핸들러 함수
const handleMoveCategory = (categoryId: number) => {
const movingBookmarksDtos = createMovingBookmarksDtos(selectedBookmarks, categoryId);

moveCategory(
{
bookMarkMovingDtos: movingBookmarksDtos,
},
{
onSuccess: () => handleMoveSuccess(movingBookmarksDtos),
onError: handleMoveError,
},
);

setIsOpenCategoryOptions(false);
};

return { handleMoveCategory };
};

export default useHandleMoveCategory;
57 changes: 5 additions & 52 deletions src/components/FilterBox/EditMode/index.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import { usePathname, useRouter } from 'next/navigation';
import { useRef, useState } from 'react';

import {
fetchBookmarkReadCount,
useBookmarkDelete,
useBookmarkMoveCategory,
useBookmarkRestore,
} from '@/apis/bookmark';
import { fetchBookmarkReadCount, useBookmarkDelete, useBookmarkRestore } from '@/apis/bookmark';
import { useCategoryList } from '@/apis/category';
import { Button } from '@/components/common/Button';
import Divider from '@/components/common/Divider';
Expand All @@ -18,32 +12,29 @@ import { cn } from '@/lib/utils';
import useEditModeStore from '@/stores/editModeStore';
import useToastStore from '@/stores/toastStore';

import useHandleMoveCategory from './hooks/useHandleMoveCategory';

interface Props {
handleEditMode: () => void;
}

const EditMode = ({ handleEditMode }: Props) => {
const router = useRouter();
const pathname = usePathname();

const {
selectedBookmarks,
getSelectedBookmarksLength,
resetEditMode,
resetSelectedBookmarks,
setEditMode,
setDeletedBookmarks,
setMovedBookmarks,
movedBookmarks,
deletedBookmarks,
} = useEditModeStore();
const { addToast } = useToastStore();

const { data: categoryData } = useCategoryList(null);
const { mutate: moveCategory } = useBookmarkMoveCategory();

const { mutate: mutateBookmarkDelete } = useBookmarkDelete();
const { mutate: mutateBookmarkRestore } = useBookmarkRestore();

const { handleMoveCategory } = useHandleMoveCategory();
const [isOpenCategoryOptions, setIsOpenCategoryOptions] = useState<boolean>(false);
const moveDivRef = useRef<HTMLDivElement>(null);

Expand All @@ -69,44 +60,6 @@ const EditMode = ({ handleEditMode }: Props) => {
});
};

const handleMoveCategory = (categoryId: number) => {
const movingBookmarksDtos = selectedBookmarks.map((bookmark) => {
return {
originCategoryId: bookmark.categoryDtos.length ? bookmark.categoryDtos[0].categoryId : null,
bookMarkId: bookmark.bookmarkId,
movingCategoryId: categoryId,
};
});

moveCategory(
{
bookMarkMovingDtos: movingBookmarksDtos,
},
{
onSuccess: () => {
setMovedBookmarks(selectedBookmarks.map((bookmark) => bookmark.bookmarkId));
addToast({
message: '북마크를 이동했어요.',
type: 'default',
clickText: '복구하기',
onClick: () => {
handleRestoreBookmarks({
targetIds: selectedBookmarks.map((bookmark) => bookmark.bookmarkId),
});
},
});

resetSelectedBookmarks();
setEditMode(false);

router.replace(`${pathname}/?tab=${categoryId}`);
},
},
);

setIsOpenCategoryOptions(false);
};

const handleDeleteBookmarks = () => {
const bookmarkIds = [...selectedBookmarks.map((bookmark) => bookmark.bookmarkId)];

Expand Down
84 changes: 44 additions & 40 deletions src/stores/editModeStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,90 +5,94 @@ export type CategoryDtoType = {
categoryName: string;
};

type Bookmark = {
bookmarkId: number;
url: string;
categoryDtos: CategoryDtoType[];
};

export type MovingBookmarkDto = {
originCategoryId: number | null;
bookMarkId: number;
movingCategoryId: number | null;
};

type Store = {
isEditMode: boolean;
setEditMode: (isEditMode: boolean) => void;
selectedBookmarks: Array<{
bookmarkId: number;
url: string;
categoryDtos: CategoryDtoType[];
}>;
selectedBookmarks: Bookmark[];
movedBookmarks: number[];
deletedBookmarks: number[];
isSelectedBookmark: (bookmarkId: number) => boolean;
setSelectedBookmarks: ({
bookmarkId,
url,
categoryDtos,
}: {
bookmarkId: number;
url: string;
categoryDtos: CategoryDtoType[];
}) => void;
setSelectedBookmarks: (bookmark: Bookmark) => void;
resetEditMode: () => void;
resetSelectedBookmarks: () => void;
getSelectedBookmarksLength: () => number;
setMovedBookmarks: (bookmarkIds: number[]) => void;
setDeletedBookmarks: (bookmarkIds: number[]) => void;
isOpenCategoryOptions: boolean;
setIsOpenCategoryOptions: (isOpen: boolean) => void;
};

const useEditModeStore = create<Store>((set, get) => ({
isEditMode: false,
selectedBookmarks: [],
movedBookmarks: [],
deletedBookmarks: [],
isOpenCategoryOptions: false,

setEditMode: (isEditMode: boolean) => {
set(() => ({
isEditMode,
}));
set({ isEditMode });
},

// @desc: 선택된 북마크 추가
setSelectedBookmarks: ({ bookmarkId, url, categoryDtos }) => {
const isAlreadyExist = get().selectedBookmarks.some((item) => item.bookmarkId === bookmarkId);
setSelectedBookmarks: (bookmark: Bookmark) => {
const isAlreadyExist = get().selectedBookmarks.some(
(item) => item.bookmarkId === bookmark.bookmarkId,
);

set((state) => ({
// @desc: toggle 되게끔
set({
selectedBookmarks: isAlreadyExist
? state.selectedBookmarks.filter((item) => item.bookmarkId !== bookmarkId)
: [...state.selectedBookmarks, { bookmarkId, url, categoryDtos }],
}));
? get().selectedBookmarks.filter((item) => item.bookmarkId !== bookmark.bookmarkId)
: [...get().selectedBookmarks, bookmark],
});
},

setMovedBookmarks: (bookmarkIds: number[]) => {
set((state) => ({
movedBookmarks: [...state.movedBookmarks, ...bookmarkIds],
}));
set({
movedBookmarks: [...get().movedBookmarks, ...bookmarkIds],
});
},

setDeletedBookmarks: (bookmarkIds: number[]) => {
set((state) => ({
deletedBookmarks: [...state.deletedBookmarks, ...bookmarkIds],
}));
set({
deletedBookmarks: [...get().deletedBookmarks, ...bookmarkIds],
});
},

isSelectedBookmark: (bookmarkId: number) => {
return get().selectedBookmarks.some((item) => item.bookmarkId === bookmarkId);
},

// @desc: 선택된 북마크 개수 반환
getSelectedBookmarksLength: () => {
return get().selectedBookmarks.length;
},

resetSelectedBookmarks: () =>
set(() => ({
selectedBookmarks: [],
})),
resetSelectedBookmarks: () => {
set({ selectedBookmarks: [] });
},

// @desc: edit mode store 초기화
resetEditMode: () =>
set(() => ({
resetEditMode: () => {
set({
selectedBookmarks: [],
movedBookmarks: [],
deletedBookmarks: [],
})),
isEditMode: false,
});
},

setIsOpenCategoryOptions: (isOpen: boolean) => {
set({ isOpenCategoryOptions: isOpen });
},
}));

export default useEditModeStore;

0 comments on commit 1590401

Please sign in to comment.