어드민: 예약 목록 필터 + 일괄 승인/거절 - #151
Merged
Merged
Conversation
총학 요청사항 2건에 대한 어드민 화면입니다.
1. 장소 예약 목록 필터
- 장소, 상태, 예약일 기간, 예약 제목으로 검색하고 생성일/예약일 기준으로
정렬할 수 있는 필터를 추가합니다.
- 필터 조건이 count 조회에도 함께 전달되어 페이지네이션이 어긋나지 않습니다.
- 검색 버튼을 누를 때만 조회하도록 입력 중인 필터와 적용된 필터를 분리했습니다.
2. 예약 대기 목록의 중복 예약 표시 및 일괄 승인 개선
- 같은 장소, 같은 날짜에서 동시 예약 허용 개수를 넘기는 예약을 "중복"으로
표시하고, 어떤 예약과 겹치는지 보여줍니다.
- "중복 없는 예약만 선택" 버튼으로 겹치지 않는 예약만 골라 승인할 수 있습니다.
- 일괄 승인 후 서버가 돌려준 승인/건너뜀 결과를 사유와 함께 보여줍니다.
- 체크박스가 선택 상태를 반영하도록 controlled 컴포넌트로 바꿨습니다.
운영 환경에서 심사중 장소 예약이 6,850건까지 쌓여 예약 대기 목록이 매우 느리고,
일괄 승인이 사실상 동작하지 않는 문제를 고칩니다.
1. 로딩 시간 개선
- 심사중 예약 전체를 한 번에 받아 클라이언트에서 정렬하던 방식을 없애고,
서버 페이지네이션(한 페이지 20건)으로 바꿉니다.
- 정렬은 서버에서 예약일 오름차순으로 처리해, 임박한 예약이 먼저 보입니다.
2. 지난 예약 처리 (기간 필터)
- 기본값은 "다가오는 예약"이라 이미 끝난 예약은 보이지 않습니다.
- 확인이 필요할 때를 위해 "지난 예약", "전체"를 고를 수 있는 기간 드롭다운을
남겨둡니다. 안내 문구로 숨겨져 있다는 사실을 알려줍니다.
3. 일괄 승인
- 아무것도 선택하지 않고 버튼을 누르면 빈 목록이 전송되어 "0개 승인" 이라는
결과만 나왔습니다. 이제 선택된 건이 없으면 안내하고 요청하지 않습니다.
- 체크박스를 controlled 로 바꾸고, 헤더에 "이 페이지 전체 선택"을 추가했습니다.
- 버튼 라벨에 선택 건수를 표시하고, 요청 중에는 중복 클릭을 막습니다.
- 장비 예약 대기 목록에도 일괄 승인을 추가했습니다. 기존에는 체크박스와
버튼이 아예 없었습니다.
- 선택/요청 로직은 useBulkAccept 훅으로 뽑아 장소와 장비가 공유합니다.
- Drop pagination from the waiting list. Splitting it into pages meant bulk accept only ever applied to the twenty rows currently on screen, which is the opposite of what the screen is for. It renders one list again. - Reuse the same filter on both waiting-list tabs. place.reservation.filter becomes components/reservation/reservation.filter, which takes the resource select (장소 or 소유 기관) and the set of fields to show, so the place list keeps its status and date-range inputs while the waiting list gets 기간 / 정렬 / 제목 on top of the resource select. - Add 예약 일괄 거절 next to 일괄 승인 in both wait tables. useBulkAccept now drives either action and tracks which one is in flight; reject asks for confirmation first. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Handling a duplicate meant opening popo, finding the competing booking, matching it back by name in the admin tab, then opening each detail modal to compare creation times. All of that is now on the list itself. - Add a 예약 생성일 column to both wait tables. It doubles as the evidence an admin sends back when a rejected student asks who booked first. - The 중복 popup lists every overlapping reservation ordered by application time, with each creation timestamp, and marks the one that will win. - Default the wait list to 생성일 오래된순. Approving in application order is the rule, but the list was sorted by reservation date, which grouped rows by date instead and hid the order that actually matters. - Refetch the list after a bulk action instead of window.location.reload(). The reload also re-ran getServerSideProps for four statistics that a status change cannot affect, which is why the screen took so long to come back. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Member
|
LGTM |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
무엇을 하는 PR인가
어드민 예약 화면에 필터 UI를 넣고, 예약 대기 목록에서 일괄 승인 / 일괄 거절을 할 수 있게 합니다.
API: PoApper/popo-nest-api#216 (먼저 배포되어야 합니다)
화면별 변경
장소/장비 예약 목록 (

/place/reservation, /equipment/reservation)예약 대기 목록 (

/reservation)일괄 처리 UX

승인 N건, 건너뜀 M건+ 건너뛴 예약의 제목·일시·사유로 보여줍니다. 조용히 사라지는 건이 없습니다.구조 정리
components/place/place.reservation.filter.jsx→components/reservation/reservation.filter.jsx. 리소스 선택(placeId/owner)과 표시할 칸을 props로 받아 장소 목록과 대기 목록이 함께 씁니다.utils/reservation-filter.js로 분리했습니다. 날짜 input의YYYY-MM-DD를 백엔드가 기대하는YYYYMMDD로 바꾸는 처리도 여기 모여 있습니다.utils/use-bulk-accept.js가 승인/거절 두 동작을 함께 다룹니다.DB / 환경변수
둘 다 변경 없습니다.
검증
npx next lint— 이 브랜치가 건드리는 파일 기준 에러 0. pre-commit 통과.리뷰 포인트
/equipment/reservation)에는 아직 필터를 붙이지 않았습니다. API는 준비돼 있으니 필요하면 후속 PR로 올리겠습니다.추가 반영 (외부 QA 대응)
운영 담당자 QA 피드백을 받아 아래를 추가했습니다.
예약 생성일을 목록에 노출
중복 건을 처리하려면 popo 앱에서 겹치는 예약을 찾고 → 어드민 탭에서 이름으로 대조하고 → 각 상세 모달을 열어 생성일을 비교해야 했습니다. 이제 목록에서 끝납니다.
← 선순위표시를 보여줍니다.정렬 기본값을 생성일로
승인은 신청 순으로 처리하는 것이 원칙인데 대기 목록이 예약일 순으로 정렬돼 있어, 같은 날짜끼리 묶여 처리하게 되고 실제 신청 순서가 보이지 않았습니다. 기본 정렬을 생성일 오래된순으로 바꿨습니다(다른 정렬로 변경 가능).
일괄 처리 후 전체 새로고침 제거
window.location.reload()가 통계 4종을getServerSideProps로 다시 받아오게 만들어 눈에 띄게 느렸습니다. 상태 변경으로 통계가 달라지지 않으므로 목록만 다시 부릅니다.함께 보면 좋은 백엔드 변경
PoApper/popo-nest-api#216 에서 심사중 예약과 겹치는 신규 신청을 차단합니다. 앞으로 새 중복은 생기지 않지만, 기존에 쌓인 중복은 남아 있어 위 도구들은 계속 필요합니다.