[feature] 지원서 관리 페이지 디자인을 적용한다#691
Conversation
- 라벨+이미지 구조 - flex로 변경
- position relative로 부모 기준으로 위치설정 - right 설정으로 객관식 박스 안으로 들어가도록 설정
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning
|
| Cohort / File(s) | Summary |
|---|---|
Choice — 삭제 버튼 아이콘화 및 스타일 조정frontend/src/components/application/questionTypes/Choice.tsx, frontend/src/components/application/questionTypes/Choice.styles.ts |
삭제 버튼 텍스트를 SVG 아이콘으로 교체하고 버튼 스타일을 투명/무테 위치 보정으로 변경. 기능 로직 불변. |
QuestionBuilder — DeleteButton 컴포넌트 도입 및 스타일 조정frontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.styles.ts, frontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.tsx |
DeleteButton 스타일 컴포넌트 신규 추가 및 적용. QuestionWrapper 패딩·갭·보더·호버 섀도우 등 레이아웃/스타일 변경. 삭제 버튼에 아이콘 적용. |
CustomTextArea 스타일 업데이트frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts |
Label 색상(#787878) 추가, TextArea 기본 보더색 변경(#f5f5f5), 보더 반경 10px 적용 및 배경 추가. 포커스/에러 로직 유지. |
ApplicationEditTab FormTitle 레이아웃 조정frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.styles.ts |
FormTitle에 폭·패딩·정렬·보더 반경·배경 추가 및 마진 조정. 포맷 정리 외 동작 변경 없음. |
Estimated code review effort
🎯 2 (Simple) | ⏱️ ~10–15 minutes
Assessment against linked issues
| Objective | Addressed | Explanation |
|---|---|---|
| 지원서 관리 페이지 디자인 적용 (MOA-166) | ✅ |
Possibly related issues
- [feature] MOA-166 지원서 관리 페이지 디자인을 적용한다 #662 — 삭제 버튼을 아이콘으로 교체하고 질문 블록 스타일을 변경하는 유사한 UI 변경을 포함함으로 연결 가능.
Possibly related PRs
- [refactor] 지원서 타입 분리 #450 — Choice 관련 UI(삭제 버튼/스타일) 변경과 직접적으로 연관됨.
- [feature] 지원서 질문 추가/삭제 및 장문형 질문 타입 구현 #454 — QuestionBuilder 및 텍스트 영역 스타일 변경과 중첩되는 스타일 수정이 있음.
- [feature & refactor] 객관식 항목 1개 허용 · 필수 입력 UX 개선 · Application 구조 리팩토링 #558 — Choice/QuestionBuilder 파일을 다루는 리팩터/기능 변경과 연관 가능.
Suggested labels
✨ Feature
Suggested reviewers
- oesnuj
- lepitaaar
- Zepelown
Tip
🔌 Remote MCP (Model Context Protocol) integration is now available!
Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.
📜 Recent review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
frontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.tsx(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.tsx
✨ Finishing Touches
- 📝 Generate Docstrings
🧪 Generate unit tests
- Create PR with unit tests
- Post copyable unit tests in a comment
- Commit unit tests in branch
feature/#662-application-form-page-ui-MOA-166
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.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. - 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 the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
Support
Need help? Create a ticket on our support page for assistance with any issues or questions.
CodeRabbit Commands (Invoked using PR/Issue comments)
Type @coderabbitai help to get the list of available commands.
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.
Status, Documentation and Community
- Visit our Status Page to check the current availability of CodeRabbit.
- 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: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/src/components/application/questionTypes/Choice.tsx (1)
110-118: 모든 버튼에 type="button" 명시 및 아이콘 접근성 속성 추가폼 내 기본
submit동작 방지를 위해 네이티브<button>과Styled.DeleteButton에는 반드시type="button"을 명시하고, 아이콘은alt="" aria-hidden="true"로 처리한 뒤 버튼에aria-label을 추가해야 합니다.수정 대상:
- frontend/src/pages/AdminPage/tabs/RecruitEditTab/components/Calendar/Calendar.tsx
• prev/next 월 변경 버튼 (라인 22, 32)- frontend/src/pages/AdminPage/tabs/RecruitEditTab/components/MarkdownEditor/MarkdownEditor.tsx
• 툴바 버튼들 (라인 50–54, 56)- frontend/src/pages/AdminPage/tabs/PhotoEditTab/components/ImagePreview/ImagePreview.tsx
•Styled.DeleteButton(라인 13)- frontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.tsx
•Styled.DeleteButton(라인 139)- frontend/src/components/application/questionTypes/Choice.tsx
•Styled.DeleteButton(라인 111)예시 (Choice.tsx):
@@ -110,7 +110,11 @@ export const Choice = ({ mode, items, ... }) => ( {mode === 'builder' && items.length > MIN_ITEMS && ( <Styled.DeleteButton - onClick={(e) => { + type="button" + aria-label={`항목 ${index + 1} 삭제`} + onClick={(e) => { e.stopPropagation(); handleDeleteItem(index); }} > - <img src={DeleteIcon} /> + <img + src={DeleteIcon} + alt="" + aria-hidden="true" + width={16} + height={16} /> </Styled.DeleteButton> )}추가 누락 검출 스크립트:
rg -nP '<(button|Styled\.DeleteButton)(?![^>]*\btype=)' -C1 --glob '*.tsx'위와 동일한 방식으로 모든 버튼에 대해
type="button",aria-label,alt="" aria-hidden="true"적용을 부탁드립니다.
🧹 Nitpick comments (9)
frontend/src/components/application/questionTypes/Choice.styles.ts (1)
22-29: 상대 위치/오프셋(right: 45px) 대신 플렉스 정렬로 배치 안정화 + 접근성 보완relative + right 오프셋은 컨테이너/폰트/여백 변화에 취약합니다. ItemWrapper가 flex이므로 margin-left: auto로 자연스럽게 오른쪽 정렬하세요. 동시에 터치 목표 최소 크기와 키보드 포커스 링을 추가하면 접근성이 좋아집니다.
적용 제안(diff):
export const DeleteButton = styled.button` - position: relative; - right: 45px; + margin-left: auto; font-size: 0.75rem; - background-color: transparent; - border: none; + background-color: transparent; + border: none; cursor: pointer; + min-width: 32px; + min-height: 32px; + display: inline-flex; + align-items: center; + justify-content: center; + + &:focus-visible { + outline: 2px solid #007bff; + outline-offset: 2px; + } `;추가로, 숫자 값(32px 등)은 디자인 토큰(예: theme.spacing.iconButton)으로 치환하면 유지보수성이 올라갑니다.
frontend/src/components/application/questionTypes/Choice.tsx (1)
8-8: 아이콘은 inline SVG로 렌더링하여 색상/상태 제어 용이성 확보
로 SVG를 넣으면 hover/focus 상태별 컬러 변경이 어렵고 CSS로 제어하기 제한적입니다. SVGR 설정이 있다면 ReactComponent로 임포트하여 스타일/접근성 제어를 단순화하세요.
예시:
import { ReactComponent as DeleteIcon } from '@/assets/images/icons/delete_choice.svg'; // 사용 <DeleteIcon aria-hidden="true" focusable="false" />frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts (2)
16-17: Label 컬러 토닝 변경은 일관적이나, 테마 토큰으로 추출 권장#787878은 반복 사용 가능성이 높은 값입니다. theme.color.textMuted 같은 토큰으로 승격하면 일관성과 유지보수성이 좋아집니다.
29-31: 배경/보더 밝기 조정 좋습니다. 대비/포커스 가시성 확인과 토큰화 제안
- background/border를 #f5f5f5로 낮춘 만큼 주변 배경과의 대비가 충분한지(특히 오류가 아닐 때) 확인하세요.
- &:focus만 있으면 마우스 클릭에도 포커스 스타일이 항상 보입니다. &:focus-visible 병행을 고려하면 키보드 접근성에 더 적합합니다.
- 색상/라운드 값은 디자인 토큰(theme.colors.surfaceF5, theme.radius.l 등)으로 추출 권장.
Also applies to: 39-44
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.styles.ts (2)
4-8: align-items는 input에 효과 없음 — 불필요 속성 제거styled.input에 align-items는 동작하지 않습니다. 의미 없는 선언은 제거하는 편이 낫습니다.
export const FormTitle = styled.input` width: 100%; padding: 10px 12px; - align-items: center; border-radius: 10px; background: var(--f5, #f5f5f5); font-size: 2.5rem; font-weight: 700; border: none; outline: none; margin: 60px 0px 35px 0px;Also applies to: 13-13
28-28: 여백/크기 매직 넘버는 토큰으로 통일margin-top: 40px 등은 theme.spacing.xl 같은 토큰으로 치환하면 수치가 여기저기 흩어지는 문제를 줄일 수 있습니다.
frontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.styles.ts (1)
91-103: 호버 그림자 추가는 👍; 트랜지션으로 시각적 품질 개선 제안hover 시 박스섀도 급변을 완화하려면 transition을 추가하세요. 디자인 토큰과 함께 사용하면 더 일관적입니다.
export const QuestionWrapper = styled.div<{ readOnly?: boolean }>` display: flex; padding: 26px 20px; gap: 20px; border-radius: 10px; border: 1px solid #f0f0f0; pointer-events: ${({ readOnly }) => (readOnly ? 'none' : 'auto')}; cursor: ${({ readOnly }) => (readOnly ? 'not-allowed' : 'auto')}; + transition: box-shadow 0.2s ease, border-color 0.2s ease; &:hover { box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1); } `;frontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.tsx (2)
11-11: SVG 아이콘 import/사용 방식 통일 제안 (SVGR 고려)현재는 파일 URL을 받아
<img src>로 사용하고 있습니다. 프로젝트가 SVGR을 사용 중이라면 ReactComponent로 임포트해 스타일/색상 제어와 접근성 처리가 용이합니다. 아이콘 사용 방식(IMG vs. ReactComponent)을 코드베이스 전반에서 통일하는 것을 권장합니다.예시(옵션):
-import DeleteIcon from '@/assets/images/icons/delete_question.svg'; +import { ReactComponent as DeleteIcon } from '@/assets/images/icons/delete_question.svg';ReactComponent 사용 시:
<Styled.DeleteButton type="button" onClick={() => onRemoveQuestion()}> 삭제 <DeleteIcon aria-hidden /> </Styled.DeleteButton>
139-141: 디자인 스펙 확인: “아이콘만” vs “텍스트+아이콘”PR 요약에는 “삭제 버튼을 이미지(아이콘)로 교체”라고 되어 있으나, 현재 구현은 텍스트("삭제")와 아이콘을 함께 노출합니다. 디자인 의도가 아이콘-only라면 텍스트를 제거하고
aria-label="질문 삭제"를 버튼에 부여하는 방식으로 맞추는 것이 일관됩니다. 확인 부탁드립니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (2)
frontend/src/assets/images/icons/delete_choice.svgis excluded by!**/*.svgfrontend/src/assets/images/icons/delete_question.svgis excluded by!**/*.svg
📒 Files selected for processing (6)
frontend/src/components/application/questionTypes/Choice.styles.ts(1 hunks)frontend/src/components/application/questionTypes/Choice.tsx(2 hunks)frontend/src/components/common/CustomTextArea/CustomTextArea.styles.ts(3 hunks)frontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.styles.ts(1 hunks)frontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.tsx(2 hunks)frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.styles.ts(2 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{ts,tsx}: Replace magic numbers with named constants for clarity.
Replace complex or nested ternary operators with if/else statements or IIFEs for readability.
Assign complex boolean conditions to named variables.
Use consistent return types for similar functions and hooks.
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle).
Use unique, descriptive names for custom wrappers and functions to avoid ambiguity.
Define constants near related logic or ensure names link them clearly.
Files:
frontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.tsxfrontend/src/components/application/questionTypes/Choice.tsxfrontend/src/components/common/CustomTextArea/CustomTextArea.styles.tsfrontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.styles.tsfrontend/src/components/application/questionTypes/Choice.styles.tsfrontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.styles.ts
frontend/**/*.tsx
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.tsx: Abstract complex logic/interactions into dedicated components or higher-order components (HOCs).
Separate significantly different conditional UI/logic into distinct components.
Colocate simple, localized logic or use inline definitions to reduce context switching.
Choose field-level or form-level cohesion based on form requirements.
Break down broad state management into smaller, focused hooks or contexts.
Use component composition instead of props drilling.
Files:
frontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.tsxfrontend/src/components/application/questionTypes/Choice.tsx
🔇 Additional comments (2)
frontend/src/pages/AdminPage/components/QuestionBuilder/QuestionBuilder.tsx (2)
138-142: readOnly 상태에서 삭제 버튼 비노출 처리 Good권한/상태에 따른 파괴적 액션 노출 제어가 명확합니다. 스타일 파일에서 포커스 가시성(focus-visible)만 유지된다면 접근성 측면에서도 적절해 보입니다.
139-141: 검증 결과:onRemoveQuestion은QuestionBuilderProps에서 필수(prop)로 정의되어 있어 optional chaining 없이 직접 호출하는 것이 맞습니다.
frontend/src/types/application.ts23행:onRemoveQuestion: () => void;확인됨ApplicationEditTab.tsx에서 항상 해당 prop을 전달하고 있음 확인됨따라서 별도 수정 없이 현 상태 유지하셔도 됩니다.
#️⃣연관된 이슈
📝작업 내용
title, description
질문 문항
중점적으로 리뷰받고 싶은 부분(선택)
논의하고 싶은 부분(선택)
🫡 참고사항
Summary by CodeRabbit