Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature-063: 카테고리 드롭다운 리팩토링 #62

Merged
merged 1 commit into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,24 +1,33 @@
import { Dropdown } from '@/styles/SummaryPage';

import DropdownItem from './DropdownItem';
import { useRecoilValue } from 'recoil';
import { categoryState } from '@/stores/category';
import React from 'react';
import { ISelectedCategoryProps } from 'types/category';

// 임시 타입
interface Item {
id: number;
text: string;
items?: Item[];
interface ICategoryDropdownProp {
setSelectedCategory: React.Dispatch<
React.SetStateAction<ISelectedCategoryProps>
>;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
}

type Props = {
categoryList: Item[];
};

const CategoryDropdown = ({ categoryList }: Props) => {
const CategoryDropdown = ({
setSelectedCategory,
setIsOpen,
}: ICategoryDropdownProp) => {
const categories = useRecoilValue(categoryState);
return (
<Dropdown onClick={(e) => e.stopPropagation()}>
<ul>
{categoryList.map((category) => (
<DropdownItem key={category.id} category={category} />
{categories.map((category) => (
<DropdownItem
key={category.categoryId}
category={category}
setSelectedCategory={setSelectedCategory}
setIsOpen={setIsOpen}
/>
))}
</ul>
</Dropdown>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,81 @@
import { useState } from 'react';

import DownIcon from '@/assets/icons/down.svg?react';
import { IFolderProps, ISelectedCategoryProps } from 'types/category';
import { DropdownTopCategoryName } from '@/styles/SummaryPage';

// 임시 타입
interface Item {
id: number;
text: string;
items?: Item[];
interface ICategoryDropdownProp {
category: IFolderProps;
setSelectedCategory: React.Dispatch<
React.SetStateAction<ISelectedCategoryProps>
>;
setIsOpen: React.Dispatch<React.SetStateAction<boolean>>;
}

type Props = {
category: Item;
};
interface IItemClickProps {
name: string;
categoryId: number;
}

const DropdownItem = ({ category }: Props) => {
const DropdownItem = ({
category,
setSelectedCategory,
setIsOpen,
}: ICategoryDropdownProp) => {
const [isShow, setIsShow] = useState(false);

const dynamicStyles = {
icon: {
transform: isShow ? 'rotateZ(180deg)' : 'rotateZ(0deg)',
},
subCategory: {
height: isShow ? (category.items?.length || 0) * 46 : 0,
height: isShow ? (category.subFolders.length || 0) * 46 : 0,
},
};

const handleItemClick = async (id: number) => {
const handleItemClick = async ({ name, categoryId }: IItemClickProps) => {
setSelectedCategory({
name,
categoryId,
});
// API 요청
console.log(id);
console.log('API 요청');
setIsOpen(false);
};

return (
<>
<li onClick={() => setIsShow(!isShow)}>
<DownIcon width={18} height={18} style={dynamicStyles.icon} />

{category.text}
<li>
<DownIcon
width={18}
height={18}
style={dynamicStyles.icon}
onClick={() => setIsShow(!isShow)}
/>
<DropdownTopCategoryName
onClick={() =>
handleItemClick({
name: category.name,
categoryId: category.categoryId,
})
}
>
{category.name}
</DropdownTopCategoryName>
</li>

<ul style={dynamicStyles.subCategory}>
{category.items?.map((subCategory) => (
{category.subFolders.map((subFolder) => (
<li
key={subCategory.id}
onClick={() => handleItemClick(subCategory.id)}
key={subFolder.categoryId}
onClick={() =>
handleItemClick({
name: subFolder.name,
categoryId: subFolder.categoryId,
})
}
>
{subCategory.text}
{subFolder.name}
</li>
))}
</ul>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,13 @@ import OpenFileIcon from '@/assets/icons/open-file.svg?react';
import useOutsideClick from '@/hooks/useOutsideClick';

import { CategoryDropdown } from './CategoryDropdown';
import { ISelectedCategoryProps } from 'types/category';

const CategorySelectBox = () => {
const categoryList = [
{
id: 1,
text: '기획',
items: [
{ id: 2, text: '마케팅' },
{ id: 3, text: '트렌드' },
{ id: 4, text: '기업' },
{ id: 5, text: '용어' },
],
},
{
id: 6,
text: '디자인',
items: [
{ id: 7, text: 'AAA' },
{ id: 8, text: 'BBB' },
{ id: 9, text: 'CCC' },
{ id: 10, text: 'DDD' },
],
},
];

const [isLogin] = useState(true);
const [isOpen, setIsOpen] = useState(false);
const [selectedCategory, setSelectedCategory] =
useState<ISelectedCategoryProps>({ name: '', categoryId: 0 });

// 다른 영역 클릭 시 dropdown 안보여지게 하기
const [ref] = useOutsideClick<HTMLDivElement>(() => {
Expand All @@ -44,24 +24,34 @@ const CategorySelectBox = () => {

setIsOpen(!isOpen);
};

return (
<div ref={ref} style={{ display: 'flex', gap: 8 }} onClick={handleBoxClick}>
<div style={{ position: 'relative', flex: '1 1 auto' }}>
<div className="select-box">
<span>
{isLogin
? '어떤 카테고리에 넣을까요?'
? selectedCategory.name
? selectedCategory.name
: '어떤 카테고리에 넣을까요?'
: '로그인하고 요약한 영상을 아카이빙해요!'}
</span>

<DownIcon width={18} height={18} />
</div>

{isOpen && <CategoryDropdown categoryList={categoryList} />}
{isOpen && (
<CategoryDropdown
setSelectedCategory={setSelectedCategory}
setIsOpen={setIsOpen}
/>
)}
</div>

<span className={`icon-button ${!isLogin && 'disabled'}`}>
<span
className={`icon-button ${!isLogin && 'disabled'} ${
selectedCategory.name ? 'selected' : 'not-selected'
}`}
>
<OpenFileIcon width={28} height={28} />
</span>
</div>
Expand Down
17 changes: 16 additions & 1 deletion src/styles/SummaryPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,16 @@ export const DetailBox = styled.div`
width: 40px;
height: 40px;
border-radius: 8px;
background-color: ${(props) => props.theme.color.gray200};
cursor: pointer;

&.selected {
background-color: ${(props) => props.theme.color.green400};
}

&.not-selected {
background-color: ${(props) => props.theme.color.gray200};
}

&.disabled svg {
& path:nth-of-type(1) {
fill: ${(props) => props.theme.color.gray300};
Expand Down Expand Up @@ -489,3 +496,11 @@ export const ModalContainer = styled(BlurBackground)`
}
}
`;

export const DropdownTopCategoryName = styled.span`
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: center;
`;
5 changes: 5 additions & 0 deletions types/category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@ export interface IFolderProps {
topCategoryId: null;
subFolders: ISubFolderProps[];
}

export interface ISelectedCategoryProps {
name: string;
categoryId: number;
}
Loading