-
Notifications
You must be signed in to change notification settings - Fork 0
모집 공고 생성 페이지 일부 수정( feat/#355 ) #357
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 3 commits
4c2b23f
cc041cd
7ad8482
f85aec7
b7b71d1
3a6c2de
27fc657
14340b7
30ba86b
8cfcf76
9104815
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,12 +3,15 @@ import * as S from './InputComponent.styled'; | |||||||||||||||||||||||||||||||||||||
| import MdEditorInput from '../editor/MarkdownEditor'; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| type InputProps = { | ||||||||||||||||||||||||||||||||||||||
| // eslint-disable-next-line @typescript-eslint/no-explicit-any | ||||||||||||||||||||||||||||||||||||||
| control: Control<any>; | ||||||||||||||||||||||||||||||||||||||
| name: string; | ||||||||||||||||||||||||||||||||||||||
| placeholder?: string; | ||||||||||||||||||||||||||||||||||||||
| errors?: FieldErrors; | ||||||||||||||||||||||||||||||||||||||
| type?: 'text' | 'date' | 'textarea' | 'number' | string; | ||||||||||||||||||||||||||||||||||||||
| indexInfo?: string; | ||||||||||||||||||||||||||||||||||||||
| unit?: string; | ||||||||||||||||||||||||||||||||||||||
| min?: number; | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const Input = ({ | ||||||||||||||||||||||||||||||||||||||
|
|
@@ -18,25 +21,70 @@ const Input = ({ | |||||||||||||||||||||||||||||||||||||
| placeholder, | ||||||||||||||||||||||||||||||||||||||
| type, | ||||||||||||||||||||||||||||||||||||||
| indexInfo, | ||||||||||||||||||||||||||||||||||||||
| unit, | ||||||||||||||||||||||||||||||||||||||
| min = 0, | ||||||||||||||||||||||||||||||||||||||
| }: InputProps) => { | ||||||||||||||||||||||||||||||||||||||
| const { field } = useController({ | ||||||||||||||||||||||||||||||||||||||
| control, | ||||||||||||||||||||||||||||||||||||||
| name, | ||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||
| const hasError = Boolean(errors?.[name]); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||||||||||||||||||||||||||||||||||||||
| const value = e.target.value; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // 숫자 입력 필드인 경우 숫자만 허용 | ||||||||||||||||||||||||||||||||||||||
| if (name === 'maxVolunteers' || name === 'duration') { | ||||||||||||||||||||||||||||||||||||||
|
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. 💡 Verification agent 🧩 Analysis chain스키마와 입력 검증의 일관성을 확인해주세요
다음 스크립트를 실행하여 스키마 일관성을 확인해주세요: 🏁 Script executed: #!/bin/bash
# 스키마에서 maxVolunteers와 duration 필드의 타입 확인
rg -A 10 "maxVolunteers.*z\." src/constants/user/projectConstants.ts
rg -A 10 "duration.*z\." src/constants/user/projectConstants.tsLength of output: 136 다음 스크립트로 🏁 Script executed: #!/bin/bash
# Zod 스키마 정의 위치 확인
rg -n "z.object" -A 20 src/constants/user/projectConstants.ts || true
# 각 필드 타입 확인
rg -n "maxVolunteers" -A 5 src/constants/user/projectConstants.ts || true
rg -n "duration" -A 5 src/constants/user/projectConstants.ts || trueLength of output: 2145
프로젝트 상수(
두 필드를 모두 숫자형으로 다룰 예정이라면 수정 예시: --- a/src/constants/user/projectConstants.ts
+++ b/src/constants/user/projectConstants.ts
@@ -95,7 +95,7 @@ export const createProjectScheme = z.object({
- duration: z
- .string({ message: '예상 기간을 입력해주세요.' })
- .min(1, { message: '예상 기간을 입력해주세요.' })
- .refine((val) => {
- const num = Number(val);
- return !isNaN(num) && num > 0;
- }, { message: '유효한 기간을 입력해주세요.' }),
+ duration: z
+ .number({ message: '예상 기간을 입력해주세요.' })
+ .min(1, { message: '예상 기간을 입력해주세요.' }),위와 같이 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
| // 숫자가 아닌 문자 제거 | ||||||||||||||||||||||||||||||||||||||
| const numericValue = value.replace(/[^0-9]/g, ''); | ||||||||||||||||||||||||||||||||||||||
| if (numericValue !== value) { | ||||||||||||||||||||||||||||||||||||||
| e.target.value = numericValue; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| // 음수 방지 (0보다 작은 값은 허용하지 않음) | ||||||||||||||||||||||||||||||||||||||
| const numValue = Number(numericValue); | ||||||||||||||||||||||||||||||||||||||
| if (numValue < min) { | ||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| field.onChange(e); | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
|
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. 🛠️ Refactor suggestion 입력 검증 로직을 개선해주세요 숫자 입력 검증 로직이 잘 구현되었지만, 더 안정적인 구현을 위해 다음과 같이 수정하는 것을 권장합니다: const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
- const value = e.target.value;
+ let value = e.target.value;
// 숫자 입력 필드인 경우 숫자만 허용
if (name === 'maxVolunteers' || name === 'duration') {
// 숫자가 아닌 문자 제거
- const numericValue = value.replace(/[^0-9]/g, '');
- if (numericValue !== value) {
- e.target.value = numericValue;
- }
+ value = value.replace(/[^0-9]/g, '');
// 음수 방지 (0보다 작은 값은 허용하지 않음)
- const numValue = Number(numericValue);
+ const numValue = Number(value);
if (numValue < min) {
return;
}
}
- field.onChange(e);
+ field.onChange(value);
};🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const renderInput = () => { | ||||||||||||||||||||||||||||||||||||||
| if (indexInfo) { | ||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||
| <S.InputInfoStyle {...field} type={type} placeholder={placeholder} /> | ||||||||||||||||||||||||||||||||||||||
| <S.InputWrapper> | ||||||||||||||||||||||||||||||||||||||
| <S.InputInfoStyle | ||||||||||||||||||||||||||||||||||||||
| {...field} | ||||||||||||||||||||||||||||||||||||||
| type={type} | ||||||||||||||||||||||||||||||||||||||
| placeholder={placeholder} | ||||||||||||||||||||||||||||||||||||||
| onChange={handleInputChange} | ||||||||||||||||||||||||||||||||||||||
| min={min} | ||||||||||||||||||||||||||||||||||||||
| name={name} | ||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||
| {unit && <S.UnitText>{unit}</S.UnitText>} | ||||||||||||||||||||||||||||||||||||||
| </S.InputWrapper> | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (name === 'markdownEditor') { | ||||||||||||||||||||||||||||||||||||||
| return <MdEditorInput field={{ ...field }} />; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| return <S.InputStyle {...field} type={type} placeholder={placeholder} />; | ||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||
| <S.InputWrapper> | ||||||||||||||||||||||||||||||||||||||
| <S.InputStyle | ||||||||||||||||||||||||||||||||||||||
| {...field} | ||||||||||||||||||||||||||||||||||||||
| type={type} | ||||||||||||||||||||||||||||||||||||||
| placeholder={placeholder} | ||||||||||||||||||||||||||||||||||||||
| onChange={handleInputChange} | ||||||||||||||||||||||||||||||||||||||
| min={min} | ||||||||||||||||||||||||||||||||||||||
| name={name} | ||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||
| {unit && <S.UnitText>{unit}</S.UnitText>} | ||||||||||||||||||||||||||||||||||||||
| </S.InputWrapper> | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,23 +7,24 @@ export const PROJECT_DATA = [ | |
| id: '1', | ||
| name: 'maxVolunteers', | ||
| label: '모집 인원', | ||
| type: 'number', | ||
| placeholder: '모집 인원을 입력하세요. (ex. 5)', | ||
| type: 'text', | ||
| unit: '명', | ||
| }, | ||
| { | ||
| id: '2', | ||
| name: 'startDatePre', | ||
| label: '시작 예정', | ||
| type: 'text', | ||
| placeholder: 'YYYY-MM-DD', | ||
| unit: '', | ||
| }, | ||
|
|
||
| { | ||
| id: '3', | ||
| name: 'duration', | ||
| label: '예상 기간', | ||
| type: 'number', | ||
| placeholder: '예상 기간을 입력하세요. (ex. 5)', | ||
| type: 'text', | ||
| unit: '개월', | ||
| }, | ||
|
|
||
| { | ||
|
|
@@ -32,6 +33,7 @@ export const PROJECT_DATA = [ | |
| label: '새싹 여부', | ||
| type: 'checkbox', | ||
| placeholder: '', | ||
| unit: '', | ||
| }, | ||
| ] as const; | ||
|
|
||
|
|
@@ -74,20 +76,32 @@ export const createProjectScheme = z.object({ | |
| .string({ message: '프로젝트 제목을 입력해주세요.' }) | ||
| .min(1, { message: '프로젝트 제목을 입력해주세요.' }), | ||
|
|
||
| maxVolunteers: z.coerce | ||
| maxVolunteers: z | ||
| .number({ message: '모집 인원을 입력해주세요.' }) | ||
| .min(1, { message: '모집 인원은 1명 이상이어야 합니다.' }) | ||
| .max(1000, { message: '모집 인원은 1000명 이하이어야 합니다.' }), | ||
| .min(1, { message: '모집 인원을 입력해주세요.' }) | ||
| .refine( | ||
| (val) => { | ||
| const num = Number(val); | ||
| return !isNaN(num) && num >= 1 && num <= 1000; | ||
| }, | ||
| { message: '모집 인원은 1명 이상 1000명 이하여야 합니다.' } | ||
| ), | ||
|
Comment on lines
+79
to
+88
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. 스키마 타입 불일치를 수정해주세요
다음과 같이 수정하여 일관성을 맞춰주세요: -maxVolunteers: z
- .number({ message: '모집 인원을 입력해주세요.' })
- .min(1, { message: '모집 인원을 입력해주세요.' })
- .refine(
- (val) => {
- const num = Number(val);
- return !isNaN(num) && num >= 1 && num <= 1000;
- },
- { message: '모집 인원은 1명 이상 1000명 이하여야 합니다.' }
- ),
+maxVolunteers: z
+ .string({ message: '모집 인원을 입력해주세요.' })
+ .min(1, { message: '모집 인원을 입력해주세요.' })
+ .refine(
+ (val) => {
+ const num = Number(val);
+ return !isNaN(num) && num >= 1 && num <= 1000;
+ },
+ { message: '모집 인원은 1명 이상 1000명 이하여야 합니다.' }
+ ),
-duration: z
- .string({ message: '예상 기간을 입력해주세요.' })
- .min(1, { message: '예상 기간을 입력해주세요.' })
- .refine(
- (val) => {
- const num = Number(val);
- return !isNaN(num) && num >= 1 && num <= 365;
- },
- { message: '예상 기간은 1일 이상 365일 이하여야 합니다.' }
- ),
+duration: z
+ .string({ message: '예상 기간을 입력해주세요.' })
+ .min(1, { message: '예상 기간을 입력해주세요.' })
+ .refine(
+ (val) => {
+ const num = Number(val);
+ return !isNaN(num) && num >= 1 && num <= 365;
+ },
+ { message: '예상 기간은 1일 이상 365일 이하여야 합니다.' }
+ ),Also applies to: 95-104 🤖 Prompt for AI Agents |
||
| startDatePre: z | ||
| .string({ required_error: '종료 날짜를 입력해주세요.' }) | ||
| .refine((date) => !isNaN(Date.parse(date)), { | ||
| message: '유효한 날짜를 입력해주세요.', | ||
| }), | ||
| field: z.number({ message: '진행 방식을 선택 해주세요.' }), | ||
| duration: z.coerce | ||
| .number({ message: '예상 기간을 입력해주세요.' }) | ||
| .positive({ message: '예상 기간은 1 이상이어야 합니다.' }) | ||
| .max(365, { message: '예상 기간은 365일을 초과할 수 없습니다.' }), | ||
| duration: z | ||
| .string({ message: '예상 기간을 입력해주세요.' }) | ||
| .min(1, { message: '예상 기간을 입력해주세요.' }) | ||
| .refine( | ||
| (val) => { | ||
| const num = Number(val); | ||
| return !isNaN(num) && num >= 1 && num <= 365; | ||
| }, | ||
| { message: '예상 기간은 1일 이상 365일 이하여야 합니다.' } | ||
| ), | ||
| position: z | ||
| .array(z.number({ message: '숫자로 입력 되어야 합니다.' })) | ||
| .min(1, { message: '1개의 분야를 선택해주세요.' }), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import { useQuery } from '@tanstack/react-query'; | ||
| import { Inquiries } from '../queries/keys'; | ||
| import { getInquiriesPreview } from '../../api/admin/customerService/inquiry.api'; | ||
|
|
||
| export const useGetInquiriesPreview = () => { | ||
| const { | ||
| data: allInquiriesPreviewData, | ||
| isLoading, | ||
| isFetching, | ||
| } = useQuery({ | ||
| queryKey: [Inquiries.inquiriesPreview], | ||
| queryFn: () => getInquiriesPreview(), | ||
| select: (data) => data.slice(0, 5), | ||
| }); | ||
|
|
||
| return { allInquiriesPreviewData, isLoading, isFetching }; | ||
| }; |
Uh oh!
There was an error while loading. Please reload this page.