Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning
|
| Cohort / File(s) | Summary |
|---|---|
API: Applicants deletefrontend/src/apis/applicants/deleteApplicants.ts |
신규 API 모듈 추가. DELETE /api/club/{clubId}/applicant로 { applicantIds } JSON 전송, 응답 에러 메시지 파싱 후 throw, 성공 시 result.data 반환. |
React Query mutation hookfrontend/src/hooks/queries/applicants/useDeleteApplicants.ts |
클럽 ID 기반 삭제 뮤테이션 훅 추가. mutationFn으로 deleteApplicants 호출, 성공 시 ['clubApplicants'] 쿼리 무효화, 에러 로깅. |
ApplicantsTab UI/logicfrontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx |
다중 선택 상태(Map), 전체선택/드롭다운 상태 도입, 상태별/전체 선택 토글 함수, 선택 항목 삭제 확인 후 useDeleteApplicants로 일괄 삭제 처리 및 성공/오류 처리, 행별 체크박스와 헤더의 전체선택/상태선택/삭제 버튼 UI 통합. |
Styles for ApplicantsTabfrontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.styles.ts |
다양한 선택/삭제 관련 스타일 컴포넌트 추가 및 수정(VerticalLine, StatusSelect, DeleteButton, ApplicantAllSelect*, Arrow props 확장 등), 체크박스/드롭다운/아이콘 hover·disabled 상태 정의. |
Sequence Diagram(s)
sequenceDiagram
actor User as 사용자
participant UI as ApplicantsTab (UI)
participant Hook as useDeleteApplicants (React Query)
participant API as deleteApplicants (API)
participant BE as Backend
User->>UI: 다중 선택 / 상태 선택
User->>UI: 삭제 버튼 클릭
UI->>User: 삭제 확인 다이얼로그
alt 삭제 확인
UI->>Hook: mutate({ applicantIds })
Hook->>API: DELETE /api/club/{clubId}/applicant { applicantIds }
API->>BE: HTTP DELETE 요청
BE-->>API: 200 JSON { data }
API-->>Hook: result.data
Hook-->>UI: onSuccess
UI->>UI: 쿼리 무효화(['clubApplicants']) 및 선택 초기화
UI-->>User: 성공 알림
else 취소/오류
Hook-->>UI: onError
UI-->>User: 오류 알림
end
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~25 minutes
Assessment against linked issues
| Objective | Addressed | Explanation |
|---|---|---|
| 동아리 지원자 삭제 기능 구현 (MOA-194) | ✅ |
Assessment against linked issues: Out-of-scope changes
(해당 없음)
Possibly related issues
- [feature] MOA-194 동아리 지원자를 삭제한다 #694 — 동일 기능(지원자 삭제) 범주로 직접 관련.
- [feature] MOA-196 동아리 지원자를 여러명을 삭제할 수 있다 #696 — 백엔드의 일괄 삭제 API 계약과 연동되는 프론트 변경과 관련.
Possibly related PRs
- [refactor] 지원자를 여러명 삭제할 수 있다. #699 — 백엔드가 applicantIds 배열을 받는 일괄 삭제 계약과 직접 연계됨.
- [release] v1.1.0 #676 — ApplicantsTab UI/스타일·선택 로직 변경이 겹침.
- [feature] 동아리 관리자는 지원자를 확인할 수 있다. #612 — 지원자 목록 훅/컴포넌트 기반 위에 삭제 기능이 추가된 연속성 있음.
Suggested labels
🎨 Design
Suggested reviewers
- seongwon030
- oesnuj
- 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/tabs/ApplicantsTab/ApplicantsTab.tsx(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.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/#694-delete-application-MOA-194
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: 6
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx (1)
316-327: 날짜 포맷팅 로직을 유틸 함수로 분리IIFE를 사용한 날짜 포맷팅이 컴포넌트 내부에 있어 가독성이 떨어집니다. date-fns 라이브러리가 이미 설치되어 있으므로 이를 활용하거나 유틸 함수로 분리하는 것이 좋습니다.
date-fns를 사용한 개선:
import { format } from 'date-fns'; // 사용처 <Styled.ApplicantTableCol> {format(new Date(item.createdAt), 'yyyy-MM-dd')} </Styled.ApplicantTableCol>또는 유틸 함수로 분리:
// utils/dateFormat.ts export const formatDate = (dateString: string): string => { const date = new Date(dateString); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; };
🧹 Nitpick comments (4)
frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.styles.ts (1)
89-97: Arrow 컴포넌트의 props 타입 개선 필요
Arrow컴포넌트가 선택적 width/height props를 받도록 수정되었으나, 기본값 설정이 비효율적입니다. styled-components의 기본 props 패턴을 사용하면 더 깔끔합니다.-export const Arrow = styled.img<{ width?: number; height?: number }>` +export const Arrow = styled.img<{ $width?: number; $height?: number }>` position: absolute; right: 12px; top: 50%; transform: translateY(-50%); - width: ${({ width }) => (width ? `${width}px` : '12px')}; - height: ${({ height }) => (height ? `${height}px` : '12px')}; + width: ${({ $width = 12 }) => `${$width}px`}; + height: ${({ $height = 12 }) => `${$height}px`}; pointer-events: none; `;그리고 사용하는 곳도 수정이 필요합니다:
-<Styled.Arrow width={8} height={8} src={selectIcon} /> +<Styled.Arrow $width={8} $height={8} src={selectIcon} />frontend/src/apis/applicants/deleteApplicants.ts (1)
11-11: 일관된 JSON 구조 사용body 직렬화 시 속성명 스타일이 일관되지 않습니다.
- body: JSON.stringify({applicantIds: applicantIds}), + body: JSON.stringify({ applicantIds }),frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx (2)
54-56: CONFIRM_MESSAGE 상수로 분리하여 가독성 개선삭제 확인 메시지가 하드코딩되어 있습니다. 상수로 분리하면 유지보수성이 향상됩니다.
삭제 확인 메시지를 상수로 분리:
const DELETE_CONFIRM_MESSAGE = (count: number) => `${count}개의 지원자를 정말로 삭제하시겠습니까?\n삭제된 지원자는 복구할 수 없습니다.`;그리고 사용처 수정:
- const check = confirm( - `${ids.length}개의 지원자를 정말로 삭제하시겠습니까?\n삭제된 지원자는 복구할 수 없습니다.`, - ); + const check = confirm(DELETE_CONFIRM_MESSAGE(ids.length));
172-172: StatusSelect disabled 상태 로직 개선현재 선택된 항목이 있을 때 활성화되는 로직이 매번 Array.from과 some을 호출하여 비효율적입니다. useMemo를 사용하여 최적화할 수 있습니다.
컴포넌트 상단에 추가:
const hasSelectedItems = useMemo( () => Array.from(checkedItem.values()).some(Boolean), [checkedItem] );그리고 사용처 수정:
- disabled={!Array.from(checkedItem.values()).some(Boolean)} + disabled={!hasSelectedItems}
📜 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 (5)
frontend/package-lock.jsonis excluded by!**/package-lock.jsonfrontend/src/assets/images/icons/applicant_delete.svgis excluded by!**/*.svgfrontend/src/assets/images/icons/applicant_delete_disabled.svgis excluded by!**/*.svgfrontend/src/assets/images/icons/applicant_delete_hover.svgis excluded by!**/*.svgfrontend/src/assets/images/icons/applicant_select_arrow.svgis excluded by!**/*.svg
📒 Files selected for processing (5)
frontend/package.json(1 hunks)frontend/src/apis/applicants/deleteApplicants.ts(1 hunks)frontend/src/hooks/queries/applicants/useDeleteApplicants.ts(1 hunks)frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.styles.ts(4 hunks)frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx(5 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/hooks/queries/applicants/useDeleteApplicants.tsfrontend/src/apis/applicants/deleteApplicants.tsfrontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsxfrontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.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/tabs/ApplicantsTab/ApplicantsTab.tsx
🧬 Code graph analysis (2)
frontend/src/apis/applicants/deleteApplicants.ts (1)
frontend/src/apis/auth/secureFetch.ts (1)
secureFetch(3-41)
frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx (3)
frontend/src/context/AdminClubContext.tsx (1)
useAdminClubContext(30-37)frontend/src/hooks/queries/applicants/useDeleteApplicants.ts (1)
useDeleteApplicants(4-17)frontend/src/types/applicants.ts (1)
Applicant(18-24)
🪛 Biome (2.1.2)
frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx
[error] 37-37: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
Hooks should not be called after an early return.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 45-45: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
Hooks should not be called after an early return.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
🔇 Additional comments (1)
frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx (1)
17-23: React Hooks 규칙 위반 - useDeleteApplicants를 조건문 이전에 호출해야 함React Hook인
useDeleteApplicants가 조건부 반환문(if (!clubId) return null;) 이후에 호출되고 있습니다. 모든 Hook은 컴포넌트의 최상위 레벨에서 무조건 호출되어야 합니다.const ApplicantsTab = () => { const navigate = useNavigate(); const { clubId, applicantsData } = useAdminClubContext(); + const { mutate: deleteApplicants } = useDeleteApplicants(clubId || ''); const [keyword, setKeyword] = useState(''); const [checkedItem, setCheckedItem] = useState<Map<string, boolean>>( new Map(), ); const [selectAll, setSelectAll] = useState(false); const [open, setOpen] = useState(false); - const { mutate: deleteApplicants } = useDeleteApplicants(clubId!); if (!clubId) return null;Likely an incorrect or invalid review comment.
frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx (1)
319-330: 날짜 형식화 로직을 유틸리티 함수로 분리IIFE로 작성된 날짜 형식화 로직이 복잡합니다. 코딩 가이드라인에 따라 복잡한 로직을 별도 함수로 분리해주세요.
// utils/dateFormatter.ts export const formatDateToYYYYMMDD = (dateString: string): string => { const date = new Date(dateString); const year = date.getFullYear(); const month = String(date.getMonth() + 1).padStart(2, '0'); const day = String(date.getDate()).padStart(2, '0'); return `${year}-${month}-${day}`; };그리고 컴포넌트에서:
- { - // createdAt을 yyyy-mm-dd 형식으로 변환 - // 임시로.. 나중에 변경해야함 - (() => { - const date = new Date(item.createdAt); - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); - return `${year}-${month}-${day}`; - })() - } + {formatDateToYYYYMMDD(item.createdAt)}
♻️ Duplicate comments (2)
frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx (2)
104-112: 중복 코메트 - 비효율적인 Map 업데이트이전 리뷰에서 지적된 바와 동일하게, Map을 변경한 후 새로운 Map을 생성하는 방식이 비효율적입니다. 함수형 방식으로 개선이 필요합니다.
const checkoutAllApplicants = () => { - setCheckedItem((prev) => { - const newMap = new Map(prev); - newMap.forEach((_, key) => { - newMap.set(key, false); - }); - return newMap; - }); + setCheckedItem(prev => + new Map(Array.from(prev.keys()).map(key => [key, false])) + ); };
172-192: 중복 코메트 - DeleteButton disabled 로직 확인 필요이전 리뷰에서 지적된 disabled 로직이 수정되었는지 확인이 필요합니다. 현재 로직은 올바르게 구현되어 있습니다 (선택된 항목이 없을 때 비활성화).
🧹 Nitpick comments (2)
frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx (2)
54-56: 임시 confirm 대화상자기존 코메트에서 언급된 바와 같이, 브라우저 기본
confirm을 사용하고 있습니다. 사용자 경험 개선을 위해 커스텀 모달로 교체를 고려해주세요.
73-102: 복잡한 선택 로직을 별도 컴포넌트나 훅으로 분리
selectApplicantsByStatus함수가 복잡한 상태 관리 로직을 포함하고 있어 단일 책임 원칙에 어긋납니다. 선택 관련 로직을 커스텀 훅으로 분리하는 것을 고려해보세요.// hooks/useApplicantSelection.ts const useApplicantSelection = (filteredApplicants: Applicant[]) => { const [checkedItem, setCheckedItem] = useState<Map<string, boolean>>(new Map()); const [selectAll, setSelectAll] = useState(false); // ... 선택 관련 로직들 return { checkedItem, selectAll, selectApplicantsByStatus, checkoutAllApplicants, // ... 다른 함수들 }; };
📜 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 (1)
frontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (3)
frontend/src/hooks/queries/applicants/useDeleteApplicants.ts(1 hunks)frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.styles.ts(4 hunks)frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.styles.ts
- frontend/src/hooks/queries/applicants/useDeleteApplicants.ts
🧰 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/tabs/ApplicantsTab/ApplicantsTab.tsx
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/tabs/ApplicantsTab/ApplicantsTab.tsx
🧬 Code graph analysis (1)
frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx (3)
frontend/src/context/AdminClubContext.tsx (1)
useAdminClubContext(30-37)frontend/src/hooks/queries/applicants/useDeleteApplicants.ts (1)
useDeleteApplicants(4-17)frontend/src/types/applicants.ts (1)
Applicant(18-24)
🪛 Biome (2.1.2)
frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx
[error] 37-37: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
Hooks should not be called after an early return.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
[error] 45-45: This hook is being called conditionally, but all hooks must be called in the exact same order in every component render.
Hooks should not be called after an early return.
For React to preserve state between calls, hooks needs to be called unconditionally and always in the same order.
See https://reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level
(lint/correctness/useHookAtTopLevel)
🔇 Additional comments (1)
frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx (1)
22-24: 훅 호출 순서 위반
useDeleteApplicants훅이 조건부 반환문(if (!clubId) return null) 이후에 호출되고 있어 React의 훅 호출 규칙을 위반합니다. 모든 훅은 컴포넌트의 최상위에서 조건 없이 호출되어야 합니다.const ApplicantsTab = () => { const navigate = useNavigate(); const { clubId, applicantsData } = useAdminClubContext(); + const { mutate: deleteApplicants } = useDeleteApplicants(clubId!); const [keyword, setKeyword] = useState(''); const [checkedItem, setCheckedItem] = useState<Map<string, boolean>>( new Map(), ); const [selectAll, setSelectAll] = useState(false); const [open, setOpen] = useState(false); - const { mutate: deleteApplicants } = useDeleteApplicants(clubId!); if (!clubId) return null;Likely an incorrect or invalid review comment.
| <Styled.ApplicantTableHeader width={55}> | ||
| <Styled.ApplicantAllSelectWrapper> | ||
| <Styled.ApplicantTableAllSelectCheckbox | ||
| checked={selectAll} | ||
| onClick={(e: React.MouseEvent<HTMLInputElement>) => { | ||
| e.stopPropagation(); | ||
| selectApplicantsByStatus('all'); | ||
| }} | ||
| /> | ||
| <Styled.ApplicantAllSelectArrow | ||
| src={selectAllIcon} | ||
| alt='전체선택' | ||
| onClick={() => setOpen((prev) => !prev)} | ||
| /> | ||
| <Styled.ApplicantAllSelectMenu open={open}> | ||
| <Styled.ApplicantAllSelectMenuItem | ||
| onClick={() => { | ||
| if (selectAll) { | ||
| setOpen(false); | ||
| return; | ||
| } | ||
| selectApplicantsByStatus('all'); | ||
| }} | ||
| > | ||
| 전체선택 | ||
| </Styled.ApplicantAllSelectMenuItem> | ||
| <Styled.ApplicantAllSelectMenuItem | ||
| onClick={() => { | ||
| selectApplicantsByStatus( | ||
| 'filter', | ||
| ApplicationStatus.SUBMITTED, | ||
| ); | ||
| }} | ||
| > | ||
| 서류 검토 필요 | ||
| </Styled.ApplicantAllSelectMenuItem> | ||
| <Styled.ApplicantAllSelectMenuItem | ||
| onClick={() => { | ||
| selectApplicantsByStatus( | ||
| 'filter', | ||
| ApplicationStatus.INTERVIEW_SCHEDULED, | ||
| ); | ||
| }} | ||
| > | ||
| 면접예정 | ||
| </Styled.ApplicantAllSelectMenuItem> | ||
| <Styled.ApplicantAllSelectMenuItem | ||
| onClick={() => { | ||
| setOpen(false); | ||
| checkoutAllApplicants(); | ||
| }} | ||
| > | ||
| 선택해제 | ||
| </Styled.ApplicantAllSelectMenuItem> | ||
| </Styled.ApplicantAllSelectMenu> | ||
| </Styled.ApplicantAllSelectWrapper> | ||
| </Styled.ApplicantTableHeader> |
There was a problem hiding this comment.
🛠️ Refactor suggestion
복잡한 UI 로직을 별도 컴포넌트로 분리
전체 선택 관련 UI 로직이 매우 복잡합니다. ApplicantAllSelector와 같은 별도 컴포넌트로 분리하여 가독성과 재사용성을 높이는 것을 고려해보세요.
// components/ApplicantAllSelector.tsx
interface ApplicantAllSelectorProps {
selectAll: boolean;
open: boolean;
onToggleOpen: () => void;
onSelectAll: () => void;
onSelectByStatus: (status: ApplicationStatus) => void;
onClearAll: () => void;
}
const ApplicantAllSelector = ({ /* props */ }: ApplicantAllSelectorProps) => {
// 현재 라인 207-261의 로직을 이곳으로 이동
};🤖 Prompt for AI Agents
In frontend/src/pages/AdminPage/tabs/ApplicantsTab/ApplicantsTab.tsx around
lines 206-262, the "전체 선택" UI and menu logic is too large and should be
extracted into a dedicated ApplicantAllSelector component; create
components/ApplicantAllSelector.tsx that accepts controlled props (selectAll:
boolean, open: boolean, onToggleOpen: () => void, onSelectAll: () => void,
onSelectByStatus: (status: ApplicationStatus) => void, onClearAll: () => void)
and move the JSX and local event handlers there (preserve e.stopPropagation on
the checkbox click and all menu item behaviors), ensure styling imports are
preserved or re-exported, update the parent file to render <ApplicantAllSelector
.../> passing state and callbacks (or lift open/selectAll control into parent if
currently local) and remove the original block so behavior and props remain
identical.
#️⃣연관된 이슈
#694
📝작업 내용
기존 디자인
변경 디자인
중점적으로 리뷰받고 싶은 부분(선택)
논의하고 싶은 부분(선택)
🫡 참고사항
Summary by CodeRabbit
New Features
Style