deckhearth/lib/scanner-route-api.js
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

113 lines
2.9 KiB
JavaScript

import { VOCAB } from './collection-vocabulary.js';
function authHeaders(json = true) {
const headers = {
Authorization: `Bearer ${localStorage.getItem('auth_token')}`,
};
if (json) {
headers['Content-Type'] = 'application/json';
}
return headers;
}
export function buildScannerCardPayload(cardData) {
const payload = {
cardId: cardData.databaseId,
quantity: cardData.quantity || 1,
condition: cardData.condition || 'NM',
is_foil: Boolean(cardData.isFoil),
};
if (cardData.scanImageUrl) {
payload.scan_image_url = cardData.scanImageUrl;
}
return payload;
}
export async function fetchScannerCollections() {
const response = await fetch('/api/collections', { headers: authHeaders(false) });
if (!response.ok) {
throw new Error('Failed to load lists');
}
const data = await response.json();
return data.filter((collection) => !collection.is_system_collection);
}
export async function fetchScannerDecks() {
const response = await fetch('/api/decks', { headers: authHeaders(false) });
if (!response.ok) {
throw new Error('Failed to load decks');
}
return response.json();
}
export async function addScannedCardToOwned(cardData) {
const response = await fetch('/api/user-cards', {
method: 'POST',
headers: authHeaders(),
body: JSON.stringify(buildScannerCardPayload(cardData)),
});
if (!response.ok) {
throw new Error(`Failed to add to ${VOCAB.MY_COLLECTION}`);
}
}
export async function addScannedCardToCollection(cardData, collectionId) {
const response = await fetch(`/api/collections/${collectionId}/cards`, {
method: 'POST',
headers: authHeaders(),
body: JSON.stringify(buildScannerCardPayload(cardData)),
});
if (!response.ok) {
throw new Error(`Failed to add to ${VOCAB.LIST}`);
}
}
export async function addScannedCardToDeck(cardData, deckId) {
const response = await fetch(`/api/decks/${deckId}/cards`, {
method: 'POST',
headers: authHeaders(),
body: JSON.stringify(buildScannerCardPayload(cardData)),
});
if (!response.ok) {
throw new Error('Failed to add to deck');
}
}
export async function createScannerCollection(name) {
const response = await fetch('/api/collections', {
method: 'POST',
headers: authHeaders(),
body: JSON.stringify({
name,
description: 'Created from card scanner',
is_public: false,
}),
});
if (!response.ok) {
throw new Error('Failed to create list');
}
return response.json();
}
export async function routeScannedCardToDestination(cardData, destination) {
if (!destination || !cardData.databaseId) return false;
if (destination.type === 'owned') {
await addScannedCardToOwned(cardData);
} else if (destination.type === 'collection') {
await addScannedCardToCollection(cardData, destination.id);
} else if (destination.type === 'deck') {
await addScannedCardToDeck(cardData, destination.id);
} else {
return false;
}
return true;
}