-
Notifications
You must be signed in to change notification settings - Fork 1
[FIX] TextArea 최소 글자 관련 수정 #246
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,10 @@ | ||
| import { useEffect, useMemo, useState } from "react"; | ||
| import { useEffect, useMemo, useState, useRef } from "react"; | ||
| import { useNavigate } from "react-router"; | ||
| import { useNewPostState } from "@/store/useNewPostState.store"; | ||
| import { TextArea } from "@/components/common/TextArea"; | ||
| import { isValidText } from "@/utils/isValidText"; | ||
| import { CTA_Button, Header } from "@/components/common"; | ||
| import { scrollToCenter } from "@/utils/scrollToCenter"; | ||
|
|
||
| const LIMITS = { | ||
| titleMin: 2, | ||
|
|
@@ -15,6 +16,11 @@ const LIMITS = { | |
|
|
||
| export default function NewPostPage() { | ||
| const navigate = useNavigate(); | ||
| const [titleError, setTitleError] = useState(false); | ||
| const [contentError, setContentError] = useState(false); | ||
| const titleRef = useRef<HTMLTextAreaElement | null>(null); | ||
| const contentRef = useRef<HTMLTextAreaElement | null>(null); | ||
|
|
||
| const files = useNewPostState((s) => s.files); | ||
| const setPostInfo = useNewPostState((s) => s.setPostInfo); | ||
| const reset = useNewPostState((s) => s.reset); | ||
|
|
@@ -47,10 +53,36 @@ export default function NewPostPage() { | |
| [contentText], | ||
| ); | ||
|
|
||
| const canGoNext = isTitleValid && isContentValid; | ||
|
|
||
| const handleNext = () => { | ||
| if (!canGoNext) return; | ||
| // 1) 제목 먼저 체크 | ||
| if (!isTitleValid) { | ||
| setTitleError(true); | ||
| setContentError(false); // 첫 에러만 강조 | ||
|
|
||
| const el = titleRef.current; | ||
| if (el) { | ||
| scrollToCenter(el); | ||
| el.focus(); | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| // 2) 그 다음 내용 체크 | ||
| if (!isContentValid) { | ||
| setContentError(true); | ||
| setTitleError(false); | ||
|
|
||
| const el = contentRef.current; | ||
| if (el) { | ||
| scrollToCenter(el); | ||
| el.focus(); | ||
| } | ||
| return; | ||
| } | ||
|
|
||
| // 3) 둘 다 valid이면 다음 | ||
| setTitleError(false); | ||
| setContentError(false); | ||
| setPostInfo(titleText, contentText); | ||
| navigate("/photoFeed/lab/find"); | ||
| }; | ||
|
|
@@ -90,25 +122,59 @@ export default function NewPostPage() { | |
| <section className="flex flex-col gap-[0.5rem]"> | ||
| <p className="text-[0.875rem] text-white">제목</p> | ||
| <TextArea | ||
| ref={titleRef} | ||
| type="title" | ||
| value={titleText} | ||
| onChange={setTitleText} | ||
| onChange={(v) => { | ||
| setTitleText(v); | ||
| if ( | ||
| titleError && | ||
| isValidText(v, LIMITS.titleMin, LIMITS.titleMax) | ||
| ) { | ||
| setTitleError(false); | ||
| } | ||
| }} | ||
|
Comment on lines
+128
to
+136
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 에러 상태가 한 글자 입력이 늦게 해제되는 문제가 있습니다.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 반영 |
||
| placeholder="제목을 입력해주세요." | ||
| minLength={LIMITS.titleMin} | ||
| maxLength={LIMITS.titleMax} | ||
| isError={titleError} | ||
| /> | ||
| {titleError && ( | ||
| <p | ||
| className={`px-[0.625rem] text-[0.875rem] font-normal text-orange-500`} | ||
| > | ||
| 최소 2글자 이상 입력해주세요. | ||
| </p> | ||
| )} | ||
| </section> | ||
|
|
||
| <section className="flex flex-col gap-[0.5rem]"> | ||
| <p className="text-[0.875rem] text-white">설명</p> | ||
| <TextArea | ||
| ref={contentRef} | ||
| type="content" | ||
| value={contentText} | ||
| onChange={setContentText} | ||
| onChange={(v) => { | ||
| setContentText(v); | ||
| if ( | ||
| contentError && | ||
| isValidText(v, LIMITS.contentMin, LIMITS.contentMax) | ||
| ) { | ||
| setContentError(false); | ||
| } | ||
| }} | ||
|
Comment on lines
+157
to
+165
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 반영 |
||
| placeholder="나만의 필름 사진 이야기를 공유해주세요." | ||
| minLength={LIMITS.contentMin} | ||
| maxLength={LIMITS.contentMax} | ||
| isError={contentError} | ||
| /> | ||
| {contentError && ( | ||
| <p | ||
| className={`px-[0.625rem] text-[0.875rem] font-normal text-orange-500`} | ||
| > | ||
| 최소 20글자 이상 입력해주세요. | ||
| </p> | ||
| )} | ||
| </section> | ||
|
|
||
| <hr className="border-neutral-800" /> | ||
|
|
@@ -157,7 +223,7 @@ export default function NewPostPage() { | |
| <CTA_Button | ||
| text="다음" | ||
| size="xlarge" | ||
| color={canGoNext ? "orange" : "black"} | ||
| color={isTitleValid && isContentValid ? "orange" : "black"} | ||
| onClick={handleNext} | ||
| /> | ||
| </div> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
handleNext함수의 유효성 검사 로직에 오류가 있습니다.isContentValid가 참이지만isTitleValid가 거짓인 경우, 제목 필드에 대한 유효성 검사를 건너뛰고 폼이 제출됩니다. 이로 인해 유효하지 않은 제목으로 게시물이 생성될 수 있습니다. 두 필드를 각각 독립적으로 확인한 후 다음 단계로 진행하도록 로직을 수정해야 합니다.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
첫번째 에러만 강조하는 로직으로 변경: 제목 체크 -> 내용 체크