feat(ADMIN-336): 쿠폰 관리 추가 - #5
Conversation
|
Caution Review failedThe pull request is closed. Walkthrough관리자용 쿠폰 관리 기능을 추가합니다. 새로운 쿠폰 관리 페이지 컴포넌트와 관련된 타입 정의, 범용 API 요청 유틸리티, 쿠폰 CRUD 및 코드/발행 관련 API 헬퍼들이 추가되며 라우트가 등록됩니다. (50단어 이내) Changes
Sequence Diagram(s)sequenceDiagram
participant 관리자 as 관리자
participant UI as CouponPage
participant API as requestApi 헬퍼 / API 함수
participant 서버 as 백엔드
관리자->>UI: 쿠폰 페이지 접속
activate UI
UI->>API: getCoupons(), getCouponCodes(), getIssuedCoupons(), getAdminMembers()
activate API
API->>서버: GET /admin/coupons<br/>GET /admin/coupons/code<br/>GET /admin/coupons/issued<br/>GET /admin/members
activate 서버
서버-->>API: 데이터 응답 (JSON)
deactivate 서버
API-->>UI: ApiResult<T> 반환
deactivate API
UI->>UI: 상태 갱신 및 렌더링
deactivate UI
UI-->>관리자: 데이터 표시
sequenceDiagram
participant 관리자 as 관리자
participant UI as CouponPage
participant API as requestApi 헬퍼 / API 함수
participant 서버 as 백엔드
관리자->>UI: 쿠폰 발행 요청 (쿠폰 선택, 회원 선택)
activate UI
UI->>UI: 입력 검증
alt 검증 성공
UI->>API: createIssuedCoupons(couponId, memberIds[])
activate API
API->>서버: POST /admin/coupons/issued { couponId, memberIds }
activate 서버
서버-->>API: 발행된 AdminIssuedCoupon[] 응답
deactivate 서버
API-->>UI: ApiResult<AdminIssuedCoupon[]>
deactivate API
UI->>UI: 알림 표시 및 getIssuedCoupons() 호출로 갱신
else 검증 실패
UI-->>관리자: 오류 메시지 표시
end
deactivate UI
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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: 1
🤖 Fix all issues with AI agents
In `@src/page/coupon.tsx`:
- Around line 530-532: The UI shows filteredMembersForIssue.length vs
selectedMemberIdsForIssue.length which can mismatch when a filter is applied;
compute the count of selected members that are within the current filter (e.g.
derive selectedAmongFiltered by filtering selectedMemberIdsForIssue against
filteredMembersForIssue ids) and display that filtered-selected count beside
filteredMembersForIssue.length, optionally also showing the global
selectedMemberIdsForIssue.length in a secondary label; update the render logic
where filteredMembersForIssue and selectedMemberIdsForIssue are used to show
counts (the span that currently renders “총 {filteredMembersForIssue.length}명 중
{selectedMemberIdsForIssue.length}명 선택”).
🧹 Nitpick comments (6)
src/api/coupon/request.ts (2)
7-15:Headers객체 전달 시 스프레드가 올바르게 동작하지 않을 수 있습니다.
init.headers가Headers인스턴스나[string, string][]배열일 경우, 객체 스프레드(...initHeaders)로는 헤더가 병합되지 않습니다. 현재 PR의 모든 호출부에서는 커스텀 헤더를 전달하지 않아 당장 문제가 되지 않지만,requestApi가 범용 헬퍼로 설계된 만큼 방어적으로 처리해두면 좋겠습니다.♻️ 제안
- const initHeaders = init?.headers ?? {}; + const initHeaders = new Headers(init?.headers); + if (!initHeaders.has('accept')) { + initHeaders.set('accept', 'application/json'); + } + if (!initHeaders.has('Content-Type')) { + initHeaders.set('Content-Type', 'application/json'); + } const response = await fetch(`${API_BASE_URL}${path}`, { ...init, credentials: 'include', - headers: { - accept: 'application/json', - 'Content-Type': 'application/json', - ...initHeaders, - }, + headers: initHeaders, });
11-14: GET/DELETE 요청에도Content-Type: application/json이 설정됩니다.body가 없는 요청(GET, DELETE)에
Content-Type헤더를 설정하면 일부 서버나 프록시에서 예기치 않은 동작을 유발할 수 있습니다. body가 있을 때만Content-Type을 설정하는 것을 권장합니다.src/page/coupon.tsx (4)
239-260: 비동기 작업 중 버튼 중복 클릭 방지가 없습니다.
handleCreateCoupon,handleUpdateCouponName,handleDeleteCoupon등 모든 mutation 핸들러에서 요청 진행 중에도 버튼이 활성화 상태로 남아 있어 중복 요청이 발생할 수 있습니다. 특히 쿠폰 생성/삭제/발급은 서버 상태를 변경하므로, 진행 중 상태(isSubmitting등)를 추가하여 버튼을 비활성화하는 것을 권장합니다.
131-136:loadAll이useEffect의존성 배열에 누락되어 있습니다.
eslint-plugin-react-hooks의exhaustive-deps규칙에서 경고가 발생할 수 있습니다.loadAll을useCallback으로 감싸거나,useEffect내부에 인라인으로 정의하는 방식을 고려해주세요.
87-129: 모든 mutation 후 전체 데이터를 다시 로드합니다.각 생성/수정/삭제 작업 후
loadAll()을 호출하여 4개 API를 모두 다시 호출합니다. 관리자 페이지이므로 트래픽이 적어 현재로서는 괜찮지만, 향후 데이터가 많아지면 변경된 리소스만 선택적으로 갱신하는 방식이 효율적일 수 있습니다.
63-805:CouponPage컴포넌트의 크기가 상당히 큽니다.현재 하나의 컴포넌트에 상태 관리, 이벤트 핸들러, 3개 탭의 렌더링 로직이 모두 포함되어 있습니다 (~740줄). 장기적으로 유지보수를 위해 각 탭의 테이블과 액션 패널을 별도 컴포넌트로 분리하는 것을 고려해주세요.
Summary by CodeRabbit
릴리스 노트