[feature] 관리자 지원서 페이지에 설명을 추가한다#563
Conversation
- formData에 description 필드가 없는 상황에서 별도의 description state로 설명 입력값 관리 - textarea 입력 시 JS로 height를 자동 조절하여 내용이 잘리지 않도록 개선 - description 입력값은 저장/전송에는 포함되지 않으며, UI 입력만 지원
✅ Deploy Preview for moadong ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Warning
|
| 파일/경로 | 변경 요약 |
|---|---|
| .../ApplicationEditTab/ApplicationEditTab.styles.ts | FormDescription라는 새로운 styled textarea 컴포넌트 추가 |
| .../ApplicationEditTab/ApplicationEditTab.tsx | description 상태 및 ref, 입력 핸들러, FormDescription textarea 추가 |
| frontend/src/constants/INITIAL_FORM_DATA.ts | INITIAL_FORM_DATA에 description 프로퍼티 추가 |
| frontend/src/mocks/data/mockData.ts | mockData에 description 프로퍼티 추가 |
| frontend/src/types/application.ts | ApplicationFormData 인터페이스에 description 프로퍼티 추가 |
Sequence Diagram(s)
sequenceDiagram
participant Admin as 관리자(사용자)
participant ApplicationEditTab as ApplicationEditTab 컴포넌트
Admin->>ApplicationEditTab: 페이지 진입
Admin->>ApplicationEditTab: 설명 입력란에 텍스트 입력
ApplicationEditTab->>ApplicationEditTab: description 상태 업데이트 및 textarea 높이 조정
Estimated code review effort
2 (60 minutes)
Possibly related PRs
- [feature] 지원서의 설명을 확인할 수 있다. #556: 백엔드에서 지원서 엔티티에 description 필드를 추가하는 PR로, 본 PR의 프론트엔드 변경과 직접적으로 연관되어 있습니다.
Suggested labels
🎨 Design
"""
📜 Recent review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
frontend/src/constants/INITIAL_FORM_DATA.ts(1 hunks)frontend/src/mocks/data/mockData.ts(1 hunks)frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx(4 hunks)frontend/src/types/application.ts(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- frontend/src/mocks/data/mockData.ts
- frontend/src/constants/INITIAL_FORM_DATA.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx
🧰 Additional context used
📓 Path-based instructions (1)
frontend/**/*.{ts,tsx}
Instructions used from:
Sources:
📄 CodeRabbit Inference Engine
- frontend/.cursorrules
🧠 Learnings (1)
frontend/src/types/application.ts (1)
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.702Z
Learning: Applies to frontend/**/*.tsx : Choose field-level or form-level cohesion based on form requirements.
🔇 Additional comments (1)
frontend/src/types/application.ts (1)
51-51: 타입 정의가 명확하고 일관성 있게 추가되었습니다.
ApplicationFormData인터페이스에description속성이 기존 패턴과 일치하게 추가되었습니다. 필수 문자열 타입으로 정의되어 다른 속성들과 일관성을 유지하고 있습니다.
✨ Finishing Touches
- 📝 Generate Docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
🪧 Tips
Chat
There are 3 ways to chat with CodeRabbit:
- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
I pushed a fix in commit <commit_id>, please review it.Explain this complex logic.Open a follow-up GitHub issue for this discussion.
- Files and specific lines of code (under the "Files changed" tab): Tag
@coderabbitaiin a new review comment at the desired location with your query. Examples:@coderabbitai explain this code block.@coderabbitai modularize this function.
- PR comments: Tag
@coderabbitaiin a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.@coderabbitai read src/utils.ts and explain its main purpose.@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.@coderabbitai help me debug CodeRabbit configuration file.
Support
Need help? Create a ticket on our support page for assistance with any issues or questions.
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)
@coderabbitai pauseto pause the reviews on a PR.@coderabbitai resumeto resume the paused reviews.@coderabbitai reviewto trigger an incremental review. This is useful when automatic reviews are disabled for the repository.@coderabbitai full reviewto do a full review from scratch and review all the files again.@coderabbitai summaryto regenerate the summary of the PR.@coderabbitai generate docstringsto generate docstrings for this PR.@coderabbitai generate sequence diagramto generate a sequence diagram of the changes in this PR.@coderabbitai resolveresolve all the CodeRabbit review comments.@coderabbitai configurationto show the current CodeRabbit configuration for the repository.@coderabbitai helpto get help.
Other keywords and placeholders
- Add
@coderabbitai ignoreanywhere in the PR description to prevent this PR from being reviewed. - Add
@coderabbitai summaryto generate the high-level summary at a specific location in the PR description. - Add
@coderabbitaianywhere in the PR title to generate the title automatically.
Documentation and Community
- Visit our Documentation for detailed information on how to use CodeRabbit.
- Join our Discord Community to get help, request features, and share feedback.
- Follow us on X/Twitter for updates and announcements.
There was a problem hiding this comment.
Actionable comments posted: 3
🔭 Outside diff range comments (1)
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx (1)
129-152: handleSubmit에 description 필드 누락 및 타입 정의 수정 필요
handleSubmit에서description을 payload에 포함하지 않아 저장되지 않으며,ApplicationFormData타입에도description필드가 정의되어 있지 않아 컴파일 오류가 발생합니다. 아래 위치를 수정해주세요.• 수정 대상 파일
- frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx
- frontend/src/types/application.ts
• ApplicationEditTab.tsx 예시 변경 (
description추가)const handleSubmit = async () => { if (!clubId) return; const reorderedQuestions = formData.questions.map((q, idx) => ({ ...q, id: idx + 1, })); - const payload: ApplicationFormData = { - ...formData, - questions: reorderedQuestions, - }; + const payload: ApplicationFormData = { + ...formData, + description, // ← description 추가 + questions: reorderedQuestions, + };• types/application.ts 예시 변경 (
description타입 정의 추가)export interface ApplicationFormData { title: string; + description: string; // ← description 필드 추가 questions: Question[]; }이후
createApplication/updateApplication호출부와 백엔드 API 스펙도description지원 여부를 확인해 주세요.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.styles.ts(1 hunks)frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx(4 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
frontend/**/*.{ts,tsx}
Instructions used from:
Sources:
📄 CodeRabbit Inference Engine
- frontend/.cursorrules
frontend/**/*.tsx
Instructions used from:
Sources:
📄 CodeRabbit Inference Engine
- frontend/.cursorrules
🧠 Learnings (2)
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx (9)
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.tsx : Break down broad state management into smaller, focused hooks or contexts.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.tsx : Choose field-level or form-level cohesion based on form requirements.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace magic numbers with named constants for clarity.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.{ts,tsx} : Define constants near related logic or ensure names link them clearly.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.tsx : Colocate simple, localized logic or use inline definitions to reduce context switching.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.tsx : Separate significantly different conditional UI/logic into distinct components.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.tsx : Abstract complex logic/interactions into dedicated components or higher-order components (HOCs).
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use consistent return types for similar functions and hooks.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.tsx : Use component composition instead of props drilling.
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.styles.ts (4)
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.tsx : Choose field-level or form-level cohesion based on form requirements.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.{ts,tsx} : Replace magic numbers with named constants for clarity.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.{ts,tsx} : Define constants near related logic or ensure names link them clearly.
Learnt from: CR
PR: Moadong/moadong#0
File: frontend/.cursorrules:0-0
Timestamp: 2025-07-19T05:09:10.682Z
Learning: Applies to frontend/**/*.{ts,tsx} : Use unique, descriptive names for custom wrappers and functions to avoid ambiguity.
🔇 Additional comments (1)
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx (1)
163-168: 컴포넌트 사용법이 적절합니다.
onInput이벤트 사용과 ref 바인딩이 자동 크기 조절 기능에 적합하게 구현되었습니다.onInput은onChange보다 실시간 반응성이 좋아 이 용도에 적절한 선택입니다.
| export const FormDescription = styled.textarea` | ||
| width: 100%; | ||
| min-height: 120px; | ||
| height: auto; | ||
| resize: none; | ||
| overflow: hidden; | ||
| border: none; | ||
| outline: none; | ||
| margin-bottom: 24px; | ||
| padding: 12px; | ||
|
|
||
| &::placeholder { | ||
| color: #c5c5c5; | ||
| transition: opacity 0.15s; | ||
| } | ||
|
|
||
| &:focus::placeholder { | ||
| opacity: 0; | ||
| } | ||
|
|
||
| &:hover { | ||
| border: 1px solid #ccc; | ||
| } | ||
| `; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
매직 넘버를 명명된 상수로 교체하고 색상 일관성을 개선하세요.
스타일 컴포넌트에서 하드코딩된 값들(120px, 24px, 12px, #c5c5c5, #ccc)을 명명된 상수로 추출해야 합니다. 또한 FormTitle과 동일한 색상값들이 반복되고 있어 일관성을 위해 공통 상수로 관리하는 것이 좋겠습니다.
+const FORM_COLORS = {
+ PLACEHOLDER: '#c5c5c5',
+ BORDER_HOVER: '#ccc',
+} as const;
+
+const FORM_DIMENSIONS = {
+ MIN_HEIGHT: '120px',
+ MARGIN_BOTTOM: '24px',
+ PADDING: '12px',
+} as const;
export const FormDescription = styled.textarea`
width: 100%;
- min-height: 120px;
+ min-height: ${FORM_DIMENSIONS.MIN_HEIGHT};
height: auto;
resize: none;
overflow: hidden;
border: none;
outline: none;
- margin-bottom: 24px;
- padding: 12px;
+ margin-bottom: ${FORM_DIMENSIONS.MARGIN_BOTTOM};
+ padding: ${FORM_DIMENSIONS.PADDING};
&::placeholder {
- color: #c5c5c5;
+ color: ${FORM_COLORS.PLACEHOLDER};
transition: opacity 0.15s;
}
&:focus::placeholder {
opacity: 0;
}
&:hover {
- border: 1px solid #ccc;
+ border: 1px solid ${FORM_COLORS.BORDER_HOVER};
}
`;📝 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.
| export const FormDescription = styled.textarea` | |
| width: 100%; | |
| min-height: 120px; | |
| height: auto; | |
| resize: none; | |
| overflow: hidden; | |
| border: none; | |
| outline: none; | |
| margin-bottom: 24px; | |
| padding: 12px; | |
| &::placeholder { | |
| color: #c5c5c5; | |
| transition: opacity 0.15s; | |
| } | |
| &:focus::placeholder { | |
| opacity: 0; | |
| } | |
| &:hover { | |
| border: 1px solid #ccc; | |
| } | |
| `; | |
| // Define related constants near the styled component for clarity | |
| const FORM_COLORS = { | |
| PLACEHOLDER: '#c5c5c5', | |
| BORDER_HOVER: '#ccc', | |
| } as const; | |
| const FORM_DIMENSIONS = { | |
| MIN_HEIGHT: '120px', | |
| MARGIN_BOTTOM: '24px', | |
| PADDING: '12px', | |
| } as const; | |
| export const FormDescription = styled.textarea` | |
| width: 100%; | |
| min-height: ${FORM_DIMENSIONS.MIN_HEIGHT}; | |
| height: auto; | |
| resize: none; | |
| overflow: hidden; | |
| border: none; | |
| outline: none; | |
| margin-bottom: ${FORM_DIMENSIONS.MARGIN_BOTTOM}; | |
| padding: ${FORM_DIMENSIONS.PADDING}; | |
| &::placeholder { | |
| color: ${FORM_COLORS.PLACEHOLDER}; | |
| transition: opacity 0.15s; | |
| } | |
| &:focus::placeholder { | |
| opacity: 0; | |
| } | |
| &:hover { | |
| border: 1px solid ${FORM_COLORS.BORDER_HOVER}; | |
| } | |
| `; |
🤖 Prompt for AI Agents
In
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.styles.ts
between lines 20 and 43, replace all hardcoded numeric values and color codes
such as 120px, 24px, 12px, #c5c5c5, and #ccc with named constants defined at the
top of the file or in a shared constants file. Ensure that color values used
here match those in FormTitle by referencing the same color constants to
maintain consistency across components.
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx
Outdated
Show resolved
Hide resolved
| const handleFormDescriptionChange = (value: string) => { | ||
| setDescription(value); | ||
| if (descriptionRef.current) { | ||
| descriptionRef.current.style.height = 'auto'; | ||
| descriptionRef.current.style.height = | ||
| descriptionRef.current.scrollHeight + 'px'; | ||
| } | ||
| }; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
복잡한 로직을 추출하고 문자열 연결을 개선하세요.
자동 크기 조절 로직이 상태 업데이트와 혼재되어 있고, 문자열 연결 방식이 일관성이 없습니다. 로직을 분리하고 상수를 사용하여 개선해보세요.
+const UNIT_PX = 'px';
+const AUTO_HEIGHT = 'auto';
+
+const adjustTextareaHeight = (element: HTMLTextAreaElement) => {
+ element.style.height = AUTO_HEIGHT;
+ element.style.height = `${element.scrollHeight}${UNIT_PX}`;
+};
const handleFormDescriptionChange = (value: string) => {
setDescription(value);
if (descriptionRef.current) {
- descriptionRef.current.style.height = 'auto';
- descriptionRef.current.style.height =
- descriptionRef.current.scrollHeight + 'px';
+ adjustTextareaHeight(descriptionRef.current);
}
};🤖 Prompt for AI Agents
In frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx
around lines 83 to 90, the auto-resize logic for the description textarea is
mixed with state update and uses inconsistent string concatenation. Extract the
auto-resize logic into a separate function for clarity, and replace string
concatenation with template literals or constants for consistent and cleaner
code.
oesnuj
left a comment
There was a problem hiding this comment.
아 맞다
방금 생각났는데 저희 CustomTextArea 컴포넌트 이미 만들어뒀었네요..
자동 높이 조절 기능도 들어가 있는데 나중에 교체하시죠
설명 추가 수고하셨습니다~ |

#️⃣연관된 이슈
📝작업 내용
중점적으로 리뷰받고 싶은 부분(선택)
논의하고 싶은 부분(선택)
🫡 참고사항
Summary by CodeRabbit