diff --git a/frontend/src/components/PostForm/CategoryWrapper/index.tsx b/frontend/src/components/PostForm/CategoryWrapper/index.tsx index 6362d8714..d744de40b 100644 --- a/frontend/src/components/PostForm/CategoryWrapper/index.tsx +++ b/frontend/src/components/PostForm/CategoryWrapper/index.tsx @@ -6,6 +6,8 @@ import { useCategoryList } from '@hooks/query/category/useCategoryList'; import MultiSelect from '@components/common/MultiSelect'; import { Option } from '@components/common/MultiSelect/types'; +import { POST_CATEGORY } from '@constants/policy'; + import { changeCategoryToOption } from '@utils/post/changeCategoryToOption'; interface CategoryWrapperProps { @@ -30,6 +32,7 @@ export default function CategoryWrapper({ multiSelectHook }: CategoryWrapperProp handleOptionAdd={handleOptionAdd} handleOptionDelete={handleOptionDelete} placeholder="카테고리를 선택해주세요." + maxOptionCount={POST_CATEGORY.MAX_AMOUNT} /> ); } diff --git a/frontend/src/components/PostForm/index.tsx b/frontend/src/components/PostForm/index.tsx index 6cc60a01a..17a153e45 100644 --- a/frontend/src/components/PostForm/index.tsx +++ b/frontend/src/components/PostForm/index.tsx @@ -68,11 +68,7 @@ export default function PostForm({ data, mutate, isSubmitting }: PostFormProps) const categorySelectHook = useMultiSelect(categoryIds ?? [], POST_CATEGORY.MAX_AMOUNT); const { text: writingTitle, handleTextChange: handleTitleChange } = useText(title ?? ''); - const { - text: writingContent, - handleTextChange: handleContentChange, - addText: addContent, - } = useText(content ?? ''); + const { text: writingContent, handleTextChange: handleContentChange } = useText(content ?? ''); const writingOptionHook = useWritingOption( serverVoteInfo?.options.map(option => ({ ...option, diff --git a/frontend/src/components/common/MultiSelect/index.tsx b/frontend/src/components/common/MultiSelect/index.tsx index bf47f35d4..19150808f 100644 --- a/frontend/src/components/common/MultiSelect/index.tsx +++ b/frontend/src/components/common/MultiSelect/index.tsx @@ -15,6 +15,7 @@ interface MultiSelectProps { handleOptionAdd: (newItem: Option) => void; handleOptionDelete: (optionId: number) => void; placeholder?: string; + maxOptionCount?: number; } export default function MultiSelect({ @@ -22,6 +23,7 @@ export default function MultiSelect({ optionList, handleOptionAdd, handleOptionDelete, + maxOptionCount, placeholder = '여러 개의 옵션을 선택해주세요', }: MultiSelectProps) { const [isOpen, setIsOpen] = useState(false); @@ -35,6 +37,15 @@ export default function MultiSelect({ setIsOpen(!isOpen); }; + const addOption = ({ id, name }: Option) => { + handleOptionAdd({ id, name }); + + // selectedOptionList.length 는 추가되기 이전의 값 + if (maxOptionCount && selectedOptionList.length + 1 >= maxOptionCount) { + setIsOpen(false); + } + }; + const handleOutsideClick = (event: MouseEvent) => { if (wrapperRef.current && !wrapperRef.current.contains(event.target as Node)) { setIsOpen(false); @@ -90,7 +101,7 @@ export default function MultiSelect({ aria-label={`클릭시 ${name} 추가`} onClick={e => { e.stopPropagation(); - handleOptionAdd({ id, name }); + addOption({ id, name }); }} > {name} diff --git a/frontend/src/hooks/useMultiSelect.ts b/frontend/src/hooks/useMultiSelect.ts index c032641a5..3151c0c0f 100644 --- a/frontend/src/hooks/useMultiSelect.ts +++ b/frontend/src/hooks/useMultiSelect.ts @@ -1,15 +1,19 @@ -import { useState } from 'react'; +import { useContext, useState } from 'react'; import type { Option } from '@components/common/MultiSelect/types'; +import { ToastContext } from './context/toast'; + export const useMultiSelect = (initialSelectedOptionList: Option[], optionCountLimit?: number) => { const [selectedOptionList, setSelectedOptionList] = useState(initialSelectedOptionList); + const { addMessage } = useContext(ToastContext); const handleOptionAdd = (newItem: Option) => { if (optionCountLimit && optionCountLimit === selectedOptionList.length) { - alert(`${optionCountLimit}개까지 선택 가능합니다!`); + addMessage(`${optionCountLimit}개까지 선택 가능합니다!`); return; } + setSelectedOptionList([...selectedOptionList, newItem]); };