Skip to content

Commit

Permalink
refactor : 아이템 선택 페이지 리펙토링 (#228)
Browse files Browse the repository at this point in the history
* chore : 폴더 경로 수정

* refactor: 편지 작성 폼 분리

* refacotor : 아이템 선택 페이지 리펙토링

* refactor: hook index.ts로 분리

* story : story 오류 수정
  • Loading branch information
HelloWook authored Dec 4, 2024
1 parent 938d15d commit 63ec205
Show file tree
Hide file tree
Showing 24 changed files with 204 additions and 100 deletions.
9 changes: 4 additions & 5 deletions src/components/Common/TextArea/TextArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ export const TextArea = ({ value, setValue, font }: TextAreaProps) => {
const calculatedLinesCount = Math.floor(
textAreaHeight / textAreaLineHeight
);
if (inputValue.length > 500) {
addToast('최대 500자까지 작성 가능합니다.', 'error');
if (calculatedLinesCount > 25) {
addToast('최대 25줄까지 작성이 가능합니다.', 'error');

return;
}

Expand Down Expand Up @@ -66,7 +67,7 @@ export const TextArea = ({ value, setValue, font }: TextAreaProps) => {
const handleResize = () => {
if (textAreaRef.current) {
setLineHeight(
2.2 + (textAreaRef.current.offsetWidth - 281) * 0.002
2.2 + (textAreaRef.current.offsetWidth - 281) * 0.0018
);
}
};
Expand All @@ -76,8 +77,6 @@ export const TextArea = ({ value, setValue, font }: TextAreaProps) => {
return () => window.removeEventListener('resize', handleResize);
}, []);

useEffect(() => {});

return (
<div>
<textarea
Expand Down
57 changes: 57 additions & 0 deletions src/components/CreatLetterPage/LettetInputForm/LettetInputForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Margin } from '@/components/Common/Margin/Margin';
import { TextArea } from '@/components/Common/TextArea/TextArea';
import { SelectSlider } from '@/components/SelectItemPage/SelectSlider/SelectSlider';
import React from 'react';

type LettetProps = {
title: string; // 제목
handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void; // 제목 변경 핸들러
letterContent: string; // 편지 내용
setLetterContent: React.Dispatch<React.SetStateAction<string>>; // 편지 내용 상태 변경 함수
font: string; // 글꼴
letter: string; // 선택된 편지지
setFont: React.Dispatch<React.SetStateAction<string>>; // 글꼴 상태 변경 함수
setLetter: React.Dispatch<React.SetStateAction<string>>; // 편지지 상태 변경 함수
};

export const LettetInputForm = ({
title,
handleChange,
letterContent,
setLetterContent,
font,
letter,
setFont,
setLetter
}: LettetProps) => {
return (
<div className="min-h-screen rounded-t-3xl bg-zinc-300">
<Margin top={20} />
<div className="relative flex flex-col justify-center w-9/12 m-auto py-9">
<input
onChange={handleChange}
value={title}
type="text"
placeholder="제목을 입력해주세요"
className="z-10 w-full bg-transparent border-none focus:border-none focus:outline-none text-wrap"
style={{ fontFamily: font || 'inherit' }}
/>
<img src={'/public/to_line.f4c129e6.svg'} />

<div className="relative z-10">
<TextArea
value={letterContent}
setValue={setLetterContent}
font={font}
/>
</div>
</div>
<SelectSlider
font={font}
letter={letter}
setFont={setFont}
setLetter={setLetter}
/>
</div>
);
};
Empty file.
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import React from 'react';
import { Margin } from '@/components/Common/Margin/Margin';
import { useState } from 'react';
import { SelectSlider } from '../SelectSlier/SelectSlider';
import { useToastStore } from '@/hooks/useToastStore';
import { TextArea } from '@/components/Common/TextArea/TextArea';
import { TopBar } from '@/components/Common/TopBar/TopBar';
import { useNavigate } from 'react-router-dom';
import { useLocalStorage } from '@/hooks/useLocalStorage';
import useAutoSave from '@/hooks/useAutoSave';
import { useAutoSave } from '@/hooks/useAutoSave';
import { LettetInputForm } from '../LettetInputForm/LettetInputForm';

export const PostLetterForm = () => {
export const PostLetterCotainer = () => {
const [title, setTitle] = useState<string>('');
const [letter, setLetter] = useState<string>('편지지_샘플_1');
const [letterContent, setLetterContent] = useState<string>('');
Expand Down Expand Up @@ -55,34 +53,16 @@ export const PostLetterForm = () => {
navigate('/letter/select');
}}
/>
<div className="min-h-screen rounded-t-3xl bg-zinc-300">
<Margin top={20} />
<div className="relative flex flex-col justify-center w-9/12 m-auto py-9">
<input
onChange={handleChange}
value={title}
type="text"
placeholder="제목을 입력해주세요"
className="z-10 w-full bg-transparent border-none focus:border-none focus:outline-none text-wrap"
style={{ fontFamily: font || 'inherit' }}
/>
<img src={'/public/to_line.f4c129e6.svg'} />

<div className="relative z-10">
<TextArea
value={letterContent}
setValue={setLetterContent}
font={font}
/>
</div>
</div>
<SelectSlider
font={font}
letter={letter}
setFont={setFont}
setLetter={setLetter}
/>
</div>
<LettetInputForm
title={title}
handleChange={handleChange}
letterContent={letterContent}
setLetterContent={setLetterContent}
font={font}
letter={letter}
setFont={setFont}
setLetter={setLetter}
/>
</>
);
};
44 changes: 44 additions & 0 deletions src/components/SelectItemPage/ItemGroup/ItemGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import React from 'react';
import { LabelList } from '../LabelList/LabelList';
import { KeywordList } from '../KeywordList/KeywordList';
import { LabelProps } from '@/types/label';

type ItemGroupProps = {
isLabel: boolean;
labels: LabelProps[];
onLabelSelect: (label: number) => void;
selectedLabels: number | null;
keywordProps: {
title: string;
subTitle: string;
keywordGroup: { content: string }[];
};
onKeywordSelect: (keyword: number) => void;
selectedKeywords: number[];
};

export const ItemGroup: React.FC<ItemGroupProps> = ({
isLabel,
labels,
onLabelSelect,
selectedLabels,
keywordProps,
onKeywordSelect,
selectedKeywords
}) => {
return isLabel ? (
<LabelList
labels={labels}
onLabelSelect={onLabelSelect}
selectedLabels={selectedLabels}
/>
) : (
<KeywordList
title={keywordProps.title}
subTitle={keywordProps.subTitle}
keywordGroup={keywordProps.keywordGroup}
onKeywordSelect={onKeywordSelect}
selectedKeywords={selectedKeywords}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export type KeywordListProps = {
title: string;
subTitle: string;
keywordGroup: KeywordProps[];
selectedKeywords: number | null;
selectedKeywords: number[];
onKeywordSelect: (index: number) => void;
};

Expand All @@ -31,7 +31,7 @@ export const KeywordList = ({
>
<KeywordToggleButton
keyword={keyword.content}
isActive={selectedKeywords === idx}
isActive={selectedKeywords.includes(idx)}
/>
</li>
))}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React, { useEffect, useState } from 'react';
import { SelectToggle } from '../SelectToggle/SelectToggle';
import { Margin } from '@/components/Common/Margin/Margin';
import { SliderMenuContainer } from '@/components/Common/SliderMenuContainer/SliderMenuContainer';
import React, { useEffect, useState } from 'react';
import { LabelProps } from '@/types/label';
import { KeywordList } from '../KeywordList/KeywordList';
import { LabelList } from '../LabelList/LabelList';
import { CreateButton } from '../CreateButton/CreateButton';
import { useNavigate } from 'react-router-dom';
import { LabelProps } from '@/types/label';
import { ItemGroup } from '../ItemGroup/ItemGroup';

type SelectItemProps = {
isActive: boolean;
Expand All @@ -15,14 +15,12 @@ type SelectItemProps = {
export const SelectItem = ({ isActive, setIsActive }: SelectItemProps) => {
const [isLabel, setIsLabel] = useState(true);
const [selectedLabels, setSelectedLabels] = useState<number | null>(null);
const [selectedKeywords, setSelectedKeywords] = useState<number | null>(
null
);
const [selectedKeywords, setSelectedKeywords] = useState<number[]>([]);

const navigate = useNavigate();

useEffect(() => {
if (selectedLabels && selectedKeywords) {
if (selectedLabels && selectedKeywords.length > 0) {
setIsActive(true);
} else {
setIsActive(false);
Expand All @@ -34,7 +32,11 @@ export const SelectItem = ({ isActive, setIsActive }: SelectItemProps) => {
};

const handleKeywordSelection = (keyword: number) => {
setSelectedKeywords(keyword);
setSelectedKeywords((prev) =>
prev.includes(keyword)
? prev.filter((k) => k !== keyword)
: [...prev, keyword]
);
};

const testLable: LabelProps[] = [
Expand Down Expand Up @@ -69,6 +71,7 @@ export const SelectItem = ({ isActive, setIsActive }: SelectItemProps) => {
{ content: 'Next.js' }
]
};

return (
<div className="relative">
<SliderMenuContainer
Expand All @@ -87,44 +90,18 @@ export const SelectItem = ({ isActive, setIsActive }: SelectItemProps) => {
}
>
<Margin top={15} />
<div className="relative flex w-full overflow-hidden text-xl align-middle h-[50px] ">
<div
className="absolute bottom-0 w-1/2 h-[2px] transition-transform duration-500 ease-in-out bg-sample-blue"
style={{
transform: `translateX(${isLabel ? '0%' : '100%'})`
}}
></div>
<div
className="flex items-center justify-center flex-1 h-full cursor-pointer"
onClick={() => setIsLabel(true)}
>
<span>라벨</span>
</div>
<div
className="flex items-center justify-center flex-1 h-full cursor-pointer"
onClick={() => setIsLabel(false)}
>
<span>키워드</span>
</div>
</div>
<SelectToggle isLabel={isLabel} setIsLabel={setIsLabel} />

<ItemGroup
isLabel={isLabel}
labels={testLable}
onLabelSelect={handleLabelSelection}
selectedLabels={selectedLabels}
keywordProps={testKeywordListProps}
onKeywordSelect={handleKeywordSelection}
selectedKeywords={selectedKeywords}
/>

{isLabel ? (
<LabelList
labels={testLable}
onLabelSelect={handleLabelSelection}
selectedLabels={selectedLabels}
/>
) : (
<div>
<KeywordList
title={testKeywordListProps.title}
subTitle={testKeywordListProps.subTitle}
keywordGroup={testKeywordListProps.keywordGroup}
onKeywordSelect={handleKeywordSelection}
selectedKeywords={selectedKeywords}
/>
</div>
)}
<Margin bottom={30} />
</SliderMenuContainer>
</div>
Expand Down
34 changes: 34 additions & 0 deletions src/components/SelectItemPage/SelectToggle/SelectToggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';

type SelectToggleProps = {
isLabel: boolean;
setIsLabel: React.Dispatch<React.SetStateAction<boolean>>;
};

export const SelectToggle: React.FC<SelectToggleProps> = ({
isLabel,
setIsLabel
}) => {
return (
<div className="relative flex w-full overflow-hidden text-xl align-middle h-[50px] ">
<div
className="absolute bottom-0 w-1/2 h-[2px] transition-transform duration-500 ease-in-out bg-sample-blue"
style={{
transform: `translateX(${isLabel ? '0%' : '100%'})`
}}
></div>
<div
className="flex items-center justify-center flex-1 h-full cursor-pointer"
onClick={() => setIsLabel(true)}
>
<span>라벨</span>
</div>
<div
className="flex items-center justify-center flex-1 h-full cursor-pointer"
onClick={() => setIsLabel(false)}
>
<span>키워드</span>
</div>
</div>
);
};
17 changes: 17 additions & 0 deletions src/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useAutoSave } from './useAutoSave';
import { useDebounce } from './useDebounde';
import { useLocalStorage } from './useLocalStorage';
import { useModal } from './useModal';
import useNominatimSearch from './useNominatimSearch';
import { useRegisterForm } from './useRegisterForm';
import { useToastStore } from './useToastStore';

export {
useAutoSave,
useDebounce,
useLocalStorage,
useModal,
useNominatimSearch,
useRegisterForm,
useToastStore
};
4 changes: 1 addition & 3 deletions src/hooks/useAutoSave.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useToastStore } from './useToastStore';

type AutoSaveCallback = () => void;

const useAutoSave = (callback: AutoSaveCallback, interval: number) => {
export const useAutoSave = (callback: AutoSaveCallback, interval: number) => {
const { addToast } = useToastStore();

useEffect(() => {
Expand All @@ -24,5 +24,3 @@ const useAutoSave = (callback: AutoSaveCallback, interval: number) => {
};
}, [callback, interval, addToast]);
};

export default useAutoSave;
Loading

0 comments on commit 63ec205

Please sign in to comment.