Skip to content

Commit

Permalink
Merge pull request #52 from teamViNO/feature-060
Browse files Browse the repository at this point in the history
feature-060: 카테고리 페이지 > 영상 삭제, 카테고리 추가 API 연동
  • Loading branch information
whistleJs authored Feb 9, 2024
2 parents f3cd503 + 02b136f commit 1758620
Show file tree
Hide file tree
Showing 13 changed files with 184 additions and 119 deletions.
18 changes: 5 additions & 13 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { useRecoilValue } from 'recoil';
import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom';
import { ThemeProvider } from 'styled-components';

Expand Down Expand Up @@ -30,22 +30,14 @@ import { ToastList } from './components/common';
// Store
import { userTokenState } from './stores/user';
import { useEffect } from 'react';
import { categoryState } from './stores/category';
import { getCategories } from './apis/category';
import handleCategory from './utils/handleCategory';
import useUpdateCategories from './hooks/useUpdateCategories';

const App = () => {
const setCategories = useSetRecoilState(categoryState);
const userToken = useRecoilValue(userTokenState);
const { initializeCategory } = handleCategory();
const { updateCategories } = useUpdateCategories();
useEffect(() => {
userToken &&
getCategories()
.then((res) => {
setCategories(initializeCategory(res));
})
.catch((err) => console.log(err));
}, [userToken]);
userToken && updateCategories();
}, [updateCategories, userToken]);

