Skip to content

v1.3.0 — Multi-TCG Decks, Card DB, Trade Analyzer, Price Alerts, and Bug Fixes

Choose a tag to compare

@novaoc novaoc released this 09 Jun 03:17

Summary

v1.3.0 is a major release adding Yu-Gi-Oh! TCG support, a card database preloader, trade analyzer, Collectr import, price alerts, meta decks for all 6 TCGs, and 20+ critical/medium bug fixes including trade persistence data loss, non-Pokemon price refresh, Lorcana/Riftbound meta deck resolution, and navigation hangs.


New Features

Yu-Gi-Oh! TCG Support

  • Full set browsing with YGOPRODeck integration
  • Card search with TCGPlayer market prices
  • Yu-Gi-Oh! meta decks (ygoprodeck.com top decks)
  • Preloader support for offline caching

Card Database (Client-Side IndexedDB)

  • On first visit, select which TCGs to track
  • Preloads all card data into IndexedDB in the background — zero API calls on subsequent searches
  • Floating progress pill shows per-game status, ETA, and overall completion
  • Interrupted preloads resume silently on refresh
  • Search works immediately — uncached TCGs fall back to live APIs
  • Two-phase preloader: sets first (~2s), then cards progressively per TCG
  • Storage usage display showing combined IndexedDB + localStorage

Trade Analyzer

  • Side-by-side trade comparison with cards added via search or camera scan
  • Live price delta with winning/losing/even label
  • Grading multiplier applied per card (PSA 10 = 2x, etc.)
  • Persistent trade state across sessions (separate IndexedDB key)
  • Camera scan integration via Tesseract.js OCR

Collectr Import

  • Import CSV or Excel exports from the Collectr app
  • Maps game names, variants, grading, and sealed products
  • Full-screen import overlay with progress bar and phase indicators
  • Resolves all 6 TCGs with images + prices automatically

Multi-TCG Meta Decks

  • Auto-fetches current tournament meta from each TCG's competitive scene
    • Pokémon — Limitless TCG
    • Magic — mtgtop8.com
    • Lorcana — inkdecks.com
    • One Piece — optcg.one
    • Riftbound — RiftDecks.com
    • Yu-Gi-Oh! — ygoprodeck.com
  • Top 10 competitive decks per TCG ranked by meta share
  • Cards resolved server-side with exact set code + number matching
  • Cached for 24h with version-based invalidation

Price Alerts

  • Set "notify when price goes above/below $X" on any card
  • Alerts fire via the browser Notification API when prices cross thresholds
  • Auto-checked on every dashboard page load
  • Manage active and triggered alerts from Settings

Other

  • Entire set add to portfolio from any Browse Sets view
  • Sealed product search with keyword filtering (boosters, ETBs, tins)
  • Graded card multipliers (PSA/BGS/CGC/SGC)
  • Reset Everything clears full card cache
  • Storage usage in Settings via navigator.storage.estimate()
  • 404 catch-all page for invalid routes

Critical Bug Fixes

Trade Store Persistence Conflict

Trade store and portfolio store both wrote to the same IDB key (app_state) with independent debounced saves — one could overwrite the other's unsaved changes. Fixed by adding loadTradeState()/saveTradeState() with a dedicated trade_state key.

Price Alerts Never Auto-Checked

checkAlerts() and notifyTriggered() existed but were never called anywhere. Now invoked after every dashboard price refresh.

Dashboard Non-Pokemon Price Refresh Broken

Dashboard refresh loop used Pokemon-only APIs for all cards. Non-Pokemon cards (MTG, Lorcana, One Piece, Riftbound, Yu-Gi-Oh) failed silently. Fixed by splitting into Pokemon (pokemontcg.io/tcgdex) and non-Pokemon (PriceCharting) refresh paths.

resolveImportedItems Silently Fails for 4 TCGs

After Collectr import, card resolution only worked for Pokemon EN/JP and MTG. Other TCGs were skipped with a comment. Fixed by adding multiSearch resolution for all games.


Medium Bug Fixes

Navigation Hangs

Route transition with mode='out-in' could hang indefinitely when transitionend was delayed (e.g., during IndexedDB writes). Fixed by adding :duration=500 timeout.

Navigation Blank Screen

Vue Router reused component instances across route transitions, causing stale state. Fixed by adding :key on route transitions to force fresh component instances.

Lorcana Meta Deck Cards Not Loading (x2)

  1. Wrong set field paths: Lorcast API returns set info under a nested set object (c.set.name, c.set.code) but code read non-existent top-level c.set_name/c.set_code.
  2. Missing version-aware matching: searchLorcanaBySet compared fallback names like "Elsa — Snow Queen" against c.name ("Elsa") without appending the API's version field.
  3. Incorrect fallback data: All 10 Lorcana meta deck fallback entries had wrong set codes and collector numbers. Corrected against live API data.

Riftbound Meta Deck Cards Not Loading

Empty setCode caused startsWith('') to match all sets, returning wrong cards. Fixed by guarding against empty setCode. Fallback decks replaced with real card names using correct API set codes (OGN, SFD).

Riftbound Card Import Timeout

Parallelized getRiftboundCards and skipped PriceCharting on bulk load to avoid timeouts.

Sealed Search Yielding Card Results

PriceCharting results included single cards. Added isSealed() keyword filter and single-card pattern detection (set codes, collector ratios).

beforeunload Handler Multiplication

Every init() call registered a new beforeunload listener. Fixed with a beforeunloadRegistered flag.

Lorcana Preloader Price Path Mismatch

Used c.tcgplayer.prices.holofoil.market but Lorcast returns c.prices.usd. Added fallback to c.prices?.usd.

One Piece API Response Shape Inconsistency

getOptCards() only checked Array.isArray(d) but API may return {data: [...]} or {cards: [...]}. Added fallback checks.

isCacheFresh First-Card-Only Check

Only checked cachedAt of the first card. Partial caches from interrupted preloads reported as fresh. Added card count check.

Router Missing 404 Catch-All, MockDashboard Route

Invalid URLs rendered blank page. Added /:pathMatch(.*)* catch-all with NotFoundView. Removed /mockup production route.

MTG Paginated Search Replaced with Bulk Data

~545 sequential Scryfall requests (45 min) reduced to 2 requests (~5s) using oracle_cards bulk data.

Sealed Search Filtering Out Prismatic Evolutions

isSealed() didn't check consoleName for keywords. Fixed by checking both productName AND consoleName.

Collectr Import Fixes

  • Rewrote to import directly into Pinia store instead of localStorage+reload
  • Added BOM stripping for CSV
  • Added Excel (.xlsx) support
  • Fixed portfolio name mapping (Portfolio Name column, not Category)
  • Fixed market price mapping (date-stamped columns)
  • Fixed reactivity (black screen after import)

Code Quality & Optimizations

  • Hoisted dynamic import: import('../services/tcg/multiSearch.js') moved outside the loop in resolveImportedItems per PR review
  • Empty catch blocks: Replaced with console.warn in critical price paths
  • Added SEO meta descriptions to every route
  • Navigation logging: Added router.beforeEach and router.afterEach for diagnostics
  • Global error handlers: config.errorHandler and onErrorCaptured for silent failure detection
  • Debounced chart rebuilds (300ms), 404s cached as misses
  • API calls batched — max 3-5 concurrent requests
  • Retry with backoff on transient errors (429, 5xx, timeout)
  • Abort-on-unmount for in-flight API calls
  • Decoupled preloader from search — only activate cache after all games finish