Commit graph

395 commits

Author SHA1 Message Date
varutasu
cc1598962e
refactor(deck-builder): extract stats lib and stats bar (Brief 1) (#89)
Move Commander basic-land checks and deck aggregate metrics into
lib/deck-builder-stats.js with unit tests; render the summary row via
DeckBuilderStatsBar to shrink the page god-component.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 17:24:40 -05:00
varutasu
2dfe584eb0
refactor(collection): useCollectionView + view (Brief 3) (#88)
* Extract useCollectionView hook and CollectionPageView (Brief 3).

Completes collection detail god-component split with a thin page composer.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Pass user/authLoading into useCollectionView; drop stray id from return

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 17:10:20 -05:00
varutasu
e9f6001066
refactor(collections): useCollectionsPage + view (Brief 3) (#87)
* Extract useCollectionsPage hook and CollectionsPageView (Brief 3).

Moves list index logic into a hook and view; CollectionsThumbnail is a shared presentational component.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Default hook params for prerender safety

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 17:10:17 -05:00
varutasu
ed370fa601
refactor(card): useCardDetail + CardDetailView (Brief 3) (#86)
* Extract useCardDetail hook and CardDetailView (Brief 3).

Completes card detail god-component split: thin page composer with loading/not-found branches.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix useCardDetail call and default params for prerender

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 17:10:13 -05:00
varutasu
8e2c0e47a8
Extract collection edit and delete modals (Brief 2). (#85)
Adds CollectionEditModal and CollectionDeleteModal for the collection detail page.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 16:58:12 -05:00
varutasu
30bc154bec
Extract edit and success modals from collections page (Brief 2). (#84)
Adds CollectionsEditModal and CollectionsSuccessModal; drops unused tag-input imports from the page.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 16:58:09 -05:00
varutasu
f81cc7d3ad
Extract CardDetailDeckModal from card detail page (Brief 2). (#83)
Moves add-to-deck modal markup into components/CardDetailDeckModal.js.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 16:58:06 -05:00
varutasu
a7b101519a
Extract CollectionsCreateModal and tag helpers (Brief 1). (#82)
Moves create-list modal UI to components/CollectionsCreateModal.js and tag input helpers to lib/collection-tag-input.js (shared with edit modal).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 16:53:08 -05:00
varutasu
5582638935
Extract CardDetailQuantityModal from card detail page (Brief 1). (#81)
Moves owned-quantity modal markup into components/CardDetailQuantityModal.js.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 16:53:04 -05:00
varutasu
91b481ffa4
Extract collection CSV export helper (Brief 1). (#80)
Moves download logic from pages/collection/[identifier].js into lib/collection-cards-csv.js.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 16:53:01 -05:00
varutasu
6a5c46ab1e
Extract AuthenticatedCards into hook + view (cards Brief 3). (#79)
Moves card-browser state and handlers to lib/use-cards-page.js and markup to components/CardsPageView.js, leaving a thin ProtectedRoute composer in pages/cards.js.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 12:49:25 -05:00
varutasu
84462417ee
Extract PublicCardsView from pages/cards.js (Brief 2). (#78)
Moves the anonymous /cards landing UI into components/PublicCardsView.js so the page file can focus on AuthenticatedCards.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 12:06:24 -05:00
varutasu
33e03d8f47
Extract Card3D and CardBack from pages/cards.js (Brief 1). (#77)
Moves ~530 lines of 3D card rendering into components/Card3D.js so the cards page god-component split can continue incrementally.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 08:57:49 -05:00
varutasu
2273fc6be0
refactor(scanner): extract ScannerPageView component (page Brief 3) (#76)
Move scanner page markup into ScannerPageView.js. pages/scanner.js is now
a thin composer of session state, useScannerQueue, and the view.
Mark pages/scanner.js resolved in ship-readiness god-component-split table.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 21:56:34 -05:00
varutasu
d9c51b8a78
refactor(scanner): extract useScannerQueue hook (page Brief 2) (#75)
Move queue state, bulk actions, in-flight guards, and destination list
loading into lib/use-scanner-queue.js. Scanner page keeps session prefs
and view markup.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 21:28:24 -05:00
varutasu
83d73eecaf
refactor(scanner): extract session and route API libs (page Brief 1) (#74)
Move scanner session persistence, queue merge helpers, and destination
routing fetch calls into lib/scanner-session.js and lib/scanner-route-api.js.
Load collections/decks on mount (were defined but never invoked).
Remove unused mana-symbol imports and dead select-all helpers.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 16:15:27 -05:00
varutasu
cf770b618c
refactor(scanner): extract CameraScannerView presentational component (#73)
Move camera feed markup, overlays, and disambiguation dialog wiring into
CameraScannerView.js. CameraScanner is now a ~45-line hook composer.
Update ship-readiness god-component-split CameraScanner slice as resolved.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 16:04:02 -05:00
varutasu
e035411f40
refactor(scanner): extract identification hook (Brief 5) (#72)
Move verify/disambiguation/review flow into lib/use-scanner-identification.js.
CameraScanner is now a thin composition of two hooks plus view markup.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 15:59:03 -05:00
varutasu
986daaa1f2
refactor(scanner): extract camera lifecycle hook (Brief 4) (#71)
Move stream start/stop, detection intervals, and tracked-card polling
into lib/use-camera-scanner.js. CameraScanner keeps identification UI
and disambiguation wiring only.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 15:44:56 -05:00
varutasu
7f3cf62344
refactor(scanner): extract card identification pipeline (Brief 3) (#70)
Move Layer-1/Layer-2 identify flow, outcome resolution, disambiguation
refine helpers, and scan-for-review API calls into lib/scanner-card-identify.js.
Remove unused manaSymbolSettings state from CameraScanner.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 15:34:13 -05:00
varutasu
a6813ef764
refactor(scanner): extract card detection and tracking lib (Brief 2) (#69)
Move OpenCV shape detection, coordinate conversion, overlap checks,
and tracked-card merge logic from CameraScanner into lib/scanner-card-detection.js
with unit tests for the pure helpers.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 12:52:40 -05:00
varutasu
b615fac865
refactor(auth): add withAdmin() wrapper for admin API routes. (#68)
Extract shared 401/403 gate into permission-middleware and sweep the
four inline admin checks (import MTG/Pokemon, sync-catalog, card-submissions).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 12:42:22 -05:00
varutasu
071a3dca21
refactor(scanner): extract disambiguation dialog and upload helpers. (#67)
Brief 1 of god-component-split: move ScanDisambiguationDialog and
scan-capture-upload lib out of CameraScanner (~90 lines) without
behavior changes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 11:01:32 -05:00
varutasu
ad0e254324
chore(convoys): mark shipped convoys and refresh ship-readiness (#66)
Close stale convoy frontmatter for merged scanner, lint, and hygiene work;
record P1 #11.5 and queued follow-ups as RESOLVED with PR references.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 11:01:27 -05:00
varutasu
ffc7afcdbf
ci: trigger visual diff on tests/visual changes (#65)
* ci: trigger visual diff on tests/visual changes

Baseline-only PRs should run Screenshot diff now that home.png is committed.

Co-authored-by: Cursor <cursoragent@cursor.com>

* ci: trigger visual diff on tests/visual changes

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 11:01:23 -05:00
varutasu
e78f78e3f6
ci: run migrations against Postgres service container in CI (#64)
* ci: run migrations against Postgres service container in CI

Add a migrate job that applies node-pg-migrate against an ephemeral
Postgres 16 service container so broken migrations fail at PR time.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(migrations): retimestamp scan tables after initial-schema.

Fresh CI/postgres runs failed because 1748365200000 sorted before
initial-schema. Renamed to 1779853647566 with IF NOT EXISTS guards intact.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(migrations): ensure is_system_collection exists before description backfill.

Fresh CI Postgres runs initial-schema without this column (added historically
via scripts); ADD COLUMN IF NOT EXISTS makes the data migration safe on new
and existing envs.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 11:01:18 -05:00
varutasu
81bed51369
fix(lint): clear lib/config baseline and make CI lint blocking. (#63)
Lazy-init theme from localStorage, hoist checkAuth with useCallback,
named config exports for PostCSS/Tailwind, and remove the non-blocking
|| true wrapper from ci.yml (requires #61 + #62 merged first).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 01:03:42 -05:00
varutasu
c32bbd19b6
fix(lint): clear ESLint baseline in pages/ (#62)
Resolve react-hooks, no-unescaped-entities, and no-img-element findings
under pages/ with lint-only changes so npx eslint pages/ exits clean.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 01:03:39 -05:00
varutasu
309cfa238a
fix(lint): clear ESLint baseline in components/ (#61)
Resolve react-hooks purity, immutability, refs, and set-state-in-effect
violations without behavior changes; align img usage with pages/ disable
pattern for external URLs.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 01:03:36 -05:00
varutasu
00193651aa
Backfill system collection descriptions to current vocabulary. (#60)
Existing is_system_collection rows may carry stale copy; align them with VOCAB.SYSTEM_COLLECTION_SEED_DESCRIPTION so UI matches new signups.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 00:42:23 -05:00
varutasu
8262fec3e8
Remove dead Lorcana import route and CLI script (#59)
* Remove dead Lorcana import route and CLI script

The admin card-import UI never wired Lorcana; catalog sync uses
pages/api/admin instead. Drop the unused API route, CLI helper, and
stale docs references to import-lorcana.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Remove orphaned import-lorcana-simple CLI script.

It POSTed to the deleted /api/cards/import-lorcana endpoint; no remaining callers.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 00:42:18 -05:00
varutasu
83a358b5dc
chore: seed Linux Playwright visual baseline for homepage (#58)
Commit home.png generated in mcr.microsoft.com/playwright:v1.60.0-noble
against https://tcg-vault.vercel.app so Screenshot diff CI matches production.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 00:42:14 -05:00
varutasu
5115683ead
Purge direct @neondatabase/serverless dependency from operational scripts. (#57)
Migrate setup-neon-db.js and reset-db.js to @vercel/postgres tagged templates so the runtime uses a single SQL client; historical add-*/fix-*/seed-* scripts remain unchanged per no-go-zone.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-02 00:42:11 -05:00
varutasu
e0218e4b05
Remove Quick Login + scanner a11y polish (#56)
Drop alice/bob password prefill from the login page, add a regression
test, and improve bulk-toolbar and disambiguation accessible names.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-29 22:58:41 -05:00
varutasu
c197dc61ed
Vocabulary cleanup follow-up (#55)
Correct dashboard title (My Collection overview, not Lists), sweep
remaining marketing/auth copy, update system-list seed description,
add vocabulary unit tests, and close the convoy record.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-29 10:01:03 -05:00
varutasu
fd781140e5
Align UI copy: My Collection vs Lists (#54)
* Align UI copy with My Collection vs Lists vocabulary.

Replace stale ownership/list labels across pages and components, add
lib/collection-vocabulary.js as the single copy source, document the
taxonomy in AGENTS.md, and gate retired strings in CI.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Fix remaining list/collection copy gaps from review.

Sweep community, settings, share modal, scanner create-list modal,
and invite flows for vocabulary consistency before merge.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-29 09:53:40 -05:00
varutasu
c51ec6a04c
Normalize collector numbers in catalog match and harden scanner adds. (#53)
Share card-number normalization across reconcile and identify paths, retry set/name matches when OCR uses leading-zero collector numbers, and extend in-flight locks to all scanner destination actions with disabled Mark Owned feedback.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-28 14:45:55 -05:00
varutasu
174a370fc3
Switch Pokémon catalog import to pokemon-tcg-data on GitHub. (#52)
Replace pokemontcg.io API discovery and import with raw JSON from PokemonTCG/pokemon-tcg-data; format collector numbers as number/printedTotal and drop the API key dependency for catalog sync.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-28 11:56:01 -05:00
varutasu
cf5c0558f1
Auto-link pending scan submissions after catalog sync imports. (#51)
When a set lands via runCatalogSync, match pending card_submissions by set/name/number to catalog rows and approve them with promoted_card_id instead of leaving them in the admin queue.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-28 09:47:59 -05:00
varutasu
8f3fbe70a2
Add admin panel button to trigger catalog sync. (#50)
Expose POST /api/admin/sync-catalog for authenticated admins (import rate limit, 300s timeout) and wire a Run catalog sync control on /admin/card-import.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-28 09:18:01 -05:00
varutasu
bec0a7abbd
Prioritize newest missing sets in catalog sync queue. (#49)
The cron was importing oldest MTG sets first and never reaching recent Pokémon releases like Perfect Order; merge MTG and Pokémon by release date descending instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 21:49:58 -05:00
varutasu
0a47362103
feat(catalog): weekly Vercel Cron sync for MTG and Pokémon sets (#48)
Extract shared import logic into lib/card-import, discover missing sets via
Scryfall/Pokémon TCG APIs, and expose GET /api/cron/sync-catalog protected
by CRON_SECRET (max 3 sets/run, paced imports).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 14:59:59 -05:00
varutasu
49d1e62fa7
test(scanner): cover redesign API and component surfaces (#47)
Add vitest specs for user-cards quantity validation, scan upload-image
auth/rate-limit/MIME gates, ScannerDestinationPicker, and ScannedCardItem.
Suite grows 21 → 37 tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 14:28:04 -05:00
varutasu
30b21b42c5
fix(api): validate quantity on POST /api/user-cards (#46)
Match decks handler parseInt/NaN guard so non-numeric quantities cannot
corrupt user_cards row counts from scanner add paths.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 14:25:20 -05:00
varutasu
66717c4198
fix(scanner): close redesign a11y audit findings (#45)
Add focus traps for modals, accessible names for icon/select controls,
ownership badge role=status, list semantics for the scan queue, and
aria-live updates for the card count.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 14:22:18 -05:00
Randall Stillwell
ff73743a9f docs(convoy): close redesign-scanner-flow post-PR audit
Record audit-redesign-scanner-flow-44 rollup and queue follow-up convoys
from reviewer, design-system, and a11y fan-out on PRs #42–#44.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 14:09:50 -05:00
varutasu
673af83519
feat(scanner): persist scan captures to Blob (Brief 3) (#44)
Upload confirmed scan frames to Vercel Blob and store the URL on user_cards
when routing to owned cards, completing the redesign-scanner-flow convoy.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 13:57:26 -05:00
varutasu
24c9da4095
feat(scanner): condition, foil, quantity, and ownership badge (Brief 2) (#43)
Extract ScannedCardItem with per-card metadata controls and ownership
lookup via GET /api/cards/[id]/ownership. Propagate condition, foil,
and quantity through owned/collection/deck POST paths.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 13:54:33 -05:00
varutasu
47a1abbe4d
feat(scanner): stack-destination picker and auto-route (Brief 1) (#42)
Add ScannerDestinationPicker with game filter and owned/collection/deck
targets. Persist session destination in localStorage and auto-add each
identified scan to the active destination.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 13:50:54 -05:00
varutasu
55af7e3c90
fix(scanner): idempotent Mark-Owned and reliable bulk actions (#41)
Add per-row in-flight locks so double-tap cannot duplicate owned POSTs.
Pass bulk action/target directly instead of setTimeout state races.
Log collection card adds via logCollectionActivity and fix rows.length
checks in the collection cards POST handler.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-27 13:44:47 -05:00