return (
<ThemeProvider theme={theme}>
Expand Down
43 changes: 32 additions & 11 deletions src/apis/category.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { APIResponse } from '@/models/config/axios';
import axiosInstance from './config/instance';
import { ICreateCategoryResponse } from '@/models/category';

// 모든 카테고리 가져오는 API
export const getCategories = async () => {
const response = await axiosInstance.get('/category');
return response.data.result;
return response.data;
};

// 카테고리 이동1 API
Expand All @@ -14,13 +16,13 @@ export const putSubToOtherTop = async (
const response = await axiosInstance.put(
`/category/${categoryId}/${topCategoryId}`,
);
return response.data.result;
return response.data;
};

// 카테고리 이동2 API
export const putSubToTop = async (categoryId: number) => {
const response = await axiosInstance.put(`/category/up/${categoryId}`);
return response.data.result;
return response.data;
};

// 카테고리 이동3 API
Expand All @@ -31,17 +33,36 @@ export const putTopToOtherTop = async (
const response = await axiosInstance.put(
`/category/down/${categoryId}/${topCategoryId}`,
);
return response.data.result;
return response.data;
};

// 상위 카테고리 추가 API
export const postTopCategroy = async () => {
const response = await axiosInstance.post('/category');
return response.data.result;
export const postTopCategroy = async (
name: string,
): Promise<APIResponse<ICreateCategoryResponse>> => {
const response = await axiosInstance.post('/category', { name });
return response.data;
};

// 상위 카테고리 추가 API
export const postSubCategroy = async (topCategoryId: number) => {
const response = await axiosInstance.post(`/category/${topCategoryId}`);
return response.data.result;
// 하위 카테고리 추가 API
export const postSubCategroy = async (
name: string,
topCategoryId: number,
): Promise<APIResponse<ICreateCategoryResponse>> => {
const response = await axiosInstance.post(`/category/${topCategoryId}`, {
name,
});
return response.data;
};

// 카테고리 삭제 API
export const deleteCategory = async (category_id: number) => {
const response = await axiosInstance.delete(`/category/${category_id}`);
return response.data;
};

// 카테고리 이름 수정 API
export const updateCategoryName = async (name: string, categoryId: number) => {
const response = await axiosInstance.put(`/category/${categoryId}`, { name });
return response.data;
};
24 changes: 21 additions & 3 deletions src/components/layout/sideBar/SubCategory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface ISubCategoryProps {
setIsDeleteModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
grabedCategory: React.MutableRefObject<ISubFolderProps | undefined>;
putCategoryFolder: () => void;
setCategoryId: React.Dispatch<React.SetStateAction<number | null>>;
}

const SubCategory = ({
Expand All @@ -25,14 +26,26 @@ const SubCategory = ({
setIsDeleteModalOpen,
grabedCategory,
putCategoryFolder,
setCategoryId,
}: ISubCategoryProps) => {
const [subFolderOptionModalOpen, setSubFolderOptionModalOpen] =
useState(false);
const [isEditing, setIsEditing] = useState(false);
const [edit, setEdit] = useState(name);
const [beforeEdit, setBeforeEdit] = useState(edit);
const { editText, finishEdit } = handleEdit();
const [editNameRef] = useOutsideClick<HTMLDivElement>(() =>
setIsEditing(false),
finishEdit(
edit,
setEdit,
beforeEdit,
setIsEditing,
nameRegex,
setNameRegex,
categoryId,
),
);
const [nameRegex, setNameRegex] = useState(true);

const [subFolderOptionModalRef] = useOutsideClick<HTMLDivElement>(() =>
setSubFolderOptionModalOpen(false),
Expand All @@ -44,7 +57,9 @@ const SubCategory = ({
e.stopPropagation();
if (option === '수정') {
setIsEditing(true);
setBeforeEdit(edit);
} else if (option === '삭제') {
setCategoryId(categoryId);
setIsDeleteModalOpen(true);
}
setSubFolderOptionModalOpen(false);
Expand All @@ -57,7 +72,7 @@ const SubCategory = ({
};

const handleInput = (e: React.ChangeEvent<HTMLInputElement>) =>
handleEdit(e, setEdit);
editText(e, setEdit, setNameRegex);

const handleDragStart = () =>
(grabedCategory.current = {
Expand All @@ -76,7 +91,10 @@ const SubCategory = ({
onDragEnd={putCategoryFolder}
>
{isEditing ? (
<SubCategoryStyles.EditNameInputWrap ref={editNameRef}>
<SubCategoryStyles.EditNameInputWrap
ref={editNameRef}
className={`${(!nameRegex || !edit.length) && 'warning'}`}
>
<SubCategoryStyles.EditNameInput
value={edit}
onChange={handleInput}
Expand Down
34 changes: 18 additions & 16 deletions src/components/layout/sideBar/TopCategory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ interface ITopCategoryProps {
dropedCategory: React.MutableRefObject<number | undefined>;
setIsSubCategoryModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
setIsDeleteModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
setCategoryId: React.Dispatch<React.SetStateAction<number | null>>;
putCategoryFolder: () => void;
}

Expand All @@ -36,6 +37,7 @@ const TopCategory = ({
setIsSubCategoryModalOpen,
setIsDeleteModalOpen,
putCategoryFolder,
setCategoryId,
}: ITopCategoryProps) => {
const [folderOptionModalOpen, setFolderOptionModalOpen] = useState(false);
const [folderOptionModalRef] = useOutsideClick<HTMLDivElement>(() =>
Expand All @@ -45,18 +47,22 @@ const TopCategory = ({
const [isEditing, setIsEditing] = useState(false);
const [edit, setEdit] = useState(name);
const [beforeEdit, setBeforeEdit] = useState(edit);
const { editText, finishEdit } = handleEdit();

const categoryNameRegex = /^[a-zA-Z0-9가-힣\s]*$/;
const [nameRegex, setNameRegex] = useState(true);
const options = ['추가', '수정', '삭제', '이동'];

const finishEdit = () => {
if (!edit.length) {
setEdit(beforeEdit);
}
setIsEditing(false);
};
const [editNameRef] = useOutsideClick<HTMLDivElement>(finishEdit);
const [editNameRef] = useOutsideClick<HTMLDivElement>(() =>
finishEdit(
edit,
setEdit,
beforeEdit,
setIsEditing,
nameRegex,
setNameRegex,
categoryId,
),
);

const handleOptionClick = (e: React.MouseEvent, option: string) => {
e.stopPropagation();
Expand All @@ -66,6 +72,7 @@ const TopCategory = ({
setIsEditing(true);
setBeforeEdit(edit);
} else if (option === '삭제') {
setCategoryId(categoryId);
setIsDeleteModalOpen(true);
}
setFolderOptionModalOpen(false);
Expand All @@ -76,14 +83,8 @@ const TopCategory = ({
setFolderOptionModalOpen(true);
};

const handleInput = (e: React.ChangeEvent<HTMLInputElement>) => {
if (!categoryNameRegex.test(e.target.value)) {
setNameRegex(false);
return;
}
setNameRegex(true);
handleEdit(e, setEdit);
};
const handleInput = (e: React.ChangeEvent<HTMLInputElement>) =>
editText(e, setEdit, setNameRegex);
const handleDragStart = () =>
(grabedCategory.current = {
categoryId: categoryId,
Expand Down Expand Up @@ -176,6 +177,7 @@ const TopCategory = ({
setIsDeleteModalOpen={setIsDeleteModalOpen}
grabedCategory={grabedCategory}
putCategoryFolder={putCategoryFolder}
setCategoryId={setCategoryId}
key={`${subFolder.name}-${subFolder.categoryId}`}
/>
))}
Expand Down
35 changes: 17 additions & 18 deletions src/components/layout/sideBar/UserMode.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
import LookSvg from '@/assets/icons/look.svg?react';
import * as UserModeStyle from '@/styles/layout/sideBar/UserMode.style';
import { useLocation } from 'react-router-dom';
import { useRecoilState, useRecoilValue } from 'recoil';
import { useLocation, useNavigate } from 'react-router-dom';
import { useRecoilValue } from 'recoil';
import { topCategoryModalState } from '@/stores/modal';
import AddCategoryModal from '@/components/modals/AddCategoryModal';
import SuccessAddCategoryModal from '@/components/modals/SuccessAddCategoryModal';
import { useRef, useState } from 'react';
import TopCategory from './TopCategory';
import DeleteCategory from './DeleteCategory';
import handleCategory from '@/utils/handleCategory';
import { categoryState } from '@/stores/category';
import { IFolderProps, ISubFolderProps } from 'types/category';
import useMoveCategory from '@/hooks/useMoveCategory';
import { deleteCategory } from '@/apis/category';
import useUpdateCategories from '@/hooks/useUpdateCategories';

const UserMode = () => {
const isTopCategoryModalOpen = useRecoilValue(topCategoryModalState);
const [isSuccessAddCategoryModalOpen, setIsSuccessAddCategoryModalOpen] =
useState(false);
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
const [isSubAdded, setIsSubAdded] = useState(false);
const [categoryName, setCategoryName] = useState('');
const [categories, setCategories] = useRecoilState(categoryState);
const [categoryId, setCategoryId] = useState<number | null>(null);
const categories = useRecoilValue(categoryState);
const [isSubCategoryModalOpen, setIsSubCategoryModalOpen] = useState(false);
const grabedCategory = useRef<ISubFolderProps | undefined>(undefined);
const dropedCategory = useRef<number | undefined>(undefined);
const { deleteSubCategory } = handleCategory();
const navigate = useNavigate();

const { updateCategories } = useUpdateCategories();

const { subToOtherTop, subToTop, topToOtherTop } = useMoveCategory();

Expand All @@ -34,14 +37,11 @@ const UserMode = () => {
const topId = Number(href[0]);
const subId = Number(href[1]);

const handleDeleteCategory = () => {
if (!isNaN(subId)) {
setCategories([...deleteSubCategory(categories, topId, subId)]);
} else {
const newData = categories.filter(
(myFolder) => myFolder.categoryId !== topId,
);
setCategories([...newData]);
const handleDeleteCategory = async () => {
const response = await deleteCategory(categoryId!);
if (response.isSuccess) {
updateCategories();
navigate('/category/recent');
}
setIsDeleteModalOpen(false);
};
Expand Down Expand Up @@ -85,6 +85,7 @@ const UserMode = () => {
setIsSubCategoryModalOpen={setIsSubCategoryModalOpen}
setIsDeleteModalOpen={setIsDeleteModalOpen}
putCategoryFolder={putCategoryFolder}
setCategoryId={setCategoryId}
key={`${category.name}-${category.categoryId}`}
/>
))}
Expand All @@ -96,8 +97,8 @@ const UserMode = () => {
categoryName={categoryName}
setCategoryName={setCategoryName}
setIsSuccessAddCategoryModalOpen={setIsSuccessAddCategoryModalOpen}
setIsSubAdded={setIsSubAdded}
topCategoryId={topId}
setCategoryId={setCategoryId}
/>
)}
{isDeleteModalOpen && (
Expand All @@ -111,9 +112,7 @@ const UserMode = () => {
categoryName={categoryName}
setCategoryName={setCategoryName}
setIsSuccessAddCategoryModalOpen={setIsSuccessAddCategoryModalOpen}
isSubAdded={isSubAdded}
setIsSubAdded={setIsSubAdded}
topId={topId}
categoryId={categoryId}
/>
)}
</>
Expand Down
Loading

0 comments on commit 1758620

Please sign in to comment.