[refactor] 어드민 텍스트 필드 글자수 제한 상수화 및 자동 높이 적용 - #1822
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 53 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
Walkthrough어드민 입력 필드의 최대 길이와 placeholder를 공통 상수로 분리하고, 클럽 정보·소개·FAQ·모집·계정 관리 화면의 데스크톱 및 모바일 입력 컴포넌트에 적용했습니다. 모바일 소개 입력에는 공통 변경 핸들러와 자동 확장 ref가 추가되었습니다. Changes어드민 입력 필드 상수화
Estimated code review effort: 3 (Moderate) | ~20 minutes Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
|
Claude finished @suhyun113's task in 2m 11s —— View job harry 리뷰 결과 ✅
총평전체적으로 깔끔한 상수화 리팩터링이에요 👍 매직넘버를 리뷰 기준(수동 메모이제이션 남용 / 불필요한
딱 한 가지, 모바일 소개 문구 한도가 수고하셨어요! 🙌 |
| export const CLUB_TAG_MAX = 5; | ||
|
|
||
| // 소개 정보 수정 (ClubIntroEditTab) | ||
| export const INTRO_DESCRIPTION_MAX = 200; |
There was a problem hiding this comment.
데스크톱/모바일 글자수를 데스크톱 기준으로 통일하면서, 모바일 소개 문구 한도가 기존 INTRO_MAX = 300에서 200으로 줄어드는 점만 한 번 확인해 주세요. 나머지 활동/인재상/혜택은 300 → 500으로 늘어나 안전한데, 소개만 한도가 축소돼요.
백엔드 club description 필드에 @Size 검증이 없어서 프론트 한도가 유일한 가드인데, 예전 모바일에서 200~300자로 저장해 둔 동아리는 이 화면에서 재저장하려면 문구를 줄여야 하는 상황이 생길 수 있어요. 의도한 정책이면 그대로 두셔도 좋아요 👍
There was a problem hiding this comment.
Code Review
This pull request centralizes text field character limits across various admin tabs (ClubInfo, ClubIntro, Recruit, and Account) into a new adminFieldLimits.ts constant file, replacing hardcoded magic numbers. It also refactors the FAQ editor by extracting FAQItemEditor and integrates the useAutoGrow hook for mobile textareas. The review feedback suggests further simplifying the input change handlers in ClubIntroEditTabMobile.tsx and FAQSection.tsx by leveraging the native HTML maxLength attribute on the textarea elements instead of manually checking string lengths in JavaScript.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| const handleIntroChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { | ||
| if (e.target.value.length <= INTRO_DESCRIPTION_MAX) { | ||
| setIntroDescription(e.target.value); | ||
| } | ||
| }; | ||
|
|
||
| const handleActivityChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { | ||
| if (e.target.value.length <= ACTIVITY_DESCRIPTION_MAX) { | ||
| setActivityDescription(e.target.value); | ||
| } | ||
| }; | ||
|
|
||
| const handleIdealChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { | ||
| if (e.target.value.length <= IDEAL_CANDIDATE_MAX) { | ||
| setIdealCandidate({ ...idealCandidate, content: e.target.value }); | ||
| } | ||
| }; | ||
|
|
||
| const handleBenefitsChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { | ||
| if (e.target.value.length <= BENEFITS_MAX) { | ||
| setBenefits(e.target.value); | ||
| } | ||
| }; |
There was a problem hiding this comment.
데스크톱 버전(ClubIntroEditTab.tsx)과 동일하게 HTML <textarea> 엘리먼트에 maxLength 속성을 직접 부여하면, 브라우저가 네이티브하게 글자 수를 제한하므로 JS 레벨에서 매번 글자 수를 체크하는 조건문(if (e.target.value.length <= ..._MAX))을 제거하여 코드를 단순화할 수 있습니다.
이 변경사항을 적용한 후, 아래의 각 Styled.TextArea 컴포넌트에도 대응하는 maxLength 속성(예: maxLength={INTRO_DESCRIPTION_MAX})을 추가해 주세요.
const handleIntroChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setIntroDescription(e.target.value);
};
const handleActivityChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setActivityDescription(e.target.value);
};
const handleIdealChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setIdealCandidate({ ...idealCandidate, content: e.target.value });
};
const handleBenefitsChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setBenefits(e.target.value);
};
| const handleAnswerChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { | ||
| if (e.target.value.length <= ANSWER_MAX_LENGTH) { | ||
| if (e.target.value.length <= FAQ_ANSWER_MAX) { | ||
| onChange(index, 'answer', e.target.value); | ||
| } | ||
| }; |
There was a problem hiding this comment.
마찬가지로 모바일 FAQ 답변 입력란에서도 HTML <textarea> 엘리먼트에 maxLength={FAQ_ANSWER_MAX} 속성을 직접 부여하고, JS 레벨의 수동 글자 수 체크 로직을 제거하여 데스크톱 버전(FAQEditor.tsx)과 일관성을 맞추는 것이 좋습니다.
이 변경사항을 적용한 후, Styled.AnswerTextarea 컴포넌트(47번 라인 부근)에 maxLength={FAQ_ANSWER_MAX} 속성을 추가해 주세요.
const handleAnswerChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
onChange(index, 'answer', e.target.value);
};
seongwon030
left a comment
There was a problem hiding this comment.
훅분리와 상수분리로 더 깔끔해졌네요 수고하셨습니다
…holders-MOA-1034-MOA-1036 [refactor] 어드민 텍스트 필드 placeholder 상수화
… refactor/admin-text-field-MOA-1034
|
Claude finished @suhyun113's task in 1m 34s —— View job harry 리뷰 결과 🚨
총평이번 push에서 추가된 변경분은
👉 해당 인라인 코멘트대로 중복 블록(84~106줄)을 삭제하고 |
| }; | ||
|
|
||
| const handleIntroChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { | ||
| if (e.target.value.length <= INTRO_MAX) { |
There was a problem hiding this comment.
이번 머지 커밋에서 핸들러 4개(handleIntroChange·handleActivityChange·handleIdealChange·handleBenefitsChange)가 중복 선언됐어요. 위쪽(6082줄)에 이미 같은 이름의 핸들러가 있어서, 이 84106줄 블록은 Cannot redeclare block-scoped variable 컴파일 에러를 내요.
게다가 이 블록은 INTRO_MAX·ACTIVITY_MAX·IDEAL_MAX를 참조하는데, adminFieldLimits.ts에는 이런 상수가 없어요(올바른 이름은 INTRO_DESCRIPTION_MAX·ACTIVITY_DESCRIPTION_MAX·IDEAL_CANDIDATE_MAX예요). 머지 충돌 해결 과정에서 예전 코드가 다시 딸려 들어온 것 같아요.
이 중복 블록(84~106줄) 전체를 삭제하고, 삭제 후 npm run typecheck로 한 번 확인해 주세요. 지금 상태로는 빌드가 깨져요 🙏
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx (1)
7-7: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
placeholder문자열도 상수로 중앙 관리해야 합니다.
maxLength는RECRUIT_TARGET_MAX상수로 잘 교체되었으나, 168행의placeholder='모집대상을 입력해주세요'는 여전히 하드코딩되어 있습니다. CLAUDE.md에 명시된 "문자열 하드코딩 금지" 원칙에 따라adminFieldPlaceholders.ts에 추가하는 것이 좋습니다.🔧 제안하는 수정
frontend/src/constants/adminFieldPlaceholders.ts에 상수 추가:export const FAQ_ANSWER_PLACEHOLDER = '답변을 입력해주세요'; + +// 모집 정보 수정 (RecruitEditTab) +export const RECRUIT_TARGET_PLACEHOLDER = '모집대상을 입력해주세요';
RecruitEditTab.tsx에 import 및 적용:import { RECRUIT_TARGET_MAX } from '`@/constants/adminFieldLimits`'; +import { RECRUIT_TARGET_PLACEHOLDER } from '`@/constants/adminFieldPlaceholders`';- placeholder='모집대상을 입력해주세요' + placeholder={RECRUIT_TARGET_PLACEHOLDER}Also applies to: 173-173
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx` at line 7, Move the hardcoded recruitment-target placeholder strings in RecruitEditTab to a named constant in adminFieldPlaceholders.ts, then import and use that constant at both the target input placeholder locations around the existing RECRUIT_TARGET_MAX usage.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/desktop/MakeTags/MakeTags.tsx`:
- Around line 52-54: Update the label text in the MakeTags component to derive
its character limit from CLUB_TAG_MAX instead of the hardcoded number 5, keeping
the label synchronized with the input maxLength value.
---
Nitpick comments:
In `@frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx`:
- Line 7: Move the hardcoded recruitment-target placeholder strings in
RecruitEditTab to a named constant in adminFieldPlaceholders.ts, then import and
use that constant at both the target input placeholder locations around the
existing RECRUIT_TARGET_MAX usage.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 12a3895f-5d55-4e55-b9c0-b5fe578fdaa8
📒 Files selected for processing (13)
frontend/src/constants/CLAUDE.mdfrontend/src/constants/adminFieldLimits.tsfrontend/src/constants/adminFieldPlaceholders.tsfrontend/src/pages/AdminPage/tabs/AccountEditTab/AccountEditTab.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTabMobile.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/desktop/MakeTags/MakeTags.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/mobile/FreeTagEditPage/FreeTagEditPage.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTab.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/ClubIntroEditTabMobile.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/desktop/FAQEditor/FAQEditor.tsxfrontend/src/pages/AdminPage/tabs/ClubIntroEditTab/components/mobile/FAQSection/FAQSection.tsxfrontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx
| maxLength={CLUB_TAG_MAX} | ||
| onChange={(e) => updateTag(index, e.target.value)} | ||
| placeholder={`자유 태그 ${index + 1}`} | ||
| placeholder={CLUB_TAG_PLACEHOLDER} |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
라벨 텍스트의 하드코딩된 숫자 5를 CLUB_TAG_MAX 상수로 통일해야 합니다.
maxLength는 CLUB_TAG_MAX 상수로 변경되었지만, 45행 라벨 텍스트 "자유태그 (5자 이내)"에는 여전히 매직 넘버 5가 하드코딩되어 있습니다. CLUB_TAG_MAX 값이 변경될 경우 라벨과 실제 제한 값이 불일치하게 됩니다.
🔧 제안하는 수정
- <Styled.Label>자유태그 (5자 이내)</Styled.Label>
+ <Styled.Label>자유태그 ({CLUB_TAG_MAX}자 이내)</Styled.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.
| maxLength={CLUB_TAG_MAX} | |
| onChange={(e) => updateTag(index, e.target.value)} | |
| placeholder={`자유 태그 ${index + 1}`} | |
| placeholder={CLUB_TAG_PLACEHOLDER} | |
| <Styled.Label>자유태그 ({CLUB_TAG_MAX}자 이내)</Styled.Label> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/desktop/MakeTags/MakeTags.tsx`
around lines 52 - 54, Update the label text in the MakeTags component to derive
its character limit from CLUB_TAG_MAX instead of the hardcoded number 5, keeping
the label synchronized with the input maxLength value.
|
Claude finished @suhyun113's task in 37s —— View job harry 리뷰 결과 ✅
총평이번 커밋(
이제 깔끔하게 정리해 주셨네요, 수고하셨어요! 🙌 |
4271b1a
into
feature/#1802-club-intro-edit-tab-mobile-MOA-1018
Summary
#1805
위 PR에서 받은 리뷰에서의 수정입니다.
src/constants/adminFieldLimits.ts생성하여 어드민 탭 전체 텍스트 필드 maxLength를 한 곳에서 관리useAutoGrow적용으로 입력량에 따라 필드 높이 자동 확장AnswerTextArea에useAutoGrow적용, FAQItemEditor 서브 컴포넌트로 분리Jira
MOA-1034
Test plan
Summary by CodeRabbit