Conversation
WalkthroughQR 코드 체크인 기능이 새롭게 도입되어, QR 스캐너 컴포넌트와 체크인 페이지가 추가되었습니다. 라우터와 경로 상수에 체크인 경로가 등록되었고, 티켓 관련 훅과 API가 스캐너 동작에 맞게 확장되었습니다. 기존 참가자 및 티켓 관련 컴포넌트와 모델도 식별자와 상태 관리 방식이 일부 변경되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant CheckInPage
participant QrScannerComponent
participant Camera
participant useTicketQrCodeValidate
participant API
User->>CheckInPage: 페이지 접속
CheckInPage->>QrScannerComponent: 렌더링
User->>QrScannerComponent: "스캔 시작" 클릭
QrScannerComponent->>Camera: 카메라 접근 요청
Camera-->>QrScannerComponent: 비디오 스트림 제공
QrScannerComponent->>QrScannerComponent: QR 코드 인식
QrScannerComponent->>useTicketQrCodeValidate: orderId, sig 추출 후 검증 요청
useTicketQrCodeValidate->>API: /ticket-qr-codes/validate POST
API-->>useTicketQrCodeValidate: 검증 결과 반환
useTicketQrCodeValidate-->>QrScannerComponent: 성공/실패 콜백
QrScannerComponent-->>User: 체크인 결과 안내(Alert)
Poem
✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (6)
src/features/ticket/api/order.ts (1)
34-40: 에러 처리 추가를 고려해보세요.QR 코드 검증은 중요한 기능이므로 네트워크 오류나 서버 에러에 대한 적절한 처리가 필요합니다. 다른 API 함수들과 일관성을 위해 try-catch 블록을 추가하는 것을 권장합니다.
export const ticketQrCode = async (orderId: number, sig: string) => { + try { const response = await axiosClient.post('/ticket-qr-codes/validate', { orderId, sig, }); return response.data; + } catch (error) { + console.error('QR 코드 검증 중 오류 발생:', error); + throw error; + } };src/widgets/dashboard/ui/ticket/TicketItem.tsx (1)
10-13: URL 매개변수 유효성 검사를 강화해보세요.현재
id가 없을 때 기본값으로 0을 사용하고 있는데, 이는 잠재적으로 문제가 될 수 있습니다. 유효하지 않은 eventId로 인한 예상치 못한 동작을 방지하기 위해 더 명확한 검증을 추가하는 것을 권장합니다.const { id } = useParams(); -const eventId = id ? parseInt(id) : 0; +const eventId = id ? parseInt(id, 10) : null; -const { mutate: handleDelete } = useDeleteTicket(eventId); +const { mutate: handleDelete } = useDeleteTicket(eventId || 0);또는 eventId가 유효하지 않을 때 삭제 버튼을 비활성화하는 것도 고려해볼 수 있습니다.
src/features/dashboard/hook/useParticipants.ts (1)
40-43: 캐시 무효화 범위를 더 구체적으로 지정해보세요.현재 모든 'participants' 쿼리를 무효화하고 있는데, 특정 이벤트의 참가자만 무효화하는 것이 더 효율적일 수 있습니다.
queryClient.invalidateQueries({ - predicate: (query) => - Array.isArray(query.queryKey) && query.queryKey[0] === 'participants', + queryKey: ['participants'], });또는 특정 이벤트 ID가 있다면:
const { id } = useParams(); const eventId = Number(id); // onSuccess에서: queryClient.invalidateQueries({ queryKey: ['participants', eventId], });src/features/ticket/hooks/useOrderHook.ts (1)
39-46: 에러 타입 개선 및 에러 처리 로직 승인특정 에러 코드(
TICKET4004)에 대한 세분화된 에러 처리가 추가되어 사용자 경험이 향상되었습니다. 하지만 TypeScript의 타입 안전성을 위해any타입 사용을 개선할 수 있습니다.다음과 같이 에러 타입을 개선할 수 있습니다:
- onError: (error: any) => { + onError: (error: { code?: string }) => {🧰 Tools
🪛 ESLint
[error] 39-39: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
src/features/ticket/ui/QrScanner.tsx (1)
42-53: 사용하지 않는 변수 제거 필요카메라 권한 처리 로직은 적절하지만, catch 블록의 에러 변수가 사용되지 않습니다.
다음과 같이 수정하여 linting 경고를 해결할 수 있습니다:
- } catch (e) { + } catch {🧰 Tools
🪛 ESLint
[error] 48-48: 'e' is defined but never used.
(@typescript-eslint/no-unused-vars)
design-system/ui/modals/QrModal.tsx (1)
77-77: children prop 사용 패턴 개선 권장React의 권장사항에 따라 children을 JSX 요소로 전달하는 것이 좋습니다.
다음과 같이 수정할 수 있습니다:
- <Countdown children={remainDays} isChecked={isCountdownChecked} /> + <Countdown isChecked={isCountdownChecked}>{remainDays}</Countdown> - children={formattedDate} + {formattedDate} - children={location} + {location} - children={ticketName} + {ticketName} - children={orderStatus === 'COMPLETED' ? '승인됨' : '대기 중'} + {orderStatus === 'COMPLETED' ? '승인됨' : '대기 중'} - children={isCheckIn ? '체크인 완료' : '체크인 미완료'} + {isCheckIn ? '체크인 완료' : '체크인 미완료'}Also applies to: 84-84, 90-90, 96-96, 104-104, 110-110
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
package-lock.jsonis excluded by!**/package-lock.jsonyarn.lockis excluded by!**/yarn.lock,!**/*.lock
📒 Files selected for processing (14)
design-system/ui/modals/QrModal.tsx(2 hunks)package.json(1 hunks)src/app/routes/Router.tsx(2 hunks)src/app/routes/routes.ts(1 hunks)src/features/dashboard/hook/useParticipants.ts(2 hunks)src/features/dashboard/model/participantInformation.ts(1 hunks)src/features/dashboard/ui/ParicipantCard.tsx(2 hunks)src/features/dashboard/ui/PariticipantsList.tsx(1 hunks)src/features/ticket/api/order.ts(1 hunks)src/features/ticket/hooks/useOrderHook.ts(2 hunks)src/features/ticket/hooks/useTicketHook.ts(2 hunks)src/features/ticket/ui/QrScanner.tsx(1 hunks)src/pages/dashboard/ui/ticket/CheckInPage.tsx(1 hunks)src/widgets/dashboard/ui/ticket/TicketItem.tsx(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (9)
src/app/routes/Router.tsx (1)
src/app/routes/routes.ts (1)
DASHBOARD_ROUTES(36-52)
src/features/dashboard/ui/ParicipantCard.tsx (1)
src/features/dashboard/hook/useParticipants.ts (1)
useApproveParticipants(33-46)
src/widgets/dashboard/ui/ticket/TicketItem.tsx (1)
src/features/ticket/hooks/useTicketHook.ts (1)
useDeleteTicket(29-41)
src/features/dashboard/hook/useParticipants.ts (2)
src/shared/types/api/apiResponse.ts (1)
ApiResponse(1-5)src/features/dashboard/api/participants.ts (1)
approveParticipants(14-22)
src/features/ticket/api/order.ts (1)
src/shared/types/api/http-client.ts (1)
axiosClient(6-13)
src/features/ticket/hooks/useOrderHook.ts (1)
src/features/ticket/api/order.ts (1)
ticketQrCode(34-40)
src/features/ticket/ui/QrScanner.tsx (1)
src/features/ticket/hooks/useOrderHook.ts (1)
useTicketQrCodeValidate(51-62)
src/features/ticket/hooks/useTicketHook.ts (3)
src/shared/types/api/apiResponse.ts (1)
ApiResponse(1-5)src/features/ticket/model/ticketInformation.ts (1)
CreateTicketRequest(3-12)src/features/ticket/api/ticket.ts (2)
createTicket(4-7)deleteTicket(16-19)
design-system/ui/modals/QrModal.tsx (2)
src/features/ticket/api/order.ts (1)
ticketQrCode(34-40)design-system/styles/flex.ts (2)
flexColumn(9-9)flexRowSpaceBetweenCenter(1-1)
🪛 ESLint
src/features/ticket/hooks/useOrderHook.ts
[error] 39-39: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
src/features/ticket/ui/QrScanner.tsx
[error] 48-48: 'e' is defined but never used.
(@typescript-eslint/no-unused-vars)
🪛 Biome (1.9.4)
design-system/ui/modals/QrModal.tsx
[error] 79-79: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 89-89: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 95-95: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 99-99: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 108-108: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 116-116: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🔇 Additional comments (23)
package.json (1)
27-27:Details
✅ Verification successful
QR Scanner 패키지 버전 및 보안 검증 필요
QR 코드 스캐닝 기능에 중요한 qr-scanner 패키지가 추가되었습니다. 버전의 유효성과 보안 취약점을 확인해주세요.
다음 스크립트로 최신 버전과 보안 권고사항을 확인해주세요:
🏁 Script executed:
#!/bin/bash # Description: qr-scanner 패키지의 최신 버전 및 보안 권고사항 확인 # 최신 버전 확인 curl -s https://registry.npmjs.org/qr-scanner | jq '.["dist-tags"].latest' # 보안 권고사항 확인 gh api graphql -f query=' { securityVulnerabilities(first: 5, ecosystem: NPM, package: "qr-scanner") { nodes { advisory { summary severity publishedAt } vulnerableVersionRange firstPatchedVersion { identifier } } } }'Length of output: 428
qr-scanner 패키지 버전 및 보안 문제 없음 확인됨
- npm 레지스트리에서 확인한 최신 버전(1.4.2)과 일치합니다.
- GitHub 보안 권고사항에도 관련 취약점이 보고되지 않았습니다.
위 내용을 바탕으로 이 변경을 승인합니다.
src/features/dashboard/model/participantInformation.ts (1)
4-4: 식별자 리팩토링 승인
orderId에서orderCode로의 프로퍼티 이름 변경이 적절합니다. 전체 코드베이스의 일관성 있는 네이밍 개선의 일부로 보입니다.src/app/routes/routes.ts (1)
51-51: 체크인 라우트 추가 승인새로운 체크인 라우트가 적절하게 추가되었습니다. 기존 대시보드 라우트 패턴과 일관성 있게 구현되었습니다.
src/app/routes/Router.tsx (2)
40-40: CheckInPage 임포트 추가 승인체크인 페이지 컴포넌트 임포트가 적절하게 추가되었습니다.
85-85: 체크인 라우트 설정 승인체크인 라우트가 올바르게 설정되었습니다.
requiresAuth: false설정이 체크인 기능에 적절한지 확인해주세요.src/features/dashboard/ui/PariticipantsList.tsx (1)
41-41: 주문 조회 로직 일관성 검증 필요
selectedOrderId가 이제participant.id값을 사용하는데, 주문 조회에서는order.orderId와 비교하고 있습니다. 이 두 값이 동일한지 확인이 필요합니다.src/pages/dashboard/ui/ticket/CheckInPage.tsx (1)
1-12: 깔끔하고 명확한 구현입니다.컴포넌트 구조가 단순하고 목적이 명확하며, 반응형 디자인도 잘 적용되어 있습니다. QR 스캐너 기능에 집중한 좋은 구현입니다.
src/features/dashboard/ui/ParicipantCard.tsx (3)
15-15: 훅 매개변수와 승인 함수 호출 간의 일관성을 확인해보세요.
useApproveParticipants훅을participant.id로 호출하고 있고, 승인 버튼에서도participant.id를orderId로 전달하고 있습니다. 관련 코드 스니펫에 따르면 훅은orderId매개변수를 받도록 설계되어 있으므로 현재 구현이 올바른 것 같습니다.
20-20: 표시되는 참가자 정보가 개선되었습니다.
orderId에서orderCode로 변경하여 사용자에게 더 의미 있는 정보를 표시하도록 개선되었습니다.
23-23: 간결한 레이블 개선입니다."이메일 주소"에서 "이메일"로 단축하여 UI가 더 깔끔해졌습니다.
src/features/ticket/hooks/useOrderHook.ts (2)
2-2: LGTM!새로운 QR 코드 검증 기능을 위한 import가 적절히 추가되었습니다.
50-62: 새로운 QR 검증 훅이 잘 구현되었습니다QR 코드 검증을 위한 mutation 훅이 적절히 구현되었으며, 성공/실패에 대한 사용자 피드백도 포함되어 있습니다.
src/features/ticket/ui/QrScanner.tsx (4)
1-11: 컴포넌트 구조와 상태 관리가 적절합니다QR 스캐너 컴포넌트의 기본 구조와 상태 관리가 잘 설계되었습니다. useRef와 useState를 적절히 활용하여 스캐너 인스턴스와 상태를 관리하고 있습니다.
13-40: QR 스캐너 초기화 및 정리 로직이 우수합니다useEffect를 사용한 QR 스캐너의 초기화와 정리 로직이 적절히 구현되었습니다. 컴포넌트 언마운트 시 스캐너를 제대로 정리하는 것도 좋습니다.
55-71: QR 데이터 파싱 로직이 견고합니다QR 코드 데이터를 파싱하고 검증하는 로직이 잘 구현되었습니다. 에러 처리와 데이터 유효성 검사도 포함되어 있어 안정성이 높습니다.
73-97: UI 구성이 사용자 친화적입니다QR 스캐너의 UI가 직관적이고 사용자 친화적으로 구성되었습니다. 스캔 상태에 따른 조건부 렌더링과 결과 표시가 적절합니다.
src/features/ticket/hooks/useTicketHook.ts (3)
1-1: React Query 패턴을 올바르게 적용한 리팩토링useQueryClient를 import하고 활용하여 페이지 새로고침 대신 캐시 무효화를 사용하는 것은 좋은 개선입니다.
Also applies to: 16-16, 30-30
19-21: 티켓 생성 후 캐시 무효화 로직이 적절합니다성공 콜백에서 variables를 통해 eventId를 가져와 해당 이벤트의 티켓 목록 캐시를 무효화하는 로직이 올바르게 구현되었습니다.
29-29: useDeleteTicket 훅의 시그니처 변경이 일관성 있습니다eventId 매개변수를 받아서 삭제 성공 시 해당 이벤트의 티켓 목록 캐시를 무효화하는 패턴이 일관성 있게 적용되었습니다.
Also applies to: 35-35
design-system/ui/modals/QrModal.tsx (4)
4-4: import 정리가 적절합니다사용하지 않는 flexColumnCenter를 제거하고 필요한 flex 스타일만 유지한 것이 좋습니다.
56-58: 모달 구조 개선이 우수합니다고정 위치와 반투명 배경을 사용한 모달 오버레이 구조가 표준적이고 사용자 경험이 향상되었습니다.
61-73: QR 코드 영역 레이아웃이 명확합니다QR 코드 표시 영역이 상단 절반에 명확히 위치하도록 구조화된 것이 좋습니다. 조건부 렌더링으로 QR 코드 유무에 따른 적절한 메시지도 표시됩니다.
74-119: 세부사항 영역과 닫기 버튼 배치가 개선되었습니다모달 하단에 티켓 정보를 체계적으로 배치하고 닫기 버튼을 모달 내부로 이동한 것이 사용성을 향상시켰습니다.
🧰 Tools
🪛 Biome (1.9.4)
[error] 79-79: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 89-89: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 95-95: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 99-99: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 108-108: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 116-116: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
There was a problem hiding this comment.
Actionable comments posted: 3
🔭 Outside diff range comments (1)
design-system/ui/modals/QrModal.tsx (1)
15-15:⚠️ Potential issue사용되지 않는 인터페이스 프로퍼티를 제거하세요.
className프로퍼티가 컴포넌트에서 더 이상 사용되지 않으므로 인터페이스에서 제거해야 합니다.- className?: string;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
design-system/ui/modals/QrModal.tsx(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
design-system/ui/modals/QrModal.tsx (1)
design-system/styles/flex.ts (2)
flexColumn(9-9)flexRowSpaceBetweenCenter(1-1)
🪛 Biome (1.9.4)
design-system/ui/modals/QrModal.tsx
[error] 79-79: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 89-89: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 95-95: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 99-99: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 108-108: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 116-116: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🔇 Additional comments (2)
design-system/ui/modals/QrModal.tsx (2)
4-4: Import 구문 업데이트가 적절합니다.필요한 flex 유틸리티만 import하도록 정리되었습니다.
56-57: 모달 레이아웃이 표준 패턴을 잘 따르고 있습니다.고정 크기와 중앙 정렬로 일관된 사용자 경험을 제공합니다.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (3)
design-system/ui/modals/QrModal.tsx (3)
78-78: React 표준 관례에 따라 children prop 사용을 수정하세요.IconText 컴포넌트들이
childrenprop을 사용하고 있는데, React의 표준 관례에 따라 JSX children으로 전달해야 합니다.- <Countdown children={remainDays} isChecked={isCountdownChecked} /> + <Countdown isChecked={isCountdownChecked}>{remainDays}</Countdown><IconText size="xSmall" iconPath={<img src={qr_calendar} alt="qr_calendar" className='mr-1' />} - children={formattedDate} className="text-11" - ></IconText> + > + {formattedDate} + </IconText>동일한 패턴을 다른 모든 IconText 컴포넌트에도 적용하세요.
Also applies to: 82-87, 88-93, 94-99, 102-107, 108-113
70-72: QR 코드 영역의 크기 일관성과 스타일링을 개선하세요.현재 QR 코드 존재 여부에 따라 크기가 다르게 설정되어 레이아웃 시프트가 발생할 수 있습니다.
- <div className="w-40 h-40 flex items-center justify-center bg-deDayBgLight rounded-md border border-deDayTextDark text-deDayTextDark text-sm text-center px-4"> + <div className="w-60 h-60 flex items-center justify-center bg-deDayBgLight rounded-md border border-deDayTextDark text-deDayTextDark text-sm text-center px-4"> 주최자의 승인이 완료되면 QR이 발급됩니다. </div>
117-119: 접근성을 고려하여 닫기 버튼을 개선하세요.현재 span 요소를 클릭 가능한 버튼으로 사용하고 있어 키보드 접근성이 부족합니다.
- <span onClick={onClick} className="text-deDayTextDark text-xs underline cursor-pointer mt-2"> - 닫기 - </span> + <button + onClick={onClick} + className="text-deDayTextDark text-xs underline cursor-pointer mt-2 bg-transparent border-none p-0" + aria-label="모달 닫기" + > + 닫기 + </button>🧰 Tools
🪛 Biome (1.9.4)
[error] 117-117: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
design-system/ui/modals/QrModal.tsx(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
design-system/ui/modals/QrModal.tsx (1)
design-system/styles/flex.ts (2)
flexColumn(9-9)flexRowSpaceBetweenCenter(1-1)
🪛 Biome (1.9.4)
design-system/ui/modals/QrModal.tsx
[error] 80-80: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 90-90: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 96-96: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 100-101: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 109-109: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
[error] 117-117: Avoid passing children using a prop
The canonical way to pass children in React is to use JSX elements
(lint/correctness/noChildrenProp)
🔇 Additional comments (1)
design-system/ui/modals/QrModal.tsx (1)
4-4: import 문 정리가 적절합니다.사용하지 않는
flexColumnCenterimport가 제거되어 코드가 더 깔끔해졌습니다.
내티켓
구매날짜 외 구매 방지
구매참가자 관리
새로고침 -> 쿼리 무효화로 변경
Summary by CodeRabbit
신규 기능
UI/UX 개선
버그 수정
기타