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

[feat/CK-142] 로드맵 생성페이지 버그를 해결한다 #101

Merged
merged 9 commits into from
Aug 9, 2023
1 change: 0 additions & 1 deletion client/src/components/_common/roadmapItem/RoadmapItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ const RoadmapItem = ({ item, hasBorder = true, roadmapId }: RoadmapItemProps) =>
{item.tags.map((tag) => {
return <span># {tag.name}</span>;
})}

</S.Tags>
</S.ItemFooter>
</S.RoadmapItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ const Description = () => {
name='introduction'
data-valid={validateInput}
/>
<TextCount maxCount={150} currentCount={value.length} />
<S.TextCountWrapper>
<TextCount maxCount={150} currentCount={value.length} />
</S.TextCountWrapper>
</S.FieldWrapper>
<S.ErrorMessage>{errorMessage}</S.ErrorMessage>
</S.Container>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@ export const Container = styled.article`

export const FieldWrapper = styled.div`
display: flex;
align-items: center;
justify-content: space-between;

width: 80%;
height: 3rem;
padding-left: 2rem;
height: 10rem;
padding: 2rem;

border-bottom: 0.2rem solid ${({ theme }) => theme.colors.gray300};
background-color: ${({ theme }) => theme.colors.gray100};
border-radius: 2rem;
`;

export const TextCountWrapper = styled.div`
height: 80%;
margin-right: 2rem;
`;

export const ErrorMessage = styled.div`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export const Input = styled.textarea`
width: 80%;
height: 80%;
color: ${({ theme }) => theme.colors.gray300};

&::placeholder {
${({ theme }) => theme.fonts.description4};
color: ${({ theme }) => theme.colors.gray200};
Expand Down
10 changes: 7 additions & 3 deletions client/src/components/roadmapCreatePage/roadmap/RoadmapItem.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeEvent } from 'react';
import React, { ChangeEvent } from 'react';
import * as S from './roadmap.styles';

type RoadmapItemProps = {
Expand All @@ -20,10 +20,13 @@ const RoadmapItem = ({
<S.TitleWrapper>
<S.RoadmapNumber>{roadmapNumber}</S.RoadmapNumber>
<S.TitleFieldWrapper>
<input
onChange={(e) => getRoadmapItemTitle<HTMLInputElement>(e, itemId)}
<S.NodeTitleInputField
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
getRoadmapItemTitle<HTMLInputElement>(e, itemId)
}
maxLength={40}
name='title'
placeholder='로드맵의 제목을 입렵해주세요'
/>
Comment on lines +23 to +29
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

on Change event 를 분리하지 않고 콜백으로 넣은 이유가 있을까용??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 핸들러 함수에 e 말고도 다른 인자도 들어가야해서 콜백으로 넣어줬어요! 근데 이게 문제가... 태그를 input으로 명시하면 e의 타입이 추론이 되는데 스타일드 컴포넌트로 명시하니깐 타입 추론이 안되더라고라... ㄹㅇ 환장할 노릇;; 그래서 일단 타입을 명시해줬는데 왜 이러는지 혹시 아실까용 ㅜ

</S.TitleFieldWrapper>
</S.TitleWrapper>
Expand All @@ -34,6 +37,7 @@ const RoadmapItem = ({
}
maxLength={2000}
name='content'
placeholder='로드맵의 본문을 입렵해주세요'
/>
</S.BodyFieldWrapper>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,13 @@ export const BodyFieldWrapper = styled.div`
border-radius: 2rem;
`;

export const NodeTitleInputField = styled.input`
width: 80%;
`;

export const NodeBodyInputField = styled.textarea`
width: 80%;
height: 10rem;
`;

export const AddButton = styled.button`
Expand Down
14 changes: 10 additions & 4 deletions client/src/components/roadmapCreatePage/tag/Tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ type TagProps = {
getTags: (tags: string[]) => void;
};
const Tag = ({ getTags }: TagProps) => {
const { tags, ref, getAddedTagText, checkIsTagCountMax } = useCreateTag();
const { tags, ref, addTagByButton, addTagByEnter, checkIsTagCountMax, delegeTag } =
useCreateTag();

useEffect(() => {
getTags(tags);
Expand All @@ -21,10 +22,15 @@ const Tag = ({ getTags }: TagProps) => {
<InputDescription text='컨텐츠와 어울리는 태그를 작성해주세요' />
<S.TagWrapper>
{tags.map((item) => (
<S.AddedTagItem key={item}>{item}</S.AddedTagItem>
<>
<S.AddedTagItem key={item}># {item}</S.AddedTagItem>
<S.DeleteButton value={item} onClick={delegeTag}>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delegeTag 가 쫌 걸리네요.. 🥲

X
</S.DeleteButton>
</>
))}
<TagItem ref={ref} />
{checkIsTagCountMax() && <S.AddButton onClick={getAddedTagText}>+</S.AddButton>}
<TagItem ref={ref} addTagByEnter={addTagByEnter} placeholder='# 태그명' />
{checkIsTagCountMax() && <S.AddButton onClick={addTagByButton}>+</S.AddButton>}
</S.TagWrapper>
</S.Container>
);
Expand Down
9 changes: 7 additions & 2 deletions client/src/components/roadmapCreatePage/tag/TagItem.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
import { TAG_MAX_LENGTH } from '@/constants/roadmap/regex';
import { TAG_ITEM_MAX_LENGTH } from '@/constants/roadmap/tag';
import { useValidateInput } from '@/hooks/_common/useValidateInput';
import { forwardRef, InputHTMLAttributes } from 'react';
import React, { forwardRef, InputHTMLAttributes } from 'react';
import * as S from './tag.styles';

type TagItemProps = InputHTMLAttributes<HTMLInputElement>;
type TagItemProps = {
addTagByEnter: (e: React.KeyboardEvent) => void;
} & InputHTMLAttributes<HTMLInputElement>;

const TagItem = forwardRef<HTMLInputElement, TagItemProps>((props, ref) => {
const { addTagByEnter, placeholder } = props;
const { handleInputChange, value } = useValidateInput(TAG_MAX_LENGTH);

return (
<S.TagItem width={props.readOnly ? String(props.value).length : value.length}>
<S.TagInputField
onChange={handleInputChange}
onKeyPress={addTagByEnter}
maxLength={TAG_ITEM_MAX_LENGTH}
value={props.value}
ref={ref}
readOnly={props.readOnly}
placeholder={placeholder}
/>
</S.TagItem>
);
Expand Down
7 changes: 5 additions & 2 deletions client/src/components/roadmapCreatePage/tag/tag.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export const AddedTagItem = styled.article`
justify-content: center;

height: 4.7rem;
margin-right: 2rem;
padding: 0 1rem;

border: 0.2rem solid ${({ theme }) => theme.colors.main_dark};
Expand All @@ -32,7 +31,6 @@ export const TagItem = styled.article<{ width: number }>`

width: ${({ width }) => (width > 4 ? width * 2 : 10)}rem;
height: 4.7rem;
margin-right: 2rem;

border: 0.2rem solid ${({ theme }) => theme.colors.main_dark};
border-radius: 100px;
Expand All @@ -49,3 +47,8 @@ export const AddButton = styled.button`
width: 5rem;
height: 5rem;
`;

export const DeleteButton = styled.button`
margin-right: 2rem;
color: ${({ theme }) => theme.colors.main_dark};
`;
26 changes: 23 additions & 3 deletions client/src/hooks/roadmap/useCreateTag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ export const useCreateTag = () => {
const [tags, setTags] = useState<string[]>([]);
const ref = useRef<HTMLInputElement | null>(null);

const getAddedTagText = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
const getAddedTagText = () => {
if (ref.current === null) return;
if (ref.current.value === '') return;

Expand All @@ -16,9 +15,30 @@ export const useCreateTag = () => {
ref.current.value = '';
};

const addTagByButton = (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
getAddedTagText();
};

const addTagByEnter = (e: React.KeyboardEvent) => {
if (e.code === 'Enter') {
e.preventDefault();
getAddedTagText();
}
};

const checkIsTagCountMax = () => {
return tags.length < TAG_LIMIT;
};

return { tags, ref, getAddedTagText, checkIsTagCountMax };
const delegeTag = (e: React.MouseEvent<HTMLButtonElement>) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete 를 뜻하는게 맞을까여??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

헉 매의눈 ㅇㅈ... 주의하겠슴미다😭

e.preventDefault();

const target = e.target as HTMLButtonElement;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e.currentTarget은 항상 button 요소가 되겠지만, e.target은 다른 요소가 될 수도 있어서 target에 타입 단언을 해주어야 하는군요👍


setTags((prev) => {
return prev.filter((tag) => tag !== target.value);
});
Comment on lines +39 to +41
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

문득 생각이 든건데, 이미 추가한 태그를 똑같은 이름으로 추가하면 어떻게 되는건가요?

getAddedTagText() 구현부를 살펴보니 중복으로 추가가 가능한 것 같아서요!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

완전 예리하네요..!! 태그 생성은 중복 가능해도 좋을 것 같은데, 삭제 자체는 한개만 되어야 하는게 맞는 것 같아요!!
이 다음 작업부분에서 수정해보도록 할게요!!

};
return { tags, ref, addTagByButton, addTagByEnter, checkIsTagCountMax, delegeTag };
};
Loading