Conversation
- 검색 결과 카드에 오류 신고 모달 추가 (가수/곡 번역, TJ/금영 번호 카테고리) - 라이브 미리보기 카드 (선택된 항목 강조 + 입력값 → 새 값 표시) - 숫자 카테고리는 5자리 숫자만 입력, "데이터 없음" 체크박스로 null 제출 가능 - POST /api/songs/report (BFF), TanStack Query mutation, ReportCategory/ReportStatus 타입 정의
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Review Summary by QodoAdd song error reporting feature with live preview and API integration
WalkthroughsDescription• Add song error reporting feature with modal dialog - Four report categories: artist translation, title translation, TJ number, KY number - Live preview card showing selected category highlight and new value • Implement BFF API endpoint for song report submission - Validates input based on category type (text vs numeric) - Handles duplicate reports with 409 conflict response • Add TanStack Query mutation hook and report type definitions • Add Radix UI radio group component for category selection Diagramflowchart LR
A["SearchResultCard"] -->|"opens"| B["ReportSongModal"]
B -->|"selects category"| C["Live Preview Card"]
C -->|"shows highlight"| D["Selected Field"]
B -->|"submits report"| E["useReportSongMutation"]
E -->|"POST /api/songs/report"| F["BFF API Route"]
F -->|"validates input"| G["Category Validation"]
G -->|"inserts to DB"| H["song_reports Table"]
H -->|"409 conflict"| I["Duplicate Check"]
File Changes1. apps/web/src/app/api/songs/report/route.ts
|
Code Review by Qodo
Context used✅ Tickets:
🎫 검색 결과 카드에 오류 신고 기능 추가 1. Report modal missing textarea
|
| <div className="flex flex-col gap-2"> | ||
| <Label htmlFor="report-suggested-value">올바른 정보</Label> | ||
| <Input | ||
| id="report-suggested-value" | ||
| placeholder={ | ||
| isNumberMode | ||
| ? '5자리 숫자로 입력해주세요.' | ||
| : '어떤 내용으로 바뀌어야 하는지 적어주세요.' | ||
| } | ||
| value={isNoData ? NO_DATA_LABEL : suggestedValue} | ||
| onChange={e => handleSuggestedValueChange(e.target.value)} | ||
| maxLength={inputMaxLength} | ||
| inputMode={isNumberMode ? 'numeric' : undefined} | ||
| pattern={isNumberMode ? '[0-9]*' : undefined} | ||
| disabled={isNoData} | ||
| required | ||
| /> | ||
| <Label | ||
| htmlFor="report-no-data" | ||
| className={cn( | ||
| 'text-muted-foreground flex items-center gap-2 text-sm', | ||
| isNumberMode ? 'cursor-pointer' : 'invisible', | ||
| )} | ||
| aria-hidden={!isNumberMode} | ||
| > | ||
| <Checkbox | ||
| id="report-no-data" | ||
| checked={isNoData} | ||
| onCheckedChange={checked => handleNoDataChange(checked === true)} | ||
| disabled={!isNumberMode} | ||
| tabIndex={isNumberMode ? 0 : -1} | ||
| /> | ||
| 데이터 없음 (해당 노래방에 등록되지 않은 곡) | ||
| </Label> | ||
| <div className={cn('text-muted-foreground self-end text-xs', isNoData && 'invisible')}> | ||
| {suggestedValue.length} / {inputMaxLength} | ||
| </div> | ||
| </div> |
There was a problem hiding this comment.
1. Report modal missing textarea 📎 Requirement gap ≡ Correctness
The new ReportSongModal UI does not include the required optional description textarea element; it only provides an Input for suggested_value. This does not meet the modal UI requirements in the checklist.
Agent Prompt
## Issue description
The report modal is missing the required (optional) description `textarea` element.
## Issue Context
Checklist requires the modal to contain a single-select category list plus a description textarea (optional) and cancel/submit buttons.
## Fix Focus Areas
- apps/web/src/components/ReportSongModal.tsx[267-304]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| export async function POST(request: Request): Promise<NextResponse<ApiResponse<void>>> { | ||
| try { | ||
| const supabase = await createClient(); | ||
| const userId = await getAuthenticatedUser(supabase); | ||
|
|
||
| const { songId, category, suggested_value } = await request.json(); | ||
|
|
There was a problem hiding this comment.
2. /api/reports endpoint missing 📎 Requirement gap ≡ Correctness
The PR implements POST /api/songs/report instead of the required POST /api/reports. This breaks the required BFF endpoint contract in the compliance checklist.
Agent Prompt
## Issue description
The compliance checklist requires `POST /api/reports`, but the PR adds `POST /api/songs/report`.
## Issue Context
Next.js route handler path determines the public API route.
## Fix Focus Areas
- apps/web/src/app/api/songs/report/route.ts[14-20]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| 'use client'; | ||
|
|
||
| import * as RadioGroupPrimitive from '@radix-ui/react-radio-group'; | ||
| import { CircleIcon } from 'lucide-react'; | ||
| import * as React from 'react'; | ||
|
|
||
| import { cn } from '@/utils/cn'; | ||
|
|
||
| function RadioGroup({ | ||
| className, | ||
| ...props | ||
| }: React.ComponentProps<typeof RadioGroupPrimitive.Root>) { | ||
| return ( | ||
| <RadioGroupPrimitive.Root | ||
| data-slot="radio-group" | ||
| className={cn('grid gap-3', className)} | ||
| {...props} | ||
| /> | ||
| ); | ||
| } | ||
|
|
||
| function RadioGroupItem({ | ||
| className, | ||
| ...props | ||
| }: React.ComponentProps<typeof RadioGroupPrimitive.Item>) { | ||
| return ( | ||
| <RadioGroupPrimitive.Item | ||
| data-slot="radio-group-item" | ||
| className={cn( | ||
| 'border-input text-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 aspect-square size-4 shrink-0 rounded-full border shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50', | ||
| className, | ||
| )} | ||
| {...props} | ||
| > | ||
| <RadioGroupPrimitive.Indicator | ||
| data-slot="radio-group-indicator" | ||
| className="relative flex items-center justify-center" | ||
| > | ||
| <CircleIcon className="fill-primary absolute top-1/2 left-1/2 size-2 -translate-x-1/2 -translate-y-1/2" /> | ||
| </RadioGroupPrimitive.Indicator> | ||
| </RadioGroupPrimitive.Item> | ||
| ); | ||
| } | ||
|
|
||
| export { RadioGroup, RadioGroupItem }; |
There was a problem hiding this comment.
3. Added ui/radio-group.tsx file 📘 Rule violation ⚙ Maintainability
A new shadcn/ui-style component file was added under apps/web/src/components/ui/, which is disallowed by the checklist. This reduces upgradeability/maintainability of the vendor-like UI layer.
Agent Prompt
## Issue description
Files under `apps/web/src/components/ui/` must not be changed/added as part of feature work.
## Issue Context
This PR adds `apps/web/src/components/ui/radio-group.tsx` and imports it from feature code.
## Fix Focus Areas
- apps/web/src/components/ui/radio-group.tsx[1-45]
- apps/web/src/components/ReportSongModal.tsx[6-13]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Summary
원본 → 새 값형태로 즉시 반영num_tj/num_ky)는 5자리 숫자만 입력 가능, 「데이터 없음」 체크박스로suggested_value: null제출POST /api/songs/report→ Supabasesong_reports테이블 insertuseReportSongMutation) +ReportCategory/ReportStatus타입 정의DB 작업 필요
※
status컬럼은 다음 작업 (info 페이지 신고 목록/삭제)에서 활용 예정Test plan
→ 새 값표시, 입력 후 토글 시 모달 높이 변동 없음Closes #217
🤖 Generated with Claude Code