From 1e0cd50c7d026615cba5eacea388c417a1e1509b Mon Sep 17 00:00:00 2001 From: Garrett Mills Date: Mon, 26 Oct 2026 21:25:15 -0500 Subject: [PATCH] Deck builder: sorting and a Price column Adds the Library's Sort by control (plus a Quantity in deck option) to the deck builder, applied within each section and group. The card table gets an optional Price column showing the per-copy price, with the total for the deck's copies in its tooltip. The toolbar now wraps on narrow screens. Refs #6 Co-Authored-By: Claude Opus 5.5 --- src/components.tsx | 23 +++++++++++++++++------ src/styles.css | 4 ++++ src/views/DeckView.tsx | 35 ++++++++++++++++++++++++++++++++--- 3 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/components.tsx b/src/components.tsx index 0387c2b..8f1c10d 100644 --- a/src/components.tsx +++ b/src/components.tsx @@ -1750,7 +1750,7 @@ export function GroupBySelect({ // --- Sorting ---------------------------------------------------------- -export type SortMode = "name" | "mv" | "color" | "type" | "qty" | "price"; +export type SortMode = "name" | "mv" | "color" | "type" | "deck-qty" | "qty" | "price"; export const SORT_OPTIONS: { value: SortMode; label: string }[] = [ { value: "name", label: "Name" }, @@ -1761,13 +1761,20 @@ export const SORT_OPTIONS: { value: SortMode; label: string }[] = [ { value: "price", label: "Price" }, ]; +/** The deck builder's: how many copies the deck runs matters there too. */ +export const DECK_SORT_OPTIONS: { value: SortMode; label: string }[] = [ + ...SORT_OPTIONS.slice(0, 4), + { value: "deck-qty", label: "Quantity in deck" }, + ...SORT_OPTIONS.slice(4), +]; + export type SortDir = "asc" | "desc"; /** Sort cards by the chosen attribute; ties always break by name so the * order stays stable and predictable regardless of `mode`. Grouping (see * [`groupCards`]) determines section order independently — sort this array * first, then group it, and each group keeps this order internally. */ -export function sortCards( +export function sortCards( cards: T[], mode: SortMode, dir: SortDir, @@ -1784,9 +1791,11 @@ export function sortCards( : mode === "type" ? typeRank(primaryType(a.type_line)) - typeRank(primaryType(b.type_line)) || a.name.localeCompare(b.name) - : mode === "qty" - ? a.quantity_owned - b.quantity_owned || a.name.localeCompare(b.name) - : a.price_usd - b.price_usd || a.name.localeCompare(b.name); + : mode === "deck-qty" + ? (a.quantity ?? 0) - (b.quantity ?? 0) || a.name.localeCompare(b.name) + : mode === "qty" + ? a.quantity_owned - b.quantity_owned || a.name.localeCompare(b.name) + : a.price_usd - b.price_usd || a.name.localeCompare(b.name); return dir === "asc" ? cmp : -cmp; }); return sorted; @@ -1798,18 +1807,20 @@ export function SortBySelect({ dir, onChangeValue, onToggleDir, + options = SORT_OPTIONS, }: { value: SortMode; dir: SortDir; onChangeValue: (m: SortMode) => void; onToggleDir: () => void; + options?: { value: SortMode; label: string }[]; }) { return (