feat(vton): expand whitelist to shoes + dedupe + keywords search + bilingual labels (#602)#609
Merged
Merged
Conversation
Expand VTON_CATEGORY_CODES to ['tops','bottoms','shoes'] so the items API honors Google Vertex AI VTON GA's officially supported categories. Update test fixture to reflect the upcoming 3-way merge expectation. Refs #602
한 solution이 여러 spot에 등록되면 spots!inner join 결과 중복 row가 생겨 UI에 중복 노출됨. mapItems에서 Set 기반 dedupe 추가. Refs #602
- CATEGORIES 상수를 { key, label_en, label_ko } 형태로 분리
- VtonItemPanel 탭 라벨을 'Tops 상의' 식 한/영 병기 렌더
- VtonModal selectedItems Record에 'shoes: null' 키 추가
(초기 state + handleClose + handleSelectPost reset 경로 모두)
Refs #602
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
7 tasks
This was referenced May 28, 2026
H1 carries the (v2.2.0) version marker; the frontmatter title was missing it, which trips wiki-lint's H1_TITLE_MISMATCH rule. Unblocks the wiki-lint check on this PR.
3 tasks
thxforall
added a commit
that referenced
this pull request
May 28, 2026
#615) - API: remove tops/bottoms/shoes subcategory whitelist that filtered posts to ~1 result. Whitelist already proved fragile once (#602/#609); rely on items.length>0 filter + post status instead. - API: cursor-based pagination via ?cursor=<created_at ISO>. Default listing branch returns nextCursor when the page filled; search and post_id branches always return nextCursor=null. Over-fetches limit*3 because items.length>0 is a JS filter, not SQL. - useVtonPostFetch: loadMore/hasMore/isLoadingMore, AbortController for in-flight cancel, dedupe across cursor boundary. - VtonItemPanel: IntersectionObserver sentinel (rootMargin 240px) inside the scroll container drives loadMore. - useVtonItemFetch: reset items state before fetching so a previously preloaded post's items don't linger in the grid while the next fetch is pending (visible when switching post -> items mode). - tests: 11 pass; new cases for cursor predicate, nextCursor emission, and cursor being ignored on search/post_id branches. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
Summary
VTON 모달의 카테고리 화이트리스트를 Google Vertex AI
virtual-try-on-001GA가 공식 지원하는tops/bottoms/shoes3종으로 확장하고,solutions.keywordsjsonb 검색 + 동일 솔루션 dedupe + 한/영 병기 라벨을 추가하여 한국어 사용자가 원하는 아이템을 더 빠르게 찾도록 함. Posts 1장만 로드되던 버그(#602 Bug #2)는 동일 화이트리스트 확장의 자연스러운 부수효과로 해결됨.Background
Domain 분석 결과 (grill 완료)
packages/api-server/migration/src/m20260110_000002_update_categories_and_seed_subcategories.rs:41-50): Wearables 7개 —headwear,eyewear,accessories,tops,bottoms,shoes,bagssolutions테이블에subcategory_id없음 → 카테고리는spots.subcategory_id로만 결정 → 한 solution이 여러 spot에 등록되면 cross-category 중복 노출 가능 → API dedupe 필수Bug #2 root cause
기존
VTON_CATEGORY_CODES = ["tops","bottoms"]화이트리스트(items/route.ts:6,posts/route.ts:5)로 인해 그 외 카테고리 spot만 가진 post가 모두items.length > 0필터에 걸려 1장만 통과. 화이트리스트 확장으로 자연 해결.Changes
API
packages/web/app/api/v1/vton/items/route.tsVTON_CATEGORY_CODES에"shoes"추가fetchVtonItems의buildQuery에keywords::textilike 분기 추가 (jsonb → text cast)Promise.all을 3-way (title/description/keywords)로 확장mergeSolutionRows를 N-way merge로 일반화mapItems에solution.id기반 Set dedupe 추가packages/web/app/api/v1/vton/posts/route.tsVTON_CATEGORY_CODES에"shoes"추가 (items API와 동일 — drift 방지)Hook / UI
packages/web/lib/hooks/useVtonItemFetch.tsCategory = "tops" | "bottoms" | "shoes"확장CATEGORIES상수를{ key, label_en, label_ko }형태로 변경subcategories.namejsonb와 정확히 일치packages/web/lib/components/vton/VtonItemPanel.tsxTops 상의 / Bottoms 하의 / Shoes 신발label_en사용packages/web/lib/components/vton/VtonModal.tsxselectedItemsstate 초기값에shoes: null키 추가handleClose/handleSelectPost의 reset 경로에도shoes키 통일Tests (TDD)
packages/web/app/api/v1/vton/items/__tests__/route.test.tsshoes카테고리 허용 케이스packages/web/app/api/v1/vton/posts/__tests__/route.test.tspackages/web/lib/components/vton/__tests__/VtonLab.test.tsxOut of scope
subcategories.vton_enabled컬럼 (백로그)bags/headwear/eyewear/accessories노출 (PoC 검증 후 별도 phase)Verification
bun run lint→ 0 errorsbun run tsc --noEmit→ 0 errorsbun run build→ PASSTest plan
Tops 상의 / Bottoms 하의 / Shoes 신발3개 노출 확인shoes카테고리에서 신발 item 선택 → person photo + try-on 실행 → 결과 이미지 정상 생성 (Vertex AI 응답 OK)Plan reference
상세 TDD plan:
docs/superpowers/plans/2026-05-28-vton-categories-and-search.mdbun run buildfailure is NOT this PRLocal
bun run build가packages/web/app/api/v1/content/assets/plan/__tests__/route.test.ts:559의useResearchInCopy타입 mismatch로 실패합니다. 이는 dev pre-existing: #498 (feat(content-studio): AI-powered content generation pipeline) 머지된 시점부터 발생. 본 PR은 vton 파일만 건드리고 vton 한정 lint/tsc/test는 모두 PASS. content-studio 영역 fix는 별도 owner가 처리해야 함.Refs #602 (sub-PR #3 of 4)