Initial commit: MTG personal library catalog (Tauri v2 + React/TS)
Full working app with: - Rust core (mtgc-core): Scryfall ingester, nucleo fuzzy search, SQLite two-DB architecture (reference.db + library.db via ATTACH), criteria filters, deck ops - Tauri v2 shell exposing the core as typed IPC commands - React/TS frontend: card entry, library browser, deck editor - Features: fuzzy card search, color/CMC/type/commander-identity filters, tile/list view toggle, hover card previews, deck format + commander support, per-card location field, grouping by type/subtype/CMC/color, localStorage persistence for active tab/deck/grouping, Discord-inspired dark UI (#C8553D accent) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
109
src/api.ts
Normal file
109
src/api.ts
Normal file
@@ -0,0 +1,109 @@
|
||||
// Typed wrappers over the Tauri command bridge into mtgc-core.
|
||||
import { invoke } from "@tauri-apps/api/core";
|
||||
|
||||
// --- Types (mirror the serde-serialized core structs) ---------------------
|
||||
|
||||
export interface CardRef {
|
||||
oracle_id: string;
|
||||
name: string;
|
||||
mana_value: number;
|
||||
colors: number; // WUBRG bitmask
|
||||
color_identity: number; // WUBRG bitmask
|
||||
type_line: string;
|
||||
image_uri: string; // Scryfall "normal" image URL, or "" if unavailable
|
||||
}
|
||||
|
||||
export interface LibraryCard extends CardRef {
|
||||
quantity_owned: number;
|
||||
decks: string[];
|
||||
quantity_assigned: number;
|
||||
location: string;
|
||||
}
|
||||
|
||||
export interface DeckEntry extends CardRef {
|
||||
quantity: number;
|
||||
is_commander: boolean;
|
||||
quantity_owned: number;
|
||||
}
|
||||
|
||||
export interface Deck {
|
||||
id: number;
|
||||
name: string;
|
||||
format: string;
|
||||
commander_oracle_id: string | null;
|
||||
notes: string;
|
||||
}
|
||||
|
||||
export interface LibraryFilter {
|
||||
text?: string | null;
|
||||
colors_exact?: number | null;
|
||||
colors_include?: number | null;
|
||||
commander_identity?: number | null;
|
||||
cmc_min?: number | null;
|
||||
cmc_max?: number | null;
|
||||
types?: string[];
|
||||
subtypes?: string[];
|
||||
keywords?: string[];
|
||||
in_deck?: number | null;
|
||||
}
|
||||
|
||||
export interface Status {
|
||||
library_path: string;
|
||||
reference_path: string;
|
||||
reference_ready: boolean;
|
||||
card_count: number;
|
||||
}
|
||||
|
||||
// --- WUBRG bitmask helpers ------------------------------------------------
|
||||
|
||||
export const COLORS: { bit: number; code: string; label: string }[] = [
|
||||
{ bit: 1, code: "W", label: "White" },
|
||||
{ bit: 2, code: "U", label: "Blue" },
|
||||
{ bit: 4, code: "B", label: "Black" },
|
||||
{ bit: 8, code: "R", label: "Red" },
|
||||
{ bit: 16, code: "G", label: "Green" },
|
||||
];
|
||||
|
||||
export function maskToLetters(mask: number): string {
|
||||
return COLORS.filter((c) => mask & c.bit)
|
||||
.map((c) => c.code)
|
||||
.join("");
|
||||
}
|
||||
|
||||
// --- Commands -------------------------------------------------------------
|
||||
|
||||
export const api = {
|
||||
getStatus: () => invoke<Status>("get_status"),
|
||||
setLibraryPath: (path: string) => invoke<Status>("set_library_path", { path }),
|
||||
updateCardData: () => invoke<Status>("update_card_data"),
|
||||
|
||||
searchCards: (query: string, limit = 20) =>
|
||||
invoke<CardRef[]>("search_cards", { query, limit }),
|
||||
|
||||
addOwned: (oracleId: string, delta: number) =>
|
||||
invoke<number>("add_owned", { oracleId, delta }),
|
||||
setOwned: (oracleId: string, quantity: number) =>
|
||||
invoke<number>("set_owned", { oracleId, quantity }),
|
||||
setLocation: (oracleId: string, location: string) =>
|
||||
invoke<void>("set_location", { oracleId, location }),
|
||||
|
||||
searchLibrary: (filter: LibraryFilter) =>
|
||||
invoke<LibraryCard[]>("search_library", { filter }),
|
||||
|
||||
listDecks: () => invoke<Deck[]>("list_decks"),
|
||||
createDeck: (name: string, commanderOracleId: string | null) =>
|
||||
invoke<Deck>("create_deck", { name, commanderOracleId }),
|
||||
deleteDeck: (deckId: number) => invoke<void>("delete_deck", { deckId }),
|
||||
setDeckFormat: (deckId: number, format: string) =>
|
||||
invoke<void>("set_deck_format", { deckId, format }),
|
||||
setDeckCommander: (deckId: number, oracleId: string | null) =>
|
||||
invoke<void>("set_deck_commander", { deckId, oracleId }),
|
||||
setDeckCard: (
|
||||
deckId: number,
|
||||
oracleId: string,
|
||||
quantity: number,
|
||||
isCommander = false,
|
||||
) => invoke<void>("set_deck_card", { deckId, oracleId, quantity, isCommander }),
|
||||
deckContents: (deckId: number) => invoke<DeckEntry[]>("deck_contents", { deckId }),
|
||||
cardDecks: (oracleId: string) => invoke<Deck[]>("card_decks", { oracleId }),
|
||||
};
|
||||
Reference in New Issue
Block a user