Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthrough새로운 QR 적립 모달 기능을 구현했습니다. Changes
Sequence Diagram(s)sequenceDiagram
actor User
participant CafeIntro
participant QRStampModal
participant Browser as Browser<br/>(MediaDevices API)
User->>CafeIntro: 스탬프 아이콘 클릭
CafeIntro->>CafeIntro: isQrModalOpen = true
CafeIntro->>QRStampModal: open={true} 전달
QRStampModal->>QRStampModal: useEffect 실행
QRStampModal->>Browser: getUserMedia({video, audio:false})
alt 카메라 접근 성공
Browser-->>QRStampModal: MediaStream 반환
QRStampModal->>QRStampModal: video.srcObject 설정
QRStampModal->>QRStampModal: video.play() 실행
QRStampModal-->>User: 카메라 피드 표시
else 카메라 접근 실패
Browser-->>QRStampModal: 에러 반환
QRStampModal-->>User: 에러 메시지 표시
end
User->>QRStampModal: "적립하기" 버튼 클릭
QRStampModal->>QRStampModal: onSubmit() 호출
User->>QRStampModal: 닫기 버튼 클릭
QRStampModal->>QRStampModal: cleanup - 모든 트랙 정지
QRStampModal->>CafeIntro: onClose() 호출
CafeIntro->>CafeIntro: isQrModalOpen = false
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~22 minutes Possibly related issues
Possibly related PRs
Poem
🚥 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. ✨ Finishing Touches📝 Generate docstrings
🧪 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: 2
🧹 Nitpick comments (3)
apps/owner/src/app/(tabs)/main/_components/QRStampModal.tsx (2)
63-68: 중복된 카메라 스트림 정리 로직이
useEffect는 첫 번째useEffect(lines 28-61)의 cleanup 함수와 동일한 작업을 수행합니다.open이false로 변경되면 첫 번째 effect의 cleanup이 자동으로 실행되므로, 이 effect는 불필요합니다.♻️ 중복 useEffect 제거
- useEffect(() => { - if (!open && streamRef.current) { - streamRef.current.getTracks().forEach((track) => track.stop()); - streamRef.current = null; - } - }, [open]);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/owner/src/app/`(tabs)/main/_components/QRStampModal.tsx around lines 63 - 68, Remove the duplicate useEffect that runs on [open] and stops tracks on streamRef.current; the cleanup is already handled in the earlier useEffect's cleanup, so delete the second effect (the one that checks if (!open && streamRef.current) and calls getTracks().forEach(track => track.stop()) and sets streamRef.current = null) and keep the existing cleanup logic in the original useEffect so camera tracks are stopped only once.
72-129: 풀스크린 모달 접근성 개선 권장풀스크린 모달에서 다음 접근성 기능 추가를 권장합니다:
- ESC 키로 모달 닫기: 키보드 사용자를 위한 표준 패턴
- Focus trap: 모달 내부로 포커스 제한
- ARIA 속성:
role="dialog",aria-modal="true",aria-labelledby♿ ESC 키 핸들링 예시
useEffect(() => { if (!open) return; const handleKeyDown = (e: KeyboardEvent) => { if (e.key === "Escape") { onClose(); } }; document.addEventListener("keydown", handleKeyDown); return () => document.removeEventListener("keydown", handleKeyDown); }, [open, onClose]);루트
<div>에 ARIA 속성 추가:- <div className="fixed inset-0 z-[999] bg-black"> + <div + role="dialog" + aria-modal="true" + aria-labelledby="qr-modal-title" + className="fixed inset-0 z-[999] bg-black" + >- <h1 className="head2-sb text-primary-variant">적립</h1> + <h1 id="qr-modal-title" className="head2-sb text-primary-variant">적립</h1>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/owner/src/app/`(tabs)/main/_components/QRStampModal.tsx around lines 72 - 129, This modal (QRStampModal component) needs keyboard/ARIA accessibility: add an effect in QRStampModal that when open mounts it attaches a keydown handler to call onClose() on Escape and restores cleanup; implement a focus trap so focus is constrained inside the modal while open (ensure initial focus moves into the modal and returned to the previously focused element on close) and ensure the close button (onClose) is focusable; add ARIA attributes to the root modal container (role="dialog", aria-modal="true") and give the title element (the h1 with text "적립") an id referenced by aria-labelledby on the root so assistive tech announces the dialog. Use existing symbols (onClose, onSubmit, videoRef, cameraError, ScanFrame, SCAN_BOX_SIZE) to locate the component code and wire these changes.apps/owner/src/app/(tabs)/main/_components/CafeIntro.tsx (1)
48-50:handleSubmitStamp에서 QR 스캔 데이터 처리 로직 누락현재
handleSubmitStamp는 콘솔 로그만 출력하며,QRStampModal의onSubmitprop도 파라미터 없이 정의되어 있습니다. 실제 QR 코드 스캔 결과를 전달받아 처리하는 로직이 필요합니다.향후 QR 스캔 라이브러리 연동 시 인터페이스 변경이 필요합니다:
// QRStampModal의 interface 변경 필요 onSubmit?: (qrData: string) => void;QR 코드 디코딩 및 데이터 전달 로직 구현을 도와드릴까요?
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/owner/src/app/`(tabs)/main/_components/CafeIntro.tsx around lines 48 - 50, handleSubmitStamp currently only logs and doesn’t accept QR data; update the QR handling by changing handleSubmitStamp to accept a string parameter (e.g., qrData) and implement processing/validation logic (parse/validate qrData, call existing stamp API or state updater, handle errors and success feedback), then pass that handler into QRStampModal via the onSubmit prop so QRStampModal.onSubmit?: (qrData: string) => void will receive the scanned string; locate and modify the handleSubmitStamp function and the QRStampModal usage in CafeIntro.tsx to wire the qrData through and add basic try/catch + success/error handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/owner/src/app/`(tabs)/main/_components/QRStampModal.tsx:
- Around line 104-111: Remove the isInteractive prop from the Icon rendered
inside the button to avoid nested interactive elements; locate the Icon
component usage within the QRStampModal (the <Icon name="CloseButton" ... />
instance) and delete the isInteractive attribute so the outer <button> remains
the sole interactive control.
- Around line 44-47: The startCamera function risks a race where after awaiting
getUserMedia the component unmounted or open became false and videoRef.current
is null; update startCamera to capture any necessary state/ref into local
variables before awaiting (e.g., const ref = videoRef.current and const isOpen =
open), then after await verify that ref is still non-null and isOpen is still
true before assigning ref.srcObject and calling ref.play; if the check fails,
immediately stop/cleanup the obtained MediaStream tracks
(stream.getTracks().forEach(t => t.stop())) to avoid leaking the camera and
return early. Ensure all references in this logic mention startCamera, videoRef,
stream and open so reviewers can find and apply the fix.
---
Nitpick comments:
In `@apps/owner/src/app/`(tabs)/main/_components/CafeIntro.tsx:
- Around line 48-50: handleSubmitStamp currently only logs and doesn’t accept QR
data; update the QR handling by changing handleSubmitStamp to accept a string
parameter (e.g., qrData) and implement processing/validation logic
(parse/validate qrData, call existing stamp API or state updater, handle errors
and success feedback), then pass that handler into QRStampModal via the onSubmit
prop so QRStampModal.onSubmit?: (qrData: string) => void will receive the
scanned string; locate and modify the handleSubmitStamp function and the
QRStampModal usage in CafeIntro.tsx to wire the qrData through and add basic
try/catch + success/error handling.
In `@apps/owner/src/app/`(tabs)/main/_components/QRStampModal.tsx:
- Around line 63-68: Remove the duplicate useEffect that runs on [open] and
stops tracks on streamRef.current; the cleanup is already handled in the earlier
useEffect's cleanup, so delete the second effect (the one that checks if (!open
&& streamRef.current) and calls getTracks().forEach(track => track.stop()) and
sets streamRef.current = null) and keep the existing cleanup logic in the
original useEffect so camera tracks are stopped only once.
- Around line 72-129: This modal (QRStampModal component) needs keyboard/ARIA
accessibility: add an effect in QRStampModal that when open mounts it attaches a
keydown handler to call onClose() on Escape and restores cleanup; implement a
focus trap so focus is constrained inside the modal while open (ensure initial
focus moves into the modal and returned to the previously focused element on
close) and ensure the close button (onClose) is focusable; add ARIA attributes
to the root modal container (role="dialog", aria-modal="true") and give the
title element (the h1 with text "적립") an id referenced by aria-labelledby on the
root so assistive tech announces the dialog. Use existing symbols (onClose,
onSubmit, videoRef, cameraError, ScanFrame, SCAN_BOX_SIZE) to locate the
component code and wire these changes.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 62cb6451-785f-4430-8311-35fe90706f13
⛔ Files ignored due to path filters (2)
packages/design-system/src/icons/generated/spriteSymbols.tsis excluded by!**/generated/**packages/design-system/src/icons/source/CloseButton.svgis excluded by!**/*.svg
📒 Files selected for processing (2)
apps/owner/src/app/(tabs)/main/_components/CafeIntro.tsxapps/owner/src/app/(tabs)/main/_components/QRStampModal.tsx
✅ 작업 내용
📝 Description
사장님 홈 화면에서 QR 적립용 풀스크린 모달을 구현했습니다.
카메라를 배경으로 사용하고, 중앙 스캔 가이드와 적립 버튼을 오버레이 형태로 배치했습니다.
🚀 설계 의도 및 개선점
0.738rem로 조정해 디자인에 맞춤📸 스크린샷 (선택)
📎 기타 참고사항
Fixes #73
Summary by CodeRabbit
릴리스 노트
새로운 기능
사용자 인터페이스