[fix] 모바일 기본정보 수정 리뷰 반영 - #1796
Conversation
데스크톱 InputField는 동아리명·한줄소개에 maxLength 20이 적용돼 있으나 모바일 TextField에는 제한이 없어 20자 초과 입력·저장이 가능했다. TextField에 maxLength prop을 추가하고 모바일 두 필드에 20을 연결한다.
형제 컴포넌트 TextField와 동일하게, 지우기 버튼 클릭 후에도 입력 필드 포커스를 유지해 바로 이어서 입력할 수 있도록 한다.
기존에는 요청 전에 initialValues를 동기적으로 갱신해, 저장이 실패해도 변경분이 저장된 것으로 간주돼 메인 저장 버튼이 비활성화되는 문제가 있었다. setInitialValues를 updateClub onSuccess 콜백으로 옮겨 성공 시에만 반영한다.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
WalkthroughTextField 컴포넌트에 maxLength 프롭을 추가하고 동아리명/동아리소개 필드에 20자 제한을 적용했습니다. LinkField는 클리어 후 input에 다시 포커스하도록 변경되었고, useClubInfoEdit 훅은 isDirty 기반으로 폼 상태 동기화 로직과 업데이트 성공 시 initialValues 갱신 흐름을 수정했습니다. Changes폼 입력 제한 및 상태 동기화 개선
Estimated code review effort: 2 (Simple) | ~12 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant useClubInfoEdit
participant API
User->>useClubInfoEdit: 정보/링크/태그 업데이트 요청
useClubInfoEdit->>API: mutation 호출
API-->>useClubInfoEdit: onSuccess 응답
useClubInfoEdit->>useClubInfoEdit: initialValues 갱신 (isDirty 아닐 때만 서버값 반영)
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 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 @seongwon030's task in 1m 10s —— View job harry 리뷰 결과 🐹
리뷰 기준 대비 위반 사항 없이 깔끔한 후속 수정이에요. 👍 좋았던 점
가벼운 제안 (선택)
반영하지 않은 gemini 리뷰( |
🎨 UI 변경사항을 확인해주세요
13개 스토리 변경 · 전체 74개 스토리 · 29개 컴포넌트 |
There was a problem hiding this comment.
Code Review
This pull request introduces maximum length constraints on club name and introduction fields, improves the UX of the link field by focusing it upon clearing, and refactors useClubInfoEdit to update initial values only after successful API calls. Feedback was provided regarding a potential bug in useClubInfoEdit.ts where unsaved input data could be lost when clubDetail is refetched after partial updates; a fix was suggested to only synchronize state if there are no unsaved changes.
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.
suhyun113
left a comment
There was a problem hiding this comment.
testField 최대 길이 제한 놓친 부분인데, 빠르게 수정해주셔서 감사합니다!
배너/로고 업로드 뮤테이션이 clubDetail 쿼리를 무효화하면 refetch가 일어나 useEffect가 무조건 서버 값으로 로컬 상태를 덮어써, 수정 중이던 동아리명·소개가 유실되던 문제가 있었다. - useEffect에 isDirty 가드를 추가해 편집 중에는 서버 값으로 덮어쓰지 않는다. - 가드로 인해 refetch 기반 리셋이 막히므로, handleUpdateClub 성공 시 initialValues를 현재 값으로 동기화해 저장 버튼이 정상 비활성화되게 한다. - deps는 clubDetail만 유지(isDirty 제외)해 재동기화 루프를 방지한다.
|
Claude finished @seongwon030's task in 1m 21s —— View job harry 리뷰 결과 🐹 (synchronize)
이번 추가 커밋( 좋았던 점
참고 (이번 PR에서 조치 불필요)
룰 위반 없이 깔끔해요. 통과예요! 🎉 |
There was a problem hiding this comment.
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/ClubInfoEditTab/hooks/useClubInfoEdit.ts (1)
188-207: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win링크/태그 저장 성공 시
initialValues부분 동기화로 인한 dirty 상태 불일치
handleUpdateClubWithLinks와handleUpdateClubWithTags는updateClub호출 시clubName,selectedDivision,selectedCategory,introduction등 폼의 모든 현재 값을 페이로드에 실어 서버에 저장합니다(189-201, 219-230). 하지만onSuccess에서는socialLinks(203-207) 또는clubTags(232-236)만initialValues에 반영하고 나머지 필드는 갱신하지 않습니다.이로 인해 사용자가 다른 필드(예: 동아리명)를 수정한 뒤 저장하지 않고 링크/태그 페이지에서 저장하면, 서버에는 해당 필드까지 이미 반영되었음에도
initialValues가 갱신되지 않아isDirty가 계속true로 남습니다.ClubInfoEditTabMobile.tsx의 저장 버튼은disabled={!isDirty}로 제어되므로(Context snippet 2), 이미 저장된 상태인데도 저장 버튼이 계속 활성 상태로 남는 등 상태 불일치가 발생합니다.
handleUpdateClub의onSuccess(163-174)처럼 전체 필드를 동기화하도록 수정하는 것을 권장합니다.🔧 제안 수정
{ - onSuccess: () => { - setInitialValues((prev) => - prev ? { ...prev, socialLinks: mergedLinks } : null, - ); - }, + onSuccess: () => { + setInitialValues({ + clubName, + introduction, + selectedDivision, + selectedCategory, + clubTags, + socialLinks: mergedLinks, + }); + }, onError: (error) => { alert(`링크 저장에 실패했습니다: ${error.message}`); }, },{ - onSuccess: () => { - setInitialValues((prev) => - prev ? { ...prev, clubTags: newTags } : null, - ); - }, + onSuccess: () => { + setInitialValues({ + clubName, + introduction, + selectedDivision, + selectedCategory, + clubTags: newTags, + socialLinks, + }); + }, onError: (error) => { alert(`자유태그 저장에 실패했습니다: ${error.message}`); }, },Also applies to: 218-236
🤖 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/hooks/useClubInfoEdit.ts` around lines 188 - 207, `handleUpdateClubWithLinks` and `handleUpdateClubWithTags` only sync part of `initialValues` after a successful `updateClub`, which leaves `isDirty` out of sync even though the server already saved the current form state. Update the `onSuccess` logic in `useClubInfoEdit` to refresh `initialValues` the same way `handleUpdateClub` does, including all fields that are sent in the payload such as `clubName`, `selectedCategory`, `selectedDivision`, `clubTags`, `introduction`, `clubPresidentName`, `telephoneNumber`, `socialLinks`, and `description`, so the dirty state is recalculated from the saved values.
🧹 Nitpick comments (1)
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTabMobile.tsx (1)
108-130: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value20자 제한 안내 표시 고려.
자유태그필드는 라벨에(5자이내)힌트가 있지만, 동아리명/동아리소개 필드는maxLength={20}이 적용되었음에도 사용자에게 글자수 제한이나 남은 글자 수를 안내하는 UI가 없습니다. 사용자가 입력이 막히는 이유를 알기 어려울 수 있습니다.🤖 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/ClubInfoEditTabMobile.tsx` around lines 108 - 130, The ClubInfoEditTabMobile text inputs for club name and introduction enforce maxLength={20} but do not surface that limit to users, unlike the free-tag field. Update the TextField usage in ClubInfoEditTabMobile so the 20-character constraint is visible in the UI, either by adding a clear label hint such as “(20자이내)” or by showing remaining/used characters for clubName and introduction. Keep the behavior tied to the existing TextField components and their maxLength/onChange handlers.
🤖 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.
Outside diff comments:
In `@frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/hooks/useClubInfoEdit.ts`:
- Around line 188-207: `handleUpdateClubWithLinks` and
`handleUpdateClubWithTags` only sync part of `initialValues` after a successful
`updateClub`, which leaves `isDirty` out of sync even though the server already
saved the current form state. Update the `onSuccess` logic in `useClubInfoEdit`
to refresh `initialValues` the same way `handleUpdateClub` does, including all
fields that are sent in the payload such as `clubName`, `selectedCategory`,
`selectedDivision`, `clubTags`, `introduction`, `clubPresidentName`,
`telephoneNumber`, `socialLinks`, and `description`, so the dirty state is
recalculated from the saved values.
---
Nitpick comments:
In `@frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTabMobile.tsx`:
- Around line 108-130: The ClubInfoEditTabMobile text inputs for club name and
introduction enforce maxLength={20} but do not surface that limit to users,
unlike the free-tag field. Update the TextField usage in ClubInfoEditTabMobile
so the 20-character constraint is visible in the UI, either by adding a clear
label hint such as “(20자이내)” or by showing remaining/used characters for
clubName and introduction. Keep the behavior tied to the existing TextField
components and their maxLength/onChange handlers.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 6587757d-984c-418b-a945-f230e2850025
📒 Files selected for processing (4)
frontend/src/pages/AdminPage/components/editFields/TextField/TextField.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTabMobile.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/mobile/LinkEditPage/LinkField.tsxfrontend/src/pages/AdminPage/tabs/ClubInfoEditTab/hooks/useClubInfoEdit.ts
개요
PR #1794 리뷰(수동 + gemini-code-assist) 중 유효한 지적을 반영한 후속 수정입니다. 관리자
기본 정보 수정모바일 뷰 대상.변경 사항
InputField는 동아리명·한줄소개에maxLength=20이 걸려 있으나 모바일TextField엔 제한이 없어 20자 초과 입력·저장이 가능했습니다(데이터 정합성 리스크).TextField에maxLengthprop 추가 후 모바일 두 필드에20연결.TextField와 동일하게 clear 후 입력 포커스 유지(gemini 리뷰 반영).initialValues를 갱신하던 것을onSuccess콜백으로 이동. 저장 실패 시 변경분이 저장된 것으로 오인돼 버튼이 비활성화되던 문제 방어.반영하지 않은 리뷰
queryClient.invalidateQueries추가 제안 →useUpdateClubDetail이 이미queryKeys.club.detail(id)를 무효화하고 outlet context가 해당 쿼리로 backing되어 중복이며,['clubDetail', id]하드코딩은 쿼리키 중앙관리 컨벤션 위반이라 제외.확인
Summary by CodeRabbit
새 기능
버그 수정