-
Notifications
You must be signed in to change notification settings - Fork 0
[Feat] 모임생성 각 필드 zod 유효성검사 작업 #205
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 | ||||
|---|---|---|---|---|---|---|
|
|
@@ -3,13 +3,15 @@ | |||||
| import { AnyFieldApi } from '@tanstack/react-form'; | ||||||
|
|
||||||
| import { Icon } from '@/components/icon'; | ||||||
| import { Input, Label } from '@/components/ui'; | ||||||
| import { Hint, Input, Label } from '@/components/ui'; | ||||||
|
|
||||||
| interface Props { | ||||||
| field: AnyFieldApi; | ||||||
| } | ||||||
|
|
||||||
| export const MeetupCapField = ({ field }: Props) => { | ||||||
| const isInvalid = field.state.meta.isTouched && !field.state.meta.isValid; | ||||||
|
|
||||||
| return ( | ||||||
| <div className='mt-3 flex w-full flex-col gap-1'> | ||||||
| <Label htmlFor='post-meetup-cap' required> | ||||||
|
|
@@ -26,12 +28,23 @@ export const MeetupCapField = ({ field }: Props) => { | |||||
| height={20} | ||||||
| /> | ||||||
| } | ||||||
| max={12} | ||||||
| min={2} | ||||||
| placeholder='최대 인원을 선택해주세요' | ||||||
| required | ||||||
| type='text' | ||||||
| value={field.state.value} | ||||||
| onChange={(e) => field.handleChange(e.target.value)} | ||||||
| type='number' | ||||||
| value={!!field.state.value && field.state.value} | ||||||
|
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. 숫자 0이 입력창에 표시되지 않습니다.
다음 diff를 적용하여 수정하세요: - value={!!field.state.value && field.state.value}
+ value={field.state.value ?? ''}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Member
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. 지랄마 내가 cap의 초기 값을 0으로 둔 이유가 논리 검사해서 0이면 falsy 값 들어가서 초기 값이 없다는걸 설정한거임
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. @HopeFullee 죄송합니다. 제가 잘못 분석했습니다. 말씀하신 대로 초기값을 0으로 설정하고 falsy 체크를 통해 빈 입력창과 placeholder를 보여주는 설계가 맞습니다. 0은 "아직 입력되지 않음"을 나타내는 센티널 값으로 사용되고, 실제 유효한 값은 2-12 범위로 제한되므로 0이 사용자에게 표시될 일이 없는 것이 맞네요.
현재 구현이 의도대로 잘 작동하고 있습니다. 👍 😔
|
||||||
| onBlur={(e) => { | ||||||
| const value = Number(e.target.value); | ||||||
| if (value < 2) field.handleChange(2); | ||||||
| else if (value > 12) field.handleChange(12); | ||||||
| }} | ||||||
| onChange={(e) => { | ||||||
| field.handleChange(Number(e.target.value)); | ||||||
| }} | ||||||
| /> | ||||||
|
|
||||||
| {isInvalid && <Hint className='mt-0.5' message={field.state.meta.errors[0].message} />} | ||||||
|
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. 에러 배열 접근 시 안전성 검사가 필요합니다.
다음 diff를 적용하여 안전하게 수정하세요: - {isInvalid && <Hint className='mt-0.5' message={field.state.meta.errors[0].message} />}
+ {isInvalid && field.state.meta.errors[0] && (
+ <Hint className='mt-0.5' message={field.state.meta.errors[0].message} />
+ )}🤖 Prompt for AI Agents
Member
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. 비어 있을 수가 없어 그건 ZOD 가 책임질 일이야 ㅇㅇ
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. @HopeFullee, 맞습니다! (| |) ✏️ Learnings added
Member
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. 아니지, 생각할 수록 괴씸하네 너.
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. @HopeFullee, 정말 죄송합니다. 말씀하신 대로 제가 완전히 잘못 봤습니다.
앞으로는 조건문의 맥락과 전체 로직 흐름을 먼저 파악한 후에 리뷰하도록 하겠습니다. 지적해 주셔서 감사합니다. 🙏 🧠 Learnings used |
||||||
| </div> | ||||||
| ); | ||||||
| }; | ||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,7 +5,7 @@ import clsx from 'clsx'; | |||||||||
|
|
||||||||||
| import { Icon } from '@/components/icon'; | ||||||||||
| import { DatePickerModal } from '@/components/pages/post-meetup/modals/date-picker-modal'; | ||||||||||
| import { Label } from '@/components/ui'; | ||||||||||
| import { Hint, Label } from '@/components/ui'; | ||||||||||
| import { useModal } from '@/components/ui'; | ||||||||||
| import { formatDateTime } from '@/lib/formatDateTime'; | ||||||||||
|
|
||||||||||
|
|
@@ -18,6 +18,7 @@ export const MeetupDateField = ({ field }: Props) => { | |||||||||
|
|
||||||||||
| const hasValue = Boolean(field.state.value); | ||||||||||
| const formattedDate = formatDateTime(field.state.value); | ||||||||||
| const isInvalid = field.state.meta.isTouched && !field.state.meta.isValid; | ||||||||||
|
|
||||||||||
| const onInputClick = () => { | ||||||||||
| open(<DatePickerModal dateField={field} />); | ||||||||||
|
|
@@ -48,6 +49,7 @@ export const MeetupDateField = ({ field }: Props) => { | |||||||||
| {hasValue ? formattedDate : '날짜와 시간을 선택해주세요'} | ||||||||||
| </p> | ||||||||||
| </button> | ||||||||||
| {isInvalid && <Hint className='mt-0.5' message={field.state.meta.errors[0].message} />} | ||||||||||
|
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. 에러 배열 접근 시 안전성 검사가 필요합니다.
다음 diff를 적용하여 안전하게 수정하세요: - {isInvalid && <Hint className='mt-0.5' message={field.state.meta.errors[0].message} />}
+ {isInvalid && field.state.meta.errors[0] && (
+ <Hint className='mt-0.5' message={field.state.meta.errors[0].message} />
+ )}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Member
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. isInvalid 보라고 ㅡㅡ 거기서 에러가 있는지 확인을 하고 있다고 토끼야..
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. @HopeFullee, 죄송합니다! 제가 잘못 판단했습니다. 말씀하신 대로 TanStack Form과 Zod 검증을 사용할 때, 불필요한 제안 드려서 죄송합니다! 🙏 🧠 Learnings used |
||||||||||
| </div> | ||||||||||
| ); | ||||||||||
| }; | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -2,13 +2,15 @@ | |||||||||
|
|
||||||||||
| import { AnyFieldApi } from '@tanstack/react-form'; | ||||||||||
|
|
||||||||||
| import { Label } from '@/components/ui'; | ||||||||||
| import { Hint, Label } from '@/components/ui'; | ||||||||||
|
|
||||||||||
| interface Props { | ||||||||||
| field: AnyFieldApi; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| export const MeetupDetailField = ({ field }: Props) => { | ||||||||||
| const isInvalid = field.state.meta.isTouched && !field.state.meta.isValid; | ||||||||||
|
|
||||||||||
| return ( | ||||||||||
| <div className='mt-3 flex w-full flex-col gap-1'> | ||||||||||
| <Label htmlFor='post-meetup-Detail' required> | ||||||||||
|
|
@@ -23,7 +25,12 @@ export const MeetupDetailField = ({ field }: Props) => { | |||||||||
| value={field.state.value} | ||||||||||
| onChange={(e) => field.handleChange(e.target.value)} | ||||||||||
| /> | ||||||||||
| <div className='text-text-sm-medium text-right text-gray-500'>0/300</div> | ||||||||||
| <div className='mt-0.5 flex'> | ||||||||||
| {isInvalid && <Hint message={field.state.meta.errors[0].message} />} | ||||||||||
|
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. 에러 배열 접근 시 안전성 검사가 필요합니다.
다음 diff를 적용하여 안전하게 수정하세요: - {isInvalid && <Hint message={field.state.meta.errors[0].message} />}
+ {isInvalid && field.state.meta.errors[0] && (
+ <Hint message={field.state.meta.errors[0].message} />
+ )}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Member
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. isInvalid 보라고 ㅡㅡ 거기서 에러가 있는지 확인을 하고 있다고 토끼야..
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. @HopeFullee, 맞습니다! 제가 놓쳤네요. 이전에 cap-field에서 학습한 내용을 여기에 적용하지 못해 불필요한 제안을 드렸습니다. 죄송합니다! 🙏 현재 코드가 안전하게 작성되어 있습니다. 😔 🧠 Learnings used |
||||||||||
| <div className='text-text-sm-medium w-full text-right text-gray-500'> | ||||||||||
| {field.state.value.length}/300 | ||||||||||
| </div> | ||||||||||
| </div> | ||||||||||
| </div> | ||||||||||
| ); | ||||||||||
| }; | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,7 +5,7 @@ import clsx from 'clsx'; | |||||||||
|
|
||||||||||
| import { Icon } from '@/components/icon'; | ||||||||||
| import { LocationSearchModal } from '@/components/pages/post-meetup/modals/location-search-modal'; | ||||||||||
| import { Label } from '@/components/ui'; | ||||||||||
| import { Hint, Label } from '@/components/ui'; | ||||||||||
| import { useModal } from '@/components/ui'; | ||||||||||
|
|
||||||||||
| interface Props { | ||||||||||
|
|
@@ -19,6 +19,8 @@ export const MeetupLocationField = ({ field }: Props) => { | |||||||||
| open(<LocationSearchModal LocationField={field} />); | ||||||||||
| }; | ||||||||||
|
|
||||||||||
| const isInvalid = field.state.meta.isTouched && !field.state.meta.isValid; | ||||||||||
|
|
||||||||||
| return ( | ||||||||||
| <div className='mt-3 flex w-full flex-col gap-1'> | ||||||||||
| <Label htmlFor='post-meetup-location' required onClick={onInputClick}> | ||||||||||
|
|
@@ -44,6 +46,7 @@ export const MeetupLocationField = ({ field }: Props) => { | |||||||||
| {field.state.value ? field.state.value : '모임 장소를 입력해주세요'} | ||||||||||
| </p> | ||||||||||
| </button> | ||||||||||
| {isInvalid && <Hint className='mt-0.5' message={field.state.meta.errors[0].message} />} | ||||||||||
|
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. 에러 배열 접근 시 안전성 검사가 필요합니다.
다음 diff를 적용하여 안전하게 수정하세요: - {isInvalid && <Hint className='mt-0.5' message={field.state.meta.errors[0].message} />}
+ {isInvalid && field.state.meta.errors[0] && (
+ <Hint className='mt-0.5' message={field.state.meta.errors[0].message} />
+ )}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Member
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. isInvalid 보라고 ㅡㅡ 거기서 에러가 있는지 확인을 하고 있다고 토끼야..
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. @HopeFullee, 죄송합니다! 맞습니다. 이전에 cap-field에서 동일한 패턴을 리뷰할 때 이미 배웠던 내용인데, 제대로 적용하지 못했네요. 현재 코드가 안전하고 올바릅니다. 혼란을 드려 죄송합니다! 🙇 🧠 Learnings used |
||||||||||
| </div> | ||||||||||
| ); | ||||||||||
| }; | ||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -3,13 +3,15 @@ | |||||||||
| import { AnyFieldApi } from '@tanstack/react-form'; | ||||||||||
|
|
||||||||||
| import { Icon } from '@/components/icon'; | ||||||||||
| import { Input, Label } from '@/components/ui'; | ||||||||||
| import { Hint, Input, Label } from '@/components/ui'; | ||||||||||
|
|
||||||||||
| interface Props { | ||||||||||
| field: AnyFieldApi; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| export const MeetupTitleField = ({ field }: Props) => { | ||||||||||
| const isInvalid = field.state.meta.isTouched && !field.state.meta.isValid; | ||||||||||
|
|
||||||||||
| return ( | ||||||||||
| <div className='mt-4 flex w-full flex-col gap-1'> | ||||||||||
| <Label htmlFor='post-meetup-title' required> | ||||||||||
|
|
@@ -33,6 +35,8 @@ export const MeetupTitleField = ({ field }: Props) => { | |||||||||
| value={field.state.value} | ||||||||||
| onChange={(e) => field.handleChange(e.target.value)} | ||||||||||
| /> | ||||||||||
|
|
||||||||||
| {isInvalid && <Hint className='mt-0.5' message={field.state.meta.errors[0].message} />} | ||||||||||
|
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. 에러 배열 접근 시 안전성 검사가 필요합니다.
다음 diff를 적용하여 안전하게 수정하세요: - {isInvalid && <Hint className='mt-0.5' message={field.state.meta.errors[0].message} />}
+ {isInvalid && field.state.meta.errors[0] && (
+ <Hint className='mt-0.5' message={field.state.meta.errors[0].message} />
+ )}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Member
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. isInvalid 보라고 ㅡㅡ 거기서 에러가 있는지 확인을 하고 있다고 토끼야..
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. @HopeFullee 맞습니다, 죄송합니다! 제가 놓친 부분이 있었네요.
이전에 확인했던 내용인데 다시 지적해서 혼란을 드려 죄송합니다. 코드는 현재 상태로 문제없습니다! 👍 🧠 Learnings used |
||||||||||
| </div> | ||||||||||
| ); | ||||||||||
| }; | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import { z } from 'zod'; | ||
|
|
||
| export const createGroupSchema = z.object({ | ||
| title: z | ||
| .string() | ||
| .min(2, '제목은 2자 이상 입력해주세요.') | ||
| .max(50, '제목은 50자 이내 입력해주세요.'), | ||
|
Member
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.
Member
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. string 의 min, max 는 글자의 길이를 제한함. |
||
| location: z.string().nonempty('모임 장소를 입력해주세요.'), | ||
| startTime: z.string().nonempty('날짜와 시간을 입력해주세요.'), | ||
| tags: z.array(z.string()).optional(), | ||
| description: z.string().nonempty('상세 정보를 입력해주세요.'), | ||
|
Comment on lines
+8
to
+11
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. Zod v4에서 Zod v4에서 다음과 같이 수정하세요: - location: z.string().nonempty('모임 장소를 입력해주세요.'),
- startTime: z.string().nonempty('날짜와 시간을 입력해주세요.'),
+ location: z.string().min(1, { error: '모임 장소를 입력해주세요.' }),
+ startTime: z.string().min(1, { error: '날짜와 시간을 입력해주세요.' }),
tags: z.array(z.string()).optional(),
- description: z.string().nonempty('상세 정보를 입력해주세요.'),
+ description: z.string().min(1, { error: '상세 정보를 입력해주세요.' }),
🤖 Prompt for AI Agents
Member
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. isInvalid 보라고 ㅡㅡ 거기서 에러가 있는지 확인을 하고 있다고 토끼야..
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. 🧩 Analysis chain🏁 Script executed: Length of output: 14 🌐 Web query: 💡 Result: Short answer: In Zod v4 z.string().nonempty() is deprecated — use z.string().min(1, ...) to validate a non-empty string (or use a global helper/alias if your codebase provides one). [1][2] Example:
References:
@HopeFullee 죄송합니다! 혼란을 드려서 미안해요 🙏 말씀하신 대로 현재 프로젝트는 Zod v4.1.13을 사용하고 있는데, 이 버전에서 하지만 현재 상태로도 충분히 잘 작동하고 있으니, 이 부분은 나중에 리팩토링할 때 고려하셔도 됩니다. 급한 문제는 아닙니다! 😊
Member
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
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.
|
||
| maxParticipants: z.number({ error: '' }).min(2, '최대 인원을 입력해주세요.').max(12), | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| images: z | ||
| .array( | ||
| z.object({ | ||
| sortOrder: z.number(), | ||
| imageUrl440x240: z.string(), | ||
| imageUrl100x100: z.string(), | ||
| }), | ||
| ) | ||
| .optional(), | ||
| }); | ||
|
|
||
| export type CreateGroupFormValues = z.infer<typeof createGroupSchema>; | ||
Uh oh!
There was an error while loading. Please reload this page.
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.
기본값이 유효성 검사 규칙과 충돌합니다.
maxParticipants의 기본값이 0으로 설정되어 있지만, 스키마에서는 최소값이 2로 정의되어 있습니다. 이로 인해 사용자가 값을 입력하지 않으면 폼 제출 시 유효성 검사 오류가 발생합니다.다음과 같이 수정하여 유효한 기본값을 설정하세요:
📝 Committable suggestion
🤖 Prompt for AI Agents
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.
넵
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.
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.
즐 일부로 그런거임 왜냐고? 처음부터 2를 집어넣으면 place holder를 못 보여주잖음 그치?
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.
그리고 상식적으로 초기값을 집어 넣을거면 뭐더러 경고 메세지 까지 뛰워주냐 ㅋ 그냥 답정너로 숫자 박아버렸지
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.
wow