-
Notifications
You must be signed in to change notification settings - Fork 0
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
π μ μ νΌ μμ± μ μ #78
Conversation
Walkthroughμ΄ ν 리νμ€νΈλ νΌ μμ± κΈ°λ₯μ μν μλ‘μ΄ React μ»΄ν¬λνΈμ κ΄λ ¨ μ νΈλ¦¬ν°λ₯Ό μΆκ°ν©λλ€. μ£Όμ λ³κ²½ μ¬νμ νΌ μμ± νμ΄μ§, λ€μν μ λ ₯ μ΅μ μ»΄ν¬λνΈ, μμ΄μ½, κ·Έλ¦¬κ³ νΌ μν κ΄λ¦¬λ₯Ό μν νμ μ μλ₯Ό ν¬ν¨ν©λλ€. μ΄λ¬ν λ³κ²½μ μ ν리μΌμ΄μ μ νΌ μμ± μν¬νλ‘μ°λ₯Ό κ°μ νκ³ νμ₯μ±μ λμ΄λ λ° μ€μ μ λ‘λλ€. Changes
Sequence DiagramsequenceDiagram
participant User
participant CreateFormPage
participant CreateForm
participant FormContainer
participant FormTypeSelect
User->>CreateFormPage: νμ΄μ§ μ μ
CreateFormPage->>CreateForm: λ λλ§
CreateForm->>User: νΌ μμ± μΈν°νμ΄μ€ νμ
User->>CreateForm: μ μ§λ¬Έ μΆκ°
CreateForm->>FormContainer: μ§λ¬Έ 컨ν
μ΄λ μμ±
FormContainer->>FormTypeSelect: νΌ νμ
μ ν
User->>FormTypeSelect: νΌ νμ
μ ν
FormContainer->>User: μ νλ νμ
μ μ
λ ₯ μ΅μ
νμ
Suggested labels
Suggested reviewers
Poem
Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? πͺ§ TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
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.
Actionable comments posted: 18
π§Ή Nitpick comments (11)
src/shared/types/create-form/type.ts (2)
4-8
: νμ μμ μ± κ°μ μ΄ νμν©λλ€.
value
μlabel
μ νμ μ λ ꡬ체μ μΌλ‘ μ μνλ©΄ μ’μ κ² κ°μ΅λλ€.export interface Option { - value: string; - label?: string; + value: 'SENTENCE' | 'CHECKBOX' | 'DROPDOWN' | 'MULTIPLE' | 'IMAGE'; + label?: 'λ¬Έμ₯ν' | '체ν¬λ°μ€' | 'λλ‘λ€μ΄' | 'κ°κ΄μ' | 'μ΄λ―Έμ§'; icon?: ReactNode; }
10-16
: νΌ μ ν¨μ± κ²μ¦ μ μ½μ‘°κ±΄μ΄ νμν©λλ€.
questions
λ°°μ΄μ κΈΈμ΄λtitle
μ μ΅λ κΈΈμ΄ λ±μ λν μ μ½μ‘°κ±΄μ μΆκ°νλ©΄ μ’μ κ² κ°μ΅λλ€.export interface FormValues { questions: { - title: string; + title: string & { maxLength?: 100 }; formType: string; options: Option[]; + maxQuestions?: number; }[]; }src/views/create-form/model/selectOptionData.tsx (1)
10-16
: μμ λ°μ΄ν° ꡬ쑰 κ°μ μ΄ νμν©λλ€.μ΅μ λ°μ΄ν°λ₯Ό λ μ μ§λ³΄μνκΈ° μ½κ² ꡬ쑰ννλ©΄ μ’μ κ² κ°μ΅λλ€.
+export const FORM_TYPES = { + SENTENCE: 'SENTENCE', + CHECKBOX: 'CHECKBOX', + DROPDOWN: 'DROPDOWN', + MULTIPLE: 'MULTIPLE', + IMAGE: 'IMAGE', +} as const; +export const FORM_LABELS = { + [FORM_TYPES.SENTENCE]: 'λ¬Έμ₯ν', + [FORM_TYPES.CHECKBOX]: '체ν¬λ°μ€', + [FORM_TYPES.DROPDOWN]: 'λλ‘λ€μ΄', + [FORM_TYPES.MULTIPLE]: 'κ°κ΄μ', + [FORM_TYPES.IMAGE]: 'μ΄λ―Έμ§', +} as const; export const selectOptionData: Option[] = [ - { value: 'SENTENCE', label: 'λ¬Έμ₯ν', icon: <Typing /> }, + { value: FORM_TYPES.SENTENCE, label: FORM_LABELS[FORM_TYPES.SENTENCE], icon: <Typing /> }, // ... λλ¨Έμ§ μ΅μ λ€λ λμΌνκ² μμ ];src/entities/create-form/index.tsx (1)
1-10
: νμ λ΄λ³΄λ΄κΈ° λ° λͺ λͺ λ λ΄λ³΄λ΄κΈ° κ³ λ €νμ¬ κ΅¬νμ κΈ°λ₯μ μΌλ‘λ λ¬Έμ κ° μμΌλ, λ€μκ³Ό κ°μ κ°μ μ¬νμ κ³ λ €ν΄λ³΄μΈμ:
- μ»΄ν¬λνΈμ κ΄λ ¨λ νμ λ€λ ν¨κ» λ΄λ³΄λ΄λ©΄ μ’μ κ² κ°μ΅λλ€.
- Tree-shakingμ μν΄ named export μ¬μ©μ κ³ λ €ν΄λ³΄μΈμ.
- export { default as CheckBoxOption } from './ui/CheckBoxOption'; + export { CheckBoxOption, type CheckBoxOptionProps } from './ui/CheckBoxOption';src/entities/create-form/ui/PictureOption/index.tsx (2)
15-19
: μ κ·Όμ± λ° μ ν¨μ± κ²μ¬ κ°μ νμμ λ ₯ νλμ λ€μ μ¬νλ€μ μΆκ°νλ κ²μ΄ μ’μ΅λλ€:
- aria-label μμ±
- μ΅λ κΈΈμ΄ μ ν
- μ λ ₯ μ ν¨μ± κ²μ¬
<input {...register(`questions.${index}.options.${optionIndex}.value`)} placeholder="λ¬Έμ₯μ μ λ ₯ν΄μ£ΌμΈμ." + aria-label={`μ¬μ§ μ΅μ ${optionIndex + 1}`} + maxLength={100} className="w-[60%] text-body4 text-black" />
21-23
: λ²νΌ μ κ·Όμ± κ°μ νμμμ λ²νΌμ μ κ·Όμ± μμ±μ μΆκ°ν΄μ£ΌμΈμ:
<button type="button" onClick={() => remove(optionIndex)} + aria-label={`μ΅μ ${optionIndex + 1} μμ `} > <XMark /> </button>
src/shared/assets/icons/FormPicture.tsx (2)
3-6
: Props μΈν°νμ΄μ€μ color μμ± μΆκ° νμμ¬μ¬μ©μ±μ λμ΄κΈ° μν΄ fill μμμ propsλ‘ λ°λ κ²μ΄ μ’μ΅λλ€.
interface Props { width?: string; height?: string; + color?: string; }
18-19
: νλμ½λ©λ μμκ° κ°μ νμνμ¬ νλμ½λ©λ
#909090
μμμ propsλ‘ λ°μ μ μ°νκ² μ²λ¦¬νλ κ²μ΄ μ’μ΅λλ€.- fill="#909090" + fill={color || '#909090'}src/widgets/create-form/ui/FormContainer/index.tsx (1)
50-91
: μ»΄ν¬λνΈ λ§΅ λ‘μ§ μ΅μ νκ° νμν©λλ€.νμ¬ μ»΄ν¬λνΈ λ§΅μ΄ λ§€ λ λλ§λ§λ€ μ¬μμ±λκ³ μμ΅λλ€. μ΄λ₯Ό μ»΄ν¬λνΈ μΈλΆλ‘ μ΄λνμ¬ μ±λ₯μ κ°μ ν μ μμ΅λλ€.
+const COMPONENT_MAP: Record<string, React.FC<{ + fields: any; + remove: any; + register: any; + index: number; +}>> = { + SENTENCE: TextOption, + CHECKBOX: CheckBoxOption, + DROPDOWN: DropDownOption, + MULTIPLE: MultipleChoiceOption, + IMAGE: PictureOption, +}; const FormContainer = ({ options, formRemove, index, register, setValue, control, }: Props) => { - const componentMap: Record<string, JSX.Element | null> = { - SENTENCE: ( - <TextOption - fields={fields} - remove={remove} - register={register} - index={index} - /> - ), - // ... other components - };src/entities/create-exhibition/ui/ExpoInput/index.tsx (1)
Line range hint
114-123
: νλ μΆκ° μ νμ μμ μ± κ°νκ° νμν©λλ€.append ν¨μμ μ λ¬λλ κ°μ²΄μ νμ μ λͺ μμ μΌλ‘ μ μνμ¬ νμ μμ μ±μ κ°μ ν μ μμ΅λλ€.
+type FieldData = { + title: string; + startedAt: string; + endedAt: string; + category?: 'CHOICE'; +}; <AddItemButton onClick={() => - append({ + append<FieldData>({ title: '', startedAt: '', endedAt: '', ...(fieldName === 'trainings' ? { category: 'CHOICE' } : {}), }) } />src/shared/assets/icons/ArrowUp.tsx (1)
3-3
: νμ μ μλ₯Ό μΆκ°ν΄μ£ΌμΈμ.μ»΄ν¬λνΈμ propsμ λν νμ μ μκ° λλ½λμμ΅λλ€. νμ μμ μ±μ μν΄ λ€μκ³Ό κ°μ΄ μΈν°νμ΄μ€λ₯Ό μΆκ°νλ κ²μ μΆμ²λ립λλ€:
+interface ArrowUpProps { + fill?: string; +} -const ArrowUp = ({ fill = '#121212' }) => { +const ArrowUp = ({ fill = '#121212' }: ArrowUpProps) => {
π Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
π Files selected for processing (33)
src/app/(pages)/create-form/page.tsx
(1 hunks)src/entities/create-exhibition/ui/ExpoInput/index.tsx
(3 hunks)src/entities/create-form/index.tsx
(1 hunks)src/entities/create-form/ui/CheckBoxOption/index.tsx
(1 hunks)src/entities/create-form/ui/CreateFormButton/index.tsx
(1 hunks)src/entities/create-form/ui/DeleteButton/index.tsx
(1 hunks)src/entities/create-form/ui/DropDownOption/index.tsx
(1 hunks)src/entities/create-form/ui/FormTitle/index.tsx
(1 hunks)src/entities/create-form/ui/FormTypeSelect/index.tsx
(1 hunks)src/entities/create-form/ui/MultipleChoiceOption/index.tsx
(1 hunks)src/entities/create-form/ui/PictureOption/index.tsx
(1 hunks)src/entities/create-form/ui/RequiredToggle/index.tsx
(1 hunks)src/entities/create-form/ui/TextOption/index.tsx
(1 hunks)src/shared/assets/icons/ArrowUp.tsx
(2 hunks)src/shared/assets/icons/CheckBoxIcon.tsx
(1 hunks)src/shared/assets/icons/DropDown.tsx
(1 hunks)src/shared/assets/icons/FormPicture.tsx
(1 hunks)src/shared/assets/icons/MultipleChoic.tsx
(1 hunks)src/shared/assets/icons/Trash.tsx
(2 hunks)src/shared/assets/icons/Typing.tsx
(1 hunks)src/shared/assets/icons/index.mdx
(2 hunks)src/shared/assets/icons/index.tsx
(1 hunks)src/shared/assets/svg/Circle.tsx
(1 hunks)src/shared/assets/svg/Squere.tsx
(1 hunks)src/shared/assets/svg/index.tsx
(1 hunks)src/shared/types/create-form/type.ts
(1 hunks)src/shared/ui/AddItemButton/index.tsx
(1 hunks)src/shared/ui/ToggleButton/index.tsx
(1 hunks)src/shared/ui/index.tsx
(1 hunks)src/views/create-form/index.tsx
(1 hunks)src/views/create-form/model/selectOptionData.tsx
(1 hunks)src/views/create-form/ui/createForm/index.tsx
(1 hunks)src/widgets/create-form/ui/FormContainer/index.tsx
(1 hunks)
β Files skipped from review due to trivial changes (7)
- src/views/create-form/index.tsx
- src/shared/assets/svg/Circle.tsx
- src/shared/assets/icons/DropDown.tsx
- src/app/(pages)/create-form/page.tsx
- src/shared/assets/icons/Typing.tsx
- src/shared/assets/svg/Squere.tsx
- src/shared/assets/icons/CheckBoxIcon.tsx
π Additional comments (6)
src/shared/assets/svg/index.tsx (1)
2-3
: λ΄λ³΄λ΄κΈ° ν¨ν΄μ΄ μΌκ΄μ± μκ² μμ±λμμ΅λλ€.λ°°λ΄(barrel) ν¨ν΄μ μ¬μ©νμ¬ SVG μ»΄ν¬λνΈλ€μ κΉλνκ² λ΄λ³΄λ΄κ³ μμ΅λλ€. μ΄λ μ’μ λ°©μμ λλ€.
src/shared/ui/index.tsx (1)
7-8
: λ³κ²½μ¬νμ΄ μ μ ν©λλ€.곡μ UI μ»΄ν¬λνΈμ λ΄λ³΄λ΄κΈ°κ° μΌκ΄λ ν¨ν΄μ λ°λ₯΄κ³ μμ΅λλ€.
src/shared/assets/icons/Trash.tsx (1)
Line range hint
3-14
: ꡬνμ΄ μ λμμ΅λλ€!color propμ ν΅ν λμ μμ μ²λ¦¬κ° μ ꡬνλμ΄ μμ΅λλ€.
src/views/create-form/ui/createForm/index.tsx (1)
65-69
: λΉ νΌ μΆκ° μ μ ν¨μ± κ²μ¬ νμμλ‘μ΄ νΌ νλ μΆκ° μ κΈ°λ³Έκ°μ λν μ ν¨μ± κ²μ¬κ° νμν©λλ€.
<CreateFormButton onClick={() => - append({ title: '', formType: 'SENTENCE', options: [] }) + append({ + title: '', + formType: 'SENTENCE', + options: [], + }, { + shouldValidate: true + }) } />src/shared/assets/icons/index.mdx (1)
26-29
: μμ΄μ½ μΆκ°κ° μ μ ν μ΄λ£¨μ΄μ‘μ΅λλ€.νΌ κΈ°λ₯μ νμν μλ‘μ΄ μμ΄μ½λ€μ΄ μ μΆκ°λμμ΅λλ€.
Also applies to: 71-74
src/shared/assets/icons/ArrowUp.tsx (1)
14-14
: λμ fill μμ± κ΅¬νμ΄ μ λμμ΅λλ€!propsλ₯Ό ν΅ν΄ fill μμμ λμ μΌλ‘ λ³κ²½ν μ μλλ‘ κ΅¬νν κ²μ΄ μ’μ΅λλ€. μ΄λ₯Ό ν΅ν΄ μ»΄ν¬λνΈμ μ¬μ¬μ©μ±μ΄ ν₯μλμμ΅λλ€.
@@ -1 +1,3 @@ | |||
export { default as Logo } from './Logo'; | |||
export { default as Squere } from './Squere'; |
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.
'Squere' μ»΄ν¬λνΈ μ΄λ¦μ μ€νλ₯Ό μμ ν΄ μ£ΌμΈμ.
'Squere'λ 'Square'μ μ€νλ‘ λ³΄μ λλ€. μ»΄ν¬λνΈ μ΄λ¦κ³Ό νμΌ μ΄λ¦μ λͺ¨λ μ¬λ°λ₯Έ μμ΄ μ² μλ‘ μμ νλ κ²μ΄ μ’κ² μ΅λλ€.
λ€μκ³Ό κ°μ΄ μμ ν΄ μ£ΌμΈμ:
-export { default as Squere } from './Squere';
+export { default as Square } from './Square';
κ΄λ ¨ νμΌλͺ
λ Squere.tsx
μμ Square.tsx
λ‘ λ³κ²½μ΄ νμν©λλ€.
Committable suggestion skipped: line range outside the PR's diff.
const RequiredToggle = () => { | ||
return ( | ||
<label className="flex items-center gap-6"> | ||
<p className="text-caption2 text-black">νμ</p> | ||
<ToggleButton /> | ||
</label> | ||
); | ||
}; |
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.
π οΈ Refactor suggestion
μν κ΄λ¦¬ λ° μ κ·Όμ± κ°μ μ΄ νμν©λλ€.
νμ¬ κ΅¬νμλ λ€μκ³Ό κ°μ λ¬Έμ κ° μμ΅λλ€:
- ToggleButtonμ μνλ₯Ό μ μ΄νκ±°λ μ½μ μ μμ΅λλ€
- onChange νΈλ€λ¬κ° λλ½λμμ΅λλ€
- μ κ·Όμ± μμ±μ΄ λΆμ‘±ν©λλ€
λ€μκ³Ό κ°μ΄ μμ νλ κ²μ μ μν©λλ€:
-const RequiredToggle = () => {
+interface Props {
+ isRequired: boolean;
+ onChange: (isRequired: boolean) => void;
+}
+
+const RequiredToggle = ({ isRequired, onChange }: Props) => {
return (
- <label className="flex items-center gap-6">
+ <label className="flex items-center gap-6" role="switch" aria-checked={isRequired}>
<p className="text-caption2 text-black">νμ</p>
- <ToggleButton />
+ <ToggleButton checked={isRequired} onChange={onChange} />
</label>
);
};
π Committable suggestion
βΌοΈ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const RequiredToggle = () => { | |
return ( | |
<label className="flex items-center gap-6"> | |
<p className="text-caption2 text-black">νμ</p> | |
<ToggleButton /> | |
</label> | |
); | |
}; | |
interface Props { | |
isRequired: boolean; | |
onChange: (isRequired: boolean) => void; | |
} | |
const RequiredToggle = ({ isRequired, onChange }: Props) => { | |
return ( | |
<label className="flex items-center gap-6" role="switch" aria-checked={isRequired}> | |
<p className="text-caption2 text-black">νμ</p> | |
<ToggleButton checked={isRequired} onChange={onChange} /> | |
</label> | |
); | |
}; |
const DeleteButton = ({ onClick }: Props) => { | ||
return ( | ||
<button onClick={onClick} className="flex items-center gap-2"> | ||
<Trash color="#BDBDBD" /> | ||
<p className="text-caption2 text-gray-300">λ²λ¦¬κΈ°</p> | ||
</button> | ||
); | ||
}; |
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.
π οΈ Refactor suggestion
λ²νΌμ μ κ·Όμ±κ³Ό μνΈμμ© μνλ₯Ό κ°μ ν΄μΌ ν©λλ€.
λ€μ μ¬νλ€μ΄ κ°μ λμ΄μΌ ν©λλ€:
- button νμ μμ± λλ½
- μ κ·Όμ± μμ± λλ½
- hover/focus μν μ€νμΌ λλ½
λ€μκ³Ό κ°μ΄ μμ νλ κ²μ μ μν©λλ€:
const DeleteButton = ({ onClick }: Props) => {
return (
<button
+ type="button"
+ aria-label="νλͺ© μμ "
- className="flex items-center gap-2"
+ className="flex items-center gap-2 hover:opacity-80 focus:outline-none focus:ring-2 focus:ring-gray-300 rounded"
onClick={onClick}
>
<Trash color="#BDBDBD" />
<p className="text-caption2 text-gray-300">λ²λ¦¬κΈ°</p>
</button>
);
};
π Committable suggestion
βΌοΈ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const DeleteButton = ({ onClick }: Props) => { | |
return ( | |
<button onClick={onClick} className="flex items-center gap-2"> | |
<Trash color="#BDBDBD" /> | |
<p className="text-caption2 text-gray-300">λ²λ¦¬κΈ°</p> | |
</button> | |
); | |
}; | |
const DeleteButton = ({ onClick }: Props) => { | |
return ( | |
<button | |
type="button" | |
aria-label="νλͺ© μμ " | |
className="flex items-center gap-2 hover:opacity-80 focus:outline-none focus:ring-2 focus:ring-gray-300 rounded" | |
onClick={onClick} | |
> | |
<Trash color="#BDBDBD" /> | |
<p className="text-caption2 text-gray-300">λ²λ¦¬κΈ°</p> | |
</button> | |
); | |
}; |
const AddItemButton = ({ onClick }: AddItemButtonProps) => ( | ||
<button | ||
type="button" | ||
className="mx-auto flex items-center gap-5" | ||
onClick={onClick} | ||
> | ||
<Plus fill="#448FFF" /> | ||
<div className="text-body3 text-main-600">μΆκ°νκΈ°</div> | ||
</button> | ||
); |
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.
π οΈ Refactor suggestion
μ κ·Όμ±κ³Ό μΌκ΄μ± κ°μ μ΄ νμν©λλ€.
λ€μ μ¬νλ€μ΄ κ°μ λμ΄μΌ ν©λλ€:
- μ κ·Όμ± μμ± λλ½
- hover/focus μν μ€νμΌ λλ½
- ν μ€νΈμ div λμ p νκ·Έ μ¬μ© νμ (μΌκ΄μ±)
λ€μκ³Ό κ°μ΄ μμ νλ κ²μ μ μν©λλ€:
const AddItemButton = ({ onClick }: AddItemButtonProps) => (
<button
type="button"
+ aria-label="νλͺ© μΆκ°"
- className="mx-auto flex items-center gap-5"
+ className="mx-auto flex items-center gap-5 hover:opacity-80 focus:outline-none focus:ring-2 focus:ring-main-600 rounded"
onClick={onClick}
>
<Plus fill="#448FFF" />
- <div className="text-body3 text-main-600">μΆκ°νκΈ°</div>
+ <p className="text-body3 text-main-600">μΆκ°νκΈ°</p>
</button>
);
π Committable suggestion
βΌοΈ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const AddItemButton = ({ onClick }: AddItemButtonProps) => ( | |
<button | |
type="button" | |
className="mx-auto flex items-center gap-5" | |
onClick={onClick} | |
> | |
<Plus fill="#448FFF" /> | |
<div className="text-body3 text-main-600">μΆκ°νκΈ°</div> | |
</button> | |
); | |
const AddItemButton = ({ onClick }: AddItemButtonProps) => ( | |
<button | |
type="button" | |
aria-label="νλͺ© μΆκ°" | |
className="mx-auto flex items-center gap-5 hover:opacity-80 focus:outline-none focus:ring-2 focus:ring-main-600 rounded" | |
onClick={onClick} | |
> | |
<Plus fill="#448FFF" /> | |
<p className="text-body3 text-main-600">μΆκ°νκΈ°</p> | |
</button> | |
); |
<button | ||
onClick={onClick} | ||
className="flex w-fit items-center gap-[10px] rounded-sm bg-main-300 px-6 py-3" | ||
> | ||
<Plus fill="#FFF" /> | ||
<p className="text-h4 text-white">μΆκ°νκΈ°</p> | ||
</button> | ||
); |
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.
π οΈ Refactor suggestion
μ κ·Όμ±κ³Ό μ μ§λ³΄μμ± κ°μ μ΄ νμν©λλ€.
- λ²νΌμ aria-labelμ΄ μμ΅λλ€.
- ν μ€νΈκ° νλμ½λ©λμ΄ μμ΅λλ€.
<button
onClick={onClick}
+ aria-label="νΌ νλͺ© μΆκ°"
className="flex w-fit items-center gap-[10px] rounded-sm bg-main-300 px-6 py-3"
>
<Plus fill="#FFF" />
- <p className="text-h4 text-white">μΆκ°νκΈ°</p>
+ <p className="text-h4 text-white">{FORM_BUTTON_LABELS.ADD}</p>
</button>
μμ νμΌ μμ±μ μΆμ²λ립λλ€:
// constants.ts
export const FORM_BUTTON_LABELS = {
ADD: 'μΆκ°νκΈ°'
} as const;
import React from 'react'; | ||
|
||
const MultipleChoic = () => { | ||
return ( | ||
<svg | ||
xmlns="http://www.w3.org/2000/svg" | ||
width="24" | ||
height="24" | ||
viewBox="0 0 24 24" | ||
fill="none" | ||
> | ||
<path | ||
d="M12 2.25C10.0716 2.25 8.18657 2.82183 6.58319 3.89317C4.97982 4.96451 3.73013 6.48726 2.99218 8.26884C2.25422 10.0504 2.06114 12.0108 2.43735 13.9021C2.81355 15.7934 3.74215 17.5307 5.10571 18.8943C6.46928 20.2579 8.20656 21.1865 10.0979 21.5627C11.9892 21.9389 13.9496 21.7458 15.7312 21.0078C17.5127 20.2699 19.0355 19.0202 20.1068 17.4168C21.1782 15.8134 21.75 13.9284 21.75 12C21.7473 9.41498 20.7192 6.93661 18.8913 5.10872C17.0634 3.28084 14.585 2.25273 12 2.25ZM12 20.25C10.3683 20.25 8.77326 19.7661 7.41655 18.8596C6.05984 17.9531 5.00242 16.6646 4.378 15.1571C3.75358 13.6496 3.5902 11.9908 3.90853 10.3905C4.22685 8.79016 5.01259 7.32015 6.16637 6.16637C7.32016 5.01259 8.79017 4.22685 10.3905 3.90852C11.9909 3.59019 13.6497 3.75357 15.1571 4.37799C16.6646 5.00242 17.9531 6.05984 18.8596 7.41655C19.7661 8.77325 20.25 10.3683 20.25 12C20.2475 14.1873 19.3775 16.2843 17.8309 17.8309C16.2843 19.3775 14.1873 20.2475 12 20.25ZM16.2806 9.96937C16.3504 10.039 16.4057 10.1217 16.4434 10.2128C16.4812 10.3038 16.5006 10.4014 16.5006 10.5C16.5006 10.5986 16.4812 10.6962 16.4434 10.7872C16.4057 10.8783 16.3504 10.961 16.2806 11.0306L12.5306 14.7806C12.461 14.8504 12.3783 14.9057 12.2872 14.9434C12.1962 14.9812 12.0986 15.0006 12 15.0006C11.9014 15.0006 11.8038 14.9812 11.7128 14.9434C11.6218 14.9057 11.539 14.8504 11.4694 14.7806L7.71938 11.0306C7.57865 10.8899 7.49959 10.699 7.49959 10.5C7.49959 10.301 7.57865 10.1101 7.71938 9.96937C7.86011 9.82864 8.05098 9.74958 8.25 9.74958C8.44903 9.74958 8.6399 9.82864 8.78063 9.96937L12 13.1897L15.2194 9.96937C15.289 9.89964 15.3718 9.84432 15.4628 9.80658C15.5538 9.76884 15.6514 9.74941 15.75 9.74941C15.8486 9.74941 15.9462 9.76884 16.0372 9.80658C16.1283 9.84432 16.211 9.89964 16.2806 9.96937Z" | ||
fill="#909090" | ||
/> | ||
</svg> | ||
); | ||
}; | ||
|
||
export default MultipleChoic; |
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.
π οΈ Refactor suggestion
μ»΄ν¬λνΈ μ΄λ¦ λ° μ¬μ¬μ©μ± κ°μ νμ
- νμΌλͺ μ΄ "MultipleChoic"μμ "MultipleChoice"λ‘ μμ λμ΄μΌ ν©λλ€.
- FormPicture μ»΄ν¬λνΈμ κ°μ΄ width, height, color propsλ₯Ό μΆκ°νλ©΄ μ¬μ¬μ©μ±μ΄ ν₯μλ κ² κ°μ΅λλ€.
-const MultipleChoic = () => {
+interface Props {
+ width?: string;
+ height?: string;
+ color?: string;
+}
+
+const MultipleChoice = ({ width = '24', height = '24', color = '#909090' }: Props) => {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
- width="24"
- height="24"
+ width={width}
+ height={height}
viewBox="0 0 24 24"
fill="none"
>
<path
d="M12 2.25C10.0716 2.25 8.18657 2.82183 6.58319 3.89317C4.97982 4.96451 3.73013 6.48726 2.99218 8.26884C2.25422 10.0504 2.06114 12.0108 2.43735 13.9021C2.81355 15.7934 3.74215 17.5307 5.10571 18.8943C6.46928 20.2579 8.20656 21.1865 10.0979 21.5627C11.9892 21.9389 13.9496 21.7458 15.7312 21.0078C17.5127 20.2699 19.0355 19.0202 20.1068 17.4168C21.1782 15.8134 21.75 13.9284 21.75 12C21.7473 9.41498 20.7192 6.93661 18.8913 5.10872C17.0634 3.28084 14.585 2.25273 12 2.25ZM12 20.25C10.3683 20.25 8.77326 19.7661 7.41655 18.8596C6.05984 17.9531 5.00242 16.6646 4.378 15.1571C3.75358 13.6496 3.5902 11.9908 3.90853 10.3905C4.22685 8.79016 5.01259 7.32015 6.16637 6.16637C7.32016 5.01259 8.79017 4.22685 10.3905 3.90852C11.9909 3.59019 13.6497 3.75357 15.1571 4.37799C16.6646 5.00242 17.9531 6.05984 18.8596 7.41655C19.7661 8.77325 20.25 10.3683 20.25 12C20.2475 14.1873 19.3775 16.2843 17.8309 17.8309C16.2843 19.3775 14.1873 20.2475 12 20.25ZM16.2806 9.96937C16.3504 10.039 16.4057 10.1217 16.4434 10.2128C16.4812 10.3038 16.5006 10.4014 16.5006 10.5C16.5006 10.5986 16.4812 10.6962 16.4434 10.7872C16.4057 10.8783 16.3504 10.961 16.2806 11.0306L12.5306 14.7806C12.461 14.8504 12.3783 14.9057 12.2872 14.9434C12.1962 14.9812 12.0986 15.0006 12 15.0006C11.9014 15.0006 11.8038 14.9812 11.7128 14.9434C11.6218 14.9057 11.539 14.8504 11.4694 14.7806L7.71938 11.0306C7.57865 10.8899 7.49959 10.699 7.49959 10.5C7.49959 10.301 7.57865 10.1101 7.71938 9.96937C7.86011 9.82864 8.05098 9.74958 8.25 9.74958C8.44903 9.74958 8.6399 9.82864 8.78063 9.96937L12 13.1897L15.2194 9.96937C15.289 9.89964 15.3718 9.84432 15.4628 9.80658C15.5538 9.76884 15.6514 9.74941 15.75 9.74941C15.8486 9.74941 15.9462 9.76884 16.0372 9.80658C16.1283 9.84432 16.211 9.89964 16.2806 9.96937Z"
- fill="#909090"
+ fill={color}
/>
</svg>
);
};
-export default MultipleChoic;
+export default MultipleChoice;
π Committable suggestion
βΌοΈ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
import React from 'react'; | |
const MultipleChoic = () => { | |
return ( | |
<svg | |
xmlns="http://www.w3.org/2000/svg" | |
width="24" | |
height="24" | |
viewBox="0 0 24 24" | |
fill="none" | |
> | |
<path | |
d="M12 2.25C10.0716 2.25 8.18657 2.82183 6.58319 3.89317C4.97982 4.96451 3.73013 6.48726 2.99218 8.26884C2.25422 10.0504 2.06114 12.0108 2.43735 13.9021C2.81355 15.7934 3.74215 17.5307 5.10571 18.8943C6.46928 20.2579 8.20656 21.1865 10.0979 21.5627C11.9892 21.9389 13.9496 21.7458 15.7312 21.0078C17.5127 20.2699 19.0355 19.0202 20.1068 17.4168C21.1782 15.8134 21.75 13.9284 21.75 12C21.7473 9.41498 20.7192 6.93661 18.8913 5.10872C17.0634 3.28084 14.585 2.25273 12 2.25ZM12 20.25C10.3683 20.25 8.77326 19.7661 7.41655 18.8596C6.05984 17.9531 5.00242 16.6646 4.378 15.1571C3.75358 13.6496 3.5902 11.9908 3.90853 10.3905C4.22685 8.79016 5.01259 7.32015 6.16637 6.16637C7.32016 5.01259 8.79017 4.22685 10.3905 3.90852C11.9909 3.59019 13.6497 3.75357 15.1571 4.37799C16.6646 5.00242 17.9531 6.05984 18.8596 7.41655C19.7661 8.77325 20.25 10.3683 20.25 12C20.2475 14.1873 19.3775 16.2843 17.8309 17.8309C16.2843 19.3775 14.1873 20.2475 12 20.25ZM16.2806 9.96937C16.3504 10.039 16.4057 10.1217 16.4434 10.2128C16.4812 10.3038 16.5006 10.4014 16.5006 10.5C16.5006 10.5986 16.4812 10.6962 16.4434 10.7872C16.4057 10.8783 16.3504 10.961 16.2806 11.0306L12.5306 14.7806C12.461 14.8504 12.3783 14.9057 12.2872 14.9434C12.1962 14.9812 12.0986 15.0006 12 15.0006C11.9014 15.0006 11.8038 14.9812 11.7128 14.9434C11.6218 14.9057 11.539 14.8504 11.4694 14.7806L7.71938 11.0306C7.57865 10.8899 7.49959 10.699 7.49959 10.5C7.49959 10.301 7.57865 10.1101 7.71938 9.96937C7.86011 9.82864 8.05098 9.74958 8.25 9.74958C8.44903 9.74958 8.6399 9.82864 8.78063 9.96937L12 13.1897L15.2194 9.96937C15.289 9.89964 15.3718 9.84432 15.4628 9.80658C15.5538 9.76884 15.6514 9.74941 15.75 9.74941C15.8486 9.74941 15.9462 9.76884 16.0372 9.80658C16.1283 9.84432 16.211 9.89964 16.2806 9.96937Z" | |
fill="#909090" | |
/> | |
</svg> | |
); | |
}; | |
export default MultipleChoic; | |
import React from 'react'; | |
interface Props { | |
width?: string; | |
height?: string; | |
color?: string; | |
} | |
const MultipleChoice = ({ width = '24', height = '24', color = '#909090' }: Props) => { | |
return ( | |
<svg | |
xmlns="http://www.w3.org/2000/svg" | |
width={width} | |
height={height} | |
viewBox="0 0 24 24" | |
fill="none" | |
> | |
<path | |
d="M12 2.25C10.0716 2.25 8.18657 2.82183 6.58319 3.89317C4.97982 4.96451 3.73013 6.48726 2.99218 8.26884C2.25422 10.0504 2.06114 12.0108 2.43735 13.9021C2.81355 15.7934 3.74215 17.5307 5.10571 18.8943C6.46928 20.2579 8.20656 21.1865 10.0979 21.5627C11.9892 21.9389 13.9496 21.7458 15.7312 21.0078C17.5127 20.2699 19.0355 19.0202 20.1068 17.4168C21.1782 15.8134 21.75 13.9284 21.75 12C21.7473 9.41498 20.7192 6.93661 18.8913 5.10872C17.0634 3.28084 14.585 2.25273 12 2.25ZM12 20.25C10.3683 20.25 8.77326 19.7661 7.41655 18.8596C6.05984 17.9531 5.00242 16.6646 4.378 15.1571C3.75358 13.6496 3.5902 11.9908 3.90853 10.3905C4.22685 8.79016 5.01259 7.32015 6.16637 6.16637C7.32016 5.01259 8.79017 4.22685 10.3905 3.90852C11.9909 3.59019 13.6497 3.75357 15.1571 4.37799C16.6646 5.00242 17.9531 6.05984 18.8596 7.41655C19.7661 8.77325 20.25 10.3683 20.25 12C20.2475 14.1873 19.3775 16.2843 17.8309 17.8309C16.2843 19.3775 14.1873 20.2475 12 20.25ZM16.2806 9.96937C16.3504 10.039 16.4057 10.1217 16.4434 10.2128C16.4812 10.3038 16.5006 10.4014 16.5006 10.5C16.5006 10.5986 16.4812 10.6962 16.4434 10.7872C16.4057 10.8783 16.3504 10.961 16.2806 11.0306L12.5306 14.7806C12.461 14.8504 12.3783 14.9057 12.2872 14.9434C12.1962 14.9812 12.0986 15.0006 12 15.0006C11.9014 15.0006 11.8038 14.9812 11.7128 14.9434C11.6218 14.9057 11.539 14.8504 11.4694 14.7806L7.71938 11.0306C7.57865 10.8899 7.49959 10.699 7.49959 10.5C7.49959 10.301 7.57865 10.1101 7.71938 9.96937C7.86011 9.82864 8.05098 9.74958 8.25 9.74958C8.44903 9.74958 8.6399 9.82864 8.78063 9.96937L12 13.1897L15.2194 9.96937C15.289 9.89964 15.3718 9.84432 15.4628 9.80658C15.5538 9.76884 15.6514 9.74941 15.75 9.74941C15.8486 9.74941 15.9462 9.76884 16.0372 9.80658C16.1283 9.84432 16.211 9.89964 16.2806 9.96937Z" | |
fill={color} | |
/> | |
</svg> | |
); | |
}; | |
export default MultipleChoice; |
const onSubmit = (data: FormValues) => { | ||
const formattedData = data.questions.map((question) => ({ | ||
title: question.title, | ||
formType: question.formType, | ||
jsonData: JSON.stringify( | ||
question.options.reduce( | ||
(acc, option, index) => { | ||
acc[(index + 1).toString()] = option.value; | ||
return acc; | ||
}, | ||
{} as Record<string, string>, | ||
), | ||
), | ||
})); | ||
|
||
console.log(formattedData); | ||
// μλ²μ μ μ‘νλ μ½λ μΆκ° κ°λ₯ | ||
}; |
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.
π οΈ Refactor suggestion
onSubmit ν¨μ κ°μ νμ
- νλ‘λμ μ½λμμλ console.logλ₯Ό μ κ±°ν΄μΌ ν©λλ€.
- μλ² μ μΆ λ‘μ§ κ΅¬νμ΄ νμν©λλ€.
- μλ¬ μ²λ¦¬κ° λλ½λμ΄ μμ΅λλ€.
const onSubmit = (data: FormValues) => {
+ try {
const formattedData = data.questions.map((question) => ({
title: question.title,
formType: question.formType,
jsonData: JSON.stringify(
question.options.reduce(
(acc, option, index) => {
acc[(index + 1).toString()] = option.value;
return acc;
},
{} as Record<string, string>,
),
),
}));
- console.log(formattedData);
- // μλ²μ μ μ‘νλ μ½λ μΆκ° κ°λ₯
+ // TODO: API νΈμΆ ꡬν
+ return await submitForm(formattedData);
+ } catch (error) {
+ // TODO: μλ¬ μ²λ¦¬ ꡬν
+ console.error('νΌ μ μΆ μ€ μ€λ₯ λ°μ:', error);
+ throw error;
+ }
};
Committable suggestion skipped: line range outside the PR's diff.
<button | ||
type="button" | ||
onClick={() => setIsOpen(!isOpen)} | ||
className="flex w-full items-center justify-between rounded-md border-1 border-solid border-gray-100 bg-white px-3 py-[10px]" | ||
> | ||
<div className="flex items-center"> | ||
{selectedOption?.icon && ( | ||
<span className="mr-2">{selectedOption.icon}</span> | ||
)} | ||
<span className="text-h5 text-gray-500">{selectedOption?.label}</span> | ||
</div> | ||
{isOpen ? <ArrowUp fill="#909090" /> : <ArrowDown fill="#909090" />} | ||
</button> |
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.
π οΈ Refactor suggestion
λλ‘λ€μ΄ μ κ·Όμ± κ°μ μ΄ νμν©λλ€.
ν€λ³΄λ λ€λΉκ²μ΄μ κ³Ό ARIA μμ±μ΄ λλ½λμ΄ μμ΅λλ€. μ€ν¬λ¦° 리λ μ¬μ©μλ₯Ό μν΄ λ€μ μ¬νλ€μ μΆκ°ν΄μ£ΌμΈμ:
aria-expanded
aria-haspopup
aria-label
- ν€λ³΄λ μ΄λ²€νΈ νΈλ€λ¬
<button
type="button"
onClick={() => setIsOpen(!isOpen)}
+ aria-expanded={isOpen}
+ aria-haspopup="listbox"
+ aria-label="νΌ νμ
μ ν"
+ onKeyDown={(e) => {
+ if (e.key === 'Enter' || e.key === ' ') {
+ setIsOpen(!isOpen);
+ }
+ }}
className="flex w-full items-center justify-between rounded-md border-1 border-solid border-gray-100 bg-white px-3 py-[10px]"
>
π Committable suggestion
βΌοΈ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
<button | |
type="button" | |
onClick={() => setIsOpen(!isOpen)} | |
className="flex w-full items-center justify-between rounded-md border-1 border-solid border-gray-100 bg-white px-3 py-[10px]" | |
> | |
<div className="flex items-center"> | |
{selectedOption?.icon && ( | |
<span className="mr-2">{selectedOption.icon}</span> | |
)} | |
<span className="text-h5 text-gray-500">{selectedOption?.label}</span> | |
</div> | |
{isOpen ? <ArrowUp fill="#909090" /> : <ArrowDown fill="#909090" />} | |
</button> | |
<button | |
type="button" | |
onClick={() => setIsOpen(!isOpen)} | |
aria-expanded={isOpen} | |
aria-haspopup="listbox" | |
aria-label="νΌ νμ μ ν" | |
onKeyDown={(e) => { | |
if (e.key === 'Enter' || e.key === ' ') { | |
setIsOpen(!isOpen); | |
} | |
}} | |
className="flex w-full items-center justify-between rounded-md border-1 border-solid border-gray-100 bg-white px-3 py-[10px]" | |
> | |
<div className="flex items-center"> | |
{selectedOption?.icon && ( | |
<span className="mr-2">{selectedOption.icon}</span> | |
)} | |
<span className="text-h5 text-gray-500">{selectedOption?.label}</span> | |
</div> | |
{isOpen ? <ArrowUp fill="#909090" /> : <ArrowDown fill="#909090" />} | |
</button> |
{isOpen && ( | ||
<ul className="absolute z-30 mt-1 flex w-full flex-col items-center gap-[10px] rounded-md border-1 border-solid border-gray-100 bg-white py-[30px] shadow-lg"> | ||
{options.map((option) => ( | ||
<li | ||
key={option.value} | ||
onClick={() => { | ||
setSelectedOption(option); | ||
setValue(`questions.${index}.formType`, option.value); | ||
setIsOpen(false); | ||
}} | ||
className="flex w-full cursor-pointer items-center justify-center p-2 text-h5 text-gray-500 hover:bg-gray-100" | ||
> | ||
{option.icon && <span className="mr-2">{option.icon}</span>} | ||
{option.label} | ||
</li> | ||
))} | ||
</ul> | ||
)} |
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.
π οΈ Refactor suggestion
λλ‘λ€μ΄ λͺ©λ‘μ μ κ·Όμ±κ³Ό ν€λ³΄λ μΈν°λμ κ°μ μ΄ νμν©λλ€.
λλ‘λ€μ΄ λͺ©λ‘μ μ μ ν ARIA μμ±κ³Ό ν€λ³΄λ λ€λΉκ²μ΄μ μ΄ νμν©λλ€.
-{isOpen && (
+{isOpen && (
+ <ul
+ role="listbox"
+ aria-label="νΌ νμ
μ΅μ
"
+ className="absolute z-30 mt-1 flex w-full flex-col items-center gap-[10px] rounded-md border-1 border-solid border-gray-100 bg-white py-[30px] shadow-lg"
+ >
{options.map((option) => (
<li
key={option.value}
+ role="option"
+ aria-selected={selectedOption?.value === option.value}
+ tabIndex={0}
onClick={() => {
setSelectedOption(option);
setValue(`questions.${index}.formType`, option.value);
setIsOpen(false);
}}
+ onKeyDown={(e) => {
+ if (e.key === 'Enter' || e.key === ' ') {
+ setSelectedOption(option);
+ setValue(`questions.${index}.formType`, option.value);
+ setIsOpen(false);
+ }
+ }}
className="flex w-full cursor-pointer items-center justify-center p-2 text-h5 text-gray-500 hover:bg-gray-100"
>
π Committable suggestion
βΌοΈ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
{isOpen && ( | |
<ul className="absolute z-30 mt-1 flex w-full flex-col items-center gap-[10px] rounded-md border-1 border-solid border-gray-100 bg-white py-[30px] shadow-lg"> | |
{options.map((option) => ( | |
<li | |
key={option.value} | |
onClick={() => { | |
setSelectedOption(option); | |
setValue(`questions.${index}.formType`, option.value); | |
setIsOpen(false); | |
}} | |
className="flex w-full cursor-pointer items-center justify-center p-2 text-h5 text-gray-500 hover:bg-gray-100" | |
> | |
{option.icon && <span className="mr-2">{option.icon}</span>} | |
{option.label} | |
</li> | |
))} | |
</ul> | |
)} | |
{isOpen && ( | |
<ul | |
role="listbox" | |
aria-label="νΌ νμ μ΅μ " | |
className="absolute z-30 mt-1 flex w-full flex-col items-center gap-[10px] rounded-md border-1 border-solid border-gray-100 bg-white py-[30px] shadow-lg" | |
> | |
{options.map((option) => ( | |
<li | |
key={option.value} | |
role="option" | |
aria-selected={selectedOption?.value === option.value} | |
tabIndex={0} | |
onClick={() => { | |
setSelectedOption(option); | |
setValue(`questions.${index}.formType`, option.value); | |
setIsOpen(false); | |
}} | |
onKeyDown={(e) => { | |
if (e.key === 'Enter' || e.key === ' ') { | |
setSelectedOption(option); | |
setValue(`questions.${index}.formType`, option.value); | |
setIsOpen(false); | |
} | |
}} | |
className="flex w-full cursor-pointer items-center justify-center p-2 text-h5 text-gray-500 hover:bg-gray-100" | |
> | |
{option.icon && <span className="mr-2">{option.icon}</span>} | |
{option.label} | |
</li> | |
))} | |
</ul> | |
)} |
const renderOptionComponent = () => { | ||
return selectedOption?.value | ||
? componentMap[selectedOption.value] || null | ||
: null; | ||
}; |
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.
π οΈ Refactor suggestion
renderOptionComponent ν¨μμ νμ μμ μ± κ°μ μ΄ νμν©λλ€.
μ νλ μ΅μ μ valueκ° μ ν¨ν μ»΄ν¬λνΈ νμ μΈμ§ νμΈνλ νμ κ°λκ° νμν©λλ€.
+type ComponentType = keyof typeof COMPONENT_MAP;
+const isValidComponentType = (value: string): value is ComponentType => {
+ return value in COMPONENT_MAP;
+};
const renderOptionComponent = () => {
- return selectedOption?.value
- ? componentMap[selectedOption.value] || null
- : null;
+ if (!selectedOption?.value || !isValidComponentType(selectedOption.value)) {
+ return null;
+ }
+ const Component = COMPONENT_MAP[selectedOption.value];
+ return (
+ <Component
+ fields={fields}
+ remove={remove}
+ register={register}
+ index={index}
+ />
+ );
};
Committable suggestion skipped: line range outside the PR's diff.
π‘ λ°°κ²½ λ° κ°μ
μ μ νΌ μμ± μ μ
π μμ λ΄μ©
Summary by CodeRabbit
μλ‘μ΄ κΈ°λ₯
λ²κ·Έ μμ
κ°μ μ¬ν