-
Notifications
You must be signed in to change notification settings - Fork 2
[fix] FAQ 수정, 삭제 버그 해결 #1024
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
[fix] FAQ 수정, 삭제 버그 해결 #1024
Conversation
- Award 타입 import를 상대 경로에서 @/types/club으로 변경 - 라벨에서 이모지(🏆) 제거하여 일관성 유지
- FAQ 타입 import를 상대 경로에서 @/types/club으로 변경 - 서버에서 받아온 FAQ에 자동으로 ID 생성하는 로직 추가 - Type predicate를 사용하여 필터링 후 타입 안정성 보장 - 불필요한 null 체크 제거로 코드 간결화 - 라벨에서 이모지(❓) 제거하여 일관성 유지
- FAQ 인터페이스에 optional id 필드 추가하여 클라이언트 측 리스트 관리 지원 - RecruitmentStatus 타입 포맷 정리
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning
|
| Cohort / File(s) | Summary |
|---|---|
라우팅 및 임포트 업데이트 frontend/src/pages/AdminPage/AdminRoutes.tsx |
ClubIntroTab 임포트·라우트 렌더링을 ClubIntroEditTab으로 교체 |
클럽 소개 편집 탭 리네임 및 레이블/스타일 변경 frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsx, frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.styles.ts |
컴포넌트명·기본 export를 ClubIntroEditTab으로 변경하고 일부 이모지 레이블 제거 및 스타일 경로 업데이트 |
FAQEditor 재작성 및 이동 frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/FAQEditor/FAQEditor.tsx |
새 FAQEditor 추가(FAQ id 자동 부여, focus 관리, 추가/삭제/수정, onChange 콜백) |
레거시 FAQEditor 제거 frontend/src/pages/AdminPage/tabs/ClubIntroTab/components/FAQEditor/FAQEditor.tsx |
기존 FAQEditor 파일 완전 삭제 |
타입 정의 업데이트 frontend/src/types/club.ts |
FAQ 인터페이스에 선택적 id?: string 추가; RecruitmentStatus 선언 형식 정리 |
클럽 정보 탭 상수/쿼리 정리 frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx |
divisions·categories 상수를 모듈 스코프로 이동하고 useQueryClient() 사용 위치 정리 |
어워드 에디터 및 상세 뷰 소소 변경 frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/AwardEditor/AwardEditor.tsx, frontend/src/pages/ClubDetailPage/components/ClubIntroContent/ClubIntroContent.tsx, frontend/src/pages/ClubDetailPage/components/ClubIntroContent/ClubIntroContent.styles.ts |
Award 타입 임포트 경로 변경(@/types/club), 일부 레이블 이모지 제거, AnswerBox에 white-space: pre-line 추가 |
이벤트 상수 추가 frontend/src/constants/eventName.ts |
PAGE_VIEW에 CLUB_INTRO_EDIT_PAGE 항목 추가 |
Sequence Diagram(s)
(생성 조건 미충족 — 생략)
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related issues
- [fix] MOA-502 관리자가 FAQ 수정 시 하나의 답변이 모든 답변을 덮어쓰는 문제를 해결한다 #1023: FAQEditor 재작성 및
FAQ.id자동 부여로 관리자 편집 시 답변 덮어쓰기 문제와 직접 관련됩니다. - MOA-502: 관리자 FAQ 수정 시 한 답변이 모든 답변을 덮어쓰는 버그 수정 목적과 연관됩니다.
Possibly related PRs
- [feature] 관리자 페이지 > 동아리 상세정보 수정 탭 추가 및 커버 업로드 UI 제공 #958: ClubIntroTab → ClubIntroEditTab 리네임·구조 변경과 직접적인 코드 연관성 있음.
- [feature] 동아리 상세페이지 > 공통 레이아웃(UI 틀) 구현 #964:
frontend/src/types/club.ts의 FAQ/타입 변경과 중복되는 타입 수정을 포함함. - [feature] 관리자페이지 기본정보 및 소개정보 수정 api 연동 #971: 클럽 소개 관리자 UI 및 타입/경로 변경과 구조적으로 연관됨.
Suggested reviewers
- lepitaaar
- suhyun113
🚥 Pre-merge checks | ✅ 4 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |
✅ Passed checks (4 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | PR 제목이 주요 변경사항인 FAQ 편집/삭제 버그 해결을 명확하게 설명하고 있으며, 변경사항과 직접적으로 관련이 있습니다. |
| Linked Issues check | ✅ Passed | PR의 변경사항이 MOA-502의 목표인 FAQ 편집 시 답변 덮어쓰기 버그를 해결하기 위해 FAQ 타입에 id 필드 추가, 자동 ID 생성 로직 구현, 타입 안전성 확보 등의 요구사항을 모두 충족합니다. |
| Out of Scope Changes check | ✅ Passed | 디렉토리명 변경(ClubIntroTab → ClubIntroEditTab), 이모지 제거, 절대 경로 통일 등의 변경사항이 있으나, 이들은 모두 FAQ 편집 기능 개선과 코드 정리를 위한 관련 변경으로 보여집니다. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing touches
- 📝 Generate docstrings
📜 Recent review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
frontend/src/constants/eventName.tsfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsx
🧰 Additional context used
📓 Path-based instructions (3)
frontend/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{ts,tsx,js,jsx}: Replace magic numbers with named constants for clarity
Replace complex/nested ternaries withif/elseor IIFEs for readability
Assign complex boolean conditions to named variables for explicit meaning
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle)
Use unique and descriptive names for custom wrappers/functions to avoid ambiguity
Define constants near related logic or ensure names link them clearly to avoid silent failures
Break down broad state management into smaller, focused hooks/contexts to reduce coupling
Files:
frontend/src/constants/eventName.tsfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsx
frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
Use consistent return types for similar functions/hooks
Files:
frontend/src/constants/eventName.tsfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsx
frontend/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{tsx,jsx}: Abstract complex logic/interactions into dedicated 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 when using form libraries like react-hook-form
Use Component Composition instead of Props Drilling to reduce coupling
Files:
frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsx
🧠 Learnings (1)
📚 Learning: 2025-03-19T05:18:07.818Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
Applied to files:
frontend/src/constants/eventName.tsfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsx
🧬 Code graph analysis (1)
frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsx (1)
frontend/src/constants/eventName.ts (1)
PAGE_VIEW(90-105)
🔇 Additional comments (4)
frontend/src/constants/eventName.ts (1)
100-100: LGTM!새로운
CLUB_INTRO_EDIT_PAGE상수가 기존 관리자 페이지 상수들의 네이밍 컨벤션(한국어 값)을 일관되게 따르고 있습니다.frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsx (3)
12-18: LGTM!컴포넌트 이름 변경(
ClubIntroTab→ClubIntroEditTab)이 import 경로, 스타일, 페이지 뷰 트래킹 상수에 일관되게 적용되었습니다. 새로운PAGE_VIEW.CLUB_INTRO_EDIT_PAGE상수가 올바르게 사용되고 있습니다.
101-139: LGTM!레이블에서 이모지를 제거하고 텍스트를 간결하게 정리한 변경이 UI 일관성 측면에서 적절합니다. AwardEditor 정리와 동일한 방향으로 통일되었습니다.
141-141: FAQ 상태 관리 통합 패턴이 올바릅니다이 파일은 FAQ 상태를 관리하고
FAQEditor컴포넌트에 전달하는 역할을 수행하고 있습니다. FAQEditor 컴포넌트에서 구현된 자동 ID 생성 및 타입 프리디케이트를 통한 필터링이 정상적으로 작동하며, ClubIntroEditTab의 상태 관리 및 API 호출 통합도 올바르게 구성되어 있습니다.
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
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: 0
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/ClubIntroEditTab/ClubIntroEditTab.tsx (1)
141-141: FAQEditor의 ID 생성 로직 개선 필요FAQEditor 컴포넌트(lines 15-23, 27-31)에서 자동 ID 생성 로직이 구현되어 있습니다. 다만 현재 구현은
Date.now() + Math.random()을 사용하고 있어 동시에 여러 FAQ가 추가될 경우 ID 충돌 가능성이 있습니다. 의존성에 이미 추가된uuid또는nanoid라이브러리를 사용하여 고유한 ID 생성 방식으로 개선해주세요.
🧹 Nitpick comments (4)
frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/AwardEditor/AwardEditor.tsx (1)
225-226: 배열 인덱스를 key로 사용하는 것에 대한 고려
achievementIndex를 key로 사용하고 있습니다. 항목이 추가/삭제될 때 React가 잘못된 요소를 재사용할 수 있어 입력 필드 상태가 꼬일 가능성이 있습니다. 다만, 이는 기존 코드이므로 이번 PR 범위를 벗어납니다.향후 개선 시 고유 ID 기반 key 사용을 고려해보세요:
♻️ 선택적 개선 제안
- <Styled.AchievementItem key={achievementIndex}> + <Styled.AchievementItem key={`${award.semester}-${achievementIndex}`}>또는 각 achievement에 고유 ID를 부여하는 구조 변경을 고려할 수 있습니다.
frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/FAQEditor/FAQEditor.tsx (3)
15-24: 초기 렌더링 시 깜빡임(flicker) 가능성서버에서 ID 없는 FAQ가 전달되면, 첫 렌더링에서 line 80의
filter로 인해 빈 목록이 표시되고, 이후 이useEffect가 실행되어 ID가 할당된 후 다시 렌더링됩니다. 이로 인해 사용자에게 순간적인 깜빡임이 발생할 수 있습니다.
useMemo를 사용하여 렌더링 시점에 ID를 동기적으로 할당하면 이 문제를 방지할 수 있습니다.♻️ 리팩토링 제안
- useEffect(() => { - const hasAnyMissingId = faqs.some((faq) => !faq.id); - if (hasAnyMissingId) { - const faqsWithIds = faqs.map((faq) => ({ - ...faq, - id: faq.id || `faq-${Date.now()}-${Math.random()}`, - })); - onChange(faqsWithIds); - } - }, [faqs, onChange]); + const faqsWithIds = useMemo(() => { + const hasAnyMissingId = faqs.some((faq) => !faq.id); + if (hasAnyMissingId) { + const updated = faqs.map((faq) => ({ + ...faq, + id: faq.id || `faq-${Date.now()}-${Math.random()}`, + })); + // 부모에게 ID가 할당된 데이터를 전달 (다음 렌더에서 동기화) + queueMicrotask(() => onChange(updated)); + return updated; + } + return faqs; + }, [faqs, onChange]);그리고 아래 렌더링 로직에서
faqs대신faqsWithIds를 사용합니다.
40-52: 중복 코드 통합 고려
handleUpdateQuestion과handleUpdateAnswer가 거의 동일한 로직입니다. 단일 함수로 통합하면 코드 중복을 줄일 수 있습니다.♻️ 통합 제안
- const handleUpdateQuestion = (id: string, value: string) => { - const updatedFAQs = faqs.map((faq) => - faq.id === id ? { ...faq, question: value } : faq, - ); - onChange(updatedFAQs); - }; - - const handleUpdateAnswer = (id: string, value: string) => { - const updatedFAQs = faqs.map((faq) => - faq.id === id ? { ...faq, answer: value } : faq, - ); - onChange(updatedFAQs); - }; + const handleUpdateFAQ = (id: string, field: keyof Pick<FAQ, 'question' | 'answer'>, value: string) => { + const updatedFAQs = faqs.map((faq) => + faq.id === id ? { ...faq, [field]: value } : faq, + ); + onChange(updatedFAQs); + };사용 시:
onChange={(event) => handleUpdateFAQ(faq.id, 'question', event.target.value)} onChange={(event) => handleUpdateFAQ(faq.id, 'answer', event.target.value)}
99-113: 매직 넘버를 상수로 추출 고려코딩 가이드라인에 따라
maxLength값(100, 300)을 명명된 상수로 추출하면 의도가 더 명확해지고 유지보수가 쉬워집니다.♻️ 상수 추출 제안
파일 상단에 상수 정의:
const MAX_QUESTION_LENGTH = 100; const MAX_ANSWER_LENGTH = 300;사용 시:
- maxLength={100} + maxLength={MAX_QUESTION_LENGTH}- maxLength={300} + maxLength={MAX_ANSWER_LENGTH}- 질문: {faq.question.length}/100 | 답변: {faq.answer.length} - /300 + 질문: {faq.question.length}/{MAX_QUESTION_LENGTH} | 답변: {faq.answer.length} + /{MAX_ANSWER_LENGTH}
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
frontend/src/pages/AdminPage/AdminRoutes.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.styles.tsfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/AwardEditor/AwardEditor.styles.tsfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/AwardEditor/AwardEditor.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/FAQEditor/FAQEditor.styles.tsfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/FAQEditor/FAQEditor.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroTab/components/FAQEditor/FAQEditor.tsxfrontend/src/types/club.ts
💤 Files with no reviewable changes (1)
- frontend/src/pages/AdminPage/tabs/ClubIntroTab/components/FAQEditor/FAQEditor.tsx
🧰 Additional context used
📓 Path-based instructions (3)
frontend/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{ts,tsx,js,jsx}: Replace magic numbers with named constants for clarity
Replace complex/nested ternaries withif/elseor IIFEs for readability
Assign complex boolean conditions to named variables for explicit meaning
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle)
Use unique and descriptive names for custom wrappers/functions to avoid ambiguity
Define constants near related logic or ensure names link them clearly to avoid silent failures
Break down broad state management into smaller, focused hooks/contexts to reduce coupling
Files:
frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/AwardEditor/AwardEditor.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/FAQEditor/FAQEditor.tsxfrontend/src/types/club.tsfrontend/src/pages/AdminPage/AdminRoutes.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
frontend/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{tsx,jsx}: Abstract complex logic/interactions into dedicated 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 when using form libraries like react-hook-form
Use Component Composition instead of Props Drilling to reduce coupling
Files:
frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/AwardEditor/AwardEditor.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/FAQEditor/FAQEditor.tsxfrontend/src/pages/AdminPage/AdminRoutes.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
Use consistent return types for similar functions/hooks
Files:
frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/AwardEditor/AwardEditor.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/FAQEditor/FAQEditor.tsxfrontend/src/types/club.tsfrontend/src/pages/AdminPage/AdminRoutes.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
🧠 Learnings (9)
📓 Common learnings
Learnt from: seongwon030
Repo: Moadong/moadong PR: 195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
📚 Learning: 2025-03-19T05:18:07.818Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
Applied to files:
frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsxfrontend/src/pages/AdminPage/AdminRoutes.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{tsx,jsx} : Separate significantly different conditional UI/logic into distinct components
Applied to files:
frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{tsx,jsx} : Abstract complex logic/interactions into dedicated components/HOCs
Applied to files:
frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/FAQEditor/FAQEditor.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{ts,tsx,js,jsx} : Replace magic numbers with named constants for clarity
Applied to files:
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{ts,tsx,js,jsx} : Define constants near related logic or ensure names link them clearly to avoid silent failures
Applied to files:
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{tsx,jsx} : Colocate simple, localized logic or use inline definitions to reduce context switching
Applied to files:
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{ts,tsx,js,jsx} : Break down broad state management into smaller, focused hooks/contexts to reduce coupling
Applied to files:
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
📚 Learning: 2025-07-19T05:05:10.196Z
Learnt from: seongwon030
Repo: Moadong/moadong PR: 548
File: frontend/src/pages/ClubDetailPage/ClubDetailPage.tsx:17-57
Timestamp: 2025-07-19T05:05:10.196Z
Learning: ClubDetailPage.tsx에서 notJoinedClubNames 배열의 하드코딩은 의도적인 설계 결정입니다. 개발자가 명시적으로 하드코딩을 선택했으므로 이에 대한 리팩토링 제안을 하지 않아야 합니다.
Applied to files:
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx
🧬 Code graph analysis (1)
frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/FAQEditor/FAQEditor.tsx (2)
frontend/src/types/club.ts (1)
FAQ(54-58)frontend/src/pages/AdminPage/tabs/ClubIntroTab/components/FAQEditor/FAQEditor.tsx (1)
FAQEditorProps(11-105)
🔇 Additional comments (13)
frontend/src/types/club.ts (1)
54-58: LGTM! FAQ 타입에 optional id 필드 추가PR 목표에 맞게 FAQ 인터페이스에
id?: string필드가 추가되어 React 리스트 key 관리 및 클라이언트 측 FAQ 추적이 가능해졌습니다. optional로 선언한 것은 서버에서 ID가 없는 데이터가 올 수 있는 상황을 적절히 처리합니다.frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx (2)
26-46: LGTM! 상수를 모듈 스코프로 추출
divisions와categories상수를 컴포넌트 외부로 추출한 것은 좋은 개선입니다. 렌더링마다 재생성되지 않아 성능이 향상되고, 코딩 가이드라인에 따라 상수를 관련 로직 근처에 명확하게 정의했습니다.
134-144: LGTM! 쿼리 무효화 로직 추가업데이트 성공 시
queryClient.invalidateQueries를 호출하여clubDetail캐시를 무효화하는 것은 React Query의 올바른 패턴입니다. 이를 통해 UI가 최신 데이터와 동기화됩니다.frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsx (2)
12-16: LGTM! 컴포넌트 이름 변경 및 스타일 경로 업데이트
ClubIntroTab에서ClubIntroEditTab으로의 이름 변경이 파일명과 일치하며, 스타일 import 경로도 올바르게 업데이트되었습니다.
101-139: LGTM! UI 라벨 일관성 개선이모지를 제거하고 깔끔한 한국어 라벨로 통일한 것은 UI 일관성을 향상시킵니다. PR 목표인 AwardEditor 정리 작업과 일관된 변경입니다.
frontend/src/pages/AdminPage/AdminRoutes.tsx (2)
12-12: LGTM! 라우트 import 업데이트
ClubIntroEditTabimport가 새로운 경로로 올바르게 업데이트되었습니다.
38-38: LGTM! 라우트 엘리먼트 변경
club-intro경로의 엘리먼트가ClubIntroEditTab으로 업데이트되었습니다. URL 경로는 유지되어 기존 링크나 북마크에 영향을 주지 않습니다.frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/AwardEditor/AwardEditor.tsx (2)
5-5: LGTM! 절대 경로 import로 변경
Award타입의 import 경로가 상대 경로에서@/types/club절대 경로로 변경되어 코드 유지보수성이 향상되었습니다. 중앙화된 타입 모듈 사용 패턴과 일관됩니다.
143-143: LGTM! UI 라벨 일관성 유지이모지를 제거하여 다른 에디터 컴포넌트들과 UI 스타일을 통일했습니다.
frontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/FAQEditor/FAQEditor.tsx (4)
1-9: LGTM!import 경로 절대화 및 인터페이스 정의가 깔끔합니다.
26-34: LGTM!새 FAQ 추가 로직이 올바르게 구현되어 있습니다. ID 생성 후 포커스 트리거까지 잘 처리되었습니다.
54-65: LGTM!마지막 FAQ 입력 필드에 포커스를 맞추는 로직이 올바르게 구현되었습니다.
lastFAQ.id존재 여부를 확인하는 방어 코드도 적절합니다.
79-80: 타입 안정성 확보를 위한 좋은 접근Type predicate를 사용한 필터링으로 TypeScript 타입 안정성을 보장하는 좋은 패턴입니다. PR 목표인 FAQ 수정/삭제 버그 해결에 핵심적인 역할을 합니다.
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: 0
🧹 Nitpick comments (1)
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx (1)
143-143: 사용자 메시지 간 네이밍 일관성 검토 필요유효성 검사 오류 메시지(Line 143)는 영문 브랜드명("Google Forms, Naver Form 또는 Everytime")을 사용하고, 힌트 텍스트(Line 369)는 한글("구글폼, 네이버폼, 에브리타임")을 사용합니다. 사용자 경험 일관성을 위해 둘 중 하나로 통일하는 것을 권장합니다.
♻️ 한글로 통일하는 경우
if (!isValidUrl) { alert( - '외부 지원서 링크는 Google Forms, Naver Form 또는 Everytime 링크여야 합니다.', + '외부 지원서 링크는 구글폼, 네이버폼 또는 에브리타임 링크여야 합니다.', ); return; }Also applies to: 369-369
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Disabled knowledge base sources:
- Jira integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsxfrontend/src/pages/ClubDetailPage/components/ClubIntroContent/ClubIntroContent.styles.ts
🧰 Additional context used
📓 Path-based instructions (3)
frontend/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{ts,tsx,js,jsx}: Replace magic numbers with named constants for clarity
Replace complex/nested ternaries withif/elseor IIFEs for readability
Assign complex boolean conditions to named variables for explicit meaning
Avoid hidden side effects; functions should only perform actions implied by their signature (Single Responsibility Principle)
Use unique and descriptive names for custom wrappers/functions to avoid ambiguity
Define constants near related logic or ensure names link them clearly to avoid silent failures
Break down broad state management into smaller, focused hooks/contexts to reduce coupling
Files:
frontend/src/pages/ClubDetailPage/components/ClubIntroContent/ClubIntroContent.styles.tsfrontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx
frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
Use consistent return types for similar functions/hooks
Files:
frontend/src/pages/ClubDetailPage/components/ClubIntroContent/ClubIntroContent.styles.tsfrontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx
frontend/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (frontend/.cursorrules)
frontend/**/*.{tsx,jsx}: Abstract complex logic/interactions into dedicated 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 when using form libraries like react-hook-form
Use Component Composition instead of Props Drilling to reduce coupling
Files:
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx
🧠 Learnings (3)
📓 Common learnings
Learnt from: seongwon030
Repo: Moadong/moadong PR: 195
File: frontend/src/pages/AdminPage/AdminPage.tsx:7-7
Timestamp: 2025-03-19T05:18:07.818Z
Learning: AdminPage.tsx에서 현재 하드코딩된 클럽 ID('67d2e3b9b15c136c6acbf20b')는 로그인 기능 구현 후 동적으로 가져오는 방식으로 수정될 예정입니다.
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{ts,tsx,js,jsx} : Replace magic numbers with named constants for clarity
Applied to files:
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx
📚 Learning: 2025-11-25T14:08:23.253Z
Learnt from: CR
Repo: Moadong/moadong PR: 0
File: frontend/.cursorrules:0-0
Timestamp: 2025-11-25T14:08:23.253Z
Learning: Applies to frontend/**/*.{ts,tsx,js,jsx} : Define constants near related logic or ensure names link them clearly to avoid silent failures
Applied to files:
frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx
🔇 Additional comments (2)
frontend/src/pages/ClubDetailPage/components/ClubIntroContent/ClubIntroContent.styles.ts (1)
206-228: LGTM! FAQ 답변 줄바꿈 보존을 위한 적절한 스타일 추가입니다.
white-space: pre-line속성 추가는 동일 파일 내Text컴포넌트(58번 라인)와 일관된 패턴을 따르고 있으며, FAQ 답변에서 멀티라인 콘텐츠를 올바르게 표시할 수 있도록 합니다.frontend/src/pages/AdminPage/tabs/ApplicationEditTab/ApplicationEditTab.tsx (1)
23-29: 상수 모듈 스코프로 추출 잘 되었습니다.허용된 URL 목록을 모듈 스코프 상수로 정의하여 코드 가독성과 유지보수성이 향상되었습니다. 코딩 가이드라인에 따라 상수를 관련 로직 근처에 정의하는 패턴을 잘 따르고 있습니다.
https://everytime.kr도메인도 에브리타임 외부 공유 링크의 올바른 형식입니다.
oesnuj
left a comment
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.
FAQ 기능을 급하게 구현했던 코드라 다시 읽어보니 개선할 여지가 꽤 있네요
나중에 시간 날 때 좀 더 깔끔하게 리팩토링해보겠습니다
빠른 버그 픽스 수고하셨습니다~
#️⃣연관된 이슈
📝작업 내용
문제상황
해결
1. 타입 정의 개선
id?: string필드 추가2. FAQ Editor 컴포넌트 개선
3. AwardEditor 컴포넌트 정리
4. 디렉토리명 변경
중점적으로 리뷰받고 싶은 부분(선택)
논의하고 싶은 부분(선택)
🫡 참고사항
Summary by CodeRabbit
New Features
UI 개선
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.