Skip to content

[FEAT] 동아리원 관리페이지 UI 및 반응형 (#422)#424

Merged
ganimjeong merged 15 commits intodevelopfrom
feature/member-management-ui#422
Feb 15, 2026
Merged

[FEAT] 동아리원 관리페이지 UI 및 반응형 (#422)#424
ganimjeong merged 15 commits intodevelopfrom
feature/member-management-ui#422

Conversation

@ganimjeong
Copy link
Contributor

#️⃣연관된 이슈

closed #422

📝작업 내용

동아리원 관리 페이지의 기본 UI 레이아웃을 구현했습니다.

  • [동아리명] 회원 명단 페이지 타이틀
  • ✅ 동아리원 추가 버튼 2개 (단건 추가, 엑셀 일괄 등록)
  • ✅ 모바일용 동아리원 추가 아이콘 (+) (단건 추가)
  • ✅ 검색창 및 정렬 드롭다운 (이름순/기수순) 및 기능구현
  • ✅ 동아리원 정보 테이블 (이름, 기수, 학과, 전화번호, 역할)
  • ✅ 역할(권한) 선택 버튼 그룹 (회장단, 운영팀, 동아리원)
  • ✅ 삭제 버튼 (x)
  • ✅ 반응형 구현 (320px 까지)

이후 api 연결하면서
타입파일, api파일, 정렬 기능 은 수정이 들어갈 예정입니다.
페이지의 목데이터도 추후 삭제될 예정입니다.

스크린샷 (선택)

스크린샷 2026-02-07 오전 1 15 21

💬리뷰 요구사항(선택)

@ganimjeong ganimjeong requested a review from kanghaeun February 6, 2026 16:22
@ganimjeong ganimjeong self-assigned this Feb 6, 2026
@ganimjeong ganimjeong added the 🌈 frontend 프론트엔드 이슈 label Feb 6, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ganimjeong, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 동아리원 관리 페이지의 기본적인 UI와 반응형 디자인을 도입합니다. 동아리원 추가, 검색, 정렬 및 정보 표시를 위한 시각적 구조와 상호작용 요소를 설정하며, 향후 백엔드 통합을 위한 준비를 마쳤습니다.

Highlights

  • 동아리원 관리 페이지 UI 구현: 동아리원 관리 페이지의 기본 UI 레이아웃을 구현했습니다.
  • 주요 UI 요소 포함: 페이지 타이틀, 동아리원 추가 버튼 (단건/엑셀 일괄), 모바일용 추가 아이콘, 검색창, 정렬 드롭다운 (이름순/기수순), 동아리원 정보 테이블 (이름, 기수, 학과, 전화번호, 역할), 역할 선택 버튼 그룹, 삭제 버튼 등이 포함됩니다.
  • 반응형 디자인 적용: 320px 너비까지 지원하는 반응형 디자인을 구현했습니다.
  • API 연동 준비: 향후 API 연동을 위한 플레이스홀더, 타입 정의 및 목 데이터 사용이 포함되어 있습니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • src/pages/admin/MemberManagement/Page.tsx
    • MemberManagementPage 컴포넌트의 메인 로직을 구현했습니다.
    • MemberHeaderSection 및 MemberTableSection 컴포넌트를 통합했습니다.
    • 목(mock) 멤버 데이터를 추가하고 API 호출을 위한 플레이스홀더를 설정했습니다.
    • useMemberFilter 및 useMemberMutations 훅을 적용했습니다.
  • src/pages/admin/MemberManagement/api/member.ts
    • fetchMembers, updateMemberRole, deleteMember API 함수를 추가했습니다.
    • API 호출 시 에러 처리를 포함했습니다.
  • src/pages/admin/MemberManagement/components/MemberHeaderSection/index.styled.ts
    • 헤더 섹션의 스타일드 컴포넌트를 정의했으며, 추가 버튼 및 검색 입력 필드에 대한 반응형 스타일을 포함했습니다.
  • src/pages/admin/MemberManagement/components/MemberHeaderSection/index.tsx
    • 검색 입력, 정렬 드롭다운, 동아리원 추가 버튼을 포함하는 MemberHeaderSection 컴포넌트를 생성했습니다.
  • src/pages/admin/MemberManagement/components/MemberTableSection/index.styled.ts
    • 멤버 테이블의 스타일드 컴포넌트를 정의했으며, 역할 및 일반 테이블 요소에 대한 반응형 스타일을 포함했습니다.
  • src/pages/admin/MemberManagement/components/MemberTableSection/index.tsx
    • 멤버 데이터를 테이블 형식으로 표시하고 역할 선택 및 삭제 기능을 제공하는 MemberTableSection 컴포넌트를 생성했습니다.
  • src/pages/admin/MemberManagement/hooks/useMemberFilter.ts
    • 멤버 데이터 검색 및 정렬을 위한 커스텀 훅 useMemberFilter를 구현했습니다.
  • src/pages/admin/MemberManagement/hooks/useMemberMutations.ts
    • react-query를 사용하여 멤버 역할 업데이트 및 삭제를 처리하는 커스텀 훅 useMemberMutations를 구현했습니다.
  • src/pages/admin/MemberManagement/index.styled.ts
    • 전체 페이지 컨테이너 및 콘텐츠 래퍼에 대한 기본 스타일드 컴포넌트를 정의했습니다.
  • src/pages/admin/MemberManagement/types/member.ts
    • MemberRole, Member, SortOption에 대한 TypeScript 타입을 정의했습니다.
  • src/pages/user/Main/components/BannerSection/ClubSearchInput.tsx
    • SearchIcon 스타일드 컴포넌트에서 주석 처리된 코드(// marginLeft → marginRight)를 제거했습니다.
Activity
  • 현재까지 풀 리퀘스트에 대한 특별한 활동(댓글, 리뷰 등)은 없습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

동아리원 관리 페이지의 UI와 반응형 레이아웃을 구현한 PR이네요. 전반적으로 컴포넌트와 훅이 잘 분리되어 있고, 코드 구조가 깔끔합니다. 특히 useMemberFilter 훅에서 useMemo를 사용하여 필터링 및 정렬 로직의 성능을 최적화한 점이 좋습니다. 몇 가지 개선점을 제안드리니 확인 부탁드립니다.

export const updateMemberRole = async (
clubId: string,
memberId: number,
role: string,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

updateMemberRole 함수의 role 파라미터 타입을 string 대신 MemberRole로 지정하여 타입 안정성을 높이는 것이 좋습니다. 이렇게 하면 의도치 않은 역할 문자열이 전달되는 것을 방지할 수 있습니다. types/member 파일에 이미 MemberRole 타입이 정의되어 있으니, import type { MemberRole } from '../types/member'; 와 같이 import하여 사용해주세요.

Suggested change
role: string,
role: MemberRole,

backgroundColor: theme.colors.bg,
gap: '1rem',

['@media (max-width: 1018px)']: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

미디어 쿼리에 1018px와 같이 하드코딩된 값을 사용하고 있습니다. 테마에 정의된 브레이크포인트 변수(예: theme.breakpoints.web)를 사용하면 코드의 일관성과 유지보수성을 높일 수 있습니다. 이 파일의 다른 미디어 쿼리(638px)에도 동일하게 적용하는 것을 권장합니다.

Suggested change
['@media (max-width: 1018px)']: {
['@media (max-width: ${theme.breakpoints.web})']: {

fontSize: theme.font.size.base,
color: theme.colors.textSecondary,

['@media (max-width: 833px)']: {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

미디어 쿼리에 833px와 같이 하드코딩된 값을 사용하고 있습니다. 테마에 정의된 브레이크포인트 변수를 사용하면 일관성을 유지하고 향후 관리를 용이하게 할 수 있습니다. 이 파일에 있는 다른 여러 미디어 쿼리(854px, 910px, 797px 등)에도 동일하게 적용하는 것을 고려해 보세요.

Suggested change
['@media (max-width: 833px)']: {
['@media (max-width: ${theme.breakpoints.tablet})']: {

Comment on lines 8 to 9
mutationFn: ({ memberId, role }: { memberId: number; role: string }) =>
updateMemberRole(clubId, memberId, role),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

updateRoleMutationmutationFn에서 role 파라미터 타입을 string 대신 MemberRole로 지정하는 것이 좋습니다. 이렇게 하면 타입 안정성이 향상됩니다. 관련하여 handleRoleChange 함수의 newRole 파라미터(22번째 줄)도 MemberRole 타입으로 변경하는 것을 권장합니다. MemberRole 타입은 ../types/member에서 가져올 수 있습니다.

Suggested change
mutationFn: ({ memberId, role }: { memberId: number; role: string }) =>
updateMemberRole(clubId, memberId, role),
mutationFn: ({ memberId, role }: { memberId: number; role: MemberRole }) =>
updateMemberRole(clubId, memberId, role),

Comment on lines 27 to 54
<tbody>
{members.map((member) => (
<S.TableRow key={member.id}>
<S.TdName>{member.name}</S.TdName>
<S.Td>{member.generation}</S.Td>
<S.Td>{member.department}</S.Td>
<S.Td>{member.phoneNumber}</S.Td>
<S.TdRole>
<S.RoleButtonGroup>
{ROLES.map((role) => (
<S.RoleButton
key={role}
active={member.role === role}
onClick={() => onRoleChange(member.id, role)}
>
{role}
</S.RoleButton>
))}
</S.RoleButtonGroup>
</S.TdRole>
<S.Td>
<S.DeleteButton onClick={() => onDelete(member.id)}>
<FiX />
</S.DeleteButton>
</S.Td>
</S.TableRow>
))}
</tbody>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map내부에 요소들을 별도 컴포넌트로 분리하는 것도 괜찮을 것 같아요!

Comment on lines 10 to 15
const filtered = members.filter(
(member) =>
member.name.includes(searchText) ||
member.generation.includes(searchText) ||
member.department.includes(searchText),
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

필드가 많으니까

(member) => 
[member.name , member.generation, member.department].some(field => field.includes(searchText))

이렇게 써도 괜찮을 듯 해요

@@ -0,0 +1,60 @@
import { FiX } from 'react-icons/fi';
import * as S from './index.styled';
import type { Member, MemberRole } from '../../types/member';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alias로 수정해주세용

<S.SearchIcon>
<FiSearch />
</S.SearchIcon>
<S.SearchInput
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

공통 input 컴포넌트를 안 쓰신 이유가 있나요?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

src/shared/components/Form 내부의 인풋이면 아이콘넣어서 사용할 수 있는 구조가 아닌 것 같아서 따로 썼어요!

@ganimjeong ganimjeong merged commit 6781b4a into develop Feb 15, 2026
5 checks passed
@ganimjeong ganimjeong deleted the feature/member-management-ui#422 branch February 15, 2026 04:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🌈 frontend 프론트엔드 이슈

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 동아리원 관리 페이지 기본 UI 구현

2 participants