Add deck synergy suggestions, a responsive deck layout, and undoable library bulk-add

Suggestion scoring is fully offline (tribal/mechanic/archetype/mana-base
signals derived at ingest, no external synergy database), with an "unusual
picks" mode that surfaces underappreciated cards instead of staples. The
deck page's top panels now use a CSS grid so wide windows don't waste
horizontal space. Library's bulk add-to-deck can clobber existing deck
quantities, so it now offers an undo (snackbar + command palette, the
latter with no timeout) that restores each card's prior state exactly.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-21 21:04:36 -05:00
parent 008ab33723
commit 3c625a9830
14 changed files with 1596 additions and 117 deletions

View File

@@ -5,7 +5,10 @@
use std::path::PathBuf;
use std::sync::Mutex;
use mtgc_core::{CardRef, Deck, DeckEntry, LibraryCard, LibraryFacets, LibraryFilter, LibraryStats};
use mtgc_core::{
CardRef, CardSuggestion, Deck, DeckEntry, LibraryCard, LibraryFacets, LibraryFilter,
LibraryStats,
};
use serde::Serialize;
use tauri::{AppHandle, Emitter, State};
@@ -130,6 +133,14 @@ pub fn deck_contents(db: Db, deck_id: i64) -> Res<Vec<DeckEntry>> {
s.catalog()?.deck_contents(deck_id).map_err(|e| e.to_string())
}
#[tauri::command]
pub fn suggest_cards(db: Db, deck_id: i64, offset: i64, unusual: bool) -> Res<Vec<CardSuggestion>> {
let s = db.lock().unwrap();
s.catalog()?
.suggest_cards(deck_id, 50, offset.max(0) as usize, unusual)
.map_err(|e| e.to_string())
}
#[tauri::command]
pub fn search_library(db: Db, filter: LibraryFilter) -> Res<Vec<LibraryCard>> {
let s = db.lock().unwrap();

View File

@@ -41,6 +41,7 @@ pub fn run() {
commands::set_deck_commander,
commands::set_deck_card,
commands::deck_contents,
commands::suggest_cards,
commands::card_decks,
commands::export_deck,
commands::import_deck,