feat:학교 동아리 목록 등록 UI 구현#329
Hidden character warning
Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
Walkthrough앱 라우팅에 Possibly related PRs
Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
apps/web/src/App.tsx (1)
8-8: ⚡ Quick win내부 페이지 import는 경로 별칭(
@/*)으로 통일해주세요.Line 8은 상대 경로 대신
@/pages/RegisterClub/RegisterClubList를 사용하면 프로젝트 컨벤션과 일관성이 맞습니다.변경 제안
-import RegisterClubList from './pages/RegisterClub/RegisterClubList'; +import RegisterClubList from '`@/pages/RegisterClub/RegisterClubList`';As per coding guidelines, "Use path alias
@/*for internal app imports (preferred over relative paths)".🤖 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 `@apps/web/src/App.tsx` at line 8, In App.tsx replace the relative import of RegisterClubList with the project path-alias import; update the import statement that currently reads import RegisterClubList from './pages/RegisterClub/RegisterClubList' to use '`@/pages/RegisterClub/RegisterClubList`' so internal app imports follow the `@/*` convention and remain consistent across the codebase.
🤖 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 `@apps/web/src/components/UniversityDropdown/index.tsx`:
- Line 38: The dropdown container in UniversityDropdown (the div with className
containing "bg-[`#FFF`]") uses an inline hex background; replace "bg-[`#FFF`]" with
the design token utility (e.g., "bg-white" or the appropriate token classname
from `@konect/design-tokens`) and ensure the component imports the CSS export from
"`@konect/design-tokens`" so tokens are available; update the className in the div
inside index.tsx to use the token-based utility instead of the inline hex.
- Around line 27-53: Add proper ARIA roles/attributes and keyboard handling to
the dropdown: give the toggle button (the element using setIsOpen) aria-expanded
tied to isOpen and aria-controls pointing to the menu id; add a unique id for
the menu and set role="listbox" on the menu container; for each option button
(the elements rendering option.name) set role="option" and aria-selected based
on selectedOption.id, and ensure onChange is called on activation; implement
keyboard handlers on the toggle/menu to support Esc (close via
setIsOpen(false)), ArrowDown/ArrowUp (move focus between options using a ref
array or index), and Enter/Space (activate current option), and ensure focus is
managed so the currently highlighted option receives focus when opening;
reference functions/variables: setIsOpen, isOpen, selectedOption, onChange,
options, and DownArrow to locate insertion points.
In `@apps/web/src/pages/RegisterClub/index.tsx`:
- Line 13: The first card's link is a relative path ('clubs/register') causing
broken navigation via to={card.link}; update the cards data so the first card's
link is an absolute path (prepend a leading slash) — locate the cards array or
object where link: 'clubs/register' is defined and change it to link:
'/clubs/register' so Router navigation always resolves to the correct absolute
route.
In `@apps/web/src/pages/RegisterClub/RegisterClubList/index.tsx`:
- Around line 20-24: Replace the hardcoded hex utility classes in
RegisterClubList (the section and the paragraph star) with the project design
tokens from `@konect/design-tokens`: remove border-[`#E7EBEF`], bg-[`#FFF`], and
text-[`#DD2E44`] and substitute the corresponding token-based utility classes or
CSS variables exported by `@konect/design-tokens` (import the token CSS export at
the top of the component and apply the token class/variable to the section
element and the star <p>); the same replacement should be made for the other
occurrence referenced around line 62.
- Around line 22-25: The current markup in RegisterClubList uses a span with
className="flex" containing block-level <p> elements, which breaks semantics;
replace the span with a block-level container (e.g., a div or label) — update
the element wrapping the two <p> nodes (the one with className="flex") to div or
label as appropriate for form semantics and keep existing className and children
unchanged so layout and styles remain intact; if this text is a form field label
prefer label to improve accessibility.
- Around line 19-76: The form currently has a submit button but no onSubmit
handler, causing a full page reload on click; add an onSubmit prop to the form
that points to a new handler (e.g., handleSubmit) in the RegisterClubList
component, implement handleSubmit to call event.preventDefault(), perform
validation/processing (use existing state like selectedUniversity and any file
inputs), and then call your upload/submit logic or API; keep the button as
type="submit" and ensure handleSubmit is bound/declared in the same component so
the form no longer triggers a default page reload.
---
Nitpick comments:
In `@apps/web/src/App.tsx`:
- Line 8: In App.tsx replace the relative import of RegisterClubList with the
project path-alias import; update the import statement that currently reads
import RegisterClubList from './pages/RegisterClub/RegisterClubList' to use
'`@/pages/RegisterClub/RegisterClubList`' so internal app imports follow the `@/*`
convention and remain consistent across the codebase.
🪄 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: 68547c26-8bd4-4fdf-a37f-8c0c12b51536
⛔ Files ignored due to path filters (1)
apps/web/src/assets/arrow-down.svgis excluded by!**/*.svg,!apps/*/src/assets/**and included by**
📒 Files selected for processing (4)
apps/web/src/App.tsxapps/web/src/components/UniversityDropdown/index.tsxapps/web/src/pages/RegisterClub/RegisterClubList/index.tsxapps/web/src/pages/RegisterClub/index.tsx
| <button | ||
| type="button" | ||
| className="border-text-100 text-text-400 flex h-15.25 w-full items-center justify-between rounded-[20px] border px-7.5 py-6.5 text-[20px] leading-10 font-medium" | ||
| onClick={() => { | ||
| setIsOpen(!isOpen); | ||
| }} | ||
| > | ||
| {selectedOption?.name ?? placeholder} | ||
| <DownArrow /> | ||
| </button> | ||
| {isOpen && ( | ||
| <div className="border-text-100 absolute top-full left-0 z-10 mt-2 flex w-full flex-col items-start gap-5 self-stretch rounded-[20px] border bg-[#FFF] px-7.5 py-6.5"> | ||
| {options.map((option) => ( | ||
| <button | ||
| key={option.id} | ||
| type="button" | ||
| onClick={() => { | ||
| onChange(option.id); | ||
| setIsOpen(false); | ||
| }} | ||
| className="text-text-400 text-[20px] leading-10 font-medium" | ||
| > | ||
| {option.name} | ||
| </button> | ||
| ))} | ||
| </div> | ||
| )} |
There was a problem hiding this comment.
드롭다운 접근성 속성을 추가해주세요.
현재 구현은 aria-expanded, aria-controls, role/aria-selected 및 키보드 탐색(최소 Esc 닫기)이 없어 접근성이 부족합니다.
수정 예시
- <button
+ <button
type="button"
+ aria-haspopup="listbox"
+ aria-expanded={isOpen}
+ aria-controls="university-dropdown-list"
className="border-text-100 text-text-400 flex h-15.25 w-full items-center justify-between rounded-[20px] border px-7.5 py-6.5 text-[20px] leading-10 font-medium"
onClick={() => {
setIsOpen(!isOpen);
}}
>
@@
- {isOpen && (
- <div className="border-text-100 absolute top-full left-0 z-10 mt-2 flex w-full flex-col items-start gap-5 self-stretch rounded-[20px] border bg-[`#FFF`] px-7.5 py-6.5">
+ {isOpen && (
+ <div
+ id="university-dropdown-list"
+ role="listbox"
+ className="border-text-100 absolute top-full left-0 z-10 mt-2 flex w-full flex-col items-start gap-5 self-stretch rounded-[20px] border bg-white px-7.5 py-6.5"
+ onKeyDown={(e) => {
+ if (e.key === 'Escape') setIsOpen(false);
+ }}
+ >
{options.map((option) => (
<button
key={option.id}
type="button"
+ role="option"
+ aria-selected={option.id === value}
onClick={() => {
onChange(option.id);
setIsOpen(false);
}}As per coding guidelines 접근성 규칙: "apps//src/components/** ... 접근성(aria-, role, 키보드 탐색)이 적절히 처리되는지".
🤖 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 `@apps/web/src/components/UniversityDropdown/index.tsx` around lines 27 - 53,
Add proper ARIA roles/attributes and keyboard handling to the dropdown: give the
toggle button (the element using setIsOpen) aria-expanded tied to isOpen and
aria-controls pointing to the menu id; add a unique id for the menu and set
role="listbox" on the menu container; for each option button (the elements
rendering option.name) set role="option" and aria-selected based on
selectedOption.id, and ensure onChange is called on activation; implement
keyboard handlers on the toggle/menu to support Esc (close via
setIsOpen(false)), ArrowDown/ArrowUp (move focus between options using a ref
array or index), and Enter/Space (activate current option), and ensure focus is
managed so the currently highlighted option receives focus when opening;
reference functions/variables: setIsOpen, isOpen, selectedOption, onChange,
options, and DownArrow to locate insertion points.
| <form className="flex flex-col gap-10"> | ||
| <section className="flex h-183.75 w-254 flex-col gap-10 rounded-[20px] border border-[#E7EBEF] bg-[#FFF] px-11 py-10"> | ||
| <div className="flex w-full flex-col gap-2.5"> | ||
| <span className="flex"> | ||
| <p className="text-text-900 text-[24px] font-bold">대학교명</p> | ||
| <p className="text-[24px] font-bold text-[#DD2E44]">*</p> | ||
| </span> | ||
| <UniversityDropdown | ||
| value={selectedUniversity} | ||
| onChange={setSelectedUniversity} | ||
| options={universityOption} | ||
| /> | ||
| </div> | ||
| <div className="flex w-full flex-col gap-2.5"> | ||
| <div className="flex w-full items-start justify-between"> | ||
| <span className="text-text-900 text-[24px] font-bold">파일 첨부</span> | ||
| <button | ||
| type="button" | ||
| className="bg-primary-500 flex h-13 w-47 items-center justify-center rounded-[20px] px-1.5 py-5 text-[20px] leading-10 font-semibold text-white" | ||
| > | ||
| 엑셀 양식 다운로드 | ||
| </button> | ||
| </div> | ||
| <div className="border-text-100 flex h-62 w-full flex-col items-center justify-center gap-2.5 rounded-[20px] border px-7.5 py-6.5"> | ||
| <p className="text-text-400 text-center text-[20px] font-medium"> | ||
| 첨부할 사진을 여기에 끌어놓거나, | ||
| <br /> | ||
| 파일 선택 버튼을 눌러 직접 파일을 선택해주세요. | ||
| </p> | ||
| <button | ||
| type="button" | ||
| className="bg-primary-500 h-13 w-39.5 rounded-[20px] text-[20px] leading-10 font-semibold text-white" | ||
| > | ||
| 파일 선택 | ||
| </button> | ||
| </div> | ||
| <div className="flex w-full justify-between"> | ||
| <p className="text-text-300 text-[20px] font-semibold"> | ||
| 학교 동아리 정보가 포함된 파일을 업로드 해주세요. | ||
| </p> | ||
| <p className="text-text-400 text-right text-[20px] leading-10 font-medium">0/5</p> | ||
| </div> | ||
| </div> | ||
| <div className="border-text-200 flex self-stretch rounded-[20px] border border-dashed p-3"> | ||
| <p className="text-text-500 px-2.5 text-[20px] leading-10 font-semibold"> | ||
| 입력해주신 정보는 내부 확인 후 동아리 상세 페이지에 반영됩니다. | ||
| <br /> | ||
| 허위정보 혹은 부적절한 내용은 반영이 제한될 수 있습니다. | ||
| </p> | ||
| </div> | ||
| </section> | ||
| <button | ||
| type="submit" | ||
| className="bg-primary-500 flex h-15.25 w-full items-center justify-center self-stretch rounded-[20px] px-5 py-1.5 text-[20px] leading-10 font-semibold text-white" | ||
| > | ||
| 내용 보내기 | ||
| </button> | ||
| </form> |
There was a problem hiding this comment.
form 제출 기본 동작을 막거나 제출 핸들러를 연결해주세요.
현재 type="submit" 버튼이 있지만 onSubmit이 없어 클릭 시 페이지 리로드가 발생할 수 있습니다.
수정 예시
- <form className="flex flex-col gap-10">
+ <form
+ className="flex flex-col gap-10"
+ onSubmit={(e) => {
+ e.preventDefault();
+ // TODO: 실제 제출 로직 연결
+ }}
+ >📝 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.
| <form className="flex flex-col gap-10"> | |
| <section className="flex h-183.75 w-254 flex-col gap-10 rounded-[20px] border border-[#E7EBEF] bg-[#FFF] px-11 py-10"> | |
| <div className="flex w-full flex-col gap-2.5"> | |
| <span className="flex"> | |
| <p className="text-text-900 text-[24px] font-bold">대학교명</p> | |
| <p className="text-[24px] font-bold text-[#DD2E44]">*</p> | |
| </span> | |
| <UniversityDropdown | |
| value={selectedUniversity} | |
| onChange={setSelectedUniversity} | |
| options={universityOption} | |
| /> | |
| </div> | |
| <div className="flex w-full flex-col gap-2.5"> | |
| <div className="flex w-full items-start justify-between"> | |
| <span className="text-text-900 text-[24px] font-bold">파일 첨부</span> | |
| <button | |
| type="button" | |
| className="bg-primary-500 flex h-13 w-47 items-center justify-center rounded-[20px] px-1.5 py-5 text-[20px] leading-10 font-semibold text-white" | |
| > | |
| 엑셀 양식 다운로드 | |
| </button> | |
| </div> | |
| <div className="border-text-100 flex h-62 w-full flex-col items-center justify-center gap-2.5 rounded-[20px] border px-7.5 py-6.5"> | |
| <p className="text-text-400 text-center text-[20px] font-medium"> | |
| 첨부할 사진을 여기에 끌어놓거나, | |
| <br /> | |
| 파일 선택 버튼을 눌러 직접 파일을 선택해주세요. | |
| </p> | |
| <button | |
| type="button" | |
| className="bg-primary-500 h-13 w-39.5 rounded-[20px] text-[20px] leading-10 font-semibold text-white" | |
| > | |
| 파일 선택 | |
| </button> | |
| </div> | |
| <div className="flex w-full justify-between"> | |
| <p className="text-text-300 text-[20px] font-semibold"> | |
| 학교 동아리 정보가 포함된 파일을 업로드 해주세요. | |
| </p> | |
| <p className="text-text-400 text-right text-[20px] leading-10 font-medium">0/5</p> | |
| </div> | |
| </div> | |
| <div className="border-text-200 flex self-stretch rounded-[20px] border border-dashed p-3"> | |
| <p className="text-text-500 px-2.5 text-[20px] leading-10 font-semibold"> | |
| 입력해주신 정보는 내부 확인 후 동아리 상세 페이지에 반영됩니다. | |
| <br /> | |
| 허위정보 혹은 부적절한 내용은 반영이 제한될 수 있습니다. | |
| </p> | |
| </div> | |
| </section> | |
| <button | |
| type="submit" | |
| className="bg-primary-500 flex h-15.25 w-full items-center justify-center self-stretch rounded-[20px] px-5 py-1.5 text-[20px] leading-10 font-semibold text-white" | |
| > | |
| 내용 보내기 | |
| </button> | |
| </form> | |
| <form | |
| className="flex flex-col gap-10" | |
| onSubmit={(e) => { | |
| e.preventDefault(); | |
| // TODO: 실제 제출 로직 연결 | |
| }} | |
| > | |
| <section className="flex h-183.75 w-254 flex-col gap-10 rounded-[20px] border border-[`#E7EBEF`] bg-[`#FFF`] px-11 py-10"> | |
| <div className="flex w-full flex-col gap-2.5"> | |
| <span className="flex"> | |
| <p className="text-text-900 text-[24px] font-bold">대학교명</p> | |
| <p className="text-[24px] font-bold text-[`#DD2E44`]">*</p> | |
| </span> | |
| <UniversityDropdown | |
| value={selectedUniversity} | |
| onChange={setSelectedUniversity} | |
| options={universityOption} | |
| /> | |
| </div> | |
| <div className="flex w-full flex-col gap-2.5"> | |
| <div className="flex w-full items-start justify-between"> | |
| <span className="text-text-900 text-[24px] font-bold">파일 첨부</span> | |
| <button | |
| type="button" | |
| className="bg-primary-500 flex h-13 w-47 items-center justify-center rounded-[20px] px-1.5 py-5 text-[20px] leading-10 font-semibold text-white" | |
| > | |
| 엑셀 양식 다운로드 | |
| </button> | |
| </div> | |
| <div className="border-text-100 flex h-62 w-full flex-col items-center justify-center gap-2.5 rounded-[20px] border px-7.5 py-6.5"> | |
| <p className="text-text-400 text-center text-[20px] font-medium"> | |
| 첨부할 사진을 여기에 끌어놓거나, | |
| <br /> | |
| 파일 선택 버튼을 눌러 직접 파일을 선택해주세요. | |
| </p> | |
| <button | |
| type="button" | |
| className="bg-primary-500 h-13 w-39.5 rounded-[20px] text-[20px] leading-10 font-semibold text-white" | |
| > | |
| 파일 선택 | |
| </button> | |
| </div> | |
| <div className="flex w-full justify-between"> | |
| <p className="text-text-300 text-[20px] font-semibold"> | |
| 학교 동아리 정보가 포함된 파일을 업로드 해주세요. | |
| </p> | |
| <p className="text-text-400 text-right text-[20px] leading-10 font-medium">0/5</p> | |
| </div> | |
| </div> | |
| <div className="border-text-200 flex self-stretch rounded-[20px] border border-dashed p-3"> | |
| <p className="text-text-500 px-2.5 text-[20px] leading-10 font-semibold"> | |
| 입력해주신 정보는 내부 확인 후 동아리 상세 페이지에 반영됩니다. | |
| <br /> | |
| 허위정보 혹은 부적절한 내용은 반영이 제한될 수 있습니다. | |
| </p> | |
| </div> | |
| </section> | |
| <button | |
| type="submit" | |
| className="bg-primary-500 flex h-15.25 w-full items-center justify-center self-stretch rounded-[20px] px-5 py-1.5 text-[20px] leading-10 font-semibold text-white" | |
| > | |
| 내용 보내기 | |
| </button> | |
| </form> |
🤖 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 `@apps/web/src/pages/RegisterClub/RegisterClubList/index.tsx` around lines 19 -
76, The form currently has a submit button but no onSubmit handler, causing a
full page reload on click; add an onSubmit prop to the form that points to a new
handler (e.g., handleSubmit) in the RegisterClubList component, implement
handleSubmit to call event.preventDefault(), perform validation/processing (use
existing state like selectedUniversity and any file inputs), and then call your
upload/submit logic or API; keep the button as type="submit" and ensure
handleSubmit is bound/declared in the same component so the form no longer
triggers a default page reload.
| <section className="flex h-183.75 w-254 flex-col gap-10 rounded-[20px] border border-[#E7EBEF] bg-[#FFF] px-11 py-10"> | ||
| <div className="flex w-full flex-col gap-2.5"> | ||
| <span className="flex"> | ||
| <p className="text-text-900 text-[24px] font-bold">대학교명</p> | ||
| <p className="text-[24px] font-bold text-[#DD2E44]">*</p> |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win
Hex 인라인 색상 대신 디자인 토큰을 사용해주세요.
border-[#E7EBEF], bg-[#FFF], text-[#DD2E44]는 토큰 우선 규칙과 맞지 않습니다. 프로젝트 토큰 클래스/토큰 CSS 변수 기반 유틸로 통일해주세요.
As per coding guidelines "**/*.{ts,tsx,css}: Use CSS export from @konect/design-tokens for design tokens, prioritized over inline values".
Also applies to: 62-62
🤖 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 `@apps/web/src/pages/RegisterClub/RegisterClubList/index.tsx` around lines 20 -
24, Replace the hardcoded hex utility classes in RegisterClubList (the section
and the paragraph star) with the project design tokens from
`@konect/design-tokens`: remove border-[`#E7EBEF`], bg-[`#FFF`], and text-[`#DD2E44`]
and substitute the corresponding token-based utility classes or CSS variables
exported by `@konect/design-tokens` (import the token CSS export at the top of the
component and apply the token class/variable to the section element and the star
<p>); the same replacement should be made for the other occurrence referenced
around line 62.
✨ 요약
😎 해결한 이슈
Summary by CodeRabbit
새로운 기능
개선