Skip to content

feat(vton): infinite scroll posts + drop whitelist + reset stale items#615

Merged
thxforall merged 1 commit into
devfrom
feat/vton-posts-infinite-scroll
May 28, 2026
Merged

feat(vton): infinite scroll posts + drop whitelist + reset stale items#615
thxforall merged 1 commit into
devfrom
feat/vton-posts-infinite-scroll

Conversation

@thxforall
Copy link
Copy Markdown
Contributor

Summary

  • API: drop tops/bottoms/shoes subcategory whitelist that silently filtered the posts modal down to 1 result. Whitelist scope has already broken this exact symptom once ([VTON] Modal 사용성·도메인 정합성 4-in-1 (filter/search/UI/render bug) #602/feat(vton): expand whitelist to shoes + dedupe + keywords search + bilingual labels (#602) #609); switching to items.length>0 + post status as the only gates is more durable.
  • API: cursor-based pagination via ?cursor=<created_at ISO> on the default listing branch (search and post_id branches keep returning nextCursor=null). Server still over-fetches limit*3 because the items.length>0 filter runs in JS, not SQL.
  • Client: useVtonPostFetch exposes loadMore/hasMore/isLoadingMore, cancels in-flight pages on close/query change, and dedupes across the cursor boundary.
  • Client: VtonItemPanel uses an IntersectionObserver sentinel (rootMargin 240px) inside the scroll container to call loadMore ahead of the viewport edge.
  • Fix: useVtonItemFetch now resets items before fetching, so a previously preloaded post's items no longer linger in the grid while the next category fetch is pending — this was visible when switching from post-selection mode back to the Items tab.

Test plan

  • bunx vitest run app/api/v1/vton/posts — 11/11 pass (incl. new cursor cases)
  • bunx tsc --noEmit — clean
  • Manual: open /lab/vton, confirm >1 post listed, scroll to trigger next page, then click a post → Items tab and verify the grid loads fresh items rather than the post's items.

🤖 Generated with Claude Code

- 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>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
decoded-app Ready Ready Preview, Comment May 28, 2026 2:23pm

@thxforall thxforall moved this from Todo to In Progress in decoded-monorepo May 28, 2026
@thxforall thxforall added the bump:minor Backward-compatible additions label May 28, 2026
@thxforall thxforall merged commit 2d3255a into dev May 28, 2026
9 of 10 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in decoded-monorepo May 28, 2026
@thxforall thxforall deleted the feat/vton-posts-infinite-scroll branch May 28, 2026 14:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bump:minor Backward-compatible additions

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant